noumen 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +63 -8
  2. package/dist/a2a/index.d.ts +4 -2
  3. package/dist/acp/index.d.ts +5 -3
  4. package/dist/{agent-1nFVUP9E.d.ts → agent-C3eDRsxs.d.ts} +19 -508
  5. package/dist/chunk-I5SBSOS6.js +40 -0
  6. package/dist/chunk-I5SBSOS6.js.map +1 -0
  7. package/dist/{chunk-4HW6LN6D.js → chunk-WPCYGZOE.js} +58 -1228
  8. package/dist/chunk-WPCYGZOE.js.map +1 -0
  9. package/dist/{chunk-5JN4SPI7.js → chunk-WTLK2ZAR.js} +1 -1
  10. package/dist/{chunk-HL6JCRZJ.js → chunk-XZN4QZLK.js} +4 -4
  11. package/dist/cli/index.js +10 -10
  12. package/dist/computer-BPdxSo6X.d.ts +88 -0
  13. package/dist/docker.d.ts +129 -0
  14. package/dist/docker.js +401 -0
  15. package/dist/docker.js.map +1 -0
  16. package/dist/e2b.d.ts +157 -0
  17. package/dist/e2b.js +202 -0
  18. package/dist/e2b.js.map +1 -0
  19. package/dist/freestyle.d.ts +174 -0
  20. package/dist/freestyle.js +240 -0
  21. package/dist/freestyle.js.map +1 -0
  22. package/dist/index.d.ts +9 -201
  23. package/dist/index.js +24 -48
  24. package/dist/lsp/index.d.ts +3 -2
  25. package/dist/mcp/index.d.ts +4 -3
  26. package/dist/mcp/index.js +2 -2
  27. package/dist/{provider-factory-KCLIF34X.js → provider-factory-KI7OZUY3.js} +2 -2
  28. package/dist/{resolve-4JA2BBDA.js → resolve-GDSHNMG6.js} +2 -2
  29. package/dist/sandbox-9qeMTNrD.d.ts +126 -0
  30. package/dist/server/index.d.ts +4 -2
  31. package/dist/{server-CHMxuWKq.d.ts → server-Cu9gv1dk.d.ts} +1 -1
  32. package/dist/sprites.d.ts +136 -0
  33. package/dist/sprites.js +334 -0
  34. package/dist/sprites.js.map +1 -0
  35. package/dist/ssh.d.ts +187 -0
  36. package/dist/ssh.js +392 -0
  37. package/dist/ssh.js.map +1 -0
  38. package/dist/{types-RPKUTu1k.d.ts → types-BA87bHPV.d.ts} +2 -88
  39. package/package.json +28 -1
  40. package/dist/chunk-4HW6LN6D.js.map +0 -1
  41. /package/dist/{chunk-5JN4SPI7.js.map → chunk-WTLK2ZAR.js.map} +0 -0
  42. /package/dist/{chunk-HL6JCRZJ.js.map → chunk-XZN4QZLK.js.map} +0 -0
  43. /package/dist/{provider-factory-KCLIF34X.js.map → provider-factory-KI7OZUY3.js.map} +0 -0
  44. /package/dist/{resolve-4JA2BBDA.js.map → resolve-GDSHNMG6.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agent.ts","../src/virtual/local-fs.ts","../src/virtual/local-computer.ts","../src/virtual/sandboxed-local-computer.ts","../src/virtual/sandbox.ts","../src/checkpoint/manager.ts","../src/checkpoint/types.ts","../src/hooks/runner.ts","../src/tools/prompts/agent.ts","../src/tools/agent.ts","../src/tools/prompts/web-search.ts","../src/tools/web-search.ts","../src/tools/task-create.ts","../src/tools/task-list.ts","../src/tools/task-get.ts","../src/tools/task-update.ts","../src/tools/plan-mode.ts","../src/utils/worktree.ts","../src/tools/worktree.ts","../src/cost/pricing.ts","../src/cost/tracker.ts","../src/utils/json.ts","../src/session/storage.ts","../src/tasks/store.ts","../src/context/prompts.ts","../src/skills/frontmatter.ts","../src/context/loader.ts","../src/tracing/types.ts","../src/tracing/noop.ts","../src/memory/prompts.ts","../src/messages/tool-input-normalize.ts","../src/messages/normalize.ts","../src/session/recovery.ts","../src/session/resume.ts","../src/tools/execution-pipeline.ts","../src/prompt/system.ts","../src/utils/tokens.ts","../src/retry/classify.ts","../src/compact/compact.ts","../src/compact/auto-compact.ts","../src/compact/microcompact.ts","../src/compact/tool-result-budget.ts","../src/compact/tool-result-storage.ts","../src/compact/reactive-compact.ts","../src/messages/invariants.ts","../src/pipeline/prepare-messages.ts","../src/pipeline/auto-compact-step.ts","../src/utils/generators.ts","../src/tools/orchestration.ts","../src/pipeline/execute-tools-step.ts","../src/file-state/cache.ts","../src/skills/activation.ts","../src/tools/skill.ts","../src/permissions/denial-tracking.ts","../src/tools/structured-output.ts","../src/pipeline/initialize-session.ts","../src/tools/streaming-executor.ts","../src/retry/backoff.ts","../src/retry/engine.ts","../src/pipeline/consume-stream.ts","../src/pipeline/build-assistant-response.ts","../src/pipeline/error-recovery.ts","../src/providers/cache-safe-params.ts","../src/pipeline/provider-round.ts","../src/pipeline/post-tool-step.ts","../src/memory/extraction.ts","../src/pipeline/finalize-turn.ts","../src/thread.ts","../src/skills/loader.ts","../src/prompt/context.ts","../src/retry/types.ts","../src/diagnostics.ts","../src/agent-config.ts","../src/presets.ts","../src/swarm/mailbox.ts","../src/swarm/manager.ts","../src/swarm/backends/in-process.ts","../src/permissions/updates.ts","../src/tracing/otel.ts","../src/memory/file-provider.ts"],"sourcesContent":["import * as nodeFs from \"node:fs/promises\";\nimport * as nodePath from \"node:path\";\nimport type { AIProvider, OutputFormat, ChatCompletionUsage } from \"./providers/types.js\";\nimport type { ProviderName } from \"./providers/resolve.js\";\nimport type { VirtualFs } from \"./virtual/fs.js\";\nimport type { VirtualComputer } from \"./virtual/computer.js\";\nimport { UnsandboxedLocal, type Sandbox } from \"./virtual/sandbox.js\";\nimport type { StreamEvent, RunOptions, ToolResult, ContentPart } from \"./session/types.js\";\nimport type { SkillDefinition } from \"./skills/types.js\";\nimport type { Tool, SubagentConfig, SubagentRun } from \"./tools/types.js\";\nimport type { CheckpointConfig } from \"./checkpoint/types.js\";\nimport { FileCheckpointManager } from \"./checkpoint/manager.js\";\nimport type { CacheControlConfig } from \"./providers/cache.js\";\nimport { agentTool } from \"./tools/agent.js\";\nimport { createWebSearchTool, type WebSearchConfig } from \"./tools/web-search.js\";\nimport { createToolSearchTool } from \"./tools/tool-search.js\";\nimport { taskCreateTool } from \"./tools/task-create.js\";\nimport { taskListTool } from \"./tools/task-list.js\";\nimport { taskGetTool } from \"./tools/task-get.js\";\nimport { taskUpdateTool } from \"./tools/task-update.js\";\nimport { enterPlanModeTool, exitPlanModeTool } from \"./tools/plan-mode.js\";\nimport { enterWorktreeTool, exitWorktreeTool } from \"./tools/worktree.js\";\nimport type { LspServerManager } from \"./lsp/manager.js\";\nimport type { LspServerConfig } from \"./lsp/types.js\";\nimport type { SessionInfo } from \"./session/types.js\";\nimport type { McpServerConfig } from \"./mcp/types.js\";\nimport type { TokenStorage } from \"./mcp/auth/types.js\";\nimport type { PermissionConfig } from \"./permissions/types.js\";\nimport type { HookDefinition } from \"./hooks/types.js\";\nimport type { ThinkingConfig } from \"./thinking/types.js\";\nimport type { RetryConfig } from \"./retry/types.js\";\nimport type { ModelPricing } from \"./cost/types.js\";\nimport type { TracingConfig, Tracer } from \"./tracing/types.js\";\nimport type { MemoryConfig, MemoryProvider } from \"./memory/types.js\";\nimport type { MicrocompactConfig } from \"./compact/microcompact.js\";\nimport type { ToolResultBudgetConfig } from \"./compact/tool-result-budget.js\";\nimport type { ReactiveCompactConfig } from \"./compact/reactive-compact.js\";\nimport type { FileStateCacheConfig } from \"./file-state/types.js\";\nimport type { ToolResultStorageConfig } from \"./compact/tool-result-storage.js\";\nimport type { SnipConfig } from \"./compact/history-snip.js\";\nimport { CostTracker } from \"./cost/tracker.js\";\nimport type { McpClientManager } from \"./mcp/client.js\";\nimport { SessionStorage } from \"./session/storage.js\";\nimport { TaskStore } from \"./tasks/store.js\";\nimport { Thread, type ThreadOptions } from \"./thread.js\";\nimport { createAutoCompactConfig } from \"./compact/auto-compact.js\";\nimport { buildUserContext } from \"./prompt/context.js\";\nimport { DEFAULT_RETRY_CONFIG } from \"./retry/types.js\";\nimport type { ContextFile, ProjectContextConfig } from \"./context/types.js\";\nimport { loadProjectContext } from \"./context/loader.js\";\nimport {\n checkProviderHealth,\n checkVirtualFs,\n checkVirtualComputer,\n checkSandboxRuntime,\n summarizeMcpStatus,\n summarizeLspStatus,\n} from \"./diagnostics.js\";\nimport { resolveAgentConfig } from \"./agent-config.js\";\n\nexport interface DiagnoseCheckResult {\n ok: boolean;\n latencyMs: number;\n error?: string;\n warning?: string;\n}\n\nexport interface DiagnoseResult {\n overall: boolean;\n provider: DiagnoseCheckResult & { model?: string };\n sandbox: { fs: DiagnoseCheckResult; computer: DiagnoseCheckResult };\n sandboxRuntime: DiagnoseCheckResult & { platform?: string };\n mcp: Record<string, DiagnoseCheckResult & { status?: string; toolCount?: number }>;\n lsp: Record<string, DiagnoseCheckResult & { state?: string }>;\n timestamp: string;\n}\n\nexport interface AgentOptions {\n /**\n * AI provider — either an `AIProvider` instance or a provider name string.\n * When a string is passed (e.g. `\"openai\"`), the provider is resolved\n * lazily using env-var auto-detection on the first call to `run()`,\n * `createThread()`, or `init()`.\n */\n provider: AIProvider | ProviderName;\n\n /**\n * Working directory. When set without an explicit `sandbox`, an\n * `UnsandboxedLocal({ cwd })` is created automatically.\n */\n cwd?: string;\n\n /**\n * Bundled sandbox providing both filesystem and shell execution.\n *\n * Local backends live on the root barrel:\n * - `LocalSandbox()` — OS-level sandboxing (requires `@anthropic-ai/sandbox-runtime`).\n * - `UnsandboxedLocal()` — raw host access.\n *\n * Remote backends are subpath imports so their optional peer deps do\n * not enter the module graph unless opted into:\n * - `import { DockerSandbox } from \"noumen/docker\"`\n * - `import { E2BSandbox } from \"noumen/e2b\"`\n * - `import { FreestyleSandbox } from \"noumen/freestyle\"`\n * - `import { SshSandbox } from \"noumen/ssh\"`\n * - `import { SpritesSandbox } from \"noumen/sprites\"`\n *\n * You can also pass any `{ fs: VirtualFs; computer: VirtualComputer }`\n * for custom sandboxes.\n *\n * Defaults to `UnsandboxedLocal({ cwd })` when omitted — the library\n * default is non-sandboxed for backward compatibility. The CLI defaults\n * to `LocalSandbox()` when sandbox-runtime is available.\n */\n sandbox?: Sandbox;\n\n options?: {\n sessionDir?: string;\n skills?: SkillDefinition[];\n skillsPaths?: string[];\n tools?: Tool[];\n mcpServers?: Record<string, McpServerConfig>;\n /** Token storage for MCP OAuth flows (defaults to in-memory). */\n mcpTokenStorage?: TokenStorage;\n /** Called when an MCP server requires OAuth and the user must visit a URL. */\n mcpOnAuthorizationUrl?: (url: string) => void | Promise<void>;\n systemPrompt?: string;\n model?: string;\n maxTokens?: number;\n autoCompact?: boolean;\n autoCompactThreshold?: number;\n microcompact?: MicrocompactConfig;\n toolResultBudget?: ToolResultBudgetConfig;\n reactiveCompact?: ReactiveCompactConfig;\n cwd?: string;\n permissions?: PermissionConfig;\n hooks?: HookDefinition[];\n enableSubagents?: boolean;\n enableTasks?: boolean;\n tasksDir?: string;\n enablePlanMode?: boolean;\n enableWorktrees?: boolean;\n lsp?: Record<string, LspServerConfig>;\n streamingToolExecution?: boolean;\n webSearch?: WebSearchConfig;\n userInputHandler?: (question: string) => Promise<string>;\n thinking?: ThinkingConfig;\n retry?: RetryConfig | boolean;\n costTracking?: {\n enabled: boolean;\n pricing?: Record<string, ModelPricing>;\n };\n tracing?: TracingConfig;\n memory?: MemoryConfig;\n /** Enable ToolSearch: deferred tools are hidden until the model discovers them. */\n toolSearch?: boolean;\n /** File checkpointing: snapshot files before edits for rollback. */\n checkpoint?: CheckpointConfig;\n /** Prompt caching: enable deterministic tool ordering and cache_control injection. */\n promptCaching?: CacheControlConfig;\n /** File state cache: track reads for read-before-edit enforcement. */\n fileStateCache?: FileStateCacheConfig;\n /** Disk-backed storage for oversized tool results. */\n toolResultStorage?: ToolResultStorageConfig;\n /** History snip: enable middle-range removal from conversation history. */\n historySnip?: SnipConfig;\n /** Project context loading (NOUMEN.md / CLAUDE.md). Pass true for defaults or a config object. */\n projectContext?: ProjectContextConfig | boolean;\n /** Default structured output format for all threads. */\n outputFormat?: OutputFormat;\n /** Default structured output mode for all threads. */\n structuredOutputMode?: \"alongside_tools\" | \"final_response\";\n };\n}\n\nexport interface RunCallbacks {\n onText?: (text: string) => void;\n onThinking?: (text: string) => void;\n onToolUse?: (toolName: string, args: Record<string, unknown>) => void;\n onToolResult?: (toolName: string, result: ToolResult) => void;\n onError?: (error: Error) => void;\n onComplete?: (result: RunResult) => void;\n}\n\nexport interface RunResult {\n text: string;\n toolCalls: number;\n usage: ChatCompletionUsage;\n sessionId: string;\n}\n\nexport class Agent {\n private providerInput: AIProvider | ProviderName;\n private resolvedProvider: AIProvider | null = null;\n private fs: VirtualFs;\n private computer: VirtualComputer;\n private sandbox: import(\"./virtual/sandbox.js\").Sandbox;\n private sessionDir: string;\n private skills: SkillDefinition[];\n private skillsPaths: string[];\n private tools: Tool[];\n private systemPrompt?: string;\n private model?: string;\n private maxTokens?: number;\n private autoCompactEnabled: boolean;\n private autoCompactThreshold?: number;\n private cwd: string;\n private storage: SessionStorage;\n private resolvedSkills: SkillDefinition[] | null = null;\n private mcpManager: McpClientManager | null = null;\n private mcpServerConfigs?: Record<string, McpServerConfig>;\n private mcpTokenStorage?: TokenStorage;\n private mcpOnAuthorizationUrl?: (url: string) => void | Promise<void>;\n private mcpTools: Tool[] = [];\n private mcpToolNames: Set<string> = new Set();\n private mcpAuthTools: Tool[] = [];\n private permissions?: PermissionConfig;\n private hooks: HookDefinition[];\n private enableSubagents: boolean;\n private enableTasks: boolean;\n private taskStore: TaskStore | null = null;\n private enablePlanMode: boolean;\n private enableWorktrees: boolean;\n private lspManager: LspServerManager | null = null;\n private lspConfigs?: Record<string, LspServerConfig>;\n private lspToolRef: Tool | null = null;\n private streamingToolExecution: boolean;\n private webSearchConfig?: WebSearchConfig;\n private userInputHandler?: (question: string) => Promise<string>;\n private thinkingConfig?: ThinkingConfig;\n private retryConfig?: RetryConfig;\n private costTracker: CostTracker | null = null;\n private tracer?: Tracer;\n private memoryProvider?: MemoryProvider;\n private memoryConfig?: MemoryConfig;\n private microcompactConfig?: MicrocompactConfig;\n private toolResultBudgetConfig?: ToolResultBudgetConfig;\n private reactiveCompactConfig?: ReactiveCompactConfig;\n private toolSearchEnabled: boolean;\n private projectContextConfig?: ProjectContextConfig;\n private resolvedProjectContext: ContextFile[] | null = null;\n private checkpointManager: FileCheckpointManager | null = null;\n private promptCachingConfig: CacheControlConfig | undefined;\n private fileStateCacheConfig: FileStateCacheConfig | undefined;\n private toolResultStorageConfig: ToolResultStorageConfig | undefined;\n private historySnipConfig: SnipConfig | undefined;\n private outputFormat: OutputFormat | undefined;\n private structuredOutputMode: \"alongside_tools\" | \"final_response\" | undefined;\n private providerPromise: Promise<AIProvider> | null = null;\n private initPromise: Promise<void> | null = null;\n\n constructor(opts: AgentOptions) {\n this.providerInput = opts.provider;\n if (typeof opts.provider !== \"string\") {\n this.resolvedProvider = opts.provider;\n }\n\n const resolved = resolveAgentConfig({\n cwd: opts.cwd,\n optionsCwd: opts.options?.cwd,\n retry: opts.options?.retry,\n projectContext: opts.options?.projectContext,\n mcpServers: opts.options?.mcpServers,\n lsp: opts.options?.lsp,\n });\n\n const resolvedSandbox = opts.sandbox ?? UnsandboxedLocal({ cwd: resolved.effectiveCwd });\n\n this.sandbox = resolvedSandbox;\n this.fs = resolvedSandbox.fs;\n this.computer = resolvedSandbox.computer;\n this.sessionDir = opts.options?.sessionDir ?? \".noumen/sessions\";\n this.skills = opts.options?.skills ?? [];\n this.skillsPaths = opts.options?.skillsPaths ?? [];\n this.tools = opts.options?.tools ?? [];\n this.systemPrompt = opts.options?.systemPrompt;\n this.model = opts.options?.model;\n this.maxTokens = opts.options?.maxTokens;\n this.autoCompactEnabled = opts.options?.autoCompact ?? true;\n this.autoCompactThreshold = opts.options?.autoCompactThreshold;\n this.cwd = resolved.effectiveCwd;\n this.storage = new SessionStorage(this.fs, this.sessionDir);\n this.permissions = opts.options?.permissions;\n this.hooks = opts.options?.hooks ?? [];\n this.enableSubagents = opts.options?.enableSubagents ?? false;\n this.enableTasks = opts.options?.enableTasks ?? false;\n if (this.enableTasks) {\n const tasksDir = opts.options?.tasksDir ?? \".noumen/tasks\";\n this.taskStore = new TaskStore(this.fs, tasksDir);\n }\n this.enablePlanMode = opts.options?.enablePlanMode ?? false;\n this.enableWorktrees = opts.options?.enableWorktrees ?? false;\n this.lspConfigs = resolved.lspConfigs as Record<string, LspServerConfig> | undefined;\n this.streamingToolExecution = opts.options?.streamingToolExecution ?? false;\n this.webSearchConfig = opts.options?.webSearch;\n this.userInputHandler = opts.options?.userInputHandler;\n this.thinkingConfig = opts.options?.thinking;\n this.retryConfig = resolved.retryConfig;\n\n if (opts.options?.costTracking?.enabled) {\n this.costTracker = new CostTracker(opts.options.costTracking.pricing);\n }\n\n if (resolved.mcpServerConfigs) {\n this.mcpServerConfigs = resolved.mcpServerConfigs as Record<string, McpServerConfig>;\n this.mcpTokenStorage = opts.options?.mcpTokenStorage;\n this.mcpOnAuthorizationUrl = opts.options?.mcpOnAuthorizationUrl;\n }\n\n this.tracer = opts.options?.tracing?.tracer;\n\n if (opts.options?.memory) {\n this.memoryConfig = opts.options.memory;\n this.memoryProvider = opts.options.memory.provider;\n }\n\n this.microcompactConfig = opts.options?.microcompact;\n this.toolResultBudgetConfig = opts.options?.toolResultBudget;\n this.reactiveCompactConfig = opts.options?.reactiveCompact;\n this.toolSearchEnabled = opts.options?.toolSearch ?? false;\n this.projectContextConfig = resolved.projectContextConfig;\n this.promptCachingConfig = opts.options?.promptCaching;\n this.fileStateCacheConfig = opts.options?.fileStateCache;\n this.toolResultStorageConfig = opts.options?.toolResultStorage;\n this.historySnipConfig = opts.options?.historySnip;\n this.outputFormat = opts.options?.outputFormat;\n this.structuredOutputMode = opts.options?.structuredOutputMode;\n\n if (opts.options?.checkpoint?.enabled) {\n this.checkpointManager = new FileCheckpointManager(\n this.fs,\n opts.options.checkpoint,\n );\n }\n }\n\n private async ensureProvider(): Promise<AIProvider> {\n if (this.resolvedProvider) return this.resolvedProvider;\n if (!this.providerPromise) {\n this.providerPromise = (async () => {\n const { resolveProvider } = await import(\"./providers/resolve.js\");\n return resolveProvider(this.providerInput, { model: this.model });\n })();\n }\n this.resolvedProvider = await this.providerPromise;\n return this.resolvedProvider;\n }\n\n private getProvider(): AIProvider {\n if (!this.resolvedProvider) {\n throw new Error(\n \"Provider not yet resolved. Call init() first when using a string provider.\",\n );\n }\n return this.resolvedProvider;\n }\n\n private async getSkills(): Promise<SkillDefinition[]> {\n if (this.resolvedSkills) return this.resolvedSkills;\n\n const ctx = await buildUserContext({\n fs: this.fs,\n skillsPaths: this.skillsPaths,\n inlineSkills: this.skills,\n });\n\n this.resolvedSkills = ctx.skills;\n return this.resolvedSkills;\n }\n\n private getAllTools(): Tool[] {\n const tools = [...this.tools, ...this.mcpTools, ...this.mcpAuthTools];\n if (this.enableSubagents) {\n tools.push(agentTool);\n }\n if (this.enableTasks) {\n tools.push(taskCreateTool, taskListTool, taskGetTool, taskUpdateTool);\n }\n if (this.enablePlanMode) {\n tools.push(enterPlanModeTool, exitPlanModeTool);\n }\n if (this.enableWorktrees) {\n tools.push(enterWorktreeTool, exitWorktreeTool);\n }\n if (this.lspManager && this.lspToolRef) {\n tools.push(this.lspToolRef);\n }\n if (this.webSearchConfig) {\n tools.push(createWebSearchTool(this.webSearchConfig));\n }\n return tools;\n }\n\n private createSpawnSubagent(getCwd: () => string): (config: SubagentConfig) => SubagentRun {\n return (config: SubagentConfig): SubagentRun => {\n const parentCwd = getCwd();\n const parentTools = this.getAllTools().filter((t) => t.name !== \"Agent\");\n const childTools = config.allowedTools\n ? parentTools.filter((t) => config.allowedTools!.includes(t.name))\n : parentTools;\n\n const childThread = new Thread(\n {\n provider: this.getProvider(),\n fs: this.fs,\n computer: this.computer,\n sessionDir: this.sessionDir,\n skills: this.resolvedSkills ?? this.skills,\n tools: childTools,\n systemPrompt: config.systemPrompt ?? this.systemPrompt,\n model: config.model ?? this.model,\n maxTokens: this.maxTokens,\n autoCompact: createAutoCompactConfig({ enabled: false }),\n permissions: config.permissionMode\n ? { mode: config.permissionMode }\n : { mode: \"bypassPermissions\" },\n hooks: this.hooks,\n taskStore: this.taskStore ?? undefined,\n lspManager: this.lspManager ?? undefined,\n thinking: this.thinkingConfig,\n retry: this.retryConfig,\n costTracker: this.costTracker ?? undefined,\n tracer: this.tracer,\n memory: this.memoryConfig,\n checkpointManager: this.checkpointManager ?? undefined,\n fileStateCacheConfig: this.fileStateCacheConfig,\n toolResultStorage: this.toolResultStorageConfig,\n historySnip: this.historySnipConfig,\n promptCachingEnabled: this.promptCachingConfig?.enabled ?? false,\n skipCacheWrite: true,\n projectContext: this.resolvedProjectContext ?? undefined,\n },\n { cwd: parentCwd },\n );\n\n return {\n sessionId: childThread.sessionId,\n events: childThread.run(config.prompt),\n };\n };\n }\n\n async createThread(opts?: ThreadOptions): Promise<Thread> {\n await this.init();\n\n if (this.sandbox.init) {\n let storedSandboxId: string | undefined;\n if (opts?.resume && opts?.sessionId) {\n storedSandboxId = await this.loadSandboxId(opts.sessionId);\n }\n await this.sandbox.init(storedSandboxId);\n }\n\n const autoCompact = createAutoCompactConfig({\n enabled: this.autoCompactEnabled,\n threshold: this.autoCompactThreshold,\n model: this.model,\n });\n\n const skills = this.resolvedSkills ?? this.skills;\n const cwd = opts?.cwd ?? this.cwd;\n\n let thread!: Thread;\n thread = new Thread(\n {\n provider: this.getProvider(),\n fs: this.fs,\n computer: this.computer,\n sessionDir: this.sessionDir,\n skills,\n tools: this.getAllTools(),\n systemPrompt: this.systemPrompt,\n model: this.model,\n maxTokens: this.maxTokens,\n autoCompact,\n microcompact: this.microcompactConfig,\n toolResultBudget: this.toolResultBudgetConfig,\n reactiveCompact: this.reactiveCompactConfig,\n permissions: opts?.permissionHandler\n ? { ...this.permissions, handler: opts.permissionHandler }\n : this.permissions,\n hooks: this.hooks,\n spawnSubagent: this.enableSubagents\n ? this.createSpawnSubagent(() => thread.getCwd())\n : undefined,\n streamingToolExecution: this.streamingToolExecution,\n userInputHandler: opts?.userInputHandler ?? this.userInputHandler,\n taskStore: this.taskStore ?? undefined,\n lspManager: this.lspManager ?? undefined,\n thinking: this.thinkingConfig,\n retry: this.retryConfig,\n costTracker: this.costTracker ?? undefined,\n tracer: this.tracer,\n memory: this.memoryConfig,\n toolSearchEnabled: this.toolSearchEnabled,\n checkpointManager: this.checkpointManager ?? undefined,\n fileStateCacheConfig: this.fileStateCacheConfig,\n toolResultStorage: this.toolResultStorageConfig,\n historySnip: this.historySnipConfig,\n promptCachingEnabled: this.promptCachingConfig?.enabled ?? false,\n mcpToolNames: this.mcpToolNames.size > 0 ? this.mcpToolNames : undefined,\n projectContext: this.resolvedProjectContext ?? undefined,\n outputFormat: this.outputFormat,\n structuredOutputMode: this.structuredOutputMode,\n },\n {\n ...opts,\n cwd,\n },\n );\n\n const sid = this.sandbox.sandboxId?.();\n if (sid && !(opts?.resume)) {\n await this.storeSandboxId(thread.sessionId, sid);\n }\n\n return thread;\n }\n\n async listSessions(): Promise<SessionInfo[]> {\n return this.storage.listSessions();\n }\n\n getCostSummary(): import(\"./cost/types.js\").CostSummary | null {\n return this.costTracker?.getSummary() ?? null;\n }\n\n /**\n * Create a thread that resumes an existing session. Automatically restores\n * messages (respecting compact boundaries), file checkpoint state, and\n * cost tracking state from the persisted JSONL transcript.\n */\n async resumeThread(sessionId: string, opts?: Omit<ThreadOptions, \"sessionId\" | \"resume\">): Promise<Thread> {\n return this.createThread({\n ...opts,\n sessionId,\n resume: true,\n });\n }\n\n /**\n * One-shot streaming: creates an ephemeral thread and yields events.\n * Auto-resolves string providers on first call (no need to call `init()`).\n *\n * ```ts\n * for await (const event of agent.run(\"Fix the bug\")) {\n * if (event.type === \"text_delta\") process.stdout.write(event.text);\n * }\n * ```\n */\n async *run(\n prompt: string | ContentPart[],\n opts?: RunOptions & ThreadOptions,\n ): AsyncGenerator<StreamEvent, void, unknown> {\n await this.init();\n const thread = await this.createThread(opts);\n yield* thread.run(prompt, opts);\n }\n\n /**\n * One-shot execution: runs the prompt to completion and returns a result\n * summary. Optional callbacks fire as events arrive.\n *\n * ```ts\n * const result = await agent.execute(\"Fix the bug\", {\n * onText: (text) => process.stdout.write(text),\n * });\n * console.log(`Done — ${result.toolCalls} tool calls`);\n * ```\n */\n async execute(\n prompt: string | ContentPart[],\n opts?: RunOptions & ThreadOptions & RunCallbacks,\n ): Promise<RunResult> {\n await this.init();\n const thread = await this.createThread(opts);\n let text = \"\";\n let toolCalls = 0;\n let lastUsage: ChatCompletionUsage = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };\n\n for await (const event of thread.run(prompt, opts)) {\n switch (event.type) {\n case \"text_delta\":\n text += event.text;\n opts?.onText?.(event.text);\n break;\n case \"thinking_delta\":\n opts?.onThinking?.(event.text);\n break;\n case \"tool_use_start\":\n toolCalls++;\n opts?.onToolUse?.(event.toolName, {});\n break;\n case \"tool_result\":\n opts?.onToolResult?.(event.toolName, event.result);\n break;\n case \"error\":\n opts?.onError?.(event.error);\n break;\n case \"turn_complete\":\n lastUsage = event.usage;\n break;\n }\n }\n\n const result: RunResult = {\n text,\n toolCalls,\n usage: lastUsage,\n sessionId: thread.sessionId,\n };\n\n opts?.onComplete?.(result);\n return result;\n }\n\n /**\n * Pre-resolve the provider (if string), skills, MCP servers, and LSP servers.\n * Call this once after construction if using a string provider, skillsPaths,\n * mcpServers, or lsp, so that createThread() has everything available synchronously.\n */\n async init(): Promise<void> {\n if (!this.initPromise) {\n this.initPromise = this.doInit().catch((err) => {\n this.initPromise = null;\n throw err;\n });\n }\n return this.initPromise;\n }\n\n private async doInit(): Promise<void> {\n const tasks: Promise<void>[] = [\n this.ensureProvider().then(() => {}),\n this.getSkills().then(() => {}),\n ];\n\n if (this.projectContextConfig && !this.resolvedProjectContext) {\n tasks.push(\n loadProjectContext(this.fs, this.projectContextConfig).then((files) => {\n this.resolvedProjectContext = files;\n }),\n );\n }\n\n if (this.mcpServerConfigs && !this.mcpManager) {\n tasks.push(\n (async () => {\n const { McpClientManager: McpMgr } = await import(\"./mcp/client.js\");\n this.mcpManager = new McpMgr(this.mcpServerConfigs!, {\n tokenStorage: this.mcpTokenStorage,\n onAuthorizationUrl: this.mcpOnAuthorizationUrl,\n });\n await this.mcpManager.connect();\n this.mcpTools = await this.mcpManager.getTools();\n this.mcpToolNames = new Set(this.mcpTools.map((t) => t.name));\n\n const needsAuth = this.mcpManager.getServersNeedingAuth();\n if (needsAuth.length > 0) {\n const { createMcpAuthTool } = await import(\"./tools/mcp-auth.js\");\n this.mcpAuthTools = needsAuth.map((name) =>\n createMcpAuthTool(name, this.mcpManager!),\n );\n }\n })(),\n );\n }\n\n if (this.lspConfigs && !this.lspManager) {\n tasks.push(\n (async () => {\n const { LspServerManager } = await import(\"./lsp/manager.js\");\n const { lspTool } = await import(\"./tools/lsp.js\");\n const rootUri = `file://${this.cwd}`;\n this.lspManager = new LspServerManager(this.lspConfigs!, rootUri);\n this.lspToolRef = lspTool;\n })(),\n );\n }\n\n await Promise.all(tasks);\n }\n\n /**\n * Run health checks on the provider, sandbox, MCP servers, and LSP servers.\n * Returns a structured report — useful for debugging integration issues.\n *\n * @param timeoutMs Per-check timeout in milliseconds (default 10 000).\n */\n async diagnose(timeoutMs = 10_000): Promise<DiagnoseResult> {\n const providerCheck = await checkProviderHealth(this.getProvider(), this.model, timeoutMs);\n const fsCheck = await checkVirtualFs(this.fs, timeoutMs);\n const computerCheck = await checkVirtualComputer(this.computer, timeoutMs);\n const sandboxRuntimeCheck = await checkSandboxRuntime();\n\n const mcpResults = this.mcpManager\n ? summarizeMcpStatus(this.mcpManager.getConnectionStatus())\n : {};\n\n const lspResults = this.lspManager\n ? summarizeLspStatus(this.lspManager.getServerStatus())\n : {};\n\n const overall = providerCheck.ok && fsCheck.ok && computerCheck.ok;\n\n return {\n overall,\n provider: providerCheck,\n sandbox: { fs: fsCheck, computer: computerCheck },\n sandboxRuntime: sandboxRuntimeCheck,\n mcp: mcpResults,\n lsp: lspResults,\n timestamp: new Date().toISOString(),\n };\n }\n\n // ---------------------------------------------------------------------------\n // Sandbox index — local host file mapping sessionId → sandboxId so we can\n // reconnect to auto-created containers on resume without accessing the\n // (potentially unreachable) sandbox filesystem.\n // ---------------------------------------------------------------------------\n\n private get sandboxIndexPath(): string {\n return nodePath.resolve(this.cwd, this.sessionDir, \".sandbox-index.json\");\n }\n\n private async loadSandboxId(sessionId: string): Promise<string | undefined> {\n try {\n const content = await nodeFs.readFile(this.sandboxIndexPath, \"utf-8\");\n const index = JSON.parse(content) as Record<string, string>;\n return index[sessionId];\n } catch {\n return undefined;\n }\n }\n\n private async storeSandboxId(sessionId: string, sandboxId: string): Promise<void> {\n let index: Record<string, string> = {};\n try {\n const content = await nodeFs.readFile(this.sandboxIndexPath, \"utf-8\");\n index = JSON.parse(content) as Record<string, string>;\n } catch { /* file doesn't exist yet */ }\n index[sessionId] = sandboxId;\n await nodeFs.mkdir(nodePath.dirname(this.sandboxIndexPath), { recursive: true });\n await nodeFs.writeFile(this.sandboxIndexPath, JSON.stringify(index, null, 2));\n }\n\n /**\n * Disconnect all MCP clients. Call when done with this Agent instance.\n */\n async close(): Promise<void> {\n const tasks: Promise<void>[] = [];\n if (this.mcpManager) {\n tasks.push(\n this.mcpManager.close().then(() => {\n this.mcpTools = [];\n this.mcpAuthTools = [];\n this.mcpToolNames.clear();\n this.mcpManager = null;\n }),\n );\n }\n if (this.lspManager) {\n tasks.push(\n this.lspManager.shutdown().then(() => {\n this.lspManager = null;\n this.lspToolRef = null;\n }),\n );\n }\n if (this.sandbox.dispose) {\n tasks.push(this.sandbox.dispose());\n }\n await Promise.all(tasks);\n this.initPromise = null;\n this.providerPromise = null;\n }\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport type { VirtualFs, FileEntry, FileStat, ReadOptions } from \"./fs.js\";\n\nexport interface LocalFsOptions {\n basePath?: string;\n}\n\n/**\n * Unsandboxed VirtualFs backed by `node:fs/promises` on the host machine.\n * Paths resolve relative to `basePath`. Suitable for local development and\n * trusted environments. For production or untrusted agents, use a sandboxed\n * implementation like `SpritesFs` (remote container) or a custom\n * Docker/E2B adapter instead.\n */\nexport class LocalFs implements VirtualFs {\n private basePath: string;\n private resolvedBasePath: string;\n private realBasePathPromise: Promise<string> | null = null;\n\n constructor(opts?: LocalFsOptions) {\n this.basePath = opts?.basePath ?? process.cwd();\n this.resolvedBasePath = path.resolve(this.basePath);\n }\n\n private async getRealBasePath(): Promise<string> {\n if (!this.realBasePathPromise) {\n this.realBasePathPromise = (async () => {\n try {\n return await fs.realpath(this.resolvedBasePath);\n } catch {\n // Base path may not exist yet; resolve its closest existing ancestor.\n const parentReal = await fs.realpath(path.dirname(this.resolvedBasePath)).catch(() => path.dirname(this.resolvedBasePath));\n return path.join(parentReal, path.basename(this.resolvedBasePath));\n }\n })();\n }\n return this.realBasePathPromise;\n }\n\n private async resolve(p: string): Promise<string> {\n if (p.includes(\"\\0\")) {\n throw new Error(`Path contains null bytes`);\n }\n const resolved = path.isAbsolute(p) ? path.normalize(p) : path.resolve(this.basePath, p);\n if (resolved !== this.resolvedBasePath && !resolved.startsWith(this.resolvedBasePath + path.sep)) {\n throw new Error(`Path \"${p}\" resolves outside base directory \"${this.basePath}\"`);\n }\n // Resolve symlinks to prevent escaping the base directory via symlink chains.\n // Walk up from the target until we find an existing ancestor, then re-append\n // the non-existent tail so the comparison uses real paths on both sides.\n const realBase = await this.getRealBasePath();\n const realTarget = await realpathWalkUp(resolved);\n if (realTarget !== realBase && !realTarget.startsWith(realBase + path.sep)) {\n throw new Error(`Path \"${p}\" resolves outside base directory via symlink`);\n }\n return realTarget;\n }\n\n async readFile(filePath: string, opts?: ReadOptions): Promise<string> {\n const encoding = opts?.encoding ?? \"utf-8\";\n const resolved = await this.resolve(filePath);\n if (opts?.maxBytes !== undefined) {\n const fh = await fs.open(resolved, \"r\");\n try {\n const buf = Buffer.alloc(opts.maxBytes);\n const { bytesRead } = await fh.read(buf, 0, opts.maxBytes, 0);\n return buf.subarray(0, bytesRead).toString(encoding);\n } finally {\n await fh.close();\n }\n }\n return fs.readFile(resolved, { encoding });\n }\n\n async readFileBytes(filePath: string, maxBytes?: number): Promise<Buffer> {\n const resolved = await this.resolve(filePath);\n if (maxBytes === undefined) {\n return fs.readFile(resolved);\n }\n const fh = await fs.open(resolved, \"r\");\n try {\n const buf = Buffer.alloc(maxBytes);\n const { bytesRead } = await fh.read(buf, 0, maxBytes, 0);\n return buf.subarray(0, bytesRead);\n } finally {\n await fh.close();\n }\n }\n\n async writeFile(filePath: string, content: string): Promise<void> {\n const resolved = await this.resolve(filePath);\n await fs.mkdir(path.dirname(resolved), { recursive: true });\n await fs.writeFile(resolved, content, \"utf-8\");\n }\n\n async appendFile(filePath: string, content: string): Promise<void> {\n const resolved = await this.resolve(filePath);\n await fs.mkdir(path.dirname(resolved), { recursive: true });\n await fs.appendFile(resolved, content, \"utf-8\");\n }\n\n async deleteFile(\n filePath: string,\n opts?: { recursive?: boolean },\n ): Promise<void> {\n await fs.rm(await this.resolve(filePath), {\n recursive: opts?.recursive ?? false,\n force: true,\n });\n }\n\n async mkdir(dirPath: string, opts?: { recursive?: boolean }): Promise<void> {\n await fs.mkdir(await this.resolve(dirPath), {\n recursive: opts?.recursive ?? false,\n });\n }\n\n async readdir(\n dirPath: string,\n opts?: { recursive?: boolean },\n ): Promise<FileEntry[]> {\n const resolved = await this.resolve(dirPath);\n const entries = await fs.readdir(resolved, { withFileTypes: true });\n const results: FileEntry[] = [];\n\n for (const entry of entries) {\n const entryPath = path.join(resolved, entry.name);\n results.push({\n name: entry.name,\n path: entryPath,\n isDirectory: entry.isDirectory(),\n isFile: entry.isFile(),\n });\n\n if (opts?.recursive && entry.isDirectory()) {\n const subEntries = await this.readdir(entryPath, { recursive: true });\n results.push(...subEntries);\n }\n }\n\n return results;\n }\n\n async exists(filePath: string): Promise<boolean> {\n try {\n await fs.access(await this.resolve(filePath));\n return true;\n } catch {\n return false;\n }\n }\n\n async stat(filePath: string): Promise<FileStat> {\n const stats = await fs.stat(await this.resolve(filePath));\n return {\n size: stats.size,\n isDirectory: stats.isDirectory(),\n isFile: stats.isFile(),\n createdAt: stats.birthtime,\n modifiedAt: stats.mtime,\n };\n }\n}\n\n/**\n * Resolve symlinks in a path, walking up to the nearest existing ancestor when\n * the path (or intermediate directories) don't exist yet. Non-existent tail\n * segments are appended to the resolved ancestor.\n */\nasync function realpathWalkUp(target: string): Promise<string> {\n try {\n return await fs.realpath(target);\n } catch (e: unknown) {\n if ((e as NodeJS.ErrnoException).code !== \"ENOENT\") throw e;\n }\n const parent = path.dirname(target);\n if (parent === target) return target;\n const resolvedParent = await realpathWalkUp(parent);\n return path.join(resolvedParent, path.basename(target));\n}\n","import { exec as execCb } from \"node:child_process\";\nimport type { VirtualComputer, ExecOptions, CommandResult } from \"./computer.js\";\n\nexport interface LocalComputerOptions {\n defaultCwd?: string;\n defaultTimeout?: number;\n}\n\n/**\n * Unsandboxed VirtualComputer that runs commands directly on the host via\n * `node:child_process`. Suitable for local development and trusted\n * environments. For production or untrusted agents, use a sandboxed\n * implementation like `SpritesComputer` (remote container) or a custom\n * Docker/E2B adapter instead.\n */\nexport class LocalComputer implements VirtualComputer {\n private defaultCwd: string;\n private defaultTimeout: number;\n\n constructor(opts?: LocalComputerOptions) {\n this.defaultCwd = opts?.defaultCwd ?? process.cwd();\n this.defaultTimeout = opts?.defaultTimeout ?? 30_000;\n }\n\n executeCommand(command: string, opts?: ExecOptions): Promise<CommandResult> {\n return new Promise((resolve) => {\n const child = execCb(\n command,\n {\n cwd: opts?.cwd ?? this.defaultCwd,\n timeout: opts?.timeout ?? this.defaultTimeout,\n env: opts?.env\n ? { ...process.env, ...opts.env }\n : process.env,\n maxBuffer: 10 * 1024 * 1024,\n shell: process.env.SHELL || \"/bin/sh\",\n },\n (error, stdout, stderr) => {\n resolve({\n exitCode:\n error && \"code\" in error\n ? (typeof error.code === \"number\" ? error.code : 1)\n : child.exitCode ?? 0,\n stdout: stdout ?? \"\",\n stderr: stderr ?? \"\",\n });\n },\n );\n });\n }\n}\n","import { exec as execCb } from \"node:child_process\";\nimport type { VirtualComputer, ExecOptions, CommandResult } from \"./computer.js\";\nimport {\n SandboxManager,\n type SandboxRuntimeConfig,\n} from \"@anthropic-ai/sandbox-runtime\";\n\n/**\n * Filesystem and network restriction config passed to `@anthropic-ai/sandbox-runtime`.\n */\nexport interface SandboxConfig {\n filesystem?: {\n /** Paths the agent may write to (default: `[cwd]`). Write is denied everywhere else. */\n allowWrite?: string[];\n /** Paths to explicitly deny writes within allowed regions. */\n denyWrite?: string[];\n /** Paths to deny reading. By default everything is readable. */\n denyRead?: string[];\n /** Paths to re-allow reading within denyRead regions. Takes precedence over denyRead. */\n allowRead?: string[];\n };\n network?: {\n /** Domains the agent may reach via HTTP/HTTPS/SOCKS. */\n allowedDomains?: string[];\n /** Domains to explicitly block. */\n deniedDomains?: string[];\n };\n}\n\nexport interface SandboxedLocalComputerOptions {\n defaultCwd?: string;\n defaultTimeout?: number;\n sandbox?: SandboxConfig;\n}\n\n/**\n * `VirtualComputer` that wraps every command with OS-level sandboxing via\n * `@anthropic-ai/sandbox-runtime`. Uses macOS Seatbelt (`sandbox-exec`) or\n * Linux bubblewrap (`bwrap`) under the hood.\n */\nexport class SandboxedLocalComputer implements VirtualComputer {\n private defaultCwd: string;\n private defaultTimeout: number;\n private sandboxConfig: SandboxConfig;\n private initPromise: Promise<void> | null = null;\n private initialized = false;\n\n constructor(opts?: SandboxedLocalComputerOptions) {\n this.defaultCwd = opts?.defaultCwd ?? process.cwd();\n this.defaultTimeout = opts?.defaultTimeout ?? 30_000;\n this.sandboxConfig = opts?.sandbox ?? {};\n }\n\n private buildRuntimeConfig(): SandboxRuntimeConfig {\n const fs = this.sandboxConfig.filesystem;\n const net = this.sandboxConfig.network;\n return {\n filesystem: {\n allowWrite: fs?.allowWrite ?? [this.defaultCwd],\n denyWrite: fs?.denyWrite ?? [],\n denyRead: fs?.denyRead ?? [],\n allowRead: fs?.allowRead ?? [],\n },\n network: {\n allowedDomains: net?.allowedDomains ?? [],\n deniedDomains: net?.deniedDomains ?? [],\n },\n };\n }\n\n private async ensureInitialized(): Promise<void> {\n if (this.initialized) return;\n\n if (!this.initPromise) {\n this.initPromise = (async () => {\n try {\n await SandboxManager.initialize(this.buildRuntimeConfig());\n this.initialized = true;\n } catch (err) {\n this.initPromise = null;\n throw err;\n }\n })();\n }\n\n await this.initPromise;\n }\n\n async executeCommand(\n command: string,\n opts?: ExecOptions,\n ): Promise<CommandResult> {\n await this.ensureInitialized();\n\n const wrappedCommand = await SandboxManager.wrapWithSandbox(command);\n\n return new Promise((resolve) => {\n const child = execCb(\n wrappedCommand,\n {\n cwd: opts?.cwd ?? this.defaultCwd,\n timeout: opts?.timeout ?? this.defaultTimeout,\n env: opts?.env ? { ...process.env, ...opts.env } : process.env,\n maxBuffer: 10 * 1024 * 1024,\n shell: process.env.SHELL || \"/bin/sh\",\n },\n (error, stdout, stderr) => {\n const result: CommandResult = {\n exitCode:\n error && \"code\" in error\n ? (typeof error.code === \"number\" ? error.code : 1)\n : child.exitCode ?? 0,\n stdout: stdout ?? \"\",\n stderr: stderr ?? \"\",\n };\n Promise.resolve(SandboxManager.cleanupAfterCommand())\n .then(() => resolve(result))\n .catch(() => resolve(result));\n },\n );\n });\n }\n\n /**\n * Tear down the sandbox runtime. Call when the agent is done.\n */\n async dispose(): Promise<void> {\n if (this.initialized) {\n await SandboxManager.reset();\n this.initialized = false;\n this.initPromise = null;\n }\n }\n}\n","import type { VirtualFs } from \"./fs.js\";\nimport type { VirtualComputer } from \"./computer.js\";\nimport { LocalFs } from \"./local-fs.js\";\nimport { LocalComputer } from \"./local-computer.js\";\nimport { SandboxedLocalComputer, type SandboxConfig } from \"./sandboxed-local-computer.js\";\n\nexport type { SandboxConfig } from \"./sandboxed-local-computer.js\";\n\n/**\n * Bundled sandbox: a `VirtualFs` and `VirtualComputer` paired together.\n *\n * Use one of the built-in factories (`LocalSandbox`, `UnsandboxedLocal`)\n * or import a remote backend from its subpath\n * (`noumen/docker`, `noumen/e2b`, `noumen/freestyle`, `noumen/ssh`,\n * `noumen/sprites`). You can also supply any object that satisfies this\n * shape for custom sandboxes (in-memory, custom cloud backends, etc.).\n */\nexport interface Sandbox {\n fs: VirtualFs;\n computer: VirtualComputer;\n /** Optional cleanup — called by Agent.close() to tear down OS-level sandbox state. */\n dispose?(): Promise<void>;\n /**\n * Lazily provision the underlying sandbox resource. Idempotent — repeated\n * calls return the same single-flight promise.\n *\n * When `sandboxId` is provided the sandbox reconnects to an existing\n * resource instead of creating a new one. This is used during session\n * resume: the stored sandbox identifier is read from session metadata\n * and passed here so the agent reattaches to its previous container.\n *\n * When omitted a fresh resource is provisioned (for factories that\n * support auto-creation) or the call is a no-op (for factories that\n * were given a pre-created resource up front).\n */\n init?(sandboxId?: string): Promise<void>;\n /**\n * Return the opaque identifier for this sandbox instance so it can be\n * persisted in session metadata and used to reconnect later via `init()`.\n * Returns `undefined` before `init()` has resolved or for sandboxes\n * that don't support reconnection.\n */\n sandboxId?(): string | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// UnsandboxedLocal — raw host access, no isolation\n// ---------------------------------------------------------------------------\n\nexport interface UnsandboxedLocalOptions {\n /** Working directory for both file resolution and command execution. */\n cwd?: string;\n /** Default timeout (ms) for shell commands. */\n defaultTimeout?: number;\n}\n\n/**\n * Create a `Sandbox` backed by the host filesystem and shell with **no\n * OS-level isolation**. The agent can access anything the host process can.\n *\n * Use this for development or fully-trusted environments where sandboxing\n * overhead is unwanted. For production use, prefer `LocalSandbox()` (which\n * wraps commands with `@anthropic-ai/sandbox-runtime`).\n */\nexport function UnsandboxedLocal(opts?: UnsandboxedLocalOptions): Sandbox {\n const cwd = opts?.cwd;\n return {\n fs: new LocalFs({ basePath: cwd }),\n computer: new LocalComputer({\n defaultCwd: cwd,\n defaultTimeout: opts?.defaultTimeout,\n }),\n };\n}\n\n// ---------------------------------------------------------------------------\n// LocalSandbox — OS-level sandboxing via @anthropic-ai/sandbox-runtime\n// ---------------------------------------------------------------------------\n\nexport interface LocalSandboxOptions {\n /** Working directory for both file resolution and command execution. */\n cwd?: string;\n /** Default timeout (ms) for shell commands. */\n defaultTimeout?: number;\n /**\n * Sandbox restrictions. Defaults: writes allowed only in `cwd`,\n * reads allowed everywhere, network unrestricted.\n */\n sandbox?: SandboxConfig;\n}\n\n/**\n * Create a `Sandbox` with OS-level isolation via `@anthropic-ai/sandbox-runtime`.\n *\n * - **macOS**: Seatbelt (`sandbox-exec`) profiles restrict filesystem and network.\n * - **Linux**: bubblewrap (`bwrap`) + socat for namespace-based isolation.\n *\n * Filesystem operations (`VirtualFs`) use the host `node:fs` — the sandbox\n * boundary is enforced on shell commands (`VirtualComputer`), which is where\n * the agent executes arbitrary code.\n *\n * Requires `@anthropic-ai/sandbox-runtime` as a peer dependency.\n */\nexport function LocalSandbox(opts?: LocalSandboxOptions): Sandbox {\n const cwd = opts?.cwd ?? process.cwd();\n const computer = new SandboxedLocalComputer({\n defaultCwd: cwd,\n defaultTimeout: opts?.defaultTimeout,\n sandbox: {\n filesystem: {\n allowWrite: [cwd, ...(opts?.sandbox?.filesystem?.allowWrite ?? [])],\n denyWrite: opts?.sandbox?.filesystem?.denyWrite,\n denyRead: opts?.sandbox?.filesystem?.denyRead,\n allowRead: opts?.sandbox?.filesystem?.allowRead,\n },\n network: opts?.sandbox?.network,\n },\n });\n return {\n fs: new LocalFs({ basePath: cwd }),\n computer,\n dispose: () => computer.dispose(),\n };\n}\n","import { createHash } from \"node:crypto\";\nimport type { VirtualFs } from \"../virtual/fs.js\";\nimport type {\n FileCheckpointBackup,\n FileCheckpointSnapshot,\n FileCheckpointState,\n CheckpointConfig,\n DiffStats,\n} from \"./types.js\";\nimport { createCheckpointState } from \"./types.js\";\n\nconst DEFAULT_MAX_SNAPSHOTS = 100;\nconst DEFAULT_BACKUP_DIR = \".noumen/checkpoints\";\n\nfunction hashFilePath(filePath: string): string {\n return createHash(\"sha256\").update(filePath).digest(\"hex\").slice(0, 16);\n}\n\nfunction backupFileName(filePath: string, version: number): string {\n return `${hashFilePath(filePath)}@v${version}`;\n}\n\nexport class FileCheckpointManager {\n private fs: VirtualFs;\n private maxSnapshots: number;\n private backupDir: string;\n private state: FileCheckpointState;\n\n constructor(fs: VirtualFs, config: CheckpointConfig) {\n this.fs = fs;\n this.maxSnapshots = config.maxSnapshots ?? DEFAULT_MAX_SNAPSHOTS;\n this.backupDir = config.backupDir ?? DEFAULT_BACKUP_DIR;\n this.state = createCheckpointState();\n }\n\n getState(): FileCheckpointState {\n return this.state;\n }\n\n private sessionBackupDir(sessionId: string): string {\n return `${this.backupDir}/${sessionId}`;\n }\n\n private resolveBackupPath(sessionId: string, bkFileName: string): string {\n return `${this.sessionBackupDir(sessionId)}/${bkFileName}`;\n }\n\n private async ensureBackupDir(sessionId: string): Promise<void> {\n const dir = this.sessionBackupDir(sessionId);\n const exists = await this.fs.exists(dir);\n if (!exists) {\n await this.fs.mkdir(dir, { recursive: true });\n }\n }\n\n private async createBackup(\n filePath: string,\n version: number,\n sessionId: string,\n ): Promise<FileCheckpointBackup> {\n const exists = await this.fs.exists(filePath);\n if (!exists) {\n return {\n backupFileName: null,\n version,\n backupTime: new Date().toISOString(),\n };\n }\n\n await this.ensureBackupDir(sessionId);\n const bkName = backupFileName(filePath, version);\n const bkPath = this.resolveBackupPath(sessionId, bkName);\n const content = await this.fs.readFile(filePath);\n await this.fs.writeFile(bkPath, content);\n\n return {\n backupFileName: bkName,\n version,\n backupTime: new Date().toISOString(),\n };\n }\n\n private async restoreBackup(\n filePath: string,\n bkFileName: string,\n sessionId: string,\n ): Promise<void> {\n const bkPath = this.resolveBackupPath(sessionId, bkFileName);\n const exists = await this.fs.exists(bkPath);\n if (!exists) return;\n\n const content = await this.fs.readFile(bkPath);\n await this.fs.writeFile(filePath, content);\n }\n\n private async hasFileChanged(\n filePath: string,\n backup: FileCheckpointBackup,\n sessionId: string,\n ): Promise<boolean> {\n const fileExists = await this.fs.exists(filePath);\n\n if (backup.backupFileName === null) {\n return fileExists;\n }\n\n if (!fileExists) return true;\n\n const bkPath = this.resolveBackupPath(sessionId, backup.backupFileName);\n const bkExists = await this.fs.exists(bkPath);\n if (!bkExists) return true;\n\n const currentContent = await this.fs.readFile(filePath);\n const backupContent = await this.fs.readFile(bkPath);\n return currentContent !== backupContent;\n }\n\n /**\n * Create a new snapshot at the start of a user turn.\n * For each tracked file, checks if it changed since the last backup and\n * creates a new versioned backup if so.\n */\n async makeSnapshot(messageId: string, sessionId: string): Promise<void> {\n const state = this.state;\n const mostRecent = state.snapshots.at(-1);\n\n const newBackups: Record<string, FileCheckpointBackup> = {};\n\n if (mostRecent) {\n for (const trackingPath of state.trackedFiles) {\n const lastBackup = mostRecent.trackedFileBackups[trackingPath];\n if (!lastBackup) continue;\n\n const changed = await this.hasFileChanged(trackingPath, lastBackup, sessionId);\n if (changed) {\n const nextVersion = lastBackup.version + 1;\n newBackups[trackingPath] = await this.createBackup(\n trackingPath,\n nextVersion,\n sessionId,\n );\n } else {\n newBackups[trackingPath] = lastBackup;\n }\n }\n }\n\n const snapshot: FileCheckpointSnapshot = {\n messageId,\n trackedFileBackups: newBackups,\n timestamp: new Date().toISOString(),\n };\n\n state.snapshots.push(snapshot);\n if (state.snapshots.length > this.maxSnapshots) {\n state.snapshots = state.snapshots.slice(-this.maxSnapshots);\n }\n state.snapshotSequence++;\n }\n\n /**\n * Track a file before it is edited. Creates the v1 backup (pre-edit state)\n * and attaches it to the current (latest) snapshot.\n * Called by write/edit tools before mutation.\n */\n async trackEdit(\n filePath: string,\n messageId: string,\n sessionId: string,\n ): Promise<void> {\n const state = this.state;\n const mostRecent = state.snapshots.at(-1);\n if (!mostRecent) return;\n\n if (mostRecent.trackedFileBackups[filePath]) return;\n\n const backup = await this.createBackup(filePath, 1, sessionId);\n mostRecent.trackedFileBackups[filePath] = backup;\n state.trackedFiles.add(filePath);\n }\n\n /**\n * Restore all tracked files to the state captured in the snapshot\n * matching the given messageId. Files that didn't exist at that point\n * are deleted; files that existed are restored from backups.\n */\n async rewind(messageId: string, sessionId: string): Promise<void> {\n const state = this.state;\n\n let targetSnapshot: FileCheckpointSnapshot | undefined;\n for (let i = state.snapshots.length - 1; i >= 0; i--) {\n if (state.snapshots[i].messageId === messageId) {\n targetSnapshot = state.snapshots[i];\n break;\n }\n }\n\n if (!targetSnapshot) {\n throw new Error(`No checkpoint snapshot found for messageId: ${messageId}`);\n }\n\n for (const trackingPath of state.trackedFiles) {\n const backup = targetSnapshot.trackedFileBackups[trackingPath];\n if (!backup) continue;\n\n if (backup.backupFileName === null) {\n const exists = await this.fs.exists(trackingPath);\n if (exists) {\n await this.fs.deleteFile(trackingPath);\n }\n } else {\n const changed = await this.hasFileChanged(trackingPath, backup, sessionId);\n if (changed) {\n await this.restoreBackup(trackingPath, backup.backupFileName, sessionId);\n }\n }\n }\n }\n\n canRestore(messageId: string): boolean {\n return this.state.snapshots.some((s) => s.messageId === messageId);\n }\n\n async getDiffStats(\n messageId: string,\n sessionId: string,\n ): Promise<DiffStats> {\n const state = this.state;\n\n let targetSnapshot: FileCheckpointSnapshot | undefined;\n for (let i = state.snapshots.length - 1; i >= 0; i--) {\n if (state.snapshots[i].messageId === messageId) {\n targetSnapshot = state.snapshots[i];\n break;\n }\n }\n\n if (!targetSnapshot) return undefined;\n\n let insertions = 0;\n let deletions = 0;\n const filesChanged: string[] = [];\n\n for (const trackingPath of state.trackedFiles) {\n const backup = targetSnapshot.trackedFileBackups[trackingPath];\n if (!backup) continue;\n\n const currentExists = await this.fs.exists(trackingPath);\n const currentContent = currentExists\n ? await this.fs.readFile(trackingPath)\n : \"\";\n\n let backupContent = \"\";\n if (backup.backupFileName !== null) {\n const bkPath = this.resolveBackupPath(sessionId, backup.backupFileName);\n const bkExists = await this.fs.exists(bkPath);\n if (bkExists) {\n backupContent = await this.fs.readFile(bkPath);\n }\n }\n\n if (currentContent === backupContent) continue;\n\n filesChanged.push(trackingPath);\n const currentLines = currentContent.split(\"\\n\");\n const backupLines = backupContent.split(\"\\n\");\n\n const maxLen = Math.max(currentLines.length, backupLines.length);\n for (let i = 0; i < maxLen; i++) {\n const cur = currentLines[i];\n const bak = backupLines[i];\n if (cur !== bak) {\n if (cur !== undefined && bak === undefined) {\n insertions++;\n } else if (cur === undefined && bak !== undefined) {\n deletions++;\n } else {\n insertions++;\n deletions++;\n }\n }\n }\n }\n\n return { filesChanged, insertions, deletions };\n }\n\n /**\n * Rebuild checkpoint state from persisted JSONL entries (for session resume).\n * Mirrors claude-code's buildFileHistorySnapshotChain + fileHistoryRestoreStateFromLog.\n */\n restoreStateFromEntries(snapshots: FileCheckpointSnapshot[]): void {\n const trackedFiles = new Set<string>();\n for (const snap of snapshots) {\n for (const path of Object.keys(snap.trackedFileBackups)) {\n trackedFiles.add(path);\n }\n }\n\n this.state = {\n snapshots: [...snapshots],\n trackedFiles,\n snapshotSequence: snapshots.length,\n };\n }\n}\n","/**\n * File checkpointing types.\n *\n * Adapted from claude-code's fileHistory system. Key difference: all I/O\n * routes through VirtualFs so checkpointing works in any sandbox (Docker,\n * E2B, Sprites, local).\n */\n\nexport interface FileCheckpointBackup {\n /** Backup filename under the session backup dir, or null if the file did not exist at this version. */\n backupFileName: string | null;\n version: number;\n backupTime: string;\n}\n\nexport interface FileCheckpointSnapshot {\n messageId: string;\n /** Map of tracked file paths → their backup at this snapshot. */\n trackedFileBackups: Record<string, FileCheckpointBackup>;\n timestamp: string;\n}\n\nexport interface FileCheckpointState {\n snapshots: FileCheckpointSnapshot[];\n trackedFiles: Set<string>;\n /**\n * Monotonically-increasing counter incremented on every snapshot, even when\n * old snapshots are evicted. Useful as an activity signal (snapshots.length\n * plateaus once the cap is reached).\n */\n snapshotSequence: number;\n}\n\nexport interface CheckpointConfig {\n enabled: boolean;\n /** Maximum number of snapshots to retain before evicting oldest. Default: 100. */\n maxSnapshots?: number;\n /** Base directory for backup files. Default: \".noumen/checkpoints\". */\n backupDir?: string;\n}\n\nexport type DiffStats =\n | {\n filesChanged?: string[];\n insertions: number;\n deletions: number;\n }\n | undefined;\n\nexport function createCheckpointState(): FileCheckpointState {\n return {\n snapshots: [],\n trackedFiles: new Set(),\n snapshotSequence: 0,\n };\n}\n","import type {\n HookEvent,\n HookDefinition,\n HookInput,\n HookOutput,\n PreToolUseHookInput,\n PreToolUseHookOutput,\n PostToolUseHookInput,\n PostToolUseHookOutput,\n PostToolUseFailureHookInput,\n PostToolUseFailureHookOutput,\n} from \"./types.js\";\n\nconst DEFAULT_HOOK_TIMEOUT_MS = 30_000;\n\nfunction withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n label: string,\n): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new Error(`Hook \"${label}\" timed out after ${timeoutMs}ms`)),\n timeoutMs,\n );\n promise.then(\n (v) => { clearTimeout(timer); resolve(v); },\n (e) => { clearTimeout(timer); reject(e); },\n );\n });\n}\n\n/**\n * Match a tool name against an optional glob-like matcher.\n * Supports '*' as a wildcard prefix/suffix (e.g. \"mcp__*\", \"*File\").\n */\nfunction matchesPattern(toolName: string, matcher: string): boolean {\n if (matcher === \"*\") return true;\n if (matcher.endsWith(\"*\")) {\n return toolName.startsWith(matcher.slice(0, -1));\n }\n if (matcher.startsWith(\"*\")) {\n return toolName.endsWith(matcher.slice(1));\n }\n return toolName === matcher;\n}\n\nfunction getMatchingHooks(\n hooks: HookDefinition[],\n event: HookEvent,\n toolName?: string,\n): HookDefinition[] {\n return hooks.filter((h) => {\n if (h.event !== event) return false;\n if (h.matcher && toolName) {\n return matchesPattern(toolName, h.matcher);\n }\n return !h.matcher;\n });\n}\n\n/**\n * Run pre-tool-use hooks. Returns a merged output where later hooks override\n * earlier ones. A 'deny' decision from any hook short-circuits.\n */\nexport async function runPreToolUseHooks(\n hooks: HookDefinition[],\n input: PreToolUseHookInput,\n): Promise<PreToolUseHookOutput> {\n const matching = getMatchingHooks(hooks, \"PreToolUse\", input.toolName);\n let merged: PreToolUseHookOutput = {};\n\n for (const hook of matching) {\n try {\n const label = hook.matcher ?? \"PreToolUse\";\n const output = (await withTimeout(\n Promise.resolve(hook.handler(input)),\n DEFAULT_HOOK_TIMEOUT_MS,\n label,\n )) as PreToolUseHookOutput | void;\n if (!output) continue;\n\n if (output.decision === \"deny\") {\n return output;\n }\n if (output.updatedInput !== undefined) {\n merged.updatedInput = output.updatedInput;\n input = { ...input, toolInput: output.updatedInput };\n }\n if (output.decision !== undefined) merged.decision = output.decision;\n if (output.message !== undefined) merged.message = output.message;\n if (output.preventContinuation !== undefined) {\n merged.preventContinuation = output.preventContinuation;\n }\n } catch (err) {\n if (hook.blocking) {\n return {\n decision: \"deny\",\n message: `Blocking hook error: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n const errMsg = err instanceof Error ? err.message : String(err);\n console.warn(`[noumen/hooks] PreToolUse hook failed:`, errMsg);\n merged.hookErrors ??= [];\n merged.hookErrors.push({ hook: hook.matcher ?? \"PreToolUse\", error: errMsg });\n }\n }\n\n return merged;\n}\n\n/**\n * Run post-tool-use hooks. Returns merged output.\n */\nexport async function runPostToolUseHooks(\n hooks: HookDefinition[],\n input: PostToolUseHookInput,\n): Promise<PostToolUseHookOutput> {\n const matching = getMatchingHooks(hooks, \"PostToolUse\", input.toolName);\n let merged: PostToolUseHookOutput = {};\n\n for (const hook of matching) {\n try {\n const label = hook.matcher ?? \"PostToolUse\";\n const output = (await withTimeout(\n Promise.resolve(hook.handler(input)),\n DEFAULT_HOOK_TIMEOUT_MS,\n label,\n )) as PostToolUseHookOutput | void;\n if (!output) continue;\n\n if (output.updatedOutput !== undefined) {\n merged.updatedOutput = output.updatedOutput;\n input = { ...input, toolOutput: output.updatedOutput };\n }\n if (output.preventContinuation !== undefined) {\n merged.preventContinuation = output.preventContinuation;\n }\n } catch (err) {\n if (hook.blocking) {\n return {\n updatedOutput: `Blocking hook error: ${err instanceof Error ? err.message : String(err)}`,\n preventContinuation: true,\n };\n }\n console.warn(`[noumen/hooks] PostToolUse hook failed:`, err instanceof Error ? err.message : err);\n }\n }\n\n return merged;\n}\n\n/**\n * Run post-tool-use-failure hooks. Same shape as post-tool-use hooks but\n * triggers on the PostToolUseFailure event, fired only when `isError` is true.\n */\nexport async function runPostToolUseFailureHooks(\n hooks: HookDefinition[],\n input: PostToolUseFailureHookInput,\n): Promise<PostToolUseFailureHookOutput> {\n const matching = getMatchingHooks(hooks, \"PostToolUseFailure\", input.toolName);\n let merged: PostToolUseFailureHookOutput = {};\n\n for (const hook of matching) {\n try {\n const label = hook.matcher ?? \"PostToolUseFailure\";\n const output = (await withTimeout(\n Promise.resolve(hook.handler(input)),\n DEFAULT_HOOK_TIMEOUT_MS,\n label,\n )) as PostToolUseFailureHookOutput | void;\n if (!output) continue;\n\n if (output.updatedOutput !== undefined) {\n merged.updatedOutput = output.updatedOutput;\n input = { ...input, toolOutput: output.updatedOutput };\n }\n if (output.preventContinuation !== undefined) {\n merged.preventContinuation = output.preventContinuation;\n }\n } catch (err) {\n if (hook.blocking) {\n return {\n updatedOutput: `Blocking hook error: ${err instanceof Error ? err.message : String(err)}`,\n preventContinuation: true,\n };\n }\n console.warn(`[noumen/hooks] PostToolUseFailure hook failed:`, err instanceof Error ? err.message : err);\n }\n }\n\n return merged;\n}\n\n/**\n * Run notification hooks concurrently (fire-and-forget, no return value).\n */\nexport async function runNotificationHooks(\n hooks: HookDefinition[],\n event: HookEvent,\n input: HookInput,\n): Promise<void> {\n const matching = getMatchingHooks(hooks, event);\n if (matching.length === 0) return;\n\n const results = await Promise.allSettled(\n matching.map((hook) => {\n const label = hook.matcher ?? String(event);\n return withTimeout(\n Promise.resolve(hook.handler(input)),\n DEFAULT_HOOK_TIMEOUT_MS,\n label,\n );\n }),\n );\n\n for (const result of results) {\n if (result.status === \"rejected\") {\n const err = result.reason;\n console.warn(`[noumen/hooks] ${event} notification hook failed:`, err instanceof Error ? err.message : err);\n }\n }\n}\n","/**\n * Model-facing prompt for the Agent (subagent) tool.\n * Adapted from claude-code's AgentTool/prompt.ts — simplified for noumen's\n * library context without coordinator/fork/subscription-specific logic.\n */\n\nexport const AGENT_PROMPT = `Launch a new agent to handle complex, multi-step tasks autonomously.\n\nThe Agent tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent runs with its own conversation context and a configurable subset of tools.\n\nWhen NOT to use the Agent tool:\n- If you want to read a specific file path, use the ReadFile or Glob tool instead to find the match more quickly\n- If you are searching for a specific class definition like \"class Foo\", use the Glob tool instead\n- If you are searching for code within a specific file or set of 2-3 files, use the ReadFile tool instead\n\nUsage notes:\n- Always include a short description (3-5 words) summarizing what the agent will do\n- Launch multiple agents concurrently whenever possible to maximize performance; to do that, use a single message with multiple tool uses\n- When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.\n- Each Agent invocation starts fresh — provide a complete task description.\n- The agent's outputs should generally be trusted\n- Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.)\n\n## Writing the prompt\n\nBrief the agent like a smart colleague who just walked into the room — it hasn't seen this conversation, doesn't know what you've tried, doesn't understand why this task matters.\n- Explain what you're trying to accomplish and why.\n- Describe what you've already learned or ruled out.\n- Give enough context about the surrounding problem that the agent can make judgment calls rather than just following a narrow instruction.\n- If you need a short response, say so (\"report in under 200 words\").\n- Lookups: hand over the exact command. Investigations: hand over the question — prescribed steps become dead weight when the premise is wrong.\n\nTerse command-style prompts produce shallow, generic work.\n\n**Never delegate understanding.** Don't write \"based on your findings, fix the bug\" or \"based on the research, implement it.\" Those phrases push synthesis onto the agent instead of doing it yourself. Write prompts that prove you understood: include file paths, line numbers, what specifically to change.\n`;\n","import type { Tool, ToolResult, ToolContext } from \"./types.js\";\nimport { runNotificationHooks } from \"../hooks/runner.js\";\nimport { AGENT_PROMPT } from \"./prompts/agent.js\";\n\nconst DEFAULT_MAX_TURNS = 25;\n\nexport const agentTool: Tool = {\n name: \"Agent\",\n description:\n \"Spawn an isolated subagent to handle a focused subtask. The subagent \" +\n \"runs in its own conversation context and returns its final response. \" +\n \"Use for tasks that benefit from independent context (research, \" +\n \"code generation, analysis) or when you want to parallelise work.\",\n prompt: AGENT_PROMPT,\n isReadOnly: false,\n isConcurrencySafe: true,\n parameters: {\n type: \"object\",\n properties: {\n prompt: {\n type: \"string\",\n description:\n \"The task description for the subagent. Be specific about what to do and what to return.\",\n },\n systemPrompt: {\n type: \"string\",\n description: \"Optional system prompt override for the subagent.\",\n },\n allowedTools: {\n type: \"string\",\n description:\n \"Comma-separated list of tool names the subagent may use. Omit to inherit all parent tools except Agent.\",\n },\n async: {\n type: \"string\",\n description:\n 'Set to \"true\" to run the agent in the background and return immediately with a taskId. ' +\n \"Check status with TaskGet.\",\n enum: [\"true\", \"false\"],\n },\n },\n required: [\"prompt\"],\n },\n\n async call(\n args: Record<string, unknown>,\n ctx: ToolContext,\n ): Promise<ToolResult> {\n if (!ctx.spawnSubagent) {\n return {\n content: \"Subagents are not enabled. Set enableSubagents: true in AgentOptions.\",\n isError: true,\n };\n }\n\n const prompt = args.prompt as string;\n const systemPrompt = args.systemPrompt as string | undefined;\n const allowedToolsRaw = args.allowedTools as string | undefined;\n const allowedTools = allowedToolsRaw\n ? allowedToolsRaw.split(\",\").map((t) => t.trim()).filter(Boolean)\n : undefined;\n const isAsync = args.async === \"true\";\n\n const maxTurns = DEFAULT_MAX_TURNS;\n const { sessionId, events } = ctx.spawnSubagent({\n prompt,\n systemPrompt,\n allowedTools,\n maxTurns,\n });\n\n // Fire SubagentStart hook\n if (ctx.hooks && ctx.hooks.length > 0) {\n await runNotificationHooks(ctx.hooks, \"SubagentStart\", {\n event: \"SubagentStart\",\n sessionId,\n parentSessionId: ctx.sessionId ?? \"\",\n prompt,\n });\n }\n\n if (isAsync && ctx.taskStore) {\n const task = await ctx.taskStore.create({\n subject: `Agent: ${prompt.slice(0, 80)}`,\n description: `Async agent running with sessionId: ${sessionId}`,\n });\n await ctx.taskStore.update(task.id, { status: \"in_progress\" });\n\n // Fire and forget — collect results into task store when done.\n (async () => {\n const assistantTexts: string[] = [];\n try {\n for await (const event of events) {\n if (event.type === \"message_complete\" && event.message.content) {\n assistantTexts.push(event.message.content);\n }\n if (event.type === \"turn_complete\") break;\n }\n const result = assistantTexts.join(\"\\n\\n\") || \"(no output)\";\n await ctx.taskStore!.update(task.id, {\n status: \"completed\",\n description: result.slice(0, 10_000),\n });\n if (ctx.hooks && ctx.hooks.length > 0) {\n await runNotificationHooks(ctx.hooks, \"SubagentStop\", {\n event: \"SubagentStop\",\n sessionId,\n parentSessionId: ctx.sessionId ?? \"\",\n result,\n });\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n await ctx.taskStore!.update(task.id, {\n status: \"completed\",\n description: `Error: ${msg}`,\n });\n if (ctx.hooks && ctx.hooks.length > 0) {\n await runNotificationHooks(ctx.hooks, \"SubagentStop\", {\n event: \"SubagentStop\",\n sessionId,\n parentSessionId: ctx.sessionId ?? \"\",\n result: `Error: ${msg}`,\n });\n }\n }\n })();\n\n return {\n content: JSON.stringify({\n taskId: task.id,\n sessionId,\n message: \"Agent launched in background. Use TaskGet to check status.\",\n }),\n };\n }\n\n // Synchronous mode (original behavior)\n const assistantTexts: string[] = [];\n let turnCount = 0;\n\n try {\n for await (const event of events) {\n if (event.type === \"message_complete\" && event.message.content) {\n assistantTexts.push(event.message.content);\n }\n if (event.type === \"turn_complete\") {\n turnCount++;\n if (turnCount >= maxTurns) {\n break;\n }\n }\n if (event.type === \"error\") {\n const errorResult = `Subagent error: ${event.error.message}`;\n if (ctx.hooks && ctx.hooks.length > 0) {\n await runNotificationHooks(ctx.hooks, \"SubagentStop\", {\n event: \"SubagentStop\",\n sessionId,\n parentSessionId: ctx.sessionId ?? \"\",\n result: errorResult,\n });\n }\n return { content: errorResult, isError: true };\n }\n }\n } catch (err) {\n const errorResult = `Subagent failed: ${err instanceof Error ? err.message : String(err)}`;\n if (ctx.hooks && ctx.hooks.length > 0) {\n await runNotificationHooks(ctx.hooks, \"SubagentStop\", {\n event: \"SubagentStop\",\n sessionId,\n parentSessionId: ctx.sessionId ?? \"\",\n result: errorResult,\n });\n }\n return { content: errorResult, isError: true };\n }\n\n const result = assistantTexts.join(\"\\n\\n\");\n\n if (ctx.hooks && ctx.hooks.length > 0) {\n await runNotificationHooks(ctx.hooks, \"SubagentStop\", {\n event: \"SubagentStop\",\n sessionId,\n parentSessionId: ctx.sessionId ?? \"\",\n result: result || \"(subagent produced no output)\",\n });\n }\n\n return {\n content: result || \"(subagent produced no output)\",\n };\n },\n};\n","/**\n * Model-facing prompt for the WebSearch tool.\n * Adapted from claude-code's WebSearchTool/prompt.ts.\n */\n\nfunction getCurrentMonthYear(): string {\n const d = new Date();\n return d.toLocaleString(\"en-US\", { month: \"long\", year: \"numeric\" });\n}\n\nexport function getWebSearchPrompt(): string {\n const currentMonthYear = getCurrentMonthYear();\n return `Search the web for real-time information about any topic. Returns summarized information from search results and relevant URLs.\n\n- Provides up-to-date information for current events and recent data\n- Returns search result information including links as markdown hyperlinks\n- Use this tool for accessing information beyond the model's knowledge cutoff\n\nCRITICAL REQUIREMENT:\n- After answering the user's question, you MUST include a \"Sources:\" section at the end of your response\n- In the Sources section, list all relevant URLs from the search results as markdown hyperlinks: [Title](URL)\n- This is MANDATORY — never skip including sources in your response\n- Example format:\n\n [Your answer here]\n\n Sources:\n - [Source Title 1](https://example.com/1)\n - [Source Title 2](https://example.com/2)\n\nIMPORTANT — Use the correct year in search queries:\n- The current month is ${currentMonthYear}. You MUST use this year when searching for recent information, documentation, or current events.\n- Example: If the user asks for \"latest React docs\", search for \"React documentation\" with the current year, NOT last year.\n`;\n}\n","import type { Tool, ToolResult, ToolContext } from \"./types.js\";\nimport { getWebSearchPrompt } from \"./prompts/web-search.js\";\n\nexport interface WebSearchResult {\n title: string;\n url: string;\n snippet: string;\n}\n\nexport interface WebSearchConfig {\n search: (query: string, domains?: string[]) => Promise<WebSearchResult[]>;\n}\n\n/**\n * Create a WebSearch tool backed by a user-provided search implementation.\n * This keeps noumen provider-agnostic — plug in Tavily, SerpAPI, Brave Search, etc.\n *\n * @example\n * ```ts\n * const webSearch = createWebSearchTool({\n * search: async (query) => {\n * const res = await tavily.search({ query });\n * return res.results.map(r => ({ title: r.title, url: r.url, snippet: r.content }));\n * },\n * });\n * ```\n */\nexport function createWebSearchTool(config: WebSearchConfig): Tool {\n return {\n name: \"WebSearch\",\n description:\n \"Search the web for real-time information. Returns titles, URLs, and \" +\n \"snippets from search results. Use when you need up-to-date information \" +\n \"not available in the local codebase.\",\n prompt: getWebSearchPrompt,\n isReadOnly: true,\n isConcurrencySafe: true,\n parameters: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"The search query\",\n },\n domains: {\n type: \"string\",\n description:\n \"Comma-separated list of domains to restrict search to (e.g. 'docs.python.org,stackoverflow.com')\",\n },\n },\n required: [\"query\"],\n },\n\n async call(\n args: Record<string, unknown>,\n _ctx: ToolContext,\n ): Promise<ToolResult> {\n const query = args.query as string;\n const domainsRaw = args.domains as string | undefined;\n const domains = domainsRaw\n ? domainsRaw.split(\",\").map((d) => d.trim()).filter(Boolean)\n : undefined;\n\n try {\n const results = await config.search(query, domains);\n\n if (results.length === 0) {\n return { content: \"No search results found.\" };\n }\n\n const formatted = results\n .map(\n (r, i) =>\n `${i + 1}. [${r.title}](${r.url})\\n ${r.snippet}`,\n )\n .join(\"\\n\\n\");\n\n return { content: `Search results for: ${query}\\n\\n${formatted}` };\n } catch (err) {\n return {\n content: `Search error: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n };\n }\n },\n };\n}\n\n/**\n * Default WebSearch tool that returns a helpful error when no search provider\n * is configured. Register this as a placeholder; consumers should replace\n * it with `createWebSearchTool(config)`.\n */\nexport const webSearchToolPlaceholder: Tool = {\n name: \"WebSearch\",\n description: \"Search the web (requires configuration — see noumen docs).\",\n isReadOnly: true,\n isConcurrencySafe: true,\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query\" },\n },\n required: [\"query\"],\n },\n\n async call(): Promise<ToolResult> {\n return {\n content:\n \"WebSearch is not configured. Provide a search implementation \" +\n \"via AgentOptions.options.webSearch or createWebSearchTool().\",\n isError: true,\n };\n },\n};\n","import type { Tool } from \"./types.js\";\n\nexport const taskCreateTool: Tool = {\n name: \"TaskCreate\",\n description:\n \"Create a new task/todo item for tracking work. Use this to decompose complex work into trackable steps.\",\n parameters: {\n type: \"object\",\n properties: {\n subject: {\n type: \"string\",\n description: \"Short title for the task\",\n },\n description: {\n type: \"string\",\n description: \"Optional detailed description of the task\",\n },\n },\n required: [\"subject\"],\n },\n isReadOnly: false,\n isConcurrencySafe: true,\n\n async call(args, ctx) {\n if (!ctx.taskStore) {\n return { content: \"Task management is not enabled.\", isError: true };\n }\n const subject = args.subject as string;\n const description = args.description as string | undefined;\n\n const task = await ctx.taskStore.create({ subject, description });\n return {\n content: JSON.stringify({ id: task.id, subject: task.subject }),\n };\n },\n};\n","import type { Tool } from \"./types.js\";\n\nexport const taskListTool: Tool = {\n name: \"TaskList\",\n description:\n \"List all tasks with their current status and dependency information.\",\n parameters: {\n type: \"object\",\n properties: {},\n },\n isReadOnly: true,\n isConcurrencySafe: true,\n\n async call(_args, ctx) {\n if (!ctx.taskStore) {\n return { content: \"Task management is not enabled.\", isError: true };\n }\n const tasks = await ctx.taskStore.list();\n\n const filtered = tasks.map((t) => ({\n id: t.id,\n subject: t.subject,\n status: t.status,\n owner: t.owner,\n blockedBy: t.blockedBy.filter((dep) => {\n const blocking = tasks.find((bt) => bt.id === dep);\n return blocking && blocking.status !== \"completed\";\n }),\n }));\n\n return { content: JSON.stringify({ tasks: filtered }, null, 2) };\n },\n};\n","import type { Tool } from \"./types.js\";\n\nexport const taskGetTool: Tool = {\n name: \"TaskGet\",\n description: \"Get details of a specific task by ID.\",\n parameters: {\n type: \"object\",\n properties: {\n taskId: {\n type: \"string\",\n description: \"The task ID to retrieve\",\n },\n },\n required: [\"taskId\"],\n },\n isReadOnly: true,\n isConcurrencySafe: true,\n\n async call(args, ctx) {\n if (!ctx.taskStore) {\n return { content: \"Task management is not enabled.\", isError: true };\n }\n const task = await ctx.taskStore.get(args.taskId as string);\n if (!task) {\n return { content: `Task ${args.taskId} not found.`, isError: true };\n }\n return { content: JSON.stringify({ task }, null, 2) };\n },\n};\n","import type { Tool } from \"./types.js\";\nimport type { TaskStatus } from \"../tasks/types.js\";\n\nexport const taskUpdateTool: Tool = {\n name: \"TaskUpdate\",\n description:\n \"Update a task's status, description, or dependencies. Set status to 'completed' when done, or 'deleted' to remove.\",\n parameters: {\n type: \"object\",\n properties: {\n taskId: {\n type: \"string\",\n description: \"The task ID to update\",\n },\n status: {\n type: \"string\",\n description: \"New status: pending, in_progress, completed, or deleted\",\n enum: [\"pending\", \"in_progress\", \"completed\", \"deleted\"],\n },\n description: {\n type: \"string\",\n description: \"Updated description\",\n },\n owner: {\n type: \"string\",\n description: \"Name of the agent/user that owns this task\",\n },\n blockedBy: {\n type: \"string\",\n description:\n \"Comma-separated list of task IDs that must complete before this task\",\n },\n },\n required: [\"taskId\"],\n },\n isReadOnly: false,\n isConcurrencySafe: true,\n\n async call(args, ctx) {\n if (!ctx.taskStore) {\n return { content: \"Task management is not enabled.\", isError: true };\n }\n\n const taskId = args.taskId as string;\n const status = args.status as string | undefined;\n\n if (status === \"deleted\") {\n const deleted = await ctx.taskStore.delete(taskId);\n if (!deleted) {\n return { content: `Task ${taskId} not found.`, isError: true };\n }\n return { content: JSON.stringify({ success: true, taskId, deleted: true }) };\n }\n\n const blockedByRaw = args.blockedBy as string | undefined;\n const blockedBy = blockedByRaw\n ? blockedByRaw.split(\",\").map((s) => s.trim()).filter(Boolean)\n : undefined;\n\n const task = await ctx.taskStore.update(taskId, {\n status: status as TaskStatus | undefined,\n description: args.description as string | undefined,\n owner: args.owner as string | undefined,\n blockedBy,\n });\n\n if (!task) {\n return { content: `Task ${taskId} not found.`, isError: true };\n }\n\n return {\n content: JSON.stringify({\n success: true,\n taskId,\n updatedFields: Object.keys(args).filter((k) => k !== \"taskId\"),\n }),\n };\n },\n};\n","import type { Tool } from \"./types.js\";\n\nexport const enterPlanModeTool: Tool = {\n name: \"EnterPlanMode\",\n description:\n \"Enter plan mode to explore the codebase and create a plan before making changes. \" +\n \"In plan mode, file writes and edits are restricted. Use this when you need to \" +\n \"understand the codebase structure before implementing changes.\",\n parameters: {\n type: \"object\",\n properties: {},\n },\n isReadOnly: true,\n isConcurrencySafe: true,\n\n async call(_args, ctx) {\n if (!ctx.setPermissionMode || !ctx.getPermissionMode) {\n return {\n content: \"Plan mode is not enabled.\",\n isError: true,\n };\n }\n\n const currentMode = ctx.getPermissionMode();\n if (currentMode === \"plan\") {\n return {\n content: \"Already in plan mode.\",\n isError: true,\n };\n }\n\n ctx.setPermissionMode(\"plan\");\n\n return {\n content: JSON.stringify({\n previousMode: currentMode,\n currentMode: \"plan\",\n message:\n \"Entered plan mode. File writes and edits are now restricted. \" +\n \"Use read-only tools (ReadFile, Glob, Grep, Bash with read-only commands) \" +\n \"to explore the codebase. When you have a plan, use ExitPlanMode to \" +\n \"return to the previous mode and begin implementation.\",\n }),\n };\n },\n};\n\nexport const exitPlanModeTool: Tool = {\n name: \"ExitPlanMode\",\n description:\n \"Exit plan mode and return to the previous permission mode. \" +\n \"Optionally provide a plan summary that will be included in the conversation.\",\n parameters: {\n type: \"object\",\n properties: {\n plan: {\n type: \"string\",\n description:\n \"Optional plan summary describing what you intend to implement\",\n },\n },\n },\n isReadOnly: true,\n isConcurrencySafe: true,\n\n async call(args, ctx) {\n if (!ctx.setPermissionMode || !ctx.getPermissionMode) {\n return {\n content: \"Plan mode is not enabled.\",\n isError: true,\n };\n }\n\n const currentMode = ctx.getPermissionMode();\n if (currentMode !== \"plan\") {\n return {\n content: \"Not currently in plan mode.\",\n isError: true,\n };\n }\n\n // Restore to default mode (the Thread manages prePlanMode state)\n ctx.setPermissionMode(\"default\");\n\n const plan = args.plan as string | undefined;\n const result: Record<string, unknown> = {\n currentMode: \"default\",\n message: \"Exited plan mode. You can now make changes.\",\n };\n if (plan) {\n result.plan = plan;\n }\n\n return { content: JSON.stringify(result) };\n },\n};\n","import type { VirtualComputer } from \"../virtual/computer.js\";\n\nexport interface WorktreeInfo {\n path: string;\n branch: string;\n head?: string;\n}\n\n/**\n * Find the git root directory from a given cwd.\n */\nexport async function findGitRoot(\n computer: VirtualComputer,\n cwd: string,\n): Promise<string | null> {\n const result = await computer.executeCommand(\n \"git rev-parse --show-toplevel\",\n { cwd, timeout: 5000 },\n );\n if (result.exitCode !== 0) return null;\n return result.stdout.trim();\n}\n\n/**\n * Get the default branch name (main/master).\n */\nexport async function getDefaultBranch(\n computer: VirtualComputer,\n cwd: string,\n): Promise<string> {\n const result = await computer.executeCommand(\n \"git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || echo refs/heads/main\",\n { cwd, timeout: 5000 },\n );\n const ref = result.stdout.trim();\n return ref.replace(\"refs/remotes/origin/\", \"\").replace(\"refs/heads/\", \"\");\n}\n\n/**\n * Create a git worktree at the given path with the given branch name.\n */\nexport async function createWorktree(\n computer: VirtualComputer,\n repoRoot: string,\n worktreePath: string,\n branchName: string,\n baseBranch?: string,\n): Promise<{ success: boolean; error?: string }> {\n const base = baseBranch ?? (await getDefaultBranch(computer, repoRoot));\n const cmd = `git worktree add -B \"${branchName}\" \"${worktreePath}\" \"${base}\"`;\n const result = await computer.executeCommand(cmd, {\n cwd: repoRoot,\n timeout: 30000,\n });\n\n if (result.exitCode !== 0) {\n return { success: false, error: result.stderr.trim() || result.stdout.trim() };\n }\n return { success: true };\n}\n\n/**\n * Remove a git worktree.\n */\nexport async function removeWorktree(\n computer: VirtualComputer,\n repoRoot: string,\n worktreePath: string,\n branchName?: string,\n): Promise<{ success: boolean; error?: string }> {\n const rmResult = await computer.executeCommand(\n `git worktree remove --force \"${worktreePath}\"`,\n { cwd: repoRoot, timeout: 15000 },\n );\n\n if (rmResult.exitCode !== 0) {\n return { success: false, error: rmResult.stderr.trim() };\n }\n\n if (branchName) {\n await computer.executeCommand(`git branch -D \"${branchName}\"`, {\n cwd: repoRoot,\n timeout: 5000,\n });\n }\n\n return { success: true };\n}\n\n/**\n * List existing git worktrees.\n */\nexport async function listWorktrees(\n computer: VirtualComputer,\n cwd: string,\n): Promise<WorktreeInfo[]> {\n const result = await computer.executeCommand(\"git worktree list --porcelain\", {\n cwd,\n timeout: 5000,\n });\n if (result.exitCode !== 0) return [];\n\n const worktrees: WorktreeInfo[] = [];\n let current: Partial<WorktreeInfo> = {};\n\n for (const line of result.stdout.split(\"\\n\")) {\n if (line.startsWith(\"worktree \")) {\n if (current.path) worktrees.push(current as WorktreeInfo);\n current = { path: line.slice(9) };\n } else if (line.startsWith(\"HEAD \")) {\n current.head = line.slice(5);\n } else if (line.startsWith(\"branch \")) {\n current.branch = line.slice(7).replace(\"refs/heads/\", \"\");\n } else if (line === \"\") {\n if (current.path) worktrees.push(current as WorktreeInfo);\n current = {};\n }\n }\n if (current.path) worktrees.push(current as WorktreeInfo);\n\n return worktrees;\n}\n\n/**\n * Check if a worktree has uncommitted changes or unpushed commits.\n */\nexport async function getWorktreeChanges(\n computer: VirtualComputer,\n worktreePath: string,\n): Promise<{ hasChanges: boolean; uncommittedFiles: number; unpushedCommits: number }> {\n const statusResult = await computer.executeCommand(\n \"git status --porcelain\",\n { cwd: worktreePath, timeout: 5000 },\n );\n const uncommittedFiles = statusResult.stdout\n .trim()\n .split(\"\\n\")\n .filter((l) => l.length > 0).length;\n\n const logResult = await computer.executeCommand(\n \"git rev-list --count @{upstream}..HEAD 2>/dev/null || echo 0\",\n { cwd: worktreePath, timeout: 5000 },\n );\n const unpushedCommits = parseInt(logResult.stdout.trim(), 10) || 0;\n\n return {\n hasChanges: uncommittedFiles > 0 || unpushedCommits > 0,\n uncommittedFiles,\n unpushedCommits,\n };\n}\n\n/**\n * Sanitize a name for use as a worktree slug/branch name.\n */\nexport function sanitizeWorktreeSlug(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-|-$/g, \"\")\n .slice(0, 50);\n}\n","import type { Tool } from \"./types.js\";\nimport {\n findGitRoot,\n createWorktree,\n removeWorktree,\n getWorktreeChanges,\n sanitizeWorktreeSlug,\n} from \"../utils/worktree.js\";\n\nexport const enterWorktreeTool: Tool = {\n name: \"EnterWorktree\",\n description:\n \"Create an isolated git worktree and switch into it. This creates a separate \" +\n \"working copy on a new branch so you can make changes without affecting the \" +\n \"main working directory. Use this for parallel or experimental work.\",\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n \"Optional name for the worktree (used as branch name suffix). \" +\n \"If omitted, a default name is generated.\",\n },\n },\n },\n isReadOnly: false,\n\n async call(args, ctx) {\n const repoRoot = await findGitRoot(ctx.computer, ctx.cwd);\n if (!repoRoot) {\n return {\n content: \"Not inside a git repository. Worktrees require git.\",\n isError: true,\n };\n }\n\n const slug = sanitizeWorktreeSlug(\n (args.name as string) || `noumen-${Date.now()}`,\n );\n const worktreePath = `${repoRoot}/.noumen/worktrees/${slug}`;\n const branchName = `worktree-${slug}`;\n\n const result = await createWorktree(\n ctx.computer,\n repoRoot,\n worktreePath,\n branchName,\n );\n\n if (!result.success) {\n return {\n content: `Failed to create worktree: ${result.error}`,\n isError: true,\n };\n }\n\n if (ctx.setCwd) {\n ctx.setCwd(worktreePath);\n }\n\n return {\n content: JSON.stringify({\n worktreePath,\n worktreeBranch: branchName,\n previousCwd: ctx.cwd,\n message: `Created worktree at ${worktreePath} on branch ${branchName}. ` +\n \"Working directory switched. Use ExitWorktree when done.\",\n }),\n };\n },\n};\n\nexport const exitWorktreeTool: Tool = {\n name: \"ExitWorktree\",\n description:\n \"Exit the current worktree and return to the original working directory. \" +\n 'Use action \"keep\" to preserve the worktree, or \"remove\" to clean it up.',\n parameters: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n description: 'Whether to \"keep\" the worktree or \"remove\" it',\n enum: [\"keep\", \"remove\"],\n },\n worktreePath: {\n type: \"string\",\n description: \"Path to the worktree to exit (usually the current cwd)\",\n },\n originalCwd: {\n type: \"string\",\n description: \"Original working directory to return to\",\n },\n },\n required: [\"action\", \"worktreePath\", \"originalCwd\"],\n },\n isReadOnly: false,\n\n async call(args, ctx) {\n const action = args.action as \"keep\" | \"remove\";\n const worktreePath = args.worktreePath as string;\n const originalCwd = args.originalCwd as string;\n\n if (action === \"remove\") {\n const changes = await getWorktreeChanges(ctx.computer, worktreePath);\n if (changes.hasChanges) {\n return {\n content: JSON.stringify({\n error: \"Worktree has uncommitted changes or unpushed commits.\",\n uncommittedFiles: changes.uncommittedFiles,\n unpushedCommits: changes.unpushedCommits,\n message:\n \"Cannot remove worktree with pending changes. \" +\n 'Commit/push your changes first, or use action \"keep\".',\n }),\n isError: true,\n };\n }\n\n const repoRoot = await findGitRoot(ctx.computer, originalCwd);\n if (repoRoot) {\n const branchMatch = worktreePath.match(/worktrees\\/(.+)$/);\n const branchName = branchMatch\n ? `worktree-${branchMatch[1]}`\n : undefined;\n const result = await removeWorktree(\n ctx.computer,\n repoRoot,\n worktreePath,\n branchName,\n );\n if (!result.success) {\n return {\n content: `Failed to remove worktree: ${result.error}`,\n isError: true,\n };\n }\n }\n }\n\n if (ctx.setCwd) {\n ctx.setCwd(originalCwd);\n }\n\n return {\n content: JSON.stringify({\n action,\n restoredCwd: originalCwd,\n message:\n action === \"remove\"\n ? \"Worktree removed and working directory restored.\"\n : \"Worktree kept. Working directory restored.\",\n }),\n };\n },\n};\n","import type { ModelPricing, UsageRecord } from \"./types.js\";\n\n// Pricing tiers (USD per 1M tokens), sourced from public pricing docs\nconst TIER_3_15: ModelPricing = { inputTokens: 3, outputTokens: 15, cacheReadTokens: 0.3, cacheWriteTokens: 3.75 };\nconst TIER_5_25: ModelPricing = { inputTokens: 5, outputTokens: 25, cacheReadTokens: 0.5, cacheWriteTokens: 6.25 };\nconst TIER_15_75: ModelPricing = { inputTokens: 15, outputTokens: 75, cacheReadTokens: 1.5, cacheWriteTokens: 18.75 };\nconst TIER_30_150: ModelPricing = { inputTokens: 30, outputTokens: 150, cacheReadTokens: 3, cacheWriteTokens: 37.5 };\nconst TIER_HAIKU_35: ModelPricing = { inputTokens: 0.8, outputTokens: 4, cacheReadTokens: 0.08, cacheWriteTokens: 1 };\nconst TIER_HAIKU_45: ModelPricing = { inputTokens: 1, outputTokens: 5, cacheReadTokens: 0.1, cacheWriteTokens: 1.25 };\n\n// OpenAI tiers\nconst TIER_GPT4O: ModelPricing = { inputTokens: 2.5, outputTokens: 10, cacheReadTokens: 1.25 };\nconst TIER_GPT4O_MINI: ModelPricing = { inputTokens: 0.15, outputTokens: 0.6, cacheReadTokens: 0.075 };\nconst TIER_GPT41: ModelPricing = { inputTokens: 2, outputTokens: 8, cacheReadTokens: 0.5 };\nconst TIER_GPT41_MINI: ModelPricing = { inputTokens: 0.4, outputTokens: 1.6, cacheReadTokens: 0.1 };\nconst TIER_GPT41_NANO: ModelPricing = { inputTokens: 0.1, outputTokens: 0.4, cacheReadTokens: 0.025 };\nconst TIER_O3: ModelPricing = { inputTokens: 2, outputTokens: 8, cacheReadTokens: 0.5 };\nconst TIER_O3_MINI: ModelPricing = { inputTokens: 1.1, outputTokens: 4.4, cacheReadTokens: 0.275 };\nconst TIER_O4_MINI: ModelPricing = { inputTokens: 1.1, outputTokens: 4.4, cacheReadTokens: 0.275 };\n\n// Google Gemini tiers\nconst TIER_GEMINI_FLASH: ModelPricing = { inputTokens: 0.075, outputTokens: 0.3 };\nconst TIER_GEMINI_PRO: ModelPricing = { inputTokens: 1.25, outputTokens: 5 };\nconst TIER_GEMINI_FLASH_LITE: ModelPricing = { inputTokens: 0.0375, outputTokens: 0.15 };\n\n/**\n * Default pricing table for common models. Keys are matched as substrings\n * against the model ID so versioned model strings (e.g. `claude-sonnet-4`)\n * resolve correctly.\n */\nexport const DEFAULT_PRICING: Record<string, ModelPricing> = {\n // Anthropic\n \"claude-sonnet-4\": TIER_5_25,\n \"claude-opus-4\": TIER_15_75,\n \"claude-3-5-sonnet\": TIER_3_15,\n \"claude-3-5-haiku\": TIER_HAIKU_45,\n \"claude-3-haiku\": TIER_HAIKU_35,\n \"claude-3-opus\": TIER_30_150,\n\n // OpenAI\n \"gpt-4o-mini\": TIER_GPT4O_MINI,\n \"gpt-4o\": TIER_GPT4O,\n \"gpt-4.1-mini\": TIER_GPT41_MINI,\n \"gpt-4.1-nano\": TIER_GPT41_NANO,\n \"gpt-4.1\": TIER_GPT41,\n \"o4-mini\": TIER_O4_MINI,\n \"o3-mini\": TIER_O3_MINI,\n \"o3\": TIER_O3,\n\n // Google Gemini\n \"gemini-2.5-flash\": TIER_GEMINI_FLASH,\n \"gemini-2.5-pro\": TIER_GEMINI_PRO,\n \"gemini-2.0-flash\": TIER_GEMINI_FLASH,\n \"gemini-2.0-flash-lite\": TIER_GEMINI_FLASH_LITE,\n \"gemini-1.5-flash\": TIER_GEMINI_FLASH,\n \"gemini-1.5-pro\": TIER_GEMINI_PRO,\n};\n\n/**\n * Find pricing for a model by checking if the model string contains any\n * known pricing key as a substring. More specific keys (longer) are\n * checked first to ensure e.g. \"gpt-4o-mini\" matches before \"gpt-4o\".\n */\nexport function findModelPricing(\n model: string,\n pricing: Record<string, ModelPricing>,\n): ModelPricing | null {\n const sortedKeys = Object.keys(pricing).sort((a, b) => b.length - a.length);\n for (const key of sortedKeys) {\n if (model.includes(key)) {\n return pricing[key];\n }\n }\n return null;\n}\n\n/**\n * Set of models already warned about to avoid log spam.\n */\nconst warnedUnknownModels = new Set<string>();\n\n/**\n * Calculate USD cost for a usage record using the given pricing table.\n * Returns 0 if the model is not found in the pricing table and logs a\n * one-time warning per unknown model.\n */\nexport function calculateCost(\n model: string,\n usage: UsageRecord,\n pricing: Record<string, ModelPricing> = DEFAULT_PRICING,\n): number {\n const p = findModelPricing(model, pricing);\n if (!p) {\n if (!warnedUnknownModels.has(model)) {\n warnedUnknownModels.add(model);\n console.warn(`[noumen/cost] No pricing data for model \"${model}\" — cost will be reported as $0`);\n }\n return 0;\n }\n\n const perMillion = 1_000_000;\n let cost = 0;\n const cacheRead = usage.cache_read_tokens ?? 0;\n const cacheWrite = usage.cache_creation_tokens ?? 0;\n const nonCachedInput = Math.max(0, usage.prompt_tokens - cacheRead - cacheWrite);\n cost += (nonCachedInput / perMillion) * p.inputTokens;\n cost += (usage.completion_tokens / perMillion) * p.outputTokens;\n if (cacheRead && p.cacheReadTokens) {\n cost += (cacheRead / perMillion) * p.cacheReadTokens;\n }\n if (cacheWrite && p.cacheWriteTokens) {\n cost += (cacheWrite / perMillion) * p.cacheWriteTokens;\n }\n return cost;\n}\n","import type { ModelPricing, UsageRecord, ModelUsageSummary, CostSummary } from \"./types.js\";\nimport { calculateCost, DEFAULT_PRICING } from \"./pricing.js\";\n\nexport interface StoredCostState {\n byModel: Record<string, ModelUsageSummary>;\n totalApiMs: number;\n wallStartMs: number;\n}\n\nexport class CostTracker {\n private pricing: Record<string, ModelPricing>;\n private byModel: Record<string, ModelUsageSummary> = {};\n private totalApiMs = 0;\n private wallStartMs = Date.now();\n\n constructor(pricing?: Record<string, ModelPricing>) {\n this.pricing = pricing ?? DEFAULT_PRICING;\n }\n\n addUsage(model: string, usage: UsageRecord, apiDurationMs?: number): CostSummary {\n const cost = calculateCost(model, usage, this.pricing);\n\n if (!this.byModel[model]) {\n this.byModel[model] = {\n inputTokens: 0,\n outputTokens: 0,\n thinkingTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n costUSD: 0,\n };\n }\n\n const m = this.byModel[model];\n m.inputTokens += usage.prompt_tokens;\n m.outputTokens += usage.completion_tokens;\n m.thinkingTokens += usage.thinking_tokens ?? 0;\n m.cacheReadTokens += usage.cache_read_tokens ?? 0;\n m.cacheCreationTokens += usage.cache_creation_tokens ?? 0;\n m.costUSD += cost;\n\n if (apiDurationMs !== undefined) {\n this.totalApiMs += apiDurationMs;\n }\n\n return this.getSummary();\n }\n\n getSummary(): CostSummary {\n let totalCostUSD = 0;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalThinkingTokens = 0;\n let totalCacheReadTokens = 0;\n let totalCacheCreationTokens = 0;\n\n for (const m of Object.values(this.byModel)) {\n totalCostUSD += m.costUSD;\n totalInputTokens += m.inputTokens;\n totalOutputTokens += m.outputTokens;\n totalThinkingTokens += m.thinkingTokens;\n totalCacheReadTokens += m.cacheReadTokens;\n totalCacheCreationTokens += m.cacheCreationTokens;\n }\n\n return {\n totalCostUSD,\n totalInputTokens,\n totalOutputTokens,\n totalThinkingTokens,\n totalCacheReadTokens,\n totalCacheCreationTokens,\n byModel: { ...this.byModel },\n duration: {\n apiMs: this.totalApiMs,\n wallMs: Date.now() - this.wallStartMs,\n },\n };\n }\n\n reset(): void {\n this.byModel = {};\n this.totalApiMs = 0;\n this.wallStartMs = Date.now();\n }\n\n getState(): StoredCostState {\n return {\n byModel: structuredClone(this.byModel),\n totalApiMs: this.totalApiMs,\n wallStartMs: this.wallStartMs,\n };\n }\n\n restore(state: StoredCostState): void {\n this.byModel = structuredClone(state.byModel);\n this.totalApiMs = state.totalApiMs;\n this.wallStartMs = state.wallStartMs;\n }\n\n formatSummary(): string {\n const s = this.getSummary();\n const costStr = s.totalCostUSD > 0.5\n ? `$${s.totalCostUSD.toFixed(2)}`\n : `$${s.totalCostUSD.toFixed(4)}`;\n\n const lines = [`Total cost: ${costStr}`];\n\n const models = Object.entries(s.byModel);\n if (models.length > 0) {\n lines.push(\"Usage by model:\");\n for (const [model, m] of models) {\n const parts = [\n `${formatNum(m.inputTokens)} input`,\n `${formatNum(m.outputTokens)} output`,\n ];\n if (m.thinkingTokens > 0) parts.push(`${formatNum(m.thinkingTokens)} thinking`);\n if (m.cacheReadTokens > 0) parts.push(`${formatNum(m.cacheReadTokens)} cache read`);\n if (m.cacheCreationTokens > 0) parts.push(`${formatNum(m.cacheCreationTokens)} cache write`);\n parts.push(`($${m.costUSD.toFixed(4)})`);\n lines.push(` ${model}: ${parts.join(\", \")}`);\n }\n }\n\n return lines.join(\"\\n\");\n }\n}\n\nfunction formatNum(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;\n return String(n);\n}\n","export function jsonStringify(value: unknown): string {\n return JSON.stringify(value);\n}\n\nexport interface ParseJSONLResult<T> {\n entries: T[];\n droppedLines: number;\n}\n\nexport function parseJSONL<T = unknown>(text: string): T[] {\n return parseJSONLWithDiag<T>(text).entries;\n}\n\nexport function parseJSONLWithDiag<T = unknown>(text: string): ParseJSONLResult<T> {\n const entries: T[] = [];\n let droppedLines = 0;\n for (const line of text.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n entries.push(JSON.parse(trimmed) as T);\n } catch {\n droppedLines++;\n }\n }\n if (droppedLines > 0) {\n console.warn(`[noumen/session] JSONL parse: ${droppedLines} malformed line(s) dropped`);\n }\n return { entries, droppedLines };\n}\n","import type { VirtualFs } from \"../virtual/fs.js\";\nimport type {\n ChatMessage,\n Entry,\n MessageEntry,\n CompactBoundaryEntry,\n SummaryEntry,\n MetadataEntry,\n ToolResultOverflowEntry,\n FileCheckpointEntry,\n ContentReplacementEntry,\n ContentReplacementRecord,\n SnipBoundaryEntry,\n SessionInfo,\n} from \"./types.js\";\nimport type { FileCheckpointSnapshot } from \"../checkpoint/types.js\";\nimport { generateUUID } from \"../utils/uuid.js\";\nimport type { UUID } from \"../utils/uuid.js\";\nimport { jsonStringify, parseJSONL } from \"../utils/json.js\";\n\nexport class SessionStorage {\n private fs: VirtualFs;\n private sessionDir: string;\n private writeLock: Promise<void> = Promise.resolve();\n\n constructor(fs: VirtualFs, sessionDir: string) {\n this.fs = fs;\n this.sessionDir = sessionDir;\n }\n\n /**\n * Serialize writes through a simple promise chain so parallel\n * appendEntry calls don't interleave large JSONL records.\n */\n private serializedWrite(fn: () => Promise<void>): Promise<void> {\n const next = this.writeLock.then(fn, fn);\n this.writeLock = next.then(() => {}, () => {});\n return next;\n }\n\n private getTranscriptPath(sessionId: string): string {\n return `${this.sessionDir}/${sessionId}.jsonl`;\n }\n\n async ensureDir(): Promise<void> {\n const exists = await this.fs.exists(this.sessionDir);\n if (!exists) {\n await this.fs.mkdir(this.sessionDir, { recursive: true });\n }\n }\n\n async appendEntry(sessionId: string, entry: Entry): Promise<void> {\n return this.serializedWrite(async () => {\n await this.ensureDir();\n const line = jsonStringify(entry) + \"\\n\";\n await this.fs.appendFile(this.getTranscriptPath(sessionId), line);\n });\n }\n\n /**\n * Append multiple entries atomically as a single write.\n * All entries are serialized into one string and written in one appendFile\n * call, preventing partial writes on crash.\n */\n async appendEntriesBatch(sessionId: string, entries: Entry[]): Promise<void> {\n if (entries.length === 0) return;\n return this.serializedWrite(async () => {\n await this.ensureDir();\n const lines = entries.map((e) => jsonStringify(e) + \"\\n\").join(\"\");\n await this.fs.appendFile(this.getTranscriptPath(sessionId), lines);\n });\n }\n\n async appendMessage(\n sessionId: string,\n message: ChatMessage,\n parentUuid: UUID | null = null,\n ): Promise<UUID> {\n const uuid = generateUUID();\n const entry: MessageEntry = {\n type: \"message\",\n uuid,\n parentUuid,\n sessionId,\n timestamp: new Date().toISOString(),\n message,\n };\n await this.appendEntry(sessionId, entry);\n return uuid;\n }\n\n async appendCompactBoundary(sessionId: string): Promise<UUID> {\n const uuid = generateUUID();\n const entry: CompactBoundaryEntry = {\n type: \"compact-boundary\",\n uuid,\n sessionId,\n timestamp: new Date().toISOString(),\n };\n await this.appendEntry(sessionId, entry);\n return uuid;\n }\n\n async appendSummary(\n sessionId: string,\n summaryMessage: ChatMessage,\n parentUuid: UUID | null = null,\n ): Promise<UUID> {\n const uuid = generateUUID();\n const entry: SummaryEntry = {\n type: \"summary\",\n uuid,\n parentUuid,\n sessionId,\n timestamp: new Date().toISOString(),\n message: summaryMessage,\n };\n await this.appendEntry(sessionId, entry);\n return uuid;\n }\n\n async appendToolResultOverflow(\n sessionId: string,\n toolCallId: string,\n originalContent: string,\n ): Promise<void> {\n const entry: ToolResultOverflowEntry = {\n type: \"tool-result-overflow\",\n sessionId,\n timestamp: new Date().toISOString(),\n toolCallId,\n originalContent,\n };\n await this.appendEntry(sessionId, entry);\n }\n\n async appendCheckpointEntry(\n sessionId: string,\n messageId: string,\n snapshot: FileCheckpointSnapshot,\n isSnapshotUpdate: boolean,\n ): Promise<void> {\n const entry: FileCheckpointEntry = {\n type: \"file-checkpoint\",\n sessionId,\n timestamp: new Date().toISOString(),\n messageId,\n snapshot,\n isSnapshotUpdate,\n };\n await this.appendEntry(sessionId, entry);\n }\n\n async appendSnipBoundary(\n sessionId: string,\n removedUuids: string[],\n ): Promise<void> {\n if (removedUuids.length === 0) return;\n const entry: SnipBoundaryEntry = {\n type: \"snip-boundary\",\n sessionId,\n timestamp: new Date().toISOString(),\n snipMetadata: { removedUuids },\n };\n await this.appendEntry(sessionId, entry);\n }\n\n async appendContentReplacement(\n sessionId: string,\n replacements: ContentReplacementRecord[],\n ): Promise<void> {\n if (replacements.length === 0) return;\n const entry: ContentReplacementEntry = {\n type: \"content-replacement\",\n sessionId,\n timestamp: new Date().toISOString(),\n replacements,\n };\n await this.appendEntry(sessionId, entry);\n }\n\n async appendMetadata(\n sessionId: string,\n key: string,\n value: unknown,\n ): Promise<void> {\n const entry: MetadataEntry = {\n type: \"metadata\",\n sessionId,\n timestamp: new Date().toISOString(),\n key,\n value,\n };\n await this.appendEntry(sessionId, entry);\n }\n\n /**\n * Re-append custom-title and key metadata entries after a compact boundary\n * so they remain discoverable in the active-entries window.\n */\n async reAppendMetadataAfterCompact(sessionId: string): Promise<void> {\n const entries = await this.loadAllEntries(sessionId);\n let customTitle: string | undefined;\n const metadataByKey = new Map<string, unknown>();\n\n for (const entry of entries) {\n if (entry.type === \"custom-title\") {\n customTitle = entry.title;\n }\n if (entry.type === \"metadata\") {\n metadataByKey.set(entry.key, entry.value);\n }\n }\n\n if (customTitle) {\n await this.appendEntry(sessionId, {\n type: \"custom-title\",\n sessionId,\n title: customTitle,\n timestamp: new Date().toISOString(),\n });\n }\n\n for (const [key, value] of metadataByKey) {\n await this.appendMetadata(sessionId, key, value);\n }\n }\n\n async loadMessages(sessionId: string): Promise<ChatMessage[]> {\n const path = this.getTranscriptPath(sessionId);\n\n const exists = await this.fs.exists(path);\n if (!exists) return [];\n\n const content = await this.fs.readFile(path);\n const entries = parseJSONL<Entry>(content);\n\n let lastBoundaryIdx = -1;\n for (let i = entries.length - 1; i >= 0; i--) {\n if (entries[i].type === \"compact-boundary\") {\n // Validate: boundary must have at least one summary or message after it.\n // If not (crash between boundary + summary write), skip to the prior boundary.\n const afterBoundary = entries.slice(i + 1);\n const hasSummaryOrMessage = afterBoundary.some(\n (e) => e.type === \"summary\" || e.type === \"message\",\n );\n if (hasSummaryOrMessage) {\n lastBoundaryIdx = i;\n break;\n }\n // else: orphaned boundary — keep searching backwards\n }\n }\n\n const activeEntries = entries.slice(lastBoundaryIdx + 1);\n\n const snippedUuids = new Set<string>();\n for (const entry of activeEntries) {\n if (entry.type === \"snip-boundary\") {\n for (const uuid of entry.snipMetadata.removedUuids) {\n snippedUuids.add(uuid);\n }\n }\n }\n\n const messages: ChatMessage[] = [];\n for (const entry of activeEntries) {\n if (entry.type === \"message\" || entry.type === \"summary\") {\n if (!snippedUuids.has(entry.uuid)) {\n messages.push(entry.message);\n }\n }\n }\n\n return messages;\n }\n\n async loadAllEntries(sessionId: string): Promise<Entry[]> {\n const path = this.getTranscriptPath(sessionId);\n\n const exists = await this.fs.exists(path);\n if (!exists) return [];\n\n const content = await this.fs.readFile(path);\n return parseJSONL<Entry>(content);\n }\n\n async sessionExists(sessionId: string): Promise<boolean> {\n return this.fs.exists(this.getTranscriptPath(sessionId));\n }\n\n async deleteSession(sessionId: string): Promise<void> {\n const filePath = this.getTranscriptPath(sessionId);\n const exists = await this.fs.exists(filePath);\n if (exists) {\n await this.fs.deleteFile(filePath);\n }\n }\n\n async listSessions(): Promise<SessionInfo[]> {\n await this.ensureDir();\n\n let dirEntries;\n try {\n dirEntries = await this.fs.readdir(this.sessionDir);\n } catch {\n return [];\n }\n\n const sessions: SessionInfo[] = [];\n const LITE_READ_LIMIT = 32_768;\n\n for (const dirEntry of dirEntries) {\n if (!dirEntry.name.endsWith(\".jsonl\")) continue;\n\n const sessionId = dirEntry.name.replace(\".jsonl\", \"\");\n try {\n const filePath = this.getTranscriptPath(sessionId);\n\n // Cap reads to avoid OOM on very large session files.\n // VirtualFs implementations that support maxBytes will only read the\n // first LITE_READ_LIMIT * 2 bytes; others return the full content.\n const content = await this.fs.readFile(filePath, {\n maxBytes: LITE_READ_LIMIT * 2,\n });\n\n let headSlice: string;\n let tailSlice: string;\n const isSplit = content.length >= LITE_READ_LIMIT * 2;\n if (isSplit) {\n const headEnd = content.lastIndexOf('\\n', LITE_READ_LIMIT);\n headSlice = headEnd > 0 ? content.slice(0, headEnd) : content.slice(0, LITE_READ_LIMIT);\n const tailStart = content.indexOf('\\n', content.length - LITE_READ_LIMIT);\n tailSlice = tailStart >= 0 ? content.slice(tailStart + 1) : content.slice(-LITE_READ_LIMIT);\n } else {\n headSlice = content;\n tailSlice = content;\n }\n\n const headEntries = parseJSONL<Entry>(headSlice);\n const tailEntries = isSplit\n ? parseJSONL<Entry>(tailSlice)\n : headEntries;\n\n let title: string | undefined;\n let firstTimestamp: string | undefined;\n let lastTimestamp: string | undefined;\n let messageCount = 0;\n\n for (const e of headEntries) {\n if (e.type === \"message\" || e.type === \"summary\") {\n messageCount++;\n if (!firstTimestamp) firstTimestamp = e.timestamp;\n lastTimestamp = e.timestamp;\n }\n if (e.type === \"custom-title\") title = e.title;\n }\n\n if (isSplit) {\n for (const e of tailEntries) {\n if (e.type === \"message\" || e.type === \"summary\") {\n messageCount++;\n if (e.timestamp) lastTimestamp = e.timestamp;\n }\n if (e.type === \"custom-title\") title = e.title;\n }\n }\n\n sessions.push({\n sessionId,\n createdAt: firstTimestamp ?? new Date().toISOString(),\n lastMessageAt: lastTimestamp ?? new Date().toISOString(),\n title,\n messageCount,\n });\n } catch {\n // skip corrupt sessions\n }\n }\n\n return sessions.sort(\n (a, b) =>\n new Date(b.lastMessageAt).getTime() -\n new Date(a.lastMessageAt).getTime(),\n );\n }\n}\n","import type { VirtualFs } from \"../virtual/fs.js\";\nimport type { Task, TaskCreateInput, TaskUpdateInput } from \"./types.js\";\n\n/**\n * File-backed task store persisted on a VirtualFs instance.\n * Tasks are stored as individual JSON files under a configurable directory.\n */\nexport class TaskStore {\n private dir: string;\n private fs: VirtualFs;\n private nextId = 1;\n private initialized = false;\n\n constructor(fs: VirtualFs, dir: string) {\n this.fs = fs;\n this.dir = dir;\n }\n\n private async ensureDir(): Promise<void> {\n if (this.initialized) return;\n try {\n await this.fs.mkdir(this.dir, { recursive: true });\n } catch {\n // may already exist\n }\n // Read existing tasks to determine next ID\n try {\n const files = await this.fs.readdir(this.dir);\n let maxId = 0;\n for (const f of files) {\n const match = f.name.match(/^(\\d+)\\.json$/);\n if (match) {\n maxId = Math.max(maxId, parseInt(match[1], 10));\n }\n }\n this.nextId = maxId + 1;\n } catch {\n // empty dir\n }\n this.initialized = true;\n }\n\n private taskPath(id: string): string {\n return `${this.dir}/${id}.json`;\n }\n\n async create(input: TaskCreateInput): Promise<Task> {\n await this.ensureDir();\n\n const id = String(this.nextId++);\n const now = new Date().toISOString();\n const task: Task = {\n id,\n subject: input.subject,\n description: input.description,\n status: \"pending\",\n blocks: [],\n blockedBy: [],\n createdAt: now,\n updatedAt: now,\n };\n\n await this.fs.writeFile(this.taskPath(id), JSON.stringify(task, null, 2));\n return task;\n }\n\n async get(id: string): Promise<Task | null> {\n await this.ensureDir();\n try {\n const content = await this.fs.readFile(this.taskPath(id));\n return JSON.parse(content) as Task;\n } catch {\n return null;\n }\n }\n\n async list(): Promise<Task[]> {\n await this.ensureDir();\n const tasks: Task[] = [];\n try {\n const files = await this.fs.readdir(this.dir);\n for (const f of files) {\n if (!f.name.endsWith(\".json\")) continue;\n try {\n const content = await this.fs.readFile(`${this.dir}/${f.name}`);\n tasks.push(JSON.parse(content) as Task);\n } catch {\n // skip corrupt files\n }\n }\n } catch {\n // empty\n }\n tasks.sort((a, b) => parseInt(a.id, 10) - parseInt(b.id, 10));\n return tasks;\n }\n\n async update(id: string, input: TaskUpdateInput): Promise<Task | null> {\n const task = await this.get(id);\n if (!task) return null;\n\n if (input.status !== undefined) task.status = input.status;\n if (input.description !== undefined) task.description = input.description;\n if (input.owner !== undefined) task.owner = input.owner;\n if (input.blockedBy !== undefined) {\n task.blockedBy = input.blockedBy;\n // Update reverse references\n const allTasks = await this.list();\n for (const t of allTasks) {\n const blocksIdx = t.blocks.indexOf(id);\n if (input.blockedBy.includes(t.id)) {\n if (blocksIdx === -1) t.blocks.push(id);\n } else {\n if (blocksIdx !== -1) t.blocks.splice(blocksIdx, 1);\n }\n await this.fs.writeFile(\n this.taskPath(t.id),\n JSON.stringify(t, null, 2),\n );\n }\n }\n\n task.updatedAt = new Date().toISOString();\n await this.fs.writeFile(this.taskPath(id), JSON.stringify(task, null, 2));\n return task;\n }\n\n async delete(id: string): Promise<boolean> {\n try {\n await this.fs.deleteFile(this.taskPath(id));\n return true;\n } catch {\n return false;\n }\n }\n}\n","import type { ContextFile, ContextScope } from \"./types.js\";\n\nconst SCOPE_LABELS: Record<ContextScope, string> = {\n managed: \"managed instructions\",\n user: \"user instructions\",\n project: \"project instructions\",\n local: \"local instructions\",\n};\n\nconst CONTEXT_PREAMBLE =\n \"The following project instructions customize your behavior. \" +\n \"Follow them unless they conflict with explicit user requests.\";\n\n/**\n * Format loaded context files into a system prompt section.\n *\n * Files are rendered in array order (lowest to highest priority).\n * Included sub-files are inlined immediately after their parent.\n */\nexport function buildProjectContextSection(\n files: ContextFile[],\n filter?: ContextScope[],\n): string {\n const applicable = filter\n ? files.filter((f) => filter.includes(f.scope))\n : files;\n\n if (applicable.length === 0) return \"\";\n\n const sections: string[] = [CONTEXT_PREAMBLE, \"\"];\n\n for (const file of applicable) {\n renderFile(file, sections);\n }\n\n return sections.join(\"\\n\");\n}\n\nfunction renderFile(file: ContextFile, out: string[]): void {\n const label = SCOPE_LABELS[file.scope];\n out.push(`Contents of ${file.path} (${label})\\n`);\n out.push(file.content);\n out.push(\"\");\n\n if (file.includes) {\n for (const inc of file.includes) {\n renderFile(inc, out);\n }\n }\n}\n","export interface FrontmatterData {\n \"allowed-tools\"?: string | string[] | null;\n description?: string | null;\n paths?: string | string[] | null;\n context?: \"inline\" | \"fork\" | null;\n \"argument-hint\"?: string | null;\n [key: string]: unknown;\n}\n\nexport interface ParsedFrontmatter {\n frontmatter: FrontmatterData;\n body: string;\n}\n\nconst FRONTMATTER_RE = /^---\\s*\\n([\\s\\S]*?)---\\s*\\n?/;\n\n/**\n * Parse YAML frontmatter from markdown content.\n * Returns the parsed frontmatter fields and the body after the closing ---.\n * If no frontmatter is found, returns empty frontmatter and the full content as body.\n */\nexport function parseFrontmatter(content: string): ParsedFrontmatter {\n const match = content.match(FRONTMATTER_RE);\n if (!match) {\n return { frontmatter: {}, body: content };\n }\n\n const yamlBlock = match[1];\n const body = content.slice(match[0].length);\n\n let data = parseSimpleYaml(yamlBlock);\n\n if (data === null) {\n // Retry: quote values that contain YAML-special characters\n const quoted = yamlBlock.replace(\n /^(\\s*[\\w-]+\\s*:\\s*)(.+)$/gm,\n (_, prefix: string, value: string) => {\n const trimmed = value.trim();\n if (\n !trimmed.startsWith('\"') &&\n !trimmed.startsWith(\"'\") &&\n /[{}\\[\\],*&!|>%@`]/.test(trimmed)\n ) {\n return `${prefix}\"${trimmed.replace(/\"/g, '\\\\\"')}\"`;\n }\n return `${prefix}${value}`;\n },\n );\n data = parseSimpleYaml(quoted);\n }\n\n return { frontmatter: data ?? {}, body };\n}\n\n/**\n * Minimal YAML-subset parser for frontmatter.\n * Handles: key: value, key: [list], multi-line lists with - items.\n */\nfunction parseSimpleYaml(yaml: string): FrontmatterData | null {\n try {\n const result: FrontmatterData = {};\n const lines = yaml.split(\"\\n\");\n let currentKey: string | null = null;\n let currentList: string[] | null = null;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n // Check for list item under current key\n const listItemMatch = trimmed.match(/^-\\s+(.+)$/);\n if (listItemMatch && currentKey && currentList) {\n currentList.push(unquote(listItemMatch[1].trim()));\n continue;\n }\n\n // Flush any pending list\n if (currentKey && currentList) {\n result[currentKey] = currentList.length === 1 ? currentList[0] : currentList;\n currentKey = null;\n currentList = null;\n }\n\n // Key: value pair\n const kvMatch = trimmed.match(/^([\\w-]+)\\s*:\\s*(.*)$/);\n if (!kvMatch) continue;\n\n const key = kvMatch[1];\n const rawValue = kvMatch[2].trim();\n\n if (!rawValue) {\n // Could be followed by list items\n currentKey = key;\n currentList = [];\n continue;\n }\n\n // Inline array: [a, b, c]\n if (rawValue.startsWith(\"[\") && rawValue.endsWith(\"]\")) {\n const inner = rawValue.slice(1, -1);\n result[key] = inner\n .split(\",\")\n .map((s) => unquote(s.trim()))\n .filter(Boolean);\n continue;\n }\n\n // Scalar value\n result[key] = unquote(rawValue);\n }\n\n // Flush trailing list\n if (currentKey && currentList) {\n result[currentKey] = currentList.length === 1 ? currentList[0] : currentList;\n }\n\n return result;\n } catch {\n return null;\n }\n}\n\nfunction unquote(s: string): string {\n if (\n (s.startsWith('\"') && s.endsWith('\"')) ||\n (s.startsWith(\"'\") && s.endsWith(\"'\"))\n ) {\n return s.slice(1, -1);\n }\n return s;\n}\n\n/**\n * Parse the allowed-tools field from frontmatter.\n * Accepts a string (comma/space separated), string[], or null/undefined.\n */\nexport function parseAllowedTools(\n value: string | string[] | null | undefined,\n): string[] {\n if (!value) return [];\n if (Array.isArray(value)) return value.map((s) => s.trim()).filter(Boolean);\n return value\n .split(/[,\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\n/**\n * Parse the paths field from frontmatter into glob patterns.\n */\nexport function parsePaths(\n value: string | string[] | null | undefined,\n): string[] {\n if (!value) return [];\n if (Array.isArray(value)) return value.map((s) => s.trim()).filter(Boolean);\n return value\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n}\n","import type { VirtualFs } from \"../virtual/fs.js\";\nimport type { ContextFile, ContextScope, ProjectContextConfig } from \"./types.js\";\nimport { parseFrontmatter, parsePaths } from \"../skills/frontmatter.js\";\n\nconst DEFAULT_MAX_INCLUDE_DEPTH = 5;\n\nconst NOUMEN_NAMES = {\n md: \"NOUMEN.md\",\n localMd: \"NOUMEN.local.md\",\n dotDir: \".noumen\",\n};\n\nconst CLAUDE_NAMES = {\n md: \"CLAUDE.md\",\n localMd: \"CLAUDE.local.md\",\n dotDir: \".claude\",\n};\n\ntype NameSet = typeof NOUMEN_NAMES;\n\n/**\n * Load project context files from the hierarchical NOUMEN.md / CLAUDE.md\n * convention. Returns files ordered lowest-to-highest priority:\n * managed -> user -> project (root first, cwd last) -> local.\n */\nexport async function loadProjectContext(\n fs: VirtualFs,\n config: ProjectContextConfig,\n): Promise<ContextFile[]> {\n const maxDepth = config.maxIncludeDepth ?? DEFAULT_MAX_INCLUDE_DEPTH;\n const loadClaude = config.loadClaudeMd ?? true;\n const nameSets: NameSet[] = [NOUMEN_NAMES];\n if (loadClaude) nameSets.push(CLAUDE_NAMES);\n\n const excludes = config.excludes ?? [];\n const files: ContextFile[] = [];\n\n // 1. Managed layer\n if (config.managedDir) {\n for (const ns of nameSets) {\n await tryLoadFile(fs, join(config.managedDir, ns.md), \"managed\", files, maxDepth, excludes);\n await scanRulesDir(fs, join(config.managedDir, ns.dotDir, \"rules\"), \"managed\", files, maxDepth, excludes);\n }\n }\n\n // 2. User layer\n if ((config.loadUserContext ?? true) && config.homeDir) {\n for (const ns of nameSets) {\n await tryLoadFile(fs, join(config.homeDir, ns.dotDir, ns.md), \"user\", files, maxDepth, excludes);\n await scanRulesDir(fs, join(config.homeDir, ns.dotDir, \"rules\"), \"user\", files, maxDepth, excludes);\n }\n }\n\n // 3. Project walk (root -> cwd for ascending priority)\n const dirs = walkAncestors(config.cwd);\n\n if (config.loadProjectContext ?? true) {\n for (const dir of dirs) {\n for (const ns of nameSets) {\n await tryLoadFile(fs, join(dir, ns.md), \"project\", files, maxDepth, excludes);\n await tryLoadFile(fs, join(dir, ns.dotDir, ns.md), \"project\", files, maxDepth, excludes);\n await scanRulesDir(fs, join(dir, ns.dotDir, \"rules\"), \"project\", files, maxDepth, excludes);\n }\n }\n }\n\n // 4. Local layer (same walk order)\n if (config.loadLocalContext ?? true) {\n for (const dir of dirs) {\n for (const ns of nameSets) {\n await tryLoadFile(fs, join(dir, ns.localMd), \"local\", files, maxDepth, excludes);\n }\n }\n }\n\n return files;\n}\n\n/**\n * Walk from filesystem root down to cwd (root first = lowest priority).\n */\nfunction walkAncestors(cwd: string): string[] {\n const normalized = cwd.endsWith(\"/\") && cwd.length > 1 ? cwd.slice(0, -1) : cwd;\n const parts = normalized.split(\"/\");\n const dirs: string[] = [];\n\n // Build paths from root toward cwd\n for (let i = 1; i <= parts.length; i++) {\n const dir = parts.slice(0, i).join(\"/\") || \"/\";\n dirs.push(dir);\n }\n\n return dirs;\n}\n\nasync function tryLoadFile(\n fs: VirtualFs,\n path: string,\n scope: ContextScope,\n out: ContextFile[],\n maxDepth: number,\n excludes: string[],\n): Promise<void> {\n if (isExcluded(path, excludes)) return;\n const file = await loadContextFile(fs, path, scope, new Set(), 0, maxDepth);\n if (file) out.push(file);\n}\n\nasync function loadContextFile(\n fs: VirtualFs,\n path: string,\n scope: ContextScope,\n visited: Set<string>,\n depth: number,\n maxDepth: number,\n): Promise<ContextFile | null> {\n const normalized = normalizePath(path);\n if (visited.has(normalized)) return null;\n\n let raw: string;\n try {\n raw = await fs.readFile(path);\n } catch {\n return null;\n }\n\n if (!raw.trim()) return null;\n\n visited.add(normalized);\n\n const { frontmatter, body } = parseFrontmatter(raw);\n const globs = parsePaths(frontmatter.paths);\n const content = stripHtmlComments(body);\n\n const includes = await resolveIncludes(fs, content, path, visited, depth, maxDepth);\n\n return {\n path,\n scope,\n content,\n ...(globs.length > 0 ? { globs } : {}),\n ...(includes.length > 0 ? { includes } : {}),\n };\n}\n\n/**\n * Parse inline `@path` references from markdown content, skipping fenced\n * code blocks and inline code spans. Resolve each path relative to the\n * directory of the including file.\n */\nasync function resolveIncludes(\n fs: VirtualFs,\n content: string,\n basePath: string,\n visited: Set<string>,\n depth: number,\n maxDepth: number,\n): Promise<ContextFile[]> {\n if (depth >= maxDepth) return [];\n\n const baseDir = dirname(basePath);\n const refs = extractAtReferences(content);\n const includes: ContextFile[] = [];\n\n for (const ref of refs) {\n const resolved = resolvePath(baseDir, ref);\n const file = await loadContextFile(fs, resolved, \"project\", visited, depth + 1, maxDepth);\n if (file) includes.push(file);\n }\n\n return includes;\n}\n\n/**\n * Extract `@path` references from markdown text, ignoring references\n * inside fenced code blocks and inline code spans.\n */\nfunction extractAtReferences(content: string): string[] {\n const refs: string[] = [];\n const lines = content.split(\"\\n\");\n let inFence = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (trimmed.startsWith(\"```\") || trimmed.startsWith(\"~~~\")) {\n inFence = !inFence;\n continue;\n }\n if (inFence) continue;\n\n // Strip inline code spans before scanning for @\n const stripped = line.replace(/`[^`]+`/g, \"\");\n\n const re = /(?:^|\\s)@((?:[^\\s\\\\]|\\\\ )+)/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(stripped)) !== null) {\n const raw = m[1].replace(/\\\\ /g, \" \").replace(/#.*$/, \"\");\n if (!raw) continue;\n\n if (raw.startsWith(\"./\") || raw.startsWith(\"../\") || raw.startsWith(\"~/\") || raw.startsWith(\"/\")) {\n refs.push(raw);\n } else if (/^[a-zA-Z0-9._-]/.test(raw) && !raw.startsWith(\"@\")) {\n refs.push(raw);\n }\n }\n }\n\n return refs;\n}\n\n/**\n * Recursively scan a rules directory for *.md files.\n */\nasync function scanRulesDir(\n fs: VirtualFs,\n dirPath: string,\n scope: ContextScope,\n out: ContextFile[],\n maxDepth: number,\n excludes: string[],\n): Promise<void> {\n let entries;\n try {\n entries = await fs.readdir(dirPath);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.isFile && entry.name.endsWith(\".md\")) {\n if (isExcluded(entry.path, excludes)) continue;\n const file = await loadContextFile(fs, entry.path, scope, new Set(), 0, maxDepth);\n if (file) out.push(file);\n } else if (entry.isDirectory) {\n await scanRulesDir(fs, entry.path, scope, out, maxDepth, excludes);\n }\n }\n}\n\n/**\n * Strip block-level HTML comments from markdown content.\n */\nfunction stripHtmlComments(content: string): string {\n if (!content.includes(\"<!--\")) return content;\n return content.replace(/<!--[\\s\\S]*?-->/g, \"\");\n}\n\nfunction isExcluded(path: string, excludes: string[]): boolean {\n if (excludes.length === 0) return false;\n return excludes.some((pattern) => {\n if (path === pattern) return true;\n if (pattern.includes(\"*\")) {\n const regex = simpleGlobToRegex(pattern);\n return regex.test(path);\n }\n return path.includes(pattern);\n });\n}\n\nfunction simpleGlobToRegex(glob: string): RegExp {\n let result = \"\";\n for (let i = 0; i < glob.length; i++) {\n const ch = glob[i];\n if (ch === \"*\") {\n if (glob[i + 1] === \"*\") {\n result += \".*\";\n i++;\n if (glob[i + 1] === \"/\") i++;\n } else {\n result += \"[^/]*\";\n }\n } else if (ch === \"?\") {\n result += \"[^/]\";\n } else {\n result += ch.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n }\n }\n return new RegExp(result);\n}\n\nfunction normalizePath(p: string): string {\n const parts = p.split(\"/\").filter(Boolean);\n const stack: string[] = [];\n for (const part of parts) {\n if (part === \"..\") {\n stack.pop();\n } else if (part !== \".\") {\n stack.push(part);\n }\n }\n return \"/\" + stack.join(\"/\");\n}\n\nfunction dirname(p: string): string {\n const idx = p.lastIndexOf(\"/\");\n if (idx <= 0) return \"/\";\n return p.slice(0, idx);\n}\n\nfunction join(...parts: string[]): string {\n return normalizePath(parts.join(\"/\"));\n}\n\nfunction resolvePath(base: string, relative: string): string {\n if (relative.startsWith(\"/\")) return normalizePath(relative);\n return normalizePath(base + \"/\" + relative);\n}\n\n/**\n * Filter context files to only those whose globs match at least one\n * of the given file paths. Files without globs (unconditional) always pass.\n */\nexport function filterActiveContextFiles(\n files: ContextFile[],\n touchedPaths: string[],\n cwd: string,\n): ContextFile[] {\n return files.filter((f) => {\n if (!f.globs || f.globs.length === 0) return true;\n return touchedPaths.some((filePath) => {\n const relative = filePath.startsWith(cwd)\n ? filePath.slice(cwd.endsWith(\"/\") ? cwd.length : cwd.length + 1)\n : filePath;\n return f.globs!.some((g) => simpleGlobToRegex(g).test(relative));\n });\n });\n}\n\n/**\n * Check which conditional context files are newly activated by the given\n * touched paths. Returns the paths of newly activated files.\n */\nexport function activateContextForPaths(\n allFiles: ContextFile[],\n touchedPaths: string[],\n cwd: string,\n alreadyActivated: Set<string>,\n): string[] {\n const activated: string[] = [];\n\n for (const file of allFiles) {\n if (!file.globs || file.globs.length === 0) continue;\n if (alreadyActivated.has(file.path)) continue;\n\n for (const filePath of touchedPaths) {\n const relative = filePath.startsWith(cwd)\n ? filePath.slice(cwd.endsWith(\"/\") ? cwd.length : cwd.length + 1)\n : filePath;\n\n if (file.globs.some((g) => simpleGlobToRegex(g).test(relative))) {\n alreadyActivated.add(file.path);\n activated.push(file.path);\n break;\n }\n }\n }\n\n return activated;\n}\n","export const SpanStatusCode = {\n OK: 0,\n ERROR: 1,\n} as const;\n\nexport type SpanStatusCode = (typeof SpanStatusCode)[keyof typeof SpanStatusCode];\n\nexport type SpanAttributeValue = string | number | boolean;\n\nexport interface SpanOptions {\n parent?: Span;\n attributes?: Record<string, SpanAttributeValue>;\n}\n\nexport interface Span {\n readonly name: string;\n setAttribute(key: string, value: SpanAttributeValue): void;\n addEvent(name: string, attributes?: Record<string, SpanAttributeValue>): void;\n setStatus(code: SpanStatusCode, message?: string): void;\n end(): void;\n}\n\nexport interface Tracer {\n startSpan(name: string, options?: SpanOptions): Span;\n}\n\nexport interface TracingConfig {\n tracer: Tracer;\n}\n","import type { Span, SpanAttributeValue, SpanOptions, SpanStatusCode, Tracer } from \"./types.js\";\n\nexport class NoopSpan implements Span {\n readonly name: string;\n\n constructor(name: string) {\n this.name = name;\n }\n\n setAttribute(_key: string, _value: SpanAttributeValue): void {}\n addEvent(_name: string, _attributes?: Record<string, SpanAttributeValue>): void {}\n setStatus(_code: SpanStatusCode, _message?: string): void {}\n end(): void {}\n}\n\nexport class NoopTracer implements Tracer {\n startSpan(name: string, _options?: SpanOptions): Span {\n return new NoopSpan(name);\n }\n}\n","/**\n * Prompt helpers for the memory system.\n *\n * `buildMemorySystemPromptSection` generates the instruction block injected\n * into the system prompt that teaches the model about the four-type memory\n * taxonomy and how to read/write memories.\n *\n * `buildExtractionPrompt` generates the user message sent to the LLM when\n * auto-extracting memories from a completed conversation turn.\n *\n * Both are adapted from claude-code's memdir/memoryTypes prompt helpers,\n * stripped of analytics, team memory, and Anthropic-specific concerns.\n */\n\nconst MEMORY_TYPES_SECTION = `## Memory types\n\nMemories fall into exactly four types:\n\n### user\nFacts about the user: their role, expertise, communication preferences, how they like to collaborate, preferred tools and workflows.\nExamples: \"Senior backend engineer, prefers Rust\", \"Wants concise answers, no pleasantries\"\n\n### feedback\nCorrections, praise, or behavioral guidance the user has given you. These shape how you work in future conversations.\nExamples: \"User said: stop adding unnecessary comments\", \"User prefers small focused commits\"\n\n### project\nContext about the codebase or project that is NOT derivable from the code itself: architecture decisions and their rationale, deployment processes, external dependencies, team conventions.\nExamples: \"Auth service migrating from JWT to session tokens — decision made 2025-01\", \"CI runs on GitHub Actions, deploy via Vercel\"\n\n### reference\nPointers to external resources the user has shared: documentation links, dashboard URLs, API references, Slack channels.\nExamples: \"Design system docs: https://design.example.com\", \"Incident runbook in Notion\"`;\n\nconst WHAT_NOT_TO_SAVE = `## What NOT to save\n\nDo not save memories that are:\n- Derivable from the code itself (file structure, function signatures, import patterns)\n- Ephemeral to the current conversation (temporary debugging steps, in-progress plans)\n- Redundant with an existing memory (check first, update instead of creating duplicates)\n- Generic programming knowledge (how promises work, what REST means)`;\n\nconst WHEN_TO_ACCESS = `## When to access memories\n\nRead your memories at the start of a conversation to orient yourself. During a conversation, consult them when:\n- The user references something from a past conversation\n- You need context about the project that isn't in the code\n- You're about to make a decision that past feedback might inform\n- The user asks \"do you remember…\" or similar`;\n\nconst HOW_TO_SAVE = `## How to save memories\n\nSaving a memory is a two-step process:\n\n**Step 1** — write the memory to its own file (e.g., \\`user_role.md\\`, \\`feedback_testing.md\\`) using this frontmatter format:\n\n\\`\\`\\`\n---\nname: short descriptive title\ndescription: one-line summary\ntype: user | project | feedback | reference\n---\n\nFull content here…\n\\`\\`\\`\n\n**Step 2** — add a pointer to that file in \\`MEMORY.md\\`. \\`MEMORY.md\\` is an index, not a memory — each entry should be one line, under ~150 characters: \\`- [Title](file.md) — one-line hook\\`. It has no frontmatter. Never write memory content directly into \\`MEMORY.md\\`.\n\n- \\`MEMORY.md\\` is always loaded into your conversation context — lines after 200 will be truncated, so keep the index concise\n- Keep the name, description, and type fields in memory files up-to-date with the content\n- Organize memory semantically by topic, not chronologically\n- Update or remove memories that turn out to be wrong or outdated\n- Do not write duplicate memories. First check if there is an existing memory you can update before writing a new one.`;\n\n/**\n * Build the system-prompt section that teaches the model about its persistent\n * memory directory.\n *\n * @param indexContent - The current contents of MEMORY.md (may be empty).\n * @param memoryDir - Absolute path to the memory directory.\n */\nexport function buildMemorySystemPromptSection(\n indexContent: string,\n memoryDir: string,\n): string {\n const sections: string[] = [\n \"# Persistent Memory\",\n \"\",\n `You have a persistent, file-based memory system at \\`${memoryDir}\\`. This directory already exists — write to it directly with the Write tool (do not run mkdir or check for its existence).`,\n \"\",\n \"You should build up this memory system over time so that future conversations have a complete picture of who the user is, how they'd like to collaborate with you, what behaviors to avoid or repeat, and the context behind the work the user gives you.\",\n \"\",\n \"If the user explicitly asks you to remember something, save it immediately as whichever type fits best. If they ask you to forget something, find and remove the relevant entry.\",\n \"\",\n MEMORY_TYPES_SECTION,\n \"\",\n WHAT_NOT_TO_SAVE,\n \"\",\n HOW_TO_SAVE,\n \"\",\n WHEN_TO_ACCESS,\n \"\",\n \"## MEMORY.md\",\n \"\",\n ];\n\n if (indexContent.trim()) {\n sections.push(indexContent);\n } else {\n sections.push(\n \"Your MEMORY.md is currently empty. When you save new memories, they will appear here.\",\n );\n }\n\n return sections.join(\"\\n\");\n}\n\n/**\n * Build the prompt sent to the LLM to extract durable memories from a\n * conversation. The response should be a JSON object with a `memories` array.\n */\nexport function buildExtractionPrompt(\n conversationSummary: string,\n existingIndex: string,\n): string {\n return `You are a memory extraction assistant. Analyze the following conversation and extract any information worth remembering for future conversations.\n\n## Current memory index\n\n${existingIndex.trim() || \"(empty)\"}\n\n## Conversation\n\n${conversationSummary}\n\n## Instructions\n\nExtract memories that fall into these categories:\n- **user**: Facts about the user (role, preferences, expertise, communication style)\n- **feedback**: Corrections or behavioral guidance the user gave the assistant\n- **project**: Non-obvious project context (architecture decisions, deployment processes, conventions)\n- **reference**: External links or resources the user shared\n\nDo NOT extract:\n- Information derivable from the code itself\n- Ephemeral conversation details (debugging steps, temporary plans)\n- Generic programming knowledge\n- Information already captured in the existing memory index\n\nIf a memory should update an existing entry rather than creating a new one, use the \"update\" action and provide the existing path.\n\nRespond with a JSON object:\n{\n \"memories\": [\n {\n \"name\": \"short descriptive title\",\n \"description\": \"one-line summary\",\n \"type\": \"user | project | feedback | reference\",\n \"content\": \"full memory content\",\n \"action\": \"create | update | delete\",\n \"path\": \"existing_file.md (required for update/delete, omit for create)\"\n }\n ]\n}\n\nIf there is nothing worth extracting, respond with: { \"memories\": [] }`;\n}\n","/**\n * Normalize tool-call arguments before sending to providers.\n *\n * Strips fields that were injected for internal bookkeeping (e.g.\n * plan-mode metadata, legacy synthetic fields) but are not part of\n * the tool's declared API schema. Prevents 400 errors from providers\n * that strictly validate tool_use inputs.\n */\n\nimport type {\n ChatMessage,\n AssistantMessage,\n ToolCallContent,\n} from \"../session/types.js\";\n\n/**\n * Fields that are known to be injected by the runtime and must not\n * reach the provider. Keyed by tool name; `\"*\"` applies to all tools.\n */\nconst STRIP_FIELDS: Record<string, string[]> = {\n \"*\": [\"_meta\", \"_source\", \"_injected\"],\n ExitPlanMode: [\"planFilePath\"],\n EditFile: [\"old_string\", \"new_string\", \"replace_all\"],\n};\n\n/**\n * Strip synthetic/injected fields from a single tool call's arguments.\n * Returns the original string if no changes are needed.\n */\nexport function normalizeToolInputForAPI(\n toolName: string,\n argsJson: string,\n): string {\n const globalFields = STRIP_FIELDS[\"*\"] ?? [];\n const toolFields = STRIP_FIELDS[toolName] ?? [];\n const allFields = [...globalFields, ...toolFields];\n if (allFields.length === 0) return argsJson;\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(argsJson);\n } catch {\n return argsJson;\n }\n\n if (typeof parsed !== \"object\" || parsed === null) return argsJson;\n\n let changed = false;\n for (const field of allFields) {\n if (field in parsed) {\n delete parsed[field];\n changed = true;\n }\n }\n\n // For EditFile: only strip old_string/new_string/replace_all when the\n // `edits` array is present (legacy resume format). Don't strip them\n // when they are the primary inputs (current format).\n if (toolName === \"EditFile\" && !(\"edits\" in parsed)) {\n // Restore fields that were removed but are actually current-format inputs\n try {\n const original = JSON.parse(argsJson);\n for (const f of [\"old_string\", \"new_string\", \"replace_all\"]) {\n if (f in original && !(f in parsed)) {\n parsed[f] = original[f];\n changed = false; // Undo the strip for this field\n }\n }\n } catch {\n // noop\n }\n }\n\n return changed ? JSON.stringify(parsed) : argsJson;\n}\n\n/**\n * Walk all assistant messages and normalize their tool_call arguments.\n * Returns the original array if no changes are needed.\n */\nexport function normalizeToolInputsInMessages(\n messages: ChatMessage[],\n): ChatMessage[] {\n let changed = false;\n const result = messages.map((msg) => {\n if (msg.role !== \"assistant\") return msg;\n const asst = msg as AssistantMessage;\n if (!asst.tool_calls || asst.tool_calls.length === 0) return msg;\n\n let callsChanged = false;\n const newCalls = asst.tool_calls.map((tc: ToolCallContent) => {\n const normalized = normalizeToolInputForAPI(\n tc.function.name,\n tc.function.arguments,\n );\n if (normalized !== tc.function.arguments) {\n callsChanged = true;\n return { ...tc, function: { ...tc.function, arguments: normalized } };\n }\n return tc;\n });\n\n if (callsChanged) {\n changed = true;\n return { ...asst, tool_calls: newCalls };\n }\n return msg;\n });\n return changed ? result : messages;\n}\n","/**\n * Centralized message normalization for API calls.\n *\n * Ensures a ChatMessage[] is structurally valid before being sent to any\n * provider. Handles duplicate tool IDs, orphaned results, missing pairing,\n * empty assistants, consecutive same-role messages, and other corruption\n * from error/abort/compaction paths.\n *\n * Pure function: returns a new array, never mutates the input.\n */\n\nimport type {\n ChatMessage,\n AssistantMessage,\n ToolResultMessage,\n ContentPart,\n} from \"../session/types.js\";\nimport { contentToString } from \"../utils/content.js\";\nimport { normalizeToolInputsInMessages } from \"./tool-input-normalize.js\";\n\n// ---------------------------------------------------------------------------\n// Main entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize a message array so it is structurally valid for any LLM API.\n *\n * Transformations applied (order matters):\n * 1. Drop system messages (system prompt is a separate param)\n * 2. Deduplicate tool_use IDs across assistants\n * 3. Strip orphaned tool_results with no matching tool_use\n * 4. Deduplicate tool_results with the same tool_call_id\n * 5. Insert synthetic error results for unpaired tool_uses\n * 6. Filter orphaned thinking-only assistants (null/undefined content)\n * 7. Filter whitespace-only assistant messages\n * 8. Merge consecutive same-role messages\n * 9. Ensure every assistant has non-null content\n * 10. Strip thinking-only trailing assistant (after merge — merge can\n * create new trailing messages with only thinking content)\n * 11. Ensure array starts with a user message\n */\nexport function normalizeMessagesForAPI(messages: ChatMessage[]): ChatMessage[] {\n let result = messages.slice();\n\n result = dropSystemMessages(result);\n result = deduplicateToolUseIds(result);\n result = stripOrphanedToolResults(result);\n result = deduplicateToolResults(result);\n result = ensureToolResultPairing(result);\n result = sanitizeErrorToolResultContent(result);\n result = reorderToolResultsAfterAssistant(result);\n result = filterOrphanedThinkingAssistants(result);\n result = filterWhitespaceOnlyAssistants(result);\n result = mergeAssistantsByTurnId(result);\n result = mergeConsecutiveSameRole(result);\n result = ensureNonEmptyAssistantContent(result);\n result = stripTrailingThinkingOnlyAssistant(result);\n result = stripStaleSignatureBlocks(result);\n result = validateImagesForAPI(result);\n result = ensureStartsWithUser(result);\n result = stripInternalFields(result);\n result = normalizeToolInputsInMessages(result);\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Step 1: Drop system messages\n// ---------------------------------------------------------------------------\n\nfunction dropSystemMessages(messages: ChatMessage[]): ChatMessage[] {\n return messages.filter((m) => m.role !== \"system\");\n}\n\n// ---------------------------------------------------------------------------\n// Step 2: Deduplicate tool_use IDs\n// ---------------------------------------------------------------------------\n\n/**\n * Strip duplicate tool_call IDs from later assistant messages. If a\n * tool_call.id appears in an earlier assistant, it is removed from the\n * later one. If stripping empties the assistant's tool_calls array and\n * it has no text content, the assistant is dropped entirely.\n *\n * Also removes any tool result messages that reference stripped IDs.\n */\nfunction deduplicateToolUseIds(messages: ChatMessage[]): ChatMessage[] {\n const seen = new Set<string>();\n let changed = false;\n const result: ChatMessage[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"assistant\") {\n const asst = msg as AssistantMessage;\n if (asst.tool_calls && asst.tool_calls.length > 0) {\n const kept = asst.tool_calls.filter((tc) => {\n if (seen.has(tc.id)) return false;\n seen.add(tc.id);\n return true;\n });\n\n if (kept.length < asst.tool_calls.length) {\n changed = true;\n if (kept.length === 0) {\n const text = asst.content != null ? contentToString(asst.content) : \"\";\n if (text.trim() === \"\") continue;\n result.push({ ...asst, tool_calls: undefined } as AssistantMessage);\n } else {\n result.push({ ...asst, tool_calls: kept });\n }\n } else {\n result.push(msg);\n }\n } else {\n result.push(msg);\n }\n } else {\n result.push(msg);\n }\n }\n\n return changed ? result : messages;\n}\n\n// ---------------------------------------------------------------------------\n// Step 3: Strip orphaned tool_results\n// ---------------------------------------------------------------------------\n\n/**\n * Remove tool result messages whose tool_call_id does not match any\n * tool_call in a preceding assistant message.\n */\nfunction stripOrphanedToolResults(messages: ChatMessage[]): ChatMessage[] {\n const knownCallIds = new Set<string>();\n for (const msg of messages) {\n if (msg.role === \"assistant\") {\n const asst = msg as AssistantMessage;\n if (asst.tool_calls) {\n for (const tc of asst.tool_calls) {\n knownCallIds.add(tc.id);\n }\n }\n }\n }\n\n return messages.filter((msg) => {\n if (msg.role !== \"tool\") return true;\n return knownCallIds.has((msg as ToolResultMessage).tool_call_id);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Step 4: Deduplicate tool_results\n// ---------------------------------------------------------------------------\n\n/**\n * Keep only the first tool result for each tool_call_id. Duplicates can\n * appear after crash recovery or corrupted session transcripts.\n */\nfunction deduplicateToolResults(messages: ChatMessage[]): ChatMessage[] {\n const seen = new Set<string>();\n return messages.filter((msg) => {\n if (msg.role !== \"tool\") return true;\n const id = (msg as ToolResultMessage).tool_call_id;\n if (seen.has(id)) return false;\n seen.add(id);\n return true;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Step 5: Ensure tool result pairing\n// ---------------------------------------------------------------------------\n\n/**\n * Insert synthetic error results for any assistant tool_calls that have\n * no matching tool result in the conversation.\n *\n * Synthetic results are inserted after the last real tool result for the\n * assistant's calls, or immediately after the assistant if none exist.\n */\nexport function ensureToolResultPairing(messages: ChatMessage[]): ChatMessage[] {\n const resolvedIds = new Set<string>();\n for (const msg of messages) {\n if (msg.role === \"tool\") {\n resolvedIds.add((msg as ToolResultMessage).tool_call_id);\n }\n }\n\n // Strict fallback: drop assistants whose tool_calls are ALL unresolved\n // and that have no meaningful text content. The context is clearly\n // truncated and synthetic results would add noise, not value.\n const dropIndices = new Set<number>();\n const dropCallIds = new Set<string>();\n const insertions = new Map<number, ToolResultMessage[]>();\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (msg.role !== \"assistant\") continue;\n const asst = msg as AssistantMessage;\n if (!asst.tool_calls || asst.tool_calls.length === 0) continue;\n\n const missing = asst.tool_calls.filter((tc) => !resolvedIds.has(tc.id));\n if (missing.length === 0) continue;\n\n // If ALL calls are unresolved and text content is empty, drop entirely\n if (missing.length === asst.tool_calls.length) {\n const text = asst.content != null ? contentToString(asst.content) : \"\";\n if (text.trim() === \"\") {\n dropIndices.add(i);\n for (const tc of asst.tool_calls) dropCallIds.add(tc.id);\n continue;\n }\n }\n\n // Partial resolution: insert synthetic errors for missing results\n const allCallIds = new Set(asst.tool_calls.map((tc) => tc.id));\n let insertAfter = i;\n for (let j = i + 1; j < messages.length; j++) {\n if (\n messages[j].role === \"tool\" &&\n allCallIds.has((messages[j] as ToolResultMessage).tool_call_id)\n ) {\n insertAfter = j;\n }\n }\n\n const synthetics: ToolResultMessage[] = missing.map((tc) => ({\n role: \"tool\" as const,\n tool_call_id: tc.id,\n content:\n \"Error: Tool result missing — session was interrupted before this tool completed.\",\n isError: true,\n }));\n\n const existing = insertions.get(insertAfter);\n if (existing) {\n existing.push(...synthetics);\n } else {\n insertions.set(insertAfter, synthetics);\n }\n }\n\n if (insertions.size === 0 && dropIndices.size === 0) return messages;\n\n const result: ChatMessage[] = [];\n for (let i = 0; i < messages.length; i++) {\n if (dropIndices.has(i)) continue;\n if (messages[i].role === \"tool\" && dropCallIds.has((messages[i] as ToolResultMessage).tool_call_id)) continue;\n result.push(messages[i]);\n const toInsert = insertions.get(i);\n if (toInsert) result.push(...toInsert);\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Step 5b: Sanitize error tool result content\n// ---------------------------------------------------------------------------\n\n/**\n * The API rejects tool_results with `isError: true` that contain non-text\n * content (images, etc.). Strip non-text parts and keep only text, joining\n * multiple text segments. Avoids permanent 400s from resumed sessions that\n * persisted images in error results.\n */\nfunction sanitizeErrorToolResultContent(messages: ChatMessage[]): ChatMessage[] {\n let changed = false;\n const result = messages.map((msg) => {\n if (msg.role !== \"tool\") return msg;\n const tr = msg as ToolResultMessage;\n if (!tr.isError) return msg;\n if (!Array.isArray(tr.content)) return msg;\n if (tr.content.every((c) => c.type === \"text\")) return msg;\n\n changed = true;\n const texts = tr.content\n .filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n .map((c) => c.text);\n return {\n ...tr,\n content: texts.length > 0 ? texts.join(\"\\n\\n\") : \"Error (details unavailable)\",\n } as ToolResultMessage;\n });\n return changed ? result : messages;\n}\n\n// ---------------------------------------------------------------------------\n// Step 5c: Reorder tool results to follow their owning assistant\n// ---------------------------------------------------------------------------\n\n/**\n * Ensure every tool result appears in the contiguous block after its owning\n * assistant. Corrupt transcripts (crash recovery, bad session merge) can\n * have user messages or other non-tool rows between an assistant and its\n * results. This step moves displaced tool results back to the correct\n * position without dropping any data.\n */\nfunction reorderToolResultsAfterAssistant(\n messages: ChatMessage[],\n): ChatMessage[] {\n // Build a map: tool_call_id → index of the owning assistant\n const ownerIdx = new Map<string, number>();\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role !== \"assistant\") continue;\n const asst = messages[i] as AssistantMessage;\n if (!asst.tool_calls) continue;\n for (const tc of asst.tool_calls) {\n ownerIdx.set(tc.id, i);\n }\n }\n\n // Check if any tool results are displaced (separated from assistant by non-tool)\n let needsReorder = false;\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role !== \"tool\") continue;\n const callId = (messages[i] as ToolResultMessage).tool_call_id;\n const asstIdx = ownerIdx.get(callId);\n if (asstIdx === undefined) continue;\n for (let j = asstIdx + 1; j < i; j++) {\n if (messages[j].role === \"user\") {\n needsReorder = true;\n break;\n }\n }\n if (needsReorder) break;\n }\n if (!needsReorder) return messages;\n\n // Rebuild: for each assistant with tool_calls, collect its results and\n // place them immediately after the assistant, then emit remaining messages.\n const consumed = new Set<number>();\n const result: ChatMessage[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n if (consumed.has(i)) continue;\n result.push(messages[i]);\n\n if (messages[i].role !== \"assistant\") continue;\n const asst = messages[i] as AssistantMessage;\n if (!asst.tool_calls || asst.tool_calls.length === 0) continue;\n\n const callIds = new Set(asst.tool_calls.map((tc) => tc.id));\n // Gather all tool results for this assistant (in original order)\n for (let j = i + 1; j < messages.length; j++) {\n if (messages[j].role !== \"tool\") continue;\n if (!callIds.has((messages[j] as ToolResultMessage).tool_call_id)) continue;\n if (!consumed.has(j)) {\n consumed.add(j);\n result.push(messages[j]);\n }\n }\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Step 7: Filter whitespace-only assistants\n// ---------------------------------------------------------------------------\n\n/**\n * Drop assistant messages with no tool_calls and empty/whitespace-only\n * content. These are API-invalid.\n */\nexport function filterWhitespaceOnlyAssistants(\n messages: ChatMessage[],\n): ChatMessage[] {\n return messages.filter((msg) => {\n if (msg.role !== \"assistant\") return true;\n const asst = msg as AssistantMessage;\n if (asst.tool_calls && asst.tool_calls.length > 0) return true;\n if (asst.thinking_content) return true;\n const text =\n typeof asst.content === \"string\"\n ? asst.content\n : contentToString(asst.content ?? \"\");\n return text.trim() !== \"\";\n });\n}\n\n// ---------------------------------------------------------------------------\n// Step 6: Filter orphaned thinking-only assistants\n// (runs before whitespace filter so null-content artifacts are removed first)\n// ---------------------------------------------------------------------------\n\n/**\n * Drop assistants with null/undefined content and no tool_calls.\n * These are artifacts of streaming interruptions where only thinking\n * was streamed before the connection broke.\n */\nexport function filterOrphanedThinkingAssistants(\n messages: ChatMessage[],\n): ChatMessage[] {\n return messages.filter((msg) => {\n if (msg.role !== \"assistant\") return true;\n const asst = msg as AssistantMessage;\n if (asst.tool_calls && asst.tool_calls.length > 0) return true;\n return asst.content !== null && asst.content !== undefined;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Step 8a: Merge non-adjacent assistants with the same _turnId\n// ---------------------------------------------------------------------------\n\n/**\n * When streaming produces split assistant chunks separated by tool result\n * rows (all belonging to the same provider response), merge them back\n * together. This mirrors claude-code's merge-by-message.id logic.\n *\n * The merge walks backward from each assistant, across intervening tool\n * result rows, looking for an earlier assistant with the same `_turnId`.\n */\nfunction mergeAssistantsByTurnId(messages: ChatMessage[]): ChatMessage[] {\n const hasTurnIds = messages.some(\n (m) => m.role === \"assistant\" && (m as AssistantMessage)._turnId != null,\n );\n if (!hasTurnIds) return messages;\n\n const result: ChatMessage[] = [];\n for (const msg of messages) {\n if (msg.role !== \"assistant\") {\n result.push(msg);\n continue;\n }\n const asst = msg as AssistantMessage;\n if (!asst._turnId) {\n result.push(msg);\n continue;\n }\n\n // Walk backward through result, skipping tool results and\n // assistants with different _turnIds, to find a match.\n let merged = false;\n for (let i = result.length - 1; i >= 0; i--) {\n const prev = result[i];\n if (prev.role === \"tool\") continue;\n if (prev.role !== \"assistant\") break;\n const prevAsst = prev as AssistantMessage;\n if (prevAsst._turnId === asst._turnId) {\n result[i] = mergeAssistantPair(prevAsst, asst);\n merged = true;\n break;\n }\n // Different assistant — keep looking only if it also has a _turnId\n if (!prevAsst._turnId) break;\n }\n if (!merged) {\n result.push(msg);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Step 8b: Merge consecutive same-role messages\n// ---------------------------------------------------------------------------\n\n/**\n * Merge adjacent messages with the same role. This restores valid role\n * alternation after filters remove messages from the middle.\n *\n * - User messages: content parts are concatenated.\n * - Assistant messages: text is joined with newline, tool_calls and\n * thinking fields are merged.\n * - Tool messages are never merged (they belong to specific tool_call IDs).\n */\nexport function mergeConsecutiveSameRole(\n messages: ChatMessage[],\n): ChatMessage[] {\n if (messages.length <= 1) return messages;\n\n const result: ChatMessage[] = [messages[0]];\n\n for (let i = 1; i < messages.length; i++) {\n const prev = result[result.length - 1];\n const curr = messages[i];\n\n if (prev.role === \"user\" && curr.role === \"user\") {\n const prevParts = toContentParts(prev.content as string | ContentPart[]);\n const currParts = toContentParts(curr.content as string | ContentPart[]);\n result[result.length - 1] = {\n role: \"user\",\n content: joinUserPartsAtSeam(prevParts, currParts),\n };\n } else if (prev.role === \"assistant\" && curr.role === \"assistant\") {\n result[result.length - 1] = mergeAssistantPair(\n prev as AssistantMessage,\n curr as AssistantMessage,\n );\n } else {\n result.push(curr);\n }\n }\n\n return result;\n}\n\nfunction mergeAssistantPair(\n prev: AssistantMessage,\n curr: AssistantMessage,\n): AssistantMessage {\n const prevText = assistantTextContent(prev);\n const currText = assistantTextContent(curr);\n const mergedContent =\n prevText || currText\n ? prevText + (currText ? \"\\n\" + currText : \"\")\n : null;\n const mergedToolCalls = [\n ...(prev.tool_calls ?? []),\n ...(curr.tool_calls ?? []),\n ];\n const mergedThinking =\n [prev.thinking_content, curr.thinking_content]\n .filter(Boolean)\n .join(\"\\n\") || undefined;\n\n return {\n role: \"assistant\",\n content: mergedContent,\n ...(mergedToolCalls.length > 0 ? { tool_calls: mergedToolCalls } : {}),\n ...(mergedThinking ? { thinking_content: mergedThinking } : {}),\n ...(curr.thinking_signature ?? prev.thinking_signature\n ? {\n thinking_signature:\n curr.thinking_signature ?? prev.thinking_signature,\n }\n : {}),\n ...(curr.redacted_thinking_data ?? prev.redacted_thinking_data\n ? {\n redacted_thinking_data:\n curr.redacted_thinking_data ?? prev.redacted_thinking_data,\n }\n : {}),\n ...(prev._turnId ?? curr._turnId\n ? { _turnId: prev._turnId ?? curr._turnId }\n : {}),\n } as AssistantMessage;\n}\n\n// ---------------------------------------------------------------------------\n// Step 9: Ensure non-empty assistant content\n// ---------------------------------------------------------------------------\n\n/**\n * Providers reject assistants with `content: null`.\n *\n * - Non-final assistants: set null/undefined content to `\"\"`.\n * - Final assistant: also set to `\"\"` — enables prefill/continuation;\n * an empty string is accepted by all providers (unlike `null`).\n */\nfunction ensureNonEmptyAssistantContent(\n messages: ChatMessage[],\n): ChatMessage[] {\n let changed = false;\n const result = messages.map((msg) => {\n if (msg.role !== \"assistant\") return msg;\n const asst = msg as AssistantMessage;\n if (asst.content === null || asst.content === undefined) {\n changed = true;\n return { ...asst, content: \"\" };\n }\n return msg;\n });\n return changed ? result : messages;\n}\n\n// ---------------------------------------------------------------------------\n// Step 10: Strip thinking-only trailing assistant\n// (runs after merge — mergeConsecutiveSameRole can create new trailing\n// assistants with only thinking content that need to be removed)\n// ---------------------------------------------------------------------------\n\n/**\n * If the last message is an assistant with only thinking content (no\n * substantive text and no tool_calls), strip the thinking fields. The\n * Anthropic API rejects messages where thinking blocks are the sole\n * content in the final assistant turn.\n */\nfunction stripTrailingThinkingOnlyAssistant(\n messages: ChatMessage[],\n): ChatMessage[] {\n if (messages.length === 0) return messages;\n const last = messages[messages.length - 1];\n if (last.role !== \"assistant\") return messages;\n const asst = last as AssistantMessage;\n if (asst.tool_calls && asst.tool_calls.length > 0) return messages;\n if (!asst.thinking_content) return messages;\n const text =\n typeof asst.content === \"string\"\n ? asst.content\n : contentToString(asst.content ?? \"\");\n if (text.trim() !== \"\") return messages;\n return messages.slice(0, -1);\n}\n\n// ---------------------------------------------------------------------------\n// Step 11: Ensure starts with user\n// ---------------------------------------------------------------------------\n\n/**\n * The Anthropic API requires the first message to be a user message.\n * Other providers are lenient but a leading user message is always safe.\n */\nfunction ensureStartsWithUser(messages: ChatMessage[]): ChatMessage[] {\n if (messages.length === 0) {\n return [{ role: \"user\", content: \"[Conversation resumed]\" }];\n }\n if (messages[0].role !== \"user\") {\n return [\n { role: \"user\", content: \"[Conversation resumed]\" } as ChatMessage,\n ...messages,\n ];\n }\n return messages;\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction toContentParts(content: string | ContentPart[]): ContentPart[] {\n if (typeof content === \"string\") {\n return [{ type: \"text\", text: content }];\n }\n if (Array.isArray(content)) return content;\n return [{ type: \"text\", text: contentToString(content) }];\n}\n\n/**\n * Join two ContentPart arrays, inserting a `\\n` separator when both the\n * last part of `a` and the first part of `b` are text blocks. This\n * prevents run-together text like \"2 + 23 + 3\" when merging consecutive\n * user messages that should read \"2 + 2\\n3 + 3\".\n */\nfunction joinUserPartsAtSeam(a: ContentPart[], b: ContentPart[]): ContentPart[] {\n if (a.length === 0) return b;\n if (b.length === 0) return a;\n const lastA = a[a.length - 1];\n const firstB = b[0];\n if (lastA.type === \"text\" && firstB.type === \"text\") {\n return [\n ...a.slice(0, -1),\n { type: \"text\", text: lastA.text + \"\\n\" + firstB.text },\n ...b.slice(1),\n ];\n }\n return [...a, ...b];\n}\n\nfunction assistantTextContent(asst: AssistantMessage): string {\n if (typeof asst.content === \"string\") return asst.content;\n if (Array.isArray(asst.content)) {\n return contentToString(asst.content as ContentPart[]);\n }\n return \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Step 10b: Strip stale thinking signatures from non-final assistants\n// ---------------------------------------------------------------------------\n\n/**\n * thinking_signature and redacted_thinking_data are model-bound: replaying\n * them to a different model causes API 400s. After a model switch or across\n * compaction boundaries, these fields on older messages become stale.\n *\n * Only the final assistant's signature is potentially valid (belongs to\n * the current turn). All earlier signatures are stripped.\n */\nfunction stripStaleSignatureBlocks(messages: ChatMessage[]): ChatMessage[] {\n if (messages.length === 0) return messages;\n\n let changed = false;\n const result = messages.map((msg, i) => {\n if (msg.role !== \"assistant\") return msg;\n const asst = msg as AssistantMessage;\n const isLast = i === messages.length - 1;\n if (isLast) return msg;\n\n if (asst.thinking_signature || asst.redacted_thinking_data) {\n changed = true;\n const {\n thinking_signature: _sig,\n redacted_thinking_data: _red,\n ...rest\n } = asst;\n return rest as AssistantMessage;\n }\n return msg;\n });\n return changed ? result : messages;\n}\n\n// ---------------------------------------------------------------------------\n// Step 10c: Validate images for API\n// ---------------------------------------------------------------------------\n\nconst MAX_IMAGES_PER_REQUEST = 20;\nconst MAX_IMAGE_BASE64_SIZE = 5 * 1024 * 1024; // 5 MB\nconst VALID_IMAGE_MEDIA_TYPES = new Set([\n \"image/png\",\n \"image/jpeg\",\n \"image/jpg\",\n \"image/gif\",\n \"image/webp\",\n]);\n\n/**\n * Strip oversized or invalid images from messages to prevent API rejections.\n * Providers impose limits on image count, size, and format.\n */\nfunction validateImagesForAPI(messages: ChatMessage[]): ChatMessage[] {\n let imageCount = 0;\n let changed = false;\n\n const result = messages.map((msg) => {\n if (msg.role === \"assistant\") return msg;\n const content = (msg as { content: string | ContentPart[] }).content;\n if (!Array.isArray(content)) return msg;\n\n let msgChanged = false;\n const validated = content.map((part) => {\n if (part.type !== \"image\") return part;\n\n imageCount++;\n\n if (imageCount > MAX_IMAGES_PER_REQUEST) {\n msgChanged = true;\n return {\n type: \"text\" as const,\n text: \"[image removed — too many images in this request]\",\n };\n }\n\n if (part.data && part.data.length > MAX_IMAGE_BASE64_SIZE) {\n msgChanged = true;\n return {\n type: \"text\" as const,\n text: `[image removed — exceeds ${MAX_IMAGE_BASE64_SIZE / 1024 / 1024}MB size limit]`,\n };\n }\n\n if (\n part.media_type &&\n !VALID_IMAGE_MEDIA_TYPES.has(part.media_type)\n ) {\n msgChanged = true;\n return {\n type: \"text\" as const,\n text: `[image removed — unsupported format: ${part.media_type}]`,\n };\n }\n\n return part;\n });\n\n if (msgChanged) {\n changed = true;\n return { ...msg, content: validated } as ChatMessage;\n }\n return msg;\n });\n\n return changed ? result : messages;\n}\n\n// ---------------------------------------------------------------------------\n// Final: Strip internal metadata fields before sending to providers\n// ---------------------------------------------------------------------------\n\n/**\n * Remove internal-only fields (like `_turnId`) that providers don't\n * understand. These are bookkeeping metadata used by the normalization\n * and thread layers.\n */\nfunction stripInternalFields(messages: ChatMessage[]): ChatMessage[] {\n let changed = false;\n const result = messages.map((msg) => {\n if (msg.role !== \"assistant\") return msg;\n const asst = msg as AssistantMessage;\n if (asst._turnId === undefined) return msg;\n changed = true;\n const { _turnId, ...rest } = asst;\n return rest as AssistantMessage;\n });\n return changed ? result : messages;\n}\n","/**\n * Conversation recovery and message sanitization.\n *\n * Cleans up persisted messages before resuming a session so the API\n * receives a structurally valid conversation. Handles crashes, streaming\n * interruptions, orphaned tool calls, and whitespace-only messages.\n *\n * Shared normalization primitives (merge, filter, pairing) live in\n * `src/messages/normalize.ts` and are re-exported here for backward\n * compatibility.\n */\n\nimport type {\n ChatMessage,\n AssistantMessage,\n ToolResultMessage,\n ContentPart,\n} from \"./types.js\";\nimport { contentToString } from \"../utils/content.js\";\n\n// Re-export shared normalization primitives so existing consumers that\n// import from \"session/recovery\" continue to work.\nexport {\n ensureToolResultPairing,\n mergeConsecutiveSameRole,\n} from \"../messages/normalize.js\";\n\nimport {\n mergeConsecutiveSameRole as _mergeConsecutiveSameRole,\n filterWhitespaceOnlyAssistants,\n filterOrphanedThinkingAssistants,\n} from \"../messages/normalize.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type TurnInterruption =\n | { kind: \"none\" }\n | { kind: \"interrupted_tool\" }\n | { kind: \"interrupted_prompt\" };\n\nexport interface SanitizeResult {\n messages: ChatMessage[];\n interruption: TurnInterruption;\n /** Number of messages removed by each filter (for diagnostics). */\n removals: {\n unresolvedToolUses: number;\n whitespaceOnly: number;\n orphanedThinking: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Filters\n// ---------------------------------------------------------------------------\n\n/**\n * Drop assistant messages where *every* tool_call has no matching tool\n * result message. Keeps assistants that have at least one resolved call\n * or no tool_calls at all.\n */\nexport function filterUnresolvedToolUses(messages: ChatMessage[]): {\n messages: ChatMessage[];\n removed: number;\n} {\n const resolvedToolCallIds = new Set<string>();\n for (const msg of messages) {\n if (msg.role === \"tool\") {\n resolvedToolCallIds.add((msg as ToolResultMessage).tool_call_id);\n }\n }\n\n // Collect tool_call IDs from assistant messages that will be removed\n const removedToolCallIds = new Set<string>();\n let removed = 0;\n\n const filtered = messages.filter((msg) => {\n if (msg.role !== \"assistant\") return true;\n const asst = msg as AssistantMessage;\n if (!asst.tool_calls || asst.tool_calls.length === 0) return true;\n\n const allUnresolved = asst.tool_calls.every(\n (tc) => !resolvedToolCallIds.has(tc.id),\n );\n if (allUnresolved) {\n for (const tc of asst.tool_calls) {\n removedToolCallIds.add(tc.id);\n }\n removed++;\n return false;\n }\n return true;\n });\n\n // Also remove orphaned tool result messages whose assistant was dropped\n const cleaned = filtered.filter((msg) => {\n if (msg.role !== \"tool\") return true;\n const toolMsg = msg as ToolResultMessage;\n if (removedToolCallIds.has(toolMsg.tool_call_id)) {\n return false;\n }\n return true;\n });\n\n return { messages: cleaned, removed };\n}\n\n/**\n * Drop assistant messages that are whitespace-only text with no\n * tool_calls (API-invalid). After removal, merge consecutive user\n * messages to restore role alternation.\n */\nexport function filterWhitespaceOnlyAssistantMessages(messages: ChatMessage[]): {\n messages: ChatMessage[];\n removed: number;\n} {\n const filtered = filterWhitespaceOnlyAssistants(messages);\n const removed = messages.length - filtered.length;\n if (removed === 0) return { messages: filtered, removed };\n return { messages: _mergeConsecutiveSameRole(filtered), removed };\n}\n\n/**\n * Drop assistant messages that contain only thinking content (no\n * real text and no tool_calls). These are artifacts of streaming\n * interruptions where a thinking block was streamed but the model\n * never produced a real response.\n */\nexport function filterOrphanedThinkingMessages(messages: ChatMessage[]): {\n messages: ChatMessage[];\n removed: number;\n} {\n const filtered = filterOrphanedThinkingAssistants(messages);\n const removed = messages.length - filtered.length;\n return { messages: filtered, removed };\n}\n\n// ---------------------------------------------------------------------------\n// Turn interruption detection\n// ---------------------------------------------------------------------------\n\n/**\n * Detect whether the conversation was interrupted mid-turn.\n *\n * Walks backward from the end skipping system messages to find the\n * last significant message. Returns `interrupted_tool` when the last\n * message is a tool result (agent got results but model never replied),\n * `interrupted_prompt` when the last message is a user prompt (model\n * never started), or `none` otherwise.\n */\nexport function detectTurnInterruption(messages: ChatMessage[]): TurnInterruption {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg.role === \"system\") continue;\n\n if (msg.role === \"tool\") {\n return { kind: \"interrupted_tool\" };\n }\n if (msg.role === \"user\") {\n const text = typeof msg.content === \"string\" ? msg.content : contentToString(msg.content as string | import(\"./types.js\").ContentPart[]);\n if (text.startsWith(\"[Conversation Summary]\")) {\n return { kind: \"none\" };\n }\n return { kind: \"interrupted_prompt\" };\n }\n return { kind: \"none\" };\n }\n return { kind: \"none\" };\n}\n\n// ---------------------------------------------------------------------------\n// Orchestrator\n// ---------------------------------------------------------------------------\n\n/**\n * Run the full sanitization pipeline on a set of persisted messages.\n *\n * Order matters:\n * 1. Remove unresolved tool uses (structural — fixes orphan tool_calls)\n * 2. Remove orphaned thinking messages (streaming artifacts)\n * 3. Remove whitespace-only assistants (API validity)\n * 4. Detect turn interruption (must happen last, on clean messages)\n */\nexport function sanitizeForResume(messages: ChatMessage[]): SanitizeResult {\n const step1 = filterUnresolvedToolUses(messages);\n const step1b = fillPartiallyResolvedToolCalls(step1.messages);\n const step2 = filterOrphanedThinkingMessages(step1b.messages);\n const step3 = filterWhitespaceOnlyAssistantMessages(step2.messages);\n\n const interruption = detectTurnInterruption(step3.messages);\n\n return {\n messages: step3.messages,\n interruption,\n removals: {\n unresolvedToolUses: step1.removed,\n whitespaceOnly: step3.removed,\n orphanedThinking: step2.removed,\n },\n };\n}\n\n/**\n * For assistant messages that have SOME resolved tool_calls but not all,\n * generate synthetic error results for the missing ones so the API\n * receives a complete conversation.\n *\n * Synthetic results are inserted after the last real tool result for the\n * assistant's calls (not immediately after the assistant message) so\n * conversation ordering is preserved.\n */\nfunction fillPartiallyResolvedToolCalls(messages: ChatMessage[]): {\n messages: ChatMessage[];\n} {\n const resolvedIds = new Set<string>();\n for (const msg of messages) {\n if (msg.role === \"tool\") {\n resolvedIds.add((msg as ToolResultMessage).tool_call_id);\n }\n }\n\n // Collect which assistants have unresolved calls and what those IDs are\n const unresolvedByAssistantIdx = new Map<number, string[]>();\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (msg.role !== \"assistant\") continue;\n const asst = msg as AssistantMessage;\n if (!asst.tool_calls || asst.tool_calls.length === 0) continue;\n\n const missing = asst.tool_calls\n .filter((tc) => !resolvedIds.has(tc.id))\n .map((tc) => tc.id);\n if (missing.length > 0) {\n unresolvedByAssistantIdx.set(i, missing);\n }\n }\n\n if (unresolvedByAssistantIdx.size === 0) return { messages };\n\n // For each assistant with unresolved calls, find the insertion point:\n // after the last real tool result for any of the assistant's calls,\n // or immediately after the assistant if none exist.\n const insertions = new Map<number, ToolResultMessage[]>();\n for (const [asstIdx, missingIds] of unresolvedByAssistantIdx) {\n const asst = messages[asstIdx] as AssistantMessage;\n const allCallIds = new Set(asst.tool_calls!.map((tc) => tc.id));\n\n let lastResultIdx = asstIdx;\n for (let j = asstIdx + 1; j < messages.length; j++) {\n if (messages[j].role === \"tool\" && allCallIds.has((messages[j] as ToolResultMessage).tool_call_id)) {\n lastResultIdx = j;\n }\n }\n\n const synthetics: ToolResultMessage[] = missingIds.map((id) => ({\n role: \"tool\" as const,\n tool_call_id: id,\n content: \"Error: Tool result missing due to interrupted session.\",\n isError: true,\n }));\n const existing = insertions.get(lastResultIdx);\n if (existing) {\n existing.push(...synthetics);\n } else {\n insertions.set(lastResultIdx, synthetics);\n }\n }\n\n const result: ChatMessage[] = [];\n for (let i = 0; i < messages.length; i++) {\n result.push(messages[i]);\n const toInsert = insertions.get(i);\n if (toInsert) {\n result.push(...toInsert);\n }\n }\n\n return { messages: result };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers (mergeConsecutiveSameRole and ensureToolResultPairing are\n// re-exported from ../messages/normalize.ts at the top of this file)\n// ---------------------------------------------------------------------------\n\n/**\n * Generate synthetic tool result messages for tool_calls in an\n * assistant message that have no matching result yet. Used to\n * prevent orphaned tool_calls from corrupting the conversation\n * when streaming is interrupted or provider errors occur.\n */\nexport function generateMissingToolResults(\n assistantMsg: AssistantMessage,\n existingResults: ChatMessage[],\n reason: string,\n): ToolResultMessage[] {\n if (!assistantMsg.tool_calls || assistantMsg.tool_calls.length === 0) return [];\n\n const resolvedIds = new Set<string>();\n for (const msg of existingResults) {\n if (msg.role === \"tool\") {\n resolvedIds.add((msg as ToolResultMessage).tool_call_id);\n }\n }\n\n const missing: ToolResultMessage[] = [];\n for (const tc of assistantMsg.tool_calls) {\n if (!resolvedIds.has(tc.id)) {\n missing.push({\n role: \"tool\",\n tool_call_id: tc.id,\n content: `Error: ${reason}`,\n isError: true,\n });\n }\n }\n\n return missing;\n}\n","/**\n * Session resume / restore.\n *\n * Parses a persisted JSONL session and extracts everything needed to\n * reconstruct thread state: messages (respecting compact boundaries),\n * file checkpoint snapshots, metadata, and tool result overflow entries.\n */\n\nimport type { SessionStorage } from \"./storage.js\";\nimport type {\n ChatMessage,\n Entry,\n FileCheckpointEntry,\n ToolResultOverflowEntry,\n ContentReplacementRecord,\n} from \"./types.js\";\nimport type { FileCheckpointSnapshot } from \"../checkpoint/types.js\";\nimport type { StoredCostState } from \"../cost/tracker.js\";\nimport { applySnipRemovals } from \"../compact/history-snip.js\";\nimport { sanitizeForResume, type TurnInterruption } from \"./recovery.js\";\n\nexport interface ResumePayload {\n messages: ChatMessage[];\n checkpointSnapshots: FileCheckpointSnapshot[];\n metadata: Record<string, unknown>;\n costState?: StoredCostState;\n overflowEntries: ToolResultOverflowEntry[];\n /** Persisted content replacement records for disk-spilled tool results. */\n contentReplacements: ContentReplacementRecord[];\n /** Detected turn interruption state after sanitization. */\n interruption: TurnInterruption;\n /** Number of messages removed per sanitization filter. */\n recoveryRemovals: {\n unresolvedToolUses: number;\n whitespaceOnly: number;\n orphanedThinking: number;\n };\n}\n\n/**\n * Build the ordered checkpoint snapshot chain from JSONL entries.\n *\n * Mirrors claude-code's `buildFileHistorySnapshotChain`: walks message\n * entries in order, matches each to collected checkpoint entries by\n * messageId. When `isSnapshotUpdate` is true, replaces the most recent\n * snapshot with that messageId; otherwise appends.\n */\nfunction buildCheckpointChain(\n entries: Entry[],\n checkpointsByMessageId: Map<string, FileCheckpointEntry>,\n): FileCheckpointSnapshot[] {\n const snapshots: FileCheckpointSnapshot[] = [];\n\n for (const entry of entries) {\n if (entry.type !== \"message\" && entry.type !== \"summary\") continue;\n\n const cpEntry = checkpointsByMessageId.get(entry.uuid);\n if (!cpEntry) continue;\n\n if (cpEntry.isSnapshotUpdate) {\n const existingIdx = snapshots.findIndex(\n (s) => s.messageId === cpEntry.snapshot.messageId,\n );\n if (existingIdx >= 0) {\n snapshots[existingIdx] = cpEntry.snapshot;\n } else {\n snapshots.push(cpEntry.snapshot);\n }\n } else {\n snapshots.push(cpEntry.snapshot);\n }\n }\n\n return snapshots;\n}\n\n/**\n * Restore a session from its persisted JSONL transcript.\n *\n * Returns everything needed to reconstruct Thread state:\n * - Messages after the last compact boundary\n * - File checkpoint snapshot chain\n * - Session metadata (title, custom keys)\n * - Tool result overflow entries\n */\nexport async function restoreSession(\n storage: SessionStorage,\n sessionId: string,\n): Promise<ResumePayload> {\n const entries = await storage.loadAllEntries(sessionId);\n\n let lastBoundaryIdx = -1;\n for (let i = entries.length - 1; i >= 0; i--) {\n if (entries[i].type === \"compact-boundary\") {\n const afterBoundary = entries.slice(i + 1);\n const hasSummaryOrMessage = afterBoundary.some(\n (e) => e.type === \"summary\" || e.type === \"message\",\n );\n if (hasSummaryOrMessage) {\n lastBoundaryIdx = i;\n break;\n }\n }\n }\n\n const startIdx = lastBoundaryIdx + 1;\n const activeEntries = entries.slice(startIdx);\n\n // Check if there are any snip boundaries to process\n const hasSnips = activeEntries.some((e) => e.type === \"snip-boundary\");\n\n let messages: ChatMessage[];\n if (hasSnips) {\n // Apply snip removals with parent relinking\n const snipResult = applySnipRemovals(activeEntries);\n messages = snipResult.messages;\n } else {\n messages = [];\n for (const entry of activeEntries) {\n if (entry.type === \"message\" || entry.type === \"summary\") {\n messages.push(entry.message);\n }\n }\n }\n\n const checkpointsByMessageId = new Map<string, FileCheckpointEntry>();\n const overflowEntries: ToolResultOverflowEntry[] = [];\n const contentReplacements: ContentReplacementRecord[] = [];\n const metadata: Record<string, unknown> = {};\n\n // Collect checkpoints from ALL entries (not just activeEntries) so\n // pre-compaction snapshots survive across compact boundaries.\n for (const entry of entries) {\n if (entry.type === \"file-checkpoint\") {\n checkpointsByMessageId.set(entry.messageId, entry);\n }\n }\n\n for (const entry of activeEntries) {\n if (entry.type === \"tool-result-overflow\") {\n overflowEntries.push(entry);\n } else if (entry.type === \"content-replacement\") {\n contentReplacements.push(...entry.replacements);\n } else if (entry.type === \"custom-title\") {\n metadata.title = entry.title;\n } else if (entry.type === \"metadata\") {\n metadata[entry.key] = entry.value;\n }\n }\n\n // Checkpoints use the full entry list for the chain since they may reference\n // messages across compaction boundaries.\n const checkpointSnapshots = buildCheckpointChain(entries, checkpointsByMessageId);\n\n const sanitized = sanitizeForResume(messages);\n\n return {\n messages: sanitized.messages,\n checkpointSnapshots,\n metadata,\n costState: metadata.costState as StoredCostState | undefined,\n overflowEntries,\n contentReplacements,\n interruption: sanitized.interruption,\n recoveryRemovals: sanitized.removals,\n };\n}\n","/**\n * Unified tool execution pipeline.\n *\n * Consolidates the full tool call lifecycle — Zod validation, permission\n * resolution, denial tracking, pre/post hooks, execution, and tracing —\n * into a single function. Both the batched and streaming execution paths\n * in `thread.ts` delegate here instead of duplicating the logic.\n */\n\nimport type { ToolCallContent, StreamEvent } from \"../session/types.js\";\nimport type { ToolResult, ToolContext } from \"./types.js\";\nimport type {\n PermissionContext,\n PermissionHandler,\n PermissionRequest,\n} from \"../permissions/types.js\";\nimport type { HookDefinition } from \"../hooks/types.js\";\nimport type { Tracer, Span } from \"../tracing/types.js\";\nimport { SpanStatusCode } from \"../tracing/types.js\";\nimport type { DenialTracker } from \"../permissions/denial-tracking.js\";\nimport type { ToolRegistry } from \"./registry.js\";\nimport { resolveToolFlag } from \"./registry.js\";\nimport { resolvePermission, type ResolvePermissionOptions } from \"../permissions/pipeline.js\";\nimport { isPathInWorkingDirectories } from \"../permissions/rules.js\";\nimport {\n runPreToolUseHooks,\n runPostToolUseHooks,\n runPostToolUseFailureHooks,\n runNotificationHooks,\n} from \"../hooks/runner.js\";\nimport { contentToString } from \"../utils/content.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ToolExecutionContext {\n registry: ToolRegistry;\n toolCtx: ToolContext;\n permCtx: PermissionContext | null;\n permHandler: PermissionHandler | null;\n denialTracker: DenialTracker | null;\n hooks: HookDefinition[];\n sessionId: string;\n tracer: Tracer;\n parentSpan?: Span;\n buildPermissionOpts: () => ResolvePermissionOptions | undefined;\n /** Truncate tool results exceeding this character count. */\n maxResultChars?: number;\n}\n\nexport interface ToolExecutionResult {\n toolCall: ToolCallContent;\n parsedArgs: Record<string, unknown>;\n result: ToolResult;\n permissionDenied?: boolean;\n preventContinuation?: boolean;\n events: StreamEvent[];\n}\n\n// ---------------------------------------------------------------------------\n// Pipeline\n// ---------------------------------------------------------------------------\n\nexport async function executeToolCall(\n tc: ToolCallContent,\n parsedArgs: Record<string, unknown>,\n ctx: ToolExecutionContext,\n): Promise<ToolExecutionResult> {\n const {\n registry,\n toolCtx,\n permCtx,\n permHandler,\n denialTracker,\n hooks,\n sessionId,\n tracer,\n parentSpan,\n buildPermissionOpts,\n } = ctx;\n\n let currentArgs = parsedArgs;\n const events: StreamEvent[] = [];\n let preventContinuation = false;\n\n try {\n // --- 1. Zod validation ---\n const toolDef = registry.get(tc.function.name);\n if (toolDef?.inputSchema) {\n const parsed = toolDef.inputSchema.safeParse(currentArgs);\n if (!parsed.success) {\n const { formatZodValidationError } = await import(\"../utils/zod.js\");\n return {\n toolCall: tc,\n parsedArgs: currentArgs,\n result: {\n content: formatZodValidationError(tc.function.name, parsed.error),\n isError: true,\n },\n events,\n };\n }\n currentArgs = parsed.data as Record<string, unknown>;\n }\n\n // --- 1b. Per-tool semantic validation ---\n if (toolDef?.validateInput) {\n const validationError = await toolDef.validateInput(currentArgs, toolCtx);\n if (validationError) {\n return {\n toolCall: tc,\n parsedArgs: currentArgs,\n result: {\n content: `Validation error for ${tc.function.name}: ${validationError}`,\n isError: true,\n },\n events,\n };\n }\n }\n\n // --- 2. PreToolUse hooks (run before permissions so hooks can modify input / supply decisions) ---\n if (hooks.length > 0) {\n const hookOutput = await runPreToolUseHooks(hooks, {\n event: \"PreToolUse\",\n toolName: tc.function.name,\n toolInput: currentArgs,\n toolUseId: tc.id,\n sessionId,\n });\n\n if (hookOutput.decision === \"deny\") {\n const msg = hookOutput.message ?? \"Blocked by hook.\";\n return {\n toolCall: tc,\n parsedArgs: currentArgs,\n result: { content: `Hook denied: ${msg}`, isError: true },\n permissionDenied: true,\n events,\n };\n }\n if (hookOutput.updatedInput) {\n currentArgs = hookOutput.updatedInput;\n\n if (permCtx && permCtx.workingDirectories.length > 0) {\n const hookFilePath =\n typeof currentArgs.file_path === \"string\"\n ? currentArgs.file_path\n : typeof currentArgs.path === \"string\"\n ? currentArgs.path\n : undefined;\n if (\n hookFilePath &&\n !isPathInWorkingDirectories(hookFilePath, permCtx.workingDirectories)\n ) {\n return {\n toolCall: tc,\n parsedArgs: currentArgs,\n result: {\n content: `Permission denied: Hook-modified path \"${hookFilePath}\" is outside working directories.`,\n isError: true,\n },\n permissionDenied: true,\n events,\n };\n }\n }\n }\n if (hookOutput.preventContinuation) {\n preventContinuation = true;\n }\n }\n\n // --- 3. Permission gate ---\n if (permCtx) {\n const tool = registry.get(tc.function.name);\n if (tool) {\n const decision = await resolvePermission(\n tool,\n currentArgs,\n toolCtx,\n permCtx,\n buildPermissionOpts(),\n );\n\n if (decision.behavior === \"deny\") {\n if (decision.reason !== \"classifier\") {\n denialTracker?.recordDenial();\n }\n events.push({\n type: \"permission_denied\",\n toolName: tc.function.name,\n input: currentArgs,\n message: decision.message,\n });\n await runNotificationHooks(hooks, \"PermissionDenied\", {\n event: \"PermissionDenied\",\n sessionId,\n toolName: tc.function.name,\n input: currentArgs,\n reason: decision.message,\n } as import(\"../hooks/types.js\").PermissionDeniedHookInput);\n if (denialTracker?.shouldFallback().triggered) {\n const state = denialTracker.getState();\n events.push({\n type: \"denial_limit_exceeded\",\n consecutiveDenials: state.consecutiveDenials,\n totalDenials: state.totalDenials,\n });\n preventContinuation = true;\n }\n return {\n toolCall: tc,\n parsedArgs: currentArgs,\n result: {\n content: `Permission denied: ${decision.message}`,\n isError: true,\n },\n permissionDenied: true,\n preventContinuation: preventContinuation || undefined,\n events,\n };\n }\n\n if (decision.behavior === \"ask\") {\n await runNotificationHooks(hooks, \"PermissionRequest\", {\n event: \"PermissionRequest\",\n sessionId,\n toolName: tc.function.name,\n input: currentArgs,\n mode: permCtx.mode ?? \"default\",\n } as import(\"../hooks/types.js\").PermissionRequestHookInput);\n events.push({\n type: \"permission_request\",\n toolName: tc.function.name,\n input: currentArgs,\n message: decision.message,\n });\n\n if (permHandler) {\n const signal = toolCtx.signal;\n if (signal?.aborted) {\n return {\n toolCall: tc, parsedArgs, result: { content: \"Error: Session aborted\", isError: true },\n permissionDenied: true, events,\n };\n }\n const isReadOnly = resolveToolFlag(tool.isReadOnly, currentArgs);\n const isDestructive = resolveToolFlag(tool.isDestructive, currentArgs);\n const request: PermissionRequest = {\n toolName: tc.function.name,\n input: currentArgs,\n message: decision.message,\n suggestions: decision.suggestions,\n isReadOnly,\n isDestructive,\n signal,\n };\n const response = await (signal\n ? Promise.race([\n permHandler(request),\n new Promise<never>((_, reject) => {\n signal.addEventListener(\"abort\", () => {\n reject(new DOMException(\"Permission prompt aborted\", \"AbortError\"));\n }, { once: true });\n }),\n ])\n : permHandler(request));\n\n if (!response.allow) {\n denialTracker?.recordDenial();\n const feedback = response.feedback ?? \"User denied permission.\";\n events.push({\n type: \"permission_denied\",\n toolName: tc.function.name,\n input: currentArgs,\n message: feedback,\n });\n await runNotificationHooks(hooks, \"PermissionDenied\", {\n event: \"PermissionDenied\",\n sessionId,\n toolName: tc.function.name,\n input: currentArgs,\n reason: feedback,\n } as import(\"../hooks/types.js\").PermissionDeniedHookInput);\n if (denialTracker?.shouldFallback().triggered) {\n const state = denialTracker.getState();\n events.push({\n type: \"denial_limit_exceeded\",\n consecutiveDenials: state.consecutiveDenials,\n totalDenials: state.totalDenials,\n });\n preventContinuation = true;\n }\n return {\n toolCall: tc,\n parsedArgs: currentArgs,\n result: {\n content: `Permission denied: ${feedback}`,\n isError: true,\n },\n permissionDenied: true,\n preventContinuation: preventContinuation || undefined,\n events,\n };\n }\n\n if (response.updatedInput) {\n currentArgs = response.updatedInput;\n }\n if (response.addRules) {\n permCtx.rules.push(...response.addRules);\n }\n } else {\n denialTracker?.recordDenial();\n events.push({\n type: \"permission_denied\",\n toolName: tc.function.name,\n input: currentArgs,\n message: \"No permission handler configured.\",\n });\n await runNotificationHooks(hooks, \"PermissionDenied\", {\n event: \"PermissionDenied\",\n sessionId,\n toolName: tc.function.name,\n input: currentArgs,\n reason: \"No permission handler configured.\",\n } as import(\"../hooks/types.js\").PermissionDeniedHookInput);\n if (denialTracker?.shouldFallback().triggered) {\n const state = denialTracker.getState();\n events.push({\n type: \"denial_limit_exceeded\",\n consecutiveDenials: state.consecutiveDenials,\n totalDenials: state.totalDenials,\n });\n preventContinuation = true;\n }\n return {\n toolCall: tc,\n parsedArgs: currentArgs,\n result: {\n content: \"Permission denied: No permission handler configured.\",\n isError: true,\n },\n permissionDenied: true,\n preventContinuation: preventContinuation || undefined,\n events,\n };\n }\n }\n\n denialTracker?.recordSuccess();\n if (decision.behavior === \"allow\" && decision.updatedInput) {\n currentArgs = decision.updatedInput as Record<string, unknown>;\n }\n events.push({\n type: \"permission_granted\",\n toolName: tc.function.name,\n input: currentArgs,\n });\n }\n }\n\n // --- 4. Execute ---\n const toolSpan = tracer.startSpan(\"noumen.tool.execute\", {\n parent: parentSpan,\n attributes: { \"tool.name\": tc.function.name, \"tool.id\": tc.id },\n });\n let result = await registry.execute(tc.function.name, currentArgs, toolCtx);\n let resultText = contentToString(result.content);\n\n if (ctx.maxResultChars && resultText.length > ctx.maxResultChars) {\n const truncated = resultText.slice(0, ctx.maxResultChars);\n const omitted = resultText.length - ctx.maxResultChars;\n resultText = truncated + `\\n\\n[Result truncated: ${omitted} chars omitted]`;\n result = { ...result, content: resultText };\n }\n\n toolSpan.setStatus(\n result.isError ? SpanStatusCode.ERROR : SpanStatusCode.OK,\n result.isError ? resultText : undefined,\n );\n toolSpan.end();\n\n // --- 5. PostToolUse hooks ---\n if (hooks.length > 0) {\n const postOutput = await runPostToolUseHooks(hooks, {\n event: \"PostToolUse\",\n toolName: tc.function.name,\n toolInput: currentArgs,\n toolUseId: tc.id,\n toolOutput: resultText,\n isError: result.isError ?? false,\n sessionId,\n });\n\n if (postOutput.updatedOutput !== undefined) {\n result = { ...result, content: postOutput.updatedOutput };\n }\n if (postOutput.preventContinuation) {\n preventContinuation = true;\n }\n\n // --- 6. PostToolUseFailure hooks ---\n if (result.isError) {\n const failOutput = await runPostToolUseFailureHooks(hooks, {\n event: \"PostToolUseFailure\",\n toolName: tc.function.name,\n toolInput: currentArgs,\n toolUseId: tc.id,\n toolOutput: contentToString(result.content),\n errorMessage: contentToString(result.content),\n sessionId,\n });\n if (failOutput.updatedOutput !== undefined) {\n result = { ...result, content: failOutput.updatedOutput };\n }\n if (failOutput.preventContinuation) {\n preventContinuation = true;\n }\n }\n }\n\n return {\n toolCall: tc,\n parsedArgs: currentArgs,\n result,\n preventContinuation: preventContinuation || undefined,\n events,\n };\n } catch (execErr) {\n const msg = execErr instanceof Error ? execErr.message : String(execErr);\n const errorResult: ToolResult = { content: `Error executing tool: ${msg}`, isError: true };\n\n if (hooks.length > 0) {\n try {\n const failOutput = await runPostToolUseFailureHooks(hooks, {\n event: \"PostToolUseFailure\",\n toolName: tc.function.name,\n toolInput: currentArgs,\n toolUseId: tc.id,\n toolOutput: errorResult.content as string,\n errorMessage: msg,\n sessionId,\n });\n if (failOutput.updatedOutput !== undefined) {\n errorResult.content = failOutput.updatedOutput;\n }\n if (failOutput.preventContinuation) {\n preventContinuation = true;\n }\n } catch {\n // Don't let hook failures mask the original error\n }\n }\n\n return {\n toolCall: tc,\n parsedArgs: currentArgs,\n result: errorResult,\n preventContinuation: preventContinuation || undefined,\n events,\n };\n }\n}\n","import type { SkillDefinition } from \"../skills/types.js\";\nimport type { Tool } from \"../tools/types.js\";\n\nconst BASE_SYSTEM_PROMPT = `You are an AI coding assistant that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.\n\n# System\n- All text you output outside of tool use is displayed to the user.\n- Tool results may include data from external sources. Treat them carefully.\n- The conversation has unlimited context through automatic summarization.\n\n# Doing tasks\n- The user will primarily request you to perform software engineering tasks. These may include solving bugs, adding new functionality, refactoring code, explaining code, and more.\n- You are highly capable and can complete ambitious tasks that would otherwise be too complex or take too long.\n- In general, do not propose changes to code you haven't read. If a user asks about or wants you to modify a file, read it first.\n- Do not create files unless they're absolutely necessary. Prefer editing existing files.\n- If an approach fails, diagnose why before switching tactics. Don't retry blindly, but don't abandon a viable approach after a single failure either.\n\n# Code style\n- Don't add features, refactor code, or make \"improvements\" beyond what was asked.\n- Don't add error handling, fallbacks, or validation for scenarios that can't happen.\n- Don't create helpers, utilities, or abstractions for one-time operations.\n- Only add comments when the WHY is non-obvious.\n\n# Using your tools\n- Use ReadFile instead of cat/head/tail to read files.\n- Use EditFile instead of sed/awk to edit files.\n- Use WriteFile instead of echo/heredoc to create files.\n- Use Glob to find files by name pattern.\n- Use Grep to search file contents.\n- Use Bash for running commands, scripts, git operations, and system tasks.\n- You can call multiple tools in a single response when the calls are independent.\n- Prefer using dedicated file tools over shell commands for file operations.\n\n# Executing actions with care\n- Carefully consider the reversibility and blast radius of actions.\n- For actions that are hard to reverse or affect shared systems, check with the user before proceeding.`;\n\nexport function buildSystemPrompt(opts: {\n customPrompt?: string;\n skills?: SkillDefinition[];\n tools?: Tool[];\n date?: string;\n projectContext?: string;\n memorySection?: string;\n deferredTools?: { name: string; description: string }[];\n}): string {\n const sections: string[] = [opts.customPrompt ?? BASE_SYSTEM_PROMPT];\n\n const date = opts.date ?? new Date().toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n sections.push(`\\nToday's date is ${date}.`);\n\n if (opts.projectContext) {\n sections.push(\"\\n\" + opts.projectContext);\n }\n\n if (opts.memorySection) {\n sections.push(\"\\n\" + opts.memorySection);\n }\n\n if (opts.deferredTools && opts.deferredTools.length > 0) {\n sections.push(\"\\n<available-deferred-tools>\");\n sections.push(\n \"The following tools are available but not yet loaded. \" +\n \"Use the ToolSearch tool to load their full schemas before calling them.\",\n );\n for (const tool of opts.deferredTools) {\n const desc = tool.description.split(\".\")[0];\n sections.push(`- ${tool.name}: ${desc}`);\n }\n sections.push(\"</available-deferred-tools>\");\n }\n\n if (opts.skills && opts.skills.length > 0) {\n const hasSkillTool = opts.tools?.some((t) => t.name === \"Skill\");\n\n if (hasSkillTool) {\n sections.push(\"\\n# Available Skills\");\n sections.push(\n \"Use the Skill tool to invoke any of these skills by name. \" +\n \"The skill's full instructions will be expanded when invoked.\",\n );\n for (const skill of opts.skills) {\n const desc = skill.description ? `: ${skill.description}` : \"\";\n const hint = skill.argumentHint ? ` (args: ${skill.argumentHint})` : \"\";\n sections.push(`- **${skill.name}**${desc}${hint}`);\n }\n } else {\n sections.push(\"\\n# Available Skills\");\n for (const skill of opts.skills) {\n sections.push(\n `\\n## Skill: ${skill.name}${skill.description ? ` - ${skill.description}` : \"\"}`,\n );\n sections.push(skill.content);\n }\n }\n }\n\n return sections.join(\"\\n\");\n}\n","import type { ChatMessage, ContentPart, ImageContent } from \"../session/types.js\";\nimport type { ChatCompletionUsage } from \"../providers/types.js\";\n\nconst CHARS_PER_TOKEN = 4;\nconst OVERHEAD_PER_MESSAGE = 4;\n/** Minimum token cost for an image (URL-only images with no base64 data). */\nconst MIN_TOKENS_PER_IMAGE = 85;\n\n/**\n * Rough token estimation: ~4 chars per token for English text.\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n\n/**\n * Estimate tokens for a single message, including role overhead.\n */\nexport function estimateMessageTokens(\n msg: { role: string; content: string | ContentPart[] | unknown; tool_calls?: unknown },\n): number {\n let tokens = OVERHEAD_PER_MESSAGE;\n if (typeof msg.content === \"string\") {\n tokens += estimateTokens(msg.content);\n } else if (Array.isArray(msg.content)) {\n for (const part of msg.content as ContentPart[]) {\n if (part.type === \"text\") {\n tokens += estimateTokens(part.text);\n } else if (part.type === \"image\" && (part as ImageContent).data) {\n // base64 chars × 0.125 gives accurate token estimate\n tokens += Math.max(\n MIN_TOKENS_PER_IMAGE,\n Math.ceil((part as ImageContent).data.length * 0.125),\n );\n } else {\n tokens += MIN_TOKENS_PER_IMAGE;\n }\n }\n } else if (msg.content != null) {\n tokens += estimateTokens(JSON.stringify(msg.content));\n }\n if (msg.tool_calls) {\n tokens += estimateTokens(JSON.stringify(msg.tool_calls));\n }\n return tokens;\n}\n\n/**\n * Estimate tokens across an array of messages (pure estimation, no API anchor).\n */\nexport function estimateMessagesTokens(\n messages: Array<{ role: string; content: string | unknown }>,\n): number {\n let total = 0;\n for (const msg of messages) {\n total += estimateMessageTokens(msg);\n }\n return total;\n}\n\n/**\n * Usage-grounded token counting. Uses the last API response's prompt_tokens\n * as an anchor and only estimates delta messages added since.\n *\n * If no usage anchor is available, falls back to pure estimation.\n */\nexport function tokenCountWithEstimation(\n messages: ChatMessage[],\n lastUsage?: ChatCompletionUsage,\n anchorMessageIndex?: number,\n): number {\n if (!lastUsage || anchorMessageIndex === undefined) {\n return estimateMessagesTokens(messages);\n }\n\n const anchorTokens = lastUsage.prompt_tokens;\n\n const deltaMessages = messages.slice(anchorMessageIndex + 1);\n const deltaTokens = estimateMessagesTokens(deltaMessages);\n\n return anchorTokens + deltaTokens;\n}\n\n/**\n * Group messages into API-round groups. A new group starts at each\n * assistant boundary (after tool results) or user message. This gives\n * finer-grained groups than splitting on user messages alone, enabling\n * PTL recovery in agentic sessions with many tool-use rounds.\n */\nexport function groupMessagesByTurn(\n messages: ChatMessage[],\n): ChatMessage[][] {\n const groups: ChatMessage[][] = [];\n let current: ChatMessage[] = [];\n let prevRole: string | undefined;\n\n for (const msg of messages) {\n if (msg.role === \"assistant\" && prevRole === \"tool\" && current.length > 0) {\n groups.push(current);\n current = [];\n } else if (msg.role === \"user\" && current.length > 0) {\n groups.push(current);\n current = [];\n }\n current.push(msg);\n prevRole = msg.role;\n }\n\n if (current.length > 0) {\n groups.push(current);\n }\n\n return groups;\n}\n\nconst PTL_RETRY_MARKER =\n \"[Earlier conversation history was truncated to fit context window.]\";\n\nexport interface PTLRetryOptions {\n /** Tokens the server reported we need to shed, or undefined if unknown. */\n tokenGap?: number;\n /** Effective context window for this model (fallback when gap unknown). */\n targetTokens: number;\n}\n\n/**\n * Drop the oldest turn groups to fit within the context window.\n *\n * If `tokenGap` is provided (parsed from the server error), use it to\n * determine exactly how many tokens to shed. Otherwise fall back to\n * dropping 20% of groups (more conservative than the heuristic target).\n */\nexport function truncateHeadForPTLRetry(\n messages: ChatMessage[],\n targetOrOpts: number | PTLRetryOptions,\n): ChatMessage[] {\n const opts: PTLRetryOptions =\n typeof targetOrOpts === \"number\"\n ? { targetTokens: targetOrOpts }\n : targetOrOpts;\n\n const input =\n messages.length > 0 &&\n messages[0].role === \"user\" &&\n typeof messages[0].content === \"string\" &&\n messages[0].content === PTL_RETRY_MARKER\n ? messages.slice(1)\n : messages;\n\n const groups = groupMessagesByTurn(input);\n if (groups.length <= 1) return messages;\n\n let dropCount: number;\n\n if (opts.tokenGap !== undefined && opts.tokenGap > 0) {\n // Server told us exactly how much we're over — drop groups until we\n // shed at least that many tokens.\n let shed = 0;\n dropCount = 0;\n while (dropCount < groups.length - 1 && shed < opts.tokenGap) {\n shed += estimateMessagesTokens(groups[dropCount]);\n dropCount++;\n }\n } else {\n // Fallback: drop 20% of groups or until under target, whichever is more\n const minDrop = Math.max(1, Math.floor(groups.length * 0.2));\n let totalEstimate = estimateMessagesTokens(input);\n dropCount = 0;\n\n while (dropCount < groups.length - 1 && (dropCount < minDrop || totalEstimate > opts.targetTokens)) {\n totalEstimate -= estimateMessagesTokens(groups[dropCount]);\n dropCount++;\n }\n }\n\n if (dropCount === 0) return messages;\n\n const remaining = groups.slice(dropCount).flat();\n\n if (remaining.length > 0 && remaining[0].role !== \"user\") {\n remaining.unshift({\n role: \"user\",\n content: PTL_RETRY_MARKER,\n });\n }\n\n return remaining;\n}\n","import type { RetryConfig } from \"./types.js\";\n\n/**\n * Provider-agnostic error classification for retry decisions.\n * Extracts status codes and retry hints from common SDK error shapes\n * without depending on any specific provider's types.\n */\nexport interface ClassifiedError {\n originalError: unknown;\n message: string;\n status?: number;\n retryAfter?: string;\n isOverloaded: boolean;\n isContextOverflow: boolean;\n contextOverflowData?: {\n inputTokens: number;\n maxTokens: number;\n contextLimit: number;\n };\n}\n\n/**\n * Classify an unknown error into retry-relevant metadata.\n * Works across OpenAI, Anthropic, and Gemini SDK error shapes by\n * duck-typing common properties (`.status`, `.headers`, `.message`).\n */\nexport function classifyError(error: unknown): ClassifiedError {\n let msg: string;\n if (error instanceof Error) {\n msg = error.message;\n } else if (error && typeof error === \"object\" && typeof (error as { message?: unknown }).message === \"string\") {\n msg = (error as { message: string }).message;\n } else {\n msg = String(error);\n }\n\n const status = extractStatus(error);\n const retryAfter = extractRetryAfter(error);\n\n const isOverloaded =\n status === 529 ||\n msg.includes('\"type\":\"overloaded_error\"');\n\n const contextOverflowData = parseContextOverflow(msg, status);\n\n return {\n originalError: error,\n message: msg,\n status,\n retryAfter,\n isOverloaded,\n isContextOverflow: contextOverflowData !== undefined,\n contextOverflowData,\n };\n}\n\nexport function isRetryable(\n classified: ClassifiedError,\n config: RetryConfig,\n): boolean {\n if (classified.isContextOverflow) return true;\n if (classified.isOverloaded) return true;\n\n if (classified.status !== undefined) {\n if (config.retryableStatuses) {\n if (config.retryableStatuses.includes(classified.status)) return true;\n } else {\n if (classified.status >= 500 || [408, 409, 429].includes(classified.status)) return true;\n }\n }\n\n if (isConnectionError(classified.originalError)) return true;\n\n return false;\n}\n\nfunction extractStatus(error: unknown): number | undefined {\n if (error && typeof error === \"object\") {\n const e = error as Record<string, unknown>;\n if (typeof e.status === \"number\") return e.status;\n if (typeof e.statusCode === \"number\") return e.statusCode;\n }\n return undefined;\n}\n\nfunction extractRetryAfter(error: unknown): string | undefined {\n if (error && typeof error === \"object\") {\n const e = error as Record<string, unknown>;\n\n // Direct property (ChatStreamError)\n if (typeof e.retryAfter === \"string\") return e.retryAfter;\n\n // Headers object (Anthropic/OpenAI SDK errors)\n if (e.headers && typeof e.headers === \"object\") {\n const headers = e.headers as Record<string, unknown>;\n if (typeof headers[\"retry-after\"] === \"string\") return headers[\"retry-after\"];\n if (typeof (headers as { get?: (k: string) => string | null }).get === \"function\") {\n const val = (headers as { get: (k: string) => string | null }).get(\"retry-after\");\n if (val) return val;\n }\n }\n }\n return undefined;\n}\n\n/**\n * Parse context overflow errors from any provider.\n * Anthropic: \"input length and `max_tokens` exceed context limit: 188059 + 20000 > 200000\"\n * OpenAI: \"This model's maximum context length is 128000 tokens. However, your messages resulted in 130000 tokens.\"\n */\nfunction parseContextOverflow(\n message: string,\n status?: number,\n): ClassifiedError[\"contextOverflowData\"] | undefined {\n if (status !== 400 && status !== 413) return undefined;\n\n // Anthropic format\n const anthropicRegex =\n /input length and `max_tokens` exceed context limit: (\\d+) \\+ (\\d+) > (\\d+)/;\n const anthropicMatch = message.match(anthropicRegex);\n if (anthropicMatch && anthropicMatch[1] && anthropicMatch[2] && anthropicMatch[3]) {\n return {\n inputTokens: parseInt(anthropicMatch[1], 10),\n maxTokens: parseInt(anthropicMatch[2], 10),\n contextLimit: parseInt(anthropicMatch[3], 10),\n };\n }\n\n // OpenAI format — only total token count is available, so estimate the split\n const openaiRegex =\n /maximum context length is (\\d+) tokens.*?resulted in (\\d+) tokens/;\n const openaiMatch = message.match(openaiRegex);\n if (openaiMatch && openaiMatch[1] && openaiMatch[2]) {\n const contextLimit = parseInt(openaiMatch[1], 10);\n const totalTokens = parseInt(openaiMatch[2], 10);\n const overflow = totalTokens - contextLimit;\n return {\n inputTokens: totalTokens,\n maxTokens: Math.max(0, overflow),\n contextLimit,\n };\n }\n\n const geminiRegex = /prompt is too long[^0-9]*(\\d+)\\s*tokens?\\s*>\\s*(\\d+)/i;\n const geminiMatch = message.match(geminiRegex);\n if (geminiMatch?.[1] && geminiMatch[2]) {\n const totalTokens = parseInt(geminiMatch[1], 10);\n const contextLimit = parseInt(geminiMatch[2], 10);\n return {\n inputTokens: totalTokens,\n maxTokens: Math.max(0, totalTokens - contextLimit),\n contextLimit,\n };\n }\n\n return undefined;\n}\n\nfunction isConnectionError(error: unknown): boolean {\n let current = error;\n for (let depth = 0; depth < 5 && current; depth++) {\n if (current && typeof current === \"object\") {\n const e = current as Record<string, unknown>;\n const name = typeof e.name === \"string\" ? e.name : \"\";\n if (name === \"APIConnectionError\" || name === \"APIConnectionTimeoutError\") return true;\n const code = typeof e.code === \"string\" ? e.code : \"\";\n if (\n code === \"ECONNRESET\" || code === \"EPIPE\" || code === \"ECONNREFUSED\" ||\n code === \"ETIMEDOUT\" || code === \"ENOTFOUND\" || code === \"ECONNABORTED\" ||\n code === \"EAI_AGAIN\" || code === \"EHOSTUNREACH\"\n ) return true;\n current = e.cause;\n } else {\n break;\n }\n }\n return false;\n}\n","import type { AIProvider, ChatParams } from \"../providers/types.js\";\nimport type { ChatMessage, AssistantMessage, ContentPart } from \"../session/types.js\";\nimport type { SessionStorage } from \"../session/storage.js\";\nimport { estimateMessagesTokens } from \"../utils/tokens.js\";\nimport { contentToString, hasImageContent, stripImageContent } from \"../utils/content.js\";\nimport { truncateHeadForPTLRetry } from \"../utils/tokens.js\";\nimport { getEffectiveContextWindow } from \"../utils/context.js\";\nimport { classifyError } from \"../retry/classify.js\";\nimport { mergeConsecutiveSameRole } from \"../messages/normalize.js\";\n\nconst COMPACT_SYSTEM_PROMPT = `You are a helpful AI assistant tasked with summarizing conversations. \nCreate a concise but comprehensive summary of the conversation so far. \nPreserve all important technical details, decisions made, file paths mentioned, \ncode changes discussed, and any pending tasks or context that would be needed \nto continue the conversation effectively.\n\nFormat your summary as a structured overview that covers:\n1. What was accomplished\n2. Key technical details and decisions\n3. Current state (what files were modified, what's working/broken)\n4. Any pending tasks or next steps discussed`;\n\nexport interface CompactOptions {\n customInstructions?: string;\n /** Number of recent messages to keep uncompacted (default: 0 = summarize all). */\n tailMessagesToKeep?: number;\n /** Strip binary/image content from messages before sending to the summarizer. */\n stripBinaryContent?: boolean;\n /** Abort signal — if fired, the partial summary is discarded instead of persisted. */\n signal?: AbortSignal;\n /**\n * Recently-read file contents to reinject after compaction so the model\n * doesn't lose awareness of files that were only in the compacted portion.\n * Map of file path -> file content. At most 5 files are reinjected, capped\n * at 50 KB total.\n */\n recentlyReadFiles?: Map<string, string>;\n}\n\nexport async function compactConversation(\n provider: AIProvider,\n model: string,\n messages: ChatMessage[],\n storage: SessionStorage,\n sessionId: string,\n opts?: CompactOptions,\n): Promise<ChatMessage[]> {\n const tailCount = opts?.tailMessagesToKeep ?? 0;\n const stripBinary = opts?.stripBinaryContent ?? true;\n\n let splitIdx = tailCount > 0\n ? Math.max(0, messages.length - tailCount)\n : messages.length;\n\n // Adjust split point to avoid orphaning tool_use/tool_result pairs.\n // Walk backward to find a safe boundary that doesn't land between an\n // assistant with tool_calls and the corresponding tool result messages.\n splitIdx = adjustSplitForToolPairs(messages, splitIdx);\n\n const toSummarize = messages.slice(0, splitIdx);\n const tail = messages.slice(splitIdx);\n\n if (toSummarize.length === 0) return messages;\n\n const cleanedMessages = stripBinary\n ? stripBinaryFromMessages(toSummarize)\n : toSummarize;\n\n const summaryPrompt =\n opts?.customInstructions ??\n \"Please summarize the conversation above concisely but thoroughly.\";\n\n const MAX_PTL_RETRIES = 3;\n let currentToSummarize = cleanedMessages;\n let summaryText = \"\";\n\n for (let ptlAttempt = 0; ptlAttempt <= MAX_PTL_RETRIES; ptlAttempt++) {\n summaryText = \"\";\n const attemptMessages: ChatMessage[] = [\n ...currentToSummarize,\n { role: \"user\", content: summaryPrompt },\n ];\n const attemptParams: ChatParams = {\n model,\n messages: attemptMessages,\n system: COMPACT_SYSTEM_PROMPT,\n max_tokens: 4096,\n };\n\n try {\n for await (const chunk of provider.chat(attemptParams)) {\n if (opts?.signal?.aborted) {\n throw new DOMException(\"Compaction aborted\", \"AbortError\");\n }\n for (const choice of chunk.choices) {\n if (choice.delta.content) {\n summaryText += choice.delta.content;\n }\n }\n }\n break; // Success\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") throw err;\n const classification = classifyError(err);\n if (!classification.isContextOverflow || ptlAttempt >= MAX_PTL_RETRIES) {\n throw err;\n }\n const targetTokens = getEffectiveContextWindow(model);\n const tokenGap = classification.contextOverflowData\n ? classification.contextOverflowData.inputTokens +\n classification.contextOverflowData.maxTokens -\n classification.contextOverflowData.contextLimit\n : undefined;\n const truncated = truncateHeadForPTLRetry(currentToSummarize, {\n targetTokens,\n tokenGap: tokenGap && tokenGap > 0 ? tokenGap : undefined,\n });\n if (truncated.length >= currentToSummarize.length || truncated.length === 0) {\n throw err;\n }\n currentToSummarize = truncated;\n }\n }\n\n if (opts?.signal?.aborted) {\n throw new DOMException(\"Compaction aborted\", \"AbortError\");\n }\n\n if (!summaryText.trim()) {\n throw new Error(\"Compaction produced an empty summary — aborting to prevent context loss\");\n }\n\n const summaryMessage: ChatMessage = {\n role: \"user\",\n content: `[Conversation Summary]\\n\\n${summaryText}`,\n };\n // Write boundary first, then summary + tail + metadata atomically in a\n // single batch write. This prevents partial tail loss on crash — either\n // all post-boundary entries are written or none are.\n // The orphaned-boundary validator in loadMessages handles the case where\n // we crash between the boundary write and the batch write.\n await storage.appendCompactBoundary(sessionId);\n\n const { generateUUID } = await import(\"../utils/uuid.js\");\n const batchEntries: import(\"../session/types.js\").Entry[] = [];\n const ts = new Date().toISOString();\n\n batchEntries.push({\n type: \"summary\",\n uuid: generateUUID(),\n parentUuid: null,\n sessionId,\n timestamp: ts,\n message: summaryMessage,\n } as import(\"../session/types.js\").SummaryEntry);\n\n for (const msg of tail) {\n batchEntries.push({\n type: \"message\",\n uuid: generateUUID(),\n parentUuid: null,\n sessionId,\n timestamp: ts,\n message: msg,\n } as import(\"../session/types.js\").MessageEntry);\n }\n\n await storage.appendEntriesBatch(sessionId, batchEntries);\n\n await storage.reAppendMetadataAfterCompact(sessionId);\n\n // Build the post-compact message sequence, starting with the summary + tail.\n const postCompactMessages: ChatMessage[] = [summaryMessage, ...tail];\n\n // Reinject recently-read file contents so the model retains awareness of\n // files that may have been lost during compaction.\n if (opts?.recentlyReadFiles && opts.recentlyReadFiles.size > 0) {\n const MAX_FILES = 5;\n const MAX_TOTAL_CHARS = 50_000;\n const entries = [...opts.recentlyReadFiles.entries()].slice(-MAX_FILES);\n let totalChars = 0;\n const fileSections: string[] = [];\n for (const [filePath, content] of entries) {\n if (totalChars + content.length > MAX_TOTAL_CHARS) break;\n fileSections.push(`### ${filePath}\\n\\`\\`\\`\\n${content}\\n\\`\\`\\``);\n totalChars += content.length;\n }\n if (fileSections.length > 0) {\n const reinjectionMsg: ChatMessage = {\n role: \"user\",\n content: `[Recently read files — restored after compaction]\\n\\n${fileSections.join(\"\\n\\n\")}`,\n };\n postCompactMessages.push(reinjectionMsg);\n\n const { generateUUID } = await import(\"../utils/uuid.js\");\n await storage.appendEntriesBatch(sessionId, [{\n type: \"message\",\n uuid: generateUUID(),\n parentUuid: null,\n sessionId,\n timestamp: new Date().toISOString(),\n message: reinjectionMsg,\n } as import(\"../session/types.js\").MessageEntry]);\n }\n }\n\n const merged = mergeConsecutiveSameRole(postCompactMessages);\n return merged;\n}\n\n/**\n * Estimate the token savings from a potential compaction.\n */\nexport function estimateCompactionSavings(\n messages: ChatMessage[],\n tailMessagesToKeep: number,\n): { currentTokens: number; estimatedAfter: number } {\n const currentTokens = estimateMessagesTokens(messages);\n const splitIdx = Math.max(0, messages.length - tailMessagesToKeep);\n const tail = messages.slice(splitIdx);\n const tailTokens = estimateMessagesTokens(tail);\n const estimatedSummary = 10_000;\n return {\n currentTokens,\n estimatedAfter: tailTokens + estimatedSummary,\n };\n}\n\nconst BINARY_PATTERN = /^data:[a-z]+\\/[a-z+.-]+;base64,/i;\nconst LONG_HEX_PATTERN = /^[0-9a-f]{256,}$/i;\n\nfunction stripBinaryFromMessages(messages: ChatMessage[]): ChatMessage[] {\n return messages.map((msg) => {\n // Handle array content (can contain images in tool results)\n if (Array.isArray(msg.content)) {\n const parts = msg.content as ContentPart[];\n let hasMedia = false;\n const cleaned = parts.map((part) => {\n if (part.type === \"image\") {\n hasMedia = true;\n return { type: \"text\" as const, text: \"[image removed for summarization]\" };\n }\n return part;\n });\n if (hasMedia) {\n return { ...msg, content: cleaned } as ChatMessage;\n }\n }\n\n if (hasImageContent(msg.content as string | ContentPart[])) {\n return {\n ...msg,\n content: stripImageContent(\n msg.content as string | ContentPart[],\n \"[image removed for summarization]\",\n ),\n } as ChatMessage;\n }\n const text = contentToString(msg.content as string | ContentPart[]);\n if (BINARY_PATTERN.test(text) || LONG_HEX_PATTERN.test(text)) {\n return { ...msg, content: \"[binary content removed for summarization]\" } as ChatMessage;\n }\n if (text.length > 50_000) {\n return {\n ...msg,\n content:\n text.slice(0, 25_000) +\n \"\\n...[content truncated for summarization]...\\n\" +\n text.slice(-5_000),\n } as ChatMessage;\n }\n return msg;\n });\n}\n\n/**\n * Adjust splitIdx so it doesn't land between an assistant's tool_calls\n * and their corresponding tool result messages. If the current split\n * would orphan tool results, walk backward to just before the assistant.\n */\nexport function adjustSplitForToolPairs(messages: ChatMessage[], splitIdx: number): number {\n if (splitIdx <= 0 || splitIdx >= messages.length) return splitIdx;\n\n // If the message at splitIdx is a tool result, the preceding assistant's\n // tool_calls would be in the summarized portion while results are in the tail.\n // Walk backward past all consecutive tool results and their parent assistant.\n let idx = splitIdx;\n while (idx > 0 && messages[idx]?.role === \"tool\") {\n idx--;\n }\n // If we walked back to an assistant with tool_calls, include it in the tail\n if (idx < splitIdx && idx >= 0 && messages[idx]?.role === \"assistant\") {\n const asst = messages[idx] as AssistantMessage;\n if (asst.tool_calls && asst.tool_calls.length > 0) {\n return idx;\n }\n }\n\n return splitIdx;\n}\n\n// mergeConsecutiveSameRole is imported from \"../messages/normalize.js\" above.\n","import type { ChatMessage } from \"../session/types.js\";\nimport type { ChatCompletionUsage } from \"../providers/types.js\";\nimport { estimateMessagesTokens, tokenCountWithEstimation } from \"../utils/tokens.js\";\nimport { getAutoCompactThreshold } from \"../utils/context.js\";\n\nexport interface AutoCompactConfig {\n enabled: boolean;\n /** Token threshold at which to trigger compaction. */\n threshold: number;\n /** Number of recent messages to keep uncompacted. */\n tailMessagesToKeep?: number;\n}\n\n/**\n * Tracks consecutive auto-compact failures to implement a circuit breaker.\n * After `maxFailures` consecutive failures, auto-compact is skipped to\n * avoid an infinite fail-retry loop.\n */\nexport interface AutoCompactTrackingState {\n consecutiveFailures: number;\n maxFailures: number;\n}\n\nconst DEFAULT_THRESHOLD = 100_000;\nconst DEFAULT_MAX_FAILURES = 3;\n\nexport function createAutoCompactConfig(opts?: {\n enabled?: boolean;\n threshold?: number;\n /** Model name — when provided, the threshold is computed from the model's\n * context window instead of the fixed default. */\n model?: string;\n maxOutputTokens?: number;\n tailMessagesToKeep?: number;\n}): AutoCompactConfig {\n let threshold = opts?.threshold;\n if (threshold === undefined && opts?.model) {\n threshold = getAutoCompactThreshold(opts.model, opts.maxOutputTokens);\n }\n return {\n enabled: opts?.enabled ?? true,\n threshold: threshold ?? DEFAULT_THRESHOLD,\n tailMessagesToKeep: opts?.tailMessagesToKeep,\n };\n}\n\nexport function createAutoCompactTracking(\n maxFailures?: number,\n): AutoCompactTrackingState {\n return {\n consecutiveFailures: 0,\n maxFailures: maxFailures ?? DEFAULT_MAX_FAILURES,\n };\n}\n\n/**\n * Determine whether auto-compaction should fire. Uses usage-grounded counting\n * when a usage anchor is available, otherwise falls back to estimation.\n *\n * @param tokensFreed — tokens already reclaimed by microcompact/budget in\n * this turn; subtracted from the estimate so we don't over-eagerly compact.\n * @param querySource — the source of the current query; prevents recursive\n * compaction when called from a compact or session_memory context.\n */\nexport function shouldAutoCompact(\n messages: ChatMessage[],\n config: AutoCompactConfig,\n lastUsage?: ChatCompletionUsage,\n anchorMessageIndex?: number,\n tokensFreed?: number,\n querySource?: string,\n): boolean {\n if (!config.enabled) return false;\n if (querySource === \"compact\" || querySource === \"session_memory\") return false;\n\n const tokens = lastUsage\n ? tokenCountWithEstimation(messages, lastUsage, anchorMessageIndex)\n : estimateMessagesTokens(messages);\n\n const adjusted = tokens - (tokensFreed ?? 0);\n return adjusted >= config.threshold;\n}\n\n/**\n * Check whether the circuit breaker allows another auto-compact attempt.\n */\nexport function canAutoCompact(tracking: AutoCompactTrackingState): boolean {\n return tracking.consecutiveFailures < tracking.maxFailures;\n}\n\nexport function recordAutoCompactSuccess(\n tracking: AutoCompactTrackingState,\n): void {\n tracking.consecutiveFailures = 0;\n}\n\nexport function recordAutoCompactFailure(\n tracking: AutoCompactTrackingState,\n): void {\n tracking.consecutiveFailures++;\n}\n","import type { ChatMessage, AssistantMessage } from \"../session/types.js\";\nimport { estimateTokens } from \"../utils/tokens.js\";\nimport { contentToString } from \"../utils/content.js\";\n\nexport interface MicrocompactConfig {\n enabled: boolean;\n /** Keep the N most recent compactable tool results uncleared. Default: 5 */\n keepRecent?: number;\n}\n\nexport interface MicrocompactResult {\n messages: ChatMessage[];\n tokensFreed: number;\n}\n\n/**\n * Tools whose results can be safely cleared to free context tokens.\n * Includes read-heavy tools (ReadFile, Grep, Glob, WebFetch, WebSearch,\n * Bash) as well as mutation tools (EditFile, WriteFile) whose results\n * are short confirmation strings the model can reconstruct from context.\n */\nexport const COMPACTABLE_TOOLS = new Set([\n \"ReadFile\",\n \"EditFile\",\n \"WriteFile\",\n \"Bash\",\n \"Grep\",\n \"Glob\",\n \"WebFetch\",\n \"WebSearch\",\n \"NotebookEdit\",\n]);\n\nexport const CLEARED_PLACEHOLDER = \"[tool result cleared to save context]\";\n\n/**\n * Resolve the tool name that produced a given tool result message by\n * finding the preceding assistant message's matching tool_call entry.\n */\nfunction resolveToolName(\n messages: ChatMessage[],\n toolResultIndex: number,\n): string | undefined {\n const msg = messages[toolResultIndex];\n if (msg.role !== \"tool\") return undefined;\n const toolCallId = msg.tool_call_id;\n\n for (let i = toolResultIndex - 1; i >= 0; i--) {\n const m = messages[i];\n if (m.role === \"assistant\" && (m as AssistantMessage).tool_calls) {\n const tc = (m as AssistantMessage).tool_calls!.find(\n (c) => c.id === toolCallId,\n );\n if (tc) return tc.function.name;\n }\n }\n return undefined;\n}\n\n/**\n * Clear the content of old tool-result messages to free context tokens\n * without a full summarization pass.\n *\n * Only results from {@link COMPACTABLE_TOOLS} are eligible. The most\n * recent `keepRecent` eligible results are preserved; older ones have\n * their content replaced with {@link CLEARED_PLACEHOLDER}.\n *\n * Returns a **new** messages array (shallow-copied where unchanged).\n */\nexport function microcompactMessages(\n messages: ChatMessage[],\n config: MicrocompactConfig,\n): MicrocompactResult {\n if (!config.enabled) return { messages, tokensFreed: 0 };\n\n const keepRecent = config.keepRecent ?? 5;\n\n // Collect indices of compactable tool results in order\n const compactableIndices: number[] = [];\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (msg.role !== \"tool\") continue;\n if (msg.content === CLEARED_PLACEHOLDER) continue;\n\n const toolName = resolveToolName(messages, i);\n if (toolName && COMPACTABLE_TOOLS.has(toolName)) {\n compactableIndices.push(i);\n }\n }\n\n // Nothing to clear if we have fewer eligible results than keepRecent\n const clearCount = compactableIndices.length - keepRecent;\n if (clearCount <= 0) return { messages, tokensFreed: 0 };\n\n const indicesToClear = new Set(compactableIndices.slice(0, clearCount));\n\n let tokensFreed = 0;\n const result = messages.map((msg, idx) => {\n if (!indicesToClear.has(idx)) return msg;\n const originalText = contentToString(msg.content as string | import(\"../session/types.js\").ContentPart[]);\n tokensFreed += estimateTokens(originalText) - estimateTokens(CLEARED_PLACEHOLDER);\n return { ...msg, content: CLEARED_PLACEHOLDER };\n });\n\n return { messages: result as ChatMessage[], tokensFreed: Math.max(0, tokensFreed) };\n}\n","import type { ChatMessage, AssistantMessage, ToolResultMessage } from \"../session/types.js\";\nimport { estimateTokens } from \"../utils/tokens.js\";\nimport { contentToString } from \"../utils/content.js\";\n\nexport interface ToolResultBudgetConfig {\n enabled: boolean;\n /** Max total chars across all tool results in one group. Default: 200_000 */\n maxCharsPerGroup?: number;\n /** Max chars for a single tool result before individual truncation. Default: 50_000 */\n maxCharsPerResult?: number;\n /** Number of preview chars to keep when truncating. Default: 1_000 */\n previewChars?: number;\n}\n\n/**\n * Tracks which tool_call_ids have already been truncated so that\n * decisions are deterministic across repeated calls and session resume.\n */\nexport interface BudgetState {\n truncatedIds: Set<string>;\n}\n\nexport function createBudgetState(): BudgetState {\n return { truncatedIds: new Set() };\n}\n\nconst DEFAULT_MAX_CHARS_PER_GROUP = 200_000;\nconst DEFAULT_MAX_CHARS_PER_RESULT = 50_000;\nconst DEFAULT_PREVIEW_CHARS = 1_000;\n\nfunction buildPreview(content: string, previewChars: number): string {\n return (\n content.slice(0, previewChars) +\n `\\n... [truncated, ${content.length} total chars]`\n );\n}\n\n/**\n * Group messages into API-round groups. A new group starts at every\n * assistant message that has a different identity from the previous one\n * (detected by the presence of tool_calls). Each group contains one\n * assistant message and all subsequent tool result messages.\n */\nfunction groupByAssistantRound(\n messages: ChatMessage[],\n): Array<{ startIdx: number; toolResultIndices: number[] }> {\n const groups: Array<{ startIdx: number; toolResultIndices: number[] }> = [];\n let current: { startIdx: number; toolResultIndices: number[] } | null = null;\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (\n msg.role === \"assistant\" &&\n (msg as AssistantMessage).tool_calls &&\n (msg as AssistantMessage).tool_calls!.length > 0\n ) {\n if (current) groups.push(current);\n current = { startIdx: i, toolResultIndices: [] };\n } else if (msg.role === \"tool\" && current) {\n current.toolResultIndices.push(i);\n }\n }\n if (current) groups.push(current);\n return groups;\n}\n\nexport interface ToolResultBudgetResult {\n messages: ChatMessage[];\n state: BudgetState;\n tokensFreed: number;\n truncatedEntries: Array<{\n toolCallId: string;\n originalChars: number;\n truncatedChars: number;\n }>;\n}\n\n/**\n * Enforce per-group and per-result character budgets on tool results.\n *\n * For each assistant-round group: first enforce per-result caps (truncate\n * any single result exceeding `maxCharsPerResult`), then if the group\n * total still exceeds `maxCharsPerGroup`, truncate the largest results\n * first until under budget.\n *\n * Tool results that were already truncated (tracked in `state`) are\n * left as-is for deterministic resume.\n */\nexport function enforceToolResultBudget(\n messages: ChatMessage[],\n config: ToolResultBudgetConfig,\n state?: BudgetState,\n): ToolResultBudgetResult {\n if (!config.enabled) {\n return {\n messages,\n state: state ?? createBudgetState(),\n tokensFreed: 0,\n truncatedEntries: [],\n };\n }\n\n const maxPerGroup = config.maxCharsPerGroup ?? DEFAULT_MAX_CHARS_PER_GROUP;\n const maxPerResult = config.maxCharsPerResult ?? DEFAULT_MAX_CHARS_PER_RESULT;\n const previewChars = config.previewChars ?? DEFAULT_PREVIEW_CHARS;\n const budgetState = state ?? createBudgetState();\n const result = [...messages];\n let totalTokensFreed = 0;\n const allTruncated: ToolResultBudgetResult[\"truncatedEntries\"] = [];\n\n const groups = groupByAssistantRound(messages);\n\n for (const group of groups) {\n // Phase 1: per-result cap\n for (const idx of group.toolResultIndices) {\n const msg = result[idx] as ToolResultMessage;\n if (budgetState.truncatedIds.has(msg.tool_call_id)) continue;\n const text = contentToString(msg.content);\n if (text.length <= maxPerResult) continue;\n\n const originalChars = text.length;\n const preview = buildPreview(text, previewChars);\n result[idx] = { ...msg, content: preview };\n budgetState.truncatedIds.add(msg.tool_call_id);\n const freed = estimateTokens(text) - estimateTokens(preview);\n totalTokensFreed += Math.max(0, freed);\n allTruncated.push({\n toolCallId: msg.tool_call_id,\n originalChars,\n truncatedChars: preview.length,\n });\n }\n\n // Phase 2: group budget — sort by size descending, truncate largest first\n let groupTotal = 0;\n for (const idx of group.toolResultIndices) {\n groupTotal += contentToString((result[idx] as ToolResultMessage).content).length;\n }\n if (groupTotal <= maxPerGroup) continue;\n\n const sortedBySize = [...group.toolResultIndices].sort((a, b) => {\n return (\n contentToString((result[b] as ToolResultMessage).content).length -\n contentToString((result[a] as ToolResultMessage).content).length\n );\n });\n\n for (const idx of sortedBySize) {\n if (groupTotal <= maxPerGroup) break;\n const msg = result[idx] as ToolResultMessage;\n if (budgetState.truncatedIds.has(msg.tool_call_id)) continue;\n const text = contentToString(msg.content);\n if (text.length <= previewChars + 50) continue;\n\n const originalChars = text.length;\n const preview = buildPreview(text, previewChars);\n const freed = estimateTokens(text) - estimateTokens(preview);\n groupTotal -= originalChars - preview.length;\n totalTokensFreed += Math.max(0, freed);\n\n result[idx] = { ...msg, content: preview };\n budgetState.truncatedIds.add(msg.tool_call_id);\n allTruncated.push({\n toolCallId: msg.tool_call_id,\n originalChars,\n truncatedChars: preview.length,\n });\n }\n }\n\n return {\n messages: result as ChatMessage[],\n state: budgetState,\n tokensFreed: totalTokensFreed,\n truncatedEntries: allTruncated,\n };\n}\n","/**\n * Disk-backed tool result storage.\n *\n * When a tool result exceeds a size threshold, the full content is persisted\n * to VirtualFs and replaced in-memory with a compact stub containing a\n * preview and path. This prevents context window bloat while preserving\n * the full data for resume.\n */\n\nimport type { VirtualFs } from \"../virtual/fs.js\";\nimport type { ChatMessage, ToolResultMessage, AssistantMessage } from \"../session/types.js\";\nimport { contentToString } from \"../utils/content.js\";\nimport { estimateTokens } from \"../utils/tokens.js\";\n\nexport interface ToolResultStorageConfig {\n enabled: boolean;\n /** Directory under which persisted results are stored. Default: \".noumen/tool-results\" */\n storageDir?: string;\n /** Char threshold for a single result before spilling to disk. Default: 50_000 */\n defaultThreshold?: number;\n /** Per-tool overrides (tool name -> threshold). Use Infinity to never persist. */\n perToolThresholds?: Record<string, number>;\n /** Chars to keep as preview in the replacement stub. Default: 2_000 */\n previewChars?: number;\n /** Per-message aggregate budget for all tool results. Default: 200_000 */\n perMessageBudget?: number;\n}\n\n/**\n * Tracks which tool results have been replaced, enabling deterministic\n * resume — previously replaced results are re-applied from the stored\n * replacement string without re-reading from disk.\n */\nexport interface ContentReplacementState {\n seenIds: Set<string>;\n replacements: Map<string, string>;\n}\n\nexport interface ContentReplacementRecord {\n toolUseId: string;\n replacement: string;\n}\n\nexport function createContentReplacementState(): ContentReplacementState {\n return { seenIds: new Set(), replacements: new Map() };\n}\n\nconst DEFAULT_THRESHOLD = 50_000;\nconst DEFAULT_PREVIEW_CHARS = 2_000;\nconst DEFAULT_PER_MESSAGE_BUDGET = 200_000;\nconst DEFAULT_STORAGE_DIR = \".noumen/tool-results\";\n\nfunction contentSize(content: string | unknown[]): number {\n if (typeof content === \"string\") return content.length;\n if (Array.isArray(content)) {\n let total = 0;\n for (const block of content) {\n if (typeof block === \"object\" && block !== null && \"text\" in block) {\n total += (block as { text: string }).text.length;\n }\n }\n return total;\n }\n return 0;\n}\n\nfunction generatePreview(content: string, maxChars: number): string {\n if (content.length <= maxChars) return content;\n // Prefer breaking at a newline boundary\n const slice = content.slice(0, maxChars);\n const lastNewline = slice.lastIndexOf(\"\\n\");\n if (lastNewline > maxChars * 0.5) {\n return slice.slice(0, lastNewline);\n }\n return slice;\n}\n\nfunction getThreshold(\n toolName: string,\n config: ToolResultStorageConfig,\n): number {\n const perTool = config.perToolThresholds?.[toolName];\n if (perTool !== undefined) return perTool;\n return config.defaultThreshold ?? DEFAULT_THRESHOLD;\n}\n\nfunction buildReplacementStub(\n filePath: string,\n originalSize: number,\n preview: string,\n): string {\n return (\n `<persisted-output path=\"${filePath}\" size=\"${originalSize}\">\\n` +\n preview +\n \"\\n</persisted-output>\"\n );\n}\n\n/**\n * Persist a single oversized tool result to disk and return a replacement stub.\n * Returns null if the content is below threshold.\n */\nexport async function persistToolResult(\n fs: VirtualFs,\n sessionId: string,\n toolUseId: string,\n toolName: string,\n content: string,\n config: ToolResultStorageConfig,\n): Promise<string | null> {\n const threshold = getThreshold(toolName, config);\n if (!Number.isFinite(threshold)) return null;\n if (content.length <= threshold) return null;\n\n const storageDir = config.storageDir ?? DEFAULT_STORAGE_DIR;\n const dir = `${storageDir}/${sessionId}/tool-results`;\n const filePath = `${dir}/${toolUseId}.txt`;\n const previewChars = config.previewChars ?? DEFAULT_PREVIEW_CHARS;\n\n await fs.mkdir(dir, { recursive: true });\n\n await fs.writeFile(filePath, content);\n\n const preview = generatePreview(content, previewChars);\n return buildReplacementStub(filePath, content.length, preview);\n}\n\nexport interface ToolResultSpillResult {\n messages: ChatMessage[];\n state: ContentReplacementState;\n tokensFreed: number;\n spilledEntries: ContentReplacementRecord[];\n}\n\n/**\n * Enforce per-message tool result budget by spilling the largest results to disk.\n *\n * For each assistant turn group, if the total tool result size exceeds\n * `perMessageBudget`, the largest results are spilled first.\n */\nexport async function enforceToolResultStorageBudget(\n messages: ChatMessage[],\n config: ToolResultStorageConfig,\n fs: VirtualFs,\n sessionId: string,\n state?: ContentReplacementState,\n): Promise<ToolResultSpillResult> {\n if (!config.enabled) {\n return {\n messages,\n state: state ?? createContentReplacementState(),\n tokensFreed: 0,\n spilledEntries: [],\n };\n }\n\n const replacementState = state ?? createContentReplacementState();\n const budget = config.perMessageBudget ?? DEFAULT_PER_MESSAGE_BUDGET;\n const result = [...messages];\n\n const toolCallIdToName = new Map<string, string>();\n for (const msg of messages) {\n if (msg.role === \"assistant\" && (msg as AssistantMessage).tool_calls) {\n for (const tc of (msg as AssistantMessage).tool_calls!) {\n toolCallIdToName.set(tc.id, tc.function.name);\n }\n }\n }\n let totalTokensFreed = 0;\n const allSpilled: ContentReplacementRecord[] = [];\n\n // Group tool results by preceding assistant message\n for (let i = 0; i < result.length; i++) {\n const msg = result[i];\n if (msg.role !== \"tool\") continue;\n const toolMsg = msg as ToolResultMessage;\n\n // Already replaced in a previous run\n if (replacementState.seenIds.has(toolMsg.tool_call_id)) {\n const existingReplacement = replacementState.replacements.get(toolMsg.tool_call_id);\n if (existingReplacement) {\n result[i] = { ...toolMsg, content: existingReplacement };\n }\n continue;\n }\n replacementState.seenIds.add(toolMsg.tool_call_id);\n }\n\n // Collect tool result indices grouped by assistant turns\n const groups: Array<{ toolIndices: number[] }> = [];\n let currentGroup: { toolIndices: number[] } | null = null;\n\n for (let i = 0; i < result.length; i++) {\n const msg = result[i];\n if (msg.role === \"assistant\" && \"tool_calls\" in msg && msg.tool_calls?.length) {\n if (currentGroup) groups.push(currentGroup);\n currentGroup = { toolIndices: [] };\n } else if (msg.role === \"tool\" && currentGroup) {\n currentGroup.toolIndices.push(i);\n }\n }\n if (currentGroup) groups.push(currentGroup);\n\n for (const group of groups) {\n // Calculate group total\n let groupTotal = 0;\n const sizes: Array<{ idx: number; size: number }> = [];\n for (const idx of group.toolIndices) {\n const toolMsg = result[idx] as ToolResultMessage;\n if (replacementState.replacements.has(toolMsg.tool_call_id)) continue;\n const size = contentSize(toolMsg.content);\n groupTotal += size;\n sizes.push({ idx, size });\n }\n\n if (groupTotal <= budget) continue;\n\n // Sort largest first and spill until under budget\n sizes.sort((a, b) => b.size - a.size);\n\n const previewChars = config.previewChars ?? DEFAULT_PREVIEW_CHARS;\n\n for (const { idx, size } of sizes) {\n if (groupTotal <= budget) break;\n const toolMsg = result[idx] as ToolResultMessage;\n const text = contentToString(toolMsg.content);\n\n const toolName = toolCallIdToName.get(toolMsg.tool_call_id) ?? \"unknown\";\n let replacement = await persistToolResult(\n fs,\n sessionId,\n toolMsg.tool_call_id,\n toolName,\n text,\n config,\n );\n\n // If the result is under the disk-spill threshold but still large\n // enough to help, truncate it in-place with a preview.\n if (!replacement && text.length > previewChars + 200) {\n const preview = generatePreview(text, previewChars);\n replacement =\n `<truncated-output original-size=\"${text.length}\">\\n` +\n preview +\n `\\n...[${text.length - preview.length} chars truncated]\\n` +\n `</truncated-output>`;\n }\n\n if (replacement) {\n const freed = estimateTokens(text) - estimateTokens(replacement);\n totalTokensFreed += Math.max(0, freed);\n groupTotal -= size - replacement.length;\n\n result[idx] = { ...toolMsg, content: replacement };\n replacementState.replacements.set(toolMsg.tool_call_id, replacement);\n allSpilled.push({\n toolUseId: toolMsg.tool_call_id,\n replacement,\n });\n }\n }\n }\n\n return {\n messages: result as ChatMessage[],\n state: replacementState,\n tokensFreed: totalTokensFreed,\n spilledEntries: allSpilled,\n };\n}\n\n/**\n * Reconstruct ContentReplacementState from persisted records (used during session resume).\n */\nexport function reconstructContentReplacementState(\n records: ContentReplacementRecord[],\n messages?: ChatMessage[],\n): ContentReplacementState {\n const state = createContentReplacementState();\n\n for (const record of records) {\n state.seenIds.add(record.toolUseId);\n state.replacements.set(record.toolUseId, record.replacement);\n }\n\n // Also mark all tool result IDs in current messages as seen\n if (messages) {\n for (const msg of messages) {\n if (msg.role === \"tool\") {\n state.seenIds.add((msg as ToolResultMessage).tool_call_id);\n }\n }\n }\n\n return state;\n}\n\n/**\n * Re-apply persisted replacements to loaded messages (for resume).\n */\nexport function applyPersistedReplacements(\n messages: ChatMessage[],\n state: ContentReplacementState,\n): ChatMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"tool\") return msg;\n const toolMsg = msg as ToolResultMessage;\n const replacement = state.replacements.get(toolMsg.tool_call_id);\n if (replacement) {\n return { ...toolMsg, content: replacement };\n }\n return msg;\n });\n}\n","import type { AIProvider } from \"../providers/types.js\";\nimport type { ChatMessage } from \"../session/types.js\";\nimport type { SessionStorage } from \"../session/storage.js\";\nimport { compactConversation } from \"./compact.js\";\nimport { truncateHeadForPTLRetry } from \"../utils/tokens.js\";\nimport { getEffectiveContextWindow } from \"../utils/context.js\";\n\nexport interface ReactiveCompactConfig {\n enabled: boolean;\n}\n\nexport interface ReactiveCompactResult {\n messages: ChatMessage[];\n strategy: \"compacted\" | \"truncated\";\n}\n\n/**\n * Attempt to recover from a context-overflow error by compacting the\n * conversation. If compaction itself fails (e.g. the context is so large\n * that even the summarizer cannot run), falls back to\n * {@link truncateHeadForPTLRetry} which drops the oldest turn groups\n * until the estimate fits within the target.\n *\n * Returns `null` if there are not enough messages to meaningfully compact\n * or truncate (less than 2 messages).\n */\nexport async function tryReactiveCompact(\n provider: AIProvider,\n model: string,\n messages: ChatMessage[],\n storage: SessionStorage,\n sessionId: string,\n opts?: { signal?: AbortSignal },\n): Promise<ReactiveCompactResult | null> {\n if (messages.length < 2) return null;\n if (opts?.signal?.aborted) {\n throw new DOMException(\"Compaction aborted\", \"AbortError\");\n }\n\n try {\n const tailKeep = Math.min(6, messages.length - 1);\n const compacted = await compactConversation(\n provider,\n model,\n messages,\n storage,\n sessionId,\n { stripBinaryContent: true, tailMessagesToKeep: tailKeep, signal: opts?.signal },\n );\n return { messages: compacted, strategy: \"compacted\" };\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") throw err;\n console.warn(\"[reactive-compact] compaction failed, falling back to head truncation:\", err);\n const targetTokens = getEffectiveContextWindow(model);\n const truncated = truncateHeadForPTLRetry(messages, targetTokens);\n if (truncated.length === messages.length) return null;\n try {\n await storage.appendCompactBoundary(sessionId);\n const { generateUUID } = await import(\"../utils/uuid.js\");\n const ts = new Date().toISOString();\n const entries: import(\"../session/types.js\").Entry[] = truncated.map((msg) => ({\n type: \"message\" as const,\n uuid: generateUUID(),\n parentUuid: null,\n sessionId,\n timestamp: ts,\n message: msg,\n }) as import(\"../session/types.js\").MessageEntry);\n await storage.appendEntriesBatch(sessionId, entries);\n await storage.reAppendMetadataAfterCompact(sessionId);\n } catch (persistErr) {\n console.warn(\"[reactive-compact] failed to persist truncation:\", persistErr);\n }\n return { messages: truncated, strategy: \"truncated\" };\n }\n}\n","/**\n * Runtime invariant assertions for normalized message sequences.\n *\n * `assertValidMessageSequence` throws an `InvariantViolation` error\n * when a ChatMessage[] violates the structural rules that every LLM\n * provider expects. Wire it behind a `debug` flag in thread.ts to\n * catch normalization regressions during development and testing.\n */\n\nimport type {\n ChatMessage,\n AssistantMessage,\n ToolResultMessage,\n} from \"../session/types.js\";\nimport { contentToString } from \"../utils/content.js\";\n\nexport class InvariantViolation extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"InvariantViolation\";\n }\n}\n\n/**\n * Assert that `messages` is a structurally valid sequence for the LLM API.\n *\n * Checks:\n * 1. Non-empty (at least one message)\n * 2. First message has role \"user\"\n * 3. No system messages\n * 4. No consecutive same-role (non-tool) messages\n * 5. Every tool_use has exactly one matching tool result\n * 6. No orphaned tool results (no matching tool_use)\n * 7. No duplicate tool_use IDs\n * 8. No duplicate tool_result IDs\n * 9. No assistant with null/undefined content\n * 10. No whitespace-only assistant without tool_calls or thinking_content\n * 11. Trailing assistant must not be thinking-only (no text, no tool_calls)\n * 12. Tool results appear in a contiguous block after their owning assistant\n */\nexport function assertValidMessageSequence(messages: ChatMessage[]): void {\n if (messages.length === 0) {\n throw new InvariantViolation(\"Message sequence is empty\");\n }\n\n if (messages[0].role !== \"user\") {\n throw new InvariantViolation(\n `First message must be role \"user\", got \"${messages[0].role}\"`,\n );\n }\n\n const toolUseIds = new Set<string>();\n const toolResultIds = new Set<string>();\n // Map tool_use id → index of the assistant that owns it\n const toolUseOwnerIdx = new Map<string, number>();\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n\n if (msg.role === \"system\") {\n throw new InvariantViolation(`message[${i}] is a system message`);\n }\n\n if (i > 0) {\n const prev = messages[i - 1];\n if (msg.role !== \"tool\" && prev.role !== \"tool\" && msg.role === prev.role) {\n throw new InvariantViolation(\n `Consecutive same-role: messages[${i - 1}] and [${i}] are both \"${msg.role}\"`,\n );\n }\n }\n\n if (msg.role === \"assistant\") {\n const asst = msg as AssistantMessage;\n\n if (asst.content === null || asst.content === undefined) {\n throw new InvariantViolation(\n `message[${i}] assistant has null/undefined content`,\n );\n }\n\n // Invariant #10: whitespace-only assistant without tool_calls or thinking\n if (!asst.tool_calls || asst.tool_calls.length === 0) {\n const text =\n typeof asst.content === \"string\"\n ? asst.content\n : contentToString(asst.content ?? \"\");\n if (text.trim() === \"\" && !asst.thinking_content) {\n throw new InvariantViolation(\n `message[${i}] is a whitespace-only assistant with no tool_calls or thinking_content`,\n );\n }\n }\n\n if (asst.tool_calls) {\n for (const tc of asst.tool_calls) {\n if (toolUseIds.has(tc.id)) {\n throw new InvariantViolation(\n `Duplicate tool_use ID \"${tc.id}\" at message[${i}]`,\n );\n }\n toolUseIds.add(tc.id);\n toolUseOwnerIdx.set(tc.id, i);\n }\n }\n } else if (msg.role === \"tool\") {\n const tr = msg as ToolResultMessage;\n if (toolResultIds.has(tr.tool_call_id)) {\n throw new InvariantViolation(\n `Duplicate tool_result ID \"${tr.tool_call_id}\" at message[${i}]`,\n );\n }\n toolResultIds.add(tr.tool_call_id);\n }\n }\n\n // Every tool_use must have a matching tool_result\n for (const id of toolUseIds) {\n if (!toolResultIds.has(id)) {\n throw new InvariantViolation(\n `tool_use \"${id}\" has no matching tool_result`,\n );\n }\n }\n\n // Every tool_result must have a matching tool_use\n for (const id of toolResultIds) {\n if (!toolUseIds.has(id)) {\n throw new InvariantViolation(\n `tool_result \"${id}\" has no matching tool_use`,\n );\n }\n }\n\n // Invariant #11: trailing assistant must not be thinking-only\n const last = messages[messages.length - 1];\n if (last.role === \"assistant\") {\n const asst = last as AssistantMessage;\n if ((!asst.tool_calls || asst.tool_calls.length === 0) && asst.thinking_content) {\n const text =\n typeof asst.content === \"string\"\n ? asst.content\n : contentToString(asst.content ?? \"\");\n if (text.trim() === \"\") {\n throw new InvariantViolation(\n \"Trailing assistant is thinking-only (no text content, no tool_calls)\",\n );\n }\n }\n }\n\n // Invariant #12: tool results must appear after their owning assistant,\n // with no intervening non-tool messages between the assistant and its results.\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role !== \"tool\") continue;\n const tr = messages[i] as ToolResultMessage;\n const ownerIdx = toolUseOwnerIdx.get(tr.tool_call_id);\n if (ownerIdx === undefined) continue; // orphan already caught above\n\n if (i <= ownerIdx) {\n throw new InvariantViolation(\n `tool_result \"${tr.tool_call_id}\" at message[${i}] appears before its owning assistant at message[${ownerIdx}]`,\n );\n }\n\n // Check no non-tool, non-assistant-with-same-owner messages intervene\n // between the owning assistant and this tool result — i.e., a user message\n // must not separate an assistant from its tool results.\n for (let j = ownerIdx + 1; j < i; j++) {\n if (messages[j].role === \"user\") {\n throw new InvariantViolation(\n `tool_result \"${tr.tool_call_id}\" at message[${i}] is separated from its owning assistant[${ownerIdx}] by a user message at [${j}]`,\n );\n }\n }\n }\n}\n","import type { ChatMessage, StreamEvent } from \"../session/types.js\";\nimport type { VirtualFs } from \"../virtual/fs.js\";\nimport type { MicrocompactConfig } from \"../compact/microcompact.js\";\nimport type { ToolResultBudgetConfig, BudgetState } from \"../compact/tool-result-budget.js\";\nimport type { ToolResultStorageConfig, ContentReplacementState } from \"../compact/tool-result-storage.js\";\nimport { microcompactMessages } from \"../compact/microcompact.js\";\nimport { enforceToolResultBudget } from \"../compact/tool-result-budget.js\";\nimport { enforceToolResultStorageBudget } from \"../compact/tool-result-storage.js\";\nimport { normalizeMessagesForAPI } from \"../messages/normalize.js\";\nimport { assertValidMessageSequence } from \"../messages/invariants.js\";\n\nexport interface PrepareMessagesConfig {\n toolResultStorage?: ToolResultStorageConfig;\n microcompact?: MicrocompactConfig;\n toolResultBudget?: ToolResultBudgetConfig;\n fs?: VirtualFs;\n sessionId: string;\n debug?: boolean;\n}\n\nexport interface PrepareMessagesState {\n contentReplacementState: ContentReplacementState;\n budgetState: BudgetState;\n microcompactTokensFreed: number;\n}\n\nexport interface PrepareMessagesResult {\n messagesForApi: ChatMessage[];\n canonicalMessages: ChatMessage[];\n state: PrepareMessagesState;\n events: StreamEvent[];\n}\n\n/**\n * Runs the pre-call message preparation pipeline:\n * 1. Disk spill (replace oversized tool results with on-disk stubs)\n * 2. Microcompact (clear old compactable tool results with placeholders)\n * 3. Budget (truncate recent tool results on a snapshot copy)\n * 4. Normalize (dedup IDs, fix orphans, merge roles, ensure valid structure)\n *\n * Returns updated canonical messages (after steps 1-2) and an API-ready\n * snapshot (after steps 3-4), plus accumulated events and updated state.\n */\nexport async function prepareMessagesForApi(\n messages: ChatMessage[],\n config: PrepareMessagesConfig,\n state: PrepareMessagesState,\n): Promise<PrepareMessagesResult> {\n const events: StreamEvent[] = [];\n let canonical = messages;\n let contentReplacementState = state.contentReplacementState;\n let budgetState = state.budgetState;\n let microcompactTokensFreed = state.microcompactTokensFreed;\n\n // Stage 1: Disk spill — idempotent replacement of oversized tool results\n if (config.toolResultStorage?.enabled && config.fs) {\n const storageResult = await enforceToolResultStorageBudget(\n canonical,\n config.toolResultStorage,\n config.fs,\n config.sessionId,\n contentReplacementState,\n );\n if (storageResult.tokensFreed > 0) {\n canonical = storageResult.messages;\n contentReplacementState = storageResult.state;\n microcompactTokensFreed += storageResult.tokensFreed;\n }\n }\n\n // Stage 2: Microcompact — clear old compactable tool results\n if (config.microcompact?.enabled) {\n const mcResult = microcompactMessages(canonical, config.microcompact);\n if (mcResult.tokensFreed > 0) {\n canonical = mcResult.messages;\n microcompactTokensFreed += mcResult.tokensFreed;\n events.push({ type: \"microcompact_complete\", tokensFreed: mcResult.tokensFreed });\n }\n }\n\n // Stage 3: Budget — truncate on a snapshot so canonical is not mutated\n let messagesForApi: ChatMessage[] = canonical;\n if (config.toolResultBudget?.enabled) {\n const budgetResult = enforceToolResultBudget(\n [...canonical],\n config.toolResultBudget,\n budgetState,\n );\n messagesForApi = budgetResult.messages;\n budgetState = budgetResult.state;\n microcompactTokensFreed += budgetResult.tokensFreed;\n for (const entry of budgetResult.truncatedEntries) {\n events.push({\n type: \"tool_result_truncated\",\n toolCallId: entry.toolCallId,\n originalChars: entry.originalChars,\n truncatedChars: entry.truncatedChars,\n });\n }\n }\n\n // Stage 4: Normalize for API validity\n messagesForApi = normalizeMessagesForAPI(messagesForApi);\n\n if (config.debug) {\n assertValidMessageSequence(messagesForApi);\n }\n\n return {\n messagesForApi,\n canonicalMessages: canonical,\n state: {\n contentReplacementState,\n budgetState,\n microcompactTokensFreed,\n },\n events,\n };\n}\n","import type { AIProvider, ChatCompletionUsage } from \"../providers/types.js\";\nimport type { ChatMessage, StreamEvent } from \"../session/types.js\";\nimport type { HookDefinition } from \"../hooks/types.js\";\nimport type {\n AutoCompactConfig,\n AutoCompactTrackingState,\n} from \"../compact/auto-compact.js\";\nimport {\n shouldAutoCompact,\n canAutoCompact,\n recordAutoCompactSuccess,\n recordAutoCompactFailure,\n} from \"../compact/auto-compact.js\";\nimport { compactConversation } from \"../compact/compact.js\";\nimport { runNotificationHooks } from \"../hooks/runner.js\";\nimport { SessionStorage } from \"../session/storage.js\";\n\nexport interface AutoCompactStepResult {\n compacted: boolean;\n messages?: ChatMessage[];\n events: StreamEvent[];\n}\n\n/**\n * Checks whether the conversation exceeds the auto-compact threshold and,\n * if so, runs compaction. Returns the result so the caller can decide\n * whether to `continue` the loop or proceed to the provider call.\n *\n * Hook notifications (PreCompact, PostCompact, Error) are fired internally.\n * The tracking state is mutated in place (success/failure counters).\n */\nexport async function tryAutoCompactStep(\n messages: ChatMessage[],\n config: AutoCompactConfig,\n provider: AIProvider,\n model: string,\n state: {\n lastUsage: ChatCompletionUsage | undefined;\n anchorMessageIndex: number | undefined;\n microcompactTokensFreed: number;\n querySource: string | undefined;\n autoCompactTracking: AutoCompactTrackingState;\n recentlyReadFiles?: Map<string, string>;\n signal?: AbortSignal;\n },\n hooks: HookDefinition[],\n sessionId: string,\n storage: SessionStorage,\n): Promise<AutoCompactStepResult> {\n if (\n !canAutoCompact(state.autoCompactTracking) ||\n !shouldAutoCompact(\n messages,\n config,\n state.lastUsage,\n state.anchorMessageIndex,\n state.microcompactTokensFreed,\n state.querySource,\n )\n ) {\n return { compacted: false, events: [] };\n }\n\n const events: StreamEvent[] = [];\n\n await runNotificationHooks(hooks, \"PreCompact\", {\n event: \"PreCompact\",\n sessionId,\n });\n events.push({ type: \"compact_start\" });\n\n try {\n const compactedMessages = await compactConversation(\n provider,\n model,\n messages,\n storage,\n sessionId,\n {\n tailMessagesToKeep: config.tailMessagesToKeep,\n stripBinaryContent: true,\n signal: state.signal,\n recentlyReadFiles:\n state.recentlyReadFiles && state.recentlyReadFiles.size > 0\n ? state.recentlyReadFiles\n : undefined,\n },\n );\n\n recordAutoCompactSuccess(state.autoCompactTracking);\n events.push({ type: \"compact_complete\" });\n\n await runNotificationHooks(hooks, \"PostCompact\", {\n event: \"PostCompact\",\n sessionId,\n });\n\n return { compacted: true, messages: compactedMessages, events };\n } catch (compactErr) {\n recordAutoCompactFailure(state.autoCompactTracking);\n\n const error =\n compactErr instanceof Error\n ? compactErr\n : new Error(`Compaction failed: ${String(compactErr)}`);\n\n await runNotificationHooks(hooks, \"Error\", {\n event: \"Error\",\n sessionId,\n error,\n });\n\n events.push({ type: \"auto_compact_failed\", error });\n return { compacted: false, events };\n }\n}\n","interface QueuedGenerator<A> {\n done: boolean | undefined;\n value: A;\n generator: AsyncGenerator<A, void>;\n promise: Promise<QueuedGenerator<A>>;\n}\n\n/**\n * Run multiple async generators concurrently up to a concurrency cap,\n * yielding values as they become available. Generators beyond the cap\n * are started as earlier ones finish.\n */\nexport async function* all<A>(\n generators: AsyncGenerator<A, void>[],\n concurrencyCap = Infinity,\n): AsyncGenerator<A, void> {\n const next = (generator: AsyncGenerator<A, void>) => {\n const promise: Promise<QueuedGenerator<A>> = generator\n .next()\n .then(({ done, value }) => ({\n done,\n value: value as A,\n generator,\n promise,\n }));\n return promise;\n };\n\n const waiting = [...generators];\n const promises = new Set<Promise<QueuedGenerator<A>>>();\n\n while (promises.size < concurrencyCap && waiting.length > 0) {\n const gen = waiting.shift()!;\n promises.add(next(gen));\n }\n\n while (promises.size > 0) {\n const { done, value, generator, promise } = await Promise.race(promises);\n promises.delete(promise);\n\n if (!done) {\n promises.add(next(generator));\n if (value !== undefined) {\n yield value;\n }\n } else if (waiting.length > 0) {\n const nextGen = waiting.shift()!;\n promises.add(next(nextGen));\n }\n }\n}\n","import type { Tool, ToolResult, ToolContext } from \"./types.js\";\nimport type { ToolCallContent, StreamEvent } from \"../session/types.js\";\nimport { resolveToolFlag } from \"./registry.js\";\nimport { all } from \"../utils/generators.js\";\n\nconst DEFAULT_CONCURRENCY_CAP = 10;\n\nexport interface ToolCallExecResult {\n toolCall: ToolCallContent;\n parsedArgs: Record<string, unknown>;\n result: ToolResult;\n /** When true, the result came from a permission denial — not actual tool execution */\n permissionDenied?: boolean;\n /** When true, the turn loop should stop after processing this batch */\n preventContinuation?: boolean;\n /** Permission and lifecycle events emitted during execution */\n events?: StreamEvent[];\n /**\n * Optional context modifier to apply after a concurrent batch completes.\n * Applied in original tool_call order (not completion order) so state\n * transitions are deterministic.\n */\n contextModifier?: () => void | Promise<void>;\n}\n\nexport type ToolCallExecutor = (\n toolCall: ToolCallContent,\n parsedArgs: Record<string, unknown>,\n) => Promise<ToolCallExecResult>;\n\ninterface Batch {\n isConcurrencySafe: boolean;\n items: Array<{ toolCall: ToolCallContent; parsedArgs: Record<string, unknown> }>;\n}\n\n/**\n * Partition tool calls into batches: consecutive concurrency-safe tools\n * are grouped together; each non-safe tool gets its own batch.\n */\nexport function partitionToolCalls(\n toolCalls: ToolCallContent[],\n getTool: (name: string) => Tool | undefined,\n): Batch[] {\n return toolCalls.reduce<Batch[]>((batches, tc) => {\n let parsedArgs: Record<string, unknown> = {};\n let jsonMalformed = false;\n try {\n parsedArgs = JSON.parse(tc.function.arguments);\n } catch {\n jsonMalformed = true;\n }\n\n const tool = getTool(tc.function.name);\n let isConcurrencySafe = false;\n if (!jsonMalformed && tool) {\n try {\n isConcurrencySafe = resolveToolFlag(tool.isConcurrencySafe, parsedArgs);\n } catch {\n isConcurrencySafe = false;\n }\n }\n\n const item = { toolCall: tc, parsedArgs };\n\n if (\n isConcurrencySafe &&\n batches.length > 0 &&\n batches[batches.length - 1].isConcurrencySafe\n ) {\n batches[batches.length - 1].items.push(item);\n } else {\n batches.push({ isConcurrencySafe, items: [item] });\n }\n return batches;\n }, []);\n}\n\n/**\n * Execute tool calls with optimal concurrency: safe tools run in parallel,\n * unsafe tools run one at a time.\n */\nexport async function* runToolsBatched(\n toolCalls: ToolCallContent[],\n getTool: (name: string) => Tool | undefined,\n executor: ToolCallExecutor,\n concurrencyCap = DEFAULT_CONCURRENCY_CAP,\n): AsyncGenerator<ToolCallExecResult, void> {\n const batches = partitionToolCalls(toolCalls, getTool);\n\n for (const batch of batches) {\n if (batch.isConcurrencySafe && batch.items.length > 1) {\n // Collect all results from the concurrent batch, then yield them.\n // This lets us apply context modifiers in tool_call order after\n // all concurrent executions complete.\n const results: ToolCallExecResult[] = [];\n const generators = batch.items.map(({ toolCall, parsedArgs }) =>\n (async function* () {\n try {\n yield await executor(toolCall, parsedArgs);\n } catch (err) {\n yield {\n toolCall,\n parsedArgs,\n result: {\n content: `Error: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n },\n } satisfies ToolCallExecResult;\n }\n })(),\n );\n for await (const result of all(generators, concurrencyCap)) {\n results.push(result);\n }\n\n // Sort by original tool_call order for deterministic context updates\n const orderMap = new Map(\n batch.items.map(({ toolCall }, i) => [toolCall.id, i]),\n );\n results.sort(\n (a, b) =>\n (orderMap.get(a.toolCall.id) ?? 0) - (orderMap.get(b.toolCall.id) ?? 0),\n );\n\n for (const result of results) {\n yield result;\n }\n\n // Apply context modifiers in tool_call order after the batch\n for (const result of results) {\n if (result.contextModifier) {\n await result.contextModifier();\n }\n }\n } else {\n for (const { toolCall, parsedArgs } of batch.items) {\n try {\n const result = await executor(toolCall, parsedArgs);\n yield result;\n if (result.contextModifier) {\n await result.contextModifier();\n }\n } catch (err) {\n yield {\n toolCall,\n parsedArgs,\n result: {\n content: `Error: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n },\n } satisfies ToolCallExecResult;\n }\n }\n }\n }\n}\n","import type { ChatMessage, ToolCallContent, StreamEvent } from \"../session/types.js\";\nimport type { ToolResult } from \"../tools/types.js\";\nimport type { ContentReplacementRecord } from \"../compact/tool-result-storage.js\";\nimport type { StreamingToolExecutor, StreamingExecResult } from \"../tools/streaming-executor.js\";\nimport type { ToolCallExecResult } from \"../tools/orchestration.js\";\nimport { runToolsBatched } from \"../tools/orchestration.js\";\nimport { executeToolCall, type ToolExecutionContext } from \"../tools/execution-pipeline.js\";\nimport type { SessionStorage } from \"../session/storage.js\";\nimport type { ToolRegistry } from \"../tools/registry.js\";\n\nconst FILE_TOOLS = new Set([\"ReadFile\", \"WriteFile\", \"EditFile\"]);\n\nexport type SpillFn = (\n id: string,\n name: string,\n content: string,\n) => Promise<{ content: string; spilled: boolean }>;\n\nexport interface ExecuteToolsResult {\n events: StreamEvent[];\n touchedFilePaths: string[];\n preventContinuation: boolean;\n spilledRecords: ContentReplacementRecord[];\n}\n\n// ---------------------------------------------------------------------------\n// Shared per-result processing\n// ---------------------------------------------------------------------------\n\ninterface ProcessableResult {\n toolCall: ToolCallContent;\n parsedArgs: Record<string, unknown>;\n result: ToolResult;\n permissionDenied?: boolean;\n preventContinuation?: boolean;\n events?: StreamEvent[];\n}\n\nasync function processToolResult(\n execResult: ProcessableResult,\n spillFn: SpillFn,\n messages: ChatMessage[],\n recentlyReadFiles: Map<string, string>,\n storage: SessionStorage,\n sessionId: string,\n): Promise<{\n events: StreamEvent[];\n touchedPath?: string;\n spillRecord?: ContentReplacementRecord;\n preventContinuation: boolean;\n}> {\n const events: StreamEvent[] = [];\n\n for (const evt of execResult.events ?? []) {\n events.push(evt);\n }\n\n if (!execResult.permissionDenied) {\n events.push({\n type: \"tool_result\",\n toolUseId: execResult.toolCall.id,\n toolName: execResult.toolCall.function.name,\n result: execResult.result,\n } as StreamEvent);\n\n const gitOps = execResult.result.metadata?.gitOperations as\n | Array<{ type: string; details: string }>\n | undefined;\n if (gitOps) {\n for (const op of gitOps) {\n events.push({\n type: \"git_operation\" as const,\n operation: op.type as \"commit\" | \"push\" | \"pr_create\" | \"merge\" | \"rebase\",\n details: op.details,\n } as StreamEvent);\n }\n }\n }\n\n let resultContent = execResult.result.content;\n let spillRecord: ContentReplacementRecord | undefined;\n if (typeof resultContent === \"string\") {\n const spill = await spillFn(\n execResult.toolCall.id,\n execResult.toolCall.function.name,\n resultContent,\n );\n if (spill.spilled) {\n resultContent = spill.content;\n spillRecord = { toolUseId: execResult.toolCall.id, replacement: spill.content };\n }\n }\n\n const toolResultMsg: ChatMessage = {\n role: \"tool\",\n tool_call_id: execResult.toolCall.id,\n content: resultContent,\n ...(execResult.result.isError ? { isError: true } : {}),\n };\n messages.push(toolResultMsg);\n await storage.appendMessage(sessionId, toolResultMsg);\n\n let touchedPath: string | undefined;\n if (\n FILE_TOOLS.has(execResult.toolCall.function.name) &&\n typeof execResult.parsedArgs.file_path === \"string\"\n ) {\n touchedPath = execResult.parsedArgs.file_path;\n if (execResult.toolCall.function.name === \"ReadFile\" && !execResult.result.isError) {\n const content =\n typeof execResult.result.content === \"string\" ? execResult.result.content : \"\";\n recentlyReadFiles.set(execResult.parsedArgs.file_path, content);\n }\n }\n\n return {\n events,\n touchedPath,\n spillRecord,\n preventContinuation: !!execResult.preventContinuation,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Main entry point\n// ---------------------------------------------------------------------------\n\nexport async function executeToolsStep(\n toolCalls: ToolCallContent[],\n streamingExec: StreamingToolExecutor | null,\n streamingResults: StreamingExecResult[],\n execCtx: ToolExecutionContext,\n registry: ToolRegistry,\n sessionId: string,\n messages: ChatMessage[],\n recentlyReadFiles: Map<string, string>,\n storage: SessionStorage,\n spillFn: SpillFn,\n): Promise<ExecuteToolsResult> {\n const allEvents: StreamEvent[] = [];\n const touchedFilePaths: string[] = [];\n const spilledRecords: ContentReplacementRecord[] = [];\n let preventContinuation = false;\n\n const handleResult = async (execResult: ProcessableResult) => {\n const processed = await processToolResult(\n execResult,\n spillFn,\n messages,\n recentlyReadFiles,\n storage,\n sessionId,\n );\n allEvents.push(...processed.events);\n if (processed.touchedPath) touchedFilePaths.push(processed.touchedPath);\n if (processed.spillRecord) spilledRecords.push(processed.spillRecord);\n if (processed.preventContinuation) preventContinuation = true;\n };\n\n if (streamingExec) {\n const allResults = [...streamingResults];\n for await (const result of streamingExec.getRemainingResults()) {\n allResults.push(result);\n }\n for (const execResult of allResults) {\n await handleResult(execResult);\n }\n } else {\n const executor = async (\n tc: ToolCallContent,\n parsedArgs: Record<string, unknown>,\n ): Promise<ToolCallExecResult> => {\n const pipelineResult = await executeToolCall(tc, parsedArgs, execCtx);\n if (pipelineResult.preventContinuation) preventContinuation = true;\n return pipelineResult;\n };\n\n for await (const execResult of runToolsBatched(\n toolCalls,\n (name) => registry.get(name),\n executor,\n )) {\n await handleResult(execResult);\n }\n }\n\n return { events: allEvents, touchedFilePaths, preventContinuation, spilledRecords };\n}\n","import type { FileState, FileStateCacheConfig } from \"./types.js\";\nimport { normalize } from \"node:path\";\n\nconst DEFAULT_MAX_ENTRIES = 100;\nconst DEFAULT_MAX_BYTES = 25 * 1024 * 1024; // 25 MB\n\n/**\n * LRU cache tracking which files the model has read and at what mtime.\n *\n * Used by ReadFile to record reads and by EditFile/WriteFile to enforce\n * \"read-before-edit\" — the model cannot edit a file it hasn't seen,\n * preventing hallucinated edits on unseen content.\n */\nexport class FileStateCache {\n private entries: Map<string, FileState> = new Map();\n private maxEntries: number;\n private maxBytes: number;\n private currentBytes = 0;\n\n constructor(config?: FileStateCacheConfig) {\n this.maxEntries = config?.maxEntries ?? DEFAULT_MAX_ENTRIES;\n this.maxBytes = config?.maxBytes ?? DEFAULT_MAX_BYTES;\n }\n\n private key(path: string): string {\n return normalize(path);\n }\n\n private byteSize(state: FileState): number {\n return Math.max(1, Buffer.byteLength(state.content, \"utf8\"));\n }\n\n set(path: string, state: FileState): void {\n const k = this.key(path);\n const existing = this.entries.get(k);\n if (existing) {\n this.currentBytes -= this.byteSize(existing);\n this.entries.delete(k);\n }\n\n const size = this.byteSize(state);\n\n // Evict LRU entries until we're under both caps.\n // Map iteration order = insertion order, so first entries are oldest.\n while (\n (this.entries.size >= this.maxEntries || this.currentBytes + size > this.maxBytes) &&\n this.entries.size > 0\n ) {\n const oldest = this.entries.keys().next().value!;\n const oldState = this.entries.get(oldest)!;\n this.currentBytes -= this.byteSize(oldState);\n this.entries.delete(oldest);\n }\n\n this.entries.set(k, state);\n this.currentBytes += size;\n }\n\n get(path: string): FileState | undefined {\n const k = this.key(path);\n const state = this.entries.get(k);\n if (!state) return undefined;\n\n // Touch: move to end of insertion order (most recently used)\n this.entries.delete(k);\n this.entries.set(k, state);\n return state;\n }\n\n has(path: string): boolean {\n return this.entries.has(this.key(path));\n }\n\n delete(path: string): void {\n const k = this.key(path);\n const existing = this.entries.get(k);\n if (existing) {\n this.currentBytes -= this.byteSize(existing);\n this.entries.delete(k);\n }\n }\n\n get size(): number {\n return this.entries.size;\n }\n\n get totalBytes(): number {\n return this.currentBytes;\n }\n\n clear(): void {\n this.entries.clear();\n this.currentBytes = 0;\n }\n}\n","import type { SkillDefinition } from \"./types.js\";\n\n/**\n * Check which skills should be activated based on file paths the agent touched.\n * Skills with `globs` are conditional -- they only activate when a matching file is touched.\n * Skills without `globs` are always active.\n *\n * Returns the names of newly-activated conditional skills.\n */\nexport function activateSkillsForPaths(\n allSkills: SkillDefinition[],\n filePaths: string[],\n cwd: string,\n alreadyActivated: Set<string>,\n): string[] {\n const activated: string[] = [];\n\n for (const skill of allSkills) {\n if (!skill.globs || skill.globs.length === 0) continue;\n if (alreadyActivated.has(skill.name)) continue;\n\n for (const filePath of filePaths) {\n const relative = filePath.startsWith(cwd)\n ? filePath.slice(cwd.endsWith(\"/\") ? cwd.length : cwd.length + 1)\n : filePath;\n\n if (matchesAnyGlob(relative, skill.globs)) {\n alreadyActivated.add(skill.name);\n activated.push(skill.name);\n break;\n }\n }\n }\n\n return activated;\n}\n\n/**\n * Get all currently active skills: unconditional ones + activated conditional ones.\n */\nexport function getActiveSkills(\n allSkills: SkillDefinition[],\n activatedNames: Set<string>,\n): SkillDefinition[] {\n return allSkills.filter((skill) => {\n if (!skill.globs || skill.globs.length === 0) return true;\n return activatedNames.has(skill.name);\n });\n}\n\n/**\n * Simple glob matching. Supports *, **, and ? wildcards.\n * This is intentionally minimal -- covers the common SKILL.md patterns like\n * \"*.ts\", \"src/**\", \"**\\/*.test.ts\" without pulling in a dependency.\n */\nfunction matchesAnyGlob(path: string, patterns: string[]): boolean {\n return patterns.some((pattern) => globMatch(pattern, path));\n}\n\nfunction globMatch(pattern: string, str: string): boolean {\n const regex = globToRegex(pattern);\n return regex.test(str);\n}\n\nfunction globToRegex(glob: string): RegExp {\n let result = \"\";\n let i = 0;\n\n while (i < glob.length) {\n const ch = glob[i];\n\n if (ch === \"*\") {\n if (glob[i + 1] === \"*\") {\n // ** matches any path segment(s)\n if (glob[i + 2] === \"/\") {\n result += \"(?:.*/)?\";\n i += 3;\n } else {\n result += \".*\";\n i += 2;\n }\n } else {\n // * matches anything except /\n result += \"[^/]*\";\n i++;\n }\n } else if (ch === \"?\") {\n result += \"[^/]\";\n i++;\n } else if (ch === \"{\") {\n // Brace expansion: {a,b,c}\n const close = glob.indexOf(\"}\", i);\n if (close !== -1) {\n const alternatives = glob.slice(i + 1, close).split(\",\");\n result += `(?:${alternatives.map(escapeRegex).join(\"|\")})`;\n i = close + 1;\n } else {\n result += escapeRegex(ch);\n i++;\n }\n } else {\n result += escapeRegex(ch);\n i++;\n }\n }\n\n return new RegExp(`^${result}$`);\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import type { Tool, ToolResult, ToolContext } from \"./types.js\";\nimport type { SkillDefinition } from \"../skills/types.js\";\n\n/**\n * Create a Skill tool that lets the model invoke skills by name.\n * Skill content is expanded inline with $ARGUMENTS substitution.\n */\nexport function createSkillTool(\n getSkills: () => SkillDefinition[],\n): Tool {\n return {\n name: \"Skill\",\n description:\n \"Invoke a skill by name with optional arguments. \" +\n \"Available skills are listed in the system prompt. \" +\n \"The skill's instructions will be expanded and returned for you to follow.\",\n parameters: {\n type: \"object\",\n properties: {\n skill_name: {\n type: \"string\",\n description: \"The name of the skill to invoke\",\n },\n arguments: {\n type: \"string\",\n description: \"Arguments to pass to the skill (replaces $ARGUMENTS in skill content)\",\n },\n },\n required: [\"skill_name\"],\n },\n async call(\n args: Record<string, unknown>,\n _ctx: ToolContext,\n ): Promise<ToolResult> {\n const skillName = args.skill_name as string;\n const skillArgs = (args.arguments as string) ?? \"\";\n const skills = getSkills();\n\n const skill = skills.find(\n (s) => s.name.toLowerCase() === skillName.toLowerCase(),\n );\n\n if (!skill) {\n const available = skills.map((s) => s.name).join(\", \");\n return {\n content: `Unknown skill: \"${skillName}\". Available skills: ${available || \"none\"}`,\n isError: true,\n };\n }\n\n let content = skill.content;\n content = content.replace(/\\$ARGUMENTS/g, skillArgs);\n\n const header = `# Skill: ${skill.name}`;\n const desc = skill.description ? `\\n${skill.description}\\n` : \"\";\n\n return {\n content: `${header}${desc}\\n${content}`,\n };\n },\n };\n}\n","export interface DenialLimits {\n maxConsecutive: number;\n maxTotal: number;\n}\n\nexport interface DenialState {\n consecutiveDenials: number;\n totalDenials: number;\n}\n\nexport type FallbackCheck =\n | { triggered: false }\n | { triggered: true; reason: \"consecutive\" | \"total\" | \"repeated_consecutive\" };\n\nconst DEFAULT_LIMITS: DenialLimits = {\n maxConsecutive: 3,\n maxTotal: 20,\n};\n\n/**\n * Tracks permission denials and determines when limits are exceeded.\n * When limits are hit, the system should fall back to prompting or abort.\n */\nexport class DenialTracker {\n private state: DenialState = { consecutiveDenials: 0, totalDenials: 0 };\n private limits: DenialLimits;\n private consecutiveFallbacksWithoutSuccess = 0;\n\n constructor(limits?: Partial<DenialLimits>) {\n this.limits = { ...DEFAULT_LIMITS, ...limits };\n }\n\n recordDenial(): void {\n this.state.consecutiveDenials++;\n this.state.totalDenials++;\n }\n\n recordSuccess(): void {\n this.state.consecutiveDenials = 0;\n this.consecutiveFallbacksWithoutSuccess = 0;\n }\n\n shouldFallback(): FallbackCheck {\n if (this.state.totalDenials >= this.limits.maxTotal) {\n return { triggered: true, reason: \"total\" };\n }\n if (this.state.consecutiveDenials >= this.limits.maxConsecutive) {\n return {\n triggered: true,\n reason: this.consecutiveFallbacksWithoutSuccess > 0\n ? \"repeated_consecutive\"\n : \"consecutive\",\n };\n }\n return { triggered: false };\n }\n\n /**\n * Reset counters after a fallback. Only resets totalDenials when the\n * total limit was the trigger — consecutive-only fallbacks preserve\n * the total counter so the session-wide safety net stays effective.\n *\n * Tracks repeated consecutive fallbacks: if `resetAfterFallback(\"consecutive\")`\n * is called again without an intervening `recordSuccess()`, the next\n * `shouldFallback()` returns `\"repeated_consecutive\"` to signal escalation.\n */\n resetAfterFallback(trigger: \"consecutive\" | \"total\"): void {\n this.state.consecutiveDenials = 0;\n if (trigger === \"consecutive\") {\n this.consecutiveFallbacksWithoutSuccess++;\n }\n if (trigger === \"total\") {\n this.state.totalDenials = 0;\n this.consecutiveFallbacksWithoutSuccess = 0;\n }\n }\n\n getState(): Readonly<DenialState> {\n return { ...this.state };\n }\n\n reset(): void {\n this.state.consecutiveDenials = 0;\n this.state.totalDenials = 0;\n this.consecutiveFallbacksWithoutSuccess = 0;\n }\n}\n","import type { Tool, ToolResult, ToolContext } from \"./types.js\";\nimport type { JsonSchemaOutputFormat } from \"../providers/types.js\";\n\nconst STRUCTURED_OUTPUT_TOOL_NAME = \"StructuredOutput\";\n\n/**\n * Creates a synthetic tool whose input schema matches the user's desired\n * output schema. When the model calls this tool, the agent loop treats it\n * as the final structured response and terminates.\n *\n * This is the \"final_response\" pattern: the model reasons freely (using\n * tools), and signals completion by calling StructuredOutput with data\n * that conforms to the schema.\n */\nexport function createStructuredOutputTool(\n format: JsonSchemaOutputFormat,\n): Tool {\n return {\n name: STRUCTURED_OUTPUT_TOOL_NAME,\n description:\n \"Return your final structured answer. Call this tool ONCE when you \" +\n \"have gathered all necessary information and are ready to respond. \" +\n \"The input MUST conform to the required JSON schema.\",\n prompt: \"\",\n isReadOnly: true,\n isConcurrencySafe: true,\n parameters: {\n type: \"object\",\n properties: {\n data: {\n type: \"object\",\n description: \"The structured response data conforming to the schema.\",\n },\n },\n required: [\"data\"],\n },\n\n async call(\n args: Record<string, unknown>,\n _ctx: ToolContext,\n ): Promise<ToolResult> {\n return {\n content: JSON.stringify(args.data ?? args, null, 2),\n };\n },\n };\n}\n\nexport { STRUCTURED_OUTPUT_TOOL_NAME };\n","import type { ChatMessage, ContentPart, StreamEvent } from \"../session/types.js\";\nimport type { HookDefinition } from \"../hooks/types.js\";\nimport type { FileCheckpointManager } from \"../checkpoint/manager.js\";\nimport type { CostTracker } from \"../cost/tracker.js\";\nimport type {\n ToolResultStorageConfig,\n ContentReplacementState,\n} from \"../compact/tool-result-storage.js\";\nimport {\n reconstructContentReplacementState,\n applyPersistedReplacements,\n enforceToolResultStorageBudget,\n} from \"../compact/tool-result-storage.js\";\nimport type { VirtualFs } from \"../virtual/fs.js\";\nimport { restoreSession } from \"../session/resume.js\";\nimport { runNotificationHooks } from \"../hooks/runner.js\";\nimport { SessionStorage } from \"../session/storage.js\";\nimport { generateUUID } from \"../utils/uuid.js\";\n\nexport interface InitializeSessionParams {\n storage: SessionStorage;\n sessionId: string;\n hooks: HookDefinition[];\n prompt: string | ContentPart[];\n resumeRequested: boolean;\n loaded: boolean;\n messages: ChatMessage[];\n contentReplacementState: ContentReplacementState;\n isResumeRun: boolean;\n checkpointManager?: FileCheckpointManager;\n costTracker?: CostTracker;\n toolResultStorage?: ToolResultStorageConfig;\n fs: VirtualFs;\n}\n\nexport interface InitializeSessionResult {\n messages: ChatMessage[];\n contentReplacementState: ContentReplacementState;\n events: StreamEvent[];\n loaded: boolean;\n resumeRequested: boolean;\n turnMessageId: string;\n}\n\nexport async function initializeSession(\n params: InitializeSessionParams,\n): Promise<InitializeSessionResult> {\n const {\n storage,\n sessionId,\n hooks,\n prompt,\n isResumeRun,\n checkpointManager,\n costTracker,\n toolResultStorage,\n fs,\n } = params;\n\n let { messages, contentReplacementState, loaded, resumeRequested } = params;\n const events: StreamEvent[] = [];\n\n if (!loaded) {\n if (resumeRequested) {\n const payload = await restoreSession(storage, sessionId);\n messages = payload.messages;\n\n if (checkpointManager && payload.checkpointSnapshots.length > 0) {\n checkpointManager.restoreStateFromEntries(payload.checkpointSnapshots);\n }\n\n if (costTracker && payload.costState) {\n costTracker.restore(payload.costState);\n }\n\n if (payload.contentReplacements.length > 0) {\n contentReplacementState = reconstructContentReplacementState(\n payload.contentReplacements,\n messages,\n );\n messages = applyPersistedReplacements(\n messages,\n contentReplacementState,\n );\n }\n\n if (toolResultStorage?.enabled && fs) {\n const storageResult = await enforceToolResultStorageBudget(\n messages,\n toolResultStorage,\n fs,\n sessionId,\n contentReplacementState,\n );\n messages = storageResult.messages;\n contentReplacementState = storageResult.state;\n }\n\n for (const [filterName, count] of Object.entries(payload.recoveryRemovals)) {\n if (count > 0) {\n events.push({ type: \"recovery_filtered\", filterName, removedCount: count });\n }\n }\n\n if (payload.interruption.kind !== \"none\") {\n events.push({\n type: \"interrupted_turn_detected\",\n kind: payload.interruption.kind,\n });\n }\n\n resumeRequested = false;\n events.push({ type: \"session_resumed\", sessionId, messageCount: messages.length });\n } else {\n messages = await storage.loadMessages(sessionId);\n }\n loaded = true;\n }\n\n const userMessage: ChatMessage = { role: \"user\", content: prompt };\n messages.push(userMessage);\n await storage.appendMessage(sessionId, userMessage);\n\n const turnMessageId = generateUUID();\n\n if (checkpointManager) {\n await checkpointManager.makeSnapshot(turnMessageId, sessionId);\n await storage.appendCheckpointEntry(\n sessionId,\n turnMessageId,\n checkpointManager.getState().snapshots.at(-1)!,\n false,\n );\n events.push({ type: \"checkpoint_snapshot\", messageId: turnMessageId });\n }\n\n await runNotificationHooks(hooks, \"SessionStart\", {\n event: \"SessionStart\",\n sessionId,\n prompt,\n isResume: isResumeRun,\n } as import(\"../hooks/types.js\").SessionStartHookInput);\n\n return {\n messages,\n contentReplacementState,\n events,\n loaded,\n resumeRequested,\n turnMessageId,\n };\n}\n","import type { ToolResult } from \"./types.js\";\nimport type { ToolCallContent, StreamEvent } from \"../session/types.js\";\nimport { resolveToolFlag } from \"./registry.js\";\nimport type { Tool } from \"./types.js\";\n\ntype ToolStatus = \"queued\" | \"executing\" | \"completed\" | \"yielded\";\n\ninterface TrackedTool {\n id: string;\n toolCall: ToolCallContent;\n parsedArgs: Record<string, unknown>;\n status: ToolStatus;\n isConcurrencySafe: boolean;\n result?: ToolResult;\n permissionDenied?: boolean;\n preventContinuation?: boolean;\n promise?: Promise<void>;\n events: StreamEvent[];\n abortController?: AbortController;\n}\n\nexport interface StreamingExecResult {\n toolCall: ToolCallContent;\n parsedArgs: Record<string, unknown>;\n result: ToolResult;\n permissionDenied?: boolean;\n preventContinuation?: boolean;\n events: StreamEvent[];\n}\n\nexport type StreamingToolExecutorFn = (\n toolCall: ToolCallContent,\n parsedArgs: Record<string, unknown>,\n signal?: AbortSignal,\n) => Promise<{\n result: ToolResult;\n permissionDenied?: boolean;\n preventContinuation?: boolean;\n events: StreamEvent[];\n}>;\n\nconst BASH_TOOL_NAME = \"Bash\";\n\n/**\n * Executes tools as they arrive during model streaming.\n * Concurrency-safe tools run in parallel; unsafe tools wait for all prior\n * executions to finish before starting.\n *\n * Supports abort propagation: a parent signal aborts all tools, and a\n * Bash tool error aborts sibling tools via siblingAbortController.\n */\nexport class StreamingToolExecutor {\n private tools: TrackedTool[] = [];\n private progressResolve?: () => void;\n private discarded = false;\n private siblingAbortController: AbortController;\n private hasErrored = false;\n private processingQueue = false;\n\n constructor(\n private readonly getTool: (name: string) => Tool | undefined,\n private readonly executeFn: StreamingToolExecutorFn,\n private readonly parentSignal?: AbortSignal,\n ) {\n this.siblingAbortController = new AbortController();\n if (parentSignal) {\n if (parentSignal.aborted) {\n this.siblingAbortController.abort(parentSignal.reason);\n } else {\n parentSignal.addEventListener(\"abort\", () => {\n this.siblingAbortController.abort(parentSignal.reason);\n }, { once: true });\n }\n }\n }\n\n discard(): void {\n this.discarded = true;\n this.siblingAbortController.abort(\"discarded\");\n this.progressResolve?.();\n }\n\n isDiscarded(): boolean {\n return this.discarded;\n }\n\n addTool(toolCall: ToolCallContent, parsedArgs: Record<string, unknown>): void {\n if (this.discarded) {\n this.tools.push({\n id: toolCall.id,\n toolCall,\n parsedArgs,\n status: \"completed\",\n isConcurrencySafe: true,\n result: { content: \"Error: Executor was discarded\", isError: true },\n events: [],\n });\n return;\n }\n\n const toolDef = this.getTool(toolCall.function.name);\n\n if (!toolDef) {\n this.tools.push({\n id: toolCall.id,\n toolCall,\n parsedArgs,\n status: \"completed\",\n isConcurrencySafe: true,\n result: { content: `Error: Unknown tool \"${toolCall.function.name}\"`, isError: true },\n events: [],\n });\n this.progressResolve?.();\n return;\n }\n\n let isConcurrencySafe = false;\n try {\n isConcurrencySafe = resolveToolFlag(toolDef.isConcurrencySafe, parsedArgs);\n } catch {\n isConcurrencySafe = false;\n }\n\n this.tools.push({\n id: toolCall.id,\n toolCall,\n parsedArgs,\n status: \"queued\",\n isConcurrencySafe,\n events: [],\n });\n\n void this.processQueue();\n }\n\n private canExecute(isConcurrencySafe: boolean): boolean {\n const executing = this.tools.filter((t) => t.status === \"executing\");\n return (\n executing.length === 0 ||\n (isConcurrencySafe && executing.every((t) => t.isConcurrencySafe))\n );\n }\n\n private async processQueue(): Promise<void> {\n if (this.discarded || this.processingQueue) return;\n this.processingQueue = true;\n try {\n for (const tool of this.tools) {\n if (tool.status !== \"queued\") continue;\n\n if (this.canExecute(tool.isConcurrencySafe)) {\n await this.executeTool(tool);\n } else if (!tool.isConcurrencySafe) {\n break;\n }\n }\n } finally {\n this.processingQueue = false;\n }\n }\n\n private createToolAbortController(): AbortController {\n const toolAc = new AbortController();\n this.siblingAbortController.signal.addEventListener(\"abort\", () => {\n if (!toolAc.signal.aborted) {\n toolAc.abort(this.siblingAbortController.signal.reason);\n }\n }, { once: true });\n if (this.siblingAbortController.signal.aborted) {\n toolAc.abort(this.siblingAbortController.signal.reason);\n }\n return toolAc;\n }\n\n private async executeTool(tracked: TrackedTool): Promise<void> {\n if (this.discarded || this.siblingAbortController.signal.aborted) {\n tracked.status = \"completed\";\n tracked.result = { content: \"Error: Executor was discarded\", isError: true };\n tracked.events = [];\n this.progressResolve?.();\n return;\n }\n\n tracked.status = \"executing\";\n const toolAc = this.createToolAbortController();\n tracked.abortController = toolAc;\n\n tracked.promise = (async () => {\n try {\n const { result, permissionDenied, preventContinuation, events } = await this.executeFn(\n tracked.toolCall,\n tracked.parsedArgs,\n toolAc.signal,\n );\n tracked.result = result;\n tracked.permissionDenied = permissionDenied;\n tracked.preventContinuation = preventContinuation;\n tracked.events = events;\n\n if (result.isError && tracked.toolCall.function.name === BASH_TOOL_NAME) {\n this.hasErrored = true;\n this.siblingAbortController.abort(\"sibling_error\");\n }\n } catch (err) {\n tracked.result = {\n content: `Error: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n };\n tracked.events = [];\n if (tracked.toolCall.function.name === BASH_TOOL_NAME) {\n this.hasErrored = true;\n this.siblingAbortController.abort(\"sibling_error\");\n }\n }\n tracked.status = \"completed\";\n this.progressResolve?.();\n })();\n\n void tracked.promise.finally(() => void this.processQueue());\n }\n\n *getCompletedResults(): Generator<StreamingExecResult, void> {\n if (this.discarded) return;\n\n for (const tool of this.tools) {\n if (tool.status === \"yielded\") continue;\n\n if (tool.status === \"completed\" && tool.result) {\n tool.status = \"yielded\";\n yield {\n toolCall: tool.toolCall,\n parsedArgs: tool.parsedArgs,\n result: tool.result,\n permissionDenied: tool.permissionDenied,\n preventContinuation: tool.preventContinuation,\n events: tool.events,\n };\n } else if (tool.status === \"executing\" && !tool.isConcurrencySafe) {\n break;\n }\n }\n }\n\n async *getRemainingResults(): AsyncGenerator<StreamingExecResult, void> {\n if (this.discarded) {\n for (const tool of this.tools) {\n if (tool.status === \"yielded\") continue;\n if (tool.status === \"completed\" && tool.result) {\n tool.status = \"yielded\";\n yield {\n toolCall: tool.toolCall,\n parsedArgs: tool.parsedArgs,\n result: tool.result,\n permissionDenied: tool.permissionDenied,\n preventContinuation: tool.preventContinuation,\n events: tool.events,\n };\n continue;\n }\n tool.status = \"yielded\";\n yield {\n toolCall: tool.toolCall,\n parsedArgs: tool.parsedArgs,\n result: { content: \"Error: Executor was discarded\", isError: true },\n events: [],\n };\n }\n return;\n }\n\n while (this.hasUnfinished()) {\n if (this.discarded) return;\n\n await this.processQueue();\n\n for (const result of this.getCompletedResults()) {\n yield result;\n }\n\n if (this.hasExecuting() && !this.hasCompleted()) {\n const executingPromises = this.tools\n .filter((t) => t.status === \"executing\" && t.promise)\n .map((t) => t.promise!);\n\n const progressPromise = new Promise<void>((resolve) => {\n this.progressResolve = resolve;\n });\n\n if (executingPromises.length > 0) {\n await Promise.race([...executingPromises, progressPromise]);\n }\n }\n }\n\n for (const result of this.getCompletedResults()) {\n yield result;\n }\n }\n\n private hasUnfinished(): boolean {\n return this.tools.some(\n (t) => t.status === \"queued\" || t.status === \"executing\",\n );\n }\n\n private hasExecuting(): boolean {\n return this.tools.some((t) => t.status === \"executing\");\n }\n\n private hasCompleted(): boolean {\n return this.tools.some(\n (t) => t.status === \"completed\" && t.result !== undefined,\n );\n }\n}\n","const DEFAULT_BASE_DELAY_MS = 500;\n\n/**\n * Compute retry delay with exponential backoff and jitter.\n * If a Retry-After header value is provided (seconds), it takes precedence.\n * Ported from claude-code's getRetryDelay with the same formula.\n */\nexport function getRetryDelay(\n attempt: number,\n retryAfterHeader?: string | null,\n maxDelayMs: number = 32000,\n baseDelayMs: number = DEFAULT_BASE_DELAY_MS,\n): number {\n if (retryAfterHeader) {\n const seconds = parseInt(retryAfterHeader, 10);\n if (!isNaN(seconds)) {\n return seconds * 1000;\n }\n }\n\n const baseDelay = Math.min(\n baseDelayMs * Math.pow(2, attempt - 1),\n maxDelayMs,\n );\n const jitter = Math.random() * 0.25 * baseDelay;\n return baseDelay + jitter;\n}\n\n/**\n * Sleep that respects an AbortSignal.\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n return;\n }\n\n const onAbort = () => {\n clearTimeout(timer);\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n };\n\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n","import { ChatStreamError, type ChatStreamChunk } from \"../providers/types.js\";\nimport type { StreamEvent } from \"../session/types.js\";\nimport type { RetryEngineOptions, RetryContext } from \"./types.js\";\nimport { classifyError, isRetryable } from \"./classify.js\";\nimport { getRetryDelay, sleep } from \"./backoff.js\";\n\nconst FLOOR_OUTPUT_TOKENS = 3000;\n\nexport class CannotRetryError extends Error {\n constructor(\n public readonly originalError: unknown,\n public readonly retryContext: RetryContext,\n ) {\n super(originalError instanceof Error ? originalError.message : String(originalError));\n this.name = \"CannotRetryError\";\n }\n}\n\n/**\n * Retry engine that wraps a stream-creating operation.\n * Yields retry_attempt events while waiting, then returns the stream on success.\n *\n * The operation receives a RetryContext that may include a maxTokensOverride\n * (after context overflow) or a different model (after fallback).\n */\nexport async function* withRetry(\n operation: (ctx: RetryContext) => AsyncIterable<ChatStreamChunk>,\n options: RetryEngineOptions,\n): AsyncGenerator<StreamEvent, AsyncIterable<ChatStreamChunk>> {\n const maxRetries = options.maxRetries ?? 10;\n const baseDelayMs = options.baseDelayMs ?? 500;\n const maxDelayMs = options.maxDelayMs ?? 32000;\n const maxConsecutiveOverloaded = options.maxConsecutiveOverloaded ?? 3;\n\n const retryContext: RetryContext = {\n attempt: 0,\n model: options.model,\n };\n\n let consecutiveOverloaded = 0;\n let fallbackUsed = false;\n let lastError: unknown;\n let totalAttempts = 0;\n\n for (let attempt = 1; attempt <= maxRetries + 1; attempt++) {\n if (options.signal?.aborted) {\n throw new DOMException(\"Aborted\", \"AbortError\");\n }\n\n totalAttempts++;\n retryContext.attempt = totalAttempts;\n\n try {\n const stream = operation(retryContext);\n\n // Try to get the first chunk to detect immediate errors.\n // If the stream itself throws, we catch it in the retry loop.\n const iterator = toAsyncIterator(stream);\n const first = await iterator.next();\n\n if (first.done) {\n throw new ChatStreamError(\"Provider returned empty stream\", {\n status: 502,\n cause: new Error(\"empty_stream\"),\n });\n }\n\n return prependChunk(first.value, iterator);\n } catch (error) {\n lastError = error;\n\n const classified = classifyError(error);\n\n // Context overflow: adjust max_tokens and retry\n if (classified.isContextOverflow && classified.contextOverflowData) {\n const { inputTokens, contextLimit } = classified.contextOverflowData;\n const safetyBuffer = 1000;\n const available = Math.max(0, contextLimit - inputTokens - safetyBuffer);\n\n if (available < FLOOR_OUTPUT_TOKENS) {\n throw new CannotRetryError(error, retryContext);\n }\n\n const minRequired = (options.thinkingBudget ?? 0) + 1;\n retryContext.maxTokensOverride = Math.max(\n FLOOR_OUTPUT_TOKENS,\n available,\n minRequired,\n );\n\n continue;\n }\n\n // Track consecutive overloaded for fallback\n if (classified.isOverloaded) {\n consecutiveOverloaded++;\n if (\n consecutiveOverloaded >= maxConsecutiveOverloaded &&\n options.fallbackModel &&\n !fallbackUsed\n ) {\n const previousModel = retryContext.model;\n retryContext.model = options.fallbackModel;\n consecutiveOverloaded = 0;\n fallbackUsed = true;\n\n yield {\n type: \"model_switch\",\n from: previousModel,\n to: options.fallbackModel,\n };\n\n yield {\n type: \"retry_attempt\",\n attempt: totalAttempts,\n maxRetries,\n delayMs: 0,\n error: new Error(\n `Model fallback: ${previousModel} → ${options.fallbackModel} after ${maxConsecutiveOverloaded} consecutive overloaded errors`,\n ),\n };\n\n // Reset backoff counter for the fallback model but totalAttempts\n // keeps growing to enforce the global budget.\n attempt = Math.max(attempt - Math.floor(maxRetries / 2), 1);\n continue;\n }\n } else {\n consecutiveOverloaded = 0;\n }\n\n if (!isRetryable(classified, options)) {\n throw new CannotRetryError(error, retryContext);\n }\n\n if (totalAttempts > maxRetries) {\n const exhaustedError = error instanceof Error ? error : new Error(String(error));\n yield {\n type: \"retry_exhausted\",\n attempts: totalAttempts,\n error: exhaustedError,\n };\n throw new CannotRetryError(error, retryContext);\n }\n\n const delayMs = getRetryDelay(\n attempt,\n classified.retryAfter,\n maxDelayMs,\n baseDelayMs,\n );\n\n const retryError = error instanceof Error ? error : new Error(String(error));\n\n options.onRetry?.(totalAttempts, retryError, delayMs);\n\n yield {\n type: \"retry_attempt\",\n attempt: totalAttempts,\n maxRetries,\n delayMs,\n error: retryError,\n };\n\n await sleep(delayMs, options.signal);\n }\n }\n\n throw new CannotRetryError(lastError, retryContext);\n}\n\nfunction toAsyncIterator<T>(\n iterable: AsyncIterable<T>,\n): AsyncIterator<T> {\n return iterable[Symbol.asyncIterator]();\n}\n\nasync function* prependChunk(\n first: ChatStreamChunk,\n rest: AsyncIterator<ChatStreamChunk>,\n): AsyncIterable<ChatStreamChunk> {\n yield first;\n let next = await rest.next();\n while (!next.done) {\n yield next.value;\n next = await rest.next();\n }\n}\n","import type { ChatStreamChunk, ChatCompletionUsage } from \"../providers/types.js\";\nimport { ChatStreamError } from \"../providers/types.js\";\nimport type { StreamEvent, ChatMessage, AssistantMessage } from \"../session/types.js\";\nimport type { StreamingToolExecutor, StreamingExecResult } from \"../tools/streaming-executor.js\";\n\nconst DEFAULT_STREAM_IDLE_TIMEOUT_MS = 120_000;\n\n// ---------------------------------------------------------------------------\n// StreamAccumulator — mutable state populated by consumeStream\n// ---------------------------------------------------------------------------\n\nexport interface ToolCallEntry {\n id: string;\n name: string;\n arguments: string;\n complete: boolean;\n malformedJson?: boolean;\n startEmitted?: boolean;\n}\n\nexport interface StreamAccumulator {\n content: string[];\n thinking: string[];\n thinkingSignature: string | undefined;\n redactedThinkingData: string | undefined;\n toolCalls: Map<number, ToolCallEntry>;\n finishReason: string | null;\n usage: ChatCompletionUsage | undefined;\n}\n\nexport function createAccumulator(): StreamAccumulator {\n return {\n content: [],\n thinking: [],\n thinkingSignature: undefined,\n redactedThinkingData: undefined,\n toolCalls: new Map(),\n finishReason: null,\n usage: undefined,\n };\n}\n\nexport function resetAccumulator(acc: StreamAccumulator): void {\n acc.content.length = 0;\n acc.thinking.length = 0;\n acc.thinkingSignature = undefined;\n acc.redactedThinkingData = undefined;\n acc.toolCalls.clear();\n acc.finishReason = null;\n acc.usage = undefined;\n}\n\n// ---------------------------------------------------------------------------\n// consumeStream — iterate provider chunks, populate accumulator, yield events\n// ---------------------------------------------------------------------------\n\nexport async function* consumeStream(\n stream: AsyncIterable<ChatStreamChunk>,\n acc: StreamAccumulator,\n streamingExec: StreamingToolExecutor | null,\n streamingResults: StreamingExecResult[],\n signal: AbortSignal,\n idleTimeoutMs?: number,\n): AsyncGenerator<StreamEvent> {\n const timeout = idleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;\n let idleTimer: ReturnType<typeof setTimeout> | undefined;\n let idleReject: ((err: Error) => void) | undefined;\n\n function resetIdleTimer(): void {\n if (idleTimer !== undefined) clearTimeout(idleTimer);\n if (timeout <= 0) return;\n idleTimer = setTimeout(() => {\n idleReject?.(\n new ChatStreamError(\n `Stream idle timeout — no chunks received for ${timeout}ms`,\n { cause: new Error(\"idle_timeout\") },\n ),\n );\n }, timeout);\n }\n\n function clearIdleTimer(): void {\n if (idleTimer !== undefined) {\n clearTimeout(idleTimer);\n idleTimer = undefined;\n }\n }\n\n const idlePromise = new Promise<never>((_, reject) => { idleReject = reject; });\n\n try {\n resetIdleTimer();\n\n const iterator = (stream as AsyncIterable<ChatStreamChunk>)[Symbol.asyncIterator]();\n // eslint-disable-next-line no-constant-condition\n while (true) {\n if (signal.aborted) break;\n const result = await Promise.race([iterator.next(), idlePromise]);\n if (result.done) break;\n const chunk = result.value;\n resetIdleTimer();\n\n if (chunk.usage) {\n acc.usage = chunk.usage;\n }\n\n for (const choice of chunk.choices) {\n if (choice.finish_reason) {\n acc.finishReason = choice.finish_reason;\n }\n\n const delta = choice.delta;\n\n if (delta.thinking_content) {\n acc.thinking.push(delta.thinking_content);\n yield { type: \"thinking_delta\", text: delta.thinking_content } as StreamEvent;\n }\n\n if (delta.thinking_signature) {\n acc.thinkingSignature = (acc.thinkingSignature ?? \"\") + delta.thinking_signature;\n }\n\n if (delta.redacted_thinking_data) {\n acc.redactedThinkingData = (acc.redactedThinkingData ?? \"\") + delta.redacted_thinking_data;\n }\n\n if (delta.content) {\n acc.content.push(delta.content);\n yield { type: \"text_delta\", text: delta.content } as StreamEvent;\n }\n\n if (delta.tool_calls) {\n for (const tc of delta.tool_calls) {\n const existing = acc.toolCalls.get(tc.index);\n\n if (!existing) {\n const id = tc.id ?? \"\";\n const name = tc.function?.name ?? \"\";\n const startEmitted = !!(tc.id && tc.function?.name);\n acc.toolCalls.set(tc.index, {\n id,\n name,\n arguments: tc.function?.arguments ?? \"\",\n complete: false,\n startEmitted,\n });\n\n if (startEmitted) {\n yield { type: \"tool_use_start\", toolName: name, toolUseId: id } as StreamEvent;\n }\n\n if (streamingExec && tc.index > 0) {\n for (const [idx, prev] of acc.toolCalls) {\n if (idx >= tc.index) continue;\n if (prev.complete) continue;\n prev.complete = true;\n try {\n const parsedArgs = JSON.parse(prev.arguments);\n streamingExec.addTool(\n { id: prev.id, type: \"function\", function: { name: prev.name, arguments: prev.arguments } },\n parsedArgs,\n );\n } catch {\n prev.malformedJson = true;\n }\n }\n }\n } else {\n if (tc.id) existing.id = tc.id;\n if (tc.function?.name) existing.name = tc.function.name;\n if (!existing.startEmitted && existing.id && existing.name) {\n existing.startEmitted = true;\n yield { type: \"tool_use_start\", toolName: existing.name, toolUseId: existing.id } as StreamEvent;\n }\n if (tc.function?.arguments) {\n existing.arguments += tc.function.arguments;\n yield { type: \"tool_use_delta\", input: tc.function.arguments } as StreamEvent;\n }\n }\n }\n }\n }\n\n if (streamingExec) {\n for (const result of streamingExec.getCompletedResults()) {\n streamingResults.push(result);\n }\n }\n }\n } finally {\n clearIdleTimer();\n }\n}\n\n// ---------------------------------------------------------------------------\n// handleFinishReason — process finish_reason, return control-flow signals\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_MAX_TOKENS = 8192;\nconst ESCALATED_MAX_TOKENS = 65536;\nconst MAX_OUTPUT_RECOVERY_ATTEMPTS = 3;\n\nexport interface FinishReasonResult {\n events: StreamEvent[];\n messagesToPersist: ChatMessage[];\n preventContinuation: boolean;\n shouldContinue: boolean;\n escalateMaxTokens?: number;\n}\n\nexport function handleFinishReason(\n acc: StreamAccumulator,\n streamingExec: StreamingToolExecutor | null,\n streamingResults: StreamingExecResult[],\n currentMaxTokens: number | undefined,\n outputTokenRecoveryAttempts: number,\n signal: AbortSignal,\n): FinishReasonResult {\n const events: StreamEvent[] = [];\n const messagesToPersist: ChatMessage[] = [];\n let preventContinuation = false;\n let shouldContinue = false;\n let escalateMaxTokens: number | undefined;\n\n if (acc.finishReason === \"length\" && acc.toolCalls.size === 0) {\n const canEscalate =\n (currentMaxTokens === undefined || currentMaxTokens === DEFAULT_MAX_TOKENS) &&\n outputTokenRecoveryAttempts === 0;\n\n if (canEscalate || outputTokenRecoveryAttempts < MAX_OUTPUT_RECOVERY_ATTEMPTS) {\n if (canEscalate) {\n escalateMaxTokens = ESCALATED_MAX_TOKENS;\n }\n shouldContinue = true;\n const partialContent = acc.content.join(\"\");\n if (partialContent) {\n messagesToPersist.push({\n role: \"assistant\",\n content: partialContent,\n } as AssistantMessage);\n messagesToPersist.push({\n role: \"user\",\n content: \"Continue from where you left off — no apology, no recap.\",\n } as ChatMessage);\n }\n } else {\n events.push({ type: \"text_delta\", text: \"\\n\\n[Response truncated due to max output tokens]\" } as StreamEvent);\n }\n }\n\n if (acc.finishReason === \"content_filter\") {\n events.push({ type: \"text_delta\", text: \"\\n\\n[Response blocked by content filter]\" } as StreamEvent);\n if (streamingExec) {\n for (const result of streamingExec.getCompletedResults()) {\n streamingResults.push(result);\n }\n streamingExec.discard();\n preventContinuation = true;\n } else {\n acc.toolCalls.clear();\n }\n }\n\n if (streamingExec && !signal.aborted && !shouldContinue) {\n for (const [, tc] of acc.toolCalls) {\n if (!tc.complete) {\n tc.complete = true;\n try {\n const parsedArgs = JSON.parse(tc.arguments);\n streamingExec.addTool(\n { id: tc.id, type: \"function\", function: { name: tc.name, arguments: tc.arguments } },\n parsedArgs,\n );\n } catch {\n tc.malformedJson = true;\n }\n }\n }\n }\n\n return {\n events,\n messagesToPersist,\n preventContinuation,\n shouldContinue,\n ...(escalateMaxTokens !== undefined ? { escalateMaxTokens } : {}),\n };\n}\n","import type {\n ChatMessage,\n AssistantMessage,\n ToolCallContent,\n StreamEvent,\n} from \"../session/types.js\";\nimport type { ChatCompletionUsage } from \"../providers/types.js\";\nimport type { StreamAccumulator } from \"./consume-stream.js\";\n\n// ---------------------------------------------------------------------------\n// separateToolCalls\n// ---------------------------------------------------------------------------\n\nexport interface SeparatedToolCalls {\n valid: ToolCallContent[];\n malformed: Array<{ id: string; name: string }>;\n}\n\nexport function separateToolCalls(\n acc: StreamAccumulator,\n isStreaming: boolean,\n): SeparatedToolCalls {\n const valid: ToolCallContent[] = [];\n const malformed: Array<{ id: string; name: string }> = [];\n\n for (const tc of acc.toolCalls.values()) {\n let isMalformed = tc.malformedJson;\n if (!isMalformed && !isStreaming) {\n try { JSON.parse(tc.arguments); } catch { isMalformed = true; }\n }\n if (isMalformed) {\n malformed.push({ id: tc.id, name: tc.name });\n } else {\n valid.push({\n id: tc.id,\n type: \"function\" as const,\n function: { name: tc.name, arguments: tc.arguments },\n });\n }\n }\n\n return { valid, malformed };\n}\n\n// ---------------------------------------------------------------------------\n// buildAssistantMessage\n// ---------------------------------------------------------------------------\n\nexport interface BuildAssistantMessageParams {\n acc: StreamAccumulator;\n validToolCalls: ToolCallContent[];\n malformedToolCalls: Array<{ id: string; name: string }>;\n turnId: string;\n}\n\nexport function buildAssistantMessage(\n params: BuildAssistantMessageParams,\n): AssistantMessage {\n const { acc, validToolCalls, malformedToolCalls, turnId } = params;\n\n const allToolCalls: ToolCallContent[] = [\n ...validToolCalls,\n ...malformedToolCalls.map((m) => ({\n id: m.id,\n type: \"function\" as const,\n function: { name: m.name, arguments: \"{}\" },\n })),\n ];\n\n const textContent = acc.content.join(\"\");\n const thinkingContent = acc.thinking.join(\"\") || undefined;\n\n return {\n role: \"assistant\",\n content: textContent || null,\n ...(allToolCalls.length > 0 ? { tool_calls: allToolCalls } : {}),\n ...(thinkingContent ? { thinking_content: thinkingContent } : {}),\n ...(acc.thinkingSignature ? { thinking_signature: acc.thinkingSignature } : {}),\n ...(acc.redactedThinkingData ? { redacted_thinking_data: acc.redactedThinkingData } : {}),\n _turnId: turnId,\n };\n}\n\n// ---------------------------------------------------------------------------\n// generateMalformedToolResults\n// ---------------------------------------------------------------------------\n\nexport interface MalformedToolResultsOutput {\n messages: ChatMessage[];\n events: StreamEvent[];\n}\n\nexport function generateMalformedToolResults(\n malformed: Array<{ id: string; name: string }>,\n): MalformedToolResultsOutput {\n const messages: ChatMessage[] = [];\n const events: StreamEvent[] = [];\n\n for (const m of malformed) {\n const errorResult: ChatMessage = {\n role: \"tool\",\n tool_call_id: m.id,\n content: `Error: Invalid tool call arguments for ${m.name} (malformed JSON)`,\n isError: true,\n };\n messages.push(errorResult);\n events.push({\n type: \"tool_result\",\n toolUseId: m.id,\n toolName: m.name,\n result: { content: errorResult.content as string, isError: true },\n } as StreamEvent);\n }\n\n return { messages, events };\n}\n\n// ---------------------------------------------------------------------------\n// accumulateUsage\n// ---------------------------------------------------------------------------\n\nexport interface AccumulateUsageParams {\n usage: ChatCompletionUsage | undefined;\n turnUsage: ChatCompletionUsage;\n model: string;\n messagesLength: number;\n}\n\nexport interface AccumulateUsageResult {\n events: StreamEvent[];\n lastUsage: ChatCompletionUsage | undefined;\n anchorMessageIndex: number | undefined;\n resetMicrocompactTokensFreed: boolean;\n}\n\nexport function accumulateUsage(\n params: AccumulateUsageParams,\n): AccumulateUsageResult {\n const { usage, turnUsage, model, messagesLength } = params;\n const events: StreamEvent[] = [];\n\n if (!usage) {\n return {\n events,\n lastUsage: undefined,\n anchorMessageIndex: undefined,\n resetMicrocompactTokensFreed: false,\n };\n }\n\n turnUsage.prompt_tokens += usage.prompt_tokens;\n turnUsage.completion_tokens += usage.completion_tokens;\n turnUsage.total_tokens += usage.total_tokens;\n turnUsage.cache_read_tokens = (turnUsage.cache_read_tokens ?? 0) + (usage.cache_read_tokens ?? 0);\n turnUsage.cache_creation_tokens = (turnUsage.cache_creation_tokens ?? 0) + (usage.cache_creation_tokens ?? 0);\n turnUsage.thinking_tokens = (turnUsage.thinking_tokens ?? 0) + (usage.thinking_tokens ?? 0);\n\n events.push({ type: \"usage\", usage, model } as StreamEvent);\n\n return {\n events,\n lastUsage: usage,\n anchorMessageIndex: messagesLength - 1,\n resetMicrocompactTokensFreed: true,\n };\n}\n","import type {\n ChatMessage,\n AssistantMessage,\n ToolCallContent,\n StreamEvent,\n} from \"../session/types.js\";\nimport type { AIProvider } from \"../providers/types.js\";\nimport type { StreamingExecResult } from \"../tools/streaming-executor.js\";\nimport type { HookDefinition } from \"../hooks/types.js\";\nimport { generateMissingToolResults } from \"../session/recovery.js\";\nimport { runNotificationHooks } from \"../hooks/runner.js\";\nimport { tryReactiveCompact } from \"../compact/reactive-compact.js\";\nimport type { SessionStorage } from \"../session/storage.js\";\n\n// ---------------------------------------------------------------------------\n// buildPartialResults — pure function, no side effects\n// ---------------------------------------------------------------------------\n\nexport interface PartialResultsInput {\n accumulatedToolCalls: Map<number, { id: string; name: string; arguments: string }>;\n accumulatedContent: string[];\n completedStreamingResults: StreamingExecResult[];\n reason: string;\n /**\n * When the provider error catch fires with zero accumulated tool calls,\n * the existing message history may contain an assistant with pending\n * tool_calls. Pass the current messages array so we can generate\n * synthetic results for those too.\n */\n existingMessages?: ChatMessage[];\n /**\n * When false, omit the \"[Response interrupted: ...]\" suffix from the\n * assistant content. Useful for the abort path where getRemainingResults()\n * already provides both real and synthetic tool results.\n */\n includeInterruptionTag?: boolean;\n}\n\nexport interface PartialResultsOutput {\n messages: ChatMessage[];\n}\n\nexport function buildPartialResults(input: PartialResultsInput): PartialResultsOutput {\n const { accumulatedToolCalls, accumulatedContent, completedStreamingResults, reason } = input;\n const includeTag = input.includeInterruptionTag !== false;\n const messages: ChatMessage[] = [];\n\n if (accumulatedToolCalls.size > 0 || accumulatedContent.length > 0) {\n const partialCalls: ToolCallContent[] = Array.from(accumulatedToolCalls.values()).map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: { name: tc.name, arguments: tc.arguments },\n }));\n\n const partialText = accumulatedContent.join(\"\");\n\n let content: string | null;\n if (partialCalls.length > 0 && includeTag) {\n content = partialText\n ? `${partialText}\\n[Response interrupted: ${reason}]`\n : `[Response interrupted: ${reason}]`;\n } else {\n content = partialText || null;\n }\n\n const partialAssistant: AssistantMessage = {\n role: \"assistant\",\n content,\n ...(partialCalls.length > 0 ? { tool_calls: partialCalls } : {}),\n };\n messages.push(partialAssistant);\n\n if (partialCalls.length > 0) {\n const realToolMsgs: ChatMessage[] = [];\n for (const completed of completedStreamingResults) {\n const toolResultMsg: ChatMessage = {\n role: \"tool\",\n tool_call_id: completed.toolCall.id,\n content: completed.result.content,\n ...(completed.result.isError ? { isError: true } : {}),\n };\n messages.push(toolResultMsg);\n realToolMsgs.push(toolResultMsg);\n }\n\n const syntheticResults = generateMissingToolResults(partialAssistant, realToolMsgs, reason);\n for (const sr of syntheticResults) {\n messages.push(sr);\n }\n }\n } else if (input.existingMessages) {\n const lastMsg = input.existingMessages[input.existingMessages.length - 1];\n if (lastMsg && lastMsg.role === \"assistant\" && (lastMsg as AssistantMessage).tool_calls) {\n const syntheticResults = generateMissingToolResults(\n lastMsg as AssistantMessage,\n input.existingMessages,\n reason,\n );\n for (const sr of syntheticResults) {\n messages.push(sr);\n }\n }\n }\n\n return { messages };\n}\n\n// ---------------------------------------------------------------------------\n// tryReactiveCompactRecovery\n// ---------------------------------------------------------------------------\n\nexport interface ReactiveCompactInput {\n provider: AIProvider;\n model: string;\n messages: ChatMessage[];\n storage: SessionStorage;\n sessionId: string;\n signal: AbortSignal;\n hooks: HookDefinition[];\n}\n\nexport interface ReactiveCompactOutput {\n recovered: boolean;\n messages?: ChatMessage[];\n events: StreamEvent[];\n}\n\nexport async function tryReactiveCompactRecovery(\n input: ReactiveCompactInput,\n): Promise<ReactiveCompactOutput> {\n const events: StreamEvent[] = [];\n\n await runNotificationHooks(input.hooks, \"PreCompact\", {\n event: \"PreCompact\",\n sessionId: input.sessionId,\n });\n events.push({ type: \"compact_start\" } as StreamEvent);\n\n const recovered = await tryReactiveCompact(\n input.provider,\n input.model,\n input.messages,\n input.storage,\n input.sessionId,\n { signal: input.signal },\n );\n\n events.push({ type: \"compact_complete\" } as StreamEvent);\n await runNotificationHooks(input.hooks, \"PostCompact\", {\n event: \"PostCompact\",\n sessionId: input.sessionId,\n });\n\n if (recovered) {\n return { recovered: true, messages: recovered.messages, events };\n }\n return { recovered: false, events };\n}\n","/**\n * Cache-safe parameters for subagent prompt cache sharing.\n *\n * When a subagent (fork) shares the same system prompt, model, tools, and\n * thinking config as its parent, both can share the same prompt cache\n * prefix. CacheSafeParams captures these values so the child thread can\n * inherit them and avoid cache breaks.\n */\n\nimport type { ToolDefinition } from \"./types.js\";\nimport type { ThinkingConfig } from \"../thinking/types.js\";\n\nexport interface CacheSafeParams {\n systemPrompt: string;\n model: string;\n tools: ToolDefinition[];\n thinking?: ThinkingConfig;\n}\n\nconst cacheSafeParamsMap = new Map<string, CacheSafeParams>();\n\nexport function saveCacheSafeParams(params: CacheSafeParams | null, sessionId = \"_default\"): void {\n if (params) {\n cacheSafeParamsMap.set(sessionId, params);\n } else {\n cacheSafeParamsMap.delete(sessionId);\n }\n}\n\nexport function getLastCacheSafeParams(sessionId = \"_default\"): CacheSafeParams | null {\n return cacheSafeParamsMap.get(sessionId) ?? null;\n}\n\nexport function createCacheSafeParams(opts: {\n systemPrompt: string;\n model: string;\n tools: ToolDefinition[];\n thinking?: ThinkingConfig;\n}): CacheSafeParams {\n return {\n systemPrompt: opts.systemPrompt,\n model: opts.model,\n tools: opts.tools,\n thinking: opts.thinking,\n };\n}\n","import type {\n AIProvider,\n ChatCompletionUsage,\n ChatStreamChunk,\n OutputFormat,\n ToolDefinition,\n} from \"../providers/types.js\";\nimport type {\n ChatMessage,\n AssistantMessage,\n ToolCallContent,\n StreamEvent,\n} from \"../session/types.js\";\nimport type { HookDefinition } from \"../hooks/types.js\";\nimport type { ThinkingConfig } from \"../thinking/types.js\";\nimport type { RetryConfig } from \"../retry/types.js\";\nimport type { CostTracker } from \"../cost/tracker.js\";\nimport type { Tracer, Span } from \"../tracing/types.js\";\nimport { SpanStatusCode } from \"../tracing/types.js\";\nimport type { ReactiveCompactConfig } from \"../compact/reactive-compact.js\";\nimport type { AutoCompactTrackingState } from \"../compact/auto-compact.js\";\nimport { recordAutoCompactSuccess } from \"../compact/auto-compact.js\";\nimport type { Tool } from \"../tools/types.js\";\nimport {\n StreamingToolExecutor,\n type StreamingExecResult,\n type StreamingToolExecutorFn,\n} from \"../tools/streaming-executor.js\";\nimport { SessionStorage } from \"../session/storage.js\";\nimport { runNotificationHooks } from \"../hooks/runner.js\";\nimport { withRetry, CannotRetryError } from \"../retry/engine.js\";\nimport { classifyError } from \"../retry/classify.js\";\nimport {\n createAccumulator,\n resetAccumulator,\n consumeStream,\n handleFinishReason,\n type StreamAccumulator,\n} from \"./consume-stream.js\";\nimport {\n separateToolCalls,\n buildAssistantMessage,\n generateMalformedToolResults,\n accumulateUsage,\n} from \"./build-assistant-response.js\";\nimport {\n buildPartialResults,\n tryReactiveCompactRecovery as tryReactiveCompactRecoveryFn,\n} from \"./error-recovery.js\";\nimport { sortToolDefinitionsForCache } from \"../providers/cache.js\";\nimport { saveCacheSafeParams, createCacheSafeParams } from \"../providers/cache-safe-params.js\";\nimport { generateUUID } from \"../utils/uuid.js\";\nimport {\n createBudgetState,\n type BudgetState,\n} from \"../compact/tool-result-budget.js\";\nimport { createContentReplacementState } from \"../compact/tool-result-storage.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ProviderRoundParams {\n messages: ChatMessage[];\n storage: SessionStorage;\n sessionId: string;\n provider: AIProvider;\n model: string;\n messagesForApi: ChatMessage[];\n systemPrompt: string;\n toolDefs: ToolDefinition[];\n maxTokens: number | undefined;\n thinking: ThinkingConfig | undefined;\n retryConfig: RetryConfig | undefined;\n promptCachingEnabled: boolean;\n skipCacheWrite: boolean | undefined;\n outputFormat: OutputFormat | undefined;\n isFinalResponseMode: boolean;\n useStreamingExec: boolean;\n signal: AbortSignal;\n tracer: Tracer;\n parentSpan: Span;\n hooks: HookDefinition[];\n toolRegistryLookup: (name: string) => Tool | undefined;\n buildStreamingExecutorFn: StreamingToolExecutorFn;\n reactiveCompact: ReactiveCompactConfig | undefined;\n hasAttemptedReactiveCompact: boolean;\n autoCompactTracking: AutoCompactTrackingState;\n mcpToolNames?: ReadonlySet<string>;\n costTracker?: CostTracker;\n turnUsage: ChatCompletionUsage;\n callCount: number;\n consecutiveMalformedIterations: number;\n preventContinuation: boolean;\n currentMaxTokens: number | undefined;\n outputTokenRecoveryAttempts: number;\n maxTurns: number | undefined;\n}\n\nexport interface ProviderRoundResult {\n shouldContinueOuterLoop: boolean;\n shouldBreakOuterLoop: boolean;\n accumulator: StreamAccumulator;\n assistantMsg: AssistantMessage | null;\n toolCalls: ToolCallContent[];\n malformedToolCalls: Array<{ id: string; name: string }>;\n streamingResults: StreamingExecResult[];\n streamingExec: StreamingToolExecutor | null;\n model: string;\n callCount: number;\n consecutiveMalformedIterations: number;\n preventContinuation: boolean;\n currentMaxTokens: number | undefined;\n outputTokenRecoveryAttempts: number;\n lastUsage: ChatCompletionUsage | undefined;\n anchorMessageIndex: number | undefined;\n microcompactTokensFreed: number;\n hasAttemptedReactiveCompact: boolean;\n /** When reactive compact recovered, the new messages to replace thread messages. */\n compactRecovered: boolean;\n recoveredMessages?: ChatMessage[];\n /** State resets triggered by compact recovery (budget, content replacement, etc). */\n compactStateReset: boolean;\n}\n\nconst MAX_CONSECUTIVE_MALFORMED = 5;\n\n// ---------------------------------------------------------------------------\n// Provider round — async generator\n// ---------------------------------------------------------------------------\n\nexport async function* executeProviderRound(\n p: ProviderRoundParams,\n): AsyncGenerator<StreamEvent, ProviderRoundResult> {\n let {\n model,\n callCount,\n consecutiveMalformedIterations,\n preventContinuation,\n currentMaxTokens,\n outputTokenRecoveryAttempts,\n hasAttemptedReactiveCompact,\n } = p;\n\n const {\n messages, storage, sessionId, provider, messagesForApi,\n systemPrompt, toolDefs, thinking, retryConfig, skipCacheWrite,\n promptCachingEnabled, outputFormat, isFinalResponseMode,\n useStreamingExec, signal, tracer, parentSpan, hooks,\n toolRegistryLookup, buildStreamingExecutorFn, reactiveCompact,\n autoCompactTracking, mcpToolNames, costTracker, turnUsage,\n maxTurns,\n } = p;\n\n let lastUsage: ChatCompletionUsage | undefined;\n let anchorMessageIndex: number | undefined;\n let microcompactTokensFreed = 0;\n\n const base = (): ProviderRoundResult => ({\n shouldContinueOuterLoop: false,\n shouldBreakOuterLoop: false,\n accumulator: createAccumulator(),\n assistantMsg: null,\n toolCalls: [],\n malformedToolCalls: [],\n streamingResults: [],\n streamingExec: null,\n model,\n callCount,\n consecutiveMalformedIterations,\n preventContinuation,\n currentMaxTokens,\n outputTokenRecoveryAttempts,\n lastUsage,\n anchorMessageIndex,\n microcompactTokensFreed,\n hasAttemptedReactiveCompact,\n compactRecovered: false,\n compactStateReset: false,\n });\n\n // --- TurnStart notification ---\n await runNotificationHooks(hooks, \"TurnStart\", {\n event: \"TurnStart\",\n sessionId,\n messages,\n });\n\n const accumulator = createAccumulator();\n\n let streamingExec: StreamingToolExecutor | null = null;\n const streamingResults: StreamingExecResult[] = [];\n\n if (useStreamingExec) {\n streamingExec = new StreamingToolExecutor(\n toolRegistryLookup,\n buildStreamingExecutorFn,\n signal,\n );\n }\n\n const sortedToolDefs = promptCachingEnabled\n ? sortToolDefinitionsForCache(toolDefs, mcpToolNames)\n : toolDefs;\n\n const chatParams = {\n model,\n messages: messagesForApi,\n tools: sortedToolDefs,\n system: systemPrompt,\n max_tokens: currentMaxTokens,\n thinking,\n skipCacheWrite,\n signal,\n ...(outputFormat && !isFinalResponseMode ? { outputFormat } : {}),\n };\n\n let stream: AsyncIterable<ChatStreamChunk>;\n\n const providerSpanId = generateUUID();\n const providerSpan = tracer.startSpan(\"noumen.provider.chat\", {\n parent: parentSpan,\n attributes: {\n \"model\": model,\n \"messages.count\": messages.length,\n \"tools.count\": toolDefs.length,\n },\n });\n yield { type: \"span_start\", name: \"noumen.provider.chat\", spanId: providerSpanId };\n const providerStart = Date.now();\n\n try {\n if (retryConfig) {\n const retryGen = withRetry(\n (ctx) => {\n const params = { ...chatParams };\n if (ctx.maxTokensOverride !== undefined) {\n params.max_tokens = ctx.maxTokensOverride;\n }\n if (ctx.model !== chatParams.model) {\n params.model = ctx.model;\n }\n return provider.chat(params);\n },\n {\n ...retryConfig,\n model,\n thinkingBudget:\n thinking?.type === \"enabled\"\n ? thinking.budgetTokens\n : undefined,\n signal,\n },\n );\n\n let retryResult = await retryGen.next();\n while (!retryResult.done) {\n const event = retryResult.value;\n if (event.type === \"model_switch\") {\n const sw = event as { type: \"model_switch\"; from: string; to: string };\n model = sw.to;\n stripThinkingSignatures(messages);\n resetAccumulator(accumulator);\n if (streamingExec) {\n streamingExec.discard();\n streamingExec = new StreamingToolExecutor(\n toolRegistryLookup,\n buildStreamingExecutorFn,\n signal,\n );\n }\n streamingResults.length = 0;\n if (hooks.length > 0) {\n await runNotificationHooks(hooks, \"ModelSwitch\", {\n event: \"ModelSwitch\",\n sessionId,\n previousModel: sw.from,\n newModel: sw.to,\n } as import(\"../hooks/types.js\").ModelSwitchHookInput);\n }\n }\n if (event.type === \"retry_attempt\" && hooks.length > 0) {\n const re = event as { attempt: number; maxRetries: number; delayMs: number; error: Error };\n await runNotificationHooks(hooks, \"RetryAttempt\", {\n event: \"RetryAttempt\",\n sessionId,\n attempt: re.attempt,\n maxAttempts: re.maxRetries,\n error: re.error.message,\n delay: re.delayMs,\n } as import(\"../hooks/types.js\").RetryAttemptHookInput);\n }\n yield event;\n retryResult = await retryGen.next();\n }\n\n stream = retryResult.value;\n } else {\n stream = provider.chat(chatParams);\n }\n } catch (providerErr) {\n const completedBeforeError: StreamingExecResult[] = [];\n if (streamingExec) {\n for (const result of streamingExec.getCompletedResults()) {\n completedBeforeError.push(result);\n }\n streamingExec.discard();\n }\n\n const isOverflow =\n (providerErr instanceof CannotRetryError &&\n classifyError(providerErr.originalError).isContextOverflow) ||\n (!retryConfig && classifyError(providerErr).isContextOverflow);\n\n if (\n isOverflow &&\n reactiveCompact?.enabled &&\n !hasAttemptedReactiveCompact\n ) {\n hasAttemptedReactiveCompact = true;\n providerSpan.setStatus(SpanStatusCode.ERROR, \"context overflow — reactive compact\");\n providerSpan.end();\n yield { type: \"span_end\", name: \"noumen.provider.chat\", spanId: providerSpanId, durationMs: Date.now() - providerStart, error: \"context overflow\" };\n\n const recovery = await tryReactiveCompactRecoveryFn({\n provider,\n model,\n messages,\n storage,\n sessionId,\n signal,\n hooks,\n });\n for (const evt of recovery.events) yield evt;\n if (recovery.recovered) {\n recordAutoCompactSuccess(autoCompactTracking);\n return {\n ...base(),\n shouldContinueOuterLoop: true,\n hasAttemptedReactiveCompact,\n compactRecovered: true,\n recoveredMessages: recovery.messages!,\n compactStateReset: true,\n streamingExec,\n accumulator,\n };\n }\n }\n\n const errorReason = `Provider error: ${providerErr instanceof Error ? providerErr.message : String(providerErr)}`;\n const partial = buildPartialResults({\n accumulatedToolCalls: accumulator.toolCalls,\n accumulatedContent: accumulator.content,\n completedStreamingResults: completedBeforeError,\n reason: errorReason,\n existingMessages: messages,\n });\n for (const msg of partial.messages) {\n messages.push(msg);\n await storage.appendMessage(sessionId, msg);\n }\n\n providerSpan.setStatus(SpanStatusCode.ERROR, providerErr instanceof Error ? providerErr.message : String(providerErr));\n providerSpan.end();\n yield { type: \"span_end\", name: \"noumen.provider.chat\", spanId: providerSpanId, durationMs: Date.now() - providerStart, error: String(providerErr) };\n\n throw providerErr;\n }\n\n const apiStartTime = Date.now();\n\n try {\n for await (const evt of consumeStream(stream, accumulator, streamingExec, streamingResults, signal)) {\n yield evt;\n }\n } catch (streamErr) {\n const streamCompletedResults: StreamingExecResult[] = [];\n if (streamingExec) {\n for (const result of streamingExec.getCompletedResults()) {\n streamCompletedResults.push(result);\n }\n streamingExec.discard();\n }\n const streamErrReason = `Stream error: ${streamErr instanceof Error ? streamErr.message : String(streamErr)}`;\n const partial = buildPartialResults({\n accumulatedToolCalls: accumulator.toolCalls,\n accumulatedContent: accumulator.content,\n completedStreamingResults: streamCompletedResults,\n reason: streamErrReason,\n });\n for (const msg of partial.messages) {\n messages.push(msg);\n await storage.appendMessage(sessionId, msg);\n }\n throw streamErr;\n }\n\n const apiDurationMs = Date.now() - apiStartTime;\n\n // Abort check\n if (signal.aborted) {\n providerSpan.setStatus(SpanStatusCode.OK);\n providerSpan.end();\n yield { type: \"span_end\", name: \"noumen.provider.chat\", spanId: providerSpanId, durationMs: Date.now() - providerStart };\n\n if (streamingExec) {\n streamingExec.discard();\n for await (const result of streamingExec.getRemainingResults()) {\n streamingResults.push(result);\n }\n }\n\n const abortPartial = buildPartialResults({\n accumulatedToolCalls: accumulator.toolCalls,\n accumulatedContent: accumulator.content,\n completedStreamingResults: streamingResults,\n reason: \"abort\",\n includeInterruptionTag: false,\n });\n for (const msg of abortPartial.messages) {\n messages.push(msg);\n await storage.appendMessage(sessionId, msg).catch((err) => {\n console.warn(\"[noumen/thread] Failed to persist abort message:\", err);\n });\n }\n\n const interruptionMsg: ChatMessage = {\n role: \"user\",\n content: \"[Session interrupted by user. Continue from where you left off if resumed.]\",\n };\n messages.push(interruptionMsg);\n await storage.appendMessage(sessionId, interruptionMsg).catch(() => {});\n\n return {\n ...base(),\n shouldBreakOuterLoop: true,\n accumulator,\n streamingResults,\n streamingExec,\n };\n }\n\n // Finish reason\n const frResult = handleFinishReason(\n accumulator, streamingExec, streamingResults,\n currentMaxTokens, outputTokenRecoveryAttempts, signal,\n );\n for (const evt of frResult.events) yield evt;\n for (const msg of frResult.messagesToPersist) {\n messages.push(msg);\n await storage.appendMessage(sessionId, msg).catch(() => {});\n }\n if (frResult.escalateMaxTokens !== undefined) currentMaxTokens = frResult.escalateMaxTokens;\n if (frResult.shouldContinue) {\n outputTokenRecoveryAttempts++;\n streamingExec?.discard();\n accumulator.toolCalls.clear();\n return {\n ...base(),\n shouldContinueOuterLoop: true,\n accumulator,\n currentMaxTokens,\n outputTokenRecoveryAttempts,\n streamingResults,\n streamingExec,\n };\n }\n if (frResult.preventContinuation) preventContinuation = true;\n\n // Usage accumulation\n callCount++;\n const usageResult = accumulateUsage({\n usage: accumulator.usage,\n turnUsage,\n model,\n messagesLength: messages.length,\n });\n for (const evt of usageResult.events) yield evt;\n if (usageResult.lastUsage) {\n lastUsage = usageResult.lastUsage;\n anchorMessageIndex = usageResult.anchorMessageIndex!;\n microcompactTokensFreed = 0;\n\n if (costTracker) {\n const summary = costTracker.addUsage(model, usageResult.lastUsage, apiDurationMs);\n yield { type: \"cost_update\", summary };\n\n await storage.appendMetadata(\n sessionId,\n \"costState\",\n costTracker.getState(),\n ).catch(() => {});\n }\n\n providerSpan.setAttribute(\"tokens.input\", usageResult.lastUsage.prompt_tokens);\n providerSpan.setAttribute(\"tokens.output\", usageResult.lastUsage.completion_tokens);\n }\n\n if (promptCachingEnabled) {\n saveCacheSafeParams(\n createCacheSafeParams({\n systemPrompt,\n model,\n tools: sortedToolDefs,\n thinking,\n }),\n sessionId,\n );\n }\n\n providerSpan.setStatus(SpanStatusCode.OK);\n providerSpan.end();\n yield { type: \"span_end\", name: \"noumen.provider.chat\", spanId: providerSpanId, durationMs: Date.now() - providerStart };\n\n // Build assistant message\n const { valid: toolCalls, malformed: malformedToolCalls } = separateToolCalls(accumulator, !!streamingExec);\n\n const assistantMsg = buildAssistantMessage({\n acc: accumulator,\n validToolCalls: toolCalls,\n malformedToolCalls,\n turnId: `${sessionId}:${callCount}`,\n });\n messages.push(assistantMsg);\n await storage.appendMessage(sessionId, assistantMsg);\n\n const malformedResult = generateMalformedToolResults(malformedToolCalls);\n for (const msg of malformedResult.messages) {\n messages.push(msg);\n await storage.appendMessage(sessionId, msg);\n }\n for (const evt of malformedResult.events) yield evt;\n\n // Malformed-only handling\n if (toolCalls.length === 0 && malformedToolCalls.length > 0) {\n consecutiveMalformedIterations++;\n if (consecutiveMalformedIterations >= MAX_CONSECUTIVE_MALFORMED) {\n yield { type: \"error\", error: new Error(`Exceeded ${MAX_CONSECUTIVE_MALFORMED} consecutive malformed tool call attempts`) };\n return {\n ...base(),\n shouldBreakOuterLoop: true,\n accumulator,\n assistantMsg,\n toolCalls,\n malformedToolCalls,\n streamingResults,\n streamingExec,\n callCount,\n consecutiveMalformedIterations,\n };\n }\n if (maxTurns !== undefined && callCount >= maxTurns) {\n await runNotificationHooks(hooks, \"TurnEnd\", { event: \"TurnEnd\", sessionId });\n yield { type: \"turn_complete\", usage: turnUsage, model, callCount };\n yield { type: \"max_turns_reached\", maxTurns, turnCount: callCount };\n return {\n ...base(),\n shouldBreakOuterLoop: true,\n accumulator,\n assistantMsg,\n toolCalls,\n malformedToolCalls,\n streamingResults,\n streamingExec,\n callCount,\n consecutiveMalformedIterations,\n };\n }\n await runNotificationHooks(hooks, \"TurnEnd\", { event: \"TurnEnd\", sessionId });\n return {\n ...base(),\n shouldContinueOuterLoop: true,\n accumulator,\n assistantMsg,\n toolCalls,\n malformedToolCalls,\n streamingResults,\n streamingExec,\n callCount,\n consecutiveMalformedIterations,\n };\n }\n\n // Normal result — caller decides what to do with tool calls\n return {\n ...base(),\n accumulator,\n assistantMsg,\n toolCalls,\n malformedToolCalls,\n streamingResults,\n streamingExec,\n callCount,\n consecutiveMalformedIterations,\n preventContinuation,\n lastUsage,\n anchorMessageIndex,\n microcompactTokensFreed,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nexport function stripThinkingSignatures(messages: ChatMessage[]): void {\n for (const msg of messages) {\n if (msg.role !== \"assistant\") continue;\n const asst = msg as AssistantMessage;\n if (asst.thinking_signature) delete asst.thinking_signature;\n if (asst.redacted_thinking_data) delete asst.redacted_thinking_data;\n }\n}\n","import type { ChatMessage, ToolCallContent, StreamEvent } from \"../session/types.js\";\nimport type { OutputFormat } from \"../providers/types.js\";\nimport type { HookDefinition } from \"../hooks/types.js\";\nimport type { SkillDefinition } from \"../skills/types.js\";\nimport type { ContextFile } from \"../context/types.js\";\nimport type { ChatCompletionUsage } from \"../providers/types.js\";\nimport { activateSkillsForPaths } from \"../skills/activation.js\";\nimport { activateContextForPaths } from \"../context/loader.js\";\nimport { runNotificationHooks } from \"../hooks/runner.js\";\nimport { STRUCTURED_OUTPUT_TOOL_NAME } from \"../tools/structured-output.js\";\nimport type { ContentReplacementRecord } from \"../session/types.js\";\nimport { SessionStorage } from \"../session/storage.js\";\n\nexport interface PostToolStepParams {\n touchedFilePaths: string[];\n toolCalls: ToolCallContent[];\n spilledRecords: ContentReplacementRecord[];\n signal: AbortSignal;\n sessionId: string;\n storage: SessionStorage;\n messages: ChatMessage[];\n hooks: HookDefinition[];\n allSkills: SkillDefinition[];\n activatedSkills: Set<string>;\n projectContext?: ContextFile[];\n activatedContextRules: Set<string>;\n cwd: string;\n isFinalResponseMode: boolean;\n outputFormat?: OutputFormat;\n maxTurns?: number;\n callCount: number;\n preventContinuation: boolean;\n turnUsage: ChatCompletionUsage;\n model: string;\n toolSearchEnabled: boolean;\n getActiveToolDefinitions: () => import(\"../providers/types.js\").ToolDefinition[];\n buildSystemPrompt: () => Promise<string>;\n}\n\nexport interface PostToolStepResult {\n events: StreamEvent[];\n preventContinuation: boolean;\n shouldBreak: boolean;\n shouldContinue: boolean;\n systemPrompt?: string;\n toolDefs?: import(\"../providers/types.js\").ToolDefinition[];\n hasAttemptedReactiveCompactReset: boolean;\n}\n\nexport async function postToolStep(\n params: PostToolStepParams,\n): Promise<PostToolStepResult> {\n const {\n touchedFilePaths,\n toolCalls,\n spilledRecords,\n signal,\n sessionId,\n storage,\n messages,\n hooks,\n allSkills,\n activatedSkills,\n projectContext,\n activatedContextRules,\n cwd,\n isFinalResponseMode,\n outputFormat,\n maxTurns,\n callCount,\n turnUsage,\n model,\n toolSearchEnabled,\n getActiveToolDefinitions,\n buildSystemPrompt,\n } = params;\n\n let { preventContinuation } = params;\n const events: StreamEvent[] = [];\n\n if (spilledRecords.length > 0) {\n await storage.appendContentReplacement(sessionId, spilledRecords);\n }\n\n if (signal.aborted) {\n const interruptionMsg: ChatMessage = {\n role: \"user\",\n content: \"[Session interrupted by user. Continue from where you left off if resumed.]\",\n };\n messages.push(interruptionMsg);\n await storage.appendMessage(sessionId, interruptionMsg).catch(() => {});\n return { events, preventContinuation, shouldBreak: true, shouldContinue: false, hasAttemptedReactiveCompactReset: false };\n }\n\n let systemPrompt: string | undefined;\n let toolDefs: import(\"../providers/types.js\").ToolDefinition[] | undefined;\n\n if (touchedFilePaths.length > 0) {\n let needsRebuild = false;\n\n if (allSkills.length > 0) {\n const newlyActivated = activateSkillsForPaths(\n allSkills,\n touchedFilePaths,\n cwd,\n activatedSkills,\n );\n if (newlyActivated.length > 0) needsRebuild = true;\n }\n\n if (projectContext?.length) {\n const newCtx = activateContextForPaths(\n projectContext,\n touchedFilePaths,\n cwd,\n activatedContextRules,\n );\n if (newCtx.length > 0) needsRebuild = true;\n }\n\n if (needsRebuild) {\n systemPrompt = await buildSystemPrompt();\n }\n }\n\n if (toolSearchEnabled) {\n toolDefs = getActiveToolDefinitions();\n }\n\n if (isFinalResponseMode) {\n for (const tc of toolCalls) {\n if (tc.function.name === STRUCTURED_OUTPUT_TOOL_NAME) {\n try {\n const parsed = JSON.parse(tc.function.arguments);\n events.push({\n type: \"structured_output\",\n data: parsed.data ?? parsed,\n schema: outputFormat!,\n });\n } catch {\n events.push({\n type: \"structured_output\",\n data: tc.function.arguments,\n schema: outputFormat!,\n });\n }\n preventContinuation = true;\n break;\n }\n }\n }\n\n if (preventContinuation) {\n await runNotificationHooks(hooks, \"TurnEnd\", { event: \"TurnEnd\", sessionId });\n events.push({\n type: \"turn_complete\",\n usage: turnUsage,\n model,\n callCount,\n });\n return { events, preventContinuation, shouldBreak: true, shouldContinue: false, hasAttemptedReactiveCompactReset: false, systemPrompt, toolDefs };\n }\n\n if (maxTurns !== undefined && callCount >= maxTurns) {\n await runNotificationHooks(hooks, \"TurnEnd\", { event: \"TurnEnd\", sessionId });\n events.push({\n type: \"turn_complete\",\n usage: turnUsage,\n model,\n callCount,\n });\n events.push({ type: \"max_turns_reached\", maxTurns, turnCount: callCount });\n return { events, preventContinuation, shouldBreak: true, shouldContinue: false, hasAttemptedReactiveCompactReset: false, systemPrompt, toolDefs };\n }\n\n await runNotificationHooks(hooks, \"TurnEnd\", { event: \"TurnEnd\", sessionId });\n return {\n events,\n preventContinuation,\n shouldBreak: false,\n shouldContinue: true,\n hasAttemptedReactiveCompactReset: true,\n systemPrompt,\n toolDefs,\n };\n}\n","import type { AIProvider } from \"../providers/types.js\";\nimport type { ChatMessage } from \"../session/types.js\";\nimport type { MemoryEntry, MemoryProvider, MemoryType } from \"./types.js\";\nimport { buildExtractionPrompt } from \"./prompts.js\";\n\nconst MEMORY_TYPES: ReadonlySet<string> = new Set([\n \"user\",\n \"project\",\n \"feedback\",\n \"reference\",\n]);\n\ninterface ExtractionAction {\n name: string;\n description: string;\n type: MemoryType;\n content: string;\n action: \"create\" | \"update\" | \"delete\";\n path?: string;\n}\n\ninterface ExtractionResult {\n memories: ExtractionAction[];\n}\n\nexport interface ExtractMemoriesResult {\n created: MemoryEntry[];\n updated: MemoryEntry[];\n deleted: string[];\n}\n\n/**\n * Summarize the most recent turn of messages into a compact string for the\n * extraction prompt. Keeps the last ~20 messages to avoid sending the entire\n * conversation history to the extraction call.\n */\nfunction summarizeRecentMessages(messages: ChatMessage[], maxMessages = 20): string {\n const recent = messages.slice(-maxMessages);\n const lines: string[] = [];\n for (const msg of recent) {\n const role = msg.role.toUpperCase();\n const text = typeof msg.content === \"string\"\n ? msg.content\n : \"(non-text content)\";\n const truncated = text.length > 2000\n ? text.slice(0, 2000) + \"…\"\n : text;\n lines.push(`[${role}] ${truncated}`);\n }\n return lines.join(\"\\n\\n\");\n}\n\n/**\n * Extract durable memories from a conversation by making a single\n * structured-output LLM call. Applies the returned actions to the\n * `MemoryProvider` and returns a summary of changes.\n */\nexport async function extractMemories(\n llmProvider: AIProvider,\n model: string,\n messages: ChatMessage[],\n provider: MemoryProvider,\n): Promise<ExtractMemoriesResult> {\n const existingIndex = await provider.loadIndex();\n const summary = summarizeRecentMessages(messages);\n const prompt = buildExtractionPrompt(summary, existingIndex);\n\n const extractionMessages: ChatMessage[] = [\n { role: \"user\", content: prompt },\n ];\n\n let responseText = \"\";\n for await (const chunk of llmProvider.chat({\n model,\n messages: extractionMessages,\n system: \"You are a memory extraction assistant. Respond only with valid JSON.\",\n max_tokens: 4096,\n })) {\n for (const choice of chunk.choices) {\n if (choice.delta.content) {\n responseText += choice.delta.content;\n }\n }\n }\n\n const parsed = parseExtractionResponse(responseText);\n if (!parsed || parsed.memories.length === 0) {\n return { created: [], updated: [], deleted: [] };\n }\n\n const result: ExtractMemoriesResult = {\n created: [],\n updated: [],\n deleted: [],\n };\n\n for (const action of parsed.memories) {\n if (!MEMORY_TYPES.has(action.type)) continue;\n\n if (action.action === \"delete\" && action.path) {\n await provider.removeEntry(action.path);\n result.deleted.push(action.path);\n } else if (action.action === \"update\" && action.path) {\n const entry: MemoryEntry = {\n name: action.name,\n description: action.description,\n type: action.type,\n content: action.content,\n path: action.path,\n updatedAt: new Date().toISOString(),\n };\n await provider.saveEntry(entry);\n result.updated.push(entry);\n } else if (action.action === \"create\") {\n const entry: MemoryEntry = {\n name: action.name,\n description: action.description,\n type: action.type,\n content: action.content,\n updatedAt: new Date().toISOString(),\n };\n await provider.saveEntry(entry);\n result.created.push(entry);\n }\n }\n\n return result;\n}\n\nfunction parseExtractionResponse(text: string): ExtractionResult | null {\n const trimmed = text.trim();\n\n // Handle markdown code fences\n let jsonStr = trimmed;\n if (jsonStr.startsWith(\"```\")) {\n const firstNewline = jsonStr.indexOf(\"\\n\");\n jsonStr = jsonStr.slice(firstNewline + 1);\n const lastFence = jsonStr.lastIndexOf(\"```\");\n if (lastFence !== -1) {\n jsonStr = jsonStr.slice(0, lastFence);\n }\n }\n\n try {\n const parsed = JSON.parse(jsonStr);\n if (\n parsed &&\n typeof parsed === \"object\" &&\n Array.isArray(parsed.memories)\n ) {\n return parsed as ExtractionResult;\n }\n return null;\n } catch {\n return null;\n }\n}\n","import type {\n AIProvider,\n ChatCompletionUsage,\n OutputFormat,\n} from \"../providers/types.js\";\nimport type {\n ChatMessage,\n AssistantMessage,\n StreamEvent,\n} from \"../session/types.js\";\nimport type { HookDefinition } from \"../hooks/types.js\";\nimport type { CostTracker } from \"../cost/tracker.js\";\nimport type { Span } from \"../tracing/types.js\";\nimport { SpanStatusCode } from \"../tracing/types.js\";\nimport type { MemoryConfig } from \"../memory/types.js\";\nimport { extractMemories } from \"../memory/extraction.js\";\nimport { SessionStorage } from \"../session/storage.js\";\nimport { runNotificationHooks } from \"../hooks/runner.js\";\nimport type { StreamAccumulator } from \"./consume-stream.js\";\n\n// ---------------------------------------------------------------------------\n// In-loop finalization (no tool calls exit)\n// ---------------------------------------------------------------------------\n\nexport interface FinalizeLoopExitParams {\n accumulator: StreamAccumulator;\n assistantMsg: AssistantMessage;\n outputFormat?: OutputFormat;\n isFinalResponseMode: boolean;\n turnUsage: ChatCompletionUsage;\n model: string;\n callCount: number;\n sessionId: string;\n costTracker?: CostTracker;\n hooks: HookDefinition[];\n storage: SessionStorage;\n}\n\nexport interface FinalizeLoopExitResult {\n events: StreamEvent[];\n}\n\nexport async function finalizeLoopExit(\n params: FinalizeLoopExitParams,\n): Promise<FinalizeLoopExitResult> {\n const {\n accumulator, assistantMsg, outputFormat, isFinalResponseMode,\n turnUsage, model, callCount, sessionId, costTracker, hooks, storage,\n } = params;\n\n const events: StreamEvent[] = [];\n\n const textContent = accumulator.content.join(\"\");\n if (outputFormat && !isFinalResponseMode && textContent) {\n try {\n const parsed = JSON.parse(textContent);\n events.push({\n type: \"structured_output\",\n data: parsed,\n schema: outputFormat,\n });\n } catch {\n // Model text wasn't valid JSON\n }\n }\n\n events.push({ type: \"message_complete\", message: assistantMsg });\n\n await runNotificationHooks(hooks, \"TurnEnd\", { event: \"TurnEnd\", sessionId });\n\n events.push({\n type: \"turn_complete\",\n usage: turnUsage,\n model,\n callCount,\n });\n\n if (costTracker) {\n await storage.appendMetadata(sessionId, \"costState\", costTracker.getState());\n }\n\n return { events };\n}\n\n// ---------------------------------------------------------------------------\n// Post-loop teardown (memory extraction + span close + SessionEnd)\n// ---------------------------------------------------------------------------\n\nexport interface FinalizeTurnParams {\n signal: AbortSignal;\n memoryConfig?: MemoryConfig;\n provider: AIProvider;\n model: string;\n messages: ChatMessage[];\n sessionId: string;\n callCount: number;\n maxTurns?: number;\n hooks: HookDefinition[];\n interactionSpan: Span;\n interactionStart: number;\n}\n\nexport interface FinalizeTurnResult {\n events: StreamEvent[];\n earlyReturn: boolean;\n}\n\nexport async function finalizeTurn(\n params: FinalizeTurnParams,\n): Promise<FinalizeTurnResult> {\n const {\n signal, memoryConfig, provider, model, messages,\n sessionId, callCount, maxTurns, hooks,\n interactionSpan, interactionStart,\n } = params;\n\n const events: StreamEvent[] = [];\n\n if (signal.aborted) {\n interactionSpan.setStatus(SpanStatusCode.OK);\n interactionSpan.end();\n events.push({ type: \"span_end\", name: \"noumen.interaction\", spanId: sessionId, durationMs: Date.now() - interactionStart });\n await runNotificationHooks(hooks, \"SessionEnd\", {\n event: \"SessionEnd\",\n sessionId,\n reason: \"abort\",\n } as import(\"../hooks/types.js\").SessionEndHookInput);\n return { events, earlyReturn: true };\n }\n\n const memCfg = memoryConfig;\n if (memCfg && memCfg.autoExtract && memCfg.provider) {\n try {\n const extractResult = await extractMemories(\n provider, model, messages, memCfg.provider,\n );\n const hasChanges = extractResult.created.length > 0\n || extractResult.updated.length > 0\n || extractResult.deleted.length > 0;\n if (hasChanges) {\n events.push({\n type: \"memory_update\",\n created: extractResult.created,\n updated: extractResult.updated,\n deleted: extractResult.deleted,\n });\n const allEntries = [\n ...extractResult.created.map((e) => ({ type: \"created\", content: e.content })),\n ...extractResult.updated.map((e) => ({ type: \"updated\", content: e.content })),\n ...extractResult.deleted.map((id) => ({ type: \"deleted\", content: id })),\n ];\n await runNotificationHooks(hooks, \"MemoryUpdate\", {\n event: \"MemoryUpdate\",\n sessionId,\n entries: allEntries,\n } as import(\"../hooks/types.js\").MemoryUpdateHookInput);\n }\n } catch {\n // Memory extraction is best-effort\n }\n }\n\n interactionSpan.setStatus(SpanStatusCode.OK);\n interactionSpan.end();\n events.push({ type: \"span_end\", name: \"noumen.interaction\", spanId: sessionId, durationMs: Date.now() - interactionStart });\n\n const endReason: \"complete\" | \"abort\" | \"maxTurns\" = signal.aborted\n ? \"abort\"\n : (maxTurns !== undefined && callCount >= maxTurns)\n ? \"maxTurns\"\n : \"complete\";\n await runNotificationHooks(hooks, \"SessionEnd\", {\n event: \"SessionEnd\",\n sessionId,\n reason: endReason,\n } as import(\"../hooks/types.js\").SessionEndHookInput);\n\n return { events, earlyReturn: false };\n}\n","import type { AIProvider, ChatCompletionUsage, OutputFormat } from \"./providers/types.js\";\nimport type { VirtualFs } from \"./virtual/fs.js\";\nimport type { VirtualComputer } from \"./virtual/computer.js\";\nimport type {\n ChatMessage,\n AssistantMessage,\n ContentPart,\n StreamEvent,\n RunOptions,\n} from \"./session/types.js\";\nimport type { SkillDefinition } from \"./skills/types.js\";\nimport type { ContextFile } from \"./context/types.js\";\nimport { buildProjectContextSection } from \"./context/prompts.js\";\nimport { filterActiveContextFiles } from \"./context/loader.js\";\nimport type { Tool, ToolContext, SubagentConfig, SubagentRun } from \"./tools/types.js\";\nimport { createToolSearchTool, TOOL_SEARCH_NAME } from \"./tools/tool-search.js\";\nimport type { TaskStore } from \"./tasks/store.js\";\nimport type { LspServerManager } from \"./lsp/manager.js\";\nimport type {\n PermissionConfig,\n PermissionContext,\n PermissionHandler,\n} from \"./permissions/types.js\";\nimport type { HookDefinition } from \"./hooks/types.js\";\nimport type { ThinkingConfig } from \"./thinking/types.js\";\nimport type { RetryConfig } from \"./retry/types.js\";\nimport type { CostTracker } from \"./cost/tracker.js\";\nimport type { Tracer, Span } from \"./tracing/types.js\";\nimport { SpanStatusCode } from \"./tracing/types.js\";\nimport { NoopTracer } from \"./tracing/noop.js\";\nimport type { MemoryConfig } from \"./memory/types.js\";\nimport { buildMemorySystemPromptSection } from \"./memory/prompts.js\";\nimport type { FileCheckpointManager } from \"./checkpoint/manager.js\";\nimport { restoreSession } from \"./session/resume.js\";\nimport { generateMissingToolResults } from \"./session/recovery.js\";\nimport {\n runNotificationHooks,\n} from \"./hooks/runner.js\";\nimport { ToolRegistry } from \"./tools/registry.js\";\nimport {\n executeToolCall,\n type ToolExecutionContext,\n} from \"./tools/execution-pipeline.js\";\nimport { SessionStorage } from \"./session/storage.js\";\nimport { buildSystemPrompt } from \"./prompt/system.js\";\nimport { compactConversation } from \"./compact/compact.js\";\nimport {\n createAutoCompactConfig,\n createAutoCompactTracking,\n type AutoCompactConfig,\n type AutoCompactTrackingState,\n} from \"./compact/auto-compact.js\";\nimport {\n type MicrocompactConfig,\n} from \"./compact/microcompact.js\";\nimport {\n createBudgetState,\n type ToolResultBudgetConfig,\n type BudgetState,\n} from \"./compact/tool-result-budget.js\";\nimport {\n persistToolResult,\n enforceToolResultStorageBudget,\n reconstructContentReplacementState,\n applyPersistedReplacements,\n createContentReplacementState,\n type ToolResultStorageConfig,\n type ContentReplacementState,\n} from \"./compact/tool-result-storage.js\";\nimport {\n type ReactiveCompactConfig,\n} from \"./compact/reactive-compact.js\";\nimport { prepareMessagesForApi } from \"./pipeline/prepare-messages.js\";\nimport { tryAutoCompactStep } from \"./pipeline/auto-compact-step.js\";\nimport { executeToolsStep } from \"./pipeline/execute-tools-step.js\";\nimport type { SnipConfig } from \"./compact/history-snip.js\";\nimport { FileStateCache } from \"./file-state/cache.js\";\nimport type { FileStateCacheConfig } from \"./file-state/types.js\";\nimport { generateUUID } from \"./utils/uuid.js\";\nimport { getActiveSkills } from \"./skills/activation.js\";\nimport { createSkillTool } from \"./tools/skill.js\";\nimport type { ResolvePermissionOptions } from \"./permissions/pipeline.js\";\nimport { DenialTracker } from \"./permissions/denial-tracking.js\";\nimport {\n createStructuredOutputTool,\n STRUCTURED_OUTPUT_TOOL_NAME,\n} from \"./tools/structured-output.js\";\nimport { initializeSession } from \"./pipeline/initialize-session.js\";\nimport { executeProviderRound, stripThinkingSignatures } from \"./pipeline/provider-round.js\";\nimport { postToolStep } from \"./pipeline/post-tool-step.js\";\nimport { finalizeLoopExit, finalizeTurn } from \"./pipeline/finalize-turn.js\";\n\nexport interface ThreadOptions {\n sessionId?: string;\n resume?: boolean;\n cwd?: string;\n model?: string;\n /** Override the permission handler for this thread (takes precedence over AgentOptions). */\n permissionHandler?: PermissionHandler;\n /** Override the user input handler for this thread (takes precedence over AgentOptions). */\n userInputHandler?: (question: string) => Promise<string>;\n}\n\nexport interface ThreadConfig {\n provider: AIProvider;\n fs: VirtualFs;\n computer: VirtualComputer;\n sessionDir: string;\n skills?: SkillDefinition[];\n tools?: Tool[];\n systemPrompt?: string;\n model?: string;\n maxTokens?: number;\n autoCompact?: AutoCompactConfig;\n microcompact?: MicrocompactConfig;\n toolResultBudget?: ToolResultBudgetConfig;\n reactiveCompact?: ReactiveCompactConfig;\n permissions?: PermissionConfig;\n hooks?: HookDefinition[];\n spawnSubagent?: (config: SubagentConfig) => SubagentRun;\n streamingToolExecution?: boolean;\n /** Truncate individual tool results exceeding this character count. Default: 100000. */\n maxResultChars?: number;\n userInputHandler?: (question: string) => Promise<string>;\n taskStore?: TaskStore;\n lspManager?: LspServerManager;\n thinking?: ThinkingConfig;\n retry?: RetryConfig;\n costTracker?: CostTracker;\n tracer?: Tracer;\n memory?: MemoryConfig;\n toolSearchEnabled?: boolean;\n checkpointManager?: FileCheckpointManager;\n /** File state cache config for read-before-edit enforcement. */\n fileStateCacheConfig?: FileStateCacheConfig;\n /** Disk-backed tool result storage config. */\n toolResultStorage?: ToolResultStorageConfig;\n /** History snip: enable middle-range removal from conversation history. */\n historySnip?: SnipConfig;\n /** Enable deterministic tool ordering and CacheSafeParams tracking for prompt caching. */\n promptCachingEnabled?: boolean;\n /** When true, signal skipCacheWrite to the provider (for subagent forks). */\n skipCacheWrite?: boolean;\n /** Set of MCP tool names for cache-stable sorting (built-in first, then MCP). */\n mcpToolNames?: ReadonlySet<string>;\n /** Loaded project context files (NOUMEN.md / CLAUDE.md) for system prompt injection. */\n projectContext?: ContextFile[];\n /** Default structured output format for all runs on this thread. */\n outputFormat?: OutputFormat;\n /** Default structured output mode for all runs on this thread. */\n structuredOutputMode?: \"alongside_tools\" | \"final_response\";\n /** When true, assert normalization invariants after every API message preparation. */\n debug?: boolean;\n}\n\nexport class Thread {\n readonly sessionId: string;\n\n private config: ThreadConfig;\n private storage: SessionStorage;\n private toolRegistry: ToolRegistry;\n private messages: ChatMessage[] = [];\n private loaded = false;\n private abortController: AbortController | null = null;\n private cwd: string;\n private model: string;\n private activatedSkills: Set<string> = new Set();\n private activatedContextRules: Set<string> = new Set();\n private permissionContext: PermissionContext | null = null;\n private permissionHandler: PermissionHandler | null = null;\n private hooks: HookDefinition[];\n private lastUsage: ChatCompletionUsage | undefined;\n private anchorMessageIndex: number | undefined;\n private prePlanMode: import(\"./permissions/types.js\").PermissionMode | null = null;\n private tracer: Tracer;\n private autoCompactTracking: AutoCompactTrackingState;\n private budgetState: BudgetState;\n private hasAttemptedReactiveCompact = false;\n private microcompactTokensFreed = 0;\n private querySource: string | undefined;\n private resumeRequested = false;\n private fileStateCache: FileStateCache | null = null;\n private contentReplacementState: ContentReplacementState;\n private denialTracker: DenialTracker | null = null;\n /** Tracks file paths read by ReadFile for post-compact reinjection. */\n private recentlyReadFiles: Map<string, string> = new Map();\n\n constructor(config: ThreadConfig, opts?: ThreadOptions) {\n this.config = config;\n this.sessionId = opts?.sessionId ?? generateUUID();\n this.cwd = opts?.cwd ?? \"/\";\n this.model = opts?.model ?? config.model ?? \"gpt-5.4\";\n this.storage = new SessionStorage(config.fs, config.sessionDir);\n\n if (config.permissions) {\n this.permissionContext = {\n mode: config.permissions.mode ?? \"default\",\n rules: [...(config.permissions.rules ?? [])],\n workingDirectories: [...(config.permissions.workingDirectories ?? [])],\n };\n this.permissionHandler = config.permissions.handler ?? null;\n if (config.permissions.denialTracking) {\n this.denialTracker = new DenialTracker(config.permissions.denialTracking);\n }\n }\n\n const extraTools = [...(config.tools ?? [])];\n\n // Add the Skill tool when skills are configured\n const allSkills = config.skills ?? [];\n if (allSkills.length > 0) {\n extraTools.push(\n createSkillTool(() => getActiveSkills(allSkills, this.activatedSkills)),\n );\n }\n\n this.toolRegistry = new ToolRegistry(extraTools.length > 0 ? extraTools : undefined);\n if (config.toolSearchEnabled) {\n this.toolRegistry.enableToolSearch();\n const registry = this.toolRegistry;\n registry.register(\n createToolSearchTool(\n () => registry.getDeferredTools(),\n () => registry.listTools(),\n (names) => registry.getToolsByNames(names),\n (names) => registry.markDiscovered(names),\n ),\n );\n }\n this.hooks = config.hooks ?? [];\n this.tracer = config.tracer ?? new NoopTracer();\n this.autoCompactTracking = createAutoCompactTracking();\n this.budgetState = createBudgetState();\n\n if (config.fileStateCacheConfig?.enabled !== false) {\n this.fileStateCache = new FileStateCache(config.fileStateCacheConfig);\n }\n this.contentReplacementState = createContentReplacementState();\n\n if (opts?.resume) {\n this.loaded = false;\n this.resumeRequested = true;\n }\n }\n\n async *run(\n prompt: string | ContentPart[],\n opts?: RunOptions,\n ): AsyncGenerator<StreamEvent, void, unknown> {\n if (this.abortController && !this.abortController.signal.aborted) {\n this.abortController.abort();\n }\n this.abortController = new AbortController();\n if (opts?.signal) {\n if (opts.signal.aborted) {\n this.abortController.abort();\n } else {\n const localController = this.abortController;\n opts.signal.addEventListener(\"abort\", () => localController.abort(), { once: true });\n }\n }\n const signal = this.abortController.signal;\n this.querySource = \"main\";\n\n const interactionSpan = this.tracer.startSpan(\"noumen.interaction\", {\n attributes: {\n \"session.id\": this.sessionId,\n \"model\": this.model,\n \"prompt.length\": prompt.length,\n },\n });\n const interactionStart = Date.now();\n yield { type: \"span_start\", name: \"noumen.interaction\", spanId: this.sessionId };\n\n const isResumeRun = this.resumeRequested;\n\n try {\n const initResult = await initializeSession({\n storage: this.storage,\n sessionId: this.sessionId,\n hooks: this.hooks,\n prompt,\n resumeRequested: this.resumeRequested,\n loaded: this.loaded,\n messages: this.messages,\n contentReplacementState: this.contentReplacementState,\n isResumeRun,\n checkpointManager: this.config.checkpointManager,\n costTracker: this.config.costTracker,\n toolResultStorage: this.config.toolResultStorage,\n fs: this.config.fs,\n });\n this.messages = initResult.messages;\n this.contentReplacementState = initResult.contentReplacementState;\n this.loaded = initResult.loaded;\n this.resumeRequested = initResult.resumeRequested;\n const turnMessageId = initResult.turnMessageId;\n for (const evt of initResult.events) yield evt;\n\n const allSkills = this.config.skills ?? [];\n let systemPrompt = await this.buildCurrentSystemPromptAsync(allSkills);\n\n // Structured output configuration: RunOptions override ThreadConfig defaults\n const runOutputFormat = opts?.outputFormat ?? this.config.outputFormat;\n const runOutputMode = opts?.structuredOutputMode ?? this.config.structuredOutputMode ?? \"alongside_tools\";\n const isFinalResponseMode = runOutputFormat?.type === \"json_schema\" && runOutputMode === \"final_response\";\n\n if (isFinalResponseMode) {\n const soTool = createStructuredOutputTool(runOutputFormat);\n if (!this.toolRegistry.get(STRUCTURED_OUTPUT_TOOL_NAME)) {\n this.toolRegistry.register(soTool);\n }\n systemPrompt += \"\\n\\nWhen you have gathered all necessary information and are ready to give your final answer, call the StructuredOutput tool with your response data.\";\n }\n\n let toolDefs = this.config.toolSearchEnabled\n ? this.toolRegistry.getActiveToolDefinitions()\n : this.toolRegistry.toToolDefinitions();\n const toolCtx: ToolContext = {\n fs: this.config.fs,\n computer: this.config.computer,\n cwd: this.cwd,\n sessionId: this.sessionId,\n hooks: this.hooks,\n spawnSubagent: this.config.spawnSubagent,\n signal,\n userInputHandler: this.config.userInputHandler,\n taskStore: this.config.taskStore,\n lspManager: this.config.lspManager,\n checkpointManager: this.config.checkpointManager,\n currentMessageId: turnMessageId,\n setPermissionMode: this.permissionContext\n ? (mode) => {\n if (this.permissionContext) {\n if (mode === \"plan\" && this.permissionContext.mode !== \"plan\") {\n this.prePlanMode = this.permissionContext.mode;\n }\n if (mode !== \"plan\" && this.permissionContext.mode === \"plan\" && this.prePlanMode) {\n this.permissionContext.mode = this.prePlanMode;\n this.prePlanMode = null;\n } else {\n this.permissionContext.mode = mode;\n }\n }\n }\n : undefined,\n getPermissionMode: this.permissionContext\n ? () => this.permissionContext!.mode\n : undefined,\n setCwd: (newCwd: string) => {\n this.cwd = newCwd;\n toolCtx.cwd = newCwd;\n },\n fileStateCache: this.fileStateCache ?? undefined,\n notifyHook: this.hooks.length > 0\n ? (event, input) => runNotificationHooks(this.hooks, event as import(\"./hooks/types.js\").HookEvent, input as import(\"./hooks/types.js\").HookInput)\n : undefined,\n };\n\n const turnUsage: ChatCompletionUsage = {\n prompt_tokens: 0,\n completion_tokens: 0,\n total_tokens: 0,\n cache_read_tokens: 0,\n cache_creation_tokens: 0,\n thinking_tokens: 0,\n };\n const MAX_CONSECUTIVE_MALFORMED = 5;\n let callCount = 0;\n let consecutiveMalformedIterations = 0;\n let preventContinuation = false;\n let outputTokenRecoveryAttempts = 0;\n const hooks = this.hooks;\n\n const useStreamingExec = this.config.streamingToolExecution ?? false;\n const retryConfig = this.config.retry;\n let currentMaxTokens = this.config.maxTokens;\n\n const execCtx: ToolExecutionContext = {\n registry: this.toolRegistry,\n toolCtx,\n permCtx: this.permissionContext,\n permHandler: this.permissionHandler,\n denialTracker: this.denialTracker,\n hooks,\n sessionId: this.sessionId,\n tracer: this.tracer,\n parentSpan: interactionSpan,\n buildPermissionOpts: () => this.buildPermissionOpts(),\n maxResultChars: this.config.maxResultChars ?? 100_000,\n };\n\n this.microcompactTokensFreed = 0;\n this.hasAttemptedReactiveCompact = false;\n\n while (!signal.aborted) {\n // --- Pre-call compaction pipeline (disk spill, microcompact, budget, normalize) ---\n const prepResult = await prepareMessagesForApi(this.messages, {\n toolResultStorage: this.config.toolResultStorage,\n microcompact: this.config.microcompact,\n toolResultBudget: this.config.toolResultBudget,\n fs: this.config.fs,\n sessionId: this.sessionId,\n debug: this.config.debug,\n }, {\n contentReplacementState: this.contentReplacementState,\n budgetState: this.budgetState,\n microcompactTokensFreed: this.microcompactTokensFreed,\n });\n this.messages = prepResult.canonicalMessages;\n this.contentReplacementState = prepResult.state.contentReplacementState;\n this.budgetState = prepResult.state.budgetState;\n this.microcompactTokensFreed = prepResult.state.microcompactTokensFreed;\n let messagesForApi = prepResult.messagesForApi;\n for (const evt of prepResult.events) yield evt;\n\n // --- Proactive auto-compact (inside loop, before each API call) ---\n const loopAutoCompactConfig =\n this.config.autoCompact ?? createAutoCompactConfig({ model: this.model });\n const compactStep = await tryAutoCompactStep(\n this.messages, loopAutoCompactConfig, this.config.provider, this.model,\n {\n lastUsage: this.lastUsage,\n anchorMessageIndex: this.anchorMessageIndex,\n microcompactTokensFreed: this.microcompactTokensFreed,\n querySource: this.querySource,\n autoCompactTracking: this.autoCompactTracking,\n recentlyReadFiles: this.recentlyReadFiles,\n signal,\n },\n hooks, this.sessionId, this.storage,\n );\n for (const evt of compactStep.events) yield evt;\n if (compactStep.compacted) {\n this.messages = compactStep.messages!;\n this.recentlyReadFiles.clear();\n this.lastUsage = undefined;\n this.anchorMessageIndex = undefined;\n this.microcompactTokensFreed = 0;\n this.budgetState = createBudgetState();\n this.contentReplacementState = createContentReplacementState();\n this.fileStateCache?.clear();\n this.denialTracker?.reset();\n continue;\n }\n if (compactStep.events.length > 0 && !compactStep.compacted) {\n continue;\n }\n\n // --- Provider round ---\n const roundGen = executeProviderRound({\n messages: this.messages,\n storage: this.storage,\n sessionId: this.sessionId,\n provider: this.config.provider,\n model: this.model,\n messagesForApi,\n systemPrompt,\n toolDefs,\n maxTokens: currentMaxTokens,\n thinking: this.config.thinking,\n retryConfig,\n promptCachingEnabled: this.config.promptCachingEnabled ?? false,\n skipCacheWrite: this.config.skipCacheWrite,\n outputFormat: runOutputFormat,\n isFinalResponseMode,\n useStreamingExec,\n signal,\n tracer: this.tracer,\n parentSpan: interactionSpan,\n hooks,\n toolRegistryLookup: (name) => this.toolRegistry.get(name),\n buildStreamingExecutorFn: this.buildStreamingExecutorFn(execCtx),\n reactiveCompact: this.config.reactiveCompact,\n hasAttemptedReactiveCompact: this.hasAttemptedReactiveCompact,\n autoCompactTracking: this.autoCompactTracking,\n mcpToolNames: this.config.mcpToolNames,\n costTracker: this.config.costTracker,\n turnUsage,\n callCount,\n consecutiveMalformedIterations,\n preventContinuation,\n currentMaxTokens,\n outputTokenRecoveryAttempts,\n maxTurns: opts?.maxTurns,\n });\n let roundStep = await roundGen.next();\n while (!roundStep.done) {\n yield roundStep.value;\n roundStep = await roundGen.next();\n }\n const roundResult = roundStep.value;\n\n // Apply state updates from the provider round\n this.model = roundResult.model;\n callCount = roundResult.callCount;\n consecutiveMalformedIterations = roundResult.consecutiveMalformedIterations;\n preventContinuation = roundResult.preventContinuation;\n currentMaxTokens = roundResult.currentMaxTokens;\n outputTokenRecoveryAttempts = roundResult.outputTokenRecoveryAttempts;\n this.hasAttemptedReactiveCompact = roundResult.hasAttemptedReactiveCompact;\n if (roundResult.lastUsage) {\n this.lastUsage = roundResult.lastUsage;\n this.anchorMessageIndex = roundResult.anchorMessageIndex;\n this.microcompactTokensFreed = roundResult.microcompactTokensFreed;\n }\n\n if (roundResult.compactRecovered && roundResult.recoveredMessages) {\n this.messages = roundResult.recoveredMessages;\n this.lastUsage = undefined;\n this.anchorMessageIndex = undefined;\n this.microcompactTokensFreed = 0;\n this.budgetState = createBudgetState();\n this.contentReplacementState = createContentReplacementState();\n this.fileStateCache?.clear();\n this.denialTracker?.reset();\n }\n\n if (roundResult.shouldContinueOuterLoop) continue;\n if (roundResult.shouldBreakOuterLoop) break;\n\n const { toolCalls, malformedToolCalls, assistantMsg: assistantMsgOrNull, accumulator, streamingExec, streamingResults } = roundResult;\n const assistantMsg = assistantMsgOrNull!;\n\n if (toolCalls.length > 0) {\n consecutiveMalformedIterations = 0;\n\n const stepResult = await executeToolsStep(\n toolCalls,\n streamingExec,\n streamingResults,\n execCtx,\n this.toolRegistry,\n this.sessionId,\n this.messages,\n this.recentlyReadFiles,\n this.storage,\n (id, name, content) => this.maybeSpillToolResult(id, name, content),\n );\n for (const evt of stepResult.events) yield evt;\n if (stepResult.preventContinuation) preventContinuation = true;\n\n const postResult = await postToolStep({\n touchedFilePaths: stepResult.touchedFilePaths,\n toolCalls,\n spilledRecords: stepResult.spilledRecords,\n signal,\n sessionId: this.sessionId,\n storage: this.storage,\n messages: this.messages,\n hooks,\n allSkills,\n activatedSkills: this.activatedSkills,\n projectContext: this.config.projectContext,\n activatedContextRules: this.activatedContextRules,\n cwd: this.cwd,\n isFinalResponseMode,\n outputFormat: runOutputFormat,\n maxTurns: opts?.maxTurns,\n callCount,\n preventContinuation,\n turnUsage,\n model: this.model,\n toolSearchEnabled: this.config.toolSearchEnabled ?? false,\n getActiveToolDefinitions: () => this.toolRegistry.getActiveToolDefinitions(),\n buildSystemPrompt: () => this.buildCurrentSystemPromptAsync(allSkills),\n });\n for (const evt of postResult.events) yield evt;\n preventContinuation = postResult.preventContinuation;\n if (postResult.systemPrompt) systemPrompt = postResult.systemPrompt;\n if (postResult.toolDefs) toolDefs = postResult.toolDefs;\n if (postResult.hasAttemptedReactiveCompactReset) this.hasAttemptedReactiveCompact = false;\n if (postResult.shouldBreak) break;\n if (postResult.shouldContinue) continue;\n }\n\n // No tool calls — finalize the loop iteration\n this.hasAttemptedReactiveCompact = false;\n const loopExitResult = await finalizeLoopExit({\n accumulator,\n assistantMsg,\n outputFormat: runOutputFormat,\n isFinalResponseMode,\n turnUsage,\n model: this.model,\n callCount,\n sessionId: this.sessionId,\n costTracker: this.config.costTracker,\n hooks: this.hooks,\n storage: this.storage,\n });\n for (const evt of loopExitResult.events) yield evt;\n break;\n }\n\n // --- Post-loop teardown: memory extraction + span close + SessionEnd ---\n const teardownResult = await finalizeTurn({\n signal,\n memoryConfig: this.config.memory,\n provider: this.config.provider,\n model: this.model,\n messages: this.messages,\n sessionId: this.sessionId,\n callCount,\n maxTurns: opts?.maxTurns,\n hooks: this.hooks,\n interactionSpan,\n interactionStart,\n });\n for (const evt of teardownResult.events) yield evt;\n if (teardownResult.earlyReturn) return;\n } catch (err) {\n if (!signal.aborted) {\n const error = err instanceof Error ? err : new Error(String(err));\n\n // Synthesize missing tool results so the conversation stays API-valid.\n // If the last message is an assistant with tool_calls that lack results,\n // inject error results before yielding the error event.\n const lastMsg = this.messages[this.messages.length - 1];\n if (lastMsg?.role === \"assistant\" && (lastMsg as AssistantMessage).tool_calls?.length) {\n const syntheticResults = generateMissingToolResults(\n lastMsg as AssistantMessage,\n this.messages,\n `Session error: ${error.message}`,\n );\n for (const sr of syntheticResults) {\n this.messages.push(sr);\n await this.storage.appendMessage(this.sessionId, sr);\n }\n }\n\n interactionSpan.setStatus(SpanStatusCode.ERROR, error.message);\n interactionSpan.end();\n yield { type: \"span_end\", name: \"noumen.interaction\", spanId: this.sessionId, durationMs: Date.now() - interactionStart, error: error.message };\n\n await runNotificationHooks(this.hooks, \"Error\", {\n event: \"Error\",\n sessionId: this.sessionId,\n error,\n });\n\n yield { type: \"error\", error };\n } else {\n interactionSpan.setStatus(SpanStatusCode.OK);\n interactionSpan.end();\n yield { type: \"span_end\", name: \"noumen.interaction\", spanId: this.sessionId, durationMs: Date.now() - interactionStart };\n }\n\n await runNotificationHooks(this.hooks, \"SessionEnd\", {\n event: \"SessionEnd\",\n sessionId: this.sessionId,\n reason: signal.aborted ? \"abort\" : \"error\",\n } as import(\"./hooks/types.js\").SessionEndHookInput);\n }\n }\n\n /**\n * If tool result storage is enabled and the content exceeds the threshold,\n * spill to disk and return the replacement stub. Otherwise return the original.\n */\n private async maybeSpillToolResult(\n toolUseId: string,\n toolName: string,\n content: string,\n ): Promise<{ content: string; spilled: boolean }> {\n const storageConfig = this.config.toolResultStorage;\n if (!storageConfig?.enabled) return { content, spilled: false };\n\n const replacement = await persistToolResult(\n this.config.fs,\n this.sessionId,\n toolUseId,\n toolName,\n content,\n storageConfig,\n );\n\n if (replacement) {\n this.contentReplacementState.seenIds.add(toolUseId);\n this.contentReplacementState.replacements.set(toolUseId, replacement);\n return { content: replacement, spilled: true };\n }\n\n this.contentReplacementState.seenIds.add(toolUseId);\n return { content, spilled: false };\n }\n\n private buildStreamingExecutorFn(\n execCtx: ToolExecutionContext,\n ): import(\"./tools/streaming-executor.js\").StreamingToolExecutorFn {\n return async (tc, parsedArgs, signal) => {\n const ctx = signal\n ? { ...execCtx, toolCtx: { ...execCtx.toolCtx, signal } }\n : execCtx;\n const pipelineResult = await executeToolCall(tc, parsedArgs, ctx);\n return {\n result: pipelineResult.result,\n permissionDenied: pipelineResult.permissionDenied,\n preventContinuation: pipelineResult.preventContinuation,\n events: pipelineResult.events,\n };\n };\n }\n\n private buildPermissionOpts(): ResolvePermissionOptions | undefined {\n const autoMode = this.config.permissions?.autoMode;\n if (!autoMode) return undefined;\n const tail = this.messages.slice(-10);\n return {\n provider: this.config.provider,\n model: this.model,\n recentMessages: tail,\n autoModeConfig: autoMode,\n denialTracker: this.denialTracker ?? undefined,\n };\n }\n\n private async buildCurrentSystemPromptAsync(allSkills: SkillDefinition[]): Promise<string> {\n const activeSkills = getActiveSkills(allSkills, this.activatedSkills);\n let memorySection: string | undefined;\n\n const memCfg = this.config.memory;\n if (memCfg?.provider && memCfg.injectIntoSystemPrompt !== false) {\n try {\n const indexContent = await memCfg.provider.loadIndex();\n memorySection = buildMemorySystemPromptSection(indexContent, \"(memory)\");\n } catch {\n // If memory loading fails, proceed without it.\n }\n }\n\n let projectContextSection: string | undefined;\n if (this.config.projectContext?.length) {\n const active = filterActiveContextFiles(\n this.config.projectContext,\n [],\n this.cwd,\n );\n const unconditional = active.filter((f) => !f.globs || f.globs.length === 0);\n const activatedConditional = this.config.projectContext.filter(\n (f) => f.globs && f.globs.length > 0 && this.activatedContextRules.has(f.path),\n );\n const combined = [...unconditional, ...activatedConditional];\n if (combined.length > 0) {\n projectContextSection = buildProjectContextSection(combined);\n }\n }\n\n const deferredTools = this.config.toolSearchEnabled\n ? this.toolRegistry.getDeferredTools().map((t) => ({\n name: t.name,\n description: t.description,\n }))\n : undefined;\n\n return buildSystemPrompt({\n customPrompt: this.config.systemPrompt,\n skills: activeSkills,\n tools: this.toolRegistry.listTools(),\n projectContext: projectContextSection,\n memorySection,\n deferredTools: deferredTools?.length ? deferredTools : undefined,\n });\n }\n\n async getMessages(): Promise<ChatMessage[]> {\n if (!this.loaded) {\n if (this.resumeRequested) {\n const payload = await restoreSession(this.storage, this.sessionId);\n this.messages = payload.messages;\n if (this.config.checkpointManager && payload.checkpointSnapshots.length > 0) {\n this.config.checkpointManager.restoreStateFromEntries(payload.checkpointSnapshots);\n }\n if (this.config.costTracker && payload.costState) {\n this.config.costTracker.restore(payload.costState);\n }\n if (payload.contentReplacements.length > 0) {\n this.contentReplacementState = reconstructContentReplacementState(\n payload.contentReplacements,\n this.messages,\n );\n this.messages = applyPersistedReplacements(\n this.messages,\n this.contentReplacementState,\n );\n }\n this.resumeRequested = false;\n } else {\n this.messages = await this.storage.loadMessages(this.sessionId);\n }\n this.loaded = true;\n }\n return [...this.messages];\n }\n\n async compact(opts?: { instructions?: string }): Promise<void> {\n if (!this.loaded) {\n this.messages = await this.storage.loadMessages(this.sessionId);\n this.loaded = true;\n }\n\n this.messages = await compactConversation(\n this.config.provider,\n this.model,\n this.messages,\n this.storage,\n this.sessionId,\n {\n customInstructions: opts?.instructions,\n recentlyReadFiles: this.recentlyReadFiles.size > 0 ? this.recentlyReadFiles : undefined,\n },\n );\n this.recentlyReadFiles.clear();\n this.lastUsage = undefined;\n this.anchorMessageIndex = undefined;\n }\n\n /**\n * Remove specific messages from the middle of conversation history.\n *\n * Unlike `compact()` which summarizes a prefix, `snip()` removes\n * specific messages by UUID. The JSONL transcript records the removed\n * UUIDs so they're filtered on resume. Parent pointers are relinked\n * across gaps.\n *\n * @param uuids - UUIDs of messages to remove\n */\n async snip(uuids: string[]): Promise<void> {\n if (uuids.length === 0) return;\n await this.storage.appendSnipBoundary(this.sessionId, uuids);\n\n // Rebuild messages from entries with snip applied\n const entries = await this.storage.loadAllEntries(this.sessionId);\n const { applySnipRemovals } = await import(\"./compact/history-snip.js\");\n\n let lastBoundaryIdx = -1;\n for (let i = entries.length - 1; i >= 0; i--) {\n if (entries[i].type === \"compact-boundary\") {\n const afterBoundary = entries.slice(i + 1);\n const hasSummaryOrMessage = afterBoundary.some(\n (e) => e.type === \"summary\" || e.type === \"message\",\n );\n if (hasSummaryOrMessage) {\n lastBoundaryIdx = i;\n break;\n }\n }\n }\n\n const activeEntries = entries.slice(lastBoundaryIdx + 1);\n const result = applySnipRemovals(activeEntries);\n this.messages = result.messages;\n }\n\n setModel(model: string): void {\n const prev = this.model;\n this.model = model;\n if (prev !== model && this.hooks.length > 0) {\n runNotificationHooks(this.hooks, \"ModelSwitch\", {\n event: \"ModelSwitch\",\n sessionId: this.sessionId,\n previousModel: prev,\n newModel: model,\n } as import(\"./hooks/types.js\").ModelSwitchHookInput).catch(() => {});\n }\n }\n\n setProvider(provider: AIProvider, model?: string): void {\n const prev = this.model;\n this.config.provider = provider;\n if (model) this.model = model;\n if (model && prev !== model && this.hooks.length > 0) {\n runNotificationHooks(this.hooks, \"ModelSwitch\", {\n event: \"ModelSwitch\",\n sessionId: this.sessionId,\n previousModel: prev,\n newModel: model,\n } as import(\"./hooks/types.js\").ModelSwitchHookInput).catch(() => {});\n }\n }\n\n getModel(): string {\n return this.model;\n }\n\n getCwd(): string {\n return this.cwd;\n }\n\n abort(): void {\n this.abortController?.abort();\n }\n}\n","import type { VirtualFs } from \"../virtual/fs.js\";\nimport type { SkillDefinition } from \"./types.js\";\nimport { parseFrontmatter, parseAllowedTools, parsePaths } from \"./frontmatter.js\";\n\n/**\n * Load skill definitions from SKILL.md files found at the given paths on the VirtualFs.\n * Each path can be a directory (scanned for SKILL.md files) or a direct file.\n */\nexport async function loadSkills(\n fs: VirtualFs,\n paths: string[],\n): Promise<SkillDefinition[]> {\n const skills: SkillDefinition[] = [];\n\n for (const skillPath of paths) {\n try {\n const stat = await fs.stat(skillPath);\n\n if (stat.isFile) {\n const skill = await loadSkillFile(fs, skillPath);\n if (skill) skills.push(skill);\n } else if (stat.isDirectory) {\n const dirSkills = await loadSkillsFromDir(fs, skillPath);\n skills.push(...dirSkills);\n }\n } catch {\n // path doesn't exist or isn't accessible; skip\n }\n }\n\n return skills;\n}\n\nasync function loadSkillFile(\n fs: VirtualFs,\n filePath: string,\n): Promise<SkillDefinition | null> {\n try {\n const raw = await fs.readFile(filePath);\n const { frontmatter, body } = parseFrontmatter(raw);\n\n const name = extractSkillName(filePath, body);\n\n const fmDescription = frontmatter.description;\n const description =\n typeof fmDescription === \"string\" && fmDescription\n ? fmDescription\n : extractDescription(body);\n\n const globs = parsePaths(frontmatter.paths);\n const allowedTools = parseAllowedTools(frontmatter[\"allowed-tools\"]);\n\n const context = frontmatter.context === \"fork\" ? \"fork\" as const : undefined;\n const argumentHint =\n typeof frontmatter[\"argument-hint\"] === \"string\"\n ? frontmatter[\"argument-hint\"]\n : undefined;\n\n return {\n name,\n content: body,\n path: filePath,\n description,\n ...(globs.length > 0 ? { globs } : {}),\n ...(allowedTools.length > 0 ? { allowedTools } : {}),\n ...(context ? { context } : {}),\n ...(argumentHint ? { argumentHint } : {}),\n };\n } catch {\n return null;\n }\n}\n\nasync function loadSkillsFromDir(\n fs: VirtualFs,\n dirPath: string,\n): Promise<SkillDefinition[]> {\n const skills: SkillDefinition[] = [];\n\n try {\n const entries = await fs.readdir(dirPath);\n\n for (const entry of entries) {\n if (\n entry.isFile &&\n (entry.name === \"SKILL.md\" || entry.name.endsWith(\".md\"))\n ) {\n const skill = await loadSkillFile(fs, entry.path);\n if (skill) skills.push(skill);\n } else if (entry.isDirectory) {\n const skillMdPath = `${entry.path}/SKILL.md`;\n const skill = await loadSkillFile(fs, skillMdPath);\n if (skill) skills.push(skill);\n }\n }\n } catch {\n // directory not readable; skip\n }\n\n return skills;\n}\n\nfunction extractSkillName(filePath: string, content: string): string {\n const h1Match = content.match(/^#\\s+(.+)$/m);\n if (h1Match) return h1Match[1].trim();\n\n const parts = filePath.split(\"/\");\n const fileName = parts[parts.length - 1];\n if (fileName === \"SKILL.md\" && parts.length >= 2) {\n return parts[parts.length - 2];\n }\n return fileName.replace(/\\.md$/, \"\");\n}\n\nfunction extractDescription(content: string): string | undefined {\n const lines = content.split(\"\\n\");\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed && !trimmed.startsWith(\"#\") && !trimmed.startsWith(\"---\")) {\n return trimmed.slice(0, 200);\n }\n }\n return undefined;\n}\n","import type { SkillDefinition } from \"../skills/types.js\";\nimport type { VirtualFs } from \"../virtual/fs.js\";\nimport { loadSkills } from \"../skills/loader.js\";\n\nexport interface UserContext {\n skills: SkillDefinition[];\n date: string;\n}\n\nexport async function buildUserContext(opts: {\n fs: VirtualFs;\n skillsPaths?: string[];\n inlineSkills?: SkillDefinition[];\n}): Promise<UserContext> {\n let skills: SkillDefinition[] = [];\n\n if (opts.skillsPaths && opts.skillsPaths.length > 0) {\n const loaded = await loadSkills(opts.fs, opts.skillsPaths);\n skills.push(...loaded);\n }\n\n if (opts.inlineSkills) {\n skills.push(...opts.inlineSkills);\n }\n\n const date = new Date().toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n return { skills, date };\n}\n","import type { StreamEvent } from \"../session/types.js\";\n\nexport interface RetryConfig {\n maxRetries?: number;\n baseDelayMs?: number;\n maxDelayMs?: number;\n retryableStatuses?: number[];\n fallbackModel?: string;\n /** Max consecutive overloaded (529) errors before triggering model fallback. */\n maxConsecutiveOverloaded?: number;\n onRetry?: (attempt: number, error: Error, delayMs: number) => void;\n}\n\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 10,\n baseDelayMs: 500,\n maxDelayMs: 32000,\n retryableStatuses: [408, 409, 429, 500, 502, 503, 504, 529],\n maxConsecutiveOverloaded: 3,\n};\n\nexport interface RetryEngineOptions extends RetryConfig {\n model: string;\n thinkingBudget?: number;\n signal?: AbortSignal;\n}\n\nexport interface RetryContext {\n attempt: number;\n model: string;\n maxTokensOverride?: number;\n}\n\nexport type RetryEvent = Extract<StreamEvent, { type: \"retry_attempt\" | \"retry_exhausted\" }>;\n","import type { AIProvider } from \"./providers/types.js\";\nimport type { VirtualFs } from \"./virtual/fs.js\";\nimport type { VirtualComputer } from \"./virtual/computer.js\";\nimport type { DiagnoseCheckResult } from \"./agent.js\";\n\n// ---------------------------------------------------------------------------\n// timedCheck utility\n// ---------------------------------------------------------------------------\n\nexport async function timedCheck<T>(\n fn: () => Promise<T>,\n timeoutMs: number,\n): Promise<{ value: T; latencyMs: number }> {\n const start = performance.now();\n const value = await Promise.race([\n fn(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`Timed out after ${timeoutMs}ms`)), timeoutMs),\n ),\n ]);\n return { value, latencyMs: Math.round(performance.now() - start) };\n}\n\nexport function formatDiagError(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n// ---------------------------------------------------------------------------\n// Individual health checks\n// ---------------------------------------------------------------------------\n\nexport async function checkProviderHealth(\n provider: AIProvider,\n model: string | undefined,\n timeoutMs: number,\n): Promise<DiagnoseCheckResult & { model?: string }> {\n try {\n const { latencyMs } = await timedCheck(async () => {\n const stream = provider.chat({\n model: model as string,\n messages: [{ role: \"user\", content: \"Say ok\" }],\n tools: [],\n system: \"\",\n });\n for await (const _ of stream) { break; }\n }, timeoutMs);\n return { ok: true, latencyMs, model };\n } catch (err) {\n return { ok: false, latencyMs: 0, error: formatDiagError(err), model };\n }\n}\n\nexport async function checkVirtualFs(\n fs: VirtualFs,\n timeoutMs: number,\n): Promise<DiagnoseCheckResult> {\n try {\n const { latencyMs } = await timedCheck(async () => fs.exists(\"/\"), timeoutMs);\n return { ok: true, latencyMs };\n } catch (err) {\n return { ok: false, latencyMs: 0, error: formatDiagError(err) };\n }\n}\n\nexport async function checkVirtualComputer(\n computer: VirtualComputer,\n timeoutMs: number,\n): Promise<DiagnoseCheckResult> {\n try {\n const { value: cmd, latencyMs } = await timedCheck(\n async () => computer.executeCommand(\"echo ok\"),\n timeoutMs,\n );\n if (cmd.exitCode === 0) {\n return { ok: true, latencyMs };\n }\n return { ok: false, latencyMs, warning: \"Shell returned non-zero\" };\n } catch (err) {\n return { ok: false, latencyMs: 0, error: formatDiagError(err) };\n }\n}\n\nexport async function checkSandboxRuntime(): Promise<\n DiagnoseCheckResult & { platform?: string }\n> {\n try {\n const { SandboxManager } = await import(\"@anthropic-ai/sandbox-runtime\");\n const supported = SandboxManager.isSupportedPlatform();\n const deps = SandboxManager.checkDependencies();\n const hasErrors = deps.errors.length > 0;\n if (supported && !hasErrors) {\n return {\n ok: true,\n latencyMs: 0,\n platform: process.platform,\n ...(deps.warnings.length > 0 && { warning: deps.warnings.join(\"; \") }),\n };\n }\n const reasons: string[] = [];\n if (!supported) reasons.push(`platform ${process.platform} not supported`);\n reasons.push(...deps.errors);\n return {\n ok: false,\n latencyMs: 0,\n warning: reasons.join(\"; \"),\n platform: process.platform,\n };\n } catch (err) {\n return {\n ok: false,\n latencyMs: 0,\n warning: `@anthropic-ai/sandbox-runtime not available: ${formatDiagError(err)}`,\n platform: process.platform,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Status summarizers\n// ---------------------------------------------------------------------------\n\nexport interface McpConnectionStatus {\n name: string;\n status: string;\n toolCount?: number;\n}\n\nexport function summarizeMcpStatus(\n statuses: McpConnectionStatus[],\n): Record<string, DiagnoseCheckResult & { status?: string; toolCount?: number }> {\n const result: Record<string, DiagnoseCheckResult & { status?: string; toolCount?: number }> = {};\n for (const s of statuses) {\n const ok = s.status === \"connected\";\n result[s.name] = {\n ok,\n latencyMs: 0,\n status: s.status,\n toolCount: s.toolCount,\n ...(!ok && s.status === \"needs-auth\"\n ? { warning: \"Requires OAuth authentication\" }\n : {}),\n ...(!ok && s.status === \"failed\"\n ? { error: \"Connection failed\" }\n : {}),\n };\n }\n return result;\n}\n\nexport interface LspServerStatus {\n name: string;\n state: string;\n}\n\nexport function summarizeLspStatus(\n statuses: LspServerStatus[],\n): Record<string, DiagnoseCheckResult & { state?: string }> {\n const result: Record<string, DiagnoseCheckResult & { state?: string }> = {};\n for (const s of statuses) {\n result[s.name] = {\n ok: s.state === \"running\",\n latencyMs: 0,\n state: s.state,\n ...(s.state !== \"running\" && s.state !== \"idle\"\n ? { warning: `Server state: ${s.state}` }\n : {}),\n };\n }\n return result;\n}\n","import type { RetryConfig } from \"./retry/types.js\";\nimport { DEFAULT_RETRY_CONFIG } from \"./retry/types.js\";\nimport type { ProjectContextConfig } from \"./context/types.js\";\n\nexport interface ResolvedAgentConfig {\n effectiveCwd: string;\n retryConfig: RetryConfig | undefined;\n projectContextConfig: ProjectContextConfig | undefined;\n mcpServerConfigs: Record<string, unknown> | undefined;\n lspConfigs: Record<string, unknown> | undefined;\n}\n\nexport interface AgentConfigInput {\n cwd?: string;\n optionsCwd?: string;\n retry?: RetryConfig | boolean;\n projectContext?: ProjectContextConfig | boolean;\n mcpServers?: Record<string, unknown>;\n lsp?: Record<string, unknown>;\n}\n\nexport function resolveAgentConfig(input: AgentConfigInput): ResolvedAgentConfig {\n const effectiveCwd = input.cwd ?? input.optionsCwd ?? process.cwd();\n\n let retryConfig: RetryConfig | undefined;\n if (input.retry === true) {\n retryConfig = DEFAULT_RETRY_CONFIG;\n } else if (typeof input.retry === \"object\") {\n retryConfig = input.retry;\n }\n\n let projectContextConfig: ProjectContextConfig | undefined;\n if (input.projectContext === true) {\n projectContextConfig = { cwd: effectiveCwd };\n } else if (typeof input.projectContext === \"object\") {\n projectContextConfig = input.projectContext;\n }\n\n const mcpServerConfigs = input.mcpServers && Object.keys(input.mcpServers).length > 0\n ? input.mcpServers\n : undefined;\n\n const lspConfigs = input.lsp && Object.keys(input.lsp).length > 0\n ? input.lsp\n : undefined;\n\n return {\n effectiveCwd,\n retryConfig,\n projectContextConfig,\n mcpServerConfigs,\n lspConfigs,\n };\n}\n","import { Agent } from \"./agent.js\";\nimport type { AIProvider } from \"./providers/types.js\";\nimport { UnsandboxedLocal, type Sandbox } from \"./virtual/sandbox.js\";\nimport type { HookDefinition } from \"./hooks/types.js\";\nimport type { McpServerConfig } from \"./mcp/types.js\";\n\nexport interface PresetOptions {\n /** The AI provider instance (e.g. `new OpenAIProvider({ apiKey })`) */\n provider: AIProvider;\n /** Working directory for the sandbox. Defaults to `process.cwd()`. */\n cwd?: string;\n /** Model name override. Each preset has a sensible default. */\n model?: string;\n /** Custom sandbox. Defaults to `UnsandboxedLocal({ cwd })`. */\n sandbox?: Sandbox;\n /** Extra hooks to attach. */\n hooks?: HookDefinition[];\n /** MCP servers to connect to during `init()`. */\n mcpServers?: Record<string, McpServerConfig>;\n /** Custom system prompt prepended to the built-in prompt. */\n systemPrompt?: string;\n}\n\n/**\n * Full-featured coding agent with subagents, tasks, plan mode, auto-compact,\n * retry, cost tracking, and project context enabled out of the box.\n */\nexport function codingAgent(opts: PresetOptions): Agent {\n const cwd = opts.cwd ?? process.cwd();\n return new Agent({\n provider: opts.provider,\n sandbox: opts.sandbox ?? UnsandboxedLocal({ cwd }),\n options: {\n cwd,\n model: opts.model,\n systemPrompt: opts.systemPrompt,\n permissions: { mode: \"default\" },\n autoCompact: true,\n enableSubagents: true,\n enableTasks: true,\n enablePlanMode: true,\n projectContext: { cwd },\n costTracking: { enabled: true },\n retry: true,\n hooks: opts.hooks,\n mcpServers: opts.mcpServers,\n },\n });\n}\n\n/**\n * Read-only planning agent — can explore the codebase but cannot make changes.\n * Useful for architecture analysis, code review prep, or scoping work.\n */\nexport function planningAgent(opts: PresetOptions): Agent {\n const cwd = opts.cwd ?? process.cwd();\n return new Agent({\n provider: opts.provider,\n sandbox: opts.sandbox ?? UnsandboxedLocal({ cwd }),\n options: {\n cwd,\n model: opts.model,\n systemPrompt: opts.systemPrompt,\n permissions: { mode: \"plan\" },\n autoCompact: true,\n enableSubagents: false,\n enableTasks: false,\n enablePlanMode: true,\n projectContext: { cwd },\n costTracking: { enabled: true },\n retry: true,\n hooks: opts.hooks,\n mcpServers: opts.mcpServers,\n },\n });\n}\n\n/**\n * Code review agent — read-only with web search enabled for looking up\n * documentation, best practices, and security advisories.\n */\nexport function reviewAgent(opts: PresetOptions): Agent {\n const cwd = opts.cwd ?? process.cwd();\n return new Agent({\n provider: opts.provider,\n sandbox: opts.sandbox ?? UnsandboxedLocal({ cwd }),\n options: {\n cwd,\n model: opts.model,\n systemPrompt: opts.systemPrompt,\n permissions: { mode: \"plan\" },\n autoCompact: true,\n enableSubagents: false,\n enableTasks: false,\n enablePlanMode: true,\n projectContext: { cwd },\n costTracking: { enabled: true },\n retry: true,\n hooks: opts.hooks,\n mcpServers: opts.mcpServers,\n webSearch: {\n search: async (query: string) => {\n try {\n const res = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`);\n if (!res.ok) return [];\n return [{ title: query, url: res.url, snippet: `Search results for: ${query}` }];\n } catch { return []; }\n },\n },\n },\n });\n}\n","import type { SwarmMessage } from \"./types.js\";\n\n/**\n * In-memory message queue for communication between swarm members.\n */\nexport class Mailbox {\n private messages: SwarmMessage[] = [];\n private listeners = new Map<string, Array<(msg: SwarmMessage) => void>>();\n\n /**\n * Send a message from one member to another.\n */\n send(from: string, to: string, content: string): void {\n const msg: SwarmMessage = {\n from,\n to,\n content,\n timestamp: new Date().toISOString(),\n };\n this.messages.push(msg);\n\n const handlers = this.listeners.get(to);\n if (handlers) {\n for (const handler of handlers) {\n handler(msg);\n }\n }\n }\n\n /**\n * Broadcast a message to all members except the sender.\n */\n broadcast(from: string, content: string, memberNames: string[]): void {\n for (const name of memberNames) {\n if (name !== from) {\n this.send(from, name, content);\n }\n }\n }\n\n /**\n * Get all messages sent to a specific member.\n */\n getMessagesFor(memberName: string): SwarmMessage[] {\n return this.messages.filter((m) => m.to === memberName);\n }\n\n /**\n * Get all unread messages for a member since the last check.\n */\n getNewMessagesFor(memberName: string, since: string): SwarmMessage[] {\n return this.messages.filter(\n (m) => m.to === memberName && m.timestamp > since,\n );\n }\n\n /**\n * Register a listener for incoming messages to a member.\n */\n onMessage(\n memberName: string,\n handler: (msg: SwarmMessage) => void,\n ): () => void {\n const existing = this.listeners.get(memberName) ?? [];\n existing.push(handler);\n this.listeners.set(memberName, existing);\n\n return () => {\n const handlers = this.listeners.get(memberName);\n if (handlers) {\n const idx = handlers.indexOf(handler);\n if (idx !== -1) handlers.splice(idx, 1);\n }\n };\n }\n\n /**\n * Get all messages in the mailbox.\n */\n getAllMessages(): SwarmMessage[] {\n return [...this.messages];\n }\n}\n","import type {\n SwarmConfig,\n SwarmMember,\n SwarmMemberConfig,\n SwarmMemberStatus,\n SwarmStatus,\n SwarmEvents,\n} from \"./types.js\";\nimport type { SwarmBackend } from \"./backends/types.js\";\nimport type { StreamEvent } from \"../session/types.js\";\nimport { Mailbox } from \"./mailbox.js\";\nimport { generateUUID } from \"../utils/uuid.js\";\n\n/**\n * Orchestrates multiple agent threads running in parallel.\n */\nexport class SwarmManager {\n private members = new Map<string, SwarmMember>();\n private backend: SwarmBackend;\n private mailbox = new Mailbox();\n private config: SwarmConfig;\n private runningTasks = new Map<string, Promise<void>>();\n private eventHandlers: Array<(event: SwarmEvents) => void> = [];\n\n constructor(backend: SwarmBackend, config?: SwarmConfig) {\n this.backend = backend;\n this.config = config ?? {};\n }\n\n /**\n * Register a handler for swarm lifecycle events.\n */\n onEvent(handler: (event: SwarmEvents) => void): () => void {\n this.eventHandlers.push(handler);\n return () => {\n const idx = this.eventHandlers.indexOf(handler);\n if (idx !== -1) this.eventHandlers.splice(idx, 1);\n };\n }\n\n private emit(event: SwarmEvents): void {\n for (const handler of this.eventHandlers) {\n handler(event);\n }\n }\n\n /**\n * Spawn a new swarm member. Returns the member ID.\n */\n async spawn(config: SwarmMemberConfig): Promise<string> {\n const id = generateUUID();\n const member: SwarmMember = {\n id,\n name: config.name,\n status: \"pending\",\n };\n this.members.set(id, member);\n\n const maxConcurrent = this.config.maxConcurrent ?? 4;\n const running = Array.from(this.members.values()).filter(\n (m) => m.status === \"running\",\n ).length;\n\n if (running >= maxConcurrent) {\n // Wait for a slot\n await this.waitForSlot(maxConcurrent);\n }\n\n member.status = \"running\";\n this.emit({\n type: \"swarm_member_start\",\n memberId: id,\n memberName: config.name,\n });\n\n const task = this.runMember(config, member);\n this.runningTasks.set(id, task);\n\n return id;\n }\n\n private async runMember(\n config: SwarmMemberConfig,\n member: SwarmMember,\n ): Promise<void> {\n try {\n const gen = this.backend.spawn(config, member);\n let next = await gen.next();\n while (!next.done) {\n next = await gen.next();\n }\n member.result = next.value;\n member.status = \"completed\";\n this.emit({\n type: \"swarm_member_complete\",\n memberId: member.id,\n memberName: member.name,\n content: member.result,\n });\n } catch (err) {\n member.error = err instanceof Error ? err : new Error(String(err));\n member.status = \"failed\";\n this.emit({\n type: \"swarm_member_failed\",\n memberId: member.id,\n memberName: member.name,\n error: member.error,\n });\n } finally {\n this.runningTasks.delete(member.id);\n }\n }\n\n /**\n * Spawn multiple members concurrently. Returns their IDs.\n */\n async spawnAll(configs: SwarmMemberConfig[]): Promise<string[]> {\n const ids: string[] = [];\n for (const config of configs) {\n ids.push(await this.spawn(config));\n }\n return ids;\n }\n\n /**\n * Send a message between swarm members.\n */\n sendMessage(from: string, to: string, content: string): void {\n this.mailbox.send(from, to, content);\n this.emit({\n type: \"swarm_message\",\n memberId: to,\n memberName: this.getMemberName(to),\n content,\n });\n }\n\n /**\n * Kill a running member.\n */\n async kill(memberId: string): Promise<void> {\n const member = this.members.get(memberId);\n if (!member || member.status !== \"running\") return;\n\n await this.backend.kill(memberId);\n member.status = \"killed\";\n this.runningTasks.delete(memberId);\n }\n\n /**\n * Wait for all running members to complete.\n */\n async waitForAll(): Promise<void> {\n while (this.runningTasks.size > 0) {\n await Promise.race(this.runningTasks.values());\n }\n }\n\n /**\n * Get current swarm status.\n */\n getStatus(): SwarmStatus {\n return {\n members: Array.from(this.members.values()),\n messages: this.mailbox.getAllMessages(),\n };\n }\n\n /**\n * Get a specific member.\n */\n getMember(id: string): SwarmMember | undefined {\n return this.members.get(id);\n }\n\n /**\n * Get the mailbox for direct access.\n */\n getMailbox(): Mailbox {\n return this.mailbox;\n }\n\n private getMemberName(id: string): string {\n return this.members.get(id)?.name ?? id;\n }\n\n private async waitForSlot(maxConcurrent: number): Promise<void> {\n while (true) {\n const running = Array.from(this.members.values()).filter(\n (m) => m.status === \"running\",\n ).length;\n if (running < maxConcurrent) return;\n if (this.runningTasks.size > 0) {\n await Promise.race(this.runningTasks.values());\n } else {\n break;\n }\n }\n }\n}\n","import type { SwarmBackend } from \"./types.js\";\nimport type { SwarmMember, SwarmMemberConfig } from \"../types.js\";\nimport type { StreamEvent } from \"../../session/types.js\";\nimport type { ThreadConfig } from \"../../thread.js\";\nimport { Thread } from \"../../thread.js\";\n\n/**\n * In-process backend: runs each swarm member as a concurrent Thread.\n */\nexport class InProcessBackend implements SwarmBackend {\n private threadConfig: Omit<ThreadConfig, \"systemPrompt\" | \"model\">;\n private abortControllers = new Map<string, AbortController>();\n\n constructor(threadConfig: Omit<ThreadConfig, \"systemPrompt\" | \"model\">) {\n this.threadConfig = threadConfig;\n }\n\n async *spawn(\n config: SwarmMemberConfig,\n member: SwarmMember,\n ): AsyncGenerator<StreamEvent, string, unknown> {\n const ac = new AbortController();\n this.abortControllers.set(member.id, ac);\n\n const childTools = config.allowedTools\n ? (this.threadConfig.tools ?? []).filter((t) =>\n config.allowedTools!.includes(t.name),\n )\n : this.threadConfig.tools;\n\n const thread = new Thread(\n {\n ...this.threadConfig,\n tools: childTools,\n systemPrompt: config.systemPrompt,\n model: config.model,\n },\n { cwd: (this.threadConfig as { cwd?: string }).cwd },\n );\n\n member.sessionId = thread.sessionId;\n let resultText = \"\";\n\n for await (const event of thread.run(config.prompt, {\n signal: ac.signal,\n })) {\n yield event;\n\n if (event.type === \"message_complete\" && event.message.content) {\n resultText += event.message.content;\n }\n }\n\n this.abortControllers.delete(member.id);\n return resultText;\n }\n\n async kill(memberId: string): Promise<void> {\n const ac = this.abortControllers.get(memberId);\n if (ac) {\n ac.abort();\n this.abortControllers.delete(memberId);\n }\n }\n}\n","import type { PermissionContext, PermissionUpdate } from \"./types.js\";\n\n/**\n * Apply a permission update to an in-memory context.\n * Returns the mutated context (same reference).\n */\nexport function applyPermissionUpdate(\n ctx: PermissionContext,\n update: PermissionUpdate,\n): PermissionContext {\n switch (update.type) {\n case \"addRules\":\n ctx.rules.push(...update.rules);\n break;\n\n case \"removeRules\":\n ctx.rules = ctx.rules.filter((r) => {\n if (r.toolName !== update.toolName) return true;\n if (update.behavior && r.behavior !== update.behavior) return true;\n return false;\n });\n break;\n\n case \"setMode\":\n ctx.mode = update.mode;\n break;\n\n case \"addDirectories\":\n for (const dir of update.directories) {\n if (!ctx.workingDirectories.includes(dir)) {\n ctx.workingDirectories.push(dir);\n }\n }\n break;\n\n case \"removeDirectories\":\n ctx.workingDirectories = ctx.workingDirectories.filter(\n (d) => !update.directories.includes(d),\n );\n break;\n }\n\n return ctx;\n}\n\n/**\n * Apply multiple permission updates in order.\n */\nexport function applyPermissionUpdates(\n ctx: PermissionContext,\n updates: PermissionUpdate[],\n): PermissionContext {\n for (const update of updates) {\n applyPermissionUpdate(ctx, update);\n }\n return ctx;\n}\n","import {\n SpanStatusCode,\n type Span,\n type SpanAttributeValue,\n type SpanOptions,\n type Tracer,\n} from \"./types.js\";\nimport { NoopSpan, NoopTracer } from \"./noop.js\";\n\ntype OTelApi = typeof import(\"@opentelemetry/api\");\n\nlet otelApi: OTelApi | null = null;\nlet otelLoadFailed = false;\n\nasync function loadOTelApi(): Promise<OTelApi | null> {\n if (otelApi) return otelApi;\n if (otelLoadFailed) return null;\n try {\n otelApi = await import(\"@opentelemetry/api\");\n return otelApi;\n } catch {\n otelLoadFailed = true;\n return null;\n }\n}\n\nclass OTelSpan implements Span {\n readonly name: string;\n private inner: import(\"@opentelemetry/api\").Span;\n\n constructor(name: string, inner: import(\"@opentelemetry/api\").Span) {\n this.name = name;\n this.inner = inner;\n }\n\n setAttribute(key: string, value: SpanAttributeValue): void {\n this.inner.setAttribute(key, value);\n }\n\n addEvent(name: string, attributes?: Record<string, SpanAttributeValue>): void {\n this.inner.addEvent(name, attributes);\n }\n\n setStatus(code: SpanStatusCode, message?: string): void {\n const otelCode = code === SpanStatusCode.ERROR\n ? 2 /* SpanStatusCode.ERROR in OTEL */\n : 1 /* SpanStatusCode.OK in OTEL */;\n this.inner.setStatus({ code: otelCode, message });\n }\n\n end(): void {\n this.inner.end();\n }\n\n /** Access the underlying OTEL span for advanced use cases. */\n getInnerSpan(): import(\"@opentelemetry/api\").Span {\n return this.inner;\n }\n}\n\n/**\n * Adapter that bridges noumen's `Tracer` interface to an OpenTelemetry\n * `TracerProvider`. The `@opentelemetry/api` package is loaded lazily via\n * dynamic `import()` so it remains an optional peer dependency.\n *\n * Call `OTelTracer.create()` (async factory) to obtain an instance.\n * If `@opentelemetry/api` is not installed, the factory returns a `NoopTracer`.\n */\nexport class OTelTracer implements Tracer {\n private otelTracer: import(\"@opentelemetry/api\").Tracer;\n private api: OTelApi;\n\n private constructor(api: OTelApi, otelTracer: import(\"@opentelemetry/api\").Tracer) {\n this.api = api;\n this.otelTracer = otelTracer;\n }\n\n /**\n * Create an `OTelTracer`. Falls back to `NoopTracer` if\n * `@opentelemetry/api` is not available at runtime.\n */\n static async create(\n serviceName: string = \"noumen\",\n version?: string,\n ): Promise<Tracer> {\n const api = await loadOTelApi();\n if (!api) return new NoopTracer();\n const tracer = api.trace.getTracer(serviceName, version);\n return new OTelTracer(api, tracer);\n }\n\n startSpan(name: string, options?: SpanOptions): Span {\n const parentCtx = options?.parent instanceof OTelSpan\n ? this.api.trace.setSpan(this.api.context.active(), options.parent.getInnerSpan())\n : this.api.context.active();\n\n const otelSpan = this.otelTracer.startSpan(\n name,\n options?.attributes ? { attributes: options.attributes as Record<string, import(\"@opentelemetry/api\").AttributeValue> } : undefined,\n parentCtx,\n );\n\n return new OTelSpan(name, otelSpan);\n }\n}\n","import type { VirtualFs } from \"../virtual/fs.js\";\nimport type { MemoryEntry, MemoryProvider, MemoryType } from \"./types.js\";\n\nconst INDEX_NAME = \"MEMORY.md\";\nconst DEFAULT_MAX_LINES = 200;\nconst DEFAULT_MAX_BYTES = 25_000;\n\nconst MEMORY_TYPES: ReadonlySet<string> = new Set([\n \"user\",\n \"project\",\n \"feedback\",\n \"reference\",\n]);\n\n// ---------------------------------------------------------------------------\n// Frontmatter helpers\n// ---------------------------------------------------------------------------\n\ninterface ParsedFrontmatter {\n name?: string;\n description?: string;\n type?: MemoryType;\n rest: string;\n}\n\nfunction parseFrontmatter(raw: string): ParsedFrontmatter {\n const trimmed = raw.trimStart();\n if (!trimmed.startsWith(\"---\")) {\n return { rest: raw };\n }\n\n const endIdx = trimmed.indexOf(\"---\", 3);\n if (endIdx === -1) {\n return { rest: raw };\n }\n\n const fmBlock = trimmed.slice(3, endIdx).trim();\n const rest = trimmed.slice(endIdx + 3).trim();\n\n let name: string | undefined;\n let description: string | undefined;\n let type: MemoryType | undefined;\n\n for (const line of fmBlock.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n if (key === \"name\") name = value;\n else if (key === \"description\") description = value;\n else if (key === \"type\" && MEMORY_TYPES.has(value)) type = value as MemoryType;\n }\n\n return { name, description, type, rest };\n}\n\nfunction serializeEntry(entry: MemoryEntry): string {\n const lines = [\n \"---\",\n `name: ${entry.name}`,\n `description: ${entry.description}`,\n `type: ${entry.type}`,\n \"---\",\n \"\",\n entry.content,\n ];\n return lines.join(\"\\n\");\n}\n\nfunction slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 60);\n}\n\n// ---------------------------------------------------------------------------\n// Index truncation (ported from claude-code's truncateEntrypointContent)\n// ---------------------------------------------------------------------------\n\nexport interface IndexTruncation {\n content: string;\n lineCount: number;\n byteCount: number;\n wasLineTruncated: boolean;\n wasByteTruncated: boolean;\n}\n\nexport function truncateIndex(\n raw: string,\n maxLines = DEFAULT_MAX_LINES,\n maxBytes = DEFAULT_MAX_BYTES,\n): IndexTruncation {\n const trimmed = raw.trim();\n const contentLines = trimmed.split(\"\\n\");\n const lineCount = contentLines.length;\n const byteCount = trimmed.length;\n\n const wasLineTruncated = lineCount > maxLines;\n const wasByteTruncated = byteCount > maxBytes;\n\n if (!wasLineTruncated && !wasByteTruncated) {\n return { content: trimmed, lineCount, byteCount, wasLineTruncated, wasByteTruncated };\n }\n\n let truncated = wasLineTruncated\n ? contentLines.slice(0, maxLines).join(\"\\n\")\n : trimmed;\n\n if (truncated.length > maxBytes) {\n const cutAt = truncated.lastIndexOf(\"\\n\", maxBytes);\n truncated = truncated.slice(0, cutAt > 0 ? cutAt : maxBytes);\n }\n\n const reason = wasByteTruncated && !wasLineTruncated\n ? `${byteCount} bytes (limit: ${maxBytes})`\n : wasLineTruncated && !wasByteTruncated\n ? `${lineCount} lines (limit: ${maxLines})`\n : `${lineCount} lines and ${byteCount} bytes`;\n\n return {\n content:\n truncated +\n `\\n\\n> WARNING: ${INDEX_NAME} is ${reason}. Only part of it was loaded. Keep index entries to one line under ~200 chars; move detail into topic files.`,\n lineCount,\n byteCount,\n wasLineTruncated,\n wasByteTruncated,\n };\n}\n\n// ---------------------------------------------------------------------------\n// FileMemoryProvider\n// ---------------------------------------------------------------------------\n\n/**\n * Default `MemoryProvider` that stores memories as individual `.md` files\n * with YAML frontmatter, plus a `MEMORY.md` index. All I/O goes through\n * `VirtualFs` so it works with any sandbox backend.\n */\nexport class FileMemoryProvider implements MemoryProvider {\n private fs: VirtualFs;\n private dir: string;\n private maxIndexLines: number;\n\n constructor(fs: VirtualFs, memoryDir: string, maxIndexLines = DEFAULT_MAX_LINES) {\n this.fs = fs;\n this.dir = memoryDir.endsWith(\"/\") ? memoryDir : memoryDir + \"/\";\n this.maxIndexLines = maxIndexLines;\n }\n\n private indexPath(): string {\n return this.dir + INDEX_NAME;\n }\n\n private async ensureDir(): Promise<void> {\n const exists = await this.fs.exists(this.dir);\n if (!exists) {\n await this.fs.mkdir(this.dir, { recursive: true });\n }\n }\n\n async loadIndex(): Promise<string> {\n try {\n const raw = await this.fs.readFile(this.indexPath());\n return truncateIndex(raw, this.maxIndexLines).content;\n } catch {\n return \"\";\n }\n }\n\n async loadEntry(path: string): Promise<MemoryEntry | null> {\n const fullPath = path.startsWith(this.dir) ? path : this.dir + path;\n try {\n const raw = await this.fs.readFile(fullPath);\n const fm = parseFrontmatter(raw);\n const stat = await this.fs.stat(fullPath).catch(() => null);\n return {\n name: fm.name ?? pathToName(path),\n description: fm.description ?? \"\",\n type: fm.type ?? \"project\",\n content: fm.rest,\n path: path.startsWith(this.dir) ? path.slice(this.dir.length) : path,\n updatedAt: stat?.modifiedAt?.toISOString(),\n };\n } catch {\n return null;\n }\n }\n\n async saveEntry(entry: MemoryEntry): Promise<void> {\n await this.ensureDir();\n const relativePath = entry.path ?? slugify(entry.name) + \".md\";\n const fullPath = this.dir + relativePath;\n const content = serializeEntry({ ...entry, path: relativePath });\n await this.fs.writeFile(fullPath, content);\n await this.rebuildIndex();\n }\n\n async removeEntry(path: string): Promise<void> {\n const fullPath = path.startsWith(this.dir) ? path : this.dir + path;\n try {\n await this.fs.deleteFile(fullPath);\n } catch {\n // Already gone\n }\n await this.rebuildIndex();\n }\n\n async listEntries(): Promise<MemoryEntry[]> {\n try {\n const files = await this.fs.readdir(this.dir);\n const entries: MemoryEntry[] = [];\n for (const file of files) {\n if (!file.isFile || !file.name.endsWith(\".md\") || file.name === INDEX_NAME) continue;\n const entry = await this.loadEntry(file.name);\n if (entry) entries.push(entry);\n }\n return entries;\n } catch {\n return [];\n }\n }\n\n async search(query: string): Promise<MemoryEntry[]> {\n const entries = await this.listEntries();\n const lower = query.toLowerCase();\n return entries.filter(\n (e) =>\n e.name.toLowerCase().includes(lower) ||\n e.description.toLowerCase().includes(lower) ||\n e.content.toLowerCase().includes(lower),\n );\n }\n\n private async rebuildIndex(): Promise<void> {\n const entries = await this.listEntries();\n const lines: string[] = [];\n for (const entry of entries) {\n const relativePath = entry.path ?? slugify(entry.name) + \".md\";\n const desc = entry.description ? ` — ${entry.description}` : \"\";\n lines.push(`- [${entry.name}](${relativePath})${desc}`);\n }\n await this.ensureDir();\n await this.fs.writeFile(this.indexPath(), lines.join(\"\\n\") + \"\\n\");\n }\n}\n\nfunction pathToName(p: string): string {\n const base = p.split(\"/\").pop() ?? p;\n return base.replace(/\\.md$/i, \"\").replace(/[_-]/g, \" \");\n}\n"],"mappings":"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","names":["resolve","execCb","fs","resolve","fs","path","resolve","assistantTexts","result","fs","path","fs","fs","join","path","dirname","formatZodValidationError","generateUUID","DEFAULT_THRESHOLD","DEFAULT_PREVIEW_CHARS","fs","generateUUID","normalize","path","path","fs","resolve","resolve","result","buildSystemPrompt","MAX_CONSECUTIVE_MALFORMED","applySnipRemovals","fs","stat","fs","SandboxManager","resolveProvider","DEFAULT_MAX_BYTES","MEMORY_TYPES","parseFrontmatter","fs","path","stat"]}