gauss-ai 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +489 -0
- package/LICENSE +21 -0
- package/README.md +269 -0
- package/dist/a2a/index.cjs +7 -0
- package/dist/a2a/index.cjs.map +1 -0
- package/dist/a2a/index.d.cts +30 -0
- package/dist/a2a/index.d.ts +30 -0
- package/dist/a2a/index.js +7 -0
- package/dist/a2a/index.js.map +1 -0
- package/dist/agent-UIQDSYCE.js +16 -0
- package/dist/agent-UIQDSYCE.js.map +1 -0
- package/dist/agent-builder-8W3mBR-N.d.ts +1075 -0
- package/dist/agent-builder-GEMYdb1p.d.cts +1075 -0
- package/dist/agent-graph-AMQYAWNF.js +1422 -0
- package/dist/agent-graph-AMQYAWNF.js.map +1 -0
- package/dist/ai-sdk-mcp.adapter-SEN6KHNU.js +124 -0
- package/dist/ai-sdk-mcp.adapter-SEN6KHNU.js.map +1 -0
- package/dist/browser/index.js +10 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/bun-runtime.adapter-MQDAJLQM.js +8 -0
- package/dist/bun-runtime.adapter-MQDAJLQM.js.map +1 -0
- package/dist/bun-runtime.adapter-XKOUXVAK.cjs +8 -0
- package/dist/bun-runtime.adapter-XKOUXVAK.cjs.map +1 -0
- package/dist/chat-A3XMRPJL.js +129 -0
- package/dist/chat-A3XMRPJL.js.map +1 -0
- package/dist/chunk-2ZRU47NC.js +91 -0
- package/dist/chunk-2ZRU47NC.js.map +1 -0
- package/dist/chunk-3LD3JTH4.cjs +18 -0
- package/dist/chunk-3LD3JTH4.cjs.map +1 -0
- package/dist/chunk-5FE5TG2W.cjs +16 -0
- package/dist/chunk-5FE5TG2W.cjs.map +1 -0
- package/dist/chunk-6XF673YC.cjs +436 -0
- package/dist/chunk-6XF673YC.cjs.map +1 -0
- package/dist/chunk-7CKWZJNS.js +230 -0
- package/dist/chunk-7CKWZJNS.js.map +1 -0
- package/dist/chunk-BI2G665F.js +4588 -0
- package/dist/chunk-BI2G665F.js.map +1 -0
- package/dist/chunk-C5NLWJS2.js +139 -0
- package/dist/chunk-C5NLWJS2.js.map +1 -0
- package/dist/chunk-CJZ66SU3.cjs +4321 -0
- package/dist/chunk-CJZ66SU3.cjs.map +1 -0
- package/dist/chunk-DAMT2CXW.cjs +91 -0
- package/dist/chunk-DAMT2CXW.cjs.map +1 -0
- package/dist/chunk-E7WG3MO5.js +18 -0
- package/dist/chunk-E7WG3MO5.js.map +1 -0
- package/dist/chunk-EFDM6R4J.js +99 -0
- package/dist/chunk-EFDM6R4J.js.map +1 -0
- package/dist/chunk-F7WIPPEO.js +256 -0
- package/dist/chunk-F7WIPPEO.js.map +1 -0
- package/dist/chunk-FAYDE67N.js +6927 -0
- package/dist/chunk-FAYDE67N.js.map +1 -0
- package/dist/chunk-GAE2KKCM.js +21 -0
- package/dist/chunk-GAE2KKCM.js.map +1 -0
- package/dist/chunk-INLNGRXM.cjs +130 -0
- package/dist/chunk-INLNGRXM.cjs.map +1 -0
- package/dist/chunk-JKXKXB5O.js +130 -0
- package/dist/chunk-JKXKXB5O.js.map +1 -0
- package/dist/chunk-K6SAETGP.js +375 -0
- package/dist/chunk-K6SAETGP.js.map +1 -0
- package/dist/chunk-KEASLAYR.js +157 -0
- package/dist/chunk-KEASLAYR.js.map +1 -0
- package/dist/chunk-KKJVNM6O.js +436 -0
- package/dist/chunk-KKJVNM6O.js.map +1 -0
- package/dist/chunk-KYIMVRIM.js +16 -0
- package/dist/chunk-KYIMVRIM.js.map +1 -0
- package/dist/chunk-MB7NXIZD.js +4321 -0
- package/dist/chunk-MB7NXIZD.js.map +1 -0
- package/dist/chunk-MHHDXPGE.js +209 -0
- package/dist/chunk-MHHDXPGE.js.map +1 -0
- package/dist/chunk-NE6JJA5W.js +401 -0
- package/dist/chunk-NE6JJA5W.js.map +1 -0
- package/dist/chunk-PF46XZBF.cjs +6927 -0
- package/dist/chunk-PF46XZBF.cjs.map +1 -0
- package/dist/chunk-PSJIAGDE.cjs +375 -0
- package/dist/chunk-PSJIAGDE.cjs.map +1 -0
- package/dist/chunk-PWOQDXNQ.js +16 -0
- package/dist/chunk-PWOQDXNQ.js.map +1 -0
- package/dist/chunk-QYOMQBBZ.cjs +230 -0
- package/dist/chunk-QYOMQBBZ.cjs.map +1 -0
- package/dist/chunk-UDFXLC4J.cjs +16 -0
- package/dist/chunk-UDFXLC4J.cjs.map +1 -0
- package/dist/chunk-UO4NGXRT.cjs +259 -0
- package/dist/chunk-UO4NGXRT.cjs.map +1 -0
- package/dist/chunk-UPFDFLEW.js +40 -0
- package/dist/chunk-UPFDFLEW.js.map +1 -0
- package/dist/chunk-V55JSQS7.cjs +16 -0
- package/dist/chunk-V55JSQS7.cjs.map +1 -0
- package/dist/chunk-VJADHXZL.cjs +16 -0
- package/dist/chunk-VJADHXZL.cjs.map +1 -0
- package/dist/chunk-VRWD7LCI.js +59 -0
- package/dist/chunk-VRWD7LCI.js.map +1 -0
- package/dist/chunk-WKKQ443C.js +487 -0
- package/dist/chunk-WKKQ443C.js.map +1 -0
- package/dist/chunk-X2GHUHAF.js +436 -0
- package/dist/chunk-X2GHUHAF.js.map +1 -0
- package/dist/chunk-XLGW3XNI.cjs +256 -0
- package/dist/chunk-XLGW3XNI.cjs.map +1 -0
- package/dist/chunk-ZFJKX4DP.js +16 -0
- package/dist/chunk-ZFJKX4DP.js.map +1 -0
- package/dist/chunk-ZM2OEWM2.js +259 -0
- package/dist/chunk-ZM2OEWM2.js.map +1 -0
- package/dist/chunk-ZNAIP2XV.js +16 -0
- package/dist/chunk-ZNAIP2XV.js.map +1 -0
- package/dist/chunk-ZYFAZYSL.js +42 -0
- package/dist/chunk-ZYFAZYSL.js.map +1 -0
- package/dist/cli/index.js +421 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config-4MHT6TQW.js +153 -0
- package/dist/config-4MHT6TQW.js.map +1 -0
- package/dist/config-REERQFK4.cjs +153 -0
- package/dist/config-REERQFK4.cjs.map +1 -0
- package/dist/cost-tracker-JLOU7IZJ.js +7 -0
- package/dist/cost-tracker-JLOU7IZJ.js.map +1 -0
- package/dist/demo-C52GMSYH.js +188 -0
- package/dist/demo-C52GMSYH.js.map +1 -0
- package/dist/deno/index.js +306 -0
- package/dist/deno/index.js.map +1 -0
- package/dist/deno-runtime.adapter-F744HY7K.js +8 -0
- package/dist/deno-runtime.adapter-F744HY7K.js.map +1 -0
- package/dist/deno-runtime.adapter-RFEVNSCV.cjs +8 -0
- package/dist/deno-runtime.adapter-RFEVNSCV.cjs.map +1 -0
- package/dist/dev-D7DDVDA4.js +218 -0
- package/dist/dev-D7DDVDA4.js.map +1 -0
- package/dist/edge/index.js +10 -0
- package/dist/edge/index.js.map +1 -0
- package/dist/edge-runtime.adapter-UQCW2F7X.js +8 -0
- package/dist/edge-runtime.adapter-UQCW2F7X.js.map +1 -0
- package/dist/edge-runtime.adapter-YED6F3AY.cjs +8 -0
- package/dist/edge-runtime.adapter-YED6F3AY.cjs.map +1 -0
- package/dist/graph-MGFAQZ5W.js +50 -0
- package/dist/graph-MGFAQZ5W.js.map +1 -0
- package/dist/graph-visualization-HBSVQXJK.js +9 -0
- package/dist/graph-visualization-HBSVQXJK.js.map +1 -0
- package/dist/index-BRgqNnh3.d.cts +982 -0
- package/dist/index-CZxpYUxZ.d.ts +982 -0
- package/dist/index.cjs +14789 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +10275 -0
- package/dist/index.d.ts +10275 -0
- package/dist/index.js +14789 -0
- package/dist/index.js.map +1 -0
- package/dist/init-CFWXTQ35.js +133 -0
- package/dist/init-CFWXTQ35.js.map +1 -0
- package/dist/llm-VWO4MC7J.cjs +17 -0
- package/dist/llm-VWO4MC7J.cjs.map +1 -0
- package/dist/llm-XLXVSPBI.js +17 -0
- package/dist/llm-XLXVSPBI.js.map +1 -0
- package/dist/logging-WRAK5ZXT.js +33 -0
- package/dist/logging-WRAK5ZXT.js.map +1 -0
- package/dist/metrics-FAHZVVD4.js +47 -0
- package/dist/metrics-FAHZVVD4.js.map +1 -0
- package/dist/node/index.cjs +280 -0
- package/dist/node/index.cjs.map +1 -0
- package/dist/node/index.d.cts +51 -0
- package/dist/node/index.d.ts +51 -0
- package/dist/node/index.js +280 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node-runtime.adapter-5L7PJ6W2.js +8 -0
- package/dist/node-runtime.adapter-5L7PJ6W2.js.map +1 -0
- package/dist/node-runtime.adapter-CCRZVGHB.cjs +8 -0
- package/dist/node-runtime.adapter-CCRZVGHB.cjs.map +1 -0
- package/dist/persist-usage-WTBTCWEF.js +7 -0
- package/dist/persist-usage-WTBTCWEF.js.map +1 -0
- package/dist/plugin-RCPBWUUA.js +207 -0
- package/dist/plugin-RCPBWUUA.js.map +1 -0
- package/dist/plugins/index.cjs +75 -0
- package/dist/plugins/index.cjs.map +1 -0
- package/dist/plugins/index.d.cts +8 -0
- package/dist/plugins/index.d.ts +8 -0
- package/dist/plugins/index.js +75 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins-L4ING3CX.js +4625 -0
- package/dist/plugins-L4ING3CX.js.map +1 -0
- package/dist/providers/index.cjs +189 -0
- package/dist/providers/index.cjs.map +1 -0
- package/dist/providers/index.d.cts +168 -0
- package/dist/providers/index.d.ts +168 -0
- package/dist/providers/index.js +189 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers-3RNQ5CKZ.js +59 -0
- package/dist/providers-3RNQ5CKZ.js.map +1 -0
- package/dist/providers-66GPXUGQ.cjs +59 -0
- package/dist/providers-66GPXUGQ.cjs.map +1 -0
- package/dist/repl-K6QN4I2S.js +678 -0
- package/dist/repl-K6QN4I2S.js.map +1 -0
- package/dist/rest/index.cjs +17 -0
- package/dist/rest/index.cjs.map +1 -0
- package/dist/rest/index.d.cts +102 -0
- package/dist/rest/index.d.ts +102 -0
- package/dist/rest/index.js +17 -0
- package/dist/rest/index.js.map +1 -0
- package/dist/runtime-deno.js +15 -0
- package/dist/runtime-deno.js.map +1 -0
- package/dist/runtime-edge.js +15 -0
- package/dist/runtime-edge.js.map +1 -0
- package/dist/runtime-node.js +15 -0
- package/dist/runtime-node.js.map +1 -0
- package/dist/scraping/index.cjs +11 -0
- package/dist/scraping/index.cjs.map +1 -0
- package/dist/scraping/index.d.cts +17 -0
- package/dist/scraping/index.d.ts +17 -0
- package/dist/scraping/index.js +11 -0
- package/dist/scraping/index.js.map +1 -0
- package/dist/semantic-scraping.port-CZWUea88.d.cts +54 -0
- package/dist/semantic-scraping.port-CZWUea88.d.ts +54 -0
- package/dist/server/index.js +166 -0
- package/dist/server/index.js.map +1 -0
- package/dist/testing/index.cjs +25 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +63 -0
- package/dist/testing/index.d.ts +63 -0
- package/dist/testing/index.js +25 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/token-counter.port-CRgxZZGe.d.ts +334 -0
- package/dist/token-counter.port-D7BHMCRR.d.cts +334 -0
- package/dist/tools-BZM33OBZ.js +10 -0
- package/dist/tools-BZM33OBZ.js.map +1 -0
- package/dist/tracing-XA3TEWP4.js +48 -0
- package/dist/tracing-XA3TEWP4.js.map +1 -0
- package/dist/types-CVsP7gFI.d.cts +235 -0
- package/dist/types-CVsP7gFI.d.ts +235 -0
- package/dist/virtual-fs.adapter-BBLS-3AY.d.ts +26 -0
- package/dist/virtual-fs.adapter-nb0CTYOj.d.cts +26 -0
- package/dist/workflow/index.cjs +9 -0
- package/dist/workflow/index.cjs.map +1 -0
- package/dist/workflow/index.d.cts +62 -0
- package/dist/workflow/index.d.ts +62 -0
- package/dist/workflow/index.js +9 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow.port-BaCttxrw.d.cts +153 -0
- package/dist/workflow.port-BaCttxrw.d.ts +153 -0
- package/package.json +230 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/giulioleone/Sviluppo/gauss/gauss-flow/dist/chunk-PF46XZBF.cjs","../src/utils/abstract-builder.ts","../src/agent/agent-config.ts","../src/adapters/memory/in-memory.adapter.ts","../src/adapters/runtime/detect-runtime.ts","../src/agent/event-bus.ts","../src/context/token-tracker.ts","../src/agent/approval-manager.ts","../src/tools/filesystem/ls.tool.ts","../src/tools/filesystem/read-file.tool.ts","../src/tools/filesystem/write-file.tool.ts","../src/tools/filesystem/edit-file.tool.ts","../src/tools/filesystem/glob.tool.ts","../src/tools/filesystem/grep.tool.ts","../src/tools/filesystem/index.ts","../src/tools/planning/write-todos.tool.ts","../src/tools/planning/shared.ts","../src/tools/planning/review-todos.tool.ts","../src/domain/plan.schema.ts","../src/tools/planning/plan-create.tool.ts","../src/tools/planning/plan-shared.ts","../src/tools/planning/plan-update.tool.ts","../src/tools/planning/plan-status.tool.ts","../src/tools/planning/plan-visualize.tool.ts","../src/graph/priority-queue.ts","../src/graph/worker-pool.ts","../src/graph/async-channel.ts","../src/graph/incremental-ready-tracker.ts","../src/graph/token-budget-controller.ts","../src/graph/fork-coordinator.ts","../src/graph/graph-executor.ts","../src/graph/shared-context.ts","../src/adapters/graph-visualization/ascii-graph.adapter.ts","../src/adapters/graph-visualization/mermaid-graph.adapter.ts","../src/domain/graph.schema.ts","../src/agent/tool-manager.ts","../src/tools/planning/plan-to-graph.ts","../src/tools/planning/index.ts","../src/tools/policy/index.ts","../src/tools/subagent/dispatch.tool.ts","../src/tools/subagent/subagent-registry.ts","../src/tools/subagent/poll.tool.ts","../src/tools/subagent/await.tool.ts","../src/tools/subagent/subagent-scheduler.ts","../src/tools/subagent/index.ts","../src/agent/execution-engine.ts","../src/agent/lifecycle.ts","../src/middleware/chain.ts","../src/agent/defaults.ts","../src/adapters/resilience/rate-limiter.ts","../src/agent/agent-builder.ts","../src/agent/agent.ts","../src/graph/agent-node.ts","../src/graph/agent-graph.ts","../src/rest/router.ts","../src/rest/server.ts","../src/rest/handlers.ts"],"names":["z","z2","result","leftPad","sanitize","lastStep","DEFAULT_POOL_CONFIG","PriorityQueue"],"mappings":"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;AACF,MAAA;AACP,IAAA;AAGY,IAAA;AACA,IAAA;AACA,IAAA;AAGH,IAAA;AACD,MAAA;AACA,QAAA;AACI,QAAA;AACV,MAAA;AACK,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACI,MAAA;AACF,QAAA;AACP,MAAA;AACF,IAAA;AACF,EAAA;AAEQ,EAAA;AACI,IAAA;AACN,IAAA;AACA,IAAA;AACA,IAAA;AACN,EAAA;AAEqB,EAAA;AAEf,IAAA;AAEM,IAAA;AAEJ,IAAA;AACD,IAAA;AAEE,IAAA;AACA,IAAA;AACT,EAAA;AAEQ,mBAAA;AAID,IAAA;AAEO,IAAA;AACN,IAAA;AACA,IAAA;AAGI,IAAA;AACD,MAAA;AACT,IAAA;AAGM,IAAA;AACM,IAAA;AACH,MAAA;AACT,IAAA;AAEI,IAAA;AACI,MAAA;AACC,IAAA;AACE,MAAA;AACP,QAAA;AACF,MAAA;AACF,IAAA;AACF,EAAA;AAEa,EAAA;AACF,IAAA;AACD,MAAA;AACR,IAAA;AACU,IAAA;AACA,IAAA;AACH,MAAA;AACA,MAAA;AACA,MAAA;AACN,IAAA;AACH,EAAA;AAE6B,EAAA;AACjB,IAAA;AACE,MAAA;AACL,MAAA;AACN,IAAA;AACQ,IAAA;AACD,MAAA;AACR,IAAA;AACF,EAAA;AACF;AvD8hNgB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/giulioleone/Sviluppo/gauss/gauss-flow/dist/chunk-PF46XZBF.cjs","sourcesContent":[null,"export abstract class AbstractBuilder<T> {\n protected abstract validate(): void;\n protected abstract construct(): T;\n\n build(): T {\n this.validate();\n return this.construct();\n }\n}\n","// =============================================================================\n// Agent Configuration — Defaults and builder\n// =============================================================================\n\nimport type {\n ContextConfig,\n ApprovalConfig,\n SubagentConfig,\n CheckpointConfig,\n} from \"../types.js\";\n\nexport interface ResolvedSubagentConfig {\n maxDepth: number;\n timeoutMs: number;\n allowNesting: boolean;\n hooks?: SubagentConfig[\"hooks\"];\n}\n\nexport const DEFAULT_CONTEXT_CONFIG: Required<ContextConfig> = {\n summarizationThreshold: 0.7,\n truncationThreshold: 0.85,\n offloadTokenThreshold: 20_000,\n summarizationModel: null, // Falls back to agent model at runtime\n preserveRecentMessages: 10,\n};\n\nexport const DEFAULT_APPROVAL_CONFIG: Required<ApprovalConfig> = {\n defaultMode: \"approve-all\",\n requireApproval: [],\n autoApprove: [],\n onApprovalRequired: async () => true,\n};\n\n/** Subagent execution timeout in ms (5 minutes) */\nconst DEFAULT_SUBAGENT_TIMEOUT_MS = 300_000;\n\nexport const DEFAULT_SUBAGENT_CONFIG: ResolvedSubagentConfig = {\n maxDepth: 3,\n timeoutMs: DEFAULT_SUBAGENT_TIMEOUT_MS,\n allowNesting: true,\n};\n\nexport const DEFAULT_CHECKPOINT_CONFIG: Required<CheckpointConfig> = {\n enabled: true,\n baseStepInterval: 5,\n maxCheckpoints: 10,\n};\n\nexport function resolveContextConfig(\n partial?: ContextConfig,\n): Required<ContextConfig> {\n if (!partial) return { ...DEFAULT_CONTEXT_CONFIG };\n return { ...DEFAULT_CONTEXT_CONFIG, ...partial };\n}\n\nexport function resolveApprovalConfig(\n partial?: ApprovalConfig,\n): Required<ApprovalConfig> {\n if (!partial) return { ...DEFAULT_APPROVAL_CONFIG };\n return { ...DEFAULT_APPROVAL_CONFIG, ...partial };\n}\n\nexport function resolveSubagentConfig(\n partial?: SubagentConfig,\n): ResolvedSubagentConfig {\n if (!partial) return { ...DEFAULT_SUBAGENT_CONFIG };\n return { ...DEFAULT_SUBAGENT_CONFIG, ...partial };\n}\n\nexport function resolveCheckpointConfig(\n partial?: CheckpointConfig,\n): Required<CheckpointConfig> {\n if (!partial) return { ...DEFAULT_CHECKPOINT_CONFIG };\n return { ...DEFAULT_CHECKPOINT_CONFIG, ...partial };\n}\n","// =============================================================================\n// InMemoryAdapter — In-memory implementation of MemoryPort\n// =============================================================================\n\nimport type { MemoryPort } from \"../../ports/memory.port.js\";\nimport type { Todo } from \"../../domain/todo.schema.js\";\nimport type { Checkpoint } from \"../../domain/checkpoint.schema.js\";\nimport type { Message } from \"../../types.js\";\n\n/**\n * Stores all state in Maps keyed by sessionId.\n * Good for testing and standalone use.\n */\nexport class InMemoryAdapter implements MemoryPort {\n private static readonly MAX_SESSIONS = 1000;\n\n private readonly sessionOrder = new Map<string, true>();\n private readonly todosMap = new Map<string, Todo[]>();\n private readonly checkpointsMap = new Map<string, Checkpoint[]>();\n private readonly conversationMap = new Map<string, Message[]>();\n private readonly metadataMap = new Map<string, Map<string, unknown>>();\n\n private trackSession(sessionId: string): void {\n // Delete + re-insert to refresh position (Map preserves insertion order)\n this.sessionOrder.delete(sessionId);\n this.sessionOrder.set(sessionId, true);\n\n while (this.sessionOrder.size > InMemoryAdapter.MAX_SESSIONS) {\n const oldest = this.sessionOrder.keys().next().value;\n if (oldest !== undefined) {\n this.sessionOrder.delete(oldest);\n this.todosMap.delete(oldest);\n this.checkpointsMap.delete(oldest);\n this.conversationMap.delete(oldest);\n this.metadataMap.delete(oldest);\n }\n }\n }\n\n // -- Todos ------------------------------------------------------------------\n\n async saveTodos(sessionId: string, todos: Todo[]): Promise<void> {\n this.todosMap.set(sessionId, [...todos]);\n this.trackSession(sessionId);\n }\n\n async loadTodos(sessionId: string): Promise<Todo[]> {\n return this.todosMap.get(sessionId) ?? [];\n }\n\n // -- Checkpoints ------------------------------------------------------------\n\n async saveCheckpoint(\n sessionId: string,\n checkpoint: Checkpoint,\n ): Promise<void> {\n const list = this.checkpointsMap.get(sessionId) ?? [];\n list.push(checkpoint);\n this.checkpointsMap.set(sessionId, list);\n this.trackSession(sessionId);\n }\n\n async loadLatestCheckpoint(\n sessionId: string,\n ): Promise<Checkpoint | null> {\n const list = this.checkpointsMap.get(sessionId);\n if (!list || list.length === 0) return null;\n return list[list.length - 1] ?? null;\n }\n\n async listCheckpoints(sessionId: string): Promise<Checkpoint[]> {\n return this.checkpointsMap.get(sessionId) ?? [];\n }\n\n async deleteOldCheckpoints(\n sessionId: string,\n keepCount: number,\n ): Promise<void> {\n const list = this.checkpointsMap.get(sessionId);\n if (!list || list.length <= keepCount) return;\n this.checkpointsMap.set(sessionId, list.slice(-keepCount));\n }\n\n // -- Conversation -----------------------------------------------------------\n\n async saveConversation(\n sessionId: string,\n messages: Message[],\n ): Promise<void> {\n this.conversationMap.set(sessionId, [...messages]);\n this.trackSession(sessionId);\n }\n\n async loadConversation(sessionId: string): Promise<Message[]> {\n return this.conversationMap.get(sessionId) ?? [];\n }\n\n // -- Metadata ---------------------------------------------------------------\n\n async saveMetadata(\n sessionId: string,\n key: string,\n value: unknown,\n ): Promise<void> {\n let map = this.metadataMap.get(sessionId);\n if (!map) {\n map = new Map<string, unknown>();\n this.metadataMap.set(sessionId, map);\n }\n map.set(key, value);\n this.trackSession(sessionId);\n }\n\n async loadMetadata<T = unknown>(\n sessionId: string,\n key: string,\n ): Promise<T | null> {\n const map = this.metadataMap.get(sessionId);\n if (!map || !map.has(key)) return null;\n return map.get(key) as T;\n }\n\n async deleteMetadata(sessionId: string, key: string): Promise<void> {\n this.metadataMap.get(sessionId)?.delete(key);\n }\n\n // -- Utility ----------------------------------------------------------------\n\n /** Clear all data for a session */\n clear(sessionId: string): void {\n this.todosMap.delete(sessionId);\n this.checkpointsMap.delete(sessionId);\n this.conversationMap.delete(sessionId);\n this.metadataMap.delete(sessionId);\n this.sessionOrder.delete(sessionId);\n }\n\n /** Clear all sessions */\n clearAll(): void {\n this.todosMap.clear();\n this.checkpointsMap.clear();\n this.conversationMap.clear();\n this.metadataMap.clear();\n this.sessionOrder.clear();\n }\n}\n","import type { RuntimePort } from \"../../ports/runtime.port.js\";\nimport { NodeRuntimeAdapter } from \"./node-runtime.adapter.js\";\nimport { DenoRuntimeAdapter } from \"./deno-runtime.adapter.js\";\nimport { BunRuntimeAdapter } from \"./bun-runtime.adapter.js\";\nimport { EdgeRuntimeAdapter } from \"./edge-runtime.adapter.js\";\n\nexport type RuntimeName = \"node\" | \"deno\" | \"bun\" | \"edge\" | \"unknown\";\n\nexport function detectRuntimeName(): RuntimeName {\n if (typeof globalThis !== \"undefined\") {\n if (\"Deno\" in globalThis) return \"deno\";\n if (\"Bun\" in globalThis) return \"bun\";\n if (typeof (globalThis as any).process?.versions?.node === \"string\") return \"node\";\n if (typeof globalThis.fetch === \"function\" && !(\"process\" in globalThis)) return \"edge\";\n }\n return \"unknown\";\n}\n\n/** Synchronous factory — eagerly imports all adapters (backward compatible). */\nexport function createRuntimeAdapter(name?: RuntimeName): RuntimePort {\n const resolved = name ?? detectRuntimeName();\n switch (resolved) {\n case \"deno\":\n return new DenoRuntimeAdapter();\n case \"bun\":\n return new BunRuntimeAdapter();\n case \"edge\":\n return new EdgeRuntimeAdapter();\n case \"node\":\n case \"unknown\":\n default:\n return new NodeRuntimeAdapter();\n }\n}\n\n/** Async factory — lazy-loads only the needed adapter. */\nexport async function createRuntimeAdapterAsync(name?: RuntimeName): Promise<RuntimePort> {\n const resolved = name ?? detectRuntimeName();\n switch (resolved) {\n case \"deno\": {\n const { DenoRuntimeAdapter: D } = await import(\"./deno-runtime.adapter.js\");\n return new D();\n }\n case \"bun\": {\n const { BunRuntimeAdapter: B } = await import(\"./bun-runtime.adapter.js\");\n return new B();\n }\n case \"edge\": {\n const { EdgeRuntimeAdapter: E } = await import(\"./edge-runtime.adapter.js\");\n return new E();\n }\n case \"node\":\n case \"unknown\":\n default: {\n const { NodeRuntimeAdapter: N } = await import(\"./node-runtime.adapter.js\");\n return new N();\n }\n }\n}\n","// =============================================================================\n// gauss — HierarchicalEventBus\n// =============================================================================\n\nimport type {\n AgentEvent,\n AgentEventHandler,\n AgentEventType,\n} from \"../types.js\";\n\ntype EventKey = AgentEventType | \"*\";\n\n/**\n * Portable event bus for agent lifecycle events.\n * Supports typed subscriptions, wildcard listeners, auto-filled metadata,\n * hierarchical parent/child relationships, bubbling, capturing, and anti-storm protection.\n */\nexport interface EventBusOptions {\n /** Maximum listeners allowed per event type (default: 100). */\n maxListenersPerEvent?: number;\n /** Maximum bubbled events per second from a single child (default: 100). */\n maxBubblesPerSecond?: number;\n}\n\nexport class EventBus {\n private readonly sessionId: string;\n private readonly listeners = new Map<EventKey, Set<AgentEventHandler>>();\n private readonly maxListenersPerEvent: number;\n private readonly maxBubblesPerSecond: number;\n\n // Hierarchical relationships\n private parent: EventBus | null = null;\n private readonly children = new Map<string, EventBus>();\n private namespace: string | null = null;\n\n // Namespaced listeners: namespace -> Set<handler>\n private readonly namespacedListeners = new Map<string, Set<AgentEventHandler>>();\n\n // Anti-storm: track bubble counts per child per second window\n private readonly bubbleCounts = new Map<string, { count: number; windowStart: number }>();\n\n constructor(sessionId: string, options?: EventBusOptions) {\n this.sessionId = sessionId;\n this.maxListenersPerEvent = options?.maxListenersPerEvent ?? 100;\n this.maxBubblesPerSecond = options?.maxBubblesPerSecond ?? 100;\n }\n\n /** Subscribe to a specific event type or '*' for all events. Returns unsubscribe fn. */\n on(eventType: EventKey, handler: AgentEventHandler): () => void {\n let set = this.listeners.get(eventType);\n if (!set) {\n set = new Set();\n this.listeners.set(eventType, set);\n }\n if (set.size >= this.maxListenersPerEvent) {\n throw new Error(\n `EventBus: max listeners (${this.maxListenersPerEvent}) reached for \"${String(eventType)}\"`,\n );\n }\n set.add(handler);\n return () => this.off(eventType, handler);\n }\n\n /** Unsubscribe a handler from a specific event type. */\n off(eventType: EventKey, handler: AgentEventHandler): void {\n const set = this.listeners.get(eventType);\n if (!set) return;\n set.delete(handler);\n if (set.size === 0) this.listeners.delete(eventType);\n }\n\n /** Emit an event, auto-filling timestamp and sessionId. Also bubbles to parent. */\n emit(type: AgentEventType, data?: unknown): void {\n const event: AgentEvent = {\n type,\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n };\n\n this.dispatchLocal(event);\n this.bubbleToParent(event);\n }\n\n /** Remove all listeners for a given event type, or all listeners if no type specified. */\n removeAllListeners(eventType?: EventKey): void {\n if (eventType) {\n this.listeners.delete(eventType);\n } else {\n this.listeners.clear();\n }\n }\n\n /** Return the number of listeners for a given event type. */\n listenerCount(eventType: EventKey): number {\n return this.listeners.get(eventType)?.size ?? 0;\n }\n\n // ===========================================================================\n // Hierarchical API\n // ===========================================================================\n\n /** Create a child bus with a given namespace. */\n createChild(childNamespace: string): EventBus {\n if (this.children.has(childNamespace)) {\n throw new Error(`EventBus: child namespace \"${childNamespace}\" already exists`);\n }\n const child = new EventBus(this.sessionId, {\n maxListenersPerEvent: this.maxListenersPerEvent,\n maxBubblesPerSecond: this.maxBubblesPerSecond,\n });\n child.parent = this;\n child.namespace = childNamespace;\n this.children.set(childNamespace, child);\n return child;\n }\n\n /** Broadcast an event from this bus to ALL children recursively (capturing phase). */\n broadcast(type: AgentEventType, data?: unknown): void {\n const event: AgentEvent = {\n type,\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n };\n\n for (const child of this.children.values()) {\n child.dispatchLocal(event);\n child.broadcast(type, data);\n }\n }\n\n /** Subscribe to events bubbled from a specific child namespace. */\n onNamespaced(childNamespace: string, handler: AgentEventHandler): () => void {\n let set = this.namespacedListeners.get(childNamespace);\n if (!set) {\n set = new Set();\n this.namespacedListeners.set(childNamespace, set);\n }\n set.add(handler);\n return () => {\n set!.delete(handler);\n if (set!.size === 0) this.namespacedListeners.delete(childNamespace);\n };\n }\n\n /** Get all child buses. */\n getChildren(): Map<string, EventBus> {\n return new Map(this.children);\n }\n\n /** Get the parent bus, or null for root. */\n getParent(): EventBus | null {\n return this.parent;\n }\n\n // ===========================================================================\n // Internal helpers\n // ===========================================================================\n\n /** Dispatch an event to local listeners (specific + wildcard). */\n private dispatchLocal(event: AgentEvent): void {\n const specific = this.listeners.get(event.type);\n if (specific) {\n for (const handler of specific) handler(event);\n }\n const wildcard = this.listeners.get(\"*\");\n if (wildcard) {\n for (const handler of wildcard) handler(event);\n }\n }\n\n /** Bubble an event to the parent bus with _source and _bubbled metadata. */\n private bubbleToParent(event: AgentEvent): void {\n if (!this.parent || !this.namespace) return;\n\n // Anti-storm protection\n if (!this.parent.checkBubbleRate(this.namespace)) return;\n\n const bubbledData =\n typeof event.data === \"object\" && event.data !== null\n ? { ...event.data, _source: this.namespace, _bubbled: true }\n : { _value: event.data, _source: this.namespace, _bubbled: true };\n\n const bubbledEvent: AgentEvent = {\n type: event.type,\n timestamp: event.timestamp,\n sessionId: event.sessionId,\n data: bubbledData,\n };\n\n // Dispatch on the parent's local listeners\n this.parent.dispatchLocal(bubbledEvent);\n\n // Dispatch on the parent's namespaced listeners for this child\n const nsListeners = this.parent.namespacedListeners.get(this.namespace);\n if (nsListeners) {\n for (const handler of nsListeners) handler(bubbledEvent);\n }\n\n // Continue bubbling up\n this.parent.bubbleToParent(bubbledEvent);\n }\n\n /** Check if a child is within the allowed bubble rate. Returns true if allowed. */\n private checkBubbleRate(childNamespace: string): boolean {\n const now = Date.now();\n let tracker = this.bubbleCounts.get(childNamespace);\n\n if (!tracker || now - tracker.windowStart >= 1000) {\n tracker = { count: 0, windowStart: now };\n this.bubbleCounts.set(childNamespace, tracker);\n }\n\n tracker.count++;\n if (tracker.count > this.maxBubblesPerSecond) {\n if (tracker.count === this.maxBubblesPerSecond + 1) {\n console.warn(\n `EventBus: anti-storm — child \"${childNamespace}\" exceeded ${this.maxBubblesPerSecond} bubbles/sec, dropping events`,\n );\n }\n return false;\n }\n return true;\n }\n}\n","// =============================================================================\n// TokenTracker — Cumulative token usage tracking\n// =============================================================================\n\nimport type { TokenCounterPort, TokenBudget } from \"../ports/token-counter.port.js\";\nimport type { TokenTrackerSnapshot } from \"./types.js\";\n\nexport class TokenTracker {\n private inputTokens = 0;\n private outputTokens = 0;\n\n constructor(\n private readonly counter: TokenCounterPort,\n private readonly budget: TokenBudget,\n ) {}\n\n addInput(tokens: number): void {\n this.inputTokens += tokens;\n }\n\n addOutput(tokens: number): void {\n this.outputTokens += tokens;\n }\n\n getUsage(): TokenTrackerSnapshot {\n const totalTokens = this.inputTokens + this.outputTokens;\n return {\n inputTokens: this.inputTokens,\n outputTokens: this.outputTokens,\n totalTokens,\n estimatedCost: this.counter.estimateCost(\n this.inputTokens,\n this.outputTokens,\n \"\",\n ),\n isOverBudget: this.isOverBudget(),\n };\n }\n\n isOverBudget(): boolean {\n return (\n this.inputTokens > this.budget.maxInputTokens ||\n this.outputTokens > this.budget.maxOutputTokens ||\n this.inputTokens + this.outputTokens > this.budget.maxTotalTokens\n );\n }\n\n isNearBudget(threshold?: number): boolean {\n const t = threshold ?? this.budget.warningThreshold;\n return (\n this.inputTokens > this.budget.maxInputTokens * t ||\n this.outputTokens > this.budget.maxOutputTokens * t ||\n this.inputTokens + this.outputTokens > this.budget.maxTotalTokens * t\n );\n }\n\n getRemainingBudget(): {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n } {\n const total = this.inputTokens + this.outputTokens;\n return {\n inputTokens: Math.max(0, this.budget.maxInputTokens - this.inputTokens),\n outputTokens: Math.max(0, this.budget.maxOutputTokens - this.outputTokens),\n totalTokens: Math.max(0, this.budget.maxTotalTokens - total),\n };\n }\n\n reset(): void {\n this.inputTokens = 0;\n this.outputTokens = 0;\n }\n}\n","// =============================================================================\n// Approval Manager — Tool call approval logic\n// =============================================================================\n\nimport type {\n ApprovalConfig,\n ApprovalRequest,\n AgentEvent,\n AgentEventHandler,\n} from \"../types.js\";\n\n/**\n * Manages tool-call approval decisions based on allow/deny lists\n * and an async approval callback for tools requiring human review.\n */\nexport class ApprovalManager {\n private readonly config: Required<ApprovalConfig>;\n private readonly sessionId: string;\n private readonly eventHandler?: AgentEventHandler;\n\n constructor(\n config: Required<ApprovalConfig>,\n sessionId: string,\n eventHandler?: AgentEventHandler,\n ) {\n this.config = config;\n this.sessionId = sessionId;\n this.eventHandler = eventHandler;\n }\n\n /**\n * Synchronous check whether a tool is auto-approved by configuration.\n *\n * - \"approve-all\": returns true unless tool is in `requireApproval`\n * - \"deny-all\": returns true only if tool is in `autoApprove`\n */\n shouldApprove(toolName: string): boolean {\n if (this.config.defaultMode === \"approve-all\") {\n return !this.config.requireApproval.includes(toolName);\n }\n return this.config.autoApprove.includes(toolName);\n }\n\n /**\n * Requests approval via the configured callback, emitting lifecycle events.\n */\n async requestApproval(\n request: ApprovalRequest,\n ): Promise<{ approved: boolean; reason?: string }> {\n this.emit(\"tool:approval-required\", request);\n\n const approved = await this.config.onApprovalRequired(request);\n\n if (approved) {\n this.emit(\"tool:approved\", { toolName: request.toolName, toolCallId: request.toolCallId });\n } else {\n this.emit(\"tool:denied\", { toolName: request.toolName, toolCallId: request.toolCallId });\n }\n\n return {\n approved,\n reason: approved ? undefined : \"Approval denied by callback\",\n };\n }\n\n /**\n * Combined check: auto-approves when policy allows, otherwise delegates\n * to the async approval flow.\n */\n async checkAndApprove(\n toolName: string,\n toolCallId: string,\n args: unknown,\n stepIndex: number,\n ): Promise<{ approved: boolean; reason?: string }> {\n if (this.shouldApprove(toolName)) {\n return { approved: true };\n }\n\n return this.requestApproval({\n toolName,\n toolCallId,\n args,\n sessionId: this.sessionId,\n stepIndex,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n private emit(type: AgentEvent[\"type\"], data: unknown): void {\n this.eventHandler?.({\n type,\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n });\n }\n}\n","import { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\n\nconst zoneSchema = z\n .enum([\"transient\", \"persistent\"])\n .default(\"transient\")\n .describe(\"Filesystem zone to operate in\");\n\nexport function createLsTool(fs: FilesystemPort) {\n return tool({\n description:\n \"List files and directories at the given path. \" +\n \"Returns names, sizes, and types. Use recursive to walk subdirectories.\",\n inputSchema: z.object({\n path: z.string().describe(\"Directory path to list\"),\n recursive: z\n .boolean()\n .optional()\n .default(false)\n .describe(\"Whether to list subdirectories recursively\"),\n zone: zoneSchema.optional(),\n }),\n execute: async ({ path, recursive, zone }) => {\n const entries = await fs.list(\n path,\n { recursive },\n zone ?? \"transient\",\n );\n if (entries.length === 0) return \"Directory is empty.\";\n const lines = entries.map((e) => {\n const tag = e.isDirectory ? \"[dir] \" : \" \";\n return `${tag}${e.path} (${e.size} bytes)`;\n });\n return lines.join(\"\\n\");\n },\n });\n}\n","import { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\n\nconst MAX_CHARS = 50_000;\n\nexport function createReadFileTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Read the contents of a file and return it as a string. \" +\n \"Very large files are truncated to 50000 characters.\",\n inputSchema: z.object({\n path: z.string().describe(\"File path to read\"),\n zone: z\n .enum([\"transient\", \"persistent\"])\n .default(\"transient\")\n .optional()\n .describe(\"Filesystem zone\"),\n }),\n execute: async ({ path, zone }) => {\n const content = await fs.read(path, zone ?? \"transient\");\n if (content.length <= MAX_CHARS) return content;\n return (\n content.slice(0, MAX_CHARS) +\n `\\n\\n[Truncated: showing ${MAX_CHARS} of ${content.length} characters]`\n );\n },\n });\n}\n","import { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\n\nexport function createWriteFileTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Create or overwrite a file with the given content. \" +\n \"Parent directories are created automatically.\",\n inputSchema: z.object({\n path: z.string().describe(\"File path to write\"),\n content: z.string().describe(\"Content to write to the file\"),\n zone: z\n .enum([\"transient\", \"persistent\"])\n .default(\"transient\")\n .optional()\n .describe(\"Filesystem zone\"),\n }),\n execute: async ({ path, content, zone }) => {\n await fs.write(path, content, zone ?? \"transient\");\n return `File written: ${path} (${content.length} bytes)`;\n },\n });\n}\n","import { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\n\nexport function createEditFileTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Perform a surgical string replacement in a file. \" +\n \"Replaces the first occurrence of oldStr with newStr. \" +\n \"Fails if oldStr is not found.\",\n inputSchema: z.object({\n path: z.string().describe(\"File path to edit\"),\n oldStr: z.string().describe(\"Exact string to find and replace\"),\n newStr: z.string().describe(\"Replacement string\"),\n zone: z\n .enum([\"transient\", \"persistent\"])\n .default(\"transient\")\n .optional()\n .describe(\"Filesystem zone\"),\n }),\n execute: async ({ path, oldStr, newStr, zone }) => {\n const z2 = zone ?? \"transient\";\n const content = await fs.read(path, z2);\n if (!content.includes(oldStr)) {\n throw new Error(`oldStr not found in ${path}`);\n }\n const updated = content.replace(oldStr, newStr);\n await fs.write(path, updated, z2);\n return `File edited: ${path}`;\n },\n });\n}\n","import { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\n\nexport function createGlobTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Find files matching a glob pattern (e.g. '**/*.ts'). \" +\n \"Returns a list of matching file paths.\",\n inputSchema: z.object({\n pattern: z.string().describe(\"Glob pattern to match files\"),\n zone: z\n .enum([\"transient\", \"persistent\"])\n .default(\"transient\")\n .optional()\n .describe(\"Filesystem zone\"),\n }),\n execute: async ({ pattern, zone }) => {\n const matches = await fs.glob(pattern, zone ?? \"transient\");\n if (matches.length === 0) return \"No files matched the pattern.\";\n return matches.join(\"\\n\");\n },\n });\n}\n","import { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\n\nexport function createGrepTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Search file contents for a regex or string pattern. \" +\n \"Returns matching lines with file paths and line numbers.\",\n inputSchema: z.object({\n pattern: z.string().describe(\"Regex or string pattern to search for\"),\n path: z\n .string()\n .optional()\n .describe(\"Directory or file to search in\"),\n caseSensitive: z.boolean().optional().default(true),\n maxResults: z\n .number()\n .int()\n .optional()\n .default(50)\n .describe(\"Maximum number of results to return\"),\n zone: z\n .enum([\"transient\", \"persistent\"])\n .default(\"transient\")\n .optional()\n .describe(\"Filesystem zone\"),\n }),\n execute: async ({ pattern, path, caseSensitive, maxResults, zone }) => {\n const results = await fs.search(\n pattern,\n { caseSensitive, maxResults, includeLineNumbers: true, filePattern: path },\n zone ?? \"transient\",\n );\n if (results.length === 0) return \"No matches found.\";\n const lines = results.map(\n (r) => `${r.filePath}:${r.lineNumber}: ${r.lineContent}`,\n );\n return lines.join(\"\\n\");\n },\n });\n}\n","import type { FilesystemPort } from \"../../ports/filesystem.port.js\";\n\nimport { createLsTool } from \"./ls.tool.js\";\nimport { createReadFileTool } from \"./read-file.tool.js\";\nimport { createWriteFileTool } from \"./write-file.tool.js\";\nimport { createEditFileTool } from \"./edit-file.tool.js\";\nimport { createGlobTool } from \"./glob.tool.js\";\nimport { createGrepTool } from \"./grep.tool.js\";\n\nexport {\n createLsTool,\n createReadFileTool,\n createWriteFileTool,\n createEditFileTool,\n createGlobTool,\n createGrepTool,\n};\n\nexport function createFilesystemTools(fs: FilesystemPort) {\n return {\n ls: createLsTool(fs),\n read_file: createReadFileTool(fs),\n write_file: createWriteFileTool(fs),\n edit_file: createEditFileTool(fs),\n glob: createGlobTool(fs),\n grep: createGrepTool(fs),\n };\n}\n","import { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\nimport type { Todo } from \"../../domain/todo.schema.js\";\nimport { TODOS_PATH, loadTodos } from \"./shared.js\";\n\nconst TodoInputSchema = z.object({\n id: z.string().describe(\"Unique identifier (kebab-case)\"),\n title: z.string().describe(\"Short title of the task\"),\n description: z.string().optional(),\n status: z.enum([\"pending\", \"in_progress\", \"done\", \"blocked\"]).optional(),\n dependencies: z.array(z.string()).optional(),\n priority: z.enum([\"low\", \"medium\", \"high\", \"critical\"]).optional(),\n});\n\nexport function createWriteTodosTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Create or update a task plan. Each todo has an id, title, \" +\n \"optional description, status, dependencies, and priority.\",\n inputSchema: z.object({\n todos: z.array(TodoInputSchema).describe(\"Todos to create or update\"),\n }),\n execute: async ({ todos }) => {\n const existing = await loadTodos(fs);\n const byId = new Map(existing.map((t) => [t.id, t]));\n let created = 0;\n let updated = 0;\n\n for (const input of todos) {\n const now = Date.now();\n const prev = byId.get(input.id);\n if (prev) {\n byId.set(input.id, { ...prev, ...input, updatedAt: now });\n updated++;\n } else {\n byId.set(input.id, {\n status: \"pending\",\n dependencies: [],\n priority: \"medium\",\n createdAt: now,\n updatedAt: now,\n ...input,\n } as Todo);\n created++;\n }\n }\n\n const all = Array.from(byId.values());\n await fs.write(TODOS_PATH, JSON.stringify(all, null, 2), \"persistent\");\n return `Plan updated: ${created} created, ${updated} updated, ${all.length} total.`;\n },\n });\n}\n\n","import type { FilesystemPort } from \"../../ports/filesystem.port.js\";\nimport type { Todo } from \"../../domain/todo.schema.js\";\n\nexport const TODOS_PATH = \"todos.json\";\n\nexport async function loadTodos(fs: FilesystemPort): Promise<Todo[]> {\n const exists = await fs.exists(TODOS_PATH, \"persistent\");\n if (!exists) return [];\n const raw = await fs.read(TODOS_PATH, \"persistent\");\n return JSON.parse(raw) as Todo[];\n}\n","import { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\nimport type { Todo, TodoStatus } from \"../../domain/todo.schema.js\";\nimport { TODOS_PATH, loadTodos } from \"./shared.js\";\n\nexport function createReviewTodosTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Review current task plan and optionally update todo statuses. \" +\n \"Returns the full plan with progress.\",\n inputSchema: z.object({\n updates: z\n .array(\n z.object({\n id: z.string().describe(\"Todo ID to update\"),\n status: z.enum([\"pending\", \"in_progress\", \"done\", \"blocked\"]),\n }),\n )\n .optional()\n .describe(\"Optional status updates to apply\"),\n }),\n execute: async ({ updates }) => {\n const todos = await loadTodos(fs);\n if (todos.length === 0) return \"No todos found. Use write_todos first.\";\n\n if (updates?.length) {\n const byId = new Map(todos.map((t) => [t.id, t]));\n for (const u of updates) {\n const t = byId.get(u.id);\n if (!t) continue;\n t.status = u.status as TodoStatus;\n t.updatedAt = Date.now();\n if (u.status === \"done\") t.completedAt = Date.now();\n }\n await fs.write(\n TODOS_PATH,\n JSON.stringify(todos, null, 2),\n \"persistent\",\n );\n }\n\n return formatPlan(todos);\n },\n });\n}\n\nfunction formatPlan(todos: Todo[]): string {\n const counts = { pending: 0, in_progress: 0, done: 0, blocked: 0 };\n for (const t of todos) counts[t.status as keyof typeof counts]++;\n\n const header =\n `Plan: ${todos.length} total | ` +\n `${counts.done} done, ${counts.in_progress} in-progress, ` +\n `${counts.pending} pending, ${counts.blocked} blocked`;\n\n const lines = todos.map(\n (t) =>\n `[${t.status}] ${t.id}: ${t.title}` +\n (t.dependencies?.length ? ` (deps: ${t.dependencies.join(\", \")})` : \"\"),\n );\n return [header, \"---\", ...lines].join(\"\\n\");\n}\n\n","// =============================================================================\n// Plan Schema — Piano gerarchico strutturato per task decomposition avanzata\n//\n// Gerarchia: Plan → Phase → Step → SubStep (N livelli ricorsivi)\n// Supporta: esecuzione sequenziale, parallela, condizionale e loop\n// Ogni step ha contratti input/output Zod, risorse, e stato osservabile\n// =============================================================================\n\nimport { z } from \"zod\";\n\n// =============================================================================\n// Enums & Primitivi\n// =============================================================================\n\n/** Modalità di esecuzione di uno step */\nexport const StepExecutionModeSchema = z.enum([\n \"sequential\",\n \"parallel\",\n \"conditional\",\n \"loop\",\n]);\nexport type StepExecutionMode = z.infer<typeof StepExecutionModeSchema>;\n\n/** Macchina a stati per lo step: idle → running → completed/failed/skipped */\nexport const StepStatusSchema = z.enum([\n \"idle\",\n \"pending\",\n \"running\",\n \"completed\",\n \"failed\",\n \"skipped\",\n \"blocked\",\n \"cancelled\",\n]);\nexport type StepStatus = z.infer<typeof StepStatusSchema>;\n\n/** Priorità dello step */\nexport const StepPrioritySchema = z.enum([\"low\", \"medium\", \"high\", \"critical\"]);\nexport type StepPriority = z.infer<typeof StepPrioritySchema>;\n\n/** Stato globale del piano */\nexport const PlanStatusSchema = z.enum([\n \"draft\",\n \"active\",\n \"paused\",\n \"completed\",\n \"failed\",\n \"cancelled\",\n]);\nexport type PlanStatus = z.infer<typeof PlanStatusSchema>;\n\n// =============================================================================\n// Transizioni di stato valide (state machine)\n// =============================================================================\n\nexport const STEP_STATUS_TRANSITIONS: Record<StepStatus, StepStatus[]> = {\n idle: [\"pending\", \"skipped\", \"cancelled\"],\n pending: [\"running\", \"blocked\", \"skipped\", \"cancelled\"],\n running: [\"completed\", \"failed\", \"cancelled\"],\n completed: [],\n failed: [\"pending\"], // retry\n skipped: [],\n blocked: [\"pending\", \"cancelled\"],\n cancelled: [],\n};\n\nexport const PLAN_STATUS_TRANSITIONS: Record<PlanStatus, PlanStatus[]> = {\n draft: [\"active\", \"cancelled\"],\n active: [\"paused\", \"completed\", \"failed\", \"cancelled\"],\n paused: [\"active\", \"cancelled\"],\n completed: [],\n failed: [\"active\"], // retry\n cancelled: [],\n};\n\n// =============================================================================\n// Resource Requirements — Budget e limiti per step\n// =============================================================================\n\nexport const ResourceRequirementsSchema = z.object({\n /** Budget massimo di token (input + output) per questo step */\n maxTokenBudget: z.number().positive().optional(),\n /** Timeout in millisecondi */\n timeoutMs: z.number().positive().optional(),\n /** Numero massimo di retry in caso di fallimento */\n maxRetries: z.number().int().min(0).optional().default(0),\n /** Modello preferito (override del default del piano) */\n preferredModel: z.string().optional(),\n /** Livello di concorrenza massimo per sotto-step paralleli */\n maxConcurrency: z.number().int().positive().optional().default(5),\n});\nexport type ResourceRequirements = z.infer<typeof ResourceRequirementsSchema>;\n\n// =============================================================================\n// I/O Contract — Contratto strutturato input/output per ogni step\n// =============================================================================\n\n/**\n * Definizione del contratto I/O come JSON Schema serializzabile.\n * Usiamo una rappresentazione JSON-safe anziché z.ZodType diretto\n * per permettere serializzazione/deserializzazione del piano.\n */\nexport const IOFieldSchema = z.object({\n name: z.string().describe(\"Nome del campo\"),\n type: z\n .enum([\"string\", \"number\", \"boolean\", \"array\", \"object\", \"any\"])\n .describe(\"Tipo del campo\"),\n description: z.string().optional(),\n required: z.boolean().default(true),\n});\nexport type IOField = z.infer<typeof IOFieldSchema>;\n\nexport const StepContractSchema = z.object({\n /** Campi di input attesi — cosa serve allo step per eseguire */\n inputs: z.array(IOFieldSchema).default([]),\n /** Campi di output prodotti — cosa produce lo step */\n outputs: z.array(IOFieldSchema).default([]),\n});\nexport type StepContract = z.infer<typeof StepContractSchema>;\n\n// =============================================================================\n// Step Result — Risultato dell'esecuzione di uno step\n// =============================================================================\n\nexport const StepResultSchema = z.object({\n /** Output testuale prodotto */\n output: z.string().optional(),\n /** Dati strutturati di output (match con contract.outputs) */\n data: z.record(z.string(), z.unknown()).optional(),\n /** Uso token */\n tokenUsage: z\n .object({ input: z.number(), output: z.number() })\n .optional(),\n /** Durata in ms */\n durationMs: z.number().optional(),\n /** Errore se fallito */\n error: z.string().optional(),\n});\nexport type StepResult = z.infer<typeof StepResultSchema>;\n\n// =============================================================================\n// Condition — Condizione per step condizionali\n// =============================================================================\n\nexport const StepConditionSchema = z.object({\n /** Espressione condizionale (riferimenti a output di step precedenti) */\n expression: z.string().describe(\n \"Espressione valutabile, es: 'steps.auth-design.status === completed'\"\n ),\n /** ID dello step da eseguire se la condizione è vera */\n ifTrueStepId: z.string().optional(),\n /** ID dello step da eseguire se la condizione è falsa */\n ifFalseStepId: z.string().optional(),\n});\nexport type StepCondition = z.infer<typeof StepConditionSchema>;\n\n// =============================================================================\n// Loop Config — Configurazione per step di tipo loop\n// =============================================================================\n\nexport const LoopConfigSchema = z.object({\n /** Condizione di continuazione */\n condition: z.string().describe(\n \"Espressione per continuare il loop, es: 'iteration < 3 && !steps.validate.data.allPassing'\"\n ),\n /** Numero massimo di iterazioni (safety) */\n maxIterations: z.number().int().positive().default(10),\n /** ID dello step che funge da corpo del loop */\n bodyStepIds: z.array(z.string()).min(1),\n});\nexport type LoopConfig = z.infer<typeof LoopConfigSchema>;\n\n// =============================================================================\n// SubStep — Livello ricorsivo di step annidati\n// =============================================================================\n\n// Definizione ricorsiva: SubStep può contenere altri SubStep\nconst BaseSubStepSchema = z.object({\n id: z.string().describe(\"ID univoco del sotto-step (kebab-case)\"),\n title: z.string().describe(\"Titolo breve del sotto-step\"),\n description: z.string().optional(),\n status: StepStatusSchema.default(\"idle\"),\n executionMode: StepExecutionModeSchema.default(\"sequential\"),\n contract: StepContractSchema.optional(),\n resources: ResourceRequirementsSchema.optional(),\n result: StepResultSchema.optional(),\n /** Istruzioni/prompt per l'agente che esegue questo sotto-step */\n prompt: z.string().optional(),\n /** Tool specifici richiesti per questo sotto-step */\n requiredTools: z.array(z.string()).default([]),\n});\n\nexport type SubStep = z.infer<typeof BaseSubStepSchema> & {\n children?: SubStep[];\n};\n\n// Use 'as any' cast to satisfy recursive ZodType — standard pattern for Zod lazy recursion\nexport const SubStepSchema: z.ZodType<SubStep> = BaseSubStepSchema.extend({\n children: z.lazy(() => z.array(SubStepSchema)).optional(),\n}) as any;\n\n// =============================================================================\n// Step — Unità atomica di lavoro con contratto I/O\n// =============================================================================\n\nexport const StepSchema = z.object({\n id: z.string().describe(\"ID univoco dello step (kebab-case)\"),\n title: z.string().describe(\"Titolo breve dello step\"),\n description: z.string().optional().describe(\"Descrizione dettagliata\"),\n\n /** Modalità di esecuzione */\n executionMode: StepExecutionModeSchema.default(\"sequential\"),\n\n /** Stato corrente */\n status: StepStatusSchema.default(\"idle\"),\n\n /** Priorità */\n priority: StepPrioritySchema.default(\"medium\"),\n\n /** Contratto input/output strutturato */\n contract: StepContractSchema.default({ inputs: [], outputs: [] }),\n\n /** Requisiti di risorse */\n resources: ResourceRequirementsSchema.optional(),\n\n /** Dipendenze esplicite: ID di step nella stessa fase o in fasi precedenti */\n dependencies: z.array(z.string()).default([]),\n\n /** Istruzioni/prompt per l'agente */\n prompt: z.string().optional().describe(\n \"Prompt specifico per l'agente che esegue questo step\"\n ),\n\n /** Tool specifici richiesti */\n requiredTools: z.array(z.string()).default([]),\n\n /** Sotto-step (gerarchia ricorsiva) */\n subSteps: z.array(SubStepSchema).default([]),\n\n /** Condizione (solo se executionMode === 'conditional') */\n condition: StepConditionSchema.optional(),\n\n /** Configurazione loop (solo se executionMode === 'loop') */\n loopConfig: LoopConfigSchema.optional(),\n\n /** Risultato dell'esecuzione */\n result: StepResultSchema.optional(),\n\n /** Timestamp */\n createdAt: z.number().default(() => Date.now()),\n updatedAt: z.number().default(() => Date.now()),\n startedAt: z.number().optional(),\n completedAt: z.number().optional(),\n\n /** Metadati arbitrari */\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\nexport type Step = z.infer<typeof StepSchema>;\n\n// =============================================================================\n// Phase — Raggruppamento logico di step\n// =============================================================================\n\nexport const PhaseSchema = z.object({\n id: z.string().describe(\"ID univoco della fase (kebab-case)\"),\n title: z.string().describe(\"Titolo della fase\"),\n description: z.string().optional(),\n\n /** Come eseguire gli step dentro questa fase */\n executionMode: StepExecutionModeSchema.default(\"sequential\"),\n\n /** Stato derivato dagli step contenuti */\n status: StepStatusSchema.default(\"idle\"),\n\n /** Step contenuti in questa fase */\n steps: z.array(StepSchema).min(1).describe(\"Step della fase\"),\n\n /** Ordine (per fasi sequenziali nel piano) */\n order: z.number().int().min(0).default(0),\n\n /** Dipendenze da altre fasi (ID) */\n dependencies: z.array(z.string()).default([]),\n\n /** Requisiti di risorse per l'intera fase */\n resources: ResourceRequirementsSchema.optional(),\n\n /** Timestamp */\n createdAt: z.number().default(() => Date.now()),\n updatedAt: z.number().default(() => Date.now()),\n});\nexport type Phase = z.infer<typeof PhaseSchema>;\n\n// =============================================================================\n// Plan — Root del piano gerarchico\n// =============================================================================\n\nexport const PlanMetadataSchema = z.object({\n /** Chi ha creato il piano (agente o umano) */\n createdBy: z.string().default(\"agent\"),\n /** Versione del piano (incrementa ad ogni modifica) */\n version: z.number().int().min(1).default(1),\n /** Tag liberi per classificazione */\n tags: z.array(z.string()).default([]),\n /** Obiettivo di alto livello che il piano deve raggiungere */\n goal: z.string().describe(\"Obiettivo principale del piano\"),\n /** Contesto/vincoli aggiuntivi */\n constraints: z.array(z.string()).default([]),\n /** Stima dei token totali per l'intero piano */\n estimatedTotalTokens: z.number().optional(),\n /** Stima della durata totale in ms */\n estimatedDurationMs: z.number().optional(),\n});\nexport type PlanMetadata = z.infer<typeof PlanMetadataSchema>;\n\nexport const PlanSchema = z.object({\n id: z.string().describe(\"ID univoco del piano (kebab-case)\"),\n title: z.string().describe(\"Titolo del piano\"),\n description: z.string().optional().describe(\"Descrizione del piano\"),\n\n /** Stato globale del piano */\n status: PlanStatusSchema.default(\"draft\"),\n\n /** Metadata del piano */\n metadata: PlanMetadataSchema,\n\n /** Fasi del piano (ordinate) */\n phases: z.array(PhaseSchema).min(1).describe(\"Fasi del piano\"),\n\n /** Configurazione risorse globali */\n globalResources: ResourceRequirementsSchema.optional(),\n\n /** Timestamp */\n createdAt: z.number().default(() => Date.now()),\n updatedAt: z.number().default(() => Date.now()),\n startedAt: z.number().optional(),\n completedAt: z.number().optional(),\n});\nexport type Plan = z.infer<typeof PlanSchema>;\n\n// =============================================================================\n// Plan Events — Eventi osservabili durante l'esecuzione del piano\n// =============================================================================\n\nexport const PlanEventTypeSchema = z.enum([\n \"plan:created\",\n \"plan:started\",\n \"plan:paused\",\n \"plan:resumed\",\n \"plan:completed\",\n \"plan:failed\",\n \"plan:cancelled\",\n \"plan:updated\",\n \"phase:started\",\n \"phase:completed\",\n \"phase:failed\",\n \"step:started\",\n \"step:completed\",\n \"step:failed\",\n \"step:skipped\",\n \"step:blocked\",\n \"step:retrying\",\n \"substep:started\",\n \"substep:completed\",\n \"substep:failed\",\n]);\nexport type PlanEventType = z.infer<typeof PlanEventTypeSchema>;\n\nexport const PlanEventSchema = z.object({\n type: PlanEventTypeSchema,\n planId: z.string(),\n phaseId: z.string().optional(),\n stepId: z.string().optional(),\n subStepId: z.string().optional(),\n timestamp: z.number().default(() => Date.now()),\n data: z.record(z.string(), z.unknown()).optional(),\n});\nexport type PlanEvent = z.infer<typeof PlanEventSchema>;\n\n// =============================================================================\n// Progress — Snapshot del progresso del piano\n// =============================================================================\n\nexport const StepProgressSchema = z.object({\n stepId: z.string(),\n title: z.string(),\n status: StepStatusSchema,\n /** Progresso dei sotto-step (0.0 - 1.0) */\n progress: z.number().min(0).max(1).default(0),\n /** Numero sotto-step completati / totali */\n subStepsDone: z.number().int().min(0).default(0),\n subStepsTotal: z.number().int().min(0).default(0),\n});\nexport type StepProgress = z.infer<typeof StepProgressSchema>;\n\nexport const PhaseProgressSchema = z.object({\n phaseId: z.string(),\n title: z.string(),\n status: StepStatusSchema,\n progress: z.number().min(0).max(1).default(0),\n steps: z.array(StepProgressSchema),\n});\nexport type PhaseProgress = z.infer<typeof PhaseProgressSchema>;\n\nexport const PlanProgressSchema = z.object({\n planId: z.string(),\n title: z.string(),\n status: PlanStatusSchema,\n /** Progresso globale (0.0 - 1.0) */\n progress: z.number().min(0).max(1).default(0),\n /** Conteggi globali */\n totalSteps: z.number().int().min(0),\n completedSteps: z.number().int().min(0),\n failedSteps: z.number().int().min(0),\n /** Dettaglio per fase */\n phases: z.array(PhaseProgressSchema),\n /** Durata totale fino ad ora */\n elapsedMs: z.number().optional(),\n /** Token usati fino ad ora */\n tokenUsage: z\n .object({ input: z.number(), output: z.number() })\n .optional(),\n});\nexport type PlanProgress = z.infer<typeof PlanProgressSchema>;\n\n// =============================================================================\n// Factory Functions — Creazione rapida di entità del piano\n// =============================================================================\n\nlet _stepCounter = 0;\n\n/** Crea uno Step con defaults ragionevoli */\nexport function createStep(\n overrides: Partial<Step> & Pick<Step, \"id\" | \"title\">\n): Step {\n return StepSchema.parse({\n executionMode: \"sequential\",\n status: \"idle\",\n priority: \"medium\",\n contract: { inputs: [], outputs: [] },\n dependencies: [],\n requiredTools: [],\n subSteps: [],\n ...overrides,\n });\n}\n\n/** Crea una Phase con defaults ragionevoli */\nexport function createPhase(\n overrides: Partial<Phase> & Pick<Phase, \"id\" | \"title\" | \"steps\">\n): Phase {\n return PhaseSchema.parse({\n executionMode: \"sequential\",\n status: \"idle\",\n dependencies: [],\n ...overrides,\n });\n}\n\n/** Crea un SubStep con defaults ragionevoli */\nexport function createSubStep(\n overrides: Partial<SubStep> & Pick<SubStep, \"id\" | \"title\">\n): SubStep {\n return SubStepSchema.parse({\n status: \"idle\",\n executionMode: \"sequential\",\n requiredTools: [],\n ...overrides,\n });\n}\n\n/** Crea un Plan completo con defaults ragionevoli */\nexport function createPlan(\n overrides: Partial<Plan> & Pick<Plan, \"id\" | \"title\" | \"metadata\" | \"phases\">\n): Plan {\n return PlanSchema.parse({\n status: \"draft\",\n ...overrides,\n });\n}\n\n/** Genera un ID univoco per step basato su prefisso */\nexport function generateStepId(prefix: string): string {\n return `${prefix}-${++_stepCounter}`;\n}\n\n// =============================================================================\n// Validazione — Controlli strutturali sul piano\n// =============================================================================\n\nexport interface PlanValidationResult {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n/** Valida la struttura e la coerenza di un piano */\nexport function validatePlan(plan: Plan): PlanValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n const allStepIds = new Set<string>();\n const allPhaseIds = new Set<string>();\n\n // Raccogli tutti gli ID\n for (const phase of plan.phases) {\n if (allPhaseIds.has(phase.id)) {\n errors.push(`ID fase duplicato: \"${phase.id}\"`);\n }\n allPhaseIds.add(phase.id);\n\n for (const step of phase.steps) {\n if (allStepIds.has(step.id)) {\n errors.push(`ID step duplicato: \"${step.id}\"`);\n }\n allStepIds.add(step.id);\n collectSubStepIds(step.subSteps, allStepIds, errors);\n }\n }\n\n // Valida dipendenze\n for (const phase of plan.phases) {\n for (const dep of phase.dependencies) {\n if (!allPhaseIds.has(dep)) {\n errors.push(`Fase \"${phase.id}\" dipende da fase inesistente \"${dep}\"`);\n }\n if (dep === phase.id) {\n errors.push(`Fase \"${phase.id}\" dipende da se stessa`);\n }\n }\n\n for (const step of phase.steps) {\n for (const dep of step.dependencies) {\n if (!allStepIds.has(dep)) {\n errors.push(\n `Step \"${step.id}\" dipende da step inesistente \"${dep}\"`\n );\n }\n if (dep === step.id) {\n errors.push(`Step \"${step.id}\" dipende da se stesso`);\n }\n }\n\n // Valida coerenza mode/config\n if (step.executionMode === \"conditional\" && !step.condition) {\n errors.push(\n `Step \"${step.id}\" è condizionale ma manca la configurazione condition`\n );\n }\n if (step.executionMode === \"loop\" && !step.loopConfig) {\n errors.push(\n `Step \"${step.id}\" è loop ma manca la configurazione loopConfig`\n );\n }\n\n // Warnings per contratti mancanti\n if (step.contract.inputs.length === 0 && step.dependencies.length > 0) {\n warnings.push(\n `Step \"${step.id}\" ha dipendenze ma nessun input definito nel contratto`\n );\n }\n }\n }\n\n // Valida cicli tra fasi\n const phaseDepErrors = detectCycles(\n plan.phases.map((p) => p.id),\n plan.phases.reduce(\n (acc, p) => { acc[p.id] = p.dependencies; return acc; },\n {} as Record<string, string[]>,\n ),\n );\n errors.push(...phaseDepErrors);\n\n return { valid: errors.length === 0, errors, warnings };\n}\n\nfunction collectSubStepIds(\n subSteps: SubStep[],\n allIds: Set<string>,\n errors: string[],\n): void {\n for (const ss of subSteps) {\n if (allIds.has(ss.id)) {\n errors.push(`ID sotto-step duplicato: \"${ss.id}\"`);\n }\n allIds.add(ss.id);\n if (ss.children) {\n collectSubStepIds(ss.children, allIds, errors);\n }\n }\n}\n\nfunction detectCycles(\n nodeIds: string[],\n deps: Record<string, string[]>,\n): string[] {\n const errors: string[] = [];\n const visited = new Set<string>();\n const stack = new Set<string>();\n\n const visit = (id: string): void => {\n if (stack.has(id)) {\n errors.push(`Ciclo rilevato che coinvolge \"${id}\"`);\n return;\n }\n if (visited.has(id)) return;\n stack.add(id);\n for (const dep of deps[id] ?? []) {\n visit(dep);\n }\n stack.delete(id);\n visited.add(id);\n };\n\n for (const id of nodeIds) {\n visit(id);\n }\n return errors;\n}\n\n// =============================================================================\n// State Machine Helpers — Transizioni di stato sicure\n// =============================================================================\n\n/** Verifica se una transizione di stato dello step è valida */\nexport function isValidStepTransition(\n from: StepStatus,\n to: StepStatus,\n): boolean {\n return STEP_STATUS_TRANSITIONS[from]?.includes(to) ?? false;\n}\n\n/** Verifica se una transizione di stato del piano è valida */\nexport function isValidPlanTransition(\n from: PlanStatus,\n to: PlanStatus,\n): boolean {\n return PLAN_STATUS_TRANSITIONS[from]?.includes(to) ?? false;\n}\n\n/** Esegue una transizione di stato su uno step con validazione */\nexport function transitionStep(step: Step, newStatus: StepStatus): Step {\n if (!isValidStepTransition(step.status, newStatus)) {\n throw new Error(\n `Transizione step non valida: \"${step.status}\" → \"${newStatus}\" per step \"${step.id}\"`\n );\n }\n const now = Date.now();\n return {\n ...step,\n status: newStatus,\n updatedAt: now,\n ...(newStatus === \"running\" ? { startedAt: now } : {}),\n ...(newStatus === \"completed\" || newStatus === \"failed\"\n ? { completedAt: now }\n : {}),\n };\n}\n\n// =============================================================================\n// Progress Calculator — Calcola il progresso del piano\n// =============================================================================\n\n/** Calcola il progresso complessivo del piano */\nexport function calculateProgress(plan: Plan): PlanProgress {\n let totalSteps = 0;\n let completedSteps = 0;\n let failedSteps = 0;\n\n const phaseProgresses: PhaseProgress[] = plan.phases.map((phase) => {\n const stepProgresses: StepProgress[] = phase.steps.map((step) => {\n totalSteps++;\n const subTotal = countSubSteps(step.subSteps);\n const subDone = countCompletedSubSteps(step.subSteps);\n\n if (step.status === \"completed\") completedSteps++;\n if (step.status === \"failed\") failedSteps++;\n\n const stepProgress =\n step.status === \"completed\"\n ? 1\n : step.status === \"running\" && subTotal > 0\n ? subDone / subTotal\n : 0;\n\n return {\n stepId: step.id,\n title: step.title,\n status: step.status,\n progress: stepProgress,\n subStepsDone: subDone,\n subStepsTotal: subTotal,\n };\n });\n\n const phaseTotal = stepProgresses.length;\n const phaseProgress =\n phaseTotal > 0\n ? stepProgresses.reduce((sum, s) => sum + s.progress, 0) / phaseTotal\n : 0;\n\n const phaseStatus = derivePhaseStatus(phase.steps);\n\n return {\n phaseId: phase.id,\n title: phase.title,\n status: phaseStatus,\n progress: phaseProgress,\n steps: stepProgresses,\n };\n });\n\n const globalProgress =\n totalSteps > 0 ? completedSteps / totalSteps : 0;\n\n const elapsedMs = plan.startedAt\n ? Date.now() - plan.startedAt\n : undefined;\n\n return {\n planId: plan.id,\n title: plan.title,\n status: plan.status,\n progress: globalProgress,\n totalSteps,\n completedSteps,\n failedSteps,\n phases: phaseProgresses,\n elapsedMs,\n };\n}\n\nfunction countSubSteps(subSteps: SubStep[]): number {\n let count = 0;\n for (const ss of subSteps) {\n count++;\n if (ss.children) count += countSubSteps(ss.children);\n }\n return count;\n}\n\nfunction countCompletedSubSteps(subSteps: SubStep[]): number {\n let count = 0;\n for (const ss of subSteps) {\n if (ss.status === \"completed\") count++;\n if (ss.children) count += countCompletedSubSteps(ss.children);\n }\n return count;\n}\n\nfunction derivePhaseStatus(steps: Step[]): StepStatus {\n if (steps.every((s) => s.status === \"completed\")) return \"completed\";\n if (steps.some((s) => s.status === \"failed\")) return \"failed\";\n if (steps.some((s) => s.status === \"running\")) return \"running\";\n if (steps.some((s) => s.status === \"pending\")) return \"pending\";\n if (steps.some((s) => s.status === \"blocked\")) return \"blocked\";\n return \"idle\";\n}\n\n// =============================================================================\n// Retrocompatibilità — Conversione Todo[] → Plan\n// =============================================================================\n\nimport type { Todo } from \"./todo.schema.js\";\n\n/** Converte una lista di Todo legacy in un Plan strutturato */\nexport function todosToplan(todos: Todo[], planTitle: string = \"Piano Migrato\"): Plan {\n const steps: Step[] = todos.map((todo) =>\n createStep({\n id: todo.id,\n title: todo.title,\n description: todo.description,\n status: mapTodoStatus(todo.status),\n priority: todo.priority as StepPriority,\n dependencies: todo.dependencies,\n createdAt: todo.createdAt,\n updatedAt: todo.updatedAt,\n completedAt: todo.completedAt,\n }),\n );\n\n return createPlan({\n id: `migrated-${Date.now()}`,\n title: planTitle,\n metadata: {\n goal: planTitle,\n createdBy: \"migration\",\n version: 1,\n tags: [\"migrated-from-todos\"],\n constraints: [],\n },\n phases: [\n createPhase({\n id: \"migrated-phase\",\n title: \"Task Migrati\",\n steps,\n }),\n ],\n });\n}\n\nfunction mapTodoStatus(\n status: \"pending\" | \"in_progress\" | \"done\" | \"blocked\",\n): StepStatus {\n const mapping: Record<string, StepStatus> = {\n pending: \"pending\",\n in_progress: \"running\",\n done: \"completed\",\n blocked: \"blocked\",\n };\n return mapping[status] ?? \"idle\";\n}\n\n// =============================================================================\n// Esempio — Piano completo per \"Costruisci API REST con auth\"\n// =============================================================================\n\n/**\n * Genera un piano di esempio per dimostrare la struttura completa.\n * Utilizzabile per test e documentazione.\n */\nexport function createExamplePlan(): Plan {\n return createPlan({\n id: \"api-rest-auth\",\n title: \"Costruisci API REST con Autenticazione\",\n description:\n \"Piano completo per creare un'API REST con autenticazione JWT, \" +\n \"database PostgreSQL, testing e deployment.\",\n metadata: {\n goal: \"Creare un'API REST production-ready con auth JWT\",\n createdBy: \"architect-agent\",\n version: 1,\n tags: [\"api\", \"rest\", \"auth\", \"jwt\", \"postgresql\"],\n constraints: [\n \"TypeScript strict mode\",\n \"100% test coverage sulle route critiche\",\n \"Response time < 200ms per endpoint\",\n ],\n estimatedTotalTokens: 500_000,\n estimatedDurationMs: 1_800_000,\n },\n phases: [\n // --- Fase 1: Design ---\n createPhase({\n id: \"design\",\n title: \"Design & Architettura\",\n order: 0,\n executionMode: \"sequential\",\n steps: [\n createStep({\n id: \"db-schema-design\",\n title: \"Design schema database\",\n description: \"Progetta le tabelle users, sessions, roles\",\n prompt:\n \"Progetta lo schema PostgreSQL per un sistema di autenticazione \" +\n \"con users, sessions e roles. Includi indici e constraint.\",\n priority: \"high\",\n contract: {\n inputs: [],\n outputs: [\n {\n name: \"sqlSchema\",\n type: \"string\",\n description: \"SQL DDL per le tabelle\",\n required: true,\n },\n {\n name: \"erDiagram\",\n type: \"string\",\n description: \"Diagramma ER in formato Mermaid\",\n required: false,\n },\n ],\n },\n resources: { maxTokenBudget: 50_000, timeoutMs: 120_000, maxRetries: 0, maxConcurrency: 5 },\n }),\n createStep({\n id: \"api-design\",\n title: \"Design endpoint API\",\n description: \"Definisci OpenAPI spec per tutti gli endpoint\",\n dependencies: [\"db-schema-design\"],\n prompt:\n \"Basandoti sullo schema DB, definisci gli endpoint REST \" +\n \"per auth (register, login, logout, refresh) e user management.\",\n contract: {\n inputs: [\n {\n name: \"sqlSchema\",\n type: \"string\",\n description: \"Schema DB dalla fase precedente\",\n required: true,\n },\n ],\n outputs: [\n {\n name: \"openApiSpec\",\n type: \"string\",\n description: \"Specifica OpenAPI 3.0 YAML\",\n required: true,\n },\n ],\n },\n resources: { maxTokenBudget: 80_000, timeoutMs: 180_000, maxRetries: 0, maxConcurrency: 5 },\n }),\n ],\n }),\n\n // --- Fase 2: Implementazione (parallela) ---\n createPhase({\n id: \"implementation\",\n title: \"Implementazione\",\n order: 1,\n executionMode: \"parallel\",\n dependencies: [\"design\"],\n resources: { maxConcurrency: 3, maxRetries: 0 },\n steps: [\n createStep({\n id: \"impl-db-layer\",\n title: \"Implementa database layer\",\n prompt: \"Implementa il database layer con Drizzle ORM basandoti sullo schema.\",\n dependencies: [\"db-schema-design\"],\n requiredTools: [\"write_file\", \"read_file\"],\n contract: {\n inputs: [\n { name: \"sqlSchema\", type: \"string\", required: true },\n ],\n outputs: [\n { name: \"dbModuleFiles\", type: \"array\", description: \"File creati\", required: true },\n ],\n },\n subSteps: [\n createSubStep({\n id: \"impl-db-connection\",\n title: \"Setup connessione DB\",\n prompt: \"Configura la connessione PostgreSQL con pool.\",\n }),\n createSubStep({\n id: \"impl-db-models\",\n title: \"Definisci i modelli Drizzle\",\n prompt: \"Crea i modelli Drizzle per users, sessions, roles.\",\n }),\n createSubStep({\n id: \"impl-db-migrations\",\n title: \"Crea migration iniziale\",\n prompt: \"Genera la migration Drizzle per lo schema iniziale.\",\n }),\n ],\n }),\n createStep({\n id: \"impl-auth-service\",\n title: \"Implementa servizio auth\",\n prompt:\n \"Implementa il servizio di autenticazione con JWT, bcrypt per password, \" +\n \"refresh token rotation.\",\n dependencies: [\"api-design\"],\n requiredTools: [\"write_file\", \"read_file\"],\n contract: {\n inputs: [\n { name: \"openApiSpec\", type: \"string\", required: true },\n ],\n outputs: [\n { name: \"authServiceFiles\", type: \"array\", required: true },\n ],\n },\n }),\n createStep({\n id: \"impl-middleware\",\n title: \"Implementa middleware auth\",\n prompt: \"Implementa il middleware di autenticazione JWT per proteggere le route.\",\n dependencies: [\"api-design\"],\n requiredTools: [\"write_file\"],\n contract: {\n inputs: [\n { name: \"openApiSpec\", type: \"string\", required: true },\n ],\n outputs: [\n {\n name: \"middlewareFile\",\n type: \"string\",\n description: \"Path del file middleware\",\n required: true,\n },\n ],\n },\n }),\n ],\n }),\n\n // --- Fase 3: Testing ---\n createPhase({\n id: \"testing\",\n title: \"Testing\",\n order: 2,\n executionMode: \"parallel\",\n dependencies: [\"implementation\"],\n steps: [\n createStep({\n id: \"test-unit\",\n title: \"Unit test\",\n prompt: \"Scrivi unit test per auth service e middleware con Vitest.\",\n dependencies: [\"impl-auth-service\", \"impl-middleware\"],\n requiredTools: [\"write_file\", \"run_command\"],\n contract: {\n inputs: [\n { name: \"authServiceFiles\", type: \"array\", required: true },\n { name: \"middlewareFile\", type: \"string\", required: true },\n ],\n outputs: [\n { name: \"testResults\", type: \"object\", description: \"Risultati test\", required: true },\n ],\n },\n }),\n createStep({\n id: \"test-integration\",\n title: \"Integration test\",\n prompt:\n \"Scrivi integration test per i flussi completi: register → login → \" +\n \"access protected → refresh → logout.\",\n dependencies: [\"impl-db-layer\", \"impl-auth-service\"],\n requiredTools: [\"write_file\", \"run_command\"],\n contract: {\n inputs: [\n { name: \"dbModuleFiles\", type: \"array\", required: true },\n { name: \"authServiceFiles\", type: \"array\", required: true },\n ],\n outputs: [\n { name: \"integrationResults\", type: \"object\", required: true },\n ],\n },\n }),\n ],\n }),\n\n // --- Fase 4: Validazione (condizionale + loop) ---\n createPhase({\n id: \"validation\",\n title: \"Validazione & Fix\",\n order: 3,\n executionMode: \"sequential\",\n dependencies: [\"testing\"],\n steps: [\n createStep({\n id: \"validate-coverage\",\n title: \"Verifica coverage\",\n executionMode: \"conditional\",\n prompt: \"Verifica che la coverage sia >= 90%.\",\n dependencies: [\"test-unit\", \"test-integration\"],\n condition: {\n expression:\n 'steps[\"test-unit\"].result.data.testResults.coverage >= 90',\n ifTrueStepId: \"deploy-prep\",\n ifFalseStepId: \"fix-coverage\",\n },\n contract: {\n inputs: [\n { name: \"testResults\", type: \"object\", required: true },\n { name: \"integrationResults\", type: \"object\", required: true },\n ],\n outputs: [\n { name: \"coverageOk\", type: \"boolean\", required: true },\n ],\n },\n }),\n createStep({\n id: \"fix-coverage\",\n title: \"Fix coverage insufficiente\",\n executionMode: \"loop\",\n prompt: \"Aggiungi test per migliorare la coverage al 90%.\",\n loopConfig: {\n condition: \"!steps['validate-coverage'].result?.data?.coverageOk\",\n maxIterations: 3,\n bodyStepIds: [\"test-unit\"],\n },\n contract: {\n inputs: [\n { name: \"coverageOk\", type: \"boolean\", required: true },\n ],\n outputs: [\n { name: \"additionalTests\", type: \"array\", required: true },\n ],\n },\n }),\n ],\n }),\n ],\n });\n}\n","// =============================================================================\n// plan:create — Tool per creare un piano strutturato gerarchico\n// =============================================================================\n\nimport { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\nimport {\n PlanSchema,\n StepExecutionModeSchema,\n StepPrioritySchema,\n IOFieldSchema,\n validatePlan,\n} from \"../../domain/plan.schema.js\";\nimport { savePlan } from \"./plan-shared.js\";\n\nconst StepInputSchema = z.object({\n id: z.string().describe(\"ID univoco dello step (kebab-case)\"),\n title: z.string().describe(\"Titolo breve\"),\n description: z.string().optional(),\n executionMode: StepExecutionModeSchema.optional(),\n priority: StepPrioritySchema.optional(),\n prompt: z.string().optional().describe(\"Istruzioni per l'agente\"),\n dependencies: z.array(z.string()).optional(),\n requiredTools: z.array(z.string()).optional(),\n inputs: z.array(IOFieldSchema).optional().describe(\"Contratto input\"),\n outputs: z.array(IOFieldSchema).optional().describe(\"Contratto output\"),\n maxTokenBudget: z.number().optional(),\n timeoutMs: z.number().optional(),\n subSteps: z.array(z.object({\n id: z.string(),\n title: z.string(),\n description: z.string().optional(),\n prompt: z.string().optional(),\n })).optional(),\n});\n\nconst PhaseInputSchema = z.object({\n id: z.string().describe(\"ID univoco della fase (kebab-case)\"),\n title: z.string().describe(\"Titolo della fase\"),\n description: z.string().optional(),\n executionMode: StepExecutionModeSchema.optional(),\n dependencies: z.array(z.string()).optional(),\n steps: z.array(StepInputSchema).min(1),\n});\n\nexport function createPlanCreateTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Crea un piano strutturato gerarchico con fasi, step e sotto-step. \" +\n \"Ogni step ha contratti input/output, priorità, risorse e dipendenze. \" +\n \"Supporta esecuzione sequenziale, parallela, condizionale e loop.\",\n inputSchema: z.object({\n id: z.string().describe(\"ID univoco del piano (kebab-case)\"),\n title: z.string().describe(\"Titolo del piano\"),\n description: z.string().optional(),\n goal: z.string().describe(\"Obiettivo principale del piano\"),\n tags: z.array(z.string()).optional(),\n constraints: z.array(z.string()).optional(),\n phases: z.array(PhaseInputSchema).min(1).describe(\"Fasi del piano\"),\n maxTokenBudget: z.number().optional(),\n timeoutMs: z.number().optional(),\n }),\n execute: async (input) => {\n const now = Date.now();\n\n const phases = input.phases.map((p, idx) => ({\n id: p.id,\n title: p.title,\n description: p.description,\n executionMode: p.executionMode ?? \"sequential\",\n status: \"idle\" as const,\n order: idx,\n dependencies: p.dependencies ?? [],\n steps: p.steps.map((s) => ({\n id: s.id,\n title: s.title,\n description: s.description,\n executionMode: s.executionMode ?? \"sequential\",\n status: \"idle\" as const,\n priority: s.priority ?? \"medium\",\n contract: {\n inputs: s.inputs ?? [],\n outputs: s.outputs ?? [],\n },\n resources: (s.maxTokenBudget || s.timeoutMs)\n ? {\n maxTokenBudget: s.maxTokenBudget,\n timeoutMs: s.timeoutMs,\n maxRetries: 0,\n maxConcurrency: 5,\n }\n : undefined,\n dependencies: s.dependencies ?? [],\n prompt: s.prompt,\n requiredTools: s.requiredTools ?? [],\n subSteps: (s.subSteps ?? []).map((ss) => ({\n id: ss.id,\n title: ss.title,\n description: ss.description,\n prompt: ss.prompt,\n status: \"idle\" as const,\n executionMode: \"sequential\" as const,\n requiredTools: [],\n })),\n createdAt: now,\n updatedAt: now,\n })),\n createdAt: now,\n updatedAt: now,\n }));\n\n const plan = PlanSchema.parse({\n id: input.id,\n title: input.title,\n description: input.description,\n status: \"draft\",\n metadata: {\n goal: input.goal,\n createdBy: \"agent\",\n version: 1,\n tags: input.tags ?? [],\n constraints: input.constraints ?? [],\n },\n phases,\n globalResources: (input.maxTokenBudget || input.timeoutMs)\n ? {\n maxTokenBudget: input.maxTokenBudget,\n timeoutMs: input.timeoutMs,\n maxRetries: 0,\n maxConcurrency: 5,\n }\n : undefined,\n createdAt: now,\n updatedAt: now,\n });\n\n // Valida la struttura\n const validation = validatePlan(plan);\n if (!validation.valid) {\n return `Errore nella creazione del piano:\\n${validation.errors.join(\"\\n\")}`;\n }\n\n await savePlan(fs, plan);\n\n const totalSteps = plan.phases.reduce((sum, p) => sum + p.steps.length, 0);\n const warnings = validation.warnings.length > 0\n ? `\\nWarning: ${validation.warnings.join(\"; \")}`\n : \"\";\n\n return (\n `Piano \"${plan.title}\" creato con successo.\\n` +\n `ID: ${plan.id}\\n` +\n `Fasi: ${plan.phases.length}\\n` +\n `Step totali: ${totalSteps}\\n` +\n `Stato: ${plan.status}` +\n warnings\n );\n },\n });\n}\n","import type { FilesystemPort } from \"../../ports/filesystem.port.js\";\nimport type { Plan } from \"../../domain/plan.schema.js\";\n\nexport const PLAN_PATH = \"plan.json\";\n\nexport async function loadPlan(fs: FilesystemPort): Promise<Plan | null> {\n const exists = await fs.exists(PLAN_PATH, \"persistent\");\n if (!exists) return null;\n const raw = await fs.read(PLAN_PATH, \"persistent\");\n return JSON.parse(raw) as Plan;\n}\n\nexport async function savePlan(fs: FilesystemPort, plan: Plan): Promise<void> {\n await fs.write(PLAN_PATH, JSON.stringify(plan, null, 2), \"persistent\");\n}\n","// =============================================================================\n// plan:update — Tool per modificare step del piano a runtime\n// =============================================================================\n\nimport { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\nimport {\n StepStatusSchema,\n StepPrioritySchema,\n StepExecutionModeSchema,\n IOFieldSchema,\n isValidStepTransition,\n validatePlan,\n type Plan,\n type Step,\n type Phase,\n} from \"../../domain/plan.schema.js\";\nimport { loadPlan, savePlan } from \"./plan-shared.js\";\n\nexport function createPlanUpdateTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Modifica un piano esistente a runtime: aggiorna stato, aggiungi/rimuovi step, \" +\n \"modifica prompt, priorità, dipendenze. Supporta transizioni di stato validate.\",\n inputSchema: z.object({\n action: z.enum([\n \"update_step\",\n \"add_step\",\n \"remove_step\",\n \"update_phase\",\n \"add_phase\",\n \"update_plan_status\",\n \"set_result\",\n ]).describe(\"Tipo di modifica\"),\n\n // Per update_step / add_step / remove_step\n phaseId: z.string().optional().describe(\"ID della fase target\"),\n stepId: z.string().optional().describe(\"ID dello step target\"),\n\n // Campi aggiornabili\n status: StepStatusSchema.optional(),\n title: z.string().optional(),\n description: z.string().optional(),\n prompt: z.string().optional(),\n priority: StepPrioritySchema.optional(),\n executionMode: StepExecutionModeSchema.optional(),\n dependencies: z.array(z.string()).optional(),\n requiredTools: z.array(z.string()).optional(),\n inputs: z.array(IOFieldSchema).optional(),\n outputs: z.array(IOFieldSchema).optional(),\n\n // Per set_result\n resultOutput: z.string().optional(),\n resultData: z.record(z.string(), z.unknown()).optional(),\n\n // Per add_phase\n phaseTitle: z.string().optional(),\n phaseOrder: z.number().optional(),\n\n // Per update_plan_status\n planStatus: z.enum([\"draft\", \"active\", \"paused\", \"completed\", \"failed\", \"cancelled\"]).optional(),\n }),\n execute: async (input) => {\n const plan = await loadPlan(fs);\n if (!plan) return \"Nessun piano trovato. Usa plan_create prima.\";\n\n const now = Date.now();\n\n switch (input.action) {\n case \"update_step\": {\n if (!input.stepId) return \"stepId richiesto per update_step\";\n const { phase, step } = findStep(plan, input.stepId);\n if (!step) return `Step \"${input.stepId}\" non trovato`;\n\n // Validazione transizione di stato\n if (input.status && input.status !== step.status) {\n if (!isValidStepTransition(step.status, input.status)) {\n return (\n `Transizione non valida: \"${step.status}\" → \"${input.status}\" ` +\n `per step \"${step.id}\"`\n );\n }\n step.status = input.status;\n if (input.status === \"running\") step.startedAt = now;\n if (input.status === \"completed\" || input.status === \"failed\") {\n step.completedAt = now;\n }\n }\n\n if (input.title) step.title = input.title;\n if (input.description) step.description = input.description;\n if (input.prompt) step.prompt = input.prompt;\n if (input.priority) step.priority = input.priority;\n if (input.executionMode) step.executionMode = input.executionMode;\n if (input.dependencies) step.dependencies = input.dependencies;\n if (input.requiredTools) step.requiredTools = input.requiredTools;\n if (input.inputs) step.contract.inputs = input.inputs;\n if (input.outputs) step.contract.outputs = input.outputs;\n step.updatedAt = now;\n\n plan.updatedAt = now;\n plan.metadata.version++;\n await savePlan(fs, plan);\n return `Step \"${step.id}\" aggiornato (v${plan.metadata.version}).`;\n }\n\n case \"add_step\": {\n if (!input.phaseId) return \"phaseId richiesto per add_step\";\n if (!input.stepId || !input.title) return \"stepId e title richiesti per add_step\";\n\n const phase = plan.phases.find((p) => p.id === input.phaseId);\n if (!phase) return `Fase \"${input.phaseId}\" non trovata`;\n\n const newStep: Step = {\n id: input.stepId,\n title: input.title,\n description: input.description,\n executionMode: input.executionMode ?? \"sequential\",\n status: \"idle\",\n priority: input.priority ?? \"medium\",\n contract: {\n inputs: input.inputs ?? [],\n outputs: input.outputs ?? [],\n },\n dependencies: input.dependencies ?? [],\n prompt: input.prompt,\n requiredTools: input.requiredTools ?? [],\n subSteps: [],\n createdAt: now,\n updatedAt: now,\n };\n\n phase.steps.push(newStep);\n phase.updatedAt = now;\n plan.updatedAt = now;\n plan.metadata.version++;\n\n const validation = validatePlan(plan);\n if (!validation.valid) {\n phase.steps.pop();\n return `Errore: lo step creerebbe problemi:\\n${validation.errors.join(\"\\n\")}`;\n }\n\n await savePlan(fs, plan);\n return `Step \"${input.stepId}\" aggiunto alla fase \"${input.phaseId}\" (v${plan.metadata.version}).`;\n }\n\n case \"remove_step\": {\n if (!input.stepId) return \"stepId richiesto per remove_step\";\n const { phase } = findStep(plan, input.stepId);\n if (!phase) return `Step \"${input.stepId}\" non trovato`;\n\n phase.steps = phase.steps.filter((s) => s.id !== input.stepId);\n phase.updatedAt = now;\n plan.updatedAt = now;\n plan.metadata.version++;\n await savePlan(fs, plan);\n return `Step \"${input.stepId}\" rimosso (v${plan.metadata.version}).`;\n }\n\n case \"update_phase\": {\n if (!input.phaseId) return \"phaseId richiesto per update_phase\";\n const phase = plan.phases.find((p) => p.id === input.phaseId);\n if (!phase) return `Fase \"${input.phaseId}\" non trovata`;\n\n if (input.title) phase.title = input.title;\n if (input.description) phase.description = input.description;\n if (input.executionMode) phase.executionMode = input.executionMode;\n if (input.dependencies) phase.dependencies = input.dependencies;\n phase.updatedAt = now;\n plan.updatedAt = now;\n plan.metadata.version++;\n await savePlan(fs, plan);\n return `Fase \"${phase.id}\" aggiornata (v${plan.metadata.version}).`;\n }\n\n case \"add_phase\": {\n if (!input.phaseId || !input.phaseTitle) {\n return \"phaseId e phaseTitle richiesti per add_phase\";\n }\n\n const newPhase: Phase = {\n id: input.phaseId,\n title: input.phaseTitle,\n description: input.description,\n executionMode: input.executionMode ?? \"sequential\",\n status: \"idle\",\n steps: [],\n order: input.phaseOrder ?? plan.phases.length,\n dependencies: input.dependencies ?? [],\n createdAt: now,\n updatedAt: now,\n };\n\n plan.phases.push(newPhase);\n plan.updatedAt = now;\n plan.metadata.version++;\n await savePlan(fs, plan);\n return `Fase \"${input.phaseId}\" aggiunta (v${plan.metadata.version}). Aggiungi step con add_step.`;\n }\n\n case \"update_plan_status\": {\n if (!input.planStatus) return \"planStatus richiesto\";\n plan.status = input.planStatus;\n if (input.planStatus === \"active\" && !plan.startedAt) {\n plan.startedAt = now;\n }\n if (input.planStatus === \"completed\" || input.planStatus === \"failed\") {\n plan.completedAt = now;\n }\n plan.updatedAt = now;\n plan.metadata.version++;\n await savePlan(fs, plan);\n return `Piano aggiornato a stato \"${input.planStatus}\" (v${plan.metadata.version}).`;\n }\n\n case \"set_result\": {\n if (!input.stepId) return \"stepId richiesto per set_result\";\n const { step } = findStep(plan, input.stepId);\n if (!step) return `Step \"${input.stepId}\" non trovato`;\n\n step.result = {\n output: input.resultOutput,\n data: input.resultData,\n };\n step.updatedAt = now;\n plan.updatedAt = now;\n await savePlan(fs, plan);\n return `Risultato salvato per step \"${input.stepId}\".`;\n }\n\n default:\n return `Azione \"${input.action}\" non supportata.`;\n }\n },\n });\n}\n\nfunction findStep(\n plan: Plan,\n stepId: string,\n): { phase?: Phase; step?: Step } {\n for (const phase of plan.phases) {\n const step = phase.steps.find((s) => s.id === stepId);\n if (step) return { phase, step };\n }\n return {};\n}\n","// =============================================================================\n// plan:status — Stato corrente con progress tree\n// =============================================================================\n\nimport { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\nimport { calculateProgress, type Plan, type StepProgress, type PhaseProgress } from \"../../domain/plan.schema.js\";\nimport { loadPlan } from \"./plan-shared.js\";\n\nexport function createPlanStatusTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Mostra lo stato corrente del piano con progress tree. \" +\n \"Visualizza avanzamento per fase, step e sotto-step.\",\n inputSchema: z.object({\n verbose: z\n .boolean()\n .optional()\n .default(false)\n .describe(\"Se true, mostra anche i sotto-step\"),\n }),\n execute: async ({ verbose }) => {\n const plan = await loadPlan(fs);\n if (!plan) return \"Nessun piano trovato. Usa plan_create prima.\";\n\n const progress = calculateProgress(plan);\n\n return formatProgressTree(progress, plan, verbose);\n },\n });\n}\n\nfunction formatProgressTree(\n progress: ReturnType<typeof calculateProgress>,\n plan: Plan,\n verbose: boolean,\n): string {\n const lines: string[] = [];\n const pct = (n: number) => `${Math.round(n * 100)}%`;\n\n // Header\n lines.push(\n `📋 ${progress.title} [${progress.status}] — ${pct(progress.progress)} completato`,\n );\n lines.push(\n ` Step: ${progress.completedSteps}/${progress.totalSteps} completati` +\n (progress.failedSteps > 0 ? `, ${progress.failedSteps} falliti` : \"\"),\n );\n if (progress.elapsedMs) {\n lines.push(` Tempo: ${Math.round(progress.elapsedMs / 1000)}s`);\n }\n if (progress.tokenUsage) {\n lines.push(\n ` Token: ${progress.tokenUsage.input + progress.tokenUsage.output} totali`,\n );\n }\n lines.push(` Versione: v${plan.metadata.version}`);\n lines.push(\"\");\n\n // Fasi\n for (const phase of progress.phases) {\n const phaseIcon = statusIcon(phase.status);\n lines.push(\n `${phaseIcon} Fase: ${phase.title} [${phase.status}] — ${pct(phase.progress)}`,\n );\n\n for (const step of phase.steps) {\n const stepIcon = statusIcon(step.status);\n const subInfo =\n step.subStepsTotal > 0\n ? ` (${step.subStepsDone}/${step.subStepsTotal} sotto-step)`\n : \"\";\n lines.push(\n ` ${stepIcon} ${step.stepId}: ${step.title} [${step.status}]${subInfo}`,\n );\n\n // SubStep (verbose only)\n if (verbose) {\n const planPhase = plan.phases.find(\n (p) => p.steps.some((s) => s.id === step.stepId),\n );\n const planStep = planPhase?.steps.find((s) => s.id === step.stepId);\n if (planStep?.subSteps.length) {\n for (const ss of planStep.subSteps) {\n const ssIcon = statusIcon(ss.status);\n lines.push(` ${ssIcon} ${ss.id}: ${ss.title} [${ss.status}]`);\n }\n }\n\n // Mostra dipendenze\n if (planStep?.dependencies.length) {\n lines.push(` ↳ dipende da: ${planStep.dependencies.join(\", \")}`);\n }\n\n // Mostra contratto\n if (planStep?.contract.outputs.length) {\n const outs = planStep.contract.outputs.map((o) => o.name).join(\", \");\n lines.push(` ↳ produce: ${outs}`);\n }\n }\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction statusIcon(status: string): string {\n const icons: Record<string, string> = {\n idle: \"⚪\",\n pending: \"🔵\",\n running: \"🔄\",\n completed: \"✅\",\n failed: \"❌\",\n skipped: \"⏭️\",\n blocked: \"🚫\",\n cancelled: \"🔴\",\n };\n return icons[status] ?? \"❓\";\n}\n","// =============================================================================\n// plan:visualize — Output ASCII o Mermaid del piano\n// =============================================================================\n\nimport { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { FilesystemPort } from \"../../ports/filesystem.port.js\";\nimport type { Plan, Phase, Step } from \"../../domain/plan.schema.js\";\nimport { loadPlan } from \"./plan-shared.js\";\n\nexport function createPlanVisualizeTool(fs: FilesystemPort) {\n return tool({\n description:\n \"Visualizza il piano come diagramma ASCII o Mermaid. \" +\n \"Mostra la gerarchia fasi/step e le dipendenze.\",\n inputSchema: z.object({\n format: z\n .enum([\"ascii\", \"mermaid\"])\n .default(\"ascii\")\n .describe(\"Formato di output\"),\n }),\n execute: async ({ format }) => {\n const plan = await loadPlan(fs);\n if (!plan) return \"Nessun piano trovato. Usa plan_create prima.\";\n\n return format === \"mermaid\"\n ? renderMermaid(plan)\n : renderAscii(plan);\n },\n });\n}\n\n// =============================================================================\n// Mermaid Renderer\n// =============================================================================\n\nfunction renderMermaid(plan: Plan): string {\n const lines: string[] = [];\n lines.push(\"```mermaid\");\n lines.push(\"graph TD\");\n lines.push(` subgraph ${sanitize(plan.title)}`);\n\n for (const phase of plan.phases) {\n const phaseLabel = `phase_${phase.id}`;\n lines.push(` subgraph ${phaseLabel}[\"${phase.title} (${phase.executionMode})\"]`);\n\n for (const step of phase.steps) {\n const shape = stepShape(step);\n lines.push(` ${step.id}${shape}`);\n }\n\n // Edge interni alla fase\n if (phase.executionMode === \"sequential\") {\n for (let i = 1; i < phase.steps.length; i++) {\n const prev = phase.steps[i - 1]!;\n const curr = phase.steps[i]!;\n if (!curr.dependencies.includes(prev.id)) {\n lines.push(` ${prev.id} --> ${curr.id}`);\n }\n }\n }\n\n lines.push(\" end\");\n }\n\n // Edge esplicite tra step (dipendenze cross-fase)\n for (const phase of plan.phases) {\n for (const step of phase.steps) {\n for (const dep of step.dependencies) {\n lines.push(` ${dep} --> ${step.id}`);\n }\n }\n }\n\n // Edge tra fasi\n for (const phase of plan.phases) {\n for (const depPhaseId of phase.dependencies) {\n const depPhase = plan.phases.find((p) => p.id === depPhaseId);\n if (depPhase) {\n const lastStep = depPhase.steps[depPhase.steps.length - 1];\n const firstStep = phase.steps[0];\n if (lastStep && firstStep) {\n lines.push(` ${lastStep.id} ==> ${firstStep.id}`);\n }\n }\n }\n }\n\n lines.push(\" end\");\n lines.push(\"```\");\n\n // Stili per stato\n lines.push(\"\");\n lines.push(\"Legenda:\");\n lines.push(\" [step] = sequenziale\");\n lines.push(\" {step} = condizionale\");\n lines.push(\" ((step)) = loop\");\n lines.push(\" ==> = dipendenza tra fasi\");\n\n return lines.join(\"\\n\");\n}\n\nfunction stepShape(step: Step): string {\n const label = `${step.title}`;\n switch (step.executionMode) {\n case \"conditional\":\n return `{${label}}`;\n case \"loop\":\n return `((${label}))`;\n case \"parallel\":\n return `[/${label}/]`;\n default:\n return `[\"${label}\"]`;\n }\n}\n\nfunction sanitize(s: string): string {\n return s.replace(/[^a-zA-Z0-9_\\- àèéìòù]/g, \"_\");\n}\n\n// =============================================================================\n// ASCII Renderer\n// =============================================================================\n\nfunction renderAscii(plan: Plan): string {\n const lines: string[] = [];\n const W = 72;\n\n lines.push(\"╔\" + \"═\".repeat(W) + \"╗\");\n lines.push(\n \"║\" + centerPad(`📋 ${plan.title}`, W) + \"║\",\n );\n lines.push(\n \"║\" + centerPad(`Stato: ${plan.status} | v${plan.metadata.version}`, W) + \"║\",\n );\n lines.push(\"╠\" + \"═\".repeat(W) + \"╣\");\n\n for (let pi = 0; pi < plan.phases.length; pi++) {\n const phase = plan.phases[pi]!;\n const modeLabel = phase.executionMode === \"parallel\" ? \"⚡ PARALLEL\" : \"→ SEQ\";\n\n lines.push(\n \"║\" +\n leftPad(\n ` Fase ${pi + 1}: ${phase.title} [${modeLabel}]`,\n W,\n ) +\n \"║\",\n );\n lines.push(\"║\" + \" \".repeat(2) + \"─\".repeat(W - 2) + \"║\");\n\n for (const step of phase.steps) {\n const icon = statusIconAscii(step.status);\n const depStr =\n step.dependencies.length > 0\n ? ` ← [${step.dependencies.join(\", \")}]`\n : \"\";\n const modeBadge = step.executionMode !== \"sequential\"\n ? ` (${step.executionMode})`\n : \"\";\n\n lines.push(\n \"║\" +\n leftPad(\n ` ${icon} ${step.id}: ${step.title}${modeBadge}${depStr}`,\n W,\n ) +\n \"║\",\n );\n\n // SubStep\n for (const ss of step.subSteps) {\n const ssIcon = statusIconAscii(ss.status);\n lines.push(\n \"║\" +\n leftPad(` ${ssIcon} └─ ${ss.id}: ${ss.title}`, W) +\n \"║\",\n );\n }\n\n // Contratto output\n if (step.contract.outputs.length > 0) {\n const outs = step.contract.outputs.map((o) => o.name).join(\", \");\n lines.push(\n \"║\" + leftPad(` ↳ output: ${outs}`, W) + \"║\",\n );\n }\n }\n\n if (pi < plan.phases.length - 1) {\n lines.push(\"║\" + \" \".repeat(W) + \"║\");\n\n // Connessione tra fasi\n const nextPhase = plan.phases[pi + 1]!;\n if (nextPhase.dependencies.includes(phase.id)) {\n lines.push(\"║\" + centerPad(\"│\", W) + \"║\");\n lines.push(\"║\" + centerPad(\"▼\", W) + \"║\");\n } else {\n lines.push(\"║\" + centerPad(\"┊\", W) + \"║\");\n }\n lines.push(\"║\" + \" \".repeat(W) + \"║\");\n }\n }\n\n lines.push(\"╚\" + \"═\".repeat(W) + \"╝\");\n return lines.join(\"\\n\");\n}\n\nfunction statusIconAscii(status: string): string {\n const icons: Record<string, string> = {\n idle: \"○\",\n pending: \"◉\",\n running: \"►\",\n completed: \"✓\",\n failed: \"✗\",\n skipped: \"⊘\",\n blocked: \"⊗\",\n cancelled: \"⊖\",\n };\n return icons[status] ?? \"?\";\n}\n\nfunction centerPad(text: string, width: number): string {\n // Account for multi-byte characters in emoji\n const visLen = [...text].length;\n if (visLen >= width) return text.slice(0, width);\n const left = Math.floor((width - visLen) / 2);\n const right = width - visLen - left;\n return \" \".repeat(left) + text + \" \".repeat(right);\n}\n\nfunction leftPad(text: string, width: number): string {\n const visLen = [...text].length;\n if (visLen >= width) return text.slice(0, width);\n return text + \" \".repeat(width - visLen);\n}\n","// =============================================================================\n// PriorityQueue<T> — Binary heap with custom comparator\n// =============================================================================\n\nexport class PriorityQueue<T> {\n private readonly heap: T[] = [];\n private readonly compare: (a: T, b: T) => number;\n\n constructor(compare: (a: T, b: T) => number) {\n this.compare = compare;\n }\n\n get size(): number {\n return this.heap.length;\n }\n\n enqueue(item: T): void {\n this.heap.push(item);\n this.bubbleUp(this.heap.length - 1);\n }\n\n dequeue(): T | undefined {\n if (this.heap.length === 0) return undefined;\n const top = this.heap[0];\n const last = this.heap.pop()!;\n if (this.heap.length > 0) {\n this.heap[0] = last;\n this.sinkDown(0);\n }\n return top;\n }\n\n peek(): T | undefined {\n return this.heap[0];\n }\n\n private bubbleUp(i: number): void {\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (this.compare(this.heap[i], this.heap[parent]) >= 0) break;\n [this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];\n i = parent;\n }\n }\n\n private sinkDown(i: number): void {\n const n = this.heap.length;\n while (true) {\n let smallest = i;\n const left = 2 * i + 1;\n const right = 2 * i + 2;\n if (left < n && this.compare(this.heap[left], this.heap[smallest]) < 0) {\n smallest = left;\n }\n if (right < n && this.compare(this.heap[right], this.heap[smallest]) < 0) {\n smallest = right;\n }\n if (smallest === i) break;\n [this.heap[i], this.heap[smallest]] = [this.heap[smallest], this.heap[i]];\n i = smallest;\n }\n }\n}\n","// =============================================================================\n// WorkerPool<T, R> — Generic async work-stealing pool with dynamic sizing\n// =============================================================================\n\nimport { PriorityQueue } from './priority-queue.js';\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface WorkerPoolConfig {\n initialSize: number;\n minSize: number;\n maxSize: number;\n taskTimeoutMs: number;\n heartbeatIntervalMs: number;\n idleShrinkMs: number;\n growThreshold: number;\n}\n\nexport interface WorkerPoolMetrics {\n activeWorkers: number;\n idleWorkers: number;\n queueDepth: number;\n totalCompleted: number;\n totalFailed: number;\n throughputPerSecond: number;\n latencyP50Ms: number;\n latencyP95Ms: number;\n latencyP99Ms: number;\n utilizationRatio: number;\n workStealCount: number;\n}\n\nexport type WorkerPoolEvent<T, R> =\n | { type: 'task:started'; taskId: string; workerId: number }\n | { type: 'task:completed'; taskId: string; result: R; durationMs: number }\n | { type: 'task:failed'; taskId: string; error: Error; durationMs: number }\n | { type: 'task:timeout'; taskId: string; workerId: number }\n | { type: 'worker:spawned'; workerId: number; poolSize: number }\n | { type: 'worker:removed'; workerId: number; poolSize: number; reason: string }\n | { type: 'pool:drained' }\n | { type: 'pool:pressure'; queueDepth: number; activeWorkers: number };\n\ninterface PoolTask<T, R = unknown> {\n readonly id: string;\n readonly input: T;\n readonly priority: number;\n readonly enqueuedAt: number;\n readonly abortController: AbortController;\n readonly resolve: (result: R | PromiseLike<R>) => void;\n readonly reject: (error: Error) => void;\n}\n\ntype WorkerState = 'idle' | 'busy' | 'dead';\n\ninterface WorkerSlot<T, R = unknown> {\n state: WorkerState;\n currentTask: PoolTask<T, R> | null;\n idleSince: number;\n wakeResolve: (() => void) | null;\n}\n\n// ── Defaults ─────────────────────────────────────────────────────────────────\n\nconst DEFAULT_POOL_CONFIG: WorkerPoolConfig = {\n initialSize: 4,\n minSize: 1,\n maxSize: 16,\n taskTimeoutMs: 60_000,\n heartbeatIntervalMs: 5_000,\n idleShrinkMs: 30_000,\n growThreshold: 3,\n};\n\n// ── Implementation ───────────────────────────────────────────────────────────\n\nexport class WorkerPool<T, R> {\n private readonly queue: PriorityQueue<PoolTask<T, R>>;\n private readonly workers = new Map<number, WorkerSlot<T, R>>();\n private readonly executor: (input: T, signal: AbortSignal) => Promise<R>;\n private readonly config: WorkerPoolConfig;\n private readonly onEvent?: (event: WorkerPoolEvent<T, R>) => void;\n private readonly latencies: number[] = [];\n private readonly completionTimestamps: number[] = [];\n private static readonly MAX_METRICS_ENTRIES = 1000;\n\n private nextWorkerId = 0;\n private draining = false;\n private drainingResolve?: () => void;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private totalCompleted = 0;\n private totalFailed = 0;\n private workStealCount = 0;\n\n constructor(\n executor: (input: T, signal: AbortSignal) => Promise<R>,\n config?: Partial<WorkerPoolConfig>,\n onEvent?: (event: WorkerPoolEvent<T, R>) => void,\n ) {\n this.executor = executor;\n this.config = { ...DEFAULT_POOL_CONFIG, ...config };\n this.onEvent = onEvent;\n this.queue = new PriorityQueue<PoolTask<T, R>>(\n (a, b) => a.priority - b.priority,\n );\n\n for (let i = 0; i < this.config.initialSize; i++) {\n this.spawnWorker();\n }\n this.startHeartbeatMonitor();\n }\n\n // ── Public API ─────────────────────────────────────────────────────────────\n\n submit(id: string, input: T, priority = 0): Promise<R> {\n if (this.draining) throw new Error('Pool is draining, cannot submit');\n\n return new Promise<R>((resolve, reject) => {\n const task: PoolTask<T, R> = {\n id,\n input,\n priority,\n enqueuedAt: Date.now(),\n abortController: new AbortController(),\n resolve,\n reject,\n };\n\n this.queue.enqueue(task);\n this.wakeOneIdleWorker();\n });\n }\n\n async drain(timeoutMs = 30_000): Promise<void> {\n this.draining = true;\n\n if (this.allIdle() && this.queue.size === 0) {\n this.cleanup();\n this.emit({ type: 'pool:drained' });\n return;\n }\n\n return new Promise<void>((resolve, reject) => {\n this.drainingResolve = () => {\n this.cleanup();\n this.emit({ type: 'pool:drained' });\n resolve();\n };\n\n const timer = setTimeout(() => {\n for (const [, slot] of this.workers) {\n slot.currentTask?.abortController.abort(\n new Error('Pool drain timeout'),\n );\n slot.state = 'dead';\n if (slot.wakeResolve) {\n slot.wakeResolve();\n slot.wakeResolve = null;\n }\n }\n this.cleanup();\n reject(new Error(`Drain timeout after ${timeoutMs}ms`));\n }, timeoutMs);\n\n const originalResolve = this.drainingResolve!;\n this.drainingResolve = () => {\n clearTimeout(timer);\n originalResolve();\n };\n\n // Wake all idle workers so they can detect drain\n for (const [, slot] of this.workers) {\n if (slot.state === 'idle' && slot.wakeResolve) {\n slot.wakeResolve();\n slot.wakeResolve = null;\n }\n }\n });\n }\n\n getMetrics(): WorkerPoolMetrics {\n let active = 0;\n let idle = 0;\n for (const slot of this.workers.values()) {\n if (slot.state === 'busy') active++;\n else if (slot.state === 'idle') idle++;\n }\n\n const now = Date.now();\n const windowMs = 60_000;\n const recentCompletions = this.completionTimestamps.filter(\n (t) => now - t < windowMs,\n );\n\n const sorted = [...this.latencies].sort((a, b) => a - b);\n const p = (pct: number) => {\n if (sorted.length === 0) return 0;\n const idx = Math.min(\n Math.floor((pct / 100) * sorted.length),\n sorted.length - 1,\n );\n return sorted[idx];\n };\n\n return {\n activeWorkers: active,\n idleWorkers: idle,\n queueDepth: this.queue.size,\n totalCompleted: this.totalCompleted,\n totalFailed: this.totalFailed,\n throughputPerSecond:\n recentCompletions.length > 0\n ? recentCompletions.length / (windowMs / 1000)\n : 0,\n latencyP50Ms: p(50),\n latencyP95Ms: p(95),\n latencyP99Ms: p(99),\n utilizationRatio:\n this.workers.size > 0 ? active / this.workers.size : 0,\n workStealCount: this.workStealCount,\n };\n }\n\n // ── Worker lifecycle ───────────────────────────────────────────────────────\n\n private spawnWorker(): void {\n const id = this.nextWorkerId++;\n const slot: WorkerSlot<T, R> = {\n state: 'idle',\n currentTask: null,\n idleSince: Date.now(),\n wakeResolve: null,\n };\n this.workers.set(id, slot);\n this.emit({\n type: 'worker:spawned',\n workerId: id,\n poolSize: this.workers.size,\n });\n // Fire-and-forget the worker loop\n this.workerLoop(id).catch(() => { /* worker loop self-recovers */ });\n }\n\n private removeWorker(id: number, reason: string): void {\n const slot = this.workers.get(id);\n if (!slot) return;\n slot.state = 'dead';\n if (slot.wakeResolve) {\n slot.wakeResolve();\n slot.wakeResolve = null;\n }\n this.workers.delete(id);\n this.emit({\n type: 'worker:removed',\n workerId: id,\n poolSize: this.workers.size,\n reason,\n });\n }\n\n private async workerLoop(workerId: number): Promise<void> {\n const slot = this.workers.get(workerId)!;\n\n while (slot.state !== 'dead') {\n const task = this.queue.dequeue();\n\n if (!task) {\n slot.state = 'idle';\n slot.idleSince = Date.now();\n\n if (this.draining && this.allIdle() && this.queue.size === 0) {\n this.drainingResolve?.();\n return;\n }\n\n // Park until woken\n await new Promise<void>((resolve) => {\n slot.wakeResolve = resolve;\n });\n\n if ((slot.state as WorkerState) === 'dead') return;\n continue;\n }\n\n // Work-stealing: took a task from the shared queue\n this.workStealCount++;\n slot.state = 'busy';\n slot.currentTask = task;\n\n this.emit({ type: 'task:started', taskId: task.id, workerId });\n const startMs = Date.now();\n\n try {\n const result = await this.executeWithTimeout(task, workerId);\n const durationMs = Date.now() - startMs;\n\n this.latencies.push(durationMs);\n this.completionTimestamps.push(Date.now());\n if (this.latencies.length > WorkerPool.MAX_METRICS_ENTRIES) {\n this.latencies.splice(0, this.latencies.length - WorkerPool.MAX_METRICS_ENTRIES);\n }\n if (this.completionTimestamps.length > WorkerPool.MAX_METRICS_ENTRIES) {\n this.completionTimestamps.splice(0, this.completionTimestamps.length - WorkerPool.MAX_METRICS_ENTRIES);\n }\n this.totalCompleted++;\n\n this.emit({\n type: 'task:completed',\n taskId: task.id,\n result,\n durationMs,\n });\n task.resolve(result);\n } catch (error) {\n const durationMs = Date.now() - startMs;\n this.latencies.push(durationMs);\n this.totalFailed++;\n\n const err =\n error instanceof Error ? error : new Error(String(error));\n this.emit({\n type: 'task:failed',\n taskId: task.id,\n error: err,\n durationMs,\n });\n task.reject(err);\n } finally {\n slot.currentTask = null;\n }\n }\n }\n\n private executeWithTimeout(\n task: PoolTask<T, R>,\n workerId: number,\n ): Promise<R> {\n return new Promise<R>((resolve, reject) => {\n let settled = false;\n const timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n task.abortController.abort(\n new Error(`Task timeout after ${this.config.taskTimeoutMs}ms`),\n );\n this.emit({\n type: 'task:timeout',\n taskId: task.id,\n workerId,\n });\n reject(\n new Error(`Task \"${task.id}\" timed out after ${this.config.taskTimeoutMs}ms`),\n );\n }\n }, this.config.taskTimeoutMs);\n\n this.executor(task.input, task.abortController.signal).then(\n (result) => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n resolve(result);\n }\n },\n (error) => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n reject(error);\n }\n },\n );\n });\n }\n\n // ── Autoscaling ────────────────────────────────────────────────────────────\n\n private autoscale(): void {\n const now = Date.now();\n let active = 0;\n let idle = 0;\n for (const slot of this.workers.values()) {\n if (slot.state === 'busy') active++;\n else if (slot.state === 'idle') idle++;\n }\n\n // Grow: deep queue + all busy\n if (\n this.queue.size > this.config.growThreshold &&\n idle === 0 &&\n this.workers.size < this.config.maxSize\n ) {\n const toAdd = Math.min(\n Math.ceil(this.queue.size / 2),\n this.config.maxSize - this.workers.size,\n );\n for (let i = 0; i < toAdd; i++) this.spawnWorker();\n }\n\n // Shrink: excess idle workers\n if (idle > 1 && this.workers.size > this.config.minSize) {\n for (const [id, slot] of this.workers) {\n if (\n slot.state === 'idle' &&\n now - slot.idleSince > this.config.idleShrinkMs &&\n this.workers.size > this.config.minSize\n ) {\n this.removeWorker(id, 'idle-timeout');\n }\n }\n }\n }\n\n // ── Health monitoring ──────────────────────────────────────────────────────\n\n private startHeartbeatMonitor(): void {\n this.heartbeatTimer = setInterval(() => {\n this.autoscale();\n }, this.config.heartbeatIntervalMs);\n }\n\n // ── Helpers ────────────────────────────────────────────────────────────────\n\n private wakeOneIdleWorker(): void {\n for (const [, slot] of this.workers) {\n if (slot.state === 'idle' && slot.wakeResolve) {\n slot.wakeResolve();\n slot.wakeResolve = null;\n return;\n }\n }\n }\n\n private allIdle(): boolean {\n for (const slot of this.workers.values()) {\n if (slot.state === 'busy') return false;\n }\n return true;\n }\n\n private emit(event: WorkerPoolEvent<T, R>): void {\n this.onEvent?.(event);\n }\n\n private cleanup(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n for (const [id] of this.workers) {\n const slot = this.workers.get(id)!;\n slot.state = 'dead';\n if (slot.wakeResolve) {\n slot.wakeResolve();\n slot.wakeResolve = null;\n }\n }\n }\n}\n","// =============================================================================\n// AsyncChannel<T> — Push-to-pull bridge implementing AsyncIterable\n// =============================================================================\n\nexport class AsyncChannel<T> implements AsyncIterable<T> {\n private buffer: T[] = [];\n private waiters: Array<{\n resolve: (value: IteratorResult<T>) => void;\n }> = [];\n private closed = false;\n\n push(value: T): void {\n if (this.closed) return;\n\n if (this.waiters.length > 0) {\n const waiter = this.waiters.shift()!;\n waiter.resolve({ value, done: false });\n } else {\n this.buffer.push(value);\n }\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n for (const waiter of this.waiters) {\n waiter.resolve({ value: undefined as unknown as T, done: true });\n }\n this.waiters = [];\n }\n\n get isClosed(): boolean {\n return this.closed;\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: (): Promise<IteratorResult<T>> => {\n if (this.buffer.length > 0) {\n return Promise.resolve({ value: this.buffer.shift()!, done: false });\n }\n if (this.closed) {\n return Promise.resolve({\n value: undefined as unknown as T,\n done: true,\n });\n }\n return new Promise<IteratorResult<T>>((resolve) => {\n this.waiters.push({ resolve });\n });\n },\n };\n }\n}\n","// =============================================================================\n// IncrementalReadyTracker — Incremental Kahn's algorithm\n// =============================================================================\n\nexport class IncrementalReadyTracker {\n /** nodeId → number of pending (uncompleted) dependencies */\n private readonly pendingDeps: Map<string, number>;\n /** nodeId → list of successor nodeIds (reverse edges) */\n private readonly successors: Map<string, string[]>;\n /** Callback invoked when a node becomes ready (all deps satisfied) */\n private readonly onReady: (nodeId: string) => void;\n\n constructor(\n edges: ReadonlyMap<string, readonly string[]>,\n allNodeIds: Iterable<string>,\n onReady: (nodeId: string) => void,\n ) {\n this.onReady = onReady;\n this.pendingDeps = new Map();\n this.successors = new Map();\n\n // Build reverse graph + dependency counts\n for (const nodeId of allNodeIds) {\n const deps = edges.get(nodeId) ?? [];\n this.pendingDeps.set(nodeId, deps.length);\n\n for (const dep of deps) {\n let succ = this.successors.get(dep);\n if (!succ) {\n succ = [];\n this.successors.set(dep, succ);\n }\n succ.push(nodeId);\n }\n }\n }\n\n /** Emit all nodes with zero dependencies */\n seedInitialReady(): void {\n for (const [nodeId, count] of this.pendingDeps) {\n if (count === 0) {\n this.onReady(nodeId);\n }\n }\n }\n\n /** Mark a node as completed; returns list of newly-ready successors */\n markCompleted(nodeId: string): string[] {\n const newlyReady: string[] = [];\n const succs = this.successors.get(nodeId) ?? [];\n\n for (const succ of succs) {\n const remaining = this.pendingDeps.get(succ)! - 1;\n this.pendingDeps.set(succ, remaining);\n\n if (remaining === 0) {\n newlyReady.push(succ);\n this.onReady(succ);\n }\n }\n\n return newlyReady;\n }\n\n /** Snapshot current pending-deps state for checkpoint */\n snapshot(): Map<string, number> {\n return new Map(this.pendingDeps);\n }\n\n /** Restore from a previously taken snapshot */\n restoreFrom(snap: Map<string, number>): void {\n for (const [k, v] of snap) {\n this.pendingDeps.set(k, v);\n }\n }\n}\n","// =============================================================================\n// TokenBudgetController — Acquire/release budget with rolling estimation\n// =============================================================================\n\nexport type BudgetStatus = 'ok' | 'soft-limit' | 'hard-limit';\n\nexport interface TokenBudgetControllerConfig {\n totalBudget: number;\n /** Fraction of budget triggering soft-limit (default 0.8) */\n softLimitRatio: number;\n /** Fraction of budget triggering hard-limit (default 0.95) */\n hardLimitRatio: number;\n /** Estimated tokens per node for pre-allocation (default 5000) */\n estimatedTokensPerNode: number;\n}\n\nconst DEFAULT_BUDGET_CONFIG: Omit<TokenBudgetControllerConfig, 'totalBudget'> = {\n softLimitRatio: 0.8,\n hardLimitRatio: 0.95,\n estimatedTokensPerNode: 5_000,\n};\n\nexport class TokenBudgetController {\n private readonly config: TokenBudgetControllerConfig;\n private reserved = 0;\n private consumed = 0;\n private readonly recentUsages: number[] = [];\n\n constructor(\n totalBudget: number,\n config?: Partial<Omit<TokenBudgetControllerConfig, 'totalBudget'>>,\n ) {\n this.config = { ...DEFAULT_BUDGET_CONFIG, totalBudget, ...config };\n }\n\n /**\n * Reserve budget BEFORE executing a node.\n * Returns whether it was granted and an optional throttle delay.\n */\n acquire(_nodeId: string): { granted: boolean; delayMs: number } {\n const estimated = this.config.estimatedTokensPerNode;\n const projected = this.consumed + this.reserved + estimated;\n const ratio = projected / this.config.totalBudget;\n\n if (ratio > this.config.hardLimitRatio) {\n return { granted: false, delayMs: 0 };\n }\n\n if (ratio > this.config.softLimitRatio) {\n const pressure =\n (ratio - this.config.softLimitRatio) /\n (this.config.hardLimitRatio - this.config.softLimitRatio);\n const delayMs = Math.round(pressure * 5_000);\n this.reserved += estimated;\n return { granted: true, delayMs };\n }\n\n this.reserved += estimated;\n return { granted: true, delayMs: 0 };\n }\n\n /**\n * Finalize actual consumption. Moves tokens from reserved to consumed.\n */\n release(actual: { input: number; output: number }): void {\n this.reserved = Math.max(\n 0,\n this.reserved - this.config.estimatedTokensPerNode,\n );\n this.consumed += actual.input + actual.output;\n this.updateEstimate(actual.input + actual.output);\n }\n\n /** Check current budget status without reserving */\n check(usage: { input: number; output: number }): BudgetStatus {\n const total = usage.input + usage.output;\n const ratio = total / this.config.totalBudget;\n if (ratio >= this.config.hardLimitRatio) return 'hard-limit';\n if (ratio >= this.config.softLimitRatio) return 'soft-limit';\n return 'ok';\n }\n\n /** Remaining budget (total - consumed - reserved) */\n remaining(): number {\n return Math.max(\n 0,\n this.config.totalBudget - this.consumed - this.reserved,\n );\n }\n\n /** Estimated number of nodes that can still execute */\n estimatedRemainingNodes(): number {\n return Math.floor(this.remaining() / this.config.estimatedTokensPerNode);\n }\n\n /** Rolling average of last N executions to refine estimates */\n private updateEstimate(actual: number): void {\n this.recentUsages.push(actual);\n if (this.recentUsages.length > 20) this.recentUsages.shift();\n this.config.estimatedTokensPerNode = Math.ceil(\n this.recentUsages.reduce((a, b) => a + b, 0) / this.recentUsages.length,\n );\n }\n}\n","// =============================================================================\n// ForkCoordinator — Manages parallel fork execution with partial results\n// =============================================================================\n\nimport type { NodeResult } from \"./agent-node.js\";\n\nexport class ForkCoordinator {\n private readonly results = new Map<string, NodeResult>();\n private readonly errors = new Map<string, Error>();\n private readonly total: number;\n private resolveAll!: (results: NodeResult[]) => void;\n private rejectAll!: (error: Error) => void;\n readonly promise: Promise<NodeResult[]>;\n private timeoutTimer?: ReturnType<typeof setTimeout>;\n private settled = false;\n\n constructor(\n private readonly forkId: string,\n nodeIds: string[],\n timeoutMs: number,\n private readonly minResults: number,\n private readonly onPartial?: (results: NodeResult[]) => void,\n ) {\n this.total = nodeIds.length;\n this.promise = new Promise((resolve, reject) => {\n this.resolveAll = resolve;\n this.rejectAll = reject;\n });\n\n this.timeoutTimer = setTimeout(() => {\n if (this.settled) return;\n if (this.results.size >= this.minResults) {\n this.settle();\n this.resolveAll([...this.results.values()]);\n } else {\n this.settle();\n this.rejectAll(\n new Error(\n `Fork \"${forkId}\" timeout: only ${this.results.size}/${this.total} ` +\n `completed (minimum: ${this.minResults})`,\n ),\n );\n }\n }, timeoutMs);\n }\n\n onNodeComplete(nodeId: string, result: NodeResult): void {\n if (this.settled) return;\n this.results.set(nodeId, result);\n this.onPartial?.([...this.results.values()]);\n\n if (this.results.size === this.total) {\n this.settle();\n this.resolveAll([...this.results.values()]);\n } else {\n this.tryEagerResolve();\n }\n }\n\n onNodeError(nodeId: string, error: Error): void {\n if (this.settled) return;\n this.errors.set(nodeId, error);\n\n if (this.errors.size > this.total - this.minResults) {\n this.settle();\n this.rejectAll(\n new Error(\n `Fork \"${this.forkId}\": too many failures (${this.errors.size}/${this.total})`,\n ),\n );\n } else {\n this.tryEagerResolve();\n }\n }\n\n /** Eagerly resolve when all nodes reported and we have enough successes */\n private tryEagerResolve(): void {\n if (this.settled) return;\n if (this.results.size + this.errors.size === this.total && this.results.size >= this.minResults) {\n this.settle();\n this.resolveAll([...this.results.values()]);\n }\n }\n\n dispose(): void {\n this.settle();\n }\n\n private settle(): void {\n if (this.settled) return;\n this.settled = true;\n if (this.timeoutTimer) {\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = undefined;\n }\n }\n}\n","// =============================================================================\n// GraphExecutor — Reactive, event-driven DAG execution engine\n// Uses WorkerPool (work-stealing), IncrementalReadyTracker (push-based),\n// AsyncChannel (callback→AsyncGenerator bridge), and TokenBudgetController.\n// =============================================================================\n\nimport type { GraphConfig, GraphResult, GraphStreamEvent } from \"../domain/graph.schema.js\";\nimport type { ConsensusPort } from \"../ports/consensus.port.js\";\nimport type { NodeResult } from \"./agent-node.js\";\nimport type { AgentNode } from \"./agent-node.js\";\nimport type { SharedContext } from \"./shared-context.js\";\nimport type { EventBus } from \"../agent/event-bus.js\";\nimport type { TelemetryPort } from \"../ports/telemetry.port.js\";\nimport { WorkerPool } from \"./worker-pool.js\";\nimport { AsyncChannel } from \"./async-channel.js\";\nimport { IncrementalReadyTracker } from \"./incremental-ready-tracker.js\";\nimport { TokenBudgetController } from \"./token-budget-controller.js\";\nimport { ForkCoordinator } from \"./fork-coordinator.js\";\n\ninterface NodeTask {\n nodeId: string;\n prompt: string;\n}\n\nexport interface GraphCheckpoint {\n completedNodes: Map<string, NodeResult>;\n pendingDepsSnapshot: Map<string, number>;\n tokenUsage: { input: number; output: number };\n elapsedMs: number;\n prompt: string;\n}\n\nexport class GraphExecutor {\n private static readonly CHECKPOINT_INTERVAL = 5;\n\n constructor(\n private readonly nodes: Map<string, AgentNode>,\n private readonly edges: Map<string, string[]>,\n private readonly forks: Map<\n string,\n { nodes: AgentNode[]; consensus?: ConsensusPort }\n >,\n private readonly config: GraphConfig,\n private readonly sharedContext: SharedContext,\n private readonly eventBus?: EventBus,\n private readonly telemetry?: TelemetryPort,\n ) {}\n\n async execute(prompt: string): Promise<GraphResult> {\n let result: GraphResult | undefined;\n for await (const event of this.stream(prompt)) {\n if (event.type === \"graph:complete\") {\n result = event.result;\n }\n if (event.type === \"graph:error\") {\n throw new Error(event.error);\n }\n }\n if (!result) throw new Error(\"Graph execution produced no result\");\n return result;\n }\n\n async *stream(prompt: string): AsyncGenerator<GraphStreamEvent> {\n const start = Date.now();\n const nodeResults = new Map<string, NodeResult>();\n let totalInput = 0;\n let totalOutput = 0;\n let completedCount = 0;\n const totalNodes = this.nodes.size;\n let terminated = false;\n\n const channel = new AsyncChannel<GraphStreamEvent>();\n const budgetCtrl = new TokenBudgetController(this.config.maxTokenBudget);\n\n // ── WorkerPool with executor closure ──\n const pool = new WorkerPool<NodeTask, NodeResult>(\n async (task: NodeTask, signal: AbortSignal): Promise<NodeResult> => {\n const { nodeId } = task;\n this.eventBus?.emit(\"node:start\", { nodeId });\n channel.push({ type: \"node:start\", nodeId });\n const nodeSpan = this.telemetry?.startSpan(\n `graph.node.${nodeId}`,\n { \"node.id\": nodeId },\n );\n\n try {\n const fork = this.forks.get(nodeId);\n if (fork) {\n const result = await this.executeForkTask(\n nodeId, prompt, fork, nodeResults, channel,\n );\n nodeSpan?.setAttribute(\"node.duration_ms\", result.durationMs);\n nodeSpan?.setStatus(\"OK\");\n return result;\n }\n\n const node = this.nodes.get(nodeId);\n if (!node) throw new Error(`Node \"${nodeId}\" not found`);\n\n const enrichedPrompt = this.buildNodePrompt(prompt, nodeId, nodeResults);\n const result = await node.run(enrichedPrompt, this.sharedContext);\n nodeSpan?.setAttribute(\"node.duration_ms\", result.durationMs);\n nodeSpan?.setStatus(\"OK\");\n return result;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n nodeSpan?.setStatus(\"ERROR\", errorMsg);\n throw error;\n } finally {\n nodeSpan?.end();\n }\n },\n {\n initialSize: this.config.maxConcurrency,\n minSize: 1,\n maxSize: this.config.maxConcurrency,\n taskTimeoutMs: 600_000,\n heartbeatIntervalMs: 60_000,\n idleShrinkMs: 30_000,\n growThreshold: 10,\n },\n );\n\n const emitError = (errorMsg: string) => {\n if (terminated) return;\n terminated = true;\n const partialResults: Record<string, NodeResult> = {};\n for (const [id, r] of nodeResults) {\n partialResults[id] = r;\n }\n this.eventBus?.emit(\"graph:complete\", {\n totalDurationMs: Date.now() - start,\n totalTokenUsage: { input: totalInput, output: totalOutput },\n error: errorMsg,\n });\n channel.push({ type: \"graph:error\", error: errorMsg, partialResults });\n channel.close();\n };\n\n const emitCompletion = () => {\n if (terminated) return;\n terminated = true;\n const lastNodeId = this.findTerminalNode();\n const lastResult = nodeResults.get(lastNodeId)!;\n const resultMap: Record<string, NodeResult> = {};\n for (const [id, r] of nodeResults) {\n resultMap[id] = r;\n }\n const result: GraphResult = {\n output: lastResult.output,\n nodeResults: resultMap,\n totalDurationMs: Date.now() - start,\n totalTokenUsage: { input: totalInput, output: totalOutput },\n };\n this.eventBus?.emit(\"graph:complete\", {\n totalDurationMs: result.totalDurationMs,\n totalTokenUsage: result.totalTokenUsage,\n });\n channel.push({ type: \"graph:complete\", result });\n channel.close();\n };\n\n // ── IncrementalReadyTracker: push-based scheduling ──\n const tracker = new IncrementalReadyTracker(\n this.edges,\n this.nodes.keys(),\n (nodeId: string) => {\n if (nodeResults.has(nodeId) || terminated) return;\n\n pool\n .submit(nodeId, { nodeId, prompt }, 0)\n .then((result) => {\n if (terminated) return;\n nodeResults.set(result.nodeId, result);\n completedCount++;\n\n if (result.tokenUsage) {\n totalInput += result.tokenUsage.input;\n totalOutput += result.tokenUsage.output;\n budgetCtrl.release(result.tokenUsage);\n }\n\n this.eventBus?.emit(\"node:complete\", { nodeId, result });\n channel.push({ type: \"node:complete\", nodeId, result });\n\n // Budget enforcement\n if (totalInput + totalOutput > this.config.maxTokenBudget) {\n emitError(\"Token budget exceeded\");\n return;\n }\n\n // Budget soft/hard warnings\n const budgetStatus = budgetCtrl.check({ input: totalInput, output: totalOutput });\n if (budgetStatus === \"soft-limit\") {\n channel.push({\n type: \"budget:warning\",\n remaining: budgetCtrl.remaining(),\n used: totalInput + totalOutput,\n threshold: \"soft\",\n });\n } else if (budgetStatus === \"hard-limit\") {\n channel.push({\n type: \"budget:warning\",\n remaining: budgetCtrl.remaining(),\n used: totalInput + totalOutput,\n threshold: \"hard\",\n });\n }\n\n // Checkpoint every N nodes\n if (\n completedCount % GraphExecutor.CHECKPOINT_INTERVAL === 0 &&\n completedCount < totalNodes\n ) {\n const cp: GraphCheckpoint = {\n completedNodes: new Map(nodeResults),\n pendingDepsSnapshot: tracker.snapshot(),\n tokenUsage: { input: totalInput, output: totalOutput },\n elapsedMs: Date.now() - start,\n prompt,\n };\n channel.push({\n type: \"checkpoint:saved\",\n checkpoint: JSON.stringify({\n completedNodeIds: [...cp.completedNodes.keys()],\n tokenUsage: cp.tokenUsage,\n elapsedMs: cp.elapsedMs,\n }),\n completedCount,\n });\n }\n\n // Trigger successors via tracker (push-based)\n tracker.markCompleted(nodeId);\n\n // Check completion\n if (completedCount === totalNodes) {\n emitCompletion();\n }\n })\n .catch((error) => {\n if (terminated) return;\n const errorMsg =\n error instanceof Error ? error.message : String(error);\n this.eventBus?.emit(\"node:complete\", { nodeId, error: errorMsg });\n channel.push({ type: \"node:error\", nodeId, error: errorMsg });\n emitError(errorMsg);\n });\n },\n );\n\n this.eventBus?.emit(\"graph:start\", { nodeCount: totalNodes });\n yield { type: \"graph:start\", nodeCount: totalNodes };\n\n // Seed nodes with zero dependencies\n tracker.seedInitialReady();\n\n // Deadlock detection: if no nodes were seeded and graph isn't empty\n if (completedCount === 0 && totalNodes > 0 && terminated === false) {\n // Check if any node has zero deps (should have been seeded)\n let hasZeroDeps = false;\n for (const nodeId of this.nodes.keys()) {\n const deps = this.edges.get(nodeId) ?? [];\n if (deps.length === 0) {\n hasZeroDeps = true;\n break;\n }\n }\n if (!hasZeroDeps) {\n emitError(\"Deadlock: no nodes ready but graph incomplete\");\n }\n }\n\n // Graph-level timeout\n const timeoutTimer = setTimeout(() => {\n emitError(\"Graph execution timed out\");\n }, this.config.timeoutMs);\n\n try {\n for await (const event of channel) {\n yield event;\n if (\n event.type === \"graph:complete\" ||\n event.type === \"graph:error\"\n ) {\n break;\n }\n }\n } finally {\n clearTimeout(timeoutTimer);\n await pool.drain(5_000).catch(() => { /* best-effort pool drain */ });\n }\n }\n\n // ── Fork execution with ForkCoordinator ──\n\n private async executeForkTask(\n forkId: string,\n prompt: string,\n fork: { nodes: AgentNode[]; consensus?: ConsensusPort },\n previousResults: Map<string, NodeResult>,\n channel: AsyncChannel<GraphStreamEvent>,\n ): Promise<NodeResult> {\n const forkStart = Date.now();\n const enrichedPrompt = this.buildNodePrompt(prompt, forkId, previousResults);\n\n this.eventBus?.emit(\"fork:start\", { forkId, agentCount: fork.nodes.length });\n channel.push({ type: \"fork:start\", forkId, agentCount: fork.nodes.length });\n\n const coordinator = new ForkCoordinator(\n forkId,\n fork.nodes.map((n) => n.id),\n Math.max(this.config.timeoutMs / 2, 5_000),\n Math.max(1, Math.ceil(fork.nodes.length / 2)),\n (partial) => {\n channel.push({\n type: \"fork:partial\",\n forkId,\n completedCount: partial.length,\n totalCount: fork.nodes.length,\n partialResults: partial,\n });\n },\n );\n\n const promises = fork.nodes.map(async (node) => {\n try {\n const result = await node.run(enrichedPrompt, this.sharedContext);\n coordinator.onNodeComplete(node.id, result);\n } catch (error) {\n coordinator.onNodeError(\n node.id,\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n });\n\n let results: NodeResult[];\n try {\n results = await coordinator.promise;\n // Ensure all fork node promises settle (prevents orphaned executions)\n await Promise.allSettled(promises);\n } catch (error) {\n await Promise.allSettled(promises);\n coordinator.dispose();\n this.eventBus?.emit(\"fork:complete\", {\n forkId,\n error: error instanceof Error ? error.message : String(error),\n });\n channel.push({ type: \"fork:complete\", forkId, results: [] });\n throw error;\n }\n\n this.eventBus?.emit(\"fork:complete\", { forkId, resultCount: results.length });\n channel.push({ type: \"fork:complete\", forkId, results });\n\n let output: string;\n let tokenUsage = { input: 0, output: 0 };\n for (const r of results) {\n if (r.tokenUsage) {\n tokenUsage.input += r.tokenUsage.input;\n tokenUsage.output += r.tokenUsage.output;\n }\n }\n\n if (fork.consensus) {\n this.eventBus?.emit(\"consensus:start\", { forkId });\n channel.push({ type: \"consensus:start\", forkId });\n try {\n const consensusInput = results.map((r) => ({\n id: r.nodeId,\n output: r.output,\n }));\n const consensusResult = await fork.consensus.evaluate(consensusInput);\n this.eventBus?.emit(\"consensus:result\", {\n forkId,\n winnerId: consensusResult.winnerId,\n merged: !!consensusResult.merged,\n });\n output = consensusResult.merged ?? consensusResult.winnerOutput;\n channel.push({ type: \"consensus:result\", forkId, output });\n } catch (error) {\n this.eventBus?.emit(\"consensus:result\", {\n forkId,\n error: error instanceof Error ? error.message : String(error),\n });\n channel.push({ type: \"consensus:result\", forkId, output: \"\" });\n coordinator.dispose();\n throw error;\n }\n } else {\n output = results[0]!.output;\n }\n\n const result: NodeResult = {\n nodeId: forkId,\n output,\n tokenUsage,\n durationMs: Date.now() - forkStart,\n };\n await this.sharedContext.setNodeResult(forkId, output);\n coordinator.dispose();\n return result;\n }\n\n // ── Helpers ──\n\n private buildNodePrompt(\n basePrompt: string,\n nodeId: string,\n previousResults: Map<string, NodeResult>,\n ): string {\n const deps = this.edges.get(nodeId) ?? [];\n if (deps.length === 0) return basePrompt;\n\n const context = deps\n .map((depId) => {\n const r = previousResults.get(depId);\n return r ? `[${depId}]: ${r.output}` : \"\";\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n return `${basePrompt}\\n\\n--- Previous results ---\\n${context}`;\n }\n\n private findTerminalNode(): string {\n const isDependency = new Set<string>();\n for (const deps of this.edges.values()) {\n for (const d of deps) isDependency.add(d);\n }\n for (const nodeId of this.nodes.keys()) {\n if (!isDependency.has(nodeId)) return nodeId;\n }\n return [...this.nodes.keys()].pop()!;\n }\n}\n","// =============================================================================\n// SharedContext — Namespaced shared state between agents in a graph\n// Supports watchers, versioning (optimistic locking), CRDT merge, and scoping.\n// =============================================================================\n\nimport type { FilesystemPort } from \"../ports/filesystem.port.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ContextChange {\n key: string;\n oldValue: unknown;\n newValue: unknown;\n version: number;\n source: string;\n timestamp: number;\n}\n\nexport type ContextChangeHandler = (change: ContextChange) => void;\n\nexport interface Versioned<T> {\n value: T;\n version: number;\n}\n\nexport class VersionConflictError extends Error {\n constructor(key: string, expected: number, actual: number) {\n super(\n `Version conflict on \"${key}\": expected ${expected}, actual ${actual}`,\n );\n this.name = \"VersionConflictError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// SharedContext\n// ---------------------------------------------------------------------------\n\nexport class SharedContext {\n private readonly watchers = new Map<string, Set<ContextChangeHandler>>();\n private readonly versions = new Map<string, number>();\n private readonly parent?: SharedContext;\n\n constructor(\n private readonly fs: FilesystemPort,\n private readonly namespace: string = \"/.shared\",\n parent?: SharedContext,\n ) {\n this.parent = parent;\n }\n\n // ---- helpers ------------------------------------------------------------\n\n private keyPath(key: string): string {\n return `${this.namespace}/${key}`;\n }\n\n private getVersion(key: string): number {\n return this.versions.get(key) ?? 0;\n }\n\n private bumpVersion(key: string): number {\n const next = this.getVersion(key) + 1;\n this.versions.set(key, next);\n return next;\n }\n\n // ---- notify watchers ----------------------------------------------------\n\n private notify(change: ContextChange): void {\n const keyHandlers = this.watchers.get(change.key);\n const wildHandlers = this.watchers.get(\"*\");\n if (keyHandlers) {\n for (const h of keyHandlers) h(change);\n }\n if (wildHandlers) {\n for (const h of wildHandlers) h(change);\n }\n // bubble to parent\n if (this.parent) {\n this.parent.notify(change);\n }\n }\n\n // ---- original API (backward compatible) ---------------------------------\n\n async set(key: string, value: unknown): Promise<void> {\n const oldValue = await this.get(key);\n await this.fs.write(this.keyPath(key), JSON.stringify(value));\n const version = this.bumpVersion(key);\n this.notify({\n key,\n oldValue,\n newValue: value,\n version,\n source: this.namespace,\n timestamp: Date.now(),\n });\n }\n\n async get<T>(key: string): Promise<T | null> {\n const path = this.keyPath(key);\n if (!(await this.fs.exists(path))) return null;\n const raw = await this.fs.read(path);\n return JSON.parse(raw) as T;\n }\n\n async delete(key: string): Promise<void> {\n const path = this.keyPath(key);\n if (await this.fs.exists(path)) {\n const oldValue = await this.get(key);\n await this.fs.delete(path);\n const version = this.bumpVersion(key);\n this.notify({\n key,\n oldValue,\n newValue: undefined,\n version,\n source: this.namespace,\n timestamp: Date.now(),\n });\n }\n }\n\n async list(): Promise<string[]> {\n if (!(await this.fs.exists(this.namespace))) return [];\n const entries = await this.fs.list(this.namespace);\n return entries\n .filter((e) => !e.isDirectory)\n .map((e) => e.name);\n }\n\n async getNodeResult(nodeId: string): Promise<string | null> {\n return this.get<string>(`results/${nodeId}`);\n }\n\n async setNodeResult(nodeId: string, result: string): Promise<void> {\n await this.set(`results/${nodeId}`, result);\n }\n\n // ---- watchers -----------------------------------------------------------\n\n /**\n * Subscribe to changes on a specific key, or use \"*\" for all changes.\n * Returns an unsubscribe function.\n */\n watch(key: string, handler: ContextChangeHandler): () => void {\n let handlers = this.watchers.get(key);\n if (!handlers) {\n handlers = new Set();\n this.watchers.set(key, handlers);\n }\n handlers.add(handler);\n\n return () => {\n handlers!.delete(handler);\n if (handlers!.size === 0) this.watchers.delete(key);\n };\n }\n\n // ---- versioning (optimistic locking) ------------------------------------\n\n async getVersioned<T>(key: string): Promise<Versioned<T> | null> {\n const value = await this.get<T>(key);\n if (value === null) return null;\n return { value, version: this.getVersion(key) };\n }\n\n async setVersioned(\n key: string,\n value: unknown,\n expectedVersion: number,\n ): Promise<void> {\n // Synchronous check-and-bump to avoid TOCTOU race\n const actual = this.getVersion(key);\n if (actual !== expectedVersion) {\n throw new VersionConflictError(key, expectedVersion, actual);\n }\n // Bump version synchronously before async write to prevent concurrent setVersioned\n // from passing the same version check\n this.bumpVersion(key);\n const oldValue = await this.get(key);\n await this.fs.write(this.keyPath(key), JSON.stringify(value));\n this.notify({\n key,\n oldValue,\n newValue: value,\n version: this.getVersion(key),\n source: this.namespace,\n timestamp: Date.now(),\n });\n }\n\n // ---- CRDT merge ---------------------------------------------------------\n\n /**\n * Read-then-write with a merge function using optimistic locking.\n * Default mergeFn is Last-Writer-Wins (returns newValue).\n * Retries on version conflict (CAS pattern).\n */\n async merge<T>(\n key: string,\n value: T,\n mergeFn: (oldValue: T | null, newValue: T) => T = (_old, nw) => nw,\n ): Promise<void> {\n const maxRetries = 3;\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const currentVersion = this.getVersion(key);\n const current = await this.get<T>(key);\n const merged = mergeFn(current, value);\n try {\n await this.setVersioned(key, merged, currentVersion);\n return;\n } catch (err) {\n if (err instanceof VersionConflictError && attempt < maxRetries) {\n continue; // retry\n }\n throw err;\n }\n }\n }\n\n // ---- scoping ------------------------------------------------------------\n\n createScoped(scope: string): SharedContext {\n return new SharedContext(this.fs, `${this.namespace}/${scope}`, this);\n }\n}\n","// =============================================================================\n// AsciiGraphAdapter — Renders a GraphDescriptor as ASCII box art\n// =============================================================================\n\nimport type {\n GraphVisualizationPort,\n GraphDescriptor,\n} from \"../../ports/graph-visualization.port.js\";\n\nexport class AsciiGraphAdapter implements GraphVisualizationPort {\n toAscii(graph: GraphDescriptor): string {\n if (graph.nodes.length === 0) return \"(empty graph)\";\n\n const ordered = this.topologicalSort(graph);\n const forkMap = new Map(graph.forks.map((f) => [f.id, f.nodeIds]));\n const lines: string[] = [];\n\n // Render main flow\n const boxes = ordered.map((id) => {\n const node = graph.nodes.find((n) => n.id === id)!;\n return this.renderBox(node.label ?? node.id, node.type);\n });\n const topLine = boxes.map((b) => b[0]).join(\" \");\n const midLine = boxes.map((b) => b[1]).join(\" ──→ \");\n const typLine = boxes.map((b) => b[2]).join(\" \");\n const botLine = boxes.map((b) => b[3]).join(\" \");\n lines.push(topLine, midLine, typLine, botLine);\n\n // Render forks below their parent node\n for (const [forkId, nodeIds] of forkMap) {\n const idx = ordered.indexOf(forkId);\n if (idx < 0) continue;\n const offset = this.computeOffset(boxes, idx);\n lines.push(\"\");\n const forkLines = this.renderFork(forkId, nodeIds);\n for (const fl of forkLines) {\n lines.push(\" \".repeat(offset) + fl);\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n toMermaid(_graph: GraphDescriptor): string {\n throw new Error(\"Use MermaidGraphAdapter for Mermaid output\");\n }\n\n private renderBox(label: string, type: string): [string, string, string, string] {\n const inner = Math.max(label.length, type.length + 2);\n const pad = (s: string) => s.padEnd(inner);\n return [\n `┌${\"─\".repeat(inner + 2)}┐`,\n `│ ${pad(label)} │`,\n `│ ${pad(`(${type})`)} │`,\n `└${\"─\".repeat(inner + 2)}┘`,\n ];\n }\n\n private renderFork(id: string, nodeIds: string[]): string[] {\n const miniBoxLine = nodeIds.map((nid) => {\n const w = nid.length + 2;\n return `┌${\"─\".repeat(w)}┐`;\n }).join(\"\");\n const miniMidLine = nodeIds.map((nid) => `│ ${nid} │`).join(\"\");\n const miniBotLine = nodeIds.map((nid) => {\n const w = nid.length + 2;\n return `└${\"─\".repeat(w)}┘`;\n }).join(\"\");\n const contentWidth = Math.max(id.length + 2, miniMidLine.length + 2);\n const padCenter = (s: string) => {\n const leftPad = Math.floor((contentWidth - s.length) / 2);\n return \" \".repeat(Math.max(0, leftPad)) + s;\n };\n\n const dashesTotal = contentWidth - 1; // -1 for the ┴ character\n const leftDashes = Math.floor(dashesTotal / 2);\n const rightDashes = dashesTotal - leftDashes;\n\n return [\n \" \".repeat(Math.floor(contentWidth / 2)) + \"│\",\n `┌${\"─\".repeat(leftDashes)}┴${\"─\".repeat(rightDashes)}┐`,\n `│${padCenter(id)}${\" \".repeat(Math.max(0, contentWidth - padCenter(id).length))}│`,\n `│${padCenter(miniBoxLine)}${\" \".repeat(Math.max(0, contentWidth - padCenter(miniBoxLine).length))}│`,\n `│${padCenter(miniMidLine)}${\" \".repeat(Math.max(0, contentWidth - padCenter(miniMidLine).length))}│`,\n `│${padCenter(miniBotLine)}${\" \".repeat(Math.max(0, contentWidth - padCenter(miniBotLine).length))}│`,\n `└${\"─\".repeat(contentWidth)}┘`,\n ];\n }\n\n private computeOffset(boxes: [string, string, string, string][], idx: number): number {\n let offset = 0;\n for (let i = 0; i < idx; i++) {\n offset += boxes[i][0].length + 5; // 5 = \" \" or \" ──→ \"\n }\n return offset;\n }\n\n private topologicalSort(graph: GraphDescriptor): string[] {\n const adjacency = new Map<string, string[]>();\n const inDegree = new Map<string, number>();\n for (const n of graph.nodes) {\n adjacency.set(n.id, []);\n inDegree.set(n.id, 0);\n }\n for (const e of graph.edges) {\n adjacency.get(e.from)?.push(e.to);\n inDegree.set(e.to, (inDegree.get(e.to) ?? 0) + 1);\n }\n const queue = graph.nodes.filter((n) => (inDegree.get(n.id) ?? 0) === 0).map((n) => n.id);\n const result: string[] = [];\n while (queue.length > 0) {\n const id = queue.shift()!;\n result.push(id);\n for (const next of adjacency.get(id) ?? []) {\n const deg = (inDegree.get(next) ?? 1) - 1;\n inDegree.set(next, deg);\n if (deg === 0) queue.push(next);\n }\n }\n return result;\n }\n}\n","// =============================================================================\n// MermaidGraphAdapter — Renders a GraphDescriptor as Mermaid flowchart syntax\n// =============================================================================\n\nimport type {\n GraphVisualizationPort,\n GraphDescriptor,\n} from \"../../ports/graph-visualization.port.js\";\n\nexport class MermaidGraphAdapter implements GraphVisualizationPort {\n toAscii(_graph: GraphDescriptor): string {\n throw new Error(\"Use AsciiGraphAdapter for ASCII output\");\n }\n\n toMermaid(graph: GraphDescriptor): string {\n const lines: string[] = [\"graph LR\"];\n const forkNodeIds = new Set(graph.forks.flatMap((f) => f.nodeIds));\n const sanitize = (id: string) => id.replace(/-/g, \"_\");\n\n // Node declarations (skip fork-internal nodes, they go inside subgraph)\n for (const node of graph.nodes) {\n if (forkNodeIds.has(node.id)) continue;\n const sid = sanitize(node.id);\n const label = node.label ?? node.id;\n lines.push(` ${sid}[${label}<br>${node.type}]`);\n }\n\n // Edges\n for (const edge of graph.edges) {\n lines.push(` ${sanitize(edge.from)} --> ${sanitize(edge.to)}`);\n }\n\n // Forks as subgraphs\n for (const fork of graph.forks) {\n lines.push(` subgraph ${fork.id}`);\n for (const nid of fork.nodeIds) {\n const node = graph.nodes.find((n) => n.id === nid);\n const label = node?.label ?? nid;\n const type = node?.type ?? \"agent\";\n lines.push(` ${sanitize(nid)}[${label}<br>${type}]`);\n }\n lines.push(\" end\");\n }\n\n return lines.join(\"\\n\");\n }\n}\n","// =============================================================================\n// Graph Schema — Configuration & result types for AgentGraph\n// =============================================================================\n\nimport { z } from \"zod\";\n\nexport const GraphConfigSchema = z.object({\n maxDepth: z.number().default(10),\n maxConcurrency: z.number().default(5),\n timeoutMs: z.number().default(600_000),\n maxTokenBudget: z.number().default(1_000_000),\n});\n\nexport type GraphConfig = z.infer<typeof GraphConfigSchema>;\n\nexport const NodeConfigSchema = z.object({\n id: z.string(),\n type: z.enum([\"agent\", \"graph\"]),\n});\n\nexport type NodeConfig = z.infer<typeof NodeConfigSchema>;\n\nexport const NodeResultSchema = z.object({\n nodeId: z.string(),\n output: z.string(),\n tokenUsage: z\n .object({\n input: z.number(),\n output: z.number(),\n })\n .optional(),\n durationMs: z.number(),\n});\n\nexport type NodeResultValue = z.infer<typeof NodeResultSchema>;\n\nexport const GraphResultSchema = z.object({\n output: z.string(),\n nodeResults: z.record(z.string(), NodeResultSchema),\n totalDurationMs: z.number(),\n totalTokenUsage: z.object({\n input: z.number(),\n output: z.number(),\n }),\n});\n\nexport type GraphResult = z.infer<typeof GraphResultSchema>;\n\nexport type GraphStreamEvent =\n | { type: \"graph:start\"; nodeCount: number }\n | { type: \"node:start\"; nodeId: string }\n | { type: \"node:complete\"; nodeId: string; result: NodeResultValue }\n | { type: \"node:error\"; nodeId: string; error: string }\n | { type: \"fork:start\"; forkId: string; agentCount: number }\n | { type: \"fork:complete\"; forkId: string; results: NodeResultValue[] }\n | { type: \"fork:partial\"; forkId: string; completedCount: number; totalCount: number; partialResults: NodeResultValue[] }\n | { type: \"consensus:start\"; forkId: string }\n | { type: \"consensus:result\"; forkId: string; output: string }\n | { type: \"graph:complete\"; result: GraphResult }\n | { type: \"graph:error\"; error: string; partialResults: Record<string, NodeResultValue> }\n | { type: \"pool:metrics\"; metrics: { activeWorkers: number; idleWorkers: number; queueDepth: number; totalCompleted: number; totalFailed: number } }\n | { type: \"budget:warning\"; remaining: number; used: number; threshold: \"soft\" | \"hard\" }\n | { type: \"backpressure:active\"; queueDepth: number; action: \"slowdown\" | \"pause\" }\n | { type: \"checkpoint:saved\"; checkpoint: string; completedCount: number }\n | { type: \"node:throttled\"; nodeId: string; delayMs: number; reason: string }\n | { type: \"node:scheduled\"; nodeId: string; queuePosition: number };\n","// =============================================================================\n// ToolManager — Tool catalog building, wrapping, and preparation\n// =============================================================================\n\nimport { tool } from \"../core/llm/index.js\";\nimport { z } from \"zod\";\nimport type { LanguageModel, Tool } from \"../core/llm/index.js\";\n\nimport type { FilesystemPort } from \"../ports/filesystem.port.js\";\nimport type { McpPort } from \"../ports/mcp.port.js\";\nimport type {\n PolicyContext,\n PolicyEnginePort,\n PolicyRequest,\n} from \"../ports/policy.port.js\";\nimport type { ApprovalConfig, SubagentConfig } from \"../types.js\";\nimport type { McpToolsetSelection } from \"../types.js\";\nimport type { PluginContext, PluginRunMetadata, PluginSetupContext } from \"../ports/plugin.port.js\";\nimport type { RuntimePort } from \"../ports/runtime.port.js\";\n\nimport { PluginManager } from \"../plugins/plugin-manager.js\";\nimport { ApprovalManager } from \"./approval-manager.js\";\nimport { createFilesystemTools } from \"../tools/filesystem/index.js\";\nimport { createPlanningTools } from \"../tools/planning/index.js\";\nimport { createPolicyTools } from \"../tools/policy/index.js\";\nimport { createAsyncSubagentTools } from \"../tools/subagent/index.js\";\nimport { SubagentRegistry } from \"../tools/subagent/subagent-registry.js\";\nimport { SubagentScheduler } from \"../tools/subagent/subagent-scheduler.js\";\nimport { DEFAULT_LIMITS } from \"../tools/subagent/subagent-registry.js\";\nimport { CircuitBreaker, RateLimiter, ToolCache } from \"../adapters/resilience/index.js\";\n\nimport { EventBus } from \"./event-bus.js\";\nimport type { MemoryPort } from \"../ports/memory.port.js\";\nimport type { LearningPort } from \"../ports/learning.port.js\";\n\n// =============================================================================\n// Config subset needed by ToolManager\n// =============================================================================\n\nexport interface ToolManagerConfig {\n model: LanguageModel;\n instructions: string;\n name?: string;\n maxSteps: number;\n fs: FilesystemPort;\n memory: MemoryPort;\n learning?: LearningPort;\n mcp?: McpPort;\n policyEngine?: PolicyEnginePort;\n userId?: string;\n planning: boolean;\n subagents: boolean;\n subagentConfig?: Partial<SubagentConfig>;\n approvalConfig?: Required<ApprovalConfig>;\n extraTools?: Record<string, Tool<any, any>>;\n}\n\n// =============================================================================\n// ToolManager\n// =============================================================================\n\nexport class ToolManager {\n private readonly config: ToolManagerConfig;\n private readonly pluginManager: PluginManager;\n private readonly circuitBreaker?: CircuitBreaker;\n private readonly rateLimiter?: RateLimiter;\n private readonly toolCache?: ToolCache;\n\n constructor(\n config: ToolManagerConfig,\n pluginManager: PluginManager,\n circuitBreaker?: CircuitBreaker,\n rateLimiter?: RateLimiter,\n toolCache?: ToolCache,\n ) {\n this.config = config;\n this.pluginManager = pluginManager;\n this.circuitBreaker = circuitBreaker;\n this.rateLimiter = rateLimiter;\n this.toolCache = toolCache;\n }\n\n // ---------------------------------------------------------------------------\n // Tool registration\n // ---------------------------------------------------------------------------\n\n private registerTools(\n target: Record<string, Tool<any, any>>,\n source: Record<string, Tool<any, any>>,\n sourceLabel: string,\n ): void {\n for (const [toolName, toolDef] of Object.entries(source)) {\n if (toolName in target) {\n throw new Error(`Tool \"${toolName}\" already registered (source: ${sourceLabel})`);\n }\n target[toolName] = toolDef;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Build catalog\n // ---------------------------------------------------------------------------\n\n async buildToolCatalog(runMetadata?: PluginRunMetadata): Promise<Record<string, Tool<any, any>>> {\n const tools: Record<string, Tool<any, any>> = {};\n\n this.registerTools(tools, createFilesystemTools(this.config.fs), \"filesystem\");\n this.registerTools(tools, this.config.extraTools ?? {}, \"builder.withTools\");\n this.registerTools(tools, this.pluginManager.collectTools(), \"plugins\");\n\n if (this.config.planning) {\n this.registerTools(tools, createPlanningTools(this.config.fs), \"planning\");\n }\n\n if (this.config.subagents) {\n const limits = {\n ...DEFAULT_LIMITS,\n maxDepth: this.config.subagentConfig?.maxDepth ?? DEFAULT_LIMITS.maxDepth,\n defaultTimeoutMs: this.config.subagentConfig?.timeoutMs ?? DEFAULT_LIMITS.defaultTimeoutMs,\n };\n const eventBus = new EventBus(\"subagent-bus\");\n const registry = new SubagentRegistry(eventBus, {\n limits,\n hooks: this.config.subagentConfig?.hooks,\n });\n const scheduler = new SubagentScheduler(registry, this.config.model, limits);\n scheduler.start();\n\n this.registerTools(\n tools,\n createAsyncSubagentTools({\n registry,\n parentId: \"root\",\n maxDepth: limits.maxDepth,\n currentDepth: 0,\n hooks: this.config.subagentConfig?.hooks,\n }),\n \"subagents\",\n );\n }\n\n if (this.config.mcp) {\n const mcpDefs = await this.config.mcp.discoverTools();\n const mcp = this.config.mcp;\n const mcpTools: Record<string, Tool<any, any>> = {};\n const selection = this.extractMcpToolsetSelection(runMetadata);\n\n for (const [name, def] of Object.entries(mcpDefs)) {\n const [serverName = \"mcp\", ...toolParts] = name.split(\":\");\n const shortName = toolParts.length > 0 ? toolParts.join(\":\") : name;\n\n if (\n !this.shouldIncludeMcpTool(selection, {\n serverName,\n fullName: name,\n shortName,\n })\n ) {\n continue;\n }\n\n mcpTools[`mcp:${name}`] = tool({\n description: def.description,\n inputSchema: z.object({}).passthrough(),\n execute: async (args: unknown) => {\n const result = await mcp.executeTool(name, args);\n if (result.isError) throw new Error(result.content[0]?.text ?? \"MCP tool error\");\n return result.content.map((c) => c.text ?? \"\").join(\"\\n\");\n },\n });\n }\n\n this.registerTools(tools, mcpTools, \"mcp\");\n }\n\n if (this.config.policyEngine) {\n this.registerTools(\n tools,\n createPolicyTools(this.config.policyEngine),\n \"policy\",\n );\n }\n\n return tools;\n }\n\n // ---------------------------------------------------------------------------\n // Wrapping — delegates to standalone pure functions\n // ---------------------------------------------------------------------------\n\n wrapToolsWithApproval(\n tools: Record<string, Tool<any, any>>,\n sessionId: string,\n eventBus: EventBus,\n runtime: RuntimePort,\n ): void {\n if (!this.config.approvalConfig) return;\n\n const approval = new ApprovalManager(\n this.config.approvalConfig,\n sessionId,\n (evt) => eventBus.emit(evt.type, evt.data),\n );\n\n applyApprovalWrapping(tools, approval, runtime);\n }\n\n wrapToolsWithResilience(tools: Record<string, Tool<any, any>>): void {\n applyResilienceWrapping(tools, this.circuitBreaker, this.toolCache);\n }\n\n wrapToolsWithPolicy(\n tools: Record<string, Tool<any, any>>,\n sessionId: string,\n runMetadata?: PluginRunMetadata,\n ): void {\n if (!this.config.policyEngine) return;\n\n const context = this.resolvePolicyContext(sessionId, runMetadata);\n applyPolicyWrapping(tools, this.config.policyEngine, context);\n }\n\n wrapToolsWithPlugins(\n tools: Record<string, Tool<any, any>>,\n pluginCtx: PluginContext,\n ): void {\n applyPluginWrapping(tools, this.pluginManager, pluginCtx);\n }\n\n resolvePolicyContext(\n sessionId: string,\n runMetadata?: PluginRunMetadata,\n ): PolicyContext {\n const base: PolicyContext = {\n sessionId,\n userId: this.config.userId,\n };\n\n const raw = runMetadata?.policyContext;\n if (!raw || typeof raw !== \"object\") {\n return base;\n }\n\n const candidate = raw as Partial<PolicyContext>;\n return {\n ...base,\n ...(candidate.sessionId ? { sessionId: candidate.sessionId } : {}),\n ...(candidate.userId ? { userId: candidate.userId } : {}),\n ...(candidate.tenantId ? { tenantId: candidate.tenantId } : {}),\n ...(candidate.metadata && typeof candidate.metadata === \"object\"\n ? { metadata: candidate.metadata }\n : {}),\n };\n }\n\n createRateLimitedModel(): LanguageModel {\n if (!this.rateLimiter) {\n return this.config.model;\n }\n\n const rateLimiter = this.rateLimiter;\n const originalModel = this.config.model;\n\n return new Proxy(originalModel as any, {\n get(target: any, prop: string | symbol, receiver: any) {\n const value = Reflect.get(target, prop, receiver);\n\n if (typeof value === 'function' && prop === 'doGenerate') {\n return async function(...args: any[]) {\n await rateLimiter.acquire();\n return value.apply(target, args);\n };\n }\n\n if (typeof value === 'function' && prop === 'doStream') {\n return async function(...args: any[]) {\n await rateLimiter.acquire();\n return value.apply(target, args);\n };\n }\n\n return value;\n }\n }) as LanguageModel;\n }\n\n // ---------------------------------------------------------------------------\n // Full preparation pipeline\n // ---------------------------------------------------------------------------\n\n async prepareTools(\n sessionId: string,\n eventBus: EventBus,\n runtime: RuntimePort,\n runMetadata?: PluginRunMetadata,\n ): Promise<{ tools: Record<string, Tool<any, any>>; pluginCtx: PluginContext }> {\n const tools = await this.buildToolCatalog(runMetadata);\n const toolNames = Object.keys(tools);\n const setupCtx = this.createPluginSetupContext(sessionId, toolNames, eventBus);\n await this.pluginManager.initialize(setupCtx);\n\n const pluginCtx = this.createPluginContext(sessionId, toolNames, runMetadata);\n this.wrapToolsWithApproval(tools, sessionId, eventBus, runtime);\n this.wrapToolsWithResilience(tools);\n if (this.config.policyEngine) {\n this.wrapToolsWithPolicy(tools, sessionId, runMetadata);\n }\n this.wrapToolsWithPlugins(tools, pluginCtx);\n\n return { tools, pluginCtx };\n }\n\n // ---------------------------------------------------------------------------\n // Plugin context factories\n // ---------------------------------------------------------------------------\n\n createPluginContext(\n sessionId: string,\n toolNames: readonly string[],\n runMetadata?: PluginRunMetadata,\n ): PluginContext {\n return {\n sessionId,\n agentName: this.config.name,\n config: {\n instructions: this.config.instructions,\n maxSteps: this.config.maxSteps,\n },\n filesystem: this.config.fs,\n memory: this.config.memory,\n learning: this.config.learning,\n toolNames,\n runMetadata,\n };\n }\n\n private createPluginSetupContext(\n sessionId: string,\n toolNames: readonly string[],\n eventBus: EventBus,\n ): PluginSetupContext {\n return {\n ...this.createPluginContext(sessionId, toolNames),\n on: (eventType, handler) => eventBus.on(eventType, handler),\n };\n }\n\n private extractMcpToolsetSelection(\n runMetadata?: PluginRunMetadata,\n ): McpToolsetSelection | undefined {\n const raw = runMetadata?.mcpToolset;\n if (!raw || typeof raw !== \"object\") {\n return undefined;\n }\n\n const normalize = (value: unknown): string[] | undefined => {\n if (!Array.isArray(value)) return undefined;\n const cleaned = value\n .filter((entry): entry is string => typeof entry === \"string\")\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n return cleaned.length > 0 ? cleaned : undefined;\n };\n\n const candidate = raw as Partial<McpToolsetSelection>;\n const selection: McpToolsetSelection = {\n includeServers: normalize(candidate.includeServers),\n excludeServers: normalize(candidate.excludeServers),\n includeTools: normalize(candidate.includeTools),\n excludeTools: normalize(candidate.excludeTools),\n };\n\n if (\n !selection.includeServers &&\n !selection.excludeServers &&\n !selection.includeTools &&\n !selection.excludeTools\n ) {\n return undefined;\n }\n\n return selection;\n }\n\n private shouldIncludeMcpTool(\n selection: McpToolsetSelection | undefined,\n toolInfo: {\n serverName: string;\n fullName: string;\n shortName: string;\n },\n ): boolean {\n if (!selection) {\n return true;\n }\n\n if (\n selection.includeServers &&\n !selection.includeServers.includes(toolInfo.serverName)\n ) {\n return false;\n }\n\n if (\n selection.excludeServers &&\n selection.excludeServers.includes(toolInfo.serverName)\n ) {\n return false;\n }\n\n if (selection.includeTools) {\n const allowed =\n selection.includeTools.includes(toolInfo.fullName) ||\n selection.includeTools.includes(toolInfo.shortName);\n if (!allowed) {\n return false;\n }\n }\n\n if (\n selection.excludeTools &&\n (selection.excludeTools.includes(toolInfo.fullName) ||\n selection.excludeTools.includes(toolInfo.shortName))\n ) {\n return false;\n }\n\n return true;\n }\n}\n\n// =============================================================================\n// Generic tool-wrapping utility\n// =============================================================================\n\n/** Iterates all executable tools and replaces each execute with the result of `wrapFn`. */\nfunction wrapAllTools(\n tools: Record<string, Tool<any, any>>,\n wrapFn: (name: string, originalExecute: (...args: unknown[]) => unknown) => (...args: unknown[]) => unknown,\n): void {\n for (const [name, toolDef] of Object.entries(tools)) {\n if (!toolDef) continue;\n const maybeExecutable = toolDef as { execute?: (...args: unknown[]) => unknown };\n if (!maybeExecutable.execute) continue;\n const originalExecute = maybeExecutable.execute.bind(maybeExecutable);\n maybeExecutable.execute = wrapFn(name, originalExecute);\n }\n}\n\n// =============================================================================\n// Standalone wrapping functions (SRP extraction)\n// =============================================================================\n\n/** Wraps each tool's execute with approval gating. */\nfunction applyApprovalWrapping(\n tools: Record<string, Tool<any, any>>,\n approval: ApprovalManager,\n runtime: RuntimePort,\n): void {\n let stepIndex = 0;\n wrapAllTools(tools, (name, originalExecute) => async (...args: unknown[]) => {\n const { approved, reason } = await approval.checkAndApprove(\n name,\n runtime.randomUUID(),\n args[0],\n stepIndex++,\n );\n\n if (!approved) {\n return `Tool call denied: ${reason ?? \"not approved\"}`;\n }\n\n return originalExecute(...args);\n });\n}\n\n/** Wraps each tool's execute with circuit breaker and/or caching. */\nfunction applyResilienceWrapping(\n tools: Record<string, Tool<any, any>>,\n circuitBreaker?: CircuitBreaker,\n toolCache?: ToolCache,\n): void {\n if (circuitBreaker) {\n wrapAllTools(tools, (_name, originalExecute) => async (...args: unknown[]): Promise<unknown> => {\n return circuitBreaker.execute(async () => originalExecute(...args));\n });\n }\n\n if (toolCache) {\n wrapAllTools(tools, (name, originalExecute) => async (...args: unknown[]): Promise<unknown> => {\n const cacheKey = `${name}:${JSON.stringify(args)}`;\n if (toolCache.has(cacheKey)) {\n return toolCache.get(cacheKey);\n }\n const result = await originalExecute(...args);\n toolCache.set(cacheKey, result);\n return result;\n });\n }\n}\n\n/** Wraps MCP tools with allow/deny policy checks and audit logging. */\nfunction applyPolicyWrapping(\n tools: Record<string, Tool<any, any>>,\n policyEngine: PolicyEnginePort,\n context: PolicyContext,\n): void {\n wrapAllTools(tools, (name, originalExecute) => async (...args: unknown[]): Promise<unknown> => {\n if (!name.startsWith(\"mcp:\")) {\n return originalExecute(...args);\n }\n\n const resource = name.slice(\"mcp:\".length);\n const [serverName = \"mcp\", ...toolParts] = resource.split(\":\");\n const toolName = toolParts.length > 0 ? toolParts.join(\":\") : resource;\n\n const request: PolicyRequest = {\n action: \"invoke\",\n resource,\n serverName,\n toolName,\n };\n\n const decision = await policyEngine.evaluate(request, context);\n if (!decision.allowed) {\n throw new Error(\n `MCP policy denied (${decision.auditId}) for ${resource}: ${decision.reason ?? \"access denied\"}`,\n );\n }\n\n return originalExecute(...args);\n });\n}\n\n/** Wraps each tool's execute with plugin before/after/onError hooks. */\nfunction applyPluginWrapping(\n tools: Record<string, Tool<any, any>>,\n pluginManager: PluginManager,\n pluginCtx: PluginContext,\n): void {\n if (pluginManager.count === 0) return;\n\n wrapAllTools(tools, (name, originalExecute) => async (...args: unknown[]) => {\n const beforeResult = await pluginManager.runBeforeTool(pluginCtx, {\n toolName: name,\n args: args[0],\n });\n\n if (beforeResult.skip) {\n return beforeResult.result;\n }\n\n const finalArgs = beforeResult.args !== undefined ? beforeResult.args : args[0];\n\n try {\n const result = await originalExecute(finalArgs, ...args.slice(1));\n await pluginManager.runAfterTool(pluginCtx, {\n toolName: name,\n args: finalArgs,\n result,\n });\n return result;\n } catch (error) {\n const onErrorResult = await pluginManager.runOnError(pluginCtx, {\n error,\n phase: \"tool\",\n });\n if (onErrorResult.suppress) return undefined;\n throw error;\n }\n });\n}\n","// =============================================================================\n// Plan-to-Graph — Conversione automatica Plan → AgentGraph\n//\n// Ogni Phase diventa un gruppo di nodi, ogni Step diventa un AgentNode.\n// Le fasi parallele diventano fork nel grafo.\n// Le dipendenze tra step diventano edge.\n// =============================================================================\n\nimport type { LanguageModel } from \"../../core/llm/index.js\";\nimport type { Plan, Phase, Step } from \"../../domain/plan.schema.js\";\nimport type { AgentConfig } from \"../../types.js\";\nimport { AgentGraph } from \"../../graph/agent-graph.js\";\n\nexport interface PlanToGraphOptions {\n /** Modello AI di default per tutti i nodi */\n defaultModel: LanguageModel;\n /** System instructions di base per tutti gli agenti */\n baseInstructions?: string;\n /** Tool aggiuntivi da iniettare in tutti i nodi */\n globalTools?: Record<string, unknown>;\n /** Mappa di override per modello specifico per step (stepId → model) */\n modelOverrides?: Record<string, LanguageModel>;\n}\n\n/**\n * Converte un Plan gerarchico in un AgentGraph eseguibile dal GraphExecutor.\n *\n * Strategia di mapping:\n * - Ogni Step → AgentNode con prompt e config derivati dal piano\n * - Dipendenze esplicite tra step → edge nel grafo\n * - Dipendenze implicite tra fasi → edge dal ultimo step della fase A al primo della fase B\n * - Fasi parallele → fork nel grafo (step eseguiti in parallelo)\n * - SubStep vengono inclusi nelle istruzioni del nodo padre (prompt arricchito)\n */\nexport function planToGraph(plan: Plan, options: PlanToGraphOptions): AgentGraph {\n const builder = AgentGraph.create({\n maxConcurrency: plan.globalResources?.maxConcurrency ?? 5,\n timeoutMs: plan.globalResources?.timeoutMs ?? 600_000,\n maxTokenBudget: plan.globalResources?.maxTokenBudget ?? 1_000_000,\n });\n\n // Ordina le fasi per campo `order`\n const sortedPhases = [...plan.phases].sort((a, b) => a.order - b.order);\n\n // Traccia ultimo step di ogni fase per dipendenze implicite\n const lastStepByPhase = new Map<string, string>();\n\n for (const phase of sortedPhases) {\n registerPhase(builder, phase, plan, options, sortedPhases, lastStepByPhase);\n }\n\n return builder.build();\n}\n\nfunction registerPhase(\n builder: ReturnType<typeof AgentGraph.create>,\n phase: Phase,\n plan: Plan,\n options: PlanToGraphOptions,\n allPhases: Phase[],\n lastStepByPhase: Map<string, string>,\n): void {\n if (phase.executionMode === \"parallel\" && phase.steps.length >= 2) {\n // Fase parallela → fork\n const configs = phase.steps.map((step) =>\n buildAgentConfig(step, plan, options),\n );\n\n builder.fork(phase.id, configs);\n\n // Edge da fasi dipendenti\n for (const depPhaseId of phase.dependencies) {\n const lastStep = lastStepByPhase.get(depPhaseId);\n if (lastStep) {\n builder.edge(lastStep, phase.id);\n }\n }\n\n lastStepByPhase.set(phase.id, phase.id);\n } else {\n // Fase sequenziale → nodi collegati in serie\n for (const step of phase.steps) {\n const config = buildAgentConfig(step, plan, options);\n builder.node(step.id, config);\n\n // Edge dalle dipendenze esplicite dello step\n for (const dep of step.dependencies) {\n builder.edge(dep, step.id);\n }\n\n // Edge dalle fasi dipendenti (solo per il primo step della fase)\n if (step === phase.steps[0]) {\n for (const depPhaseId of phase.dependencies) {\n const lastStep = lastStepByPhase.get(depPhaseId);\n if (lastStep) {\n builder.edge(lastStep, step.id);\n }\n }\n }\n }\n\n // Collega step sequenziali interni (se non hanno già dipendenze esplicite)\n for (let i = 1; i < phase.steps.length; i++) {\n const prev = phase.steps[i - 1]!;\n const curr = phase.steps[i]!;\n if (!curr.dependencies.includes(prev.id)) {\n builder.edge(prev.id, curr.id);\n }\n }\n\n const lastStep = phase.steps[phase.steps.length - 1];\n if (lastStep) {\n lastStepByPhase.set(phase.id, lastStep.id);\n }\n }\n}\n\nfunction buildAgentConfig(\n step: Step,\n plan: Plan,\n options: PlanToGraphOptions,\n): AgentConfig {\n const model =\n options.modelOverrides?.[step.id] ??\n (step.resources?.preferredModel\n ? options.defaultModel // In produzione: resolve model by name\n : options.defaultModel);\n\n const instructions = buildStepInstructions(step, plan, options);\n\n return {\n id: step.id,\n name: step.title,\n instructions,\n model,\n maxSteps: 20,\n context: {\n summarizationThreshold: 0.7,\n truncationThreshold: 0.85,\n },\n };\n}\n\nfunction buildStepInstructions(\n step: Step,\n plan: Plan,\n options: PlanToGraphOptions,\n): string {\n const sections: string[] = [];\n\n // Base instructions\n if (options.baseInstructions) {\n sections.push(options.baseInstructions);\n }\n\n // Contesto del piano\n sections.push(\n `## Contesto Piano\\n` +\n `Piano: ${plan.title}\\n` +\n `Obiettivo: ${plan.metadata.goal}`,\n );\n\n // Step prompt\n if (step.prompt) {\n sections.push(`## Task\\n${step.prompt}`);\n }\n\n if (step.description) {\n sections.push(`## Descrizione\\n${step.description}`);\n }\n\n // Contratto I/O\n if (step.contract.inputs.length > 0) {\n const inputDesc = step.contract.inputs\n .map((i) => `- ${i.name} (${i.type}${i.required ? \", obbligatorio\" : \"\"}): ${i.description ?? \"\"}`)\n .join(\"\\n\");\n sections.push(`## Input Attesi\\n${inputDesc}`);\n }\n\n if (step.contract.outputs.length > 0) {\n const outputDesc = step.contract.outputs\n .map((o) => `- ${o.name} (${o.type}${o.required ? \", obbligatorio\" : \"\"}): ${o.description ?? \"\"}`)\n .join(\"\\n\");\n sections.push(\n `## Output Richiesti\\nProduci i seguenti output:\\n${outputDesc}`,\n );\n }\n\n // SubStep come checklist\n if (step.subSteps.length > 0) {\n const subStepList = formatSubSteps(step.subSteps, 0);\n sections.push(`## Sotto-task\\nSegui questi sotto-task in ordine:\\n${subStepList}`);\n }\n\n // Risorse/limiti\n if (step.resources) {\n const limits: string[] = [];\n if (step.resources.maxTokenBudget) {\n limits.push(`Token budget: ${step.resources.maxTokenBudget}`);\n }\n if (step.resources.timeoutMs) {\n limits.push(`Timeout: ${step.resources.timeoutMs}ms`);\n }\n if (limits.length > 0) {\n sections.push(`## Limiti\\n${limits.join(\"\\n\")}`);\n }\n }\n\n return sections.join(\"\\n\\n\");\n}\n\nfunction formatSubSteps(\n subSteps: Array<{ id: string; title: string; prompt?: string; children?: unknown[] }>,\n indent: number,\n): string {\n const prefix = \" \".repeat(indent);\n return subSteps\n .map((ss, i) => {\n let line = `${prefix}${i + 1}. [${ss.id}] ${ss.title}`;\n if (ss.prompt) line += `\\n${prefix} → ${ss.prompt}`;\n if (ss.children && Array.isArray(ss.children) && ss.children.length > 0) {\n line += \"\\n\" + formatSubSteps(\n ss.children as Array<{ id: string; title: string; prompt?: string; children?: unknown[] }>,\n indent + 1,\n );\n }\n return line;\n })\n .join(\"\\n\");\n}\n","import type { FilesystemPort } from \"../../ports/filesystem.port.js\";\nimport { createWriteTodosTool } from \"./write-todos.tool.js\";\nimport { createReviewTodosTool } from \"./review-todos.tool.js\";\nimport { createPlanCreateTool } from \"./plan-create.tool.js\";\nimport { createPlanUpdateTool } from \"./plan-update.tool.js\";\nimport { createPlanStatusTool } from \"./plan-status.tool.js\";\nimport { createPlanVisualizeTool } from \"./plan-visualize.tool.js\";\n\n// Legacy tools (retrocompatibilità)\nexport { createWriteTodosTool } from \"./write-todos.tool.js\";\nexport { createReviewTodosTool } from \"./review-todos.tool.js\";\n\n// Structured plan tools\nexport { createPlanCreateTool } from \"./plan-create.tool.js\";\nexport { createPlanUpdateTool } from \"./plan-update.tool.js\";\nexport { createPlanStatusTool } from \"./plan-status.tool.js\";\nexport { createPlanVisualizeTool } from \"./plan-visualize.tool.js\";\n\n// Plan-to-Graph converter\nexport { planToGraph, type PlanToGraphOptions } from \"./plan-to-graph.js\";\n\n/**\n * Crea tutti i tool di planning (legacy + structured).\n * I vecchi write_todos/review_todos coesistono con i nuovi plan_* tools.\n */\nexport function createPlanningTools(fs: FilesystemPort) {\n return {\n // Legacy (retrocompatibilità)\n write_todos: createWriteTodosTool(fs),\n review_todos: createReviewTodosTool(fs),\n // Structured planning\n plan_create: createPlanCreateTool(fs),\n plan_update: createPlanUpdateTool(fs),\n plan_status: createPlanStatusTool(fs),\n plan_visualize: createPlanVisualizeTool(fs),\n };\n}\n","import { tool, type Tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type {\n PolicyContext,\n PolicyEnginePort,\n PolicyRule,\n} from \"../../ports/policy.port.js\";\n\nconst policyRuleSchema = z.object({\n id: z.string().min(1),\n effect: z.enum([\"allow\", \"deny\"]),\n resourcePattern: z.string().min(1),\n serverPattern: z.string().optional(),\n toolPattern: z.string().optional(),\n priority: z.number().int().optional(),\n reason: z.string().optional(),\n context: z\n .object({\n sessionId: z.string().optional(),\n userId: z.string().optional(),\n tenantId: z.string().optional(),\n })\n .optional(),\n});\n\nfunction normalizeRule(input: z.infer<typeof policyRuleSchema>): PolicyRule {\n const context: PolicyContext | undefined = input.context\n ? {\n ...(input.context.sessionId\n ? { sessionId: input.context.sessionId }\n : {}),\n ...(input.context.userId ? { userId: input.context.userId } : {}),\n ...(input.context.tenantId ? { tenantId: input.context.tenantId } : {}),\n }\n : undefined;\n\n return {\n id: input.id,\n effect: input.effect,\n resourcePattern: input.resourcePattern,\n ...(input.serverPattern ? { serverPattern: input.serverPattern } : {}),\n ...(input.toolPattern ? { toolPattern: input.toolPattern } : {}),\n ...(input.priority !== undefined ? { priority: input.priority } : {}),\n ...(input.reason ? { reason: input.reason } : {}),\n ...(context ? { context } : {}),\n };\n}\n\nexport function createPolicyTools(policyEngine: PolicyEnginePort): Record<string, Tool<any, any>> {\n return {\n policy_list_rules: tool({\n description: \"List current policy rules sorted by priority\",\n inputSchema: z.object({}),\n execute: async () => {\n const rules = await policyEngine.listRules();\n return { rules, count: rules.length };\n },\n }),\n\n policy_add_rule: tool({\n description: \"Add a new policy rule (allow or deny)\",\n inputSchema: policyRuleSchema,\n execute: async (input: z.infer<typeof policyRuleSchema>) => {\n const rule = normalizeRule(input);\n await policyEngine.addRule(rule);\n return { ok: true, ruleId: rule.id };\n },\n }),\n\n policy_remove_rule: tool({\n description: \"Remove an existing policy rule by id\",\n inputSchema: z.object({ id: z.string().min(1) }),\n execute: async ({ id }: { id: string }) => {\n const removed = await policyEngine.removeRule(id);\n return { ok: true, removed, ruleId: id };\n },\n }),\n\n policy_list_audit: tool({\n description: \"List policy audit records (most recent first)\",\n inputSchema: z.object({ limit: z.number().int().positive().optional() }),\n execute: async ({ limit }: { limit?: number }) => {\n const audit = await policyEngine.getAuditLog(limit);\n return { audit, count: audit.length };\n },\n }),\n\n policy_clear_audit: tool({\n description: \"Clear policy audit records\",\n inputSchema: z.object({}),\n execute: async () => {\n await policyEngine.clearAuditLog();\n return { ok: true };\n },\n }),\n };\n}\n","// =============================================================================\n// dispatch_subagent tool — Fire-and-forget subagent dispatch\n// =============================================================================\n\nimport { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { DelegationHooks } from \"../../types.js\";\nimport type { SubagentRegistry } from \"./subagent-registry.js\";\nimport {\n SubagentQueueFullError,\n SubagentDepthExceededError,\n SubagentQuotaExceededError,\n} from \"./subagent-registry.js\";\n\n// ---------------------------------------------------------------------------\n// Input Schema\n// ---------------------------------------------------------------------------\n\nexport const DispatchSubagentInputSchema = z.object({\n prompt: z\n .string()\n .min(1)\n .max(10_000)\n .describe(\"Task description for the subagent\"),\n instructions: z\n .string()\n .max(5_000)\n .optional()\n .describe(\"Optional system instructions for the subagent\"),\n priority: z\n .number()\n .int()\n .min(1)\n .max(10)\n .default(5)\n .describe(\"Priority (1=highest, 10=lowest). Default: 5\"),\n timeoutMs: z\n .number()\n .int()\n .min(5_000)\n .max(600_000)\n .optional()\n .describe(\"Timeout in milliseconds. Default: 300000 (5 min)\"),\n metadata: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\"Optional metadata to pass to the subagent\"),\n});\n\nexport type DispatchSubagentInput = z.infer<typeof DispatchSubagentInputSchema>;\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface DispatchToolConfig {\n registry: SubagentRegistry;\n parentId: string;\n currentDepth: number;\n hooks?: DelegationHooks;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createDispatchTool(config: DispatchToolConfig) {\n const { registry, parentId, currentDepth, hooks } = config;\n\n return tool({\n description:\n \"Dispatch a subtask to a specialized subagent. Returns immediately with a taskId. \" +\n \"Use poll_subagent to check progress, or await_subagent to wait for completion. \" +\n \"You can dispatch multiple tasks in a single step for parallel execution.\",\n inputSchema: DispatchSubagentInputSchema,\n execute: async (input): Promise<string> => {\n try {\n let prompt = input.prompt;\n let instructions = input.instructions;\n let priority = input.priority;\n let timeoutMs = input.timeoutMs;\n let metadata = input.metadata;\n\n if (hooks?.onDelegationStart) {\n const hookResult = await hooks.onDelegationStart({\n parentId,\n currentDepth,\n prompt,\n instructions,\n priority,\n timeoutMs,\n metadata,\n });\n\n if (hookResult?.allow === false) {\n return JSON.stringify({\n blocked: true,\n error:\n hookResult.reason ??\n \"Delegation blocked by supervisor hook\",\n });\n }\n\n if (hookResult?.prompt !== undefined) {\n prompt = hookResult.prompt;\n }\n if (hookResult?.instructions !== undefined) {\n instructions = hookResult.instructions;\n }\n if (hookResult?.priority !== undefined) {\n priority = hookResult.priority;\n }\n if (hookResult?.timeoutMs !== undefined) {\n timeoutMs = hookResult.timeoutMs;\n }\n if (hookResult?.metadata !== undefined) {\n metadata = hookResult.metadata;\n }\n }\n\n const handle = registry.dispatch(parentId, currentDepth, {\n prompt,\n instructions,\n priority,\n timeoutMs,\n metadata,\n });\n\n return JSON.stringify({\n taskId: handle.taskId,\n status: \"queued\",\n queuePosition: registry.queuedCount,\n message:\n \"Task dispatched. Use poll_subagent or await_subagent to get results.\",\n });\n } catch (error: unknown) {\n if (\n error instanceof SubagentQueueFullError ||\n error instanceof SubagentDepthExceededError ||\n error instanceof SubagentQuotaExceededError\n ) {\n return JSON.stringify({ error: error.message });\n }\n const msg =\n error instanceof Error ? error.message : String(error);\n return JSON.stringify({ error: `Dispatch failed: ${msg}` });\n }\n },\n });\n}\n","// =============================================================================\n// SubagentRegistry — Lifecycle manager for async subagent handles\n// =============================================================================\n\nimport type { EventBus } from \"../../agent/event-bus.js\";\nimport type { TelemetryPort } from \"../../ports/telemetry.port.js\";\nimport type { DelegationHooks } from \"../../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type SubagentTaskStatus =\n | \"queued\"\n | \"running\"\n | \"streaming\"\n | \"completed\"\n | \"failed\"\n | \"timeout\"\n | \"cancelled\";\n\nconst TERMINAL_STATES: ReadonlySet<SubagentTaskStatus> = new Set([\n \"completed\",\n \"failed\",\n \"timeout\",\n \"cancelled\",\n]);\n\n/** Valid transitions map: from → Set<to> */\nconst VALID_TRANSITIONS = new Map<SubagentTaskStatus, ReadonlySet<SubagentTaskStatus>>([\n [\"queued\", new Set([\"running\", \"cancelled\"])],\n [\"running\", new Set([\"streaming\", \"completed\", \"failed\", \"timeout\", \"cancelled\"])],\n [\"streaming\", new Set([\"completed\", \"failed\", \"timeout\", \"cancelled\"])],\n [\"completed\", new Set()],\n [\"failed\", new Set()],\n [\"timeout\", new Set()],\n [\"cancelled\", new Set()],\n]);\n\nexport interface SubagentHandle {\n readonly taskId: string;\n readonly parentId: string;\n readonly depth: number;\n readonly createdAt: number;\n status: SubagentTaskStatus;\n statusChangedAt: number;\n priority: number;\n partialOutput: string;\n finalOutput: string | null;\n error: string | null;\n readonly abortController: AbortController;\n readonly prompt: string;\n readonly instructions: string | null;\n readonly timeoutMs: number;\n timeoutTimer: ReturnType<typeof setTimeout> | null;\n tokenUsage: { input: number; output: number };\n readonly metadata: Record<string, unknown>;\n}\n\nexport interface SubagentResourceLimits {\n maxConcurrentPerParent: number;\n maxConcurrentGlobal: number;\n maxDepth: number;\n defaultTimeoutMs: number;\n maxTimeoutMs: number;\n maxQueueSize: number;\n gcTtlMs: number;\n gcIntervalMs: number;\n maxStepsPerSubagent: number;\n}\n\nexport interface DispatchParams {\n prompt: string;\n instructions?: string;\n priority?: number;\n timeoutMs?: number;\n metadata?: Record<string, unknown>;\n}\n\nexport const DEFAULT_LIMITS: SubagentResourceLimits = {\n maxConcurrentPerParent: 5,\n maxConcurrentGlobal: 50,\n maxDepth: 3,\n defaultTimeoutMs: 300_000,\n maxTimeoutMs: 600_000,\n maxQueueSize: 100,\n gcTtlMs: 60_000,\n gcIntervalMs: 30_000,\n maxStepsPerSubagent: 20,\n};\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class SubagentQueueFullError extends Error {\n constructor(queueSize: number, maxSize: number) {\n super(\n `Subagent queue is full (${queueSize}/${maxSize}). ` +\n `Try again after some tasks complete.`,\n );\n this.name = \"SubagentQueueFullError\";\n }\n}\n\nexport class SubagentDepthExceededError extends Error {\n constructor(currentDepth: number, maxDepth: number) {\n super(\n `Maximum subagent nesting depth exceeded (${currentDepth}/${maxDepth}).`,\n );\n this.name = \"SubagentDepthExceededError\";\n }\n}\n\nexport class SubagentQuotaExceededError extends Error {\n constructor(parentId: string, reason: string) {\n super(`Quota exceeded for parent \"${parentId}\": ${reason}`);\n this.name = \"SubagentQuotaExceededError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Forward declaration for bidirectional reference\n// ---------------------------------------------------------------------------\n\ninterface Schedulable {\n enqueue(handle: SubagentHandle): void;\n}\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\nexport class SubagentRegistry {\n private readonly handles = new Map<string, SubagentHandle>();\n private readonly parentIndex = new Map<string, Set<string>>();\n private readonly limits: SubagentResourceLimits;\n private readonly eventBus: EventBus;\n private readonly telemetry?: TelemetryPort;\n private readonly hooks?: DelegationHooks;\n private readonly generateId: () => string;\n private gcTimer: ReturnType<typeof setInterval> | null = null;\n\n /** Listeners waiting for a specific task to reach terminal state */\n private readonly completionListeners = new Map<\n string,\n Array<(handle: SubagentHandle) => void>\n >();\n\n /** Scheduler reference — set via setScheduler() after construction */\n private scheduler: Schedulable | null = null;\n\n constructor(\n eventBus: EventBus,\n options?: {\n limits?: Partial<SubagentResourceLimits>;\n telemetry?: TelemetryPort;\n hooks?: DelegationHooks;\n generateId?: () => string;\n },\n ) {\n this.eventBus = eventBus;\n this.limits = { ...DEFAULT_LIMITS, ...options?.limits };\n this.telemetry = options?.telemetry;\n this.hooks = options?.hooks;\n this.generateId = options?.generateId ?? (() => crypto.randomUUID());\n }\n\n /** Wire the scheduler (called during setup) */\n setScheduler(scheduler: Schedulable): void {\n this.scheduler = scheduler;\n }\n\n get resourceLimits(): Readonly<SubagentResourceLimits> {\n return this.limits;\n }\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n start(): void {\n this.gcTimer = setInterval(() => this.gc(), this.limits.gcIntervalMs);\n }\n\n async shutdown(): Promise<void> {\n if (this.gcTimer) {\n clearInterval(this.gcTimer);\n this.gcTimer = null;\n }\n for (const handle of this.handles.values()) {\n if (!TERMINAL_STATES.has(handle.status)) {\n this.cancel(handle.taskId, \"registry-shutdown\");\n }\n }\n this.handles.clear();\n this.parentIndex.clear();\n this.completionListeners.clear();\n }\n\n // -------------------------------------------------------------------------\n // Dispatch\n // -------------------------------------------------------------------------\n\n dispatch(\n parentId: string,\n currentDepth: number,\n params: DispatchParams,\n ): SubagentHandle {\n if (currentDepth >= this.limits.maxDepth) {\n throw new SubagentDepthExceededError(currentDepth, this.limits.maxDepth);\n }\n\n const parentHandles = this.parentIndex.get(parentId);\n const parentActive = parentHandles\n ? [...parentHandles].filter((id) => {\n const h = this.handles.get(id);\n return h && !TERMINAL_STATES.has(h.status);\n }).length\n : 0;\n\n if (parentActive >= this.limits.maxConcurrentPerParent) {\n throw new SubagentQuotaExceededError(\n parentId,\n `max concurrent per parent (${this.limits.maxConcurrentPerParent}) reached`,\n );\n }\n\n const queuedCount = [...this.handles.values()].filter(\n (h) => h.status === \"queued\",\n ).length;\n\n if (queuedCount >= this.limits.maxQueueSize) {\n throw new SubagentQueueFullError(queuedCount, this.limits.maxQueueSize);\n }\n\n const timeoutMs = Math.min(\n params.timeoutMs ?? this.limits.defaultTimeoutMs,\n this.limits.maxTimeoutMs,\n );\n\n const handle: SubagentHandle = {\n taskId: this.generateId(),\n parentId,\n depth: currentDepth,\n createdAt: Date.now(),\n status: \"queued\",\n statusChangedAt: Date.now(),\n priority: params.priority ?? 5,\n partialOutput: \"\",\n finalOutput: null,\n error: null,\n abortController: new AbortController(),\n prompt: params.prompt,\n instructions: params.instructions ?? null,\n timeoutMs,\n timeoutTimer: null,\n tokenUsage: { input: 0, output: 0 },\n metadata: params.metadata ?? {},\n };\n\n this.handles.set(handle.taskId, handle);\n if (!this.parentIndex.has(parentId)) {\n this.parentIndex.set(parentId, new Set());\n }\n this.parentIndex.get(parentId)!.add(handle.taskId);\n\n this.eventBus.emit(\"subagent:spawn\" as any, {\n taskId: handle.taskId,\n parentId,\n depth: currentDepth,\n prompt: params.prompt,\n priority: handle.priority,\n });\n this.eventBus.emit(\"delegation:start\" as any, {\n taskId: handle.taskId,\n parentId,\n depth: currentDepth,\n prompt: params.prompt,\n priority: handle.priority,\n timeoutMs: handle.timeoutMs,\n metadata: handle.metadata,\n });\n this.telemetry?.recordMetric(\"subagent.dispatch.count\", 1);\n\n this.scheduler?.enqueue(handle);\n return handle;\n }\n\n // -------------------------------------------------------------------------\n // Status Transitions\n // -------------------------------------------------------------------------\n\n transition(\n taskId: string,\n newStatus: SubagentTaskStatus,\n data?: {\n partialOutput?: string;\n finalOutput?: string;\n error?: string;\n },\n ): void {\n const handle = this.handles.get(taskId);\n if (!handle) return;\n if (TERMINAL_STATES.has(handle.status)) return;\n\n // Validate transition\n const allowedTargets = VALID_TRANSITIONS.get(handle.status);\n if (!allowedTargets || !allowedTargets.has(newStatus)) return;\n\n const previousStatus = handle.status;\n handle.status = newStatus;\n handle.statusChangedAt = Date.now();\n\n if (data?.partialOutput !== undefined) {\n handle.partialOutput += data.partialOutput;\n }\n if (data?.finalOutput !== undefined) {\n handle.finalOutput = data.finalOutput;\n }\n if (data?.error !== undefined) {\n handle.error = data.error;\n }\n\n this.eventBus.emit(\"subagent:status-change\" as any, {\n taskId,\n previousStatus,\n newStatus,\n parentId: handle.parentId,\n });\n\n this.eventBus.emit(\"delegation:iteration\" as any, {\n taskId,\n parentId: handle.parentId,\n previousStatus,\n status: newStatus,\n durationMs: Date.now() - handle.createdAt,\n tokenUsage: handle.tokenUsage,\n });\n\n this.invokeIterationHook(handle, previousStatus, newStatus);\n\n if (TERMINAL_STATES.has(newStatus)) {\n if (handle.timeoutTimer) {\n clearTimeout(handle.timeoutTimer);\n handle.timeoutTimer = null;\n }\n\n this.eventBus.emit(\"subagent:complete\" as any, {\n taskId,\n status: newStatus,\n parentId: handle.parentId,\n durationMs: Date.now() - handle.createdAt,\n tokenUsage: handle.tokenUsage,\n });\n this.eventBus.emit(\"delegation:complete\" as any, {\n taskId,\n status: newStatus,\n parentId: handle.parentId,\n durationMs: Date.now() - handle.createdAt,\n tokenUsage: handle.tokenUsage,\n error: handle.error,\n });\n this.telemetry?.recordMetric(`subagent.status.${newStatus}`, 1);\n this.telemetry?.recordMetric(\n \"subagent.completion.duration_ms\",\n Date.now() - handle.createdAt,\n );\n\n this.invokeCompletionHook(handle);\n\n const listeners = this.completionListeners.get(taskId);\n if (listeners) {\n for (const cb of listeners) cb(handle);\n this.completionListeners.delete(taskId);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Query\n // -------------------------------------------------------------------------\n\n private invokeIterationHook(\n handle: SubagentHandle,\n previousStatus: SubagentTaskStatus,\n status: SubagentTaskStatus,\n ): void {\n if (!this.hooks?.onIterationComplete) return;\n\n void Promise.resolve(\n this.hooks.onIterationComplete({\n taskId: handle.taskId,\n parentId: handle.parentId,\n previousStatus,\n status,\n partialOutput: handle.partialOutput,\n finalOutput: handle.finalOutput,\n error: handle.error,\n durationMs: Date.now() - handle.createdAt,\n tokenUsage: handle.tokenUsage,\n metadata: handle.metadata,\n }),\n )\n .then((result) => {\n if (!result) return;\n if (result.shouldEscalate) {\n this.eventBus.emit(\"delegation:blocked\" as any, {\n taskId: handle.taskId,\n parentId: handle.parentId,\n reason: result.reason ?? \"delegation escalation requested\",\n score: result.score,\n });\n }\n })\n .catch(() => {\n // Hook failures must never break task lifecycle transitions.\n });\n }\n\n private invokeCompletionHook(handle: SubagentHandle): void {\n if (!this.hooks?.onDelegationComplete) return;\n\n void Promise.resolve(\n this.hooks.onDelegationComplete({\n taskId: handle.taskId,\n parentId: handle.parentId,\n status: handle.status,\n finalOutput: handle.finalOutput,\n error: handle.error,\n durationMs: Date.now() - handle.createdAt,\n tokenUsage: handle.tokenUsage,\n metadata: handle.metadata,\n }),\n ).catch(() => {\n // Hook failures must never break task lifecycle transitions.\n });\n }\n\n get(taskId: string): SubagentHandle | undefined {\n return this.handles.get(taskId);\n }\n\n getByParent(parentId: string): SubagentHandle[] {\n const ids = this.parentIndex.get(parentId);\n if (!ids) return [];\n return [...ids]\n .map((id) => this.handles.get(id)!)\n .filter(Boolean);\n }\n\n get activeCount(): number {\n return [...this.handles.values()].filter(\n (h) => h.status === \"running\" || h.status === \"streaming\",\n ).length;\n }\n\n get queuedCount(): number {\n return [...this.handles.values()].filter(\n (h) => h.status === \"queued\",\n ).length;\n }\n\n get totalCount(): number {\n return this.handles.size;\n }\n\n // -------------------------------------------------------------------------\n // Await\n // -------------------------------------------------------------------------\n\n waitForCompletion(\n taskId: string,\n timeoutMs: number,\n ): Promise<SubagentHandle> {\n const handle = this.handles.get(taskId);\n if (!handle) {\n return Promise.reject(new Error(`Task \"${taskId}\" not found`));\n }\n if (TERMINAL_STATES.has(handle.status)) {\n return Promise.resolve(handle);\n }\n\n return new Promise<SubagentHandle>((resolve) => {\n const timer = setTimeout(() => {\n const listeners = this.completionListeners.get(taskId);\n if (listeners) {\n const idx = listeners.indexOf(onComplete);\n if (idx !== -1) listeners.splice(idx, 1);\n }\n // Return current handle state on timeout\n resolve(handle);\n }, timeoutMs);\n\n const onComplete = (h: SubagentHandle) => {\n clearTimeout(timer);\n resolve(h);\n };\n\n if (!this.completionListeners.has(taskId)) {\n this.completionListeners.set(taskId, []);\n }\n this.completionListeners.get(taskId)!.push(onComplete);\n });\n }\n\n // -------------------------------------------------------------------------\n // Cancellation\n // -------------------------------------------------------------------------\n\n cancel(taskId: string, reason = \"cancelled\"): boolean {\n const handle = this.handles.get(taskId);\n if (!handle || TERMINAL_STATES.has(handle.status)) return false;\n\n handle.abortController.abort(reason);\n this.transition(taskId, \"cancelled\", { error: reason });\n\n // Cascade to children that have this task as parent\n for (const h of this.handles.values()) {\n if (h.parentId === taskId && !TERMINAL_STATES.has(h.status)) {\n this.cancel(h.taskId, `parent-cancelled:${reason}`);\n }\n }\n\n return true;\n }\n\n cancelAll(parentId: string): number {\n let count = 0;\n const ids = this.parentIndex.get(parentId);\n if (!ids) return 0;\n for (const id of ids) {\n if (this.cancel(id, \"parent-shutdown\")) count++;\n }\n return count;\n }\n\n // -------------------------------------------------------------------------\n // Garbage Collection\n // -------------------------------------------------------------------------\n\n /** Exposed for testing */\n gc(): void {\n const now = Date.now();\n let collected = 0;\n\n for (const [taskId, handle] of this.handles) {\n // Collect terminal handles past TTL\n if (\n TERMINAL_STATES.has(handle.status) &&\n now - handle.statusChangedAt > this.limits.gcTtlMs\n ) {\n this.handles.delete(taskId);\n this.parentIndex.get(handle.parentId)?.delete(taskId);\n this.completionListeners.delete(taskId);\n collected++;\n }\n\n // Watchdog: force-timeout stuck handles (2x timeout)\n if (\n (handle.status === \"running\" || handle.status === \"streaming\") &&\n now - handle.createdAt > handle.timeoutMs * 2\n ) {\n this.cancel(taskId, \"watchdog-timeout\");\n }\n }\n\n // Aggressive GC when handle count is excessive\n if (this.handles.size > this.limits.maxConcurrentGlobal * 10) {\n for (const [taskId, handle] of this.handles) {\n if (TERMINAL_STATES.has(handle.status)) {\n this.handles.delete(taskId);\n this.parentIndex.get(handle.parentId)?.delete(taskId);\n this.completionListeners.delete(taskId);\n collected++;\n }\n }\n }\n\n if (collected > 0) {\n this.telemetry?.recordMetric(\"subagent.gc.collected\", collected);\n }\n\n this.telemetry?.recordMetric(\"subagent.queue.depth\", this.queuedCount);\n this.telemetry?.recordMetric(\"subagent.active.count\", this.activeCount);\n }\n}\n\nexport function isTerminalStatus(status: SubagentTaskStatus): boolean {\n return TERMINAL_STATES.has(status);\n}\n","// =============================================================================\n// poll_subagent tool — Non-blocking status check for dispatched subagents\n// =============================================================================\n\nimport { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { SubagentRegistry } from \"./subagent-registry.js\";\n\n// ---------------------------------------------------------------------------\n// Input Schema\n// ---------------------------------------------------------------------------\n\nexport const PollSubagentInputSchema = z.object({\n taskIds: z\n .array(z.string())\n .min(1)\n .max(50)\n .describe(\"Task IDs to check status for\"),\n includePartialOutput: z\n .boolean()\n .default(true)\n .describe(\"Whether to include partial output from streaming tasks\"),\n maxPartialOutputLength: z\n .number()\n .int()\n .min(0)\n .max(10_000)\n .default(2_000)\n .describe(\"Maximum characters of partial output to return per task\"),\n});\n\nexport type PollSubagentInput = z.infer<typeof PollSubagentInputSchema>;\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface PollToolConfig {\n registry: SubagentRegistry;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createPollTool(config: PollToolConfig) {\n const { registry } = config;\n\n return tool({\n description:\n \"Check the status of dispatched subtasks. Returns current status and partial output. \" +\n \"Never blocks — returns immediately.\",\n inputSchema: PollSubagentInputSchema,\n execute: async (input): Promise<string> => {\n const summary = {\n total: 0,\n queued: 0,\n running: 0,\n streaming: 0,\n completed: 0,\n failed: 0,\n timeout: 0,\n cancelled: 0,\n };\n\n const tasks = input.taskIds.map((taskId) => {\n summary.total++;\n const handle = registry.get(taskId);\n if (!handle) {\n return {\n taskId,\n status: \"not_found\",\n error: \"Task not found\",\n durationMs: 0,\n };\n }\n\n const status = handle.status;\n if (status in summary) (summary as any)[status]++;\n\n const result: Record<string, unknown> = {\n taskId,\n status,\n durationMs: Date.now() - handle.createdAt,\n };\n\n if (\n input.includePartialOutput &&\n (status === \"streaming\" || status === \"running\") &&\n handle.partialOutput\n ) {\n result.partialOutput = handle.partialOutput.slice(\n -input.maxPartialOutputLength,\n );\n }\n\n if (status === \"completed\" && handle.finalOutput) {\n result.finalOutput = handle.finalOutput;\n }\n\n if (\n (status === \"failed\" ||\n status === \"timeout\" ||\n status === \"cancelled\") &&\n handle.error\n ) {\n result.error = handle.error;\n }\n\n if (\n handle.tokenUsage.input > 0 ||\n handle.tokenUsage.output > 0\n ) {\n result.tokenUsage = handle.tokenUsage;\n }\n\n return result;\n });\n\n return JSON.stringify({ tasks, summary }, null, 2);\n },\n });\n}\n","// =============================================================================\n// await_subagent tool — Blocking wait for subagent completion\n// =============================================================================\n\nimport { tool } from \"../../core/llm/index.js\";\nimport { z } from \"zod\";\n\nimport type { DelegationHooks } from \"../../types.js\";\nimport type { SubagentRegistry } from \"./subagent-registry.js\";\nimport { isTerminalStatus } from \"./subagent-registry.js\";\n\n// ---------------------------------------------------------------------------\n// Input Schema\n// ---------------------------------------------------------------------------\n\nexport const AwaitSubagentInputSchema = z.object({\n taskIds: z\n .array(z.string())\n .min(1)\n .max(50)\n .describe(\"Task IDs to wait for\"),\n timeoutMs: z\n .number()\n .int()\n .min(1_000)\n .max(600_000)\n .default(60_000)\n .describe(\"Maximum time to wait in milliseconds. Default: 60000\"),\n pollIntervalMs: z\n .number()\n .int()\n .min(50)\n .max(5_000)\n .default(200)\n .describe(\"Polling interval used for optional completion checks\"),\n});\n\nexport type AwaitSubagentInput = z.infer<typeof AwaitSubagentInputSchema>;\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface AwaitToolConfig {\n registry: SubagentRegistry;\n hooks?: DelegationHooks;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createAwaitTool(config: AwaitToolConfig) {\n const { registry, hooks } = config;\n\n const wait = (ms: number) =>\n new Promise<void>((resolve) => {\n setTimeout(resolve, ms);\n });\n\n const normalizeCompletionResult = (\n result: Awaited<ReturnType<NonNullable<DelegationHooks[\"isTaskComplete\"]>>>,\n ): { isComplete: boolean; reason?: string } => {\n if (typeof result === \"boolean\") {\n return { isComplete: result };\n }\n if (!result) {\n return { isComplete: false };\n }\n return {\n isComplete: result.isComplete,\n reason: result.reason,\n };\n };\n\n return tool({\n description:\n \"Wait for one or more subtasks to complete. Blocks until all are done, timed out, or cancelled. \" +\n \"Returns partial results if timeout is reached. Use poll_subagent for non-blocking checks.\",\n inputSchema: AwaitSubagentInputSchema,\n execute: async (input): Promise<string> => {\n const results = await Promise.allSettled(\n input.taskIds.map(async (taskId) => {\n const handle = registry.get(taskId);\n if (!handle) {\n return {\n taskId,\n status: \"not_found\" as const,\n error:\n \"Task not found. It may have been garbage collected.\",\n };\n }\n\n let completionOverride = false;\n let completionReason: string | undefined;\n let resolved = handle;\n\n if (!hooks?.isTaskComplete) {\n resolved = await registry.waitForCompletion(\n taskId,\n input.timeoutMs,\n );\n } else {\n const startedAt = Date.now();\n let iterations = 0;\n while (Date.now() - startedAt < input.timeoutMs) {\n const current = registry.get(taskId);\n if (!current) {\n return {\n taskId,\n status: \"not_found\" as const,\n error:\n \"Task not found. It may have been garbage collected.\",\n };\n }\n\n resolved = current;\n if (isTerminalStatus(current.status)) {\n break;\n }\n\n try {\n const decision = normalizeCompletionResult(\n await hooks.isTaskComplete({\n taskId: current.taskId,\n parentId: current.parentId,\n status: current.status,\n partialOutput: current.partialOutput,\n finalOutput: current.finalOutput,\n error: current.error,\n elapsedMs: Date.now() - current.createdAt,\n iterations,\n tokenUsage: current.tokenUsage,\n metadata: current.metadata,\n }),\n );\n\n if (decision.isComplete) {\n completionOverride = true;\n completionReason = decision.reason;\n break;\n }\n } catch {\n // Ignore hook errors and continue waiting with default behavior.\n }\n\n iterations++;\n await wait(input.pollIntervalMs);\n }\n }\n\n const response: {\n taskId: string;\n status: string;\n output?: string;\n error?: string;\n durationMs: number;\n tokenUsage: { input: number; output: number };\n completionOverride?: boolean;\n completionReason?: string;\n } = {\n taskId: resolved.taskId,\n status: resolved.status,\n output: resolved.finalOutput ?? undefined,\n error: resolved.error ?? undefined,\n durationMs: Date.now() - resolved.createdAt,\n tokenUsage: resolved.tokenUsage,\n };\n\n if (completionOverride) {\n response.completionOverride = true;\n if (completionReason) {\n response.completionReason = completionReason;\n }\n }\n\n return response;\n }),\n );\n\n const formatted = results.map((r) => {\n if (r.status === \"fulfilled\") return r.value;\n return {\n status: \"error\",\n error:\n r.reason instanceof Error\n ? r.reason.message\n : String(r.reason),\n };\n });\n\n return JSON.stringify(formatted, null, 2);\n },\n });\n}\n","// =============================================================================\n// SubagentScheduler — Pool sizing + priority queue + circuit breaker\n// =============================================================================\n\nimport { generateText, streamText, stepCountIs } from \"../../core/llm/index.js\";\nimport type { LanguageModel } from \"../../core/llm/index.js\";\n\nimport type { TelemetryPort } from \"../../ports/telemetry.port.js\";\nimport { VirtualFilesystem } from \"../../adapters/filesystem/virtual-fs.adapter.js\";\nimport { createFilesystemTools } from \"../filesystem/index.js\";\nimport type {\n SubagentHandle,\n SubagentResourceLimits,\n} from \"./subagent-registry.js\";\nimport { SubagentRegistry } from \"./subagent-registry.js\";\n\n// ---------------------------------------------------------------------------\n// Pool Config\n// ---------------------------------------------------------------------------\n\nexport interface PoolConfig {\n minWorkers: number;\n maxWorkers: number;\n scaleUpThreshold: number;\n scaleDownThreshold: number;\n resizeCooldownMs: number;\n}\n\nconst DEFAULT_POOL_CONFIG: PoolConfig = {\n minWorkers: 2,\n maxWorkers: 20,\n scaleUpThreshold: 0.8,\n scaleDownThreshold: 0.3,\n resizeCooldownMs: 10_000,\n};\n\n// ---------------------------------------------------------------------------\n// Priority Queue (binary min-heap with aging)\n// ---------------------------------------------------------------------------\n\ninterface QueueEntry {\n handle: SubagentHandle;\n effectivePriority: number;\n enqueuedAt: number;\n}\n\nexport class PriorityQueue {\n private heap: QueueEntry[] = [];\n private readonly agingIntervalMs: number;\n\n constructor(agingIntervalMs = 5_000) {\n this.agingIntervalMs = agingIntervalMs;\n }\n\n get size(): number {\n return this.heap.length;\n }\n\n enqueue(handle: SubagentHandle): void {\n const entry: QueueEntry = {\n handle,\n effectivePriority: handle.priority,\n enqueuedAt: Date.now(),\n };\n this.heap.push(entry);\n this.bubbleUp(this.heap.length - 1);\n }\n\n dequeue(): SubagentHandle | null {\n if (this.heap.length === 0) return null;\n this.refreshPriorities();\n\n const top = this.heap[0]!;\n const last = this.heap.pop()!;\n if (this.heap.length > 0) {\n this.heap[0] = last;\n this.sinkDown(0);\n }\n return top.handle;\n }\n\n peek(): SubagentHandle | null {\n return this.heap.length > 0 ? this.heap[0]!.handle : null;\n }\n\n remove(taskId: string): boolean {\n const idx = this.heap.findIndex((e) => e.handle.taskId === taskId);\n if (idx === -1) return false;\n const last = this.heap.pop()!;\n if (idx < this.heap.length) {\n this.heap[idx] = last;\n this.bubbleUp(idx);\n this.sinkDown(idx);\n }\n return true;\n }\n\n private refreshPriorities(): void {\n const now = Date.now();\n let dirty = false;\n for (const entry of this.heap) {\n const ageBonus = Math.floor(\n (now - entry.enqueuedAt) / this.agingIntervalMs,\n );\n const newPriority = Math.max(1, entry.handle.priority - ageBonus);\n if (newPriority !== entry.effectivePriority) {\n entry.effectivePriority = newPriority;\n dirty = true;\n }\n }\n if (dirty) {\n // Rebuild heap\n for (let i = Math.floor(this.heap.length / 2) - 1; i >= 0; i--) {\n this.sinkDown(i);\n }\n }\n }\n\n private bubbleUp(idx: number): void {\n while (idx > 0) {\n const parentIdx = Math.floor((idx - 1) / 2);\n if (\n this.heap[parentIdx]!.effectivePriority <=\n this.heap[idx]!.effectivePriority\n )\n break;\n [this.heap[parentIdx]!, this.heap[idx]!] = [\n this.heap[idx]!,\n this.heap[parentIdx]!,\n ];\n idx = parentIdx;\n }\n }\n\n private sinkDown(idx: number): void {\n const length = this.heap.length;\n while (true) {\n let smallest = idx;\n const left = 2 * idx + 1;\n const right = 2 * idx + 2;\n if (\n left < length &&\n this.heap[left]!.effectivePriority <\n this.heap[smallest]!.effectivePriority\n ) {\n smallest = left;\n }\n if (\n right < length &&\n this.heap[right]!.effectivePriority <\n this.heap[smallest]!.effectivePriority\n ) {\n smallest = right;\n }\n if (smallest === idx) break;\n [this.heap[smallest]!, this.heap[idx]!] = [\n this.heap[idx]!,\n this.heap[smallest]!,\n ];\n idx = smallest;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Circuit Breaker state per task type\n// ---------------------------------------------------------------------------\n\ninterface TaskTypeCircuitState {\n failures: number[];\n state: \"closed\" | \"open\" | \"half-open\";\n lastFailure: number;\n}\n\n// ---------------------------------------------------------------------------\n// Scheduler\n// ---------------------------------------------------------------------------\n\nexport class SubagentScheduler {\n private readonly registry: SubagentRegistry;\n private readonly queue: PriorityQueue;\n private readonly poolConfig: PoolConfig;\n private readonly model: LanguageModel;\n private readonly limits: SubagentResourceLimits;\n private readonly telemetry?: TelemetryPort;\n\n private currentPoolSize: number;\n private activeWorkers = 0;\n private lastResizeAt = 0;\n private drainTimer: ReturnType<typeof setInterval> | null = null;\n\n private readonly circuitBreakers = new Map<string, TaskTypeCircuitState>();\n private readonly cbConfig = {\n failureThreshold: 3,\n monitorWindowMs: 60_000,\n resetTimeoutMs: 30_000,\n };\n\n constructor(\n registry: SubagentRegistry,\n model: LanguageModel,\n limits: SubagentResourceLimits,\n options?: {\n poolConfig?: Partial<PoolConfig>;\n telemetry?: TelemetryPort;\n },\n ) {\n this.registry = registry;\n this.model = model;\n this.limits = limits;\n this.poolConfig = { ...DEFAULT_POOL_CONFIG, ...options?.poolConfig };\n this.telemetry = options?.telemetry;\n this.queue = new PriorityQueue();\n this.currentPoolSize = this.poolConfig.minWorkers;\n\n registry.setScheduler(this);\n }\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n start(): void {\n this.drainTimer = setInterval(() => this.drain(), 100);\n }\n\n async shutdown(): Promise<void> {\n if (this.drainTimer) {\n clearInterval(this.drainTimer);\n this.drainTimer = null;\n }\n }\n\n // -------------------------------------------------------------------------\n // Enqueue (called by registry on dispatch)\n // -------------------------------------------------------------------------\n\n enqueue(handle: SubagentHandle): void {\n this.queue.enqueue(handle);\n this.drain();\n }\n\n // -------------------------------------------------------------------------\n // Metrics\n // -------------------------------------------------------------------------\n\n getMetrics(): {\n activeWorkers: number;\n poolSize: number;\n queueSize: number;\n } {\n return {\n activeWorkers: this.activeWorkers,\n poolSize: this.currentPoolSize,\n queueSize: this.queue.size,\n };\n }\n\n // -------------------------------------------------------------------------\n // Drain loop\n // -------------------------------------------------------------------------\n\n drain(): void {\n while (\n this.queue.size > 0 &&\n this.activeWorkers < this.currentPoolSize\n ) {\n const handle = this.queue.dequeue();\n if (!handle) break;\n\n if (handle.abortController.signal.aborted) {\n this.registry.transition(handle.taskId, \"cancelled\", {\n error: \"cancelled-while-queued\",\n });\n continue;\n }\n\n const taskType = this.getTaskType(handle);\n if (this.isCircuitOpen(taskType)) {\n this.registry.transition(handle.taskId, \"failed\", {\n error:\n \"Circuit breaker open for this task type. Too many recent failures.\",\n });\n continue;\n }\n\n this.activeWorkers++;\n this.executeHandle(handle).finally(() => {\n this.activeWorkers--;\n this.maybeResize();\n this.drain();\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Execute a single handle\n // -------------------------------------------------------------------------\n\n private async executeHandle(handle: SubagentHandle): Promise<void> {\n this.registry.transition(handle.taskId, \"running\");\n\n const subVfs = new VirtualFilesystem();\n const fsTools = createFilesystemTools(subVfs);\n\n handle.timeoutTimer = setTimeout(() => {\n handle.abortController.abort(\"timeout\");\n this.registry.transition(handle.taskId, \"timeout\", {\n error: `Subagent timed out after ${handle.timeoutMs}ms`,\n });\n }, handle.timeoutMs);\n\n try {\n const result = await generateText({\n model: this.model,\n system:\n handle.instructions ??\n \"You are a specialized subagent. Complete the task and return your findings.\",\n tools: { ...fsTools },\n stopWhen: stepCountIs(this.limits.maxStepsPerSubagent),\n prompt: handle.prompt,\n abortSignal: handle.abortController.signal,\n });\n\n const output =\n result.text || \"[Subagent completed with no text output]\";\n\n const usage = (result as any).usage;\n if (usage) {\n handle.tokenUsage.input += usage.inputTokens ?? 0;\n handle.tokenUsage.output += usage.outputTokens ?? 0;\n }\n\n this.registry.transition(handle.taskId, \"completed\", {\n finalOutput: output,\n });\n this.recordSuccess(this.getTaskType(handle));\n } catch (error: unknown) {\n if (handle.abortController.signal.aborted) return;\n\n const message =\n error instanceof Error ? error.message : String(error);\n this.registry.transition(handle.taskId, \"failed\", {\n error: message,\n });\n this.recordFailure(this.getTaskType(handle));\n }\n }\n\n // -------------------------------------------------------------------------\n // Pool Sizing\n // -------------------------------------------------------------------------\n\n private maybeResize(): void {\n const now = Date.now();\n if (now - this.lastResizeAt < this.poolConfig.resizeCooldownMs) return;\n\n const utilization =\n this.currentPoolSize > 0\n ? this.activeWorkers / this.currentPoolSize\n : 0;\n\n let newSize = this.currentPoolSize;\n if (utilization > this.poolConfig.scaleUpThreshold) {\n newSize = Math.min(\n Math.ceil(this.currentPoolSize * 1.5),\n this.poolConfig.maxWorkers,\n );\n } else if (utilization < this.poolConfig.scaleDownThreshold) {\n newSize = Math.max(\n Math.floor(this.currentPoolSize * 0.75),\n this.poolConfig.minWorkers,\n );\n }\n\n if (newSize !== this.currentPoolSize) {\n this.currentPoolSize = newSize;\n this.lastResizeAt = now;\n this.telemetry?.recordMetric(\"subagent.pool.size\", newSize);\n }\n this.telemetry?.recordMetric(\n \"subagent.pool.utilization\",\n utilization,\n );\n }\n\n // -------------------------------------------------------------------------\n // Circuit Breaker per task type\n // -------------------------------------------------------------------------\n\n private getTaskType(handle: SubagentHandle): string {\n return handle.instructions ?? \"__default__\";\n }\n\n private isCircuitOpen(taskType: string): boolean {\n const state = this.circuitBreakers.get(taskType);\n if (!state) return false;\n if (state.state === \"open\") {\n if (\n Date.now() - state.lastFailure >\n this.cbConfig.resetTimeoutMs\n ) {\n state.state = \"half-open\";\n return false;\n }\n return true;\n }\n return false;\n }\n\n private recordFailure(taskType: string): void {\n const now = Date.now();\n let state = this.circuitBreakers.get(taskType);\n if (!state) {\n state = { failures: [], state: \"closed\", lastFailure: 0 };\n this.circuitBreakers.set(taskType, state);\n }\n state.failures.push(now);\n state.lastFailure = now;\n state.failures = state.failures.filter(\n (t) => now - t < this.cbConfig.monitorWindowMs,\n );\n\n if (state.failures.length >= this.cbConfig.failureThreshold) {\n state.state = \"open\";\n this.telemetry?.recordMetric(\n \"subagent.circuit_breaker.open\",\n 1,\n );\n }\n }\n\n private recordSuccess(taskType: string): void {\n const state = this.circuitBreakers.get(taskType);\n if (state?.state === \"half-open\") {\n state.state = \"closed\";\n state.failures = [];\n }\n }\n}\n","import type { Tool } from \"../../core/llm/index.js\";\nimport type { DelegationHooks } from \"../../types.js\";\nimport type { SubagentRegistry } from \"./subagent-registry.js\";\nimport { createDispatchTool } from \"./dispatch.tool.js\";\nimport { createPollTool } from \"./poll.tool.js\";\nimport { createAwaitTool } from \"./await.tool.js\";\n\n// Async subagent exports\nexport { SubagentRegistry } from \"./subagent-registry.js\";\nexport type {\n SubagentHandle,\n SubagentTaskStatus,\n SubagentResourceLimits,\n DispatchParams,\n} from \"./subagent-registry.js\";\nexport { SubagentScheduler } from \"./subagent-scheduler.js\";\nexport type { PoolConfig } from \"./subagent-scheduler.js\";\nexport { createDispatchTool } from \"./dispatch.tool.js\";\nexport { createPollTool } from \"./poll.tool.js\";\nexport { createAwaitTool } from \"./await.tool.js\";\n\n// ---------------------------------------------------------------------------\n// Async 3-tool set\n// ---------------------------------------------------------------------------\n\nexport interface AsyncSubagentToolsConfig {\n registry: SubagentRegistry;\n parentId: string;\n maxDepth: number;\n currentDepth: number;\n hooks?: DelegationHooks;\n}\n\nexport function createAsyncSubagentTools(\n config: AsyncSubagentToolsConfig,\n): Record<string, Tool<any, any>> {\n const { registry, parentId, currentDepth, hooks } = config;\n\n return {\n dispatch_subagent: createDispatchTool({\n registry,\n parentId,\n currentDepth,\n hooks,\n }),\n poll_subagent: createPollTool({ registry }),\n await_subagent: createAwaitTool({ registry, hooks }),\n };\n}\n","// =============================================================================\n// ExecutionEngine — Run & stream orchestration\n// =============================================================================\n\nimport { generateText, streamText, stepCountIs } from \"../core/llm/index.js\";\nimport type { LanguageModel, Tool } from \"../core/llm/index.js\";\n\nimport type { MemoryPort } from \"../ports/memory.port.js\";\nimport type { LearningPort } from \"../ports/learning.port.js\";\nimport type { CheckpointConfig, DelegationHooks } from \"../types.js\";\nimport type { PluginContext, PluginRunMetadata } from \"../ports/plugin.port.js\";\nimport type { RuntimePort } from \"../ports/runtime.port.js\";\nimport type { CostTrackerPort } from \"../ports/cost-tracker.port.js\";\nimport type { UserProfile, UserMemory } from \"../domain/learning.schema.js\";\nimport type { TelemetryPort } from \"../ports/telemetry.port.js\";\nimport type { MiddlewareContext } from \"../ports/middleware.port.js\";\n\nimport type { EventBus } from \"./event-bus.js\";\nimport type { ToolManager } from \"./tool-manager.js\";\nimport { PluginManager } from \"../plugins/plugin-manager.js\";\nimport { TokenTracker } from \"../context/token-tracker.js\";\nimport type { MiddlewareChain } from \"../middleware/chain.js\";\n\nimport type { AgentResult, AgentRunOptions } from \"./agent.js\";\n\n// =============================================================================\n// Config subset needed by ExecutionEngine\n// =============================================================================\n\nexport interface ExecutionEngineConfig {\n model: LanguageModel;\n instructions: string;\n maxSteps: number;\n memory: MemoryPort;\n learning?: LearningPort;\n userId?: string;\n agentName?: string;\n delegationHooks?: DelegationHooks;\n checkpointConfig?: Required<CheckpointConfig>;\n telemetry?: TelemetryPort;\n costTracker?: CostTrackerPort;\n /** AI SDK Output specification for structured output (passthrough to ToolLoopAgent). */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n output?: any;\n}\n\n// =============================================================================\n// ExecutionEngine\n// =============================================================================\n\nexport class ExecutionEngine {\n private readonly config: ExecutionEngineConfig;\n private readonly toolManager: ToolManager;\n private readonly pluginManager: PluginManager;\n private readonly eventBus: EventBus;\n private readonly tokenTracker: TokenTracker;\n private readonly middlewareChain?: MiddlewareChain;\n\n constructor(\n config: ExecutionEngineConfig,\n toolManager: ToolManager,\n pluginManager: PluginManager,\n eventBus: EventBus,\n tokenTracker: TokenTracker,\n middlewareChain?: MiddlewareChain,\n ) {\n this.config = config;\n this.toolManager = toolManager;\n this.pluginManager = pluginManager;\n this.eventBus = eventBus;\n this.tokenTracker = tokenTracker;\n this.middlewareChain = middlewareChain;\n }\n\n // ---------------------------------------------------------------------------\n // Middleware context factory\n // ---------------------------------------------------------------------------\n\n private createMiddlewareContext(sessionId: string): MiddlewareContext {\n return {\n sessionId,\n agentName: this.config.agentName,\n timestamp: Date.now(),\n metadata: {},\n };\n }\n\n // ---------------------------------------------------------------------------\n // Telemetry helper — DRY span lifecycle (try/catch/finally)\n // ---------------------------------------------------------------------------\n\n private isDelegationTool(toolName: string): boolean {\n return (\n toolName === \"dispatch_subagent\" ||\n toolName === \"poll_subagent\" ||\n toolName === \"await_subagent\"\n );\n }\n\n private async applyDelegationMessageFilter(params: {\n direction: \"tool:call\" | \"tool:result\";\n toolName: string;\n stepIndex: number;\n payload: unknown;\n }): Promise<{ allow: boolean; payload: unknown; reason?: string }> {\n const hook = this.config.delegationHooks?.messageFilter;\n if (!hook || !this.isDelegationTool(params.toolName)) {\n return {\n allow: true,\n payload: params.payload,\n };\n }\n\n try {\n const filtered = await hook(params);\n if (typeof filtered === \"boolean\") {\n return {\n allow: filtered,\n payload: params.payload,\n };\n }\n if (!filtered) {\n return {\n allow: true,\n payload: params.payload,\n };\n }\n\n return {\n allow: filtered.allow !== false,\n payload:\n filtered.payload !== undefined\n ? filtered.payload\n : params.payload,\n reason: filtered.reason,\n };\n } catch {\n // Filtering failures should not break execution flow.\n return {\n allow: true,\n payload: params.payload,\n };\n }\n }\n\n private async withSpan<T>(name: string, attrs: Record<string, string | number | boolean>, fn: () => Promise<T>): Promise<T> {\n const span = this.config.telemetry?.startSpan(name, attrs);\n try {\n const result = await fn();\n span?.setStatus(\"OK\");\n return result;\n } catch (error) {\n span?.setStatus(\"ERROR\", error instanceof Error ? error.message : String(error));\n throw error;\n } finally {\n span?.end();\n }\n }\n\n // ---------------------------------------------------------------------------\n // Run\n // ---------------------------------------------------------------------------\n\n async run(\n prompt: string,\n sessionId: string,\n runtime: RuntimePort,\n options: AgentRunOptions = {},\n ): Promise<AgentResult> {\n const runMetadata: PluginRunMetadata = {\n ...(options.pluginMetadata ?? {}),\n ...(options.mcpToolset ? { mcpToolset: options.mcpToolset } : {}),\n ...(options.policyContext ? { policyContext: options.policyContext } : {}),\n };\n\n let pluginCtx = this.toolManager.createPluginContext(\n sessionId,\n [],\n runMetadata,\n );\n\n try {\n const prepared = await this.toolManager.prepareTools(\n sessionId,\n this.eventBus,\n runtime,\n runMetadata,\n );\n const tools = prepared.tools;\n pluginCtx = prepared.pluginCtx;\n\n // Inject learning context if available\n if (this.config.learning) {\n const userId = this.config.userId ?? sessionId;\n const [profile, memories] = await Promise.all([\n this.config.learning.getProfile(userId),\n this.config.learning.getMemories(userId, { limit: 10 }),\n ]);\n const learningContext = this.buildLearningContext(profile, memories);\n if (learningContext) prompt = `${learningContext}\\n\\n${prompt}`;\n }\n\n const beforeRunResult = await this.pluginManager.runBeforeRun(pluginCtx, { prompt });\n if (beforeRunResult.prompt !== undefined) {\n prompt = beforeRunResult.prompt;\n }\n\n // --- Middleware: beforeAgent ---\n const mwCtx = this.createMiddlewareContext(sessionId);\n let instructions = this.config.instructions;\n if (this.middlewareChain) {\n const mwResult = await this.middlewareChain.runBeforeAgent(mwCtx, {\n prompt,\n instructions,\n tools,\n });\n\n // Abort: middleware requested short-circuit\n if (mwResult.aborted) {\n const earlyText = mwResult.earlyResult ?? \"\";\n this.eventBus.emit(\"agent:stop\", {\n result: { text: earlyText, steps: [], sessionId, toolCalls: [] },\n });\n return { text: earlyText, steps: [], sessionId, toolCalls: [] };\n }\n\n prompt = mwResult.prompt;\n instructions = mwResult.instructions;\n // NOTE: mwResult.tools is intentionally NOT merged here.\n // Tool injection must go through ToolManager to ensure security\n // validation, circuit breakers, and rate limiting are applied.\n }\n\n this.eventBus.emit(\"agent:start\", { prompt });\n\n const cpConfig = this.config.checkpointConfig;\n if (cpConfig?.enabled) {\n const cp = await this.config.memory.loadLatestCheckpoint(sessionId);\n if (cp) this.eventBus.emit(\"checkpoint:load\", { checkpoint: cp });\n }\n\n const agentOptions: Record<string, unknown> = {\n model: this.toolManager.createRateLimitedModel(),\n system: instructions,\n tools,\n stopWhen: stepCountIs(this.config.maxSteps),\n prompt,\n };\n if (this.config.output) agentOptions.output = this.config.output;\n\n // Wrap LLM call in telemetry span (safe on exception via withSpan)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = await this.withSpan(\"llm.generate\", { \"llm.model\": String(this.config.model) }, () =>\n generateText(agentOptions as unknown as Parameters<typeof generateText>[0]),\n );\n\n // Track token usage\n const resultObj = result as unknown as { usage?: { promptTokens?: number; completionTokens?: number } };\n const usage = resultObj.usage;\n if (usage) {\n if (usage.promptTokens) {\n this.tokenTracker.addInput(usage.promptTokens);\n this.config.telemetry?.recordMetric(\"llm.tokens.input\", usage.promptTokens);\n }\n if (usage.completionTokens) {\n this.tokenTracker.addOutput(usage.completionTokens);\n this.config.telemetry?.recordMetric(\"llm.tokens.output\", usage.completionTokens);\n }\n\n // Record cost tracking if available\n if (this.config.costTracker && (usage.promptTokens || usage.completionTokens)) {\n const modelId = (this.config.model as unknown as { modelId?: string }).modelId ?? \"unknown\";\n const provider = (this.config.model as unknown as { provider?: string }).provider ?? \"unknown\";\n this.config.costTracker.recordUsage({\n inputTokens: usage.promptTokens ?? 0,\n outputTokens: usage.completionTokens ?? 0,\n model: modelId,\n provider,\n timestamp: Date.now(),\n });\n }\n }\n\n const steps = (result.steps ?? []) as unknown[];\n for (let i = 0; i < steps.length; i++) {\n let step = steps[i];\n const stepObj = step as Record<string, unknown> | undefined;\n const toolName = (stepObj?.toolName as string) ?? `step.${i}`;\n const toolSpanStart = Date.now();\n\n try {\n await this.withSpan(`tool.${toolName}`, { \"tool.name\": toolName, \"step.index\": i }, async () => {\n const beforeStepResult = await this.pluginManager.runBeforeStep(pluginCtx, {\n stepIndex: i,\n step,\n });\n\n if (beforeStepResult.skip) return;\n if (beforeStepResult.step !== undefined) {\n step = beforeStepResult.step;\n steps[i] = step;\n }\n\n this.eventBus.emit(\"step:start\", { stepIndex: i, step });\n\n // Emit tool:call for each tool call in this step\n const toolCalls = (stepObj?.toolCalls as Array<{ toolName: string; toolCallId?: string; args?: unknown }>) ?? [];\n for (const tc of toolCalls) {\n const filtered = await this.applyDelegationMessageFilter({\n direction: \"tool:call\",\n toolName: tc.toolName,\n stepIndex: i,\n payload: tc.args,\n });\n\n if (!filtered.allow) {\n this.eventBus.emit(\"delegation:message-filtered\", {\n direction: \"tool:call\",\n toolName: tc.toolName,\n stepIndex: i,\n reason: filtered.reason,\n });\n continue;\n }\n\n this.eventBus.emit(\"tool:call\", {\n toolName: tc.toolName,\n toolCallId: tc.toolCallId,\n args: filtered.payload,\n stepIndex: i,\n });\n }\n\n // Emit tool:result for each tool result in this step\n const toolResults = (stepObj?.toolResults as Array<{ toolName: string; toolCallId?: string; result?: unknown }>) ?? [];\n for (const tr of toolResults) {\n const filtered = await this.applyDelegationMessageFilter({\n direction: \"tool:result\",\n toolName: tr.toolName,\n stepIndex: i,\n payload: tr.result,\n });\n\n if (!filtered.allow) {\n this.eventBus.emit(\"delegation:message-filtered\", {\n direction: \"tool:result\",\n toolName: tr.toolName,\n stepIndex: i,\n reason: filtered.reason,\n });\n continue;\n }\n\n this.eventBus.emit(\"tool:result\", {\n toolName: tr.toolName,\n toolCallId: tr.toolCallId,\n result: filtered.payload,\n stepIndex: i,\n });\n }\n\n this.eventBus.emit(\"step:end\", { stepIndex: i, step });\n\n await this.pluginManager.runAfterStep(pluginCtx, {\n stepIndex: i,\n step,\n });\n\n const toolDurationMs = Date.now() - toolSpanStart;\n this.config.telemetry?.recordMetric(\"tool.duration_ms\", toolDurationMs, { tool: toolName });\n });\n } catch (error) {\n const onStepError = await this.pluginManager.runOnError(pluginCtx, {\n error,\n phase: \"step\",\n });\n if (!onStepError.suppress) throw error;\n }\n }\n\n if (cpConfig?.enabled) {\n const checkpoint = {\n id: runtime.randomUUID(),\n sessionId,\n stepIndex: steps.length,\n conversation: [\n { role: \"user\" as const, content: prompt },\n { role: \"assistant\" as const, content: result.text ?? \"\" },\n ],\n todos: await this.config.memory.loadTodos(sessionId),\n filesSnapshot: {},\n toolResults: {},\n generatedTokens: 0,\n lastToolCallId: null,\n metadata: {},\n createdAt: Date.now(),\n };\n await this.config.memory.saveCheckpoint(sessionId, checkpoint);\n this.eventBus.emit(\"checkpoint:save\", { checkpoint });\n }\n\n // Extract all tool calls from steps\n const allToolCalls: Array<{ name: string; args?: unknown; stepIndex: number }> = [];\n for (let i = 0; i < steps.length; i++) {\n const s = steps[i] as Record<string, unknown> | undefined;\n const calls = (s?.toolCalls as Array<{ toolName: string; args?: unknown }>) ?? [];\n for (const tc of calls) {\n allToolCalls.push({ name: tc.toolName, args: tc.args, stepIndex: i });\n }\n }\n\n const agentResult: AgentResult = {\n text: result.text ?? \"\",\n steps,\n sessionId,\n output: (result as unknown as { output?: unknown }).output,\n toolCalls: allToolCalls,\n };\n\n // --- Middleware: afterAgent ---\n if (this.middlewareChain) {\n const mwAfterResult = await this.middlewareChain.runAfterAgent(mwCtx, {\n prompt,\n result: { text: agentResult.text, steps: agentResult.steps, sessionId },\n });\n agentResult.text = mwAfterResult.result.text;\n }\n\n this.eventBus.emit(\"agent:stop\", { result: agentResult });\n await this.pluginManager.runAfterRun(pluginCtx, { result: agentResult });\n return agentResult;\n } catch (error: unknown) {\n const onErrorResult = await this.pluginManager.runOnError(pluginCtx, {\n error,\n phase: \"run\",\n });\n if (onErrorResult.suppress) {\n return { text: \"\", steps: [], sessionId, toolCalls: [] };\n }\n this.eventBus.emit(\"error\", { error });\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Stream\n // ---------------------------------------------------------------------------\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async stream(\n params: { messages: Array<{ role: string; content: unknown }> },\n sessionId: string,\n runtime: RuntimePort,\n options: AgentRunOptions = {},\n ): Promise<any> {\n let pluginCtx = this.toolManager.createPluginContext(sessionId, [], options.pluginMetadata);\n\n try {\n const prepared = await this.toolManager.prepareTools(\n sessionId,\n this.eventBus,\n runtime,\n options.pluginMetadata,\n );\n const tools = prepared.tools;\n pluginCtx = prepared.pluginCtx;\n\n // Inject learning context as a system message\n if (this.config.learning) {\n const userId = this.config.userId ?? sessionId;\n const [profile, memories] = await Promise.all([\n this.config.learning.getProfile(userId),\n this.config.learning.getMemories(userId, { limit: 10 }),\n ]);\n const learningContext = this.buildLearningContext(profile, memories);\n if (learningContext) {\n params = {\n ...params,\n messages: [\n { role: \"system\", content: learningContext },\n ...params.messages,\n ],\n };\n }\n }\n\n this.eventBus.emit(\"agent:start\", { messages: params.messages });\n\n return this.withSpan(\"stream\", { \"stream.messages\": params.messages.length }, async () => {\n const streamAgentOptions: Record<string, unknown> = {\n model: this.toolManager.createRateLimitedModel(),\n system: this.config.instructions,\n tools,\n stopWhen: stepCountIs(this.config.maxSteps),\n };\n if (this.config.output) streamAgentOptions.output = this.config.output;\n\n const streamResult = streamText(streamAgentOptions as unknown as Parameters<typeof streamText>[0]);\n\n // Track cost from streaming after completion\n if (this.config.costTracker) {\n const costTracker = this.config.costTracker;\n const model = this.config.model;\n const tokenTracker = this.tokenTracker;\n return Promise.resolve(streamResult).then((stream) => {\n const usagePromise = (stream as unknown as Record<string, unknown>).usage ?? (stream as unknown as Record<string, unknown>).totalUsage;\n if (usagePromise && typeof (usagePromise as Promise<unknown>).then === \"function\") {\n (usagePromise as Promise<{ promptTokens?: number; completionTokens?: number }>).then((u) => {\n if (u) {\n if (u.promptTokens) tokenTracker.addInput(u.promptTokens);\n if (u.completionTokens) tokenTracker.addOutput(u.completionTokens);\n if (u.promptTokens || u.completionTokens) {\n const modelId = (model as unknown as { modelId?: string }).modelId ?? \"unknown\";\n const provider = (model as unknown as { provider?: string }).provider ?? \"unknown\";\n costTracker.recordUsage({\n inputTokens: u.promptTokens ?? 0,\n outputTokens: u.completionTokens ?? 0,\n model: modelId,\n provider,\n timestamp: Date.now(),\n });\n }\n }\n }).catch((err: unknown) => {\n // fire-and-forget: usage tracking must not break streaming\n console.warn(\"[usage-tracking] Failed to record usage:\", err instanceof Error ? err.message : String(err));\n });\n }\n return stream;\n });\n }\n\n return streamResult;\n });\n } catch (error: unknown) {\n const onErrorResult = await this.pluginManager.runOnError(pluginCtx, {\n error,\n phase: \"stream\",\n });\n if (onErrorResult.suppress) {\n return new ReadableStream({ start(c) { c.close(); } });\n }\n this.eventBus.emit(\"error\", { error });\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Learning context\n // ---------------------------------------------------------------------------\n\n private buildLearningContext(profile: UserProfile | null, memories: UserMemory[]): string {\n const parts: string[] = [];\n if (profile) {\n if (profile.context) parts.push(`User context: ${profile.context}`);\n if (profile.style) parts.push(`Preferred style: ${profile.style}`);\n if (profile.language) parts.push(`Language: ${profile.language}`);\n }\n if (memories.length > 0) {\n parts.push(`Known facts about this user:\\n${memories.map((m) => `- ${m.content}`).join(\"\\n\")}`);\n }\n return parts.length > 0 ? `[Learning Context]\\n${parts.join(\"\\n\")}` : \"\";\n }\n}\n","// =============================================================================\n// Agent Lifecycle Manager — Startup, Shutdown, and Health Management\n// =============================================================================\n\n/** Graceful shutdown timeout in ms (30 seconds) */\nconst SHUTDOWN_TIMEOUT_MS = 30_000;\n\nexport interface LifecycleHooks {\n onStartup?: () => Promise<void>;\n onShutdown?: () => Promise<void>;\n onHealthCheck?: () => Promise<HealthStatus>;\n}\n\nexport interface HealthStatus {\n healthy: boolean;\n details?: Record<string, { status: 'up' | 'down'; message?: string }>;\n}\n\nexport class LifecycleManager {\n private _isReady = false;\n private _isShuttingDown = false;\n private readonly hooks: LifecycleHooks;\n private readonly runningOperations = new Set<Promise<unknown>>();\n\n constructor(hooks: LifecycleHooks) {\n this.hooks = hooks;\n }\n\n async startup(): Promise<void> {\n if (this._isReady) return;\n \n try {\n if (this.hooks.onStartup) {\n await this.hooks.onStartup();\n }\n this._isReady = true;\n } catch (error) {\n this._isReady = false;\n throw error;\n }\n }\n\n async shutdown(): Promise<void> {\n if (this._isShuttingDown) return;\n \n this._isShuttingDown = true;\n this._isReady = false;\n\n // Wait for running operations to complete (timeout 30s)\n if (this.runningOperations.size > 0) {\n const controller = new AbortController();\n const timeout = new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, SHUTDOWN_TIMEOUT_MS);\n controller.signal.addEventListener('abort', () => {\n clearTimeout(timer);\n resolve();\n });\n });\n \n const allOperations = Promise.all(Array.from(this.runningOperations))\n .then(() => {})\n // fire-and-forget: running operations must not prevent graceful shutdown\n .catch((err: unknown) => {\n console.warn(\"[shutdown] Error in running operation:\", err instanceof Error ? err.message : String(err));\n });\n \n await Promise.race([allOperations, timeout]);\n controller.abort();\n }\n\n try {\n if (this.hooks.onShutdown) {\n await this.hooks.onShutdown();\n }\n } finally {\n // Clear any remaining operations\n this.runningOperations.clear();\n }\n }\n\n async healthCheck(): Promise<HealthStatus> {\n if (this.hooks.onHealthCheck) {\n return this.hooks.onHealthCheck();\n }\n \n return {\n healthy: this._isReady && !this._isShuttingDown,\n details: {\n lifecycle: {\n status: this._isReady && !this._isShuttingDown ? 'up' : 'down',\n message: this._isShuttingDown \n ? 'Agent is shutting down' \n : this._isReady \n ? 'Agent is ready' \n : 'Agent not started',\n },\n },\n };\n }\n\n get isReady(): boolean {\n return this._isReady;\n }\n\n get isShuttingDown(): boolean {\n return this._isShuttingDown;\n }\n\n /**\n * Track a running operation for graceful shutdown.\n * Returns a cleanup function to remove the operation from tracking.\n */\n trackOperation<T>(operation: Promise<T>): Promise<T> {\n this.runningOperations.add(operation);\n \n const cleanup = () => {\n this.runningOperations.delete(operation);\n };\n \n operation.finally(cleanup);\n return operation;\n }\n}","// =============================================================================\n// MiddlewareChain — Priority-ordered middleware executor\n// =============================================================================\n\nimport type {\n MiddlewarePort,\n MiddlewareChainPort,\n MiddlewareContext,\n BeforeAgentParams,\n BeforeAgentResult,\n BeforeAgentChainResult,\n AfterAgentParams,\n AfterAgentResult,\n BeforeToolCallParams,\n BeforeToolCallResult,\n AfterToolCallParams,\n AfterToolCallResult,\n OnMiddlewareErrorParams,\n} from \"../ports/middleware.port.js\";\n\nexport class MiddlewareChain implements MiddlewareChainPort {\n private middlewares: MiddlewarePort[] = [];\n private sorted = true;\n\n // ---------------------------------------------------------------------------\n // Registration\n // ---------------------------------------------------------------------------\n\n use(middleware: MiddlewarePort): void {\n if (this.middlewares.some((m) => m.name === middleware.name)) {\n throw new Error(`Middleware \"${middleware.name}\" is already registered`);\n }\n this.middlewares.push(middleware);\n this.sorted = false;\n }\n\n remove(name: string): boolean {\n const idx = this.middlewares.findIndex((m) => m.name === name);\n if (idx === -1) return false;\n this.middlewares.splice(idx, 1);\n return true;\n }\n\n list(): readonly MiddlewarePort[] {\n this.ensureSorted();\n return this.middlewares;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n async setup(ctx: MiddlewareContext): Promise<void> {\n this.ensureSorted();\n for (const mw of this.middlewares) {\n if (mw.setup) {\n await mw.setup(ctx);\n }\n }\n }\n\n async teardown(ctx: MiddlewareContext): Promise<void> {\n // Teardown in reverse order\n for (let i = this.middlewares.length - 1; i >= 0; i--) {\n const mw = this.middlewares[i];\n if (mw.teardown) {\n try {\n await mw.teardown(ctx);\n } catch {\n // Teardown errors should not block other teardowns\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // beforeAgent — forward order, accumulate mutations\n // ---------------------------------------------------------------------------\n\n async runBeforeAgent(\n ctx: MiddlewareContext,\n params: BeforeAgentParams,\n ): Promise<BeforeAgentChainResult> {\n this.ensureSorted();\n let current = { ...params };\n\n for (const mw of this.middlewares) {\n if (!mw.beforeAgent) continue;\n\n let result: BeforeAgentResult | void;\n try {\n result = await mw.beforeAgent(ctx, current);\n } catch (error) {\n const shouldContinue = await this.handleError(ctx, {\n error,\n phase: \"beforeAgent\",\n middlewareName: mw.name,\n });\n if (!shouldContinue) throw error;\n continue;\n }\n\n if (!result) continue;\n\n if (result.abort) {\n return {\n ...current,\n aborted: true,\n earlyResult: result.earlyResult,\n };\n }\n\n current = {\n prompt: result.prompt ?? current.prompt,\n instructions: result.instructions ?? current.instructions,\n tools: result.tools\n ? { ...current.tools, ...result.tools }\n : current.tools,\n };\n }\n\n return current;\n }\n\n // ---------------------------------------------------------------------------\n // afterAgent — reverse order, accumulate mutations\n // ---------------------------------------------------------------------------\n\n async runAfterAgent(\n ctx: MiddlewareContext,\n params: AfterAgentParams,\n ): Promise<AfterAgentParams> {\n this.ensureSorted();\n let current = { ...params };\n\n // After hooks run in reverse priority (LAST → FIRST)\n for (let i = this.middlewares.length - 1; i >= 0; i--) {\n const mw = this.middlewares[i];\n if (!mw.afterAgent) continue;\n\n let result: AfterAgentResult | void;\n try {\n result = await mw.afterAgent(ctx, current);\n } catch (error) {\n const shouldContinue = await this.handleError(ctx, {\n error,\n phase: \"afterAgent\",\n middlewareName: mw.name,\n });\n if (!shouldContinue) throw error;\n continue;\n }\n\n if (result?.text !== undefined) {\n current = {\n ...current,\n result: { ...current.result, text: result.text },\n };\n }\n }\n\n return current;\n }\n\n // ---------------------------------------------------------------------------\n // beforeTool — forward order\n // ---------------------------------------------------------------------------\n\n async runBeforeTool(\n ctx: MiddlewareContext,\n params: BeforeToolCallParams,\n ): Promise<BeforeToolCallResult> {\n this.ensureSorted();\n let currentArgs = params.args;\n\n for (const mw of this.middlewares) {\n if (!mw.beforeTool) continue;\n\n let result: BeforeToolCallResult | void;\n try {\n result = await mw.beforeTool(ctx, {\n ...params,\n args: currentArgs,\n });\n } catch (error) {\n const shouldContinue = await this.handleError(ctx, {\n error,\n phase: \"beforeTool\",\n middlewareName: mw.name,\n });\n if (!shouldContinue) throw error;\n continue;\n }\n\n if (!result) continue;\n\n if (result.skip) {\n return { skip: true, mockResult: result.mockResult };\n }\n\n if (result.args !== undefined) {\n currentArgs = result.args;\n }\n }\n\n return { args: currentArgs };\n }\n\n // ---------------------------------------------------------------------------\n // afterTool — reverse order\n // ---------------------------------------------------------------------------\n\n async runAfterTool(\n ctx: MiddlewareContext,\n params: AfterToolCallParams,\n ): Promise<AfterToolCallParams> {\n this.ensureSorted();\n let current = { ...params };\n\n for (let i = this.middlewares.length - 1; i >= 0; i--) {\n const mw = this.middlewares[i];\n if (!mw.afterTool) continue;\n\n let result: AfterToolCallResult | void;\n try {\n result = await mw.afterTool(ctx, current);\n } catch (error) {\n const shouldContinue = await this.handleError(ctx, {\n error,\n phase: \"afterTool\",\n middlewareName: mw.name,\n });\n if (!shouldContinue) throw error;\n continue;\n }\n\n if (result?.result !== undefined) {\n current = { ...current, result: result.result };\n }\n }\n\n return current;\n }\n\n // ---------------------------------------------------------------------------\n // Error handling — delegates to middleware onError hooks\n // ---------------------------------------------------------------------------\n\n private async handleError(\n ctx: MiddlewareContext,\n params: OnMiddlewareErrorParams,\n ): Promise<boolean> {\n for (const mw of this.middlewares) {\n if (!mw.onError) continue;\n try {\n const result = await mw.onError(ctx, params);\n if (result?.suppress) return true;\n } catch {\n // Error handler itself failed — ignore and continue\n }\n }\n return false;\n }\n\n // ---------------------------------------------------------------------------\n // Internal — sort by priority (stable sort)\n // ---------------------------------------------------------------------------\n\n private ensureSorted(): void {\n if (this.sorted) return;\n this.middlewares.sort((a, b) => a.priority - b.priority);\n this.sorted = true;\n }\n}\n\n// =============================================================================\n// compose — Merge multiple middleware into a single middleware unit\n// =============================================================================\n\nexport function composeMiddleware(\n name: string,\n ...middlewares: MiddlewarePort[]\n): MiddlewarePort {\n const chain = new MiddlewareChain();\n for (const mw of middlewares) {\n chain.use(mw);\n }\n\n // Use the lowest priority among composed middleware\n const priority = middlewares.length > 0\n ? Math.min(...middlewares.map((m) => m.priority))\n : 500;\n\n return {\n name,\n priority,\n async setup(ctx) { await chain.setup(ctx); },\n async teardown(ctx) { await chain.teardown(ctx); },\n async beforeAgent(ctx, params) {\n const result = await chain.runBeforeAgent(ctx, params);\n if (result.prompt !== params.prompt || result.instructions !== params.instructions) {\n return { prompt: result.prompt, instructions: result.instructions };\n }\n },\n async afterAgent(ctx, params) {\n const result = await chain.runAfterAgent(ctx, params);\n if (result.result.text !== params.result.text) {\n return { text: result.result.text };\n }\n },\n async beforeTool(ctx, params) {\n return chain.runBeforeTool(ctx, params);\n },\n async afterTool(ctx, params) {\n const result = await chain.runAfterTool(ctx, params);\n if (result.result !== params.result) {\n return { result: result.result };\n }\n },\n };\n}\n","import { VirtualFilesystem } from \"../adapters/filesystem/virtual-fs.adapter.js\";\nimport { InMemoryAdapter } from \"../adapters/memory/in-memory.adapter.js\";\nimport { ApproximateTokenCounter } from \"../adapters/token-counter/approximate.adapter.js\";\n\nexport function defaultFilesystem() { return new VirtualFilesystem(); }\nexport function defaultMemory() { return new InMemoryAdapter(); }\nexport function defaultTokenCounter() { return new ApproximateTokenCounter(); }\n","/**\n * Rate Limiter using token bucket algorithm\n */\n\nexport interface RateLimiterConfig {\n readonly maxTokens: number;\n readonly refillRateMs: number;\n}\n\nexport const DEFAULT_RATE_LIMITER_CONFIG: RateLimiterConfig = {\n maxTokens: 10,\n refillRateMs: 1000,\n};\n\nexport class RateLimiter {\n private tokens: number;\n private lastRefillTime: number;\n private waitQueue: Array<{ resolve: () => void; reject: (error: Error) => void }> = [];\n private processingScheduled = false;\n\n constructor(private readonly config: RateLimiterConfig = DEFAULT_RATE_LIMITER_CONFIG) {\n this.tokens = config.maxTokens;\n this.lastRefillTime = Date.now();\n }\n\n /**\n * Acquire a token, waiting if necessary\n */\n async acquire(): Promise<void> {\n if (this.tryAcquire()) {\n return;\n }\n\n return new Promise<void>((resolve, reject) => {\n this.waitQueue.push({ resolve, reject });\n this.processQueue();\n });\n }\n\n /**\n * Try to acquire a token immediately\n * @returns true if token acquired, false otherwise\n */\n tryAcquire(): boolean {\n this.refillTokens();\n \n if (this.tokens > 0) {\n this.tokens--;\n return true;\n }\n \n return false;\n }\n\n /**\n * Get number of available tokens\n */\n get availableTokens(): number {\n this.refillTokens();\n return this.tokens;\n }\n\n /**\n * Reset the rate limiter to initial state\n */\n reset(): void {\n this.tokens = this.config.maxTokens;\n this.lastRefillTime = Date.now();\n this.processingScheduled = false;\n \n // Reject all waiting requests\n const queue = [...this.waitQueue];\n this.waitQueue = [];\n queue.forEach(({ reject }) => {\n reject(new RateLimiterError('Rate limiter was reset'));\n });\n }\n\n private refillTokens(): void {\n const now = Date.now();\n const timePassed = now - this.lastRefillTime;\n \n if (timePassed >= this.config.refillRateMs) {\n const tokensToAdd = Math.floor(timePassed / this.config.refillRateMs);\n this.tokens = Math.min(this.config.maxTokens, this.tokens + tokensToAdd);\n this.lastRefillTime = now - (timePassed % this.config.refillRateMs);\n }\n }\n\n private processQueue(): void {\n if (this.waitQueue.length === 0 || this.processingScheduled) {\n return;\n }\n\n this.processingScheduled = true;\n\n // Schedule processing after the next refill\n const timeUntilNextRefill = this.config.refillRateMs - (Date.now() - this.lastRefillTime);\n const delay = Math.max(0, timeUntilNextRefill);\n\n setTimeout(() => {\n this.processingScheduled = false;\n this.refillTokens();\n \n while (this.waitQueue.length > 0 && this.tokens > 0) {\n const waiter = this.waitQueue.shift()!;\n this.tokens--;\n waiter.resolve();\n }\n\n // Continue processing if there are still waiters\n if (this.waitQueue.length > 0) {\n this.processQueue();\n }\n }, delay);\n }\n}\n\nexport class RateLimiterError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RateLimiterError';\n }\n}","// =============================================================================\n// AgentBuilder — Configuration & construction of Agent instances\n// =============================================================================\n\nimport type { Tool } from \"../core/llm/index.js\";\n\nimport type { FilesystemPort } from \"../ports/filesystem.port.js\";\nimport type { MemoryPort } from \"../ports/memory.port.js\";\nimport type { LearningPort } from \"../ports/learning.port.js\";\nimport type { TokenCounterPort } from \"../ports/token-counter.port.js\";\nimport type { McpPort } from \"../ports/mcp.port.js\";\nimport type { PolicyEnginePort } from \"../ports/policy.port.js\";\nimport type { TelemetryPort } from \"../ports/telemetry.port.js\";\nimport type { CostTrackerPort } from \"../ports/cost-tracker.port.js\";\nimport type { AgentEventHandler, AgentEventType, AgentConfig, ApprovalConfig, SubagentConfig } from \"../types.js\";\nimport type { Plugin } from \"../ports/plugin.port.js\";\nimport type { RuntimePort } from \"../ports/runtime.port.js\";\nimport type { LifecycleHooks } from \"./lifecycle.js\";\nimport type { PromptTemplate } from \"../templates/index.js\";\n\nimport { AbstractBuilder } from \"../utils/abstract-builder.js\";\nimport { resolveApprovalConfig, resolveCheckpointConfig } from \"./agent-config.js\";\nimport { defaultFilesystem, defaultMemory, defaultTokenCounter } from \"./defaults.js\";\nimport { CircuitBreaker, RateLimiter, ToolCache, DEFAULT_CIRCUIT_BREAKER_CONFIG, DEFAULT_RATE_LIMITER_CONFIG, DEFAULT_TOOL_CACHE_CONFIG } from \"../adapters/resilience/index.js\";\nimport type { CircuitBreakerConfig, RateLimiterConfig, ToolCacheConfig } from \"../adapters/resilience/index.js\";\n\nimport { Agent } from \"./agent.js\";\n\nexport class AgentBuilder extends AbstractBuilder<Agent> {\n private readonly agentConfig: AgentConfig;\n private maxStepsOverride?: number;\n\n private fs?: FilesystemPort;\n private memory?: MemoryPort;\n private learning?: LearningPort;\n private userId?: string;\n private tokenCounter?: TokenCounterPort;\n private mcp?: McpPort;\n private policyEngine?: PolicyEnginePort;\n private runtime?: RuntimePort;\n private costTracker?: CostTrackerPort;\n\n private planning = false;\n private subagents = false;\n private subagentConfig?: Partial<SubagentConfig>;\n private approvalConfig?: Partial<ApprovalConfig>;\n\n // Resilience patterns\n private circuitBreaker?: CircuitBreaker;\n private rateLimiter?: RateLimiter;\n private toolCache?: ToolCache;\n \n // Telemetry\n private telemetryAdapter?: TelemetryPort;\n\n private extraTools: Record<string, Tool<any, any>> = {};\n private readonly plugins: Plugin[] = [];\n private lifecycleHooks?: LifecycleHooks;\n\n private readonly eventHandlers: Array<{\n type: AgentEventType | \"*\";\n handler: AgentEventHandler;\n }> = [];\n\n /** AI SDK Output specification (e.g. Output.object({schema})) */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private outputSpec?: any;\n\n constructor(config: AgentConfig) {\n super();\n this.agentConfig = config;\n }\n\n withFilesystem(fs: FilesystemPort): this {\n this.fs = fs;\n return this;\n }\n\n withMemory(memory: MemoryPort): this {\n this.memory = memory;\n return this;\n }\n\n withLearning(learning: LearningPort, userId?: string): this {\n this.learning = learning;\n this.userId = userId;\n return this;\n }\n\n withTokenCounter(counter: TokenCounterPort): this {\n this.tokenCounter = counter;\n return this;\n }\n\n withMcp(mcp: McpPort): this {\n this.mcp = mcp;\n return this;\n }\n\n withPolicyEngine(policyEngine: PolicyEnginePort): this {\n this.policyEngine = policyEngine;\n return this;\n }\n\n withRuntime(runtime: RuntimePort): this {\n this.runtime = runtime;\n return this;\n }\n\n withCostTracker(tracker: CostTrackerPort): this {\n this.costTracker = tracker;\n return this;\n }\n\n withPlanning(): this {\n this.planning = true;\n return this;\n }\n\n withSubagents(config?: Partial<SubagentConfig>): this {\n this.subagents = true;\n this.subagentConfig = config;\n return this;\n }\n\n withApproval(config?: Partial<ApprovalConfig>): this {\n this.approvalConfig = config;\n return this;\n }\n\n withMaxSteps(steps: number): this {\n this.maxStepsOverride = steps;\n return this;\n }\n\n withCircuitBreaker(config?: Partial<CircuitBreakerConfig>): this {\n this.circuitBreaker = new CircuitBreaker({ ...DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config });\n return this;\n }\n\n withRateLimiter(config?: Partial<RateLimiterConfig>): this {\n this.rateLimiter = new RateLimiter({ ...DEFAULT_RATE_LIMITER_CONFIG, ...config });\n return this;\n }\n\n withToolCache(config?: Partial<ToolCacheConfig>): this {\n this.toolCache = new ToolCache({ ...DEFAULT_TOOL_CACHE_CONFIG, ...config });\n return this;\n }\n\n withTools(tools: Record<string, Tool<any, any>>): this {\n Object.assign(this.extraTools, tools);\n return this;\n }\n\n withTool(name: string, tool: Tool): this {\n this.extraTools[name] = tool;\n return this;\n }\n\n withPlugin(plugin: Plugin): this {\n this.plugins.push(plugin);\n return this;\n }\n\n on(type: AgentEventType | \"*\", handler: AgentEventHandler): this {\n this.eventHandlers.push({ type, handler });\n return this;\n }\n\n withLifecycle(hooks: LifecycleHooks): this {\n this.lifecycleHooks = hooks;\n return this;\n }\n\n withTelemetry(adapter: TelemetryPort): this {\n this.telemetryAdapter = adapter;\n return this;\n }\n\n /**\n * Set structured output specification (AI SDK passthrough).\n * Usage: `.withOutput(Output.object({ schema: z.object({...}) }))`\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n withOutput(output: any): this {\n this.outputSpec = output;\n return this;\n }\n\n withInstructions(instructions: string): this;\n withInstructions(template: PromptTemplate, variables?: Record<string, string>): this;\n withInstructions(instructionsOrTemplate: string | PromptTemplate, variables?: Record<string, string>): this {\n if (typeof instructionsOrTemplate === 'string') {\n this.agentConfig.instructions = instructionsOrTemplate;\n } else {\n this.agentConfig.instructions = instructionsOrTemplate.compile(variables);\n }\n return this;\n }\n\n protected validate(): void {\n if (!this.agentConfig.model) throw new Error(\"model is required\");\n if (!this.agentConfig.instructions) throw new Error(\"instructions is required\");\n }\n\n protected construct(): Agent {\n const agent = new Agent({\n model: this.agentConfig.model,\n instructions: this.agentConfig.instructions,\n id: this.agentConfig.id,\n name: this.agentConfig.name,\n maxSteps: this.maxStepsOverride ?? this.agentConfig.maxSteps ?? 30,\n fs: this.fs ?? defaultFilesystem(),\n memory: this.memory ?? defaultMemory(),\n learning: this.learning,\n userId: this.userId,\n tokenCounter: this.tokenCounter ?? defaultTokenCounter(),\n mcp: this.mcp,\n policyEngine: this.policyEngine,\n runtime: this.runtime,\n costTracker: this.costTracker,\n planning: this.planning,\n subagents: this.subagents,\n subagentConfig: this.subagentConfig,\n approvalConfig: this.approvalConfig\n ? resolveApprovalConfig(this.approvalConfig)\n : undefined,\n checkpointConfig: resolveCheckpointConfig(\n this.agentConfig.checkpoint,\n ),\n extraTools: this.extraTools,\n plugins: this.plugins,\n circuitBreaker: this.circuitBreaker,\n rateLimiter: this.rateLimiter,\n toolCache: this.toolCache,\n lifecycleHooks: this.lifecycleHooks,\n telemetry: this.telemetryAdapter,\n output: this.outputSpec,\n });\n\n for (const { type, handler } of this.eventHandlers) {\n agent.eventBus.on(type, handler);\n }\n\n return agent;\n }\n\n build(): Agent {\n return super.build();\n }\n}\n","// =============================================================================\n// Agent — Execution orchestrator (SRP: building logic in agent-builder.ts)\n// =============================================================================\n\nimport type { LanguageModel, Tool } from \"../core/llm/index.js\";\n\nimport type { FilesystemPort } from \"../ports/filesystem.port.js\";\nimport type { MemoryPort } from \"../ports/memory.port.js\";\nimport type { LearningPort } from \"../ports/learning.port.js\";\nimport type { TokenCounterPort } from \"../ports/token-counter.port.js\";\nimport type { McpPort } from \"../ports/mcp.port.js\";\nimport type {\n PolicyContext,\n PolicyEnginePort,\n} from \"../ports/policy.port.js\";\nimport type { TelemetryPort } from \"../ports/telemetry.port.js\";\nimport type { CostTrackerPort } from \"../ports/cost-tracker.port.js\";\nimport type {\n AgentConfig,\n CheckpointConfig,\n SubagentConfig,\n ApprovalConfig,\n McpToolsetSelection,\n} from \"../types.js\";\nimport type { Plugin, PluginRunMetadata } from \"../ports/plugin.port.js\";\nimport type { RuntimePort } from \"../ports/runtime.port.js\";\nimport type { MiddlewarePort } from \"../ports/middleware.port.js\";\nimport { createRuntimeAdapterAsync } from \"../adapters/runtime/detect-runtime.js\";\n\nimport { EventBus } from \"./event-bus.js\";\nimport { PluginManager } from \"../plugins/plugin-manager.js\";\nimport { TokenTracker } from \"../context/token-tracker.js\";\nimport { CircuitBreaker, RateLimiter, ToolCache } from \"../adapters/resilience/index.js\";\nimport { ToolManager } from \"./tool-manager.js\";\nimport { ExecutionEngine } from \"./execution-engine.js\";\nimport { LifecycleManager, type LifecycleHooks, type HealthStatus } from \"./lifecycle.js\";\nimport { MiddlewareChain } from \"../middleware/chain.js\";\n\n// Builder is imported for use in static factory methods\nimport { AgentBuilder } from \"./agent-builder.js\";\n\n// =============================================================================\n// Result type\n// =============================================================================\n\nexport interface AgentResult<TOutput = unknown> {\n text: string;\n steps: unknown[];\n sessionId: string;\n /** Parsed structured output when `output` is configured via builder or run options. */\n output?: TOutput;\n /** Tool calls extracted from all steps. */\n toolCalls: Array<{ name: string; args?: unknown; stepIndex: number }>;\n}\n\nexport interface AgentRunOptions {\n pluginMetadata?: PluginRunMetadata;\n mcpToolset?: McpToolsetSelection;\n policyContext?: PolicyContext;\n}\n\n// Re-export builder for backward compatibility\nexport { AgentBuilder } from \"./agent-builder.js\";\n\n// =============================================================================\n// Agent\n// =============================================================================\n\ninterface AgentInternalConfig {\n model: LanguageModel;\n instructions: string;\n id?: string;\n name?: string;\n maxSteps: number;\n fs: FilesystemPort;\n memory: MemoryPort;\n tokenCounter: TokenCounterPort;\n mcp?: McpPort;\n policyEngine?: PolicyEnginePort;\n runtime?: RuntimePort;\n learning?: LearningPort;\n userId?: string;\n planning: boolean;\n subagents: boolean;\n subagentConfig?: Partial<SubagentConfig>;\n approvalConfig?: Required<ApprovalConfig>;\n checkpointConfig?: Required<CheckpointConfig>;\n extraTools?: Record<string, Tool<any, any>>;\n plugins?: Plugin[];\n costTracker?: CostTrackerPort;\n circuitBreaker?: CircuitBreaker;\n rateLimiter?: RateLimiter;\n toolCache?: ToolCache;\n lifecycleHooks?: LifecycleHooks;\n telemetry?: TelemetryPort;\n /** AI SDK Output specification for structured output (passthrough to ToolLoopAgent). */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n output?: any;\n /** Middleware stack — composable, priority-ordered hooks */\n middleware?: MiddlewarePort[];\n}\n\nexport class Agent {\n readonly sessionId: string;\n readonly eventBus: EventBus;\n\n private readonly config: AgentInternalConfig;\n private _runtime: RuntimePort | null;\n private _runtimePromise: Promise<RuntimePort> | null = null;\n private readonly tokenTracker: TokenTracker;\n private readonly pluginManager: PluginManager;\n private readonly middlewareChain: MiddlewareChain;\n private _toolManager?: ToolManager;\n private _executionEngine?: ExecutionEngine;\n private readonly lifecycleManager: LifecycleManager;\n \n // Resilience patterns\n private readonly circuitBreaker?: CircuitBreaker;\n private readonly rateLimiter?: RateLimiter;\n private readonly toolCache?: ToolCache;\n \n // Telemetry\n private readonly telemetry?: TelemetryPort;\n\n constructor(config: AgentInternalConfig) {\n this._runtime = config.runtime ?? null;\n this.sessionId = config.id ?? (this._runtime ? this._runtime.randomUUID() : crypto.randomUUID());\n this.eventBus = new EventBus(this.sessionId);\n this.config = config;\n this.tokenTracker = new TokenTracker(config.tokenCounter, {\n maxInputTokens: Infinity,\n maxOutputTokens: Infinity,\n maxTotalTokens: Infinity,\n warningThreshold: 0.9,\n });\n this.pluginManager = new PluginManager();\n for (const plugin of config.plugins ?? []) {\n this.pluginManager.register(plugin);\n }\n \n // Initialize middleware chain\n this.middlewareChain = new MiddlewareChain();\n for (const mw of config.middleware ?? []) {\n this.middlewareChain.use(mw);\n }\n \n // Initialize resilience patterns\n this.circuitBreaker = config.circuitBreaker;\n this.rateLimiter = config.rateLimiter;\n this.toolCache = config.toolCache;\n \n // Initialize telemetry\n this.telemetry = config.telemetry;\n\n // Initialize lifecycle manager\n this.lifecycleManager = new LifecycleManager(config.lifecycleHooks ?? {});\n }\n\n // ---------------------------------------------------------------------------\n // Lazy-initialized heavy managers (created on first access)\n // ---------------------------------------------------------------------------\n\n private get toolManager(): ToolManager {\n return this._toolManager ??= new ToolManager(\n {\n model: this.config.model,\n instructions: this.config.instructions,\n name: this.config.name,\n maxSteps: this.config.maxSteps,\n fs: this.config.fs,\n memory: this.config.memory,\n learning: this.config.learning,\n mcp: this.config.mcp,\n policyEngine: this.config.policyEngine,\n userId: this.config.userId,\n planning: this.config.planning,\n subagents: this.config.subagents,\n subagentConfig: this.config.subagentConfig,\n approvalConfig: this.config.approvalConfig,\n extraTools: this.config.extraTools,\n },\n this.pluginManager,\n this.circuitBreaker,\n this.rateLimiter,\n this.toolCache,\n );\n }\n\n private get executionEngine(): ExecutionEngine {\n return this._executionEngine ??= new ExecutionEngine(\n {\n model: this.config.model,\n instructions: this.config.instructions,\n maxSteps: this.config.maxSteps,\n memory: this.config.memory,\n learning: this.config.learning,\n userId: this.config.userId,\n agentName: this.config.name,\n delegationHooks: this.config.subagentConfig?.hooks,\n checkpointConfig: this.config.checkpointConfig,\n telemetry: this.config.telemetry,\n costTracker: this.config.costTracker,\n output: this.config.output,\n },\n this.toolManager,\n this.pluginManager,\n this.eventBus,\n this.tokenTracker,\n this.middlewareChain,\n );\n }\n\n /** Lazy-initialized runtime adapter. Resolves on first use. */\n private async ensureRuntime(): Promise<RuntimePort> {\n if (this._runtime) return this._runtime;\n if (!this._runtimePromise) {\n this._runtimePromise = createRuntimeAdapterAsync().then((rt) => {\n this._runtime = rt;\n return rt;\n });\n }\n return this._runtimePromise;\n }\n\n // ---------------------------------------------------------------------------\n // Static factories\n // ---------------------------------------------------------------------------\n\n static create(config: AgentConfig): AgentBuilder {\n return new AgentBuilder(config);\n }\n\n static minimal(config: AgentConfig): Agent {\n return Agent.create(config).withPlanning().build();\n }\n\n static full(config: AgentConfig & {\n memory?: MemoryPort;\n mcp?: McpPort;\n tokenCounter?: TokenCounterPort;\n }): Agent {\n const builder = Agent.create(config).withPlanning().withSubagents();\n if (config.memory) builder.withMemory(config.memory);\n if (config.mcp) builder.withMcp(config.mcp);\n if (config.tokenCounter) builder.withTokenCounter(config.tokenCounter);\n return builder.build();\n }\n\n /**\n * Auto-configuring factory that works in any runtime.\n * Uses universal adapters (VirtualFilesystem, InMemoryAdapter, ApproximateTokenCounter)\n * that require zero platform-specific APIs.\n *\n * For runtime-specific adapters (LocalFilesystem, DenoFilesystem, OpfsFilesystem, etc.),\n * use `Agent.create()` and compose manually.\n */\n static auto(config: AgentConfig): Agent {\n return Agent.create(config).withPlanning().build();\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle Management\n // ---------------------------------------------------------------------------\n\n async startup(): Promise<void> {\n return this.lifecycleManager.startup();\n }\n\n async shutdown(): Promise<void> {\n return this.lifecycleManager.shutdown();\n }\n\n async healthCheck(): Promise<HealthStatus> {\n return this.lifecycleManager.healthCheck();\n }\n\n get isReady(): boolean {\n return this.lifecycleManager.isReady;\n }\n\n get isShuttingDown(): boolean {\n return this.lifecycleManager.isShuttingDown;\n }\n\n // ---------------------------------------------------------------------------\n // Run & Stream - Delegation to ExecutionEngine\n // ---------------------------------------------------------------------------\n\n async run(prompt: string, options: AgentRunOptions = {}): Promise<AgentResult> {\n await this.ensureRuntime();\n return this.executionEngine.run(prompt, this.sessionId, this._runtime!, options);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async stream(\n params: { messages: Array<{ role: string; content: unknown }> },\n options: AgentRunOptions = {},\n ): Promise<any> {\n await this.ensureRuntime();\n return this.executionEngine.stream(params, this.sessionId, this._runtime!, options);\n }\n\n // ---------------------------------------------------------------------------\n // Cleanup\n // ---------------------------------------------------------------------------\n\n async dispose(): Promise<void> {\n try {\n await this.lifecycleManager.shutdown();\n } catch {\n // Continue with cleanup even if shutdown fails\n }\n \n try {\n await this.config.telemetry?.flush();\n } catch {\n // Continue with cleanup even if telemetry flush fails\n }\n\n try {\n await this.pluginManager.dispose();\n } finally {\n try {\n if (this.config.mcp) await this.config.mcp.closeAll();\n } finally {\n this.eventBus.removeAllListeners();\n }\n }\n }\n}","// =============================================================================\n// AgentNode — Wraps a Agent or nested AgentGraph for graph execution\n// =============================================================================\n\nimport type { AgentConfig } from \"../types.js\";\nimport type { GraphConfig } from \"../domain/graph.schema.js\";\nimport type { SharedContext } from \"./shared-context.js\";\nimport type { AgentGraph } from \"./agent-graph.js\";\nimport { Agent } from \"../agent/agent.js\";\n\nexport interface AgentNodeConfig {\n id: string;\n type: \"agent\" | \"graph\";\n agentConfig?: AgentConfig;\n graph?: AgentGraph;\n overrides?: Partial<GraphConfig>;\n}\n\nexport interface NodeResult {\n nodeId: string;\n output: string;\n tokenUsage?: { input: number; output: number };\n durationMs: number;\n}\n\nexport class AgentNode {\n readonly id: string;\n readonly type: \"agent\" | \"graph\";\n private readonly config: AgentNodeConfig;\n\n constructor(config: AgentNodeConfig) {\n this.id = config.id;\n this.type = config.type;\n this.config = config;\n }\n\n async run(prompt: string, sharedContext: SharedContext): Promise<NodeResult> {\n const start = Date.now();\n\n if (this.config.type === \"graph\" && this.config.graph) {\n const graphResult = await this.config.graph.run(prompt);\n const result: NodeResult = {\n nodeId: this.id,\n output: graphResult.output,\n tokenUsage: graphResult.totalTokenUsage,\n durationMs: Date.now() - start,\n };\n await sharedContext.setNodeResult(this.id, result.output);\n return result;\n }\n\n if (!this.config.agentConfig) {\n throw new Error(`Node \"${this.id}\" has no agentConfig or graph`);\n }\n\n const agent = Agent.minimal(this.config.agentConfig);\n try {\n const agentResult = await agent.run(prompt);\n\n const result: NodeResult = {\n nodeId: this.id,\n output: agentResult.text,\n durationMs: Date.now() - start,\n };\n await sharedContext.setNodeResult(this.id, result.output);\n return result;\n } finally {\n await agent.dispose();\n }\n }\n}\n","// =============================================================================\n// AgentGraph — Declarative agent graph with builder API\n// =============================================================================\n\nimport { GraphConfigSchema } from \"../domain/graph.schema.js\";\nimport type { GraphConfig, GraphResult, GraphStreamEvent } from \"../domain/graph.schema.js\";\nimport type { AgentConfig } from \"../types.js\";\nimport type { ConsensusPort } from \"../ports/consensus.port.js\";\nimport type { FilesystemPort } from \"../ports/filesystem.port.js\";\nimport type { TelemetryPort } from \"../ports/telemetry.port.js\";\nimport type { EventBus } from \"../agent/event-bus.js\";\nimport { AbstractBuilder } from \"../utils/abstract-builder.js\";\nimport { AgentNode } from \"./agent-node.js\";\nimport { GraphExecutor } from \"./graph-executor.js\";\nimport { SharedContext } from \"./shared-context.js\";\nimport { VirtualFilesystem } from \"../adapters/filesystem/virtual-fs.adapter.js\";\nimport type { GraphDescriptor } from \"../ports/graph-visualization.port.js\";\nimport { AsciiGraphAdapter } from \"../adapters/graph-visualization/ascii-graph.adapter.js\";\nimport { MermaidGraphAdapter } from \"../adapters/graph-visualization/mermaid-graph.adapter.js\";\n\nexport class AgentGraph {\n constructor(\n private readonly nodes: Map<string, AgentNode>,\n private readonly edges: Map<string, string[]>,\n private readonly forks: Map<\n string,\n { nodes: AgentNode[]; consensus?: ConsensusPort }\n >,\n private readonly config: GraphConfig,\n private readonly fs: FilesystemPort,\n private readonly eventBus?: EventBus,\n private readonly telemetry?: TelemetryPort,\n ) {}\n\n getNodes(): ReadonlyMap<string, AgentNode> {\n return this.nodes;\n }\n\n getEdges(): ReadonlyMap<string, readonly string[]> {\n return this.edges;\n }\n\n getForks(): ReadonlyMap<string, { nodes: readonly AgentNode[]; consensus?: ConsensusPort }> {\n return this.forks;\n }\n\n describe(): GraphDescriptor {\n const nodes = [...this.nodes.values()].map((n) => ({\n id: n.id,\n type: n.type,\n }));\n const edges: GraphDescriptor[\"edges\"] = [];\n for (const [to, sources] of this.edges) {\n for (const from of sources) {\n edges.push({ from, to });\n }\n }\n const forks = [...this.forks.entries()].map(([id, f]) => ({\n id,\n nodeIds: f.nodes.map((n) => n.id),\n }));\n return { nodes, edges, forks };\n }\n\n visualize(format: \"ascii\" | \"mermaid\" = \"ascii\"): string {\n const descriptor = this.describe();\n if (format === \"mermaid\") {\n return new MermaidGraphAdapter().toMermaid(descriptor);\n }\n return new AsciiGraphAdapter().toAscii(descriptor);\n }\n\n static create(config?: Partial<GraphConfig>): AgentGraphBuilder {\n return new AgentGraphBuilder(config);\n }\n\n async run(prompt: string): Promise<GraphResult> {\n const sharedContext = new SharedContext(this.fs);\n const executor = new GraphExecutor(\n this.nodes,\n this.edges,\n this.forks,\n this.config,\n sharedContext,\n this.eventBus,\n this.telemetry,\n );\n return executor.execute(prompt);\n }\n\n async *stream(prompt: string): AsyncGenerator<GraphStreamEvent> {\n const sharedContext = new SharedContext(this.fs);\n const executor = new GraphExecutor(\n this.nodes,\n this.edges,\n this.forks,\n this.config,\n sharedContext,\n this.eventBus,\n this.telemetry,\n );\n yield* executor.stream(prompt);\n }\n}\n\nexport class AgentGraphBuilder extends AbstractBuilder<AgentGraph> {\n private readonly nodeMap = new Map<string, AgentNode>();\n private readonly edgeMap = new Map<string, string[]>();\n private readonly forkMap = new Map<\n string,\n { nodes: AgentNode[]; consensus?: ConsensusPort }\n >();\n private readonly config: GraphConfig;\n private fs: FilesystemPort | undefined;\n private eventBus: EventBus | undefined;\n private telemetryAdapter: TelemetryPort | undefined;\n\n constructor(config?: Partial<GraphConfig>) {\n super();\n this.config = GraphConfigSchema.parse(config ?? {});\n }\n\n node(id: string, config: AgentConfig): this {\n if (this.nodeMap.has(id)) {\n throw new Error(`Node \"${id}\" already exists`);\n }\n this.nodeMap.set(\n id,\n new AgentNode({ id, type: \"agent\", agentConfig: config }),\n );\n return this;\n }\n\n edge(from: string, to: string): this {\n const deps = this.edgeMap.get(to) ?? [];\n deps.push(from);\n this.edgeMap.set(to, deps);\n return this;\n }\n\n fork(id: string, configs: AgentConfig[]): this {\n if (configs.length < 2) {\n throw new Error(`Fork \"${id}\" requires at least 2 configs`);\n }\n if (this.nodeMap.has(id) || this.forkMap.has(id)) {\n throw new Error(`Node \"${id}\" already exists`);\n }\n const forkNodes = configs.map(\n (cfg, i) =>\n new AgentNode({\n id: `${id}__fork_${i}`,\n type: \"agent\",\n agentConfig: cfg,\n }),\n );\n // Register a placeholder node for the fork so edges can reference it\n this.nodeMap.set(\n id,\n new AgentNode({ id, type: \"agent\" }),\n );\n this.forkMap.set(id, { nodes: forkNodes });\n return this;\n }\n\n consensus(forkId: string, strategy: ConsensusPort): this {\n const fork = this.forkMap.get(forkId);\n if (!fork) {\n throw new Error(\n `Cannot set consensus: \"${forkId}\" is not a fork node`,\n );\n }\n fork.consensus = strategy;\n return this;\n }\n\n withFilesystem(fs: FilesystemPort): this {\n this.fs = fs;\n return this;\n }\n\n withEventBus(eventBus: EventBus): this {\n this.eventBus = eventBus;\n return this;\n }\n\n withTelemetry(adapter: TelemetryPort): this {\n this.telemetryAdapter = adapter;\n return this;\n }\n\n protected validate(): void {\n this.validateEdges();\n this.validateNoCycles();\n }\n\n protected construct(): AgentGraph {\n return new AgentGraph(\n this.nodeMap,\n this.edgeMap,\n this.forkMap,\n this.config,\n this.fs ?? new VirtualFilesystem(),\n this.eventBus,\n this.telemetryAdapter,\n );\n }\n\n private validateEdges(): void {\n for (const [to, deps] of this.edgeMap) {\n if (!this.nodeMap.has(to)) {\n throw new Error(`Edge target \"${to}\" does not exist`);\n }\n for (const from of deps) {\n if (!this.nodeMap.has(from)) {\n throw new Error(`Edge source \"${from}\" does not exist`);\n }\n }\n }\n }\n\n private validateNoCycles(): void {\n const visited = new Set<string>();\n const stack = new Set<string>();\n\n const visit = (nodeId: string): void => {\n if (stack.has(nodeId)) {\n throw new Error(`Cycle detected involving node \"${nodeId}\"`);\n }\n if (visited.has(nodeId)) return;\n stack.add(nodeId);\n const deps = this.edgeMap.get(nodeId) ?? [];\n for (const dep of deps) {\n visit(dep);\n }\n stack.delete(nodeId);\n visited.add(nodeId);\n };\n\n for (const nodeId of this.nodeMap.keys()) {\n visit(nodeId);\n }\n }\n}\n","// =============================================================================\n// REST API — Simple path-based router (zero dependencies)\n// =============================================================================\n\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nexport type RouteHandler = (\n req: IncomingMessage,\n res: ServerResponse,\n params: Record<string, string>,\n) => void | Promise<void>;\n\ninterface Route {\n method: string;\n path: string;\n handler: RouteHandler;\n}\n\nexport class Router {\n private readonly routes: Route[] = [];\n\n get(path: string, handler: RouteHandler): void {\n this.routes.push({ method: \"GET\", path, handler });\n }\n\n post(path: string, handler: RouteHandler): void {\n this.routes.push({ method: \"POST\", path, handler });\n }\n\n options(path: string, handler: RouteHandler): void {\n this.routes.push({ method: \"OPTIONS\", path, handler });\n }\n\n resolve(\n method: string,\n pathname: string,\n ): { handler: RouteHandler; params: Record<string, string> } | null {\n for (const route of this.routes) {\n if (route.method !== method) continue;\n const params = matchPath(route.path, pathname);\n if (params !== null) {\n return { handler: route.handler, params };\n }\n }\n return null;\n }\n}\n\n/** Simple path matcher supporting exact matches. */\nfunction matchPath(\n pattern: string,\n pathname: string,\n): Record<string, string> | null {\n if (pattern === pathname) return {};\n\n const patternParts = pattern.split(\"/\");\n const pathParts = pathname.split(\"/\");\n if (patternParts.length !== pathParts.length) return null;\n\n const params: Record<string, string> = {};\n for (let i = 0; i < patternParts.length; i++) {\n const pp = patternParts[i];\n if (pp.startsWith(\":\")) {\n params[pp.slice(1)] = pathParts[i];\n } else if (pp !== pathParts[i]) {\n return null;\n }\n }\n return params;\n}\n\n// ---------------------------------------------------------------------------\n// HTTP helpers\n// ---------------------------------------------------------------------------\n\nconst MAX_BODY_BYTES = 1_048_576; // 1 MB\n\nexport function parseBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on(\"data\", (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY_BYTES) {\n req.destroy();\n reject(new Error(\"Request body too large (max 1MB)\"));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf-8\")));\n req.on(\"error\", reject);\n });\n}\n\nexport function sendJson(\n res: ServerResponse,\n status: number,\n data: unknown,\n): void {\n const body = JSON.stringify(data);\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\n res.end(body);\n}\n\nexport function sendError(\n res: ServerResponse,\n code: number,\n message: string,\n): void {\n sendJson(res, code, { error: { code, message } });\n}\n","// =============================================================================\n// REST API — GaussServer (zero-dependency HTTP server using node:http)\n// =============================================================================\n\nimport { createServer, type Server, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { ServerOptions } from \"./types.js\";\nimport { Router, sendError, sendJson } from \"./router.js\";\nimport {\n handleHealth,\n handleInfo,\n handleRun,\n handleStream,\n handleGraphRun,\n handleAgentHealth,\n} from \"./handlers.js\";\nimport { Agent } from \"../agent/agent.js\";\n\nexport class GaussServer {\n private readonly options: Required<ServerOptions>;\n private readonly router: Router;\n private server: Server | null = null;\n private agent?: Agent;\n\n constructor(options?: ServerOptions, agent?: Agent) {\n this.options = {\n port: options?.port ?? 3456,\n apiKey: options?.apiKey ?? \"\",\n defaultProvider: options?.defaultProvider ?? \"openai\",\n defaultModel: options?.defaultModel ?? \"gpt-5.2\",\n cors: options?.cors ?? true,\n };\n\n this.agent = agent;\n this.router = new Router();\n this.registerRoutes();\n }\n\n private registerRoutes(): void {\n const opts = this.options;\n\n // Public endpoints\n this.router.get(\"/api/health\", handleHealth);\n this.router.get(\"/api/info\", handleInfo(opts));\n \n // Agent health endpoint (if agent is provided)\n if (this.agent) {\n this.router.get(\"/health\", handleAgentHealth(this.agent));\n }\n\n // Protected endpoints\n this.router.post(\"/api/run\", handleRun(opts));\n this.router.post(\"/api/stream\", handleStream(opts));\n this.router.post(\"/api/graph/run\", handleGraphRun(opts));\n\n // CORS preflight for all API routes\n if (opts.cors) {\n const corsHandler = (_req: IncomingMessage, res: ServerResponse) => {\n res.writeHead(204);\n res.end();\n };\n this.router.options(\"/api/run\", corsHandler);\n this.router.options(\"/api/stream\", corsHandler);\n this.router.options(\"/api/graph/run\", corsHandler);\n this.router.options(\"/api/health\", corsHandler);\n this.router.options(\"/api/info\", corsHandler);\n if (this.agent) {\n this.router.options(\"/health\", corsHandler);\n }\n }\n }\n\n private addCorsHeaders(res: ServerResponse): void {\n if (!this.options.cors) return;\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, Authorization\");\n }\n\n private authenticate(req: IncomingMessage, pathname: string): boolean {\n // Health endpoints are always public\n if (pathname === \"/api/health\" || pathname === \"/health\") return true;\n // If no API key configured, auth is disabled\n if (!this.options.apiKey) return true;\n\n const authHeader = req.headers.authorization;\n if (!authHeader) return false;\n\n const [scheme, token] = authHeader.split(\" \");\n return scheme === \"Bearer\" && token === this.options.apiKey;\n }\n\n private handleRequest = async (\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void> => {\n this.addCorsHeaders(res);\n\n const url = new URL(req.url ?? \"/\", `http://${req.headers.host ?? \"localhost\"}`);\n const method = req.method?.toUpperCase() ?? \"GET\";\n const pathname = url.pathname;\n\n // Auth check\n if (!this.authenticate(req, pathname)) {\n return sendError(res, 401, \"Unauthorized: invalid or missing API key\");\n }\n\n // Route\n const match = this.router.resolve(method, pathname);\n if (!match) {\n return sendError(res, 404, `Not found: ${method} ${pathname}`);\n }\n\n try {\n await match.handler(req, res, match.params);\n } catch (err) {\n if (!res.headersSent) {\n sendError(res, 500, err instanceof Error ? err.message : String(err));\n }\n }\n };\n\n async listen(port?: number): Promise<void> {\n if (this.agent) {\n await this.agent.startup();\n }\n const p = port ?? this.options.port;\n await new Promise<void>((resolve, reject) => {\n this.server = createServer(this.handleRequest);\n this.server.on(\"error\", reject);\n this.server.listen(p, () => resolve());\n });\n }\n\n async close(): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n if (!this.server) return resolve();\n this.server.close((err) => (err ? reject(err) : resolve()));\n });\n if (this.agent) {\n await this.agent.shutdown();\n }\n }\n}\n","// =============================================================================\n// REST API — Request Handlers\n// =============================================================================\n\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type {\n ServerOptions,\n RunRequest,\n GraphRunRequest,\n HealthResponse,\n InfoResponse,\n} from \"./types.js\";\nimport { parseBody, sendJson, sendError } from \"./router.js\";\nimport { Agent } from \"../agent/agent.js\";\nimport { AgentGraph } from \"../graph/agent-graph.js\";\nimport type { LanguageModel } from \"../core/llm/index.js\";\n\nconst VERSION = \"0.1.0\";\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n// ---------------------------------------------------------------------------\n// Provider resolution (same dynamic import pattern as CLI)\n// ---------------------------------------------------------------------------\n\nasync function resolveModel(\n provider: string,\n modelId: string,\n requestApiKey?: string,\n): Promise<LanguageModel> {\n const { createModel, isValidProvider } = await import(\n \"../cli/providers.js\"\n );\n if (!isValidProvider(provider)) {\n throw new Error(`Unsupported provider: \"${provider}\"`);\n }\n\n const { envVarName } = await import(\"../cli/config.js\");\n const apiKey = requestApiKey ?? process.env[envVarName(provider)] ?? \"\";\n return createModel(provider as Parameters<typeof createModel>[0], apiKey, modelId);\n}\n\n// ---------------------------------------------------------------------------\n// Health\n// ---------------------------------------------------------------------------\n\nexport function handleHealth(\n _req: IncomingMessage,\n res: ServerResponse,\n): void {\n const body: HealthResponse = { status: \"ok\", version: VERSION };\n sendJson(res, 200, body);\n}\n\n// ---------------------------------------------------------------------------\n// Info\n// ---------------------------------------------------------------------------\n\nexport function handleInfo(\n options: ServerOptions,\n): (_req: IncomingMessage, res: ServerResponse) => void {\n return (_req, res) => {\n const body: InfoResponse = {\n version: VERSION,\n defaultProvider: options.defaultProvider ?? \"openai\",\n defaultModel: options.defaultModel ?? \"gpt-5.2\",\n endpoints: [\n \"POST /api/run\",\n \"POST /api/stream\",\n \"POST /api/graph/run\",\n \"GET /api/health\",\n \"GET /api/info\",\n ],\n };\n sendJson(res, 200, body);\n };\n}\n\n// ---------------------------------------------------------------------------\n// GET /health (Agent Health Check)\n// ---------------------------------------------------------------------------\n\nexport function handleAgentHealth(\n agent: Agent,\n): (_req: IncomingMessage, res: ServerResponse) => Promise<void> {\n return async (_req, res) => {\n try {\n const healthStatus = await agent.healthCheck();\n const statusCode = healthStatus.healthy ? 200 : 503;\n sendJson(res, statusCode, healthStatus);\n } catch (err) {\n sendError(res, 500, errorMessage(err));\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// POST /api/run\n// ---------------------------------------------------------------------------\n\nexport function handleRun(\n options: ServerOptions,\n): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\n return async (req, res) => {\n let body: RunRequest;\n try {\n const raw = await parseBody(req);\n body = JSON.parse(raw) as RunRequest;\n } catch {\n return sendError(res, 400, \"Invalid JSON body\");\n }\n\n if (!body.prompt || typeof body.prompt !== \"string\") {\n return sendError(res, 400, \"Missing required field: prompt\");\n }\n\n const provider = body.provider ?? options.defaultProvider ?? \"openai\";\n const modelId = body.model ?? options.defaultModel ?? \"gpt-5.2\";\n\n let model: LanguageModel;\n try {\n model = await resolveModel(provider, modelId, body.apiKey);\n } catch (err) {\n return sendError(res, 400, errorMessage(err));\n }\n\n const start = Date.now();\n const agent = Agent.auto({\n instructions: body.instructions ?? \"You are a helpful assistant.\",\n model,\n maxSteps: body.maxSteps ?? 10,\n });\n\n try {\n const result = await agent.run(body.prompt);\n const duration = Date.now() - start;\n\n sendJson(res, 200, {\n text: result.text,\n sessionId: result.sessionId,\n steps: result.steps.length,\n duration,\n });\n } catch (err) {\n return sendError(res, 500, errorMessage(err));\n } finally {\n await agent.dispose();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// POST /api/stream\n// ---------------------------------------------------------------------------\n\nexport function handleStream(\n options: ServerOptions,\n): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\n return async (req, res) => {\n let body: RunRequest;\n try {\n const raw = await parseBody(req);\n body = JSON.parse(raw) as RunRequest;\n } catch {\n return sendError(res, 400, \"Invalid JSON body\");\n }\n\n if (!body.prompt || typeof body.prompt !== \"string\") {\n return sendError(res, 400, \"Missing required field: prompt\");\n }\n\n const provider = body.provider ?? options.defaultProvider ?? \"openai\";\n const modelId = body.model ?? options.defaultModel ?? \"gpt-5.2\";\n\n let model: LanguageModel;\n try {\n model = await resolveModel(provider, modelId, body.apiKey);\n } catch (err) {\n return sendError(res, 400, errorMessage(err));\n }\n\n // SSE headers\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n\n const agent = Agent.auto({\n instructions: body.instructions ?? \"You are a helpful assistant.\",\n model,\n maxSteps: body.maxSteps ?? 10,\n });\n\n try {\n const streamResult = await agent.stream({\n messages: [{ role: \"user\", content: body.prompt }],\n });\n\n // Consume the text stream\n const reader = streamResult.textStream.getReader();\n const chunks: string[] = [];\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n chunks.push(value);\n const event = JSON.stringify({ type: \"token\", content: value });\n res.write(`data: ${event}\\n\\n`);\n }\n\n const fullText = chunks.join(\"\");\n const doneEvent = JSON.stringify({\n type: \"done\",\n text: fullText,\n sessionId: agent.sessionId,\n });\n res.write(`data: ${doneEvent}\\n\\n`);\n res.end();\n } catch (err) {\n const errEvent = JSON.stringify({\n type: \"error\",\n error: errorMessage(err),\n });\n res.write(`data: ${errEvent}\\n\\n`);\n res.end();\n } finally {\n await agent.dispose();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// POST /api/graph/run\n// ---------------------------------------------------------------------------\n\nexport function handleGraphRun(\n options: ServerOptions,\n): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\n return async (req, res) => {\n let body: GraphRunRequest;\n try {\n const raw = await parseBody(req);\n body = JSON.parse(raw) as GraphRunRequest;\n } catch {\n return sendError(res, 400, \"Invalid JSON body\");\n }\n\n if (!body.prompt || typeof body.prompt !== \"string\") {\n return sendError(res, 400, \"Missing required field: prompt\");\n }\n if (!body.nodes || !Array.isArray(body.nodes) || body.nodes.length === 0) {\n return sendError(res, 400, \"Missing required field: nodes\");\n }\n\n const defaultProvider = body.provider ?? options.defaultProvider ?? \"openai\";\n const defaultModelId = body.model ?? options.defaultModel ?? \"gpt-5.2\";\n\n const start = Date.now();\n try {\n const builder = AgentGraph.create();\n\n for (const nodeDef of body.nodes) {\n const nodeProvider = nodeDef.provider ?? defaultProvider;\n const nodeModelId = nodeDef.model ?? defaultModelId;\n const model = await resolveModel(nodeProvider, nodeModelId, body.apiKey);\n builder.node(nodeDef.id, {\n instructions: nodeDef.instructions,\n model,\n });\n }\n\n if (body.edges) {\n for (const edge of body.edges) {\n builder.edge(edge.from, edge.to);\n }\n }\n\n const graph = builder.build();\n const result = await graph.run(body.prompt);\n const duration = Date.now() - start;\n\n sendJson(res, 200, {\n results: Object.fromEntries(\n Object.entries(result.nodeResults).map(([k, v]) => [k, v.output]),\n ),\n duration,\n });\n } catch (err) {\n return sendError(res, 500, errorMessage(err));\n }\n };\n}\n"]}
|