{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { Agent, type AgentMessage, type StreamFn, type ThinkingLevel } from \"@apholdings/jensen-agent-core\";\nimport {\n\tassertValidChatCompletionsPayload,\n\tassertValidResponsesPayload,\n\ttype Message,\n\ttype Model,\n} from \"@apholdings/jensen-ai\";\nimport { getAgentDir, getDocsPath } from \"../config.js\";\nimport { AgentSession } from \"./agent-session.js\";\nimport { AuthStorage } from \"./auth-storage.js\";\nimport {\n\ttype ContextCapabilityOverrides,\n\tContextGovernor,\n\tEvidenceFileStore,\n\tresolveContextCapability,\n\ttype ToolVirtualizationRecord,\n} from \"./context-runtime/index.js\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.js\";\nimport type { ExtensionRunner, LoadExtensionsResult, ToolDefinition } from \"./extensions/index.js\";\nimport { governancePolicyFromEnv } from \"./governance/evaluator.js\";\nimport { GovernanceService } from \"./governance/service.js\";\nimport { convertToLlm } from \"./messages.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { findInitialModel } from \"./model-resolver.js\";\nimport type { ResourceLoader } from \"./resource-loader.js\";\nimport { DefaultResourceLoader } from \"./resource-loader.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { SettingsManager } from \"./settings-manager.js\";\nimport { resolveSharedInferenceRuntime } from \"./shared-inference/config.js\";\nimport { time } from \"./timings.js\";\nimport {\n\tallTools,\n\tbashTool,\n\tcodingTools,\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreatePowerShellTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\teditTool,\n\tfindTool,\n\tgrepTool,\n\tlsTool,\n\tpowershellTool,\n\treadOnlyTools,\n\treadTool,\n\ttype Tool,\n\ttype ToolName,\n\twriteTool,\n} from \"./tools/index.js\";\n\n/** Coerce a persisted virtualization record into its typed form, failing safe. */\nfunction coerceToolVirtualizationRecord(value: unknown): ToolVirtualizationRecord | undefined {\n\tif (typeof value !== \"object\" || value === null) return undefined;\n\tconst r = value as Record<string, unknown>;\n\tif (\n\t\ttypeof r.toolCallId !== \"string\" ||\n\t\ttypeof r.evidenceId !== \"string\" ||\n\t\ttypeof r.contentHash !== \"string\" ||\n\t\ttypeof r.source !== \"string\" ||\n\t\ttypeof r.synopsis !== \"string\" ||\n\t\ttypeof r.contentBytes !== \"number\" ||\n\t\ttypeof r.virtualizedAtMs !== \"number\"\n\t) {\n\t\treturn undefined;\n\t}\n\treturn {\n\t\ttoolCallId: r.toolCallId,\n\t\tevidenceId: r.evidenceId,\n\t\tcontentHash: r.contentHash,\n\t\tsource: r.source,\n\t\tsynopsis: r.synopsis,\n\t\tcontentBytes: r.contentBytes,\n\t\tvirtualizedAtMs: r.virtualizedAtMs,\n\t};\n}\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.pi/agent */\n\tagentDir?: string;\n\n\t/** Auth storage for credentials. Default: AuthStorage.create(agentDir/auth.json) */\n\tauthStorage?: AuthStorage;\n\t/** Model registry. Default: new ModelRegistry(authStorage, agentDir/models.json) */\n\tmodelRegistry?: ModelRegistry;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Fallback models to try if the primary model fails */\n\tfallbackModels?: 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/** Built-in tools to use. Default: codingTools [read, bash, edit, write] */\n\ttools?: Tool[];\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\n\t/**\n\t * Optional custom stream function. When omitted, the session uses the\n\t * configured shared-inference scheduler stream (if active) or the default\n\t * provider stream.\n\t */\n\tstreamFn?: StreamFn;\n\t/** Structured runtime correlation for durable mission governance. */\n\tmissionId?: string;\n\tassignmentId?: string;\n\texecutionId?: string;\n}\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}\n\n// Re-exports\n\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tSlashCommandInfo,\n\tSlashCommandLocation,\n\tSlashCommandSource,\n\tToolDefinition,\n} from \"./extensions/index.js\";\nexport type { PromptTemplate } from \"./prompt-templates.js\";\nexport type { Skill } from \"./skills.js\";\nexport type { Tool } from \"./tools/index.js\";\n\nexport {\n\tallTools as allBuiltInTools,\n\tbashTool,\n\tcodingTools,\n\tcreateBashTool,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\tcreatePowerShellTool,\n\teditTool,\n\tfindTool,\n\tgrepTool,\n\tlsTool,\n\tpowershellTool,\n\treadOnlyTools,\n\t// Pre-built tools (use process.cwd())\n\treadTool,\n\twriteTool,\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 '@apholdings/jensen-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: [readTool, bashTool],\n *   resourceLoader: loader,\n *   sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst agentDir = options.agentDir ?? getDefaultAgentDir();\n\tlet resourceLoader = options.resourceLoader;\n\n\t// Use provided or create AuthStorage and ModelRegistry\n\tconst authPath = options.agentDir ? join(agentDir, \"auth.json\") : undefined;\n\tconst modelsPath = options.agentDir ? join(agentDir, \"models.json\") : undefined;\n\tconst authStorage = options.authStorage ?? AuthStorage.create(authPath);\n\tconst modelRegistry = options.modelRegistry ?? new ModelRegistry(authStorage, modelsPath);\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd);\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 = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && (await modelRegistry.getApiKey(restoredModel))) {\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\tmodelRegistry,\n\t\t});\n\t\tmodel = result.model;\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `No models available. Use /login or set an API key environment variable. See ${join(getDocsPath(), \"providers.md\")}. Then use /model to select a model.`;\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 settings default\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;\n\t}\n\n\t// Clamp to model capabilities\n\tif (!model || !model.reasoning) {\n\t\tthinkingLevel = \"off\";\n\t}\n\n\t// Determine initial active tools: explicit options.tools takes priority,\n\t// then settings config, then legacy defaults\n\t// Initial active tools: explicit options.tools takes priority, then settings\n\t// config, then legacy defaults. The legacy defaults expose the web research\n\t// family (web_search, web_fetch, deep_research, web_research_status) so that a\n\t// fresh session fulfills the 1.2.1 release contract: read-only web research is\n\t// available without requiring explicit --tools or settings configuration.\n\tconst legacyDefaultTools: ToolName[] = [\n\t\t\"read\",\n\t\t\"bash\",\n\t\t\"edit\",\n\t\t\"write\",\n\t\t\"todo_write\",\n\t\t\"todo_read\",\n\t\t\"todo_update\",\n\t\t\"memory_write\",\n\t\t\"retrieve_evidence\",\n\t\t\"web_search\",\n\t\t\"web_fetch\",\n\t\t\"deep_research\",\n\t\t\"web_research_status\",\n\t];\n\tconst configuredTools = settingsManager.getDefaultActiveToolNames();\n\tconst initialActiveToolNames: ToolName[] = options.tools\n\t\t? options.tools.map((t) => t.name).filter((n): n is ToolName => n in allTools)\n\t\t: (configuredTools ?? legacyDefaultTools);\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\t// Cold evidence archive (L3) is created once and shared by the governor (for\n\t// virtualization) and the model-facing retrieve_evidence capability (for\n\t// bounded rehydration). A single store means evidence references remain\n\t// resolvable across rollovers and session resumes.\n\tconst evidenceArchive = new EvidenceFileStore(join(agentDir, \"context-evidence\"));\n\n\t// Long-Horizon Context Virtualization (2.5.0). The governor is the preflight\n\t// boundary that keeps every request within the safe input budget. It is\n\t// wired into transformContext below and its checkpoint provider is bound to\n\t// the AgentSession after construction.\n\tconst governorSettings = settingsManager.getContextGovernorSettings();\n\tconst contextCapabilityOverrides: ContextCapabilityOverrides = {\n\t\tconfiguredContextWindow: governorSettings.configuredContextWindow,\n\t\treservedOutputTokens: governorSettings.reservedOutputTokens,\n\t\tsafetyReserveTokens: governorSettings.safetyReserveTokens,\n\t\tsoftPressureRatio: governorSettings.softPressureRatio,\n\t};\n\tconst contextGovernor = governorSettings.enabled\n\t\t? new ContextGovernor({\n\t\t\t\tcapability: resolveContextCapability(\n\t\t\t\t\t{\n\t\t\t\t\t\tmodelContextWindow: model?.contextWindow ?? 0,\n\t\t\t\t\t\tmodelMaxTokens: model?.maxTokens ?? 8192,\n\t\t\t\t\t\treasoning: model?.reasoning,\n\t\t\t\t\t},\n\t\t\t\t\tcontextCapabilityOverrides,\n\t\t\t\t),\n\t\t\t\tarchive: evidenceArchive,\n\t\t\t\tcapabilityProvider: () => {\n\t\t\t\t\tconst currentModel = agent.state.model;\n\t\t\t\t\tif (!currentModel?.contextWindow) return undefined as never;\n\t\t\t\t\treturn resolveContextCapability(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmodelContextWindow: currentModel.contextWindow,\n\t\t\t\t\t\t\tmodelMaxTokens: currentModel.maxTokens ?? 8192,\n\t\t\t\t\t\t\treasoning: currentModel.reasoning,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcontextCapabilityOverrides,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tkeepRecentTokens: governorSettings.keepRecentTokens,\n\t\t\t\ttoolResultVirtualizeThreshold: governorSettings.toolResultVirtualizeThreshold,\n\t\t\t\t// Durable virtualization provenance: tool results that were already\n\t\t\t\t// archived stay virtualized across requests, session resume, process\n\t\t\t\t// restart, and durable child resume.\n\t\t\t\tinitialVirtualizations: sessionManager\n\t\t\t\t\t.getLatestSessionToolVirtualizations()\n\t\t\t\t\t.map(coerceToolVirtualizationRecord)\n\t\t\t\t\t.filter((r): r is NonNullable<typeof r> => r !== undefined),\n\t\t\t\tinitialEvidenceRefs: sessionManager.getLatestSessionEvidenceRefs(),\n\t\t\t\tvirtualizationProvider: () =>\n\t\t\t\t\tsessionManager\n\t\t\t\t\t\t.getLatestSessionToolVirtualizations()\n\t\t\t\t\t\t.map(coerceToolVirtualizationRecord)\n\t\t\t\t\t\t.filter((r): r is NonNullable<typeof r> => r !== undefined),\n\t\t\t\tvirtualizationSink: (records) => {\n\t\t\t\t\tsessionManager.appendSessionToolVirtualizations(records);\n\t\t\t\t},\n\t\t\t})\n\t\t: undefined;\n\n\tconst governance = options.missionId ? new GovernanceService({ policy: governancePolicyFromEnv() }) : undefined;\n\tconst sharedInference = resolveSharedInferenceRuntime({\n\t\tsessionId: sessionManager.getSessionId(),\n\t\tmissionId: options.missionId ?? process.env.JENSEN_MISSION_ID,\n\t\tassignmentId: options.assignmentId ?? process.env.JENSEN_ASSIGNMENT_ID,\n\t\texecutionId: options.executionId ?? process.env.JENSEN_EXECUTION_ID,\n\t\tgovernance,\n\t});\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\tstreamFn: options.streamFn ?? sharedInference?.streamFn,\n\t\tconvertToLlm: convertToLlmWithBlockImages,\n\t\tonPayload: async (payload, model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tlet finalPayload = payload;\n\t\t\tif (runner?.hasHandlers(\"before_provider_request\")) {\n\t\t\t\tfinalPayload = await runner.emitBeforeProviderRequest(payload);\n\t\t\t}\n\t\t\tif (model.api === \"openai-completions\") {\n\t\t\t\tassertValidChatCompletionsPayload(finalPayload, model.provider, model.id);\n\t\t\t} else if (model.api.endsWith(\"-responses\")) {\n\t\t\t\tassertValidResponsesPayload(finalPayload, model.provider, model.id);\n\t\t\t}\n\t\t\treturn finalPayload;\n\t\t},\n\t\tsessionId: sessionManager.getSessionId(),\n\t\ttransformContext: async (messages) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tconst withExtensions = runner ? await runner.emitContext(messages) : messages;\n\t\t\tif (!contextGovernor) return withExtensions;\n\t\t\tconst currentModel = agent.state.model;\n\t\t\tif (!currentModel?.contextWindow) return withExtensions;\n\t\t\tconst result = await contextGovernor.govern({\n\t\t\t\tsystemPrompt: agent.state.systemPrompt,\n\t\t\t\tdynamicPrompt: agent.state.dynamicPrompt,\n\t\t\t\tmessages: withExtensions,\n\t\t\t\ttools: agent.state.tools,\n\t\t\t});\n\t\t\tif (process.env.JENSEN_CONTEXT_TELEMETRY) {\n\t\t\t\tprocess.stderr.write(`[context-governor] ${JSON.stringify(result.diagnostics)}\\n`);\n\t\t\t}\n\t\t\treturn result.assembly.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.getRetrySettings().maxDelayMs,\n\t\tgetApiKey: async (provider) => {\n\t\t\t// Use the provider argument from the in-flight request;\n\t\t\t// agent.state.model may already be switched mid-turn.\n\t\t\tconst resolvedProvider = provider || agent.state.model?.provider;\n\t\t\tif (!resolvedProvider) {\n\t\t\t\tthrow new Error(\"No model selected\");\n\t\t\t}\n\t\t\tconst key = await modelRegistry.getApiKeyForProvider(resolvedProvider);\n\t\t\tif (!key) {\n\t\t\t\tconst model = agent.state.model;\n\t\t\t\tconst isOAuth = model && modelRegistry.isUsingOAuth(model);\n\t\t\t\tif (isOAuth) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Authentication failed for \"${resolvedProvider}\". ` +\n\t\t\t\t\t\t\t`Credentials may have expired or network is unavailable. ` +\n\t\t\t\t\t\t\t`Run '/login ${resolvedProvider}' to re-authenticate.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No API key found for \"${resolvedProvider}\". ` +\n\t\t\t\t\t\t`Set an API key environment variable or run '/login ${resolvedProvider}'.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn key;\n\t\t},\n\t});\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.replaceMessages(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\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tscopedModels: options.scopedModels,\n\t\tfallbackModels: options.fallbackModels,\n\t\tresourceLoader,\n\t\tcustomTools: options.customTools,\n\t\tmodelRegistry,\n\t\tinitialActiveToolNames,\n\t\textensionRunnerRef,\n\t\tevidenceArchive,\n\t\tcontextGovernor,\n\t});\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tif (governance && options.missionId) {\n\t\tconst seenToolCalls = new Set<string>();\n\t\tlet turnSequence = 0;\n\t\tlet retrySequence = 0;\n\t\tsession.subscribe((event) => {\n\t\t\tvoid (async () => {\n\t\t\t\tif (event.type === \"turn_end\") {\n\t\t\t\t\tturnSequence += 1;\n\t\t\t\t\tawait governance.consume(options.missionId!, {\n\t\t\t\t\t\teventId: `${sessionManager.getSessionId()}:turn:${turnSequence}`,\n\t\t\t\t\t\tscope: \"session\",\n\t\t\t\t\t\tresource: \"turns\",\n\t\t\t\t\t\tamount: 1,\n\t\t\t\t\t\tatMs: Date.now(),\n\t\t\t\t\t});\n\t\t\t\t} else if (event.type === \"tool_execution_start\" && !seenToolCalls.has(event.toolCallId)) {\n\t\t\t\t\tseenToolCalls.add(event.toolCallId);\n\t\t\t\t\tawait governance.consume(options.missionId!, {\n\t\t\t\t\t\teventId: `${sessionManager.getSessionId()}:tool:${event.toolCallId}`,\n\t\t\t\t\t\tscope: \"session\",\n\t\t\t\t\t\tresource: \"toolCalls\",\n\t\t\t\t\t\tamount: 1,\n\t\t\t\t\t\tatMs: Date.now(),\n\t\t\t\t\t});\n\t\t\t\t} else if (event.type === \"auto_retry_start\") {\n\t\t\t\t\tretrySequence += 1;\n\t\t\t\t\tawait governance.recordRetry(\n\t\t\t\t\t\toptions.missionId!,\n\t\t\t\t\t\t`${sessionManager.getSessionId()}:provider-retry:${retrySequence}`,\n\t\t\t\t\t\t\"provider\",\n\t\t\t\t\t\tDate.now(),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t})().catch(() => {\n\t\t\t\t// Governance failures are surfaced by the governed stream/admission path;\n\t\t\t\t// event observers never create an unhandled session rejection.\n\t\t\t});\n\t\t});\n\t}\n\n\t// Bind the governor's checkpoint provider to the session's durable-projection\n\t// checkpoint so a rollover rehydrates operational state across the SAME mission.\n\t// Evidence references are persisted so the model can page old cold artifacts\n\t// back after rollover via retrieve_evidence.\n\tcontextGovernor?.setCheckpointProvider(() =>\n\t\tsession.buildMissionContextCheckpoint(contextGovernor.getArchivedEvidenceRefs()),\n\t);\n\n\t// Persist newly-archived evidence references into the session so a durable\n\t// child can retrieve pre-interruption evidence after explicit resume.\n\tcontextGovernor?.setEvidenceRefsSink((refs) => {\n\t\tsessionManager.appendSessionEvidenceRefs(refs);\n\t});\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}