@agntk/agent-harness 0.1.4 → 0.1.6

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.
Files changed (178) hide show
  1. package/README.md +104 -43
  2. package/dist/{analytics-RPT73WNM.js → analytics-L24W3B7U.js} +1 -2
  3. package/dist/auto-processor-QIRUOGEI.js +12 -0
  4. package/dist/{chunk-UPLBF4RZ.js → chunk-2UVWCTAY.js} +2 -2
  5. package/dist/{chunk-CSL3ERUI.js → chunk-4P6TRFPZ.js} +3 -3
  6. package/dist/chunk-4P6TRFPZ.js.map +1 -0
  7. package/dist/{chunk-4CWAGBNS.js → chunk-4TQQZILG.js} +73 -3
  8. package/dist/chunk-4TQQZILG.js.map +1 -0
  9. package/dist/{chunk-DA7IKHC4.js → chunk-5CO5JTYT.js} +2 -2
  10. package/dist/chunk-5CO5JTYT.js.map +1 -0
  11. package/dist/{chunk-A7BJPQQ6.js → chunk-5O5OGOOQ.js} +2 -2
  12. package/dist/{chunk-UWQTZMNI.js → chunk-7GZ4D6V6.js} +2 -2
  13. package/dist/{chunk-FLZU44SV.js → chunk-AN6Y4MDD.js} +6 -6
  14. package/dist/{chunk-4FDUOGSZ.js → chunk-D7AWV24Z.js} +3 -3
  15. package/dist/{chunk-CHJ5GNZC.js → chunk-EC42HQQH.js} +2 -2
  16. package/dist/{chunk-YIJY5DBV.js → chunk-KLYMGWQJ.js} +4 -4
  17. package/dist/chunk-KLYMGWQJ.js.map +1 -0
  18. package/dist/{chunk-YUFNYN2H.js → chunk-M62KLIEK.js} +4 -4
  19. package/dist/chunk-M62KLIEK.js.map +1 -0
  20. package/dist/{chunk-GJNNR2RA.js → chunk-M6PDMK2O.js} +3 -3
  21. package/dist/{chunk-M7NXUK55.js → chunk-NVC2WY4K.js} +2 -2
  22. package/dist/{chunk-XTBKL5BI.js → chunk-PMFAYKBD.js} +2 -2
  23. package/dist/chunk-PMFAYKBD.js.map +1 -0
  24. package/dist/{chunk-274RV3YO.js → chunk-QMOIVORH.js} +3 -3
  25. package/dist/chunk-QMOIVORH.js.map +1 -0
  26. package/dist/{chunk-RY3ZFII7.js → chunk-SEHAQTBO.js} +6 -6
  27. package/dist/{chunk-MPZ3BPUI.js → chunk-UMXPOYZR.js} +4 -4
  28. package/dist/{chunk-W4T7PGI2.js → chunk-UXCHAS3Z.js} +4 -4
  29. package/dist/cli/index.js +153 -167
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/config-PYSS3QY6.js +12 -0
  32. package/dist/context-loader-RSXXFW5R.js +12 -0
  33. package/dist/{conversation-QDEIDQPH.js → conversation-TBTFIJVU.js} +6 -7
  34. package/dist/{cost-tracker-RS3W7SVY.js → cost-tracker-NZRZEHVA.js} +1 -2
  35. package/dist/{delegate-VJCJLYEK.js → delegate-3KJAL4NZ.js} +7 -8
  36. package/dist/{emotional-state-VQVRA6ED.js → emotional-state-IN4ZUL2Q.js} +1 -2
  37. package/dist/{emotional-state-VQVRA6ED.js.map → emotional-state-IN4ZUL2Q.js.map} +1 -1
  38. package/dist/{env-discovery-2BLVMAIM.js → env-discovery-PXBRE5FX.js} +1 -2
  39. package/dist/{env-discovery-2BLVMAIM.js.map → env-discovery-PXBRE5FX.js.map} +1 -1
  40. package/dist/{export-6GCYHEHQ.js → export-GYLWROMB.js} +3 -4
  41. package/dist/{export-6GCYHEHQ.js.map → export-GYLWROMB.js.map} +1 -1
  42. package/dist/graph-LEEO37L3.js +13 -0
  43. package/dist/{harness-WE4SLCML.js → harness-R5FKRICG.js} +8 -9
  44. package/dist/{health-NZ6WNIMV.js → health-HL2JYHIY.js} +1 -2
  45. package/dist/indexer-L5UC6J2V.js +15 -0
  46. package/dist/{instinct-learner-SRM72DHF.js → instinct-learner-QGAMIS3X.js} +5 -6
  47. package/dist/{intake-4M3HNU43.js → intake-SVJKFHTL.js} +5 -6
  48. package/dist/{intelligence-HJOCA4SJ.js → intelligence-XPV3MC5U.js} +10 -13
  49. package/dist/intelligence-XPV3MC5U.js.map +1 -0
  50. package/dist/{journal-WANJL3MI.js → journal-ITUMKT6U.js} +5 -6
  51. package/dist/{loader-C3TKIKZR.js → loader-27PLDCOJ.js} +3 -4
  52. package/dist/{mcp-WTQJJZAO.js → mcp-JSIUJJZV.js} +1 -2
  53. package/dist/{mcp-discovery-WPAQFL6S.js → mcp-discovery-DG3RQYLM.js} +1 -2
  54. package/dist/{mcp-discovery-WPAQFL6S.js.map → mcp-discovery-DG3RQYLM.js.map} +1 -1
  55. package/dist/{mcp-installer-6O2XXD3V.js → mcp-installer-X2TJ2S2G.js} +3 -4
  56. package/dist/{mcp-installer-6O2XXD3V.js.map → mcp-installer-X2TJ2S2G.js.map} +1 -1
  57. package/dist/{metrics-KXGNFAAB.js → metrics-2MNINXNQ.js} +1 -2
  58. package/dist/{primitive-registry-I6VTIR4W.js → primitive-registry-ZMGGXSO5.js} +3 -4
  59. package/dist/{primitive-registry-I6VTIR4W.js.map → primitive-registry-ZMGGXSO5.js.map} +1 -1
  60. package/dist/{project-discovery-C4UMD7JI.js → project-discovery-FQLAZKEM.js} +1 -2
  61. package/dist/project-discovery-FQLAZKEM.js.map +1 -0
  62. package/dist/{provider-SXPQZ74H.js → provider-HQY6SPZI.js} +1 -2
  63. package/dist/{rate-limiter-RLRVM325.js → rate-limiter-PH5DCVU4.js} +1 -2
  64. package/dist/{rule-engine-YGQ3RYZM.js → rule-engine-DM26S77N.js} +3 -4
  65. package/dist/{rule-engine-YGQ3RYZM.js.map → rule-engine-DM26S77N.js.map} +1 -1
  66. package/dist/{scaffold-A3VRRCBV.js → scaffold-2F36YVW6.js} +5 -6
  67. package/dist/{scaffold-A3VRRCBV.js.map → scaffold-2F36YVW6.js.map} +1 -1
  68. package/dist/{scheduler-XHHIVHRI.js → scheduler-Q7GB2KCW.js} +11 -12
  69. package/dist/{scheduler-XHHIVHRI.js.map → scheduler-Q7GB2KCW.js.map} +1 -1
  70. package/dist/{search-V3W5JMJG.js → search-6Y6NCOLQ.js} +3 -4
  71. package/dist/search-6Y6NCOLQ.js.map +1 -0
  72. package/dist/{semantic-search-2DTOO5UX.js → semantic-search-FN6FZIXI.js} +3 -4
  73. package/dist/semantic-search-FN6FZIXI.js.map +1 -0
  74. package/dist/{serve-DTQ3HENY.js → serve-MXRTP2HE.js} +10 -11
  75. package/dist/serve-MXRTP2HE.js.map +1 -0
  76. package/dist/{sessions-CZGVXKQE.js → sessions-G6SZZXWS.js} +1 -2
  77. package/dist/{sources-RW5DT56F.js → sources-7LDYO5GK.js} +1 -2
  78. package/dist/{starter-packs-76YUVHEU.js → starter-packs-OR7NI5NA.js} +1 -2
  79. package/dist/{starter-packs-76YUVHEU.js.map → starter-packs-OR7NI5NA.js.map} +1 -1
  80. package/dist/{state-GMXILIHW.js → state-25IQEC5C.js} +1 -2
  81. package/dist/{state-merge-NKO5FRBA.js → state-merge-E333OEIQ.js} +1 -2
  82. package/dist/{state-merge-NKO5FRBA.js.map → state-merge-E333OEIQ.js.map} +1 -1
  83. package/dist/{telemetry-UC6PBXC7.js → telemetry-RS2JZUZP.js} +4 -5
  84. package/dist/{tool-executor-MJ7IG7PQ.js → tool-executor-6I5PHQDY.js} +5 -6
  85. package/dist/{tools-DZ4KETET.js → tools-NDFJNVHK.js} +4 -5
  86. package/dist/{types-EW7AIB3R.js → types-NPJZAI72.js} +2 -3
  87. package/dist/{universal-installer-AAXXYM5A.js → universal-installer-LCAZHFZR.js} +91 -7
  88. package/dist/universal-installer-LCAZHFZR.js.map +1 -0
  89. package/dist/validator-LM7RZWSH.js +21 -0
  90. package/dist/{verification-gate-FYXUX6LH.js → verification-gate-2O6DF2B7.js} +3 -4
  91. package/dist/verification-gate-2O6DF2B7.js.map +1 -0
  92. package/dist/{versioning-Z3XNE2Q2.js → versioning-WEGF6KJG.js} +1 -2
  93. package/dist/versioning-WEGF6KJG.js.map +1 -0
  94. package/dist/{watcher-ISJC7YKL.js → watcher-GZWQSWZ6.js} +5 -6
  95. package/dist/{watcher-ISJC7YKL.js.map → watcher-GZWQSWZ6.js.map} +1 -1
  96. package/dist/{web-server-DD7ZOP46.js → web-server-2Y4CHD2W.js} +8 -9
  97. package/package.json +1 -9
  98. package/dist/agent-framework-K4GUIICH.js +0 -344
  99. package/dist/agent-framework-K4GUIICH.js.map +0 -1
  100. package/dist/auto-processor-OLE45UI3.js +0 -13
  101. package/dist/chunk-274RV3YO.js.map +0 -1
  102. package/dist/chunk-4CWAGBNS.js.map +0 -1
  103. package/dist/chunk-CSL3ERUI.js.map +0 -1
  104. package/dist/chunk-DA7IKHC4.js.map +0 -1
  105. package/dist/chunk-DGUM43GV.js +0 -11
  106. package/dist/chunk-FD55B3IO.js +0 -204
  107. package/dist/chunk-FD55B3IO.js.map +0 -1
  108. package/dist/chunk-GUJTBGVS.js +0 -2212
  109. package/dist/chunk-GUJTBGVS.js.map +0 -1
  110. package/dist/chunk-KFX54TQM.js +0 -165
  111. package/dist/chunk-KFX54TQM.js.map +0 -1
  112. package/dist/chunk-XTBKL5BI.js.map +0 -1
  113. package/dist/chunk-YIJY5DBV.js.map +0 -1
  114. package/dist/chunk-YUFNYN2H.js.map +0 -1
  115. package/dist/chunk-ZZJOFKAT.js +0 -13
  116. package/dist/config-WVMRUOCA.js +0 -13
  117. package/dist/context-loader-3ORBPMHJ.js +0 -13
  118. package/dist/graph-YUIPOSOO.js +0 -14
  119. package/dist/harness-LCHA3DWP.js +0 -10
  120. package/dist/index.d.ts +0 -3612
  121. package/dist/index.js +0 -13713
  122. package/dist/index.js.map +0 -1
  123. package/dist/indexer-LONANRRM.js +0 -16
  124. package/dist/intelligence-HJOCA4SJ.js.map +0 -1
  125. package/dist/project-discovery-C4UMD7JI.js.map +0 -1
  126. package/dist/provider-LQHQX7Z7.js +0 -26
  127. package/dist/search-V3W5JMJG.js.map +0 -1
  128. package/dist/semantic-search-2DTOO5UX.js.map +0 -1
  129. package/dist/serve-DTQ3HENY.js.map +0 -1
  130. package/dist/tools-DZ4KETET.js.map +0 -1
  131. package/dist/types-EW7AIB3R.js.map +0 -1
  132. package/dist/types-WGDLSPO6.js +0 -16
  133. package/dist/types-WGDLSPO6.js.map +0 -1
  134. package/dist/universal-installer-AAXXYM5A.js.map +0 -1
  135. package/dist/validator-7WXMDIHH.js +0 -22
  136. package/dist/validator-7WXMDIHH.js.map +0 -1
  137. package/dist/verification-gate-FYXUX6LH.js.map +0 -1
  138. package/dist/versioning-Z3XNE2Q2.js.map +0 -1
  139. package/dist/web-server-DD7ZOP46.js.map +0 -1
  140. /package/dist/{analytics-RPT73WNM.js.map → analytics-L24W3B7U.js.map} +0 -0
  141. /package/dist/{auto-processor-OLE45UI3.js.map → auto-processor-QIRUOGEI.js.map} +0 -0
  142. /package/dist/{chunk-UPLBF4RZ.js.map → chunk-2UVWCTAY.js.map} +0 -0
  143. /package/dist/{chunk-A7BJPQQ6.js.map → chunk-5O5OGOOQ.js.map} +0 -0
  144. /package/dist/{chunk-UWQTZMNI.js.map → chunk-7GZ4D6V6.js.map} +0 -0
  145. /package/dist/{chunk-FLZU44SV.js.map → chunk-AN6Y4MDD.js.map} +0 -0
  146. /package/dist/{chunk-4FDUOGSZ.js.map → chunk-D7AWV24Z.js.map} +0 -0
  147. /package/dist/{chunk-CHJ5GNZC.js.map → chunk-EC42HQQH.js.map} +0 -0
  148. /package/dist/{chunk-GJNNR2RA.js.map → chunk-M6PDMK2O.js.map} +0 -0
  149. /package/dist/{chunk-M7NXUK55.js.map → chunk-NVC2WY4K.js.map} +0 -0
  150. /package/dist/{chunk-RY3ZFII7.js.map → chunk-SEHAQTBO.js.map} +0 -0
  151. /package/dist/{chunk-MPZ3BPUI.js.map → chunk-UMXPOYZR.js.map} +0 -0
  152. /package/dist/{chunk-W4T7PGI2.js.map → chunk-UXCHAS3Z.js.map} +0 -0
  153. /package/dist/{chunk-DGUM43GV.js.map → config-PYSS3QY6.js.map} +0 -0
  154. /package/dist/{chunk-ZZJOFKAT.js.map → context-loader-RSXXFW5R.js.map} +0 -0
  155. /package/dist/{config-WVMRUOCA.js.map → conversation-TBTFIJVU.js.map} +0 -0
  156. /package/dist/{context-loader-3ORBPMHJ.js.map → cost-tracker-NZRZEHVA.js.map} +0 -0
  157. /package/dist/{conversation-QDEIDQPH.js.map → delegate-3KJAL4NZ.js.map} +0 -0
  158. /package/dist/{cost-tracker-RS3W7SVY.js.map → graph-LEEO37L3.js.map} +0 -0
  159. /package/dist/{delegate-VJCJLYEK.js.map → harness-R5FKRICG.js.map} +0 -0
  160. /package/dist/{graph-YUIPOSOO.js.map → health-HL2JYHIY.js.map} +0 -0
  161. /package/dist/{harness-LCHA3DWP.js.map → indexer-L5UC6J2V.js.map} +0 -0
  162. /package/dist/{harness-WE4SLCML.js.map → instinct-learner-QGAMIS3X.js.map} +0 -0
  163. /package/dist/{health-NZ6WNIMV.js.map → intake-SVJKFHTL.js.map} +0 -0
  164. /package/dist/{indexer-LONANRRM.js.map → journal-ITUMKT6U.js.map} +0 -0
  165. /package/dist/{instinct-learner-SRM72DHF.js.map → loader-27PLDCOJ.js.map} +0 -0
  166. /package/dist/{intake-4M3HNU43.js.map → mcp-JSIUJJZV.js.map} +0 -0
  167. /package/dist/{journal-WANJL3MI.js.map → metrics-2MNINXNQ.js.map} +0 -0
  168. /package/dist/{loader-C3TKIKZR.js.map → provider-HQY6SPZI.js.map} +0 -0
  169. /package/dist/{mcp-WTQJJZAO.js.map → rate-limiter-PH5DCVU4.js.map} +0 -0
  170. /package/dist/{metrics-KXGNFAAB.js.map → sessions-G6SZZXWS.js.map} +0 -0
  171. /package/dist/{provider-LQHQX7Z7.js.map → sources-7LDYO5GK.js.map} +0 -0
  172. /package/dist/{provider-SXPQZ74H.js.map → state-25IQEC5C.js.map} +0 -0
  173. /package/dist/{rate-limiter-RLRVM325.js.map → telemetry-RS2JZUZP.js.map} +0 -0
  174. /package/dist/{sessions-CZGVXKQE.js.map → tool-executor-6I5PHQDY.js.map} +0 -0
  175. /package/dist/{sources-RW5DT56F.js.map → tools-NDFJNVHK.js.map} +0 -0
  176. /package/dist/{state-GMXILIHW.js.map → types-NPJZAI72.js.map} +0 -0
  177. /package/dist/{telemetry-UC6PBXC7.js.map → validator-LM7RZWSH.js.map} +0 -0
  178. /package/dist/{tool-executor-MJ7IG7PQ.js.map → web-server-2Y4CHD2W.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/harness.ts"],"sourcesContent":["import { existsSync } from 'fs';\nimport { resolve } from 'path';\nimport { loadConfig } from './config.js';\nimport { log } from './logger.js';\nimport type {\n CreateHarnessOptions,\n HarnessConfig,\n HarnessAgent,\n HarnessHooks,\n AgentRunResult,\n AgentStreamResult,\n AgentState,\n} from './types.js';\nimport { getModel, generate, streamGenerateWithDetails } from '../llm/provider.js';\nimport { buildSystemPrompt } from '../runtime/context-loader.js';\nimport { loadState, saveState } from '../runtime/state.js';\nimport { createSessionId, writeSession, type SessionRecord } from '../runtime/sessions.js';\nimport { recordCost } from '../runtime/cost-tracker.js';\nimport { recordSuccess, recordFailure, recordBoot } from '../runtime/health.js';\nimport { checkGuardrails } from '../runtime/guardrails.js';\nimport { buildToolSet, type AIToolSet } from '../runtime/tool-executor.js';\nimport { createMcpManager, type McpManager } from '../runtime/mcp.js';\n\nexport function createHarness(options: CreateHarnessOptions): HarnessAgent {\n const dir = resolve(options.dir);\n\n if (!existsSync(dir)) {\n throw new Error(`Harness directory not found: ${dir}`);\n }\n\n const config = loadConfig(dir, options.config);\n\n // Apply model and provider overrides from options\n if (options.model) {\n config.model = { ...config.model, id: options.model };\n }\n if (options.provider) {\n config.model = { ...config.model, provider: options.provider };\n }\n\n const model = getModel(config, options.apiKey);\n const hooks: HarnessHooks = options.hooks ?? {};\n\n let state: AgentState;\n let systemPrompt: string;\n let booted = false;\n let toolSet: AIToolSet = {};\n let mcpManager: McpManager | undefined;\n\n const agent: HarnessAgent = {\n name: config.agent.name,\n config,\n\n async boot() {\n // Load state\n state = loadState(dir);\n const previousMode = state.mode;\n state.mode = 'active';\n state.last_interaction = new Date().toISOString();\n\n // Build system prompt from harness files\n const ctx = buildSystemPrompt(dir, config);\n systemPrompt = ctx.systemPrompt;\n\n // Connect to MCP servers and load their tools\n let mcpTools: AIToolSet = {};\n mcpManager = createMcpManager(config);\n if (mcpManager.hasServers()) {\n try {\n await mcpManager.connect();\n mcpTools = mcpManager.getTools();\n } catch (err) {\n log.warn(`MCP connection failed during boot: ${err instanceof Error ? err.message : String(err)}. Continuing without MCP tools.`);\n }\n }\n\n // Load tools and convert to AI SDK format (includes markdown + programmatic + MCP)\n toolSet = buildToolSet(dir, options.toolExecutor, mcpTools);\n const toolCount = Object.keys(toolSet).length;\n\n booted = true;\n\n log.info(\n `Booted \"${config.agent.name}\" | ` +\n `${ctx.budget.loaded_files.length} files loaded | ` +\n `~${ctx.budget.used_tokens} tokens used | ` +\n `${ctx.budget.remaining} remaining` +\n (toolCount > 0 ? ` | ${toolCount} tools` : ''),\n );\n\n for (const warning of ctx.warnings) {\n log.warn(warning);\n }\n\n // Lifecycle: onStateChange\n if (previousMode !== 'active' && hooks.onStateChange) {\n await hooks.onStateChange({ agent, previous: previousMode, current: 'active' });\n }\n\n // Record boot in health metrics\n try { recordBoot(dir); } catch { /* best-effort */ }\n\n // Lifecycle: onBoot\n if (hooks.onBoot) {\n await hooks.onBoot({ agent, config, state });\n }\n },\n\n async run(prompt: string): Promise<AgentRunResult> {\n if (!booted) await agent.boot();\n\n // Check guardrails (rate limits + budget) before LLM call\n const guard = checkGuardrails(dir, config);\n if (!guard.allowed) {\n const error = new Error(`Guardrail blocked: ${guard.reason}`);\n try { recordFailure(dir, error.message); } catch { /* best-effort */ }\n if (hooks.onError) {\n try { await hooks.onError({ agent, error, prompt }); } catch { /* best-effort */ }\n }\n throw error;\n }\n\n const sessionId = createSessionId();\n const started = new Date().toISOString();\n\n const hasTools = Object.keys(toolSet).length > 0;\n let result;\n try {\n result = await generate({\n model,\n system: systemPrompt,\n prompt,\n maxRetries: config.model.max_retries,\n timeoutMs: config.model.timeout_ms,\n ...(hasTools ? { tools: toolSet, maxToolSteps: options.toolExecutor?.maxToolCalls ?? 5 } : {}),\n });\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n try { recordFailure(dir, error.message); } catch { /* best-effort */ }\n if (hooks.onError) {\n try { await hooks.onError({ agent, error, prompt }); } catch { /* best-effort */ }\n }\n throw error;\n }\n\n const ended = new Date().toISOString();\n\n // Write session record\n const session: SessionRecord = {\n id: sessionId,\n started,\n ended,\n prompt,\n summary: result.text.slice(0, 200),\n tokens_used: result.usage.totalTokens,\n steps: result.steps,\n model_id: config.model.id,\n tool_calls: result.toolCalls.length > 0 ? result.toolCalls : undefined,\n };\n\n // Post-LLM recording — wrapped in try-catch so telemetry failures\n // never mask a successful LLM result\n try {\n writeSession(dir, session);\n } catch (err) {\n log.warn(`Failed to write session ${sessionId}: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n try {\n recordCost(dir, {\n model_id: config.model.id,\n provider: config.model.provider ?? 'openrouter',\n input_tokens: result.usage.inputTokens,\n output_tokens: result.usage.outputTokens,\n source: `run:${sessionId}`,\n });\n } catch (err) {\n log.warn(`Failed to record cost: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n try {\n recordSuccess(dir);\n } catch (err) {\n log.warn(`Failed to record health: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n try {\n state.last_interaction = ended;\n saveState(dir, state);\n } catch (err) {\n log.warn(`Failed to save state: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const runResult: AgentRunResult = {\n text: result.text,\n usage: result.usage,\n session_id: sessionId,\n steps: result.steps,\n toolCalls: result.toolCalls,\n };\n\n // Lifecycle: onSessionEnd — wrapped so hook errors don't lose the result\n if (hooks.onSessionEnd) {\n try {\n await hooks.onSessionEnd({ agent, sessionId, prompt, result: runResult });\n } catch (err) {\n log.warn(`onSessionEnd hook error: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return runResult;\n },\n\n stream(prompt: string): AgentStreamResult {\n const sessionId = createSessionId();\n\n // Deferred result — resolves after stream is fully consumed and recording completes\n let resolveResult: (r: AgentRunResult) => void;\n let rejectResult: (e: Error) => void;\n const resultPromise = new Promise<AgentRunResult>((res, rej) => {\n resolveResult = res;\n rejectResult = rej;\n });\n // Prevent unhandled rejection when error propagates via the generator throw path\n // and consumer doesn't explicitly await .result\n resultPromise.catch(() => {});\n\n async function* generateStream(): AsyncIterable<string> {\n if (!booted) await agent.boot();\n\n // Check guardrails (rate limits + budget) before LLM call\n const guard = checkGuardrails(dir, config);\n if (!guard.allowed) {\n const error = new Error(`Guardrail blocked: ${guard.reason}`);\n try { recordFailure(dir, error.message); } catch { /* best-effort */ }\n if (hooks.onError) {\n try { await hooks.onError({ agent, error, prompt }); } catch { /* best-effort */ }\n }\n rejectResult(error);\n throw error;\n }\n\n const started = new Date().toISOString();\n let fullText = '';\n\n const hasTools = Object.keys(toolSet).length > 0;\n\n let streamResult;\n try {\n streamResult = streamGenerateWithDetails({\n model,\n system: systemPrompt,\n prompt,\n maxRetries: config.model.max_retries,\n timeoutMs: config.model.timeout_ms,\n ...(hasTools ? { tools: toolSet, maxToolSteps: options.toolExecutor?.maxToolCalls ?? 5 } : {}),\n });\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n try { recordFailure(dir, error.message); } catch { /* best-effort */ }\n if (hooks.onError) {\n try { await hooks.onError({ agent, error, prompt }); } catch { /* best-effort */ }\n }\n rejectResult(error);\n throw error;\n }\n\n try {\n for await (const chunk of streamResult.textStream) {\n fullText += chunk;\n yield chunk;\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n try { recordFailure(dir, error.message); } catch { /* best-effort */ }\n if (hooks.onError) {\n try { await hooks.onError({ agent, error, prompt }); } catch { /* best-effort */ }\n }\n rejectResult(error);\n throw error;\n }\n\n // Await post-stream metadata — wrapped so failures don't crash the generator\n let usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n let steps = 1;\n let toolCalls: Array<{ toolName: string; args: Record<string, unknown>; result: unknown }> = [];\n try {\n [usage, steps, toolCalls] = await Promise.all([\n streamResult.usage,\n streamResult.steps,\n streamResult.toolCalls,\n ]);\n } catch (err) {\n log.warn(`Failed to resolve post-stream metadata: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const ended = new Date().toISOString();\n\n const session: SessionRecord = {\n id: sessionId,\n started,\n ended,\n prompt,\n summary: fullText.slice(0, 200),\n tokens_used: usage.totalTokens,\n steps,\n model_id: config.model.id,\n tool_calls: toolCalls.length > 0 ? toolCalls : undefined,\n };\n\n // Post-stream recording — wrapped so telemetry failures don't break the caller\n try {\n writeSession(dir, session);\n } catch (err) {\n log.warn(`Failed to write session ${sessionId}: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n try {\n recordCost(dir, {\n model_id: config.model.id,\n provider: config.model.provider ?? 'openrouter',\n input_tokens: usage.inputTokens,\n output_tokens: usage.outputTokens,\n source: `stream:${sessionId}`,\n });\n } catch (err) {\n log.warn(`Failed to record cost: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n try {\n recordSuccess(dir);\n } catch (err) {\n log.warn(`Failed to record health: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n try {\n state.last_interaction = ended;\n saveState(dir, state);\n } catch (err) {\n log.warn(`Failed to save state: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const runResult: AgentRunResult = {\n text: fullText,\n usage,\n session_id: sessionId,\n steps,\n toolCalls,\n };\n\n // Lifecycle: onSessionEnd\n if (hooks.onSessionEnd) {\n try {\n await hooks.onSessionEnd({ agent, sessionId, prompt, result: runResult });\n } catch (err) {\n log.warn(`onSessionEnd hook error: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n resolveResult(runResult);\n }\n\n return {\n textStream: generateStream(),\n result: resultPromise,\n };\n },\n\n async shutdown() {\n if (!booted) return;\n\n // Lifecycle: onShutdown — wrapped so hook errors don't prevent cleanup\n if (hooks.onShutdown) {\n try {\n await hooks.onShutdown({ agent, state });\n } catch (err) {\n log.warn(`onShutdown hook error: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // Close MCP server connections\n if (mcpManager) {\n try {\n await mcpManager.close();\n } catch (err) {\n log.warn(`MCP shutdown error: ${err instanceof Error ? err.message : String(err)}`);\n }\n mcpManager = undefined;\n }\n\n const previousMode = state.mode;\n state.mode = 'idle';\n try {\n saveState(dir, state);\n } catch (err) {\n log.warn(`Failed to save state during shutdown: ${err instanceof Error ? err.message : String(err)}`);\n }\n booted = false;\n\n // Lifecycle: onStateChange\n if (previousMode !== 'idle' && hooks.onStateChange) {\n try {\n await hooks.onStateChange({ agent, previous: previousMode, current: 'idle' });\n } catch (err) {\n log.warn(`onStateChange hook error: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n log.info(`Shutdown \"${config.agent.name}\"`);\n },\n\n getSystemPrompt() {\n return systemPrompt || '';\n },\n\n getState() {\n return state || loadState(dir);\n },\n };\n\n return agent;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AAsBjB,SAAS,cAAc,SAA6C;AACzE,QAAM,MAAM,QAAQ,QAAQ,GAAG;AAE/B,MAAI,CAAC,WAAW,GAAG,GAAG;AACpB,UAAM,IAAI,MAAM,gCAAgC,GAAG,EAAE;AAAA,EACvD;AAEA,QAAM,SAAS,WAAW,KAAK,QAAQ,MAAM;AAG7C,MAAI,QAAQ,OAAO;AACjB,WAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,IAAI,QAAQ,MAAM;AAAA,EACtD;AACA,MAAI,QAAQ,UAAU;AACpB,WAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,UAAU,QAAQ,SAAS;AAAA,EAC/D;AAEA,QAAM,QAAQ,SAAS,QAAQ,QAAQ,MAAM;AAC7C,QAAM,QAAsB,QAAQ,SAAS,CAAC;AAE9C,MAAI;AACJ,MAAI;AACJ,MAAI,SAAS;AACb,MAAI,UAAqB,CAAC;AAC1B,MAAI;AAEJ,QAAM,QAAsB;AAAA,IAC1B,MAAM,OAAO,MAAM;AAAA,IACnB;AAAA,IAEA,MAAM,OAAO;AAEX,cAAQ,UAAU,GAAG;AACrB,YAAM,eAAe,MAAM;AAC3B,YAAM,OAAO;AACb,YAAM,oBAAmB,oBAAI,KAAK,GAAE,YAAY;AAGhD,YAAM,MAAM,kBAAkB,KAAK,MAAM;AACzC,qBAAe,IAAI;AAGnB,UAAI,WAAsB,CAAC;AAC3B,mBAAa,iBAAiB,MAAM;AACpC,UAAI,WAAW,WAAW,GAAG;AAC3B,YAAI;AACF,gBAAM,WAAW,QAAQ;AACzB,qBAAW,WAAW,SAAS;AAAA,QACjC,SAAS,KAAK;AACZ,cAAI,KAAK,sCAAsC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,iCAAiC;AAAA,QAClI;AAAA,MACF;AAGA,gBAAU,aAAa,KAAK,QAAQ,cAAc,QAAQ;AAC1D,YAAM,YAAY,OAAO,KAAK,OAAO,EAAE;AAEvC,eAAS;AAET,UAAI;AAAA,QACF,WAAW,OAAO,MAAM,IAAI,OACzB,IAAI,OAAO,aAAa,MAAM,oBAC7B,IAAI,OAAO,WAAW,kBACvB,IAAI,OAAO,SAAS,gBACtB,YAAY,IAAI,MAAM,SAAS,WAAW;AAAA,MAC7C;AAEA,iBAAW,WAAW,IAAI,UAAU;AAClC,YAAI,KAAK,OAAO;AAAA,MAClB;AAGA,UAAI,iBAAiB,YAAY,MAAM,eAAe;AACpD,cAAM,MAAM,cAAc,EAAE,OAAO,UAAU,cAAc,SAAS,SAAS,CAAC;AAAA,MAChF;AAGA,UAAI;AAAE,mBAAW,GAAG;AAAA,MAAG,QAAQ;AAAA,MAAoB;AAGnD,UAAI,MAAM,QAAQ;AAChB,cAAM,MAAM,OAAO,EAAE,OAAO,QAAQ,MAAM,CAAC;AAAA,MAC7C;AAAA,IACF;AAAA,IAEA,MAAM,IAAI,QAAyC;AACjD,UAAI,CAAC,OAAQ,OAAM,MAAM,KAAK;AAG9B,YAAM,QAAQ,gBAAgB,KAAK,MAAM;AACzC,UAAI,CAAC,MAAM,SAAS;AAClB,cAAM,QAAQ,IAAI,MAAM,sBAAsB,MAAM,MAAM,EAAE;AAC5D,YAAI;AAAE,wBAAc,KAAK,MAAM,OAAO;AAAA,QAAG,QAAQ;AAAA,QAAoB;AACrE,YAAI,MAAM,SAAS;AACjB,cAAI;AAAE,kBAAM,MAAM,QAAQ,EAAE,OAAO,OAAO,OAAO,CAAC;AAAA,UAAG,QAAQ;AAAA,UAAoB;AAAA,QACnF;AACA,cAAM;AAAA,MACR;AAEA,YAAM,YAAY,gBAAgB;AAClC,YAAM,WAAU,oBAAI,KAAK,GAAE,YAAY;AAEvC,YAAM,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS;AAC/C,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,SAAS;AAAA,UACtB;AAAA,UACA,QAAQ;AAAA,UACR;AAAA,UACA,YAAY,OAAO,MAAM;AAAA,UACzB,WAAW,OAAO,MAAM;AAAA,UACxB,GAAI,WAAW,EAAE,OAAO,SAAS,cAAc,QAAQ,cAAc,gBAAgB,EAAE,IAAI,CAAC;AAAA,QAC9F,CAAC;AAAA,MACH,SAAS,KAAK;AACZ,cAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,YAAI;AAAE,wBAAc,KAAK,MAAM,OAAO;AAAA,QAAG,QAAQ;AAAA,QAAoB;AACrE,YAAI,MAAM,SAAS;AACjB,cAAI;AAAE,kBAAM,MAAM,QAAQ,EAAE,OAAO,OAAO,OAAO,CAAC;AAAA,UAAG,QAAQ;AAAA,UAAoB;AAAA,QACnF;AACA,cAAM;AAAA,MACR;AAEA,YAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY;AAGrC,YAAM,UAAyB;AAAA,QAC7B,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,OAAO,KAAK,MAAM,GAAG,GAAG;AAAA,QACjC,aAAa,OAAO,MAAM;AAAA,QAC1B,OAAO,OAAO;AAAA,QACd,UAAU,OAAO,MAAM;AAAA,QACvB,YAAY,OAAO,UAAU,SAAS,IAAI,OAAO,YAAY;AAAA,MAC/D;AAIA,UAAI;AACF,qBAAa,KAAK,OAAO;AAAA,MAC3B,SAAS,KAAK;AACZ,YAAI,KAAK,2BAA2B,SAAS,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MACtG;AAEA,UAAI;AACF,mBAAW,KAAK;AAAA,UACd,UAAU,OAAO,MAAM;AAAA,UACvB,UAAU,OAAO,MAAM,YAAY;AAAA,UACnC,cAAc,OAAO,MAAM;AAAA,UAC3B,eAAe,OAAO,MAAM;AAAA,UAC5B,QAAQ,OAAO,SAAS;AAAA,QAC1B,CAAC;AAAA,MACH,SAAS,KAAK;AACZ,YAAI,KAAK,0BAA0B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MACvF;AAEA,UAAI;AACF,sBAAc,GAAG;AAAA,MACnB,SAAS,KAAK;AACZ,YAAI,KAAK,4BAA4B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MACzF;AAEA,UAAI;AACF,cAAM,mBAAmB;AACzB,kBAAU,KAAK,KAAK;AAAA,MACtB,SAAS,KAAK;AACZ,YAAI,KAAK,yBAAyB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MACtF;AAEA,YAAM,YAA4B;AAAA,QAChC,MAAM,OAAO;AAAA,QACb,OAAO,OAAO;AAAA,QACd,YAAY;AAAA,QACZ,OAAO,OAAO;AAAA,QACd,WAAW,OAAO;AAAA,MACpB;AAGA,UAAI,MAAM,cAAc;AACtB,YAAI;AACF,gBAAM,MAAM,aAAa,EAAE,OAAO,WAAW,QAAQ,QAAQ,UAAU,CAAC;AAAA,QAC1E,SAAS,KAAK;AACZ,cAAI,KAAK,4BAA4B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QACzF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,OAAO,QAAmC;AACxC,YAAM,YAAY,gBAAgB;AAGlC,UAAI;AACJ,UAAI;AACJ,YAAM,gBAAgB,IAAI,QAAwB,CAAC,KAAK,QAAQ;AAC9D,wBAAgB;AAChB,uBAAe;AAAA,MACjB,CAAC;AAGD,oBAAc,MAAM,MAAM;AAAA,MAAC,CAAC;AAE5B,sBAAgB,iBAAwC;AACtD,YAAI,CAAC,OAAQ,OAAM,MAAM,KAAK;AAG9B,cAAM,QAAQ,gBAAgB,KAAK,MAAM;AACzC,YAAI,CAAC,MAAM,SAAS;AAClB,gBAAM,QAAQ,IAAI,MAAM,sBAAsB,MAAM,MAAM,EAAE;AAC5D,cAAI;AAAE,0BAAc,KAAK,MAAM,OAAO;AAAA,UAAG,QAAQ;AAAA,UAAoB;AACrE,cAAI,MAAM,SAAS;AACjB,gBAAI;AAAE,oBAAM,MAAM,QAAQ,EAAE,OAAO,OAAO,OAAO,CAAC;AAAA,YAAG,QAAQ;AAAA,YAAoB;AAAA,UACnF;AACA,uBAAa,KAAK;AAClB,gBAAM;AAAA,QACR;AAEA,cAAM,WAAU,oBAAI,KAAK,GAAE,YAAY;AACvC,YAAI,WAAW;AAEf,cAAM,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS;AAE/C,YAAI;AACJ,YAAI;AACF,yBAAe,0BAA0B;AAAA,YACvC;AAAA,YACA,QAAQ;AAAA,YACR;AAAA,YACA,YAAY,OAAO,MAAM;AAAA,YACzB,WAAW,OAAO,MAAM;AAAA,YACxB,GAAI,WAAW,EAAE,OAAO,SAAS,cAAc,QAAQ,cAAc,gBAAgB,EAAE,IAAI,CAAC;AAAA,UAC9F,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,gBAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,cAAI;AAAE,0BAAc,KAAK,MAAM,OAAO;AAAA,UAAG,QAAQ;AAAA,UAAoB;AACrE,cAAI,MAAM,SAAS;AACjB,gBAAI;AAAE,oBAAM,MAAM,QAAQ,EAAE,OAAO,OAAO,OAAO,CAAC;AAAA,YAAG,QAAQ;AAAA,YAAoB;AAAA,UACnF;AACA,uBAAa,KAAK;AAClB,gBAAM;AAAA,QACR;AAEA,YAAI;AACF,2BAAiB,SAAS,aAAa,YAAY;AACjD,wBAAY;AACZ,kBAAM;AAAA,UACR;AAAA,QACF,SAAS,KAAK;AACZ,gBAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,cAAI;AAAE,0BAAc,KAAK,MAAM,OAAO;AAAA,UAAG,QAAQ;AAAA,UAAoB;AACrE,cAAI,MAAM,SAAS;AACjB,gBAAI;AAAE,oBAAM,MAAM,QAAQ,EAAE,OAAO,OAAO,OAAO,CAAC;AAAA,YAAG,QAAQ;AAAA,YAAoB;AAAA,UACnF;AACA,uBAAa,KAAK;AAClB,gBAAM;AAAA,QACR;AAGA,YAAI,QAAQ,EAAE,aAAa,GAAG,cAAc,GAAG,aAAa,EAAE;AAC9D,YAAI,QAAQ;AACZ,YAAI,YAAyF,CAAC;AAC9F,YAAI;AACF,WAAC,OAAO,OAAO,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,YAC5C,aAAa;AAAA,YACb,aAAa;AAAA,YACb,aAAa;AAAA,UACf,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,cAAI,KAAK,2CAA2C,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QACxG;AAEA,cAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY;AAErC,cAAM,UAAyB;AAAA,UAC7B,IAAI;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA,SAAS,SAAS,MAAM,GAAG,GAAG;AAAA,UAC9B,aAAa,MAAM;AAAA,UACnB;AAAA,UACA,UAAU,OAAO,MAAM;AAAA,UACvB,YAAY,UAAU,SAAS,IAAI,YAAY;AAAA,QACjD;AAGA,YAAI;AACF,uBAAa,KAAK,OAAO;AAAA,QAC3B,SAAS,KAAK;AACZ,cAAI,KAAK,2BAA2B,SAAS,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QACtG;AAEA,YAAI;AACF,qBAAW,KAAK;AAAA,YACd,UAAU,OAAO,MAAM;AAAA,YACvB,UAAU,OAAO,MAAM,YAAY;AAAA,YACnC,cAAc,MAAM;AAAA,YACpB,eAAe,MAAM;AAAA,YACrB,QAAQ,UAAU,SAAS;AAAA,UAC7B,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,cAAI,KAAK,0BAA0B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QACvF;AAEA,YAAI;AACF,wBAAc,GAAG;AAAA,QACnB,SAAS,KAAK;AACZ,cAAI,KAAK,4BAA4B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QACzF;AAEA,YAAI;AACF,gBAAM,mBAAmB;AACzB,oBAAU,KAAK,KAAK;AAAA,QACtB,SAAS,KAAK;AACZ,cAAI,KAAK,yBAAyB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QACtF;AAEA,cAAM,YAA4B;AAAA,UAChC,MAAM;AAAA,UACN;AAAA,UACA,YAAY;AAAA,UACZ;AAAA,UACA;AAAA,QACF;AAGA,YAAI,MAAM,cAAc;AACtB,cAAI;AACF,kBAAM,MAAM,aAAa,EAAE,OAAO,WAAW,QAAQ,QAAQ,UAAU,CAAC;AAAA,UAC1E,SAAS,KAAK;AACZ,gBAAI,KAAK,4BAA4B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,UACzF;AAAA,QACF;AAEA,sBAAc,SAAS;AAAA,MACzB;AAEA,aAAO;AAAA,QACL,YAAY,eAAe;AAAA,QAC3B,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,IAEA,MAAM,WAAW;AACf,UAAI,CAAC,OAAQ;AAGb,UAAI,MAAM,YAAY;AACpB,YAAI;AACF,gBAAM,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC;AAAA,QACzC,SAAS,KAAK;AACZ,cAAI,KAAK,0BAA0B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QACvF;AAAA,MACF;AAGA,UAAI,YAAY;AACd,YAAI;AACF,gBAAM,WAAW,MAAM;AAAA,QACzB,SAAS,KAAK;AACZ,cAAI,KAAK,uBAAuB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QACpF;AACA,qBAAa;AAAA,MACf;AAEA,YAAM,eAAe,MAAM;AAC3B,YAAM,OAAO;AACb,UAAI;AACF,kBAAU,KAAK,KAAK;AAAA,MACtB,SAAS,KAAK;AACZ,YAAI,KAAK,yCAAyC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MACtG;AACA,eAAS;AAGT,UAAI,iBAAiB,UAAU,MAAM,eAAe;AAClD,YAAI;AACF,gBAAM,MAAM,cAAc,EAAE,OAAO,UAAU,cAAc,SAAS,OAAO,CAAC;AAAA,QAC9E,SAAS,KAAK;AACZ,cAAI,KAAK,6BAA6B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QAC1F;AAAA,MACF;AAEA,UAAI,KAAK,aAAa,OAAO,MAAM,IAAI,GAAG;AAAA,IAC5C;AAAA,IAEA,kBAAkB;AAChB,aAAO,gBAAgB;AAAA,IACzB;AAAA,IAEA,WAAW;AACT,aAAO,SAAS,UAAU,GAAG;AAAA,IAC/B;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime/delegate.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { loadDirectory, estimateTokens, getAtLevel } from '../primitives/loader.js';\nimport { loadConfig } from '../core/config.js';\nimport { log } from '../core/logger.js';\nimport { getModel, generate, streamGenerateWithDetails } from '../llm/provider.js';\nimport { buildToolSet, type AIToolSet } from './tool-executor.js';\nimport { createSessionId, writeSession, type SessionRecord } from './sessions.js';\nimport type { HarnessDocument, HarnessConfig } from '../core/types.js';\n\n// --- Types ---\n\nexport interface DelegationResult {\n agentId: string;\n text: string;\n usage: { inputTokens: number; outputTokens: number; totalTokens: number };\n sessionId: string;\n}\n\nexport interface AgentInfo {\n id: string;\n l0: string;\n l1: string;\n path: string;\n tags: string[];\n status: string;\n}\n\n// --- Agent Discovery ---\n\n/**\n * Load all agent documents from the agents/ directory.\n */\nexport function loadAgentDocs(harnessDir: string): HarnessDocument[] {\n return loadDirectory(join(harnessDir, 'agents'));\n}\n\n/**\n * Find an agent document by its frontmatter id.\n * Falls back to filename match if id doesn't match.\n */\nexport function findAgent(harnessDir: string, agentId: string): HarnessDocument | undefined {\n const agents = loadAgentDocs(harnessDir);\n\n // Exact id match\n const byId = agents.find((a) => a.frontmatter.id === agentId);\n if (byId) return byId;\n\n // Try with \"agent-\" prefix\n const prefixed = agents.find((a) => a.frontmatter.id === `agent-${agentId}`);\n if (prefixed) return prefixed;\n\n // Filename match (e.g., \"evaluator\" matches \"evaluator.md\")\n const byFilename = agents.find((a) => {\n const filename = a.path.split('/').pop()?.replace('.md', '') || '';\n return filename === agentId || filename === `agent-${agentId}`;\n });\n\n return byFilename;\n}\n\n/**\n * List all available agents with summary info.\n */\nexport function listAgents(harnessDir: string): AgentInfo[] {\n return loadAgentDocs(harnessDir).map((doc) => ({\n id: doc.frontmatter.id,\n l0: doc.l0,\n l1: doc.l1,\n path: doc.path,\n tags: doc.frontmatter.tags,\n status: doc.frontmatter.status,\n }));\n}\n\n// --- System Prompt Assembly ---\n\n/**\n * Build a minimal system prompt for a delegated agent.\n * Sub-agents are stateless — they get:\n * 1. The agent's own body (L2) as primary instructions\n * 2. CORE.md identity (so they know who they serve)\n * 3. Active rules (at L1 level — compressed for efficiency)\n */\nexport function buildAgentPrompt(harnessDir: string, agentDoc: HarnessDocument, config: HarnessConfig): string {\n const sections: string[] = [];\n const maxTokens = config.model.max_tokens;\n const targetBudget = maxTokens * 0.10; // Sub-agents get 10% context budget\n let usedTokens = 0;\n\n // 1. Agent identity and instructions (always full L2)\n const agentBody = agentDoc.body;\n sections.push(`# AGENT: ${agentDoc.frontmatter.id}\\n\\n${agentBody}`);\n usedTokens += estimateTokens(agentBody);\n\n // 2. Primary agent identity from CORE.md (brief context)\n const corePath = join(harnessDir, 'CORE.md');\n if (existsSync(corePath)) {\n const core = readFileSync(corePath, 'utf-8');\n const coreTokens = estimateTokens(core);\n if (usedTokens + coreTokens <= targetBudget) {\n sections.push(`# PRIMARY AGENT CONTEXT\\n\\n${core}`);\n usedTokens += coreTokens;\n }\n }\n\n // 3. Rules (at appropriate disclosure level based on remaining budget)\n const rulesDir = join(harnessDir, 'rules');\n if (existsSync(rulesDir)) {\n const rules = loadDirectory(rulesDir);\n if (rules.length > 0) {\n const ruleDocs: string[] = [];\n for (const rule of rules) {\n // Estimate how much room is left\n const remaining = targetBudget - usedTokens;\n if (remaining < 50) break;\n\n // Try L1 first, fall back to L0\n let level: 0 | 1 | 2 = 1;\n let content = getAtLevel(rule, level);\n let tokens = estimateTokens(content);\n\n if (usedTokens + tokens > targetBudget) {\n level = 0;\n content = getAtLevel(rule, 0);\n tokens = estimateTokens(content);\n }\n\n if (usedTokens + tokens <= targetBudget) {\n ruleDocs.push(`### ${rule.frontmatter.id}\\n${content}`);\n usedTokens += tokens;\n }\n }\n if (ruleDocs.length > 0) {\n sections.push(`# RULES\\n\\n${ruleDocs.join('\\n\\n')}`);\n }\n }\n }\n\n return sections.join('\\n\\n---\\n\\n');\n}\n\n// --- Delegation ---\n\nexport interface DelegateOptions {\n harnessDir: string;\n agentId: string;\n prompt: string;\n apiKey?: string;\n modelOverride?: string;\n}\n\nfunction prepareDelegation(opts: DelegateOptions) {\n const { harnessDir, agentId, apiKey } = opts;\n\n if (!agentId || !agentId.trim()) {\n throw new Error('agentId is required');\n }\n if (!opts.prompt || !opts.prompt.trim()) {\n throw new Error('prompt cannot be empty');\n }\n\n const agentDoc = findAgent(harnessDir, agentId);\n if (!agentDoc) {\n const available = listAgents(harnessDir);\n const agentList = available.length > 0\n ? available.map((a) => ` - ${a.id}: ${a.l0}`).join('\\n')\n : ' (none)';\n throw new Error(\n `Agent \"${agentId}\" not found.\\n\\nAvailable agents:\\n${agentList}`\n );\n }\n\n const config = loadConfig(harnessDir, opts.modelOverride\n ? { model: { id: opts.modelOverride } }\n : undefined);\n\n const systemPrompt = buildAgentPrompt(harnessDir, agentDoc, config);\n const model = getModel(config, apiKey);\n\n // Load tools from the harness so sub-agents can use them\n const toolSet = buildToolSet(harnessDir);\n const hasTools = Object.keys(toolSet).length > 0;\n\n return { agentDoc, config, systemPrompt, model, toolSet, hasTools };\n}\n\n/**\n * Delegate a prompt to a sub-agent.\n * Sub-agents are stateless single-turn executors. They:\n * - Receive their own body as system prompt + rules + CORE.md\n * - Execute a single prompt\n * - Record a session (tagged with the agent id)\n * - Return the result\n *\n * They do NOT have persistent state, memory, or learning.\n */\nexport async function delegateTo(opts: DelegateOptions): Promise<DelegationResult> {\n const { harnessDir, prompt } = opts;\n const { agentDoc, config, systemPrompt, model, toolSet, hasTools } = prepareDelegation(opts);\n\n const sessionId = createSessionId();\n const started = new Date().toISOString();\n\n const result = await generate({\n model,\n system: systemPrompt,\n prompt,\n maxRetries: config.model.max_retries,\n timeoutMs: config.model.timeout_ms,\n ...(hasTools ? { tools: toolSet, maxToolSteps: 5 } : {}),\n });\n\n const ended = new Date().toISOString();\n\n const session: SessionRecord = {\n id: sessionId,\n started,\n ended,\n prompt,\n summary: result.text.slice(0, 200),\n tokens_used: result.usage.totalTokens,\n model_id: config.model.id,\n delegated_to: agentDoc.frontmatter.id,\n steps: result.steps,\n tool_calls: result.toolCalls.length > 0 ? result.toolCalls : undefined,\n };\n\n try {\n writeSession(harnessDir, session);\n } catch (err) {\n log.warn(`Failed to write delegation session ${sessionId}: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n return {\n agentId: agentDoc.frontmatter.id,\n text: result.text,\n usage: result.usage,\n sessionId,\n };\n}\n\nexport interface DelegateStreamResult {\n agentId: string;\n sessionId: string;\n textStream: AsyncIterable<string>;\n}\n\n/**\n * Stream-delegate a prompt to a sub-agent.\n * Returns an async iterable of text chunks. Session is recorded after\n * the stream is fully consumed.\n */\nexport function delegateStream(opts: DelegateOptions): DelegateStreamResult {\n const { harnessDir, prompt } = opts;\n\n // prepareDelegation() is called eagerly so callers get immediate errors\n // (e.g., agent not found) before consuming the stream.\n const { agentDoc, config, systemPrompt, model, toolSet, hasTools } = prepareDelegation(opts);\n\n const sessionId = createSessionId();\n const started = new Date().toISOString();\n\n const result = streamGenerateWithDetails({\n model,\n system: systemPrompt,\n prompt,\n maxRetries: config.model.max_retries,\n timeoutMs: config.model.timeout_ms,\n ...(hasTools ? { tools: toolSet, maxToolSteps: 5 } : {}),\n });\n\n async function* wrappedStream(): AsyncIterable<string> {\n let fullText = '';\n try {\n for await (const chunk of result.textStream) {\n fullText += chunk;\n yield chunk;\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n log.warn(`Delegation stream error for agent \"${agentDoc.frontmatter.id}\": ${error.message}`);\n throw error;\n }\n\n // Await post-stream metadata — wrapped so failures don't crash the generator\n let usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n let steps = 1;\n let toolCalls: Array<{ toolName: string; args: Record<string, unknown>; result: unknown }> = [];\n try {\n [usage, steps, toolCalls] = await Promise.all([\n result.usage,\n result.steps,\n result.toolCalls,\n ]);\n } catch (err) {\n log.warn(`Failed to resolve delegation post-stream metadata: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const ended = new Date().toISOString();\n\n const session: SessionRecord = {\n id: sessionId,\n started,\n ended,\n prompt,\n summary: fullText.slice(0, 200),\n tokens_used: usage.totalTokens,\n model_id: config.model.id,\n delegated_to: agentDoc.frontmatter.id,\n steps,\n tool_calls: toolCalls.length > 0 ? toolCalls : undefined,\n };\n\n try {\n writeSession(harnessDir, session);\n } catch (err) {\n log.warn(`Failed to write delegation session ${sessionId}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return {\n agentId: agentDoc.frontmatter.id,\n sessionId,\n textStream: wrappedStream(),\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
- }) : x)(function(x) {
6
- if (typeof require !== "undefined") return require.apply(this, arguments);
7
- throw Error('Dynamic require of "' + x + '" is not supported');
8
- });
9
-
10
- export {
11
- __require
12
- };
13
- //# sourceMappingURL=chunk-ZZJOFKAT.js.map
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import {
4
- loadConfig,
5
- writeDefaultConfig
6
- } from "./chunk-CHJ5GNZC.js";
7
- import "./chunk-4CWAGBNS.js";
8
- import "./chunk-ZZJOFKAT.js";
9
- export {
10
- loadConfig,
11
- writeDefaultConfig
12
- };
13
- //# sourceMappingURL=config-WVMRUOCA.js.map
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import {
4
- buildSystemPrompt
5
- } from "./chunk-UWQTZMNI.js";
6
- import "./chunk-UPLBF4RZ.js";
7
- import "./chunk-BSKDOFRT.js";
8
- import "./chunk-4CWAGBNS.js";
9
- import "./chunk-ZZJOFKAT.js";
10
- export {
11
- buildSystemPrompt
12
- };
13
- //# sourceMappingURL=context-loader-3ORBPMHJ.js.map
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import {
4
- buildDependencyGraph,
5
- getGraphStats
6
- } from "./chunk-274RV3YO.js";
7
- import "./chunk-UPLBF4RZ.js";
8
- import "./chunk-4CWAGBNS.js";
9
- import "./chunk-ZZJOFKAT.js";
10
- export {
11
- buildDependencyGraph,
12
- getGraphStats
13
- };
14
- //# sourceMappingURL=graph-YUIPOSOO.js.map
@@ -1,10 +0,0 @@
1
- import {
2
- createHarness
3
- } from "./chunk-GUJTBGVS.js";
4
- import "./chunk-KFX54TQM.js";
5
- import "./chunk-FD55B3IO.js";
6
- import "./chunk-DGUM43GV.js";
7
- export {
8
- createHarness
9
- };
10
- //# sourceMappingURL=harness-LCHA3DWP.js.map