apex-code 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/dist/cli/agent-lifecycle.d.ts +24 -0
  3. package/dist/cli/agent-lifecycle.d.ts.map +1 -0
  4. package/dist/cli/agent-lifecycle.js +126 -0
  5. package/dist/cli/agent-lifecycle.js.map +1 -0
  6. package/dist/cli/args.d.ts +13 -0
  7. package/dist/cli/args.d.ts.map +1 -1
  8. package/dist/cli/args.js +80 -0
  9. package/dist/cli/args.js.map +1 -1
  10. package/dist/core/agent-session.d.ts +160 -0
  11. package/dist/core/agent-session.d.ts.map +1 -1
  12. package/dist/core/agent-session.js +265 -0
  13. package/dist/core/agent-session.js.map +1 -1
  14. package/dist/core/delegation/runtime.d.ts +682 -1
  15. package/dist/core/delegation/runtime.d.ts.map +1 -1
  16. package/dist/core/delegation/runtime.js +1339 -66
  17. package/dist/core/delegation/runtime.js.map +1 -1
  18. package/dist/core/sdk.d.ts +61 -3
  19. package/dist/core/sdk.d.ts.map +1 -1
  20. package/dist/core/sdk.js +316 -22
  21. package/dist/core/sdk.js.map +1 -1
  22. package/dist/core/tools/delegate.d.ts +8 -0
  23. package/dist/core/tools/delegate.d.ts.map +1 -1
  24. package/dist/core/tools/delegate.js +33 -3
  25. package/dist/core/tools/delegate.js.map +1 -1
  26. package/dist/core/workspace/git-observer.d.ts +16 -0
  27. package/dist/core/workspace/git-observer.d.ts.map +1 -1
  28. package/dist/core/workspace/git-observer.js +8 -1
  29. package/dist/core/workspace/git-observer.js.map +1 -1
  30. package/dist/core/workspace/git-worktree-owner.d.ts +89 -0
  31. package/dist/core/workspace/git-worktree-owner.d.ts.map +1 -0
  32. package/dist/core/workspace/git-worktree-owner.js +240 -0
  33. package/dist/core/workspace/git-worktree-owner.js.map +1 -0
  34. package/dist/main.d.ts.map +1 -1
  35. package/dist/main.js +20 -0
  36. package/dist/main.js.map +1 -1
  37. package/dist/modes/acp/server.d.ts +43 -1
  38. package/dist/modes/acp/server.d.ts.map +1 -1
  39. package/dist/modes/acp/server.js +78 -0
  40. package/dist/modes/acp/server.js.map +1 -1
  41. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  42. package/dist/modes/rpc/rpc-mode.js +38 -0
  43. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  44. package/dist/modes/rpc/rpc-types.d.ts +110 -0
  45. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  46. package/dist/modes/rpc/rpc-types.js.map +1 -1
  47. package/npm-shrinkwrap.json +5 -5
  48. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport type { CredentialStore } from \"@earendil-works/pi-ai\";\nimport { clampThinkingLevel, type Message, type Model, streamSimple } from \"@earendil-works/pi-ai/compat\";\nimport { Agent, type AgentMessage, setDefaultStreamFn, type ThinkingLevel } from \"apex-code-agent-core\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { AgentSession, type AgentSessionConfig } from \"./agent-session.ts\";\nimport { formatNoModelsAvailableMessage } from \"./auth-guidance.ts\";\nimport { AuthStorage } from \"./auth-storage.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport { createAgentDefinitionResolver } from \"./delegation/agents.ts\";\nimport type { AgentDefinitionResolver, DelegationRuntimeOptions } from \"./delegation/runtime.ts\";\nimport type { ExtensionRunner, LoadExtensionsResult, SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { loadHookRuntime } from \"./hooks/loader.ts\";\nimport type { HookRuntime } from \"./hooks/types.ts\";\nimport { createSessionMcpConnector } from \"./mcp/connector.ts\";\nimport { createMcpRuntime } from \"./mcp/runtime.ts\";\nimport { convertToLlm } from \"./messages.ts\";\nimport { findInitialModel } from \"./model-resolver.ts\";\nimport { ModelRuntime } from \"./model-runtime.ts\";\nimport { DerivedPermissionRuleStore } from \"./permissions/store.ts\";\nimport { mergeProviderAttributionHeaders } from \"./provider-attribution.ts\";\nimport type { ResourceLoader } from \"./resource-loader.ts\";\nimport { DefaultResourceLoader } from \"./resource-loader.ts\";\nimport { SANDBOX_ENFORCEMENT_MARKER_VALUE, SANDBOX_ENFORCEMENT_MARKER_VARIABLE } from \"./sandbox/cli-launch.ts\";\nimport { createSandboxCredentialStore } from \"./sandbox/rpc/credential-client.ts\";\nimport { getDefaultSessionDir, SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { time } from \"./timings.ts\";\nimport { type BackgroundShellRegistry, createBackgroundShellRegistry } from \"./tools/background-shell.ts\";\nimport type { ApexToolDefinition, Capability, EvidenceSink } from \"./tools/contract.ts\";\nimport {\n\tcreateAllToolDefinitions,\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateDelegateToolDefinition,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreatePowerShellTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype ToolName,\n\twithFileMutationQueue,\n} from \"./tools/index.ts\";\n\n// Preserve the pre-0.81 fallback for extensions that construct Agent instances\n// or invoke low-level agent loops without supplying streamFn. Agent core remains\n// provider-agnostic and does not import pi-ai/compat itself.\nsetDefaultStreamFn(streamSimple);\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.apex-code/agent */\n\tagentDir?: string;\n\n\t/** Canonical model/auth runtime. Defaults to a runtime using agentDir/auth.json and models.json. */\n\tmodelRuntime?: ModelRuntime;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'medium' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Models available for cycling (Ctrl+P in interactive mode) */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\n\t/**\n\t * Optional default tool suppression mode when no explicit allowlist is provided.\n\t *\n\t * - \"all\": start with no tools enabled\n\t * - \"builtin\": disable the default built-in tools (read, bash, edit, write)\n\t * but keep extension/custom tools enabled\n\t */\n\tnoTools?: \"all\" | \"builtin\";\n\t/**\n\t * Optional allowlist of tool names.\n\t *\n\t * When omitted, pi uses the `defaultTools` setting for the initial built-in\n\t * selection when configured. Otherwise it enables the default built-in tools\n\t * (read, bash, edit, write). Extension/custom tools remain enabled unless\n\t * `noTools` changes that default. When provided, only the listed tool names are\n\t * enabled.\n\t */\n\ttools?: string[];\n\t/** Optional denylist of tool names to disable. Applies after `tools` when both are provided. */\n\texcludeTools?: string[];\n\t/** Custom tools to register (in addition to built-in tools). */\n\tcustomTools?: ToolDefinition[];\n\n\t/** Resource loader. When omitted, DefaultResourceLoader is used. */\n\tresourceLoader?: ResourceLoader;\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n\t/** Session start event metadata for extension runtime startup. */\n\tsessionStartEvent?: SessionStartEvent;\n\t/** Authorization configuration for every registered tool call. */\n\tpermissionGate?: AgentSessionConfig[\"permissionGate\"];\n\t/** Optional headless permission bridge (ACP, spec 2026-08-31-acp-adapter.md): consulted before the interactive TUI responder. */\n\tpermissionResponderFactory?: AgentSessionConfig[\"permissionResponderFactory\"];\n\t/** Pre-assembled declarative hooks. Absent by default; `createAgentSession` assembles them from the settings manager when not supplied. */\n\thookRuntime?: HookRuntime;\n\t/** Background-shell registry. Absent by default; `createAgentSession` creates one and disposes it with the session. */\n\tbackgroundShellRegistry?: BackgroundShellRegistry;\n\t/** Optional destination for source-level evidence; defaults to the durable session sink. */\n\tevidenceSink?: EvidenceSink;\n\t/** Optional post-mutation diagnostics injected into `edit`/`write` (LSP.4). */\n\tdiagnosticsOperations?: AgentSessionConfig[\"diagnosticsOperations\"];\n\t/** Optional `lsp` navigation tool transport (LSP.5); registers and activates `lsp` when present. */\n\tlspOperations?: AgentSessionConfig[\"lspOperations\"];\n\twebSearchOperations?: AgentSessionConfig[\"webSearchOperations\"];\n\t/**\n\t * Delegation entry point (roadmap Phase 5, ADR 0008). When set, `delegate`\n\t * executes real child sessions through `resolveAgent`, with the child's\n\t * authority derived from this session's live active tools and permission\n\t * store -- never reconstructed. When omitted, `delegate` stays inert (no agent\n\t * types resolve). Agent discovery is injected here as a caller-supplied\n\t * resolver rather than built in, until Phase 5 task 5.5 lands real\n\t * markdown/frontmatter discovery. Requires `permissionGate` to be set too: a\n\t * child's authority has nothing to derive from otherwise.\n\t */\n\tdelegation?: { resolveAgent?: AgentDefinitionResolver };\n\t/**\n\t * Credential store the MCP OAuth connector uses (spec 2026-09-01-mcp-oauth).\n\t * Default: the sandbox channel store in a sandboxed child, else the host\n\t * AuthStorage — the same fallback chain the model runtime applies.\n\t */\n\tmcpCredentials?: CredentialStore;\n\t/** The caller's assertion about OS sandbox containment. */\n\tsandbox?: SdkSandboxContract;\n}\n\nexport type SdkSandboxContract = \"required\" | \"external\" | \"none\";\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Extensions result (for UI context setup in interactive mode) */\n\textensionsResult: LoadExtensionsResult;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n\tsandboxContract: SdkSandboxContract;\n\tsandboxDiagnostic?: string;\n}\n\nexport const SDK_SANDBOX_ENFORCEMENT_MARKER_VARIABLE = SANDBOX_ENFORCEMENT_MARKER_VARIABLE;\nexport const SDK_SANDBOX_ENFORCEMENT_MARKER_VALUE = SANDBOX_ENFORCEMENT_MARKER_VALUE;\n\n// Re-exports\n\nexport * from \"./agent-session-runtime.ts\";\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tInlineExtension,\n\tSlashCommandInfo,\n\tSlashCommandSource,\n\tToolDefinition,\n} from \"./extensions/index.ts\";\nexport type { PromptTemplate } from \"./prompt-templates.ts\";\nexport type { Skill } from \"./skills.ts\";\nexport type { Tool } from \"./tools/index.ts\";\n\nexport {\n\twithFileMutationQueue,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n\tcreatePowerShellTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from '@earendil-works/pi-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const loader = new DefaultResourceLoader({\n * cwd: process.cwd(),\n * agentDir: getAgentDir(),\n * settingsManager: SettingsManager.create(),\n * });\n * await loader.reload();\n * const { session } = await createAgentSession({\n * model: myModel,\n * tools: [\"read\", \"bash\"],\n * resourceLoader: loader,\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\n/** The most recent assistant text in a completed session -- what a delegated child returns to its parent as its result. */\nfunction extractFinalAssistantText(session: AgentSession): string {\n\tconst messages = session.agent.state.messages;\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst message = messages[i];\n\t\tif (message.role !== \"assistant\") continue;\n\t\tconst text = message.content\n\t\t\t.filter(\n\t\t\t\t(content): content is Extract<AgentMessage, { role: \"assistant\" }>[\"content\"][number] & { type: \"text\" } =>\n\t\t\t\t\tcontent.type === \"text\",\n\t\t\t)\n\t\t\t.map((content) => content.text)\n\t\t\t.join(\"\\n\");\n\t\tif (text) return text;\n\t}\n\treturn \"\";\n}\n\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst sandboxContract = options.sandbox ?? \"none\";\n\tconst markerPresent = process.env[SDK_SANDBOX_ENFORCEMENT_MARKER_VARIABLE] === SDK_SANDBOX_ENFORCEMENT_MARKER_VALUE;\n\tif (sandboxContract === \"required\" && !markerPresent) {\n\t\tthrow new Error(\"SDK sandbox contract requires OS containment, but no enforcing supervisor marker is present.\");\n\t}\n\tconst sandboxDiagnostic =\n\t\tsandboxContract === \"external\"\n\t\t\t? \"Sandbox containment is external to the SDK; the SDK cannot verify OS containment.\"\n\t\t\t: sandboxContract === \"none\"\n\t\t\t\t? \"No OS containment is asserted by the SDK sandbox contract.\"\n\t\t\t\t: undefined;\n\tconst cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd());\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir();\n\tlet resourceLoader = options.resourceLoader;\n\n\tconst authPath = options.agentDir ? join(agentDir, \"auth.json\") : undefined;\n\tconst modelsPath = options.agentDir ? join(agentDir, \"models.json\") : undefined;\n\tconst modelRuntime = options.modelRuntime ?? (await ModelRuntime.create({ authPath, modelsPath }));\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));\n\tconst backgroundShellRegistry = options.backgroundShellRegistry ?? createBackgroundShellRegistry();\n\n\tif (!resourceLoader) {\n\t\tresourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager });\n\t\tawait resourceLoader.reload();\n\t\ttime(\"resourceLoader.reload\");\n\t}\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.buildSessionContext();\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\tconst hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === \"thinking_level_change\");\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRuntime.getModel(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && modelRuntime.hasConfiguredAuth(restoredModel.provider)) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, use findInitialModel (checks settings default, then provider defaults)\n\tif (!model) {\n\t\tconst result = await findInitialModel({\n\t\t\tscopedModels: [],\n\t\t\tisContinuing: hasExistingSession,\n\t\t\tdefaultProvider: settingsManager.getDefaultProvider(),\n\t\t\tdefaultModelId: settingsManager.getDefaultModel(),\n\t\t\tdefaultThinkingLevel: settingsManager.getDefaultThinkingLevel(),\n\t\t\tmodelThinkingLevels: settingsManager.getAllModelThinkingLevels(),\n\t\t\tmodelRuntime,\n\t\t});\n\t\tmodel = result.model;\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = formatNoModelsAvailableMessage();\n\t\t} else if (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t}\n\t}\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = hasThinkingEntry\n\t\t\t? (existingSession.thinkingLevel as ThinkingLevel)\n\t\t\t: (settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);\n\t}\n\n\t// Fall back to per-model override, then global default\n\tif (thinkingLevel === undefined && model) {\n\t\tconst perModel = settingsManager.getModelThinkingLevel(model.provider, model.id);\n\t\tif (perModel) {\n\t\t\tthinkingLevel = perModel;\n\t\t}\n\t}\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;\n\t}\n\n\t// Clamp to model capabilities\n\tif (!model) {\n\t\tthinkingLevel = \"off\";\n\t} else {\n\t\tthinkingLevel = clampThinkingLevel(model, thinkingLevel) as ThinkingLevel;\n\t}\n\n\t// OAuth-capable MCP servers resolve tokens through the session's own credential\n\t// seam: direct and lock-serialized on the host, supervisor-mediated in a sandboxed\n\t// child, fail-closed when neither applies (spec 2026-09-01-mcp-oauth). Servers\n\t// without `auth: \"oauth\"` never touch it.\n\tconst mcpRuntime = createMcpRuntime(\n\t\tcwd,\n\t\tcreateSessionMcpConnector({\n\t\t\tcredentials: options.mcpCredentials ?? createSandboxCredentialStore() ?? AuthStorage.create(authPath),\n\t\t}),\n\t\t{ projectTrusted: settingsManager.isProjectTrusted() },\n\t);\n\n\t// `web_search`, `lsp`, and `mcp` join the core four only when configured. All stay\n\t// registered either way, so an explicit `--tools` selection still reaches them and an\n\t// unconfigured call still explains itself. Activating an unconfigured tool would put a\n\t// name in the prompt that can only ever fail.\n\tconst defaultActiveToolNames: string[] = [\n\t\t...([\"read\", \"bash\", \"edit\", \"write\"] satisfies ToolName[]),\n\t\t...(options.lspOperations ? [\"lsp\"] : []),\n\t\t...(options.webSearchOperations ? ([\"web_search\"] satisfies ToolName[]) : []),\n\t\t...(mcpRuntime ? [\"mcp\"] : []),\n\t];\n\tconst configuredDefaultToolNames = settingsManager.getDefaultTools();\n\tconst allowedToolNames = options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n\tconst excludedToolNames = options.excludeTools;\n\tconst excludedToolNameSet = excludedToolNames ? new Set(excludedToolNames) : undefined;\n\tconst initialActiveToolNames = (\n\t\toptions.tools ?? (options.noTools ? [] : (configuredDefaultToolNames ?? defaultActiveToolNames))\n\t).filter((name) => !excludedToolNameSet?.has(name));\n\n\tlet agent: Agent;\n\n\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\n\n\tconst extensionRunnerRef: { current?: ExtensionRunner } = {};\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: \"\",\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [],\n\t\t},\n\t\t// One normalized budget policy from settings; every execution mode (interactive,\n\t\t// print, JSON, RPC, ACP, SDK) runs through this session, so none counts on its\n\t\t// own (spec 2026-09-01-tool-reliability-and-execution-budgets.md).\n\t\trunBudget: settingsManager.getRunBudget(),\n\t\tconvertToLlm: convertToLlmWithBlockImages,\n\t\tstreamFn: async (model, context, options) => {\n\t\t\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\t\t\tconst httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();\n\t\t\t// SDKs treat timeout=0 as 0ms (immediate timeout), not \"no timeout\".\n\t\t\t// Use max int32 to effectively disable the timeout.\n\t\t\tconst effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;\n\t\t\tconst timeoutMs = options?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;\n\t\t\tconst websocketConnectTimeoutMs =\n\t\t\t\toptions?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();\n\t\t\tconst headerRunner = extensionRunnerRef.current;\n\t\t\treturn modelRuntime.streamSimple(model, context, {\n\t\t\t\t...options,\n\t\t\t\ttimeoutMs,\n\t\t\t\twebsocketConnectTimeoutMs,\n\t\t\t\tmaxRetries: options?.maxRetries ?? providerRetrySettings.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,\n\t\t\t\ttransformHeaders: async (requestHeaders) => {\n\t\t\t\t\tconst headers = mergeProviderAttributionHeaders(\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tsettingsManager,\n\t\t\t\t\t\toptions?.sessionId,\n\t\t\t\t\t\trequestHeaders,\n\t\t\t\t\t);\n\t\t\t\t\treturn headerRunner?.hasHandlers(\"before_provider_headers\")\n\t\t\t\t\t\t? headerRunner.emitBeforeProviderHeaders(headers ?? {})\n\t\t\t\t\t\t: (headers ?? {});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tonPayload: async (payload, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"before_provider_request\")) {\n\t\t\t\treturn payload;\n\t\t\t}\n\t\t\treturn runner.emitBeforeProviderRequest(payload);\n\t\t},\n\t\tonResponse: async (response, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"after_provider_response\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runner.emit({\n\t\t\t\ttype: \"after_provider_response\",\n\t\t\t\tstatus: response.status,\n\t\t\t\theaders: response.headers,\n\t\t\t});\n\t\t},\n\t\tsessionId: sessionManager.getSessionId(),\n\t\ttransformContext: async (messages) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner) return messages;\n\t\t\treturn runner.emitContext(messages);\n\t\t},\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\ttransport: settingsManager.getTransport(),\n\t\tthinkingBudgets: settingsManager.getThinkingBudgets(),\n\t\tmaxRetryDelayMs: settingsManager.getProviderRetrySettings().maxRetryDelayMs,\n\t});\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.state.messages = existingSession.messages;\n\t\tif (!hasThinkingEntry) {\n\t\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t\t}\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\t// Forward ref, mirroring extensionRunnerRef above: the delegation runtime's\n\t// closures are needed to build `customTools` before `session` exists, but they\n\t// must read the *live* session (active tools can change after construction),\n\t// not a snapshot frozen at this point.\n\tconst parentSessionRef: { current?: AgentSession } = {};\n\tconst customTools: ToolDefinition[] = options.customTools ? [...options.customTools] : [];\n\t// A configured permission gate supplies the authority a child must derive, so\n\t// discovery is enabled by default in real sessions. Callers that need fixture\n\t// definitions may still provide an explicit resolver.\n\tconst delegation = options.delegation ?? (options.permissionGate ? {} : undefined);\n\tif (delegation) {\n\t\tconst parentPermissionGate = options.permissionGate;\n\t\tconst resolveAgent =\n\t\t\tdelegation.resolveAgent ??\n\t\t\tcreateAgentDefinitionResolver({\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tisProjectTrusted: () => settingsManager.isProjectTrusted(),\n\t\t\t});\n\t\tconst delegationRuntime: DelegationRuntimeOptions = {\n\t\t\tresolveAgent,\n\t\t\tgetParentCapabilities: () => {\n\t\t\t\tconst capabilities = new Set<Capability>();\n\t\t\t\tfor (const name of parentSessionRef.current?.getActiveToolNames() ?? []) {\n\t\t\t\t\tconst contract = (\n\t\t\t\t\t\tparentSessionRef.current?.getToolDefinition(name) as Partial<ApexToolDefinition> | undefined\n\t\t\t\t\t)?.contract;\n\t\t\t\t\tif (contract) for (const capability of contract.capabilities) capabilities.add(capability);\n\t\t\t\t}\n\t\t\t\treturn capabilities;\n\t\t\t},\n\t\t\tgetToolCapabilities: (toolName) => {\n\t\t\t\t// Prefer the parent's own live registry first (it also covers\n\t\t\t\t// extension/custom tools an agent definition might name), but fall back\n\t\t\t\t// to the canonical built-in registry: \"what capability does tool X\n\t\t\t\t// need\" is a property of the tool itself, independent of whether the\n\t\t\t\t// parent's own session restricted it out of its active/allowed set via\n\t\t\t\t// `tools`/`excludeTools` -- that restriction affects the parent's own\n\t\t\t\t// *authority* (getParentCapabilities, above), not what a named tool is.\n\t\t\t\tconst fromParent = (\n\t\t\t\t\tparentSessionRef.current?.getToolDefinition(toolName) as Partial<ApexToolDefinition> | undefined\n\t\t\t\t)?.contract?.capabilities;\n\t\t\t\tif (fromParent) return fromParent;\n\t\t\t\treturn (createAllToolDefinitions(cwd)[toolName as ToolName] as ApexToolDefinition | undefined)?.contract\n\t\t\t\t\t?.capabilities;\n\t\t\t},\n\t\t\t// Read fresh each call, not captured once: depth is a live property of\n\t\t\t// the (possibly delegated) session this createAgentSession call is\n\t\t\t// building, via the same sessionManager this closure already captures.\n\t\t\tgetDelegationDepth: () => sessionManager.getDelegationDepth(),\n\t\t\tmaxDelegationDepth: settingsManager.getDelegationMaxDepth(),\n\t\t\tgetParentSessionDir: () => sessionManager.getSessionDir(),\n\t\t\tbuildChildSession: async ({ definition, toolNames, depth, sessionId, artifactDir }) => {\n\t\t\t\tif (!parentPermissionGate) {\n\t\t\t\t\tthrow new Error(\"delegate requires a permission gate configured on the parent session (ADR 0008).\");\n\t\t\t\t}\n\t\t\t\tconst childModel =\n\t\t\t\t\t(definition.model && modelRuntime.getAvailableSnapshot().find((m) => m.id === definition.model)) ||\n\t\t\t\t\tmodel;\n\t\t\t\tif (!childModel) {\n\t\t\t\t\tthrow new Error(`Cannot delegate to \"${definition.name}\": no model is available for the child session.`);\n\t\t\t\t}\n\t\t\t\tconst childSessionManager = artifactDir\n\t\t\t\t\t? SessionManager.create(cwd, artifactDir, {\n\t\t\t\t\t\t\tid: sessionId,\n\t\t\t\t\t\t\tparentSession: sessionManager.getSessionId(),\n\t\t\t\t\t\t\tdelegationDepth: depth,\n\t\t\t\t\t\t})\n\t\t\t\t\t: SessionManager.inMemory(cwd, {\n\t\t\t\t\t\t\tparentSession: sessionManager.getSessionId(),\n\t\t\t\t\t\t\tdelegationDepth: depth,\n\t\t\t\t\t\t});\n\t\t\t\tconst derivedStore = new DerivedPermissionRuleStore({ parent: parentPermissionGate.store });\n\t\t\t\tconst { session: childSession } = await createAgentSession({\n\t\t\t\t\tcwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tmodel: childModel,\n\t\t\t\t\tmodelRuntime,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\tsessionManager: childSessionManager,\n\t\t\t\t\tresourceLoader,\n\t\t\t\t\ttools: toolNames,\n\t\t\t\t\t// No responder: a child's `ask` fails closed rather than prompting the\n\t\t\t\t\t// human for a call the human did not make (ADR 0008, \"Who answers a\n\t\t\t\t\t// child's ask\").\n\t\t\t\t\tpermissionGate: { store: derivedStore, getMode: parentPermissionGate.getMode },\n\t\t\t\t\t// A delegated child shares the parent's cwd-bound LSP pool (spec, \"no\n\t\t\t\t\t// multi-root LSP connection and no sharing across cwd-bound service\n\t\t\t\t\t// lifetimes\" -- delegated children are the one sharing exception).\n\t\t\t\t\tdiagnosticsOperations: options.diagnosticsOperations,\n\t\t\t\t\tlspOperations: options.lspOperations,\n\t\t\t\t\t// Shared for the same reason as the LSP pool: the backend was resolved\n\t\t\t\t\t// once (possibly by running a shell command for the key) and a child\n\t\t\t\t\t// that re-resolved nothing would hold a `web_search` that only throws.\n\t\t\t\t\twebSearchOperations: options.webSearchOperations,\n\t\t\t\t\t// `checkpointSettings` is deliberately *not* forwarded. A child shares the\n\t\t\t\t\t// parent's cwd, so it would write refs under its own session id into the\n\t\t\t\t\t// same repository and interleave them with the parent's. The parent's\n\t\t\t\t\t// per-turn capture already covers everything a child does inside that turn.\n\n\t\t\t\t\t// Forwarded so a child that itself holds `delegate` can delegate again\n\t\t\t\t\t// (bounded by the depth guard above, read fresh from its own session\n\t\t\t\t\t// header on its next createAgentSession call) -- otherwise recursion\n\t\t\t\t\t// would be silently capped at one level regardless of maxDelegationDepth.\n\t\t\t\t\tdelegation,\n\t\t\t\t\tsandbox: sandboxContract,\n\t\t\t\t});\n\t\t\t\tawait childSession.bindExtensions({});\n\t\t\t\treturn {\n\t\t\t\t\tasync run(task: string) {\n\t\t\t\t\t\tconst prompt = definition.systemPrompt\n\t\t\t\t\t\t\t? `${definition.systemPrompt}\\n\\nTask: ${task}`\n\t\t\t\t\t\t\t: `Task: ${task}`;\n\t\t\t\t\t\tawait childSession.prompt(prompt);\n\t\t\t\t\t\treturn { output: extractFinalAssistantText(childSession) };\n\t\t\t\t\t},\n\t\t\t\t\tdispose() {\n\t\t\t\t\t\tchildSession.dispose();\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t};\n\t\tcustomTools.push(createDelegateToolDefinition(delegationRuntime) as ToolDefinition<any, any>);\n\t}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tscopedModels: options.scopedModels,\n\t\tresourceLoader,\n\t\tcustomTools,\n\t\tmodelRuntime,\n\t\tinitialActiveToolNames,\n\t\tallowedToolNames,\n\t\texcludedToolNames,\n\t\textensionRunnerRef,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t\tpermissionGate: options.permissionGate,\n\t\tpermissionResponderFactory: options.permissionResponderFactory,\n\t\tevidenceSink: options.evidenceSink,\n\t\tdiagnosticsOperations: options.diagnosticsOperations,\n\t\tlspOperations: options.lspOperations,\n\t\twebSearchOperations: options.webSearchOperations,\n\t\tmcpRuntime,\n\t\tcheckpointSettings: settingsManager.getCheckpointSettings(),\n\t\t// Declarative hooks (spec 2026-08-31-declarative-hooks): assembled from the\n\t\t// merged settings -- project-scope entries only appear once trusted. A\n\t\t// malformed hooks key throws here, failing closed at wiring. Deliberately\n\t\t// not forwarded to delegation children (see the spec's boundary note).\n\t\thookRuntime: options.hookRuntime ?? loadHookRuntime(settingsManager.getHookSettings()),\n\t\tbackgroundShellRegistry,\n\t});\n\tparentSessionRef.current = session;\n\t// Eager servers connect here rather than on first use, so their tools are in the\n\t// cache before the model's first search. Detached: a slow or broken server delays\n\t// nothing, and `warmEagerServers` already swallows its own failures.\n\tvoid mcpRuntime?.warm();\n\tconst extensionsResult = resourceLoader.getExtensions();\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tmodelFallbackMessage,\n\t\tsandboxContract,\n\t\tsandboxDiagnostic,\n\t};\n}\n"]}
