@agentclientprotocol/claude-agent-acp 0.42.0 → 0.44.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.
@@ -227,7 +227,7 @@ export declare class ClaudeAcpAgent implements Agent {
227
227
  /** Tear down all active sessions. Called when the ACP connection closes. */
228
228
  dispose(): Promise<void>;
229
229
  closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse>;
230
- unstable_deleteSession(params: DeleteSessionRequest): Promise<DeleteSessionResponse>;
230
+ deleteSession(params: DeleteSessionRequest): Promise<DeleteSessionResponse>;
231
231
  setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse>;
232
232
  setSessionConfigOption(params: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse>;
233
233
  private applySessionMode;
@@ -235,10 +235,29 @@ export declare class ClaudeAcpAgent implements Agent {
235
235
  readTextFile(params: ReadTextFileRequest): Promise<ReadTextFileResponse>;
236
236
  writeTextFile(params: WriteTextFileRequest): Promise<WriteTextFileResponse>;
237
237
  canUseTool(sessionId: string): CanUseTool;
238
+ /**
239
+ * Handle elicitation requests that originate from MCP servers by forwarding
240
+ * them to the client over ACP. Modes the client did not advertise (or
241
+ * requests we can't represent) are declined.
242
+ */
243
+ private handleMcpElicitation;
244
+ /**
245
+ * Present the built-in AskUserQuestion tool's questions as an ACP form
246
+ * elicitation and return the answers as the tool's `updatedInput`. Called from
247
+ * `canUseTool` since that is where the SDK routes the tool's permission check.
248
+ */
249
+ private handleAskUserQuestion;
238
250
  private sendAvailableCommandsUpdate;
239
251
  private updateConfigOption;
240
252
  private applyConfigOptionValue;
241
253
  private getOrCreateSession;
254
+ /**
255
+ * Ensures the requested `cwd` is an absolute path that points at an existing
256
+ * directory before we create a session. Throws an `invalidParams` error with
257
+ * an actionable message so clients (e.g. Zed) can surface it to the user
258
+ * instead of failing later with an opaque SDK error.
259
+ */
260
+ private validateCwd;
242
261
  private createSession;
243
262
  }
244
263
  export declare function promptToClaude(prompt: PromptRequest): SDKUserMessage;
@@ -1 +1 @@
1
- {"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"}
package/dist/acp-agent.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { AgentSideConnection, ndJsonStream, RequestError, } from "@agentclientprotocol/sdk";
2
2
  import { deleteSession, getSessionMessages, listSessions, query, } from "@anthropic-ai/claude-agent-sdk";
3
3
  import { randomUUID } from "node:crypto";
4
+ import * as fs from "node:fs/promises";
4
5
  import * as os from "node:os";
5
6
  import * as path from "node:path";
6
7
  import packageJson from "../package.json" with { type: "json" };
8
+ import { applyAskElicitationResponse, askUserQuestionsToCreateRequest, createElicitationResponseToElicitResult, extractAskUserQuestions, mcpElicitationToCreateRequest, } from "./elicitation.js";
7
9
  import { SettingsManager } from "./settings.js";
8
10
  import { applyTaskCreate, applyTaskUpdate, createPostToolUseHook, createTaskHook, parseTaskCreateOutput, planEntries, registerHookCallback, taskStateToPlanEntries, toolInfoFromToolUse, toolUpdateFromDiffToolResponse, toolUpdateFromToolResult, } from "./tools.js";
9
11
  import { nodeToWebReadable, nodeToWebWritable, Pushable, unreachable } from "./utils.js";
@@ -499,6 +501,21 @@ export class ClaudeAcpAgent {
499
501
  // `parent_tool_use_id === null` (subagent work is folded into tool-result
500
502
  // messages, never surfaced as partial streams).
501
503
  let currentStreamMessageId;
504
+ // Per-message-id record of which assistant content actually streamed live via
505
+ // `stream_event` deltas, split by block type. The `assistant` case below
506
+ // normally drops `text`/`thinking` blocks on the assumption they already
507
+ // reached the client as `agent_message_chunk`/`agent_thought_chunk`. That
508
+ // breaks behind Anthropic-protocol gateways that return a turn as a single
509
+ // non-streamed block (common with OpenAI-compatible proxies): no
510
+ // `content_block_delta` fires, so the assembled block is the only copy the
511
+ // client will ever see. We keep the filter per (id, block type) for content
512
+ // that did stream, and fall back to forwarding what did not. Split by type so
513
+ // a gateway that streams text but not thinking (or vice versa) doesn't lose
514
+ // the un-streamed block. Only top-level (`parent_tool_use_id === null`)
515
+ // streams are recorded — subagent text is never streamed and must stay
516
+ // filtered, as it is internal to the tool call.
517
+ const streamedTextIds = new Set();
518
+ const streamedThinkingIds = new Set();
502
519
  const userMessage = promptToClaude(params);
503
520
  const promptUuid = randomUUID();
504
521
  userMessage.uuid = promptUuid;
@@ -755,11 +772,28 @@ export class ClaudeAcpAgent {
755
772
  case "task_notification":
756
773
  case "task_progress":
757
774
  case "task_updated":
758
- case "elicitation_complete":
775
+ break;
776
+ case "elicitation_complete": {
777
+ // A url-mode MCP elicitation finished server-side. Let the client
778
+ // dismiss any UI it opened for it. Only meaningful when the
779
+ // client supports url elicitation; ignore failures otherwise.
780
+ if (this.clientCapabilities?.elicitation?.url) {
781
+ try {
782
+ await this.client.unstable_completeElicitation({
783
+ elicitationId: message.elicitation_id,
784
+ });
785
+ }
786
+ catch (error) {
787
+ this.logger.error(`Failed to complete elicitation: ${error}`);
788
+ }
789
+ }
790
+ break;
791
+ }
759
792
  case "plugin_install":
760
793
  case "notification":
761
794
  case "api_retry":
762
795
  case "thinking_tokens":
796
+ case "model_refusal_fallback":
763
797
  // Todo: process via status api: https://docs.claude.com/en/docs/claude-code/hooks#hook-output
764
798
  break;
765
799
  default:
@@ -894,6 +928,21 @@ export class ClaudeAcpAgent {
894
928
  if (message.event.type === "message_start") {
895
929
  currentStreamMessageId = message.event.message.id || undefined;
896
930
  }
931
+ // Record that this top-level message id actually streamed text/
932
+ // thinking, so the `assistant` case below knows its assembled blocks
933
+ // are duplicates (filter them) rather than the only copy (forward
934
+ // them). Gated on `parent_tool_use_id === null` so a subagent stream
935
+ // can't attribute its content to the top-level message id.
936
+ if (currentStreamMessageId &&
937
+ message.parent_tool_use_id === null &&
938
+ message.event.type === "content_block_delta") {
939
+ if (message.event.delta.type === "text_delta") {
940
+ streamedTextIds.add(currentStreamMessageId);
941
+ }
942
+ else if (message.event.delta.type === "thinking_delta") {
943
+ streamedThinkingIds.add(currentStreamMessageId);
944
+ }
945
+ }
897
946
  if (message.parent_tool_use_id === null &&
898
947
  (message.event.type === "message_start" || message.event.type === "message_delta")) {
899
948
  if (message.event.type === "message_start") {
@@ -1049,10 +1098,46 @@ export class ClaudeAcpAgent {
1049
1098
  message.message.content[0].text.includes("Please run /login")) {
1050
1099
  throw RequestError.authRequired();
1051
1100
  }
1052
- const content = message.type === "assistant"
1053
- ? // Handled by stream events above
1054
- message.message.content.filter((item) => !["text", "thinking"].includes(item.type))
1055
- : message.message.content;
1101
+ let content;
1102
+ if (message.type === "assistant" && message.parent_tool_use_id === null) {
1103
+ // Top-level assistant message: drop text/thinking blocks already
1104
+ // streamed live as chunks, and forward (as a fallback) any that were
1105
+ // not, so non-streaming gateways still deliver the final answer.
1106
+ const id = messageIdForGrouping(message);
1107
+ content = message.message.content.filter((item) => {
1108
+ // Non-text blocks (tool_use, etc.) always pass through; their own
1109
+ // dedupe (`toolUseCache`) collapses the streamed/assembled pair.
1110
+ if (item.type !== "text" && item.type !== "thinking") {
1111
+ return true;
1112
+ }
1113
+ // Already delivered live as a chunk of this exact type — drop the
1114
+ // duplicate. Checked per type so streaming one (e.g. text) doesn't
1115
+ // suppress an un-streamed block of the other (e.g. thinking).
1116
+ const streamedLive = id !== undefined &&
1117
+ (item.type === "text" ? streamedTextIds : streamedThinkingIds).has(id);
1118
+ if (streamedLive) {
1119
+ return false;
1120
+ }
1121
+ // Empty assembled blocks carry nothing (some gateways emit an empty
1122
+ // `thinking` block before the real text) — don't forward stray
1123
+ // empty chunks.
1124
+ const text = item.type === "text" ? item.text : item.thinking;
1125
+ if (text.length === 0) {
1126
+ return false;
1127
+ }
1128
+ return true;
1129
+ });
1130
+ }
1131
+ else if (message.type === "assistant") {
1132
+ // Subagent assistant message (`parent_tool_use_id !== null`). It is
1133
+ // never streamed live and its text/thinking is internal to the tool
1134
+ // call — keep dropping it so subagent prose doesn't leak into the
1135
+ // top-level feed.
1136
+ content = message.message.content.filter((item) => item.type !== "text" && item.type !== "thinking");
1137
+ }
1138
+ else {
1139
+ content = message.message.content;
1140
+ }
1056
1141
  for (const notification of toAcpNotifications(content, message.message.role, params.sessionId, session.toolUseCache, this.client, this.logger, {
1057
1142
  clientCapabilities: this.clientCapabilities,
1058
1143
  parentToolUseId: message.parent_tool_use_id,
@@ -1253,7 +1338,7 @@ export class ClaudeAcpAgent {
1253
1338
  await this.teardownSession(params.sessionId);
1254
1339
  return {};
1255
1340
  }
1256
- async unstable_deleteSession(params) {
1341
+ async deleteSession(params) {
1257
1342
  // Tear down any active in-memory state first so the on-disk file isn't
1258
1343
  // recreated by an outstanding query writing to it.
1259
1344
  if (this.sessions[params.sessionId]) {
@@ -1415,6 +1500,13 @@ export class ClaudeAcpAgent {
1415
1500
  message: "Session not found",
1416
1501
  };
1417
1502
  }
1503
+ // AskUserQuestion is surfaced to us as a normal permission check (the SDK
1504
+ // routes it through canUseTool whenever a callback is registered, rather
1505
+ // than the interactive dialog). Present it as an ACP form elicitation and
1506
+ // feed the answers back as updatedInput for the tool's own call() to read.
1507
+ if (toolName === "AskUserQuestion" && this.clientCapabilities?.elicitation?.form) {
1508
+ return this.handleAskUserQuestion(sessionId, toolInput, toolUseID, signal);
1509
+ }
1418
1510
  if (toolName === "ExitPlanMode") {
1419
1511
  const optionsAll = [
1420
1512
  { kind: "allow_always", name: 'Yes, and use "auto" mode', optionId: "auto" },
@@ -1540,6 +1632,62 @@ export class ClaudeAcpAgent {
1540
1632
  }
1541
1633
  };
1542
1634
  }
1635
+ /**
1636
+ * Handle elicitation requests that originate from MCP servers by forwarding
1637
+ * them to the client over ACP. Modes the client did not advertise (or
1638
+ * requests we can't represent) are declined.
1639
+ */
1640
+ handleMcpElicitation(sessionId, support) {
1641
+ return async (request, { signal }) => {
1642
+ const isUrl = request.mode === "url";
1643
+ if ((isUrl && !support.url) || (!isUrl && !support.form)) {
1644
+ return { action: "decline" };
1645
+ }
1646
+ const createRequest = mcpElicitationToCreateRequest(request, sessionId);
1647
+ if (!createRequest) {
1648
+ return { action: "decline" };
1649
+ }
1650
+ try {
1651
+ const response = await this.client.unstable_createElicitation(createRequest);
1652
+ if (signal.aborted) {
1653
+ return { action: "cancel" };
1654
+ }
1655
+ return createElicitationResponseToElicitResult(response);
1656
+ }
1657
+ catch (error) {
1658
+ this.logger.error(`Failed to forward MCP elicitation: ${error}`);
1659
+ return { action: "decline" };
1660
+ }
1661
+ };
1662
+ }
1663
+ /**
1664
+ * Present the built-in AskUserQuestion tool's questions as an ACP form
1665
+ * elicitation and return the answers as the tool's `updatedInput`. Called from
1666
+ * `canUseTool` since that is where the SDK routes the tool's permission check.
1667
+ */
1668
+ async handleAskUserQuestion(sessionId, toolInput, toolUseID, signal) {
1669
+ const questions = extractAskUserQuestions(toolInput);
1670
+ if (!questions) {
1671
+ return { behavior: "deny", message: "AskUserQuestion called with no valid questions." };
1672
+ }
1673
+ const createRequest = askUserQuestionsToCreateRequest(questions, sessionId, toolUseID);
1674
+ let response;
1675
+ try {
1676
+ response = await this.client.unstable_createElicitation(createRequest);
1677
+ }
1678
+ catch (error) {
1679
+ this.logger.error(`Failed to present AskUserQuestion elicitation: ${error}`);
1680
+ return { behavior: "deny", message: "Could not present the question to the user." };
1681
+ }
1682
+ if (signal.aborted) {
1683
+ throw new Error("Tool use aborted");
1684
+ }
1685
+ const outcome = applyAskElicitationResponse(response, toolInput, questions);
1686
+ if (outcome.action === "cancel") {
1687
+ throw new Error("Tool use aborted");
1688
+ }
1689
+ return { behavior: "allow", updatedInput: outcome.updatedInput };
1690
+ }
1543
1691
  async sendAvailableCommandsUpdate(sessionId) {
1544
1692
  const session = this.sessions[sessionId];
1545
1693
  if (!session)
@@ -1676,7 +1824,34 @@ export class ClaudeAcpAgent {
1676
1824
  configOptions: response.configOptions,
1677
1825
  };
1678
1826
  }
1827
+ /**
1828
+ * Ensures the requested `cwd` is an absolute path that points at an existing
1829
+ * directory before we create a session. Throws an `invalidParams` error with
1830
+ * an actionable message so clients (e.g. Zed) can surface it to the user
1831
+ * instead of failing later with an opaque SDK error.
1832
+ */
1833
+ async validateCwd(cwd) {
1834
+ if (!path.isAbsolute(cwd)) {
1835
+ throw RequestError.invalidParams({ cwd }, `\`cwd\` must be an absolute path, but received: ${cwd}`);
1836
+ }
1837
+ let stats;
1838
+ try {
1839
+ stats = await fs.stat(cwd);
1840
+ }
1841
+ catch {
1842
+ throw RequestError.invalidParams({ cwd }, `\`cwd\` does not exist on the machine running the agent: ${cwd}`);
1843
+ }
1844
+ if (!stats.isDirectory()) {
1845
+ throw RequestError.invalidParams({ cwd }, `\`cwd\` is not a directory: ${cwd}`);
1846
+ }
1847
+ }
1679
1848
  async createSession(params, creationOpts = {}) {
1849
+ // Validate `cwd` up front. The ACP spec requires an absolute path, and the
1850
+ // directory must actually exist on the machine running the agent. Without
1851
+ // this check a session is created against a missing directory and the
1852
+ // failure only surfaces later as a confusing "native binary failed to
1853
+ // launch" error from the SDK (see issue #749).
1854
+ await this.validateCwd(params.cwd);
1680
1855
  // We want to create a new session id unless it is resume,
1681
1856
  // but not resume + forkSession.
1682
1857
  let sessionId;
@@ -1746,8 +1921,17 @@ export class ClaudeAcpAgent {
1746
1921
  const thinking = resolveThinkingConfig(process.env.MAX_THINKING_TOKENS, this.logger);
1747
1922
  // Parse model configuration from environment (e.g. Bedrock model overrides)
1748
1923
  const modelConfig = parseModelConfig(process.env.CLAUDE_MODEL_CONFIG);
1749
- // Disable this for now, not a great way to expose this over ACP at the moment (in progress work so we can revisit)
1750
- const disallowedTools = ["AskUserQuestion"];
1924
+ // Elicitation modes the connected client advertised. We only forward
1925
+ // elicitations (and only re-enable AskUserQuestion) for modes the client
1926
+ // can actually render.
1927
+ const elicitationSupport = {
1928
+ form: !!this.clientCapabilities?.elicitation?.form,
1929
+ url: !!this.clientCapabilities?.elicitation?.url,
1930
+ };
1931
+ // AskUserQuestion surfaces as a `permission_ask_user_question` dialog that
1932
+ // we render as a form elicitation. Without form-elicitation support there
1933
+ // is no way to present it over ACP, so keep it disabled in that case.
1934
+ const disallowedTools = elicitationSupport.form ? [] : ["AskUserQuestion"];
1751
1935
  // Resolve which built-in tools to expose.
1752
1936
  // Explicit tools array from _meta.claudeCode.options takes precedence.
1753
1937
  // disableBuiltInTools is a legacy shorthand for tools: [] — kept for
@@ -1791,6 +1975,13 @@ export class ClaudeAcpAgent {
1791
1975
  allowDangerouslySkipPermissions: ALLOW_BYPASS,
1792
1976
  permissionMode,
1793
1977
  canUseTool: this.canUseTool(sessionId),
1978
+ // Forward MCP elicitation requests onto ACP elicitation. Only attached
1979
+ // when the client advertised support, so non-supporting clients keep the
1980
+ // SDK's default (auto-decline) behavior. (AskUserQuestion is handled in
1981
+ // canUseTool, not here.)
1982
+ ...(elicitationSupport.form || elicitationSupport.url
1983
+ ? { onElicitation: this.handleMcpElicitation(sessionId, elicitationSupport) }
1984
+ : {}),
1794
1985
  pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_EXECUTABLE ?? (await claudeCliPath()),
1795
1986
  extraArgs: {
1796
1987
  ...userProvidedOptions?.extraArgs,
@@ -2798,6 +2989,7 @@ export function toAcpNotifications(content, role, sessionId, toolUseCache, clien
2798
2989
  case "compaction_delta":
2799
2990
  case "advisor_tool_result":
2800
2991
  case "mid_conv_system":
2992
+ case "fallback":
2801
2993
  break;
2802
2994
  default:
2803
2995
  unreachable(chunk, logger);
@@ -0,0 +1,80 @@
1
+ import type { CreateElicitationRequest, CreateElicitationResponse } from "@agentclientprotocol/sdk";
2
+ import type { ElicitationRequest, ElicitationResult } from "@anthropic-ai/claude-agent-sdk";
3
+ import type { AskUserQuestionInput } from "@anthropic-ai/claude-agent-sdk/sdk-tools.js";
4
+ /**
5
+ * Bridges between the Claude Agent SDK's elicitation/dialog callbacks and ACP's
6
+ * (unstable) elicitation protocol.
7
+ *
8
+ * Two distinct SDK surfaces flow through here:
9
+ *
10
+ * 1. `onElicitation` — fired when an MCP server requests user input. These map
11
+ * directly onto ACP `session/create_elicitation` (form or url mode).
12
+ * 2. The built-in AskUserQuestion tool — when a `canUseTool` callback is
13
+ * registered the SDK routes its permission check through `canUseTool`
14
+ * (not the interactive `permission_ask_user_question` dialog). We render
15
+ * its questions as an ACP form elicitation and feed the user's selections
16
+ * back as the tool's `updatedInput`, which the tool's own `call()` reads.
17
+ */
18
+ /** Modes the connected client advertised support for. */
19
+ export type ElicitationSupport = {
20
+ form: boolean;
21
+ url: boolean;
22
+ };
23
+ /**
24
+ * Convert an MCP elicitation request (from the SDK's `onElicitation` callback)
25
+ * into an ACP `CreateElicitationRequest`. Returns `null` when the request can't
26
+ * be represented (e.g. a url-mode request with no url).
27
+ */
28
+ export declare function mcpElicitationToCreateRequest(request: ElicitationRequest, sessionId: string): CreateElicitationRequest | null;
29
+ /**
30
+ * Map an ACP elicitation response back to the MCP `ElicitResult` the SDK expects
31
+ * to hand back to the requesting server.
32
+ */
33
+ export declare function createElicitationResponseToElicitResult(response: CreateElicitationResponse): ElicitationResult;
34
+ /**
35
+ * A single question as supplied by the AskUserQuestion tool. Derived from the
36
+ * SDK's input type so the shape stays in sync; the SDK validates the model's
37
+ * tool call against this schema before it reaches us.
38
+ */
39
+ export type AskUserQuestion = AskUserQuestionInput["questions"][number];
40
+ /**
41
+ * Pull the well-formed questions out of an AskUserQuestion tool input. Returns
42
+ * `null` when there are no usable questions — including the case where every
43
+ * entry is malformed and filtering leaves an empty list — so callers can treat
44
+ * "nothing to ask" uniformly.
45
+ */
46
+ export declare function extractAskUserQuestions(input: Record<string, unknown>): AskUserQuestion[] | null;
47
+ /**
48
+ * Render the AskUserQuestion tool's questions as an ACP form elicitation.
49
+ *
50
+ * Fields are keyed by a short stable id (`question_<n>`) rather than the full
51
+ * question text, so the question text appears in exactly one place per field.
52
+ * Single-select questions use a titled `oneOf` enum; multi-select questions use
53
+ * an array with a titled `anyOf` item enum. The enum `const` is always the
54
+ * option label, since that is what the tool records as the answer.
55
+ *
56
+ * A trailing optional free-text field mirrors the CLI's custom-answer box: the
57
+ * user can type their own answer instead of (or as well as) picking an option.
58
+ * Nothing is marked required, so the user can also just skip — matching the
59
+ * built-in tool, which always offers Skip + a free-text box.
60
+ */
61
+ export declare function askUserQuestionsToCreateRequest(questions: AskUserQuestion[], sessionId: string, toolCallId: string | undefined): CreateElicitationRequest;
62
+ /** Outcome of an AskUserQuestion elicitation, decoupled from any transport. */
63
+ export type AskUserQuestionOutcome = {
64
+ action: "answered";
65
+ updatedInput: Record<string, unknown>;
66
+ } | {
67
+ action: "cancel";
68
+ };
69
+ /**
70
+ * Fold an ACP elicitation response into the AskUserQuestion tool's input.
71
+ *
72
+ * Selected labels are read back from the indexed form fields and written into
73
+ * `answers` as a `{ [questionText]: label }` map (comma-joining multi-selects)
74
+ * — the key shape the tool's own `call()` reads. Free text from the custom-
75
+ * answer field becomes the tool's top-level `response`. Decline yields empty
76
+ * answers (the model is told the user skipped rather than the turn aborting);
77
+ * cancel aborts the tool call.
78
+ */
79
+ export declare function applyAskElicitationResponse(response: CreateElicitationResponse, toolInput: Record<string, unknown>, questions: AskUserQuestion[]): AskUserQuestionOutcome;
80
+ //# sourceMappingURL=elicitation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elicitation.d.ts","sourceRoot":"","sources":["../src/elicitation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EAI1B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAC5F,OAAO,KAAK,EACV,oBAAoB,EAErB,MAAM,6CAA6C,CAAC;AAErD;;;;;;;;;;;;;GAaG;AAEH,yDAAyD;AACzD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,GAChB,wBAAwB,GAAG,IAAI,CAyBjC;AAED;;;GAGG;AACH,wBAAgB,uCAAuC,CACrD,QAAQ,EAAE,yBAAyB,GAClC,iBAAiB,CAUnB;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,EAAE,GAAG,IAAI,CAUhG;AAUD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,eAAe,EAAE,EAC5B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,wBAAwB,CAyC1B;AAED,+EAA+E;AAC/E,MAAM,MAAM,sBAAsB,GAC9B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC7D;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEzB;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,yBAAyB,EACnC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,SAAS,EAAE,eAAe,EAAE,GAC3B,sBAAsB,CAiCxB"}
@@ -0,0 +1,166 @@
1
+ import { randomUUID } from "node:crypto";
2
+ /**
3
+ * Convert an MCP elicitation request (from the SDK's `onElicitation` callback)
4
+ * into an ACP `CreateElicitationRequest`. Returns `null` when the request can't
5
+ * be represented (e.g. a url-mode request with no url).
6
+ */
7
+ export function mcpElicitationToCreateRequest(request, sessionId) {
8
+ if (request.mode === "url") {
9
+ if (!request.url) {
10
+ return null;
11
+ }
12
+ return {
13
+ mode: "url",
14
+ sessionId,
15
+ message: request.message,
16
+ url: request.url,
17
+ // URL elicitations need a stable id so the client can correlate the
18
+ // later `session/complete_elicitation` notification. MCP servers usually
19
+ // provide one; fall back to a generated id if not.
20
+ elicitationId: request.elicitationId ?? randomUUID(),
21
+ };
22
+ }
23
+ // Form mode (the default). The MCP `requestedSchema` is already a JSON Schema
24
+ // with primitive-typed properties, which is structurally what ACP expects.
25
+ return {
26
+ mode: "form",
27
+ sessionId,
28
+ message: request.message,
29
+ requestedSchema: normalizeElicitationSchema(request.requestedSchema),
30
+ };
31
+ }
32
+ /**
33
+ * Map an ACP elicitation response back to the MCP `ElicitResult` the SDK expects
34
+ * to hand back to the requesting server.
35
+ */
36
+ export function createElicitationResponseToElicitResult(response) {
37
+ switch (response.action) {
38
+ case "accept":
39
+ return { action: "accept", content: response.content ?? {} };
40
+ case "decline":
41
+ return { action: "decline" };
42
+ case "cancel":
43
+ default:
44
+ return { action: "cancel" };
45
+ }
46
+ }
47
+ /**
48
+ * Pull the well-formed questions out of an AskUserQuestion tool input. Returns
49
+ * `null` when there are no usable questions — including the case where every
50
+ * entry is malformed and filtering leaves an empty list — so callers can treat
51
+ * "nothing to ask" uniformly.
52
+ */
53
+ export function extractAskUserQuestions(input) {
54
+ const questions = input.questions;
55
+ if (!Array.isArray(questions)) {
56
+ return null;
57
+ }
58
+ const valid = questions.filter((q) => !!q && typeof q.question === "string" && Array.isArray(q.options) && q.options.length > 0);
59
+ return valid.length > 0 ? valid : null;
60
+ }
61
+ /** Stable form-field key for the question at the given index. */
62
+ function questionFieldKey(index) {
63
+ return `question_${index}`;
64
+ }
65
+ /** Form-field key for the optional free-text "custom answer" field. */
66
+ const CUSTOM_ANSWER_FIELD = "customAnswer";
67
+ /**
68
+ * Render the AskUserQuestion tool's questions as an ACP form elicitation.
69
+ *
70
+ * Fields are keyed by a short stable id (`question_<n>`) rather than the full
71
+ * question text, so the question text appears in exactly one place per field.
72
+ * Single-select questions use a titled `oneOf` enum; multi-select questions use
73
+ * an array with a titled `anyOf` item enum. The enum `const` is always the
74
+ * option label, since that is what the tool records as the answer.
75
+ *
76
+ * A trailing optional free-text field mirrors the CLI's custom-answer box: the
77
+ * user can type their own answer instead of (or as well as) picking an option.
78
+ * Nothing is marked required, so the user can also just skip — matching the
79
+ * built-in tool, which always offers Skip + a free-text box.
80
+ */
81
+ export function askUserQuestionsToCreateRequest(questions, sessionId, toolCallId) {
82
+ const single = questions.length === 1;
83
+ const properties = {};
84
+ questions.forEach((question, index) => {
85
+ const options = question.options.map((option) => ({
86
+ const: option.label,
87
+ title: option.description ? `${option.label} — ${option.description}` : option.label,
88
+ }));
89
+ // For a single question the prompt is carried by `message`, so we don't
90
+ // repeat it in the field description. With multiple questions each field
91
+ // needs its own question text.
92
+ const description = single ? undefined : question.question;
93
+ const title = question.header || undefined;
94
+ properties[questionFieldKey(index)] = question.multiSelect
95
+ ? { type: "array", title, description, items: { anyOf: options } }
96
+ : { type: "string", title, description, oneOf: options };
97
+ });
98
+ properties[CUSTOM_ANSWER_FIELD] = {
99
+ type: "string",
100
+ title: "Other",
101
+ description: "Type your own answer instead of choosing an option above (optional).",
102
+ };
103
+ const requestedSchema = {
104
+ type: "object",
105
+ properties,
106
+ };
107
+ const message = single ? questions[0].question : "Please answer the following questions.";
108
+ return {
109
+ mode: "form",
110
+ sessionId,
111
+ ...(toolCallId ? { toolCallId } : {}),
112
+ message,
113
+ requestedSchema,
114
+ };
115
+ }
116
+ /**
117
+ * Fold an ACP elicitation response into the AskUserQuestion tool's input.
118
+ *
119
+ * Selected labels are read back from the indexed form fields and written into
120
+ * `answers` as a `{ [questionText]: label }` map (comma-joining multi-selects)
121
+ * — the key shape the tool's own `call()` reads. Free text from the custom-
122
+ * answer field becomes the tool's top-level `response`. Decline yields empty
123
+ * answers (the model is told the user skipped rather than the turn aborting);
124
+ * cancel aborts the tool call.
125
+ */
126
+ export function applyAskElicitationResponse(response, toolInput, questions) {
127
+ if (response.action === "cancel") {
128
+ return { action: "cancel" };
129
+ }
130
+ if (response.action === "decline") {
131
+ return { action: "answered", updatedInput: { ...toolInput, answers: {} } };
132
+ }
133
+ const content = response.content ?? {};
134
+ // Typed against the tool's own output schema so the answer/response shapes
135
+ // stay in sync with what the built-in tool's call() expects to read back.
136
+ const answers = {};
137
+ questions.forEach((question, index) => {
138
+ const value = content[questionFieldKey(index)];
139
+ if (value === undefined || value === null) {
140
+ return;
141
+ }
142
+ const text = Array.isArray(value) ? value.join(", ") : String(value);
143
+ if (text === "") {
144
+ return;
145
+ }
146
+ answers[question.question] = text;
147
+ });
148
+ const updatedInput = { ...toolInput, answers };
149
+ const custom = content[CUSTOM_ANSWER_FIELD];
150
+ if (typeof custom === "string" && custom.trim() !== "") {
151
+ const response = custom;
152
+ updatedInput.response = response;
153
+ }
154
+ return { action: "answered", updatedInput };
155
+ }
156
+ /**
157
+ * Coerce an arbitrary MCP `requestedSchema` into an ACP `ElicitationSchema`.
158
+ * The two are structurally compatible JSON Schemas; we just guarantee the
159
+ * `type: "object"` discriminator is present.
160
+ */
161
+ function normalizeElicitationSchema(schema) {
162
+ if (!schema || typeof schema !== "object") {
163
+ return { type: "object", properties: {} };
164
+ }
165
+ return { ...schema, type: "object" };
166
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/dist/tools.js CHANGED
@@ -274,6 +274,22 @@ export function toolInfoFromToolUse(toolUse, supportsTerminalOutput = false, cwd
274
274
  : [],
275
275
  };
276
276
  }
277
+ case "AskUserQuestion": {
278
+ const input = toolUse.input;
279
+ const questions = Array.isArray(input?.questions) ? input.questions : [];
280
+ return {
281
+ title: questions.length === 1 && questions[0]?.question
282
+ ? questions[0].question
283
+ : "Asking for your input",
284
+ kind: "other",
285
+ content: questions
286
+ .filter((q) => typeof q?.question === "string")
287
+ .map((q) => ({
288
+ type: "content",
289
+ content: { type: "text", text: q.question },
290
+ })),
291
+ };
292
+ }
277
293
  case "Other": {
278
294
  const input = toolUse.input;
279
295
  let output;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.42.0",
6
+ "version": "0.44.0",
7
7
  "description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
8
8
  "main": "dist/lib.js",
9
9
  "types": "dist/lib.d.ts",
@@ -60,20 +60,20 @@
60
60
  "author": "Zed Industries",
61
61
  "license": "Apache-2.0",
62
62
  "dependencies": {
63
- "@agentclientprotocol/sdk": "0.24.0",
64
- "@anthropic-ai/claude-agent-sdk": "0.3.165",
63
+ "@agentclientprotocol/sdk": "0.25.0",
64
+ "@anthropic-ai/claude-agent-sdk": "0.3.170",
65
65
  "zod": "^3.25.0 || ^4.0.0"
66
66
  },
67
67
  "devDependencies": {
68
- "@anthropic-ai/sdk": "0.100.1",
68
+ "@anthropic-ai/sdk": "0.103.0",
69
69
  "@eslint/js": "10.0.1",
70
- "@types/node": "25.9.1",
71
- "@typescript-eslint/eslint-plugin": "8.60.1",
72
- "@typescript-eslint/parser": "8.60.1",
70
+ "@types/node": "25.9.2",
71
+ "@typescript-eslint/eslint-plugin": "8.61.0",
72
+ "@typescript-eslint/parser": "8.61.0",
73
73
  "eslint": "10.4.1",
74
74
  "eslint-config-prettier": "10.1.8",
75
75
  "globals": "17.6.0",
76
- "prettier": "3.8.3",
76
+ "prettier": "3.8.4",
77
77
  "ts-node": "10.9.2",
78
78
  "typescript": "6.0.3",
79
79
  "vitest": "4.1.8"