fix: auto-restart stale daemon and improve connection error messages#1028
Merged
fix: auto-restart stale daemon and improve connection error messages#1028
Conversation
When daemon is running but extension never connected (stale daemon started before extension was installed), the CLI now auto-restarts the daemon to give the extension a fresh WebSocket endpoint, instead of just waiting and then telling the user to install the extension. Also improves error messages across cli.ts, bridge.ts, and doctor.ts to suggest "opencli daemon stop && opencli doctor" as the quick fix, since that's what actually resolves the issue.
- Daemon /status now includes `daemonVersion` field - bridge.ts: when daemon is running but extension not connected, checks daemonVersion vs CLI version. Only auto-restarts if version mismatch (stale daemon from older CLI). Same-version daemon shows improved error message with "opencli daemon stop && opencli doctor" hint. - doctor.ts: explicitly identifies stale daemon (version mismatch) in diagnostics report, shows daemon version in status line - cli.ts: error message changed to suggest "opencli daemon stop && opencli doctor"
…pawn - Missing daemonVersion (pre-version daemon) is now treated as stale, covering the most common user scenario (old daemon without version field) - After requestDaemonShutdown(), poll until daemon actually stops (port released) before spawning new one, with 3s timeout - If shutdown request fails, log warning instead of silently proceeding - doctor.ts also treats missing daemonVersion as stale with clear message
- If shutdown request fails or port isn't released within 3s, throw 'Stale daemon could not be replaced' instead of blindly spawning on an occupied port - Add tests for all three stale-daemon branches: same-version (no restart), missing daemonVersion (stale), mismatched version (stale)
… matching
browserAction() now checks `instanceof BrowserConnectError` first and
renders both message and hint, instead of string-matching on message
content. This ensures stale daemon errors ("Stale daemon could not be
replaced") surface the actionable hint to the user.
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.
Summary
Fixes the issue where a stale daemon (started before extension was installed) causes persistent "Browser not connected" errors that users can't resolve without discovering
opencli daemon stopon their own.bridge.tsnow auto-restarts the daemon when extension doesn't connect within the timeout, instead of just giving up. This gives the extension a fresh WebSocket endpoint to connect to.cli.ts,bridge.ts,doctor.ts) now suggestopencli daemon stop && opencli doctoras the quick fix, instead of only saying "install the extension" or "run opencli doctor".Root cause
The daemon is passive — it waits for the extension to connect via WebSocket at
/ext. If the daemon starts before the extension is installed, and the extension's reconnection attempts fail (e.g., due to MV3 service worker suspension timing), the connection is never established. The old behavior was to wait 10s then tell the user to install the extension (which they already had).Test plan