import type { AgencyNode, AgencyProgram } from "../../types.js"; import type { TsNode } from "../../ir/tsIR.js"; /** * Two helpers for the orchestration phase of `TypeScriptBuilder.build()`: * * 1. {@link partitionProgram} — single pass over the program nodes * that sorts them into the buckets the output assembly cares * about (static-var init, global init, top-level declarations). * 2. {@link assembleSections} — concatenates the already-built * pieces (imports, builtins, type aliases, init functions, * generated statements, sourcemap) into the final TsNode in the * correct, fixed order. * * Both are functions, not classes — they hold no state of their own; * the builder still owns all of the shared scratch state. Pulling * them out makes `build()` read declaratively as * "partition → assemble" rather than ~180 lines of inline glue. */ export type PartitionDeps = { processNode: (node: AgencyNode) => TsNode; processNodeInGlobalInit: (node: AgencyNode) => TsNode; buildHandlerArrow: (handlerName: string) => TsNode; isTopLevelDeclaration: (node: AgencyNode) => boolean; moduleId: string; /** * Optional per-phase initialization plan from `compileClosure`. When * present, local var assignments are emitted in `localOrder` rather * than source order, ensuring cross-module dependencies (Example 1 * from `agent-init-design.md`) resolve before reads. Bare top-level * statements stay in source order. * * When absent (legacy callers that bypass `compileClosure`), partition * falls back to source order. The lazy isInitialized guards remain the * safety net for that path. */ staticOrder?: string[]; globalOrder?: string[]; }; export type ProgramPartition = { /** Names of `static` variables declared at module level. */ staticVarNames: Set; /** Subset of `staticVarNames` that are `export`-ed. */ exportedStaticVarNames: Set; /** Statements that initialize static variables, run once. */ staticInitStatements: TsNode[]; /** Statements that initialize global variables / run top-level code per execution. */ globalInitStatements: TsNode[]; /** Top-level declarations (functions, graph nodes, type aliases, classes). */ topLevelStatements: TsNode[]; /** * Top-level `callback(...)` registration calls. Kept separate from * `globalInitStatements` so the codegen can emit them inside a * rerunnable `__registerTopLevelCallbacks(__ctx)` helper that fires on * every fresh run AND every resume. Globals are checkpointed and * restored on resume; the `topLevelCallbacks` array on the runtime * context is not — so the callbacks must be re-registered on every * resume cycle. * * Critical ordering: resume paths (`respondToInterrupts`, * `rewindFrom`) call `registerTopLevelCallbacks(execCtx)` BEFORE * `restoreState(...)`. The `_callbackImpl` stdlib helper routes a * registration to `ctx.topLevelCallbacks` only when the state stack is * empty (i.e., the call is happening at module-init / top-level * position); once `restoreState` has rebuilt a non-empty stack, the * same registration call would be misrouted as a scoped callback on * the wrong frame. If you change the order of these two calls, every * top-level callback registered after the first interrupt cycle will * either silently land on a foreign frame or not fire at all. */ topLevelCallbackStatements: TsNode[]; }; /** * Walk the program once and route each node into the right bucket: * * - `static` assignments (and `with handler { static x = ... }`) * contribute names + frozen init statements. * - `global` assignments (and their `with handler` form) contribute * `__ctx.globals.set(...)` calls. * - Top-level declarations (per `isTopLevelDeclaration`) become * module-scope generated statements. * - Anything else (bare expressions, function calls, …) goes into * `__initializeGlobals` so it can access `__ctx`. */ export declare function partitionProgram(program: AgencyProgram, deps: PartitionDeps): ProgramPartition; export type AssembleSectionsOpts = { moduleId: string; preprocess: TsNode[]; importStatements: TsNode[]; /** Raw string output of `generateImports()`. Already-rendered template. */ generatedImports: string; /** Raw string output of `generateBuiltins()`. Already-rendered template. */ generatedBuiltins: string; toolRegistrations: TsNode[]; typeAliases: TsNode[]; staticVarNames: Set; exportedStaticVarNames: Set; staticInitStatements: TsNode[]; globalInitStatements: TsNode[]; topLevelCallbackStatements: TsNode[]; generatedStatements: TsNode[]; postprocess: TsNode[]; /** JSON-stringified source map, embedded into the generated module. */ sourceMapJson: string; /** * Per-phase cross-module dependencies sourced from the topsort plan. * For each entry, the generated `__initializeStatic` / * `__initializeGlobals` body awaits the corresponding function on * that source module before running its own assignments. Together with * `reorderTagged` (which orders local statements by topsort) this is * what makes Example 1 (`fooStatic = barStatic + "!"`) yield "hello!" * instead of throwing the read-before-init trap. * * Empty / absent when the legacy callers bypass `compileClosure`. */ staticAwaitModules?: { localImport: string; sourceModuleId: string; }[]; globalAwaitModules?: { localImport: string; sourceModuleId: string; }[]; /** * Absolute moduleId used as the registry key for * `__registerStaticInit` / `__registerGlobalsInit`. Falls back to * `moduleId` when the plan didn't supply one (legacy callers); in * that case cross-module awaits won't find this module's init in the * registry, but the lazy isInitialized guard still keeps things * correct for same-module flows. */ registryModuleId?: string; /** * Plan-driven local init orders. Used purely for the human-readable * banner comments above `__initializeStatic` / `__initializeGlobals` * — the actual order is already baked into `staticInitStatements` / * `globalInitStatements` by `reorderTagged` during partition. */ staticLocalOrder?: string[]; globalLocalOrder?: string[]; }; /** * Concatenate the per-section outputs into the final generated module, * in the canonical order: * * preprocess * importStatements * generated imports (template) * generated builtins (template) * tool registrations * type aliases * static-var declarations + __initializeStatic + __getStaticVars (if any) * __initializeGlobals * generated statements * postprocess * __sourceMap export */ export declare function assembleSections(opts: AssembleSectionsOpts): TsNode;