From 02fac67f52eaa7011c357c48b4ca5b935bd1620f Mon Sep 17 00:00:00 2001 From: Agus Zubiaga Date: Tue, 2 Sep 2025 11:53:54 -0300 Subject: [PATCH] Do not send tool_call_update for `TodoWrite` (#10) When we receive a `TodoWrite` tool use, we send a plan update instead of a tool call. However, we were still trying to send a tool call update when we received the `TodoWrite` tool result, which caused an ACP error. Co-authored-by: Bennet Bo Fenner --- src/acp-agent.ts | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/acp-agent.ts b/src/acp-agent.ts index c807481e..2600ae61 100644 --- a/src/acp-agent.ts +++ b/src/acp-agent.ts @@ -440,14 +440,16 @@ function promptToClaude(prompt: PromptRequest): SDKUserMessage { export function toAcpNotifications( message: SDKAssistantMessage | SDKUserMessage, sessionId: string, - toolUseCache: { [key: string]: any }, + toolUseCache: { + [key: string]: { type: "tool_use"; id: string; name: string; input: any }; + }, fileContentCache: { [key: string]: string }, ): SessionNotification[] { let chunks = message.message.content as ContentChunk[]; let output = []; // Only handle the first chunk for streaming; extend as needed for batching for (const chunk of chunks) { - let update: SessionNotification["update"]; + let update: SessionNotification["update"] | null = null; switch (chunk.type) { case "text": update = { @@ -497,19 +499,32 @@ export function toAcpNotifications( } break; - case "tool_result": - update = { - toolCallId: chunk.tool_use_id, - sessionUpdate: "tool_call_update", - status: chunk.is_error ? "failed" : "completed", - ...toolUpdateFromToolResult(chunk, toolUseCache[chunk.tool_use_id]), - }; + case "tool_result": { + const toolUse = toolUseCache[chunk.tool_use_id]; + if (!toolUse) { + console.error( + `[claude-code-acp] Got a tool result for tool use that wasn't tracked: ${chunk.tool_use_id}`, + ); + break; + } + + if (toolUse.name !== "TodoWrite") { + update = { + toolCallId: chunk.tool_use_id, + sessionUpdate: "tool_call_update", + status: chunk.is_error ? "failed" : "completed", + ...toolUpdateFromToolResult(chunk, toolUseCache[chunk.tool_use_id]), + }; + } break; + } default: throw new Error("unhandled chunk type: " + chunk.type); } - output.push({ sessionId, update }); + if (update) { + output.push({ sessionId, update }); + } } return output;