claude-code-acp-ts 0.38.2 → 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.
- package/dist/acp-agent.d.ts +90 -15
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +654 -106
- package/dist/elicitation.d.ts +80 -0
- package/dist/elicitation.d.ts.map +1 -0
- package/dist/elicitation.js +166 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +16 -0
- package/package.json +13 -13
|
@@ -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
|
+
}
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,
|
|
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.
|
|
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",
|
|
@@ -49,33 +49,33 @@
|
|
|
49
49
|
"sdk",
|
|
50
50
|
"code"
|
|
51
51
|
],
|
|
52
|
-
"homepage": "https://github.com/
|
|
52
|
+
"homepage": "https://github.com/agentclientprotocol/claude-agent-acp#readme",
|
|
53
53
|
"bugs": {
|
|
54
|
-
"url": "https://github.com/
|
|
54
|
+
"url": "https://github.com/agentclientprotocol/claude-agent-acp/issues"
|
|
55
55
|
},
|
|
56
56
|
"repository": {
|
|
57
57
|
"type": "git",
|
|
58
|
-
"url": "git+https://github.com/
|
|
58
|
+
"url": "git+https://github.com/agentclientprotocol/claude-agent-acp.git"
|
|
59
59
|
},
|
|
60
60
|
"author": "Zed Industries",
|
|
61
61
|
"license": "Apache-2.0",
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@agentclientprotocol/sdk": "0.
|
|
64
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.
|
|
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.
|
|
68
|
+
"@anthropic-ai/sdk": "0.104.1",
|
|
69
69
|
"@eslint/js": "10.0.1",
|
|
70
|
-
"@types/node": "25.9.
|
|
71
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
72
|
-
"@typescript-eslint/parser": "8.
|
|
73
|
-
"eslint": "10.4.
|
|
70
|
+
"@types/node": "25.9.2",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "8.61.0",
|
|
72
|
+
"@typescript-eslint/parser": "8.61.0",
|
|
73
|
+
"eslint": "10.4.1",
|
|
74
74
|
"eslint-config-prettier": "10.1.8",
|
|
75
75
|
"globals": "17.6.0",
|
|
76
|
-
"prettier": "3.8.
|
|
76
|
+
"prettier": "3.8.4",
|
|
77
77
|
"ts-node": "10.9.2",
|
|
78
78
|
"typescript": "6.0.3",
|
|
79
|
-
"vitest": "4.1.
|
|
79
|
+
"vitest": "4.1.8"
|
|
80
80
|
}
|
|
81
81
|
}
|