fix(agents): cancel pending bundle LSP requests when the agent stops#104110
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 11, 2026, 10:00 AM ET / 14:00 UTC. Summary PR surface: Source +46, Tests +64. Total +110 across 2 files. Reproducibility: yes. at source level with high confidence. Current main does not consume the tool-call abort signal in its LSP request owner, and the PR provides matching real-process before-and-after protocol output. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Next step before merge
Security Review detailsBest possible solution: Land the exact-head request-scoped cancellation implementation after ordinary merge gating, keeping initialization, shutdown, late-response handling, and unrelated shared-session requests independent from a single tool abort. Do we have a high-confidence way to reproduce the issue? Yes, at source level with high confidence. Current main does not consume the tool-call abort signal in its LSP request owner, and the PR provides matching real-process before-and-after protocol output. Is this the best way to solve the issue? Yes. Handling cancellation at the pending JSON-RPC request owner is the narrowest maintainable solution because it settles local resources once, notifies conforming servers, ignores late responses, and preserves unrelated shared-session work. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against ba826be268a7. Label changesLabel justifications:
Evidence reviewedPR surface: Source +46, Tests +64. Total +110 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (4 earlier review cycles)
|
…rompt calls Forward the per-call AbortSignal from materialized bundle MCP tools down through SessionMcpRuntime and into the MCP SDK client request options. This lets agent cancellation stop pending MCP work instead of leaving it running after the caller has aborted, matching the LSP JSON-RPC cancel behavior in openclaw#104110. - Add optional signal parameters to SessionMcpRuntime request methods. - Pass signal through materializeBundleMcpToolsForRun execute factories. - Forward signal into client.callTool/listResources/readResource/listPrompts/getPrompt. - Add regression test verifying signal reaches each runtime method.
Co-authored-by: Vincent Koc <[email protected]>
What Problem This Solves
Fixes an issue where users who stopped an agent while a bundle-provided LSP hover, definition, or references tool was pending could still leave the language server working for up to the request timeout and receive a late tool result after the run had been cancelled.
Why This Change Was Made
Bundle LSP tools now pass their per-call abort signal into the JSON-RPC request owner. Aborting removes that request from the pending map, clears its timer and listener, rejects the tool promise, and sends the LSP-standard
$/cancelRequestnotification for the same request id. The shared language-server process is intentionally kept alive for other calls.User Impact
Stopping an agent now stops its pending bundle LSP tool calls promptly. The language server can cancel the corresponding work, late responses no longer resolve the cancelled tool call, and other tools can continue using the same server session.
Evidence
Reporter-provided pre-fix live proof used Claude bundle discovery,
.lsp.json, a real stdio child process, and Content-Length JSON-RPC framing. The aborted hover call did not send cancellation and resolved 602 ms after abort:{ "lspCancelRequestReceived": false, "settledWithin100msAfterAbort": false, "toolResolved": true, "settledAfterAbortMs": 602, "serverRespondedAfterAbort": true }Post-fix local E2E live proof drives the same production surfaces and also verifies the shared server handles another request after cancellation:
{ "realClaudeBundleLoaded": true, "materializedTool": "lsp_hover_prooflive", "runSignalAborted": true, "lspRequestReceivedBeforeAbort": true, "lspCancelRequestReceived": true, "settledWithin100msAfterAbort": true, "toolResolved": false, "settledAfterAbortMs": 1, "serverRespondedAfterAbort": true, "sharedSessionSurvived": true }Focused regression suite:
Additional checks:
oxfmt --checkpassed for both touched files.run-oxlint.mjspassed for both touched files.