mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 12:40:32 +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.