mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 04:30:59 +00:00
After a cancel, the output of a background subagent that the cancel did not stop now reaches the client: its tool results, its new tool calls, and its permission requests. ## The bug The adapter has one rule for work that a cancel does not stop, as agentclientprotocol/agent-client-protocol#2308 asks: a background subagent that still runs (`runsInBackground`). The closing at the cancel leaves that subagent's tool calls open for their results (`closedAtCancel`). But the window after the cancel dropped the same subagent's output, results included: - **A subagent that completes after the cancel** kept its calls open. Its commands' results came after the cancel was reported and were dropped, and since it was not stopped, nothing closed them. - **A subagent that runs on** after the cancel showed nothing more: new tool calls were dropped, and its permission requests were denied as the stopped work's (#1334). Claude Code currently stops background subagents at an interrupt, as live runs show, so today this applies only to the output that comes before the SDK reports a subagent's end. It decides the rest once Claude Code lets them run. ## The fix `isRunningBackgroundSubagentOutput` uses the closing's predicate for the three places the window applies: - the drop of streamed output; - the record that `canUseTool` and the v2 preview hook read (#1334); - the guard of the user/assistant messages. A subagent's output after the SDK reported its end is still dropped, and #1336 closes its calls. ## Evidence **Tests** (`src/tests/incomplete-tools.test.ts`): - **A command's own result,** for a subagent that completes after the cancel, reaches the client, for a held turn and with no turn. This replaces "leaves the command of a subagent that completed after the cancel as it is", whose fixture sent no result at all. - **New work after the cancel was reported:** a command's streamed start, complete message and result reach the client. - **Permission requests after the cancel:** they are allowed, for a tool use that streamed first and for one that only its complete message holds. - **Unchanged:** a stopped subagent's late result is still dropped, and its call closed. - **Mutation checks:** removing each of the three uses, or widening the predicate to every subagent, fails at least one test. **Live, Claude Code 2.1.296,** a v1 cancel of a turn held for a background subagent that runs a command, on a plain client and an RFD client: Claude Code stopped the subagent, and its command was closed after the cancelled response, as on `main`. No schema violations. A subagent that survives a cancel cannot be set up live today. `npm run check`, build and the full suite (2983 tests) pass, with no golden changes. ## Not covered - **A foreground subagent nested in a background one:** its own Agent call is not backgrounded, so the closing closes its calls at the cancel, and the window drops its output, both as before. The two stay consistent.