mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 04:30:59 +00:00
First part of step 4 of opt-in ACP v2 support (#1217, #1219, #1226, #1230): the v2 surface now sends the agent's tool calls. Nothing changes on ACP v1. ## Change `src/v2/tool-call.ts` maps the agent's v1 tool call reports to v2: - **One message.** v1 reports a new tool call with `tool_call` and changes it with `tool_call_update`. v2 has one `tool_call_update` that upserts by `toolCallId`, so both become that. - **`null` is left out.** Both versions leave an omitted field unchanged and replace `content` and `locations` as whole arrays. They differ on `null`: in v1 it leaves a field unchanged (v1's `name` docs say so explicitly), in v2 it clears it. The agent doesn't send `null` fields today; a unit test pins the rule. - **Content blocks pass through.** v2's content blocks are a superset of v1's. - **Diff and terminal content still throw**, until their own parts of step 4. ## Scenario suite Of the 30 scenarios that stopped at their first `tool_call`: | Status now | Scenarios | |---|---| | passes | 17: `read`, `grep-and-glob`, `bash-error`, `bash-background`, `skill`, `ask-user-question`, `memory-recall`, `permission-denied`, `tool-progress`, `task-output-and-stop`, four subagent scenarios, the three compaction scenarios | | stops at a permission request (step 5) | 9 | | stops at diff content (next part of step 4) | 4 | The 17 new golden files are in `src/tests/acp-scenarios/__snapshots__/v2/`. **One new check.** In v1, a `tool_call_update` for an id the client hasn't seen is an orphan, and clients drop it. In v2 the same message creates a tool call. A stray update would show up as a blank tool call, and the schema can't catch that. So every scenario recording, including those that stop, must give each tool call a title in its first report. It passes everywhere; making the first report lose its title fails it in 30 scenarios. ## Noted for later, not changed here - **`_meta` becomes stored state.** In v1, a report's `_meta` belongs to that report. In v2 it's stored on the tool call, and a concrete value replaces it. So a v2 client keeps only the last report's `_meta.claudeCode`: in `permission-denied`, the denial's `toolResponse` is replaced by the result's `{ toolName }`. No v2 client reads these keys yet. - **v2 has a `cancelled` tool status.** v1 reports an interrupted tool as `failed` with `_meta.claudeCode.nonExecutionKind`. Mapping it to `cancelled` means deciding where that fact lives. ## Verification Build, lint and all 2353 tests pass.
13 lines
3.6 KiB
JSON
Generated
13 lines
3.6 KiB
JSON
Generated
{"kind":"response","method":"initialize","payload":{"_meta":{"steering":{"supported":true}},"authMethods":[],"capabilities":{"_meta":{"authStatus":{},"claudeCode":{"promptQueueing":true}}},"info":{"name":"@agentclientprotocol/claude-agent-acp","title":"Claude Agent","version":"<version>"},"protocolVersion":2}}
|
|
{"kind":"response","method":"session/new","payload":{"configOptions":[{"category":"mode","configId":"mode","currentValue":"default","description":"Session permission mode","name":"Mode","options":[{"description":"Always ask before making changes","name":"Manual","value":"default"},{"description":"Automatically accept all file edits","name":"Accept edits","value":"acceptEdits"},{"description":"Create a plan before making changes","name":"Plan","value":"plan"},{"description":"Claude handles permission decisions","name":"Auto","value":"auto"},{"description":"Accepts all permissions","name":"Bypass permissions","value":"bypassPermissions"}],"type":"select"},{"category":"model","configId":"model","currentValue":"claude-sonnet-4-6","description":"AI model to use","name":"Model","options":[{"description":"Fast","name":"Claude Sonnet 4.6","value":"claude-sonnet-4-6"}],"type":"select"}],"sessionId":"<session>"}}
|
|
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"availableCommands":[{"description":"Show the MCP servers and their status, or reconnect, enable, or disable a server","input":{"hint":"[reconnect|enable|disable [<server>|all]]","type":"text"},"name":"mcp"}],"sessionUpdate":"available_commands_update"}}}
|
|
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"text":"prompt 1","type":"text"}],"messageId":"<id-1>","sessionUpdate":"user_message"}}}
|
|
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
|
{"kind":"response","method":"session/prompt","payload":{"messageId":"<id-1>"}}
|
|
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"claudeCode":{"toolName":"compact"}},"kind":"think","sessionUpdate":"tool_call_update","status":"in_progress","title":"Compact conversation","toolCallId":"00000000-0000-4000-8000-000000000001"}}}
|
|
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"claudeCode":{"toolName":"compact"}},"sessionUpdate":"tool_call_update","status":"in_progress","toolCallId":"00000000-0000-4000-8000-000000000001"}}}
|
|
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"claudeCode":{"toolName":"compact"}},"rawOutput":{"durationMs":7,"postTokens":100,"preTokens":1000,"trigger":"automatic"},"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"00000000-0000-4000-8000-000000000001"}}}
|
|
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"usage_update","size":200000,"used":100}}}
|
|
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":100}}}
|
|
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"quota":{"model_usage":[],"token_count":{"cachedInputTokens":0,"cachedWriteTokens":0,"inputTokens":0,"outputTokens":0,"reasoningOutputTokens":0,"totalTokens":0}}},"sessionUpdate":"state_update","state":"idle","stopReason":"end_turn","usage":{"cachedReadTokens":0,"cachedWriteTokens":0,"inputTokens":0,"outputTokens":0,"totalTokens":0}}}}
|