You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The package root exports 705 names (265 values, 440 types) while the docs use about 123 of them. Flows, the credentialed Jira / GitHub / Slack / email tools, encryption, StorageService and the small validators are not agent functionality a new user needs from the root, and they make up 97 of those names. Moving them to ./flows, ./integrations and ./utils shrinks the root's type surface without removing anything. Audit evidence: .agent-loop/audit2/our-report.md section 3 (705 root exports) and section 5 (rows Flows, EncryptionUtils, StorageService, Jira, GitHub, Slack and email, Validators).
Current state
Verified on main at cc5ddb8:
src/index.ts is export * over 26 modules, including ./types (line 15), ./tools (21), ./flows (24), ./execution (31), ./security (37), ./storage (40) and ./utils (50).
Flows: src/flows/index.ts re-exports FlowBuilder, FlowExecutor, inputs, validators (18 names); the flow types are in src/types/flow.ts (33 names, re-exported by src/types/index.ts:4, so they are in the root and in ./types, but not in ./flows). ./flows already exists in package.jsonexports and in tsup.config.ts ('flows/index': 'src/flows/index.ts').
Integrations: src/tools/built-in/index.ts:9-12 re-exports ./email, ./jira, ./github, ./slack, so they are in the root and in ./tools. 24 names: createEmailTool, EmailToolOptions, createJiraTools, JiraTools, JiraConfig, JiraTicket, JiraComment, JiraTransition, createGitHubTools, GitHubTools, GitHubConfig, GitHubFile, GitHubSearchResult, GitHubPullRequest, GitHubBranch, createSlackTool, slackTool, postSlackAlert, postSlackAlertViaSandbox, buildSlackAlertPayload, SLACK_WEBHOOK_URL_ENV_KEY, SlackBlock, SlackAlertPayload, SlackToolOptions.
Utilities (20 names): src/security/crypto.ts (EncryptionUtils, DTOEncryptionFilter, DecryptionError, generatePassword, sha256), src/security/types.ts (EncryptionConfig, DTOEncryptionSettings, AuthorizationContext; only crypto.ts uses them), src/storage/StorageService.ts (StorageService, FileSystemAdapter, PathAdapter), src/storage/types.ts (IStorageService, StorageConfig), src/utils/validators.ts (validateWithSchema, safeValidate, isValidEmail, isValidUrl, isValidJson, sanitizeString, hasRequiredKeys). src/security/index.ts:8,11 re-exports ./types and ./crypto next to ./sandbox and ./credentialBroker. src/utils/index.ts re-exports ./errors, ./validators, ./errorCodes.
The two stores built on StorageService: StorageServiceApprovalStore (src/execution/ApprovalGate.ts:171) and LocalStorageCheckpointStore (src/execution/checkpoint.ts:238), both reaching the root through export * from './ApprovalGate' and export * from './checkpoint' in src/execution/index.ts:9,12. Their only purpose is to wrap a StorageService, so they move with it.
Internal users that must keep working: src/execution/ApprovalGate.ts:8 and src/execution/checkpoint.ts:7 import StorageService from '../storage'; src/triggers/adapters/SlackTriggerAdapter.ts:27 imports SLACK_WEBHOOK_URL_ENV_KEY from '../../tools/built-in/slack'; src/spec/specToAgent.ts:76-80 builds the error text "see src/tools/built-in/${name}.ts's create...Tools(config)", a path that does not exist for a user.
scripts/verify-docs-snippets.ts:66 declares the placeholder storage: import('@lousho/build-ai-agent').StorageService. Snippet paths are derived from exports (sourcePaths(), line 296-304: ./dist/X.d.ts maps to src/X.ts), so a new subpath's source file must sit at the path its types entry mirrors.
./core and ./types subpaths are unaffected by this ticket except that ./types loses the flow types (they move to ./flows).
Consumers that import a moving name from the root today (grep of every import { ... } from '@lousho/build-ai-agent'):
examples/: none. The examples import deep source paths (examples/ops-pipeline/mocks/mockSlackTool.ts:10 from src/tools/built-in/slack), which do not change.
Prose that names the moved exports as root exports: docs/api-overview.md:50, :590, :631-632; docs/tools.md:128; docs/errors.md:228-232; README.md:206 (utilities row).
Scope
In:
./flows: src/flows/index.ts also re-exports ../types/flow (all 33 flow types and FlowChunkType). src/types/index.ts drops export * from './flow' (so the root and ./types no longer export them). src/types/agent.ts keeps importing AgentFlow from ./flow internally. Root drops export * from './flows'.
./integrations (new): src/integrations/index.ts re-exports ../tools/built-in/email, jira, github, slack. The files stay where they are. src/tools/built-in/index.ts drops lines 9-12, so ./tools and the root no longer export them. Name decided: ./integrations (the plan's name; it says what they are: third-party services that need credentials).
./utils (new): src/utils/index.ts becomes the subpath barrel and exports exactly: ../security/crypto, the three types of ../security/types, ../storage/StorageService, ../storage/types, StorageServiceApprovalStore from ../execution/ApprovalGate, LocalStorageCheckpointStore from ../execution/checkpoint, and ./validators. It no longer re-exports ./errors or ./errorCodes.
Root src/index.ts: replace export * from './utils' with export * from './utils/errors' and export * from './utils/errorCodes'; replace export * from './security' by keeping src/security/index.ts but dropping its ./types and ./crypto lines; remove export * from './storage' and delete src/storage/index.ts (change ApprovalGate.ts:8 and checkpoint.ts:7 to import from '../storage/StorageService').
src/execution/index.ts: replace export * from './ApprovalGate' and export * from './checkpoint' with explicit named lists that leave out StorageServiceApprovalStore and LocalStorageCheckpointStore (every other current export stays).
package.jsonexports: add "./integrations" (./dist/integrations/index.{d.ts,mjs,js}) and "./utils" (./dist/utils/index.{d.ts,mjs,js}), same shape as the existing entries. No entry is removed.
tsup.config.tsentry: add 'integrations/index': 'src/integrations/index.ts' and 'utils/index': 'src/utils/index.ts'.
src/spec/specToAgent.ts:76-80: the message names the import a user can use: "...needs credentials: build it with createGitHubTools(config) from '@lousho/build-ai-agent/integrations' and pass it to createAgent() ...". Keep the error code LOUSHO_TOOL_NEEDS_CREDENTIALS.
src/providers/importGraph.test.ts:29: add 'integrations/index' and 'utils/index' to ENTRY_POINTS, so the new entries are checked for loading no optional peer at import time.
Agent Forge: change the five files above to import the flow names from @lousho/build-ai-agent/flows (split the import statements; keep the other names on the root import).
Docs: update every consumer and prose line listed under Current state to the new subpath. Add a table of entry points to docs/installation.md at the end of the existing ## Entry points share code (ESM and CJS) section (line 114): one row per subpath in exports and what it holds. Add no heading: the Arabic pages are matched by heading position, and a new heading here would shift every heading after it.
A test that pins the move: src/publicSurface.test.ts imports * as root from './index', * as flows from './flows', * as integrations from './integrations', * as utils from './utils' and asserts each moved value name is absent from root and present in its subpath; src/publicSurface.test-d.ts does the same for the moved type names with expectTypeOf / @ts-expect-error on import('./index'). Later tickets (A2a, A2b, A2c, A3) append their names to these two files.
CHANGELOG under ## [Unreleased], a ### Breaking entry with the migration note below.
Out:
Removing anything: A2a, A2b, A2c remove dead exports; this ticket only moves.
FlowAttr / FLOW_NODE_SPAN_NAME (src/execution/semconv.ts) and FlowExecutionError (src/execution/errors.ts:92) stay in the root: they are telemetry constants and an error class, not the flow engine.
The docs site (LinuxDevil/agent-sdk-docs): no page is added or renamed, so no navigation change; the R5 sync picks up the text changes.
Acceptance criteria
src/publicSurface.test.ts and src/publicSurface.test-d.ts exist and pass (npm test, npm run test:types).
The root exports exactly 97 fewer names than on main before this PR (51 flow names, 24 integration names, 20 utility names, the 2 StorageService stores). Measure with a TypeScript checker over src/index.ts (count the exports of the module symbol) before and after, and put both numbers in the pull request.
./flows, ./integrations and ./utils resolve from the packed tarball in ESM and CJS: npm run pack-smoke passes (it walks every exports entry).
./tools no longer exports the 24 integration names; ./types no longer exports the 33 flow types.
Agent Forge checks pass: typecheck, typecheck:server, test -- --run, test:server (run npm run build first; Forge resolves the SDK through file:../..).
npm run docs:verify-snippets -- --skip-build passes with the updated imports.
docs/installation.md has the entry-point table (no new heading); docs/flows.md, docs/utilities.md, docs/approvals.md, docs/sessions.md, docs/durable-execution.md, docs/api-overview.md, docs/tools.md, docs/errors.md and README.md name the new import paths. npm run docs:llms re-run and committed.
CHANGELOG ### Breaking entry with this migration note:
Flows, the Jira / GitHub / Slack / email tools, encryption, StorageService and the validators moved out of the package root. Import them from their subpath: FlowBuilder, FlowExecutor, validateFlow and every flow type (AgentFlow, EditorStep, FlowExecutionEvent, ...) from @lousho/build-ai-agent/flows; createJiraTools, createGitHubTools, createSlackTool, slackTool, postSlackAlert, createEmailTool and their types from @lousho/build-ai-agent/integrations; EncryptionUtils, DTOEncryptionFilter, DecryptionError, sha256, generatePassword, StorageService, StorageServiceApprovalStore, LocalStorageCheckpointStore and the validators (validateWithSchema, safeValidate, isValidEmail, ...) from @lousho/build-ai-agent/utils. The integrations are no longer in @lousho/build-ai-agent/tools and the flow types are no longer in @lousho/build-ai-agent/types. Nothing else changed: the classes and functions are the same. For file-backed stores with createAgent(), prefer fileStore(dir).
Live test
None: this ticket spends nothing.
Dependencies
R2 must merge first: the migration note points StorageService users to fileStore(dir).
Owner decision required before starting (see Notes).
Every wave-4 breaking ticket edits src/index.ts, src/execution/index.ts and CHANGELOG.md: run A1, A2a, A2b, A2c, A3, A5 one after another, not in parallel. A1 creates src/publicSurface.test.ts that the others extend.
Conflicts: G7 splits docs/api-overview.md; if G7 has merged, update the moved text wherever it now lives. N-wave tickets that add exports to src/index.ts may conflict textually; rebase.
Notes for the implementer
Owner question (record the answer in the issue before starting): "The package is public at 1.0.0-alpha.8. May A1 move flows, integrations and utilities out of the root (no removal, two new exports entries ./integrations and ./utils) in the next alpha?"
export * collisions: after the change, run npx tsc --noEmit and npm run build; tsup's dts build reports ambiguous re-exports. src/flows/index.ts re-exporting ../types/flow adds names that ./flows did not have; check none clashes with inputs.ts (FlowDefinitionNode is distinct).
Keep identity across entry points: tsup splitting: true puts shared classes in chunks, so StorageService from ./utils and the one createAgent() uses internally are the same class. Do not copy code into the new barrels; re-export only.
src/utils/index.ts currently has no internal importers other than src/index.ts:50 (verified with grep for from '../utils'), so turning it into the subpath barrel is safe; internal code imports ../utils/errors, ../utils/zodCompat and so on directly.
fallow treats exports entries as entry points, so the new barrels are not flagged; if it flags src/storage/index.ts before you delete it, that is expected.
Do not touch docs/research/ or docs/plan/ (history).
Round 2 ticket A1. Before starting, read the agent brief (worktree rules, verification list, live-test budget) and the plan. One ticket is one pull request; put Closes #<this issue> in it.
Goal
The package root exports 705 names (265 values, 440 types) while the docs use about 123 of them. Flows, the credentialed Jira / GitHub / Slack / email tools, encryption,
StorageServiceand the small validators are not agent functionality a new user needs from the root, and they make up 97 of those names. Moving them to./flows,./integrationsand./utilsshrinks the root's type surface without removing anything. Audit evidence:.agent-loop/audit2/our-report.mdsection 3 (705 root exports) and section 5 (rows Flows,EncryptionUtils,StorageService, Jira, GitHub, Slack and email, Validators).Current state
Verified on
mainatcc5ddb8:src/index.tsisexport *over 26 modules, including./types(line 15),./tools(21),./flows(24),./execution(31),./security(37),./storage(40) and./utils(50).src/flows/index.tsre-exportsFlowBuilder,FlowExecutor,inputs,validators(18 names); the flow types are insrc/types/flow.ts(33 names, re-exported bysrc/types/index.ts:4, so they are in the root and in./types, but not in./flows)../flowsalready exists inpackage.jsonexportsand intsup.config.ts('flows/index': 'src/flows/index.ts').src/tools/built-in/index.ts:9-12re-exports./email,./jira,./github,./slack, so they are in the root and in./tools. 24 names:createEmailTool,EmailToolOptions,createJiraTools,JiraTools,JiraConfig,JiraTicket,JiraComment,JiraTransition,createGitHubTools,GitHubTools,GitHubConfig,GitHubFile,GitHubSearchResult,GitHubPullRequest,GitHubBranch,createSlackTool,slackTool,postSlackAlert,postSlackAlertViaSandbox,buildSlackAlertPayload,SLACK_WEBHOOK_URL_ENV_KEY,SlackBlock,SlackAlertPayload,SlackToolOptions.src/security/crypto.ts(EncryptionUtils,DTOEncryptionFilter,DecryptionError,generatePassword,sha256),src/security/types.ts(EncryptionConfig,DTOEncryptionSettings,AuthorizationContext; onlycrypto.tsuses them),src/storage/StorageService.ts(StorageService,FileSystemAdapter,PathAdapter),src/storage/types.ts(IStorageService,StorageConfig),src/utils/validators.ts(validateWithSchema,safeValidate,isValidEmail,isValidUrl,isValidJson,sanitizeString,hasRequiredKeys).src/security/index.ts:8,11re-exports./typesand./cryptonext to./sandboxand./credentialBroker.src/utils/index.tsre-exports./errors,./validators,./errorCodes.StorageService:StorageServiceApprovalStore(src/execution/ApprovalGate.ts:171) andLocalStorageCheckpointStore(src/execution/checkpoint.ts:238), both reaching the root throughexport * from './ApprovalGate'andexport * from './checkpoint'insrc/execution/index.ts:9,12. Their only purpose is to wrap aStorageService, so they move with it.src/execution/ApprovalGate.ts:8andsrc/execution/checkpoint.ts:7importStorageServicefrom'../storage';src/triggers/adapters/SlackTriggerAdapter.ts:27importsSLACK_WEBHOOK_URL_ENV_KEYfrom'../../tools/built-in/slack';src/spec/specToAgent.ts:76-80builds the error text "see src/tools/built-in/${name}.ts's create...Tools(config)", a path that does not exist for a user.scripts/verify-docs-snippets.ts:66declares the placeholderstorage: import('@lousho/build-ai-agent').StorageService. Snippetpathsare derived fromexports(sourcePaths(), line 296-304:./dist/X.d.tsmaps tosrc/X.ts), so a new subpath's source file must sit at the path itstypesentry mirrors../coreand./typessubpaths are unaffected by this ticket except that./typesloses the flow types (they move to./flows).Consumers that import a moving name from the root today (grep of every
import { ... } from '@lousho/build-ai-agent'):apps/agent-forge/server/buildAgent.ts:17(type AgentFlow)apps/agent-forge/server/logEntries.ts:6(FlowExecutionEvent,FlowExecutionEventOf)apps/agent-forge/server/runRegistry.ts:13(FlowExecutor)apps/agent-forge/src/graph/graphToFlow.ts:1(AgentFlow,EditorStep)apps/agent-forge/src/graph/__tests__/graphToFlow.test.ts:2(FlowExecutor)docs/flows.md:9(FlowBuilder,FlowExecutor,EditorStep)docs/utilities.md:10(EncryptionUtils,sha256) and:31(StorageService)docs/approvals.md:331(StorageServiceApprovalStore, withAgentExecutor), table row at:362docs/sessions.md:239-245(LocalStorageCheckpointStore,StorageServiceApprovalStore), table row at:230docs/durable-execution.md:11(LocalStorageCheckpointStore)examples/: none. The examples import deep source paths (examples/ops-pipeline/mocks/mockSlackTool.ts:10fromsrc/tools/built-in/slack), which do not change.Prose that names the moved exports as root exports:
docs/api-overview.md:50,:590,:631-632;docs/tools.md:128;docs/errors.md:228-232;README.md:206(utilities row).Scope
In:
./flows:src/flows/index.tsalso re-exports../types/flow(all 33 flow types andFlowChunkType).src/types/index.tsdropsexport * from './flow'(so the root and./typesno longer export them).src/types/agent.tskeeps importingAgentFlowfrom./flowinternally. Root dropsexport * from './flows'../integrations(new):src/integrations/index.tsre-exports../tools/built-in/email,jira,github,slack. The files stay where they are.src/tools/built-in/index.tsdrops lines 9-12, so./toolsand the root no longer export them. Name decided:./integrations(the plan's name; it says what they are: third-party services that need credentials)../utils(new):src/utils/index.tsbecomes the subpath barrel and exports exactly:../security/crypto, the three types of../security/types,../storage/StorageService,../storage/types,StorageServiceApprovalStorefrom../execution/ApprovalGate,LocalStorageCheckpointStorefrom../execution/checkpoint, and./validators. It no longer re-exports./errorsor./errorCodes.src/index.ts: replaceexport * from './utils'withexport * from './utils/errors'andexport * from './utils/errorCodes'; replaceexport * from './security'by keepingsrc/security/index.tsbut dropping its./typesand./cryptolines; removeexport * from './storage'and deletesrc/storage/index.ts(changeApprovalGate.ts:8andcheckpoint.ts:7to import from'../storage/StorageService').src/execution/index.ts: replaceexport * from './ApprovalGate'andexport * from './checkpoint'with explicit named lists that leave outStorageServiceApprovalStoreandLocalStorageCheckpointStore(every other current export stays).package.jsonexports: add"./integrations"(./dist/integrations/index.{d.ts,mjs,js}) and"./utils"(./dist/utils/index.{d.ts,mjs,js}), same shape as the existing entries. No entry is removed.tsup.config.tsentry: add'integrations/index': 'src/integrations/index.ts'and'utils/index': 'src/utils/index.ts'.src/spec/specToAgent.ts:76-80: the message names the import a user can use: "...needs credentials: build it with createGitHubTools(config) from '@lousho/build-ai-agent/integrations' and pass it to createAgent() ...". Keep the error codeLOUSHO_TOOL_NEEDS_CREDENTIALS.src/providers/importGraph.test.ts:29: add'integrations/index'and'utils/index'toENTRY_POINTS, so the new entries are checked for loading no optional peer at import time.scripts/verify-docs-snippets.ts:66:storageplaceholder becomesimport('@lousho/build-ai-agent/utils').StorageService.@lousho/build-ai-agent/flows(split the import statements; keep the other names on the root import).docs/installation.mdat the end of the existing## Entry points share code (ESM and CJS)section (line 114): one row per subpath inexportsand what it holds. Add no heading: the Arabic pages are matched by heading position, and a new heading here would shift every heading after it.src/publicSurface.test.tsimports* as root from './index',* as flows from './flows',* as integrations from './integrations',* as utils from './utils'and asserts each moved value name is absent fromrootand present in its subpath;src/publicSurface.test-d.tsdoes the same for the moved type names withexpectTypeOf/@ts-expect-erroronimport('./index'). Later tickets (A2a, A2b, A2c, A3) append their names to these two files.## [Unreleased], a### Breakingentry with the migration note below.Out:
AgentBuilder,AgentExecutor,ToolRegistry,resumeAfterApproval: A3.FlowAttr/FLOW_NODE_SPAN_NAME(src/execution/semconv.ts) andFlowExecutionError(src/execution/errors.ts:92) stay in the root: they are telemetry constants and an error class, not the flow engine.LinuxDevil/agent-sdk-docs): no page is added or renamed, so no navigation change; the R5 sync picks up the text changes.Acceptance criteria
src/publicSurface.test.tsandsrc/publicSurface.test-d.tsexist and pass (npm test,npm run test:types).mainbefore this PR (51 flow names, 24 integration names, 20 utility names, the 2StorageServicestores). Measure with a TypeScript checker oversrc/index.ts(count the exports of the module symbol) before and after, and put both numbers in the pull request../flows,./integrationsand./utilsresolve from the packed tarball in ESM and CJS:npm run pack-smokepasses (it walks everyexportsentry)../toolsno longer exports the 24 integration names;./typesno longer exports the 33 flow types.typecheck,typecheck:server,test -- --run,test:server(runnpm run buildfirst; Forge resolves the SDK throughfile:../..).npm run docs:verify-snippets -- --skip-buildpasses with the updated imports.docs/installation.mdhas the entry-point table (no new heading);docs/flows.md,docs/utilities.md,docs/approvals.md,docs/sessions.md,docs/durable-execution.md,docs/api-overview.md,docs/tools.md,docs/errors.mdandREADME.mdname the new import paths.npm run docs:llmsre-run and committed.### Breakingentry with this migration note:Live test
None: this ticket spends nothing.
Dependencies
StorageServiceusers tofileStore(dir).src/index.ts,src/execution/index.tsandCHANGELOG.md: run A1, A2a, A2b, A2c, A3, A5 one after another, not in parallel. A1 createssrc/publicSurface.test.tsthat the others extend.docs/api-overview.md; if G7 has merged, update the moved text wherever it now lives. N-wave tickets that add exports tosrc/index.tsmay conflict textually; rebase.Notes for the implementer
exportsentries./integrationsand./utils) in the next alpha?"export *collisions: after the change, runnpx tsc --noEmitandnpm run build; tsup's dts build reports ambiguous re-exports.src/flows/index.tsre-exporting../types/flowadds names that./flowsdid not have; check none clashes withinputs.ts(FlowDefinitionNodeis distinct).splitting: trueputs shared classes in chunks, soStorageServicefrom./utilsand the onecreateAgent()uses internally are the same class. Do not copy code into the new barrels; re-export only.src/utils/index.tscurrently has no internal importers other thansrc/index.ts:50(verified with grep forfrom '../utils'), so turning it into the subpath barrel is safe; internal code imports../utils/errors,../utils/zodCompatand so on directly.fallowtreatsexportsentries as entry points, so the new barrels are not flagged; if it flagssrc/storage/index.tsbefore you delete it, that is expected.docs/research/ordocs/plan/(history).Round 2 ticket
A1. Before starting, read the agent brief (worktree rules, verification list, live-test budget) and the plan. One ticket is one pull request; putCloses #<this issue>in it.