mirror of
https://github.com/block/buzz.git
synced 2026-11-01 23:11:58 +00:00
The new cancel test caught two real bugs, both from breaking out of the select loop the moment the token fired. Dropping `stream` drops the futures goose is awaiting, so `mcp_client.rs:688` never reaches its `cancel_token.cancelled()` arm and never sends `notifications/cancelled`. Consequences: the MCP child keeps running its tool after the turn is over, and any announced `tool_call` never reaches a terminal state -- the desktop renders that as a spinner forever, which is the invariant buzz-agent held at agent.rs:470-477. Cancellation is cooperative, so treat it that way: keep polling the stream and let goose unwind (emit tool responses, send the MCP cancellations, end the stream), bounded by CANCEL_DRAIN_TIMEOUT = 5s. Track announced-minus-resolved tool call ids and synthesise terminal updates for any stragglers if the drain times out -- a wrong status beats a stuck spinner. 3 new tests: cancel mid-tool-call returns stopReason=cancelled with every tool call resolved and activeRunId cleared; notifications/cancelled actually reaches the MCP server (asserted via FAKE_MCP_CANCEL_LOG); cancel for an unknown session doesn't kill the process. 28 tests green, fmt + clippy -D warnings clean. Signed-off-by: Michael Neale <michael.neale@gmail.com>