From 30ad5f73728d23ae9c49da8287526bf7ea5edbdd Mon Sep 17 00:00:00 2001 From: Ben Brandt Date: Tue, 13 Oct 2026 07:57:05 +0200 Subject: [PATCH] refactor: send each tool call's _meta as the state a v2 client stores on the experimental ACP v2 surface (#1318) ## Problem A v1 report's `_meta` belongs to that report, and the agent gives each report its own `_meta.claudeCode` keys. A v2 client stores a tool call's `_meta`, and any report that carries `_meta` replaces it (`tool-calls.mdx`; the migration guide since agentclientprotocol/agent-client-protocol#2355). So a v2 client kept only the last report's keys. For example, a result's `{ toolName }` replaced the denial reason that came before it. On top of that, a PostToolUse hook stored the whole `tool_response` in `_meta`, which for a Write is the whole file text. ## Change All of this is v2 only. No v1 or AIR output changes, and no v1 golden changes. - **Stored `_meta` (`src/v2/tool-call-meta.ts`).** The v2 bridge keeps each tool call's `_meta` the way the client stores it. `claudeCode` keys merge one by one, and every other key replaces whole, the same model `ToolCallFieldTracker` uses. - A report that changes the stored `_meta` carries all of it. - A report that changes nothing carries no `_meta`, which leaves the stored value unchanged. - A permission request's subject always carries the stored `_meta`, since a client can show the request on its own. - The tool call's first report starts from nothing. - **`toolName` becomes `name`.** `claudeCode.toolName` repeats the tool's name, which v2 has a field for. It becomes the `name` of a tool call that has none yet, and is left out otherwise. A memory recall gets a `name` this way. Subagent routing still reads `toolName` on the agent's v1 reports, before the bridge. - **The `toolResponse` AIR gets.** A v2 client also keeps `_meta`, so it gets AIR's trimmed `toolResponse`: - a hook carries only the `status` and `isAsync` markers, not output the content already shows; - a denial carries the SDK message only when it differs from the reason. ## Evidence - **v2 goldens:** 28 change. Most only lose `toolName`. Hook reports lose the repeated stdout or file text. Memory recall gains `name`. The denial keeps its reason type and message. Subagent tool calls and their permission subjects keep `parentToolUseId`. - **Live, CLI 2.1.293 on Haiku, v2:** a Write and a Bash command arrived with `name` on their first report and no `_meta` at all. - **Tests:** 7 unit tests for the stored `_meta`. - **Mutation checks:** removing any of these 9 rules fails at least one test: - naming once; - leaving `toolName` out; - merging with earlier `claudeCode` keys, which also fails the `subagent-late-child-update` golden; - keeping other keys; - omitting unchanged `_meta`; - starting fresh; - the subject's stored `_meta`; - the bridge wiring; - the trimmed `toolResponse`. Forgetting a closed session's tool calls is memory cleanup that no test observes, like `V2Terminals.forget`. A limit of 2048 tool calls also bounds the memory. - `npm run check`, build and all 2820 tests pass. --- .../__snapshots__/v2/ask-user-question.jsonl | 6 +- .../__snapshots__/v2/bash-background.jsonl | 10 +- .../__snapshots__/v2/bash-error.jsonl | 8 +- .../__snapshots__/v2/bash-foreground.jsonl | 9 +- .../__snapshots__/v2/edit-rejected.jsonl | 10 +- .../v2/edit-with-permission.jsonl | 12 +- .../__snapshots__/v2/exit-plan-approve.jsonl | 6 +- .../__snapshots__/v2/exit-plan-reject.jsonl | 6 +- .../__snapshots__/v2/grep-and-glob.jsonl | 18 +-- .../__snapshots__/v2/mcp-tool.jsonl | 9 +- .../__snapshots__/v2/memory-recall.jsonl | 4 +- .../__snapshots__/v2/network-permission.jsonl | 2 +- .../__snapshots__/v2/notebook-edit.jsonl | 12 +- .../__snapshots__/v2/permission-denied.jsonl | 8 +- .../acp-scenarios/__snapshots__/v2/read.jsonl | 7 +- .../v2/session-load-replay.jsonl | 12 +- .../__snapshots__/v2/skill.jsonl | 7 +- .../v2/subagent-agent-async.jsonl | 14 +-- .../v2/subagent-late-child-update.jsonl | 18 +-- .../v2/subagent-native-sessions.jsonl | 28 ++--- .../__snapshots__/v2/subagent-nested.jsonl | 26 ++--- .../v2/subagent-task-legacy.jsonl | 44 ++++---- .../v2/subagent-transcript-extension.jsonl | 16 +-- .../v2/task-output-and-stop.jsonl | 14 +-- .../__snapshots__/v2/tool-progress.jsonl | 12 +- .../v2/web-fetch-and-search.jsonl | 14 +-- .../__snapshots__/v2/write-existing.jsonl | 10 +- .../__snapshots__/v2/write-new.jsonl | 9 +- src/tests/acp-v2.test.ts | 102 +++++++++++++++++ src/tool-calls/renderer.ts | 31 ++++-- src/v2/agent.ts | 16 ++- src/v2/tool-call-meta.ts | 104 ++++++++++++++++++ 32 files changed, 414 insertions(+), 190 deletions(-) create mode 100644 src/v2/tool-call-meta.ts diff --git a/src/tests/acp-scenarios/__snapshots__/v2/ask-user-question.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/ask-user-question.jsonl index 925d666e..80e012e2 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/ask-user-question.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/ask-user-question.jsonl @@ -4,12 +4,12 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"AskUserQuestion"}},"content":[],"kind":"other","name":"AskUserQuestion","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Asking for your input","toolCallId":"toolu_ask"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"other","name":"AskUserQuestion","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Asking for your input","toolCallId":"toolu_ask"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"AskUserQuestion"}},"content":[{"content":{"text":"Which database?","type":"text"},"type":"content"}],"rawInput":{"questions":[{"header":"Database","multiSelect":false,"options":[{"description":"Relational","label":"Postgres","preview":"CREATE TABLE t ();"},{"description":"Key-value","label":"Redis"}],"question":"Which database?"}]},"sessionUpdate":"tool_call_update","title":"Which database?","toolCallId":"toolu_ask"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Which database?","type":"text"},"type":"content"}],"rawInput":{"questions":[{"header":"Database","multiSelect":false,"options":[{"description":"Relational","label":"Postgres","preview":"CREATE TABLE t ();"},{"description":"Key-value","label":"Redis"}],"question":"Which database?"}]},"sessionUpdate":"tool_call_update","title":"Which database?","toolCallId":"toolu_ask"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"elicitation/create","payload":{"message":"Which database?","mode":"form","requestedSchema":{"properties":{"question_0":{"oneOf":[{"_meta":{"_claude/askUserQuestionOption":{"preview":"CREATE TABLE t ();"}},"const":"Postgres","description":"Relational","title":"Postgres"},{"const":"Redis","description":"Key-value","title":"Redis"}],"title":"Database","type":"string"},"question_0_custom":{"description":"Type your own answer, or add a note to the option you chose above (optional).","title":"Other","type":"string"}},"type":"object"},"sessionId":"","toolCallId":"toolu_ask"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"AskUserQuestion"}},"content":[{"content":{"text":"User has answered your questions: \"Which database?\"=\"Postgres\".","type":"text"},"type":"content"}],"rawOutput":"User has answered your questions: \"Which database?\"=\"Postgres\".","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_ask"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"User has answered your questions: \"Which database?\"=\"Postgres\".","type":"text"},"type":"content"}],"rawOutput":"User has answered your questions: \"Which database?\"=\"Postgres\".","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_ask"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/bash-background.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/bash-background.jsonl index 506c7064..1790b00c 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/bash-background.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/bash-background.jsonl @@ -5,14 +5,14 @@ {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"terminal_update","terminalId":"toolu_bg"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"content":[{"terminalId":"toolu_bg","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_bg"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"terminalId":"toolu_bg","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_bg"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"command":"sleep 100","sessionUpdate":"terminal_update","terminalId":"toolu_bg"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"rawInput":{"command":"sleep 100"},"sessionUpdate":"tool_call_update","title":"sleep 100","toolCallId":"toolu_bg"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"rawInput":{"command":"sleep 100","description":"Wait"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bg"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"sleep 100"},"sessionUpdate":"tool_call_update","title":"sleep 100","toolCallId":"toolu_bg"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"sleep 100","description":"Wait"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bg"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"rawInput":{"command":"sleep 100","description":"Wait","run_in_background":true},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bg"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"sleep 100","description":"Wait","run_in_background":true},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bg"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"output":{"data":"Q29tbWFuZCBydW5uaW5nIGluIGJhY2tncm91bmQgd2l0aCBJRDogYmFzaF8xLiBPdXRwdXQgaXMgYmVpbmcgd3JpdHRlbiB0bzogL3RtcC90YXNrcy9iYXNoXzEub3V0cHV0LiBZb3Ugd2lsbCBiZSBub3RpZmllZCB3aGVuIGl0IGNvbXBsZXRlcy4="},"sessionUpdate":"terminal_update","terminalId":"toolu_bg"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"exitStatus":{},"sessionUpdate":"terminal_update","terminalId":"toolu_bg"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_bg"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_bg"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/bash-error.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/bash-error.jsonl index a72d5a69..723e9c7b 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/bash-error.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/bash-error.jsonl @@ -5,13 +5,13 @@ {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"content":[{"terminalId":"toolu_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"terminalId":"toolu_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"command":"false","sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"rawInput":{"command":"false"},"sessionUpdate":"tool_call_update","title":"false","toolCallId":"toolu_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"false"},"sessionUpdate":"tool_call_update","title":"false","toolCallId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"rawInput":{"command":"false","description":"Fail"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"false","description":"Fail"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"output":{"data":"RXhpdCBjb2RlIDEKYm9vbQ=="},"sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"exitStatus":{"exitCode":1},"sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/bash-foreground.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/bash-foreground.jsonl index c404012b..3ce922ed 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/bash-foreground.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/bash-foreground.jsonl @@ -5,18 +5,17 @@ {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"content":[{"terminalId":"toolu_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"terminalId":"toolu_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"command":"ls -la","sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"rawInput":{"command":"ls -la"},"sessionUpdate":"tool_call_update","title":"ls -la","toolCallId":"toolu_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"ls -la"},"sessionUpdate":"tool_call_update","title":"ls -la","toolCallId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"rawInput":{"command":"ls -la","description":"List files"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"ls -la","description":"List files"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"content":[{"terminalId":"toolu_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"ls -la","description":"List files"},"status":"pending","title":"ls -la","toolCallId":"toolu_bash"},"type":"tool_call"},"title":"ls -la"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"output":{"data":"YS50cwpiLnRz"},"sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"exitStatus":{"exitCode":0},"sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash","toolResponse":{"interrupted":false,"isImage":false,"stderr":"","stdout":"a.ts\nb.ts"}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":{"text":"Do","type":"text"},"messageId":"msg_done","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":{"text":"ne.","type":"text"},"messageId":"msg_done","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/edit-rejected.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/edit-rejected.jsonl index 2ba64111..f9dbb7e5 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/edit-rejected.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/edit-rejected.jsonl @@ -4,15 +4,15 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"content":[],"kind":"edit","locations":[],"name":"Edit","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Edit","toolCallId":"toolu_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"locations":[{"path":"/src/app.ts"}],"rawInput":{"file_path":"/src/app.ts"},"sessionUpdate":"tool_call_update","title":"Edit src/app.ts","toolCallId":"toolu_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"rawInput":{"file_path":"/src/app.ts","old_string":"value = 1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"edit","locations":[],"name":"Edit","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Edit","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"path":"/src/app.ts"}],"rawInput":{"file_path":"/src/app.ts"},"sessionUpdate":"tool_call_update","title":"Edit src/app.ts","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"file_path":"/src/app.ts","old_string":"value = 1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"rawInput":{"file_path":"/src/app.ts","new_string":"value = 2","old_string":"value = 1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"file_path":"/src/app.ts","new_string":"value = 2","old_string":"value = 1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git /src/app.ts /src/app.ts\n--- /src/app.ts\n+++ /src/app.ts\n@@ -1 +1 @@\n-const value = 1;\n+const value = 2;\n"},"type":"diff"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git /src/app.ts /src/app.ts\n--- /src/app.ts\n+++ /src/app.ts\n@@ -1 +1 @@\n-const value = 1;\n+const value = 2;\n"},"type":"diff"}],"kind":"edit","locations":[{"path":"/src/app.ts"}],"name":"Edit","rawInput":{"file_path":"/src/app.ts","new_string":"value = 2","old_string":"value = 1"},"status":"pending","title":"Edit src/app.ts","toolCallId":"toolu_edit"},"type":"tool_call"},"title":"Edit src/app.ts"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"content":[{"content":{"text":"```\nThe user doesn't want to proceed with this tool use. The tool use was rejected.\n```","type":"text"},"type":"content"}],"rawOutput":"The user doesn't want to proceed with this tool use. The tool use was rejected.","sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"```\nThe user doesn't want to proceed with this tool use. The tool use was rejected.\n```","type":"text"},"type":"content"}],"rawOutput":"The user doesn't want to proceed with this tool use. The tool use was rejected.","sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/edit-with-permission.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/edit-with-permission.jsonl index f44dd365..b5821ffb 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/edit-with-permission.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/edit-with-permission.jsonl @@ -4,16 +4,16 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"content":[],"kind":"edit","locations":[],"name":"Edit","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Edit","toolCallId":"toolu_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"locations":[{"path":"/src/app.ts"}],"rawInput":{"file_path":"/src/app.ts"},"sessionUpdate":"tool_call_update","title":"Edit src/app.ts","toolCallId":"toolu_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"rawInput":{"file_path":"/src/app.ts","old_string":"const value = 1;"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"edit","locations":[],"name":"Edit","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Edit","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"path":"/src/app.ts"}],"rawInput":{"file_path":"/src/app.ts"},"sessionUpdate":"tool_call_update","title":"Edit src/app.ts","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"file_path":"/src/app.ts","old_string":"const value = 1;"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"rawInput":{"file_path":"/src/app.ts","new_string":"const value = 2;","old_string":"const value = 1;"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"file_path":"/src/app.ts","new_string":"const value = 2;","old_string":"const value = 1;"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git /src/app.ts /src/app.ts\n--- /src/app.ts\n+++ /src/app.ts\n@@ -1,3 +1,3 @@\n line 1\n-const value = 1;\n+const value = 2;\n line 3\n"},"type":"diff"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git /src/app.ts /src/app.ts\n--- /src/app.ts\n+++ /src/app.ts\n@@ -1,3 +1,3 @@\n line 1\n-const value = 1;\n+const value = 2;\n line 3\n"},"type":"diff"}],"kind":"edit","locations":[{"path":"/src/app.ts"}],"name":"Edit","rawInput":{"file_path":"/src/app.ts","new_string":"const value = 2;","old_string":"const value = 1;"},"status":"pending","title":"Edit src/app.ts","toolCallId":"toolu_edit"},"type":"tool_call"},"title":"Edit src/app.ts"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"rawOutput":"The file /src/app.ts has been updated successfully.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit","toolResponse":{"filePath":"/src/app.ts","newString":"const value = 2;","oldString":"const value = 1;","originalFile":"line 1\nconst value = 1;\nline 3\n","replaceAll":false,"structuredPatch":[{"lines":[" line 1","-const value = 1;","+const value = 2;"," line 3"],"newLines":3,"newStart":1,"oldLines":3,"oldStart":1}],"userModified":false}}},"locations":[{"line":1,"path":"/src/app.ts"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawOutput":"The file /src/app.ts has been updated successfully.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"line":1,"path":"/src/app.ts"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/exit-plan-approve.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/exit-plan-approve.jsonl index e3c571dd..7bbcb824 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/exit-plan-approve.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/exit-plan-approve.jsonl @@ -4,14 +4,14 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"ExitPlanMode"}},"content":[],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Approve Plan","toolCallId":"toolu_plan"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Approve Plan","toolCallId":"toolu_plan"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"ExitPlanMode"}},"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"rawInput":{"plan":"# Plan\n1. Do it"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_plan"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"rawInput":{"plan":"# Plan\n1. Do it"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_plan"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes, manually approve edits","optionId":"exit-plan-default"},{"kind":"allow_always","name":"Yes, clear context (0% used) and use auto mode","optionId":"exit-plan-clear-auto"},{"kind":"allow_always","name":"Yes, and use auto mode","optionId":"exit-plan-auto"},{"kind":"allow_always","name":"Yes, and bypass permissions","optionId":"exit-plan-bypass"},{"kind":"reject_once","name":"No, keep planning","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{"plan":"# Plan\n1. Do it"},"status":"pending","title":"Approve Plan","toolCallId":"toolu_plan"},"type":"tool_call"},"title":"Ready to code?"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"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"}],"sessionUpdate":"config_option_update"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"ExitPlanMode"}},"rawOutput":"User has approved your plan. You can now start coding.\n\n## Approved Plan:\n# Plan\n1. Do it","sessionUpdate":"tool_call_update","status":"completed","title":"Exited Plan Mode","toolCallId":"toolu_plan"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawOutput":"User has approved your plan. You can now start coding.\n\n## Approved Plan:\n# Plan\n1. Do it","sessionUpdate":"tool_call_update","status":"completed","title":"Exited Plan Mode","toolCallId":"toolu_plan"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"plan":{"content":"# Plan\n1. Do it","planId":"plan-mode","type":"markdown"},"sessionUpdate":"plan_update"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/exit-plan-reject.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/exit-plan-reject.jsonl index 5f59cca3..9ba9745f 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/exit-plan-reject.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/exit-plan-reject.jsonl @@ -4,12 +4,12 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"ExitPlanMode"}},"content":[],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Approve Plan","toolCallId":"toolu_plan"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Approve Plan","toolCallId":"toolu_plan"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"ExitPlanMode"}},"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"rawInput":{"plan":"# Plan\n1. Do it"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_plan"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"rawInput":{"plan":"# Plan\n1. Do it"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_plan"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes, manually approve edits","optionId":"exit-plan-default"},{"kind":"allow_always","name":"Yes, clear context (0% used) and use auto mode","optionId":"exit-plan-clear-auto"},{"kind":"allow_always","name":"Yes, and use auto mode","optionId":"exit-plan-auto"},{"kind":"allow_always","name":"Yes, and bypass permissions","optionId":"exit-plan-bypass"},{"kind":"reject_once","name":"No, keep planning","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{"plan":"# Plan\n1. Do it"},"status":"pending","title":"Approve Plan","toolCallId":"toolu_plan"},"type":"tool_call"},"title":"Ready to code?"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"ExitPlanMode"}},"content":[{"content":{"text":"```\n```\nThe user doesn't want to proceed with this tool use.\n```\n```","type":"text"},"type":"content"}],"rawOutput":"The user doesn't want to proceed with this tool use.","sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_plan"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"```\n```\nThe user doesn't want to proceed with this tool use.\n```\n```","type":"text"},"type":"content"}],"rawOutput":"The user doesn't want to proceed with this tool use.","sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_plan"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/grep-and-glob.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/grep-and-glob.jsonl index 07d6484c..07404dbe 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/grep-and-glob.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/grep-and-glob.jsonl @@ -4,16 +4,16 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Grep"}},"content":[],"kind":"search","name":"Grep","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"grep","toolCallId":"toolu_grep"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Grep"}},"rawInput":{"pattern":"value"},"sessionUpdate":"tool_call_update","title":"grep \"value\"","toolCallId":"toolu_grep"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Grep"}},"rawInput":{"path":"src","pattern":"value"},"sessionUpdate":"tool_call_update","title":"grep \"value\" src","toolCallId":"toolu_grep"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Grep"}},"rawInput":{"output_mode":"content","path":"src","pattern":"value"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"search","name":"Grep","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"grep","toolCallId":"toolu_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"pattern":"value"},"sessionUpdate":"tool_call_update","title":"grep \"value\"","toolCallId":"toolu_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"path":"src","pattern":"value"},"sessionUpdate":"tool_call_update","title":"grep \"value\" src","toolCallId":"toolu_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"output_mode":"content","path":"src","pattern":"value"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_grep"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Grep"}},"rawInput":{"-n":true,"output_mode":"content","path":"src","pattern":"value"},"sessionUpdate":"tool_call_update","title":"grep -n \"value\" src","toolCallId":"toolu_grep"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Grep"}},"content":[{"content":{"text":"src/app.ts:2:const value = 1;","type":"text"},"type":"content"}],"rawOutput":"src/app.ts:2:const value = 1;","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_grep"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Glob"}},"content":[],"kind":"search","locations":[],"name":"Glob","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Find","toolCallId":"toolu_glob"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"-n":true,"output_mode":"content","path":"src","pattern":"value"},"sessionUpdate":"tool_call_update","title":"grep -n \"value\" src","toolCallId":"toolu_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"src/app.ts:2:const value = 1;","type":"text"},"type":"content"}],"rawOutput":"src/app.ts:2:const value = 1;","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"search","locations":[],"name":"Glob","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Find","toolCallId":"toolu_glob"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Glob"}},"rawInput":{"pattern":"**/*.ts"},"sessionUpdate":"tool_call_update","title":"Find `**/*.ts`","toolCallId":"toolu_glob"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Glob"}},"content":[{"content":{"text":"src/app.ts\nsrc/b.ts","type":"text"},"type":"content"}],"rawOutput":"src/app.ts\nsrc/b.ts","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_glob"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"pattern":"**/*.ts"},"sessionUpdate":"tool_call_update","title":"Find `**/*.ts`","toolCallId":"toolu_glob"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"src/app.ts\nsrc/b.ts","type":"text"},"type":"content"}],"rawOutput":"src/app.ts\nsrc/b.ts","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_glob"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/mcp-tool.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/mcp-tool.jsonl index eb5d9cd6..24c3b2c0 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/mcp-tool.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/mcp-tool.jsonl @@ -4,13 +4,12 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"mcp__docs__search"}},"content":[],"kind":"other","name":"mcp__docs__search","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"mcp__docs__search","toolCallId":"toolu_mcp"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"other","name":"mcp__docs__search","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"mcp__docs__search","toolCallId":"toolu_mcp"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"mcp__docs__search"}},"rawInput":{"q":"acp"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_mcp"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"q":"acp"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_mcp"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} -{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"_meta":{"claudeCode":{"mcpServer":{"name":"docs","source":"project"},"toolName":"mcp__docs__search"}},"content":[],"kind":"other","name":"mcp__docs__search","rawInput":{"q":"acp"},"status":"pending","title":"mcp__docs__search","toolCallId":"toolu_mcp"},"type":"tool_call"},"title":"mcp__docs__search"}} +{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"_meta":{"claudeCode":{"mcpServer":{"name":"docs","source":"project"}}},"content":[],"kind":"other","name":"mcp__docs__search","rawInput":{"q":"acp"},"status":"pending","title":"mcp__docs__search","toolCallId":"toolu_mcp"},"type":"tool_call"},"title":"mcp__docs__search"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"mcp__docs__search"}},"content":[{"content":{"text":"Found 2 documents.","type":"text"},"type":"content"}],"rawOutput":[{"text":"Found 2 documents.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_mcp"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"mcp__docs__search","toolResponse":[{"text":"Found 2 documents.","type":"text"}]}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_mcp"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Found 2 documents.","type":"text"},"type":"content"}],"rawOutput":[{"text":"Found 2 documents.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_mcp"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/memory-recall.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/memory-recall.jsonl index 400e8e26..614d77a1 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/memory-recall.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/memory-recall.jsonl @@ -3,6 +3,6 @@ {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"text":"prompt 1","type":"text"}],"messageId":"","sessionUpdate":"user_message"}}} {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"memory_recall","toolResponse":{"mode":"select"}}},"kind":"read","locations":[{"path":"/memory/a.md"},{"path":"/memory/b.md"}],"sessionUpdate":"tool_call_update","status":"completed","title":"Recalled 2 memories","toolCallId":"00000000-0000-4000-8000-000000000001"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"memory_recall","toolResponse":{"mode":"synthesize"}}},"content":[{"content":{"text":"The user prefers tabs.","type":"text"},"type":"content"}],"kind":"read","sessionUpdate":"tool_call_update","status":"completed","title":"Recalled synthesized memory","toolCallId":"00000000-0000-4000-8000-000000000002"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolResponse":{"mode":"select"}}},"kind":"read","locations":[{"path":"/memory/a.md"},{"path":"/memory/b.md"}],"name":"memory_recall","sessionUpdate":"tool_call_update","status":"completed","title":"Recalled 2 memories","toolCallId":"00000000-0000-4000-8000-000000000001"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolResponse":{"mode":"synthesize"}}},"content":[{"content":{"text":"The user prefers tabs.","type":"text"},"type":"content"}],"kind":"read","name":"memory_recall","sessionUpdate":"tool_call_update","status":"completed","title":"Recalled synthesized memory","toolCallId":"00000000-0000-4000-8000-000000000002"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/network-permission.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/network-permission.jsonl index 1bf55aa3..0c73478e 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/network-permission.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/network-permission.jsonl @@ -3,7 +3,7 @@ {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"text":"prompt 1","type":"text"}],"messageId":"","sessionUpdate":"user_message"}}} {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"SandboxNetworkAccess"}},"content":[],"kind":"other","name":"SandboxNetworkAccess","rawInput":{"host":"example.com"},"sessionUpdate":"tool_call_update","status":"pending","title":"SandboxNetworkAccess","toolCallId":"toolu_net"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"other","name":"SandboxNetworkAccess","rawInput":{"host":"example.com"},"sessionUpdate":"tool_call_update","status":"pending","title":"SandboxNetworkAccess","toolCallId":"toolu_net"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"session/request_permission","payload":{"description":"Reason: Sandbox blocks network","options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"content":[{"content":{"text":"```json\n{\n \"host\": \"example.com\"\n}\n```","type":"text"},"type":"content"}],"kind":"other","name":"SandboxNetworkAccess","rawInput":{"host":"example.com"},"status":"pending","title":"example.com","toolCallId":"toolu_net"},"type":"tool_call"},"title":"example.com"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/notebook-edit.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/notebook-edit.jsonl index fe6c585a..1e67221c 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/notebook-edit.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/notebook-edit.jsonl @@ -4,15 +4,15 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"NotebookEdit"}},"content":[],"kind":"other","name":"NotebookEdit","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"NotebookEdit","toolCallId":"toolu_nb"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"NotebookEdit"}},"rawInput":{"notebook_path":"/n.ipynb"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_nb"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"NotebookEdit"}},"rawInput":{"cell_id":"cell-1","notebook_path":"/n.ipynb"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_nb"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"NotebookEdit"}},"rawInput":{"cell_id":"cell-1","new_source":"print('hi')","notebook_path":"/n.ipynb"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_nb"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"other","name":"NotebookEdit","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"NotebookEdit","toolCallId":"toolu_nb"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"notebook_path":"/n.ipynb"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_nb"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"cell_id":"cell-1","notebook_path":"/n.ipynb"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_nb"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"cell_id":"cell-1","new_source":"print('hi')","notebook_path":"/n.ipynb"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_nb"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"NotebookEdit"}},"rawInput":{"cell_id":"cell-1","edit_mode":"replace","new_source":"print('hi')","notebook_path":"/n.ipynb"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_nb"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"cell_id":"cell-1","edit_mode":"replace","new_source":"print('hi')","notebook_path":"/n.ipynb"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_nb"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"content":[],"kind":"other","name":"NotebookEdit","rawInput":{"cell_id":"cell-1","edit_mode":"replace","new_source":"print('hi')","notebook_path":"/n.ipynb"},"status":"pending","title":"NotebookEdit","toolCallId":"toolu_nb"},"type":"tool_call"},"title":"NotebookEdit"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"NotebookEdit"}},"content":[{"content":{"text":"Updated cell cell-1 with print('hi')","type":"text"},"type":"content"}],"rawOutput":"Updated cell cell-1 with print('hi')","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_nb"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Updated cell cell-1 with print('hi')","type":"text"},"type":"content"}],"rawOutput":"Updated cell cell-1 with print('hi')","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_nb"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/permission-denied.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/permission-denied.jsonl index 645ebda1..15e1e5ad 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/permission-denied.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/permission-denied.jsonl @@ -5,13 +5,13 @@ {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"terminal_update","terminalId":"toolu_denied"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"content":[{"terminalId":"toolu_denied","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_denied"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"terminalId":"toolu_denied","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_denied"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"command":"rm -rf /","sessionUpdate":"terminal_update","terminalId":"toolu_denied"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"rawInput":{"command":"rm -rf /"},"sessionUpdate":"tool_call_update","title":"rm -rf /","toolCallId":"toolu_denied"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash","toolResponse":{"decisionReason":"Denied by rule Bash(rm:*)","decisionReasonType":"rule","message":"Permission to use Bash has been denied."}}},"content":[{"content":{"text":"Permission denied: Denied by rule Bash(rm:*)","type":"text"},"type":"content"}],"sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_denied"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"rm -rf /"},"sessionUpdate":"tool_call_update","title":"rm -rf /","toolCallId":"toolu_denied"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolResponse":{"decisionReasonType":"rule","message":"Permission to use Bash has been denied."}}},"content":[{"content":{"text":"Permission denied: Denied by rule Bash(rm:*)","type":"text"},"type":"content"}],"sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_denied"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"output":{"data":"UGVybWlzc2lvbiB0byB1c2UgQmFzaCBoYXMgYmVlbiBkZW5pZWQu"},"sessionUpdate":"terminal_update","terminalId":"toolu_denied"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"exitStatus":{},"sessionUpdate":"terminal_update","terminalId":"toolu_denied"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"content":[{"terminalId":"toolu_denied","type":"terminal"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_denied"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"terminalId":"toolu_denied","type":"terminal"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_denied"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/read.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/read.jsonl index 5d258e6f..1895ea5b 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/read.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/read.jsonl @@ -4,10 +4,9 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Read"}},"content":[],"kind":"read","locations":[],"name":"Read","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Read File","toolCallId":"toolu_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"read","locations":[],"name":"Read","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Read File","toolCallId":"toolu_read"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Read"}},"locations":[{"line":1,"path":"/a.ts"}],"rawInput":{"file_path":"/a.ts"},"sessionUpdate":"tool_call_update","title":"Read a.ts","toolCallId":"toolu_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Read"}},"content":[{"content":{"text":"```\n1\tconst a = 1;\n```","type":"text"},"type":"content"}],"rawOutput":"1\tconst a = 1;\nx","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Read","toolResponse":{"file":{"content":"const a = 1;\n","filePath":"/a.ts","numLines":1,"startLine":1,"totalLines":1},"type":"text"}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"line":1,"path":"/a.ts"}],"rawInput":{"file_path":"/a.ts"},"sessionUpdate":"tool_call_update","title":"Read a.ts","toolCallId":"toolu_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"```\n1\tconst a = 1;\n```","type":"text"},"type":"content"}],"rawOutput":"1\tconst a = 1;\nx","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_read"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/session-load-replay.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/session-load-replay.jsonl index 4dab5a0e..aaac669c 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/session-load-replay.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/session-load-replay.jsonl @@ -6,14 +6,14 @@ {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"messageId":"msg_r1","sessionUpdate":"agent_message"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":{"text":"I will edit it.","type":"text"},"messageId":"msg_r1","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"command":"ls","sessionUpdate":"terminal_update","terminalId":"toolu_r_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"content":[{"terminalId":"toolu_r_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"ls","description":"List"},"sessionUpdate":"tool_call_update","status":"pending","title":"ls","toolCallId":"toolu_r_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"content":[],"kind":"edit","locations":[{"path":"/src/app.ts"}],"name":"Edit","rawInput":{"file_path":"/src/app.ts","new_string":"b","old_string":"a"},"sessionUpdate":"tool_call_update","status":"pending","title":"Edit src/app.ts","toolCallId":"toolu_r_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"content":[{"content":{"text":"Look around","type":"text"},"type":"content"}],"kind":"think","name":"Task","rawInput":{"description":"Explore","prompt":"Look around"},"sessionUpdate":"tool_call_update","status":"pending","title":"Explore","toolCallId":"toolu_r_task"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"terminalId":"toolu_r_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"ls","description":"List"},"sessionUpdate":"tool_call_update","status":"pending","title":"ls","toolCallId":"toolu_r_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"edit","locations":[{"path":"/src/app.ts"}],"name":"Edit","rawInput":{"file_path":"/src/app.ts","new_string":"b","old_string":"a"},"sessionUpdate":"tool_call_update","status":"pending","title":"Edit src/app.ts","toolCallId":"toolu_r_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Look around","type":"text"},"type":"content"}],"kind":"think","name":"Task","rawInput":{"description":"Explore","prompt":"Look around"},"sessionUpdate":"tool_call_update","status":"pending","title":"Explore","toolCallId":"toolu_r_task"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"output":{"data":"YXBwLnRz"},"sessionUpdate":"terminal_update","terminalId":"toolu_r_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"exitStatus":{"exitCode":0},"sessionUpdate":"terminal_update","terminalId":"toolu_r_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"content":[{"terminalId":"toolu_r_bash","type":"terminal"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_r_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Edit"}},"rawOutput":"The file /src/app.ts has been updated successfully.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_r_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"content":[{"content":{"text":"Report.","type":"text"},"type":"content"}],"rawOutput":"Report.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_r_task"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"terminalId":"toolu_r_bash","type":"terminal"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_r_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawOutput":"The file /src/app.ts has been updated successfully.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_r_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Report.","type":"text"},"type":"content"}],"rawOutput":"Report.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_r_task"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"messageId":"msg_r2","sessionUpdate":"agent_message"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":{"text":"Fixed.","type":"text"},"messageId":"msg_r2","sessionUpdate":"agent_message_chunk"}}} {"kind":"response","method":"session/resume","payload":{"availableCommands":[{"description":"Show the MCP servers and their status, or reconnect, enable, or disable a server","input":{"hint":"[reconnect|enable|disable [|all]]","type":"text"},"name":"mcp"}],"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"}]}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/skill.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/skill.jsonl index 793ea451..8f95377c 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/skill.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/skill.jsonl @@ -4,10 +4,9 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Skill"}},"content":[],"kind":"other","name":"Skill","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Load skill","toolCallId":"toolu_skill"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"other","name":"Skill","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Load skill","toolCallId":"toolu_skill"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Skill"}},"rawInput":{"skill":"commits"},"sessionUpdate":"tool_call_update","title":"Load skill: commits","toolCallId":"toolu_skill"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Skill"}},"rawOutput":"Launching skill: commits","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_skill"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Skill","toolResponse":{"commandName":"commits","success":true}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_skill"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"skill":"commits"},"sessionUpdate":"tool_call_update","title":"Load skill: commits","toolCallId":"toolu_skill"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawOutput":"Launching skill: commits","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_skill"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/subagent-agent-async.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/subagent-agent-async.jsonl index 08cc47e6..9991c0ce 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/subagent-agent-async.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/subagent-agent-async.jsonl @@ -4,14 +4,14 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_agent"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"rawInput":{"description":"Background review"},"sessionUpdate":"tool_call_update","title":"Background review","toolCallId":"toolu_agent"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"rawInput":{"description":"Background review","prompt":"Review the diff"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_agent"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"rawInput":{"description":"Background review","prompt":"Review the diff","subagent_type":"general-purpose"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_agent"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_agent"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Background review"},"sessionUpdate":"tool_call_update","title":"Background review","toolCallId":"toolu_agent"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Background review","prompt":"Review the diff"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_agent"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Background review","prompt":"Review the diff","subagent_type":"general-purpose"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_agent"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[{"content":{"text":"Review the diff","type":"text"},"type":"content"}],"rawInput":{"description":"Background review","prompt":"Review the diff","run_in_background":true,"subagent_type":"general-purpose"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_agent"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[{"content":{"text":"Async agent launched successfully.","type":"text"},"type":"content"}],"rawOutput":"Async agent launched successfully.\nagentId: a2 (use SendMessage to continue)","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_agent"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent","toolResponse":{"agentId":"a2","description":"Background review","isAsync":true,"outputFile":"/tmp/tasks/a2.output","prompt":"Review the diff","status":"async_launched"}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_agent"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Review the diff","type":"text"},"type":"content"}],"rawInput":{"description":"Background review","prompt":"Review the diff","run_in_background":true,"subagent_type":"general-purpose"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_agent"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Async agent launched successfully.","type":"text"},"type":"content"}],"rawOutput":"Async agent launched successfully.\nagentId: a2 (use SendMessage to continue)","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_agent"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolResponse":{"isAsync":true,"status":"async_launched"}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_agent"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_agent"}},"content":{"text":"Reviewi","type":"text"},"messageId":"msg_async_sub","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_agent"}},"content":{"text":"ng now.","type":"text"},"messageId":"msg_async_sub","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/subagent-late-child-update.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/subagent-late-child-update.jsonl index a8b3ca60..c7a2e281 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/subagent-late-child-update.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/subagent-late-child-update.jsonl @@ -4,15 +4,15 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_late"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"rawInput":{"description":"Check the logs"},"sessionUpdate":"tool_call_update","title":"Check the logs","toolCallId":"toolu_late"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"rawInput":{"description":"Check the logs","prompt":"Check logs"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_late"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_late"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Check the logs"},"sessionUpdate":"tool_call_update","title":"Check the logs","toolCallId":"toolu_late"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Check the logs","prompt":"Check logs"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_late"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[{"content":{"text":"Check logs","type":"text"},"type":"content"}],"rawInput":{"description":"Check the logs","prompt":"Check logs","subagent_type":"general-purpose"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_late"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_late","toolName":"Read"}},"content":[],"kind":"read","locations":[],"name":"Read","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Read File","toolCallId":"toolu_late_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_late","toolName":"Read"}},"locations":[{"line":1,"path":"/var/log/app.log"}],"rawInput":{"file_path":"/var/log/app.log"},"sessionUpdate":"tool_call_update","title":"Read /var/log/app.log","toolCallId":"toolu_late_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[{"content":{"text":"The logs are clean.","type":"text"},"type":"content"}],"rawOutput":[{"text":"The logs are clean.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_late"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Read","toolResponse":{"elapsedTimeSeconds":4}}},"sessionUpdate":"tool_call_update","status":"in_progress","toolCallId":"toolu_late_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_late","toolName":"Read"}},"content":[{"content":{"text":"```\n1\tok\n```","type":"text"},"type":"content"}],"rawOutput":"1\tok","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_late_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Check logs","type":"text"},"type":"content"}],"rawInput":{"description":"Check the logs","prompt":"Check logs","subagent_type":"general-purpose"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_late"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_late"}},"content":[],"kind":"read","locations":[],"name":"Read","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Read File","toolCallId":"toolu_late_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"line":1,"path":"/var/log/app.log"}],"rawInput":{"file_path":"/var/log/app.log"},"sessionUpdate":"tool_call_update","title":"Read /var/log/app.log","toolCallId":"toolu_late_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"The logs are clean.","type":"text"},"type":"content"}],"rawOutput":[{"text":"The logs are clean.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_late"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_late","toolResponse":{"elapsedTimeSeconds":4}}},"sessionUpdate":"tool_call_update","status":"in_progress","toolCallId":"toolu_late_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"```\n1\tok\n```","type":"text"},"type":"content"}],"rawOutput":"1\tok","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_late_read"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/subagent-native-sessions.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/subagent-native-sessions.jsonl index bbe2da80..ea870695 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/subagent-native-sessions.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/subagent-native-sessions.jsonl @@ -4,28 +4,28 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_native"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"rawInput":{"description":"Fix the build"},"sessionUpdate":"tool_call_update","title":"Fix the build","toolCallId":"toolu_native"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"rawInput":{"description":"Fix the build","prompt":"Make the build pass"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_native"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_native"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Fix the build"},"sessionUpdate":"tool_call_update","title":"Fix the build","toolCallId":"toolu_native"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Fix the build","prompt":"Make the build pass"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_native"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[{"content":{"text":"Make the build pass","type":"text"},"type":"content"}],"rawInput":{"description":"Fix the build","prompt":"Make the build pass","subagent_type":"general-purpose"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_native"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Make the build pass","type":"text"},"type":"content"}],"rawInput":{"description":"Fix the build","prompt":"Make the build pass","subagent_type":"general-purpose"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_native"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native"}},"content":{"text":"Running t","type":"text"},"messageId":"msg_native_sub_1","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native"}},"content":{"text":"he build.","type":"text"},"messageId":"msg_native_sub_1","sessionUpdate":"agent_message_chunk"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native","toolName":"Grep"}},"content":[],"kind":"search","name":"Grep","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"grep","toolCallId":"toolu_native_grep"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native","toolName":"Grep"}},"rawInput":{"pattern":"TODO"},"sessionUpdate":"tool_call_update","title":"grep \"TODO\"","toolCallId":"toolu_native_grep"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native","toolName":"Grep"}},"rawInput":{"path":"/src","pattern":"TODO"},"sessionUpdate":"tool_call_update","title":"grep \"TODO\" /src","toolCallId":"toolu_native_grep"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native","toolName":"Grep"}},"content":[{"content":{"text":"src/a.ts","type":"text"},"type":"content"}],"rawOutput":"src/a.ts","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_native_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native"}},"content":[],"kind":"search","name":"Grep","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"grep","toolCallId":"toolu_native_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"pattern":"TODO"},"sessionUpdate":"tool_call_update","title":"grep \"TODO\"","toolCallId":"toolu_native_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"path":"/src","pattern":"TODO"},"sessionUpdate":"tool_call_update","title":"grep \"TODO\" /src","toolCallId":"toolu_native_grep"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"src/a.ts","type":"text"},"type":"content"}],"rawOutput":"src/a.ts","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_native_grep"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"terminal_update","terminalId":"toolu_native_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native","toolName":"Bash"}},"content":[{"terminalId":"toolu_native_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_native_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native"}},"content":[{"terminalId":"toolu_native_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_native_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"command":"make","sessionUpdate":"terminal_update","terminalId":"toolu_native_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native","toolName":"Bash"}},"rawInput":{"command":"make"},"sessionUpdate":"tool_call_update","title":"make","toolCallId":"toolu_native_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native","toolName":"Bash"}},"rawInput":{"command":"make","description":"Build"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_native_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"make"},"sessionUpdate":"tool_call_update","title":"make","toolCallId":"toolu_native_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"make","description":"Build"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_native_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} -{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native","toolName":"Bash"}},"content":[{"terminalId":"toolu_native_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"make","description":"Build"},"status":"pending","title":"make","toolCallId":"toolu_native_bash"},"type":"tool_call"},"title":"make"}} +{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native"}},"content":[{"terminalId":"toolu_native_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"make","description":"Build"},"status":"pending","title":"make","toolCallId":"toolu_native_bash"},"type":"tool_call"},"title":"make"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"output":{"data":"bWFrZTogKioqIEVycm9yIDI="},"sessionUpdate":"terminal_update","terminalId":"toolu_native_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"exitStatus":{},"sessionUpdate":"terminal_update","terminalId":"toolu_native_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native","toolName":"Bash"}},"sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_native_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[{"content":{"text":"```\nThe build still fails.\n```","type":"text"},"type":"content"}],"rawOutput":[{"text":"The build still fails.","type":"text"}],"sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_native"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_native_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"```\nThe build still fails.\n```","type":"text"},"type":"content"}],"rawOutput":[{"text":"The build still fails.","type":"text"}],"sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_native"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/subagent-nested.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/subagent-nested.jsonl index e4d734cd..eb235d5a 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/subagent-nested.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/subagent-nested.jsonl @@ -4,21 +4,21 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_outer"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"rawInput":{"description":"Plan the work"},"sessionUpdate":"tool_call_update","title":"Plan the work","toolCallId":"toolu_outer"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"rawInput":{"description":"Plan the work","prompt":"Plan it"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_outer"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_outer"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Plan the work"},"sessionUpdate":"tool_call_update","title":"Plan the work","toolCallId":"toolu_outer"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Plan the work","prompt":"Plan it"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_outer"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[{"content":{"text":"Plan it","type":"text"},"type":"content"}],"rawInput":{"description":"Plan the work","prompt":"Plan it","subagent_type":"Plan"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_outer"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_outer","toolName":"Agent"}},"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_inner"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_outer","toolName":"Agent"}},"rawInput":{"description":"Read the spec"},"sessionUpdate":"tool_call_update","title":"Read the spec","toolCallId":"toolu_inner"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_outer","toolName":"Agent"}},"rawInput":{"description":"Read the spec","prompt":"Read spec.md"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_inner"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_outer","toolName":"Agent"}},"content":[{"content":{"text":"Read spec.md","type":"text"},"type":"content"}],"rawInput":{"description":"Read the spec","prompt":"Read spec.md","subagent_type":"Explore"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_inner"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_inner","toolName":"Read"}},"content":[],"kind":"read","locations":[],"name":"Read","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Read File","toolCallId":"toolu_grandchild_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_inner","toolName":"Read"}},"locations":[{"line":1,"path":"/spec.md"}],"rawInput":{"file_path":"/spec.md"},"sessionUpdate":"tool_call_update","title":"Read /spec.md","toolCallId":"toolu_grandchild_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_inner","toolName":"Read"}},"content":[{"content":{"text":"```\n1\tspec\n```","type":"text"},"type":"content"}],"rawOutput":"1\tspec","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_grandchild_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_outer","toolName":"Agent"}},"content":[{"content":{"text":"The spec says X.","type":"text"},"type":"content"}],"rawOutput":[{"text":"The spec says X.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_inner"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Plan it","type":"text"},"type":"content"}],"rawInput":{"description":"Plan the work","prompt":"Plan it","subagent_type":"Plan"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_outer"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_outer"}},"content":[],"kind":"think","name":"Agent","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_inner"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Read the spec"},"sessionUpdate":"tool_call_update","title":"Read the spec","toolCallId":"toolu_inner"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Read the spec","prompt":"Read spec.md"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_inner"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Read spec.md","type":"text"},"type":"content"}],"rawInput":{"description":"Read the spec","prompt":"Read spec.md","subagent_type":"Explore"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_inner"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_inner"}},"content":[],"kind":"read","locations":[],"name":"Read","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Read File","toolCallId":"toolu_grandchild_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"line":1,"path":"/spec.md"}],"rawInput":{"file_path":"/spec.md"},"sessionUpdate":"tool_call_update","title":"Read /spec.md","toolCallId":"toolu_grandchild_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"```\n1\tspec\n```","type":"text"},"type":"content"}],"rawOutput":"1\tspec","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_grandchild_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"The spec says X.","type":"text"},"type":"content"}],"rawOutput":[{"text":"The spec says X.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_inner"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_outer"}},"content":{"text":"Plan:","type":"text"},"messageId":"msg_outer_text","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_outer"}},"content":{"text":" do X.","type":"text"},"messageId":"msg_outer_text","sessionUpdate":"agent_message_chunk"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Agent"}},"content":[{"content":{"text":"Plan: do X.","type":"text"},"type":"content"}],"rawOutput":[{"text":"Plan: do X.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_outer"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Plan: do X.","type":"text"},"type":"content"}],"rawOutput":[{"text":"Plan: do X.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_outer"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/subagent-task-legacy.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/subagent-task-legacy.jsonl index 93163ef3..dce79af8 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/subagent-task-legacy.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/subagent-task-legacy.jsonl @@ -4,40 +4,40 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"content":[],"kind":"think","name":"Task","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_task"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"rawInput":{"description":"Explore code"},"sessionUpdate":"tool_call_update","title":"Explore code","toolCallId":"toolu_task"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"rawInput":{"description":"Explore code","prompt":"Find the parser"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_task"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"think","name":"Task","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_task"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Explore code"},"sessionUpdate":"tool_call_update","title":"Explore code","toolCallId":"toolu_task"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Explore code","prompt":"Find the parser"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_task"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"content":[{"content":{"text":"Find the parser","type":"text"},"type":"content"}],"rawInput":{"description":"Explore code","prompt":"Find the parser","subagent_type":"Explore"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_task"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Find the parser","type":"text"},"type":"content"}],"rawInput":{"description":"Explore code","prompt":"Find the parser","subagent_type":"Explore"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_task"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":{"text":"Looking for","type":"text"},"messageId":"msg_sub_1","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":{"text":" the parser.","type":"text"},"messageId":"msg_sub_1","sessionUpdate":"agent_message_chunk"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Read"}},"content":[],"kind":"read","locations":[],"name":"Read","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Read File","toolCallId":"toolu_sub_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Read"}},"locations":[{"line":1,"path":"/x.ts"}],"rawInput":{"file_path":"/x.ts"},"sessionUpdate":"tool_call_update","title":"Read /x.ts","toolCallId":"toolu_sub_read"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task","toolResponse":{"elapsedTimeSeconds":3,"subagentType":"Explore"}}},"sessionUpdate":"tool_call_update","status":"in_progress","toolCallId":"toolu_task"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Read"}},"content":[{"content":{"text":"```\n1\tparser\n```","type":"text"},"type":"content"}],"rawOutput":"1\tparser","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_sub_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":[],"kind":"read","locations":[],"name":"Read","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Read File","toolCallId":"toolu_sub_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"line":1,"path":"/x.ts"}],"rawInput":{"file_path":"/x.ts"},"sessionUpdate":"tool_call_update","title":"Read /x.ts","toolCallId":"toolu_sub_read"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolResponse":{"elapsedTimeSeconds":3,"subagentType":"Explore"}}},"sessionUpdate":"tool_call_update","status":"in_progress","toolCallId":"toolu_task"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"```\n1\tparser\n```","type":"text"},"type":"content"}],"rawOutput":"1\tparser","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_sub_read"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"terminal_update","terminalId":"toolu_sub_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Bash"}},"content":[{"terminalId":"toolu_sub_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_sub_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":[{"terminalId":"toolu_sub_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_sub_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"command":"rg parser","sessionUpdate":"terminal_update","terminalId":"toolu_sub_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Bash"}},"rawInput":{"command":"rg parser"},"sessionUpdate":"tool_call_update","title":"rg parser","toolCallId":"toolu_sub_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Bash"}},"rawInput":{"command":"rg parser","description":"Search"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_sub_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"rg parser"},"sessionUpdate":"tool_call_update","title":"rg parser","toolCallId":"toolu_sub_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"rg parser","description":"Search"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_sub_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} -{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Bash"}},"content":[{"terminalId":"toolu_sub_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"rg parser","description":"Search"},"status":"pending","title":"rg parser","toolCallId":"toolu_sub_bash"},"type":"tool_call"},"title":"rg parser"}} +{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":[{"terminalId":"toolu_sub_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"rg parser","description":"Search"},"status":"pending","title":"rg parser","toolCallId":"toolu_sub_bash"},"type":"tool_call"},"title":"rg parser"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"output":{"data":"eC50cw=="},"sessionUpdate":"terminal_update","terminalId":"toolu_sub_bash"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"exitStatus":{"exitCode":0},"sessionUpdate":"terminal_update","terminalId":"toolu_sub_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Bash"}},"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_sub_bash"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Edit"}},"content":[],"kind":"edit","locations":[],"name":"Edit","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Edit","toolCallId":"toolu_sub_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Edit"}},"locations":[{"path":"/x.ts"}],"rawInput":{"file_path":"/x.ts"},"sessionUpdate":"tool_call_update","title":"Edit x.ts","toolCallId":"toolu_sub_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Edit"}},"rawInput":{"file_path":"/x.ts","old_string":"a"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_sub_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Edit"}},"rawInput":{"file_path":"/x.ts","new_string":"b","old_string":"a"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_sub_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_sub_bash"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":[],"kind":"edit","locations":[],"name":"Edit","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Edit","toolCallId":"toolu_sub_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"path":"/x.ts"}],"rawInput":{"file_path":"/x.ts"},"sessionUpdate":"tool_call_update","title":"Edit x.ts","toolCallId":"toolu_sub_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"file_path":"/x.ts","old_string":"a"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_sub_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"file_path":"/x.ts","new_string":"b","old_string":"a"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_sub_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} -{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Edit"}},"content":[],"kind":"edit","locations":[{"path":"/x.ts"}],"name":"Edit","rawInput":{"file_path":"/x.ts","new_string":"b","old_string":"a"},"status":"pending","title":"Edit x.ts","toolCallId":"toolu_sub_edit"},"type":"tool_call"},"title":"Edit x.ts"}} +{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":[],"kind":"edit","locations":[{"path":"/x.ts"}],"name":"Edit","rawInput":{"file_path":"/x.ts","new_string":"b","old_string":"a"},"status":"pending","title":"Edit x.ts","toolCallId":"toolu_sub_edit"},"type":"tool_call"},"title":"Edit x.ts"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Edit"}},"rawOutput":"The file has been updated.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_sub_edit"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task","toolName":"Edit","toolResponse":{"filePath":"/x.ts","newString":"b","oldString":"a","originalFile":"a\n","replaceAll":false,"structuredPatch":[{"lines":["-a","+b"],"newLines":1,"newStart":1,"oldLines":1,"oldStart":1}],"userModified":false}}},"content":[{"changes":[{"fileType":"text","operation":"modify","path":"/x.ts"}],"patch":{"format":"git_patch","text":"diff --git /x.ts /x.ts\n--- /x.ts\n+++ /x.ts\n@@ -1 +1 @@\n-a\n+b\n"},"type":"diff"}],"locations":[{"line":1,"path":"/x.ts"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_sub_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawOutput":"The file has been updated.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_sub_edit"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"/x.ts"}],"patch":{"format":"git_patch","text":"diff --git /x.ts /x.ts\n--- /x.ts\n+++ /x.ts\n@@ -1 +1 @@\n-a\n+b\n"},"type":"diff"}],"locations":[{"line":1,"path":"/x.ts"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_sub_edit"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":{"text":"Foun","type":"text"},"messageId":"msg_sub_2","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":{"text":"d it.","type":"text"},"messageId":"msg_sub_2","sessionUpdate":"agent_message_chunk"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"content":[{"content":{"text":"The parser is in x.ts.","type":"text"},"type":"content"}],"rawOutput":[{"text":"The parser is in x.ts.\nagentId: a1 (use SendMessage to continue)","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_task"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task","toolResponse":{"agentId":"a1","content":[{"text":"The parser is in x.ts.","type":"text"}],"prompt":"Find the parser","status":"completed","totalDurationMs":10,"totalTokens":5,"totalToolUseCount":1}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_task"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"The parser is in x.ts.","type":"text"},"type":"content"}],"rawOutput":[{"text":"The parser is in x.ts.\nagentId: a1 (use SendMessage to continue)","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_task"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolResponse":{"status":"completed"}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_task"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/subagent-transcript-extension.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/subagent-transcript-extension.jsonl index 023a7caf..5d3f947a 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/subagent-transcript-extension.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/subagent-transcript-extension.jsonl @@ -4,18 +4,18 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"content":[],"kind":"think","name":"Task","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_transcript"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"rawInput":{"description":"Summarize"},"sessionUpdate":"tool_call_update","title":"Summarize","toolCallId":"toolu_transcript"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"rawInput":{"description":"Summarize","prompt":"Summarize the repo"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_transcript"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"think","name":"Task","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Task","toolCallId":"toolu_transcript"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Summarize"},"sessionUpdate":"tool_call_update","title":"Summarize","toolCallId":"toolu_transcript"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"description":"Summarize","prompt":"Summarize the repo"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_transcript"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"content":[{"content":{"text":"Summarize the repo","type":"text"},"type":"content"}],"rawInput":{"description":"Summarize","prompt":"Summarize the repo","subagent_type":"Explore"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_transcript"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Summarize the repo","type":"text"},"type":"content"}],"rawInput":{"description":"Summarize","prompt":"Summarize the repo","subagent_type":"Explore"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_transcript"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_transcript"}},"content":{"text":"Look at t","type":"text"},"messageId":"msg_transcript_sub","sessionUpdate":"agent_thought_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_transcript"}},"content":{"text":"he layout.","type":"text"},"messageId":"msg_transcript_sub","sessionUpdate":"agent_thought_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_transcript"}},"content":{"text":"The repo has ","type":"text"},"messageId":"msg_transcript_sub","sessionUpdate":"agent_message_chunk"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_transcript"}},"content":{"text":"two packages.","type":"text"},"messageId":"msg_transcript_sub","sessionUpdate":"agent_message_chunk"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_transcript","toolName":"Glob"}},"content":[],"kind":"search","locations":[],"name":"Glob","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Find","toolCallId":"toolu_transcript_glob"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_transcript","toolName":"Glob"}},"rawInput":{"pattern":"*"},"sessionUpdate":"tool_call_update","title":"Find `*`","toolCallId":"toolu_transcript_glob"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_transcript","toolName":"Glob"}},"content":[{"content":{"text":"a\nb","type":"text"},"type":"content"}],"rawOutput":"a\nb","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_transcript_glob"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Task"}},"content":[{"content":{"text":"Two packages.","type":"text"},"type":"content"}],"rawOutput":[{"text":"Two packages.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_transcript"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_transcript"}},"content":[],"kind":"search","locations":[],"name":"Glob","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Find","toolCallId":"toolu_transcript_glob"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"pattern":"*"},"sessionUpdate":"tool_call_update","title":"Find `*`","toolCallId":"toolu_transcript_glob"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"a\nb","type":"text"},"type":"content"}],"rawOutput":"a\nb","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_transcript_glob"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Two packages.","type":"text"},"type":"content"}],"rawOutput":[{"text":"Two packages.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_transcript"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/task-output-and-stop.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/task-output-and-stop.jsonl index 24939261..9f781190 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/task-output-and-stop.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/task-output-and-stop.jsonl @@ -4,14 +4,14 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"TaskOutput"}},"content":[],"kind":"other","name":"TaskOutput","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"TaskOutput","toolCallId":"toolu_out"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"TaskOutput"}},"rawInput":{"task_id":"bash_1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_out"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"other","name":"TaskOutput","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"TaskOutput","toolCallId":"toolu_out"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"task_id":"bash_1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_out"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"TaskOutput"}},"rawInput":{"block":true,"task_id":"bash_1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_out"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"TaskOutput"}},"content":[{"content":{"text":"success\ndone","type":"text"},"type":"content"}],"rawOutput":"success\ndone","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_out"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"TaskStop"}},"content":[],"kind":"other","name":"TaskStop","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"TaskStop","toolCallId":"toolu_stop"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"block":true,"task_id":"bash_1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_out"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"success\ndone","type":"text"},"type":"content"}],"rawOutput":"success\ndone","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_out"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"other","name":"TaskStop","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"TaskStop","toolCallId":"toolu_stop"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"TaskStop"}},"rawInput":{"task_id":"bash_1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_stop"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"TaskStop"}},"content":[{"content":{"text":"Successfully stopped task: bash_1","type":"text"},"type":"content"}],"rawOutput":"Successfully stopped task: bash_1","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_stop"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"task_id":"bash_1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_stop"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Successfully stopped task: bash_1","type":"text"},"type":"content"}],"rawOutput":"Successfully stopped task: bash_1","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_stop"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/tool-progress.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/tool-progress.jsonl index 1adc12b0..fa92f360 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/tool-progress.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/tool-progress.jsonl @@ -5,15 +5,15 @@ {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"terminal_update","terminalId":"toolu_slow"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"content":[{"terminalId":"toolu_slow","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_slow"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"terminalId":"toolu_slow","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Terminal","toolCallId":"toolu_slow"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"command":"make","sessionUpdate":"terminal_update","terminalId":"toolu_slow"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"rawInput":{"command":"make"},"sessionUpdate":"tool_call_update","title":"make","toolCallId":"toolu_slow"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash","toolResponse":{"elapsedTimeSeconds":1}}},"sessionUpdate":"tool_call_update","status":"in_progress","toolCallId":"toolu_slow"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash","toolResponse":{"elapsedTimeSeconds":2}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_slow"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash","toolResponse":{"elapsedTimeSeconds":3}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_slow"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"command":"make"},"sessionUpdate":"tool_call_update","title":"make","toolCallId":"toolu_slow"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolResponse":{"elapsedTimeSeconds":1}}},"sessionUpdate":"tool_call_update","status":"in_progress","toolCallId":"toolu_slow"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolResponse":{"elapsedTimeSeconds":2}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_slow"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolResponse":{"elapsedTimeSeconds":3}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_slow"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"output":{"data":"YnVpbHQ="},"sessionUpdate":"terminal_update","terminalId":"toolu_slow"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"exitStatus":{"exitCode":0},"sessionUpdate":"terminal_update","terminalId":"toolu_slow"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Bash"}},"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_slow"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_slow"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/web-fetch-and-search.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/web-fetch-and-search.jsonl index 420116e5..e3619fd7 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/web-fetch-and-search.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/web-fetch-and-search.jsonl @@ -4,17 +4,17 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"WebFetch"}},"content":[],"kind":"fetch","name":"WebFetch","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Fetch","toolCallId":"toolu_fetch"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"WebFetch"}},"rawInput":{"url":"https://example.com"},"sessionUpdate":"tool_call_update","title":"Fetch https://example.com","toolCallId":"toolu_fetch"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"fetch","name":"WebFetch","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Fetch","toolCallId":"toolu_fetch"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"url":"https://example.com"},"sessionUpdate":"tool_call_update","title":"Fetch https://example.com","toolCallId":"toolu_fetch"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"WebFetch"}},"content":[{"content":{"text":"Summarize the page","type":"text"},"type":"content"}],"rawInput":{"prompt":"Summarize the page","url":"https://example.com"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_fetch"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"Summarize the page","type":"text"},"type":"content"}],"rawInput":{"prompt":"Summarize the page","url":"https://example.com"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_fetch"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"allow_always","name":"Yes, and don't ask again for example.com","optionId":"allow-with-updates"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"content":[{"content":{"text":"Summarize the page","type":"text"},"type":"content"}],"kind":"fetch","name":"WebFetch","rawInput":{"prompt":"Summarize the page","url":"https://example.com"},"status":"pending","title":"Fetch https://example.com","toolCallId":"toolu_fetch"},"type":"tool_call"},"title":"Fetch https://example.com"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"WebFetch"}},"content":[{"content":{"text":"The page is an example.","type":"text"},"type":"content"}],"rawOutput":"The page is an example.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_fetch"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"WebSearch"}},"content":[],"kind":"fetch","name":"WebSearch","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Web search","toolCallId":"toolu_search"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"The page is an example.","type":"text"},"type":"content"}],"rawOutput":"The page is an example.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_fetch"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"fetch","name":"WebSearch","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Web search","toolCallId":"toolu_search"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"WebSearch"}},"rawInput":{"query":"acp protocol"},"sessionUpdate":"tool_call_update","title":"Search \"acp protocol\"","toolCallId":"toolu_search"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"WebSearch"}},"content":[{"content":{"text":"ACP (https://agentclientprotocol.com)\nA summary.","type":"text"},"type":"content"}],"rawOutput":"Web search results for query: \"acp protocol\"\n\nLinks: [...]","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_search"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"query":"acp protocol"},"sessionUpdate":"tool_call_update","title":"Search \"acp protocol\"","toolCallId":"toolu_search"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"content":{"text":"ACP (https://agentclientprotocol.com)\nA summary.","type":"text"},"type":"content"}],"rawOutput":"Web search results for query: \"acp protocol\"\n\nLinks: [...]","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_search"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/write-existing.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/write-existing.jsonl index ac8a91dd..42e45f9c 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/write-existing.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/write-existing.jsonl @@ -4,12 +4,12 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write"}},"content":[],"kind":"edit","locations":[],"name":"Write","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Preparing file…","toolCallId":"toolu_write"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write"}},"locations":[{"path":"/old.ts"}],"rawInput":{"file_path":"/old.ts"},"sessionUpdate":"tool_call_update","title":"Write old.ts","toolCallId":"toolu_write"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"edit","locations":[],"name":"Write","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Preparing file…","toolCallId":"toolu_write"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"path":"/old.ts"}],"rawInput":{"file_path":"/old.ts"},"sessionUpdate":"tool_call_update","title":"Write old.ts","toolCallId":"toolu_write"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write"}},"rawInput":{"content":"export const x = 1;\n","file_path":"/old.ts"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"content":"export const x = 1;\n","file_path":"/old.ts"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"/old.ts"}],"patch":{"format":"git_patch","text":"diff --git /old.ts /old.ts\n--- /old.ts\n+++ /old.ts\n@@ -1 +1 @@\n-export const x = 0;\n+export const x = 1;\n"},"type":"diff"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write"}},"rawOutput":"The file /old.ts has been updated successfully.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_write"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write","toolResponse":{"content":"export const x = 1;\n","filePath":"/old.ts","originalFile":"export const x = 0;\n","structuredPatch":[{"lines":["-export const x = 0;","+export const x = 1;"],"newLines":1,"newStart":1,"oldLines":1,"oldStart":1}],"type":"update"}}},"locations":[{"line":1,"path":"/old.ts"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawOutput":"The file /old.ts has been updated successfully.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_write"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"line":1,"path":"/old.ts"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-scenarios/__snapshots__/v2/write-new.jsonl b/src/tests/acp-scenarios/__snapshots__/v2/write-new.jsonl index 5dc63fa1..17baddfd 100644 --- a/src/tests/acp-scenarios/__snapshots__/v2/write-new.jsonl +++ b/src/tests/acp-scenarios/__snapshots__/v2/write-new.jsonl @@ -4,15 +4,14 @@ {"kind":"response","method":"session/prompt","payload":{"messageId":""}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":2}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write"}},"content":[],"kind":"edit","locations":[],"name":"Write","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Preparing file…","toolCallId":"toolu_write"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write"}},"locations":[{"path":"/new.ts"}],"rawInput":{"file_path":"/new.ts"},"sessionUpdate":"tool_call_update","title":"Write new.ts","toolCallId":"toolu_write"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[],"kind":"edit","locations":[],"name":"Write","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Preparing file…","toolCallId":"toolu_write"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"locations":[{"path":"/new.ts"}],"rawInput":{"file_path":"/new.ts"},"sessionUpdate":"tool_call_update","title":"Write new.ts","toolCallId":"toolu_write"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write"}},"rawInput":{"content":"export const x = 1;\n","file_path":"/new.ts"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawInput":{"content":"export const x = 1;\n","file_path":"/new.ts"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"content":[{"changes":[{"fileType":"text","operation":"add","path":"/new.ts"}],"patch":{"format":"git_patch","text":"diff --git /new.ts /new.ts\nnew file mode 100644\n--- /dev/null\n+++ /new.ts\n@@ -0,0 +1 @@\n+export const x = 1;\n"},"type":"diff"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"requires_action"}}} {"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"","subject":{"toolCall":{"content":[{"changes":[{"fileType":"text","operation":"add","path":"/new.ts"}],"patch":{"format":"git_patch","text":"diff --git /new.ts /new.ts\nnew file mode 100644\n--- /dev/null\n+++ /new.ts\n@@ -0,0 +1 @@\n+export const x = 1;\n"},"type":"diff"}],"kind":"edit","locations":[{"path":"/new.ts"}],"name":"Write","rawInput":{"content":"export const x = 1;\n","file_path":"/new.ts"},"status":"pending","title":"Write new.ts","toolCallId":"toolu_write"},"type":"tool_call"},"title":"Write new.ts"}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"sessionUpdate":"state_update","state":"running"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write"}},"rawOutput":"File created successfully at: /new.ts","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_write"}}} -{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"claudeCode":{"toolName":"Write","toolResponse":{"content":"export const x = 1;\n","filePath":"/new.ts","originalFile":null,"structuredPatch":[],"type":"create"}}},"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}} +{"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"rawOutput":"File created successfully at: /new.ts","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_write"}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}} {"kind":"notification","method":"session/update","payload":{"sessionId":"","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}}}} diff --git a/src/tests/acp-v2.test.ts b/src/tests/acp-v2.test.ts index 9fca9288..52faae25 100644 --- a/src/tests/acp-v2.test.ts +++ b/src/tests/acp-v2.test.ts @@ -26,6 +26,7 @@ import { clientSupportsNotices } from "../session-notices.js"; import { v1PermissionResponse, v2PermissionRequest } from "../v2/permission.js"; import { v1PromptRequest } from "../v2/prompt.js"; import { V2Terminals } from "../v2/terminal.js"; +import { V2ToolCallMeta } from "../v2/tool-call-meta.js"; import { v2SessionUpdate } from "../v2/session-update.js"; import { v1SetSessionConfigOptionRequest, v2ConfigOptions } from "../v2/session.js"; import packageJson from "../../package.json" with { type: "json" }; @@ -3199,6 +3200,107 @@ describe("ACP v2 session translation", () => { expect(commanded("open")).toHaveLength(1); }); + describe("the _meta that the client stores for a tool call", () => { + const report = (_meta?: Record, fields: Record = {}) => ({ + toolCallId: "t", + ...fields, + ...(_meta ? { _meta } : {}), + }); + + it("gives the tool's name as name, once, and leaves it out of _meta", () => { + const meta = new V2ToolCallMeta(); + expect(meta.apply("s", report({ claudeCode: { toolName: "memory_recall" } }), true)).toEqual({ + toolCallId: "t", + name: "memory_recall", + }); + expect(meta.apply("s", report({ claudeCode: { toolName: "Bash" } }), false)).toEqual({ + toolCallId: "t", + }); + // A report's own name wins. + expect( + meta.apply("s", report({ claudeCode: { toolName: "Bash" } }, { name: "Read" }), true), + ).toEqual({ toolCallId: "t", name: "Read" }); + }); + + it("sends the earlier claudeCode keys again with a key that changes", () => { + const meta = new V2ToolCallMeta(); + const denial = { toolResponse: { decisionReasonType: "rule" } }; + expect(meta.apply("s", report({ claudeCode: denial }), true)).toEqual( + report({ claudeCode: denial }), + ); + expect( + meta.apply("s", report({ claudeCode: { nonExecutionKind: "permission-rule" } }), false), + ).toEqual(report({ claudeCode: { ...denial, nonExecutionKind: "permission-rule" } })); + }); + + it("replaces a claudeCode key whole, and other _meta keys whole", () => { + const meta = new V2ToolCallMeta(); + meta.apply( + "s", + report({ claudeCode: { toolResponse: { elapsedTimeSeconds: 1 } }, flag: { a: 1 } }), + true, + ); + expect( + meta.apply("s", report({ claudeCode: { toolResponse: { status: "ok" } } }), false), + ).toEqual(report({ claudeCode: { toolResponse: { status: "ok" } }, flag: { a: 1 } })); + expect(meta.apply("s", report({ flag: { b: 2 } }), false)).toEqual( + report({ claudeCode: { toolResponse: { status: "ok" } }, flag: { b: 2 } }), + ); + }); + + it("sends no _meta on a report that changes nothing", () => { + const meta = new V2ToolCallMeta(); + meta.apply("s", report({ claudeCode: { toolName: "Bash", parentToolUseId: "p" } }), true); + expect( + meta.apply( + "s", + report( + { claudeCode: { toolName: "Bash", parentToolUseId: "p" } }, + { status: "completed" }, + ), + false, + ), + ).toEqual({ toolCallId: "t", status: "completed" }); + }); + + it("gives a permission request's subject the whole _meta, also when it changes nothing", () => { + const meta = new V2ToolCallMeta(); + meta.apply("s", report({ claudeCode: { toolName: "Bash", parentToolUseId: "p" } }), true); + expect(meta.subject("s", report({ claudeCode: { toolName: "Bash" } }))).toEqual( + report({ claudeCode: { parentToolUseId: "p" } }), + ); + // Its own keys are stored, since the subject updates the tool call. + meta.subject("s", report({ claudeCode: { mcpServer: { name: "docs" } } })); + expect(meta.apply("s", report({ claudeCode: { nonExecutionKind: "x" } }), false)).toEqual( + report({ + claudeCode: { parentToolUseId: "p", mcpServer: { name: "docs" }, nonExecutionKind: "x" }, + }), + ); + }); + + it("keeps the tool calls of each session apart, and forgets a closed session's", () => { + const meta = new V2ToolCallMeta(); + const started = { claudeCode: { parentToolUseId: "p" } }; + meta.apply("closed", report(started), true); + meta.apply("open", report(started), true); + meta.forget("closed"); + const failed = report({ claudeCode: { nonExecutionKind: "x" } }); + expect(meta.apply("closed", failed, false)._meta).toEqual(failed._meta); + expect(meta.apply("open", failed, false)._meta).toEqual({ + claudeCode: { parentToolUseId: "p", nonExecutionKind: "x" }, + }); + }); + + it("forgets what an earlier tool call with the same id stored, when one starts", () => { + const meta = new V2ToolCallMeta(); + meta.apply("s", report({ claudeCode: { toolName: "Bash", parentToolUseId: "p" } }), true); + expect(meta.apply("s", report({ claudeCode: { toolName: "Read" } }), true)).toEqual({ + toolCallId: "t", + name: "Read", + }); + }); + }); + it("fails on a permission request without the title that v2 requires", () => { const request = { sessionId: "s", diff --git a/src/tool-calls/renderer.ts b/src/tool-calls/renderer.ts index 14ec773b..df97cecc 100644 --- a/src/tool-calls/renderer.ts +++ b/src/tool-calls/renderer.ts @@ -44,11 +44,13 @@ export type ToolUpdateMeta = { claudeCode?: { /* The name of the tool that was used in Claude Code. Also carried as the standard ACP `name` field on the initial `tool_call`. A progress beat - for AIR leaves it out when the adapter does not know the tool. */ + for AIR leaves it out when the adapter does not know the tool. A v2 + client gets it as `name` alone (see `V2ToolCallMeta`). */ toolName?: string; - /* The structured output provided by Claude Code. For an AIR client, a - PostToolUse update carries only the `status` and `isAsync` markers of - the tool_response: the tool output itself is in the tool-call content. */ + /* The structured output provided by Claude Code. For an AIR or a v2 + client, a PostToolUse update carries only the `status` and `isAsync` + markers of the tool_response: the tool output itself is in the + tool-call content. */ toolResponse?: unknown; /* For a tool call made inside a subagent: the tool_use id of the Agent/Task call that spawned the subagent. Mirrors the SDK's @@ -150,6 +152,15 @@ export class AcpToolCallRenderer { return new AcpToolCallRenderer(ClientCapabilities.from(capabilities), replay); } + /** + * Whether the client keeps a tool call's `_meta` across reports: AIR merges + * its keys, and v2 stores it. Such a client gets no `toolResponse` text that + * the tool call's content already shows, which it would otherwise keep. + */ + private get keepsMeta(): boolean { + return this.capabilities.air.client || this.capabilities.v2; + } + /** * The status of a tool result. Claude Code reports a run that it aborted in * one of two ways: an error result whose `nonExecution` kind says so (a @@ -506,7 +517,8 @@ export class AcpToolCallRenderer { /** * The report of a PostToolUse hook: the final change of an edit tool, and * the `status` and `isAsync` markers of the `tool_response`. The rest of the - * `tool_response` repeats output that the content already carries. + * `tool_response` repeats output that the content already carries, such as + * the whole text of a written file. */ async hookResult( toolUse: Pick, @@ -517,7 +529,7 @@ export class AcpToolCallRenderer { const change = reporter.hookResult ? await reporter.hookResult(toolResponse, { cwd, capabilities: this.capabilities }) : {}; - if (!this.capabilities.air.client) { + if (!this.keepsMeta) { // The upstream shape: the whole tool_response, on every hook. return { _meta: { claudeCode: { toolResponse, toolName: toolUse.name } } satisfies ToolUpdateMeta, @@ -587,9 +599,10 @@ export class AcpToolCallRenderer { message?: string; }): ToolCallUpdate { const reason = denial.decisionReason ?? denial.message; - // AIR gets the SDK message only when it differs from the reason, which - // the content shows. Every other client gets the upstream toolResponse. - const extraMessage = !this.capabilities.air.client + // AIR and v2 get the SDK message only when it differs from the reason, + // which the content shows. Every other client gets the upstream + // toolResponse. + const extraMessage = !this.keepsMeta ? { decisionReason: denial.decisionReason, message: denial.message } : denial.decisionReason !== undefined && denial.message !== undefined && diff --git a/src/v2/agent.ts b/src/v2/agent.ts index 9b739802..ac5b345b 100644 --- a/src/v2/agent.ts +++ b/src/v2/agent.ts @@ -32,6 +32,7 @@ import { } from "./session.js"; import { v2SessionUpdate } from "./session-update.js"; import { V2Terminals } from "./terminal.js"; +import { V2ToolCallMeta } from "./tool-call-meta.js"; /** * The ACP v2 surface, for one connection. @@ -104,6 +105,7 @@ export function v2AgentApp( .onRequest(v2.methods.agent.session.close, async ({ params }) => { const response = await agent.closeSession(params); client.terminals.forget(params.sessionId); + client.toolCallMeta.forget(params.sessionId); return response; }) .onRequest(v2.methods.agent.session.delete, ({ params }) => agent.deleteSession(params)) @@ -157,6 +159,9 @@ class V2ClientConnection implements AcpClient { /** The display terminals of the commands that the agent runs. */ readonly terminals = new V2Terminals(); + /** The `_meta` that the client stores for each tool call. */ + readonly toolCallMeta = new V2ToolCallMeta(); + constructor( private readonly ctx: v2.AgentContext, private readonly logger: Logger, @@ -217,7 +222,8 @@ class V2ClientConnection implements AcpClient { /** * The v2 updates of a v1 update: for a tool call report, the updates of its - * terminal first, then the report itself (see {@link V2Terminals}). + * terminal first (see {@link V2Terminals}), then the report itself, with the + * `_meta` that the client stores (see {@link V2ToolCallMeta}). */ private v2Updates( sessionId: string, @@ -228,7 +234,9 @@ class V2ClientConnection implements AcpClient { return v2Update ? [v2Update] : []; } const { terminal, report } = this.terminals.split(sessionId, update); - const reportUpdate = report && v2SessionUpdate(report); + if (!report) return terminal; + const starts = report.sessionUpdate === "tool_call"; + const reportUpdate = v2SessionUpdate(this.toolCallMeta.apply(sessionId, report, starts)); return [...terminal, ...(reportUpdate ? [reportUpdate] : [])]; } @@ -252,9 +260,11 @@ class V2ClientConnection implements AcpClient { params: AcpPermissionRequest, signal?: AbortSignal, ): Promise { + // The subject is an update of the tool call, with its stored `_meta`. + const toolCall = this.toolCallMeta.subject(params.sessionId, params.toolCall); const response = await this.ctx.request( v2.methods.client.session.requestPermission, - v2PermissionRequest(params), + v2PermissionRequest({ ...params, toolCall }), { cancellationSignal: signal }, ); return v1PermissionResponse(response); diff --git a/src/v2/tool-call-meta.ts b/src/v2/tool-call-meta.ts new file mode 100644 index 00000000..539a0cd8 --- /dev/null +++ b/src/v2/tool-call-meta.ts @@ -0,0 +1,104 @@ +/** + * The `_meta` of the tool calls of one ACP v2 connection, as the client stores + * it. + * + * The agent gives each v1 tool call report the `_meta` keys of that report. + * An AIR client merges them by key (see `ToolCallFieldTracker`), and another + * v1 client reads them per report. A v2 client stores a tool call's `_meta`, + * and a report that carries `_meta` replaces it. So the earlier keys must + * travel again, or the `{ toolName }` of a tool's result would replace, for + * example, the reason of the denial before it. + * + * {@link V2ToolCallMeta} therefore keeps the merged `_meta` of each tool call, + * with the `claudeCode` keys merged one by one and every other key replaced + * whole, as `ToolCallFieldTracker` models it. A report that changes it carries + * all of it; a report that changes nothing carries no `_meta`. + * + * `claudeCode.toolName` repeats the name of the tool, which v2 has a field + * for. It becomes the `name` of a tool call that has none yet, and is left out + * of the stored `_meta`. Subagent routing reads it before this, on the agent's + * v1 reports. + */ +import type { ToolCall, ToolCallUpdate } from "@agentclientprotocol/sdk"; + +type Meta = Record; + +/** The number of tool calls whose `_meta` a connection remembers. */ +const TOOL_CALL_LIMIT = 2048; + +export class V2ToolCallMeta { + /** The stored `_meta` of each tool call, by session and tool call, oldest first. */ + private readonly calls = new Map(); + + /** + * `report` with the tool call's whole `_meta` when the report changes it, + * without `_meta` when it does not, and with `name` when it names the tool + * call for the first time. `starts` says that the report starts the tool + * call (a v1 `tool_call`), which forgets what an earlier one stored. + */ + apply( + sessionId: string, + report: Report, + starts: boolean, + ): Report { + const key = `${sessionId} ${report.toolCallId}`; + const call = (!starts && this.calls.get(key)) || { meta: {}, named: false }; + this.remember(key, call); + + const { _meta, ...fields } = report; + const result = fields as Report; + const { toolName, ...claudeCode } = asRecord(_meta?.claudeCode) ?? {}; + if (report.name != null) { + call.named = true; + } else if (!call.named && typeof toolName === "string") { + result.name = toolName; + call.named = true; + } + + const meta: Meta = { ...call.meta }; + for (const [name, value] of Object.entries(_meta ?? {})) { + if (name !== "claudeCode") meta[name] = value; + } + if (Object.keys(claudeCode).length > 0) { + meta.claudeCode = { ...asRecord(call.meta.claudeCode), ...claudeCode }; + } + if (JSON.stringify(meta) !== JSON.stringify(call.meta)) { + call.meta = meta; + result._meta = meta; + } + return result; + } + + /** + * The tool call of a permission request's subject: like {@link apply}, but + * with the tool call's whole `_meta` even when the subject changes nothing, + * since a client can show the request from the request alone. + */ + subject(sessionId: string, toolCall: Report): Report { + const result = this.apply(sessionId, toolCall, false); + const stored = this.calls.get(`${sessionId} ${toolCall.toolCallId}`)?.meta ?? {}; + if (result._meta === undefined && Object.keys(stored).length > 0) result._meta = stored; + return result; + } + + /** Forgets the tool calls of a session, when it closes. */ + forget(sessionId: string): void { + for (const key of this.calls.keys()) { + if (key.startsWith(`${sessionId} `)) this.calls.delete(key); + } + } + + /** Stores the entry as the most recent one, and forgets the oldest one past the limit. */ + private remember(key: string, call: { meta: Meta; named: boolean }): void { + this.calls.delete(key); + this.calls.set(key, call); + if (this.calls.size > TOOL_CALL_LIMIT) { + const oldest = this.calls.keys().next().value; + if (oldest !== undefined) this.calls.delete(oldest); + } + } +} + +function asRecord(value: unknown): Meta | undefined { + return value && typeof value === "object" && !Array.isArray(value) ? (value as Meta) : undefined; +}