You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug: Multiple execute_command tool calls in single request only ask permission for first command
Description
When the AI sends multiple execute_command tool calls in a single request (e.g., 3 commands), Zoo Code processes them via a recursive loop (presentAssistantMessage.ts line 962). After the user approves the first command, all subsequent commands execute automatically without showing individual permission prompts.
User sees prompt for cmd1 only. After clicking approve, all 3 commands execute immediately without further prompts — even with auto-approve completely disabled.
Root Cause Analysis
Code Flow
In src/core/assistant-message/presentAssistantMessage.ts, tool calls from a single AI request are processed via a recursive sequential loop:
// Line 962 - Recursive loop processes each tool call sequentiallyreturnpresentAssistantMessage(cline)
Each execute_command tool call invokes askApproval("command", ...) which calls task.ask("tool", message) in Task.ts. The bug occurs because of two interacting mechanisms:
}elseif(isMessageQueued&&shouldDrainQueuedMessageForAsk){constmessage=this.messageQueueService.dequeueMessage()if(message){// For tool approvals, auto-dequeue and approve!if(type==="tool"||type==="command"||type==="use_mcp_server"){this.handleWebviewAskResponse("yesButtonClicked",message.text,message.images)}}}
Mechanism 2 — Shared Timestamp Check (Line 1374):
awaitpWaitFor(()=>{if(this.askResponse!==undefined||this.lastMessageTs!==askTs){returntrue// Skip waiting, use existing response}
...
})
Bug Flow
Command feat: support OAuth 2.1 for streamable-http MCP servers #1: askApproval("command", "echo \"cmd1\"") → displays prompt → user clicks approve → handleWebviewAskResponse("yesButtonClicked") sets this.askResponse = "yesButtonClicked"
All 3 commands execute immediately without further prompts
Expected behavior:
Show prompt for each command individually
Wait for user approval before executing each command
Affected Files
src/core/task/Task.ts — Line 1354-1368: Message queue auto-dequeue approves tool calls silently; Line 1374: Shared timestamp check may skip waiting
src/core/assistant-message/presentAssistantMessage.ts — Line 962: Recursive loop processes batch tool calls sequentially without per-call UI delay
src/core/tools/ExecuteCommandTool.ts — Line 109: Each call uses askApproval("command", canonicalCommand) but may not display prompt due to queue/state issues
Suggested Fix Directions
Option A: Prevent message queue auto-dequeue for tool calls within the same batch. Only dequeue when the user explicitly queues a follow-up action, not during rapid sequential iteration.
Option B: Add a per-tool-use-id approval cache so that each individual command in a batch gets its own prompt and approval state, rather than relying on global askResponse.
Option C: Introduce a small delay or UI lock between tool calls in the same batch to ensure each prompt is displayed before the next iteration begins.
Bug: Multiple execute_command tool calls in single request only ask permission for first command
Description
When the AI sends multiple
execute_commandtool calls in a single request (e.g., 3 commands), Zoo Code processes them via a recursive loop (presentAssistantMessage.tsline 962). After the user approves the first command, all subsequent commands execute automatically without showing individual permission prompts.This means if AI sends:
[ {"tool": "execute_command", "command": "echo \"cmd1\""}, {"tool": "execute_command", "command": "echo \"cmd2\""}, {"tool": "execute_command", "command": "echo \"cmd3\""} ]User sees prompt for
cmd1only. After clicking approve, all 3 commands execute immediately without further prompts — even with auto-approve completely disabled.Root Cause Analysis
Code Flow
In
src/core/assistant-message/presentAssistantMessage.ts, tool calls from a single AI request are processed via a recursive sequential loop:Each
execute_commandtool call invokesaskApproval("command", ...)which callstask.ask("tool", message)inTask.ts. The bug occurs because of two interacting mechanisms:Mechanism 1 — Message Queue Auto-Approve (Line 1354-1368):
Mechanism 2 — Shared Timestamp Check (Line 1374):
Bug Flow
Command feat: support OAuth 2.1 for streamable-http MCP servers #1:
askApproval("command", "echo \"cmd1\"")→ displays prompt → user clicks approve →handleWebviewAskResponse("yesButtonClicked")setsthis.askResponse = "yesButtonClicked"Loop continues to command Roo to zoo upgrade #2 (line 962):
Command Roo to zoo upgrade #2:
askApproval("command", "echo \"cmd2\"")→task.ask("tool", message)→ line 1256 resetsthis.askResponse = undefined→ BUT:"yesButtonClicked"— no prompt shown to user.lastMessageTs !== askTscheck may pass if timestamps are too close together, causing the wait to be skipped entirely.Result: Command Roo to zoo upgrade #2 (and all subsequent commands) return
"yesButtonClicked"without showing any prompt to user.Key Suspects
messageQueueServiceauto-dequeue behavior (Task.tsline 1354-1368): Queued messages from rapid loop iteration are auto-approved for command tool callsaskResponseglobal state: Shared across batch command tool calls, causing approval state to leak between iterationsExample
Input: AI sends 3x
execute_commandin one request[ {"tool": "execute_command", "command": "echo \"cmd1\""}, {"tool": "execute_command", "command": "echo \"cmd2\""}, {"tool": "execute_command", "command": "echo \"cmd3\""} ]Current behavior:
echo "cmd1"onlyExpected behavior:
Affected Files
src/core/task/Task.ts— Line 1354-1368: Message queue auto-dequeue approves tool calls silently; Line 1374: Shared timestamp check may skip waitingsrc/core/assistant-message/presentAssistantMessage.ts— Line 962: Recursive loop processes batch tool calls sequentially without per-call UI delaysrc/core/tools/ExecuteCommandTool.ts— Line 109: Each call usesaskApproval("command", canonicalCommand)but may not display prompt due to queue/state issuesSuggested Fix Directions
Option A: Prevent message queue auto-dequeue for tool calls within the same batch. Only dequeue when the user explicitly queues a follow-up action, not during rapid sequential iteration.
Option B: Add a per-tool-use-id approval cache so that each individual command in a batch gets its own prompt and approval state, rather than relying on global
askResponse.Option C: Introduce a small delay or UI lock between tool calls in the same batch to ensure each prompt is displayed before the next iteration begins.