1
+ {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport type { CredentialStore } from \"@earendil-works/pi-ai\";\nimport { clampThinkingLevel, type Message, type Model, streamSimple } from \"@earendil-works/pi-ai/compat\";\nimport {\n\tAgent,\n\ttype AgentMessage,\n\ttype AgentRunBudgetController,\n\ttype AgentStopReason,\n\tcreateRunBudgetController,\n\tsetDefaultStreamFn,\n\ttype ThinkingLevel,\n} from \"apex-code-agent-core\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { AgentSession, type AgentSessionConfig, type AggregateBudgetUsageSnapshot } from \"./agent-session.ts\";\nimport { formatNoModelsAvailableMessage } from \"./auth-guidance.ts\";\nimport { AuthStorage } from \"./auth-storage.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport { createAgentDefinitionResolver } from \"./delegation/agents.ts\";\nimport {\n\ttype AgentDefinitionResolver,\n\ttype ChildRunPolicySnapshot,\n\tChildRunRegistry,\n\ttype ChildTurnResult,\n\ttype DelegationRuntimeOptions,\n} from \"./delegation/runtime.ts\";\nimport type { ExtensionRunner, LoadExtensionsResult, SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { loadHookRuntime } from \"./hooks/loader.ts\";\nimport type { HookRuntime } from \"./hooks/types.ts\";\nimport { createSessionMcpConnector } from \"./mcp/connector.ts\";\nimport { createMcpRuntime } from \"./mcp/runtime.ts\";\nimport { convertToLlm } from \"./messages.ts\";\nimport { findInitialModel } from \"./model-resolver.ts\";\nimport { ModelRuntime } from \"./model-runtime.ts\";\nimport { DerivedPermissionRuleStore } from \"./permissions/store.ts\";\nimport { mergeProviderAttributionHeaders } from \"./provider-attribution.ts\";\nimport type { ResourceLoader } from \"./resource-loader.ts\";\nimport { DefaultResourceLoader } from \"./resource-loader.ts\";\nimport { SANDBOX_ENFORCEMENT_MARKER_VALUE, SANDBOX_ENFORCEMENT_MARKER_VARIABLE } from \"./sandbox/cli-launch.ts\";\nimport { createSandboxCredentialStore } from \"./sandbox/rpc/credential-client.ts\";\nimport { getDefaultSessionDir, SessionManager } from \"./session-manager.ts\";\nimport { type ResolvedRunBudget, SettingsManager } from \"./settings-manager.ts\";\nimport { time } from \"./timings.ts\";\nimport { type BackgroundShellRegistry, createBackgroundShellRegistry } from \"./tools/background-shell.ts\";\nimport type { ApexToolDefinition, Capability, EvidenceSink } from \"./tools/contract.ts\";\nimport {\n\tcreateAllToolDefinitions,\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateDelegateToolDefinition,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreatePowerShellTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype ToolName,\n\twithFileMutationQueue,\n} from \"./tools/index.ts\";\nimport { GitWorktreeWorkspaceOwner } from \"./workspace/git-worktree-owner.ts\";\n\n// Preserve the pre-0.81 fallback for extensions that construct Agent instances\n// or invoke low-level agent loops without supplying streamFn. Agent core remains\n// provider-agnostic and does not import pi-ai/compat itself.\nsetDefaultStreamFn(streamSimple);\n\nexport interface CreateAgentSessionOptions {\n\tchildRunRegistry?: AgentSessionConfig[\"childRunRegistry\"];\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.apex-code/agent */\n\tagentDir?: string;\n\n\t/** Canonical model/auth runtime. Defaults to a runtime using agentDir/auth.json and models.json. */\n\tmodelRuntime?: ModelRuntime;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'medium' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Models available for cycling (Ctrl+P in interactive mode) */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\n\t/**\n\t * Optional default tool suppression mode when no explicit allowlist is provided.\n\t *\n\t * - \"all\": start with no tools enabled\n\t * - \"builtin\": disable the default built-in tools (read, bash, edit, write)\n\t * but keep extension/custom tools enabled\n\t */\n\tnoTools?: \"all\" | \"builtin\";\n\t/**\n\t * Optional allowlist of tool names.\n\t *\n\t * When omitted, pi uses the `defaultTools` setting for the initial built-in\n\t * selection when configured. Otherwise it enables the default built-in tools\n\t * (read, bash, edit, write). Extension/custom tools remain enabled unless\n\t * `noTools` changes that default. When provided, only the listed tool names are\n\t * enabled.\n\t */\n\ttools?: string[];\n\t/** Optional denylist of tool names to disable. Applies after `tools` when both are provided. */\n\texcludeTools?: string[];\n\t/** Custom tools to register (in addition to built-in tools). */\n\tcustomTools?: ToolDefinition[];\n\n\t/** Resource loader. When omitted, DefaultResourceLoader is used. */\n\tresourceLoader?: ResourceLoader;\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n\t/**\n\t * Per-run budget policy override (spec 2026-09-09-run-and-child-session-architecture.md,\n\t * \"Shared budgets\"). When supplied, it replaces the settings read for this\n\t * session's Agent construction; `settingsManager.getRunBudget()` stays the\n\t * default. Per-run only: every session -- parent and child alike -- counts\n\t * its own runs against this policy. It never creates a shared ceiling.\n\t */\n\trunBudget?: ResolvedRunBudget;\n\t/**\n\t * The root aggregate budget for this session's whole delegation tree (spec\n\t * 2026-09-09, \"Shared budgets\"). Explicit opt-in: it is never derived from\n\t * `runBudget`. When set, this session creates ONE aggregate controller and\n\t * (a) composes it under its own Agent's controller, so the parent's own runs\n\t * consume the aggregate while the local per-prompt scope is unchanged, and\n\t * (b) hands THE SAME controller instance to every delegated child regardless\n\t * of depth, so the whole tree -- grandchildren included -- shares one\n\t * ceiling. Read it through `session.aggregateBudgetUsage()`. Absent: no\n\t * shared ceiling anywhere -- every session keeps local-only budgets (the\n\t * per-run policy is still inherited).\n\t */\n\taggregateBudget?: ResolvedRunBudget;\n\t/**\n\t * Maximum simultaneously-active delegated children this session's delegation\n\t * runtime admits (spec 2026-09-09, \"Shared budgets\"). Checked at child\n\t * admission, BEFORE any child session is built; over the limit the admission\n\t * throws an actionable error naming the limit. An admitted run holds one\n\t * slot until terminal settlement (completed/failed/interrupted), close, or\n\t * launch failure. `undefined` (default) is unlimited. Only meaningful when\n\t * delegation is configured.\n\t */\n\tmaxConcurrentChildren?: number;\n\t/**\n\t * Budget controller scope for this session's Agent. \"prompt\" (default;\n\t * upstream semantics) starts a fresh controller at every prompt();\n\t * \"session\" creates one controller at the first prompt/continue and reuses\n\t * it, so a resumed or follow-up turn continues the same budget. Delegated\n\t * children are built with \"session\" so their budget survives sendInput /\n\t * follow-up / resume turns (spec 2026-09-09, \"Shared budgets\").\n\t */\n\tbudgetScope?: \"prompt\" | \"session\";\n\t/**\n\t * A shared budget controller composed under this session's own controller\n\t * (`createCompositeBudgetController`): every gate allows only if both\n\t * allow, and only accepted attempts record to both. The caller owns\n\t * the controller's lifetime; this session never resets it. This is how a\n\t * delegated child receives its root's aggregate controller (spec 2026-09-09,\n\t * \"Shared budgets\") -- sessions that are not delegated children normally\n\t * pass `aggregateBudget` instead and leave this unset.\n\t */\n\tsharedBudgetController?: AgentRunBudgetController;\n\t/** Session start event metadata for extension runtime startup. */\n\tsessionStartEvent?: SessionStartEvent;\n\t/** Authorization configuration for every registered tool call. */\n\tpermissionGate?: AgentSessionConfig[\"permissionGate\"];\n\t/** Optional headless permission bridge (ACP, spec 2026-08-31-acp-adapter.md): consulted before the interactive TUI responder. */\n\tpermissionResponderFactory?: AgentSessionConfig[\"permissionResponderFactory\"];\n\t/** Pre-assembled declarative hooks. Absent by default; `createAgentSession` assembles them from the settings manager when not supplied. */\n\thookRuntime?: HookRuntime;\n\t/** Background-shell registry. Absent by default; `createAgentSession` creates one and disposes it with the session. */\n\tbackgroundShellRegistry?: BackgroundShellRegistry;\n\t/** Optional destination for source-level evidence; defaults to the durable session sink. */\n\tevidenceSink?: EvidenceSink;\n\t/** Optional post-mutation diagnostics injected into `edit`/`write` (LSP.4). */\n\tdiagnosticsOperations?: AgentSessionConfig[\"diagnosticsOperations\"];\n\t/** Optional `lsp` navigation tool transport (LSP.5); registers and activates `lsp` when present. */\n\tlspOperations?: AgentSessionConfig[\"lspOperations\"];\n\twebSearchOperations?: AgentSessionConfig[\"webSearchOperations\"];\n\t/**\n\t * Delegation entry point (roadmap Phase 5, ADR 0008). When set, `delegate`\n\t * executes real child sessions through `resolveAgent`, with the child's\n\t * authority derived from this session's live active tools and permission\n\t * store -- never reconstructed. When omitted, `delegate` stays inert (no agent\n\t * types resolve). Agent discovery is injected here as a caller-supplied\n\t * resolver rather than built in, until Phase 5 task 5.5 lands real\n\t * markdown/frontmatter discovery. Requires `permissionGate` to be set too: a\n\t * child's authority has nothing to derive from otherwise.\n\t */\n\tdelegation?: { resolveAgent?: AgentDefinitionResolver };\n\t/**\n\t * Credential store the MCP OAuth connector uses (spec 2026-09-01-mcp-oauth).\n\t * Default: the sandbox channel store in a sandboxed child, else the host\n\t * AuthStorage — the same fallback chain the model runtime applies.\n\t */\n\tmcpCredentials?: CredentialStore;\n\t/** The caller's assertion about OS sandbox containment. */\n\tsandbox?: SdkSandboxContract;\n}\n\nexport type SdkSandboxContract = \"required\" | \"external\" | \"none\";\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Extensions result (for UI context setup in interactive mode) */\n\textensionsResult: LoadExtensionsResult;\n\t/**\n\t * The session's delegation runtime options when delegation is configured\n\t * (undefined otherwise). Exposing the one runtime the `delegate` tool uses\n\t * lets external lifecycle callers (tests) launch\n\t * children through the same authority derivation instead of re-deriving it.\n\t */\n\tdelegationRuntime?: DelegationRuntimeOptions;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n\tsandboxContract: SdkSandboxContract;\n\tsandboxDiagnostic?: string;\n}\n\nexport const SDK_SANDBOX_ENFORCEMENT_MARKER_VARIABLE = SANDBOX_ENFORCEMENT_MARKER_VARIABLE;\nexport const SDK_SANDBOX_ENFORCEMENT_MARKER_VALUE = SANDBOX_ENFORCEMENT_MARKER_VALUE;\n\n// Re-exports\n\nexport * from \"./agent-session-runtime.ts\";\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tInlineExtension,\n\tSlashCommandInfo,\n\tSlashCommandSource,\n\tToolDefinition,\n} from \"./extensions/index.ts\";\nexport type { PromptTemplate } from \"./prompt-templates.ts\";\nexport type { Skill } from \"./skills.ts\";\nexport type { Tool } from \"./tools/index.ts\";\n\nexport {\n\twithFileMutationQueue,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n\tcreatePowerShellTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from '@earendil-works/pi-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const loader = new DefaultResourceLoader({\n * cwd: process.cwd(),\n * agentDir: getAgentDir(),\n * settingsManager: SettingsManager.create(),\n * });\n * await loader.reload();\n * const { session } = await createAgentSession({\n * model: myModel,\n * tools: [\"read\", \"bash\"],\n * resourceLoader: loader,\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\n/** The most recent assistant text in a completed session -- what a delegated child returns to its parent as its result. */\nfunction extractFinalAssistantText(session: AgentSession): string {\n\tconst messages = session.agent.state.messages;\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst message = messages[i];\n\t\tif (message.role !== \"assistant\") continue;\n\t\tconst text = message.content\n\t\t\t.filter(\n\t\t\t\t(content): content is Extract<AgentMessage, { role: \"assistant\" }>[\"content\"][number] & { type: \"text\" } =>\n\t\t\t\t\tcontent.type === \"text\",\n\t\t\t)\n\t\t\t.map((content) => content.text)\n\t\t\t.join(\"\\n\");\n\t\tif (text) return text;\n\t}\n\treturn \"\";\n}\n\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst sandboxContract = options.sandbox ?? \"none\";\n\tconst markerPresent = process.env[SDK_SANDBOX_ENFORCEMENT_MARKER_VARIABLE] === SDK_SANDBOX_ENFORCEMENT_MARKER_VALUE;\n\tif (sandboxContract === \"required\" && !markerPresent) {\n\t\tthrow new Error(\"SDK sandbox contract requires OS containment, but no enforcing supervisor marker is present.\");\n\t}\n\tconst sandboxDiagnostic =\n\t\tsandboxContract === \"external\"\n\t\t\t? \"Sandbox containment is external to the SDK; the SDK cannot verify OS containment.\"\n\t\t\t: sandboxContract === \"none\"\n\t\t\t\t? \"No OS containment is asserted by the SDK sandbox contract.\"\n\t\t\t\t: undefined;\n\tconst cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd());\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir();\n\tlet resourceLoader = options.resourceLoader;\n\n\tconst authPath = options.agentDir ? join(agentDir, \"auth.json\") : undefined;\n\tconst modelsPath = options.agentDir ? join(agentDir, \"models.json\") : undefined;\n\tconst modelRuntime = options.modelRuntime ?? (await ModelRuntime.create({ authPath, modelsPath }));\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));\n\tconst backgroundShellRegistry = options.backgroundShellRegistry ?? createBackgroundShellRegistry();\n\t// One resolved per-run budget policy: the caller's override when supplied,\n\t// else the settings policy. Children built below inherit this resolved value\n\t// so a child run carries the same per-run policy as its parent without\n\t// re-reading settings (spec 2026-09-09, \"Shared budgets\"). Per-run only: it\n\t// never creates a shared ceiling.\n\tconst runBudget = options.runBudget ?? settingsManager.getRunBudget();\n\t// The root aggregate budget (spec 2026-09-09, \"Shared budgets\"): created\n\t// ONLY when the caller explicitly configures `aggregateBudget` -- never\n\t// derived from the per-run policy. One controller per root tree: the\n\t// parent's own Agent consumes it (composed under its per-prompt controller),\n\t// and buildChildSession forwards THE SAME instance to every child regardless\n\t// of depth, so a grandchild's consumption lands on the root ledger. Its wall\n\t// time starts here, at root session construction, and no descendant can\n\t// reset it: descendants only consume.\n\tconst aggregateBudgetController = options.aggregateBudget\n\t\t? createRunBudgetController(options.aggregateBudget)\n\t\t: undefined;\n\t// The shared ceiling this session consumes and hands to its delegated\n\t// children: the root aggregate when configured, else a caller-supplied\n\t// controller (which is how a delegated child receives its root's aggregate).\n\t// With neither there is NO shared controller at all: every session keeps\n\t// local-only budgets under its inherited per-run policy.\n\tconst sharedBudgetController = aggregateBudgetController ?? options.sharedBudgetController;\n\t// The tree-facing usage snapshot: the aggregate controller's counters cover\n\t// every accepted provider request, tool call, and maintenance request of the\n\t// parent's own runs and of every descendant, so one read reports the tree.\n\tconst aggregateBudgetUsage = sharedBudgetController\n\t\t? (): AggregateBudgetUsageSnapshot => {\n\t\t\t\tconst usage = sharedBudgetController.usage();\n\t\t\t\treturn {\n\t\t\t\t\tproviderRequests: usage.providerRequests,\n\t\t\t\t\ttoolCalls: usage.toolCalls,\n\t\t\t\t\tmaintenanceRequests: usage.maintenanceRequests,\n\t\t\t\t\tstartedAtMs: usage.startedAt,\n\t\t\t\t};\n\t\t\t}\n\t\t: undefined;\n\n\tif (!resourceLoader) {\n\t\tresourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager });\n\t\tawait resourceLoader.reload();\n\t\ttime(\"resourceLoader.reload\");\n\t}\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.buildSessionContext();\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\tconst hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === \"thinking_level_change\");\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRuntime.getModel(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && modelRuntime.hasConfiguredAuth(restoredModel.provider)) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, use findInitialModel (checks settings default, then provider defaults)\n\tif (!model) {\n\t\tconst result = await findInitialModel({\n\t\t\tscopedModels: [],\n\t\t\tisContinuing: hasExistingSession,\n\t\t\tdefaultProvider: settingsManager.getDefaultProvider(),\n\t\t\tdefaultModelId: settingsManager.getDefaultModel(),\n\t\t\tdefaultThinkingLevel: settingsManager.getDefaultThinkingLevel(),\n\t\t\tmodelThinkingLevels: settingsManager.getAllModelThinkingLevels(),\n\t\t\tmodelRuntime,\n\t\t});\n\t\tmodel = result.model;\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = formatNoModelsAvailableMessage();\n\t\t} else if (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t}\n\t}\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = hasThinkingEntry\n\t\t\t? (existingSession.thinkingLevel as ThinkingLevel)\n\t\t\t: (settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);\n\t}\n\n\t// Fall back to per-model override, then global default\n\tif (thinkingLevel === undefined && model) {\n\t\tconst perModel = settingsManager.getModelThinkingLevel(model.provider, model.id);\n\t\tif (perModel) {\n\t\t\tthinkingLevel = perModel;\n\t\t}\n\t}\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;\n\t}\n\n\t// Clamp to model capabilities\n\tif (!model) {\n\t\tthinkingLevel = \"off\";\n\t} else {\n\t\tthinkingLevel = clampThinkingLevel(model, thinkingLevel) as ThinkingLevel;\n\t}\n\n\t// OAuth-capable MCP servers resolve tokens through the session's own credential\n\t// seam: direct and lock-serialized on the host, supervisor-mediated in a sandboxed\n\t// child, fail-closed when neither applies (spec 2026-09-01-mcp-oauth). Servers\n\t// without `auth: \"oauth\"` never touch it.\n\tconst mcpRuntime = createMcpRuntime(\n\t\tcwd,\n\t\tcreateSessionMcpConnector({\n\t\t\tcredentials: options.mcpCredentials ?? createSandboxCredentialStore() ?? AuthStorage.create(authPath),\n\t\t}),\n\t\t{ projectTrusted: settingsManager.isProjectTrusted() },\n\t);\n\n\t// `web_search`, `lsp`, and `mcp` join the core four only when configured. All stay\n\t// registered either way, so an explicit `--tools` selection still reaches them and an\n\t// unconfigured call still explains itself. Activating an unconfigured tool would put a\n\t// name in the prompt that can only ever fail.\n\tconst defaultActiveToolNames: string[] = [\n\t\t...([\"read\", \"bash\", \"edit\", \"write\"] satisfies ToolName[]),\n\t\t...(options.lspOperations ? [\"lsp\"] : []),\n\t\t...(options.webSearchOperations ? ([\"web_search\"] satisfies ToolName[]) : []),\n\t\t...(mcpRuntime ? [\"mcp\"] : []),\n\t];\n\tconst configuredDefaultToolNames = settingsManager.getDefaultTools();\n\tconst allowedToolNames = options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n\tconst excludedToolNames = options.excludeTools;\n\tconst excludedToolNameSet = excludedToolNames ? new Set(excludedToolNames) : undefined;\n\tconst initialActiveToolNames = (\n\t\toptions.tools ?? (options.noTools ? [] : (configuredDefaultToolNames ?? defaultActiveToolNames))\n\t).filter((name) => !excludedToolNameSet?.has(name));\n\n\tlet agent: Agent;\n\n\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\n\n\tconst extensionRunnerRef: { current?: ExtensionRunner } = {};\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: \"\",\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [],\n\t\t},\n\t\t// The resolved budget policy from above (override or settings); every\n\t\t// execution mode (interactive, print, JSON, RPC, ACP, SDK) runs through\n\t\t// this session, so none counts on its own\n\t\t// (spec 2026-09-01-tool-reliability-and-execution-budgets.md).\n\t\trunBudget,\n\t\tbudgetScope: options.budgetScope ?? \"prompt\",\n\t\t// The root aggregate when configured (the parent's own runs consume it,\n\t\t// per-prompt local scope unchanged), else a caller-supplied shared\n\t\t// controller, else nothing (spec 2026-09-09, \"Shared budgets\").\n\t\tsharedBudgetController,\n\t\tconvertToLlm: convertToLlmWithBlockImages,\n\t\tstreamFn: async (model, context, options) => {\n\t\t\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\t\t\tconst httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();\n\t\t\t// SDKs treat timeout=0 as 0ms (immediate timeout), not \"no timeout\".\n\t\t\t// Use max int32 to effectively disable the timeout.\n\t\t\tconst effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;\n\t\t\tconst timeoutMs = options?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;\n\t\t\tconst websocketConnectTimeoutMs =\n\t\t\t\toptions?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();\n\t\t\tconst headerRunner = extensionRunnerRef.current;\n\t\t\treturn modelRuntime.streamSimple(model, context, {\n\t\t\t\t...options,\n\t\t\t\ttimeoutMs,\n\t\t\t\twebsocketConnectTimeoutMs,\n\t\t\t\tmaxRetries: options?.maxRetries ?? providerRetrySettings.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,\n\t\t\t\ttransformHeaders: async (requestHeaders) => {\n\t\t\t\t\tconst headers = mergeProviderAttributionHeaders(\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tsettingsManager,\n\t\t\t\t\t\toptions?.sessionId,\n\t\t\t\t\t\trequestHeaders,\n\t\t\t\t\t);\n\t\t\t\t\treturn headerRunner?.hasHandlers(\"before_provider_headers\")\n\t\t\t\t\t\t? headerRunner.emitBeforeProviderHeaders(headers ?? {})\n\t\t\t\t\t\t: (headers ?? {});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tonPayload: async (payload, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"before_provider_request\")) {\n\t\t\t\treturn payload;\n\t\t\t}\n\t\t\treturn runner.emitBeforeProviderRequest(payload);\n\t\t},\n\t\tonResponse: async (response, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"after_provider_response\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runner.emit({\n\t\t\t\ttype: \"after_provider_response\",\n\t\t\t\tstatus: response.status,\n\t\t\t\theaders: response.headers,\n\t\t\t});\n\t\t},\n\t\tsessionId: sessionManager.getSessionId(),\n\t\ttransformContext: async (messages) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner) return messages;\n\t\t\treturn runner.emitContext(messages);\n\t\t},\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\ttransport: settingsManager.getTransport(),\n\t\tthinkingBudgets: settingsManager.getThinkingBudgets(),\n\t\tmaxRetryDelayMs: settingsManager.getProviderRetrySettings().maxRetryDelayMs,\n\t});\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.state.messages = existingSession.messages;\n\t\tif (!hasThinkingEntry) {\n\t\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t\t}\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\t// Forward ref, mirroring extensionRunnerRef above: the delegation runtime's\n\t// closures are needed to build `customTools` before `session` exists, but they\n\t// must read the *live* session (active tools can change after construction),\n\t// not a snapshot frozen at this point.\n\tconst parentSessionRef: { current?: AgentSession } = {};\n\tconst childRunRegistry = options.childRunRegistry ?? new ChildRunRegistry();\n\tconst customTools: ToolDefinition[] = options.customTools ? [...options.customTools] : [];\n\t// A configured permission gate supplies the authority a child must derive, so\n\t// discovery is enabled by default in real sessions. Callers that need fixture\n\t// definitions may still provide an explicit resolver.\n\tconst delegation = options.delegation ?? (options.permissionGate ? {} : undefined);\n\tlet delegationRuntime: DelegationRuntimeOptions | undefined;\n\tif (delegation) {\n\t\tconst parentPermissionGate = options.permissionGate;\n\t\tconst resolveAgent =\n\t\t\tdelegation.resolveAgent ??\n\t\t\tcreateAgentDefinitionResolver({\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tisProjectTrusted: () => settingsManager.isProjectTrusted(),\n\t\t\t});\n\t\tlet worktreeOwner: GitWorktreeWorkspaceOwner | undefined;\n\t\t// One read of the delegation bound for this runtime; the policy snapshot\n\t\t// below reports the same value it enforces instead of re-reading settings.\n\t\tconst delegationMaxDepth = settingsManager.getDelegationMaxDepth();\n\t\tdelegationRuntime = {\n\t\t\tchildRunRegistry,\n\t\t\tresolveAgent,\n\t\t\t// Concurrency cap (spec 2026-09-09, \"Shared budgets\"): the registry's\n\t\t\t// admission path reads it from the runtime options. Undefined is\n\t\t\t// unlimited.\n\t\t\tmaxConcurrentChildren: options.maxConcurrentChildren,\n\t\t\tgetParentCapabilities: () => {\n\t\t\t\tconst capabilities = new Set<Capability>();\n\t\t\t\tfor (const name of parentSessionRef.current?.getActiveToolNames() ?? []) {\n\t\t\t\t\tconst contract = (\n\t\t\t\t\t\tparentSessionRef.current?.getToolDefinition(name) as Partial<ApexToolDefinition> | undefined\n\t\t\t\t\t)?.contract;\n\t\t\t\t\tif (contract) for (const capability of contract.capabilities) capabilities.add(capability);\n\t\t\t\t}\n\t\t\t\treturn capabilities;\n\t\t\t},\n\t\t\tgetToolCapabilities: (toolName) => {\n\t\t\t\t// Prefer the parent's own live registry first (it also covers\n\t\t\t\t// extension/custom tools an agent definition might name), but fall back\n\t\t\t\t// to the canonical built-in registry: \"what capability does tool X\n\t\t\t\t// need\" is a property of the tool itself, independent of whether the\n\t\t\t\t// parent's own session restricted it out of its active/allowed set via\n\t\t\t\t// `tools`/`excludeTools` -- that restriction affects the parent's own\n\t\t\t\t// *authority* (getParentCapabilities, above), not what a named tool is.\n\t\t\t\tconst fromParent = (\n\t\t\t\t\tparentSessionRef.current?.getToolDefinition(toolName) as Partial<ApexToolDefinition> | undefined\n\t\t\t\t)?.contract?.capabilities;\n\t\t\t\tif (fromParent) return fromParent;\n\t\t\t\treturn (createAllToolDefinitions(cwd)[toolName as ToolName] as ApexToolDefinition | undefined)?.contract\n\t\t\t\t\t?.capabilities;\n\t\t\t},\n\t\t\t// Read fresh each call, not captured once: depth is a live property of\n\t\t\t// the (possibly delegated) session this createAgentSession call is\n\t\t\t// building, via the same sessionManager this closure already captures.\n\t\t\tgetDelegationDepth: () => sessionManager.getDelegationDepth(),\n\t\t\tmaxDelegationDepth: delegationMaxDepth,\n\t\t\tgetParentSessionDir: () => sessionManager.getSessionDir(),\n\t\t\t// Child-run records carry the parent session id so durable records and\n\t\t\t// protocol payloads tie each child to this session's own identity.\n\t\t\tgetParentSessionId: () => sessionManager.getSessionId(),\n\t\t\t// Worktree isolation (spec 2026-09-09, \"Parallel work and ownership\"):\n\t\t\t// the production workspace owner, constructed on the first worktree-\n\t\t\t// isolated delegation only. Shared-read delegations never read this\n\t\t\t// property (the runtime consults the owner only for isolation\n\t\t\t// \"worktree\"), so they never construct an owner and never invoke git.\n\t\t\tget workspaceOwner() {\n\t\t\t\tif (worktreeOwner === undefined) {\n\t\t\t\t\tworktreeOwner = new GitWorktreeWorkspaceOwner(cwd);\n\t\t\t\t}\n\t\t\t\treturn worktreeOwner;\n\t\t\t},\n\t\t\tbuildChildSession: async ({\n\t\t\t\tdefinition,\n\t\t\t\ttoolNames,\n\t\t\t\tcapabilities,\n\t\t\t\tdepth,\n\t\t\t\tsessionId,\n\t\t\t\tartifactDir,\n\t\t\t\tworkspace,\n\t\t\t\treattachSessionPath,\n\t\t\t\ttimeoutMs,\n\t\t\t}) => {\n\t\t\t\tif (!parentPermissionGate) {\n\t\t\t\t\tthrow new Error(\"delegate requires a permission gate configured on the parent session (ADR 0008).\");\n\t\t\t\t}\n\t\t\t\tconst childModel =\n\t\t\t\t\t(definition.model && modelRuntime.getAvailableSnapshot().find((m) => m.id === definition.model)) ||\n\t\t\t\t\tmodel;\n\t\t\t\tif (!childModel) {\n\t\t\t\t\tthrow new Error(`Cannot delegate to \"${definition.name}\": no model is available for the child session.`);\n\t\t\t\t}\n\t\t\t\t// The derived policy snapshot (spec 2026-09-09, \"Derive, do not\n\t\t\t\t// reconstruct\"): the exact values this construction used -- the\n\t\t\t\t// ceiling-checked tool allowlist, the admitted capability set from\n\t\t\t\t// the runtime's single admission projection (never a second\n\t\t\t\t// classification, ADR 0010), this session's sandbox contract, the\n\t\t\t\t// delegation bound it enforces, the child's model, and the budget\n\t\t\t\t// wiring every child is built with (session-scoped own controller;\n\t\t\t\t// aggregate only when a shared ceiling was configured at the root).\n\t\t\t\t// It rides on the returned handle so the registry persists it on the\n\t\t\t\t// child-run record, and `sandboxEnforced` reports whether the\n\t\t\t\t// OS-containment supervisor marker check passed for this parent\n\t\t\t\t// session (always true under the \"required\" contract, which refuses\n\t\t\t\t// construction without it).\n\t\t\t\tconst policy: ChildRunPolicySnapshot = {\n\t\t\t\t\ttools: [...toolNames],\n\t\t\t\t\tcapabilities: [...capabilities].sort(),\n\t\t\t\t\tsandbox: sandboxContract,\n\t\t\t\t\tmaxDelegationDepth: delegationMaxDepth,\n\t\t\t\t\tmodel: childModel.id,\n\t\t\t\t\tbudgetScope: \"session\",\n\t\t\t\t\taggregateBudget: sharedBudgetController !== undefined,\n\t\t\t\t};\n\t\t\t\tconst sandboxEnforced = markerPresent;\n\t\t\t\t// An isolated child runs inside the workspace owner's prepared root\n\t\t\t\t// (its linked worktree); a shared child keeps this session's cwd.\n\t\t\t\tconst childCwd = workspace?.root ?? cwd;\n\t\t\t\t// The one reattachment seam (restart reconstruction): when the request\n\t\t\t\t// carries the existing child session path, that transcript is OPENED\n\t\t\t\t// rather than created; identity (header id, parentSession, depth) comes\n\t\t\t\t// from the file's own header. Every other input below is derived\n\t\t\t\t// exactly as for a fresh delegation -- permission store, model, tools,\n\t\t\t\t// budget -- so there is no second construction path.\n\t\t\t\tconst childSessionManager = reattachSessionPath\n\t\t\t\t\t? SessionManager.open(reattachSessionPath, artifactDir)\n\t\t\t\t\t: artifactDir\n\t\t\t\t\t\t? SessionManager.create(childCwd, artifactDir, {\n\t\t\t\t\t\t\t\tid: sessionId,\n\t\t\t\t\t\t\t\tparentSession: sessionManager.getSessionId(),\n\t\t\t\t\t\t\t\tdelegationDepth: depth,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: SessionManager.inMemory(childCwd, {\n\t\t\t\t\t\t\t\tparentSession: sessionManager.getSessionId(),\n\t\t\t\t\t\t\t\tdelegationDepth: depth,\n\t\t\t\t\t\t\t});\n\t\t\t\tconst derivedStore = new DerivedPermissionRuleStore({ parent: parentPermissionGate.store });\n\t\t\t\tconst { session: childSession } = await createAgentSession({\n\t\t\t\t\tcwd: childCwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tmodel: childModel,\n\t\t\t\t\tmodelRuntime,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\t// The parent's already-resolved per-run budget (override or settings),\n\t\t\t\t\t// not a fresh settings read: every child run carries the same per-run\n\t\t\t\t\t// policy as its parent (spec 2026-09-09, \"Shared budgets\").\n\t\t\t\t\t//\n\t\t\t\t\t// Session scope + the root aggregate: a resumed or follow-up child\n\t\t\t\t\t// turn continues the same child budget (one controller per child\n\t\t\t\t\t// Agent, created at its first turn), and every gate also answers\n\t\t\t\t\t// to the tree's shared ceiling -- accepted consumption records to\n\t\t\t\t\t// both the child's own controller and the aggregate. THE SAME\n\t\t\t\t\t// aggregate instance reaches every descendant regardless of\n\t\t\t\t\t// depth (a grandchild's parent forwards it onward), so there is\n\t\t\t\t\t// exactly ONE aggregate per root tree and no child can reset it\n\t\t\t\t\t// by resuming or spawning children (spec 2026-09-09, \"Shared\n\t\t\t\t\t// budgets\"). Without an aggregate there is no shared controller:\n\t\t\t\t\t// the child keeps local-only budgets under the inherited policy.\n\t\t\t\t\t//\n\t\t\t\t\t// A launch timeout (spec 2026-09-09, timeouts) overrides the\n\t\t\t\t\t// child's OWN wall-time limit with the requested timeoutMs, so the\n\t\t\t\t\t// existing AgentRunBudget wall-time gate enforces it mid-run; the\n\t\t\t\t\t// parent policy's other limits still apply unchanged.\n\t\t\t\t\trunBudget: timeoutMs === undefined ? runBudget : { ...runBudget, maxWallTimeMs: timeoutMs },\n\t\t\t\t\tbudgetScope: \"session\",\n\t\t\t\t\tsharedBudgetController,\n\t\t\t\t\t// The same per-parent admission cap applies to a child's own\n\t\t\t\t\t// delegations (each runtime counts its direct children).\n\t\t\t\t\tmaxConcurrentChildren: options.maxConcurrentChildren,\n\t\t\t\t\tsessionManager: childSessionManager,\n\t\t\t\t\tresourceLoader,\n\t\t\t\t\ttools: toolNames,\n\t\t\t\t\t// No responder: a child's `ask` fails closed rather than prompting the\n\t\t\t\t\t// human for a call the human did not make (ADR 0008, \"Who answers a\n\t\t\t\t\t// child's ask\").\n\t\t\t\t\tpermissionGate: { store: derivedStore, getMode: parentPermissionGate.getMode },\n\t\t\t\t\t// A delegated child shares the parent's cwd-bound LSP pool (spec, \"no\n\t\t\t\t\t// multi-root LSP connection and no sharing across cwd-bound service\n\t\t\t\t\t// lifetimes\" -- delegated children are the one sharing exception).\n\t\t\t\t\tdiagnosticsOperations: options.diagnosticsOperations,\n\t\t\t\t\tlspOperations: options.lspOperations,\n\t\t\t\t\t// Shared for the same reason as the LSP pool: the backend was resolved\n\t\t\t\t\t// once (possibly by running a shell command for the key) and a child\n\t\t\t\t\t// that re-resolved nothing would hold a `web_search` that only throws.\n\t\t\t\t\twebSearchOperations: options.webSearchOperations,\n\t\t\t\t\t// `checkpointSettings` is deliberately *not* forwarded. A child shares the\n\t\t\t\t\t// parent's cwd, so it would write refs under its own session id into the\n\t\t\t\t\t// same repository and interleave them with the parent's. The parent's\n\t\t\t\t\t// per-turn capture already covers everything a child does inside that turn.\n\n\t\t\t\t\t// Forwarded so a child that itself holds `delegate` can delegate again\n\t\t\t\t\t// (bounded by the depth guard above, read fresh from its own session\n\t\t\t\t\t// header on its next createAgentSession call) -- otherwise recursion\n\t\t\t\t\t// would be silently capped at one level regardless of maxDelegationDepth.\n\t\t\t\t\tdelegation,\n\t\t\t\t\tsandbox: sandboxContract,\n\t\t\t\t});\n\t\t\t\tawait childSession.bindExtensions({});\n\t\t\t\tlet status: import(\"./delegation/runtime.ts\").ChildSessionStatus = \"idle\";\n\t\t\t\tlet runPromise: Promise<void> | undefined;\n\t\t\t\tlet lastTurnResult: ChildTurnResult | undefined;\n\t\t\t\t// The captured structured terminal outcome of the run in flight\n\t\t\t\t// (`agent_end`'s stopReason). Budget refusals emit agent_end without\n\t\t\t\t// an assistant message, so this is the only way the settlement below\n\t\t\t\t// can see and name them.\n\t\t\t\tlet runStopReason: AgentStopReason | undefined;\n\t\t\t\tconst ensureOpen = () => {\n\t\t\t\t\tif (status === \"closed\") throw new Error(\"Child session is closed.\");\n\t\t\t\t};\n\t\t\t\tconst start = (input: string): Promise<void> => {\n\t\t\t\t\tensureOpen();\n\t\t\t\t\tif (runPromise) throw new Error(\"Child session is already running.\");\n\t\t\t\t\tstatus = \"running\";\n\t\t\t\t\trunStopReason = undefined;\n\t\t\t\t\t// Capture the run's structured terminal outcome: a budget refusal\n\t\t\t\t\t// emits agent_end without producing an assistant message, so the\n\t\t\t\t\t// message-based checks below cannot see it.\n\t\t\t\t\tconst unsubscribeStop = childSession.subscribe((event) => {\n\t\t\t\t\t\tif (event.type === \"agent_end\") runStopReason = event.stopReason;\n\t\t\t\t\t});\n\t\t\t\t\tconst pending = childSession\n\t\t\t\t\t\t.prompt(input)\n\t\t\t\t\t\t.then(\n\t\t\t\t\t\t\t() => {\n\t\t\t\t\t\t\t\tunsubscribeStop();\n\t\t\t\t\t\t\t\tif (status === \"closed\") {\n\t\t\t\t\t\t\t\t\tlastTurnResult = { outcome: \"failed\", output: \"\" };\n\t\t\t\t\t\t\t\t\tthrow new Error(\"Child session is closed.\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (status === \"interrupted\") {\n\t\t\t\t\t\t\t\t\tlastTurnResult = { outcome: \"interrupted\", output: extractFinalAssistantText(childSession) };\n\t\t\t\t\t\t\t\t\tthrow new Error(\"Child session is interrupted.\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst lastAssistant = [...childSession.agent.state.messages]\n\t\t\t\t\t\t\t\t\t.reverse()\n\t\t\t\t\t\t\t\t\t.find((message) => message.role === \"assistant\");\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\tlastAssistant?.role === \"assistant\" &&\n\t\t\t\t\t\t\t\t\t(lastAssistant.stopReason === \"aborted\" || lastAssistant.stopReason === \"error\")\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\tstatus = \"interrupted\";\n\t\t\t\t\t\t\t\t\tlastTurnResult = {\n\t\t\t\t\t\t\t\t\t\toutcome: lastAssistant.stopReason === \"aborted\" ? \"interrupted\" : \"failed\",\n\t\t\t\t\t\t\t\t\t\toutput: lastAssistant.errorMessage || extractFinalAssistantText(childSession),\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\tthrow new Error(lastAssistant.errorMessage || \"Child session was interrupted.\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tstatus = \"idle\";\n\t\t\t\t\t\t\t\tlastTurnResult = { outcome: \"completed\", output: extractFinalAssistantText(childSession) };\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t(error) => {\n\t\t\t\t\t\t\t\tunsubscribeStop();\n\t\t\t\t\t\t\t\tif (status !== \"closed\") status = \"interrupted\";\n\t\t\t\t\t\t\t\tlastTurnResult =\n\t\t\t\t\t\t\t\t\tstatus === \"closed\"\n\t\t\t\t\t\t\t\t\t\t? { outcome: \"failed\", output: \"\" }\n\t\t\t\t\t\t\t\t\t\t: { outcome: \"interrupted\", output: extractFinalAssistantText(childSession) };\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\t\trunPromise = undefined;\n\t\t\t\t\t\t});\n\t\t\t\t\trunPromise = pending;\n\t\t\t\t\treturn pending;\n\t\t\t\t};\n\t\t\t\tconst sendInput = (input: string) => {\n\t\t\t\t\tensureOpen();\n\t\t\t\t\tif (runPromise) {\n\t\t\t\t\t\tif (status !== \"running\") throw new Error(\"Child session is still stopping.\");\n\t\t\t\t\t\t// A follow-up queued onto a live run settles through that run's\n\t\t\t\t\t\t// own loop; only turns that settle here pass through the gate.\n\t\t\t\t\t\treturn childSession.followUp(input);\n\t\t\t\t\t}\n\t\t\t\t\treturn start(input).then(() => requireVerifiedTurn());\n\t\t\t\t};\n\t\t\t\tconst close = () => {\n\t\t\t\t\tif (status === \"closed\") return;\n\t\t\t\t\tstatus = \"closed\";\n\t\t\t\t\tchildSession.dispose();\n\t\t\t\t};\n\t\t\t\t// Verification gate (spec 2026-09-09, \"Verification at completion\"):\n\t\t\t\t// a child with configured verification policies may not settle a turn\n\t\t\t\t// as successful unless the session's canonical tracker reports\n\t\t\t\t// \"verified\". The tracker is the only verifier; no child-local one is\n\t\t\t\t// introduced. With the \"explicit\" boundary the gate runs\n\t\t\t\t// requestVerification once here; with the \"post-turn\" boundary the\n\t\t\t\t// session already ran verification at its own turn boundary, so the\n\t\t\t\t// gate only reads the status. Any other completion status --\n\t\t\t\t// failed/unavailable/interrupted/continued-unverified -- fails the\n\t\t\t\t// turn with the status named in the error.\n\t\t\t\tconst requireVerifiedTurn = async (): Promise<void> => {\n\t\t\t\t\tconst policyIds = childSession.verificationPolicyIds();\n\t\t\t\t\tif (policyIds.length === 0) return;\n\t\t\t\t\tconst verificationStatus =\n\t\t\t\t\t\tchildSession.verificationBoundary() === \"explicit\"\n\t\t\t\t\t\t\t? await childSession.requestVerification()\n\t\t\t\t\t\t\t: childSession.verificationStatus();\n\t\t\t\t\tif (verificationStatus === \"verified\") return;\n\t\t\t\t\tconst message = `Child verification failed: ${verificationStatus} (policies: ${policyIds.join(\", \")}).`;\n\t\t\t\t\tlastTurnResult = { outcome: \"failed\", output: message };\n\t\t\t\t\tthrow new Error(message);\n\t\t\t\t};\n\t\t\t\treturn {\n\t\t\t\t\tget status() {\n\t\t\t\t\t\treturn status;\n\t\t\t\t\t},\n\t\t\t\t\tlatestResult: () => lastTurnResult,\n\t\t\t\t\tusage: () => childSession.agent.budgetUsage(),\n\t\t\t\t\t// The usage-rollup seam (spec 2026-09-09): the registry reads the\n\t\t\t\t\t// child's own transcript file when one exists, and falls back to\n\t\t\t\t\t// these in-memory entries only for a child that never persisted a\n\t\t\t\t\t// transcript. Read-only; the child's SessionManager stays the owner.\n\t\t\t\t\tsessionEntries: () => childSessionManager.getEntries(),\n\t\t\t\t\tasync run(task: string) {\n\t\t\t\t\t\tconst prompt = definition.systemPrompt\n\t\t\t\t\t\t\t? `${definition.systemPrompt}\\n\\nTask: ${task}`\n\t\t\t\t\t\t\t: `Task: ${task}`;\n\t\t\t\t\t\tawait start(prompt);\n\t\t\t\t\t\tif (status === \"closed\" || status === \"interrupted\") throw new Error(`Child session is ${status}.`);\n\t\t\t\t\t\t// The launch timeout's settlement error path (spec 2026-09-09,\n\t\t\t\t\t\t// timeouts): a run refused at the child's own wall-time gate never\n\t\t\t\t\t\t// started meaningful work, so the delegation settles failed with\n\t\t\t\t\t\t// the exhausted limit named, reusing the budget's existing\n\t\t\t\t\t\t// exhaustedLimit vocabulary. Other budget refusals keep their\n\t\t\t\t\t\t// existing semantics (the refusal is named in the child transcript\n\t\t\t\t\t\t// and the prior result stands).\n\t\t\t\t\t\tif (runStopReason?.kind === \"budget-exhausted\" && runStopReason.limit === \"wall-time\") {\n\t\t\t\t\t\t\tconst message = `Child run stopped before completing: the run's ${runStopReason.limit} budget was exhausted.`;\n\t\t\t\t\t\t\tlastTurnResult = { outcome: \"failed\", output: message };\n\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Delegated work cannot claim success when the child has a\n\t\t\t\t\t\t// required verification boundary and verification did not pass.\n\t\t\t\t\t\t// Use the session's canonical tracker rather than introducing\n\t\t\t\t\t\t// a second child-only verifier.\n\t\t\t\t\t\tawait requireVerifiedTurn();\n\t\t\t\t\t\treturn { output: extractFinalAssistantText(childSession) };\n\t\t\t\t\t},\n\t\t\t\t\twait: async () => {\n\t\t\t\t\t\twhile (runPromise) await runPromise;\n\t\t\t\t\t},\n\t\t\t\t\tinterrupt: () => {\n\t\t\t\t\t\tensureOpen();\n\t\t\t\t\t\tif (status === \"running\") {\n\t\t\t\t\t\t\tstatus = \"interrupted\";\n\t\t\t\t\t\t\tvoid childSession.abort().catch(() => undefined);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tclose,\n\t\t\t\t\tsendInput,\n\t\t\t\t\tfollowUp: sendInput,\n\t\t\t\t\tdispose: close,\n\t\t\t\t\t// Construction linkage (spec 2026-09-09, policy/sandbox/artifact\n\t\t\t\t\t// linkage): the registry relays these onto the persisted child_run\n\t\t\t\t\t// record and every status/wait payload derived from it.\n\t\t\t\t\tpolicy,\n\t\t\t\t\tsandboxEnforced,\n\t\t\t\t};\n\t\t\t},\n\t\t};\n\t\tcustomTools.push(createDelegateToolDefinition(delegationRuntime) as ToolDefinition<any, any>);\n\t\t// Historical resume (restart reconstruction) reattaches a persisted child\n\t\t// through THIS runtime's buildChildSession seam. Wiring it here -- not only\n\t\t// at the first delegation -- is what makes resume work on a freshly\n\t\t// reopened session before any new delegation has run.\n\t\tchildRunRegistry.setRuntimeOptions(delegationRuntime);\n\t}\n\n\tconst session = new AgentSession({\n\t\tchildRunRegistry,\n\t\tdelegationRuntime,\n\t\tagent,\n\t\t// Root aggregate usage (spec 2026-09-09, \"Shared budgets\"): undefined\n\t\t// when the tree has no aggregate budget.\n\t\taggregateBudgetUsage,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tscopedModels: options.scopedModels,\n\t\tresourceLoader,\n\t\tcustomTools,\n\t\tmodelRuntime,\n\t\tinitialActiveToolNames,\n\t\tallowedToolNames,\n\t\texcludedToolNames,\n\t\textensionRunnerRef,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t\tpermissionGate: options.permissionGate,\n\t\tpermissionResponderFactory: options.permissionResponderFactory,\n\t\tevidenceSink: options.evidenceSink,\n\t\tdiagnosticsOperations: options.diagnosticsOperations,\n\t\tlspOperations: options.lspOperations,\n\t\twebSearchOperations: options.webSearchOperations,\n\t\tmcpRuntime,\n\t\tcheckpointSettings: settingsManager.getCheckpointSettings(),\n\t\t// Declarative hooks (spec 2026-08-31-declarative-hooks): assembled from the\n\t\t// merged settings -- project-scope entries only appear once trusted. A\n\t\t// malformed hooks key throws here, failing closed at wiring. Deliberately\n\t\t// not forwarded to delegation children (see the spec's boundary note).\n\t\thookRuntime: options.hookRuntime ?? loadHookRuntime(settingsManager.getHookSettings()),\n\t\tbackgroundShellRegistry,\n\t});\n\tparentSessionRef.current = session;\n\t// Eager servers connect here rather than on first use, so their tools are in the\n\t// cache before the model's first search. Detached: a slow or broken server delays\n\t// nothing, and `warmEagerServers` already swallows its own failures.\n\tvoid mcpRuntime?.warm();\n\tconst extensionsResult = resourceLoader.getExtensions();\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tdelegationRuntime,\n\t\tmodelFallbackMessage,\n\t\tsandboxContract,\n\t\tsandboxDiagnostic,\n\t};\n}\n"]}
@@ -4,6 +4,10 @@ import { type ApexToolDefinition } from "./contract.ts";
4
4
  declare const delegateSchema: Type.TUnion<[Type.TObject<{
5
5
  agentType: Type.TString;
6
6
  task: Type.TString;
7
+ workspace: Type.TOptional<Type.TObject<{
8
+ isolation: Type.TUnion<[Type.TLiteral<"shared-read">, Type.TLiteral<"worktree">]>;
9
+ ownedPaths: Type.TOptional<Type.TArray<Type.TString>>;
10
+ }>>;
7
11
  background: Type.TOptional<Type.TBoolean>;
8
12
  }>, Type.TObject<{
9
13
  agentType: Type.TString;
@@ -31,6 +35,10 @@ export declare function createDelegateToolDefinition(runtime: DelegationRuntimeO
31
35
  export declare function createDelegateTool(runtime: DelegationRuntimeOptions): import("apex-code-agent-core").AgentTool<Type.TUnion<[Type.TObject<{
32
36
  agentType: Type.TString;
33
37
  task: Type.TString;
38
+ workspace: Type.TOptional<Type.TObject<{
39
+ isolation: Type.TUnion<[Type.TLiteral<"shared-read">, Type.TLiteral<"worktree">]>;
40
+ ownedPaths: Type.TOptional<Type.TArray<Type.TString>>;
41
+ }>>;
34
42
  background: Type.TOptional<Type.TBoolean>;
35
43
  }>, Type.TObject<{
36
44
  agentType: Type.TString;
@@ -1 +1 @@
1
- {"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../../../src/core/tools/delegate.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,OAAO,EAAE,KAAK,kBAAkB,EAAkC,MAAM,eAAe,CAAC;AAgBxF,QAAA,MAAM,cAAc;;;;;;;IAUnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAgBD;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,wBAAwB,GAC/B,kBAAkB,CAAC,OAAO,cAAc,EAAE,eAAe,CAAC,CAiD5D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,wBAAwB;;;;;;;uBAEnE","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { AgentToolResult } from \"apex-code-agent-core\";\nimport { minimatch } from \"minimatch\";\nimport { type Static, Type } from \"typebox\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { DelegationRuntimeOptions } from \"../delegation/runtime.ts\";\nimport { retrieveDelegationResult, runDelegation } from \"../delegation/runtime.ts\";\nimport { type ApexToolDefinition, type EvidenceRecord, toolUnion } from \"./contract.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst delegateSchemaProperties = {\n\tagentType: Type.String({\n\t\tdescription: \"The subagent type. Required both to launch a task and to retrieve a background result.\",\n\t}),\n\ttask: Type.String({ description: \"The task to delegate. Supply it to launch a delegation.\" }),\n\tbackground: Type.Optional(\n\t\tType.Boolean({ description: \"Return a handle immediately instead of waiting for the child.\" }),\n\t),\n\thandle: Type.String({\n\t\tdescription: \"A background delegation handle returned by an earlier call. Supply it to retrieve the result.\",\n\t}),\n};\n\nconst delegateSchema = toolUnion(\n\t[\n\t\tType.Object({\n\t\t\tagentType: Type.String(),\n\t\t\ttask: Type.String(),\n\t\t\tbackground: Type.Optional(Type.Boolean()),\n\t\t}),\n\t\tType.Object({ agentType: Type.String(), handle: Type.String() }),\n\t],\n\tdelegateSchemaProperties,\n);\n\nexport type DelegateInput = Static<typeof delegateSchema>;\n\nexport interface DelegateDetails {\n\tagentType: string;\n\ttask: string;\n\toutput: string;\n\thandle?: string;\n}\n\nfunction formatDelegateCall(input: DelegateInput, theme: Theme): string {\n\tif (\"handle\" in input) {\n\t\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · retrieve`;\n\t}\n\tconst task = input.task.replace(/\\s+/g, \" \").trim();\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · ${theme.fg(\"toolOutput\", task)}`;\n}\n\nfunction formatDelegateResult(details: DelegateDetails, expanded: boolean, theme: Theme): string {\n\tif (expanded) return theme.fg(\"toolOutput\", details.output);\n\tconst lineCount = details.output ? details.output.split(\"\\n\").length : 0;\n\treturn `${theme.fg(\"accent\", details.agentType)} · ${lineCount} ${lineCount === 1 ? \"line\" : \"lines\"}`;\n}\n\n/**\n * The delegation entry point (task 4.6's contract, task 5.2's execution). Runs a\n * real child through the injected `DelegationRuntimeOptions` -- capability ceiling,\n * derived permission store, and child-session construction all live behind that\n * injection (ADR 0008), matching the `todo_write`/`tool_schema` convention of\n * injecting collaborators rather than reaching for global state. Recursion\n * depth, artifact isolation, and real agent discovery are wired:\n * `../delegation/runtime.ts` bounds depth and roots per-child artifact\n * directories, and `../delegation/agents.ts` supplies production markdown\n * discovery through the injected resolver.\n */\nexport function createDelegateToolDefinition(\n\truntime: DelegationRuntimeOptions,\n): ApexToolDefinition<typeof delegateSchema, DelegateDetails> {\n\treturn {\n\t\tname: \"delegate\",\n\t\tlabel: \"delegate\",\n\t\tdescription: \"Delegate a task to a subagent.\",\n\t\tparameters: delegateSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"delegate\"]),\n\t\t\tpermission: {\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tmatches: (ruleContent, params) => minimatch(params.agentType, ruleContent),\n\t\t\t\tdescribe: (ruleContent) => `Delegate to agent types matching \"${ruleContent}\"`,\n\t\t\t\truleForCall: (params) => params.agentType,\n\t\t\t},\n\t\t\tcontext: { resultRecoverable: false, deferSchema: true },\n\t\t\tevidence: {\n\t\t\t\temits: new Set([\"workflow\"]),\n\t\t\t\tcapture: (params): EvidenceRecord[] =>\n\t\t\t\t\t\"task\" in params\n\t\t\t\t\t\t? [{ kind: \"workflow\", agentType: params.agentType, task: params.task }]\n\t\t\t\t\t\t: [{ kind: \"workflow\", agentType: params.agentType, handle: params.handle }],\n\t\t\t},\n\t\t},\n\t\tasync execute(_toolCallId, input: DelegateInput): Promise<AgentToolResult<DelegateDetails>> {\n\t\t\tconst result =\n\t\t\t\t\"task\" in input\n\t\t\t\t\t? await runDelegation(runtime, input.agentType, input.task, { background: input.background })\n\t\t\t\t\t: await retrieveDelegationResult(runtime, input.handle, input.agentType);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: result.output }],\n\t\t\t\tdetails: {\n\t\t\t\t\tagentType: result.agentType,\n\t\t\t\t\ttask: result.task,\n\t\t\t\t\toutput: result.output,\n\t\t\t\t\thandle: result.handleId,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\trenderCall(input, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateCall(input, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateResult(result.details, options.expanded, theme));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDelegateTool(runtime: DelegationRuntimeOptions) {\n\treturn wrapToolDefinition(createDelegateToolDefinition(runtime));\n}\n"]}
1
+ {"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../../../src/core/tools/delegate.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,OAAO,EAAE,KAAK,kBAAkB,EAAkC,MAAM,eAAe,CAAC;AAsCxF,QAAA,MAAM,cAAc;;;;;;;;;;;IAWnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAgBD;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,wBAAwB,GAC/B,kBAAkB,CAAC,OAAO,cAAc,EAAE,eAAe,CAAC,CAmE5D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,wBAAwB;;;;;;;;;;;uBAEnE","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { AgentToolResult } from \"apex-code-agent-core\";\nimport { minimatch } from \"minimatch\";\nimport { type Static, Type } from \"typebox\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { DelegationRuntimeOptions } from \"../delegation/runtime.ts\";\nimport { retrieveDelegationResult, runDelegation } from \"../delegation/runtime.ts\";\nimport { type ApexToolDefinition, type EvidenceRecord, toolUnion } from \"./contract.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst workspaceSchema = Type.Object({\n\tisolation: Type.Union([Type.Literal(\"shared-read\"), Type.Literal(\"worktree\")], {\n\t\tdescription:\n\t\t\t'Child workspace isolation: \"shared-read\" runs in the parent checkout; \"worktree\" gives the child its own git worktree.',\n\t}),\n\townedPaths: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription:\n\t\t\t\t\"Workspace-relative paths the child owns for writes. Advisory claims; overlapping claims are refused.\",\n\t\t}),\n\t),\n});\n\nconst delegateSchemaProperties = {\n\tagentType: Type.String({\n\t\tdescription: \"The subagent type. Required both to launch a task and to retrieve a background result.\",\n\t}),\n\ttask: Type.String({ description: \"The task to delegate. Supply it to launch a delegation.\" }),\n\tworkspace: Type.Optional(\n\t\tType.Object(\n\t\t\t{\n\t\t\t\tisolation: workspaceSchema.properties.isolation,\n\t\t\t\townedPaths: workspaceSchema.properties.ownedPaths,\n\t\t\t},\n\t\t\t{ description: \"The child's requested workspace authority. Defaults to shared-read with no owned paths.\" },\n\t\t),\n\t),\n\tbackground: Type.Optional(\n\t\tType.Boolean({ description: \"Return a handle immediately instead of waiting for the child.\" }),\n\t),\n\thandle: Type.String({\n\t\tdescription: \"A background delegation handle returned by an earlier call. Supply it to retrieve the result.\",\n\t}),\n};\n\nconst delegateSchema = toolUnion(\n\t[\n\t\tType.Object({\n\t\t\tagentType: Type.String(),\n\t\t\ttask: Type.String(),\n\t\t\tworkspace: Type.Optional(workspaceSchema),\n\t\t\tbackground: Type.Optional(Type.Boolean()),\n\t\t}),\n\t\tType.Object({ agentType: Type.String(), handle: Type.String() }),\n\t],\n\tdelegateSchemaProperties,\n);\n\nexport type DelegateInput = Static<typeof delegateSchema>;\n\nexport interface DelegateDetails {\n\tagentType: string;\n\ttask: string;\n\toutput: string;\n\thandle?: string;\n}\n\nfunction formatDelegateCall(input: DelegateInput, theme: Theme): string {\n\tif (\"handle\" in input) {\n\t\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · retrieve`;\n\t}\n\tconst task = input.task.replace(/\\s+/g, \" \").trim();\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · ${theme.fg(\"toolOutput\", task)}`;\n}\n\nfunction formatDelegateResult(details: DelegateDetails, expanded: boolean, theme: Theme): string {\n\tif (expanded) return theme.fg(\"toolOutput\", details.output);\n\tconst lineCount = details.output ? details.output.split(\"\\n\").length : 0;\n\treturn `${theme.fg(\"accent\", details.agentType)} · ${lineCount} ${lineCount === 1 ? \"line\" : \"lines\"}`;\n}\n\n/**\n * The delegation entry point (task 4.6's contract, task 5.2's execution). Runs a\n * real child through the injected `DelegationRuntimeOptions` -- capability ceiling,\n * derived permission store, and child-session construction all live behind that\n * injection (ADR 0008), matching the `todo_write`/`tool_schema` convention of\n * injecting collaborators rather than reaching for global state. Recursion\n * depth, artifact isolation, and real agent discovery are wired:\n * `../delegation/runtime.ts` bounds depth and roots per-child artifact\n * directories, and `../delegation/agents.ts` supplies production markdown\n * discovery through the injected resolver.\n */\nexport function createDelegateToolDefinition(\n\truntime: DelegationRuntimeOptions,\n): ApexToolDefinition<typeof delegateSchema, DelegateDetails> {\n\treturn {\n\t\tname: \"delegate\",\n\t\tlabel: \"delegate\",\n\t\tdescription: \"Delegate a task to a subagent.\",\n\t\tparameters: delegateSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"delegate\"]),\n\t\t\tpermission: {\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tmatches: (ruleContent, params) => minimatch(params.agentType, ruleContent),\n\t\t\t\tdescribe: (ruleContent) => `Delegate to agent types matching \"${ruleContent}\"`,\n\t\t\t\truleForCall: (params) => params.agentType,\n\t\t\t},\n\t\t\tcontext: { resultRecoverable: false, deferSchema: true },\n\t\t\tevidence: {\n\t\t\t\temits: new Set([\"workflow\"]),\n\t\t\t\t// capture runs in afterToolCall with the completed result, so a launch\n\t\t\t\t// can carry its handle even though the params could not know it: the\n\t\t\t\t// handle is the child's session id, which names the child's session\n\t\t\t\t// file and artifact dir under the parent's delegations/. This reuses\n\t\t\t\t// the existing WorkflowEvidenceRecord.handle field -- no contract or\n\t\t\t\t// sink shape change (the per-child session linkage is the evidence\n\t\t\t\t// model; see docs/plans/2026-09-09-run-and-child-session-architecture.md).\n\t\t\t\tcapture: (params, result): EvidenceRecord[] =>\n\t\t\t\t\t\"task\" in params\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkind: \"workflow\",\n\t\t\t\t\t\t\t\t\tagentType: params.agentType,\n\t\t\t\t\t\t\t\t\ttask: params.task,\n\t\t\t\t\t\t\t\t\thandle: result.details.handle,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: [{ kind: \"workflow\", agentType: params.agentType, handle: params.handle }],\n\t\t\t},\n\t\t},\n\t\tasync execute(_toolCallId, input: DelegateInput): Promise<AgentToolResult<DelegateDetails>> {\n\t\t\tconst workspace =\n\t\t\t\t\"task\" in input && input.workspace\n\t\t\t\t\t? { isolation: input.workspace.isolation, ownedPaths: input.workspace.ownedPaths ?? [] }\n\t\t\t\t\t: undefined;\n\t\t\tconst result =\n\t\t\t\t\"task\" in input\n\t\t\t\t\t? await runDelegation(runtime, input.agentType, input.task, { background: input.background, workspace })\n\t\t\t\t\t: await retrieveDelegationResult(runtime, input.handle, input.agentType);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: result.output }],\n\t\t\t\tdetails: {\n\t\t\t\t\tagentType: result.agentType,\n\t\t\t\t\ttask: result.task,\n\t\t\t\t\toutput: result.output,\n\t\t\t\t\thandle: result.handleId,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\trenderCall(input, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateCall(input, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateResult(result.details, options.expanded, theme));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDelegateTool(runtime: DelegationRuntimeOptions) {\n\treturn wrapToolDefinition(createDelegateToolDefinition(runtime));\n}\n"]}
@@ -4,11 +4,23 @@ import { Type } from "typebox";
4
4
  import { retrieveDelegationResult, runDelegation } from "../delegation/runtime.js";
5
5
  import { toolUnion } from "./contract.js";
6
6
  import { wrapToolDefinition } from "./tool-definition-wrapper.js";
7
+ const workspaceSchema = Type.Object({
8
+ isolation: Type.Union([Type.Literal("shared-read"), Type.Literal("worktree")], {
9
+ description: 'Child workspace isolation: "shared-read" runs in the parent checkout; "worktree" gives the child its own git worktree.',
10
+ }),
11
+ ownedPaths: Type.Optional(Type.Array(Type.String(), {
12
+ description: "Workspace-relative paths the child owns for writes. Advisory claims; overlapping claims are refused.",
13
+ })),
14
+ });
7
15
  const delegateSchemaProperties = {
8
16
  agentType: Type.String({
9
17
  description: "The subagent type. Required both to launch a task and to retrieve a background result.",
10
18
  }),
11
19
  task: Type.String({ description: "The task to delegate. Supply it to launch a delegation." }),
20
+ workspace: Type.Optional(Type.Object({
21
+ isolation: workspaceSchema.properties.isolation,
22
+ ownedPaths: workspaceSchema.properties.ownedPaths,
23
+ }, { description: "The child's requested workspace authority. Defaults to shared-read with no owned paths." })),
12
24
  background: Type.Optional(Type.Boolean({ description: "Return a handle immediately instead of waiting for the child." })),
13
25
  handle: Type.String({
14
26
  description: "A background delegation handle returned by an earlier call. Supply it to retrieve the result.",
@@ -18,6 +30,7 @@ const delegateSchema = toolUnion([
18
30
  Type.Object({
19
31
  agentType: Type.String(),
20
32
  task: Type.String(),
33
+ workspace: Type.Optional(workspaceSchema),
21
34
  background: Type.Optional(Type.Boolean()),
22
35
  }),
23
36
  Type.Object({ agentType: Type.String(), handle: Type.String() }),
@@ -63,14 +76,31 @@ export function createDelegateToolDefinition(runtime) {
63
76
  context: { resultRecoverable: false, deferSchema: true },
64
77
  evidence: {
65
78
  emits: new Set(["workflow"]),
66
- capture: (params) => "task" in params
67
- ? [{ kind: "workflow", agentType: params.agentType, task: params.task }]
79
+ // capture runs in afterToolCall with the completed result, so a launch
80
+ // can carry its handle even though the params could not know it: the
81
+ // handle is the child's session id, which names the child's session
82
+ // file and artifact dir under the parent's delegations/. This reuses
83
+ // the existing WorkflowEvidenceRecord.handle field -- no contract or
84
+ // sink shape change (the per-child session linkage is the evidence
85
+ // model; see docs/plans/2026-09-09-run-and-child-session-architecture.md).
86
+ capture: (params, result) => "task" in params
87
+ ? [
88
+ {
89
+ kind: "workflow",
90
+ agentType: params.agentType,
91
+ task: params.task,
92
+ handle: result.details.handle,
93
+ },
94
+ ]
68
95
  : [{ kind: "workflow", agentType: params.agentType, handle: params.handle }],
69
96
  },
70
97
  },
71
98
  async execute(_toolCallId, input) {
99
+ const workspace = "task" in input && input.workspace
100
+ ? { isolation: input.workspace.isolation, ownedPaths: input.workspace.ownedPaths ?? [] }
101
+ : undefined;
72
102
  const result = "task" in input
73
- ? await runDelegation(runtime, input.agentType, input.task, { background: input.background })
103
+ ? await runDelegation(runtime, input.agentType, input.task, { background: input.background, workspace })
74
104
  : await retrieveDelegationResult(runtime, input.handle, input.agentType);
75
105
  return {
76
106
  content: [{ type: "text", text: result.output }],
@@ -1 +1 @@
1
- {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../../src/core/tools/delegate.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { AgentToolResult } from \"apex-code-agent-core\";\nimport { minimatch } from \"minimatch\";\nimport { type Static, Type } from \"typebox\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { DelegationRuntimeOptions } from \"../delegation/runtime.ts\";\nimport { retrieveDelegationResult, runDelegation } from \"../delegation/runtime.ts\";\nimport { type ApexToolDefinition, type EvidenceRecord, toolUnion } from \"./contract.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst delegateSchemaProperties = {\n\tagentType: Type.String({\n\t\tdescription: \"The subagent type. Required both to launch a task and to retrieve a background result.\",\n\t}),\n\ttask: Type.String({ description: \"The task to delegate. Supply it to launch a delegation.\" }),\n\tbackground: Type.Optional(\n\t\tType.Boolean({ description: \"Return a handle immediately instead of waiting for the child.\" }),\n\t),\n\thandle: Type.String({\n\t\tdescription: \"A background delegation handle returned by an earlier call. Supply it to retrieve the result.\",\n\t}),\n};\n\nconst delegateSchema = toolUnion(\n\t[\n\t\tType.Object({\n\t\t\tagentType: Type.String(),\n\t\t\ttask: Type.String(),\n\t\t\tbackground: Type.Optional(Type.Boolean()),\n\t\t}),\n\t\tType.Object({ agentType: Type.String(), handle: Type.String() }),\n\t],\n\tdelegateSchemaProperties,\n);\n\nexport type DelegateInput = Static<typeof delegateSchema>;\n\nexport interface DelegateDetails {\n\tagentType: string;\n\ttask: string;\n\toutput: string;\n\thandle?: string;\n}\n\nfunction formatDelegateCall(input: DelegateInput, theme: Theme): string {\n\tif (\"handle\" in input) {\n\t\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · retrieve`;\n\t}\n\tconst task = input.task.replace(/\\s+/g, \" \").trim();\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · ${theme.fg(\"toolOutput\", task)}`;\n}\n\nfunction formatDelegateResult(details: DelegateDetails, expanded: boolean, theme: Theme): string {\n\tif (expanded) return theme.fg(\"toolOutput\", details.output);\n\tconst lineCount = details.output ? details.output.split(\"\\n\").length : 0;\n\treturn `${theme.fg(\"accent\", details.agentType)} · ${lineCount} ${lineCount === 1 ? \"line\" : \"lines\"}`;\n}\n\n/**\n * The delegation entry point (task 4.6's contract, task 5.2's execution). Runs a\n * real child through the injected `DelegationRuntimeOptions` -- capability ceiling,\n * derived permission store, and child-session construction all live behind that\n * injection (ADR 0008), matching the `todo_write`/`tool_schema` convention of\n * injecting collaborators rather than reaching for global state. Recursion\n * depth, artifact isolation, and real agent discovery are wired:\n * `../delegation/runtime.ts` bounds depth and roots per-child artifact\n * directories, and `../delegation/agents.ts` supplies production markdown\n * discovery through the injected resolver.\n */\nexport function createDelegateToolDefinition(\n\truntime: DelegationRuntimeOptions,\n): ApexToolDefinition<typeof delegateSchema, DelegateDetails> {\n\treturn {\n\t\tname: \"delegate\",\n\t\tlabel: \"delegate\",\n\t\tdescription: \"Delegate a task to a subagent.\",\n\t\tparameters: delegateSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"delegate\"]),\n\t\t\tpermission: {\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tmatches: (ruleContent, params) => minimatch(params.agentType, ruleContent),\n\t\t\t\tdescribe: (ruleContent) => `Delegate to agent types matching \"${ruleContent}\"`,\n\t\t\t\truleForCall: (params) => params.agentType,\n\t\t\t},\n\t\t\tcontext: { resultRecoverable: false, deferSchema: true },\n\t\t\tevidence: {\n\t\t\t\temits: new Set([\"workflow\"]),\n\t\t\t\tcapture: (params): EvidenceRecord[] =>\n\t\t\t\t\t\"task\" in params\n\t\t\t\t\t\t? [{ kind: \"workflow\", agentType: params.agentType, task: params.task }]\n\t\t\t\t\t\t: [{ kind: \"workflow\", agentType: params.agentType, handle: params.handle }],\n\t\t\t},\n\t\t},\n\t\tasync execute(_toolCallId, input: DelegateInput): Promise<AgentToolResult<DelegateDetails>> {\n\t\t\tconst result =\n\t\t\t\t\"task\" in input\n\t\t\t\t\t? await runDelegation(runtime, input.agentType, input.task, { background: input.background })\n\t\t\t\t\t: await retrieveDelegationResult(runtime, input.handle, input.agentType);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: result.output }],\n\t\t\t\tdetails: {\n\t\t\t\t\tagentType: result.agentType,\n\t\t\t\t\ttask: result.task,\n\t\t\t\t\toutput: result.output,\n\t\t\t\t\thandle: result.handleId,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\trenderCall(input, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateCall(input, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateResult(result.details, options.expanded, theme));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDelegateTool(runtime: DelegationRuntimeOptions) {\n\treturn wrapToolDefinition(createDelegateToolDefinition(runtime));\n}\n"]}
1
+ {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../../src/core/tools/delegate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAgD,SAAS,EAAE,MAAM,eAAe,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC;IACnC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE;QAC9E,WAAW,EACV,wHAAwH;KACzH,CAAC;IACF,UAAU,EAAE,IAAI,CAAC,QAAQ,CACxB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;QACzB,WAAW,EACV,sGAAsG;KACvG,CAAC,CACF;CACD,CAAC,CAAC;AAEH,MAAM,wBAAwB,GAAG;IAChC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC;QACtB,WAAW,EAAE,wFAAwF;KACrG,CAAC;IACF,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,yDAAyD,EAAE,CAAC;IAC7F,SAAS,EAAE,IAAI,CAAC,QAAQ,CACvB,IAAI,CAAC,MAAM,CACV;QACC,SAAS,EAAE,eAAe,CAAC,UAAU,CAAC,SAAS;QAC/C,UAAU,EAAE,eAAe,CAAC,UAAU,CAAC,UAAU;KACjD,EACD,EAAE,WAAW,EAAE,yFAAyF,EAAE,CAC1G,CACD;IACD,UAAU,EAAE,IAAI,CAAC,QAAQ,CACxB,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,+DAA+D,EAAE,CAAC,CAC9F;IACD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,+FAA+F;KAC5G,CAAC;CACF,CAAC;AAEF,MAAM,cAAc,GAAG,SAAS,CAC/B;IACC,IAAI,CAAC,MAAM,CAAC;QACX,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;QACxB,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE;QACnB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;QACzC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;KACzC,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;CAChE,EACD,wBAAwB,CACxB,CAAC;AAWF,SAAS,kBAAkB,CAAC,KAAoB,EAAE,KAAY,EAAU;IACvE,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;QACvB,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,cAAa,CAAC;IAC7G,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,OAAM,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,CACnI;AAED,SAAS,oBAAoB,CAAC,OAAwB,EAAE,QAAiB,EAAE,KAAY,EAAU;IAChG,IAAI,QAAQ;QAAE,OAAO,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,OAAM,SAAS,IAAI,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;AAAA,CACvG;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,4BAA4B,CAC3C,OAAiC,EAC4B;IAC7D,OAAO;QACN,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,gCAAgC;QAC7C,UAAU,EAAE,cAAc;QAC1B,QAAQ,EAAE;YACT,YAAY,EAAE,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;YACnC,UAAU,EAAE;gBACX,eAAe,EAAE,KAAK;gBACtB,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC;gBAC1E,QAAQ,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,qCAAqC,WAAW,GAAG;gBAC9E,WAAW,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS;aACzC;YACD,OAAO,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE;YACxD,QAAQ,EAAE;gBACT,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;gBAC5B,uEAAuE;gBACvE,qEAAqE;gBACrE,oEAAoE;gBACpE,qEAAqE;gBACrE,qEAAqE;gBACrE,mEAAmE;gBACnE,2EAA2E;gBAC3E,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAoB,EAAE,CAC7C,MAAM,IAAI,MAAM;oBACf,CAAC,CAAC;wBACA;4BACC,IAAI,EAAE,UAAU;4BAChB,SAAS,EAAE,MAAM,CAAC,SAAS;4BAC3B,IAAI,EAAE,MAAM,CAAC,IAAI;4BACjB,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;yBAC7B;qBACD;oBACF,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;aAC9E;SACD;QACD,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,KAAoB,EAA6C;YAC3F,MAAM,SAAS,GACd,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,SAAS;gBACjC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,UAAU,IAAI,EAAE,EAAE;gBACxF,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,MAAM,GACX,MAAM,IAAI,KAAK;gBACd,CAAC,CAAC,MAAM,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC;gBACxG,CAAC,CAAC,MAAM,wBAAwB,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YAC3E,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChD,OAAO,EAAE;oBACR,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,MAAM,EAAE,MAAM,CAAC,QAAQ;iBACvB;aACD,CAAC;QAAA,CACF;QACD,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;YACjC,MAAM,IAAI,GAAI,OAAO,CAAC,aAAkC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC;QAAA,CACZ;QACD,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YAC7C,MAAM,IAAI,GAAI,OAAO,CAAC,aAAkC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;YAC5E,OAAO,IAAI,CAAC;QAAA,CACZ;KACD,CAAC;AAAA,CACF;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAiC,EAAE;IACrE,OAAO,kBAAkB,CAAC,4BAA4B,CAAC,OAAO,CAAC,CAAC,CAAC;AAAA,CACjE","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { AgentToolResult } from \"apex-code-agent-core\";\nimport { minimatch } from \"minimatch\";\nimport { type Static, Type } from \"typebox\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { DelegationRuntimeOptions } from \"../delegation/runtime.ts\";\nimport { retrieveDelegationResult, runDelegation } from \"../delegation/runtime.ts\";\nimport { type ApexToolDefinition, type EvidenceRecord, toolUnion } from \"./contract.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst workspaceSchema = Type.Object({\n\tisolation: Type.Union([Type.Literal(\"shared-read\"), Type.Literal(\"worktree\")], {\n\t\tdescription:\n\t\t\t'Child workspace isolation: \"shared-read\" runs in the parent checkout; \"worktree\" gives the child its own git worktree.',\n\t}),\n\townedPaths: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription:\n\t\t\t\t\"Workspace-relative paths the child owns for writes. Advisory claims; overlapping claims are refused.\",\n\t\t}),\n\t),\n});\n\nconst delegateSchemaProperties = {\n\tagentType: Type.String({\n\t\tdescription: \"The subagent type. Required both to launch a task and to retrieve a background result.\",\n\t}),\n\ttask: Type.String({ description: \"The task to delegate. Supply it to launch a delegation.\" }),\n\tworkspace: Type.Optional(\n\t\tType.Object(\n\t\t\t{\n\t\t\t\tisolation: workspaceSchema.properties.isolation,\n\t\t\t\townedPaths: workspaceSchema.properties.ownedPaths,\n\t\t\t},\n\t\t\t{ description: \"The child's requested workspace authority. Defaults to shared-read with no owned paths.\" },\n\t\t),\n\t),\n\tbackground: Type.Optional(\n\t\tType.Boolean({ description: \"Return a handle immediately instead of waiting for the child.\" }),\n\t),\n\thandle: Type.String({\n\t\tdescription: \"A background delegation handle returned by an earlier call. Supply it to retrieve the result.\",\n\t}),\n};\n\nconst delegateSchema = toolUnion(\n\t[\n\t\tType.Object({\n\t\t\tagentType: Type.String(),\n\t\t\ttask: Type.String(),\n\t\t\tworkspace: Type.Optional(workspaceSchema),\n\t\t\tbackground: Type.Optional(Type.Boolean()),\n\t\t}),\n\t\tType.Object({ agentType: Type.String(), handle: Type.String() }),\n\t],\n\tdelegateSchemaProperties,\n);\n\nexport type DelegateInput = Static<typeof delegateSchema>;\n\nexport interface DelegateDetails {\n\tagentType: string;\n\ttask: string;\n\toutput: string;\n\thandle?: string;\n}\n\nfunction formatDelegateCall(input: DelegateInput, theme: Theme): string {\n\tif (\"handle\" in input) {\n\t\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · retrieve`;\n\t}\n\tconst task = input.task.replace(/\\s+/g, \" \").trim();\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"delegate\"))} ${theme.fg(\"accent\", input.agentType)} · ${theme.fg(\"toolOutput\", task)}`;\n}\n\nfunction formatDelegateResult(details: DelegateDetails, expanded: boolean, theme: Theme): string {\n\tif (expanded) return theme.fg(\"toolOutput\", details.output);\n\tconst lineCount = details.output ? details.output.split(\"\\n\").length : 0;\n\treturn `${theme.fg(\"accent\", details.agentType)} · ${lineCount} ${lineCount === 1 ? \"line\" : \"lines\"}`;\n}\n\n/**\n * The delegation entry point (task 4.6's contract, task 5.2's execution). Runs a\n * real child through the injected `DelegationRuntimeOptions` -- capability ceiling,\n * derived permission store, and child-session construction all live behind that\n * injection (ADR 0008), matching the `todo_write`/`tool_schema` convention of\n * injecting collaborators rather than reaching for global state. Recursion\n * depth, artifact isolation, and real agent discovery are wired:\n * `../delegation/runtime.ts` bounds depth and roots per-child artifact\n * directories, and `../delegation/agents.ts` supplies production markdown\n * discovery through the injected resolver.\n */\nexport function createDelegateToolDefinition(\n\truntime: DelegationRuntimeOptions,\n): ApexToolDefinition<typeof delegateSchema, DelegateDetails> {\n\treturn {\n\t\tname: \"delegate\",\n\t\tlabel: \"delegate\",\n\t\tdescription: \"Delegate a task to a subagent.\",\n\t\tparameters: delegateSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"delegate\"]),\n\t\t\tpermission: {\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tmatches: (ruleContent, params) => minimatch(params.agentType, ruleContent),\n\t\t\t\tdescribe: (ruleContent) => `Delegate to agent types matching \"${ruleContent}\"`,\n\t\t\t\truleForCall: (params) => params.agentType,\n\t\t\t},\n\t\t\tcontext: { resultRecoverable: false, deferSchema: true },\n\t\t\tevidence: {\n\t\t\t\temits: new Set([\"workflow\"]),\n\t\t\t\t// capture runs in afterToolCall with the completed result, so a launch\n\t\t\t\t// can carry its handle even though the params could not know it: the\n\t\t\t\t// handle is the child's session id, which names the child's session\n\t\t\t\t// file and artifact dir under the parent's delegations/. This reuses\n\t\t\t\t// the existing WorkflowEvidenceRecord.handle field -- no contract or\n\t\t\t\t// sink shape change (the per-child session linkage is the evidence\n\t\t\t\t// model; see docs/plans/2026-09-09-run-and-child-session-architecture.md).\n\t\t\t\tcapture: (params, result): EvidenceRecord[] =>\n\t\t\t\t\t\"task\" in params\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkind: \"workflow\",\n\t\t\t\t\t\t\t\t\tagentType: params.agentType,\n\t\t\t\t\t\t\t\t\ttask: params.task,\n\t\t\t\t\t\t\t\t\thandle: result.details.handle,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: [{ kind: \"workflow\", agentType: params.agentType, handle: params.handle }],\n\t\t\t},\n\t\t},\n\t\tasync execute(_toolCallId, input: DelegateInput): Promise<AgentToolResult<DelegateDetails>> {\n\t\t\tconst workspace =\n\t\t\t\t\"task\" in input && input.workspace\n\t\t\t\t\t? { isolation: input.workspace.isolation, ownedPaths: input.workspace.ownedPaths ?? [] }\n\t\t\t\t\t: undefined;\n\t\t\tconst result =\n\t\t\t\t\"task\" in input\n\t\t\t\t\t? await runDelegation(runtime, input.agentType, input.task, { background: input.background, workspace })\n\t\t\t\t\t: await retrieveDelegationResult(runtime, input.handle, input.agentType);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: result.output }],\n\t\t\t\tdetails: {\n\t\t\t\t\tagentType: result.agentType,\n\t\t\t\t\ttask: result.task,\n\t\t\t\t\toutput: result.output,\n\t\t\t\t\thandle: result.handleId,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\trenderCall(input, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateCall(input, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDelegateResult(result.details, options.expanded, theme));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDelegateTool(runtime: DelegationRuntimeOptions) {\n\treturn wrapToolDefinition(createDelegateToolDefinition(runtime));\n}\n"]}
@@ -17,6 +17,22 @@ export interface GitObserveOptions {
17
17
  */
18
18
  excludePaths?: string[];
19
19
  }
20
+ export interface GitRunResult {
21
+ ok: boolean;
22
+ code: number | null;
23
+ stdout: Buffer;
24
+ stderr: string;
25
+ timedOut: boolean;
26
+ spawnError: boolean;
27
+ }
28
+ /**
29
+ * The workspace subsystem's one git exec seam: shell-less argv (no quoting
30
+ * bugs, Windows-safe), pinned `core.autocrlf=false`, optional index locks
31
+ * disabled, per-command timeout, abort support. The observer above uses it
32
+ * read-only; `git-worktree-owner.ts` reuses it for the worktree mutations so
33
+ * the subsystem never grows a second spawn pattern.
34
+ */
35
+ export declare function runGit(cwd: string, args: string[], timeoutMs: number, signal?: AbortSignal): Promise<GitRunResult>;
20
36
  /**
21
37
  * Observe a Git workspace without mutating it. Returns a version-1
22
38
  * `WorkspaceStateRecord`: `unsupported` for non-Git workspaces, `failed`
@@ -1 +1 @@
1
- {"version":3,"file":"git-observer.d.ts","sourceRoot":"","sources":["../../../src/core/workspace/git-observer.ts"],"names":[],"mappings":"AAIA,OAAO,EAIN,KAAK,oBAAoB,EACzB,MAAM,YAAY,CAAC;AAoBpB,MAAM,WAAW,iBAAiB;IACjC,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAmLD;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IAClC,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC;IAChB,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,YAAY,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC9B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACT,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC,GACC,kBAAkB,CA2BpB;AAED,wBAAsB,mBAAmB,CACxC,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,iBAAiB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CAyI/B","sourcesContent":["import { type ChildProcess, spawn } from \"node:child_process\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { lstatSync, readFileSync, readlinkSync, realpathSync } from \"node:fs\";\nimport { dirname, isAbsolute, win32 as pathWin32, relative, sep } from \"node:path\";\nimport {\n\tWORKSPACE_RECORD_VERSION,\n\ttype WorkspaceStateCoverage,\n\ttype WorkspaceStatePath,\n\ttype WorkspaceStateRecord,\n} from \"./state.ts\";\n\n/**\n * Read-only Git workspace observation (spec 2026-09-01-harness-correctness-\n * and-workspace-state.md § 1).\n *\n * The adapter never mutates repository state: `HEAD`, the current branch, the\n * index, the worktree, the stash, and local config are only read. Optional\n * index locks are disabled (`GIT_OPTIONAL_LOCKS=0`) so even `git status`\n * cannot refresh the on-disk index. It never walks the workspace; all path\n * knowledge comes from git. Symlinks are hashed as link text (what git\n * stores), never followed. Submodule (gitlink) paths carry no worktree hash.\n */\n\nconst DEFAULT_MAX_PATHS = 200;\nconst DEFAULT_MAX_HASH_BYTES = 5 * 1024 * 1024;\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst GIT_CONFIG = [\"-c\", \"core.autocrlf=false\", \"-c\", \"status.renames=true\"];\nconst UNMERGED_XY = new Set([\"DD\", \"AU\", \"UD\", \"UA\", \"DU\", \"AA\", \"UU\"]);\n\nexport interface GitObserveOptions {\n\t/** Compute per-path content hashes of present files (default true). */\n\thashPaths?: boolean;\n\t/** Maximum number of reported paths (default 200). */\n\tmaxPaths?: number;\n\t/** Skip hashing files larger than this many bytes (default 5 MiB). */\n\tmaxHashBytes?: number;\n\t/** Per-command timeout in milliseconds (default 10 000). */\n\ttimeoutMs?: number;\n\t/** Cancels the observation; the record reports `failed`. */\n\tsignal?: AbortSignal;\n\t/**\n\t * Repository-relative path prefixes to omit from `paths` (exact match or\n\t * directory prefix). Used for harness bookkeeping that lives inside the\n\t * workspace — e.g. the session directory — which is not workspace state.\n\t */\n\texcludePaths?: string[];\n}\n\ninterface GitRunResult {\n\tok: boolean;\n\tcode: number | null;\n\tstdout: Buffer;\n\tstderr: string;\n\ttimedOut: boolean;\n\tspawnError: boolean;\n}\n\nfunction runGit(cwd: string, args: string[], timeoutMs: number, signal?: AbortSignal): Promise<GitRunResult> {\n\treturn new Promise((resolve) => {\n\t\tlet stdout = Buffer.alloc(0);\n\t\tlet stderr = \"\";\n\t\tlet timedOut = false;\n\t\tlet settled = false;\n\t\tlet child: ChildProcess;\n\t\tconst finish = (code: number | null, spawnError: boolean) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve({\n\t\t\t\tok: !spawnError && !timedOut && code === 0,\n\t\t\t\tcode,\n\t\t\t\tstdout,\n\t\t\t\tstderr,\n\t\t\t\ttimedOut,\n\t\t\t\tspawnError,\n\t\t\t});\n\t\t};\n\t\tconst onAbort = () => {\n\t\t\tchild?.kill(\"SIGKILL\");\n\t\t};\n\t\tconst timer = setTimeout(() => {\n\t\t\ttimedOut = true;\n\t\t\tchild?.kill(\"SIGKILL\");\n\t\t}, timeoutMs);\n\t\ttry {\n\t\t\tchild = spawn(\"git\", [...GIT_CONFIG, ...args], {\n\t\t\t\tcwd,\n\t\t\t\tshell: false,\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\t// Observation must leave the on-disk index untouched.\n\t\t\t\tenv: { ...process.env, GIT_OPTIONAL_LOCKS: \"0\" },\n\t\t\t});\n\t\t} catch {\n\t\t\tresolve({ ok: false, code: null, stdout, stderr: \"\", timedOut: false, spawnError: true });\n\t\t\treturn;\n\t\t}\n\t\tif (signal) {\n\t\t\tif (signal.aborted) onAbort();\n\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\tstdout = Buffer.concat([stdout, chunk]);\n\t\t});\n\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\tstderr += chunk.toString(\"utf-8\");\n\t\t});\n\t\tchild.on(\"error\", () => finish(null, true));\n\t\tchild.on(\"close\", (code) => finish(code, false));\n\t});\n}\n\nfunction emptyCoverage(): WorkspaceStateCoverage {\n\treturn {\n\t\ttracked: false,\n\t\tstaged: false,\n\t\tunstaged: false,\n\t\tuntracked: false,\n\t\tignored: false,\n\t\thashes: false,\n\t\tpatch: false,\n\t};\n}\n\nfunction fullCoverage(): WorkspaceStateCoverage {\n\treturn {\n\t\ttracked: true,\n\t\tstaged: true,\n\t\tunstaged: true,\n\t\tuntracked: true,\n\t\tignored: true,\n\t\thashes: true,\n\t\tpatch: false,\n\t};\n}\n\ninterface ParsedStatusPath {\n\tx: string;\n\ty: string;\n\tpath: string;\n\tpreviousPath?: string;\n}\n\nfunction parsePorcelainZ(stdout: Buffer): ParsedStatusPath[] {\n\tconst fields = stdout.toString(\"utf-8\").split(\"\\0\");\n\tconst parsed: ParsedStatusPath[] = [];\n\tlet i = 0;\n\twhile (i < fields.length) {\n\t\tconst record = fields[i++];\n\t\tif (!record || record.length < 4) continue;\n\t\tconst entry: ParsedStatusPath = { x: record[0], y: record[1], path: record.slice(3) };\n\t\tif (entry.x === \"R\" || entry.x === \"C\" || entry.y === \"R\" || entry.y === \"C\") {\n\t\t\tentry.previousPath = fields[i++];\n\t\t}\n\t\tparsed.push(entry);\n\t}\n\treturn parsed;\n}\n\nfunction classify(entry: ParsedStatusPath): {\n\tkind: WorkspaceStatePath[\"kind\"];\n\tstaged: boolean;\n\tunstaged: boolean;\n\tignored: boolean;\n} {\n\tconst { x, y } = entry;\n\tif (x === \"?\" && y === \"?\") {\n\t\treturn { kind: \"untracked\", staged: false, unstaged: false, ignored: false };\n\t}\n\tif (x === \"!\" && y === \"!\") {\n\t\treturn { kind: \"untracked\", staged: false, unstaged: false, ignored: true };\n\t}\n\tif (UNMERGED_XY.has(`${x}${y}`)) {\n\t\treturn {\n\t\t\tkind: x === \"D\" && y === \"D\" ? \"deleted\" : \"modified\",\n\t\t\tstaged: true,\n\t\t\tunstaged: true,\n\t\t\tignored: false,\n\t\t};\n\t}\n\tlet kind: WorkspaceStatePath[\"kind\"] = \"modified\";\n\tif (x === \"A\" || y === \"A\" || x === \"C\" || y === \"C\") kind = \"added\";\n\telse if (x === \"D\" || y === \"D\") kind = \"deleted\";\n\telse if (x === \"R\" || y === \"R\") kind = \"renamed\";\n\treturn {\n\t\tkind,\n\t\tstaged: x !== \" \" && x !== \"?\" && x !== \"!\",\n\t\tunstaged: y !== \" \" && y !== \"?\" && y !== \"!\",\n\t\tignored: false,\n\t};\n}\n\n/** Hash one workspace path: regular files by bytes, symlinks by link text. */\nfunction hashWorkspacePath(\n\ttoplevel: string,\n\tpath: string,\n\tmaxBytes: number,\n): { hash?: string; skipped: \"size\" | \"error\" | false } {\n\ttry {\n\t\tconst full = `${toplevel}/${path}`;\n\t\tconst stat = lstatSync(full);\n\t\tif (stat.isFile()) {\n\t\t\tif (stat.size > maxBytes) return { skipped: \"size\" };\n\t\t\treturn { hash: `sha256:${createHash(\"sha256\").update(readFileSync(full)).digest(\"hex\")}`, skipped: false };\n\t\t}\n\t\tif (stat.isSymbolicLink()) {\n\t\t\treturn {\n\t\t\t\thash: `sha256:${createHash(\"sha256\").update(readlinkSync(full)).digest(\"hex\")}`,\n\t\t\t\tskipped: false,\n\t\t\t};\n\t\t}\n\t\t// Directories (submodule gitlinks) have no worktree content to hash;\n\t\t// that is expected, not a coverage gap.\n\t\tif (stat.isDirectory()) return { skipped: false };\n\t\treturn { skipped: \"error\" };\n\t} catch {\n\t\treturn { skipped: \"error\" };\n\t}\n}\n\nfunction prefixRelative(prefix: string, path: string): string {\n\tif (prefix === \"\" || prefix === \".\") return path;\n\treturn `${prefix}/${path}`;\n}\n\n/**\n * Observe a Git workspace without mutating it. Returns a version-1\n * `WorkspaceStateRecord`: `unsupported` for non-Git workspaces, `failed`\n * when git could not run or the observation was cancelled, and `incomplete`\n * when a limit truncated the capture. `observed` never implies more than\n * `coverage` states.\n */\nexport interface ToplevelComparison {\n\t/** Whether the physically resolved workspace root sits under the toplevel. */\n\tinside: boolean;\n\t/** Root path relative to the toplevel; strip this prefix from porcelain paths. */\n\tprefix: string;\n\t/** Physically resolved toplevel; base for absolute-path work like hashing. */\n\ttoplevelReal: string;\n}\n\n/**\n * Decide containment of the workspace root inside git's toplevel after both\n * sides are physically resolved. Windows spellings diverge from what Node's\n * realpath returns for the same directory (short 8.3 names, drive-letter\n * case), so the win32 branch resolves through the native resolver, folds\n * case for the comparison, and uses win32 path semantics. The platform and\n * resolver are injectable so tests can exercise those branches anywhere.\n */\nexport function compareToplevel(\n\tworkspaceRoot: string,\n\ttoplevel: string,\n\toptions?: {\n\t\tplatform?: NodeJS.Platform;\n\t\trealpath?: (path: string) => string;\n\t},\n): ToplevelComparison {\n\tconst platform = options?.platform ?? process.platform;\n\tconst isWin32 = platform === \"win32\";\n\tconst realpath =\n\t\toptions?.realpath ??\n\t\t(isWin32\n\t\t\t? (p: string) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn realpathSync.native(p);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn realpathSync(p);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t: realpathSync);\n\tconst rootReal = realpath(workspaceRoot);\n\tconst toplevelReal = realpath(toplevel);\n\tconst pathMod = isWin32 ? pathWin32 : { relative, sep, dirname };\n\tconst fold = (p: string) => (isWin32 ? p.toLowerCase() : p);\n\tconst prefix = pathMod.relative(toplevelReal, rootReal);\n\tconst inside = !(prefix === \"..\" || prefix.startsWith(`..${pathMod.sep}`) || isAbsolute(prefix));\n\tif (isWin32 && inside) {\n\t\t// Recompute the strip prefix under case folding so a divergent drive or\n\t\t// directory case still yields the clean \"\" or relative form.\n\t\tconst folded = pathMod.relative(fold(toplevelReal), fold(rootReal));\n\t\treturn { inside, prefix: folded, toplevelReal };\n\t}\n\treturn { inside, prefix, toplevelReal };\n}\n\nexport async function observeWorkspaceGit(\n\tworkspaceRoot: string,\n\toptions?: GitObserveOptions,\n): Promise<WorkspaceStateRecord> {\n\tconst maxPaths = options?.maxPaths ?? DEFAULT_MAX_PATHS;\n\tconst maxHashBytes = options?.maxHashBytes ?? DEFAULT_MAX_HASH_BYTES;\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst hashPaths = options?.hashPaths ?? true;\n\tconst signal = options?.signal;\n\tconst excludePaths = (options?.excludePaths ?? [])\n\t\t.map((p) => p.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/+$/, \"\"))\n\t\t.filter((p) => p.length > 0);\n\tconst isExcluded = (repoPath: string): boolean =>\n\t\texcludePaths.some((ex) => repoPath === ex || repoPath.startsWith(`${ex}/`));\n\n\tconst warnings: string[] = [];\n\tconst failed = (message: string): WorkspaceStateRecord => ({\n\t\tversion: WORKSPACE_RECORD_VERSION,\n\t\tobservationId: randomUUID(),\n\t\tstatus: \"failed\",\n\t\tbackend: \"git\",\n\t\tworkspaceRoot,\n\t\tcapturedAt: new Date().toISOString(),\n\t\tcoverage: emptyCoverage(),\n\t\tpaths: [],\n\t\twarnings: [message],\n\t});\n\n\tif (signal?.aborted) {\n\t\treturn failed(\"workspace observation cancelled\");\n\t}\n\n\tconst head = await runGit(workspaceRoot, [\"rev-parse\", \"--show-toplevel\"], timeoutMs, signal);\n\tif (head.spawnError) return failed(\"git could not be executed\");\n\tif (head.timedOut) return failed(\"workspace observation timed out\");\n\tif (signal?.aborted) return failed(\"workspace observation cancelled\");\n\tif (!head.ok) {\n\t\tif (/not a git repository/i.test(head.stderr) || head.code === 128) {\n\t\t\treturn {\n\t\t\t\t...failed(\"not a git repository\"),\n\t\t\t\tstatus: \"unsupported\",\n\t\t\t};\n\t\t}\n\t\treturn failed(\"git rev-parse failed\");\n\t}\n\t// git resolves the toplevel physically (macOS /tmp -> /private/tmp,\n\t// Windows drive-letter case and short names), so containment is decided\n\t// through compareToplevel; otherwise a divergent spelling of the same\n\t// directory would fail the observation or corrupt every reported path.\n\tconst toplevel = head.stdout.toString(\"utf-8\").trim();\n\tconst comparison = compareToplevel(workspaceRoot, toplevel);\n\tif (!comparison.inside) {\n\t\treturn failed(\"workspace root is outside the repository toplevel\");\n\t}\n\tconst insidePrefix = comparison.prefix;\n\n\tconst headCommit = await runGit(workspaceRoot, [\"rev-parse\", \"--verify\", \"HEAD\"], timeoutMs, signal);\n\tconst mergeHead = await runGit(workspaceRoot, [\"rev-parse\", \"-q\", \"--verify\", \"MERGE_HEAD\"], timeoutMs, signal);\n\tif (signal?.aborted) return failed(\"workspace observation cancelled\");\n\tif (mergeHead.ok) warnings.push(\"merge in progress\");\n\tconst branch = await runGit(workspaceRoot, [\"branch\", \"--show-current\"], timeoutMs, signal);\n\n\tconst headCommitValue = headCommit.ok ? headCommit.stdout.toString(\"utf-8\").trim() : undefined;\n\tif (!headCommit.ok) warnings.push(\"unborn HEAD (no commits)\");\n\tconst branchValue = branch.ok ? branch.stdout.toString(\"utf-8\").trim() : \"\";\n\tif (branchValue === \"\") warnings.push(\"detached HEAD\");\n\n\t// Index baseline.\n\tconst index = await runGit(workspaceRoot, [\"ls-files\", \"--stage\", \"-z\"], timeoutMs, signal);\n\tif (!index.ok) return failed(\"git ls-files failed\");\n\tconst indexDigest = `sha256:${createHash(\"sha256\").update(index.stdout).digest(\"hex\")}`;\n\n\t// Staged / unstaged / untracked / ignored change sets.\n\tconst status = await runGit(\n\t\tworkspaceRoot,\n\t\t[\"status\", \"--porcelain\", \"-z\", \"--untracked-files=all\", \"--ignored=matching\"],\n\t\ttimeoutMs,\n\t\tsignal,\n\t);\n\tif (!status.ok) return failed(\"git status failed\");\n\n\tconst paths: WorkspaceStatePath[] = [];\n\tlet truncated = false;\n\tlet skippedHashes = 0;\n\tfor (const entry of parsePorcelainZ(status.stdout)) {\n\t\tif (isExcluded(entry.path) || (entry.previousPath !== undefined && isExcluded(entry.previousPath))) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (paths.length >= maxPaths) {\n\t\t\ttruncated = true;\n\t\t\twarnings.push(`path list truncated at ${maxPaths} paths`);\n\t\t\tbreak;\n\t\t}\n\t\tconst { kind, staged, unstaged, ignored } = classify(entry);\n\t\tconst workspacePath: WorkspaceStatePath = {\n\t\t\tpath: prefixRelative(insidePrefix, entry.path),\n\t\t\tkind,\n\t\t\tstaged,\n\t\t\tunstaged,\n\t\t\t...(ignored ? { ignored: true } : {}),\n\t\t\t...(entry.previousPath ? { previousPath: prefixRelative(insidePrefix, entry.previousPath) } : {}),\n\t\t};\n\t\tif (hashPaths && kind !== \"deleted\") {\n\t\t\tconst { hash, skipped } = hashWorkspacePath(comparison.toplevelReal, entry.path, maxHashBytes);\n\t\t\tif (hash) workspacePath.contentHash = hash;\n\t\t\telse if (skipped) skippedHashes++;\n\t\t}\n\t\tpaths.push(workspacePath);\n\t}\n\tif (skippedHashes > 0) warnings.push(`content hashing skipped for ${skippedHashes} path(s)`);\n\n\t// Digest over exactly the paths this record includes, so a later\n\t// comparison can cheaply detect that the covered state moved.\n\tconst digestInput = paths\n\t\t.map(\n\t\t\t(p) =>\n\t\t\t\t`${p.path}\\0${p.kind}\\0${p.staged ? \"S\" : \"\"}${p.unstaged ? \"U\" : \"\"}${p.ignored ? \"I\" : \"\"}\\0${p.contentHash ?? \"\"}\\n`,\n\t\t)\n\t\t.sort()\n\t\t.join(\"\");\n\n\treturn {\n\t\tversion: WORKSPACE_RECORD_VERSION,\n\t\tobservationId: randomUUID(),\n\t\tstatus: truncated || skippedHashes > 0 ? \"incomplete\" : \"observed\",\n\t\tbackend: \"git\",\n\t\tworkspaceRoot,\n\t\tcapturedAt: new Date().toISOString(),\n\t\t// `hashes` reflects the configured policy: a disabled hash pass is a\n\t\t// coverage statement, not an incomplete capture.\n\t\tcoverage: { ...fullCoverage(), hashes: hashPaths },\n\t\tbase: {\n\t\t\t...(headCommitValue ? { headCommit: headCommitValue } : {}),\n\t\t\t...(branchValue ? { branch: branchValue } : {}),\n\t\t\tindexDigest,\n\t\t\t...(truncated ? {} : { worktreeDigest: `sha256:${createHash(\"sha256\").update(digestInput).digest(\"hex\")}` }),\n\t\t},\n\t\tpaths,\n\t\twarnings,\n\t};\n}\n"]}
1
+ {"version":3,"file":"git-observer.d.ts","sourceRoot":"","sources":["../../../src/core/workspace/git-observer.ts"],"names":[],"mappings":"AAIA,OAAO,EAIN,KAAK,oBAAoB,EACzB,MAAM,YAAY,CAAC;AAoBpB,MAAM,WAAW,iBAAiB;IACjC,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAqDlH;AAmHD;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IAClC,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC;IAChB,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,YAAY,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC9B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACT,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC,GACC,kBAAkB,CA2BpB;AAED,wBAAsB,mBAAmB,CACxC,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,iBAAiB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CAyI/B","sourcesContent":["import { type ChildProcess, spawn } from \"node:child_process\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { lstatSync, readFileSync, readlinkSync, realpathSync } from \"node:fs\";\nimport { dirname, isAbsolute, win32 as pathWin32, relative, sep } from \"node:path\";\nimport {\n\tWORKSPACE_RECORD_VERSION,\n\ttype WorkspaceStateCoverage,\n\ttype WorkspaceStatePath,\n\ttype WorkspaceStateRecord,\n} from \"./state.ts\";\n\n/**\n * Read-only Git workspace observation (spec 2026-09-01-harness-correctness-\n * and-workspace-state.md § 1).\n *\n * The adapter never mutates repository state: `HEAD`, the current branch, the\n * index, the worktree, the stash, and local config are only read. Optional\n * index locks are disabled (`GIT_OPTIONAL_LOCKS=0`) so even `git status`\n * cannot refresh the on-disk index. It never walks the workspace; all path\n * knowledge comes from git. Symlinks are hashed as link text (what git\n * stores), never followed. Submodule (gitlink) paths carry no worktree hash.\n */\n\nconst DEFAULT_MAX_PATHS = 200;\nconst DEFAULT_MAX_HASH_BYTES = 5 * 1024 * 1024;\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst GIT_CONFIG = [\"-c\", \"core.autocrlf=false\", \"-c\", \"status.renames=true\"];\nconst UNMERGED_XY = new Set([\"DD\", \"AU\", \"UD\", \"UA\", \"DU\", \"AA\", \"UU\"]);\n\nexport interface GitObserveOptions {\n\t/** Compute per-path content hashes of present files (default true). */\n\thashPaths?: boolean;\n\t/** Maximum number of reported paths (default 200). */\n\tmaxPaths?: number;\n\t/** Skip hashing files larger than this many bytes (default 5 MiB). */\n\tmaxHashBytes?: number;\n\t/** Per-command timeout in milliseconds (default 10 000). */\n\ttimeoutMs?: number;\n\t/** Cancels the observation; the record reports `failed`. */\n\tsignal?: AbortSignal;\n\t/**\n\t * Repository-relative path prefixes to omit from `paths` (exact match or\n\t * directory prefix). Used for harness bookkeeping that lives inside the\n\t * workspace — e.g. the session directory — which is not workspace state.\n\t */\n\texcludePaths?: string[];\n}\n\nexport interface GitRunResult {\n\tok: boolean;\n\tcode: number | null;\n\tstdout: Buffer;\n\tstderr: string;\n\ttimedOut: boolean;\n\tspawnError: boolean;\n}\n\n/**\n * The workspace subsystem's one git exec seam: shell-less argv (no quoting\n * bugs, Windows-safe), pinned `core.autocrlf=false`, optional index locks\n * disabled, per-command timeout, abort support. The observer above uses it\n * read-only; `git-worktree-owner.ts` reuses it for the worktree mutations so\n * the subsystem never grows a second spawn pattern.\n */\nexport function runGit(cwd: string, args: string[], timeoutMs: number, signal?: AbortSignal): Promise<GitRunResult> {\n\treturn new Promise((resolve) => {\n\t\tlet stdout = Buffer.alloc(0);\n\t\tlet stderr = \"\";\n\t\tlet timedOut = false;\n\t\tlet settled = false;\n\t\tlet child: ChildProcess;\n\t\tconst finish = (code: number | null, spawnError: boolean) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve({\n\t\t\t\tok: !spawnError && !timedOut && code === 0,\n\t\t\t\tcode,\n\t\t\t\tstdout,\n\t\t\t\tstderr,\n\t\t\t\ttimedOut,\n\t\t\t\tspawnError,\n\t\t\t});\n\t\t};\n\t\tconst onAbort = () => {\n\t\t\tchild?.kill(\"SIGKILL\");\n\t\t};\n\t\tconst timer = setTimeout(() => {\n\t\t\ttimedOut = true;\n\t\t\tchild?.kill(\"SIGKILL\");\n\t\t}, timeoutMs);\n\t\ttry {\n\t\t\tchild = spawn(\"git\", [...GIT_CONFIG, ...args], {\n\t\t\t\tcwd,\n\t\t\t\tshell: false,\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\t// Observation must leave the on-disk index untouched.\n\t\t\t\tenv: { ...process.env, GIT_OPTIONAL_LOCKS: \"0\" },\n\t\t\t});\n\t\t} catch {\n\t\t\tresolve({ ok: false, code: null, stdout, stderr: \"\", timedOut: false, spawnError: true });\n\t\t\treturn;\n\t\t}\n\t\tif (signal) {\n\t\t\tif (signal.aborted) onAbort();\n\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t\tchild.stdout?.on(\"data\", (chunk: Buffer) => {\n\t\t\tstdout = Buffer.concat([stdout, chunk]);\n\t\t});\n\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\tstderr += chunk.toString(\"utf-8\");\n\t\t});\n\t\tchild.on(\"error\", () => finish(null, true));\n\t\tchild.on(\"close\", (code) => finish(code, false));\n\t});\n}\n\nfunction emptyCoverage(): WorkspaceStateCoverage {\n\treturn {\n\t\ttracked: false,\n\t\tstaged: false,\n\t\tunstaged: false,\n\t\tuntracked: false,\n\t\tignored: false,\n\t\thashes: false,\n\t\tpatch: false,\n\t};\n}\n\nfunction fullCoverage(): WorkspaceStateCoverage {\n\treturn {\n\t\ttracked: true,\n\t\tstaged: true,\n\t\tunstaged: true,\n\t\tuntracked: true,\n\t\tignored: true,\n\t\thashes: true,\n\t\tpatch: false,\n\t};\n}\n\ninterface ParsedStatusPath {\n\tx: string;\n\ty: string;\n\tpath: string;\n\tpreviousPath?: string;\n}\n\nfunction parsePorcelainZ(stdout: Buffer): ParsedStatusPath[] {\n\tconst fields = stdout.toString(\"utf-8\").split(\"\\0\");\n\tconst parsed: ParsedStatusPath[] = [];\n\tlet i = 0;\n\twhile (i < fields.length) {\n\t\tconst record = fields[i++];\n\t\tif (!record || record.length < 4) continue;\n\t\tconst entry: ParsedStatusPath = { x: record[0], y: record[1], path: record.slice(3) };\n\t\tif (entry.x === \"R\" || entry.x === \"C\" || entry.y === \"R\" || entry.y === \"C\") {\n\t\t\tentry.previousPath = fields[i++];\n\t\t}\n\t\tparsed.push(entry);\n\t}\n\treturn parsed;\n}\n\nfunction classify(entry: ParsedStatusPath): {\n\tkind: WorkspaceStatePath[\"kind\"];\n\tstaged: boolean;\n\tunstaged: boolean;\n\tignored: boolean;\n} {\n\tconst { x, y } = entry;\n\tif (x === \"?\" && y === \"?\") {\n\t\treturn { kind: \"untracked\", staged: false, unstaged: false, ignored: false };\n\t}\n\tif (x === \"!\" && y === \"!\") {\n\t\treturn { kind: \"untracked\", staged: false, unstaged: false, ignored: true };\n\t}\n\tif (UNMERGED_XY.has(`${x}${y}`)) {\n\t\treturn {\n\t\t\tkind: x === \"D\" && y === \"D\" ? \"deleted\" : \"modified\",\n\t\t\tstaged: true,\n\t\t\tunstaged: true,\n\t\t\tignored: false,\n\t\t};\n\t}\n\tlet kind: WorkspaceStatePath[\"kind\"] = \"modified\";\n\tif (x === \"A\" || y === \"A\" || x === \"C\" || y === \"C\") kind = \"added\";\n\telse if (x === \"D\" || y === \"D\") kind = \"deleted\";\n\telse if (x === \"R\" || y === \"R\") kind = \"renamed\";\n\treturn {\n\t\tkind,\n\t\tstaged: x !== \" \" && x !== \"?\" && x !== \"!\",\n\t\tunstaged: y !== \" \" && y !== \"?\" && y !== \"!\",\n\t\tignored: false,\n\t};\n}\n\n/** Hash one workspace path: regular files by bytes, symlinks by link text. */\nfunction hashWorkspacePath(\n\ttoplevel: string,\n\tpath: string,\n\tmaxBytes: number,\n): { hash?: string; skipped: \"size\" | \"error\" | false } {\n\ttry {\n\t\tconst full = `${toplevel}/${path}`;\n\t\tconst stat = lstatSync(full);\n\t\tif (stat.isFile()) {\n\t\t\tif (stat.size > maxBytes) return { skipped: \"size\" };\n\t\t\treturn { hash: `sha256:${createHash(\"sha256\").update(readFileSync(full)).digest(\"hex\")}`, skipped: false };\n\t\t}\n\t\tif (stat.isSymbolicLink()) {\n\t\t\treturn {\n\t\t\t\thash: `sha256:${createHash(\"sha256\").update(readlinkSync(full)).digest(\"hex\")}`,\n\t\t\t\tskipped: false,\n\t\t\t};\n\t\t}\n\t\t// Directories (submodule gitlinks) have no worktree content to hash;\n\t\t// that is expected, not a coverage gap.\n\t\tif (stat.isDirectory()) return { skipped: false };\n\t\treturn { skipped: \"error\" };\n\t} catch {\n\t\treturn { skipped: \"error\" };\n\t}\n}\n\nfunction prefixRelative(prefix: string, path: string): string {\n\tif (prefix === \"\" || prefix === \".\") return path;\n\treturn `${prefix}/${path}`;\n}\n\n/**\n * Observe a Git workspace without mutating it. Returns a version-1\n * `WorkspaceStateRecord`: `unsupported` for non-Git workspaces, `failed`\n * when git could not run or the observation was cancelled, and `incomplete`\n * when a limit truncated the capture. `observed` never implies more than\n * `coverage` states.\n */\nexport interface ToplevelComparison {\n\t/** Whether the physically resolved workspace root sits under the toplevel. */\n\tinside: boolean;\n\t/** Root path relative to the toplevel; strip this prefix from porcelain paths. */\n\tprefix: string;\n\t/** Physically resolved toplevel; base for absolute-path work like hashing. */\n\ttoplevelReal: string;\n}\n\n/**\n * Decide containment of the workspace root inside git's toplevel after both\n * sides are physically resolved. Windows spellings diverge from what Node's\n * realpath returns for the same directory (short 8.3 names, drive-letter\n * case), so the win32 branch resolves through the native resolver, folds\n * case for the comparison, and uses win32 path semantics. The platform and\n * resolver are injectable so tests can exercise those branches anywhere.\n */\nexport function compareToplevel(\n\tworkspaceRoot: string,\n\ttoplevel: string,\n\toptions?: {\n\t\tplatform?: NodeJS.Platform;\n\t\trealpath?: (path: string) => string;\n\t},\n): ToplevelComparison {\n\tconst platform = options?.platform ?? process.platform;\n\tconst isWin32 = platform === \"win32\";\n\tconst realpath =\n\t\toptions?.realpath ??\n\t\t(isWin32\n\t\t\t? (p: string) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn realpathSync.native(p);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn realpathSync(p);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t: realpathSync);\n\tconst rootReal = realpath(workspaceRoot);\n\tconst toplevelReal = realpath(toplevel);\n\tconst pathMod = isWin32 ? pathWin32 : { relative, sep, dirname };\n\tconst fold = (p: string) => (isWin32 ? p.toLowerCase() : p);\n\tconst prefix = pathMod.relative(toplevelReal, rootReal);\n\tconst inside = !(prefix === \"..\" || prefix.startsWith(`..${pathMod.sep}`) || isAbsolute(prefix));\n\tif (isWin32 && inside) {\n\t\t// Recompute the strip prefix under case folding so a divergent drive or\n\t\t// directory case still yields the clean \"\" or relative form.\n\t\tconst folded = pathMod.relative(fold(toplevelReal), fold(rootReal));\n\t\treturn { inside, prefix: folded, toplevelReal };\n\t}\n\treturn { inside, prefix, toplevelReal };\n}\n\nexport async function observeWorkspaceGit(\n\tworkspaceRoot: string,\n\toptions?: GitObserveOptions,\n): Promise<WorkspaceStateRecord> {\n\tconst maxPaths = options?.maxPaths ?? DEFAULT_MAX_PATHS;\n\tconst maxHashBytes = options?.maxHashBytes ?? DEFAULT_MAX_HASH_BYTES;\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst hashPaths = options?.hashPaths ?? true;\n\tconst signal = options?.signal;\n\tconst excludePaths = (options?.excludePaths ?? [])\n\t\t.map((p) => p.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/+$/, \"\"))\n\t\t.filter((p) => p.length > 0);\n\tconst isExcluded = (repoPath: string): boolean =>\n\t\texcludePaths.some((ex) => repoPath === ex || repoPath.startsWith(`${ex}/`));\n\n\tconst warnings: string[] = [];\n\tconst failed = (message: string): WorkspaceStateRecord => ({\n\t\tversion: WORKSPACE_RECORD_VERSION,\n\t\tobservationId: randomUUID(),\n\t\tstatus: \"failed\",\n\t\tbackend: \"git\",\n\t\tworkspaceRoot,\n\t\tcapturedAt: new Date().toISOString(),\n\t\tcoverage: emptyCoverage(),\n\t\tpaths: [],\n\t\twarnings: [message],\n\t});\n\n\tif (signal?.aborted) {\n\t\treturn failed(\"workspace observation cancelled\");\n\t}\n\n\tconst head = await runGit(workspaceRoot, [\"rev-parse\", \"--show-toplevel\"], timeoutMs, signal);\n\tif (head.spawnError) return failed(\"git could not be executed\");\n\tif (head.timedOut) return failed(\"workspace observation timed out\");\n\tif (signal?.aborted) return failed(\"workspace observation cancelled\");\n\tif (!head.ok) {\n\t\tif (/not a git repository/i.test(head.stderr) || head.code === 128) {\n\t\t\treturn {\n\t\t\t\t...failed(\"not a git repository\"),\n\t\t\t\tstatus: \"unsupported\",\n\t\t\t};\n\t\t}\n\t\treturn failed(\"git rev-parse failed\");\n\t}\n\t// git resolves the toplevel physically (macOS /tmp -> /private/tmp,\n\t// Windows drive-letter case and short names), so containment is decided\n\t// through compareToplevel; otherwise a divergent spelling of the same\n\t// directory would fail the observation or corrupt every reported path.\n\tconst toplevel = head.stdout.toString(\"utf-8\").trim();\n\tconst comparison = compareToplevel(workspaceRoot, toplevel);\n\tif (!comparison.inside) {\n\t\treturn failed(\"workspace root is outside the repository toplevel\");\n\t}\n\tconst insidePrefix = comparison.prefix;\n\n\tconst headCommit = await runGit(workspaceRoot, [\"rev-parse\", \"--verify\", \"HEAD\"], timeoutMs, signal);\n\tconst mergeHead = await runGit(workspaceRoot, [\"rev-parse\", \"-q\", \"--verify\", \"MERGE_HEAD\"], timeoutMs, signal);\n\tif (signal?.aborted) return failed(\"workspace observation cancelled\");\n\tif (mergeHead.ok) warnings.push(\"merge in progress\");\n\tconst branch = await runGit(workspaceRoot, [\"branch\", \"--show-current\"], timeoutMs, signal);\n\n\tconst headCommitValue = headCommit.ok ? headCommit.stdout.toString(\"utf-8\").trim() : undefined;\n\tif (!headCommit.ok) warnings.push(\"unborn HEAD (no commits)\");\n\tconst branchValue = branch.ok ? branch.stdout.toString(\"utf-8\").trim() : \"\";\n\tif (branchValue === \"\") warnings.push(\"detached HEAD\");\n\n\t// Index baseline.\n\tconst index = await runGit(workspaceRoot, [\"ls-files\", \"--stage\", \"-z\"], timeoutMs, signal);\n\tif (!index.ok) return failed(\"git ls-files failed\");\n\tconst indexDigest = `sha256:${createHash(\"sha256\").update(index.stdout).digest(\"hex\")}`;\n\n\t// Staged / unstaged / untracked / ignored change sets.\n\tconst status = await runGit(\n\t\tworkspaceRoot,\n\t\t[\"status\", \"--porcelain\", \"-z\", \"--untracked-files=all\", \"--ignored=matching\"],\n\t\ttimeoutMs,\n\t\tsignal,\n\t);\n\tif (!status.ok) return failed(\"git status failed\");\n\n\tconst paths: WorkspaceStatePath[] = [];\n\tlet truncated = false;\n\tlet skippedHashes = 0;\n\tfor (const entry of parsePorcelainZ(status.stdout)) {\n\t\tif (isExcluded(entry.path) || (entry.previousPath !== undefined && isExcluded(entry.previousPath))) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (paths.length >= maxPaths) {\n\t\t\ttruncated = true;\n\t\t\twarnings.push(`path list truncated at ${maxPaths} paths`);\n\t\t\tbreak;\n\t\t}\n\t\tconst { kind, staged, unstaged, ignored } = classify(entry);\n\t\tconst workspacePath: WorkspaceStatePath = {\n\t\t\tpath: prefixRelative(insidePrefix, entry.path),\n\t\t\tkind,\n\t\t\tstaged,\n\t\t\tunstaged,\n\t\t\t...(ignored ? { ignored: true } : {}),\n\t\t\t...(entry.previousPath ? { previousPath: prefixRelative(insidePrefix, entry.previousPath) } : {}),\n\t\t};\n\t\tif (hashPaths && kind !== \"deleted\") {\n\t\t\tconst { hash, skipped } = hashWorkspacePath(comparison.toplevelReal, entry.path, maxHashBytes);\n\t\t\tif (hash) workspacePath.contentHash = hash;\n\t\t\telse if (skipped) skippedHashes++;\n\t\t}\n\t\tpaths.push(workspacePath);\n\t}\n\tif (skippedHashes > 0) warnings.push(`content hashing skipped for ${skippedHashes} path(s)`);\n\n\t// Digest over exactly the paths this record includes, so a later\n\t// comparison can cheaply detect that the covered state moved.\n\tconst digestInput = paths\n\t\t.map(\n\t\t\t(p) =>\n\t\t\t\t`${p.path}\\0${p.kind}\\0${p.staged ? \"S\" : \"\"}${p.unstaged ? \"U\" : \"\"}${p.ignored ? \"I\" : \"\"}\\0${p.contentHash ?? \"\"}\\n`,\n\t\t)\n\t\t.sort()\n\t\t.join(\"\");\n\n\treturn {\n\t\tversion: WORKSPACE_RECORD_VERSION,\n\t\tobservationId: randomUUID(),\n\t\tstatus: truncated || skippedHashes > 0 ? \"incomplete\" : \"observed\",\n\t\tbackend: \"git\",\n\t\tworkspaceRoot,\n\t\tcapturedAt: new Date().toISOString(),\n\t\t// `hashes` reflects the configured policy: a disabled hash pass is a\n\t\t// coverage statement, not an incomplete capture.\n\t\tcoverage: { ...fullCoverage(), hashes: hashPaths },\n\t\tbase: {\n\t\t\t...(headCommitValue ? { headCommit: headCommitValue } : {}),\n\t\t\t...(branchValue ? { branch: branchValue } : {}),\n\t\t\tindexDigest,\n\t\t\t...(truncated ? {} : { worktreeDigest: `sha256:${createHash(\"sha256\").update(digestInput).digest(\"hex\")}` }),\n\t\t},\n\t\tpaths,\n\t\twarnings,\n\t};\n}\n"]}