@pwrdrvr/agent-acp 0.1.9 → 0.2.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 CHANGED
@@ -852,7 +852,6 @@ var AcpAgentClient = class {
852
852
  async startThread(options = {}) {
853
853
  const ignored = [];
854
854
  for (const key of [
855
- "instructions",
856
855
  "approvalPolicy",
857
856
  "sandbox",
858
857
  "config",
@@ -873,6 +872,10 @@ var AcpAgentClient = class {
873
872
  const native = {};
874
873
  if (options.cwd !== void 0) native.cwd = options.cwd;
875
874
  const result = await this.startThreadNative(native);
875
+ if (typeof options.instructions === "string" && options.instructions.length > 0) {
876
+ const session = this.sessions.get(result.threadId);
877
+ if (session) session.pendingInstructions = options.instructions;
878
+ }
876
879
  if (options.model !== void 0) {
877
880
  await this.setModel(result.threadId, options.model).catch((cause) => {
878
881
  this.logger.debug("acp startThread: model selection not applied", {
@@ -913,7 +916,9 @@ var AcpAgentClient = class {
913
916
  protocolSessionId,
914
917
  normalizer: new AcpSessionNormalizer({ quirks: this.strategy.quirks }),
915
918
  turnId: void 0,
916
- runtimeState: void 0
919
+ runtimeState: void 0,
920
+ pendingTurn: void 0,
921
+ pendingInstructions: void 0
917
922
  };
918
923
  this.sessions.set(threadId, session);
919
924
  this.threadIdByProtocolId.set(protocolSessionId, threadId);
@@ -943,9 +948,13 @@ var AcpAgentClient = class {
943
948
  * IGNORED (debug-logged).
944
949
  */
945
950
  async startTurn(options) {
946
- const promptContent = [
947
- { type: "text", text: options.input.text }
948
- ];
951
+ const promptContent = [];
952
+ const session = this.sessions.get(options.threadId);
953
+ if (session?.pendingInstructions !== void 0) {
954
+ promptContent.push({ type: "text", text: session.pendingInstructions });
955
+ session.pendingInstructions = void 0;
956
+ }
957
+ promptContent.push({ type: "text", text: options.input.text });
949
958
  for (const imagePath of options.input.imagePaths ?? []) {
950
959
  const block = await this.imageBlockFromPath(imagePath).catch((cause) => {
951
960
  this.logger.debug("acp startTurn: skipping unreadable image", {
@@ -978,18 +987,35 @@ var AcpAgentClient = class {
978
987
  session.normalizer.resetTurn();
979
988
  this.emit({ kind: "turn_started", threadId: session.threadId, turnId });
980
989
  const prompt = options.promptContent ?? textPrompt(options.prompt ?? "");
981
- let promptResult;
982
- try {
983
- promptResult = await this.transport.request(
984
- "session/prompt",
985
- {
986
- sessionId: session.protocolSessionId,
987
- prompt
988
- },
989
- ACP_PROMPT_REQUEST_TIMEOUT_MS
990
- );
991
- } catch (error) {
990
+ session.pendingTurn = this.transport.request(
991
+ "session/prompt",
992
+ {
993
+ sessionId: session.protocolSessionId,
994
+ prompt
995
+ },
996
+ ACP_PROMPT_REQUEST_TIMEOUT_MS
997
+ ).then((promptResult) => {
998
+ const usage = readAcpPromptUsage(promptResult);
999
+ if (usage) {
1000
+ this.emit({ kind: "token_usage", threadId: session.threadId, turnId, usage });
1001
+ }
1002
+ for (const event of session.normalizer.finalizeAssistantMessage({
1003
+ threadId: session.threadId,
1004
+ turnId
1005
+ })) {
1006
+ this.emit(event);
1007
+ }
992
1008
  session.turnId = void 0;
1009
+ session.pendingTurn = void 0;
1010
+ this.emit({
1011
+ kind: "turn_completed",
1012
+ threadId: session.threadId,
1013
+ turnId,
1014
+ status: "completed"
1015
+ });
1016
+ }).catch((error) => {
1017
+ session.turnId = void 0;
1018
+ session.pendingTurn = void 0;
993
1019
  this.emit({
994
1020
  kind: "turn_completed",
995
1021
  threadId: session.threadId,
@@ -1002,24 +1028,6 @@ var AcpAgentClient = class {
1002
1028
  turnId,
1003
1029
  message: errorMessage(error)
1004
1030
  });
1005
- throw error;
1006
- }
1007
- const usage = readAcpPromptUsage(promptResult);
1008
- if (usage) {
1009
- this.emit({ kind: "token_usage", threadId: session.threadId, turnId, usage });
1010
- }
1011
- for (const event of session.normalizer.finalizeAssistantMessage({
1012
- threadId: session.threadId,
1013
- turnId
1014
- })) {
1015
- this.emit(event);
1016
- }
1017
- session.turnId = void 0;
1018
- this.emit({
1019
- kind: "turn_completed",
1020
- threadId: session.threadId,
1021
- turnId,
1022
- status: "completed"
1023
1031
  });
1024
1032
  return { turnId };
1025
1033
  }
@@ -1049,10 +1057,12 @@ var AcpAgentClient = class {
1049
1057
  this.unsubscribeNotification = void 0;
1050
1058
  this.unsubscribeRequest?.();
1051
1059
  this.unsubscribeRequest = void 0;
1060
+ const pending = [...this.sessions.values()].map((s) => s.pendingTurn).filter((p) => p !== void 0);
1052
1061
  this.sessions.clear();
1053
1062
  this.threadIdByProtocolId.clear();
1054
1063
  this.initialized = false;
1055
1064
  await this.transport.close?.();
1065
+ if (pending.length > 0) await Promise.allSettled(pending);
1056
1066
  }
1057
1067
  // ---- internals ----
1058
1068
  emit(event) {
@@ -1452,11 +1462,18 @@ var AcpOneShotClient = class {
1452
1462
  let finalText = "";
1453
1463
  const deltas = [];
1454
1464
  let usage = null;
1465
+ let turnError = null;
1466
+ let settle = () => void 0;
1467
+ const done = new Promise((resolve) => {
1468
+ settle = resolve;
1469
+ });
1455
1470
  const unsubscribe = this.client.onEvent((event) => {
1456
1471
  if (!("threadId" in event) || event.threadId !== thread.threadId) return;
1457
1472
  if (event.kind === "agent_message") finalText = event.message.text;
1458
1473
  else if (event.kind === "agent_message_delta") deltas.push(event.delta);
1459
1474
  else if (event.kind === "token_usage") usage = event.usage;
1475
+ else if (event.kind === "error") turnError = event.message;
1476
+ else if (event.kind === "turn_completed") settle(event.status);
1460
1477
  });
1461
1478
  try {
1462
1479
  const { turnId } = await this.client.startTurn({
@@ -1467,6 +1484,10 @@ var AcpOneShotClient = class {
1467
1484
  },
1468
1485
  ...request.effort !== void 0 ? { reasoning: request.effort } : {}
1469
1486
  });
1487
+ const status = await done;
1488
+ if (status !== "completed") {
1489
+ throw new Error(turnError ?? `ACP one-shot turn ${status}`);
1490
+ }
1470
1491
  const rawText = finalText.length > 0 ? finalText : deltas.join("");
1471
1492
  return {
1472
1493
  rawText,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/acp-stdio-transport.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/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 stdio transport. Wraps @pwrdrvr/agent-transport's JsonRpcConnection +\n// StdioJsonRpcTransport — we do NOT reimplement JSON-RPC or the line-delimited\n// stdio framing. This adapter just spawns the agent's ACP stdio command and\n// presents the bidirectional ACP shape (request / notify / onNotification /\n// onRequest) the AcpAgentClient consumes.\n//\n// Ported from PwrAgnt acp-stdio-transport.ts, retargeted onto the shared core.\n\nimport { noopLogger, type Logger } from \"@pwrdrvr/agent-core\";\nimport {\n JsonRpcConnection,\n StdioJsonRpcTransport,\n type JsonRpcId,\n type JsonRpcObserver,\n type JsonRpcTransport\n} from \"@pwrdrvr/agent-transport\";\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10 * 60_000;\n\n/** The bidirectional transport shape the ACP client drives. */\nexport interface AcpJsonRpcTransport {\n request(\n method: string,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ): Promise<unknown>;\n notify?(method: string, params?: Record<string, unknown>): Promise<void>;\n close?(): Promise<void>;\n onNotification(\n listener: (method: string, params: Record<string, unknown>) => void\n ): () => void;\n onRequest?(\n listener: (\n method: string,\n params: Record<string, unknown>,\n id?: JsonRpcId\n ) => Promise<unknown> | unknown\n ): () => void;\n}\n\nexport type AcpStdioJsonRpcTransportOptions = {\n command: string;\n args: string[];\n env?: NodeJS.ProcessEnv;\n requestTimeoutMs?: number;\n observer?: JsonRpcObserver;\n logger?: Logger;\n /** Override the underlying JSON-RPC transport (tests inject a fake). */\n transport?: JsonRpcTransport;\n};\n\nexport class AcpStdioJsonRpcTransport implements AcpJsonRpcTransport {\n private readonly connection: JsonRpcConnection;\n private readonly notificationListeners = new Set<\n (method: string, params: Record<string, unknown>) => void\n >();\n private requestHandler:\n | ((\n method: string,\n params: Record<string, unknown>,\n id?: JsonRpcId\n ) => Promise<unknown> | unknown)\n | undefined;\n\n constructor(options: AcpStdioJsonRpcTransportOptions) {\n const logger = options.logger ?? noopLogger;\n const transport =\n options.transport ??\n new StdioJsonRpcTransport({\n command: options.command,\n args: options.args,\n ...(options.env !== undefined ? { env: options.env } : {}),\n logger\n });\n this.connection = new JsonRpcConnection(\n transport,\n options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n options.observer,\n { logger, logContext: { owner: \"acp-stdio-transport\" } }\n );\n this.connection.setNotificationHandler((method, params) => {\n const normalized = asRecord(params) ?? {};\n for (const listener of this.notificationListeners) {\n listener(method, normalized);\n }\n });\n this.connection.setRequestHandler(async (method, params, id) => {\n if (!this.requestHandler) {\n throw new Error(`ACP request handler unavailable for ${method}`);\n }\n return await this.requestHandler(method, asRecord(params) ?? {}, id);\n });\n }\n\n async connect(): Promise<void> {\n await this.connection.connect();\n }\n\n async request(\n method: string,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ): Promise<unknown> {\n await this.connection.connect();\n return await this.connection.request(method, params, timeoutMs);\n }\n\n async notify(method: string, params?: Record<string, unknown>): Promise<void> {\n await this.connection.connect();\n await this.connection.notify(method, params);\n }\n\n async close(): Promise<void> {\n await this.connection.close();\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\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","// 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 { 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 acpRuntimeSupportsSessionLoad,\n acpSessionRuntimeStateFromCapabilities,\n acpSessionRuntimeStateFromUpdate,\n mergeAcpRuntimeState,\n modeLabelFor,\n normalizeAcpRuntimeCapabilities,\n type AcpRuntimeCapabilities,\n type AcpSessionRuntimeState\n} from \"./normalizer/runtime-capabilities\";\nimport type { AcpJsonRpcTransport } from \"./acp-stdio-transport\";\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 AcpMcpServerConfig = {\n name: string;\n command: string;\n args?: string[];\n env?: Record<string, string>;\n};\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?: 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?: 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};\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 private threadSequence = 0;\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: 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 \"instructions\",\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 if (options.model !== undefined) {\n await this.setModel(result.threadId, options.model).catch((cause) => {\n this.logger.debug(\"acp startThread: model selection not applied\", {\n model: options.model,\n message: cause instanceof Error ? cause.message : String(cause)\n });\n });\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 await this.initialize();\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 mcpServers = options.mcpServers ?? this.defaultMcpServers;\n const result = await this.transport.request(\"session/new\", {\n cwd,\n mcpServers\n });\n const record = asRecord(result);\n const protocolSessionId =\n readString(record, \"sessionId\") ?? readString(record, \"session_id\");\n if (!protocolSessionId) {\n throw new Error(\"ACP session/new did not return a session id\");\n }\n const threadId = `acp:${this.strategy.id}:${++this.threadSequence}`;\n const session: AcpSessionState = {\n threadId,\n protocolSessionId,\n normalizer: new AcpSessionNormalizer({ quirks: this.strategy.quirks }),\n turnId: undefined,\n runtimeState: undefined\n };\n this.sessions.set(threadId, session);\n this.threadIdByProtocolId.set(protocolSessionId, threadId);\n\n const runtimeCapabilities = this.captureRuntimeCapabilities(\"session-new\", result);\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 started\", { threadId, protocolSessionId });\n const out: AgentBackendStartThreadResult = { threadId };\n const model = runtimeCapabilities?.models?.currentModelId;\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 { type: \"text\", text: options.input.text }\n ];\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 let promptResult: unknown;\n try {\n promptResult = await this.transport.request(\n \"session/prompt\",\n {\n sessionId: session.protocolSessionId,\n prompt\n },\n ACP_PROMPT_REQUEST_TIMEOUT_MS\n );\n } catch (error) {\n session.turnId = 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 throw error;\n }\n\n // Token usage rides on the `session/prompt` RESPONSE (`_meta.quota`), not a\n // session/update — emit it so hosts can account for ACP turns the same way\n // they do Codex turns.\n const usage = readAcpPromptUsage(promptResult);\n if (usage) {\n this.emit({ kind: \"token_usage\", threadId: session.threadId, turnId, usage });\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 this.emit({\n kind: \"turn_completed\",\n threadId: session.threadId,\n turnId,\n status: \"completed\"\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 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 this.sessions.clear();\n this.threadIdByProtocolId.clear();\n this.initialized = false;\n await this.transport.close?.();\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 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 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 decision = await handler(\"session/request_permission\", params);\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. We try to match\n * it to an available MODE (by id or label, case-insensitively) and switch via\n * `session/set_mode`. ACP has no first-class \"reasoning effort\" concept, so if\n * no mode matches we leave it alone — the caller's `.catch` debug-logs. */\n private async applyReasoning(threadId: string, reasoning: string): Promise<void> {\n const modes = this.runtimeCapabilities?.modes?.availableModes ?? [];\n const target = reasoning.toLowerCase();\n const match = modes.find(\n (mode) =>\n mode.id.toLowerCase() === target ||\n (typeof mode.label === \"string\" && mode.label.toLowerCase() === target)\n );\n if (match === undefined) {\n this.logger.debug(\"acp reasoning has no matching mode — ignored\", { reasoning });\n return;\n }\n await this.setMode(threadId, match.id);\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 ?? capabilities?.models?.currentModelId;\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 /** Whether the agent advertises session/load support (for hosts that resume). */\n supportsSessionLoad(): boolean {\n return acpRuntimeSupportsSessionLoad(this.runtimeCapabilities);\n }\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\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 return (\n options.find((option) => option.kind === \"allow_once\") ??\n options.find((option) => option.kind === \"allow_always\") ??\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\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error && error.message.trim()) {\n return error.message;\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\n/** Read token usage from a `session/prompt` response. Agents report it in\n * `_meta.quota.token_count`, e.g. Gemini:\n * `{ _meta: { quota: { token_count: { input_tokens, output_tokens } } } }`.\n * Returns undefined when no usage is present. */\nfunction readAcpPromptUsage(result: unknown): NormalizedTokenUsage | undefined {\n const meta = asRecord(asRecord(result)?._meta);\n const tokenCount = asRecord(asRecord(meta?.quota)?.token_count);\n if (!tokenCount) return undefined;\n const num = (value: unknown): number | undefined =>\n typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n const input = num(tokenCount.input_tokens);\n const output = num(tokenCount.output_tokens);\n const cached = num(tokenCount.cached_input_tokens ?? tokenCount.cached_tokens);\n const reasoning = num(tokenCount.thoughts_tokens ?? tokenCount.reasoning_tokens);\n if (input === undefined && output === undefined) return undefined;\n const usage: NormalizedTokenUsage = { totalTokens: (input ?? 0) + (output ?? 0) };\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","// 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 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 // An explicit display target only when the update actually names one. A\n // kind-derived label (\"execute\") is NOT used here, so a later output-only\n // update never clobbers an earlier specific displayCommand on merge (the\n // normalizer reconciles displayCommand via preferSpecificLabel).\n const explicitDisplay = command ?? readString(update, \"title\");\n if (command || output !== 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 if ((toolKind === \"write\" || toolKind === \"read\") && path) {\n // Surface the path through the label-adjacent command detail so consumers\n // that render a file target can find it without an ACP-specific field.\n if (!call.command) {\n call.command = { displayCommand: label };\n }\n }\n\n return call;\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};\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 AcpRuntimeAgentCapabilities = {\n loadSession?: boolean;\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\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) result.currentModelId = currentModelId;\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\n const capabilities: AcpRuntimeAgentCapabilities = {\n raw: record ?? sessionCapabilities\n };\n if (loadSession !== undefined) capabilities.loadSession = loadSession;\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","// 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-stdio-transport\";\nimport type { AcpAgentStrategy } from \"./strategies/strategy-types\";\nimport type { AcpRuntimeModel } 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 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 });\n\n try {\n // `startTurn` resolves AT turn end — by then the terminal `agent_message`\n // (full text) and `turn_completed` have already been emitted + captured.\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 rawText = finalText.length > 0 ? finalText : deltas.join(\"\");\n return {\n rawText,\n threadId: thread.threadId,\n turnId,\n model: request.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 const observed = event.runtimeCapabilities.models?.availableModels;\n if (observed !== undefined && 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 that print help/usage text the `helpMatches` regex confirms ACP support against. */\n helpArgs: string[];\n /** Regex the help/usage output must match for the agent to count as ACP-capable. */\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 helpArgs: [\"acp\", \"--help\"],\n // Real `kimi acp --help` (v0.11.0): \"Run kimi-code as an Agent Client\n // Protocol (ACP) server over stdio.\" The old /\\bACP server\\b/ never matched\n // — \"(ACP) server\" has a paren between ACP and \"server\". Match the protocol\n // name, or \"ACP\" loosely followed by \"server\".\n helpMatches: /agent client protocol|\\bacp\\b[\\s)]*server\\b/i,\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// • `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 { prependCommandDirToPath } 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/** 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 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};\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.\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 )\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): Promise<DiscoveredAcpAgentGroup | undefined> {\n const candidates = candidateCommands(strategy, env, listExecutables, override);\n const instances: DiscoveredAcpAgentInstance[] = [];\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 if (!versionResult || !helpResult) {\n continue;\n }\n if (!strategy.discoveryProbe.helpMatches.test(resultText(helpResult))) {\n continue;\n }\n const version = parseCliVersion(resultText(versionResult));\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) {\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 discoveredAt: now()\n };\n}\n\ntype Candidate = { command: string; source: AcpAgentInstanceSource };\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 = (command: string, source: AcpAgentInstanceSource): 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 });\n };\n\n if (override && override.trim().length > 0) {\n push(override, \"override\");\n }\n const pathMatches = listExecutables(strategy.discoveryProbe.command, env);\n if (pathMatches.length > 0) {\n for (const match of pathMatches) push(match, \"path\");\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\");\n }\n for (const fallback of strategy.discoveryProbe.fallbackCommands ?? []) {\n push(fallback, \"fallback\");\n }\n return out;\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)) return command;\n try {\n return realpathSync(command);\n } catch {\n return 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`. POSIX only (Windows\n * returns none).\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 if (process.platform === \"win32\") return [];\n // A bare command name only — never enumerate when a path was passed.\n if (command.includes(path.sep)) return [];\n const found: string[] = [];\n const seenDir = new Set<string>();\n for (const dir of discoveryDirs(env)) {\n if (dir.length === 0 || seenDir.has(dir)) continue;\n seenDir.add(dir);\n const candidate = path.join(dir, command);\n try {\n const stat = statSync(candidate);\n if (stat.isFile() && (stat.mode & 0o111) !== 0) {\n found.push(candidate);\n }\n } catch {\n // Not in this dir; keep scanning.\n }\n }\n return found;\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 = env.PATH ?? env.Path ?? \"\";\n return [...pathValue.split(path.delimiter), ...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 return await execFile(command, 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: prependCommandDirToPath(command, env)\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","asRecord","path","path","asRecord","asRecord","asRecord","noopLogger","asRecord","readString","noopLogger","noopLogger","homedir","path","path","homedir","homedir","path","path","homedir","homedir","path","path","homedir","asRecord"]}
1
+ {"version":3,"sources":["../src/acp-stdio-transport.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/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 stdio transport. Wraps @pwrdrvr/agent-transport's JsonRpcConnection +\n// StdioJsonRpcTransport — we do NOT reimplement JSON-RPC or the line-delimited\n// stdio framing. This adapter just spawns the agent's ACP stdio command and\n// presents the bidirectional ACP shape (request / notify / onNotification /\n// onRequest) the AcpAgentClient consumes.\n//\n// Ported from PwrAgnt acp-stdio-transport.ts, retargeted onto the shared core.\n\nimport { noopLogger, type Logger } from \"@pwrdrvr/agent-core\";\nimport {\n JsonRpcConnection,\n StdioJsonRpcTransport,\n type JsonRpcId,\n type JsonRpcObserver,\n type JsonRpcTransport\n} from \"@pwrdrvr/agent-transport\";\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10 * 60_000;\n\n/** The bidirectional transport shape the ACP client drives. */\nexport interface AcpJsonRpcTransport {\n request(\n method: string,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ): Promise<unknown>;\n notify?(method: string, params?: Record<string, unknown>): Promise<void>;\n close?(): Promise<void>;\n onNotification(\n listener: (method: string, params: Record<string, unknown>) => void\n ): () => void;\n onRequest?(\n listener: (\n method: string,\n params: Record<string, unknown>,\n id?: JsonRpcId\n ) => Promise<unknown> | unknown\n ): () => void;\n}\n\nexport type AcpStdioJsonRpcTransportOptions = {\n command: string;\n args: string[];\n env?: NodeJS.ProcessEnv;\n requestTimeoutMs?: number;\n observer?: JsonRpcObserver;\n logger?: Logger;\n /** Override the underlying JSON-RPC transport (tests inject a fake). */\n transport?: JsonRpcTransport;\n};\n\nexport class AcpStdioJsonRpcTransport implements AcpJsonRpcTransport {\n private readonly connection: JsonRpcConnection;\n private readonly notificationListeners = new Set<\n (method: string, params: Record<string, unknown>) => void\n >();\n private requestHandler:\n | ((\n method: string,\n params: Record<string, unknown>,\n id?: JsonRpcId\n ) => Promise<unknown> | unknown)\n | undefined;\n\n constructor(options: AcpStdioJsonRpcTransportOptions) {\n const logger = options.logger ?? noopLogger;\n const transport =\n options.transport ??\n new StdioJsonRpcTransport({\n command: options.command,\n args: options.args,\n ...(options.env !== undefined ? { env: options.env } : {}),\n logger\n });\n this.connection = new JsonRpcConnection(\n transport,\n options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n options.observer,\n { logger, logContext: { owner: \"acp-stdio-transport\" } }\n );\n this.connection.setNotificationHandler((method, params) => {\n const normalized = asRecord(params) ?? {};\n for (const listener of this.notificationListeners) {\n listener(method, normalized);\n }\n });\n this.connection.setRequestHandler(async (method, params, id) => {\n if (!this.requestHandler) {\n throw new Error(`ACP request handler unavailable for ${method}`);\n }\n return await this.requestHandler(method, asRecord(params) ?? {}, id);\n });\n }\n\n async connect(): Promise<void> {\n await this.connection.connect();\n }\n\n async request(\n method: string,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ): Promise<unknown> {\n await this.connection.connect();\n return await this.connection.request(method, params, timeoutMs);\n }\n\n async notify(method: string, params?: Record<string, unknown>): Promise<void> {\n await this.connection.connect();\n await this.connection.notify(method, params);\n }\n\n async close(): Promise<void> {\n await this.connection.close();\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\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","// 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 { 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 acpRuntimeSupportsSessionLoad,\n acpSessionRuntimeStateFromCapabilities,\n acpSessionRuntimeStateFromUpdate,\n mergeAcpRuntimeState,\n modeLabelFor,\n normalizeAcpRuntimeCapabilities,\n type AcpRuntimeCapabilities,\n type AcpSessionRuntimeState\n} from \"./normalizer/runtime-capabilities\";\nimport type { AcpJsonRpcTransport } from \"./acp-stdio-transport\";\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 AcpMcpServerConfig = {\n name: string;\n command: string;\n args?: string[];\n env?: Record<string, string>;\n};\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?: 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?: 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};\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 private threadSequence = 0;\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: 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 if (options.model !== undefined) {\n await this.setModel(result.threadId, options.model).catch((cause) => {\n this.logger.debug(\"acp startThread: model selection not applied\", {\n model: options.model,\n message: cause instanceof Error ? cause.message : String(cause)\n });\n });\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 await this.initialize();\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 mcpServers = options.mcpServers ?? this.defaultMcpServers;\n const result = await this.transport.request(\"session/new\", {\n cwd,\n mcpServers\n });\n const record = asRecord(result);\n const protocolSessionId =\n readString(record, \"sessionId\") ?? readString(record, \"session_id\");\n if (!protocolSessionId) {\n throw new Error(\"ACP session/new did not return a session id\");\n }\n const threadId = `acp:${this.strategy.id}:${++this.threadSequence}`;\n const session: AcpSessionState = {\n threadId,\n protocolSessionId,\n normalizer: new AcpSessionNormalizer({ quirks: this.strategy.quirks }),\n turnId: undefined,\n runtimeState: undefined,\n pendingTurn: undefined,\n pendingInstructions: undefined\n };\n this.sessions.set(threadId, session);\n this.threadIdByProtocolId.set(protocolSessionId, threadId);\n\n const runtimeCapabilities = this.captureRuntimeCapabilities(\"session-new\", result);\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 started\", { threadId, protocolSessionId });\n const out: AgentBackendStartThreadResult = { threadId };\n const model = runtimeCapabilities?.models?.currentModelId;\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 }\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 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 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 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 decision = await handler(\"session/request_permission\", params);\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. We try to match\n * it to an available MODE (by id or label, case-insensitively) and switch via\n * `session/set_mode`. ACP has no first-class \"reasoning effort\" concept, so if\n * no mode matches we leave it alone — the caller's `.catch` debug-logs. */\n private async applyReasoning(threadId: string, reasoning: string): Promise<void> {\n const modes = this.runtimeCapabilities?.modes?.availableModes ?? [];\n const target = reasoning.toLowerCase();\n const match = modes.find(\n (mode) =>\n mode.id.toLowerCase() === target ||\n (typeof mode.label === \"string\" && mode.label.toLowerCase() === target)\n );\n if (match === undefined) {\n this.logger.debug(\"acp reasoning has no matching mode — ignored\", { reasoning });\n return;\n }\n await this.setMode(threadId, match.id);\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 ?? capabilities?.models?.currentModelId;\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 /** Whether the agent advertises session/load support (for hosts that resume). */\n supportsSessionLoad(): boolean {\n return acpRuntimeSupportsSessionLoad(this.runtimeCapabilities);\n }\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\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 return (\n options.find((option) => option.kind === \"allow_once\") ??\n options.find((option) => option.kind === \"allow_always\") ??\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\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error && error.message.trim()) {\n return error.message;\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\n/** Read token usage from a `session/prompt` response. Agents report it in\n * `_meta.quota.token_count`, e.g. Gemini:\n * `{ _meta: { quota: { token_count: { input_tokens, output_tokens } } } }`.\n * Returns undefined when no usage is present. */\nfunction readAcpPromptUsage(result: unknown): NormalizedTokenUsage | undefined {\n const meta = asRecord(asRecord(result)?._meta);\n const tokenCount = asRecord(asRecord(meta?.quota)?.token_count);\n if (!tokenCount) return undefined;\n const num = (value: unknown): number | undefined =>\n typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n const input = num(tokenCount.input_tokens);\n const output = num(tokenCount.output_tokens);\n const cached = num(tokenCount.cached_input_tokens ?? tokenCount.cached_tokens);\n const reasoning = num(tokenCount.thoughts_tokens ?? tokenCount.reasoning_tokens);\n if (input === undefined && output === undefined) return undefined;\n const usage: NormalizedTokenUsage = { totalTokens: (input ?? 0) + (output ?? 0) };\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","// 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 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 // An explicit display target only when the update actually names one. A\n // kind-derived label (\"execute\") is NOT used here, so a later output-only\n // update never clobbers an earlier specific displayCommand on merge (the\n // normalizer reconciles displayCommand via preferSpecificLabel).\n const explicitDisplay = command ?? readString(update, \"title\");\n if (command || output !== 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 if ((toolKind === \"write\" || toolKind === \"read\") && path) {\n // Surface the path through the label-adjacent command detail so consumers\n // that render a file target can find it without an ACP-specific field.\n if (!call.command) {\n call.command = { displayCommand: label };\n }\n }\n\n return call;\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};\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 AcpRuntimeAgentCapabilities = {\n loadSession?: boolean;\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\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) result.currentModelId = currentModelId;\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\n const capabilities: AcpRuntimeAgentCapabilities = {\n raw: record ?? sessionCapabilities\n };\n if (loadSession !== undefined) capabilities.loadSession = loadSession;\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","// 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-stdio-transport\";\nimport type { AcpAgentStrategy } from \"./strategies/strategy-types\";\nimport type { AcpRuntimeModel } 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 model: request.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 const observed = event.runtimeCapabilities.models?.availableModels;\n if (observed !== undefined && 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 that print help/usage text the `helpMatches` regex confirms ACP support against. */\n helpArgs: string[];\n /** Regex the help/usage output must match for the agent to count as ACP-capable. */\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 helpArgs: [\"acp\", \"--help\"],\n // Real `kimi acp --help` (v0.11.0): \"Run kimi-code as an Agent Client\n // Protocol (ACP) server over stdio.\" The old /\\bACP server\\b/ never matched\n // — \"(ACP) server\" has a paren between ACP and \"server\". Match the protocol\n // name, or \"ACP\" loosely followed by \"server\".\n helpMatches: /agent client protocol|\\bacp\\b[\\s)]*server\\b/i,\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// • `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 { prependCommandDirToPath } 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/** 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 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};\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.\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 )\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): Promise<DiscoveredAcpAgentGroup | undefined> {\n const candidates = candidateCommands(strategy, env, listExecutables, override);\n const instances: DiscoveredAcpAgentInstance[] = [];\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 if (!versionResult || !helpResult) {\n continue;\n }\n if (!strategy.discoveryProbe.helpMatches.test(resultText(helpResult))) {\n continue;\n }\n const version = parseCliVersion(resultText(versionResult));\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) {\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 discoveredAt: now()\n };\n}\n\ntype Candidate = { command: string; source: AcpAgentInstanceSource };\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 = (command: string, source: AcpAgentInstanceSource): 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 });\n };\n\n if (override && override.trim().length > 0) {\n push(override, \"override\");\n }\n const pathMatches = listExecutables(strategy.discoveryProbe.command, env);\n if (pathMatches.length > 0) {\n for (const match of pathMatches) push(match, \"path\");\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\");\n }\n for (const fallback of strategy.discoveryProbe.fallbackCommands ?? []) {\n push(fallback, \"fallback\");\n }\n return out;\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)) return command;\n try {\n return realpathSync(command);\n } catch {\n return 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`. POSIX only (Windows\n * returns none).\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 if (process.platform === \"win32\") return [];\n // A bare command name only — never enumerate when a path was passed.\n if (command.includes(path.sep)) return [];\n const found: string[] = [];\n const seenDir = new Set<string>();\n for (const dir of discoveryDirs(env)) {\n if (dir.length === 0 || seenDir.has(dir)) continue;\n seenDir.add(dir);\n const candidate = path.join(dir, command);\n try {\n const stat = statSync(candidate);\n if (stat.isFile() && (stat.mode & 0o111) !== 0) {\n found.push(candidate);\n }\n } catch {\n // Not in this dir; keep scanning.\n }\n }\n return found;\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 = env.PATH ?? env.Path ?? \"\";\n return [...pathValue.split(path.delimiter), ...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 return await execFile(command, 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: prependCommandDirToPath(command, env)\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","asRecord","path","path","asRecord","asRecord","asRecord","noopLogger","asRecord","readString","noopLogger","noopLogger","homedir","path","path","homedir","homedir","path","path","homedir","homedir","path","path","homedir","asRecord"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pwrdrvr/agent-acp",
3
- "version": "0.1.9",
3
+ "version": "0.2.0",
4
4
  "description": "ACP (Agent Client Protocol) backend adapter for agent-kit: speaks ACP over stdio to local Kimi/Qwen/Gemini/Grok CLIs and normalizes their session/update stream into the agent-core neutral schema.",
5
5
  "license": "MIT",
6
6
  "author": "PwrDrvr LLC",