@pwrdrvr/agent-acp 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/acp-connection.ts","../src/acp-client.ts","../src/normalizer/acp-normalizer.ts","../src/normalizer/content.ts","../src/normalizer/tool-activity.ts","../src/normalizer/runtime-capabilities.ts","../src/mcp-server-config.ts","../src/acp-agent-client-pool.ts","../src/acp-oneshot-client.ts","../src/strategies/strategy-types.ts","../src/strategies/gemini.ts","../src/strategies/grok.ts","../src/strategies/kimi.ts","../src/strategies/qwen.ts","../src/strategies/index.ts","../src/discovery/acp-local-discovery.ts","../src/discovery/acp-agent-allowlist.ts","../src/discovery/acp-registry-types.ts","../src/discovery/acp-registry-service.ts"],"sourcesContent":["// ACP connection backed by the official `@agentclientprotocol/sdk`\n// library. Replaces our hand-rolled ACP wire layer (acp-stdio-transport.ts): the\n// library owns JSON-RPC framing, ndjson stdio, protocol-method dispatch, and\n// schema validation. We keep ownership of the things the library does NOT do —\n// spawning + process lifetime, discovery, the normalizer, and per-agent quirks.\n//\n// This implements the SAME `AcpJsonRpcTransport` seam the ACP clients already\n// drive (request / notify / onNotification / onRequest), so `AcpAgentClient`,\n// `AcpOneShotClient`, and the pool are unchanged — only the concrete connection\n// they're handed swaps. The generic `request(method, params)` calls map onto the\n// library's typed methods (with generic `request` / `notify` for non-standard\n// ones like `session/set_config_option`); the library's `Client` callbacks\n// (`sessionUpdate` / `extNotification` / `requestPermission`) bridge back out.\n\nimport { spawn } from \"node:child_process\";\nimport { Readable, Writable } from \"node:stream\";\nimport {\n ClientSideConnection,\n ndJsonStream,\n type Agent,\n type Client,\n type RequestPermissionRequest,\n type RequestPermissionResponse,\n type SessionNotification\n} from \"@agentclientprotocol/sdk\";\nimport { noopLogger, type Logger } from \"@pwrdrvr/agent-core\";\nimport {\n createCommandInvocation,\n prependCommandDirToPath,\n type JsonRpcId\n} from \"@pwrdrvr/agent-transport\";\nimport type { AcpJsonRpcTransport } from \"./acp-transport\";\n\n/** The subset of the library's client→agent surface that `AcpConnection`\n * drives. Injectable (via `createConnection`) so the adapter can be unit-tested\n * without spawning a real agent. The library's `ClientSideConnection` satisfies\n * this structurally (its methods take typed schema params; we pass records that\n * match at runtime). */\nexport interface AcpAgentConnection {\n initialize(params: Record<string, unknown>): Promise<unknown>;\n newSession(params: Record<string, unknown>): Promise<unknown>;\n loadSession(params: Record<string, unknown>): Promise<unknown>;\n prompt(params: Record<string, unknown>): Promise<unknown>;\n cancel(params: Record<string, unknown>): Promise<void>;\n setSessionMode(params: Record<string, unknown>): Promise<unknown>;\n setSessionModel(params: Record<string, unknown>): Promise<unknown>;\n authenticate(params: Record<string, unknown>): Promise<unknown>;\n request(method: string, params: Record<string, unknown>): Promise<unknown>;\n notify(method: string, params: Record<string, unknown>): Promise<void>;\n}\n\n/** Built connection + a teardown handle (kills the child / closes streams). */\nexport type AcpAgentConnectionHandle = {\n connection: AcpAgentConnection;\n dispose: () => void;\n};\n\nexport type AcpConnectionOptions = {\n command: string;\n args: string[];\n env?: NodeJS.ProcessEnv;\n logger?: Logger;\n /** Test seam: build the underlying connection. Defaults to spawning the agent\n * and wiring its stdio through the library's `ClientSideConnection`. */\n createConnection?: (client: Client) => AcpAgentConnectionHandle;\n};\n\nexport class AcpConnection implements AcpJsonRpcTransport {\n private readonly logger: Logger;\n private connection: AcpAgentConnection | undefined;\n private dispose: (() => void) | undefined;\n private connecting: Promise<void> | undefined;\n private readonly notificationListeners = new Set<\n (method: string, params: Record<string, unknown>) => void\n >();\n private requestHandler:\n | ((method: string, params: Record<string, unknown>, id?: JsonRpcId) => Promise<unknown> | unknown)\n | undefined;\n\n constructor(private readonly options: AcpConnectionOptions) {\n this.logger = options.logger ?? noopLogger;\n }\n\n /** The `Client` handler the library invokes for agent→client traffic. */\n private buildClient(): Client {\n const emit = (method: string, params: Record<string, unknown>): void => {\n for (const listener of this.notificationListeners) listener(method, params);\n };\n return {\n requestPermission: async (\n params: RequestPermissionRequest\n ): Promise<RequestPermissionResponse> => {\n if (!this.requestHandler) {\n throw new Error(\"ACP request handler unavailable for session/request_permission\");\n }\n return (await this.requestHandler(\n \"session/request_permission\",\n params as unknown as Record<string, unknown>\n )) as RequestPermissionResponse;\n },\n sessionUpdate: async (params: SessionNotification): Promise<void> => {\n // Emit the full notification ({ sessionId, update }); the client extracts\n // `update` and feeds the normalizer — same shape the old transport gave.\n emit(\"session/update\", params as unknown as Record<string, unknown>);\n },\n extNotification: async (method: string, params: Record<string, unknown>): Promise<void> => {\n // Vendor notifications (e.g. Grok's session_summary_generated) — routed to\n // the client's `vendorNotificationMethods` handling.\n emit(method, params);\n },\n extMethod: async (\n method: string,\n params: Record<string, unknown>\n ): Promise<Record<string, unknown>> => {\n if (!this.requestHandler) {\n throw new Error(`ACP request handler unavailable for ${method}`);\n }\n return ((await this.requestHandler(method, params)) ?? {}) as Record<string, unknown>;\n }\n // No fs/terminal handlers: we don't advertise those client capabilities at\n // `initialize`, so a conformant agent won't call them.\n };\n }\n\n private async ensureConnected(): Promise<void> {\n if (this.connection) return;\n this.connecting ??= this.connect();\n await this.connecting;\n }\n\n private async connect(): Promise<void> {\n const create = this.options.createConnection ?? this.defaultCreateConnection();\n const handle = create(this.buildClient());\n this.connection = handle.connection;\n this.dispose = handle.dispose;\n }\n\n private defaultCreateConnection(): (client: Client) => AcpAgentConnectionHandle {\n const { command, args, env } = this.options;\n const logger = this.logger;\n return (client) => {\n const launchEnv = prependCommandDirToPath(command, env ?? process.env);\n const invocation = createCommandInvocation({ command, args, env: launchEnv });\n const child = spawn(invocation.command, invocation.args, {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: launchEnv,\n windowsVerbatimArguments: invocation.windowsVerbatimArguments\n });\n child.on(\"error\", (error: Error) => {\n logger.error(\"acp agent process error\", { command, message: error.message });\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n const line = chunk.toString(\"utf8\").trimEnd();\n if (line.length > 0) logger.debug(\"acp agent stderr\", { line });\n });\n // ndJsonStream(writeToAgentStdin, readFromAgentStdout) — arg order: first is\n // the WritableStream we send to, second is the ReadableStream we read from.\n // SDK 1.3 accepts the protocol's scalar/array tool raw values and config\n // option updates directly, so passing stdio through unmodified preserves\n // the agent's exact notification payload.\n const toAgentStdin = Writable.toWeb(child.stdin) as WritableStream<Uint8Array>;\n const fromAgentStdout = Readable.toWeb(child.stdout) as ReadableStream<Uint8Array>;\n const stream = ndJsonStream(toAgentStdin, fromAgentStdout);\n // ClientSideConnection is deprecated in favor of the SDK's typed\n // client() builder, but it is the supported compatibility bridge that\n // retains wildcard inbound extension handlers. Agent-kit must preserve\n // unknown vendor request/notification routing for discovery strategies;\n // the typed builder requires registering each custom method up front.\n const connection = new ClientSideConnection(\n (_agent: Agent) => client,\n stream\n ) as unknown as AcpAgentConnection;\n return {\n connection,\n dispose: () => {\n try {\n child.stdin?.end();\n } catch {\n // already closed\n }\n child.kill();\n }\n };\n };\n }\n\n async request(\n method: string,\n params: Record<string, unknown> = {},\n _timeoutMs?: number\n ): Promise<unknown> {\n await this.ensureConnected();\n const conn = this.connection;\n if (!conn) throw new Error(\"acp connection unavailable\");\n switch (method) {\n case \"initialize\":\n return await conn.initialize(params);\n case \"session/new\":\n return await conn.newSession(params);\n case \"session/load\":\n return await conn.loadSession(params);\n case \"session/prompt\":\n return await conn.prompt(params);\n case \"session/set_mode\":\n return await conn.setSessionMode(params);\n case \"session/set_model\":\n return await conn.setSessionModel(params);\n case \"session/cancel\":\n await conn.cancel(params);\n return {};\n case \"authenticate\":\n return await conn.authenticate(params);\n default:\n // Unknown vendor methods remain part of agent-kit's generic transport\n // seam. SDK 1.3 sends them verbatim through its non-deprecated request().\n return await conn.request(method, params);\n }\n }\n\n async notify(method: string, params: Record<string, unknown> = {}): Promise<void> {\n await this.ensureConnected();\n const conn = this.connection;\n if (!conn) throw new Error(\"acp connection unavailable\");\n if (method === \"session/cancel\") {\n await conn.cancel(params);\n return;\n }\n await conn.notify(method, params);\n }\n\n async close(): Promise<void> {\n try {\n this.dispose?.();\n } finally {\n this.connection = undefined;\n this.dispose = undefined;\n this.connecting = undefined;\n }\n }\n\n onNotification(\n listener: (method: string, params: Record<string, unknown>) => void\n ): () => void {\n this.notificationListeners.add(listener);\n return () => {\n this.notificationListeners.delete(listener);\n };\n }\n\n onRequest(\n listener: (\n method: string,\n params: Record<string, unknown>,\n id?: JsonRpcId\n ) => Promise<unknown> | unknown\n ): () => void {\n this.requestHandler = listener;\n return () => {\n if (this.requestHandler === listener) {\n this.requestHandler = undefined;\n }\n };\n }\n}\n","// Long-lived ACP client. Speaks ACP over the stdio transport and normalizes the\n// agent's `session/update` stream into agent-core `NormalizedThreadEvent` — the\n// same shapes CodexThreadClient emits, so the two unify behind `AgentBackend`.\n//\n// PUBLIC SURFACE mirrors CodexThreadClient on purpose:\n// startThread / startTurn / interruptTurn / onEvent / onToolCall /\n// onApprovalRequest / close.\n//\n// Ported from PwrAgnt acp-client.ts, with all app concerns stripped (SQLite\n// session/rollout stores, live-notifications, DesktopBackendRegistry). Per-\n// session state the normalizer needs is held IN-MEMORY here; persistence is the\n// host's job (agent-core ThreadStore).\n//\n// Per-agent quirks (suppress thoughts, title source, vendor notification\n// methods) come from the registered STRATEGY — never an inline agent-id branch.\n\nimport {\n noopLogger,\n type AgentBackend,\n type AgentBackendApprovalHandler,\n type AgentBackendStartThreadResult,\n type AgentBackendToolCall,\n type AgentBackendToolCallHandler,\n type AgentStartThreadOptions,\n type AgentStartTurnOptions,\n type Logger,\n type NormalizedApprovalDecision,\n type NormalizedApprovalRequest,\n type NormalizedThreadEvent,\n type NormalizedThreadSettings,\n type NormalizedTokenUsage,\n type Unsubscribe\n} from \"@pwrdrvr/agent-core\";\nimport { mkdirSync } from \"node:fs\";\nimport { randomUUID } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { extname } from \"node:path\";\nimport type { JsonRpcId } from \"@pwrdrvr/agent-transport\";\nimport type { AcpAgentStrategy } from \"./strategies/strategy-types\";\nimport {\n AcpSessionNormalizer,\n type AcpApplyContext\n} from \"./normalizer/acp-normalizer\";\nimport {\n acpRuntimeSupportsHttpMcp,\n acpRuntimeSupportsSessionLoad,\n acpRuntimeSupportsSseMcp,\n acpSessionRuntimeStateFromCapabilities,\n acpSessionRuntimeStateFromUpdate,\n mergeAcpRuntimeState,\n modeLabelFor,\n modelIdFromCapabilities,\n normalizeAcpRuntimeCapabilities,\n type AcpRuntimeCapabilities,\n type AcpRuntimeConfigOptionValue,\n type AcpSessionRuntimeState\n} from \"./normalizer/runtime-capabilities\";\nimport type { AcpJsonRpcTransport } from \"./acp-transport\";\nimport {\n normalizeAcpMcpServerConfigs,\n redactAcpMcpCredentials,\n type AcpMcpServerConfig\n} from \"./mcp-server-config\";\n\nconst ACP_PROTOCOL_VERSION = 1;\nconst ACP_PROMPT_REQUEST_TIMEOUT_MS = 60 * 60_000;\nconst ACP_REQUEST_TIMEOUT_MS = 30_000;\n\nexport type AcpPromptContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"image\"; mimeType: string; data: string };\n\nexport type AcpRuntimeOptionSource = \"mode\" | \"model\" | \"configOption\";\n\nexport type AcpAgentClientOptions = {\n /** The transport (real stdio or a fake). */\n transport: AcpJsonRpcTransport;\n /** The agent strategy (carries quirks + display name). */\n strategy: AcpAgentStrategy;\n /** Identity sent at `initialize`. Defaults to \"agent-kit\". */\n clientName?: string;\n clientTitle?: string;\n clientVersion?: string;\n /** Default cwd for `session/new` when `startThread` omits one. */\n cwd?: string;\n /** MCP servers to attach at `session/new` / `session/load`. */\n mcpServers?: readonly AcpMcpServerConfig[];\n now?: () => number;\n logger?: Logger;\n};\n\n/** ACP-NATIVE thread/start options. **No longer the public `startThread`\n * surface** — `AcpAgentClient` implements the non-generic `AgentBackend` and its\n * public `startThread` takes neutral `AgentStartThreadOptions`. Retained as the\n * internal mapping target and exposed via `startThreadNative` for hosts wanting\n * ACP-specific control (e.g. per-thread `mcpServers`). */\nexport type AcpStartThreadOptions = {\n /** Working directory for the agent session. */\n cwd?: string;\n mcpServers?: readonly AcpMcpServerConfig[];\n};\n\n/** ACP-native `session/load` options. The protocol session id is the id the\n * agent persisted; `threadId` optionally preserves a separate host-facing id. */\nexport type AcpLoadThreadOptions = {\n sessionId: string;\n threadId?: string;\n cwd?: string;\n mcpServers?: readonly AcpMcpServerConfig[];\n};\n\n/** ACP-NATIVE turn/start options. Internal mapping target; the public `startTurn`\n * takes neutral `AgentStartTurnOptions`. */\nexport type AcpStartTurnOptions = {\n threadId: string;\n /** Plain prompt text. */\n prompt?: string;\n /** Pre-built ACP content blocks (text/image); overrides `prompt` when set. */\n promptContent?: AcpPromptContentBlock[];\n};\n\n/** Fired when the normalizer extracts a thread title from the stream. */\nexport type AcpTitleHandler = (event: {\n threadId: string;\n title: string;\n}) => void;\n\n/** Fired when runtime capabilities (models/modes/config-options) are observed. */\nexport type AcpRuntimeCapabilitiesHandler = (event: {\n threadId?: string;\n runtimeCapabilities: AcpRuntimeCapabilities;\n runtimeState?: AcpSessionRuntimeState;\n}) => void;\n\ntype AcpSessionState = {\n threadId: string;\n protocolSessionId: string;\n normalizer: AcpSessionNormalizer;\n turnId: string | undefined;\n runtimeState: AcpSessionRuntimeState | undefined;\n /** The in-flight `session/prompt` completion chain for the active turn.\n * `startTurnNative` resolves at turn START and streams terminal events from\n * this chain when the request settles; `undefined` between turns. Awaited by\n * `close()` so teardown doesn't orphan a running turn. The chain is\n * `.catch`-terminated, so it never rejects. */\n pendingTurn: Promise<void> | undefined;\n /** System prompt captured from the neutral `startThread({ instructions })`.\n * ACP has no `session/new` baseInstructions seam, so we fold it into the\n * FIRST turn's prompt as a leading text block (same approach the one-shot\n * enrichment client uses), then clear it. `undefined` once consumed / when\n * the host supplied none. */\n pendingInstructions: string | undefined;\n /** Names of the MCP servers attached to THIS session (per-thread, since one\n * shared client can serve surfaces with different tool sets). Used to\n * give the host's approval policy session-isolated MCP context. */\n mcpServerNames: string[];\n};\n\nconst DEFAULT_CLIENT_NAME = \"agent-kit\";\n\n/** Map a neutral approval decision onto an ACP permission decision token. */\nfunction permissionDecisionToken(decision: NormalizedApprovalDecision): string {\n switch (decision) {\n case \"approved\":\n return \"approve\";\n case \"abort\":\n case \"denied\":\n default:\n return \"reject\";\n }\n}\n\nexport class AcpAgentClient implements AgentBackend {\n private readonly transport: AcpJsonRpcTransport;\n private readonly strategy: AcpAgentStrategy;\n private readonly now: () => number;\n private readonly logger: Logger;\n\n private readonly eventListeners = new Set<(event: NormalizedThreadEvent) => void>();\n private toolCallHandler: AgentBackendToolCallHandler | null = null;\n private approvalHandler: AgentBackendApprovalHandler | null = null;\n private titleHandler: AcpTitleHandler | null = null;\n private runtimeCapabilitiesHandler: AcpRuntimeCapabilitiesHandler | null = null;\n\n // threadId ↔ protocol sessionId mapping + per-session state.\n private readonly sessions = new Map<string, AcpSessionState>();\n private readonly threadIdByProtocolId = new Map<string, string>();\n\n private unsubscribeNotification: (() => void) | undefined = undefined;\n private unsubscribeRequest: (() => void) | undefined = undefined;\n private initialized = false;\n private runtimeCapabilities?: AcpRuntimeCapabilities;\n\n constructor(options: AcpAgentClientOptions) {\n this.transport = options.transport;\n this.strategy = options.strategy;\n this.now = options.now ?? Date.now;\n this.logger = options.logger ?? noopLogger;\n this.clientName = options.clientName ?? DEFAULT_CLIENT_NAME;\n this.clientTitle = options.clientTitle ?? this.clientName;\n this.clientVersion = options.clientVersion ?? \"0.0.0\";\n this.defaultCwd = options.cwd;\n this.defaultMcpServers = options.mcpServers ?? [];\n }\n\n private readonly clientName: string;\n private readonly clientTitle: string;\n private readonly clientVersion: string;\n private readonly defaultCwd: string | undefined;\n private readonly defaultMcpServers: readonly AcpMcpServerConfig[];\n\n // ---- subscriptions (mirror CodexThreadClient) ----\n\n onEvent(cb: (event: NormalizedThreadEvent) => void): Unsubscribe {\n this.eventListeners.add(cb);\n return () => {\n this.eventListeners.delete(cb);\n };\n }\n\n onToolCall(handler: AgentBackendToolCallHandler): Unsubscribe {\n this.toolCallHandler = handler;\n return () => {\n if (this.toolCallHandler === handler) this.toolCallHandler = null;\n };\n }\n\n onApprovalRequest(handler: AgentBackendApprovalHandler): Unsubscribe {\n this.approvalHandler = handler;\n return () => {\n if (this.approvalHandler === handler) this.approvalHandler = null;\n };\n }\n\n /** Subscribe to title extraction (topic-update / session-summary). */\n onTitle(handler: AcpTitleHandler): Unsubscribe {\n this.titleHandler = handler;\n return () => {\n if (this.titleHandler === handler) this.titleHandler = null;\n };\n }\n\n /** Subscribe to runtime-capabilities (models/modes/config-options) changes. */\n onRuntimeCapabilities(handler: AcpRuntimeCapabilitiesHandler): Unsubscribe {\n this.runtimeCapabilitiesHandler = handler;\n return () => {\n if (this.runtimeCapabilitiesHandler === handler) {\n this.runtimeCapabilitiesHandler = null;\n }\n };\n }\n\n // ---- lifecycle ----\n\n /**\n * Public `AgentBackend.startThread`: accepts NEUTRAL `AgentStartThreadOptions`\n * and maps them onto an ACP `session/new`. ACP supports:\n * • `cwd` → `session/new.cwd`.\n * • `model` → applied via `session/set_model` after the session opens, when\n * the agent advertises model selection (best-effort; debug-logged if not).\n * • `instructions` is NOT injected here — ACP `session/new` has no base-\n * instructions slot, matching the adapter's existing behavior. A host that\n * wants system framing sends it as leading turn text.\n * Codex-only fields (`approvalPolicy`, `sandbox`, `config`, `environments`,\n * `tools`, `serviceName`, `modelProvider`, `serviceTier`, `workspaceRoots`) are\n * IGNORED — logged at debug so it's visible the backend doesn't honor them.\n */\n async startThread(\n options: AgentStartThreadOptions = {}\n ): Promise<AgentBackendStartThreadResult> {\n const ignored: string[] = [];\n for (const key of [\n \"approvalPolicy\",\n \"sandbox\",\n \"config\",\n \"environments\",\n \"tools\",\n \"serviceName\",\n \"modelProvider\",\n \"serviceTier\",\n \"workspaceRoots\"\n ] as const) {\n if (options[key] !== undefined) ignored.push(key);\n }\n if (ignored.length > 0) {\n this.logger.debug(\"acp startThread: ignoring Codex-only neutral options\", {\n ignored\n });\n }\n const native: AcpStartThreadOptions = {};\n if (options.cwd !== undefined) native.cwd = options.cwd;\n const result = await this.startThreadNative(native);\n // ACP has no `session/new` system-prompt seam, so stash the host's\n // `instructions` and fold them into the first turn's prompt (below). Without\n // this an ACP chat agent runs with NO host system prompt / persona / anchor\n // context — just its own CLI harness prompt.\n if (typeof options.instructions === \"string\" && options.instructions.length > 0) {\n const session = this.sessions.get(result.threadId);\n if (session) session.pendingInstructions = options.instructions;\n }\n // Report the model that ACTUALLY runs. `result.model` is the session/new\n // default (currentModelId); `setModel` may or may not apply the requested\n // one. If it applies, the effective model is the request; if it fails (e.g.\n // an unknown/stale id), the agent keeps its default — so a caller must NOT\n // report the requested id. Track the outcome and return the effective model.\n if (options.model !== undefined) {\n const applied = await this.setModel(result.threadId, options.model)\n .then(() => true)\n .catch((cause) => {\n this.logger.debug(\"acp startThread: model selection not applied\", {\n model: options.model,\n message: errorMessage(cause)\n });\n return false;\n });\n if (applied) return { ...result, model: options.model };\n }\n return result;\n }\n\n /** ACP-native `session/new`. The neutral `startThread` delegates here after\n * mapping cwd + dropping Codex-only fields. Exposed for hosts that need\n * ACP-specific control (per-thread `mcpServers`). */\n async startThreadNative(\n options: AcpStartThreadOptions = {}\n ): Promise<AgentBackendStartThreadResult> {\n return this.establishSession({\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.mcpServers !== undefined ? { mcpServers: options.mcpServers } : {})\n });\n }\n\n /** ACP-native `session/load`. The pinned ACP v1 library has no separate\n * `session/resume` method; loading is the protocol-defined history restore\n * path and receives the same per-thread MCP configuration as `session/new`. */\n async loadThreadNative(\n options: AcpLoadThreadOptions\n ): Promise<AgentBackendStartThreadResult> {\n return this.openSession({\n lifecycle: \"load\",\n protocolSessionId: options.sessionId,\n ...(options.threadId !== undefined ? { bindThreadId: options.threadId } : {}),\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.mcpServers !== undefined ? { mcpServers: options.mcpServers } : {})\n });\n }\n\n /**\n * Re-establish a fresh ACP session for a PERSISTED thread id whose underlying\n * session is gone (e.g. resuming a chat after an app restart — the agent\n * process, and its in-memory session, died with the previous run). ACP\n * sessions don't survive a process restart the way a Codex thread does, so a\n * host that persists threads must rebind them. No-op when the session is still\n * live. The conversation starts fresh on the agent side (prior turns aren't\n * replayed), but the host keeps the visible transcript and the system prompt\n * is re-applied to the first turn.\n */\n async reopenThread(options: {\n threadId: string;\n /** Built ONLY when a re-establish actually happens (skipped for a live\n * session), so the host doesn't rebuild the system prompt every turn. */\n buildInstructions?: () => string;\n /** Per-thread MCP servers for THIS session. Lets ONE shared client serve\n * surfaces with different tool sets (library vs sizzle): each surface\n * passes its own servers, so its threads spawn its tools — overriding the\n * client-level default. */\n mcpServers?: readonly AcpMcpServerConfig[];\n }): Promise<void> {\n if (this.sessions.has(options.threadId)) return;\n const instructions = options.buildInstructions?.();\n await this.establishSession({\n bindThreadId: options.threadId,\n ...(instructions !== undefined ? { instructions } : {}),\n ...(options.mcpServers !== undefined ? { mcpServers: options.mcpServers } : {})\n });\n }\n\n /**\n * Mint a thread id WITHOUT spawning the agent or opening a session. The\n * session is established lazily on the FIRST turn (via `reopenThread`, which\n * the chat controller calls before each turn), so opening a new chat is\n * instant — the multi-second agent spawn + `session/new` happens only when\n * the user actually sends a message. Options are ignored (cwd/mcpServers come\n * from the client defaults at establish time; instructions ride the first\n * turn). The host id is a random UUID since there's no session GUID yet.\n */\n async createDeferredThread(\n _options?: AgentStartThreadOptions\n ): Promise<AgentBackendStartThreadResult> {\n const threadId = `acp:${this.strategy.id}:${randomUUID()}`;\n const out: AgentBackendStartThreadResult = { threadId };\n out.modelProvider = this.strategy.id;\n return out;\n }\n\n /** Warm the agent: spawn the process + run the `initialize` handshake WITHOUT\n * opening a session, so the first thread/turn doesn't pay the multi-second\n * spawn. Idempotent. Used by `AcpAgentClientPool` to hold a configured agent\n * ready from app startup. */\n async connect(): Promise<void> {\n await this.initialize();\n }\n\n /** Shared `session/new` + session registration. Mints a new thread id unless\n * `bindThreadId` is given (resume), in which case the new ACP session is\n * bound to that existing host thread id. */\n private async establishSession(options: {\n cwd?: string;\n mcpServers?: readonly AcpMcpServerConfig[];\n bindThreadId?: string;\n instructions?: string;\n }): Promise<AgentBackendStartThreadResult> {\n return this.openSession({ lifecycle: \"new\", ...options });\n }\n\n private async openSession(options: {\n lifecycle: \"new\" | \"load\";\n protocolSessionId?: string;\n cwd?: string;\n mcpServers?: readonly AcpMcpServerConfig[];\n bindThreadId?: string;\n instructions?: string;\n }): Promise<AgentBackendStartThreadResult> {\n await this.initialize();\n if (\n options.lifecycle === \"load\" &&\n !acpRuntimeSupportsSessionLoad(this.runtimeCapabilities)\n ) {\n throw new Error(\"ACP agent does not advertise session/load support\");\n }\n const cwd = options.cwd ?? this.defaultCwd ?? process.cwd();\n // Ensure the session workspace exists. ACP agents use `cwd` as their\n // working directory; some (e.g. Gemini) fail `session/new` with an opaque\n // \"-32603 Internal error\" when it doesn't exist. Best-effort — if the\n // mkdir fails the agent surfaces its own error as before.\n try {\n mkdirSync(cwd, { recursive: true });\n } catch (cause) {\n this.logger.debug(\"acp session cwd ensure failed\", {\n cwd,\n message: cause instanceof Error ? cause.message : String(cause)\n });\n }\n const configuredMcpServers = options.mcpServers ?? this.defaultMcpServers;\n this.assertMcpTransportSupport(configuredMcpServers);\n const mcpServers = normalizeAcpMcpServerConfigs(configuredMcpServers);\n const method = options.lifecycle === \"load\" ? \"session/load\" : \"session/new\";\n // `session/load` replays history through `session/update` notifications\n // WHILE the request is in flight. Its protocol id is already known, so\n // install the routing state before sending the request; otherwise replayed\n // updates arrive as \"unknown session\" and are silently dropped.\n let session: AcpSessionState | undefined;\n if (options.lifecycle === \"load\") {\n const protocolSessionId = options.protocolSessionId;\n if (!protocolSessionId) {\n throw new Error(\"ACP session/load did not provide a session id\");\n }\n const threadId =\n options.bindThreadId ??\n `acp:${this.strategy.id}:${isUuid(protocolSessionId) ? protocolSessionId : randomUUID()}`;\n if (this.sessions.has(threadId)) {\n throw new Error(`ACP thread is already open: ${threadId}`);\n }\n const mappedThreadId = this.threadIdByProtocolId.get(protocolSessionId);\n if (mappedThreadId !== undefined) {\n throw new Error(\n `ACP session is already loaded for thread: ${mappedThreadId}`\n );\n }\n session = {\n threadId,\n protocolSessionId,\n normalizer: new AcpSessionNormalizer({ quirks: this.strategy.quirks }),\n turnId: undefined,\n runtimeState: undefined,\n pendingTurn: undefined,\n pendingInstructions: options.instructions,\n mcpServerNames: configuredMcpServers.map((server) => server.name)\n };\n this.sessions.set(threadId, session);\n this.threadIdByProtocolId.set(protocolSessionId, threadId);\n }\n let result: unknown;\n try {\n result = await this.transport.request(method, {\n cwd,\n mcpServers,\n ...(options.lifecycle === \"load\"\n ? { sessionId: options.protocolSessionId }\n : {})\n });\n } catch (cause) {\n const message = redactAcpMcpCredentials(\n errorMessage(cause),\n configuredMcpServers\n );\n // A failed load never established a live session. Remove only the exact\n // provisional entries installed above so later notifications cannot\n // route into a dead session.\n if (session !== undefined) {\n if (this.sessions.get(session.threadId) === session) {\n this.sessions.delete(session.threadId);\n }\n if (\n this.threadIdByProtocolId.get(session.protocolSessionId) ===\n session.threadId\n ) {\n this.threadIdByProtocolId.delete(session.protocolSessionId);\n }\n }\n throw new Error(`ACP ${method} failed: ${message}`);\n }\n const record = asRecord(result);\n const protocolSessionId =\n options.lifecycle === \"load\"\n ? options.protocolSessionId\n : readString(record, \"sessionId\") ?? readString(record, \"session_id\");\n if (!protocolSessionId) {\n throw new Error(`ACP ${method} did not provide a session id`);\n }\n // Prefer the agent's session GUID for the host-facing `threadId` (it's the\n // id ACP already hands us, so the thread is traceable straight to the live\n // session) — but ONLY when it's a well-formed UUID. Many agents return a\n // proper UUID; if one returns a counter / opaque token instead, fall back\n // to a host-minted `randomUUID()` so our id is globally unique regardless of\n // the agent's choice. Never a plain integer counter. On resume, bind to the\n // caller's existing thread id instead of minting one.\n const threadId =\n session?.threadId ??\n options.bindThreadId ??\n `acp:${this.strategy.id}:${isUuid(protocolSessionId) ? protocolSessionId : randomUUID()}`;\n session ??= {\n threadId,\n protocolSessionId,\n normalizer: new AcpSessionNormalizer({ quirks: this.strategy.quirks }),\n turnId: undefined,\n runtimeState: undefined,\n pendingTurn: undefined,\n pendingInstructions: options.instructions,\n // Remember ONLY the MCP servers attached to THIS session so the host's\n // approval policy never sees another pooled thread's tool set.\n mcpServerNames: configuredMcpServers.map((server) => server.name)\n };\n if (options.lifecycle === \"new\") {\n this.sessions.set(threadId, session);\n this.threadIdByProtocolId.set(protocolSessionId, threadId);\n }\n\n const runtimeCapabilities = this.captureRuntimeCapabilities(\n options.lifecycle === \"load\" ? \"session-load\" : \"session-new\",\n result\n );\n if (runtimeCapabilities) {\n const runtimeState = acpSessionRuntimeStateFromCapabilities(\n runtimeCapabilities,\n this.now()\n );\n if (runtimeState) session.runtimeState = runtimeState;\n this.notifyRuntimeCapabilities({ threadId, runtimeCapabilities, runtimeState });\n this.emitThreadSettings(session, runtimeCapabilities, runtimeState);\n }\n\n this.logger.debug(\"acp thread opened\", {\n threadId,\n protocolSessionId,\n lifecycle: options.lifecycle,\n rebound: options.bindThreadId !== undefined\n });\n const out: AgentBackendStartThreadResult = { threadId };\n // Effective model — prefers `models.currentModelId`, falling back to the\n // `model` configOption for agents (Kimi) that advertise model choice there.\n const model = modelIdFromCapabilities(runtimeCapabilities);\n if (model !== undefined) out.model = model;\n out.modelProvider = this.strategy.id;\n return out;\n }\n\n /**\n * Public `AgentBackend.startTurn`: accepts NEUTRAL `AgentStartTurnOptions` and\n * maps them onto ACP prompt content blocks — a leading `text` block from\n * `input.text`, then one `image` block per `input.imagePaths` entry (read from\n * disk, base64-encoded, mimeType inferred from extension). `reasoning` maps to\n * an ACP mode/config when the session advertises a matching option, else it is\n * IGNORED (debug-logged).\n */\n async startTurn(options: AgentStartTurnOptions): Promise<{ turnId: string }> {\n const promptContent: AcpPromptContentBlock[] = [];\n // Fold the host system prompt (captured at startThread) into the FIRST turn\n // as a leading text block — ACP has no baseInstructions seam. Consumed once.\n const session = this.sessions.get(options.threadId);\n if (session?.pendingInstructions !== undefined) {\n promptContent.push({ type: \"text\", text: session.pendingInstructions });\n session.pendingInstructions = undefined;\n }\n promptContent.push({ type: \"text\", text: options.input.text });\n for (const imagePath of options.input.imagePaths ?? []) {\n const block = await this.imageBlockFromPath(imagePath).catch((cause) => {\n this.logger.debug(\"acp startTurn: skipping unreadable image\", {\n imagePath,\n message: cause instanceof Error ? cause.message : String(cause)\n });\n return undefined;\n });\n if (block !== undefined) promptContent.push(block);\n }\n if (options.reasoning !== undefined) {\n await this.applyReasoning(options.threadId, options.reasoning).catch((cause) => {\n this.logger.debug(\"acp startTurn: reasoning not applied\", {\n reasoning: options.reasoning,\n message: cause instanceof Error ? cause.message : String(cause)\n });\n });\n }\n return this.startTurnNative({ threadId: options.threadId, promptContent });\n }\n\n /** ACP-native `session/prompt`. Takes a plain prompt or pre-built content\n * blocks. The neutral `startTurn` delegates here after building blocks. */\n async startTurnNative(options: AcpStartTurnOptions): Promise<{ turnId: string }> {\n const session = this.requireSession(options.threadId);\n if (session.turnId !== undefined) {\n throw new Error(\"A turn is already active for this ACP session.\");\n }\n const turnId = `turn:${session.threadId}:${this.now()}`;\n session.turnId = turnId;\n session.normalizer.resetTurn();\n this.emit({ kind: \"turn_started\", threadId: session.threadId, turnId });\n\n const prompt =\n options.promptContent ??\n textPrompt(options.prompt ?? \"\");\n\n // Resolve at turn START, not turn END. ACP's `session/prompt` resolves only\n // when the whole turn is done (assistant chunks arrive as `session/update`\n // notifications WHILE the request is in flight). Awaiting it here would make\n // `startTurn` block for the entire turn — violating the `AgentBackend`\n // contract (Codex resolves at turn start) and freezing any host UI that\n // gates on `startTurn` (e.g. a chat composer waiting to clear). Instead we\n // fire the request and stream its terminal events (token_usage,\n // agent_message, turn_completed/error) asynchronously when it settles.\n session.pendingTurn = this.transport\n .request(\n \"session/prompt\",\n {\n sessionId: session.protocolSessionId,\n prompt\n },\n ACP_PROMPT_REQUEST_TIMEOUT_MS\n )\n .then((promptResult) => {\n // Token usage rides on the `session/prompt` RESPONSE (`_meta.quota`),\n // not a session/update — emit it so hosts can account for ACP turns the\n // same way they do Codex turns.\n const usage = readAcpPromptUsage(promptResult);\n if (usage) {\n this.emit({ kind: \"token_usage\", threadId: session.threadId, turnId, usage });\n } else {\n // No recognized usage shape — log WHERE usage-like keys live (paths\n // only, never values) so a new agent's reporting format is\n // diagnosable instead of silently surfacing \"usage unavailable\".\n this.logger.debug(\"acp prompt response carried no recognized token usage\", {\n threadId: session.threadId,\n turnId,\n shape: describeUsageShape(promptResult)\n });\n }\n // Flush any in-flight assistant bubble into a terminal agent_message.\n for (const event of session.normalizer.finalizeAssistantMessage({\n threadId: session.threadId,\n turnId\n })) {\n this.emit(event);\n }\n session.turnId = undefined;\n session.pendingTurn = undefined;\n this.emit({\n kind: \"turn_completed\",\n threadId: session.threadId,\n turnId,\n status: \"completed\"\n });\n })\n .catch((error) => {\n session.turnId = undefined;\n session.pendingTurn = undefined;\n this.emit({\n kind: \"turn_completed\",\n threadId: session.threadId,\n turnId,\n status: \"failed\"\n });\n this.emit({\n kind: \"error\",\n threadId: session.threadId,\n turnId,\n message: errorMessage(error)\n });\n });\n\n return { turnId };\n }\n\n async interruptTurn(threadId: string): Promise<void> {\n const session = this.requireSession(threadId);\n if (this.transport.notify) {\n await this.transport.notify(\"session/cancel\", {\n sessionId: session.protocolSessionId\n });\n } else {\n await this.transport.request(\"session/cancel\", {\n sessionId: session.protocolSessionId\n });\n }\n }\n\n /** Release a thread the host has archived/closed.\n *\n * ACP has NO protocol-level session delete/archive — sessions are\n * connection-scoped and the spec offers only `session/cancel` (interrupt).\n * So unlike the Codex backend (which sends `thread/archive`), there's no\n * remote call to make here. What we MUST do is drop the live session\n * LOCALLY: a long-lived pooled client (one process shared across surfaces,\n * warmed at startup) would otherwise accumulate a dead `AcpSessionState` for\n * every closed chat for the life of the app. Best-effort cancels an\n * in-flight turn first so the agent stops working on a thread the user\n * closed. Idempotent — no-ops if the session is already gone. A later\n * `reopenThread` re-establishes a fresh session under the same threadId, so\n * releasing here never blocks resume. */\n async archiveThread(threadId: string): Promise<void> {\n const session = this.sessions.get(threadId);\n if (session === undefined) return;\n if (session.turnId !== undefined) {\n try {\n if (this.transport.notify) {\n await this.transport.notify(\"session/cancel\", {\n sessionId: session.protocolSessionId\n });\n } else {\n await this.transport.request(\"session/cancel\", {\n sessionId: session.protocolSessionId\n });\n }\n } catch {\n // best-effort — the session is being released regardless.\n }\n }\n this.sessions.delete(threadId);\n this.threadIdByProtocolId.delete(session.protocolSessionId);\n this.logger.debug(\"acp thread archived (session released locally)\", { threadId });\n }\n\n async setMode(threadId: string, modeId: string): Promise<void> {\n await this.setRuntimeOption(threadId, \"mode\", modeId, modeId);\n }\n\n async setModel(threadId: string, modelId: string): Promise<void> {\n await this.setRuntimeOption(threadId, \"model\", modelId, modelId);\n }\n\n async setConfigOption(\n threadId: string,\n optionId: string,\n value: string\n ): Promise<void> {\n await this.setRuntimeOption(threadId, \"configOption\", optionId, value);\n }\n\n async close(): Promise<void> {\n this.unsubscribeNotification?.();\n this.unsubscribeNotification = undefined;\n this.unsubscribeRequest?.();\n this.unsubscribeRequest = undefined;\n // Snapshot in-flight turn chains before clearing sessions. Closing the\n // transport rejects any pending `session/prompt`, which the chain's\n // `.catch` turns into a terminal failed/error emit — await them so teardown\n // doesn't leave a turn settling after `close()` resolves. The chains never\n // reject (they're `.catch`-terminated), so `allSettled` is belt-and-braces.\n const pending = [...this.sessions.values()]\n .map((s) => s.pendingTurn)\n .filter((p): p is Promise<void> => p !== undefined);\n this.sessions.clear();\n this.threadIdByProtocolId.clear();\n this.initialized = false;\n await this.transport.close?.();\n if (pending.length > 0) await Promise.allSettled(pending);\n }\n\n // ---- internals ----\n\n private emit(event: NormalizedThreadEvent): void {\n for (const listener of this.eventListeners) listener(event);\n }\n\n private async initialize(): Promise<void> {\n if (this.initialized) return;\n\n this.unsubscribeNotification = this.transport.onNotification((method, params) => {\n this.handleNotification(method, params);\n });\n this.unsubscribeRequest = this.transport.onRequest?.(\n async (method, params, id) => await this.handleAcpRequest(method, params, id)\n );\n\n const result = await this.transport.request(\n \"initialize\",\n {\n protocolVersion: ACP_PROTOCOL_VERSION,\n clientCapabilities: {\n auth: { terminal: false },\n fs: { readTextFile: false, writeTextFile: false },\n terminal: false\n },\n clientInfo: {\n name: this.clientName,\n title: this.clientTitle,\n version: this.clientVersion\n }\n },\n ACP_REQUEST_TIMEOUT_MS\n );\n const runtimeCapabilities = this.captureRuntimeCapabilities(\"initialize\", result);\n if (runtimeCapabilities) {\n this.notifyRuntimeCapabilities({ runtimeCapabilities });\n }\n this.initialized = true;\n }\n\n private handleNotification(method: string, params: unknown): void {\n const vendorMethods = this.strategy.quirks.vendorNotificationMethods ?? [];\n if (method !== \"session/update\" && !vendorMethods.includes(method)) {\n return;\n }\n const record = asRecord(params);\n if (!record) return;\n this.applySessionUpdate(record);\n }\n\n private applySessionUpdate(params: Record<string, unknown>): void {\n const protocolSessionId =\n readString(params, \"sessionId\") ?? readString(params, \"session_id\");\n const update = asRecord(params.update);\n if (!protocolSessionId || !update) {\n return;\n }\n const threadId = this.threadIdByProtocolId.get(protocolSessionId);\n const session = threadId ? this.sessions.get(threadId) : undefined;\n if (!session) {\n this.logger.debug(\"acp session/update for unknown session\", { protocolSessionId });\n return;\n }\n\n // Runtime-state changes (mode/model/config) ride session/update too.\n const runtimeState = acpSessionRuntimeStateFromUpdate(update, this.now());\n if (runtimeState) {\n session.runtimeState = mergeAcpRuntimeState(session.runtimeState, runtimeState);\n if (this.runtimeCapabilities) {\n this.notifyRuntimeCapabilities({\n threadId: session.threadId,\n runtimeCapabilities: this.runtimeCapabilities,\n runtimeState: session.runtimeState\n });\n }\n this.emitThreadSettings(session, this.runtimeCapabilities, session.runtimeState);\n return;\n }\n\n // Diagnostic: for tool notifications, log the RAW identity fields so a\n // host can see exactly what an agent streamed — how many distinct\n // toolCallIds, and whether each carries a title/name (Grok often sends\n // titleless `tool_call_update`s, which is why a chip can read \"tool call\n // update\" instead of the tool name). debug-level; off the hot path for\n // non-tool updates.\n const updateKind = readString(update, \"sessionUpdate\");\n if (updateKind === \"tool_call\" || updateKind === \"tool_call_update\") {\n this.logger.debug(\"acp tool notification\", {\n kind: updateKind,\n toolCallId: readString(update, \"toolCallId\") ?? readString(update, \"tool_call_id\"),\n title: readString(update, \"title\"),\n name: readString(update, \"name\"),\n status: readString(update, \"status\")\n });\n }\n\n const ctx: AcpApplyContext = {\n threadId: session.threadId,\n turnId: session.turnId ?? `turn:${session.threadId}:detached`\n };\n const result = session.normalizer.apply(update, ctx);\n if (result.title !== undefined) {\n this.titleHandler?.({ threadId: session.threadId, title: result.title });\n return;\n }\n for (const event of result.events) {\n this.emit(event);\n }\n }\n\n private async handleAcpRequest(\n method: string,\n params: Record<string, unknown>,\n id?: JsonRpcId\n ): Promise<unknown> {\n if (method === \"session/request_permission\") {\n return await this.handlePermissionRequest(params, id);\n }\n // Any other inbound server-request (e.g. a future tool-call request) routes\n // to the tool-call handler when one is registered.\n if (this.toolCallHandler) {\n const call: AgentBackendToolCall = { method, params };\n return await this.toolCallHandler(call);\n }\n throw new Error(`Unsupported ACP request: ${method}`);\n }\n\n private async handlePermissionRequest(\n params: Record<string, unknown>,\n id?: JsonRpcId\n ): Promise<unknown> {\n const protocolSessionId =\n readString(params, \"sessionId\") ?? readString(params, \"session_id\");\n const threadId = protocolSessionId\n ? this.threadIdByProtocolId.get(protocolSessionId)\n : undefined;\n const options = readPermissionOptions(params.options);\n\n // The client makes NO trust decision of its own — every permission request\n // goes to the host's approval handler, which owns the policy (e.g. a host\n // may pre-approve tools from MCP servers IT configured). We give the host\n // the context the raw ACP params lack: the RESOLVED `threadId` (params only\n // carry a `sessionId`) and ONLY that session's `mcpServerNames`, so a pooled\n // client never exposes another thread's configured tool set to this policy\n // decision. With no handler registered there's no one to decide, so the\n // request is cancelled.\n const handler = this.approvalHandler;\n if (!handler) {\n return cancelledPermissionOutcome();\n }\n\n const approval = buildApprovalRequest({\n params,\n id,\n threadId,\n session: threadId ? this.sessions.get(threadId) : undefined,\n now: this.now\n });\n if (threadId) {\n this.emit({ kind: \"approval_request\", threadId, approval });\n }\n\n const handlerParams: Record<string, unknown> = {\n ...params,\n mcpServerNames: threadId\n ? (this.sessions.get(threadId)?.mcpServerNames ?? [])\n : []\n };\n if (threadId !== undefined) handlerParams.threadId = threadId;\n const decision = await handler(\"session/request_permission\", handlerParams);\n return permissionOutcomeFromDecision(decision, options);\n }\n\n private async setRuntimeOption(\n threadId: string,\n source: AcpRuntimeOptionSource,\n optionId: string,\n value: string\n ): Promise<void> {\n const session = this.requireSession(threadId);\n const result = await this.setRuntimeOptionOnTransport(\n session.protocolSessionId,\n source,\n optionId,\n value\n );\n const runtimeCapabilities = this.captureRuntimeCapabilities(\"session-load\", result);\n const requested: AcpSessionRuntimeState =\n source === \"configOption\"\n ? { configValues: { [optionId]: value }, updatedAt: this.now() }\n : source === \"mode\"\n ? { currentModeId: value, updatedAt: this.now() }\n : { currentModelId: value, updatedAt: this.now() };\n session.runtimeState = mergeAcpRuntimeState(session.runtimeState, requested);\n const effectiveCapabilities = runtimeCapabilities ?? this.runtimeCapabilities;\n if (effectiveCapabilities) {\n this.notifyRuntimeCapabilities({\n threadId,\n runtimeCapabilities: effectiveCapabilities,\n ...(session.runtimeState !== undefined\n ? { runtimeState: session.runtimeState }\n : {})\n });\n }\n this.emitThreadSettings(session, effectiveCapabilities, session.runtimeState);\n }\n\n private async setRuntimeOptionOnTransport(\n protocolSessionId: string,\n source: AcpRuntimeOptionSource,\n optionId: string,\n value: string\n ): Promise<unknown> {\n if (source === \"configOption\") {\n return await this.transport.request(\"session/set_config_option\", {\n sessionId: protocolSessionId,\n configId: optionId,\n value\n });\n }\n if (source === \"mode\") {\n return await this.transport.request(\"session/set_mode\", {\n sessionId: protocolSessionId,\n modeId: value\n });\n }\n return await this.transport.request(\"session/set_model\", {\n sessionId: protocolSessionId,\n modelId: value\n });\n }\n\n /** Map a neutral `reasoning` token onto an ACP runtime option. ACP has no\n * first-class \"reasoning effort\" concept, so we map it to whatever the agent\n * exposes, in order:\n * 1. An available MODE whose id/label matches the token (set_mode).\n * 2. A \"thinking\" config option (`category: \"thought_level\"`, or id\n * `thinking`) — map low-effort tokens to its OFF-like value and\n * high-effort tokens to its ON-like value (set_config_option). This is\n * what lets a one-shot enrichment turn (\"low\") disable a reasoning\n * model's thinking pass, which is dramatically faster.\n * If nothing matches we leave it alone — the caller's `.catch` debug-logs. */\n private async applyReasoning(threadId: string, reasoning: string): Promise<void> {\n const target = reasoning.toLowerCase();\n const modes = this.runtimeCapabilities?.modes?.availableModes ?? [];\n const modeMatch = modes.find(\n (mode) =>\n mode.id.toLowerCase() === target ||\n (typeof mode.label === \"string\" && mode.label.toLowerCase() === target)\n );\n if (modeMatch !== undefined) {\n await this.setMode(threadId, modeMatch.id);\n return;\n }\n const thinking = this.runtimeCapabilities?.configOptions?.find(\n (option) => option.category === \"thought_level\" || option.id === \"thinking\"\n );\n if (thinking !== undefined) {\n const value = reasoningValueForThoughtLevel(target, thinking.values);\n if (value === undefined) {\n this.logger.debug(\"acp reasoning has no matching thought-level value — ignored\", {\n reasoning\n });\n return;\n }\n // Already at the desired value → no redundant set_config_option round-trip.\n if (value !== thinking.currentValue) {\n await this.setConfigOption(threadId, thinking.id, value);\n }\n return;\n }\n this.logger.debug(\"acp reasoning has no matching mode or thought-level option — ignored\", {\n reasoning\n });\n }\n\n /** Read an image file and build an ACP `image` content block (base64 + inferred\n * mimeType). Throws on read failure; the caller catches + skips. */\n private async imageBlockFromPath(imagePath: string): Promise<AcpPromptContentBlock> {\n const data = await readFile(imagePath);\n return {\n type: \"image\",\n mimeType: mimeTypeForImagePath(imagePath),\n data: data.toString(\"base64\")\n };\n }\n\n private captureRuntimeCapabilities(\n source: AcpRuntimeCapabilities[\"source\"],\n result: unknown\n ): AcpRuntimeCapabilities | undefined {\n const runtimeCapabilities = normalizeAcpRuntimeCapabilities({\n value: result,\n now: this.now(),\n source,\n ...(this.runtimeCapabilities !== undefined\n ? { initialize: this.runtimeCapabilities }\n : {})\n });\n if (runtimeCapabilities) {\n this.runtimeCapabilities = runtimeCapabilities;\n }\n return runtimeCapabilities;\n }\n\n private notifyRuntimeCapabilities(event: {\n threadId?: string | undefined;\n runtimeCapabilities: AcpRuntimeCapabilities;\n runtimeState?: AcpSessionRuntimeState | undefined;\n }): void {\n this.runtimeCapabilitiesHandler?.({\n ...(event.threadId !== undefined ? { threadId: event.threadId } : {}),\n runtimeCapabilities: event.runtimeCapabilities,\n ...(event.runtimeState !== undefined ? { runtimeState: event.runtimeState } : {})\n });\n }\n\n private emitThreadSettings(\n session: AcpSessionState,\n capabilities: AcpRuntimeCapabilities | undefined,\n runtimeState: AcpSessionRuntimeState | undefined\n ): void {\n const settings: NormalizedThreadSettings = { threadId: session.threadId };\n const model =\n runtimeState?.currentModelId ?? modelIdFromCapabilities(capabilities);\n if (model !== undefined) settings.model = model;\n settings.modelProvider = this.strategy.id;\n const modeId =\n runtimeState?.currentModeId ?? capabilities?.modes?.currentModeId;\n if (modeId !== undefined) {\n settings.modeId = modeId;\n const label = modeLabelFor(capabilities, modeId);\n if (label !== undefined) settings.modeLabel = label;\n }\n this.emit({ kind: \"thread_settings\", settings });\n }\n\n private requireSession(threadId: string): AcpSessionState {\n const session = this.sessions.get(threadId);\n if (!session) {\n throw new Error(`Unknown ACP thread: ${threadId}`);\n }\n return session;\n }\n\n private assertMcpTransportSupport(\n servers: readonly AcpMcpServerConfig[]\n ): void {\n for (const server of servers) {\n if (!(\"type\" in server)) continue;\n if (\n server.type === \"http\" &&\n !acpRuntimeSupportsHttpMcp(this.runtimeCapabilities)\n ) {\n throw new Error(\n `ACP agent does not advertise HTTP MCP support for server \"${server.name}\"`\n );\n }\n if (\n server.type === \"sse\" &&\n !acpRuntimeSupportsSseMcp(this.runtimeCapabilities)\n ) {\n throw new Error(\n `ACP agent does not advertise SSE MCP support for server \"${server.name}\"`\n );\n }\n }\n }\n\n /** Whether the agent advertises session/load support (for hosts that resume). */\n supportsSessionLoad(): boolean {\n return acpRuntimeSupportsSessionLoad(this.runtimeCapabilities);\n }\n\n /** Whether the initialize result explicitly advertises streamable HTTP MCP. */\n supportsHttpMcp(): boolean {\n return acpRuntimeSupportsHttpMcp(this.runtimeCapabilities);\n }\n\n /** Whether the initialize result explicitly advertises legacy HTTP+SSE MCP. */\n supportsSseMcp(): boolean {\n return acpRuntimeSupportsSseMcp(this.runtimeCapabilities);\n }\n}\n\n/** Effort tokens that mean \"deliberate as little as possible\" → thinking OFF. */\nconst LOW_EFFORT_TOKENS = new Set([\n \"off\",\n \"none\",\n \"minimal\",\n \"min\",\n \"minimum\",\n \"low\",\n \"fast\"\n]);\n/** Effort tokens that mean \"deliberate fully\" → thinking ON. */\nconst HIGH_EFFORT_TOKENS = new Set([\n \"on\",\n \"high\",\n \"medium\",\n \"max\",\n \"maximum\",\n \"full\",\n \"think\"\n]);\n\n/** Classify a thinking/thought-level option VALUE as on/off-like from its value\n * id + label (e.g. `{ value: \"off\", label: \"Thinking Off\" }` → \"off\"). */\nfunction thoughtLevelPolarity(\n value: AcpRuntimeConfigOptionValue\n): \"on\" | \"off\" | \"other\" {\n const haystack = `${value.value} ${value.label ?? \"\"}`.toLowerCase();\n if (/\\b(off|none|disabled?|no)\\b/.test(haystack)) return \"off\";\n if (/\\b(on|enabled?|high|full|yes)\\b/.test(haystack)) return \"on\";\n return \"other\";\n}\n\n/** Pick the value to set on a \"thinking\" config option for a neutral reasoning\n * token: low-effort → the OFF-like value, high-effort → the ON-like value.\n * Returns undefined when the token isn't an effort signal we recognize, or the\n * option has no value of the needed polarity (caller leaves the option alone).\n * Exported for testing. */\nexport function reasoningValueForThoughtLevel(\n reasoning: string,\n values: ReadonlyArray<AcpRuntimeConfigOptionValue>\n): string | undefined {\n const token = reasoning.toLowerCase();\n const wantOff = LOW_EFFORT_TOKENS.has(token);\n const wantOn = HIGH_EFFORT_TOKENS.has(token);\n if (!wantOff && !wantOn) return undefined;\n const desired = wantOff ? \"off\" : \"on\";\n return values.find((value) => thoughtLevelPolarity(value) === desired)?.value;\n}\n\nfunction buildApprovalRequest(args: {\n params: Record<string, unknown>;\n id: JsonRpcId | undefined;\n threadId: string | undefined;\n session: AcpSessionState | undefined;\n now: () => number;\n}): NormalizedApprovalRequest {\n const toolCall = asRecord(args.params.toolCall) ?? {};\n const title =\n typeof toolCall.title === \"string\" && toolCall.title.trim()\n ? toolCall.title.trim()\n : \"ACP tool call\";\n const toolCallId =\n readString(toolCall, \"toolCallId\") ?? readString(toolCall, \"tool_call_id\");\n const requestId =\n args.id == null ? toolCallId ?? `acp:${args.now()}` : String(args.id);\n const acpKind = typeof toolCall.kind === \"string\" ? toolCall.kind : undefined;\n const approval: NormalizedApprovalRequest = {\n id: requestId,\n method: \"session/request_permission\",\n kind: approvalKindFor(acpKind),\n params: args.params\n };\n approval.summary = acpKind ? `${acpKind}: ${title}` : title;\n return approval;\n}\n\nfunction approvalKindFor(acpKind: string | undefined): NormalizedApprovalRequest[\"kind\"] {\n switch (acpKind) {\n case \"execute\":\n case \"exec\":\n case \"shell\":\n return \"exec\";\n case \"edit\":\n case \"write\":\n return \"patch\";\n case \"read\":\n case \"search\":\n case \"fetch\":\n return \"tool\";\n default:\n return \"other\";\n }\n}\n\ntype AcpPermissionOption = {\n optionId: string;\n name?: string;\n kind?: string;\n};\n\nfunction readPermissionOptions(value: unknown): AcpPermissionOption[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.flatMap((option) => {\n const record = asRecord(option);\n const optionId = readString(record, \"optionId\");\n if (!record || !optionId) {\n return [];\n }\n const normalized: AcpPermissionOption = { optionId };\n const name = readString(record, \"name\");\n if (name !== undefined) normalized.name = name;\n const kind = readString(record, \"kind\");\n if (kind !== undefined) normalized.kind = kind;\n return [normalized];\n });\n}\n\nfunction permissionOutcomeFromDecision(\n decision: NormalizedApprovalDecision,\n options: AcpPermissionOption[]\n): { outcome: { outcome: \"selected\"; optionId: string } | { outcome: \"cancelled\" } } {\n const token = permissionDecisionToken(decision);\n const optionId = selectPermissionOptionId(token, options);\n return optionId\n ? { outcome: { outcome: \"selected\", optionId } }\n : cancelledPermissionOutcome();\n}\n\nfunction cancelledPermissionOutcome(): { outcome: { outcome: \"cancelled\" } } {\n return { outcome: { outcome: \"cancelled\" } };\n}\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nfunction isUuid(value: string | undefined): value is string {\n return value !== undefined && UUID_RE.test(value);\n}\n\nfunction selectPermissionOptionId(\n decision: string,\n options: AcpPermissionOption[]\n): string | undefined {\n const normalized = decision.toLowerCase();\n const exact = options.find((option) =>\n [option.optionId, option.name, option.kind]\n .filter((value): value is string => typeof value === \"string\")\n .some((value) => value.toLowerCase() === normalized)\n );\n if (exact) {\n return exact.optionId;\n }\n if (normalized === \"approve\" || normalized === \"accept\" || normalized === \"allow\") {\n // Prefer the BROADEST allow — a session-wide server allow first (so a host\n // that pre-approves its own MCP tools isn't re-prompted on every call this\n // session), then any allow-always, then allow-once.\n return (\n options.find(\n (option) => option.kind === \"allow_always\" && /server/i.test(option.optionId)\n ) ??\n options.find((option) => option.kind === \"allow_always\") ??\n options.find((option) => option.kind === \"allow_once\") ??\n options.find((option) => option.name?.toLowerCase().includes(\"allow\"))\n )?.optionId;\n }\n if (normalized === \"reject\" || normalized === \"decline\" || normalized === \"deny\") {\n return (\n options.find((option) => option.kind === \"reject_once\") ??\n options.find((option) => option.name?.toLowerCase().includes(\"reject\"))\n )?.optionId;\n }\n return undefined;\n}\n\nfunction textPrompt(text: string): AcpPromptContentBlock[] {\n return [{ type: \"text\", text }];\n}\n\n/** Best-effort image mimeType from a file extension. Falls back to PNG. */\nfunction mimeTypeForImagePath(imagePath: string): string {\n switch (extname(imagePath).toLowerCase()) {\n case \".jpg\":\n case \".jpeg\":\n return \"image/jpeg\";\n case \".gif\":\n return \"image/gif\";\n case \".webp\":\n return \"image/webp\";\n case \".bmp\":\n return \"image/bmp\";\n case \".svg\":\n return \"image/svg+xml\";\n case \".png\":\n default:\n return \"image/png\";\n }\n}\n\n/** Render an unknown thrown value as a readable string. Exported for testing. */\nexport function errorMessage(error: unknown): string {\n if (error === undefined || error === null) return \"Turn failed.\";\n if (error instanceof Error && error.message.trim()) {\n return error.message;\n }\n // JSON-RPC errors reject as PLAIN OBJECTS ({ code, message, data }), not\n // Errors — `String(obj)` is the useless \"[object Object]\". Pull out a readable\n // message (+ code), falling back to a JSON dump, so callers/logs see why the\n // agent refused (e.g. why `session/set_model` was rejected).\n if (error !== null && typeof error === \"object\") {\n const record = error as Record<string, unknown>;\n if (typeof record.message === \"string\" && record.message.trim()) {\n const code = typeof record.code === \"number\" ? ` (${record.code})` : \"\";\n return `${record.message.trim()}${code}`;\n }\n try {\n const json = JSON.stringify(error);\n if (json !== undefined && json !== \"{}\" && json !== \"[]\") return json;\n } catch {\n // non-serializable → fall through\n }\n // An object with nothing useful — return the default rather than letting it\n // reach String(), which would produce the useless \"[object Object]\".\n return \"Turn failed.\";\n }\n const message = String(error).trim();\n return message || \"Turn failed.\";\n}\n\nfunction readString(\n record: Record<string, unknown> | undefined,\n key: string\n): string | undefined {\n const value = record?.[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nconst usageNum = (value: unknown): number | undefined =>\n typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n\n/** Assemble a NormalizedTokenUsage from already-extracted counts, or undefined\n * when neither input nor output is present. */\nfunction assembleUsage(parts: {\n input?: number | undefined;\n output?: number | undefined;\n cached?: number | undefined;\n reasoning?: number | undefined;\n total?: number | undefined;\n}): NormalizedTokenUsage | undefined {\n const { input, output, cached, reasoning, total } = parts;\n if (input === undefined && output === undefined && total === undefined) return undefined;\n const usage: NormalizedTokenUsage = {\n totalTokens: total ?? (input ?? 0) + (output ?? 0)\n };\n if (input !== undefined) usage.inputTokens = input;\n if (output !== undefined) usage.outputTokens = output;\n if (cached !== undefined) usage.cachedInputTokens = cached;\n if (reasoning !== undefined) usage.reasoningOutputTokens = reasoning;\n return usage;\n}\n\n/** Gemini quota shape: `_meta.quota.token_count.{input_tokens,output_tokens,…}`. */\nfunction usageFromGeminiQuota(tokenCount: Record<string, unknown>): NormalizedTokenUsage | undefined {\n return assembleUsage({\n input: usageNum(tokenCount.input_tokens),\n output: usageNum(tokenCount.output_tokens),\n cached: usageNum(tokenCount.cached_input_tokens ?? tokenCount.cached_tokens),\n reasoning: usageNum(tokenCount.thoughts_tokens ?? tokenCount.reasoning_tokens)\n });\n}\n\n/** Generic `usage` object covering both the OpenAI dialect (Grok/xAI, Qwen:\n * `prompt_tokens`/`completion_tokens`, nested `*_tokens_details`) and the\n * Anthropic dialect (`input_tokens`/`output_tokens`, `cache_read_input_tokens`). */\nfunction usageFromGenericUsage(usage: Record<string, unknown>): NormalizedTokenUsage | undefined {\n const promptDetails = asRecord(usage.prompt_tokens_details);\n const completionDetails = asRecord(usage.completion_tokens_details);\n // Accepts snake_case (OpenAI/Anthropic) AND camelCase (Grok/xAI, which reports\n // `inputTokens`/`outputTokens`/`cachedReadTokens`/`reasoningTokens`/`totalTokens`).\n return assembleUsage({\n input: usageNum(usage.prompt_tokens ?? usage.input_tokens ?? usage.inputTokens),\n output: usageNum(usage.completion_tokens ?? usage.output_tokens ?? usage.outputTokens),\n cached: usageNum(\n promptDetails?.cached_tokens ??\n usage.cache_read_input_tokens ??\n usage.cached_tokens ??\n usage.cached_input_tokens ??\n usage.cachedReadTokens ??\n usage.cachedTokens\n ),\n reasoning: usageNum(\n completionDetails?.reasoning_tokens ??\n usage.reasoning_tokens ??\n usage.thoughts_tokens ??\n usage.reasoningTokens\n ),\n total: usageNum(usage.total_tokens ?? usage.totalTokens)\n });\n}\n\n/** Read token usage from a `session/prompt` response. Agents disagree on shape:\n * - Gemini: `_meta.quota.token_count.{input_tokens,output_tokens,…}`\n * - OpenAI dialect (Qwen): `usage.{prompt_tokens,completion_tokens,…}` — at the\n * result root OR under `_meta`.\n * - Anthropic dialect: `usage.{input_tokens,output_tokens,cache_read_input_tokens}`.\n * - Grok/xAI: camelCase counts DIRECTLY on `_meta`\n * (`_meta.{totalTokens,inputTokens,outputTokens,cachedReadTokens,reasoningTokens}`).\n * Returns undefined when nothing recognizable is present. */\nfunction readAcpPromptUsage(result: unknown): NormalizedTokenUsage | undefined {\n const root = asRecord(result);\n const meta = asRecord(root?._meta);\n\n const tokenCount = asRecord(asRecord(meta?.quota)?.token_count);\n if (tokenCount) {\n const fromGemini = usageFromGeminiQuota(tokenCount);\n if (fromGemini) return fromGemini;\n }\n\n // OpenAI / Anthropic `usage` object — at the result root or under `_meta`.\n const usageObj = asRecord(root?.usage) ?? asRecord(meta?.usage);\n if (usageObj) {\n const fromGeneric = usageFromGenericUsage(usageObj);\n if (fromGeneric) return fromGeneric;\n }\n\n // Grok/xAI: the counts sit directly on `_meta` (no nested `usage`/`quota`).\n // usageFromGenericUsage reads only token keys and returns undefined otherwise,\n // so passing the whole `_meta` is safe.\n if (meta) {\n const fromMeta = usageFromGenericUsage(meta);\n if (fromMeta) return fromMeta;\n }\n\n return undefined;\n}\n\n/** Compact description of WHERE usage-like keys live in a prompt response, for a\n * one-line debug log when `readAcpPromptUsage` finds nothing. Never logs values\n * — only the key paths present — so it's safe to emit and reveals a new agent's\n * usage shape without a full payload dump. */\nfunction describeUsageShape(result: unknown): string {\n const root = asRecord(result);\n if (!root) return typeof result;\n const paths: string[] = [];\n const walk = (record: Record<string, unknown>, prefix: string, depth: number): void => {\n for (const [key, value] of Object.entries(record)) {\n const path = prefix ? `${prefix}.${key}` : key;\n if (/token|usage|quota/i.test(key)) paths.push(path);\n const child = asRecord(value);\n if (child && depth < 3) walk(child, path, depth + 1);\n }\n };\n walk(root, \"\", 0);\n return paths.length > 0 ? paths.join(\", \") : `keys: ${Object.keys(root).join(\", \")}`;\n}\n","// The crown jewel: fold the messy, inconsistent ACP `session/update` stream into\n// agent-core's neutral `NormalizedThreadEvent` — the SAME shapes the Codex\n// adapter emits, so a consumer is backend-agnostic.\n//\n// Ported from PwrAgnt acp-session-normalizer.ts, re-targeted off its\n// AppServerThreadReplay onto agent-core NormalizedThreadEvent. Preserves:\n// • camel/snake tolerance on every field (via ./content readers);\n// • recursive content unwrap (readAcpContentText);\n// • agent_message_chunk coalescing — consecutive chunks merge into one\n// message bubble (one itemId); text AFTER a tool call splits a new bubble;\n// • tool_call → tool_call_update merge via agent-core mergeToolCall /\n// preferSpecificLabel, kind inference via inferToolKind;\n// • per-agent behaviors (suppress thoughts, topic→title) read from the\n// STRATEGY's quirks — NO inline per-agent-id branch ever appears here.\n//\n// Stateful per session: one normalizer instance per ACP session, holding the\n// active assistant/thought message ids (for coalescing) and prior tool calls\n// (for delta merge + label reconciliation).\n\nimport {\n mergeToolCall,\n preferSpecificLabel,\n type NormalizedMessage,\n type NormalizedPlan,\n type NormalizedPlanStep,\n type NormalizedThreadEvent,\n type NormalizedToolCall\n} from \"@pwrdrvr/agent-core\";\nimport type { AcpAgentQuirks } from \"../strategies/strategy-types\";\nimport {\n asRecord,\n readContentText,\n readFirstString,\n readKind,\n readString,\n readUpdateText\n} from \"./content\";\nimport { toolCallFromUpdate } from \"./tool-activity\";\n\nexport type AcpNormalizerOptions = {\n /** The agent's normalization quirks (surface thoughts, where title comes from). */\n quirks: AcpAgentQuirks;\n};\n\nexport type AcpNormalizeResult = {\n events: NormalizedThreadEvent[];\n /** A thread title extracted from a topic-update / session-summary, if any. */\n title?: string;\n};\n\nexport type AcpApplyContext = {\n threadId: string;\n turnId: string;\n};\n\nconst EMPTY_RESULT: AcpNormalizeResult = { events: [] };\n\nexport class AcpSessionNormalizer {\n private readonly quirks: AcpAgentQuirks;\n\n // Coalescing state. One \"live\" assistant message bubble at a time; a tool\n // call (or any non-text update) clears it so the next text starts a new one.\n private activeAssistantItemId: string | undefined;\n private assistantText = \"\";\n private assistantSequence = 0;\n\n // Tool-call merge state: id → last fully-merged NormalizedToolCall, so a\n // tool_call_update reconciles labels / fills command output against it.\n private readonly toolCalls = new Map<string, NormalizedToolCall>();\n\n constructor(options: AcpNormalizerOptions) {\n this.quirks = options.quirks;\n }\n\n /** Reset coalescing state at a turn boundary (new prompt / turn finished). */\n resetTurn(): void {\n this.activeAssistantItemId = undefined;\n this.assistantText = \"\";\n }\n\n /** Finalize the in-flight assistant bubble into a terminal `agent_message`, if any. */\n finalizeAssistantMessage(ctx: AcpApplyContext): NormalizedThreadEvent[] {\n if (this.activeAssistantItemId === undefined || this.assistantText === \"\") {\n this.resetTurn();\n return [];\n }\n const message: NormalizedMessage = {\n id: this.activeAssistantItemId,\n role: \"assistant\",\n text: this.assistantText\n };\n this.resetTurn();\n return [\n {\n kind: \"agent_message\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n message\n }\n ];\n }\n\n /** Normalize one ACP session/update into neutral events (+ optional title). */\n apply(update: Record<string, unknown>, ctx: AcpApplyContext): AcpNormalizeResult {\n const kind = readKind(update);\n\n // 1) Title-bearing updates (topic-update / vendor session-summary). Strategy\n // quirks decide which spellings count. Never a transcript event.\n const title = this.extractTitle(update, kind);\n if (title !== undefined) {\n return { events: [], title };\n }\n\n switch (kind) {\n case \"agent_message_chunk\":\n return { events: this.applyAgentMessageChunk(update, ctx) };\n case \"agent_thought_chunk\":\n return { events: this.applyThoughtChunk(update, ctx) };\n case \"user_message_chunk\":\n return { events: this.applyUserMessageChunk(update, ctx) };\n case \"plan\":\n this.activeAssistantItemId = undefined;\n return { events: this.applyPlan(update, ctx) };\n case \"tool_call\":\n case \"tool_call_update\":\n case \"file\":\n case \"terminal\":\n this.activeAssistantItemId = undefined;\n return { events: this.applyToolCall(update, kind, ctx) };\n case \"available_commands_update\":\n case \"current_mode_update\":\n case \"config_option_update\":\n // Runtime metadata, not transcript — the client handles these via\n // runtime-capabilities and emits thread_settings itself.\n return EMPTY_RESULT;\n default:\n // Unknown update: no transcript noise. (PwrAgnt surfaced an \"unknown\n // activity\" entry; in the event model we simply drop it — a consumer\n // that wants raw access can subscribe to the transport observer.)\n this.activeAssistantItemId = undefined;\n return EMPTY_RESULT;\n }\n }\n\n private applyAgentMessageChunk(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n const text = readUpdateText(update) ?? \"\";\n if (text === \"\" || isModeUpdateMarker(text)) {\n return [];\n }\n const itemId = this.assistantItemIdForChunk(update, ctx);\n this.assistantText = appendTranscriptChunk(this.assistantText, text);\n return [\n {\n kind: \"agent_message_delta\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n itemId,\n delta: text\n }\n ];\n }\n\n private applyThoughtChunk(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n if (!this.quirks.surfaceThoughts) {\n return [];\n }\n const text = readUpdateText(update) ?? \"\";\n if (text === \"\") {\n return [];\n }\n // Thoughts coalesce into the same live bubble as message chunks (matching\n // PwrAgnt, which surfaced thoughts as assistant text). In the neutral schema\n // they ride the `reasoning_delta` channel so a consumer can style them.\n const itemId = this.assistantItemIdForChunk(update, ctx);\n this.assistantText = appendTranscriptChunk(this.assistantText, text);\n return [\n {\n kind: \"reasoning_delta\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n itemId,\n delta: text\n }\n ];\n }\n\n private applyUserMessageChunk(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n this.activeAssistantItemId = undefined;\n const text = readUpdateText(update) ?? \"\";\n if (text === \"\") {\n return [];\n }\n const id =\n readFirstString(update, \"messageId\", \"message_id\", \"id\") ??\n `user:${ctx.threadId}:${ctx.turnId}`;\n const message: NormalizedMessage = { id, role: \"user\", text };\n return [\n {\n kind: \"agent_message\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n message\n }\n ];\n }\n\n private applyPlan(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n const id = readString(update, \"planId\") ?? `plan:${ctx.threadId}`;\n const plan: NormalizedPlan = {\n id,\n steps: readPlanSteps(update)\n };\n const explanation = readString(update, \"explanation\");\n if (explanation !== undefined) plan.explanation = explanation;\n const markdown = readString(update, \"markdown\");\n if (markdown !== undefined) plan.markdown = markdown;\n return [{ kind: \"plan_update\", threadId: ctx.threadId, turnId: ctx.turnId, plan }];\n }\n\n private applyToolCall(\n update: Record<string, unknown>,\n kind: string,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n const incoming = toolCallFromUpdate(update, kind, ctx.threadId);\n const prev = this.toolCalls.get(incoming.id);\n if (prev === undefined) {\n this.toolCalls.set(incoming.id, incoming);\n return [\n { kind: \"tool_call\", threadId: ctx.threadId, turnId: ctx.turnId, toolCall: incoming }\n ];\n }\n // Subsequent update: merge via agent-core (label reconciliation, command\n // detail fill, later-status-wins) and emit a tool_call_update delta.\n const merged = mergeToolCall(prev, incoming);\n // agent-core merges command detail shallowly (later displayCommand wins);\n // reconcile it with the same prefer-specific rule the label uses, so a\n // later output-only update keeps the earlier specific displayCommand.\n if (merged.command && prev.command) {\n merged.command = {\n ...merged.command,\n displayCommand: preferSpecificLabel(\n prev.command.displayCommand,\n merged.command.displayCommand\n )\n };\n }\n this.toolCalls.set(incoming.id, merged);\n return [\n {\n kind: \"tool_call_update\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n toolCall: merged\n }\n ];\n }\n\n private assistantItemIdForChunk(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): string {\n const explicitId = readFirstString(update, \"messageId\", \"message_id\");\n if (explicitId) {\n if (explicitId !== this.activeAssistantItemId) {\n this.activeAssistantItemId = explicitId;\n this.assistantText = \"\";\n }\n return explicitId;\n }\n if (this.activeAssistantItemId === undefined) {\n this.activeAssistantItemId = `assistant:${ctx.turnId}:${this.assistantSequence++}`;\n this.assistantText = \"\";\n }\n return this.activeAssistantItemId;\n }\n\n /** Strategy-driven title extraction. NO agent-id literal — reads quirks.titleFrom. */\n private extractTitle(\n update: Record<string, unknown>,\n kind: string\n ): string | undefined {\n const wantsSummary =\n this.quirks.titleFrom === \"session-summary\" || this.quirks.titleFrom === \"both\";\n const wantsTopic =\n this.quirks.titleFrom === \"topic-update\" || this.quirks.titleFrom === \"both\";\n\n if (wantsSummary && kind === \"session_summary_generated\") {\n const summary = (\n readString(update, \"session_summary\") ?? readString(update, \"sessionSummary\")\n )?.trim();\n return summary || undefined;\n }\n\n if (wantsTopic) {\n const isToolish =\n kind === \"tool_call\" || kind === \"tool_call_update\" || kind === \"think\";\n if (!isToolish) {\n return undefined;\n }\n const titleText = readString(update, \"title\")?.trim();\n if (!titleText) {\n return undefined;\n }\n const quoted = /^Update topic to:\\s*[\"“](.+?)[\"”]\\s*$/iu.exec(titleText);\n const fallback = /^Update topic to:\\s*(.+)$/iu.exec(titleText);\n const topic = (quoted?.[1] ?? fallback?.[1])?.trim();\n return topic || undefined;\n }\n\n return undefined;\n }\n}\n\n// Consecutive ACP text chunks concatenate, but a markdown heading / bold lead\n// that starts a new block gets a paragraph break so bubbles read correctly.\nfunction appendTranscriptChunk(existing: string, next: string): string {\n if (!existing || !next) {\n return `${existing}${next}`;\n }\n if (shouldSeparateTranscriptChunks(existing, next)) {\n return `${existing}\\n\\n${next}`;\n }\n return `${existing}${next}`;\n}\n\nfunction shouldSeparateTranscriptChunks(existing: string, next: string): boolean {\n if (/\\s$/.test(existing)) {\n return false;\n }\n return /^(?:#{1,6}\\s|\\*\\*[^*]+?\\*\\*(?:\\s|$))/.test(next);\n}\n\nfunction isModeUpdateMarker(text: string): boolean {\n return /^\\[MODE_UPDATE\\]\\s*[A-Za-z0-9_-]+\\s*$/.test(text.trim());\n}\n\nfunction readPlanSteps(record: Record<string, unknown>): NormalizedPlanStep[] {\n const steps = Array.isArray(record.steps) ? record.steps : [];\n return steps.flatMap((step): NormalizedPlanStep[] => {\n if (typeof step === \"string\") {\n return [{ step, status: \"pending\" }];\n }\n const stepRecord = asRecord(step);\n if (!stepRecord) {\n return [];\n }\n const text = readString(stepRecord, \"step\") ?? readString(stepRecord, \"content\");\n if (!text) {\n return [];\n }\n const status = readString(stepRecord, \"status\");\n return [\n {\n step: text,\n status: status === \"in_progress\" || status === \"completed\" ? status : \"pending\"\n }\n ];\n });\n}\n\n/** Read the message parts (text/image) of a prompt, camel/snake tolerant. */\nexport function readPromptText(content: unknown): string | undefined {\n return readContentText({ content }, \"content\");\n}\n","// camel/snake-tolerant readers + recursive ACP content unwrapping. ACP agents\n// are wildly inconsistent: the same field arrives camelCase from one agent and\n// snake_case from another, and content blocks nest arbitrarily\n// (`content` → `[{ type: \"content\", content: { type: \"text\", text } }]`).\n// Every reader here tolerates both casings and unwraps recursively.\n\nexport function asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nexport function readString(\n record: Record<string, unknown> | undefined,\n key: string\n): string | undefined {\n const value = record?.[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nexport function readNonEmptyString(\n record: Record<string, unknown> | undefined,\n key: string\n): string | undefined {\n const value = record?.[key];\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nexport function readNumber(\n record: Record<string, unknown> | undefined,\n key: string\n): number | undefined {\n const value = record?.[key];\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nexport function readBoolean(\n record: Record<string, unknown> | undefined,\n key: string\n): boolean | undefined {\n const value = record?.[key];\n return typeof value === \"boolean\" ? value : undefined;\n}\n\n/**\n * Read the first defined string among the given keys, in order. Used for\n * camel/snake parity (`toolCallId` vs `tool_call_id`).\n */\nexport function readFirstString(\n record: Record<string, unknown> | undefined,\n ...keys: string[]\n): string | undefined {\n for (const key of keys) {\n const value = readString(record, key);\n if (value !== undefined) return value;\n }\n return undefined;\n}\n\n/** The session-update kind, tolerant of all four key spellings. */\nexport function readKind(update: Record<string, unknown>): string {\n return (\n readString(update, \"sessionUpdate\") ??\n readString(update, \"session_update\") ??\n readString(update, \"kind\") ??\n readString(update, \"type\") ??\n \"unknown\"\n );\n}\n\n/**\n * Recursively unwrap an ACP content value to plain text. Handles a bare string,\n * an array of content blocks (joined with newlines), and nested\n * `{ type:\"text\", text }` / `{ content }` / `{ text }` / `{ output }` /\n * `{ result }` shapes.\n */\nexport function readAcpContentText(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (Array.isArray(value)) {\n const parts = value\n .map((item) => readAcpContentText(item))\n .filter((item): item is string => Boolean(item));\n return parts.length > 0 ? parts.join(\"\\n\") : undefined;\n }\n\n const content = asRecord(value);\n if (!content) {\n return undefined;\n }\n\n if (content.type === \"text\" && typeof content.text === \"string\") {\n return content.text;\n }\n return (\n readAcpContentText(content.content) ??\n readAcpContentText(content.text) ??\n readAcpContentText(content.output) ??\n readAcpContentText(content.result)\n );\n}\n\nexport function readContentText(\n record: Record<string, unknown>,\n key: string\n): string | undefined {\n return readAcpContentText(record[key]);\n}\n\n/** Tool output, checked across all the spellings agents use. */\nexport function readToolOutput(record: Record<string, unknown>): string | undefined {\n return (\n readString(record, \"output\") ??\n readString(record, \"stdout\") ??\n readString(record, \"stderr\") ??\n readString(record, \"result\") ??\n readContentText(record, \"content\")\n );\n}\n\n/** First location path from an ACP `locations: [{ path }]` array. */\nexport function readFirstLocationPath(\n record: Record<string, unknown>\n): string | undefined {\n const locations = record.locations ?? record.location;\n if (!Array.isArray(locations)) {\n return undefined;\n }\n for (const location of locations) {\n const path = readString(asRecord(location), \"path\");\n if (path && path.trim()) {\n return path;\n }\n }\n return undefined;\n}\n\n/** The assistant/user text carried by a chunk update (camel/snake tolerant). */\nexport function readUpdateText(update: Record<string, unknown>): string | undefined {\n return (\n readString(update, \"text\") ??\n readString(update, \"outputText\") ??\n readString(update, \"output_text\") ??\n readContentText(update, \"content\")\n );\n}\n","// ACP tool_call / tool_call_update / file / terminal → agent-core\n// NormalizedToolCall. Reuses agent-core's `inferToolKind` for kind inference and\n// `mergeToolCall` / `preferSpecificLabel` for delta merging, so ACP tool-call\n// streams merge identically to Codex's.\n\nimport {\n inferToolKind,\n type NormalizedCommandDetail,\n type NormalizedToolCall,\n type NormalizedToolKind,\n type NormalizedToolLocation,\n type NormalizedToolStatus\n} from \"@pwrdrvr/agent-core\";\nimport {\n asRecord,\n readContentText,\n readFirstLocationPath,\n readFirstString,\n readNumber,\n readString,\n readToolOutput\n} from \"./content\";\n\n/** Read the tool-call correlation id across every spelling agents use. */\nexport function readToolCallId(\n update: Record<string, unknown>,\n kind: string,\n sessionId: string\n): string {\n return (\n readFirstString(\n update,\n \"toolCallId\",\n \"tool_call_id\",\n \"id\",\n \"itemId\",\n \"item_id\"\n ) ?? `${kind}:${sessionId}`\n );\n}\n\n/** Map an ACP status string onto a NormalizedToolStatus (pending → in_progress). */\nfunction normalizeStatus(status: string | undefined): NormalizedToolStatus | undefined {\n switch (status) {\n case \"completed\":\n case \"failed\":\n case \"cancelled\":\n case \"in_progress\":\n return status;\n case \"pending\":\n return \"in_progress\";\n default:\n return undefined;\n }\n}\n\n/**\n * Choose the tool kind. ACP carries an explicit `kind` on tool calls\n * (read/edit/write/execute/search/…); when present it maps directly, otherwise\n * we fall back to agent-core's name-based `inferToolKind` over the label, and to\n * a command/read heuristic.\n */\nfunction toolKindFor(\n acpKind: string | undefined,\n command: string | undefined,\n path: string | undefined,\n label: string\n): NormalizedToolKind {\n switch (acpKind) {\n case \"edit\":\n case \"write\":\n return \"write\";\n case \"execute\":\n case \"exec\":\n case \"shell\":\n return \"command\";\n case \"read\":\n return \"read\";\n case \"search\":\n return \"search\";\n case \"fetch\":\n return \"fetch\";\n default:\n break;\n }\n if (command) return \"command\";\n const inferred = inferToolKind(label);\n if (inferred !== \"other\") return inferred;\n // A tool with a file path but no other signal is a read; otherwise unknown.\n return path ? \"read\" : \"other\";\n}\n\n/**\n * Normalize one ACP tool-ish update (tool_call / tool_call_update / file /\n * terminal) into a NormalizedToolCall. The result is fed to the normalizer's\n * upsert, which merges deltas with the same id via agent-core's `mergeToolCall`.\n */\nexport function toolCallFromUpdate(\n update: Record<string, unknown>,\n kind: string,\n sessionId: string\n): NormalizedToolCall {\n const id = readToolCallId(update, kind, sessionId);\n const label =\n readString(update, \"title\") ??\n readString(update, \"name\") ??\n readString(update, \"kind\") ??\n kind.replaceAll(\"_\", \" \");\n const acpKind = readString(update, \"kind\");\n const path = readString(update, \"path\") ?? readFirstLocationPath(update);\n const command = readString(update, \"command\");\n const output = readToolOutput(update);\n const exitCode = readNumber(update, \"exitCode\") ?? readNumber(update, \"exit_code\");\n const status = normalizeStatus(readString(update, \"status\"));\n const toolKind = toolKindFor(acpKind, command, path, label);\n\n const call: NormalizedToolCall = {\n id,\n name: readString(update, \"name\") ?? acpKind ?? label,\n kind: toolKind,\n label,\n status: status ?? \"in_progress\",\n args: readToolArgs(update)\n };\n\n if (output !== undefined) {\n call.result = output;\n }\n\n // Preserve the file(s) a read/write/file tool touched (ACP `locations`) so a\n // consumer can show the path. Lossless: ALL locations, not just the first.\n const locations = readToolLocations(update);\n if (locations.length > 0) {\n call.locations = locations;\n }\n\n // Build a command detail ONLY for genuine command tools — i.e. when the update\n // carries a command string or an exit code. A `read` returning file content\n // has `output` but no command/exitCode, so its output stays on `result` (not\n // folded into a fake command) and its path rides `locations`. An explicit\n // display target is used only when the update names one, so a later output-\n // only update never clobbers an earlier specific displayCommand on merge.\n const explicitDisplay = command ?? readString(update, \"title\");\n if (command !== undefined || exitCode !== undefined) {\n const detail: NormalizedCommandDetail = {\n displayCommand: explicitDisplay ?? label\n };\n if (command !== undefined) detail.rawCommand = command;\n if (output !== undefined) detail.output = output;\n if (exitCode !== undefined) detail.exitCode = exitCode;\n call.command = detail;\n }\n\n return call;\n}\n\n/** Read all ACP tool-call `locations` ({ path, line? }), dropping entries with\n * no path. The ACP field is `locations: [{ path, line? }]`. */\nfunction readToolLocations(update: Record<string, unknown>): NormalizedToolLocation[] {\n const raw = update.locations;\n if (!Array.isArray(raw)) return [];\n const out: NormalizedToolLocation[] = [];\n for (const item of raw) {\n const record = asRecord(item);\n const path = record ? readString(record, \"path\") : undefined;\n if (path === undefined) continue;\n const location: NormalizedToolLocation = { path };\n const line = record ? readNumber(record, \"line\") : undefined;\n if (line !== undefined) location.line = line;\n out.push(location);\n }\n return out;\n}\n\nfunction readToolArgs(update: Record<string, unknown>): unknown {\n const raw =\n update.rawInput ??\n update.raw_input ??\n update.input ??\n update.arguments ??\n update.args;\n return asRecord(raw) ?? (raw === undefined ? undefined : raw);\n}\n\n/** Tool output text from a content array, for permission prompts. */\nexport function readToolContentText(value: unknown): string | undefined {\n return readContentText({ content: value }, \"content\");\n}\n","// ACP runtime capabilities: the models, modes, and config-options an agent\n// advertises at `initialize` / `session/new` / `session/load`, and how those\n// merge over the initialize snapshot. These are package-internal metadata\n// surfaced through client callbacks (NOT a NormalizedThreadEvent) — a host that\n// renders a model/mode picker reads them. camel/snake tolerant throughout, and\n// new data merges OVER the initialize snapshot without dropping prior fields.\n//\n// Ported from PwrAgnt acp-runtime-capabilities.ts, retargeted off @pwragent/shared\n// onto neutral local types.\n\nimport { asRecord, readBoolean, readString } from \"./content\";\n\nexport type AcpRuntimeConfigOptionValue = {\n value: string;\n label?: string;\n description?: string;\n};\n\nexport type AcpRuntimeConfigOption = {\n id: string;\n label: string;\n description?: string;\n type: \"select\";\n category?: string;\n currentValue?: string;\n values: AcpRuntimeConfigOptionValue[];\n};\n\nexport type AcpRuntimeMode = {\n id: string;\n label: string;\n description?: string;\n};\n\nexport type AcpRuntimeModel = {\n id: string;\n label?: string;\n description?: string;\n /** True when this is the model the agent reports as current/default\n * (`currentModelId`). At most one model in a list is flagged; absent when the\n * agent advertises models but no current id. A host can pre-select this and\n * render it as the \"(default)\" option. */\n isDefault?: boolean;\n};\n\nexport type AcpRuntimeModes = {\n availableModes: AcpRuntimeMode[];\n currentModeId?: string;\n};\n\nexport type AcpRuntimeModels = {\n availableModels: AcpRuntimeModel[];\n currentModelId?: string;\n};\n\nexport type AcpRuntimeAgentInfo = {\n name?: string;\n title?: string;\n version?: string;\n};\n\nexport type AcpRuntimeMcpCapabilities = {\n http?: boolean;\n sse?: boolean;\n};\n\nexport type AcpRuntimeAgentCapabilities = {\n loadSession?: boolean;\n mcp?: AcpRuntimeMcpCapabilities;\n sessionHistoryReplay?: boolean;\n session?: { close?: boolean; cancel?: boolean };\n raw?: unknown;\n};\n\nexport type AcpRuntimeCapabilitiesSource =\n | \"initialize\"\n | \"session-new\"\n | \"session-load\";\n\nexport type AcpRuntimeCapabilities = {\n source: AcpRuntimeCapabilitiesSource;\n discoveredAt: number;\n checkedAt: number;\n protocolVersion?: number;\n agentInfo?: AcpRuntimeAgentInfo;\n agentCapabilities?: AcpRuntimeAgentCapabilities;\n configOptions?: AcpRuntimeConfigOption[];\n modes?: AcpRuntimeModes;\n models?: AcpRuntimeModels;\n};\n\nexport type AcpSessionRuntimeState = {\n updatedAt?: number;\n currentModeId?: string;\n currentModelId?: string;\n configValues?: Record<string, string>;\n};\n\nexport function normalizeAcpRuntimeCapabilities(params: {\n value: unknown;\n now: number;\n source: AcpRuntimeCapabilitiesSource;\n initialize?: AcpRuntimeCapabilities;\n}): AcpRuntimeCapabilities | undefined {\n const record = asRecord(params.value);\n if (!record) {\n return params.initialize;\n }\n\n const configOptions = readConfigOptions(record.configOptions ?? record.config_options);\n const modes = readModes(record.modes);\n const models = readModels(record.models);\n const agentCapabilities = readAgentCapabilities(\n record.agentCapabilities ?? record.agent_capabilities ?? record.capabilities,\n record.sessionCapabilities ?? record.session_capabilities\n );\n const agentInfo = readAgentInfo(record.agentInfo ?? record.agent_info);\n const protocolVersion =\n typeof record.protocolVersion === \"number\"\n ? record.protocolVersion\n : typeof record.protocol_version === \"number\"\n ? record.protocol_version\n : params.initialize?.protocolVersion;\n\n const hasRuntimeData =\n configOptions.length > 0 ||\n Boolean(modes) ||\n Boolean(models) ||\n Boolean(agentCapabilities) ||\n Boolean(agentInfo) ||\n typeof protocolVersion === \"number\";\n\n if (!hasRuntimeData && !params.initialize) {\n return undefined;\n }\n\n const merged: AcpRuntimeCapabilities = {\n source: params.source,\n discoveredAt: params.initialize?.discoveredAt ?? params.now,\n checkedAt: params.now\n };\n if (typeof protocolVersion === \"number\") merged.protocolVersion = protocolVersion;\n\n if (agentInfo ?? params.initialize?.agentInfo) {\n merged.agentInfo = { ...params.initialize?.agentInfo, ...agentInfo };\n }\n if (agentCapabilities ?? params.initialize?.agentCapabilities) {\n merged.agentCapabilities = {\n ...params.initialize?.agentCapabilities,\n ...agentCapabilities\n };\n }\n if (configOptions.length > 0) {\n merged.configOptions = configOptions;\n } else if (params.initialize?.configOptions) {\n merged.configOptions = params.initialize.configOptions;\n }\n if (modes) {\n merged.modes = modes;\n } else if (params.initialize?.modes) {\n merged.modes = params.initialize.modes;\n }\n if (models) {\n merged.models = models;\n } else if (params.initialize?.models) {\n merged.models = params.initialize.models;\n }\n\n return merged;\n}\n\nexport function acpRuntimeSupportsSessionLoad(\n capabilities: AcpRuntimeCapabilities | undefined\n): boolean {\n return capabilities?.agentCapabilities?.loadSession !== false;\n}\n\n/** Optional ACP MCP transports are supported only when explicitly advertised. */\nexport function acpRuntimeSupportsHttpMcp(\n capabilities: AcpRuntimeCapabilities | undefined\n): boolean {\n return capabilities?.agentCapabilities?.mcp?.http === true;\n}\n\n/** Optional ACP MCP transports are supported only when explicitly advertised. */\nexport function acpRuntimeSupportsSseMcp(\n capabilities: AcpRuntimeCapabilities | undefined\n): boolean {\n return capabilities?.agentCapabilities?.mcp?.sse === true;\n}\n\n/** The configOption an agent uses to expose model choice (ACP `category:\n * \"model\"`, falling back to a literal `model` id). Some agents (e.g. Kimi)\n * advertise the active model HERE rather than via top-level\n * `models.currentModelId`. */\nexport function modelConfigOption(\n capabilities: AcpRuntimeCapabilities | undefined\n): AcpRuntimeConfigOption | undefined {\n return capabilities?.configOptions?.find(\n (option) => option.category === \"model\" || option.id === \"model\"\n );\n}\n\n/** The effective model id the agent will run with, agnostic of HOW it advertises\n * it. Prefers a protocol-confirmed `models.currentModelId`; falls back to the\n * `model` configOption's `currentValue` for agents that expose model choice as a\n * config option (Kimi). Returns undefined when the agent advertises no model at\n * all — callers report that as \"no model\" rather than inventing one. */\nexport function modelIdFromCapabilities(\n capabilities: AcpRuntimeCapabilities | undefined\n): string | undefined {\n return capabilities?.models?.currentModelId ?? modelConfigOption(capabilities)?.currentValue;\n}\n\n/** The full model list a host can render/cache, agnostic of advertisement style.\n * Returns `models.availableModels` when present; otherwise derives the list from\n * the `model` configOption's values (Kimi), preserving labels/descriptions and\n * flagging the current value as default. `[]` when no model is advertised. */\nexport function modelsFromCapabilities(\n capabilities: AcpRuntimeCapabilities | undefined\n): AcpRuntimeModel[] {\n const advertised = capabilities?.models?.availableModels;\n if (advertised !== undefined && advertised.length > 0) return advertised;\n const option = modelConfigOption(capabilities);\n if (option === undefined) return [];\n return option.values.map((value) => ({\n id: value.value,\n ...(value.label !== undefined ? { label: value.label } : {}),\n ...(value.description !== undefined ? { description: value.description } : {}),\n ...(option.currentValue === value.value ? { isDefault: true } : {})\n }));\n}\n\nexport function acpSessionRuntimeStateFromCapabilities(\n capabilities: AcpRuntimeCapabilities | undefined,\n now: number\n): AcpSessionRuntimeState | undefined {\n if (!capabilities) {\n return undefined;\n }\n const configValues = Object.fromEntries(\n (capabilities.configOptions ?? []).flatMap((option) =>\n typeof option.currentValue === \"string\"\n ? [[option.id, option.currentValue] as const]\n : []\n )\n );\n const state: AcpSessionRuntimeState = { updatedAt: now };\n if (Object.keys(configValues).length > 0) state.configValues = configValues;\n if (capabilities.modes?.currentModeId) {\n state.currentModeId = capabilities.modes.currentModeId;\n }\n if (capabilities.models?.currentModelId) {\n state.currentModelId = capabilities.models.currentModelId;\n }\n return Object.keys(state).length > 1 ? state : undefined;\n}\n\n/** Runtime-state change carried inside a session/update (mode/model/config). */\nexport function acpSessionRuntimeStateFromUpdate(\n update: Record<string, unknown>,\n now: number\n): AcpSessionRuntimeState | undefined {\n const kind =\n readString(update, \"sessionUpdate\") ??\n readString(update, \"session_update\") ??\n readString(update, \"kind\") ??\n readString(update, \"type\");\n if (kind === \"agent_message_chunk\") {\n const modeId = readModeUpdateMarker(update);\n return modeId ? { currentModeId: modeId, updatedAt: now } : undefined;\n }\n if (kind === \"current_mode_update\") {\n const currentModeId =\n readString(update, \"currentModeId\") ??\n readString(update, \"current_mode_id\") ??\n readString(update, \"modeId\") ??\n readString(update, \"mode_id\") ??\n readString(update, \"id\");\n return currentModeId ? { currentModeId, updatedAt: now } : undefined;\n }\n if (kind === \"config_option_update\") {\n const configOption = asRecord(update.configOption ?? update.config_option) ?? update;\n const id =\n readString(configOption, \"id\") ??\n readString(configOption, \"configOptionId\") ??\n readString(configOption, \"configId\");\n const value =\n readString(configOption, \"currentValue\") ?? readString(configOption, \"value\");\n return id && value ? { configValues: { [id]: value }, updatedAt: now } : undefined;\n }\n return undefined;\n}\n\nexport function mergeAcpRuntimeState(\n existing: AcpSessionRuntimeState | undefined,\n update: AcpSessionRuntimeState\n): AcpSessionRuntimeState {\n return {\n ...existing,\n ...update,\n configValues: {\n ...(existing?.configValues ?? {}),\n ...(update.configValues ?? {})\n }\n };\n}\n\n/** Resolve the human-facing label for a mode id from the capabilities snapshot. */\nexport function modeLabelFor(\n capabilities: AcpRuntimeCapabilities | undefined,\n modeId: string\n): string | undefined {\n return capabilities?.modes?.availableModes.find((mode) => mode.id === modeId)?.label;\n}\n\nfunction readModeUpdateMarker(update: Record<string, unknown>): string | undefined {\n const text = readString(update, \"content\") ?? readString(update, \"text\");\n const match = text?.trim().match(/^\\[MODE_UPDATE\\]\\s*([A-Za-z0-9_-]+)\\s*$/);\n return match?.[1];\n}\n\nfunction readConfigOptions(value: unknown): AcpRuntimeConfigOption[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.flatMap((item) => {\n const record = asRecord(item);\n const id =\n readString(record, \"id\") ??\n readString(record, \"configOptionId\") ??\n readString(record, \"configId\");\n if (!record || !id) {\n return [];\n }\n const values = readConfigOptionValues(record.values ?? record.options);\n if (values.length === 0) {\n return [];\n }\n const option: AcpRuntimeConfigOption = {\n id,\n label:\n readString(record, \"name\") ??\n readString(record, \"label\") ??\n readString(record, \"title\") ??\n id,\n type: \"select\",\n values\n };\n const description = readString(record, \"description\");\n if (description !== undefined) option.description = description;\n const category = readString(record, \"category\");\n if (category !== undefined) option.category = category;\n const currentValue =\n readString(record, \"currentValue\") ?? readString(record, \"value\");\n if (currentValue !== undefined) option.currentValue = currentValue;\n return [option];\n });\n}\n\nfunction readConfigOptionValues(value: unknown): AcpRuntimeConfigOptionValue[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.flatMap((item) => {\n const record = asRecord(item);\n const optionValue =\n readString(record, \"value\") ??\n readString(record, \"id\") ??\n readString(record, \"optionId\");\n if (!record || !optionValue) {\n return [];\n }\n const normalized: AcpRuntimeConfigOptionValue = { value: optionValue };\n const label =\n readString(record, \"name\") ??\n readString(record, \"label\") ??\n readString(record, \"title\");\n if (label !== undefined) normalized.label = label;\n const description = readString(record, \"description\");\n if (description !== undefined) normalized.description = description;\n return [normalized];\n });\n}\n\nfunction readModes(value: unknown): AcpRuntimeModes | undefined {\n const record = asRecord(value);\n const modes = Array.isArray(record?.availableModes)\n ? record.availableModes.flatMap(readMode)\n : [];\n if (modes.length === 0) {\n return undefined;\n }\n const result: AcpRuntimeModes = { availableModes: modes };\n const currentModeId = readString(record, \"currentModeId\");\n if (currentModeId !== undefined) result.currentModeId = currentModeId;\n return result;\n}\n\nfunction readMode(value: unknown): AcpRuntimeMode[] {\n const record = asRecord(value);\n const id = readString(record, \"id\") ?? readString(record, \"modeId\");\n if (!record || !id) {\n return [];\n }\n const mode: AcpRuntimeMode = {\n id,\n label: readString(record, \"name\") ?? readString(record, \"label\") ?? id\n };\n const description = readString(record, \"description\");\n if (description !== undefined) mode.description = description;\n return [mode];\n}\n\nfunction readModels(value: unknown): AcpRuntimeModels | undefined {\n const record = asRecord(value);\n const models = Array.isArray(record?.availableModels)\n ? record.availableModels.flatMap(readModel)\n : [];\n if (models.length === 0) {\n return undefined;\n }\n const result: AcpRuntimeModels = { availableModels: models };\n const currentModelId =\n readString(record, \"currentModelId\") ?? readString(record, \"modelId\");\n if (currentModelId !== undefined) {\n result.currentModelId = currentModelId;\n // Flag the agent's protocol-confirmed default so a host can pre-select it\n // and label it \"(default)\" without re-deriving from currentModelId.\n const defaultModel = models.find((model) => model.id === currentModelId);\n if (defaultModel) defaultModel.isDefault = true;\n }\n return result;\n}\n\nfunction readModel(value: unknown): AcpRuntimeModel[] {\n const record = asRecord(value);\n const id = readString(record, \"modelId\") ?? readString(record, \"id\");\n if (!record || !id) {\n return [];\n }\n const model: AcpRuntimeModel = { id };\n const label = readString(record, \"name\") ?? readString(record, \"label\");\n if (label !== undefined) model.label = label;\n const description = readString(record, \"description\");\n if (description !== undefined) model.description = description;\n return [model];\n}\n\nfunction readAgentCapabilities(\n value: unknown,\n sessionCapabilitiesValue?: unknown\n): AcpRuntimeAgentCapabilities | undefined {\n const record = asRecord(value);\n const sessionCapabilities = asRecord(sessionCapabilitiesValue);\n const sessionMeta = asRecord(sessionCapabilities?._meta);\n const kimiMeta = asRecord(sessionMeta?.kimi);\n if (!record && !sessionCapabilities) {\n return undefined;\n }\n const loadSession =\n readBoolean(record, \"loadSession\") ??\n readBoolean(record, \"load_session\") ??\n readBoolean(asRecord(record?.session), \"load\");\n const close = readBoolean(asRecord(record?.session), \"close\");\n const cancel = readBoolean(asRecord(record?.session), \"cancel\");\n const sessionHistoryReplay =\n readBoolean(kimiMeta, \"sessionHistoryReplay\") ??\n readBoolean(kimiMeta, \"session_history_replay\");\n const mcpRecord = asRecord(\n record?.mcpCapabilities ?? record?.mcp_capabilities ?? record?.mcp\n );\n const http = readBoolean(mcpRecord, \"http\");\n const sse = readBoolean(mcpRecord, \"sse\");\n\n const capabilities: AcpRuntimeAgentCapabilities = {\n raw: record ?? sessionCapabilities\n };\n if (loadSession !== undefined) capabilities.loadSession = loadSession;\n if (http !== undefined || sse !== undefined) {\n capabilities.mcp = {\n ...(http !== undefined ? { http } : {}),\n ...(sse !== undefined ? { sse } : {})\n };\n }\n if (sessionHistoryReplay !== undefined) {\n capabilities.sessionHistoryReplay = sessionHistoryReplay;\n }\n if (close !== undefined || cancel !== undefined) {\n capabilities.session = {\n ...(close !== undefined ? { close } : {}),\n ...(cancel !== undefined ? { cancel } : {})\n };\n }\n return capabilities;\n}\n\nfunction readAgentInfo(value: unknown): AcpRuntimeAgentInfo | undefined {\n const record = asRecord(value);\n if (!record) {\n return undefined;\n }\n const agentInfo: AcpRuntimeAgentInfo = {};\n const name = readString(record, \"name\");\n if (name !== undefined) agentInfo.name = name;\n const title = readString(record, \"title\");\n if (title !== undefined) agentInfo.title = title;\n const version = readString(record, \"version\");\n if (version !== undefined) agentInfo.version = version;\n return Object.keys(agentInfo).length > 0 ? agentInfo : undefined;\n}\n","import type { McpServer } from \"@agentclientprotocol/sdk\";\n\n/** ACP key/value entry used by stdio environments and HTTP headers. */\nexport type AcpMcpKeyValue = {\n name: string;\n value: string;\n};\n\n/** Host-friendly collection accepted wherever ACP requires key/value entries. */\nexport type AcpMcpKeyValueCollection =\n | Readonly<Record<string, string>>\n | readonly AcpMcpKeyValue[];\n\n/** Backward-compatible stdio MCP configuration. ACP stdio has no `type` field. */\nexport type AcpStdioMcpServerConfig = {\n name: string;\n command: string;\n args?: readonly string[];\n env?: AcpMcpKeyValueCollection;\n};\n\n/** Streamable HTTP MCP configuration from the ACP v1 schema. */\nexport type AcpHttpMcpServerConfig = {\n name: string;\n type: \"http\";\n url: string;\n headers: AcpMcpKeyValueCollection;\n};\n\n/** Legacy HTTP+SSE MCP configuration from the ACP v1 schema. */\nexport type AcpSseMcpServerConfig = {\n name: string;\n type: \"sse\";\n url: string;\n headers: AcpMcpKeyValueCollection;\n};\n\n/** Public MCP input accepted by agent-acp session lifecycle methods. */\nexport type AcpMcpServerConfig =\n | AcpStdioMcpServerConfig\n | AcpHttpMcpServerConfig\n | AcpSseMcpServerConfig;\n\n/** Exact MCP server wire union from the pinned ACP protocol library. */\nexport type AcpMcpServerWireConfig = McpServer;\n\nfunction isKeyValueArray(\n collection: AcpMcpKeyValueCollection\n): collection is readonly AcpMcpKeyValue[] {\n return Array.isArray(collection);\n}\n\nfunction normalizeKeyValues(\n collection: AcpMcpKeyValueCollection | undefined\n): AcpMcpKeyValue[] {\n if (collection === undefined) return [];\n if (isKeyValueArray(collection)) {\n return collection.map(({ name, value }) => ({ name, value }));\n }\n return Object.entries(collection).map(([name, value]) => ({ name, value }));\n}\n\n/** Serialize a host-friendly config into the exact ACP v1 wire representation. */\nexport function normalizeAcpMcpServerConfig(\n server: AcpMcpServerConfig\n): AcpMcpServerWireConfig {\n if (\"type\" in server) {\n return {\n name: server.name,\n type: server.type,\n url: server.url,\n headers: normalizeKeyValues(server.headers)\n };\n }\n return {\n name: server.name,\n command: server.command,\n args: [...(server.args ?? [])],\n env: normalizeKeyValues(server.env)\n };\n}\n\n/** Serialize a per-session list without retaining mutable caller collections. */\nexport function normalizeAcpMcpServerConfigs(\n servers: readonly AcpMcpServerConfig[]\n): AcpMcpServerWireConfig[] {\n return servers.map(normalizeAcpMcpServerConfig);\n}\n\n/**\n * Remove credential-bearing MCP values from a lifecycle error. The server URL\n * is redacted in full because it may carry user-info or query credentials.\n */\nexport function redactAcpMcpCredentials(\n message: string,\n servers: readonly AcpMcpServerConfig[]\n): string {\n const secrets = new Set<string>();\n for (const server of servers) {\n const values =\n \"type\" in server\n ? [server.url, ...normalizeKeyValues(server.headers).map(({ value }) => value)]\n : normalizeKeyValues(server.env).map(({ value }) => value);\n for (const value of values) {\n if (value.length > 0) secrets.add(value);\n }\n }\n let redacted = message;\n for (const secret of [...secrets].sort((a, b) => b.length - a.length)) {\n redacted = redacted.split(secret).join(\"[REDACTED]\");\n }\n return redacted;\n}\n","// Lifecycle pool for `AcpAgentClient`. An ACP agent is a long-lived OS process\n// with a stdio connection, and ONE client can host many concurrent sessions\n// (threads). Without pooling, every consumer (each chat surface, enrichment,\n// the model-lister) news up its own client → its own process; a careless React\n// caller can spawn dozens. The pool gives every caller the SAME warmed client\n// for a key, dedups concurrent warm-ups onto one spawn, and owns teardown.\n//\n// const pool = new AcpAgentClientPool();\n// pool.warm(\"gemini@/opt/homebrew/bin/gemini\", () => new AcpAgentClient(...)); // startup\n// const client = await pool.acquire(key, factory); // surfaces — same instance\n\nimport { noopLogger, type Logger } from \"@pwrdrvr/agent-core\";\nimport type { AcpAgentClient } from \"./acp-client\";\n\nexport type AcpAgentClientFactory = () => AcpAgentClient;\n\nexport type AcpAgentClientPoolOptions = {\n /** Max time to wait for a client to warm (spawn + `initialize`) before an\n * `acquire` rejects. Default 30s. */\n warmTimeoutMs?: number;\n logger?: Logger;\n};\n\ntype PoolEntry = {\n client: AcpAgentClient;\n /** Resolves to the client once warmed; shared by concurrent acquires. */\n ready: Promise<AcpAgentClient>;\n};\n\nfunction errorMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : String(cause);\n}\n\nexport class AcpAgentClientPool {\n private readonly entries = new Map<string, PoolEntry>();\n private readonly warmTimeoutMs: number;\n private readonly logger: Logger;\n\n constructor(options: AcpAgentClientPoolOptions = {}) {\n this.warmTimeoutMs = options.warmTimeoutMs ?? 30_000;\n this.logger = options.logger ?? noopLogger;\n }\n\n /**\n * Return the shared, warmed client for `key`, creating it via `factory` if it\n * doesn't exist. Concurrent acquires for the same key share ONE spawn — they\n * receive the same in-flight promise, which resolves when the agent is ready\n * or rejects if warm-up fails / times out. A failed warm-up evicts the entry\n * so a later acquire retries with a fresh client.\n */\n async acquire(key: string, factory: AcpAgentClientFactory): Promise<AcpAgentClient> {\n const existing = this.entries.get(key);\n if (existing !== undefined) return existing.ready;\n const client = factory();\n const ready = this.warmWithTimeout(key, client);\n this.entries.set(key, { client, ready });\n return ready;\n }\n\n /** Fire-and-forget warm-up for app startup. Errors are logged, not thrown. */\n warm(key: string, factory: AcpAgentClientFactory): void {\n void this.acquire(key, factory).catch((cause) => {\n this.logger.warn?.(\"acp pool: background warm-up failed\", {\n key,\n message: errorMessage(cause)\n });\n });\n }\n\n /** Whether a (warming or warm) entry exists for `key`. */\n has(key: string): boolean {\n return this.entries.has(key);\n }\n\n /** Close + evict ONE key (e.g. its config changed). Safe if absent. */\n async release(key: string): Promise<void> {\n const entry = this.entries.get(key);\n if (entry === undefined) return;\n this.entries.delete(key);\n // Don't let a still-warming entry surface an unhandled rejection on release.\n entry.ready.catch(() => undefined);\n await entry.client.close().catch(() => undefined);\n }\n\n /** Close + evict EVERY entry (app quit). */\n async closeAll(): Promise<void> {\n const entries = [...this.entries.values()];\n this.entries.clear();\n for (const entry of entries) entry.ready.catch(() => undefined);\n await Promise.allSettled(entries.map((entry) => entry.client.close()));\n }\n\n private async warmWithTimeout(\n key: string,\n client: AcpAgentClient\n ): Promise<AcpAgentClient> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n client.connect(),\n new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(`ACP agent \"${key}\" warm-up timed out after ${this.warmTimeoutMs}ms`)\n ),\n this.warmTimeoutMs\n );\n })\n ]);\n return client;\n } catch (cause) {\n // Evict so a later acquire retries with a fresh client, and tear down the\n // half-spawned process.\n if (this.entries.get(key)?.client === client) this.entries.delete(key);\n await client.close().catch(() => undefined);\n throw cause;\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n }\n}\n","// One-shot structured turn against an ACP agent — the ACP analog of the Codex\n// `CodexOneShotClient`. Used for non-interactive jobs (e.g. capture\n// enrichment): one prompt + optional images in, one assistant message out, no\n// chat, no tools, no approvals.\n//\n// Lifecycle parity with the Codex one-shot:\n// • The agent PROCESS is persistent — the transport connects lazily on the\n// first request and stays connected across `run()` calls; `close()` tears\n// it down.\n// • Each `run()` opens a FRESH ACP session (`session/new`) so per-call\n// context is clean. ACP has no `thread/rollback`, so a new session is the\n// equivalent of Codex's per-turn rollback.\n//\n// Differences from Codex, by protocol:\n// • No `outputSchema` — ACP can't constrain the reply, so the CALLER must\n// bake the \"reply with JSON only\" contract into the prompt and parse +\n// validate the returned text.\n// • No base-instructions on `session/new` — the caller folds any system\n// preamble into the prompt text too.\n//\n// Enrichment is non-interactive: approvals are auto-denied and tool calls are\n// rejected, so the agent can only answer.\n\nimport {\n noopLogger,\n type Logger,\n type NormalizedThreadEvent,\n type NormalizedTokenUsage\n} from \"@pwrdrvr/agent-core\";\nimport { AcpAgentClient } from \"./acp-client\";\nimport type { AcpJsonRpcTransport } from \"./acp-transport\";\nimport type { AcpAgentStrategy } from \"./strategies/strategy-types\";\nimport {\n modelsFromCapabilities,\n type AcpRuntimeModel\n} from \"./normalizer/runtime-capabilities\";\n\nexport type AcpOneShotClientOptions = {\n /** Connected (or lazily-connecting) ACP stdio transport for the agent. */\n transport: AcpJsonRpcTransport;\n /** Strategy carrying the agent's spawn + normalization quirks. */\n strategy: AcpAgentStrategy;\n clientName?: string;\n clientTitle?: string;\n clientVersion?: string;\n /** Scratch cwd for the session (keep enrichment out of any repo). */\n cwd?: string;\n logger?: Logger;\n now?: () => number;\n};\n\nexport type AcpOneShotRequest = {\n /** Full prompt text — the caller folds in any system preamble + the\n * \"reply with ONLY JSON matching <schema>\" contract. */\n prompt: string;\n /** Local image file paths attached to the turn (ACP image content blocks). */\n imagePaths?: readonly string[];\n /** Model id to select for the session. Omit for the agent default. */\n model?: string | null;\n /** Reasoning effort token (agent-specific). */\n effort?: string;\n abortSignal?: AbortSignal;\n};\n\nexport type AcpOneShotResponse = {\n /** The agent's final assistant-message text. Caller parses + validates it. */\n rawText: string;\n threadId: string;\n turnId: string;\n model: string;\n modelProvider: string;\n serviceTier: string | null;\n tokenUsage: NormalizedTokenUsage | null;\n};\n\nexport class AcpOneShotClient {\n private readonly client: AcpAgentClient;\n private readonly strategy: AcpAgentStrategy;\n private readonly denyApprovals: () => void;\n private readonly rejectTools: () => void;\n /** Serialize runs — one turn at a time against the agent. */\n private queue: Promise<void> = Promise.resolve();\n\n constructor(options: AcpOneShotClientOptions) {\n this.strategy = options.strategy;\n const logger = options.logger ?? noopLogger;\n this.client = new AcpAgentClient({\n transport: options.transport,\n strategy: options.strategy,\n ...(options.clientName !== undefined ? { clientName: options.clientName } : {}),\n ...(options.clientTitle !== undefined ? { clientTitle: options.clientTitle } : {}),\n ...(options.clientVersion !== undefined ? { clientVersion: options.clientVersion } : {}),\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.now !== undefined ? { now: options.now } : {}),\n logger\n });\n // Non-interactive: never approve, never run tools.\n this.denyApprovals = this.client.onApprovalRequest(async () => \"denied\");\n this.rejectTools = this.client.onToolCall(async () => {\n throw new Error(\"ACP one-shot does not support tool calls\");\n });\n }\n\n /** Run one structured turn. Serialized — one in-flight at a time. */\n async run(request: AcpOneShotRequest): Promise<AcpOneShotResponse> {\n const run = this.queue.catch(() => undefined).then(() => this.runInner(request));\n this.queue = run.then(\n () => undefined,\n () => undefined\n );\n return run;\n }\n\n private async runInner(request: AcpOneShotRequest): Promise<AcpOneShotResponse> {\n if (request.abortSignal?.aborted === true) {\n throw new Error(\"ACP one-shot aborted before start\");\n }\n // Fresh session per call → clean per-capture context.\n const thread = await this.client.startThread(\n request.model !== undefined && request.model !== null ? { model: request.model } : {}\n );\n\n let finalText = \"\";\n const deltas: string[] = [];\n let usage: NormalizedTokenUsage | null = null;\n let turnError: string | null = null;\n // `startTurn` now resolves at turn START (it streams terminal events\n // asynchronously), so we gate completion on the `turn_completed` event for\n // this thread rather than on `startTurn` resolving.\n let settle: (status: string) => void = () => undefined;\n const done = new Promise<string>((resolve) => {\n settle = resolve;\n });\n const unsubscribe = this.client.onEvent((event: NormalizedThreadEvent) => {\n if (!(\"threadId\" in event) || event.threadId !== thread.threadId) return;\n if (event.kind === \"agent_message\") finalText = event.message.text;\n else if (event.kind === \"agent_message_delta\") deltas.push(event.delta);\n else if (event.kind === \"token_usage\") usage = event.usage;\n else if (event.kind === \"error\") turnError = event.message;\n else if (event.kind === \"turn_completed\") settle(event.status);\n });\n\n try {\n const { turnId } = await this.client.startTurn({\n threadId: thread.threadId,\n input: {\n text: request.prompt,\n ...(request.imagePaths !== undefined && request.imagePaths.length > 0\n ? { imagePaths: request.imagePaths }\n : {})\n },\n ...(request.effort !== undefined ? { reasoning: request.effort } : {})\n });\n const status = await done;\n if (status !== \"completed\") {\n throw new Error(turnError ?? `ACP one-shot turn ${status}`);\n }\n const rawText = finalText.length > 0 ? finalText : deltas.join(\"\");\n return {\n rawText,\n threadId: thread.threadId,\n turnId,\n // `thread.model` is the EFFECTIVE model — startThread sets it to the\n // requested id ONLY when setModel applied, otherwise it's the agent's\n // session default (or \"\" when none is advertised). We deliberately do\n // NOT fall back to `request.model`: a stale/unknown id the agent ignored\n // must never be reported as what ran (showing \"\" → \"model unavailable\"\n // is honest; showing the rejected id is a lie).\n model: thread.model ?? \"\",\n modelProvider: thread.modelProvider ?? this.strategy.backendId,\n serviceTier: thread.serviceTier ?? null,\n tokenUsage: usage\n };\n } finally {\n unsubscribe();\n }\n }\n\n /** Open a throwaway session and read the agent's advertised models (ACP\n * agents report runtime capabilities — models/modes — on `session/new`).\n * Returns [] when the agent advertises none. Serialized with `run()`. */\n async listModels(): Promise<AcpRuntimeModel[]> {\n const run = this.queue.catch(() => undefined).then(() => this.listModelsInner());\n this.queue = run.then(\n () => undefined,\n () => undefined\n );\n return run;\n }\n\n private async listModelsInner(): Promise<AcpRuntimeModel[]> {\n let models: AcpRuntimeModel[] = [];\n const unsubscribe = this.client.onRuntimeCapabilities((event) => {\n // `modelsFromCapabilities` reads `models.availableModels` when present and\n // otherwise derives the list from the `model` configOption (Kimi), so a\n // host caches a model id + label for either advertisement style.\n const observed = modelsFromCapabilities(event.runtimeCapabilities);\n if (observed.length > 0) models = observed;\n });\n try {\n // `session/new` triggers the runtime-capabilities notification\n // synchronously, so `models` is populated by the time this resolves.\n await this.client.startThread();\n return models;\n } finally {\n unsubscribe();\n }\n }\n\n async close(): Promise<void> {\n this.denyApprovals();\n this.rejectTools();\n await this.client.close();\n }\n}\n","// Per-agent quirks live in a registered strategy table, never as inline\n// `if (agentId === ...)` branches in the normalizer or client (KTD-A2). Adding a\n// 5th ACP agent is a new table entry — zero normalizer edits.\n//\n// A strategy carries three things:\n// • discovery — how to probe whether the CLI is installed + ACP-capable;\n// • spawn — the command + args that launch it in ACP stdio mode;\n// • quirks — normalization behavior toggles the normalizer READS\n// (e.g. whether agent \"thought\" chunks surface as messages,\n// where the thread title comes from).\n\nexport type LocalAcpProbeResult = {\n stdout?: string | Buffer;\n stderr?: string | Buffer;\n};\n\nexport type LocalAcpAgentProbe = (\n command: string,\n args: string[]\n) => Promise<LocalAcpProbeResult>;\n\n/** How a strategy decides it is installed + ACP-capable on this machine. */\nexport type AcpDiscoveryProbe = {\n /** Args that print a version (probed first; failure = not installed). */\n versionArgs: string[];\n /** Args probed to confirm ACP support. When `helpMatches` is set the OUTPUT\n * must match it; when omitted, a SUCCESSFUL probe (exit 0) is itself the\n * signal — for args that are an ACP subcommand whose mere existence proves\n * capability (e.g. `kimi acp --help`). */\n helpArgs: string[];\n /** Regex the help/usage output must match for the agent to count as\n * ACP-capable. OMIT to rely on the help probe's EXIT CODE instead — more\n * robust than parsing help prose, which drifts across CLI versions. */\n helpMatches?: RegExp;\n /** Bare command name tried first. */\n command: string;\n /** Additional candidate command paths (Homebrew prefixes, `~/.<agent>/bin`, …). */\n fallbackCommands?: string[];\n};\n\n/** Launch invocation: how to spawn the CLI in ACP stdio server mode. */\nexport type AcpSpawnSpec = {\n /** Command to run (resolved against the discovered candidate at spawn time). */\n command: string;\n /** Args that put the CLI into ACP stdio server mode (e.g. `[\"--acp\"]`). */\n args: string[];\n /** Extra env to set when launching (e.g. Gemini workspace-trust). */\n env?: Record<string, string>;\n /** Extra args appended only when missing (e.g. Gemini `--skip-trust`). */\n ensureArgs?: string[];\n};\n\n/**\n * Normalization quirks the normalizer reads. NO agent-id literal ever appears\n * in the normalizer — it reads these fields off the strategy it was constructed\n * with. A synthetic strategy with different quirk values flows through the\n * normalizer with zero normalizer changes (asserted in tests).\n */\nexport type AcpAgentQuirks = {\n /**\n * Whether agent \"thought\"/reasoning chunks surface as assistant messages.\n * Qwen sets this false (its thoughts are noisy scaffolding); others true.\n */\n surfaceThoughts: boolean;\n /**\n * Where the auto-generated thread title comes from:\n * • \"topic-update\" — a `tool_call` titled `Update topic to: \"…\"` (Gemini/Kimi/Qwen);\n * • \"session-summary\" — a vendor `session_summary_generated` update (Grok);\n * • \"both\" — recognize either.\n */\n titleFrom: \"topic-update\" | \"session-summary\" | \"both\";\n /** Vendor notification methods routed through the same session/update path. */\n vendorNotificationMethods?: string[];\n};\n\nexport type AcpAgentStrategy = {\n /** Strategy id, also the registry id (`gemini`, `grok`, `kimi`, `qwen`, …). */\n id: string;\n /** Neutral backend id (`acp:<id>`) used as the thread/session correlation key. */\n backendId: string;\n displayName: string;\n authors: string[];\n license?: string;\n repositoryUrl?: string;\n discoveryProbe: AcpDiscoveryProbe;\n spawn: AcpSpawnSpec;\n quirks: AcpAgentQuirks;\n};\n\n/** Build the neutral backend id for a registry id. */\nexport function buildAcpBackendId(registryId: string): string {\n return `acp:${registryId}`;\n}\n\nconst DEFAULT_QUIRKS: AcpAgentQuirks = {\n surfaceThoughts: true,\n titleFrom: \"topic-update\"\n};\n\n/** Quirks for an unknown/synthetic strategy default to the common case. */\nexport function defaultQuirks(overrides: Partial<AcpAgentQuirks> = {}): AcpAgentQuirks {\n return { ...DEFAULT_QUIRKS, ...overrides };\n}\n","import { buildAcpBackendId, defaultQuirks, type AcpAgentStrategy } from \"./strategy-types\";\n\nexport const geminiStrategy: AcpAgentStrategy = {\n id: \"gemini\",\n backendId: buildAcpBackendId(\"gemini\"),\n displayName: \"Gemini CLI\",\n authors: [\"Google\"],\n discoveryProbe: {\n command: \"gemini\",\n versionArgs: [\"--version\"],\n helpArgs: [\"--help\"],\n helpMatches: /(^|\\s)--acp(\\s|,|$)/\n },\n spawn: {\n command: \"gemini\",\n args: [\"--acp\"],\n // Gemini refuses to operate without workspace trust; matching PwrAgnt's\n // launch-descriptor normalization, append --skip-trust + set the env flag.\n ensureArgs: [\"--skip-trust\"],\n env: { GEMINI_CLI_TRUST_WORKSPACE: \"true\" }\n },\n quirks: defaultQuirks({ surfaceThoughts: true, titleFrom: \"topic-update\" })\n};\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { buildAcpBackendId, defaultQuirks, type AcpAgentStrategy } from \"./strategy-types\";\n\nexport const grokStrategy: AcpAgentStrategy = {\n id: \"grok\",\n backendId: buildAcpBackendId(\"grok\"),\n displayName: \"Grok\",\n authors: [\"xAI\"],\n discoveryProbe: {\n command: \"grok\",\n versionArgs: [\"--version\"],\n helpArgs: [\"agent\", \"stdio\", \"--help\"],\n helpMatches: /Run the agent over stdio/i,\n fallbackCommands: [\n path.join(homedir(), \".grok\", \"bin\", \"grok\"),\n \"/opt/homebrew/bin/grok\",\n \"/usr/local/bin/grok\"\n ]\n },\n spawn: {\n command: \"grok\",\n args: [\"agent\", \"stdio\"]\n },\n // Grok auto-generates the thread title via its vendor notification\n // `_x.ai/session_notification` carrying `session_summary_generated`.\n quirks: defaultQuirks({\n surfaceThoughts: true,\n titleFrom: \"session-summary\",\n vendorNotificationMethods: [\"_x.ai/session_notification\"]\n })\n};\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { buildAcpBackendId, defaultQuirks, type AcpAgentStrategy } from \"./strategy-types\";\n\nexport const kimiStrategy: AcpAgentStrategy = {\n id: \"kimi\",\n backendId: buildAcpBackendId(\"kimi\"),\n displayName: \"Kimi Code CLI\",\n authors: [\"Moonshot AI\"],\n discoveryProbe: {\n command: \"kimi\",\n versionArgs: [\"--version\"],\n // Capability signal is the EXIT CODE of `kimi acp --help`, NOT its prose.\n // kimi's commander CLI exits non-zero for an unknown subcommand, so a\n // zero-exit proves the `acp` subcommand exists. No `helpMatches`: the help\n // wording has already drifted across kimi versions (0.11.0 prints \"Agent\n // Client Protocol (ACP) server over stdio\"), so matching it is fragile.\n helpArgs: [\"acp\", \"--help\"],\n // The official Kimi Code installer drops a standalone binary at\n // ~/.kimi-code/bin/kimi and does NOT add it to PATH — so a Finder-launched\n // app misses it without this fallback (mirrors grok/qwen).\n fallbackCommands: [\n path.join(homedir(), \".kimi-code\", \"bin\", \"kimi\"),\n \"/opt/homebrew/bin/kimi\",\n \"/usr/local/bin/kimi\"\n ]\n },\n spawn: {\n command: \"kimi\",\n args: [\"acp\"]\n },\n quirks: defaultQuirks({ surfaceThoughts: true, titleFrom: \"topic-update\" })\n};\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { buildAcpBackendId, defaultQuirks, type AcpAgentStrategy } from \"./strategy-types\";\n\nexport const qwenStrategy: AcpAgentStrategy = {\n id: \"qwen\",\n backendId: buildAcpBackendId(\"qwen\"),\n displayName: \"Qwen Code\",\n authors: [\"Qwen Team\"],\n license: \"Apache-2.0\",\n repositoryUrl: \"https://github.com/QwenLM/qwen-code\",\n discoveryProbe: {\n command: \"qwen\",\n versionArgs: [\"--version\"],\n helpArgs: [\"--help\"],\n helpMatches: /(^|\\s)--acp(\\s|,|$)/,\n fallbackCommands: [\n path.join(homedir(), \".qwen\", \"bin\", \"qwen\"),\n \"/opt/homebrew/bin/qwen\",\n \"/usr/local/bin/qwen\"\n ]\n },\n spawn: {\n command: \"qwen\",\n args: [\"--acp\"]\n },\n // Qwen's thought chunks are noisy internal scaffolding — suppress them.\n quirks: defaultQuirks({ surfaceThoughts: false, titleFrom: \"topic-update\" })\n};\n","// The strategy table. The four built-ins do not require the registry — the\n// registry (discovery/acp-registry.ts) is the EXTENSION path. Adding a 5th\n// agent is a new entry here, with zero normalizer/client edits.\n\nimport type { AcpAgentStrategy } from \"./strategy-types\";\nimport { geminiStrategy } from \"./gemini\";\nimport { grokStrategy } from \"./grok\";\nimport { kimiStrategy } from \"./kimi\";\nimport { qwenStrategy } from \"./qwen\";\n\nexport { geminiStrategy } from \"./gemini\";\nexport { grokStrategy } from \"./grok\";\nexport { kimiStrategy } from \"./kimi\";\nexport { qwenStrategy } from \"./qwen\";\n\nexport const BUILT_IN_ACP_STRATEGIES: readonly AcpAgentStrategy[] = [\n geminiStrategy,\n kimiStrategy,\n grokStrategy,\n qwenStrategy\n];\n\n/** Index a list of strategies by id (built-ins by default). */\nexport function buildStrategyTable(\n strategies: readonly AcpAgentStrategy[] = BUILT_IN_ACP_STRATEGIES\n): Map<string, AcpAgentStrategy> {\n const table = new Map<string, AcpAgentStrategy>();\n for (const strategy of strategies) {\n table.set(strategy.id, strategy);\n }\n return table;\n}\n\n/** Look up a strategy by its registry id, falling back to the built-in table. */\nexport function strategyById(\n id: string,\n table: Map<string, AcpAgentStrategy> = buildStrategyTable()\n): AcpAgentStrategy | undefined {\n return table.get(id);\n}\n\n/** Look up a strategy by its neutral backend id (`acp:<id>`). */\nexport function strategyByBackendId(\n backendId: string,\n strategies: readonly AcpAgentStrategy[] = BUILT_IN_ACP_STRATEGIES\n): AcpAgentStrategy | undefined {\n return strategies.find((strategy) => strategy.backendId === backendId);\n}\n","// Probe which ACP CLIs are installed locally. STRATEGY-DRIVEN: iterates the\n// strategy table and runs each strategy's `discoveryProbe`. Adding a 5th agent\n// (a new strategy entry) surfaces it through discovery with ZERO changes here.\n//\n// Two granularities:\n// • `discoverLocalAcpAgentInstances` — returns EVERY installed instance of\n// each agent (each executable on `PATH` + the strategy's fallback paths +\n// an optional override that passes the probe), with its parsed version and\n// where it was found. A host UI can list them all and let the user pick.\n// Hosts that opt in can also receive detected candidates rejected by the\n// probe, so they can explain why a known CLI cannot be used.\n// • `discoverLocalAcpAgents` — the original first-match-per-agent view, kept\n// for back-compat. Implemented on top of the instance view.\n//\n// Ported from PwrAgnt acp-local-discovery.ts, generalized so the per-agent probe\n// details live in the strategy, not inline branches.\n\nimport { execFile as execFileCallback } from \"node:child_process\";\nimport { readdirSync, realpathSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport {\n createCommandInvocation,\n prependCommandDirToPath\n} from \"@pwrdrvr/agent-transport\";\nimport { BUILT_IN_ACP_STRATEGIES } from \"../strategies/index\";\nimport type {\n AcpAgentStrategy,\n AcpAgentStrategy as Strategy,\n LocalAcpAgentProbe,\n LocalAcpProbeResult\n} from \"../strategies/strategy-types\";\n\nconst execFile = promisify(execFileCallback);\n\nexport type { LocalAcpAgentProbe, LocalAcpProbeResult } from \"../strategies/strategy-types\";\n\n/** How a discovered instance's executable path was located. */\nexport type AcpAgentInstanceSource = \"override\" | \"path\" | \"fallback\";\n\n/** One installed executable of an agent that passed the probe. */\nexport type DiscoveredAcpAgentInstance = {\n /** Resolved command/path that passed the probe. */\n command: string;\n /** Parsed CLI version, when the version probe yielded one. */\n version?: string;\n /** Where this candidate came from (user override, `PATH`, or a fallback path). */\n source: AcpAgentInstanceSource;\n};\n\n/** A detected executable that did not satisfy a strategy's discovery probe.\n * It is diagnostic-only: hosts must never use it to launch an ACP session. */\nexport type RejectedAcpAgentInstance = {\n command: string;\n /** Parsed from successful `--version` output when available. */\n version?: string;\n source: AcpAgentInstanceSource;\n reason: \"version-probe-failed\" | \"acp-probe-failed\" | \"acp-help-mismatch\";\n};\n\n/** Every installed instance of one agent found on this machine. */\nexport type DiscoveredAcpAgentGroup = {\n strategyId: string;\n backendId: string;\n name: string;\n /** Spawn args that put it into ACP stdio mode (same for every instance). */\n args: string[];\n /** Extra env to set at launch (same for every instance). */\n env: Record<string, string>;\n /** All instances that passed the probe, in candidate order (override → PATH → fallback). */\n instances: DiscoveredAcpAgentInstance[];\n /** Detected candidates that failed the version or ACP-capability probe. Only\n * populated when `includeRejectedCandidates` is enabled. */\n rejectedInstances?: RejectedAcpAgentInstance[];\n discoveredAt: number;\n};\n\nexport type DiscoveredAcpAgent = {\n strategyId: string;\n backendId: string;\n name: string;\n version?: string;\n /** Resolved command that passed the probe (may be a fallback path). */\n command: string;\n /** Spawn args that put it into ACP stdio mode. */\n args: string[];\n /** Extra env to set at launch. */\n env: Record<string, string>;\n discoveredAt: number;\n};\n\n/** Lists every executable named `command` across the dirs in `env.PATH`,\n * in `PATH` order (the `which -a` view). */\nexport type AcpPathExecutableLister = (\n command: string,\n env: NodeJS.ProcessEnv\n) => string[];\n\nexport type LocalAcpDiscoveryOptions = {\n probe?: LocalAcpAgentProbe;\n now?: () => number;\n /** Strategy table to probe (built-ins by default). */\n strategies?: readonly AcpAgentStrategy[];\n /** Per-strategy command override (tried before the strategy's own candidates). */\n overrides?: Record<string, string>;\n /** Env used both for PATH enumeration and (by the default probe) for spawns. */\n env?: NodeJS.ProcessEnv;\n /** Injectable `PATH` executable lister (real-fs scan by default). */\n listExecutables?: AcpPathExecutableLister;\n /** Include candidates known to exist but rejected by a discovery probe.\n * Defaults false to preserve the legacy installed-only result. */\n includeRejectedCandidates?: boolean;\n};\n\n/**\n * Discover every installed instance of each agent (all `PATH` matches +\n * fallbacks + override that pass the probe), grouped per strategy. Groups with\n * no passing instance are omitted unless `includeRejectedCandidates` is true\n * and a detected candidate failed a probe.\n */\nexport async function discoverLocalAcpAgentInstances(\n options: LocalAcpDiscoveryOptions = {}\n): Promise<DiscoveredAcpAgentGroup[]> {\n const strategies = options.strategies ?? BUILT_IN_ACP_STRATEGIES;\n const env = options.env ?? process.env;\n const probe = options.probe ?? makeDefaultProbe(env);\n const listExecutables = options.listExecutables ?? defaultListExecutables;\n const now = options.now ?? Date.now;\n const groups = await Promise.all(\n strategies.map((strategy) =>\n discoverStrategyInstances(\n strategy,\n probe,\n now,\n env,\n listExecutables,\n options.overrides?.[strategy.id],\n options.includeRejectedCandidates === true\n )\n )\n );\n return groups.filter((group): group is DiscoveredAcpAgentGroup => group !== undefined);\n}\n\n/**\n * First-match-per-agent discovery (legacy view). Returns at most one record per\n * agent — the first instance that passed the probe in candidate order.\n */\nexport async function discoverLocalAcpAgents(\n options: LocalAcpDiscoveryOptions = {}\n): Promise<DiscoveredAcpAgent[]> {\n const groups = await discoverLocalAcpAgentInstances(options);\n return groups.flatMap((group) => {\n const first = group.instances[0];\n if (first === undefined) return [];\n const agent: DiscoveredAcpAgent = {\n strategyId: group.strategyId,\n backendId: group.backendId,\n name: group.name,\n command: first.command,\n args: group.args,\n env: group.env,\n discoveredAt: group.discoveredAt\n };\n if (first.version !== undefined) agent.version = first.version;\n return [agent];\n });\n}\n\nasync function discoverStrategyInstances(\n strategy: Strategy,\n probe: LocalAcpAgentProbe,\n now: () => number,\n env: NodeJS.ProcessEnv,\n listExecutables: AcpPathExecutableLister,\n override?: string,\n includeRejectedCandidates = false\n): Promise<DiscoveredAcpAgentGroup | undefined> {\n const candidates = candidateCommands(strategy, env, listExecutables, override);\n const instances: DiscoveredAcpAgentInstance[] = [];\n const rejectedInstances: RejectedAcpAgentInstance[] = [];\n for (const candidate of candidates) {\n const [versionResult, helpResult] = await Promise.all([\n runProbe(probe, candidate.command, strategy.discoveryProbe.versionArgs),\n runProbe(probe, candidate.command, strategy.discoveryProbe.helpArgs)\n ]);\n const version = versionResult ? parseCliVersion(resultText(versionResult)) : undefined;\n if (!versionResult || !helpResult) {\n if (includeRejectedCandidates && candidate.detected) {\n const rejected: RejectedAcpAgentInstance = {\n command: candidate.command,\n source: candidate.source,\n reason: versionResult ? \"acp-probe-failed\" : \"version-probe-failed\"\n };\n if (version !== undefined) rejected.version = version;\n rejectedInstances.push(rejected);\n }\n continue;\n }\n // A strategy with no `helpMatches` relies on the EXIT CODE: the help probe\n // succeeding (enforced just above — a non-zero exit makes `runProbe` return\n // undefined) is itself the ACP-capability signal. Only when a regex is set\n // do we additionally parse the (drift-prone) help text.\n if (\n strategy.discoveryProbe.helpMatches !== undefined &&\n !strategy.discoveryProbe.helpMatches.test(resultText(helpResult))\n ) {\n if (includeRejectedCandidates && candidate.detected) {\n const rejected: RejectedAcpAgentInstance = {\n command: candidate.command,\n source: candidate.source,\n reason: \"acp-help-mismatch\"\n };\n if (version !== undefined) rejected.version = version;\n rejectedInstances.push(rejected);\n }\n continue;\n }\n const instance: DiscoveredAcpAgentInstance = {\n command: candidate.command,\n source: candidate.source\n };\n if (version !== undefined) instance.version = version;\n instances.push(instance);\n }\n if (instances.length === 0 && rejectedInstances.length === 0) {\n return undefined;\n }\n return {\n strategyId: strategy.id,\n backendId: strategy.backendId,\n name: strategy.displayName,\n args: ensureArgs(strategy.spawn.args, strategy.spawn.ensureArgs),\n env: strategy.spawn.env ?? {},\n instances,\n ...(rejectedInstances.length > 0 ? { rejectedInstances } : {}),\n discoveredAt: now()\n };\n}\n\ntype Candidate = {\n command: string;\n source: AcpAgentInstanceSource;\n /** True only when command enumeration found a concrete executable path. */\n detected: boolean;\n};\n\n/** Build the de-duplicated candidate list for a strategy: override first, then\n * every `PATH` match of the bare command (or the bare command itself when the\n * lister finds none, so `execFile`'s own `PATH` resolution still gets a shot),\n * then the strategy's fallback paths. Duplicates (by resolved real path) are\n * collapsed so the same physical binary isn't listed twice. */\nfunction candidateCommands(\n strategy: Strategy,\n env: NodeJS.ProcessEnv,\n listExecutables: AcpPathExecutableLister,\n override?: string\n): Candidate[] {\n const out: Candidate[] = [];\n const seen = new Set<string>();\n const push = (\n command: string,\n source: AcpAgentInstanceSource,\n detected: boolean\n ): void => {\n const trimmed = command.trim();\n if (trimmed.length === 0) return;\n const key = canonicalize(trimmed);\n if (seen.has(key)) return;\n seen.add(key);\n out.push({ command: trimmed, source, detected });\n };\n\n if (override && override.trim().length > 0) {\n push(override, \"override\", isExecutableFile(override));\n }\n const pathMatches = listExecutables(strategy.discoveryProbe.command, env);\n if (pathMatches.length > 0) {\n for (const match of pathMatches) push(match, \"path\", true);\n } else {\n // No PATH hit (or an injected no-op lister): keep the bare command so\n // `execFile` resolves it via its own PATH and scripted-probe tests match.\n push(strategy.discoveryProbe.command, \"path\", false);\n }\n for (const fallback of strategy.discoveryProbe.fallbackCommands ?? []) {\n push(fallback, \"fallback\", isExecutableFile(fallback));\n }\n return out;\n}\n\nfunction isExecutableFile(command: string): boolean {\n try {\n const stat = statSync(command);\n return stat.isFile() && (process.platform === \"win32\" || (stat.mode & 0o111) !== 0);\n } catch {\n return false;\n }\n}\n\n/** Resolve symlinks so the same binary reached via two PATH entries dedupes. */\nfunction canonicalize(command: string): string {\n if (!path.isAbsolute(command)) {\n return process.platform === \"win32\" ? command.toLowerCase() : command;\n }\n try {\n const canonical = realpathSync(command);\n return process.platform === \"win32\" ? canonical.toLowerCase() : canonical;\n } catch {\n return process.platform === \"win32\" ? command.toLowerCase() : command;\n }\n}\n\n/** Default executable lister: scan `env.PATH` AND well-known version-manager /\n * install dirs for an executable file named `command`. On Windows, expand\n * each PATH entry using PATHEXT and return the actual .COM/.EXE/.BAT/.CMD\n * candidates rather than a bare command that `execFile` cannot launch.\n *\n * Scanning beyond `PATH` is deliberate: a desktop app launched from Finder /\n * Dock inherits launchd's minimal `PATH`, and login-shell hydration can't\n * reliably recover a version-manager `PATH` (nvm is often lazy-loaded and\n * pins a different node version than the one the agent CLI is installed\n * under). So an `npm i -g qwen` under nvm would be invisible. We find it by\n * scanning the version-manager bin dirs directly. */\nfunction defaultListExecutables(command: string, env: NodeJS.ProcessEnv): string[] {\n // A bare command name only — never enumerate when a path was passed.\n if (command.includes(\"/\") || command.includes(\"\\\\\")) return [];\n const found: string[] = [];\n const seenDir = new Set<string>();\n for (const dir of discoveryDirs(env)) {\n const normalizedDir = normalizePathEntry(dir);\n const dirKey = process.platform === \"win32\" ? normalizedDir.toLowerCase() : normalizedDir;\n if (normalizedDir.length === 0 || seenDir.has(dirKey)) continue;\n seenDir.add(dirKey);\n for (const commandName of executableCommandNames(command, env)) {\n const candidate = path.join(normalizedDir, commandName);\n try {\n const stat = statSync(candidate);\n if (stat.isFile() && (process.platform === \"win32\" || (stat.mode & 0o111) !== 0)) {\n found.push(candidate);\n }\n } catch {\n // Not in this dir; keep scanning.\n }\n }\n }\n return found;\n}\n\nfunction executableCommandNames(command: string, env: NodeJS.ProcessEnv): string[] {\n if (process.platform !== \"win32\") return [command];\n const extensions = (readWindowsEnv(env, \"PATHEXT\")?.trim() || \".COM;.EXE;.BAT;.CMD\")\n .split(\";\")\n .map((extension) => extension.trim())\n .filter(Boolean)\n .map((extension) => extension.startsWith(\".\") ? extension : `.${extension}`);\n const commandExtension = path.win32.extname(command);\n if (\n commandExtension.length > 0 &&\n extensions.some((extension) => extension.toLowerCase() === commandExtension.toLowerCase())\n ) {\n return [command];\n }\n return extensions.map((extension) => `${command}${extension}`);\n}\n\nfunction readWindowsEnv(env: NodeJS.ProcessEnv, name: string): string | undefined {\n const key = Object.keys(env).find((candidate) => candidate.toLowerCase() === name.toLowerCase());\n return key ? env[key] : undefined;\n}\n\nfunction normalizePathEntry(entry: string): string {\n const trimmed = entry.trim();\n const quoted = trimmed.match(/^\"(.*)\"$/);\n return quoted?.[1] ?? trimmed;\n}\n\n/** Dirs to scan for agent executables: every `env.PATH` entry first, then the\n * well-known version-manager / package-manager bin dirs a GUI app's `PATH`\n * usually omits. */\nfunction discoveryDirs(env: NodeJS.ProcessEnv): string[] {\n const pathValue = process.platform === \"win32\"\n ? readWindowsEnv(env, \"PATH\") ?? \"\"\n : env.PATH ?? \"\";\n const pathDirs = pathValue.split(path.delimiter);\n return process.platform === \"win32\"\n ? pathDirs\n : [...pathDirs, ...wellKnownAgentBinDirs(homedir())];\n}\n\n/** Well-known bin dirs where a CLI installed via a node/JS version manager or\n * a per-user package manager lives — even when it isn't on a GUI app's `PATH`.\n * Exported for testing; `home` defaults to the user's home dir. */\nexport function wellKnownAgentBinDirs(home: string = homedir()): string[] {\n return [\n // Every installed nvm node version's bin (the agent may be under any one).\n ...nvmNodeBinDirs(home),\n // Other version / package managers.\n path.join(home, \".volta\", \"bin\"),\n path.join(home, \".bun\", \"bin\"),\n path.join(home, \".asdf\", \"shims\"),\n path.join(home, \".deno\", \"bin\"),\n path.join(home, \".local\", \"bin\"),\n path.join(home, \".npm-global\", \"bin\"),\n // Common system install prefixes.\n \"/opt/homebrew/bin\",\n \"/usr/local/bin\"\n ];\n}\n\n/** Every `~/.nvm/versions/node/<v>/bin` dir, newest-first so the most recent\n * node version's install is tried before older ones. Empty when nvm absent. */\nfunction nvmNodeBinDirs(home: string): string[] {\n const base = path.join(home, \".nvm\", \"versions\", \"node\");\n try {\n return readdirSync(base)\n .sort()\n .reverse()\n .map((version) => path.join(base, version, \"bin\"));\n } catch {\n return [];\n }\n}\n\nfunction ensureArgs(args: string[], ensure: string[] | undefined): string[] {\n if (!ensure || ensure.length === 0) {\n return args;\n }\n const result = [...args];\n for (const arg of ensure) {\n if (!result.includes(arg)) result.push(arg);\n }\n return result;\n}\n\nfunction makeDefaultProbe(env: NodeJS.ProcessEnv): LocalAcpAgentProbe {\n return async (command: string, args: string[]): Promise<LocalAcpProbeResult> => {\n const launchEnv = prependCommandDirToPath(command, env);\n const invocation = createCommandInvocation({ command, args, env: launchEnv });\n return await execFile(invocation.command, invocation.args, {\n timeout: 5_000,\n maxBuffer: 1024 * 1024,\n // Prepend the candidate's own dir so a node-script CLI (e.g. an nvm-\n // installed `qwen`) finds its sibling `node` during the probe.\n env: launchEnv,\n windowsVerbatimArguments: invocation.windowsVerbatimArguments\n });\n };\n}\n\nasync function runProbe(\n probe: LocalAcpAgentProbe,\n command: string,\n args: string[]\n): Promise<LocalAcpProbeResult | undefined> {\n try {\n return await probe(command, args);\n } catch {\n return undefined;\n }\n}\n\nfunction resultText(result: LocalAcpProbeResult): string {\n return [result.stdout, result.stderr]\n .flatMap((value) => (value === undefined ? [] : [value]))\n .map((value) => (Buffer.isBuffer(value) ? value.toString(\"utf8\") : value))\n .join(\"\\n\");\n}\n\nfunction parseCliVersion(output: string): string | undefined {\n const trimmed = output.trim();\n if (!trimmed) {\n return undefined;\n }\n return trimmed.match(/\\d+\\.\\d+\\.\\d+(?:[-+][\\w.-]+)?/)?.[0] ?? trimmed;\n}\n","// Gate registry-sourced ACP agents. Rejects the GPL family, unpinned npx/uvx\n// packages, and unpinned binary archive hosts; `BANNED_ACP_REGISTRY_IDS` keeps\n// `codex-acp` out (PwrDrvr talks to Codex through the first-class Codex adapter,\n// not as an ACP duplicate).\n//\n// Ported from PwrAgnt acp-agent-allowlist.ts, with @pwragent/shared types\n// inlined.\n\nimport type {\n AcpAllowlistDecision,\n AcpDistributionKind,\n AcpRegistryAgent,\n AcpRegistryDistribution\n} from \"./acp-registry-types\";\n\nexport type AcpAgentAllowlistRule = {\n id: string;\n registryId: string;\n versions?: string[];\n distributionKinds?: AcpDistributionKind[];\n allowedPackageNames?: string[];\n allowedArchiveHosts?: string[];\n allowUnverifiedBinary?: boolean;\n allowGplFamilyLicense?: boolean;\n};\n\nexport const BANNED_ACP_REGISTRY_IDS = new Set([\"codex-acp\"]);\n\nexport const DEFAULT_ACP_AGENT_ALLOWLIST: AcpAgentAllowlistRule[] = [\n { id: \"local-grok-cli\", registryId: \"grok\", distributionKinds: [\"local\"] },\n { id: \"local-qwen-code-cli\", registryId: \"qwen\", distributionKinds: [\"local\"] }\n];\n\nexport class AcpAgentAllowlist {\n constructor(private readonly rules: AcpAgentAllowlistRule[]) {}\n\n evaluate(agent: AcpRegistryAgent): AcpAllowlistDecision {\n if (isBannedAcpRegistryId(agent.id)) {\n return { allowed: false, reason: \"banned\" };\n }\n const matchingRules = this.rules.filter((rule) => rule.registryId === agent.id);\n if (matchingRules.length === 0) {\n return { allowed: false, reason: \"not-allowlisted\" };\n }\n for (const rule of matchingRules) {\n const denial = evaluateRule(rule, agent);\n if (!denial) {\n return {\n allowed: true,\n ruleId: rule.id,\n unverifiedBinaryAllowed: rule.allowUnverifiedBinary === true\n };\n }\n }\n return { allowed: false, reason: \"allowlist-rule-mismatch\" };\n }\n\n evaluateDistribution(\n agent: AcpRegistryAgent,\n distribution: AcpRegistryDistribution\n ): AcpAllowlistDecision {\n if (isBannedAcpRegistryId(agent.id)) {\n return { allowed: false, reason: \"banned\" };\n }\n const matchingRules = this.rules.filter((rule) => rule.registryId === agent.id);\n if (matchingRules.length === 0) {\n return { allowed: false, reason: \"not-allowlisted\" };\n }\n for (const rule of matchingRules) {\n const denial = evaluateDistributionRule(rule, agent, distribution);\n if (!denial) {\n return {\n allowed: true,\n ruleId: rule.id,\n unverifiedBinaryAllowed: rule.allowUnverifiedBinary === true\n };\n }\n }\n return { allowed: false, reason: \"allowlist-rule-mismatch\" };\n }\n}\n\nexport const defaultAcpAgentAllowlist = new AcpAgentAllowlist(\n DEFAULT_ACP_AGENT_ALLOWLIST\n);\n\nexport function isBannedAcpRegistryId(registryId: string): boolean {\n return BANNED_ACP_REGISTRY_IDS.has(registryId);\n}\n\nfunction evaluateRule(\n rule: AcpAgentAllowlistRule,\n agent: AcpRegistryAgent\n): string | undefined {\n if (rule.versions && (!agent.version || !rule.versions.includes(agent.version))) {\n return \"version-not-allowed\";\n }\n if (isGplFamilyLicense(agent.license) && !rule.allowGplFamilyLicense) {\n return \"license-not-allowed\";\n }\n let distributionDeniedBySource = false;\n for (const distribution of agent.distributions) {\n const denial = evaluateDistributionRule(rule, agent, distribution, {\n skipAgentChecks: true\n });\n if (!denial) {\n return undefined;\n }\n if (denial === \"distribution-source-not-allowed\") {\n distributionDeniedBySource = true;\n }\n }\n return distributionDeniedBySource\n ? \"distribution-source-not-allowed\"\n : \"distribution-not-allowed\";\n}\n\nfunction evaluateDistributionRule(\n rule: AcpAgentAllowlistRule,\n agent: AcpRegistryAgent,\n distribution: AcpRegistryDistribution,\n options: { skipAgentChecks?: boolean } = {}\n): string | undefined {\n if (\n !options.skipAgentChecks &&\n rule.versions &&\n (!agent.version || !rule.versions.includes(agent.version))\n ) {\n return \"version-not-allowed\";\n }\n if (\n !options.skipAgentChecks &&\n isGplFamilyLicense(agent.license) &&\n !rule.allowGplFamilyLicense\n ) {\n return \"license-not-allowed\";\n }\n if (!distributionAllowedByKind(rule, distribution)) {\n return \"distribution-not-allowed\";\n }\n if (!distributionSourceAllowed(rule, distribution)) {\n return \"distribution-source-not-allowed\";\n }\n return undefined;\n}\n\nfunction distributionAllowedByKind(\n rule: AcpAgentAllowlistRule,\n distribution: AcpRegistryDistribution\n): boolean {\n return !rule.distributionKinds || rule.distributionKinds.includes(distribution.kind);\n}\n\nfunction distributionSourceAllowed(\n rule: AcpAgentAllowlistRule,\n distribution: AcpRegistryDistribution\n): boolean {\n if (distribution.kind === \"npx\" || distribution.kind === \"uvx\") {\n return (\n !rule.allowedPackageNames ||\n rule.allowedPackageNames.includes(distribution.packageName)\n );\n }\n if (distribution.kind !== \"binary\") {\n return false;\n }\n if (!rule.allowedArchiveHosts) {\n return true;\n }\n try {\n return rule.allowedArchiveHosts.includes(new URL(distribution.archiveUrl).host);\n } catch {\n return false;\n }\n}\n\nfunction isGplFamilyLicense(license: string | undefined): boolean {\n return /\\b(?:GPL|AGPL|LGPL)\\b/i.test(license ?? \"\");\n}\n","// Registry types for the ACP extension path. The four built-in strategies do\n// NOT require the registry; this is how a host adds more ACP agents from the\n// public Agent Client Protocol registry, gated by the allowlist.\n//\n// Ported from PwrAgnt acp-registry-types.ts, with @pwragent/shared types\n// inlined as neutral local types.\n\nimport { buildAcpBackendId } from \"../strategies/strategy-types\";\n\nexport const ACP_REGISTRY_URL =\n \"https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json\";\n\nexport type AcpDistributionKind = \"npx\" | \"uvx\" | \"binary\" | \"local\";\n\nexport type AcpRegistryDistributionEnv = Record<string, string>;\n\nexport type AcpPackageDistribution = {\n kind: \"npx\" | \"uvx\";\n packageName: string;\n args: string[];\n env: AcpRegistryDistributionEnv;\n};\n\nexport type AcpBinaryPlatformDistribution = {\n kind: \"binary\";\n platform: string;\n archiveUrl: string;\n command: string;\n args: string[];\n env: AcpRegistryDistributionEnv;\n checksum?: string;\n signatureUrl?: string;\n};\n\nexport type AcpRegistryDistribution =\n | AcpPackageDistribution\n | AcpBinaryPlatformDistribution;\n\nexport type AcpRegistryAuthMethod = \"agent-managed\" | \"terminal\" | \"unknown\";\n\nexport type AcpRegistryAuthDescriptor = {\n required: boolean;\n methods: AcpRegistryAuthMethod[];\n raw?: unknown;\n};\n\nexport type AcpRegistryAgent = {\n id: string;\n backendId: string;\n name: string;\n version?: string;\n description?: string;\n authors: string[];\n license?: string;\n repositoryUrl?: string;\n websiteUrl?: string;\n iconUrl?: string;\n distributions: AcpRegistryDistribution[];\n distributionKinds: AcpDistributionKind[];\n auth: AcpRegistryAuthDescriptor;\n raw: unknown;\n};\n\nexport type AcpVerificationStatus =\n | \"verified\"\n | \"unverified-allowed\"\n | \"unverified-blocked\"\n | \"not-applicable\";\n\nexport type AcpAllowlistDecision =\n | { allowed: true; ruleId: string; unverifiedBinaryAllowed: boolean }\n | { allowed: false; reason: string };\n\nexport type AcpRegistryAgentWithPolicy = AcpRegistryAgent & {\n allowlist: AcpAllowlistDecision;\n installable: boolean;\n unavailableReason?: string;\n verificationStatus: AcpVerificationStatus;\n};\n\nexport type AcpRegistrySnapshot = {\n fetchedAt: number;\n agents: AcpRegistryAgent[];\n raw: unknown;\n};\n\nexport { buildAcpBackendId };\n","// Fetch + normalize the public ACP registry and apply the allowlist policy.\n// The EXTENSION path for adding ACP agents beyond the four built-in strategies.\n//\n// Ported from PwrAgnt acp-registry-service.ts, with @pwragent/shared dropped.\n\nimport {\n ACP_REGISTRY_URL,\n buildAcpBackendId,\n type AcpAllowlistDecision,\n type AcpBinaryPlatformDistribution,\n type AcpPackageDistribution,\n type AcpRegistryAgent,\n type AcpRegistryAgentWithPolicy,\n type AcpRegistryAuthDescriptor,\n type AcpRegistryDistribution,\n type AcpRegistrySnapshot,\n type AcpVerificationStatus\n} from \"./acp-registry-types\";\nimport {\n AcpAgentAllowlist,\n defaultAcpAgentAllowlist\n} from \"./acp-agent-allowlist\";\n\nexport type AcpRegistryFetch = (\n input: string,\n init?: { headers?: Record<string, string> }\n) => Promise<{\n ok: boolean;\n status: number;\n statusText: string;\n json(): Promise<unknown>;\n}>;\n\nexport type AcpRegistryServiceOptions = {\n allowlist?: AcpAgentAllowlist;\n fetch?: AcpRegistryFetch;\n now?: () => number;\n registryUrl?: string;\n};\n\nexport type AcpDistributionPolicy = {\n allowlist: AcpAllowlistDecision;\n installable: boolean;\n verificationStatus: AcpVerificationStatus;\n unavailableReason?: string;\n};\n\nexport class AcpRegistryService {\n private readonly allowlist: AcpAgentAllowlist;\n private readonly fetcher: AcpRegistryFetch;\n private readonly now: () => number;\n private readonly registryUrl: string;\n\n constructor(options: AcpRegistryServiceOptions = {}) {\n this.allowlist = options.allowlist ?? defaultAcpAgentAllowlist;\n this.fetcher =\n options.fetch ??\n (async (input, init) => {\n const response = await globalThis.fetch(input, init);\n return {\n ok: response.ok,\n status: response.status,\n statusText: response.statusText,\n json: () => response.json() as Promise<unknown>\n };\n });\n this.now = options.now ?? Date.now;\n this.registryUrl = options.registryUrl ?? ACP_REGISTRY_URL;\n }\n\n async fetchRegistry(): Promise<AcpRegistrySnapshot> {\n const response = await this.fetcher(this.registryUrl, {\n headers: { accept: \"application/json\" }\n });\n if (!response.ok) {\n throw new Error(\n `ACP registry request failed: ${response.status} ${response.statusText}`\n );\n }\n const raw = await response.json();\n return { fetchedAt: this.now(), agents: normalizeRegistry(raw), raw };\n }\n\n applyAllowlist(snapshot: AcpRegistrySnapshot): AcpRegistryAgentWithPolicy[] {\n return snapshot.agents.map((agent) => {\n const allowlist = this.allowlist.evaluate(agent);\n const distributionPolicies = agent.distributions.map((distribution) =>\n this.evaluateDistribution(agent, distribution)\n );\n const installablePolicy = distributionPolicies.find((policy) => policy.installable);\n const firstBlockedAllowedPolicy = distributionPolicies.find(\n (policy) => policy.allowlist.allowed\n );\n const installable = Boolean(installablePolicy);\n const result: AcpRegistryAgentWithPolicy = {\n ...agent,\n allowlist,\n installable,\n verificationStatus:\n installablePolicy?.verificationStatus ??\n firstBlockedAllowedPolicy?.verificationStatus ??\n \"not-applicable\"\n };\n const unavailableReason = installable\n ? undefined\n : (firstBlockedAllowedPolicy?.unavailableReason ??\n (allowlist.allowed ? \"distribution-not-installable\" : allowlist.reason));\n if (unavailableReason !== undefined) result.unavailableReason = unavailableReason;\n return result;\n });\n }\n\n evaluateDistribution(\n agent: AcpRegistryAgent,\n distribution: AcpRegistryDistribution\n ): AcpDistributionPolicy {\n const allowlist = this.allowlist.evaluateDistribution(agent, distribution);\n return evaluateAcpDistributionPolicy(distribution, allowlist);\n }\n}\n\nexport function evaluateAcpDistributionPolicy(\n distribution: AcpRegistryDistribution,\n allowlist: AcpAllowlistDecision\n): AcpDistributionPolicy {\n if (!allowlist.allowed) {\n return {\n allowlist,\n installable: false,\n verificationStatus: \"not-applicable\",\n unavailableReason: allowlist.reason\n };\n }\n if (distribution.kind !== \"binary\") {\n return { allowlist, installable: true, verificationStatus: \"not-applicable\" };\n }\n if (distribution.checksum) {\n return { allowlist, installable: true, verificationStatus: \"verified\" };\n }\n return {\n allowlist,\n installable: allowlist.unverifiedBinaryAllowed,\n verificationStatus: allowlist.unverifiedBinaryAllowed\n ? \"unverified-allowed\"\n : \"unverified-blocked\",\n ...(allowlist.unverifiedBinaryAllowed\n ? {}\n : { unavailableReason: \"binary-integrity-metadata-missing\" })\n };\n}\n\nexport function normalizeRegistry(raw: unknown): AcpRegistryAgent[] {\n const record = asRecord(raw);\n const rawAgents = Array.isArray(record?.agents) ? record.agents : [];\n return rawAgents.flatMap((item) => {\n const agent = normalizeAgent(item);\n return agent ? [agent] : [];\n });\n}\n\nfunction normalizeAgent(raw: unknown): AcpRegistryAgent | undefined {\n const record = asRecord(raw);\n if (!record || typeof record.id !== \"string\" || typeof record.name !== \"string\") {\n return undefined;\n }\n const distributions = normalizeDistributions(record.distribution);\n if (distributions.length === 0) {\n return undefined;\n }\n const agent: AcpRegistryAgent = {\n id: record.id,\n backendId: buildAcpBackendId(record.id),\n name: record.name,\n authors: Array.isArray(record.authors)\n ? record.authors.filter((author): author is string => typeof author === \"string\")\n : [],\n distributions,\n distributionKinds: [...new Set(distributions.map((d) => d.kind))],\n auth: normalizeAuth(record.auth),\n raw\n };\n const version = stringValue(record.version);\n if (version !== undefined) agent.version = version;\n const description = stringValue(record.description);\n if (description !== undefined) agent.description = description;\n const license = stringValue(record.license);\n if (license !== undefined) agent.license = license;\n const repositoryUrl = stringValue(record.repository);\n if (repositoryUrl !== undefined) agent.repositoryUrl = repositoryUrl;\n const websiteUrl = stringValue(record.website);\n if (websiteUrl !== undefined) agent.websiteUrl = websiteUrl;\n const iconUrl = stringValue(record.icon);\n if (iconUrl !== undefined) agent.iconUrl = iconUrl;\n return agent;\n}\n\nfunction normalizeDistributions(raw: unknown): AcpRegistryDistribution[] {\n const record = asRecord(raw);\n if (!record) {\n return [];\n }\n const distributions: AcpRegistryDistribution[] = [];\n const npx = normalizePackageDistribution(\"npx\", record.npx);\n if (npx) distributions.push(npx);\n const uvx = normalizePackageDistribution(\"uvx\", record.uvx);\n if (uvx) distributions.push(uvx);\n const binaryRecord = asRecord(record.binary);\n if (binaryRecord) {\n for (const [platform, value] of Object.entries(binaryRecord)) {\n const binary = normalizeBinaryDistribution(platform, value);\n if (binary) distributions.push(binary);\n }\n }\n return distributions;\n}\n\nfunction normalizePackageDistribution(\n kind: \"npx\" | \"uvx\",\n raw: unknown\n): AcpPackageDistribution | undefined {\n const record = asRecord(raw);\n if (!record || typeof record.package !== \"string\") {\n return undefined;\n }\n return {\n kind,\n packageName: record.package,\n args: stringArray(record.args),\n env: stringRecord(record.env)\n };\n}\n\nfunction normalizeBinaryDistribution(\n platform: string,\n raw: unknown\n): AcpBinaryPlatformDistribution | undefined {\n const record = asRecord(raw);\n if (!record || typeof record.archive !== \"string\" || typeof record.cmd !== \"string\") {\n return undefined;\n }\n const distribution: AcpBinaryPlatformDistribution = {\n kind: \"binary\",\n platform,\n archiveUrl: record.archive,\n command: record.cmd,\n args: stringArray(record.args),\n env: stringRecord(record.env)\n };\n const checksum = stringValue(record.checksum) ?? stringValue(record.sha256);\n if (checksum !== undefined) distribution.checksum = checksum;\n const signatureUrl = stringValue(record.signature) ?? stringValue(record.signatureUrl);\n if (signatureUrl !== undefined) distribution.signatureUrl = signatureUrl;\n return distribution;\n}\n\nfunction normalizeAuth(raw: unknown): AcpRegistryAuthDescriptor {\n if (!raw) {\n return { required: false, methods: [] };\n }\n const record = asRecord(raw);\n if (!record) {\n return { required: true, methods: [\"unknown\"], raw };\n }\n const methods = stringArray(record.methods).map((method) =>\n method === \"agent-managed\" || method === \"terminal\" ? method : \"unknown\"\n );\n return {\n required: record.required === false ? false : true,\n methods: methods.length > 0 ? [...new Set(methods)] : [\"unknown\"],\n raw\n };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction stringArray(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === \"string\")\n : [];\n}\n\nfunction stringRecord(value: unknown): Record<string, string> {\n const record = asRecord(value);\n if (!record) {\n return {};\n }\n return Object.fromEntries(\n Object.entries(record).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\"\n )\n );\n}\n"],"mappings":"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","names":["noopLogger","path","path","noopLogger","protocolSessionId","threadId","asRecord","readString","path","noopLogger","errorMessage","noopLogger","noopLogger","homedir","path","path","homedir","homedir","path","path","homedir","homedir","path","createCommandInvocation","prependCommandDirToPath","path","homedir","prependCommandDirToPath","createCommandInvocation","asRecord"]}
1
+ {"version":3,"sources":["../src/acp-connection.ts","../src/acp-client.ts","../src/normalizer/acp-normalizer.ts","../src/normalizer/content.ts","../src/normalizer/tool-activity.ts","../src/normalizer/runtime-capabilities.ts","../src/mcp-server-config.ts","../src/acp-agent-client-pool.ts","../src/acp-oneshot-client.ts","../src/strategies/strategy-types.ts","../src/strategies/gemini.ts","../src/strategies/grok.ts","../src/strategies/kimi.ts","../src/strategies/qwen.ts","../src/strategies/index.ts","../src/discovery/acp-local-discovery.ts","../src/discovery/acp-agent-allowlist.ts","../src/discovery/acp-registry-types.ts","../src/discovery/acp-registry-service.ts"],"sourcesContent":["// ACP connection backed by the official `@agentclientprotocol/sdk`\n// library. Replaces our hand-rolled ACP wire layer (acp-stdio-transport.ts): the\n// library owns JSON-RPC framing, ndjson stdio, protocol-method dispatch, and\n// schema validation. We keep ownership of the things the library does NOT do —\n// spawning + process lifetime, discovery, the normalizer, and per-agent quirks.\n//\n// This implements the SAME `AcpJsonRpcTransport` seam the ACP clients already\n// drive (request / notify / onNotification / onRequest), so `AcpAgentClient`,\n// `AcpOneShotClient`, and the pool are unchanged — only the concrete connection\n// they're handed swaps. The generic `request(method, params)` calls map onto the\n// library's typed methods (with generic `request` / `notify` for non-standard\n// ones like `session/set_config_option`); the library's `Client` callbacks\n// (`sessionUpdate` / `extNotification` / `requestPermission`) bridge back out.\n\nimport { spawn } from \"node:child_process\";\nimport { Readable, Writable } from \"node:stream\";\nimport {\n ClientSideConnection,\n ndJsonStream,\n type Agent,\n type Client,\n type RequestPermissionRequest,\n type RequestPermissionResponse,\n type SessionNotification\n} from \"@agentclientprotocol/sdk\";\nimport { noopLogger, type Logger } from \"@pwrdrvr/agent-core\";\nimport {\n createCommandInvocation,\n prependCommandDirToPath,\n type JsonRpcId\n} from \"@pwrdrvr/agent-transport\";\nimport type { AcpJsonRpcTransport } from \"./acp-transport\";\n\n/** The subset of the library's client→agent surface that `AcpConnection`\n * drives. Injectable (via `createConnection`) so the adapter can be unit-tested\n * without spawning a real agent. The library's `ClientSideConnection` satisfies\n * this structurally (its methods take typed schema params; we pass records that\n * match at runtime).\n *\n * Every entry here MUST exist on the real `ClientSideConnection`. It is\n * attached with an `as unknown as` cast (see `createConnection`), so a name\n * that is merely plausible type-checks and then throws\n * \"conn.<name> is not a function\" at runtime, on the wire, against a user's\n * agent. `setSessionModel` was such an entry: ACP 1.3 has no `session/set_model`\n * at all, so every model selection died before it was sent. Anything the SDK\n * does not expose as a typed method belongs in `dispatch`'s default arm, which\n * sends it verbatim through `request()`. */\nexport interface AcpAgentConnection {\n initialize(params: Record<string, unknown>): Promise<unknown>;\n newSession(params: Record<string, unknown>): Promise<unknown>;\n loadSession(params: Record<string, unknown>): Promise<unknown>;\n prompt(params: Record<string, unknown>): Promise<unknown>;\n cancel(params: Record<string, unknown>): Promise<void>;\n setSessionMode(params: Record<string, unknown>): Promise<unknown>;\n authenticate(params: Record<string, unknown>): Promise<unknown>;\n request(method: string, params: Record<string, unknown>): Promise<unknown>;\n notify(method: string, params: Record<string, unknown>): Promise<void>;\n}\n\n/** Prefix on the rejection when a request outlived its budget. Lets a caller\n * tell \"the agent did not answer in time\" apart from \"the agent answered with\n * an error\" — the two want different recovery (retry / restart vs. surface). */\nexport const ACP_REQUEST_TIMEOUT_MESSAGE_PREFIX = \"acp request timed out\";\n\n/**\n * Enforce a per-request budget. Callers have been passing `timeoutMs` all\n * along (`AcpAgentClient` sends 30s for `initialize`, 1h for `session/prompt`)\n * but it was dropped on the floor here, so an agent that accepted the request\n * and then went quiet hung the caller forever with no diagnostic.\n *\n * The in-flight SDK call cannot be cancelled, so this unblocks the CALLER and\n * lets the connection's own teardown deal with the process.\n */\nfunction withAcpRequestTimeout<T>(\n method: string,\n timeoutMs: number | undefined,\n run: () => Promise<T>\n): Promise<T> {\n // `undefined`, non-finite, and non-positive all mean \"no budget\". Clamping a\n // 0 up to 1ms would make the two common ways to spell \"unlimited\" behave\n // oppositely: `Infinity` disables the timeout while `0` would reject every\n // request after a millisecond.\n if (timeoutMs === undefined || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n return run();\n }\n const budget = Math.max(1, Math.floor(timeoutMs));\n const call = run();\n // The abandoned call settles eventually; keep that from surfacing as an\n // unhandled rejection once the race is already decided.\n void call.catch(() => undefined);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const expiry = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(`${ACP_REQUEST_TIMEOUT_MESSAGE_PREFIX} after ${budget}ms: ${method}`)\n ),\n budget\n );\n });\n return Promise.race([call, expiry]).finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n });\n}\n\n/** Built connection + a teardown handle (kills the child / closes streams). */\nexport type AcpAgentConnectionHandle = {\n connection: AcpAgentConnection;\n dispose: () => void;\n};\n\nexport type AcpConnectionOptions = {\n command: string;\n args: string[];\n env?: NodeJS.ProcessEnv;\n logger?: Logger;\n /** Test seam: build the underlying connection. Defaults to spawning the agent\n * and wiring its stdio through the library's `ClientSideConnection`. */\n createConnection?: (client: Client) => AcpAgentConnectionHandle;\n};\n\nexport class AcpConnection implements AcpJsonRpcTransport {\n private readonly logger: Logger;\n private connection: AcpAgentConnection | undefined;\n private dispose: (() => void) | undefined;\n private connecting: Promise<void> | undefined;\n private readonly notificationListeners = new Set<\n (method: string, params: Record<string, unknown>) => void\n >();\n private requestHandler:\n | ((method: string, params: Record<string, unknown>, id?: JsonRpcId) => Promise<unknown> | unknown)\n | undefined;\n\n constructor(private readonly options: AcpConnectionOptions) {\n this.logger = options.logger ?? noopLogger;\n }\n\n /** The `Client` handler the library invokes for agent→client traffic. */\n private buildClient(): Client {\n const emit = (method: string, params: Record<string, unknown>): void => {\n for (const listener of this.notificationListeners) listener(method, params);\n };\n return {\n requestPermission: async (\n params: RequestPermissionRequest\n ): Promise<RequestPermissionResponse> => {\n if (!this.requestHandler) {\n throw new Error(\"ACP request handler unavailable for session/request_permission\");\n }\n return (await this.requestHandler(\n \"session/request_permission\",\n params as unknown as Record<string, unknown>\n )) as RequestPermissionResponse;\n },\n sessionUpdate: async (params: SessionNotification): Promise<void> => {\n // Emit the full notification ({ sessionId, update }); the client extracts\n // `update` and feeds the normalizer — same shape the old transport gave.\n emit(\"session/update\", params as unknown as Record<string, unknown>);\n },\n extNotification: async (method: string, params: Record<string, unknown>): Promise<void> => {\n // Vendor notifications (e.g. Grok's session_summary_generated) — routed to\n // the client's `vendorNotificationMethods` handling.\n emit(method, params);\n },\n extMethod: async (\n method: string,\n params: Record<string, unknown>\n ): Promise<Record<string, unknown>> => {\n if (!this.requestHandler) {\n throw new Error(`ACP request handler unavailable for ${method}`);\n }\n return ((await this.requestHandler(method, params)) ?? {}) as Record<string, unknown>;\n }\n // No fs/terminal handlers: we don't advertise those client capabilities at\n // `initialize`, so a conformant agent won't call them.\n };\n }\n\n private async ensureConnected(): Promise<void> {\n if (this.connection) return;\n this.connecting ??= this.connect();\n await this.connecting;\n }\n\n private async connect(): Promise<void> {\n const create = this.options.createConnection ?? this.defaultCreateConnection();\n const handle = create(this.buildClient());\n this.connection = handle.connection;\n this.dispose = handle.dispose;\n }\n\n private defaultCreateConnection(): (client: Client) => AcpAgentConnectionHandle {\n const { command, args, env } = this.options;\n const logger = this.logger;\n return (client) => {\n const launchEnv = prependCommandDirToPath(command, env ?? process.env);\n const invocation = createCommandInvocation({ command, args, env: launchEnv });\n const child = spawn(invocation.command, invocation.args, {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: launchEnv,\n windowsVerbatimArguments: invocation.windowsVerbatimArguments\n });\n child.on(\"error\", (error: Error) => {\n logger.error(\"acp agent process error\", { command, message: error.message });\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n const line = chunk.toString(\"utf8\").trimEnd();\n if (line.length > 0) logger.debug(\"acp agent stderr\", { line });\n });\n // ndJsonStream(writeToAgentStdin, readFromAgentStdout) — arg order: first is\n // the WritableStream we send to, second is the ReadableStream we read from.\n // SDK 1.3 accepts the protocol's scalar/array tool raw values and config\n // option updates directly, so passing stdio through unmodified preserves\n // the agent's exact notification payload.\n const toAgentStdin = Writable.toWeb(child.stdin) as WritableStream<Uint8Array>;\n const fromAgentStdout = Readable.toWeb(child.stdout) as ReadableStream<Uint8Array>;\n const stream = ndJsonStream(toAgentStdin, fromAgentStdout);\n // ClientSideConnection is deprecated in favor of the SDK's typed\n // client() builder, but it is the supported compatibility bridge that\n // retains wildcard inbound extension handlers. Agent-kit must preserve\n // unknown vendor request/notification routing for discovery strategies;\n // the typed builder requires registering each custom method up front.\n const connection = new ClientSideConnection(\n (_agent: Agent) => client,\n stream\n ) as unknown as AcpAgentConnection;\n return {\n connection,\n dispose: () => {\n try {\n child.stdin?.end();\n } catch {\n // already closed\n }\n child.kill();\n }\n };\n };\n }\n\n async request(\n method: string,\n params: Record<string, unknown> = {},\n timeoutMs?: number\n ): Promise<unknown> {\n await this.ensureConnected();\n const conn = this.connection;\n if (!conn) throw new Error(\"acp connection unavailable\");\n return await withAcpRequestTimeout(method, timeoutMs, () =>\n this.dispatch(conn, method, params)\n );\n }\n\n private async dispatch(\n conn: AcpAgentConnection,\n method: string,\n params: Record<string, unknown>\n ): Promise<unknown> {\n switch (method) {\n case \"initialize\":\n return await conn.initialize(params);\n case \"session/new\":\n return await conn.newSession(params);\n case \"session/load\":\n return await conn.loadSession(params);\n case \"session/prompt\":\n return await conn.prompt(params);\n case \"session/set_mode\":\n return await conn.setSessionMode(params);\n // `session/set_model` is deliberately NOT cased here: SDK 1.3 has no\n // typed `setSessionModel`, so it goes out through the default arm's\n // generic `request()` for agents still speaking the older method.\n case \"session/cancel\":\n await conn.cancel(params);\n return {};\n case \"authenticate\":\n return await conn.authenticate(params);\n default:\n // Unknown vendor methods remain part of agent-kit's generic transport\n // seam. SDK 1.3 sends them verbatim through its non-deprecated request().\n return await conn.request(method, params);\n }\n }\n\n async notify(method: string, params: Record<string, unknown> = {}): Promise<void> {\n await this.ensureConnected();\n const conn = this.connection;\n if (!conn) throw new Error(\"acp connection unavailable\");\n if (method === \"session/cancel\") {\n await conn.cancel(params);\n return;\n }\n await conn.notify(method, params);\n }\n\n async close(): Promise<void> {\n try {\n this.dispose?.();\n } finally {\n this.connection = undefined;\n this.dispose = undefined;\n this.connecting = undefined;\n }\n }\n\n onNotification(\n listener: (method: string, params: Record<string, unknown>) => void\n ): () => void {\n this.notificationListeners.add(listener);\n return () => {\n this.notificationListeners.delete(listener);\n };\n }\n\n onRequest(\n listener: (\n method: string,\n params: Record<string, unknown>,\n id?: JsonRpcId\n ) => Promise<unknown> | unknown\n ): () => void {\n this.requestHandler = listener;\n return () => {\n if (this.requestHandler === listener) {\n this.requestHandler = undefined;\n }\n };\n }\n}\n","// Long-lived ACP client. Speaks ACP over the stdio transport and normalizes the\n// agent's `session/update` stream into agent-core `NormalizedThreadEvent` — the\n// same shapes CodexThreadClient emits, so the two unify behind `AgentBackend`.\n//\n// PUBLIC SURFACE mirrors CodexThreadClient on purpose:\n// startThread / startTurn / interruptTurn / onEvent / onToolCall /\n// onApprovalRequest / close.\n//\n// Ported from PwrAgnt acp-client.ts, with all app concerns stripped (SQLite\n// session/rollout stores, live-notifications, DesktopBackendRegistry). Per-\n// session state the normalizer needs is held IN-MEMORY here; persistence is the\n// host's job (agent-core ThreadStore).\n//\n// Per-agent quirks (suppress thoughts, title source, vendor notification\n// methods) come from the registered STRATEGY — never an inline agent-id branch.\n\nimport {\n noopLogger,\n type AgentBackend,\n type AgentBackendApprovalHandler,\n type AgentBackendStartThreadResult,\n type AgentBackendToolCall,\n type AgentBackendToolCallHandler,\n type AgentStartThreadOptions,\n type AgentStartTurnOptions,\n type Logger,\n type NormalizedApprovalDecision,\n type NormalizedApprovalRequest,\n type NormalizedThreadEvent,\n type NormalizedThreadSettings,\n type NormalizedTokenUsage,\n type Unsubscribe\n} from \"@pwrdrvr/agent-core\";\nimport { mkdirSync } from \"node:fs\";\nimport { randomUUID } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { extname } from \"node:path\";\nimport type { JsonRpcId } from \"@pwrdrvr/agent-transport\";\nimport type { AcpAgentStrategy } from \"./strategies/strategy-types\";\nimport {\n AcpSessionNormalizer,\n type AcpApplyContext\n} from \"./normalizer/acp-normalizer\";\nimport {\n acpRuntimeSupportsHttpMcp,\n acpRuntimeSupportsSessionLoad,\n acpRuntimeSupportsSseMcp,\n acpSessionRuntimeStateFromCapabilities,\n acpSessionRuntimeStateFromUpdate,\n mergeAcpRuntimeState,\n modeLabelFor,\n modelConfigOption,\n modelIdFromCapabilities,\n normalizeAcpRuntimeCapabilities,\n type AcpRuntimeCapabilities,\n type AcpRuntimeConfigOptionValue,\n type AcpSessionRuntimeState\n} from \"./normalizer/runtime-capabilities\";\nimport type { AcpJsonRpcTransport } from \"./acp-transport\";\nimport {\n normalizeAcpMcpServerConfigs,\n redactAcpMcpCredentials,\n type AcpMcpServerConfig\n} from \"./mcp-server-config\";\n\nconst ACP_PROTOCOL_VERSION = 1;\nconst ACP_PROMPT_REQUEST_TIMEOUT_MS = 60 * 60_000;\nconst ACP_REQUEST_TIMEOUT_MS = 30_000;\n\nexport type AcpPromptContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"image\"; mimeType: string; data: string };\n\nexport type AcpRuntimeOptionSource =\n | \"mode\"\n | \"model\"\n | \"configOption\"\n /** A model write that travels as `session/set_config_option` because the\n * agent exposes model choice as a config option rather than via the legacy\n * top-level `models` capability. See `setModel`. */\n | \"modelConfigOption\";\n\nexport type AcpAgentClientOptions = {\n /** The transport (real stdio or a fake). */\n transport: AcpJsonRpcTransport;\n /** The agent strategy (carries quirks + display name). */\n strategy: AcpAgentStrategy;\n /** Identity sent at `initialize`. Defaults to \"agent-kit\". */\n clientName?: string;\n clientTitle?: string;\n clientVersion?: string;\n /** Default cwd for `session/new` when `startThread` omits one. */\n cwd?: string;\n /** MCP servers to attach at `session/new` / `session/load`. */\n mcpServers?: readonly AcpMcpServerConfig[];\n now?: () => number;\n logger?: Logger;\n};\n\n/** ACP-NATIVE thread/start options. **No longer the public `startThread`\n * surface** — `AcpAgentClient` implements the non-generic `AgentBackend` and its\n * public `startThread` takes neutral `AgentStartThreadOptions`. Retained as the\n * internal mapping target and exposed via `startThreadNative` for hosts wanting\n * ACP-specific control (e.g. per-thread `mcpServers`). */\nexport type AcpStartThreadOptions = {\n /** Working directory for the agent session. */\n cwd?: string;\n mcpServers?: readonly AcpMcpServerConfig[];\n};\n\n/** ACP-native `session/load` options. The protocol session id is the id the\n * agent persisted; `threadId` optionally preserves a separate host-facing id. */\nexport type AcpLoadThreadOptions = {\n sessionId: string;\n threadId?: string;\n cwd?: string;\n mcpServers?: readonly AcpMcpServerConfig[];\n};\n\n/** ACP-NATIVE turn/start options. Internal mapping target; the public `startTurn`\n * takes neutral `AgentStartTurnOptions`. */\nexport type AcpStartTurnOptions = {\n threadId: string;\n /** Plain prompt text. */\n prompt?: string;\n /** Pre-built ACP content blocks (text/image); overrides `prompt` when set. */\n promptContent?: AcpPromptContentBlock[];\n};\n\n/** Fired when the normalizer extracts a thread title from the stream. */\nexport type AcpTitleHandler = (event: {\n threadId: string;\n title: string;\n}) => void;\n\n/** Fired when runtime capabilities (models/modes/config-options) are observed. */\nexport type AcpRuntimeCapabilitiesHandler = (event: {\n threadId?: string;\n runtimeCapabilities: AcpRuntimeCapabilities;\n runtimeState?: AcpSessionRuntimeState;\n}) => void;\n\ntype AcpSessionState = {\n threadId: string;\n protocolSessionId: string;\n normalizer: AcpSessionNormalizer;\n turnId: string | undefined;\n runtimeState: AcpSessionRuntimeState | undefined;\n /** The in-flight `session/prompt` completion chain for the active turn.\n * `startTurnNative` resolves at turn START and streams terminal events from\n * this chain when the request settles; `undefined` between turns. Awaited by\n * `close()` so teardown doesn't orphan a running turn. The chain is\n * `.catch`-terminated, so it never rejects. */\n pendingTurn: Promise<void> | undefined;\n /** System prompt captured from the neutral `startThread({ instructions })`.\n * ACP has no `session/new` baseInstructions seam, so we fold it into the\n * FIRST turn's prompt as a leading text block (same approach the one-shot\n * enrichment client uses), then clear it. `undefined` once consumed / when\n * the host supplied none. */\n pendingInstructions: string | undefined;\n /** Names of the MCP servers attached to THIS session (per-thread, since one\n * shared client can serve surfaces with different tool sets). Used to\n * give the host's approval policy session-isolated MCP context. */\n mcpServerNames: string[];\n};\n\nconst DEFAULT_CLIENT_NAME = \"agent-kit\";\n\n/** Map a neutral approval decision onto an ACP permission decision token. */\nfunction permissionDecisionToken(decision: NormalizedApprovalDecision): string {\n switch (decision) {\n case \"approved\":\n return \"approve\";\n case \"abort\":\n case \"denied\":\n default:\n return \"reject\";\n }\n}\n\nexport class AcpAgentClient implements AgentBackend {\n private readonly transport: AcpJsonRpcTransport;\n private readonly strategy: AcpAgentStrategy;\n private readonly now: () => number;\n private readonly logger: Logger;\n\n private readonly eventListeners = new Set<(event: NormalizedThreadEvent) => void>();\n private toolCallHandler: AgentBackendToolCallHandler | null = null;\n private approvalHandler: AgentBackendApprovalHandler | null = null;\n private titleHandler: AcpTitleHandler | null = null;\n private runtimeCapabilitiesHandler: AcpRuntimeCapabilitiesHandler | null = null;\n\n // threadId ↔ protocol sessionId mapping + per-session state.\n private readonly sessions = new Map<string, AcpSessionState>();\n private readonly threadIdByProtocolId = new Map<string, string>();\n\n private unsubscribeNotification: (() => void) | undefined = undefined;\n private unsubscribeRequest: (() => void) | undefined = undefined;\n private initialized = false;\n private runtimeCapabilities?: AcpRuntimeCapabilities;\n\n constructor(options: AcpAgentClientOptions) {\n this.transport = options.transport;\n this.strategy = options.strategy;\n this.now = options.now ?? Date.now;\n this.logger = options.logger ?? noopLogger;\n this.clientName = options.clientName ?? DEFAULT_CLIENT_NAME;\n this.clientTitle = options.clientTitle ?? this.clientName;\n this.clientVersion = options.clientVersion ?? \"0.0.0\";\n this.defaultCwd = options.cwd;\n this.defaultMcpServers = options.mcpServers ?? [];\n }\n\n private readonly clientName: string;\n private readonly clientTitle: string;\n private readonly clientVersion: string;\n private readonly defaultCwd: string | undefined;\n private readonly defaultMcpServers: readonly AcpMcpServerConfig[];\n\n // ---- subscriptions (mirror CodexThreadClient) ----\n\n onEvent(cb: (event: NormalizedThreadEvent) => void): Unsubscribe {\n this.eventListeners.add(cb);\n return () => {\n this.eventListeners.delete(cb);\n };\n }\n\n onToolCall(handler: AgentBackendToolCallHandler): Unsubscribe {\n this.toolCallHandler = handler;\n return () => {\n if (this.toolCallHandler === handler) this.toolCallHandler = null;\n };\n }\n\n onApprovalRequest(handler: AgentBackendApprovalHandler): Unsubscribe {\n this.approvalHandler = handler;\n return () => {\n if (this.approvalHandler === handler) this.approvalHandler = null;\n };\n }\n\n /** Subscribe to title extraction (topic-update / session-summary). */\n onTitle(handler: AcpTitleHandler): Unsubscribe {\n this.titleHandler = handler;\n return () => {\n if (this.titleHandler === handler) this.titleHandler = null;\n };\n }\n\n /** Subscribe to runtime-capabilities (models/modes/config-options) changes. */\n onRuntimeCapabilities(handler: AcpRuntimeCapabilitiesHandler): Unsubscribe {\n this.runtimeCapabilitiesHandler = handler;\n return () => {\n if (this.runtimeCapabilitiesHandler === handler) {\n this.runtimeCapabilitiesHandler = null;\n }\n };\n }\n\n // ---- lifecycle ----\n\n /**\n * Public `AgentBackend.startThread`: accepts NEUTRAL `AgentStartThreadOptions`\n * and maps them onto an ACP `session/new`. ACP supports:\n * • `cwd` → `session/new.cwd`.\n * • `model` → applied after the session opens, by whichever route the agent\n * advertises: the `model` config option, or legacy `session/set_model`\n * (best-effort; debug-logged if not). See `setModel`.\n * • `instructions` is NOT injected here — ACP `session/new` has no base-\n * instructions slot, matching the adapter's existing behavior. A host that\n * wants system framing sends it as leading turn text.\n * Codex-only fields (`approvalPolicy`, `sandbox`, `config`, `environments`,\n * `tools`, `serviceName`, `modelProvider`, `serviceTier`, `workspaceRoots`) are\n * IGNORED — logged at debug so it's visible the backend doesn't honor them.\n */\n async startThread(\n options: AgentStartThreadOptions = {}\n ): Promise<AgentBackendStartThreadResult> {\n const ignored: string[] = [];\n for (const key of [\n \"approvalPolicy\",\n \"sandbox\",\n \"config\",\n \"environments\",\n \"tools\",\n \"serviceName\",\n \"modelProvider\",\n \"serviceTier\",\n \"workspaceRoots\"\n ] as const) {\n if (options[key] !== undefined) ignored.push(key);\n }\n if (ignored.length > 0) {\n this.logger.debug(\"acp startThread: ignoring Codex-only neutral options\", {\n ignored\n });\n }\n const native: AcpStartThreadOptions = {};\n if (options.cwd !== undefined) native.cwd = options.cwd;\n const result = await this.startThreadNative(native);\n // ACP has no `session/new` system-prompt seam, so stash the host's\n // `instructions` and fold them into the first turn's prompt (below). Without\n // this an ACP chat agent runs with NO host system prompt / persona / anchor\n // context — just its own CLI harness prompt.\n if (typeof options.instructions === \"string\" && options.instructions.length > 0) {\n const session = this.sessions.get(result.threadId);\n if (session) session.pendingInstructions = options.instructions;\n }\n // Report the model that ACTUALLY runs. `result.model` is the session/new\n // default (currentModelId); `setModel` may or may not apply the requested\n // one. If it applies, the effective model is the request; if it fails (e.g.\n // an unknown/stale id), the agent keeps its default — so a caller must NOT\n // report the requested id. Track the outcome and return the effective model.\n if (options.model !== undefined) {\n const applied = await this.setModel(result.threadId, options.model)\n .then(() => true)\n .catch((cause) => {\n this.logger.debug(\"acp startThread: model selection not applied\", {\n model: options.model,\n message: errorMessage(cause)\n });\n return false;\n });\n if (applied) return { ...result, model: options.model };\n }\n return result;\n }\n\n /** ACP-native `session/new`. The neutral `startThread` delegates here after\n * mapping cwd + dropping Codex-only fields. Exposed for hosts that need\n * ACP-specific control (per-thread `mcpServers`). */\n async startThreadNative(\n options: AcpStartThreadOptions = {}\n ): Promise<AgentBackendStartThreadResult> {\n return this.establishSession({\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.mcpServers !== undefined ? { mcpServers: options.mcpServers } : {})\n });\n }\n\n /** ACP-native `session/load`. The pinned ACP v1 library has no separate\n * `session/resume` method; loading is the protocol-defined history restore\n * path and receives the same per-thread MCP configuration as `session/new`. */\n async loadThreadNative(\n options: AcpLoadThreadOptions\n ): Promise<AgentBackendStartThreadResult> {\n return this.openSession({\n lifecycle: \"load\",\n protocolSessionId: options.sessionId,\n ...(options.threadId !== undefined ? { bindThreadId: options.threadId } : {}),\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.mcpServers !== undefined ? { mcpServers: options.mcpServers } : {})\n });\n }\n\n /**\n * Re-establish a fresh ACP session for a PERSISTED thread id whose underlying\n * session is gone (e.g. resuming a chat after an app restart — the agent\n * process, and its in-memory session, died with the previous run). ACP\n * sessions don't survive a process restart the way a Codex thread does, so a\n * host that persists threads must rebind them. No-op when the session is still\n * live. The conversation starts fresh on the agent side (prior turns aren't\n * replayed), but the host keeps the visible transcript and the system prompt\n * is re-applied to the first turn.\n */\n async reopenThread(options: {\n threadId: string;\n /** Built ONLY when a re-establish actually happens (skipped for a live\n * session), so the host doesn't rebuild the system prompt every turn. */\n buildInstructions?: () => string;\n /** Per-thread MCP servers for THIS session. Lets ONE shared client serve\n * surfaces with different tool sets (library vs sizzle): each surface\n * passes its own servers, so its threads spawn its tools — overriding the\n * client-level default. */\n mcpServers?: readonly AcpMcpServerConfig[];\n }): Promise<void> {\n if (this.sessions.has(options.threadId)) return;\n const instructions = options.buildInstructions?.();\n await this.establishSession({\n bindThreadId: options.threadId,\n ...(instructions !== undefined ? { instructions } : {}),\n ...(options.mcpServers !== undefined ? { mcpServers: options.mcpServers } : {})\n });\n }\n\n /**\n * Mint a thread id WITHOUT spawning the agent or opening a session. The\n * session is established lazily on the FIRST turn (via `reopenThread`, which\n * the chat controller calls before each turn), so opening a new chat is\n * instant — the multi-second agent spawn + `session/new` happens only when\n * the user actually sends a message. Options are ignored (cwd/mcpServers come\n * from the client defaults at establish time; instructions ride the first\n * turn). The host id is a random UUID since there's no session GUID yet.\n */\n async createDeferredThread(\n _options?: AgentStartThreadOptions\n ): Promise<AgentBackendStartThreadResult> {\n const threadId = `acp:${this.strategy.id}:${randomUUID()}`;\n const out: AgentBackendStartThreadResult = { threadId };\n out.modelProvider = this.strategy.id;\n return out;\n }\n\n /** Warm the agent: spawn the process + run the `initialize` handshake WITHOUT\n * opening a session, so the first thread/turn doesn't pay the multi-second\n * spawn. Idempotent. Used by `AcpAgentClientPool` to hold a configured agent\n * ready from app startup. */\n async connect(): Promise<void> {\n await this.initialize();\n }\n\n /** Shared `session/new` + session registration. Mints a new thread id unless\n * `bindThreadId` is given (resume), in which case the new ACP session is\n * bound to that existing host thread id. */\n private async establishSession(options: {\n cwd?: string;\n mcpServers?: readonly AcpMcpServerConfig[];\n bindThreadId?: string;\n instructions?: string;\n }): Promise<AgentBackendStartThreadResult> {\n return this.openSession({ lifecycle: \"new\", ...options });\n }\n\n private async openSession(options: {\n lifecycle: \"new\" | \"load\";\n protocolSessionId?: string;\n cwd?: string;\n mcpServers?: readonly AcpMcpServerConfig[];\n bindThreadId?: string;\n instructions?: string;\n }): Promise<AgentBackendStartThreadResult> {\n await this.initialize();\n if (\n options.lifecycle === \"load\" &&\n !acpRuntimeSupportsSessionLoad(this.runtimeCapabilities)\n ) {\n throw new Error(\"ACP agent does not advertise session/load support\");\n }\n const cwd = options.cwd ?? this.defaultCwd ?? process.cwd();\n // Ensure the session workspace exists. ACP agents use `cwd` as their\n // working directory; some (e.g. Gemini) fail `session/new` with an opaque\n // \"-32603 Internal error\" when it doesn't exist. Best-effort — if the\n // mkdir fails the agent surfaces its own error as before.\n try {\n mkdirSync(cwd, { recursive: true });\n } catch (cause) {\n this.logger.debug(\"acp session cwd ensure failed\", {\n cwd,\n message: cause instanceof Error ? cause.message : String(cause)\n });\n }\n const configuredMcpServers = options.mcpServers ?? this.defaultMcpServers;\n this.assertMcpTransportSupport(configuredMcpServers);\n const mcpServers = normalizeAcpMcpServerConfigs(configuredMcpServers);\n const method = options.lifecycle === \"load\" ? \"session/load\" : \"session/new\";\n // `session/load` replays history through `session/update` notifications\n // WHILE the request is in flight. Its protocol id is already known, so\n // install the routing state before sending the request; otherwise replayed\n // updates arrive as \"unknown session\" and are silently dropped.\n let session: AcpSessionState | undefined;\n if (options.lifecycle === \"load\") {\n const protocolSessionId = options.protocolSessionId;\n if (!protocolSessionId) {\n throw new Error(\"ACP session/load did not provide a session id\");\n }\n const threadId =\n options.bindThreadId ??\n `acp:${this.strategy.id}:${isUuid(protocolSessionId) ? protocolSessionId : randomUUID()}`;\n if (this.sessions.has(threadId)) {\n throw new Error(`ACP thread is already open: ${threadId}`);\n }\n const mappedThreadId = this.threadIdByProtocolId.get(protocolSessionId);\n if (mappedThreadId !== undefined) {\n throw new Error(\n `ACP session is already loaded for thread: ${mappedThreadId}`\n );\n }\n session = {\n threadId,\n protocolSessionId,\n normalizer: new AcpSessionNormalizer({ quirks: this.strategy.quirks }),\n turnId: undefined,\n runtimeState: undefined,\n pendingTurn: undefined,\n pendingInstructions: options.instructions,\n mcpServerNames: configuredMcpServers.map((server) => server.name)\n };\n this.sessions.set(threadId, session);\n this.threadIdByProtocolId.set(protocolSessionId, threadId);\n }\n let result: unknown;\n try {\n result = await this.transport.request(method, {\n cwd,\n mcpServers,\n ...(options.lifecycle === \"load\"\n ? { sessionId: options.protocolSessionId }\n : {})\n });\n } catch (cause) {\n const message = redactAcpMcpCredentials(\n errorMessage(cause),\n configuredMcpServers\n );\n // A failed load never established a live session. Remove only the exact\n // provisional entries installed above so later notifications cannot\n // route into a dead session.\n if (session !== undefined) {\n if (this.sessions.get(session.threadId) === session) {\n this.sessions.delete(session.threadId);\n }\n if (\n this.threadIdByProtocolId.get(session.protocolSessionId) ===\n session.threadId\n ) {\n this.threadIdByProtocolId.delete(session.protocolSessionId);\n }\n }\n throw new Error(`ACP ${method} failed: ${message}`);\n }\n const record = asRecord(result);\n const protocolSessionId =\n options.lifecycle === \"load\"\n ? options.protocolSessionId\n : readString(record, \"sessionId\") ?? readString(record, \"session_id\");\n if (!protocolSessionId) {\n throw new Error(`ACP ${method} did not provide a session id`);\n }\n // Prefer the agent's session GUID for the host-facing `threadId` (it's the\n // id ACP already hands us, so the thread is traceable straight to the live\n // session) — but ONLY when it's a well-formed UUID. Many agents return a\n // proper UUID; if one returns a counter / opaque token instead, fall back\n // to a host-minted `randomUUID()` so our id is globally unique regardless of\n // the agent's choice. Never a plain integer counter. On resume, bind to the\n // caller's existing thread id instead of minting one.\n const threadId =\n session?.threadId ??\n options.bindThreadId ??\n `acp:${this.strategy.id}:${isUuid(protocolSessionId) ? protocolSessionId : randomUUID()}`;\n session ??= {\n threadId,\n protocolSessionId,\n normalizer: new AcpSessionNormalizer({ quirks: this.strategy.quirks }),\n turnId: undefined,\n runtimeState: undefined,\n pendingTurn: undefined,\n pendingInstructions: options.instructions,\n // Remember ONLY the MCP servers attached to THIS session so the host's\n // approval policy never sees another pooled thread's tool set.\n mcpServerNames: configuredMcpServers.map((server) => server.name)\n };\n if (options.lifecycle === \"new\") {\n this.sessions.set(threadId, session);\n this.threadIdByProtocolId.set(protocolSessionId, threadId);\n }\n\n const runtimeCapabilities = this.captureRuntimeCapabilities(\n options.lifecycle === \"load\" ? \"session-load\" : \"session-new\",\n result\n );\n if (runtimeCapabilities) {\n const runtimeState = acpSessionRuntimeStateFromCapabilities(\n runtimeCapabilities,\n this.now()\n );\n if (runtimeState) session.runtimeState = runtimeState;\n this.notifyRuntimeCapabilities({ threadId, runtimeCapabilities, runtimeState });\n this.emitThreadSettings(session, runtimeCapabilities, runtimeState);\n }\n\n this.logger.debug(\"acp thread opened\", {\n threadId,\n protocolSessionId,\n lifecycle: options.lifecycle,\n rebound: options.bindThreadId !== undefined\n });\n const out: AgentBackendStartThreadResult = { threadId };\n // Effective model — prefers `models.currentModelId`, falling back to the\n // `model` configOption for agents (Kimi) that advertise model choice there.\n const model = modelIdFromCapabilities(runtimeCapabilities);\n if (model !== undefined) out.model = model;\n out.modelProvider = this.strategy.id;\n return out;\n }\n\n /**\n * Public `AgentBackend.startTurn`: accepts NEUTRAL `AgentStartTurnOptions` and\n * maps them onto ACP prompt content blocks — a leading `text` block from\n * `input.text`, then one `image` block per `input.imagePaths` entry (read from\n * disk, base64-encoded, mimeType inferred from extension). `reasoning` maps to\n * an ACP mode/config when the session advertises a matching option, else it is\n * IGNORED (debug-logged).\n */\n async startTurn(options: AgentStartTurnOptions): Promise<{ turnId: string }> {\n const promptContent: AcpPromptContentBlock[] = [];\n // Fold the host system prompt (captured at startThread) into the FIRST turn\n // as a leading text block — ACP has no baseInstructions seam. Consumed once.\n const session = this.sessions.get(options.threadId);\n if (session?.pendingInstructions !== undefined) {\n promptContent.push({ type: \"text\", text: session.pendingInstructions });\n session.pendingInstructions = undefined;\n }\n promptContent.push({ type: \"text\", text: options.input.text });\n for (const imagePath of options.input.imagePaths ?? []) {\n const block = await this.imageBlockFromPath(imagePath).catch((cause) => {\n this.logger.debug(\"acp startTurn: skipping unreadable image\", {\n imagePath,\n message: cause instanceof Error ? cause.message : String(cause)\n });\n return undefined;\n });\n if (block !== undefined) promptContent.push(block);\n }\n if (options.reasoning !== undefined) {\n await this.applyReasoning(options.threadId, options.reasoning).catch((cause) => {\n this.logger.debug(\"acp startTurn: reasoning not applied\", {\n reasoning: options.reasoning,\n message: cause instanceof Error ? cause.message : String(cause)\n });\n });\n }\n return this.startTurnNative({ threadId: options.threadId, promptContent });\n }\n\n /** ACP-native `session/prompt`. Takes a plain prompt or pre-built content\n * blocks. The neutral `startTurn` delegates here after building blocks. */\n async startTurnNative(options: AcpStartTurnOptions): Promise<{ turnId: string }> {\n const session = this.requireSession(options.threadId);\n if (session.turnId !== undefined) {\n throw new Error(\"A turn is already active for this ACP session.\");\n }\n const turnId = `turn:${session.threadId}:${this.now()}`;\n session.turnId = turnId;\n session.normalizer.resetTurn();\n this.emit({ kind: \"turn_started\", threadId: session.threadId, turnId });\n\n const prompt =\n options.promptContent ??\n textPrompt(options.prompt ?? \"\");\n\n // Resolve at turn START, not turn END. ACP's `session/prompt` resolves only\n // when the whole turn is done (assistant chunks arrive as `session/update`\n // notifications WHILE the request is in flight). Awaiting it here would make\n // `startTurn` block for the entire turn — violating the `AgentBackend`\n // contract (Codex resolves at turn start) and freezing any host UI that\n // gates on `startTurn` (e.g. a chat composer waiting to clear). Instead we\n // fire the request and stream its terminal events (token_usage,\n // agent_message, turn_completed/error) asynchronously when it settles.\n session.pendingTurn = this.transport\n .request(\n \"session/prompt\",\n {\n sessionId: session.protocolSessionId,\n prompt\n },\n ACP_PROMPT_REQUEST_TIMEOUT_MS\n )\n .then((promptResult) => {\n // Token usage rides on the `session/prompt` RESPONSE (`_meta.quota`),\n // not a session/update — emit it so hosts can account for ACP turns the\n // same way they do Codex turns.\n const usage = readAcpPromptUsage(promptResult);\n if (usage) {\n this.emit({ kind: \"token_usage\", threadId: session.threadId, turnId, usage });\n } else {\n // No recognized usage shape — log WHERE usage-like keys live (paths\n // only, never values) so a new agent's reporting format is\n // diagnosable instead of silently surfacing \"usage unavailable\".\n this.logger.debug(\"acp prompt response carried no recognized token usage\", {\n threadId: session.threadId,\n turnId,\n shape: describeUsageShape(promptResult)\n });\n }\n // Flush any in-flight assistant bubble into a terminal agent_message.\n for (const event of session.normalizer.finalizeAssistantMessage({\n threadId: session.threadId,\n turnId\n })) {\n this.emit(event);\n }\n session.turnId = undefined;\n session.pendingTurn = undefined;\n this.emit({\n kind: \"turn_completed\",\n threadId: session.threadId,\n turnId,\n status: \"completed\"\n });\n })\n .catch((error) => {\n session.turnId = undefined;\n session.pendingTurn = undefined;\n this.emit({\n kind: \"turn_completed\",\n threadId: session.threadId,\n turnId,\n status: \"failed\"\n });\n this.emit({\n kind: \"error\",\n threadId: session.threadId,\n turnId,\n message: errorMessage(error)\n });\n });\n\n return { turnId };\n }\n\n async interruptTurn(threadId: string): Promise<void> {\n const session = this.requireSession(threadId);\n if (this.transport.notify) {\n await this.transport.notify(\"session/cancel\", {\n sessionId: session.protocolSessionId\n });\n } else {\n await this.transport.request(\"session/cancel\", {\n sessionId: session.protocolSessionId\n });\n }\n }\n\n /** Release a thread the host has archived/closed.\n *\n * ACP has NO protocol-level session delete/archive — sessions are\n * connection-scoped and the spec offers only `session/cancel` (interrupt).\n * So unlike the Codex backend (which sends `thread/archive`), there's no\n * remote call to make here. What we MUST do is drop the live session\n * LOCALLY: a long-lived pooled client (one process shared across surfaces,\n * warmed at startup) would otherwise accumulate a dead `AcpSessionState` for\n * every closed chat for the life of the app. Best-effort cancels an\n * in-flight turn first so the agent stops working on a thread the user\n * closed. Idempotent — no-ops if the session is already gone. A later\n * `reopenThread` re-establishes a fresh session under the same threadId, so\n * releasing here never blocks resume. */\n async archiveThread(threadId: string): Promise<void> {\n const session = this.sessions.get(threadId);\n if (session === undefined) return;\n if (session.turnId !== undefined) {\n try {\n if (this.transport.notify) {\n await this.transport.notify(\"session/cancel\", {\n sessionId: session.protocolSessionId\n });\n } else {\n await this.transport.request(\"session/cancel\", {\n sessionId: session.protocolSessionId\n });\n }\n } catch {\n // best-effort — the session is being released regardless.\n }\n }\n this.sessions.delete(threadId);\n this.threadIdByProtocolId.delete(session.protocolSessionId);\n this.logger.debug(\"acp thread archived (session released locally)\", { threadId });\n }\n\n async setMode(threadId: string, modeId: string): Promise<void> {\n await this.setRuntimeOption(threadId, \"mode\", modeId, modeId);\n }\n\n /** Apply a model selection by whichever route the agent actually advertises.\n *\n * ACP 1.3 has NO `session/set_model` — it is absent from `AGENT_METHODS`.\n * An agent that offers model choice does it through a config option with\n * `category: \"model\"` (Kimi's `session/new` returns exactly that, and nothing\n * under `models`). Some agents still accept `session/set_model` as a vendor\n * extension, and the `models.availableModels` shape is still honoured for\n * them, but it is not what the protocol defines any more.\n *\n * Two reasons to prefer the config option when the agent offers it. The READ\n * path already draws this distinction — `modelIdFromCapabilities` and\n * `modelsFromCapabilities` both fall back to the config option — and the two\n * disagreeing lets a host list models it cannot then select. And the config\n * option's REPLY carries the agent's full refreshed config set, where\n * `session/set_model` answers `{}` and refreshes only via an async\n * notification. On Kimi the model DETERMINES which thought levels exist —\n * `K2.7 Coding` offers only `on`, `K3` offers `low`/`high`/`max` — and\n * `applyReasoning` picks from `runtimeCapabilities` on the following\n * `startTurn`, so the refresh this write leaves behind is what it reads. */\n async setModel(threadId: string, modelId: string): Promise<void> {\n const advertisesModelsCapability =\n (this.runtimeCapabilities?.models?.availableModels?.length ?? 0) > 0;\n const option = modelConfigOption(this.runtimeCapabilities);\n if (!advertisesModelsCapability && option !== undefined) {\n await this.setRuntimeOption(threadId, \"modelConfigOption\", option.id, modelId);\n return;\n }\n await this.setRuntimeOption(threadId, \"model\", modelId, modelId);\n }\n\n async setConfigOption(\n threadId: string,\n optionId: string,\n value: string\n ): Promise<void> {\n await this.setRuntimeOption(threadId, \"configOption\", optionId, value);\n }\n\n async close(): Promise<void> {\n this.unsubscribeNotification?.();\n this.unsubscribeNotification = undefined;\n this.unsubscribeRequest?.();\n this.unsubscribeRequest = undefined;\n // Snapshot in-flight turn chains before clearing sessions. Closing the\n // transport rejects any pending `session/prompt`, which the chain's\n // `.catch` turns into a terminal failed/error emit — await them so teardown\n // doesn't leave a turn settling after `close()` resolves. The chains never\n // reject (they're `.catch`-terminated), so `allSettled` is belt-and-braces.\n const pending = [...this.sessions.values()]\n .map((s) => s.pendingTurn)\n .filter((p): p is Promise<void> => p !== undefined);\n this.sessions.clear();\n this.threadIdByProtocolId.clear();\n this.initialized = false;\n await this.transport.close?.();\n if (pending.length > 0) await Promise.allSettled(pending);\n }\n\n // ---- internals ----\n\n private emit(event: NormalizedThreadEvent): void {\n for (const listener of this.eventListeners) listener(event);\n }\n\n private async initialize(): Promise<void> {\n if (this.initialized) return;\n\n // `initialize` can REJECT (it carries a 30s budget), leaving `initialized`\n // false — so this method is re-entered on the caller's retry. Drop any\n // handlers a previous attempt installed first: they are unreachable once\n // the fields below are overwritten, and a stale one left registered makes\n // every later session/update dispatch twice, duplicating the transcript.\n this.unsubscribeNotification?.();\n this.unsubscribeRequest?.();\n\n this.unsubscribeNotification = this.transport.onNotification((method, params) => {\n this.handleNotification(method, params);\n });\n this.unsubscribeRequest = this.transport.onRequest?.(\n async (method, params, id) => await this.handleAcpRequest(method, params, id)\n );\n\n const result = await this.transport.request(\n \"initialize\",\n {\n protocolVersion: ACP_PROTOCOL_VERSION,\n clientCapabilities: {\n auth: { terminal: false },\n fs: { readTextFile: false, writeTextFile: false },\n terminal: false\n },\n clientInfo: {\n name: this.clientName,\n title: this.clientTitle,\n version: this.clientVersion\n }\n },\n ACP_REQUEST_TIMEOUT_MS\n );\n const runtimeCapabilities = this.captureRuntimeCapabilities(\"initialize\", result);\n if (runtimeCapabilities) {\n this.notifyRuntimeCapabilities({ runtimeCapabilities });\n }\n this.initialized = true;\n }\n\n private handleNotification(method: string, params: unknown): void {\n const vendorMethods = this.strategy.quirks.vendorNotificationMethods ?? [];\n if (method !== \"session/update\" && !vendorMethods.includes(method)) {\n return;\n }\n const record = asRecord(params);\n if (!record) return;\n this.applySessionUpdate(record);\n }\n\n private applySessionUpdate(params: Record<string, unknown>): void {\n const protocolSessionId =\n readString(params, \"sessionId\") ?? readString(params, \"session_id\");\n const update = asRecord(params.update);\n if (!protocolSessionId || !update) {\n return;\n }\n const threadId = this.threadIdByProtocolId.get(protocolSessionId);\n const session = threadId ? this.sessions.get(threadId) : undefined;\n if (!session) {\n this.logger.debug(\"acp session/update for unknown session\", { protocolSessionId });\n return;\n }\n\n // Runtime-state changes (mode/model/config) ride session/update too.\n const runtimeState = acpSessionRuntimeStateFromUpdate(update, this.now());\n if (runtimeState) {\n session.runtimeState = mergeAcpRuntimeState(session.runtimeState, runtimeState);\n if (this.runtimeCapabilities) {\n this.notifyRuntimeCapabilities({\n threadId: session.threadId,\n runtimeCapabilities: this.runtimeCapabilities,\n runtimeState: session.runtimeState\n });\n }\n this.emitThreadSettings(session, this.runtimeCapabilities, session.runtimeState);\n return;\n }\n\n // Diagnostic: for tool notifications, log the RAW identity fields so a\n // host can see exactly what an agent streamed — how many distinct\n // toolCallIds, and whether each carries a title/name (Grok often sends\n // titleless `tool_call_update`s, which is why a chip can read \"tool call\n // update\" instead of the tool name). debug-level; off the hot path for\n // non-tool updates.\n const updateKind = readString(update, \"sessionUpdate\");\n if (updateKind === \"tool_call\" || updateKind === \"tool_call_update\") {\n this.logger.debug(\"acp tool notification\", {\n kind: updateKind,\n toolCallId: readString(update, \"toolCallId\") ?? readString(update, \"tool_call_id\"),\n title: readString(update, \"title\"),\n name: readString(update, \"name\"),\n status: readString(update, \"status\")\n });\n }\n\n const ctx: AcpApplyContext = {\n threadId: session.threadId,\n turnId: session.turnId ?? `turn:${session.threadId}:detached`\n };\n const result = session.normalizer.apply(update, ctx);\n if (result.title !== undefined) {\n this.titleHandler?.({ threadId: session.threadId, title: result.title });\n return;\n }\n for (const event of result.events) {\n this.emit(event);\n }\n }\n\n private async handleAcpRequest(\n method: string,\n params: Record<string, unknown>,\n id?: JsonRpcId\n ): Promise<unknown> {\n if (method === \"session/request_permission\") {\n return await this.handlePermissionRequest(params, id);\n }\n // Any other inbound server-request (e.g. a future tool-call request) routes\n // to the tool-call handler when one is registered.\n if (this.toolCallHandler) {\n const call: AgentBackendToolCall = { method, params };\n return await this.toolCallHandler(call);\n }\n throw new Error(`Unsupported ACP request: ${method}`);\n }\n\n private async handlePermissionRequest(\n params: Record<string, unknown>,\n id?: JsonRpcId\n ): Promise<unknown> {\n const protocolSessionId =\n readString(params, \"sessionId\") ?? readString(params, \"session_id\");\n const threadId = protocolSessionId\n ? this.threadIdByProtocolId.get(protocolSessionId)\n : undefined;\n const options = readPermissionOptions(params.options);\n\n // The client makes NO trust decision of its own — every permission request\n // goes to the host's approval handler, which owns the policy (e.g. a host\n // may pre-approve tools from MCP servers IT configured). We give the host\n // the context the raw ACP params lack: the RESOLVED `threadId` (params only\n // carry a `sessionId`) and ONLY that session's `mcpServerNames`, so a pooled\n // client never exposes another thread's configured tool set to this policy\n // decision. With no handler registered there's no one to decide, so the\n // request is cancelled.\n const handler = this.approvalHandler;\n if (!handler) {\n return cancelledPermissionOutcome();\n }\n\n const approval = buildApprovalRequest({\n params,\n id,\n threadId,\n session: threadId ? this.sessions.get(threadId) : undefined,\n now: this.now\n });\n if (threadId) {\n this.emit({ kind: \"approval_request\", threadId, approval });\n }\n\n const handlerParams: Record<string, unknown> = {\n ...params,\n mcpServerNames: threadId\n ? (this.sessions.get(threadId)?.mcpServerNames ?? [])\n : []\n };\n if (threadId !== undefined) handlerParams.threadId = threadId;\n const decision = await handler(\"session/request_permission\", handlerParams);\n return permissionOutcomeFromDecision(decision, options);\n }\n\n private async setRuntimeOption(\n threadId: string,\n source: AcpRuntimeOptionSource,\n optionId: string,\n value: string\n ): Promise<void> {\n const session = this.requireSession(threadId);\n const result = await this.setRuntimeOptionOnTransport(\n session.protocolSessionId,\n source,\n optionId,\n value\n );\n const runtimeCapabilities = this.captureRuntimeCapabilities(\"session-load\", result);\n const requested: AcpSessionRuntimeState =\n source === \"configOption\"\n ? { configValues: { [optionId]: value }, updatedAt: this.now() }\n : source === \"mode\"\n ? { currentModeId: value, updatedAt: this.now() }\n : source === \"modelConfigOption\"\n ? // Record BOTH: it IS the config option's value, and it IS the\n // session's model. A consumer reading `currentModelId` must not\n // have to know which route the agent happened to expose.\n {\n currentModelId: value,\n configValues: { [optionId]: value },\n updatedAt: this.now()\n }\n : { currentModelId: value, updatedAt: this.now() };\n session.runtimeState = mergeAcpRuntimeState(session.runtimeState, requested);\n const effectiveCapabilities = runtimeCapabilities ?? this.runtimeCapabilities;\n if (effectiveCapabilities) {\n this.notifyRuntimeCapabilities({\n threadId,\n runtimeCapabilities: effectiveCapabilities,\n ...(session.runtimeState !== undefined\n ? { runtimeState: session.runtimeState }\n : {})\n });\n }\n this.emitThreadSettings(session, effectiveCapabilities, session.runtimeState);\n }\n\n private async setRuntimeOptionOnTransport(\n protocolSessionId: string,\n source: AcpRuntimeOptionSource,\n optionId: string,\n value: string\n ): Promise<unknown> {\n if (source === \"configOption\" || source === \"modelConfigOption\") {\n return await this.transport.request(\"session/set_config_option\", {\n sessionId: protocolSessionId,\n configId: optionId,\n value\n });\n }\n if (source === \"mode\") {\n return await this.transport.request(\"session/set_mode\", {\n sessionId: protocolSessionId,\n modeId: value\n });\n }\n return await this.transport.request(\"session/set_model\", {\n sessionId: protocolSessionId,\n modelId: value\n });\n }\n\n /** Map a neutral `reasoning` token onto an ACP runtime option. ACP has no\n * first-class \"reasoning effort\" concept, so we map it to whatever the agent\n * exposes, in order:\n * 1. An available MODE whose id/label matches the token (set_mode).\n * 2. A \"thinking\" config option (`category: \"thought_level\"`, or id\n * `thinking`) — map low-effort tokens to its OFF-like value and\n * high-effort tokens to its ON-like value (set_config_option). This is\n * what lets a one-shot enrichment turn (\"low\") disable a reasoning\n * model's thinking pass, which is dramatically faster.\n * If nothing matches we leave it alone — the caller's `.catch` debug-logs. */\n private async applyReasoning(threadId: string, reasoning: string): Promise<void> {\n const target = reasoning.toLowerCase();\n const modes = this.runtimeCapabilities?.modes?.availableModes ?? [];\n const modeMatch = modes.find(\n (mode) =>\n mode.id.toLowerCase() === target ||\n (typeof mode.label === \"string\" && mode.label.toLowerCase() === target)\n );\n if (modeMatch !== undefined) {\n await this.setMode(threadId, modeMatch.id);\n return;\n }\n const thinking = this.runtimeCapabilities?.configOptions?.find(\n (option) => option.category === \"thought_level\" || option.id === \"thinking\"\n );\n if (thinking !== undefined) {\n const value = reasoningValueForThoughtLevel(target, thinking.values);\n if (value === undefined) {\n this.logger.debug(\"acp reasoning has no matching thought-level value — ignored\", {\n reasoning\n });\n return;\n }\n // Already at the desired value → no redundant set_config_option round-trip.\n if (value !== thinking.currentValue) {\n await this.setConfigOption(threadId, thinking.id, value);\n }\n return;\n }\n this.logger.debug(\"acp reasoning has no matching mode or thought-level option — ignored\", {\n reasoning\n });\n }\n\n /** Read an image file and build an ACP `image` content block (base64 + inferred\n * mimeType). Throws on read failure; the caller catches + skips. */\n private async imageBlockFromPath(imagePath: string): Promise<AcpPromptContentBlock> {\n const data = await readFile(imagePath);\n return {\n type: \"image\",\n mimeType: mimeTypeForImagePath(imagePath),\n data: data.toString(\"base64\")\n };\n }\n\n private captureRuntimeCapabilities(\n source: AcpRuntimeCapabilities[\"source\"],\n result: unknown\n ): AcpRuntimeCapabilities | undefined {\n const runtimeCapabilities = normalizeAcpRuntimeCapabilities({\n value: result,\n now: this.now(),\n source,\n ...(this.runtimeCapabilities !== undefined\n ? { initialize: this.runtimeCapabilities }\n : {})\n });\n if (runtimeCapabilities) {\n this.runtimeCapabilities = runtimeCapabilities;\n }\n return runtimeCapabilities;\n }\n\n private notifyRuntimeCapabilities(event: {\n threadId?: string | undefined;\n runtimeCapabilities: AcpRuntimeCapabilities;\n runtimeState?: AcpSessionRuntimeState | undefined;\n }): void {\n this.runtimeCapabilitiesHandler?.({\n ...(event.threadId !== undefined ? { threadId: event.threadId } : {}),\n runtimeCapabilities: event.runtimeCapabilities,\n ...(event.runtimeState !== undefined ? { runtimeState: event.runtimeState } : {})\n });\n }\n\n private emitThreadSettings(\n session: AcpSessionState,\n capabilities: AcpRuntimeCapabilities | undefined,\n runtimeState: AcpSessionRuntimeState | undefined\n ): void {\n const settings: NormalizedThreadSettings = { threadId: session.threadId };\n const model =\n runtimeState?.currentModelId ?? modelIdFromCapabilities(capabilities);\n if (model !== undefined) settings.model = model;\n settings.modelProvider = this.strategy.id;\n const modeId =\n runtimeState?.currentModeId ?? capabilities?.modes?.currentModeId;\n if (modeId !== undefined) {\n settings.modeId = modeId;\n const label = modeLabelFor(capabilities, modeId);\n if (label !== undefined) settings.modeLabel = label;\n }\n this.emit({ kind: \"thread_settings\", settings });\n }\n\n private requireSession(threadId: string): AcpSessionState {\n const session = this.sessions.get(threadId);\n if (!session) {\n throw new Error(`Unknown ACP thread: ${threadId}`);\n }\n return session;\n }\n\n private assertMcpTransportSupport(\n servers: readonly AcpMcpServerConfig[]\n ): void {\n for (const server of servers) {\n if (!(\"type\" in server)) continue;\n if (\n server.type === \"http\" &&\n !acpRuntimeSupportsHttpMcp(this.runtimeCapabilities)\n ) {\n throw new Error(\n `ACP agent does not advertise HTTP MCP support for server \"${server.name}\"`\n );\n }\n if (\n server.type === \"sse\" &&\n !acpRuntimeSupportsSseMcp(this.runtimeCapabilities)\n ) {\n throw new Error(\n `ACP agent does not advertise SSE MCP support for server \"${server.name}\"`\n );\n }\n }\n }\n\n /** Whether the agent advertises session/load support (for hosts that resume). */\n supportsSessionLoad(): boolean {\n return acpRuntimeSupportsSessionLoad(this.runtimeCapabilities);\n }\n\n /** Whether the initialize result explicitly advertises streamable HTTP MCP. */\n supportsHttpMcp(): boolean {\n return acpRuntimeSupportsHttpMcp(this.runtimeCapabilities);\n }\n\n /** Whether the initialize result explicitly advertises legacy HTTP+SSE MCP. */\n supportsSseMcp(): boolean {\n return acpRuntimeSupportsSseMcp(this.runtimeCapabilities);\n }\n}\n\n/** Effort tokens that mean \"deliberate as little as possible\" → thinking OFF. */\nconst LOW_EFFORT_TOKENS = new Set([\n \"off\",\n \"none\",\n \"minimal\",\n \"min\",\n \"minimum\",\n \"low\",\n \"fast\"\n]);\n/** Effort tokens that mean \"deliberate fully\" → thinking ON. */\nconst HIGH_EFFORT_TOKENS = new Set([\n \"on\",\n \"high\",\n \"medium\",\n \"max\",\n \"maximum\",\n \"full\",\n \"think\"\n]);\n\n/** Classify a thinking/thought-level option VALUE as on/off-like from its value\n * id + label (e.g. `{ value: \"off\", label: \"Thinking Off\" }` → \"off\"). */\nfunction thoughtLevelPolarity(\n value: AcpRuntimeConfigOptionValue\n): \"on\" | \"off\" | \"other\" {\n const haystack = `${value.value} ${value.label ?? \"\"}`.toLowerCase();\n if (/\\b(off|none|disabled?|no)\\b/.test(haystack)) return \"off\";\n if (/\\b(on|enabled?|high|full|yes)\\b/.test(haystack)) return \"on\";\n return \"other\";\n}\n\n/** Pick the value to set on a \"thinking\" config option for a neutral reasoning\n * token: low-effort → the OFF-like value, high-effort → the ON-like value.\n * Returns undefined when the token isn't an effort signal we recognize, or the\n * option has no value of the needed polarity (caller leaves the option alone).\n * Exported for testing. */\nexport function reasoningValueForThoughtLevel(\n reasoning: string,\n values: ReadonlyArray<AcpRuntimeConfigOptionValue>\n): string | undefined {\n const token = reasoning.toLowerCase();\n const wantOff = LOW_EFFORT_TOKENS.has(token);\n const wantOn = HIGH_EFFORT_TOKENS.has(token);\n if (!wantOff && !wantOn) return undefined;\n const desired = wantOff ? \"off\" : \"on\";\n return values.find((value) => thoughtLevelPolarity(value) === desired)?.value;\n}\n\nfunction buildApprovalRequest(args: {\n params: Record<string, unknown>;\n id: JsonRpcId | undefined;\n threadId: string | undefined;\n session: AcpSessionState | undefined;\n now: () => number;\n}): NormalizedApprovalRequest {\n const toolCall = asRecord(args.params.toolCall) ?? {};\n const title =\n typeof toolCall.title === \"string\" && toolCall.title.trim()\n ? toolCall.title.trim()\n : \"ACP tool call\";\n const toolCallId =\n readString(toolCall, \"toolCallId\") ?? readString(toolCall, \"tool_call_id\");\n const requestId =\n args.id == null ? toolCallId ?? `acp:${args.now()}` : String(args.id);\n const acpKind = typeof toolCall.kind === \"string\" ? toolCall.kind : undefined;\n const approval: NormalizedApprovalRequest = {\n id: requestId,\n method: \"session/request_permission\",\n kind: approvalKindFor(acpKind),\n params: args.params\n };\n approval.summary = acpKind ? `${acpKind}: ${title}` : title;\n return approval;\n}\n\nfunction approvalKindFor(acpKind: string | undefined): NormalizedApprovalRequest[\"kind\"] {\n switch (acpKind) {\n case \"execute\":\n case \"exec\":\n case \"shell\":\n return \"exec\";\n case \"edit\":\n case \"write\":\n return \"patch\";\n case \"read\":\n case \"search\":\n case \"fetch\":\n return \"tool\";\n default:\n return \"other\";\n }\n}\n\ntype AcpPermissionOption = {\n optionId: string;\n name?: string;\n kind?: string;\n};\n\nfunction readPermissionOptions(value: unknown): AcpPermissionOption[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.flatMap((option) => {\n const record = asRecord(option);\n const optionId = readString(record, \"optionId\");\n if (!record || !optionId) {\n return [];\n }\n const normalized: AcpPermissionOption = { optionId };\n const name = readString(record, \"name\");\n if (name !== undefined) normalized.name = name;\n const kind = readString(record, \"kind\");\n if (kind !== undefined) normalized.kind = kind;\n return [normalized];\n });\n}\n\nfunction permissionOutcomeFromDecision(\n decision: NormalizedApprovalDecision,\n options: AcpPermissionOption[]\n): { outcome: { outcome: \"selected\"; optionId: string } | { outcome: \"cancelled\" } } {\n const token = permissionDecisionToken(decision);\n const optionId = selectPermissionOptionId(token, options);\n return optionId\n ? { outcome: { outcome: \"selected\", optionId } }\n : cancelledPermissionOutcome();\n}\n\nfunction cancelledPermissionOutcome(): { outcome: { outcome: \"cancelled\" } } {\n return { outcome: { outcome: \"cancelled\" } };\n}\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nfunction isUuid(value: string | undefined): value is string {\n return value !== undefined && UUID_RE.test(value);\n}\n\nfunction selectPermissionOptionId(\n decision: string,\n options: AcpPermissionOption[]\n): string | undefined {\n const normalized = decision.toLowerCase();\n const exact = options.find((option) =>\n [option.optionId, option.name, option.kind]\n .filter((value): value is string => typeof value === \"string\")\n .some((value) => value.toLowerCase() === normalized)\n );\n if (exact) {\n return exact.optionId;\n }\n if (normalized === \"approve\" || normalized === \"accept\" || normalized === \"allow\") {\n // Prefer the BROADEST allow — a session-wide server allow first (so a host\n // that pre-approves its own MCP tools isn't re-prompted on every call this\n // session), then any allow-always, then allow-once.\n return (\n options.find(\n (option) => option.kind === \"allow_always\" && /server/i.test(option.optionId)\n ) ??\n options.find((option) => option.kind === \"allow_always\") ??\n options.find((option) => option.kind === \"allow_once\") ??\n options.find((option) => option.name?.toLowerCase().includes(\"allow\"))\n )?.optionId;\n }\n if (normalized === \"reject\" || normalized === \"decline\" || normalized === \"deny\") {\n return (\n options.find((option) => option.kind === \"reject_once\") ??\n options.find((option) => option.name?.toLowerCase().includes(\"reject\"))\n )?.optionId;\n }\n return undefined;\n}\n\nfunction textPrompt(text: string): AcpPromptContentBlock[] {\n return [{ type: \"text\", text }];\n}\n\n/** Best-effort image mimeType from a file extension. Falls back to PNG. */\nfunction mimeTypeForImagePath(imagePath: string): string {\n switch (extname(imagePath).toLowerCase()) {\n case \".jpg\":\n case \".jpeg\":\n return \"image/jpeg\";\n case \".gif\":\n return \"image/gif\";\n case \".webp\":\n return \"image/webp\";\n case \".bmp\":\n return \"image/bmp\";\n case \".svg\":\n return \"image/svg+xml\";\n case \".png\":\n default:\n return \"image/png\";\n }\n}\n\n/** Render an unknown thrown value as a readable string. Exported for testing. */\nexport function errorMessage(error: unknown): string {\n if (error === undefined || error === null) return \"Turn failed.\";\n if (error instanceof Error && error.message.trim()) {\n return error.message;\n }\n // JSON-RPC errors reject as PLAIN OBJECTS ({ code, message, data }), not\n // Errors — `String(obj)` is the useless \"[object Object]\". Pull out a readable\n // message (+ code), falling back to a JSON dump, so callers/logs see why the\n // agent refused (e.g. why `session/set_model` was rejected).\n if (error !== null && typeof error === \"object\") {\n const record = error as Record<string, unknown>;\n if (typeof record.message === \"string\" && record.message.trim()) {\n const code = typeof record.code === \"number\" ? ` (${record.code})` : \"\";\n return `${record.message.trim()}${code}`;\n }\n try {\n const json = JSON.stringify(error);\n if (json !== undefined && json !== \"{}\" && json !== \"[]\") return json;\n } catch {\n // non-serializable → fall through\n }\n // An object with nothing useful — return the default rather than letting it\n // reach String(), which would produce the useless \"[object Object]\".\n return \"Turn failed.\";\n }\n const message = String(error).trim();\n return message || \"Turn failed.\";\n}\n\nfunction readString(\n record: Record<string, unknown> | undefined,\n key: string\n): string | undefined {\n const value = record?.[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nconst usageNum = (value: unknown): number | undefined =>\n typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n\n/** Assemble a NormalizedTokenUsage from already-extracted counts, or undefined\n * when neither input nor output is present. */\nfunction assembleUsage(parts: {\n input?: number | undefined;\n output?: number | undefined;\n cached?: number | undefined;\n reasoning?: number | undefined;\n total?: number | undefined;\n}): NormalizedTokenUsage | undefined {\n const { input, output, cached, reasoning, total } = parts;\n if (input === undefined && output === undefined && total === undefined) return undefined;\n const usage: NormalizedTokenUsage = {\n totalTokens: total ?? (input ?? 0) + (output ?? 0)\n };\n if (input !== undefined) usage.inputTokens = input;\n if (output !== undefined) usage.outputTokens = output;\n if (cached !== undefined) usage.cachedInputTokens = cached;\n if (reasoning !== undefined) usage.reasoningOutputTokens = reasoning;\n return usage;\n}\n\n/** Gemini quota shape: `_meta.quota.token_count.{input_tokens,output_tokens,…}`. */\nfunction usageFromGeminiQuota(tokenCount: Record<string, unknown>): NormalizedTokenUsage | undefined {\n return assembleUsage({\n input: usageNum(tokenCount.input_tokens),\n output: usageNum(tokenCount.output_tokens),\n cached: usageNum(tokenCount.cached_input_tokens ?? tokenCount.cached_tokens),\n reasoning: usageNum(tokenCount.thoughts_tokens ?? tokenCount.reasoning_tokens)\n });\n}\n\n/** Generic `usage` object covering both the OpenAI dialect (Grok/xAI, Qwen:\n * `prompt_tokens`/`completion_tokens`, nested `*_tokens_details`) and the\n * Anthropic dialect (`input_tokens`/`output_tokens`, `cache_read_input_tokens`). */\nfunction usageFromGenericUsage(usage: Record<string, unknown>): NormalizedTokenUsage | undefined {\n const promptDetails = asRecord(usage.prompt_tokens_details);\n const completionDetails = asRecord(usage.completion_tokens_details);\n // Accepts snake_case (OpenAI/Anthropic) AND camelCase (Grok/xAI, which reports\n // `inputTokens`/`outputTokens`/`cachedReadTokens`/`reasoningTokens`/`totalTokens`).\n return assembleUsage({\n input: usageNum(usage.prompt_tokens ?? usage.input_tokens ?? usage.inputTokens),\n output: usageNum(usage.completion_tokens ?? usage.output_tokens ?? usage.outputTokens),\n cached: usageNum(\n promptDetails?.cached_tokens ??\n usage.cache_read_input_tokens ??\n usage.cached_tokens ??\n usage.cached_input_tokens ??\n usage.cachedReadTokens ??\n usage.cachedTokens\n ),\n reasoning: usageNum(\n completionDetails?.reasoning_tokens ??\n usage.reasoning_tokens ??\n usage.thoughts_tokens ??\n usage.reasoningTokens\n ),\n total: usageNum(usage.total_tokens ?? usage.totalTokens)\n });\n}\n\n/** Read token usage from a `session/prompt` response. Agents disagree on shape:\n * - Gemini: `_meta.quota.token_count.{input_tokens,output_tokens,…}`\n * - OpenAI dialect (Qwen): `usage.{prompt_tokens,completion_tokens,…}` — at the\n * result root OR under `_meta`.\n * - Anthropic dialect: `usage.{input_tokens,output_tokens,cache_read_input_tokens}`.\n * - Grok/xAI: camelCase counts DIRECTLY on `_meta`\n * (`_meta.{totalTokens,inputTokens,outputTokens,cachedReadTokens,reasoningTokens}`).\n * Returns undefined when nothing recognizable is present. */\nfunction readAcpPromptUsage(result: unknown): NormalizedTokenUsage | undefined {\n const root = asRecord(result);\n const meta = asRecord(root?._meta);\n\n const tokenCount = asRecord(asRecord(meta?.quota)?.token_count);\n if (tokenCount) {\n const fromGemini = usageFromGeminiQuota(tokenCount);\n if (fromGemini) return fromGemini;\n }\n\n // OpenAI / Anthropic `usage` object — at the result root or under `_meta`.\n const usageObj = asRecord(root?.usage) ?? asRecord(meta?.usage);\n if (usageObj) {\n const fromGeneric = usageFromGenericUsage(usageObj);\n if (fromGeneric) return fromGeneric;\n }\n\n // Grok/xAI: the counts sit directly on `_meta` (no nested `usage`/`quota`).\n // usageFromGenericUsage reads only token keys and returns undefined otherwise,\n // so passing the whole `_meta` is safe.\n if (meta) {\n const fromMeta = usageFromGenericUsage(meta);\n if (fromMeta) return fromMeta;\n }\n\n return undefined;\n}\n\n/** Compact description of WHERE usage-like keys live in a prompt response, for a\n * one-line debug log when `readAcpPromptUsage` finds nothing. Never logs values\n * — only the key paths present — so it's safe to emit and reveals a new agent's\n * usage shape without a full payload dump. */\nfunction describeUsageShape(result: unknown): string {\n const root = asRecord(result);\n if (!root) return typeof result;\n const paths: string[] = [];\n const walk = (record: Record<string, unknown>, prefix: string, depth: number): void => {\n for (const [key, value] of Object.entries(record)) {\n const path = prefix ? `${prefix}.${key}` : key;\n if (/token|usage|quota/i.test(key)) paths.push(path);\n const child = asRecord(value);\n if (child && depth < 3) walk(child, path, depth + 1);\n }\n };\n walk(root, \"\", 0);\n return paths.length > 0 ? paths.join(\", \") : `keys: ${Object.keys(root).join(\", \")}`;\n}\n","// The crown jewel: fold the messy, inconsistent ACP `session/update` stream into\n// agent-core's neutral `NormalizedThreadEvent` — the SAME shapes the Codex\n// adapter emits, so a consumer is backend-agnostic.\n//\n// Ported from PwrAgnt acp-session-normalizer.ts, re-targeted off its\n// AppServerThreadReplay onto agent-core NormalizedThreadEvent. Preserves:\n// • camel/snake tolerance on every field (via ./content readers);\n// • recursive content unwrap (readAcpContentText);\n// • agent_message_chunk coalescing — consecutive chunks merge into one\n// message bubble (one itemId); text AFTER a tool call splits a new bubble;\n// • tool_call → tool_call_update merge via agent-core mergeToolCall /\n// preferSpecificLabel, kind inference via inferToolKind;\n// • per-agent behaviors (suppress thoughts, topic→title) read from the\n// STRATEGY's quirks — NO inline per-agent-id branch ever appears here.\n//\n// Stateful per session: one normalizer instance per ACP session, holding the\n// active assistant/thought message ids (for coalescing) and prior tool calls\n// (for delta merge + label reconciliation).\n\nimport {\n mergeToolCall,\n preferSpecificLabel,\n type NormalizedMessage,\n type NormalizedPlan,\n type NormalizedPlanStep,\n type NormalizedThreadEvent,\n type NormalizedToolCall\n} from \"@pwrdrvr/agent-core\";\nimport type { AcpAgentQuirks } from \"../strategies/strategy-types\";\nimport {\n asRecord,\n readContentText,\n readFirstString,\n readKind,\n readString,\n readUpdateText\n} from \"./content\";\nimport { toolCallFromUpdate } from \"./tool-activity\";\n\nexport type AcpNormalizerOptions = {\n /** The agent's normalization quirks (surface thoughts, where title comes from). */\n quirks: AcpAgentQuirks;\n};\n\nexport type AcpNormalizeResult = {\n events: NormalizedThreadEvent[];\n /** A thread title extracted from a topic-update / session-summary, if any. */\n title?: string;\n};\n\nexport type AcpApplyContext = {\n threadId: string;\n turnId: string;\n};\n\nconst EMPTY_RESULT: AcpNormalizeResult = { events: [] };\n\nexport class AcpSessionNormalizer {\n private readonly quirks: AcpAgentQuirks;\n\n // Coalescing state. One \"live\" assistant message bubble at a time; a tool\n // call (or any non-text update) clears it so the next text starts a new one.\n private activeAssistantItemId: string | undefined;\n private assistantText = \"\";\n private assistantSequence = 0;\n\n // Tool-call merge state: id → last fully-merged NormalizedToolCall, so a\n // tool_call_update reconciles labels / fills command output against it.\n private readonly toolCalls = new Map<string, NormalizedToolCall>();\n\n constructor(options: AcpNormalizerOptions) {\n this.quirks = options.quirks;\n }\n\n /** Reset coalescing state at a turn boundary (new prompt / turn finished). */\n resetTurn(): void {\n this.activeAssistantItemId = undefined;\n this.assistantText = \"\";\n }\n\n /** Finalize the in-flight assistant bubble into a terminal `agent_message`, if any. */\n finalizeAssistantMessage(ctx: AcpApplyContext): NormalizedThreadEvent[] {\n if (this.activeAssistantItemId === undefined || this.assistantText === \"\") {\n this.resetTurn();\n return [];\n }\n const message: NormalizedMessage = {\n id: this.activeAssistantItemId,\n role: \"assistant\",\n text: this.assistantText\n };\n this.resetTurn();\n return [\n {\n kind: \"agent_message\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n message\n }\n ];\n }\n\n /** Normalize one ACP session/update into neutral events (+ optional title). */\n apply(update: Record<string, unknown>, ctx: AcpApplyContext): AcpNormalizeResult {\n const kind = readKind(update);\n\n // 1) Title-bearing updates (topic-update / vendor session-summary). Strategy\n // quirks decide which spellings count. Never a transcript event.\n const title = this.extractTitle(update, kind);\n if (title !== undefined) {\n return { events: [], title };\n }\n\n switch (kind) {\n case \"agent_message_chunk\":\n return { events: this.applyAgentMessageChunk(update, ctx) };\n case \"agent_thought_chunk\":\n return { events: this.applyThoughtChunk(update, ctx) };\n case \"user_message_chunk\":\n return { events: this.applyUserMessageChunk(update, ctx) };\n case \"plan\":\n this.activeAssistantItemId = undefined;\n return { events: this.applyPlan(update, ctx) };\n case \"tool_call\":\n case \"tool_call_update\":\n case \"file\":\n case \"terminal\":\n this.activeAssistantItemId = undefined;\n return { events: this.applyToolCall(update, kind, ctx) };\n case \"available_commands_update\":\n case \"current_mode_update\":\n case \"config_option_update\":\n // Runtime metadata, not transcript — the client handles these via\n // runtime-capabilities and emits thread_settings itself.\n return EMPTY_RESULT;\n default:\n // Unknown update: no transcript noise. (PwrAgnt surfaced an \"unknown\n // activity\" entry; in the event model we simply drop it — a consumer\n // that wants raw access can subscribe to the transport observer.)\n this.activeAssistantItemId = undefined;\n return EMPTY_RESULT;\n }\n }\n\n private applyAgentMessageChunk(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n const text = readUpdateText(update) ?? \"\";\n if (text === \"\" || isModeUpdateMarker(text)) {\n return [];\n }\n const itemId = this.assistantItemIdForChunk(update, ctx);\n this.assistantText = appendTranscriptChunk(this.assistantText, text);\n return [\n {\n kind: \"agent_message_delta\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n itemId,\n delta: text\n }\n ];\n }\n\n private applyThoughtChunk(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n if (!this.quirks.surfaceThoughts) {\n return [];\n }\n const text = readUpdateText(update) ?? \"\";\n if (text === \"\") {\n return [];\n }\n // Thoughts coalesce into the same live bubble as message chunks (matching\n // PwrAgnt, which surfaced thoughts as assistant text). In the neutral schema\n // they ride the `reasoning_delta` channel so a consumer can style them.\n const itemId = this.assistantItemIdForChunk(update, ctx);\n this.assistantText = appendTranscriptChunk(this.assistantText, text);\n return [\n {\n kind: \"reasoning_delta\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n itemId,\n delta: text\n }\n ];\n }\n\n private applyUserMessageChunk(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n this.activeAssistantItemId = undefined;\n const text = readUpdateText(update) ?? \"\";\n if (text === \"\") {\n return [];\n }\n const id =\n readFirstString(update, \"messageId\", \"message_id\", \"id\") ??\n `user:${ctx.threadId}:${ctx.turnId}`;\n const message: NormalizedMessage = { id, role: \"user\", text };\n return [\n {\n kind: \"agent_message\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n message\n }\n ];\n }\n\n private applyPlan(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n const id = readString(update, \"planId\") ?? `plan:${ctx.threadId}`;\n const plan: NormalizedPlan = {\n id,\n steps: readPlanSteps(update)\n };\n const explanation = readString(update, \"explanation\");\n if (explanation !== undefined) plan.explanation = explanation;\n const markdown = readString(update, \"markdown\");\n if (markdown !== undefined) plan.markdown = markdown;\n return [{ kind: \"plan_update\", threadId: ctx.threadId, turnId: ctx.turnId, plan }];\n }\n\n private applyToolCall(\n update: Record<string, unknown>,\n kind: string,\n ctx: AcpApplyContext\n ): NormalizedThreadEvent[] {\n const incoming = toolCallFromUpdate(update, kind, ctx.threadId);\n const prev = this.toolCalls.get(incoming.id);\n if (prev === undefined) {\n this.toolCalls.set(incoming.id, incoming);\n return [\n { kind: \"tool_call\", threadId: ctx.threadId, turnId: ctx.turnId, toolCall: incoming }\n ];\n }\n // Subsequent update: merge via agent-core (label reconciliation, command\n // detail fill, later-status-wins) and emit a tool_call_update delta.\n const merged = mergeToolCall(prev, incoming);\n // agent-core merges command detail shallowly (later displayCommand wins);\n // reconcile it with the same prefer-specific rule the label uses, so a\n // later output-only update keeps the earlier specific displayCommand.\n if (merged.command && prev.command) {\n merged.command = {\n ...merged.command,\n displayCommand: preferSpecificLabel(\n prev.command.displayCommand,\n merged.command.displayCommand\n )\n };\n }\n this.toolCalls.set(incoming.id, merged);\n return [\n {\n kind: \"tool_call_update\",\n threadId: ctx.threadId,\n turnId: ctx.turnId,\n toolCall: merged\n }\n ];\n }\n\n private assistantItemIdForChunk(\n update: Record<string, unknown>,\n ctx: AcpApplyContext\n ): string {\n const explicitId = readFirstString(update, \"messageId\", \"message_id\");\n if (explicitId) {\n if (explicitId !== this.activeAssistantItemId) {\n this.activeAssistantItemId = explicitId;\n this.assistantText = \"\";\n }\n return explicitId;\n }\n if (this.activeAssistantItemId === undefined) {\n this.activeAssistantItemId = `assistant:${ctx.turnId}:${this.assistantSequence++}`;\n this.assistantText = \"\";\n }\n return this.activeAssistantItemId;\n }\n\n /** Strategy-driven title extraction. NO agent-id literal — reads quirks.titleFrom. */\n private extractTitle(\n update: Record<string, unknown>,\n kind: string\n ): string | undefined {\n const wantsSummary =\n this.quirks.titleFrom === \"session-summary\" || this.quirks.titleFrom === \"both\";\n const wantsTopic =\n this.quirks.titleFrom === \"topic-update\" || this.quirks.titleFrom === \"both\";\n\n if (wantsSummary && kind === \"session_summary_generated\") {\n const summary = (\n readString(update, \"session_summary\") ?? readString(update, \"sessionSummary\")\n )?.trim();\n return summary || undefined;\n }\n\n if (wantsTopic) {\n const isToolish =\n kind === \"tool_call\" || kind === \"tool_call_update\" || kind === \"think\";\n if (!isToolish) {\n return undefined;\n }\n const titleText = readString(update, \"title\")?.trim();\n if (!titleText) {\n return undefined;\n }\n const quoted = /^Update topic to:\\s*[\"“](.+?)[\"”]\\s*$/iu.exec(titleText);\n const fallback = /^Update topic to:\\s*(.+)$/iu.exec(titleText);\n const topic = (quoted?.[1] ?? fallback?.[1])?.trim();\n return topic || undefined;\n }\n\n return undefined;\n }\n}\n\n// Consecutive ACP text chunks concatenate, but a markdown heading / bold lead\n// that starts a new block gets a paragraph break so bubbles read correctly.\nfunction appendTranscriptChunk(existing: string, next: string): string {\n if (!existing || !next) {\n return `${existing}${next}`;\n }\n if (shouldSeparateTranscriptChunks(existing, next)) {\n return `${existing}\\n\\n${next}`;\n }\n return `${existing}${next}`;\n}\n\nfunction shouldSeparateTranscriptChunks(existing: string, next: string): boolean {\n if (/\\s$/.test(existing)) {\n return false;\n }\n return /^(?:#{1,6}\\s|\\*\\*[^*]+?\\*\\*(?:\\s|$))/.test(next);\n}\n\nfunction isModeUpdateMarker(text: string): boolean {\n return /^\\[MODE_UPDATE\\]\\s*[A-Za-z0-9_-]+\\s*$/.test(text.trim());\n}\n\nfunction readPlanSteps(record: Record<string, unknown>): NormalizedPlanStep[] {\n const steps = Array.isArray(record.steps) ? record.steps : [];\n return steps.flatMap((step): NormalizedPlanStep[] => {\n if (typeof step === \"string\") {\n return [{ step, status: \"pending\" }];\n }\n const stepRecord = asRecord(step);\n if (!stepRecord) {\n return [];\n }\n const text = readString(stepRecord, \"step\") ?? readString(stepRecord, \"content\");\n if (!text) {\n return [];\n }\n const status = readString(stepRecord, \"status\");\n return [\n {\n step: text,\n status: status === \"in_progress\" || status === \"completed\" ? status : \"pending\"\n }\n ];\n });\n}\n\n/** Read the message parts (text/image) of a prompt, camel/snake tolerant. */\nexport function readPromptText(content: unknown): string | undefined {\n return readContentText({ content }, \"content\");\n}\n","// camel/snake-tolerant readers + recursive ACP content unwrapping. ACP agents\n// are wildly inconsistent: the same field arrives camelCase from one agent and\n// snake_case from another, and content blocks nest arbitrarily\n// (`content` → `[{ type: \"content\", content: { type: \"text\", text } }]`).\n// Every reader here tolerates both casings and unwraps recursively.\n\nexport function asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nexport function readString(\n record: Record<string, unknown> | undefined,\n key: string\n): string | undefined {\n const value = record?.[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nexport function readNonEmptyString(\n record: Record<string, unknown> | undefined,\n key: string\n): string | undefined {\n const value = record?.[key];\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nexport function readNumber(\n record: Record<string, unknown> | undefined,\n key: string\n): number | undefined {\n const value = record?.[key];\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nexport function readBoolean(\n record: Record<string, unknown> | undefined,\n key: string\n): boolean | undefined {\n const value = record?.[key];\n return typeof value === \"boolean\" ? value : undefined;\n}\n\n/**\n * Read the first defined string among the given keys, in order. Used for\n * camel/snake parity (`toolCallId` vs `tool_call_id`).\n */\nexport function readFirstString(\n record: Record<string, unknown> | undefined,\n ...keys: string[]\n): string | undefined {\n for (const key of keys) {\n const value = readString(record, key);\n if (value !== undefined) return value;\n }\n return undefined;\n}\n\n/** The session-update kind, tolerant of all four key spellings. */\nexport function readKind(update: Record<string, unknown>): string {\n return (\n readString(update, \"sessionUpdate\") ??\n readString(update, \"session_update\") ??\n readString(update, \"kind\") ??\n readString(update, \"type\") ??\n \"unknown\"\n );\n}\n\n/**\n * Recursively unwrap an ACP content value to plain text. Handles a bare string,\n * an array of content blocks (joined with newlines), and nested\n * `{ type:\"text\", text }` / `{ content }` / `{ text }` / `{ output }` /\n * `{ result }` shapes.\n */\nexport function readAcpContentText(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (Array.isArray(value)) {\n const parts = value\n .map((item) => readAcpContentText(item))\n .filter((item): item is string => Boolean(item));\n return parts.length > 0 ? parts.join(\"\\n\") : undefined;\n }\n\n const content = asRecord(value);\n if (!content) {\n return undefined;\n }\n\n if (content.type === \"text\" && typeof content.text === \"string\") {\n return content.text;\n }\n return (\n readAcpContentText(content.content) ??\n readAcpContentText(content.text) ??\n readAcpContentText(content.output) ??\n readAcpContentText(content.result)\n );\n}\n\nexport function readContentText(\n record: Record<string, unknown>,\n key: string\n): string | undefined {\n return readAcpContentText(record[key]);\n}\n\n/** Tool output, checked across all the spellings agents use. */\nexport function readToolOutput(record: Record<string, unknown>): string | undefined {\n return (\n readString(record, \"output\") ??\n readString(record, \"stdout\") ??\n readString(record, \"stderr\") ??\n readString(record, \"result\") ??\n readContentText(record, \"content\")\n );\n}\n\n/** First location path from an ACP `locations: [{ path }]` array. */\nexport function readFirstLocationPath(\n record: Record<string, unknown>\n): string | undefined {\n const locations = record.locations ?? record.location;\n if (!Array.isArray(locations)) {\n return undefined;\n }\n for (const location of locations) {\n const path = readString(asRecord(location), \"path\");\n if (path && path.trim()) {\n return path;\n }\n }\n return undefined;\n}\n\n/** The assistant/user text carried by a chunk update (camel/snake tolerant). */\nexport function readUpdateText(update: Record<string, unknown>): string | undefined {\n return (\n readString(update, \"text\") ??\n readString(update, \"outputText\") ??\n readString(update, \"output_text\") ??\n readContentText(update, \"content\")\n );\n}\n","// ACP tool_call / tool_call_update / file / terminal → agent-core\n// NormalizedToolCall. Reuses agent-core's `inferToolKind` for kind inference and\n// `mergeToolCall` / `preferSpecificLabel` for delta merging, so ACP tool-call\n// streams merge identically to Codex's.\n\nimport {\n inferToolKind,\n type NormalizedCommandDetail,\n type NormalizedToolCall,\n type NormalizedToolKind,\n type NormalizedToolLocation,\n type NormalizedToolStatus\n} from \"@pwrdrvr/agent-core\";\nimport {\n asRecord,\n readContentText,\n readFirstLocationPath,\n readFirstString,\n readNumber,\n readString,\n readToolOutput\n} from \"./content\";\n\n/** Read the tool-call correlation id across every spelling agents use. */\nexport function readToolCallId(\n update: Record<string, unknown>,\n kind: string,\n sessionId: string\n): string {\n return (\n readFirstString(\n update,\n \"toolCallId\",\n \"tool_call_id\",\n \"id\",\n \"itemId\",\n \"item_id\"\n ) ?? `${kind}:${sessionId}`\n );\n}\n\n/** Map an ACP status string onto a NormalizedToolStatus (pending → in_progress). */\nfunction normalizeStatus(status: string | undefined): NormalizedToolStatus | undefined {\n switch (status) {\n case \"completed\":\n case \"failed\":\n case \"cancelled\":\n case \"in_progress\":\n return status;\n case \"pending\":\n return \"in_progress\";\n default:\n return undefined;\n }\n}\n\n/**\n * Choose the tool kind. ACP carries an explicit `kind` on tool calls\n * (read/edit/write/execute/search/…); when present it maps directly, otherwise\n * we fall back to agent-core's name-based `inferToolKind` over the label, and to\n * a command/read heuristic.\n */\nfunction toolKindFor(\n acpKind: string | undefined,\n command: string | undefined,\n path: string | undefined,\n label: string\n): NormalizedToolKind {\n switch (acpKind) {\n case \"edit\":\n case \"write\":\n return \"write\";\n case \"execute\":\n case \"exec\":\n case \"shell\":\n return \"command\";\n case \"read\":\n return \"read\";\n case \"search\":\n return \"search\";\n case \"fetch\":\n return \"fetch\";\n default:\n break;\n }\n if (command) return \"command\";\n const inferred = inferToolKind(label);\n if (inferred !== \"other\") return inferred;\n // A tool with a file path but no other signal is a read; otherwise unknown.\n return path ? \"read\" : \"other\";\n}\n\n/**\n * Normalize one ACP tool-ish update (tool_call / tool_call_update / file /\n * terminal) into a NormalizedToolCall. The result is fed to the normalizer's\n * upsert, which merges deltas with the same id via agent-core's `mergeToolCall`.\n */\nexport function toolCallFromUpdate(\n update: Record<string, unknown>,\n kind: string,\n sessionId: string\n): NormalizedToolCall {\n const id = readToolCallId(update, kind, sessionId);\n const label =\n readString(update, \"title\") ??\n readString(update, \"name\") ??\n readString(update, \"kind\") ??\n kind.replaceAll(\"_\", \" \");\n const acpKind = readString(update, \"kind\");\n const path = readString(update, \"path\") ?? readFirstLocationPath(update);\n const command = readString(update, \"command\");\n const output = readToolOutput(update);\n const exitCode = readNumber(update, \"exitCode\") ?? readNumber(update, \"exit_code\");\n const status = normalizeStatus(readString(update, \"status\"));\n const toolKind = toolKindFor(acpKind, command, path, label);\n\n const call: NormalizedToolCall = {\n id,\n name: readString(update, \"name\") ?? acpKind ?? label,\n kind: toolKind,\n label,\n status: status ?? \"in_progress\",\n args: readToolArgs(update)\n };\n\n if (output !== undefined) {\n call.result = output;\n }\n\n // Preserve the file(s) a read/write/file tool touched (ACP `locations`) so a\n // consumer can show the path. Lossless: ALL locations, not just the first.\n const locations = readToolLocations(update);\n if (locations.length > 0) {\n call.locations = locations;\n }\n\n // Build a command detail ONLY for genuine command tools — i.e. when the update\n // carries a command string or an exit code. A `read` returning file content\n // has `output` but no command/exitCode, so its output stays on `result` (not\n // folded into a fake command) and its path rides `locations`. An explicit\n // display target is used only when the update names one, so a later output-\n // only update never clobbers an earlier specific displayCommand on merge.\n const explicitDisplay = command ?? readString(update, \"title\");\n if (command !== undefined || exitCode !== undefined) {\n const detail: NormalizedCommandDetail = {\n displayCommand: explicitDisplay ?? label\n };\n if (command !== undefined) detail.rawCommand = command;\n if (output !== undefined) detail.output = output;\n if (exitCode !== undefined) detail.exitCode = exitCode;\n call.command = detail;\n }\n\n return call;\n}\n\n/** Read all ACP tool-call `locations` ({ path, line? }), dropping entries with\n * no path. The ACP field is `locations: [{ path, line? }]`. */\nfunction readToolLocations(update: Record<string, unknown>): NormalizedToolLocation[] {\n const raw = update.locations;\n if (!Array.isArray(raw)) return [];\n const out: NormalizedToolLocation[] = [];\n for (const item of raw) {\n const record = asRecord(item);\n const path = record ? readString(record, \"path\") : undefined;\n if (path === undefined) continue;\n const location: NormalizedToolLocation = { path };\n const line = record ? readNumber(record, \"line\") : undefined;\n if (line !== undefined) location.line = line;\n out.push(location);\n }\n return out;\n}\n\nfunction readToolArgs(update: Record<string, unknown>): unknown {\n const raw =\n update.rawInput ??\n update.raw_input ??\n update.input ??\n update.arguments ??\n update.args;\n return asRecord(raw) ?? (raw === undefined ? undefined : raw);\n}\n\n/** Tool output text from a content array, for permission prompts. */\nexport function readToolContentText(value: unknown): string | undefined {\n return readContentText({ content: value }, \"content\");\n}\n","// ACP runtime capabilities: the models, modes, and config-options an agent\n// advertises at `initialize` / `session/new` / `session/load`, and how those\n// merge over the initialize snapshot. These are package-internal metadata\n// surfaced through client callbacks (NOT a NormalizedThreadEvent) — a host that\n// renders a model/mode picker reads them. camel/snake tolerant throughout, and\n// new data merges OVER the initialize snapshot without dropping prior fields.\n//\n// Ported from PwrAgnt acp-runtime-capabilities.ts, retargeted off @pwragent/shared\n// onto neutral local types.\n\nimport { asRecord, readBoolean, readString } from \"./content\";\n\nexport type AcpRuntimeConfigOptionValue = {\n value: string;\n label?: string;\n description?: string;\n};\n\nexport type AcpRuntimeConfigOption = {\n id: string;\n label: string;\n description?: string;\n type: \"select\";\n category?: string;\n currentValue?: string;\n values: AcpRuntimeConfigOptionValue[];\n};\n\nexport type AcpRuntimeMode = {\n id: string;\n label: string;\n description?: string;\n};\n\nexport type AcpRuntimeModel = {\n id: string;\n label?: string;\n description?: string;\n /** True when this is the model the agent reports as current/default\n * (`currentModelId`). At most one model in a list is flagged; absent when the\n * agent advertises models but no current id. A host can pre-select this and\n * render it as the \"(default)\" option. */\n isDefault?: boolean;\n};\n\nexport type AcpRuntimeModes = {\n availableModes: AcpRuntimeMode[];\n currentModeId?: string;\n};\n\nexport type AcpRuntimeModels = {\n availableModels: AcpRuntimeModel[];\n currentModelId?: string;\n};\n\nexport type AcpRuntimeAgentInfo = {\n name?: string;\n title?: string;\n version?: string;\n};\n\nexport type AcpRuntimeMcpCapabilities = {\n http?: boolean;\n sse?: boolean;\n};\n\nexport type AcpRuntimeAgentCapabilities = {\n loadSession?: boolean;\n mcp?: AcpRuntimeMcpCapabilities;\n sessionHistoryReplay?: boolean;\n session?: { close?: boolean; cancel?: boolean };\n raw?: unknown;\n};\n\nexport type AcpRuntimeCapabilitiesSource =\n | \"initialize\"\n | \"session-new\"\n | \"session-load\";\n\nexport type AcpRuntimeCapabilities = {\n source: AcpRuntimeCapabilitiesSource;\n discoveredAt: number;\n checkedAt: number;\n protocolVersion?: number;\n agentInfo?: AcpRuntimeAgentInfo;\n agentCapabilities?: AcpRuntimeAgentCapabilities;\n configOptions?: AcpRuntimeConfigOption[];\n modes?: AcpRuntimeModes;\n models?: AcpRuntimeModels;\n};\n\nexport type AcpSessionRuntimeState = {\n updatedAt?: number;\n currentModeId?: string;\n currentModelId?: string;\n configValues?: Record<string, string>;\n};\n\nexport function normalizeAcpRuntimeCapabilities(params: {\n value: unknown;\n now: number;\n source: AcpRuntimeCapabilitiesSource;\n initialize?: AcpRuntimeCapabilities;\n}): AcpRuntimeCapabilities | undefined {\n const record = asRecord(params.value);\n if (!record) {\n return params.initialize;\n }\n\n const configOptions = readConfigOptions(record.configOptions ?? record.config_options);\n const modes = readModes(record.modes);\n const models = readModels(record.models);\n const agentCapabilities = readAgentCapabilities(\n record.agentCapabilities ?? record.agent_capabilities ?? record.capabilities,\n record.sessionCapabilities ?? record.session_capabilities\n );\n const agentInfo = readAgentInfo(record.agentInfo ?? record.agent_info);\n const protocolVersion =\n typeof record.protocolVersion === \"number\"\n ? record.protocolVersion\n : typeof record.protocol_version === \"number\"\n ? record.protocol_version\n : params.initialize?.protocolVersion;\n\n const hasRuntimeData =\n configOptions.length > 0 ||\n Boolean(modes) ||\n Boolean(models) ||\n Boolean(agentCapabilities) ||\n Boolean(agentInfo) ||\n typeof protocolVersion === \"number\";\n\n if (!hasRuntimeData && !params.initialize) {\n return undefined;\n }\n\n const merged: AcpRuntimeCapabilities = {\n source: params.source,\n discoveredAt: params.initialize?.discoveredAt ?? params.now,\n checkedAt: params.now\n };\n if (typeof protocolVersion === \"number\") merged.protocolVersion = protocolVersion;\n\n if (agentInfo ?? params.initialize?.agentInfo) {\n merged.agentInfo = { ...params.initialize?.agentInfo, ...agentInfo };\n }\n if (agentCapabilities ?? params.initialize?.agentCapabilities) {\n merged.agentCapabilities = {\n ...params.initialize?.agentCapabilities,\n ...agentCapabilities\n };\n }\n if (configOptions.length > 0) {\n merged.configOptions = configOptions;\n } else if (params.initialize?.configOptions) {\n merged.configOptions = params.initialize.configOptions;\n }\n if (modes) {\n merged.modes = modes;\n } else if (params.initialize?.modes) {\n merged.modes = params.initialize.modes;\n }\n if (models) {\n merged.models = models;\n } else if (params.initialize?.models) {\n merged.models = params.initialize.models;\n }\n\n return merged;\n}\n\nexport function acpRuntimeSupportsSessionLoad(\n capabilities: AcpRuntimeCapabilities | undefined\n): boolean {\n return capabilities?.agentCapabilities?.loadSession !== false;\n}\n\n/** Optional ACP MCP transports are supported only when explicitly advertised. */\nexport function acpRuntimeSupportsHttpMcp(\n capabilities: AcpRuntimeCapabilities | undefined\n): boolean {\n return capabilities?.agentCapabilities?.mcp?.http === true;\n}\n\n/** Optional ACP MCP transports are supported only when explicitly advertised. */\nexport function acpRuntimeSupportsSseMcp(\n capabilities: AcpRuntimeCapabilities | undefined\n): boolean {\n return capabilities?.agentCapabilities?.mcp?.sse === true;\n}\n\n/** The configOption an agent uses to expose model choice (ACP `category:\n * \"model\"`, falling back to a literal `model` id). Some agents (e.g. Kimi)\n * advertise the active model HERE rather than via top-level\n * `models.currentModelId`. */\nexport function modelConfigOption(\n capabilities: AcpRuntimeCapabilities | undefined\n): AcpRuntimeConfigOption | undefined {\n return capabilities?.configOptions?.find(\n (option) => option.category === \"model\" || option.id === \"model\"\n );\n}\n\n/** The effective model id the agent will run with, agnostic of HOW it advertises\n * it. Prefers a protocol-confirmed `models.currentModelId`; falls back to the\n * `model` configOption's `currentValue` for agents that expose model choice as a\n * config option (Kimi). Returns undefined when the agent advertises no model at\n * all — callers report that as \"no model\" rather than inventing one. */\nexport function modelIdFromCapabilities(\n capabilities: AcpRuntimeCapabilities | undefined\n): string | undefined {\n return capabilities?.models?.currentModelId ?? modelConfigOption(capabilities)?.currentValue;\n}\n\n/** The full model list a host can render/cache, agnostic of advertisement style.\n * Returns `models.availableModels` when present; otherwise derives the list from\n * the `model` configOption's values (Kimi), preserving labels/descriptions and\n * flagging the current value as default. `[]` when no model is advertised. */\nexport function modelsFromCapabilities(\n capabilities: AcpRuntimeCapabilities | undefined\n): AcpRuntimeModel[] {\n const advertised = capabilities?.models?.availableModels;\n if (advertised !== undefined && advertised.length > 0) return advertised;\n const option = modelConfigOption(capabilities);\n if (option === undefined) return [];\n return option.values.map((value) => ({\n id: value.value,\n ...(value.label !== undefined ? { label: value.label } : {}),\n ...(value.description !== undefined ? { description: value.description } : {}),\n ...(option.currentValue === value.value ? { isDefault: true } : {})\n }));\n}\n\nexport function acpSessionRuntimeStateFromCapabilities(\n capabilities: AcpRuntimeCapabilities | undefined,\n now: number\n): AcpSessionRuntimeState | undefined {\n if (!capabilities) {\n return undefined;\n }\n const configValues = Object.fromEntries(\n (capabilities.configOptions ?? []).flatMap((option) =>\n typeof option.currentValue === \"string\"\n ? [[option.id, option.currentValue] as const]\n : []\n )\n );\n const state: AcpSessionRuntimeState = { updatedAt: now };\n if (Object.keys(configValues).length > 0) state.configValues = configValues;\n if (capabilities.modes?.currentModeId) {\n state.currentModeId = capabilities.modes.currentModeId;\n }\n if (capabilities.models?.currentModelId) {\n state.currentModelId = capabilities.models.currentModelId;\n }\n return Object.keys(state).length > 1 ? state : undefined;\n}\n\n/** Runtime-state change carried inside a session/update (mode/model/config). */\nexport function acpSessionRuntimeStateFromUpdate(\n update: Record<string, unknown>,\n now: number\n): AcpSessionRuntimeState | undefined {\n const kind =\n readString(update, \"sessionUpdate\") ??\n readString(update, \"session_update\") ??\n readString(update, \"kind\") ??\n readString(update, \"type\");\n if (kind === \"agent_message_chunk\") {\n const modeId = readModeUpdateMarker(update);\n return modeId ? { currentModeId: modeId, updatedAt: now } : undefined;\n }\n if (kind === \"current_mode_update\") {\n const currentModeId =\n readString(update, \"currentModeId\") ??\n readString(update, \"current_mode_id\") ??\n readString(update, \"modeId\") ??\n readString(update, \"mode_id\") ??\n readString(update, \"id\");\n return currentModeId ? { currentModeId, updatedAt: now } : undefined;\n }\n if (kind === \"config_option_update\") {\n const configOption = asRecord(update.configOption ?? update.config_option) ?? update;\n const id =\n readString(configOption, \"id\") ??\n readString(configOption, \"configOptionId\") ??\n readString(configOption, \"configId\");\n const value =\n readString(configOption, \"currentValue\") ?? readString(configOption, \"value\");\n return id && value ? { configValues: { [id]: value }, updatedAt: now } : undefined;\n }\n return undefined;\n}\n\nexport function mergeAcpRuntimeState(\n existing: AcpSessionRuntimeState | undefined,\n update: AcpSessionRuntimeState\n): AcpSessionRuntimeState {\n return {\n ...existing,\n ...update,\n configValues: {\n ...(existing?.configValues ?? {}),\n ...(update.configValues ?? {})\n }\n };\n}\n\n/** Resolve the human-facing label for a mode id from the capabilities snapshot. */\nexport function modeLabelFor(\n capabilities: AcpRuntimeCapabilities | undefined,\n modeId: string\n): string | undefined {\n return capabilities?.modes?.availableModes.find((mode) => mode.id === modeId)?.label;\n}\n\nfunction readModeUpdateMarker(update: Record<string, unknown>): string | undefined {\n const text = readString(update, \"content\") ?? readString(update, \"text\");\n const match = text?.trim().match(/^\\[MODE_UPDATE\\]\\s*([A-Za-z0-9_-]+)\\s*$/);\n return match?.[1];\n}\n\nfunction readConfigOptions(value: unknown): AcpRuntimeConfigOption[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.flatMap((item) => {\n const record = asRecord(item);\n const id =\n readString(record, \"id\") ??\n readString(record, \"configOptionId\") ??\n readString(record, \"configId\");\n if (!record || !id) {\n return [];\n }\n const values = readConfigOptionValues(record.values ?? record.options);\n if (values.length === 0) {\n return [];\n }\n const option: AcpRuntimeConfigOption = {\n id,\n label:\n readString(record, \"name\") ??\n readString(record, \"label\") ??\n readString(record, \"title\") ??\n id,\n type: \"select\",\n values\n };\n const description = readString(record, \"description\");\n if (description !== undefined) option.description = description;\n const category = readString(record, \"category\");\n if (category !== undefined) option.category = category;\n const currentValue =\n readString(record, \"currentValue\") ?? readString(record, \"value\");\n if (currentValue !== undefined) option.currentValue = currentValue;\n return [option];\n });\n}\n\nfunction readConfigOptionValues(value: unknown): AcpRuntimeConfigOptionValue[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.flatMap((item) => {\n const record = asRecord(item);\n const optionValue =\n readString(record, \"value\") ??\n readString(record, \"id\") ??\n readString(record, \"optionId\");\n if (!record || !optionValue) {\n return [];\n }\n const normalized: AcpRuntimeConfigOptionValue = { value: optionValue };\n const label =\n readString(record, \"name\") ??\n readString(record, \"label\") ??\n readString(record, \"title\");\n if (label !== undefined) normalized.label = label;\n const description = readString(record, \"description\");\n if (description !== undefined) normalized.description = description;\n return [normalized];\n });\n}\n\nfunction readModes(value: unknown): AcpRuntimeModes | undefined {\n const record = asRecord(value);\n const modes = Array.isArray(record?.availableModes)\n ? record.availableModes.flatMap(readMode)\n : [];\n if (modes.length === 0) {\n return undefined;\n }\n const result: AcpRuntimeModes = { availableModes: modes };\n const currentModeId = readString(record, \"currentModeId\");\n if (currentModeId !== undefined) result.currentModeId = currentModeId;\n return result;\n}\n\nfunction readMode(value: unknown): AcpRuntimeMode[] {\n const record = asRecord(value);\n const id = readString(record, \"id\") ?? readString(record, \"modeId\");\n if (!record || !id) {\n return [];\n }\n const mode: AcpRuntimeMode = {\n id,\n label: readString(record, \"name\") ?? readString(record, \"label\") ?? id\n };\n const description = readString(record, \"description\");\n if (description !== undefined) mode.description = description;\n return [mode];\n}\n\nfunction readModels(value: unknown): AcpRuntimeModels | undefined {\n const record = asRecord(value);\n const models = Array.isArray(record?.availableModels)\n ? record.availableModels.flatMap(readModel)\n : [];\n if (models.length === 0) {\n return undefined;\n }\n const result: AcpRuntimeModels = { availableModels: models };\n const currentModelId =\n readString(record, \"currentModelId\") ?? readString(record, \"modelId\");\n if (currentModelId !== undefined) {\n result.currentModelId = currentModelId;\n // Flag the agent's protocol-confirmed default so a host can pre-select it\n // and label it \"(default)\" without re-deriving from currentModelId.\n const defaultModel = models.find((model) => model.id === currentModelId);\n if (defaultModel) defaultModel.isDefault = true;\n }\n return result;\n}\n\nfunction readModel(value: unknown): AcpRuntimeModel[] {\n const record = asRecord(value);\n const id = readString(record, \"modelId\") ?? readString(record, \"id\");\n if (!record || !id) {\n return [];\n }\n const model: AcpRuntimeModel = { id };\n const label = readString(record, \"name\") ?? readString(record, \"label\");\n if (label !== undefined) model.label = label;\n const description = readString(record, \"description\");\n if (description !== undefined) model.description = description;\n return [model];\n}\n\nfunction readAgentCapabilities(\n value: unknown,\n sessionCapabilitiesValue?: unknown\n): AcpRuntimeAgentCapabilities | undefined {\n const record = asRecord(value);\n const sessionCapabilities = asRecord(sessionCapabilitiesValue);\n const sessionMeta = asRecord(sessionCapabilities?._meta);\n const kimiMeta = asRecord(sessionMeta?.kimi);\n if (!record && !sessionCapabilities) {\n return undefined;\n }\n const loadSession =\n readBoolean(record, \"loadSession\") ??\n readBoolean(record, \"load_session\") ??\n readBoolean(asRecord(record?.session), \"load\");\n const close = readBoolean(asRecord(record?.session), \"close\");\n const cancel = readBoolean(asRecord(record?.session), \"cancel\");\n const sessionHistoryReplay =\n readBoolean(kimiMeta, \"sessionHistoryReplay\") ??\n readBoolean(kimiMeta, \"session_history_replay\");\n const mcpRecord = asRecord(\n record?.mcpCapabilities ?? record?.mcp_capabilities ?? record?.mcp\n );\n const http = readBoolean(mcpRecord, \"http\");\n const sse = readBoolean(mcpRecord, \"sse\");\n\n const capabilities: AcpRuntimeAgentCapabilities = {\n raw: record ?? sessionCapabilities\n };\n if (loadSession !== undefined) capabilities.loadSession = loadSession;\n if (http !== undefined || sse !== undefined) {\n capabilities.mcp = {\n ...(http !== undefined ? { http } : {}),\n ...(sse !== undefined ? { sse } : {})\n };\n }\n if (sessionHistoryReplay !== undefined) {\n capabilities.sessionHistoryReplay = sessionHistoryReplay;\n }\n if (close !== undefined || cancel !== undefined) {\n capabilities.session = {\n ...(close !== undefined ? { close } : {}),\n ...(cancel !== undefined ? { cancel } : {})\n };\n }\n return capabilities;\n}\n\nfunction readAgentInfo(value: unknown): AcpRuntimeAgentInfo | undefined {\n const record = asRecord(value);\n if (!record) {\n return undefined;\n }\n const agentInfo: AcpRuntimeAgentInfo = {};\n const name = readString(record, \"name\");\n if (name !== undefined) agentInfo.name = name;\n const title = readString(record, \"title\");\n if (title !== undefined) agentInfo.title = title;\n const version = readString(record, \"version\");\n if (version !== undefined) agentInfo.version = version;\n return Object.keys(agentInfo).length > 0 ? agentInfo : undefined;\n}\n","import type { McpServer } from \"@agentclientprotocol/sdk\";\n\n/** ACP key/value entry used by stdio environments and HTTP headers. */\nexport type AcpMcpKeyValue = {\n name: string;\n value: string;\n};\n\n/** Host-friendly collection accepted wherever ACP requires key/value entries. */\nexport type AcpMcpKeyValueCollection =\n | Readonly<Record<string, string>>\n | readonly AcpMcpKeyValue[];\n\n/** Backward-compatible stdio MCP configuration. ACP stdio has no `type` field. */\nexport type AcpStdioMcpServerConfig = {\n name: string;\n command: string;\n args?: readonly string[];\n env?: AcpMcpKeyValueCollection;\n};\n\n/** Streamable HTTP MCP configuration from the ACP v1 schema. */\nexport type AcpHttpMcpServerConfig = {\n name: string;\n type: \"http\";\n url: string;\n headers: AcpMcpKeyValueCollection;\n};\n\n/** Legacy HTTP+SSE MCP configuration from the ACP v1 schema. */\nexport type AcpSseMcpServerConfig = {\n name: string;\n type: \"sse\";\n url: string;\n headers: AcpMcpKeyValueCollection;\n};\n\n/** Public MCP input accepted by agent-acp session lifecycle methods. */\nexport type AcpMcpServerConfig =\n | AcpStdioMcpServerConfig\n | AcpHttpMcpServerConfig\n | AcpSseMcpServerConfig;\n\n/** Exact MCP server wire union from the pinned ACP protocol library. */\nexport type AcpMcpServerWireConfig = McpServer;\n\nfunction isKeyValueArray(\n collection: AcpMcpKeyValueCollection\n): collection is readonly AcpMcpKeyValue[] {\n return Array.isArray(collection);\n}\n\nfunction normalizeKeyValues(\n collection: AcpMcpKeyValueCollection | undefined\n): AcpMcpKeyValue[] {\n if (collection === undefined) return [];\n if (isKeyValueArray(collection)) {\n return collection.map(({ name, value }) => ({ name, value }));\n }\n return Object.entries(collection).map(([name, value]) => ({ name, value }));\n}\n\n/** Serialize a host-friendly config into the exact ACP v1 wire representation. */\nexport function normalizeAcpMcpServerConfig(\n server: AcpMcpServerConfig\n): AcpMcpServerWireConfig {\n if (\"type\" in server) {\n return {\n name: server.name,\n type: server.type,\n url: server.url,\n headers: normalizeKeyValues(server.headers)\n };\n }\n return {\n name: server.name,\n command: server.command,\n args: [...(server.args ?? [])],\n env: normalizeKeyValues(server.env)\n };\n}\n\n/** Serialize a per-session list without retaining mutable caller collections. */\nexport function normalizeAcpMcpServerConfigs(\n servers: readonly AcpMcpServerConfig[]\n): AcpMcpServerWireConfig[] {\n return servers.map(normalizeAcpMcpServerConfig);\n}\n\n/**\n * Remove credential-bearing MCP values from a lifecycle error. The server URL\n * is redacted in full because it may carry user-info or query credentials.\n */\nexport function redactAcpMcpCredentials(\n message: string,\n servers: readonly AcpMcpServerConfig[]\n): string {\n const secrets = new Set<string>();\n for (const server of servers) {\n const values =\n \"type\" in server\n ? [server.url, ...normalizeKeyValues(server.headers).map(({ value }) => value)]\n : normalizeKeyValues(server.env).map(({ value }) => value);\n for (const value of values) {\n if (value.length > 0) secrets.add(value);\n }\n }\n let redacted = message;\n for (const secret of [...secrets].sort((a, b) => b.length - a.length)) {\n redacted = redacted.split(secret).join(\"[REDACTED]\");\n }\n return redacted;\n}\n","// Lifecycle pool for `AcpAgentClient`. An ACP agent is a long-lived OS process\n// with a stdio connection, and ONE client can host many concurrent sessions\n// (threads). Without pooling, every consumer (each chat surface, enrichment,\n// the model-lister) news up its own client → its own process; a careless React\n// caller can spawn dozens. The pool gives every caller the SAME warmed client\n// for a key, dedups concurrent warm-ups onto one spawn, and owns teardown.\n//\n// const pool = new AcpAgentClientPool();\n// pool.warm(\"gemini@/opt/homebrew/bin/gemini\", () => new AcpAgentClient(...)); // startup\n// const client = await pool.acquire(key, factory); // surfaces — same instance\n\nimport { noopLogger, type Logger } from \"@pwrdrvr/agent-core\";\nimport type { AcpAgentClient } from \"./acp-client\";\n\nexport type AcpAgentClientFactory = () => AcpAgentClient;\n\nexport type AcpAgentClientPoolOptions = {\n /** Max time to wait for a client to warm (spawn + `initialize`) before an\n * `acquire` rejects. Default 30s. */\n warmTimeoutMs?: number;\n logger?: Logger;\n};\n\ntype PoolEntry = {\n client: AcpAgentClient;\n /** Resolves to the client once warmed; shared by concurrent acquires. */\n ready: Promise<AcpAgentClient>;\n};\n\nfunction errorMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : String(cause);\n}\n\nexport class AcpAgentClientPool {\n private readonly entries = new Map<string, PoolEntry>();\n private readonly warmTimeoutMs: number;\n private readonly logger: Logger;\n\n constructor(options: AcpAgentClientPoolOptions = {}) {\n this.warmTimeoutMs = options.warmTimeoutMs ?? 30_000;\n this.logger = options.logger ?? noopLogger;\n }\n\n /**\n * Return the shared, warmed client for `key`, creating it via `factory` if it\n * doesn't exist. Concurrent acquires for the same key share ONE spawn — they\n * receive the same in-flight promise, which resolves when the agent is ready\n * or rejects if warm-up fails / times out. A failed warm-up evicts the entry\n * so a later acquire retries with a fresh client.\n */\n async acquire(key: string, factory: AcpAgentClientFactory): Promise<AcpAgentClient> {\n const existing = this.entries.get(key);\n if (existing !== undefined) return existing.ready;\n const client = factory();\n const ready = this.warmWithTimeout(key, client);\n this.entries.set(key, { client, ready });\n return ready;\n }\n\n /** Fire-and-forget warm-up for app startup. Errors are logged, not thrown. */\n warm(key: string, factory: AcpAgentClientFactory): void {\n void this.acquire(key, factory).catch((cause) => {\n this.logger.warn?.(\"acp pool: background warm-up failed\", {\n key,\n message: errorMessage(cause)\n });\n });\n }\n\n /** Whether a (warming or warm) entry exists for `key`. */\n has(key: string): boolean {\n return this.entries.has(key);\n }\n\n /** Close + evict ONE key (e.g. its config changed). Safe if absent. */\n async release(key: string): Promise<void> {\n const entry = this.entries.get(key);\n if (entry === undefined) return;\n this.entries.delete(key);\n // Don't let a still-warming entry surface an unhandled rejection on release.\n entry.ready.catch(() => undefined);\n await entry.client.close().catch(() => undefined);\n }\n\n /** Close + evict EVERY entry (app quit). */\n async closeAll(): Promise<void> {\n const entries = [...this.entries.values()];\n this.entries.clear();\n for (const entry of entries) entry.ready.catch(() => undefined);\n await Promise.allSettled(entries.map((entry) => entry.client.close()));\n }\n\n private async warmWithTimeout(\n key: string,\n client: AcpAgentClient\n ): Promise<AcpAgentClient> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n client.connect(),\n new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(`ACP agent \"${key}\" warm-up timed out after ${this.warmTimeoutMs}ms`)\n ),\n this.warmTimeoutMs\n );\n })\n ]);\n return client;\n } catch (cause) {\n // Evict so a later acquire retries with a fresh client, and tear down the\n // half-spawned process.\n if (this.entries.get(key)?.client === client) this.entries.delete(key);\n await client.close().catch(() => undefined);\n throw cause;\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n }\n}\n","// One-shot structured turn against an ACP agent — the ACP analog of the Codex\n// `CodexOneShotClient`. Used for non-interactive jobs (e.g. capture\n// enrichment): one prompt + optional images in, one assistant message out, no\n// chat, no tools, no approvals.\n//\n// Lifecycle parity with the Codex one-shot:\n// • The agent PROCESS is persistent — the transport connects lazily on the\n// first request and stays connected across `run()` calls; `close()` tears\n// it down.\n// • Each `run()` opens a FRESH ACP session (`session/new`) so per-call\n// context is clean. ACP has no `thread/rollback`, so a new session is the\n// equivalent of Codex's per-turn rollback.\n//\n// Differences from Codex, by protocol:\n// • No `outputSchema` — ACP can't constrain the reply, so the CALLER must\n// bake the \"reply with JSON only\" contract into the prompt and parse +\n// validate the returned text.\n// • No base-instructions on `session/new` — the caller folds any system\n// preamble into the prompt text too.\n//\n// Enrichment is non-interactive: approvals are auto-denied and tool calls are\n// rejected, so the agent can only answer.\n\nimport {\n noopLogger,\n type Logger,\n type NormalizedThreadEvent,\n type NormalizedTokenUsage\n} from \"@pwrdrvr/agent-core\";\nimport { AcpAgentClient } from \"./acp-client\";\nimport type { AcpJsonRpcTransport } from \"./acp-transport\";\nimport type { AcpAgentStrategy } from \"./strategies/strategy-types\";\nimport {\n modelsFromCapabilities,\n type AcpRuntimeModel\n} from \"./normalizer/runtime-capabilities\";\n\nexport type AcpOneShotClientOptions = {\n /** Connected (or lazily-connecting) ACP stdio transport for the agent. */\n transport: AcpJsonRpcTransport;\n /** Strategy carrying the agent's spawn + normalization quirks. */\n strategy: AcpAgentStrategy;\n clientName?: string;\n clientTitle?: string;\n clientVersion?: string;\n /** Scratch cwd for the session (keep enrichment out of any repo). */\n cwd?: string;\n logger?: Logger;\n now?: () => number;\n};\n\nexport type AcpOneShotRequest = {\n /** Full prompt text — the caller folds in any system preamble + the\n * \"reply with ONLY JSON matching <schema>\" contract. */\n prompt: string;\n /** Local image file paths attached to the turn (ACP image content blocks). */\n imagePaths?: readonly string[];\n /** Model id to select for the session. Omit for the agent default. */\n model?: string | null;\n /** Reasoning effort token (agent-specific). */\n effort?: string;\n abortSignal?: AbortSignal;\n};\n\nexport type AcpOneShotResponse = {\n /** The agent's final assistant-message text. Caller parses + validates it. */\n rawText: string;\n threadId: string;\n turnId: string;\n model: string;\n modelProvider: string;\n serviceTier: string | null;\n tokenUsage: NormalizedTokenUsage | null;\n};\n\nexport class AcpOneShotClient {\n private readonly client: AcpAgentClient;\n private readonly strategy: AcpAgentStrategy;\n private readonly denyApprovals: () => void;\n private readonly rejectTools: () => void;\n /** Serialize runs — one turn at a time against the agent. */\n private queue: Promise<void> = Promise.resolve();\n\n constructor(options: AcpOneShotClientOptions) {\n this.strategy = options.strategy;\n const logger = options.logger ?? noopLogger;\n this.client = new AcpAgentClient({\n transport: options.transport,\n strategy: options.strategy,\n ...(options.clientName !== undefined ? { clientName: options.clientName } : {}),\n ...(options.clientTitle !== undefined ? { clientTitle: options.clientTitle } : {}),\n ...(options.clientVersion !== undefined ? { clientVersion: options.clientVersion } : {}),\n ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),\n ...(options.now !== undefined ? { now: options.now } : {}),\n logger\n });\n // Non-interactive: never approve, never run tools.\n this.denyApprovals = this.client.onApprovalRequest(async () => \"denied\");\n this.rejectTools = this.client.onToolCall(async () => {\n throw new Error(\"ACP one-shot does not support tool calls\");\n });\n }\n\n /** Run one structured turn. Serialized — one in-flight at a time. */\n async run(request: AcpOneShotRequest): Promise<AcpOneShotResponse> {\n const run = this.queue.catch(() => undefined).then(() => this.runInner(request));\n this.queue = run.then(\n () => undefined,\n () => undefined\n );\n return run;\n }\n\n private async runInner(request: AcpOneShotRequest): Promise<AcpOneShotResponse> {\n if (request.abortSignal?.aborted === true) {\n throw new Error(\"ACP one-shot aborted before start\");\n }\n // Fresh session per call → clean per-capture context.\n const thread = await this.client.startThread(\n request.model !== undefined && request.model !== null ? { model: request.model } : {}\n );\n\n let finalText = \"\";\n const deltas: string[] = [];\n let usage: NormalizedTokenUsage | null = null;\n let turnError: string | null = null;\n // `startTurn` now resolves at turn START (it streams terminal events\n // asynchronously), so we gate completion on the `turn_completed` event for\n // this thread rather than on `startTurn` resolving.\n let settle: (status: string) => void = () => undefined;\n const done = new Promise<string>((resolve) => {\n settle = resolve;\n });\n const unsubscribe = this.client.onEvent((event: NormalizedThreadEvent) => {\n if (!(\"threadId\" in event) || event.threadId !== thread.threadId) return;\n if (event.kind === \"agent_message\") finalText = event.message.text;\n else if (event.kind === \"agent_message_delta\") deltas.push(event.delta);\n else if (event.kind === \"token_usage\") usage = event.usage;\n else if (event.kind === \"error\") turnError = event.message;\n else if (event.kind === \"turn_completed\") settle(event.status);\n });\n\n try {\n const { turnId } = await this.client.startTurn({\n threadId: thread.threadId,\n input: {\n text: request.prompt,\n ...(request.imagePaths !== undefined && request.imagePaths.length > 0\n ? { imagePaths: request.imagePaths }\n : {})\n },\n ...(request.effort !== undefined ? { reasoning: request.effort } : {})\n });\n const status = await done;\n if (status !== \"completed\") {\n throw new Error(turnError ?? `ACP one-shot turn ${status}`);\n }\n const rawText = finalText.length > 0 ? finalText : deltas.join(\"\");\n return {\n rawText,\n threadId: thread.threadId,\n turnId,\n // `thread.model` is the EFFECTIVE model — startThread sets it to the\n // requested id ONLY when setModel applied, otherwise it's the agent's\n // session default (or \"\" when none is advertised). We deliberately do\n // NOT fall back to `request.model`: a stale/unknown id the agent ignored\n // must never be reported as what ran (showing \"\" → \"model unavailable\"\n // is honest; showing the rejected id is a lie).\n model: thread.model ?? \"\",\n modelProvider: thread.modelProvider ?? this.strategy.backendId,\n serviceTier: thread.serviceTier ?? null,\n tokenUsage: usage\n };\n } finally {\n unsubscribe();\n }\n }\n\n /** Open a throwaway session and read the agent's advertised models (ACP\n * agents report runtime capabilities — models/modes — on `session/new`).\n * Returns [] when the agent advertises none. Serialized with `run()`. */\n async listModels(): Promise<AcpRuntimeModel[]> {\n const run = this.queue.catch(() => undefined).then(() => this.listModelsInner());\n this.queue = run.then(\n () => undefined,\n () => undefined\n );\n return run;\n }\n\n private async listModelsInner(): Promise<AcpRuntimeModel[]> {\n let models: AcpRuntimeModel[] = [];\n const unsubscribe = this.client.onRuntimeCapabilities((event) => {\n // `modelsFromCapabilities` reads `models.availableModels` when present and\n // otherwise derives the list from the `model` configOption (Kimi), so a\n // host caches a model id + label for either advertisement style.\n const observed = modelsFromCapabilities(event.runtimeCapabilities);\n if (observed.length > 0) models = observed;\n });\n try {\n // `session/new` triggers the runtime-capabilities notification\n // synchronously, so `models` is populated by the time this resolves.\n await this.client.startThread();\n return models;\n } finally {\n unsubscribe();\n }\n }\n\n async close(): Promise<void> {\n this.denyApprovals();\n this.rejectTools();\n await this.client.close();\n }\n}\n","// Per-agent quirks live in a registered strategy table, never as inline\n// `if (agentId === ...)` branches in the normalizer or client (KTD-A2). Adding a\n// 5th ACP agent is a new table entry — zero normalizer edits.\n//\n// A strategy carries three things:\n// • discovery — how to probe whether the CLI is installed + ACP-capable;\n// • spawn — the command + args that launch it in ACP stdio mode;\n// • quirks — normalization behavior toggles the normalizer READS\n// (e.g. whether agent \"thought\" chunks surface as messages,\n// where the thread title comes from).\n\nexport type LocalAcpProbeResult = {\n stdout?: string | Buffer;\n stderr?: string | Buffer;\n};\n\nexport type LocalAcpProbeOptions = {\n /** Budget for this probe spawn. An injected probe should honor it so a slow\n * CLI is reported as \"did not answer in time\", not as \"not installed\". */\n timeoutMs?: number | undefined;\n /** Fires when discovery is abandoned mid-probe. */\n signal?: AbortSignal | undefined;\n};\n\nexport type LocalAcpAgentProbe = (\n command: string,\n args: string[],\n options?: LocalAcpProbeOptions\n) => Promise<LocalAcpProbeResult>;\n\n/** How a strategy decides it is installed + ACP-capable on this machine. */\nexport type AcpDiscoveryProbe = {\n /** Args that print a version (probed first; failure = not installed). */\n versionArgs: string[];\n /** Args probed to confirm ACP support. When `helpMatches` is set the OUTPUT\n * must match it; when omitted, a SUCCESSFUL probe (exit 0) is itself the\n * signal — for args that are an ACP subcommand whose mere existence proves\n * capability (e.g. `kimi acp --help`). */\n helpArgs: string[];\n /** Regex the help/usage output must match for the agent to count as\n * ACP-capable. OMIT to rely on the help probe's EXIT CODE instead — more\n * robust than parsing help prose, which drifts across CLI versions. */\n helpMatches?: RegExp;\n /** Bare command name tried first. */\n command: string;\n /** Additional candidate command paths (Homebrew prefixes, `~/.<agent>/bin`, …). */\n fallbackCommands?: string[];\n};\n\n/** Launch invocation: how to spawn the CLI in ACP stdio server mode. */\nexport type AcpSpawnSpec = {\n /** Command to run (resolved against the discovered candidate at spawn time). */\n command: string;\n /** Args that put the CLI into ACP stdio server mode (e.g. `[\"--acp\"]`). */\n args: string[];\n /** Extra env to set when launching (e.g. Gemini workspace-trust). */\n env?: Record<string, string>;\n /** Extra args appended only when missing (e.g. Gemini `--skip-trust`). */\n ensureArgs?: string[];\n};\n\n/**\n * Normalization quirks the normalizer reads. NO agent-id literal ever appears\n * in the normalizer — it reads these fields off the strategy it was constructed\n * with. A synthetic strategy with different quirk values flows through the\n * normalizer with zero normalizer changes (asserted in tests).\n */\nexport type AcpAgentQuirks = {\n /**\n * Whether agent \"thought\"/reasoning chunks surface as assistant messages.\n * Qwen sets this false (its thoughts are noisy scaffolding); others true.\n */\n surfaceThoughts: boolean;\n /**\n * Where the auto-generated thread title comes from:\n * • \"topic-update\" — a `tool_call` titled `Update topic to: \"…\"` (Gemini/Kimi/Qwen);\n * • \"session-summary\" — a vendor `session_summary_generated` update (Grok);\n * • \"both\" — recognize either.\n */\n titleFrom: \"topic-update\" | \"session-summary\" | \"both\";\n /** Vendor notification methods routed through the same session/update path. */\n vendorNotificationMethods?: string[];\n};\n\nexport type AcpAgentStrategy = {\n /** Strategy id, also the registry id (`gemini`, `grok`, `kimi`, `qwen`, …). */\n id: string;\n /** Neutral backend id (`acp:<id>`) used as the thread/session correlation key. */\n backendId: string;\n displayName: string;\n authors: string[];\n license?: string;\n repositoryUrl?: string;\n discoveryProbe: AcpDiscoveryProbe;\n spawn: AcpSpawnSpec;\n quirks: AcpAgentQuirks;\n};\n\n/** Build the neutral backend id for a registry id. */\nexport function buildAcpBackendId(registryId: string): string {\n return `acp:${registryId}`;\n}\n\nconst DEFAULT_QUIRKS: AcpAgentQuirks = {\n surfaceThoughts: true,\n titleFrom: \"topic-update\"\n};\n\n/** Quirks for an unknown/synthetic strategy default to the common case. */\nexport function defaultQuirks(overrides: Partial<AcpAgentQuirks> = {}): AcpAgentQuirks {\n return { ...DEFAULT_QUIRKS, ...overrides };\n}\n","import { buildAcpBackendId, defaultQuirks, type AcpAgentStrategy } from \"./strategy-types\";\n\nexport const geminiStrategy: AcpAgentStrategy = {\n id: \"gemini\",\n backendId: buildAcpBackendId(\"gemini\"),\n displayName: \"Gemini CLI\",\n authors: [\"Google\"],\n discoveryProbe: {\n command: \"gemini\",\n versionArgs: [\"--version\"],\n helpArgs: [\"--help\"],\n helpMatches: /(^|\\s)--acp(\\s|,|$)/\n },\n spawn: {\n command: \"gemini\",\n args: [\"--acp\"],\n // Gemini refuses to operate without workspace trust; matching PwrAgnt's\n // launch-descriptor normalization, append --skip-trust + set the env flag.\n ensureArgs: [\"--skip-trust\"],\n env: { GEMINI_CLI_TRUST_WORKSPACE: \"true\" }\n },\n quirks: defaultQuirks({ surfaceThoughts: true, titleFrom: \"topic-update\" })\n};\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { buildAcpBackendId, defaultQuirks, type AcpAgentStrategy } from \"./strategy-types\";\n\nexport const grokStrategy: AcpAgentStrategy = {\n id: \"grok\",\n backendId: buildAcpBackendId(\"grok\"),\n displayName: \"Grok\",\n authors: [\"xAI\"],\n discoveryProbe: {\n command: \"grok\",\n versionArgs: [\"--version\"],\n helpArgs: [\"agent\", \"stdio\", \"--help\"],\n helpMatches: /Run the agent over stdio/i,\n fallbackCommands: [\n path.join(homedir(), \".grok\", \"bin\", \"grok\"),\n \"/opt/homebrew/bin/grok\",\n \"/usr/local/bin/grok\"\n ]\n },\n spawn: {\n command: \"grok\",\n args: [\"agent\", \"stdio\"]\n },\n // Grok auto-generates the thread title via its vendor notification\n // `_x.ai/session_notification` carrying `session_summary_generated`.\n quirks: defaultQuirks({\n surfaceThoughts: true,\n titleFrom: \"session-summary\",\n vendorNotificationMethods: [\"_x.ai/session_notification\"]\n })\n};\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { buildAcpBackendId, defaultQuirks, type AcpAgentStrategy } from \"./strategy-types\";\n\nexport const kimiStrategy: AcpAgentStrategy = {\n id: \"kimi\",\n backendId: buildAcpBackendId(\"kimi\"),\n displayName: \"Kimi Code CLI\",\n authors: [\"Moonshot AI\"],\n discoveryProbe: {\n command: \"kimi\",\n versionArgs: [\"--version\"],\n // Capability signal is the EXIT CODE of `kimi acp --help`, NOT its prose.\n // kimi's commander CLI exits non-zero for an unknown subcommand, so a\n // zero-exit proves the `acp` subcommand exists. No `helpMatches`: the help\n // wording has already drifted across kimi versions (0.11.0 prints \"Agent\n // Client Protocol (ACP) server over stdio\"), so matching it is fragile.\n helpArgs: [\"acp\", \"--help\"],\n // The official Kimi Code installer drops a standalone binary at\n // ~/.kimi-code/bin/kimi and does NOT add it to PATH — so a Finder-launched\n // app misses it without this fallback (mirrors grok/qwen).\n fallbackCommands: [\n path.join(homedir(), \".kimi-code\", \"bin\", \"kimi\"),\n \"/opt/homebrew/bin/kimi\",\n \"/usr/local/bin/kimi\"\n ]\n },\n spawn: {\n command: \"kimi\",\n args: [\"acp\"]\n },\n quirks: defaultQuirks({ surfaceThoughts: true, titleFrom: \"topic-update\" })\n};\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { buildAcpBackendId, defaultQuirks, type AcpAgentStrategy } from \"./strategy-types\";\n\nexport const qwenStrategy: AcpAgentStrategy = {\n id: \"qwen\",\n backendId: buildAcpBackendId(\"qwen\"),\n displayName: \"Qwen Code\",\n authors: [\"Qwen Team\"],\n license: \"Apache-2.0\",\n repositoryUrl: \"https://github.com/QwenLM/qwen-code\",\n discoveryProbe: {\n command: \"qwen\",\n versionArgs: [\"--version\"],\n helpArgs: [\"--help\"],\n helpMatches: /(^|\\s)--acp(\\s|,|$)/,\n fallbackCommands: [\n path.join(homedir(), \".qwen\", \"bin\", \"qwen\"),\n \"/opt/homebrew/bin/qwen\",\n \"/usr/local/bin/qwen\"\n ]\n },\n spawn: {\n command: \"qwen\",\n args: [\"--acp\"]\n },\n // Qwen's thought chunks are noisy internal scaffolding — suppress them.\n quirks: defaultQuirks({ surfaceThoughts: false, titleFrom: \"topic-update\" })\n};\n","// The strategy table. The four built-ins do not require the registry — the\n// registry (discovery/acp-registry.ts) is the EXTENSION path. Adding a 5th\n// agent is a new entry here, with zero normalizer/client edits.\n\nimport type { AcpAgentStrategy } from \"./strategy-types\";\nimport { geminiStrategy } from \"./gemini\";\nimport { grokStrategy } from \"./grok\";\nimport { kimiStrategy } from \"./kimi\";\nimport { qwenStrategy } from \"./qwen\";\n\nexport { geminiStrategy } from \"./gemini\";\nexport { grokStrategy } from \"./grok\";\nexport { kimiStrategy } from \"./kimi\";\nexport { qwenStrategy } from \"./qwen\";\n\nexport const BUILT_IN_ACP_STRATEGIES: readonly AcpAgentStrategy[] = [\n geminiStrategy,\n kimiStrategy,\n grokStrategy,\n qwenStrategy\n];\n\n/** Index a list of strategies by id (built-ins by default). */\nexport function buildStrategyTable(\n strategies: readonly AcpAgentStrategy[] = BUILT_IN_ACP_STRATEGIES\n): Map<string, AcpAgentStrategy> {\n const table = new Map<string, AcpAgentStrategy>();\n for (const strategy of strategies) {\n table.set(strategy.id, strategy);\n }\n return table;\n}\n\n/** Look up a strategy by its registry id, falling back to the built-in table. */\nexport function strategyById(\n id: string,\n table: Map<string, AcpAgentStrategy> = buildStrategyTable()\n): AcpAgentStrategy | undefined {\n return table.get(id);\n}\n\n/** Look up a strategy by its neutral backend id (`acp:<id>`). */\nexport function strategyByBackendId(\n backendId: string,\n strategies: readonly AcpAgentStrategy[] = BUILT_IN_ACP_STRATEGIES\n): AcpAgentStrategy | undefined {\n return strategies.find((strategy) => strategy.backendId === backendId);\n}\n","// Probe which ACP CLIs are installed locally. STRATEGY-DRIVEN: iterates the\n// strategy table and runs each strategy's `discoveryProbe`. Adding a 5th agent\n// (a new strategy entry) surfaces it through discovery with ZERO changes here.\n//\n// Two granularities:\n// • `discoverLocalAcpAgentInstances` — returns EVERY installed instance of\n// each agent (each executable on `PATH` + the strategy's fallback paths +\n// an optional override that passes the probe), with its parsed version and\n// where it was found. A host UI can list them all and let the user pick.\n// Hosts that opt in can also receive detected candidates rejected by the\n// probe, so they can explain why a known CLI cannot be used.\n// • `discoverLocalAcpAgents` — the original first-match-per-agent view, kept\n// for back-compat. Implemented on top of the instance view.\n//\n// Ported from PwrAgnt acp-local-discovery.ts, generalized so the per-agent probe\n// details live in the strategy, not inline branches.\n\nimport { execFile as execFileCallback } from \"node:child_process\";\nimport { readdirSync, realpathSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport {\n createCommandInvocation,\n prependCommandDirToPath\n} from \"@pwrdrvr/agent-transport\";\nimport { BUILT_IN_ACP_STRATEGIES } from \"../strategies/index\";\nimport type {\n AcpAgentStrategy,\n AcpAgentStrategy as Strategy,\n LocalAcpAgentProbe,\n LocalAcpProbeOptions,\n LocalAcpProbeResult\n} from \"../strategies/strategy-types\";\n\nconst execFile = promisify(execFileCallback);\n\nexport type {\n LocalAcpAgentProbe,\n LocalAcpProbeOptions,\n LocalAcpProbeResult\n} from \"../strategies/strategy-types\";\n\n/** How a discovered instance's executable path was located. */\nexport type AcpAgentInstanceSource = \"override\" | \"path\" | \"fallback\";\n\n/** One installed executable of an agent that passed the probe. */\nexport type DiscoveredAcpAgentInstance = {\n /** Resolved command/path that passed the probe. */\n command: string;\n /** Parsed CLI version, when the version probe yielded one. */\n version?: string;\n /** Where this candidate came from (user override, `PATH`, or a fallback path). */\n source: AcpAgentInstanceSource;\n};\n\n/** A detected executable that did not satisfy a strategy's discovery probe.\n * It is diagnostic-only: hosts must never use it to launch an ACP session. */\nexport type RejectedAcpAgentInstance = {\n command: string;\n /** Parsed from successful `--version` output when available. */\n version?: string;\n source: AcpAgentInstanceSource;\n /** `probe-timed-out` means the CLI did not answer within the probe budget —\n * UNLIKE the other reasons it is not a verdict on the CLI, and a host may\n * re-probe on a larger `probeTimeoutMs` instead of reporting it unusable. */\n reason:\n | \"version-probe-failed\"\n | \"acp-probe-failed\"\n | \"acp-help-mismatch\"\n | \"probe-timed-out\";\n};\n\n/** Every installed instance of one agent found on this machine. */\nexport type DiscoveredAcpAgentGroup = {\n strategyId: string;\n backendId: string;\n name: string;\n /** Spawn args that put it into ACP stdio mode (same for every instance). */\n args: string[];\n /** Extra env to set at launch (same for every instance). */\n env: Record<string, string>;\n /** All instances that passed the probe, in candidate order (override → PATH → fallback). */\n instances: DiscoveredAcpAgentInstance[];\n /** Detected candidates that failed the version or ACP-capability probe. Only\n * populated when `includeRejectedCandidates` is enabled. */\n rejectedInstances?: RejectedAcpAgentInstance[];\n discoveredAt: number;\n};\n\nexport type DiscoveredAcpAgent = {\n strategyId: string;\n backendId: string;\n name: string;\n version?: string;\n /** Resolved command that passed the probe (may be a fallback path). */\n command: string;\n /** Spawn args that put it into ACP stdio mode. */\n args: string[];\n /** Extra env to set at launch. */\n env: Record<string, string>;\n discoveredAt: number;\n};\n\n/** Lists every executable named `command` across the dirs in `env.PATH`,\n * in `PATH` order (the `which -a` view). */\nexport type AcpPathExecutableLister = (\n command: string,\n env: NodeJS.ProcessEnv\n) => string[];\n\nexport type LocalAcpDiscoveryOptions = {\n probe?: LocalAcpAgentProbe;\n now?: () => number;\n /** Strategy table to probe (built-ins by default). */\n strategies?: readonly AcpAgentStrategy[];\n /** Per-strategy command override (tried before the strategy's own candidates). */\n overrides?: Record<string, string>;\n /** Env used both for PATH enumeration and (by the default probe) for spawns. */\n env?: NodeJS.ProcessEnv;\n /** Injectable `PATH` executable lister (real-fs scan by default). */\n listExecutables?: AcpPathExecutableLister;\n /** Include candidates known to exist but rejected by a discovery probe.\n * Defaults false to preserve the legacy installed-only result. */\n includeRejectedCandidates?: boolean;\n /** Budget for ONE probe spawn (the default probe only — an injected `probe`\n * owns its own timing). Defaults to `DEFAULT_ACP_PROBE_TIMEOUT_MS`. */\n probeTimeoutMs?: number;\n /** Abandon discovery in flight (re-triggered discovery, app quitting).\n * Already-probed groups are still returned. */\n signal?: AbortSignal;\n};\n\n/**\n * Budget for one ACP discovery probe spawn, in ms.\n *\n * Unchanged from the value this module has always used. Kept lower than\n * codex-discovery's version-probe budget on purpose: `discoverStrategyInstances`\n * walks its candidates SERIALLY, so the worst case here is (candidates x\n * budget) rather than a single budget. Hosts that scan machines with many\n * installed copies can raise it knowingly via `probeTimeoutMs`.\n */\nexport const DEFAULT_ACP_PROBE_TIMEOUT_MS = 5_000;\n\n/**\n * Discover every installed instance of each agent (all `PATH` matches +\n * fallbacks + override that pass the probe), grouped per strategy. Groups with\n * no passing instance are omitted unless `includeRejectedCandidates` is true\n * and a detected candidate failed a probe.\n */\nexport async function discoverLocalAcpAgentInstances(\n options: LocalAcpDiscoveryOptions = {}\n): Promise<DiscoveredAcpAgentGroup[]> {\n const strategies = options.strategies ?? BUILT_IN_ACP_STRATEGIES;\n const env = options.env ?? process.env;\n const probe = options.probe ?? makeDefaultProbe(env);\n const listExecutables = options.listExecutables ?? defaultListExecutables;\n const now = options.now ?? Date.now;\n const probeOptions: LocalAcpProbeOptions = {\n timeoutMs: options.probeTimeoutMs ?? DEFAULT_ACP_PROBE_TIMEOUT_MS,\n signal: options.signal\n };\n const groups = await Promise.all(\n strategies.map((strategy) =>\n discoverStrategyInstances(\n strategy,\n probe,\n now,\n env,\n listExecutables,\n options.overrides?.[strategy.id],\n options.includeRejectedCandidates === true,\n probeOptions\n )\n )\n );\n return groups.filter((group): group is DiscoveredAcpAgentGroup => group !== undefined);\n}\n\n/**\n * First-match-per-agent discovery (legacy view). Returns at most one record per\n * agent — the first instance that passed the probe in candidate order.\n */\nexport async function discoverLocalAcpAgents(\n options: LocalAcpDiscoveryOptions = {}\n): Promise<DiscoveredAcpAgent[]> {\n const groups = await discoverLocalAcpAgentInstances(options);\n return groups.flatMap((group) => {\n const first = group.instances[0];\n if (first === undefined) return [];\n const agent: DiscoveredAcpAgent = {\n strategyId: group.strategyId,\n backendId: group.backendId,\n name: group.name,\n command: first.command,\n args: group.args,\n env: group.env,\n discoveredAt: group.discoveredAt\n };\n if (first.version !== undefined) agent.version = first.version;\n return [agent];\n });\n}\n\nasync function discoverStrategyInstances(\n strategy: Strategy,\n probe: LocalAcpAgentProbe,\n now: () => number,\n env: NodeJS.ProcessEnv,\n listExecutables: AcpPathExecutableLister,\n override?: string,\n includeRejectedCandidates = false,\n probeOptions: LocalAcpProbeOptions = {}\n): Promise<DiscoveredAcpAgentGroup | undefined> {\n const candidates = candidateCommands(strategy, env, listExecutables, override);\n const instances: DiscoveredAcpAgentInstance[] = [];\n const rejectedInstances: RejectedAcpAgentInstance[] = [];\n for (const candidate of candidates) {\n if (probeOptions.signal?.aborted) break;\n const [versionAttempt, helpAttempt] = await Promise.all([\n runProbe(probe, candidate.command, strategy.discoveryProbe.versionArgs, probeOptions),\n runProbe(probe, candidate.command, strategy.discoveryProbe.helpArgs, probeOptions)\n ]);\n // An abort landed while these were in flight: whatever they returned is an\n // abandoned measurement, not a verdict on this candidate. Record nothing.\n if (probeOptions.signal?.aborted) break;\n const versionResult = versionAttempt.ok ? versionAttempt.result : undefined;\n const helpResult = helpAttempt.ok ? helpAttempt.result : undefined;\n const version = versionResult ? parseCliVersion(resultText(versionResult)) : undefined;\n if (!versionResult || !helpResult) {\n // A probe that ran out of budget is not a verdict on the CLI — it is an\n // unfinished measurement. Record it even when the caller did not opt into\n // diagnostics, because dropping it is exactly what makes a slow machine\n // look like a machine with nothing installed. (Genuine probe FAILURES\n // stay behind `includeRejectedCandidates` — those are verdicts, and the\n // legacy default is installed-only.)\n const timedOut =\n (!versionAttempt.ok && versionAttempt.timedOut) ||\n (!helpAttempt.ok && helpAttempt.timedOut);\n if (candidate.detected && (timedOut || includeRejectedCandidates)) {\n const rejected: RejectedAcpAgentInstance = {\n command: candidate.command,\n source: candidate.source,\n reason: timedOut\n ? \"probe-timed-out\"\n : versionResult\n ? \"acp-probe-failed\"\n : \"version-probe-failed\"\n };\n if (version !== undefined) rejected.version = version;\n rejectedInstances.push(rejected);\n }\n continue;\n }\n // A strategy with no `helpMatches` relies on the EXIT CODE: the help probe\n // succeeding (enforced just above — a non-zero exit makes `runProbe` return\n // undefined) is itself the ACP-capability signal. Only when a regex is set\n // do we additionally parse the (drift-prone) help text.\n if (\n strategy.discoveryProbe.helpMatches !== undefined &&\n !strategy.discoveryProbe.helpMatches.test(resultText(helpResult))\n ) {\n if (includeRejectedCandidates && candidate.detected) {\n const rejected: RejectedAcpAgentInstance = {\n command: candidate.command,\n source: candidate.source,\n reason: \"acp-help-mismatch\"\n };\n if (version !== undefined) rejected.version = version;\n rejectedInstances.push(rejected);\n }\n continue;\n }\n const instance: DiscoveredAcpAgentInstance = {\n command: candidate.command,\n source: candidate.source\n };\n if (version !== undefined) instance.version = version;\n instances.push(instance);\n }\n if (instances.length === 0 && rejectedInstances.length === 0) {\n return undefined;\n }\n return {\n strategyId: strategy.id,\n backendId: strategy.backendId,\n name: strategy.displayName,\n args: ensureArgs(strategy.spawn.args, strategy.spawn.ensureArgs),\n env: strategy.spawn.env ?? {},\n instances,\n ...(rejectedInstances.length > 0 ? { rejectedInstances } : {}),\n discoveredAt: now()\n };\n}\n\ntype Candidate = {\n command: string;\n source: AcpAgentInstanceSource;\n /** True only when command enumeration found a concrete executable path. */\n detected: boolean;\n};\n\n/** Build the de-duplicated candidate list for a strategy: override first, then\n * every `PATH` match of the bare command (or the bare command itself when the\n * lister finds none, so `execFile`'s own `PATH` resolution still gets a shot),\n * then the strategy's fallback paths. Duplicates (by resolved real path) are\n * collapsed so the same physical binary isn't listed twice. */\nfunction candidateCommands(\n strategy: Strategy,\n env: NodeJS.ProcessEnv,\n listExecutables: AcpPathExecutableLister,\n override?: string\n): Candidate[] {\n const out: Candidate[] = [];\n const seen = new Set<string>();\n const push = (\n command: string,\n source: AcpAgentInstanceSource,\n detected: boolean\n ): void => {\n const trimmed = command.trim();\n if (trimmed.length === 0) return;\n const key = canonicalize(trimmed);\n if (seen.has(key)) return;\n seen.add(key);\n out.push({ command: trimmed, source, detected });\n };\n\n if (override && override.trim().length > 0) {\n push(override, \"override\", isExecutableFile(override));\n }\n const pathMatches = listExecutables(strategy.discoveryProbe.command, env);\n if (pathMatches.length > 0) {\n for (const match of pathMatches) push(match, \"path\", true);\n } else {\n // No PATH hit (or an injected no-op lister): keep the bare command so\n // `execFile` resolves it via its own PATH and scripted-probe tests match.\n push(strategy.discoveryProbe.command, \"path\", false);\n }\n for (const fallback of strategy.discoveryProbe.fallbackCommands ?? []) {\n push(fallback, \"fallback\", isExecutableFile(fallback));\n }\n return out;\n}\n\nfunction isExecutableFile(command: string): boolean {\n try {\n const stat = statSync(command);\n return stat.isFile() && (process.platform === \"win32\" || (stat.mode & 0o111) !== 0);\n } catch {\n return false;\n }\n}\n\n/** Resolve symlinks so the same binary reached via two PATH entries dedupes. */\nfunction canonicalize(command: string): string {\n if (!path.isAbsolute(command)) {\n return process.platform === \"win32\" ? command.toLowerCase() : command;\n }\n try {\n const canonical = realpathSync(command);\n return process.platform === \"win32\" ? canonical.toLowerCase() : canonical;\n } catch {\n return process.platform === \"win32\" ? command.toLowerCase() : command;\n }\n}\n\n/** Default executable lister: scan `env.PATH` AND well-known version-manager /\n * install dirs for an executable file named `command`. On Windows, expand\n * each PATH entry using PATHEXT and return the actual .COM/.EXE/.BAT/.CMD\n * candidates rather than a bare command that `execFile` cannot launch.\n *\n * Scanning beyond `PATH` is deliberate: a desktop app launched from Finder /\n * Dock inherits launchd's minimal `PATH`, and login-shell hydration can't\n * reliably recover a version-manager `PATH` (nvm is often lazy-loaded and\n * pins a different node version than the one the agent CLI is installed\n * under). So an `npm i -g qwen` under nvm would be invisible. We find it by\n * scanning the version-manager bin dirs directly. */\nfunction defaultListExecutables(command: string, env: NodeJS.ProcessEnv): string[] {\n // A bare command name only — never enumerate when a path was passed.\n if (command.includes(\"/\") || command.includes(\"\\\\\")) return [];\n const found: string[] = [];\n const seenDir = new Set<string>();\n for (const dir of discoveryDirs(env)) {\n const normalizedDir = normalizePathEntry(dir);\n const dirKey = process.platform === \"win32\" ? normalizedDir.toLowerCase() : normalizedDir;\n if (normalizedDir.length === 0 || seenDir.has(dirKey)) continue;\n seenDir.add(dirKey);\n for (const commandName of executableCommandNames(command, env)) {\n const candidate = path.join(normalizedDir, commandName);\n try {\n const stat = statSync(candidate);\n if (stat.isFile() && (process.platform === \"win32\" || (stat.mode & 0o111) !== 0)) {\n found.push(candidate);\n }\n } catch {\n // Not in this dir; keep scanning.\n }\n }\n }\n return found;\n}\n\nfunction executableCommandNames(command: string, env: NodeJS.ProcessEnv): string[] {\n if (process.platform !== \"win32\") return [command];\n const extensions = (readWindowsEnv(env, \"PATHEXT\")?.trim() || \".COM;.EXE;.BAT;.CMD\")\n .split(\";\")\n .map((extension) => extension.trim())\n .filter(Boolean)\n .map((extension) => extension.startsWith(\".\") ? extension : `.${extension}`);\n const commandExtension = path.win32.extname(command);\n if (\n commandExtension.length > 0 &&\n extensions.some((extension) => extension.toLowerCase() === commandExtension.toLowerCase())\n ) {\n return [command];\n }\n return extensions.map((extension) => `${command}${extension}`);\n}\n\nfunction readWindowsEnv(env: NodeJS.ProcessEnv, name: string): string | undefined {\n const key = Object.keys(env).find((candidate) => candidate.toLowerCase() === name.toLowerCase());\n return key ? env[key] : undefined;\n}\n\nfunction normalizePathEntry(entry: string): string {\n const trimmed = entry.trim();\n const quoted = trimmed.match(/^\"(.*)\"$/);\n return quoted?.[1] ?? trimmed;\n}\n\n/** Dirs to scan for agent executables: every `env.PATH` entry first, then the\n * well-known version-manager / package-manager bin dirs a GUI app's `PATH`\n * usually omits. */\nfunction discoveryDirs(env: NodeJS.ProcessEnv): string[] {\n const pathValue = process.platform === \"win32\"\n ? readWindowsEnv(env, \"PATH\") ?? \"\"\n : env.PATH ?? \"\";\n const pathDirs = pathValue.split(path.delimiter);\n return process.platform === \"win32\"\n ? pathDirs\n : [...pathDirs, ...wellKnownAgentBinDirs(homedir())];\n}\n\n/** Well-known bin dirs where a CLI installed via a node/JS version manager or\n * a per-user package manager lives — even when it isn't on a GUI app's `PATH`.\n * Exported for testing; `home` defaults to the user's home dir. */\nexport function wellKnownAgentBinDirs(home: string = homedir()): string[] {\n return [\n // Every installed nvm node version's bin (the agent may be under any one).\n ...nvmNodeBinDirs(home),\n // Other version / package managers.\n path.join(home, \".volta\", \"bin\"),\n path.join(home, \".bun\", \"bin\"),\n path.join(home, \".asdf\", \"shims\"),\n path.join(home, \".deno\", \"bin\"),\n path.join(home, \".local\", \"bin\"),\n path.join(home, \".npm-global\", \"bin\"),\n // Common system install prefixes.\n \"/opt/homebrew/bin\",\n \"/usr/local/bin\"\n ];\n}\n\n/** Every `~/.nvm/versions/node/<v>/bin` dir, newest-first so the most recent\n * node version's install is tried before older ones. Empty when nvm absent. */\nfunction nvmNodeBinDirs(home: string): string[] {\n const base = path.join(home, \".nvm\", \"versions\", \"node\");\n try {\n return readdirSync(base)\n .sort()\n .reverse()\n .map((version) => path.join(base, version, \"bin\"));\n } catch {\n return [];\n }\n}\n\nfunction ensureArgs(args: string[], ensure: string[] | undefined): string[] {\n if (!ensure || ensure.length === 0) {\n return args;\n }\n const result = [...args];\n for (const arg of ensure) {\n if (!result.includes(arg)) result.push(arg);\n }\n return result;\n}\n\n/** Thrown by the default probe when its budget elapses. Distinguishable from\n * a probe that ran and failed, which is a verdict on the CLI. */\nclass AcpProbeTimeoutError extends Error {\n constructor(command: string, timeoutMs: number) {\n super(`acp probe did not answer within ${timeoutMs}ms: ${command}`);\n this.name = \"AcpProbeTimeoutError\";\n }\n}\n\nfunction isProbeTimeout(error: unknown): boolean {\n if (error instanceof AcpProbeTimeoutError) return true;\n // Covers an injected probe that leans on `execFile`'s own `timeout` (which\n // sets `killed`) or on an AbortSignal.\n const name = (error as { name?: unknown } | undefined)?.name;\n return (\n (error as { killed?: unknown } | undefined)?.killed === true ||\n name === \"AbortError\" ||\n name === \"TimeoutError\"\n );\n}\n\n/**\n * Clamp a caller-supplied probe budget.\n *\n * The `Number.isFinite` guard is load-bearing: `Infinity` is the natural way to\n * ask for \"no budget\", and `execFile` rejects a non-finite `timeout` with a\n * synchronous `ERR_OUT_OF_RANGE` — which `runProbe` would then classify as a\n * failed probe and report as \"not installed\" for every agent on the machine.\n */\nfunction normalizeProbeTimeoutMs(timeoutMs: number | undefined): number {\n if (timeoutMs === undefined || !Number.isFinite(timeoutMs)) {\n return DEFAULT_ACP_PROBE_TIMEOUT_MS;\n }\n return Math.max(1, Math.floor(timeoutMs));\n}\n\nfunction makeDefaultProbe(env: NodeJS.ProcessEnv): LocalAcpAgentProbe {\n return async (\n command: string,\n args: string[],\n options: LocalAcpProbeOptions = {}\n ): Promise<LocalAcpProbeResult> => {\n const timeoutMs = normalizeProbeTimeoutMs(options.timeoutMs);\n const launchEnv = prependCommandDirToPath(command, env);\n const invocation = createCommandInvocation({ command, args, env: launchEnv });\n const controller = new AbortController();\n let timedOut = false;\n const onAbort = (): void => controller.abort();\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n const timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, timeoutMs);\n // Race the spawn against the budget rather than trusting `execFile`'s own\n // `timeout` alone: these CLIs are frequently Windows `.cmd` shims, and\n // killing the `cmd.exe` wrapper can leave a `node` grandchild holding the\n // pipes open so `execFile` never calls back at all.\n const expired = new Promise<\"expired\">((resolve) => {\n controller.signal.addEventListener(\"abort\", () => resolve(\"expired\"), {\n once: true\n });\n });\n try {\n const execution = execFile(invocation.command, invocation.args, {\n timeout: timeoutMs,\n signal: controller.signal,\n maxBuffer: 1024 * 1024,\n // A Windows `.cmd` shim runs through `cmd.exe`; without this every\n // discovery pass flashes console windows over the host app.\n windowsHide: true,\n // Prepend the candidate's own dir so a node-script CLI (e.g. an nvm-\n // installed `qwen`) finds its sibling `node` during the probe.\n env: launchEnv,\n windowsVerbatimArguments: invocation.windowsVerbatimArguments\n }).then(\n (result) => ({ ok: true as const, result }),\n (error: unknown) => ({ ok: false as const, error })\n );\n const settled = await Promise.race([execution, expired]);\n if (settled === \"expired\") {\n if (timedOut) throw new AcpProbeTimeoutError(command, timeoutMs);\n throw new Error(`acp probe aborted: ${command}`);\n }\n if (!settled.ok) {\n if (timedOut) throw new AcpProbeTimeoutError(command, timeoutMs);\n throw settled.error;\n }\n return settled.result;\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", onAbort);\n }\n };\n}\n\ntype ProbeAttempt =\n | { ok: true; result: LocalAcpProbeResult }\n | { ok: false; timedOut: boolean };\n\nasync function runProbe(\n probe: LocalAcpAgentProbe,\n command: string,\n args: string[],\n options: LocalAcpProbeOptions\n): Promise<ProbeAttempt> {\n try {\n return { ok: true, result: await probe(command, args, options) };\n } catch (error) {\n return { ok: false, timedOut: isProbeTimeout(error) };\n }\n}\n\nfunction resultText(result: LocalAcpProbeResult): string {\n return [result.stdout, result.stderr]\n .flatMap((value) => (value === undefined ? [] : [value]))\n .map((value) => (Buffer.isBuffer(value) ? value.toString(\"utf8\") : value))\n .join(\"\\n\");\n}\n\nfunction parseCliVersion(output: string): string | undefined {\n const trimmed = output.trim();\n if (!trimmed) {\n return undefined;\n }\n return trimmed.match(/\\d+\\.\\d+\\.\\d+(?:[-+][\\w.-]+)?/)?.[0] ?? trimmed;\n}\n","// Gate registry-sourced ACP agents. Rejects the GPL family, unpinned npx/uvx\n// packages, and unpinned binary archive hosts; `BANNED_ACP_REGISTRY_IDS` keeps\n// `codex-acp` out (PwrDrvr talks to Codex through the first-class Codex adapter,\n// not as an ACP duplicate).\n//\n// Ported from PwrAgnt acp-agent-allowlist.ts, with @pwragent/shared types\n// inlined.\n\nimport type {\n AcpAllowlistDecision,\n AcpDistributionKind,\n AcpRegistryAgent,\n AcpRegistryDistribution\n} from \"./acp-registry-types\";\n\nexport type AcpAgentAllowlistRule = {\n id: string;\n registryId: string;\n versions?: string[];\n distributionKinds?: AcpDistributionKind[];\n allowedPackageNames?: string[];\n allowedArchiveHosts?: string[];\n allowUnverifiedBinary?: boolean;\n allowGplFamilyLicense?: boolean;\n};\n\nexport const BANNED_ACP_REGISTRY_IDS = new Set([\"codex-acp\"]);\n\nexport const DEFAULT_ACP_AGENT_ALLOWLIST: AcpAgentAllowlistRule[] = [\n { id: \"local-grok-cli\", registryId: \"grok\", distributionKinds: [\"local\"] },\n { id: \"local-qwen-code-cli\", registryId: \"qwen\", distributionKinds: [\"local\"] }\n];\n\nexport class AcpAgentAllowlist {\n constructor(private readonly rules: AcpAgentAllowlistRule[]) {}\n\n evaluate(agent: AcpRegistryAgent): AcpAllowlistDecision {\n if (isBannedAcpRegistryId(agent.id)) {\n return { allowed: false, reason: \"banned\" };\n }\n const matchingRules = this.rules.filter((rule) => rule.registryId === agent.id);\n if (matchingRules.length === 0) {\n return { allowed: false, reason: \"not-allowlisted\" };\n }\n for (const rule of matchingRules) {\n const denial = evaluateRule(rule, agent);\n if (!denial) {\n return {\n allowed: true,\n ruleId: rule.id,\n unverifiedBinaryAllowed: rule.allowUnverifiedBinary === true\n };\n }\n }\n return { allowed: false, reason: \"allowlist-rule-mismatch\" };\n }\n\n evaluateDistribution(\n agent: AcpRegistryAgent,\n distribution: AcpRegistryDistribution\n ): AcpAllowlistDecision {\n if (isBannedAcpRegistryId(agent.id)) {\n return { allowed: false, reason: \"banned\" };\n }\n const matchingRules = this.rules.filter((rule) => rule.registryId === agent.id);\n if (matchingRules.length === 0) {\n return { allowed: false, reason: \"not-allowlisted\" };\n }\n for (const rule of matchingRules) {\n const denial = evaluateDistributionRule(rule, agent, distribution);\n if (!denial) {\n return {\n allowed: true,\n ruleId: rule.id,\n unverifiedBinaryAllowed: rule.allowUnverifiedBinary === true\n };\n }\n }\n return { allowed: false, reason: \"allowlist-rule-mismatch\" };\n }\n}\n\nexport const defaultAcpAgentAllowlist = new AcpAgentAllowlist(\n DEFAULT_ACP_AGENT_ALLOWLIST\n);\n\nexport function isBannedAcpRegistryId(registryId: string): boolean {\n return BANNED_ACP_REGISTRY_IDS.has(registryId);\n}\n\nfunction evaluateRule(\n rule: AcpAgentAllowlistRule,\n agent: AcpRegistryAgent\n): string | undefined {\n if (rule.versions && (!agent.version || !rule.versions.includes(agent.version))) {\n return \"version-not-allowed\";\n }\n if (isGplFamilyLicense(agent.license) && !rule.allowGplFamilyLicense) {\n return \"license-not-allowed\";\n }\n let distributionDeniedBySource = false;\n for (const distribution of agent.distributions) {\n const denial = evaluateDistributionRule(rule, agent, distribution, {\n skipAgentChecks: true\n });\n if (!denial) {\n return undefined;\n }\n if (denial === \"distribution-source-not-allowed\") {\n distributionDeniedBySource = true;\n }\n }\n return distributionDeniedBySource\n ? \"distribution-source-not-allowed\"\n : \"distribution-not-allowed\";\n}\n\nfunction evaluateDistributionRule(\n rule: AcpAgentAllowlistRule,\n agent: AcpRegistryAgent,\n distribution: AcpRegistryDistribution,\n options: { skipAgentChecks?: boolean } = {}\n): string | undefined {\n if (\n !options.skipAgentChecks &&\n rule.versions &&\n (!agent.version || !rule.versions.includes(agent.version))\n ) {\n return \"version-not-allowed\";\n }\n if (\n !options.skipAgentChecks &&\n isGplFamilyLicense(agent.license) &&\n !rule.allowGplFamilyLicense\n ) {\n return \"license-not-allowed\";\n }\n if (!distributionAllowedByKind(rule, distribution)) {\n return \"distribution-not-allowed\";\n }\n if (!distributionSourceAllowed(rule, distribution)) {\n return \"distribution-source-not-allowed\";\n }\n return undefined;\n}\n\nfunction distributionAllowedByKind(\n rule: AcpAgentAllowlistRule,\n distribution: AcpRegistryDistribution\n): boolean {\n return !rule.distributionKinds || rule.distributionKinds.includes(distribution.kind);\n}\n\nfunction distributionSourceAllowed(\n rule: AcpAgentAllowlistRule,\n distribution: AcpRegistryDistribution\n): boolean {\n if (distribution.kind === \"npx\" || distribution.kind === \"uvx\") {\n return (\n !rule.allowedPackageNames ||\n rule.allowedPackageNames.includes(distribution.packageName)\n );\n }\n if (distribution.kind !== \"binary\") {\n return false;\n }\n if (!rule.allowedArchiveHosts) {\n return true;\n }\n try {\n return rule.allowedArchiveHosts.includes(new URL(distribution.archiveUrl).host);\n } catch {\n return false;\n }\n}\n\nfunction isGplFamilyLicense(license: string | undefined): boolean {\n return /\\b(?:GPL|AGPL|LGPL)\\b/i.test(license ?? \"\");\n}\n","// Registry types for the ACP extension path. The four built-in strategies do\n// NOT require the registry; this is how a host adds more ACP agents from the\n// public Agent Client Protocol registry, gated by the allowlist.\n//\n// Ported from PwrAgnt acp-registry-types.ts, with @pwragent/shared types\n// inlined as neutral local types.\n\nimport { buildAcpBackendId } from \"../strategies/strategy-types\";\n\nexport const ACP_REGISTRY_URL =\n \"https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json\";\n\nexport type AcpDistributionKind = \"npx\" | \"uvx\" | \"binary\" | \"local\";\n\nexport type AcpRegistryDistributionEnv = Record<string, string>;\n\nexport type AcpPackageDistribution = {\n kind: \"npx\" | \"uvx\";\n packageName: string;\n args: string[];\n env: AcpRegistryDistributionEnv;\n};\n\nexport type AcpBinaryPlatformDistribution = {\n kind: \"binary\";\n platform: string;\n archiveUrl: string;\n command: string;\n args: string[];\n env: AcpRegistryDistributionEnv;\n checksum?: string;\n signatureUrl?: string;\n};\n\nexport type AcpRegistryDistribution =\n | AcpPackageDistribution\n | AcpBinaryPlatformDistribution;\n\nexport type AcpRegistryAuthMethod = \"agent-managed\" | \"terminal\" | \"unknown\";\n\nexport type AcpRegistryAuthDescriptor = {\n required: boolean;\n methods: AcpRegistryAuthMethod[];\n raw?: unknown;\n};\n\nexport type AcpRegistryAgent = {\n id: string;\n backendId: string;\n name: string;\n version?: string;\n description?: string;\n authors: string[];\n license?: string;\n repositoryUrl?: string;\n websiteUrl?: string;\n iconUrl?: string;\n distributions: AcpRegistryDistribution[];\n distributionKinds: AcpDistributionKind[];\n auth: AcpRegistryAuthDescriptor;\n raw: unknown;\n};\n\nexport type AcpVerificationStatus =\n | \"verified\"\n | \"unverified-allowed\"\n | \"unverified-blocked\"\n | \"not-applicable\";\n\nexport type AcpAllowlistDecision =\n | { allowed: true; ruleId: string; unverifiedBinaryAllowed: boolean }\n | { allowed: false; reason: string };\n\nexport type AcpRegistryAgentWithPolicy = AcpRegistryAgent & {\n allowlist: AcpAllowlistDecision;\n installable: boolean;\n unavailableReason?: string;\n verificationStatus: AcpVerificationStatus;\n};\n\nexport type AcpRegistrySnapshot = {\n fetchedAt: number;\n agents: AcpRegistryAgent[];\n raw: unknown;\n};\n\nexport { buildAcpBackendId };\n","// Fetch + normalize the public ACP registry and apply the allowlist policy.\n// The EXTENSION path for adding ACP agents beyond the four built-in strategies.\n//\n// Ported from PwrAgnt acp-registry-service.ts, with @pwragent/shared dropped.\n\nimport {\n ACP_REGISTRY_URL,\n buildAcpBackendId,\n type AcpAllowlistDecision,\n type AcpBinaryPlatformDistribution,\n type AcpPackageDistribution,\n type AcpRegistryAgent,\n type AcpRegistryAgentWithPolicy,\n type AcpRegistryAuthDescriptor,\n type AcpRegistryDistribution,\n type AcpRegistrySnapshot,\n type AcpVerificationStatus\n} from \"./acp-registry-types\";\nimport {\n AcpAgentAllowlist,\n defaultAcpAgentAllowlist\n} from \"./acp-agent-allowlist\";\n\nexport type AcpRegistryFetch = (\n input: string,\n init?: { headers?: Record<string, string> }\n) => Promise<{\n ok: boolean;\n status: number;\n statusText: string;\n json(): Promise<unknown>;\n}>;\n\nexport type AcpRegistryServiceOptions = {\n allowlist?: AcpAgentAllowlist;\n fetch?: AcpRegistryFetch;\n now?: () => number;\n registryUrl?: string;\n};\n\nexport type AcpDistributionPolicy = {\n allowlist: AcpAllowlistDecision;\n installable: boolean;\n verificationStatus: AcpVerificationStatus;\n unavailableReason?: string;\n};\n\nexport class AcpRegistryService {\n private readonly allowlist: AcpAgentAllowlist;\n private readonly fetcher: AcpRegistryFetch;\n private readonly now: () => number;\n private readonly registryUrl: string;\n\n constructor(options: AcpRegistryServiceOptions = {}) {\n this.allowlist = options.allowlist ?? defaultAcpAgentAllowlist;\n this.fetcher =\n options.fetch ??\n (async (input, init) => {\n const response = await globalThis.fetch(input, init);\n return {\n ok: response.ok,\n status: response.status,\n statusText: response.statusText,\n json: () => response.json() as Promise<unknown>\n };\n });\n this.now = options.now ?? Date.now;\n this.registryUrl = options.registryUrl ?? ACP_REGISTRY_URL;\n }\n\n async fetchRegistry(): Promise<AcpRegistrySnapshot> {\n const response = await this.fetcher(this.registryUrl, {\n headers: { accept: \"application/json\" }\n });\n if (!response.ok) {\n throw new Error(\n `ACP registry request failed: ${response.status} ${response.statusText}`\n );\n }\n const raw = await response.json();\n return { fetchedAt: this.now(), agents: normalizeRegistry(raw), raw };\n }\n\n applyAllowlist(snapshot: AcpRegistrySnapshot): AcpRegistryAgentWithPolicy[] {\n return snapshot.agents.map((agent) => {\n const allowlist = this.allowlist.evaluate(agent);\n const distributionPolicies = agent.distributions.map((distribution) =>\n this.evaluateDistribution(agent, distribution)\n );\n const installablePolicy = distributionPolicies.find((policy) => policy.installable);\n const firstBlockedAllowedPolicy = distributionPolicies.find(\n (policy) => policy.allowlist.allowed\n );\n const installable = Boolean(installablePolicy);\n const result: AcpRegistryAgentWithPolicy = {\n ...agent,\n allowlist,\n installable,\n verificationStatus:\n installablePolicy?.verificationStatus ??\n firstBlockedAllowedPolicy?.verificationStatus ??\n \"not-applicable\"\n };\n const unavailableReason = installable\n ? undefined\n : (firstBlockedAllowedPolicy?.unavailableReason ??\n (allowlist.allowed ? \"distribution-not-installable\" : allowlist.reason));\n if (unavailableReason !== undefined) result.unavailableReason = unavailableReason;\n return result;\n });\n }\n\n evaluateDistribution(\n agent: AcpRegistryAgent,\n distribution: AcpRegistryDistribution\n ): AcpDistributionPolicy {\n const allowlist = this.allowlist.evaluateDistribution(agent, distribution);\n return evaluateAcpDistributionPolicy(distribution, allowlist);\n }\n}\n\nexport function evaluateAcpDistributionPolicy(\n distribution: AcpRegistryDistribution,\n allowlist: AcpAllowlistDecision\n): AcpDistributionPolicy {\n if (!allowlist.allowed) {\n return {\n allowlist,\n installable: false,\n verificationStatus: \"not-applicable\",\n unavailableReason: allowlist.reason\n };\n }\n if (distribution.kind !== \"binary\") {\n return { allowlist, installable: true, verificationStatus: \"not-applicable\" };\n }\n if (distribution.checksum) {\n return { allowlist, installable: true, verificationStatus: \"verified\" };\n }\n return {\n allowlist,\n installable: allowlist.unverifiedBinaryAllowed,\n verificationStatus: allowlist.unverifiedBinaryAllowed\n ? \"unverified-allowed\"\n : \"unverified-blocked\",\n ...(allowlist.unverifiedBinaryAllowed\n ? {}\n : { unavailableReason: \"binary-integrity-metadata-missing\" })\n };\n}\n\nexport function normalizeRegistry(raw: unknown): AcpRegistryAgent[] {\n const record = asRecord(raw);\n const rawAgents = Array.isArray(record?.agents) ? record.agents : [];\n return rawAgents.flatMap((item) => {\n const agent = normalizeAgent(item);\n return agent ? [agent] : [];\n });\n}\n\nfunction normalizeAgent(raw: unknown): AcpRegistryAgent | undefined {\n const record = asRecord(raw);\n if (!record || typeof record.id !== \"string\" || typeof record.name !== \"string\") {\n return undefined;\n }\n const distributions = normalizeDistributions(record.distribution);\n if (distributions.length === 0) {\n return undefined;\n }\n const agent: AcpRegistryAgent = {\n id: record.id,\n backendId: buildAcpBackendId(record.id),\n name: record.name,\n authors: Array.isArray(record.authors)\n ? record.authors.filter((author): author is string => typeof author === \"string\")\n : [],\n distributions,\n distributionKinds: [...new Set(distributions.map((d) => d.kind))],\n auth: normalizeAuth(record.auth),\n raw\n };\n const version = stringValue(record.version);\n if (version !== undefined) agent.version = version;\n const description = stringValue(record.description);\n if (description !== undefined) agent.description = description;\n const license = stringValue(record.license);\n if (license !== undefined) agent.license = license;\n const repositoryUrl = stringValue(record.repository);\n if (repositoryUrl !== undefined) agent.repositoryUrl = repositoryUrl;\n const websiteUrl = stringValue(record.website);\n if (websiteUrl !== undefined) agent.websiteUrl = websiteUrl;\n const iconUrl = stringValue(record.icon);\n if (iconUrl !== undefined) agent.iconUrl = iconUrl;\n return agent;\n}\n\nfunction normalizeDistributions(raw: unknown): AcpRegistryDistribution[] {\n const record = asRecord(raw);\n if (!record) {\n return [];\n }\n const distributions: AcpRegistryDistribution[] = [];\n const npx = normalizePackageDistribution(\"npx\", record.npx);\n if (npx) distributions.push(npx);\n const uvx = normalizePackageDistribution(\"uvx\", record.uvx);\n if (uvx) distributions.push(uvx);\n const binaryRecord = asRecord(record.binary);\n if (binaryRecord) {\n for (const [platform, value] of Object.entries(binaryRecord)) {\n const binary = normalizeBinaryDistribution(platform, value);\n if (binary) distributions.push(binary);\n }\n }\n return distributions;\n}\n\nfunction normalizePackageDistribution(\n kind: \"npx\" | \"uvx\",\n raw: unknown\n): AcpPackageDistribution | undefined {\n const record = asRecord(raw);\n if (!record || typeof record.package !== \"string\") {\n return undefined;\n }\n return {\n kind,\n packageName: record.package,\n args: stringArray(record.args),\n env: stringRecord(record.env)\n };\n}\n\nfunction normalizeBinaryDistribution(\n platform: string,\n raw: unknown\n): AcpBinaryPlatformDistribution | undefined {\n const record = asRecord(raw);\n if (!record || typeof record.archive !== \"string\" || typeof record.cmd !== \"string\") {\n return undefined;\n }\n const distribution: AcpBinaryPlatformDistribution = {\n kind: \"binary\",\n platform,\n archiveUrl: record.archive,\n command: record.cmd,\n args: stringArray(record.args),\n env: stringRecord(record.env)\n };\n const checksum = stringValue(record.checksum) ?? stringValue(record.sha256);\n if (checksum !== undefined) distribution.checksum = checksum;\n const signatureUrl = stringValue(record.signature) ?? stringValue(record.signatureUrl);\n if (signatureUrl !== undefined) distribution.signatureUrl = signatureUrl;\n return distribution;\n}\n\nfunction normalizeAuth(raw: unknown): AcpRegistryAuthDescriptor {\n if (!raw) {\n return { required: false, methods: [] };\n }\n const record = asRecord(raw);\n if (!record) {\n return { required: true, methods: [\"unknown\"], raw };\n }\n const methods = stringArray(record.methods).map((method) =>\n method === \"agent-managed\" || method === \"terminal\" ? method : \"unknown\"\n );\n return {\n required: record.required === false ? false : true,\n methods: methods.length > 0 ? [...new Set(methods)] : [\"unknown\"],\n raw\n };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction stringArray(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === \"string\")\n : [];\n}\n\nfunction stringRecord(value: unknown): Record<string, string> {\n const record = asRecord(value);\n if (!record) {\n return {};\n }\n return Object.fromEntries(\n Object.entries(record).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\"\n )\n );\n}\n"],"mappings":"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","names":["noopLogger","path","path","noopLogger","protocolSessionId","threadId","asRecord","readString","path","noopLogger","errorMessage","noopLogger","noopLogger","homedir","path","path","homedir","homedir","path","path","homedir","homedir","path","createCommandInvocation","prependCommandDirToPath","path","homedir","prependCommandDirToPath","createCommandInvocation","asRecord"]}