fix(daemon): report a connected extension that cannot run commands - #319
Merged
Merged
Conversation
Fail in-flight calls when a browser generation is replaced, mark a silent heartbeat interval as unresponsive without dropping the socket, and allow one handshake grace after a pong.
…sive mark Terminate a socket's pending calls when it is replaced or closed, and register and send under the same lock so no call can reach an abandoned socket. A call that was already dispatched keeps its unknown-outcome contract in every wait stage, including tab borrow. Session start is no longer retried. Only mark heartbeat-capable extensions unresponsive, after two missed heartbeats, and never let the mark replace a cleanup failure. The handshake pong grace moves to a separate change. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Calls that fail because the extension's socket closed now carry `reason: extension_disconnected`, so the CLI no longer tells the user to check protocol versions. Native input keeps its unknown-outcome reason. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A browser can show as connected in the extension popup,
bsk doctor, andbsk browserswhile session start and tool calls wait until they time out. Reconnecting replaces the daemon registration but leaves calls on the old socket blocked. A socket that stays open and stops sending frames also stays registered until the existing liveness window, about 60 seconds. A browser process can answer a WebSocket ping before its service worker sendssystem.handshake; those connections are dropped after 5 seconds.Change
Replacing a registration now fails that socket's in-flight calls immediately. Session start retries once on the new connection. If that connection is replaced too, the call reports that the extension is reconnecting and does not retry again. Tool calls are not retried. Clicks, key presses, wheel input, uploads, and downloads keep an unknown outcome, so a caller does not repeat a side effect that may already have reached the page. A disconnect that does not install a newer generation is unchanged.
A timed-out call marks the browser unresponsive only when no inbound frame has arrived for one heartbeat interval, 20 seconds. The registry entry and its other sessions stay. Later commands fail immediately with the same reason until any inbound frame clears the mark. Removal is still the existing liveness reaper. A shorter timeout does not mark the browser when a frame arrived inside that interval.
After upgrade the daemon sends one ping. A pong without a handshake extends the first-frame wait once, by 10 seconds. If neither a pong nor a handshake arrives, the connection still drops at 5 seconds. Ping and pong are not accepted as the handshake.
bsk doctorreports a warning and still exits successfully.bsk browsersnames each unresponsive browser. The popup is unchanged, because a frozen service worker cannot repaint it. There is no new error code. Existing codes carryextension_reconnected,extension_reconnecting, orextension_unresponsive.BrowserStatusEntry.unresponsivedefaults to false, so older status payloads still decode.Related: #294
Validation
cargo test -p bsk-protocol: 156 passed.cargo test -p bsk --lib: passed, including replacement, the single session-start retry, the 20-second silence threshold, handshake grace, and the CLI reason text.crates/bsk-cliintegration test target passed. Oneauto_spawncase timed out under parallel load and passed when run alone.cargo fmt --all -- --checkandcargo clippy --workspace --all-targets --locked -- -D warningspassed.