@agntk/agent-harness 0.1.4 → 0.1.5
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/dist/{agent-framework-K4GUIICH.js → agent-framework-CMFC3VJM.js} +8 -8
- package/dist/{auto-processor-OLE45UI3.js → auto-processor-SDAJF67T.js} +3 -3
- package/dist/{chunk-XTBKL5BI.js → chunk-2ENYRENZ.js} +2 -2
- package/dist/{chunk-UPLBF4RZ.js → chunk-2UVWCTAY.js} +2 -2
- package/dist/{chunk-4CWAGBNS.js → chunk-4TQQZILG.js} +73 -3
- package/dist/chunk-4TQQZILG.js.map +1 -0
- package/dist/{chunk-A7BJPQQ6.js → chunk-5O5OGOOQ.js} +2 -2
- package/dist/{chunk-UWQTZMNI.js → chunk-7GZ4D6V6.js} +2 -2
- package/dist/{chunk-FLZU44SV.js → chunk-AN6Y4MDD.js} +6 -6
- package/dist/{chunk-4FDUOGSZ.js → chunk-D7AWV24Z.js} +3 -3
- package/dist/{chunk-CHJ5GNZC.js → chunk-EC42HQQH.js} +2 -2
- package/dist/{chunk-274RV3YO.js → chunk-GX2RCSFJ.js} +3 -3
- package/dist/{chunk-GJNNR2RA.js → chunk-M6PDMK2O.js} +3 -3
- package/dist/{chunk-GUJTBGVS.js → chunk-MSO7DKBK.js} +99 -188
- package/dist/chunk-MSO7DKBK.js.map +1 -0
- package/dist/{chunk-CSL3ERUI.js → chunk-NBEAK63K.js} +3 -3
- package/dist/{chunk-DA7IKHC4.js → chunk-NOJW5KG2.js} +2 -2
- package/dist/{chunk-M7NXUK55.js → chunk-NVC2WY4K.js} +2 -2
- package/dist/{chunk-YIJY5DBV.js → chunk-P74KXHA4.js} +4 -4
- package/dist/{chunk-YUFNYN2H.js → chunk-PTQ37NRI.js} +4 -4
- package/dist/{chunk-KFX54TQM.js → chunk-RPBC2QOA.js} +73 -3
- package/dist/chunk-RPBC2QOA.js.map +1 -0
- package/dist/{chunk-RY3ZFII7.js → chunk-SEHAQTBO.js} +6 -6
- package/dist/{chunk-MPZ3BPUI.js → chunk-UMXPOYZR.js} +4 -4
- package/dist/{chunk-W4T7PGI2.js → chunk-UXCHAS3Z.js} +4 -4
- package/dist/chunk-XVFVTDE6.js +98 -0
- package/dist/chunk-XVFVTDE6.js.map +1 -0
- package/dist/cli/index.js +105 -104
- package/dist/cli/index.js.map +1 -1
- package/dist/{config-WVMRUOCA.js → config-2O6S2YJO.js} +3 -3
- package/dist/config-LLQZYN2Q.js +11 -0
- package/dist/{context-loader-3ORBPMHJ.js → context-loader-XCZ5EXNG.js} +4 -4
- package/dist/{conversation-QDEIDQPH.js → conversation-OPLE23IM.js} +6 -6
- package/dist/{delegate-VJCJLYEK.js → delegate-ZJCIADNN.js} +7 -7
- package/dist/{export-6GCYHEHQ.js → export-2HEAAOUF.js} +3 -3
- package/dist/{graph-YUIPOSOO.js → graph-5MKRTC3J.js} +4 -4
- package/dist/harness-ABKZWP47.js +11 -0
- package/dist/{harness-WE4SLCML.js → harness-XSBQBY7T.js} +8 -8
- package/dist/index.d.ts +22 -0
- package/dist/index.js +90 -6
- package/dist/index.js.map +1 -1
- package/dist/{indexer-LONANRRM.js → indexer-YKSGUVYT.js} +4 -4
- package/dist/{instinct-learner-SRM72DHF.js → instinct-learner-CWVMLUWX.js} +5 -5
- package/dist/{intake-4M3HNU43.js → intake-M5NRR6QR.js} +5 -5
- package/dist/{intelligence-HJOCA4SJ.js → intelligence-UW4TCOC7.js} +10 -10
- package/dist/{journal-WANJL3MI.js → journal-KN265YLU.js} +5 -5
- package/dist/{loader-C3TKIKZR.js → loader-BOCVXVCH.js} +3 -3
- package/dist/{mcp-installer-6O2XXD3V.js → mcp-installer-KV3XZRRF.js} +3 -3
- package/dist/{primitive-registry-I6VTIR4W.js → primitive-registry-HOJMUFBT.js} +3 -3
- package/dist/{rule-engine-YGQ3RYZM.js → rule-engine-I4AFQSSR.js} +3 -3
- package/dist/{scaffold-A3VRRCBV.js → scaffold-ZY4XWINP.js} +4 -4
- package/dist/{scheduler-XHHIVHRI.js → scheduler-TYOQKO4C.js} +11 -11
- package/dist/{search-V3W5JMJG.js → search-4IYM525O.js} +3 -3
- package/dist/{semantic-search-2DTOO5UX.js → semantic-search-G624D6CI.js} +3 -3
- package/dist/{serve-DTQ3HENY.js → serve-QFUZWOU3.js} +9 -9
- package/dist/{telemetry-UC6PBXC7.js → telemetry-MVDNGJEC.js} +4 -4
- package/dist/{tool-executor-MJ7IG7PQ.js → tool-executor-KEYQLO4M.js} +5 -5
- package/dist/{tools-DZ4KETET.js → tools-EB3BHRRF.js} +4 -4
- package/dist/{types-EW7AIB3R.js → types-NYKB2DN3.js} +2 -2
- package/dist/{types-WGDLSPO6.js → types-VRSXU4AM.js} +2 -2
- package/dist/{universal-installer-AAXXYM5A.js → universal-installer-7MFCJUW7.js} +91 -6
- package/dist/universal-installer-7MFCJUW7.js.map +1 -0
- package/dist/{validator-7WXMDIHH.js → validator-LZXBFEPV.js} +8 -8
- package/dist/{verification-gate-FYXUX6LH.js → verification-gate-ALSJVKSW.js} +3 -3
- package/dist/{watcher-ISJC7YKL.js → watcher-CSHVDOCM.js} +5 -5
- package/dist/{web-server-DD7ZOP46.js → web-server-7NGOTK7J.js} +8 -8
- package/dist/web-server-7NGOTK7J.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-4CWAGBNS.js.map +0 -1
- package/dist/chunk-GUJTBGVS.js.map +0 -1
- package/dist/chunk-KFX54TQM.js.map +0 -1
- package/dist/harness-LCHA3DWP.js +0 -10
- package/dist/universal-installer-AAXXYM5A.js.map +0 -1
- /package/dist/{agent-framework-K4GUIICH.js.map → agent-framework-CMFC3VJM.js.map} +0 -0
- /package/dist/{auto-processor-OLE45UI3.js.map → auto-processor-SDAJF67T.js.map} +0 -0
- /package/dist/{chunk-XTBKL5BI.js.map → chunk-2ENYRENZ.js.map} +0 -0
- /package/dist/{chunk-UPLBF4RZ.js.map → chunk-2UVWCTAY.js.map} +0 -0
- /package/dist/{chunk-A7BJPQQ6.js.map → chunk-5O5OGOOQ.js.map} +0 -0
- /package/dist/{chunk-UWQTZMNI.js.map → chunk-7GZ4D6V6.js.map} +0 -0
- /package/dist/{chunk-FLZU44SV.js.map → chunk-AN6Y4MDD.js.map} +0 -0
- /package/dist/{chunk-4FDUOGSZ.js.map → chunk-D7AWV24Z.js.map} +0 -0
- /package/dist/{chunk-CHJ5GNZC.js.map → chunk-EC42HQQH.js.map} +0 -0
- /package/dist/{chunk-274RV3YO.js.map → chunk-GX2RCSFJ.js.map} +0 -0
- /package/dist/{chunk-GJNNR2RA.js.map → chunk-M6PDMK2O.js.map} +0 -0
- /package/dist/{chunk-CSL3ERUI.js.map → chunk-NBEAK63K.js.map} +0 -0
- /package/dist/{chunk-DA7IKHC4.js.map → chunk-NOJW5KG2.js.map} +0 -0
- /package/dist/{chunk-M7NXUK55.js.map → chunk-NVC2WY4K.js.map} +0 -0
- /package/dist/{chunk-YIJY5DBV.js.map → chunk-P74KXHA4.js.map} +0 -0
- /package/dist/{chunk-YUFNYN2H.js.map → chunk-PTQ37NRI.js.map} +0 -0
- /package/dist/{chunk-RY3ZFII7.js.map → chunk-SEHAQTBO.js.map} +0 -0
- /package/dist/{chunk-MPZ3BPUI.js.map → chunk-UMXPOYZR.js.map} +0 -0
- /package/dist/{chunk-W4T7PGI2.js.map → chunk-UXCHAS3Z.js.map} +0 -0
- /package/dist/{config-WVMRUOCA.js.map → config-2O6S2YJO.js.map} +0 -0
- /package/dist/{context-loader-3ORBPMHJ.js.map → config-LLQZYN2Q.js.map} +0 -0
- /package/dist/{conversation-QDEIDQPH.js.map → context-loader-XCZ5EXNG.js.map} +0 -0
- /package/dist/{delegate-VJCJLYEK.js.map → conversation-OPLE23IM.js.map} +0 -0
- /package/dist/{graph-YUIPOSOO.js.map → delegate-ZJCIADNN.js.map} +0 -0
- /package/dist/{export-6GCYHEHQ.js.map → export-2HEAAOUF.js.map} +0 -0
- /package/dist/{harness-LCHA3DWP.js.map → graph-5MKRTC3J.js.map} +0 -0
- /package/dist/{harness-WE4SLCML.js.map → harness-ABKZWP47.js.map} +0 -0
- /package/dist/{indexer-LONANRRM.js.map → harness-XSBQBY7T.js.map} +0 -0
- /package/dist/{instinct-learner-SRM72DHF.js.map → indexer-YKSGUVYT.js.map} +0 -0
- /package/dist/{intake-4M3HNU43.js.map → instinct-learner-CWVMLUWX.js.map} +0 -0
- /package/dist/{journal-WANJL3MI.js.map → intake-M5NRR6QR.js.map} +0 -0
- /package/dist/{intelligence-HJOCA4SJ.js.map → intelligence-UW4TCOC7.js.map} +0 -0
- /package/dist/{loader-C3TKIKZR.js.map → journal-KN265YLU.js.map} +0 -0
- /package/dist/{telemetry-UC6PBXC7.js.map → loader-BOCVXVCH.js.map} +0 -0
- /package/dist/{mcp-installer-6O2XXD3V.js.map → mcp-installer-KV3XZRRF.js.map} +0 -0
- /package/dist/{primitive-registry-I6VTIR4W.js.map → primitive-registry-HOJMUFBT.js.map} +0 -0
- /package/dist/{rule-engine-YGQ3RYZM.js.map → rule-engine-I4AFQSSR.js.map} +0 -0
- /package/dist/{scaffold-A3VRRCBV.js.map → scaffold-ZY4XWINP.js.map} +0 -0
- /package/dist/{scheduler-XHHIVHRI.js.map → scheduler-TYOQKO4C.js.map} +0 -0
- /package/dist/{search-V3W5JMJG.js.map → search-4IYM525O.js.map} +0 -0
- /package/dist/{semantic-search-2DTOO5UX.js.map → semantic-search-G624D6CI.js.map} +0 -0
- /package/dist/{serve-DTQ3HENY.js.map → serve-QFUZWOU3.js.map} +0 -0
- /package/dist/{tool-executor-MJ7IG7PQ.js.map → telemetry-MVDNGJEC.js.map} +0 -0
- /package/dist/{tools-DZ4KETET.js.map → tool-executor-KEYQLO4M.js.map} +0 -0
- /package/dist/{types-EW7AIB3R.js.map → tools-EB3BHRRF.js.map} +0 -0
- /package/dist/{types-WGDLSPO6.js.map → types-NYKB2DN3.js.map} +0 -0
- /package/dist/{validator-7WXMDIHH.js.map → types-VRSXU4AM.js.map} +0 -0
- /package/dist/{web-server-DD7ZOP46.js.map → validator-LZXBFEPV.js.map} +0 -0
- /package/dist/{verification-gate-FYXUX6LH.js.map → verification-gate-ALSJVKSW.js.map} +0 -0
- /package/dist/{watcher-ISJC7YKL.js.map → watcher-CSHVDOCM.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/harness.ts","../src/core/logger.ts","../src/runtime/context-loader.ts","../src/primitives/loader.ts","../src/runtime/state.ts","../src/runtime/file-lock.ts","../src/runtime/sessions.ts","../src/runtime/cost-tracker.ts","../src/runtime/health.ts","../src/runtime/rate-limiter.ts","../src/runtime/guardrails.ts","../src/runtime/tool-executor.ts","../src/runtime/tools.ts","../src/runtime/mcp.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","export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\nexport interface Logger {\n debug(msg: string, ...args: unknown[]): void;\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n setLevel(level: LogLevel): void;\n getLevel(): LogLevel;\n child(prefix: string): Logger;\n}\n\nlet globalLevel: LogLevel = 'info';\n\nfunction shouldLog(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[globalLevel];\n}\n\nfunction formatMessage(prefix: string, level: LogLevel, msg: string): string {\n const tag = prefix ? `[${prefix}]` : '';\n if (level === 'debug') return `${tag} ${msg}`.trimStart();\n if (level === 'warn') return `${tag} WARN: ${msg}`.trimStart();\n if (level === 'error') return `${tag} ERROR: ${msg}`.trimStart();\n return `${tag} ${msg}`.trimStart();\n}\n\nfunction createLoggerWithPrefix(prefix: string): Logger {\n return {\n debug(msg: string, ...args: unknown[]) {\n if (shouldLog('debug')) console.error(formatMessage(prefix, 'debug', msg), ...args);\n },\n info(msg: string, ...args: unknown[]) {\n if (shouldLog('info')) console.error(formatMessage(prefix, 'info', msg), ...args);\n },\n warn(msg: string, ...args: unknown[]) {\n if (shouldLog('warn')) console.error(formatMessage(prefix, 'warn', msg), ...args);\n },\n error(msg: string, ...args: unknown[]) {\n if (shouldLog('error')) console.error(formatMessage(prefix, 'error', msg), ...args);\n },\n setLevel(level: LogLevel) {\n globalLevel = level;\n },\n getLevel() {\n return globalLevel;\n },\n child(childPrefix: string) {\n const combined = prefix ? `${prefix}:${childPrefix}` : childPrefix;\n return createLoggerWithPrefix(combined);\n },\n };\n}\n\nexport function createLogger(prefix: string = ''): Logger {\n return createLoggerWithPrefix(prefix);\n}\n\nexport function setGlobalLogLevel(level: LogLevel): void {\n globalLevel = level;\n}\n\nexport function getGlobalLogLevel(): LogLevel {\n return globalLevel;\n}\n\nexport const log = createLogger('harness');\n","import { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { loadAllPrimitivesWithErrors, estimateTokens, getAtLevel } from '../primitives/loader.js';\nimport type { ParseError } from '../primitives/loader.js';\nimport type { HarnessConfig, HarnessDocument, ContextBudget } from '../core/types.js';\nimport { log } from '../core/logger.js';\n\nexport interface LoadedContext {\n systemPrompt: string;\n budget: ContextBudget;\n parseErrors: ParseError[];\n warnings: string[];\n}\n\nexport function buildSystemPrompt(harnessDir: string, config: HarnessConfig): LoadedContext {\n const maxTokens = config.model.max_tokens;\n const budget: ContextBudget = {\n max_tokens: maxTokens,\n used_tokens: 0,\n remaining: maxTokens,\n loaded_files: [],\n };\n\n const warnings: string[] = [];\n const sections: string[] = [];\n\n // --- Step 1: Load CORE.md (always, full content) ---\n const corePath = join(harnessDir, 'CORE.md');\n if (existsSync(corePath)) {\n const core = readFileSync(corePath, 'utf-8');\n sections.push(`# CORE IDENTITY\\n\\n${core}`);\n budget.used_tokens += estimateTokens(core);\n budget.loaded_files.push('CORE.md');\n }\n\n // --- Step 2: Load state.md ---\n const statePath = join(harnessDir, 'state.md');\n if (existsSync(statePath)) {\n const state = readFileSync(statePath, 'utf-8');\n sections.push(`# CURRENT STATE\\n\\n${state}`);\n budget.used_tokens += estimateTokens(state);\n budget.loaded_files.push('state.md');\n }\n\n // --- Step 3: Load SYSTEM.md (boot instructions) ---\n const systemPath = join(harnessDir, 'SYSTEM.md');\n if (existsSync(systemPath)) {\n const system = readFileSync(systemPath, 'utf-8');\n sections.push(`# SYSTEM\\n\\n${system}`);\n budget.used_tokens += estimateTokens(system);\n budget.loaded_files.push('SYSTEM.md');\n }\n\n // --- Step 4: Load all primitives at appropriate level ---\n const extDirs = config.extensions?.directories ?? [];\n const { primitives, errors: parseErrors } = loadAllPrimitivesWithErrors(harnessDir, extDirs);\n\n // Report parse errors\n if (parseErrors.length > 0) {\n for (const pe of parseErrors) {\n log.warn(`Failed to parse primitive: ${pe.path} — ${pe.error}`);\n }\n warnings.push(`${parseErrors.length} primitive file(s) failed to parse`);\n }\n\n const targetBudget = maxTokens * 0.15; // Use 15% of context for harness\n\n // Priority order for loading primitives (core dirs first, extensions appended)\n const priorityOrder = ['rules', 'instincts', 'skills', 'playbooks', 'tools', 'workflows', 'agents'];\n for (const dir of extDirs) {\n if (!priorityOrder.includes(dir)) {\n priorityOrder.push(dir);\n }\n }\n\n // Collect all docs to estimate total demand before deciding levels\n const allDocs: { category: string; doc: HarnessDocument }[] = [];\n for (const category of priorityOrder) {\n const docs = primitives.get(category);\n if (!docs || docs.length === 0) continue;\n for (const doc of docs) {\n allDocs.push({ category, doc });\n }\n }\n\n if (allDocs.length === 0) {\n warnings.push('No primitives found — add rules, instincts, or skills to improve agent behavior');\n }\n\n // Estimate total L2 demand vs available budget for primitives\n const primitiveBudget = targetBudget - budget.used_tokens;\n let totalL2Demand = 0;\n for (const { doc } of allDocs) {\n totalL2Demand += estimateTokens(getAtLevel(doc, 2));\n }\n\n // Choose a global disclosure level based on how much fits\n let globalLevel: 0 | 1 | 2;\n if (totalL2Demand <= primitiveBudget) {\n globalLevel = 2; // Everything fits at full\n } else {\n // Estimate L1 demand\n let totalL1Demand = 0;\n for (const { doc } of allDocs) {\n totalL1Demand += estimateTokens(getAtLevel(doc, 1));\n }\n globalLevel = totalL1Demand <= primitiveBudget ? 1 : 0;\n }\n\n for (const category of priorityOrder) {\n const docs = primitives.get(category);\n if (!docs || docs.length === 0) continue;\n\n const categoryLabel = category.toUpperCase();\n const categoryDocs: string[] = [];\n\n for (const doc of docs) {\n // Start from global level, fall back if this doc would exceed budget\n let level = globalLevel;\n let content = getAtLevel(doc, level);\n let tokens = estimateTokens(content);\n\n while (budget.used_tokens + tokens > targetBudget && level > 0) {\n level = (level - 1) as 0 | 1;\n content = getAtLevel(doc, level);\n tokens = estimateTokens(content);\n }\n\n categoryDocs.push(`### ${doc.frontmatter.id}\\n${content}`);\n budget.used_tokens += tokens;\n budget.loaded_files.push(doc.path);\n }\n\n if (categoryDocs.length > 0) {\n sections.push(`# ${categoryLabel}\\n\\n${categoryDocs.join('\\n\\n')}`);\n }\n }\n\n // --- Step 5: Load scratch.md if exists ---\n const scratchPath = join(harnessDir, 'memory', 'scratch.md');\n if (existsSync(scratchPath)) {\n const scratch = readFileSync(scratchPath, 'utf-8');\n if (scratch.trim()) {\n sections.push(`# SCRATCH (Current Working Memory)\\n\\n${scratch}`);\n budget.used_tokens += estimateTokens(scratch);\n budget.loaded_files.push('memory/scratch.md');\n }\n }\n\n budget.remaining = maxTokens - budget.used_tokens;\n\n // --- Step 6: Budget warnings ---\n const usagePercent = (budget.used_tokens / maxTokens) * 100;\n if (usagePercent > 12) {\n // System prompt using more than 80% of its 15% allocation\n warnings.push(\n `System prompt using ${usagePercent.toFixed(1)}% of total context ` +\n `(${budget.used_tokens}/${maxTokens} tokens) — some primitives may be truncated`,\n );\n log.warn(\n `Context budget high: ${budget.used_tokens}/${maxTokens} tokens ` +\n `(${usagePercent.toFixed(1)}%), ${budget.loaded_files.length} files loaded`,\n );\n }\n\n if (globalLevel < 2) {\n const levelName = globalLevel === 0 ? 'L0 (summary only)' : 'L1 (paragraph summary)';\n warnings.push(`Primitives loaded at ${levelName} due to budget constraints`);\n }\n\n return {\n systemPrompt: sections.join('\\n\\n---\\n\\n'),\n budget,\n parseErrors,\n warnings,\n };\n}\n","import { readFileSync, readdirSync, existsSync } from 'fs';\nimport { join, extname } from 'path';\nimport matter from 'gray-matter';\nimport { FrontmatterSchema, CORE_PRIMITIVE_DIRS, type HarnessDocument, type Frontmatter } from '../core/types.js';\n\nexport interface ParseError {\n path: string;\n error: string;\n}\n\nexport interface LoadResult {\n docs: HarnessDocument[];\n errors: ParseError[];\n}\n\n// Extract L0 and L1 from HTML comments at the top of the markdown body\n// Format: <!-- L0: one-line summary -->\n// <!-- L1: paragraph summary -->\nconst L0_REGEX = /<!--\\s*L0:\\s*([\\s\\S]*?)\\s*-->/;\nconst L1_REGEX = /<!--\\s*L1:\\s*([\\s\\S]*?)\\s*-->/;\n\nexport function parseHarnessDocument(filePath: string): HarnessDocument {\n const raw = readFileSync(filePath, 'utf-8');\n const { data, content } = matter(raw);\n\n // Parse frontmatter with defaults\n // Normalize dates: gray-matter converts date strings to Date objects\n const normalized = { ...data };\n for (const key of ['created', 'updated']) {\n if (normalized[key] instanceof Date) {\n normalized[key] = (normalized[key] as Date).toISOString().split('T')[0];\n }\n }\n\n let frontmatter: Frontmatter;\n try {\n frontmatter = FrontmatterSchema.parse(normalized);\n } catch {\n // Fallback: create minimal frontmatter from filename\n const id = filePath.split('/').pop()?.replace('.md', '') || 'unknown';\n frontmatter = FrontmatterSchema.parse({ id });\n }\n\n // Extract L0 and L1 from content\n const l0Match = content.match(L0_REGEX);\n const l1Match = content.match(L1_REGEX);\n\n const l0 = l0Match ? l0Match[1].trim() : '';\n const l1 = l1Match ? l1Match[1].trim() : '';\n\n // Body is the content without L0/L1 comments\n const body = content\n .replace(L0_REGEX, '')\n .replace(L1_REGEX, '')\n .trim();\n\n return {\n path: filePath,\n frontmatter,\n l0,\n l1,\n body,\n raw,\n };\n}\n\nexport function loadDirectory(dirPath: string): HarnessDocument[] {\n return loadDirectoryWithErrors(dirPath).docs;\n}\n\nexport function loadDirectoryWithErrors(dirPath: string): LoadResult {\n if (!existsSync(dirPath)) return { docs: [], errors: [] };\n\n const files = readdirSync(dirPath);\n const docs: HarnessDocument[] = [];\n const errors: ParseError[] = [];\n\n for (const file of files) {\n if (extname(file) !== '.md') continue;\n if (file.startsWith('_')) continue; // Skip index files\n if (file.startsWith('.')) continue; // Skip hidden files\n\n const filePath = join(dirPath, file);\n try {\n const doc = parseHarnessDocument(filePath);\n if (doc.frontmatter.status !== 'archived' && doc.frontmatter.status !== 'deprecated') {\n docs.push(doc);\n }\n } catch (err) {\n errors.push({\n path: filePath,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return { docs, errors };\n}\n\nexport interface LoadAllResult {\n primitives: Map<string, HarnessDocument[]>;\n errors: ParseError[];\n}\n\nexport function loadAllPrimitives(harnessDir: string, extraDirs?: string[]): Map<string, HarnessDocument[]> {\n return loadAllPrimitivesWithErrors(harnessDir, extraDirs).primitives;\n}\n\nexport function loadAllPrimitivesWithErrors(harnessDir: string, extraDirs?: string[]): LoadAllResult {\n const primitives = new Map<string, HarnessDocument[]>();\n const allErrors: ParseError[] = [];\n\n const directories: string[] = [...CORE_PRIMITIVE_DIRS];\n if (extraDirs) {\n for (const dir of extraDirs) {\n if (!directories.includes(dir)) {\n directories.push(dir);\n }\n }\n }\n\n for (const dir of directories) {\n const { docs, errors } = loadDirectoryWithErrors(join(harnessDir, dir));\n primitives.set(dir, docs);\n allErrors.push(...errors);\n }\n\n return { primitives, errors: allErrors };\n}\n\n// Estimate token count (rough: 1 token ≈ 4 chars)\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n// Load a file at a specific disclosure level\nexport function getAtLevel(doc: HarnessDocument, level: 0 | 1 | 2): string {\n switch (level) {\n case 0:\n return doc.l0 || doc.frontmatter.id;\n case 1:\n return doc.l1 || doc.l0 || doc.body.slice(0, 400);\n case 2:\n return doc.body;\n }\n}\n","import { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport type { AgentState } from '../core/types.js';\nimport { withFileLockSync } from './file-lock.js';\n\nconst DEFAULT_STATE: AgentState = {\n mode: 'idle',\n goals: [],\n active_workflows: [],\n last_interaction: new Date().toISOString(),\n unfinished_business: [],\n};\n\nexport function loadState(harnessDir: string): AgentState {\n const statePath = join(harnessDir, 'state.md');\n\n if (!existsSync(statePath)) {\n return { ...DEFAULT_STATE };\n }\n\n const content = readFileSync(statePath, 'utf-8');\n return parseStateMd(content);\n}\n\nexport function saveState(harnessDir: string, state: AgentState): void {\n const statePath = join(harnessDir, 'state.md');\n const content = renderStateMd(state);\n withFileLockSync(harnessDir, statePath, () => {\n writeFileSync(statePath, content, 'utf-8');\n });\n}\n\nfunction parseStateMd(content: string): AgentState {\n const state = { ...DEFAULT_STATE };\n\n const modeMatch = content.match(/## Mode\\s*\\n(.+)/);\n if (modeMatch) state.mode = modeMatch[1].trim();\n\n const goalsMatch = content.match(/## Goals\\s*\\n([\\s\\S]*?)(?=\\n## |\\n$|$)/);\n if (goalsMatch) {\n state.goals = goalsMatch[1]\n .split('\\n')\n .filter(l => l.startsWith('- '))\n .map(l => l.replace(/^- /, '').trim());\n }\n\n const workflowsMatch = content.match(/## Active Workflows\\s*\\n([\\s\\S]*?)(?=\\n## |\\n$|$)/);\n if (workflowsMatch) {\n state.active_workflows = workflowsMatch[1]\n .split('\\n')\n .filter(l => l.startsWith('- '))\n .map(l => l.replace(/^- /, '').trim());\n }\n\n const lastMatch = content.match(/## Last Interaction\\s*\\n(.+)/);\n if (lastMatch) state.last_interaction = lastMatch[1].trim();\n\n const unfinishedMatch = content.match(/## Unfinished Business\\s*\\n([\\s\\S]*?)(?=\\n## |\\n$|$)/);\n if (unfinishedMatch) {\n state.unfinished_business = unfinishedMatch[1]\n .split('\\n')\n .filter(l => l.startsWith('- '))\n .map(l => l.replace(/^- /, '').trim());\n }\n\n return state;\n}\n\nfunction renderStateMd(state: AgentState): string {\n const lines: string[] = [\n '# Agent State',\n '',\n '## Mode',\n state.mode,\n '',\n '## Goals',\n ...state.goals.map(g => `- ${g}`),\n '',\n '## Active Workflows',\n ...state.active_workflows.map(w => `- ${w}`),\n '',\n '## Last Interaction',\n state.last_interaction,\n '',\n '## Unfinished Business',\n ...state.unfinished_business.map(u => `- ${u}`),\n '',\n ];\n\n return lines.join('\\n');\n}\n","import { writeFileSync, unlinkSync, readFileSync, existsSync, mkdirSync } from 'fs';\nimport { join, basename } from 'path';\n\nexport interface LockInfo {\n pid: number;\n acquired: string;\n file: string;\n}\n\nexport interface LockOptions {\n /** Stale lock timeout in ms (default: 30000 = 30s) */\n staleMs?: number;\n /** How often to retry in ms (default: 50) */\n retryIntervalMs?: number;\n /** Max time to wait for lock in ms (default: 5000 = 5s) */\n waitMs?: number;\n}\n\nconst DEFAULT_STALE_MS = 30000;\nconst DEFAULT_RETRY_MS = 50;\nconst DEFAULT_WAIT_MS = 5000;\n\nfunction getLockDir(harnessDir: string): string {\n return join(harnessDir, 'memory');\n}\n\nfunction getLockPath(harnessDir: string, filePath: string): string {\n const lockDir = getLockDir(harnessDir);\n const lockName = basename(filePath).replace(/\\.[^.]+$/, '') + '.lock';\n return join(lockDir, lockName);\n}\n\n/**\n * Read lock info from a lock file. Returns null if missing or corrupt.\n */\nfunction readLockInfo(lockPath: string): LockInfo | null {\n if (!existsSync(lockPath)) return null;\n try {\n const content = readFileSync(lockPath, 'utf-8');\n const parsed: unknown = JSON.parse(content);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n 'pid' in parsed &&\n 'acquired' in parsed\n ) {\n return parsed as LockInfo;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a lock is stale (older than staleMs or held by dead process).\n */\nfunction isStale(info: LockInfo, staleMs: number): boolean {\n const age = Date.now() - new Date(info.acquired).getTime();\n if (age > staleMs) return true;\n\n // Check if the process that holds the lock is still alive\n try {\n process.kill(info.pid, 0);\n return false; // Process exists\n } catch {\n return true; // Process is dead\n }\n}\n\n/**\n * Try to acquire a file lock. Non-blocking — returns immediately.\n * Returns true if lock was acquired, false if already held.\n */\nexport function tryLock(harnessDir: string, filePath: string, options?: LockOptions): boolean {\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const lockPath = getLockPath(harnessDir, filePath);\n\n // Ensure lock directory exists\n const lockDir = getLockDir(harnessDir);\n if (!existsSync(lockDir)) {\n mkdirSync(lockDir, { recursive: true });\n }\n\n // Check existing lock\n const existing = readLockInfo(lockPath);\n if (existing) {\n if (isStale(existing, staleMs)) {\n // Stale lock — remove it\n try {\n unlinkSync(lockPath);\n } catch {\n // Another process may have already cleaned it up\n }\n } else {\n // Lock is valid and held by another process\n return false;\n }\n }\n\n // Write our lock file\n const info: LockInfo = {\n pid: process.pid,\n acquired: new Date().toISOString(),\n file: filePath,\n };\n\n try {\n // Use wx flag — fails if file already exists (atomic-ish on most systems)\n writeFileSync(lockPath, JSON.stringify(info), { flag: 'wx' });\n return true;\n } catch {\n // Another process got the lock between our check and write\n return false;\n }\n}\n\n/**\n * Release a file lock. Safe to call even if we don't hold it.\n */\nexport function releaseLock(harnessDir: string, filePath: string): void {\n const lockPath = getLockPath(harnessDir, filePath);\n\n if (!existsSync(lockPath)) return;\n\n // Only release if we own it\n const info = readLockInfo(lockPath);\n if (info && info.pid === process.pid) {\n try {\n unlinkSync(lockPath);\n } catch {\n // Already cleaned up\n }\n }\n}\n\n/**\n * Wait to acquire a file lock with timeout.\n * Polls at retryIntervalMs until lock is acquired or waitMs expires.\n */\nexport async function acquireLock(\n harnessDir: string,\n filePath: string,\n options?: LockOptions,\n): Promise<boolean> {\n const retryMs = options?.retryIntervalMs ?? DEFAULT_RETRY_MS;\n const waitMs = options?.waitMs ?? DEFAULT_WAIT_MS;\n const deadline = Date.now() + waitMs;\n\n while (Date.now() < deadline) {\n if (tryLock(harnessDir, filePath, options)) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, retryMs));\n }\n\n return false;\n}\n\n/**\n * Execute a function while holding a file lock.\n * Acquires lock, runs fn, releases lock (even on error).\n * If lock cannot be acquired within waitMs, runs fn anyway (fail-open).\n */\nexport async function withFileLock<T>(\n harnessDir: string,\n filePath: string,\n fn: () => T | Promise<T>,\n options?: LockOptions,\n): Promise<T> {\n const acquired = await acquireLock(harnessDir, filePath, options);\n\n try {\n return await fn();\n } finally {\n if (acquired) {\n releaseLock(harnessDir, filePath);\n }\n }\n}\n\n/**\n * Synchronous version of withFileLock for use in sync code paths.\n * Tries lock once — if fails, proceeds anyway (fail-open).\n */\nexport function withFileLockSync<T>(\n harnessDir: string,\n filePath: string,\n fn: () => T,\n options?: LockOptions,\n): T {\n const acquired = tryLock(harnessDir, filePath, options);\n\n try {\n return fn();\n } finally {\n if (acquired) {\n releaseLock(harnessDir, filePath);\n }\n }\n}\n\n/**\n * Check if a file is currently locked (by any process).\n */\nexport function isLocked(harnessDir: string, filePath: string, options?: LockOptions): boolean {\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const lockPath = getLockPath(harnessDir, filePath);\n const info = readLockInfo(lockPath);\n if (!info) return false;\n return !isStale(info, staleMs);\n}\n\n/**\n * Force-remove a lock regardless of who owns it.\n * Use only for manual cleanup via CLI.\n */\nexport function breakLock(harnessDir: string, filePath: string): boolean {\n const lockPath = getLockPath(harnessDir, filePath);\n if (!existsSync(lockPath)) return false;\n try {\n unlinkSync(lockPath);\n return true;\n } catch {\n return false;\n }\n}\n","import { writeFileSync, mkdirSync, existsSync, readdirSync, unlinkSync, copyFileSync } from 'fs';\nimport { join } from 'path';\nimport { randomUUID } from 'crypto';\nimport { withFileLockSync } from './file-lock.js';\nimport type { ToolCallInfo } from '../core/types.js';\n\nexport interface SessionRecord {\n id: string;\n started: string;\n ended: string;\n prompt: string;\n summary: string;\n tokens_used: number;\n steps: number;\n model_id?: string;\n delegated_to?: string;\n /** Tool calls executed during this session */\n tool_calls?: ToolCallInfo[];\n}\n\nexport function createSessionId(): string {\n const now = new Date();\n const date = now.toISOString().split('T')[0];\n const short = randomUUID().slice(0, 8);\n return `${date}-${short}`;\n}\n\n/** Format tool calls as markdown for session files */\nfunction formatToolCalls(toolCalls?: ToolCallInfo[]): string {\n if (!toolCalls || toolCalls.length === 0) return '';\n\n const lines = ['\\n## Tools Used\\n'];\n for (const tc of toolCalls) {\n lines.push(`### ${tc.toolName}`);\n const argsStr = JSON.stringify(tc.args, null, 2);\n lines.push(`**Args:** \\`${argsStr.length > 200 ? argsStr.slice(0, 200) + '...' : argsStr}\\``);\n if (tc.result !== null && tc.result !== undefined) {\n const resultStr = typeof tc.result === 'string' ? tc.result : JSON.stringify(tc.result);\n lines.push(`**Result:** ${resultStr.length > 300 ? resultStr.slice(0, 300) + '...' : resultStr}`);\n }\n lines.push('');\n }\n return lines.join('\\n');\n}\n\nexport function writeSession(harnessDir: string, session: SessionRecord): string {\n const sessionsDir = join(harnessDir, 'memory', 'sessions');\n if (!existsSync(sessionsDir)) {\n mkdirSync(sessionsDir, { recursive: true });\n }\n\n const filePath = join(sessionsDir, `${session.id}.md`);\n const tags = session.delegated_to\n ? `[session, delegation, ${session.delegated_to}]`\n : '[session]';\n const modelLine = session.model_id ? `\\n**Model:** ${session.model_id}` : '';\n const delegateLine = session.delegated_to ? `\\n**Delegated to:** ${session.delegated_to}` : '';\n const toolSection = formatToolCalls(session.tool_calls);\n\n const content = `---\nid: ${session.id}\ntags: ${tags}\ncreated: ${session.started}\nupdated: ${session.ended}\nauthor: agent\nstatus: active\nduration_minutes: ${Math.round((new Date(session.ended).getTime() - new Date(session.started).getTime()) / 60000)}\n---\n\n<!-- L0: Session ${session.id} — ${session.summary.slice(0, 60)} -->\n<!-- L1: ${session.summary} -->\n\n# Session: ${session.id}\n\n**Started:** ${session.started}\n**Ended:** ${session.ended}\n**Tokens:** ${session.tokens_used}\n**Steps:** ${session.steps}${modelLine}${delegateLine}\n\n## Prompt\n${session.prompt}\n\n## Summary\n${session.summary}\n${toolSection}`;\n\n withFileLockSync(harnessDir, filePath, () => {\n writeFileSync(filePath, content, 'utf-8');\n });\n return filePath;\n}\n\nexport interface CleanupResult {\n sessionsRemoved: number;\n journalsRemoved: number;\n sessionFiles: string[];\n journalFiles: string[];\n}\n\nexport interface ArchiveResult {\n sessionsArchived: number;\n journalsArchived: number;\n sessionFiles: string[];\n journalFiles: string[];\n}\n\n/**\n * Archive sessions and journals older than their configured retention periods.\n * Moves files to archive/YYYY-MM/ subdirectories instead of deleting them.\n * Archived files remain on disk for audit/query but aren't loaded by default.\n */\nexport function archiveOldFiles(\n harnessDir: string,\n sessionRetentionDays: number,\n journalRetentionDays: number,\n): ArchiveResult {\n const result: ArchiveResult = {\n sessionsArchived: 0,\n journalsArchived: 0,\n sessionFiles: [],\n journalFiles: [],\n };\n\n const now = Date.now();\n\n // Archive sessions\n const sessionsDir = join(harnessDir, 'memory', 'sessions');\n if (existsSync(sessionsDir)) {\n const cutoff = now - sessionRetentionDays * 24 * 60 * 60 * 1000;\n const files = readdirSync(sessionsDir).filter(\n (f) => f.endsWith('.md') && !f.startsWith('.') && !f.startsWith('_'),\n );\n\n for (const file of files) {\n const dateStr = extractDateFromFilename(file);\n if (dateStr && new Date(dateStr).getTime() < cutoff) {\n const yearMonth = dateStr.slice(0, 7); // YYYY-MM\n const archiveDir = join(sessionsDir, 'archive', yearMonth);\n mkdirSync(archiveDir, { recursive: true });\n copyFileSync(join(sessionsDir, file), join(archiveDir, file));\n unlinkSync(join(sessionsDir, file));\n result.sessionsArchived++;\n result.sessionFiles.push(file);\n }\n }\n }\n\n // Archive journals\n const journalDir = join(harnessDir, 'memory', 'journal');\n if (existsSync(journalDir)) {\n const cutoff = now - journalRetentionDays * 24 * 60 * 60 * 1000;\n const files = readdirSync(journalDir).filter(\n (f) => f.endsWith('.md') && !f.startsWith('.') && !f.startsWith('_'),\n );\n\n for (const file of files) {\n const dateStr = extractDateFromFilename(file);\n if (dateStr && new Date(dateStr).getTime() < cutoff) {\n const yearMonth = dateStr.slice(0, 7);\n const archiveDir = join(journalDir, 'archive', yearMonth);\n mkdirSync(archiveDir, { recursive: true });\n copyFileSync(join(journalDir, file), join(archiveDir, file));\n unlinkSync(join(journalDir, file));\n result.journalsArchived++;\n result.journalFiles.push(file);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Remove sessions and journals older than their configured retention periods.\n * @deprecated Use archiveOldFiles() instead — it preserves files in archive/.\n * This function deletes files permanently.\n */\nexport function cleanupOldFiles(\n harnessDir: string,\n sessionRetentionDays: number,\n journalRetentionDays: number,\n): CleanupResult {\n const result: CleanupResult = {\n sessionsRemoved: 0,\n journalsRemoved: 0,\n sessionFiles: [],\n journalFiles: [],\n };\n\n const now = Date.now();\n\n // Clean sessions\n const sessionsDir = join(harnessDir, 'memory', 'sessions');\n if (existsSync(sessionsDir)) {\n const cutoff = now - sessionRetentionDays * 24 * 60 * 60 * 1000;\n const files = readdirSync(sessionsDir).filter((f) => f.endsWith('.md') && !f.startsWith('.'));\n\n for (const file of files) {\n const dateStr = extractDateFromFilename(file);\n if (dateStr && new Date(dateStr).getTime() < cutoff) {\n unlinkSync(join(sessionsDir, file));\n result.sessionsRemoved++;\n result.sessionFiles.push(file);\n }\n }\n }\n\n // Clean journals\n const journalDir = join(harnessDir, 'memory', 'journal');\n if (existsSync(journalDir)) {\n const cutoff = now - journalRetentionDays * 24 * 60 * 60 * 1000;\n const files = readdirSync(journalDir).filter((f) => f.endsWith('.md') && !f.startsWith('.'));\n\n for (const file of files) {\n const dateStr = extractDateFromFilename(file);\n if (dateStr && new Date(dateStr).getTime() < cutoff) {\n unlinkSync(join(journalDir, file));\n result.journalsRemoved++;\n result.journalFiles.push(file);\n }\n }\n }\n\n return result;\n}\n\n/** Extract YYYY-MM-DD from filename like \"2026-04-06-abcdef12.md\" or \"2026-04-06.md\" */\nfunction extractDateFromFilename(filename: string): string | null {\n const match = filename.match(/^(\\d{4}-\\d{2}-\\d{2})/);\n if (!match) return null;\n const date = new Date(match[1]);\n return isNaN(date.getTime()) ? null : match[1];\n}\n\n/** List all session files with their dates */\nexport function listSessions(harnessDir: string): Array<{ id: string; date: string; path: string }> {\n const sessionsDir = join(harnessDir, 'memory', 'sessions');\n if (!existsSync(sessionsDir)) return [];\n\n return readdirSync(sessionsDir)\n .filter((f) => f.endsWith('.md') && !f.startsWith('.'))\n .sort()\n .reverse()\n .map((f) => ({\n id: f.replace('.md', ''),\n date: extractDateFromFilename(f) || 'unknown',\n path: join(sessionsDir, f),\n }));\n}\n\n/** List files that would be removed by cleanup (dry run — doesn't delete) */\nexport function listExpiredFiles(\n harnessDir: string,\n sessionRetentionDays: number,\n journalRetentionDays: number,\n): { sessionFiles: string[]; journalFiles: string[] } {\n const now = Date.now();\n const sessionFiles: string[] = [];\n const journalFiles: string[] = [];\n\n const sessionsDir = join(harnessDir, 'memory', 'sessions');\n if (existsSync(sessionsDir)) {\n const cutoff = now - sessionRetentionDays * 24 * 60 * 60 * 1000;\n const files = readdirSync(sessionsDir).filter((f) => f.endsWith('.md') && !f.startsWith('.'));\n for (const file of files) {\n const dateStr = extractDateFromFilename(file);\n if (dateStr && new Date(dateStr).getTime() < cutoff) {\n sessionFiles.push(file);\n }\n }\n }\n\n const journalDir = join(harnessDir, 'memory', 'journal');\n if (existsSync(journalDir)) {\n const cutoff = now - journalRetentionDays * 24 * 60 * 60 * 1000;\n const files = readdirSync(journalDir).filter((f) => f.endsWith('.md') && !f.startsWith('.'));\n for (const file of files) {\n const dateStr = extractDateFromFilename(file);\n if (dateStr && new Date(dateStr).getTime() < cutoff) {\n journalFiles.push(file);\n }\n }\n }\n\n return { sessionFiles, journalFiles };\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\n\n/** Cost per 1M tokens for a model (input and output separately) */\nexport interface ModelPricing {\n model_pattern: string;\n input_per_million: number;\n output_per_million: number;\n}\n\n/** A recorded cost event */\nexport interface CostEntry {\n timestamp: string;\n model_id: string;\n provider: string;\n input_tokens: number;\n output_tokens: number;\n cost_usd: number;\n source: string;\n}\n\n/** Budget configuration */\nexport interface BudgetConfig {\n daily_limit_usd?: number;\n monthly_limit_usd?: number;\n alert_threshold_pct?: number;\n}\n\n/** Budget status check result */\nexport interface BudgetStatus {\n daily_spent_usd: number;\n daily_limit_usd: number | null;\n daily_remaining_usd: number | null;\n daily_pct: number | null;\n monthly_spent_usd: number;\n monthly_limit_usd: number | null;\n monthly_remaining_usd: number | null;\n monthly_pct: number | null;\n alerts: string[];\n}\n\n/** Spending summary for a time period */\nexport interface SpendingSummary {\n total_cost_usd: number;\n total_input_tokens: number;\n total_output_tokens: number;\n entries: number;\n by_model: Record<string, { cost_usd: number; input_tokens: number; output_tokens: number; count: number }>;\n by_provider: Record<string, { cost_usd: number; count: number }>;\n}\n\n/** Persisted cost store */\nexport interface CostStore {\n entries: CostEntry[];\n updated: string;\n}\n\nconst COST_FILE = 'costs.json';\nconst MAX_ENTRIES = 5000;\n\n/** Default pricing for common models (per 1M tokens) */\nconst DEFAULT_PRICING: ModelPricing[] = [\n // Anthropic via OpenRouter\n { model_pattern: 'anthropic/claude-sonnet-4', input_per_million: 3.0, output_per_million: 15.0 },\n { model_pattern: 'anthropic/claude-opus-4', input_per_million: 15.0, output_per_million: 75.0 },\n { model_pattern: 'anthropic/claude-haiku-3.5', input_per_million: 0.8, output_per_million: 4.0 },\n // Direct Anthropic\n { model_pattern: 'claude-sonnet-4', input_per_million: 3.0, output_per_million: 15.0 },\n { model_pattern: 'claude-opus-4', input_per_million: 15.0, output_per_million: 75.0 },\n { model_pattern: 'claude-haiku-3.5', input_per_million: 0.8, output_per_million: 4.0 },\n // OpenAI\n { model_pattern: 'openai/gpt-4o', input_per_million: 2.5, output_per_million: 10.0 },\n { model_pattern: 'gpt-4o', input_per_million: 2.5, output_per_million: 10.0 },\n { model_pattern: 'openai/gpt-4o-mini', input_per_million: 0.15, output_per_million: 0.6 },\n { model_pattern: 'gpt-4o-mini', input_per_million: 0.15, output_per_million: 0.6 },\n // Local models\n { model_pattern: 'local/', input_per_million: 0, output_per_million: 0 },\n];\n\nfunction getStorePath(harnessDir: string): string {\n return join(harnessDir, 'memory', COST_FILE);\n}\n\n/**\n * Load cost entries from disk.\n */\nexport function loadCosts(harnessDir: string): CostStore {\n const storePath = getStorePath(harnessDir);\n if (!existsSync(storePath)) {\n return { entries: [], updated: new Date().toISOString() };\n }\n\n try {\n const content = readFileSync(storePath, 'utf-8');\n const parsed: unknown = JSON.parse(content);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n 'entries' in parsed &&\n Array.isArray((parsed as CostStore).entries)\n ) {\n return parsed as CostStore;\n }\n return { entries: [], updated: new Date().toISOString() };\n } catch {\n return { entries: [], updated: new Date().toISOString() };\n }\n}\n\n/**\n * Save cost entries to disk. Trims to MAX_ENTRIES.\n */\nexport function saveCosts(harnessDir: string, store: CostStore): void {\n const memoryDir = join(harnessDir, 'memory');\n if (!existsSync(memoryDir)) {\n mkdirSync(memoryDir, { recursive: true });\n }\n\n if (store.entries.length > MAX_ENTRIES) {\n store.entries = store.entries.slice(store.entries.length - MAX_ENTRIES);\n }\n\n store.updated = new Date().toISOString();\n writeFileSync(getStorePath(harnessDir), JSON.stringify(store, null, 2), 'utf-8');\n}\n\n/**\n * Find pricing for a model ID. Uses prefix matching against DEFAULT_PRICING.\n * Custom pricing can be passed to override defaults.\n */\nexport function findPricing(\n modelId: string,\n customPricing?: ModelPricing[],\n): ModelPricing | null {\n const allPricing = [...(customPricing ?? []), ...DEFAULT_PRICING];\n\n for (const pricing of allPricing) {\n if (modelId === pricing.model_pattern || modelId.startsWith(pricing.model_pattern)) {\n return pricing;\n }\n }\n\n return null;\n}\n\n/**\n * Calculate cost in USD for a given usage.\n */\nexport function calculateCost(\n modelId: string,\n inputTokens: number,\n outputTokens: number,\n customPricing?: ModelPricing[],\n): number {\n const pricing = findPricing(modelId, customPricing);\n if (!pricing) return 0;\n\n const inputCost = (inputTokens / 1_000_000) * pricing.input_per_million;\n const outputCost = (outputTokens / 1_000_000) * pricing.output_per_million;\n return Math.round((inputCost + outputCost) * 1_000_000) / 1_000_000;\n}\n\n/**\n * Record a cost entry.\n */\nexport function recordCost(\n harnessDir: string,\n entry: Omit<CostEntry, 'timestamp' | 'cost_usd'> & { cost_usd?: number },\n customPricing?: ModelPricing[],\n): CostEntry {\n const store = loadCosts(harnessDir);\n\n const costUsd = entry.cost_usd ?? calculateCost(\n entry.model_id,\n entry.input_tokens,\n entry.output_tokens,\n customPricing,\n );\n\n const fullEntry: CostEntry = {\n timestamp: new Date().toISOString(),\n model_id: entry.model_id,\n provider: entry.provider,\n input_tokens: entry.input_tokens,\n output_tokens: entry.output_tokens,\n cost_usd: costUsd,\n source: entry.source,\n };\n\n store.entries.push(fullEntry);\n saveCosts(harnessDir, store);\n\n return fullEntry;\n}\n\n/**\n * Get spending summary for a date range.\n * Defaults to today if no range specified.\n */\nexport function getSpending(\n harnessDir: string,\n from?: string,\n to?: string,\n): SpendingSummary {\n const store = loadCosts(harnessDir);\n\n const fromDate = from ?? new Date().toISOString().split('T')[0];\n const toDate = to ?? new Date(Date.now() + 86400000).toISOString().split('T')[0];\n\n const filtered = store.entries.filter(\n (e) => e.timestamp >= fromDate && e.timestamp < toDate + 'T99',\n );\n\n const byModel: SpendingSummary['by_model'] = {};\n const byProvider: SpendingSummary['by_provider'] = {};\n\n let totalCost = 0;\n let totalInput = 0;\n let totalOutput = 0;\n\n for (const entry of filtered) {\n totalCost += entry.cost_usd;\n totalInput += entry.input_tokens;\n totalOutput += entry.output_tokens;\n\n if (!byModel[entry.model_id]) {\n byModel[entry.model_id] = { cost_usd: 0, input_tokens: 0, output_tokens: 0, count: 0 };\n }\n byModel[entry.model_id].cost_usd += entry.cost_usd;\n byModel[entry.model_id].input_tokens += entry.input_tokens;\n byModel[entry.model_id].output_tokens += entry.output_tokens;\n byModel[entry.model_id].count += 1;\n\n if (!byProvider[entry.provider]) {\n byProvider[entry.provider] = { cost_usd: 0, count: 0 };\n }\n byProvider[entry.provider].cost_usd += entry.cost_usd;\n byProvider[entry.provider].count += 1;\n }\n\n return {\n total_cost_usd: Math.round(totalCost * 1_000_000) / 1_000_000,\n total_input_tokens: totalInput,\n total_output_tokens: totalOutput,\n entries: filtered.length,\n by_model: byModel,\n by_provider: byProvider,\n };\n}\n\n/**\n * Check budget status against configured limits.\n */\nexport function checkBudget(\n harnessDir: string,\n budget: BudgetConfig,\n): BudgetStatus {\n const now = new Date();\n const today = now.toISOString().split('T')[0];\n const monthStart = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-01`;\n\n const dailySpending = getSpending(harnessDir, today);\n const monthlySpending = getSpending(harnessDir, monthStart);\n\n const alerts: string[] = [];\n const alertPct = budget.alert_threshold_pct ?? 80;\n\n const dailyLimit = budget.daily_limit_usd ?? null;\n const monthlyLimit = budget.monthly_limit_usd ?? null;\n\n let dailyPct: number | null = null;\n let dailyRemaining: number | null = null;\n\n if (dailyLimit !== null) {\n dailyPct = dailyLimit > 0 ? (dailySpending.total_cost_usd / dailyLimit) * 100 : 0;\n dailyRemaining = Math.max(0, dailyLimit - dailySpending.total_cost_usd);\n\n if (dailySpending.total_cost_usd >= dailyLimit) {\n alerts.push(`Daily budget exceeded: $${dailySpending.total_cost_usd.toFixed(4)} / $${dailyLimit.toFixed(2)}`);\n } else if (dailyPct >= alertPct) {\n alerts.push(`Daily budget at ${dailyPct.toFixed(0)}%: $${dailySpending.total_cost_usd.toFixed(4)} / $${dailyLimit.toFixed(2)}`);\n }\n }\n\n let monthlyPct: number | null = null;\n let monthlyRemaining: number | null = null;\n\n if (monthlyLimit !== null) {\n monthlyPct = monthlyLimit > 0 ? (monthlySpending.total_cost_usd / monthlyLimit) * 100 : 0;\n monthlyRemaining = Math.max(0, monthlyLimit - monthlySpending.total_cost_usd);\n\n if (monthlySpending.total_cost_usd >= monthlyLimit) {\n alerts.push(`Monthly budget exceeded: $${monthlySpending.total_cost_usd.toFixed(4)} / $${monthlyLimit.toFixed(2)}`);\n } else if (monthlyPct >= alertPct) {\n alerts.push(`Monthly budget at ${monthlyPct.toFixed(0)}%: $${monthlySpending.total_cost_usd.toFixed(4)} / $${monthlyLimit.toFixed(2)}`);\n }\n }\n\n return {\n daily_spent_usd: dailySpending.total_cost_usd,\n daily_limit_usd: dailyLimit,\n daily_remaining_usd: dailyRemaining,\n daily_pct: dailyPct,\n monthly_spent_usd: monthlySpending.total_cost_usd,\n monthly_limit_usd: monthlyLimit,\n monthly_remaining_usd: monthlyRemaining,\n monthly_pct: monthlyPct,\n alerts,\n };\n}\n\n/**\n * Clear all cost entries, or entries for a specific model.\n */\nexport function clearCosts(harnessDir: string, modelId?: string): number {\n const store = loadCosts(harnessDir);\n const before = store.entries.length;\n\n if (modelId) {\n store.entries = store.entries.filter((e) => e.model_id !== modelId);\n } else {\n store.entries = [];\n }\n\n saveCosts(harnessDir, store);\n return before - store.entries.length;\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { getSpending } from './cost-tracker.js';\n\n/** Individual health check result */\nexport interface HealthCheck {\n name: string;\n status: 'pass' | 'warn' | 'fail';\n message: string;\n}\n\n/** Persisted health metrics */\nexport interface HealthMetrics {\n lastSuccessfulRun: string | null;\n lastFailedRun: string | null;\n lastError: string | null;\n consecutiveFailures: number;\n totalRuns: number;\n totalSuccesses: number;\n totalFailures: number;\n bootedAt: string | null;\n updatedAt: string;\n}\n\n/** Overall health status */\nexport interface HealthStatus {\n status: 'healthy' | 'degraded' | 'unhealthy';\n checks: HealthCheck[];\n metrics: HealthMetrics;\n costToday: number;\n costThisMonth: number;\n}\n\nconst HEALTH_FILE = 'health.json';\n\nfunction getHealthPath(harnessDir: string): string {\n return join(harnessDir, 'memory', HEALTH_FILE);\n}\n\nfunction defaultMetrics(): HealthMetrics {\n return {\n lastSuccessfulRun: null,\n lastFailedRun: null,\n lastError: null,\n consecutiveFailures: 0,\n totalRuns: 0,\n totalSuccesses: 0,\n totalFailures: 0,\n bootedAt: null,\n updatedAt: new Date().toISOString(),\n };\n}\n\n/**\n * Load health metrics from disk.\n */\nexport function loadHealth(harnessDir: string): HealthMetrics {\n const healthPath = getHealthPath(harnessDir);\n if (!existsSync(healthPath)) {\n return defaultMetrics();\n }\n\n try {\n const content = readFileSync(healthPath, 'utf-8');\n const parsed: unknown = JSON.parse(content);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n 'totalRuns' in parsed\n ) {\n return parsed as HealthMetrics;\n }\n return defaultMetrics();\n } catch {\n return defaultMetrics();\n }\n}\n\n/**\n * Save health metrics to disk.\n */\nexport function saveHealth(harnessDir: string, metrics: HealthMetrics): void {\n const memoryDir = join(harnessDir, 'memory');\n if (!existsSync(memoryDir)) {\n mkdirSync(memoryDir, { recursive: true });\n }\n\n metrics.updatedAt = new Date().toISOString();\n writeFileSync(getHealthPath(harnessDir), JSON.stringify(metrics, null, 2), 'utf-8');\n}\n\n/**\n * Record a successful run.\n */\nexport function recordSuccess(harnessDir: string): void {\n const metrics = loadHealth(harnessDir);\n metrics.totalRuns++;\n metrics.totalSuccesses++;\n metrics.consecutiveFailures = 0;\n metrics.lastSuccessfulRun = new Date().toISOString();\n saveHealth(harnessDir, metrics);\n}\n\n/**\n * Record a failed run.\n */\nexport function recordFailure(harnessDir: string, error?: string): void {\n const metrics = loadHealth(harnessDir);\n metrics.totalRuns++;\n metrics.totalFailures++;\n metrics.consecutiveFailures++;\n metrics.lastFailedRun = new Date().toISOString();\n metrics.lastError = error ?? null;\n saveHealth(harnessDir, metrics);\n}\n\n/**\n * Record boot time.\n */\nexport function recordBoot(harnessDir: string): void {\n const metrics = loadHealth(harnessDir);\n metrics.bootedAt = new Date().toISOString();\n saveHealth(harnessDir, metrics);\n}\n\n/**\n * Run all health checks and return overall status.\n */\nexport function getHealthStatus(harnessDir: string): HealthStatus {\n const metrics = loadHealth(harnessDir);\n const checks: HealthCheck[] = [];\n\n // Check 1: Required files exist\n const requiredFiles = ['CORE.md', 'config.yaml', 'state.md'];\n const missingFiles = requiredFiles.filter((f) => !existsSync(join(harnessDir, f)));\n if (missingFiles.length === 0) {\n checks.push({ name: 'core-files', status: 'pass', message: 'All core files present' });\n } else {\n checks.push({ name: 'core-files', status: 'fail', message: `Missing: ${missingFiles.join(', ')}` });\n }\n\n // Check 2: Memory directory exists\n const memoryDir = join(harnessDir, 'memory');\n if (existsSync(memoryDir)) {\n checks.push({ name: 'memory-dir', status: 'pass', message: 'Memory directory exists' });\n } else {\n checks.push({ name: 'memory-dir', status: 'fail', message: 'Memory directory missing' });\n }\n\n // Check 3: API key availability\n const apiKeys: Array<{ name: string; envVar: string }> = [\n { name: 'OpenRouter', envVar: 'OPENROUTER_API_KEY' },\n { name: 'Anthropic', envVar: 'ANTHROPIC_API_KEY' },\n { name: 'OpenAI', envVar: 'OPENAI_API_KEY' },\n ];\n const presentKeys = apiKeys.filter((k) => process.env[k.envVar]);\n if (presentKeys.length > 0) {\n checks.push({\n name: 'api-keys',\n status: 'pass',\n message: `API keys: ${presentKeys.map((k) => k.name).join(', ')}`,\n });\n } else {\n checks.push({ name: 'api-keys', status: 'warn', message: 'No API keys found in environment' });\n }\n\n // Check 4: Consecutive failures\n if (metrics.consecutiveFailures === 0) {\n checks.push({ name: 'run-health', status: 'pass', message: 'No consecutive failures' });\n } else if (metrics.consecutiveFailures < 3) {\n checks.push({\n name: 'run-health',\n status: 'warn',\n message: `${metrics.consecutiveFailures} consecutive failure(s)`,\n });\n } else {\n checks.push({\n name: 'run-health',\n status: 'fail',\n message: `${metrics.consecutiveFailures} consecutive failures — last error: ${metrics.lastError ?? 'unknown'}`,\n });\n }\n\n // Check 5: Last run recency (warn if no successful run in 24h when there have been runs)\n if (metrics.lastSuccessfulRun) {\n const hoursSinceSuccess = (Date.now() - new Date(metrics.lastSuccessfulRun).getTime()) / 3600000;\n if (hoursSinceSuccess < 24) {\n checks.push({ name: 'last-success', status: 'pass', message: `Last success: ${metrics.lastSuccessfulRun}` });\n } else {\n checks.push({\n name: 'last-success',\n status: 'warn',\n message: `Last success was ${Math.round(hoursSinceSuccess)}h ago`,\n });\n }\n } else if (metrics.totalRuns > 0) {\n checks.push({ name: 'last-success', status: 'warn', message: 'No successful runs recorded' });\n }\n\n // Cost checks\n let costToday = 0;\n let costThisMonth = 0;\n\n try {\n const today = new Date().toISOString().split('T')[0];\n const monthStart = `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-01`;\n costToday = getSpending(harnessDir, today).total_cost_usd;\n costThisMonth = getSpending(harnessDir, monthStart).total_cost_usd;\n } catch {\n // Cost data may not exist\n }\n\n // Determine overall status\n const failCount = checks.filter((c) => c.status === 'fail').length;\n const warnCount = checks.filter((c) => c.status === 'warn').length;\n\n let status: HealthStatus['status'];\n if (failCount > 0) {\n status = 'unhealthy';\n } else if (warnCount > 0) {\n status = 'degraded';\n } else {\n status = 'healthy';\n }\n\n return { status, checks, metrics, costToday, costThisMonth };\n}\n\n/**\n * Reset health metrics (for testing or fresh start).\n */\nexport function resetHealth(harnessDir: string): void {\n saveHealth(harnessDir, defaultMetrics());\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\n\n/** A recorded event in the sliding window */\nexport interface RateEvent {\n key: string;\n timestamp: number;\n}\n\n/** Rate limit rule: max requests per window_ms */\nexport interface RateLimit {\n key: string;\n max_requests: number;\n window_ms: number;\n}\n\n/** Result of a rate limit check */\nexport interface RateLimitCheck {\n allowed: boolean;\n key: string;\n current: number;\n max: number;\n window_ms: number;\n /** ms until oldest event expires (0 if allowed) */\n retry_after_ms: number;\n}\n\n/** Persisted rate limit state */\nexport interface RateLimitStore {\n events: RateEvent[];\n updated: string;\n}\n\nconst RATE_FILE = 'rate-limits.json';\nconst MAX_EVENTS = 10000;\n\nfunction getStorePath(harnessDir: string): string {\n return join(harnessDir, 'memory', RATE_FILE);\n}\n\n/**\n * Load rate limit events from disk.\n * Returns empty store if file doesn't exist or is corrupt.\n */\nexport function loadRateLimits(harnessDir: string): RateLimitStore {\n const storePath = getStorePath(harnessDir);\n if (!existsSync(storePath)) {\n return { events: [], updated: new Date().toISOString() };\n }\n\n try {\n const content = readFileSync(storePath, 'utf-8');\n const parsed: unknown = JSON.parse(content);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n 'events' in parsed &&\n Array.isArray((parsed as RateLimitStore).events)\n ) {\n return parsed as RateLimitStore;\n }\n return { events: [], updated: new Date().toISOString() };\n } catch {\n return { events: [], updated: new Date().toISOString() };\n }\n}\n\n/**\n * Save rate limit events to disk. Trims to MAX_EVENTS.\n */\nexport function saveRateLimits(harnessDir: string, store: RateLimitStore): void {\n const memoryDir = join(harnessDir, 'memory');\n if (!existsSync(memoryDir)) {\n mkdirSync(memoryDir, { recursive: true });\n }\n\n if (store.events.length > MAX_EVENTS) {\n store.events = store.events.slice(store.events.length - MAX_EVENTS);\n }\n\n store.updated = new Date().toISOString();\n writeFileSync(getStorePath(harnessDir), JSON.stringify(store, null, 2), 'utf-8');\n}\n\n/**\n * Prune expired events from the store (older than the largest known window).\n */\nfunction pruneExpired(store: RateLimitStore, now: number, maxWindowMs: number): void {\n const cutoff = now - maxWindowMs;\n store.events = store.events.filter((e) => e.timestamp > cutoff);\n}\n\n/**\n * Check if a request is allowed under the given rate limit.\n * Does NOT record the event — call recordEvent() separately on success.\n */\nexport function checkRateLimit(\n harnessDir: string,\n limit: RateLimit,\n now?: number,\n): RateLimitCheck {\n const currentTime = now ?? Date.now();\n const store = loadRateLimits(harnessDir);\n\n const windowStart = currentTime - limit.window_ms;\n const eventsInWindow = store.events.filter(\n (e) => e.key === limit.key && e.timestamp > windowStart,\n );\n\n const current = eventsInWindow.length;\n const allowed = current < limit.max_requests;\n\n let retryAfterMs = 0;\n if (!allowed && eventsInWindow.length > 0) {\n // Time until the oldest event in the window expires\n const oldest = eventsInWindow.reduce((min, e) => Math.min(min, e.timestamp), Infinity);\n retryAfterMs = Math.max(0, oldest + limit.window_ms - currentTime);\n }\n\n return {\n allowed,\n key: limit.key,\n current,\n max: limit.max_requests,\n window_ms: limit.window_ms,\n retry_after_ms: retryAfterMs,\n };\n}\n\n/**\n * Record a rate limit event for a key.\n */\nexport function recordEvent(harnessDir: string, key: string, now?: number): void {\n const currentTime = now ?? Date.now();\n const store = loadRateLimits(harnessDir);\n\n store.events.push({ key, timestamp: currentTime });\n\n // Prune events older than 1 hour to keep the store manageable\n pruneExpired(store, currentTime, 3600000);\n\n saveRateLimits(harnessDir, store);\n}\n\n/**\n * Check rate limit AND record the event if allowed.\n * Returns the check result. If not allowed, does NOT record.\n */\nexport function tryAcquire(\n harnessDir: string,\n limit: RateLimit,\n now?: number,\n): RateLimitCheck {\n const currentTime = now ?? Date.now();\n const check = checkRateLimit(harnessDir, limit, currentTime);\n\n if (check.allowed) {\n recordEvent(harnessDir, limit.key, currentTime);\n }\n\n return check;\n}\n\n/**\n * Get current usage for a key within a window.\n */\nexport function getUsage(\n harnessDir: string,\n key: string,\n windowMs: number,\n now?: number,\n): { count: number; oldest: number | null; newest: number | null } {\n const currentTime = now ?? Date.now();\n const store = loadRateLimits(harnessDir);\n\n const windowStart = currentTime - windowMs;\n const eventsInWindow = store.events.filter(\n (e) => e.key === key && e.timestamp > windowStart,\n );\n\n if (eventsInWindow.length === 0) {\n return { count: 0, oldest: null, newest: null };\n }\n\n const timestamps = eventsInWindow.map((e) => e.timestamp);\n return {\n count: eventsInWindow.length,\n oldest: Math.min(...timestamps),\n newest: Math.max(...timestamps),\n };\n}\n\n/**\n * Clear all rate limit events for a key, or all keys.\n */\nexport function clearRateLimits(harnessDir: string, key?: string): number {\n const store = loadRateLimits(harnessDir);\n const before = store.events.length;\n\n if (key) {\n store.events = store.events.filter((e) => e.key !== key);\n } else {\n store.events = [];\n }\n\n saveRateLimits(harnessDir, store);\n return before - store.events.length;\n}\n","import { recordEvent, checkRateLimit } from './rate-limiter.js';\nimport { checkBudget } from './cost-tracker.js';\nimport type { HarnessConfig } from '../core/types.js';\nimport type { RateLimit, RateLimitCheck } from './rate-limiter.js';\nimport type { BudgetStatus } from './cost-tracker.js';\n\n/** Result of a guardrail check before an LLM call. */\nexport interface GuardrailResult {\n allowed: boolean;\n reason: string | null;\n rateLimitCheck: RateLimitCheck | null;\n budgetStatus: BudgetStatus | null;\n /** Suggested wait time in ms if rate-limited (0 otherwise) */\n retryAfterMs: number;\n}\n\nconst RATE_KEY = 'llm-calls';\n\n/**\n * Build rate limit rules from config.\n * Returns an array of limits to check (per-minute, per-hour, per-day).\n */\nexport function buildRateLimits(config: HarnessConfig): RateLimit[] {\n const limits: RateLimit[] = [];\n const rl = config.rate_limits;\n\n if (rl?.per_minute) {\n limits.push({ key: `${RATE_KEY}:minute`, max_requests: rl.per_minute, window_ms: 60_000 });\n }\n if (rl?.per_hour) {\n limits.push({ key: `${RATE_KEY}:hour`, max_requests: rl.per_hour, window_ms: 3_600_000 });\n }\n if (rl?.per_day) {\n limits.push({ key: `${RATE_KEY}:day`, max_requests: rl.per_day, window_ms: 86_400_000 });\n }\n\n return limits;\n}\n\n/**\n * Check all guardrails (rate limits + budget) before an LLM call.\n *\n * Rate limits: Checks all configured limits. If any limit is exceeded,\n * the call is blocked with `retry_after_ms` from the first violated limit.\n *\n * Budget: Checks daily and monthly spending limits. If `budget.enforce` is true\n * and any limit is exceeded, the call is blocked.\n *\n * Returns { allowed: true } if all checks pass.\n */\nexport function checkGuardrails(\n harnessDir: string,\n config: HarnessConfig,\n): GuardrailResult {\n // Check rate limits\n const limits = buildRateLimits(config);\n for (const limit of limits) {\n const check = checkRateLimit(harnessDir, limit);\n if (!check.allowed) {\n const windowLabel = limit.window_ms <= 60_000 ? 'minute' : limit.window_ms <= 3_600_000 ? 'hour' : 'day';\n return {\n allowed: false,\n reason: `Rate limit exceeded: ${check.current}/${check.max} calls per ${windowLabel}. Retry after ${Math.ceil(check.retry_after_ms / 1000)}s.`,\n rateLimitCheck: check,\n budgetStatus: null,\n retryAfterMs: check.retry_after_ms,\n };\n }\n }\n\n // Check budget\n const budgetConfig = config.budget;\n if (budgetConfig?.enforce !== false && (budgetConfig?.daily_limit_usd || budgetConfig?.monthly_limit_usd)) {\n const status = checkBudget(harnessDir, {\n daily_limit_usd: budgetConfig.daily_limit_usd,\n monthly_limit_usd: budgetConfig.monthly_limit_usd,\n });\n\n const exceeded = status.alerts.some((a) => a.includes('exceeded'));\n if (exceeded) {\n return {\n allowed: false,\n reason: status.alerts.filter((a) => a.includes('exceeded')).join('; '),\n rateLimitCheck: null,\n budgetStatus: status,\n retryAfterMs: 0,\n };\n }\n }\n\n // All checks pass — record rate limit events for all configured limits\n const now = Date.now();\n for (const limit of limits) {\n recordEvent(harnessDir, limit.key, now);\n }\n\n return {\n allowed: true,\n reason: null,\n rateLimitCheck: null,\n budgetStatus: null,\n retryAfterMs: 0,\n };\n}\n","import { tool as aiTool, jsonSchema, type ToolSet } from 'ai';\nimport { z } from 'zod';\nimport { loadTools, type ToolDefinition, type ToolOperation } from './tools.js';\nimport type { HarnessConfig } from '../core/types.js';\nimport { log } from '../core/logger.js';\n\n// --- Types ---\n\n/** Result of a single tool execution */\nexport interface ToolCallResult {\n toolName: string;\n input: Record<string, unknown>;\n output: unknown;\n durationMs: number;\n error: string | null;\n}\n\n/** Record of all tool calls in a run (for session recording) */\nexport interface ToolCallRecord {\n calls: ToolCallResult[];\n totalDurationMs: number;\n}\n\n/** A programmatic tool definition (not from markdown) */\nexport interface ProgrammaticTool {\n name: string;\n description: string;\n inputSchema: z.ZodType;\n execute: (input: Record<string, unknown>) => Promise<unknown>;\n}\n\n/** Configuration for tool execution */\nexport interface ToolExecutorConfig {\n /** Maximum tool calls per run (default: 10) */\n maxToolCalls?: number;\n /** Timeout per tool call in ms (default: 30000) */\n toolTimeoutMs?: number;\n /** Whether to allow HTTP tool execution (default: true) */\n allowHttpExecution?: boolean;\n /** Additional programmatic tools */\n tools?: ProgrammaticTool[];\n}\n\n/** AI SDK ToolSet — record of named tool definitions */\nexport type AIToolSet = ToolSet;\n\n// --- HTTP Execution ---\n\n/**\n * Resolve a URL template by replacing `{param}` placeholders with input values.\n * E.g., `/repos/{owner}/{repo}/pulls` with { owner: 'a', repo: 'b' } → `/repos/a/b/pulls`\n */\nexport function resolveEndpoint(endpoint: string, input: Record<string, unknown>): string {\n return endpoint.replace(/\\{(\\w+)\\}/g, (_match, key: string) => {\n const value = input[key];\n if (value === undefined || value === null) {\n return `{${key}}`;\n }\n return encodeURIComponent(String(value));\n });\n}\n\n/**\n * Build a JSON Schema object for a tool operation's URL parameters.\n * Extracts `{param}` patterns from the endpoint URL and creates string properties for each.\n */\nexport function buildOperationSchema(operation: ToolOperation): Record<string, unknown> {\n const params: string[] = [];\n const paramRegex = /\\{(\\w+)\\}/g;\n let match: RegExpExecArray | null;\n while ((match = paramRegex.exec(operation.endpoint)) !== null) {\n params.push(match[1]);\n }\n\n const properties: Record<string, { type: string; description: string }> = {};\n for (const param of params) {\n properties[param] = { type: 'string', description: `Value for ${param}` };\n }\n\n // Add a body property for POST/PUT/PATCH\n if (['POST', 'PUT', 'PATCH'].includes(operation.method)) {\n properties['body'] = { type: 'string', description: 'Request body (JSON string)' };\n }\n\n // Add optional query parameters\n properties['query'] = { type: 'string', description: 'Query parameters (key=value&key2=value2)' };\n\n return {\n type: 'object',\n properties,\n required: params,\n };\n}\n\n/**\n * Execute an HTTP tool operation.\n * Resolves URL parameters, attaches auth headers, and makes the HTTP request.\n */\nexport async function executeHttpOperation(\n operation: ToolOperation,\n baseUrl: string,\n authHeaders: Record<string, string>,\n input: Record<string, unknown>,\n timeoutMs: number,\n): Promise<unknown> {\n const resolvedPath = resolveEndpoint(operation.endpoint, input);\n let url = resolvedPath.startsWith('http') ? resolvedPath : `${baseUrl}${resolvedPath}`;\n\n // Append query parameters if provided\n const query = input['query'];\n if (typeof query === 'string' && query.length > 0) {\n const separator = url.includes('?') ? '&' : '?';\n url = `${url}${separator}${query}`;\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n ...authHeaders,\n };\n\n const fetchOptions: RequestInit = {\n method: operation.method,\n headers,\n signal: AbortSignal.timeout(timeoutMs),\n };\n\n // Attach body for methods that support it\n if (['POST', 'PUT', 'PATCH'].includes(operation.method)) {\n const body = input['body'];\n if (typeof body === 'string') {\n fetchOptions.body = body;\n } else if (body !== undefined && body !== null) {\n fetchOptions.body = JSON.stringify(body);\n }\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`HTTP ${response.status} ${response.statusText}: ${errorText.slice(0, 500)}`);\n }\n\n const contentType = response.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) {\n return response.json() as Promise<unknown>;\n }\n return response.text();\n}\n\n// --- Tool Conversion ---\n\n/**\n * Sanitize a tool name for the AI SDK.\n * Tool names must be alphanumeric with underscores/hyphens only.\n */\nfunction sanitizeToolName(name: string): string {\n return name\n .replace(/[^a-zA-Z0-9_-]/g, '_')\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '')\n .slice(0, 64);\n}\n\n/**\n * Extract a base URL from the tool's operations or body.\n * Looks for full URLs in operations, or common API URL patterns in the body.\n */\nfunction extractBaseUrl(toolDef: ToolDefinition): string {\n // Check operations for full URLs\n for (const op of toolDef.operations) {\n if (op.endpoint.startsWith('http')) {\n try {\n const url = new URL(op.endpoint);\n return `${url.protocol}//${url.host}`;\n } catch {\n // not a valid URL\n }\n }\n }\n\n // Try to find API base URL in the document body\n const urlMatch = toolDef.doc.body.match(/(?:base[_ ]?url|api[_ ]?url|endpoint)\\s*[:=]\\s*`?(https?:\\/\\/[^\\s`\"']+)/i);\n if (urlMatch) {\n try {\n const url = new URL(urlMatch[1]);\n return `${url.protocol}//${url.host}`;\n } catch {\n // not a valid URL\n }\n }\n\n return '';\n}\n\n/**\n * Build auth headers from a tool's auth configuration.\n * Maps known env var patterns to standard header formats.\n */\nexport function buildAuthHeaders(toolDef: ToolDefinition): Record<string, string> {\n const headers: Record<string, string> = {};\n\n for (const auth of toolDef.auth) {\n const value = process.env[auth.envVar];\n if (!value) continue;\n\n // Common patterns for auth header mapping (check specific patterns first)\n const envLower = auth.envVar.toLowerCase();\n if (envLower.includes('bot_token')) {\n headers['Authorization'] = `Bot ${value}`;\n } else if (envLower.includes('token') || envLower.includes('api_key') || envLower.includes('apikey')) {\n headers['Authorization'] = `Bearer ${value}`;\n } else {\n // Generic: use as Bearer token\n headers['Authorization'] = `Bearer ${value}`;\n }\n }\n\n return headers;\n}\n\n/**\n * Convert a single ToolDefinition (from markdown) into AI SDK tools.\n * Each operation becomes a separate tool entry.\n */\nexport function convertToolDefinition(\n toolDef: ToolDefinition,\n config: ToolExecutorConfig,\n): AIToolSet {\n const tools: AIToolSet = {};\n const baseUrl = extractBaseUrl(toolDef);\n const allowHttp = config.allowHttpExecution !== false;\n const timeoutMs = config.toolTimeoutMs ?? 30_000;\n\n for (const operation of toolDef.operations) {\n const toolName = sanitizeToolName(`${toolDef.id}_${operation.name}`);\n const opSchema = buildOperationSchema(operation);\n\n tools[toolName] = aiTool({\n description: `[${toolDef.id}] ${operation.method} ${operation.endpoint} — ${toolDef.doc.l0}`,\n inputSchema: jsonSchema<Record<string, unknown>>(opSchema),\n execute: async (input) => {\n const typedInput = input;\n\n if (!allowHttp) {\n return { error: 'HTTP tool execution is disabled' };\n }\n\n // Check auth\n const missingAuth = toolDef.auth.filter((a) => !process.env[a.envVar]);\n if (missingAuth.length > 0) {\n return {\n error: `Missing required auth: ${missingAuth.map((a) => a.envVar).join(', ')}`,\n };\n }\n\n const authHeaders = buildAuthHeaders(toolDef);\n\n try {\n const result = await executeHttpOperation(\n operation,\n baseUrl,\n authHeaders,\n typedInput,\n timeoutMs,\n );\n return result;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n log.error(`Tool ${toolName} execution failed: ${message}`);\n return { error: message };\n }\n },\n });\n }\n\n return tools;\n}\n\n/**\n * Convert a programmatic tool definition into an AI SDK tool.\n */\nfunction convertProgrammaticTool(pt: ProgrammaticTool): AIToolSet {\n const toolName = sanitizeToolName(pt.name);\n\n return {\n [toolName]: aiTool({\n description: pt.description,\n inputSchema: pt.inputSchema,\n execute: async (input: unknown) => {\n try {\n return await pt.execute(input as Record<string, unknown>);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n log.error(`Tool ${toolName} execution failed: ${message}`);\n return { error: message };\n }\n },\n }),\n };\n}\n\n// --- Public API ---\n\n/**\n * Load all tools from the harness directory and convert them to AI SDK format.\n * Includes markdown-defined tools, programmatic tools from config, and MCP tools.\n *\n * Returns an empty object if no tools are configured.\n *\n * @param harnessDir - Path to the harness directory\n * @param config - Tool executor configuration\n * @param mcpTools - Pre-loaded MCP tools to merge (from McpManager.getTools())\n */\nexport function buildToolSet(\n harnessDir: string,\n config?: ToolExecutorConfig,\n mcpTools?: AIToolSet,\n): AIToolSet {\n const executorConfig = config ?? {};\n const tools: AIToolSet = {};\n\n // Load markdown-defined tools\n const toolDefs = loadTools(harnessDir);\n for (const toolDef of toolDefs) {\n // Skip inactive tools\n if (toolDef.status !== 'active') continue;\n\n // Skip tools without operations\n if (toolDef.operations.length === 0) continue;\n\n const converted = convertToolDefinition(toolDef, executorConfig);\n Object.assign(tools, converted);\n }\n\n // Add programmatic tools\n if (executorConfig.tools) {\n for (const pt of executorConfig.tools) {\n const converted = convertProgrammaticTool(pt);\n Object.assign(tools, converted);\n }\n }\n\n // Merge MCP tools (from connected MCP servers)\n if (mcpTools) {\n Object.assign(tools, mcpTools);\n }\n\n return tools;\n}\n\n/**\n * Create a ToolCallRecord tracker for recording tool calls in a run.\n */\nexport function createToolCallTracker(): {\n record: (result: ToolCallResult) => void;\n getRecord: () => ToolCallRecord;\n} {\n const calls: ToolCallResult[] = [];\n let totalDurationMs = 0;\n\n return {\n record(result: ToolCallResult) {\n calls.push(result);\n totalDurationMs += result.durationMs;\n },\n getRecord(): ToolCallRecord {\n return { calls: [...calls], totalDurationMs };\n },\n };\n}\n\n/**\n * Get a human-readable summary of tools available in the harness.\n */\nexport function getToolSetSummary(tools: AIToolSet): string[] {\n return Object.entries(tools).map(([name, t]) => {\n const desc = (t as { description?: string }).description ?? '';\n return `${name}: ${desc}`;\n });\n}\n","import { existsSync, readdirSync } from 'fs';\nimport { join, basename } from 'path';\nimport { loadDirectory } from '../primitives/loader.js';\nimport type { HarnessDocument } from '../core/types.js';\n\nexport interface ToolAuth {\n envVar: string;\n present: boolean;\n}\n\nexport interface ToolOperation {\n name: string;\n method: string;\n endpoint: string;\n}\n\nexport interface ToolDefinition {\n id: string;\n doc: HarnessDocument;\n tags: string[];\n status: string;\n auth: ToolAuth[];\n operations: ToolOperation[];\n rateLimits: string[];\n gotchas: string[];\n}\n\nexport interface ToolSummary {\n id: string;\n l0: string;\n tags: string[];\n status: string;\n authReady: boolean;\n operationCount: number;\n}\n\n/**\n * Extract environment variable names from authentication section.\n * Looks for `ENV_VAR_NAME` patterns (all-caps with underscores) in the auth section.\n */\nfunction extractAuth(body: string): ToolAuth[] {\n const authSection = body.match(/## Authentication\\s*\\n([\\s\\S]*?)(?=\\n## |\\n$|$)/i);\n if (!authSection) return [];\n\n const envVarPattern = /`([A-Z][A-Z0-9_]+)`/g;\n const vars: ToolAuth[] = [];\n const seen = new Set<string>();\n let match: RegExpExecArray | null;\n\n while ((match = envVarPattern.exec(authSection[1])) !== null) {\n const envVar = match[1];\n if (!seen.has(envVar)) {\n seen.add(envVar);\n vars.push({\n envVar,\n present: process.env[envVar] !== undefined && process.env[envVar] !== '',\n });\n }\n }\n\n return vars;\n}\n\n/**\n * Extract operations from Common Operations / Operations sections.\n * Looks for lines with HTTP method + endpoint patterns.\n */\nfunction extractOperations(body: string): ToolOperation[] {\n const opsSection = body.match(/## (?:Common )?Operations\\s*\\n([\\s\\S]*?)(?=\\n## |\\n$|$)/i);\n if (!opsSection) return [];\n\n const ops: ToolOperation[] = [];\n const lines = opsSection[1].split('\\n');\n let currentSection = '';\n\n for (const line of lines) {\n const headingMatch = line.match(/^### (.+)/);\n if (headingMatch) {\n currentSection = headingMatch[1].trim();\n continue;\n }\n\n // Match patterns like: `GET /repos/{owner}/{repo}/pulls`\n // or: POST /sendMessage\n const opMatch = line.match(/`?(GET|POST|PUT|DELETE|PATCH)\\s+(\\S+?)`?(?:\\s|$)/);\n if (opMatch) {\n const name = currentSection\n ? `${currentSection}: ${opMatch[2].split('/').pop() || opMatch[2]}`\n : opMatch[2].split('/').pop() || opMatch[2];\n ops.push({\n name,\n method: opMatch[1],\n endpoint: opMatch[2],\n });\n }\n }\n\n return ops;\n}\n\n/**\n * Extract rate limit lines from Rate Limits section.\n */\nfunction extractRateLimits(body: string): string[] {\n const section = body.match(/## Rate Limits\\s*\\n([\\s\\S]*?)(?=\\n## |\\n$|$)/i);\n if (!section) return [];\n\n return section[1]\n .split('\\n')\n .filter((l) => l.startsWith('- '))\n .map((l) => l.replace(/^- /, '').trim());\n}\n\n/**\n * Extract gotchas/caveats from Gotchas section.\n */\nfunction extractGotchas(body: string): string[] {\n const section = body.match(/## Gotchas\\s*\\n([\\s\\S]*?)(?=\\n## |\\n$|$)/i);\n if (!section) return [];\n\n return section[1]\n .split('\\n')\n .filter((l) => l.startsWith('- '))\n .map((l) => l.replace(/^- /, '').trim());\n}\n\n/**\n * Parse a tool document into a structured ToolDefinition.\n */\nexport function parseToolDefinition(doc: HarnessDocument): ToolDefinition {\n return {\n id: doc.frontmatter.id,\n doc,\n tags: doc.frontmatter.tags,\n status: doc.frontmatter.status,\n auth: extractAuth(doc.body),\n operations: extractOperations(doc.body),\n rateLimits: extractRateLimits(doc.body),\n gotchas: extractGotchas(doc.body),\n };\n}\n\n/**\n * Load all tool definitions from the tools/ directory.\n */\nexport function loadTools(harnessDir: string): ToolDefinition[] {\n const toolsDir = join(harnessDir, 'tools');\n if (!existsSync(toolsDir)) return [];\n\n const docs = loadDirectory(toolsDir);\n return docs.map(parseToolDefinition);\n}\n\n/**\n * Get a specific tool definition by ID.\n */\nexport function getToolById(harnessDir: string, toolId: string): ToolDefinition | null {\n const tools = loadTools(harnessDir);\n return tools.find((t) => t.id === toolId) ?? null;\n}\n\n/**\n * List tools with summary info (without full document content).\n */\nexport function listToolSummaries(harnessDir: string): ToolSummary[] {\n const tools = loadTools(harnessDir);\n return tools.map((t) => ({\n id: t.id,\n l0: t.doc.l0,\n tags: t.tags,\n status: t.status,\n authReady: t.auth.length === 0 || t.auth.every((a) => a.present),\n operationCount: t.operations.length,\n }));\n}\n\n/**\n * Check auth status for a specific tool or all tools.\n */\nexport function checkToolAuth(harnessDir: string, toolId?: string): Array<{ tool: string; auth: ToolAuth[] }> {\n const tools = toolId\n ? [getToolById(harnessDir, toolId)].filter((t): t is ToolDefinition => t !== null)\n : loadTools(harnessDir);\n\n return tools.map((t) => ({\n tool: t.id,\n auth: t.auth,\n }));\n}\n","import { createMCPClient, type MCPClient, type MCPClientConfig } from '@ai-sdk/mcp';\nimport { Experimental_StdioMCPTransport } from '@ai-sdk/mcp/mcp-stdio';\nimport type { ToolSet } from 'ai';\nimport type { HarnessConfig } from '../core/types.js';\nimport { log, getGlobalLogLevel } from '../core/logger.js';\n\n// --- Types ---\n\n/** Single MCP server configuration (mirrors config schema) */\nexport interface McpServerConfig {\n transport: 'stdio' | 'http' | 'sse';\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n url?: string;\n headers?: Record<string, string>;\n enabled?: boolean;\n}\n\n/** Result of connecting to an MCP server */\nexport interface McpServerConnection {\n name: string;\n client: MCPClient;\n toolCount: number;\n tools: ToolSet;\n}\n\n/** Summary of an MCP server for display */\nexport interface McpServerSummary {\n name: string;\n transport: string;\n enabled: boolean;\n connected: boolean;\n toolCount: number;\n toolNames: string[];\n error?: string;\n}\n\n/** Manages all MCP server connections for a harness */\nexport interface McpManager {\n /** Connect to all enabled MCP servers and load their tools */\n connect(): Promise<void>;\n /** Get merged tool set from all connected servers */\n getTools(): ToolSet;\n /** Get summary of all configured servers */\n getSummaries(): McpServerSummary[];\n /** Close all connected clients */\n close(): Promise<void>;\n /** Check if any servers are configured */\n hasServers(): boolean;\n}\n\n// --- Transport Factory ---\n\n/**\n * Build an MCPClientConfig from a server config entry.\n * Maps transport type to the appropriate transport configuration.\n */\nfunction buildClientConfig(name: string, serverConfig: McpServerConfig): MCPClientConfig {\n switch (serverConfig.transport) {\n case 'stdio': {\n if (!serverConfig.command) {\n throw new Error(`MCP server \"${name}\": stdio transport requires \"command\" field`);\n }\n // Suppress MCP server stderr noise unless --verbose (log level debug)\n const stderr = getGlobalLogLevel() === 'debug' ? 'inherit' as const : 'pipe' as const;\n return {\n transport: new Experimental_StdioMCPTransport({\n command: serverConfig.command,\n args: serverConfig.args,\n env: serverConfig.env ? { ...process.env, ...serverConfig.env } as Record<string, string> : undefined,\n cwd: serverConfig.cwd,\n stderr,\n }),\n name: `harness-mcp-${name}`,\n };\n }\n case 'http': {\n if (!serverConfig.url) {\n throw new Error(`MCP server \"${name}\": http transport requires \"url\" field`);\n }\n return {\n transport: {\n type: 'http' as const,\n url: serverConfig.url,\n headers: serverConfig.headers,\n },\n name: `harness-mcp-${name}`,\n };\n }\n case 'sse': {\n if (!serverConfig.url) {\n throw new Error(`MCP server \"${name}\": sse transport requires \"url\" field`);\n }\n return {\n transport: {\n type: 'sse' as const,\n url: serverConfig.url,\n headers: serverConfig.headers,\n },\n name: `harness-mcp-${name}`,\n };\n }\n default:\n throw new Error(`MCP server \"${name}\": unknown transport \"${serverConfig.transport}\"`);\n }\n}\n\n// --- Connection ---\n\n/**\n * Connect to a single MCP server and load its tools.\n * Returns the connection with tool set, or throws on failure.\n */\nasync function connectToServer(name: string, serverConfig: McpServerConfig): Promise<McpServerConnection> {\n const clientConfig = buildClientConfig(name, serverConfig);\n const client = await createMCPClient(clientConfig);\n\n // Load tools with auto-discovery (no schema pre-definition needed)\n const tools = await client.tools();\n const toolCount = Object.keys(tools).length;\n\n return { name, client, toolCount, tools };\n}\n\n// --- Manager ---\n\n/**\n * Create an MCP manager from harness config.\n * Manages lifecycle of all MCP server connections.\n */\nexport function createMcpManager(config: HarnessConfig): McpManager {\n const servers = config.mcp?.servers ?? {};\n const connections: McpServerConnection[] = [];\n const summaries: McpServerSummary[] = [];\n\n return {\n hasServers(): boolean {\n return Object.keys(servers).length > 0;\n },\n\n async connect(): Promise<void> {\n const entries = Object.entries(servers);\n\n if (entries.length === 0) {\n return;\n }\n\n log.info(`Connecting to ${entries.length} MCP server(s)...`);\n\n for (const [name, serverConfig] of entries) {\n const enabled = serverConfig.enabled !== false;\n\n if (!enabled) {\n summaries.push({\n name,\n transport: serverConfig.transport,\n enabled: false,\n connected: false,\n toolCount: 0,\n toolNames: [],\n });\n log.debug(`MCP server \"${name}\" is disabled, skipping`);\n continue;\n }\n\n try {\n const connection = await connectToServer(name, serverConfig);\n connections.push(connection);\n\n const toolNames = Object.keys(connection.tools);\n summaries.push({\n name,\n transport: serverConfig.transport,\n enabled: true,\n connected: true,\n toolCount: connection.toolCount,\n toolNames,\n });\n\n log.info(`MCP \"${name}\": connected, ${connection.toolCount} tool(s) [${toolNames.join(', ')}]`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n summaries.push({\n name,\n transport: serverConfig.transport,\n enabled: true,\n connected: false,\n toolCount: 0,\n toolNames: [],\n error: message,\n });\n\n log.warn(`MCP \"${name}\": connection failed — ${message}`);\n }\n }\n\n const totalTools = connections.reduce((sum, c) => sum + c.toolCount, 0);\n if (totalTools > 0) {\n log.info(`MCP: ${totalTools} tool(s) loaded from ${connections.length} server(s)`);\n }\n },\n\n getTools(): ToolSet {\n const merged: ToolSet = {};\n for (const connection of connections) {\n Object.assign(merged, connection.tools);\n }\n return merged;\n },\n\n getSummaries(): McpServerSummary[] {\n // Include unchecked servers that haven't been connected yet\n const serverNames = Object.keys(servers);\n const checkedNames = new Set(summaries.map((s) => s.name));\n\n for (const name of serverNames) {\n if (!checkedNames.has(name)) {\n const serverConfig = servers[name];\n summaries.push({\n name,\n transport: serverConfig.transport,\n enabled: serverConfig.enabled !== false,\n connected: false,\n toolCount: 0,\n toolNames: [],\n });\n }\n }\n\n return [...summaries];\n },\n\n async close(): Promise<void> {\n const closePromises = connections.map(async (connection) => {\n try {\n await connection.client.close();\n log.debug(`MCP \"${connection.name}\": closed`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn(`MCP \"${connection.name}\": close failed — ${message}`);\n }\n });\n\n await Promise.all(closePromises);\n connections.length = 0;\n },\n };\n}\n\n/**\n * Load MCP tools from all enabled servers in config.\n * Convenience function for one-shot usage (connects, loads, returns tools + close fn).\n */\nexport async function loadMcpTools(config: HarnessConfig): Promise<{\n tools: ToolSet;\n summaries: McpServerSummary[];\n close: () => Promise<void>;\n}> {\n const manager = createMcpManager(config);\n await manager.connect();\n\n return {\n tools: manager.getTools(),\n summaries: manager.getSummaries(),\n close: () => manager.close(),\n };\n}\n\n/**\n * Validate MCP server configurations without connecting.\n * Returns validation errors for each server.\n */\nexport function validateMcpConfig(config: HarnessConfig): Array<{ server: string; error: string }> {\n const errors: Array<{ server: string; error: string }> = [];\n const servers = config.mcp?.servers ?? {};\n\n for (const [name, serverConfig] of Object.entries(servers)) {\n if (serverConfig.transport === 'stdio') {\n if (!serverConfig.command) {\n errors.push({ server: name, error: 'stdio transport requires \"command\" field' });\n }\n } else if (serverConfig.transport === 'http' || serverConfig.transport === 'sse') {\n if (!serverConfig.url) {\n errors.push({ server: name, error: `${serverConfig.transport} transport requires \"url\" field` });\n }\n } else {\n errors.push({ server: name, error: `unknown transport \"${serverConfig.transport}\"` });\n }\n }\n\n return errors;\n}\n"],"mappings":"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","names":["existsSync","readFileSync","existsSync","join","join","existsSync","readFileSync","globalLevel","readFileSync","writeFileSync","existsSync","join","readFileSync","existsSync","join","resolve","join","existsSync","readFileSync","writeFileSync","writeFileSync","mkdirSync","existsSync","readdirSync","unlinkSync","join","join","existsSync","mkdirSync","writeFileSync","readdirSync","unlinkSync","readFileSync","writeFileSync","existsSync","mkdirSync","join","readFileSync","writeFileSync","existsSync","mkdirSync","join","join","existsSync","readFileSync","mkdirSync","writeFileSync","readFileSync","writeFileSync","existsSync","mkdirSync","join","getStorePath","existsSync","join","join","existsSync","existsSync"]}
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
parseHarnessDocument
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2UVWCTAY.js";
|
|
6
6
|
import {
|
|
7
7
|
generate,
|
|
8
8
|
getModel
|
|
9
9
|
} from "./chunk-IZ6UZ3ZL.js";
|
|
10
10
|
import {
|
|
11
11
|
loadConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-EC42HQQH.js";
|
|
13
13
|
|
|
14
14
|
// src/runtime/journal.ts
|
|
15
15
|
import { readFileSync, writeFileSync, readdirSync, existsSync, mkdirSync } from "fs";
|
|
@@ -304,4 +304,4 @@ export {
|
|
|
304
304
|
listJournals,
|
|
305
305
|
compressJournals
|
|
306
306
|
};
|
|
307
|
-
//# sourceMappingURL=chunk-
|
|
307
|
+
//# sourceMappingURL=chunk-NBEAK63K.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
loadTools
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2ENYRENZ.js";
|
|
6
6
|
import {
|
|
7
7
|
log
|
|
8
8
|
} from "./chunk-BSKDOFRT.js";
|
|
@@ -226,4 +226,4 @@ export {
|
|
|
226
226
|
createToolCallTracker,
|
|
227
227
|
getToolSetSummary
|
|
228
228
|
};
|
|
229
|
-
//# sourceMappingURL=chunk-
|
|
229
|
+
//# sourceMappingURL=chunk-NOJW5KG2.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
getPrimitiveDirs
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4TQQZILG.js";
|
|
6
6
|
|
|
7
7
|
// src/runtime/auto-processor.ts
|
|
8
8
|
import { readFileSync, writeFileSync, existsSync, readdirSync } from "fs";
|
|
@@ -196,4 +196,4 @@ export {
|
|
|
196
196
|
autoProcessFile,
|
|
197
197
|
autoProcessAll
|
|
198
198
|
};
|
|
199
|
-
//# sourceMappingURL=chunk-
|
|
199
|
+
//# sourceMappingURL=chunk-NVC2WY4K.js.map
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
} from "./chunk-5H34JPMB.js";
|
|
9
9
|
import {
|
|
10
10
|
buildToolSet
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-NOJW5KG2.js";
|
|
12
12
|
import {
|
|
13
13
|
buildSystemPrompt
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-7GZ4D6V6.js";
|
|
15
15
|
import {
|
|
16
16
|
loadState,
|
|
17
17
|
saveState
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
} from "./chunk-IZ6UZ3ZL.js";
|
|
39
39
|
import {
|
|
40
40
|
loadConfig
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-EC42HQQH.js";
|
|
42
42
|
|
|
43
43
|
// src/core/harness.ts
|
|
44
44
|
import { existsSync } from "fs";
|
|
@@ -396,4 +396,4 @@ function createHarness(options) {
|
|
|
396
396
|
export {
|
|
397
397
|
createHarness
|
|
398
398
|
};
|
|
399
|
-
//# sourceMappingURL=chunk-
|
|
399
|
+
//# sourceMappingURL=chunk-P74KXHA4.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
buildToolSet
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NOJW5KG2.js";
|
|
6
6
|
import {
|
|
7
7
|
createSessionId,
|
|
8
8
|
writeSession
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
estimateTokens,
|
|
12
12
|
getAtLevel,
|
|
13
13
|
loadDirectory
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-2UVWCTAY.js";
|
|
15
15
|
import {
|
|
16
16
|
log
|
|
17
17
|
} from "./chunk-BSKDOFRT.js";
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from "./chunk-IZ6UZ3ZL.js";
|
|
23
23
|
import {
|
|
24
24
|
loadConfig
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-EC42HQQH.js";
|
|
26
26
|
|
|
27
27
|
// src/runtime/delegate.ts
|
|
28
28
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -239,4 +239,4 @@ export {
|
|
|
239
239
|
delegateTo,
|
|
240
240
|
delegateStream
|
|
241
241
|
};
|
|
242
|
-
//# sourceMappingURL=chunk-
|
|
242
|
+
//# sourceMappingURL=chunk-PTQ37NRI.js.map
|
|
@@ -121,7 +121,62 @@ var HarnessConfigSchema = z.object({
|
|
|
121
121
|
name: z.string().optional(),
|
|
122
122
|
/** Optional auth token for private registries */
|
|
123
123
|
token: z.string().optional()
|
|
124
|
-
}).passthrough()).default([])
|
|
124
|
+
}).passthrough()).default([]),
|
|
125
|
+
/**
|
|
126
|
+
* License policy for `harness install <url>`. Controls how the universal
|
|
127
|
+
* installer reacts to the license detected on a fetched primitive (Level 3
|
|
128
|
+
* of task 12.14). Detection itself runs unconditionally — this only governs
|
|
129
|
+
* what happens after the license is determined.
|
|
130
|
+
*/
|
|
131
|
+
install: z.object({
|
|
132
|
+
/**
|
|
133
|
+
* SPDX ids the installer accepts without warning. Permissive defaults
|
|
134
|
+
* cover the OSI-approved ecosystem most users care about. Add or remove
|
|
135
|
+
* here to tighten or loosen the policy.
|
|
136
|
+
*/
|
|
137
|
+
allowed_licenses: z.array(z.string()).default([
|
|
138
|
+
"MIT",
|
|
139
|
+
"Apache-2.0",
|
|
140
|
+
"BSD-2-Clause",
|
|
141
|
+
"BSD-3-Clause",
|
|
142
|
+
"ISC",
|
|
143
|
+
"MPL-2.0",
|
|
144
|
+
"CC-BY-4.0",
|
|
145
|
+
"CC0-1.0",
|
|
146
|
+
"Unlicense"
|
|
147
|
+
]),
|
|
148
|
+
/**
|
|
149
|
+
* What to do when the detected license is not in `allowed_licenses` and
|
|
150
|
+
* is not classified as PROPRIETARY. Includes the UNKNOWN case (no LICENSE
|
|
151
|
+
* file found anywhere) and any non-permissive SPDX id like GPL-3.0.
|
|
152
|
+
*
|
|
153
|
+
* - allow: install silently (legacy v0.1.3 behavior — safest for migration)
|
|
154
|
+
* - warn: install with a stderr warning naming the license_source
|
|
155
|
+
* - prompt: ask Y/n on TTY; treats non-TTY as `block`
|
|
156
|
+
* - block: refuse the install with an error showing the override flag
|
|
157
|
+
*/
|
|
158
|
+
on_unknown_license: z.enum(["allow", "warn", "prompt", "block"]).default("warn"),
|
|
159
|
+
/**
|
|
160
|
+
* What to do when the detected license is PROPRIETARY (text contains
|
|
161
|
+
* "all rights reserved" or no permission grant). Defaults to `block`
|
|
162
|
+
* because shipping proprietary content was the v0.1.0 yank cause.
|
|
163
|
+
*/
|
|
164
|
+
on_proprietary: z.enum(["allow", "warn", "prompt", "block"]).default("block")
|
|
165
|
+
}).passthrough().default({
|
|
166
|
+
allowed_licenses: [
|
|
167
|
+
"MIT",
|
|
168
|
+
"Apache-2.0",
|
|
169
|
+
"BSD-2-Clause",
|
|
170
|
+
"BSD-3-Clause",
|
|
171
|
+
"ISC",
|
|
172
|
+
"MPL-2.0",
|
|
173
|
+
"CC-BY-4.0",
|
|
174
|
+
"CC0-1.0",
|
|
175
|
+
"Unlicense"
|
|
176
|
+
],
|
|
177
|
+
on_unknown_license: "warn",
|
|
178
|
+
on_proprietary: "block"
|
|
179
|
+
})
|
|
125
180
|
}).passthrough();
|
|
126
181
|
var CONFIG_DEFAULTS = {
|
|
127
182
|
agent: { name: "agent", version: "0.1.0" },
|
|
@@ -140,7 +195,22 @@ var CONFIG_DEFAULTS = {
|
|
|
140
195
|
intelligence: { auto_journal: false, auto_learn: false },
|
|
141
196
|
proactive: { enabled: false, max_per_hour: 5, cooldown_minutes: 30 },
|
|
142
197
|
mcp: { servers: {} },
|
|
143
|
-
registries: []
|
|
198
|
+
registries: [],
|
|
199
|
+
install: {
|
|
200
|
+
allowed_licenses: [
|
|
201
|
+
"MIT",
|
|
202
|
+
"Apache-2.0",
|
|
203
|
+
"BSD-2-Clause",
|
|
204
|
+
"BSD-3-Clause",
|
|
205
|
+
"ISC",
|
|
206
|
+
"MPL-2.0",
|
|
207
|
+
"CC-BY-4.0",
|
|
208
|
+
"CC0-1.0",
|
|
209
|
+
"Unlicense"
|
|
210
|
+
],
|
|
211
|
+
on_unknown_license: "warn",
|
|
212
|
+
on_proprietary: "block"
|
|
213
|
+
}
|
|
144
214
|
};
|
|
145
215
|
var CORE_PRIMITIVE_DIRS = ["rules", "instincts", "skills", "playbooks", "workflows", "tools", "agents"];
|
|
146
216
|
function getPrimitiveDirs(config) {
|
|
@@ -162,4 +232,4 @@ export {
|
|
|
162
232
|
CORE_PRIMITIVE_DIRS,
|
|
163
233
|
getPrimitiveDirs
|
|
164
234
|
};
|
|
165
|
-
//# sourceMappingURL=chunk-
|
|
235
|
+
//# sourceMappingURL=chunk-RPBC2QOA.js.map
|