← Back to PRs

#22571: fix(browser): complete extension relay handshake on connect.challenge

by pandego open 2026-02-21 09:29 View on GitHub →
channel: msteams size: S
## Summary Fixes Chrome extension relay sessions getting stuck at badge `…` by implementing the required gateway handshake flow in the bundled extension background worker. Closes #22553 ## Root cause Gateway now emits a pre-connect `connect.challenge` event. The extension websocket client did not handle that event and never sent a `connect` request, so the relay session never became authenticated/ready. ## What changed - Handle `type=event,event=connect.challenge` in `assets/chrome-extension/background.js` - Send a proper gateway `connect` request from the extension with token auth and client metadata - Wait for successful `connect` response before considering relay setup complete - Ensure message listener is bound early so the first challenge frame cannot be missed - Cleanly reject pending handshake promise on disconnect/timeouts ## Validation - `node --check assets/chrome-extension/background.js` ## AI assistance AI-assisted; change reviewed and validated locally. <!-- greptile_comment --> <h3>Greptile Summary</h3> Implemented the required gateway handshake flow to fix Chrome extension relay sessions getting stuck at the connecting badge (`…`). The extension now properly handles the `connect.challenge` event sent by the gateway server and responds with a `connect` request containing authentication credentials and client metadata. The message handler is bound early (before WebSocket open) to prevent race conditions where the challenge could be missed, and the connection waits for successful handshake completion before proceeding with relay operations. - Added state variables to track handshake progress (`relayGatewayToken`, `relayConnectRequestId`, `relayConnectResolve/Reject`, `relayConnectTimer`, `relayChallengeSeen`) - Implemented `waitForGatewayConnect()` to create a promise-based handshake with 8-second timeout - Added `ensureGatewayHandshakeStarted()` to send the `connect` request with proper protocol parameters - Handle `connect.challenge` event and successful/failed `connect` responses in `onRelayMessage` - Clean up handshake state on disconnect/errors via `clearRelayConnectState()` - Bound `ws.onmessage` before the WebSocket opens to prevent missing the initial challenge event <h3>Confidence Score: 5/5</h3> - Safe to merge - addresses a critical bug with proper error handling and timeout protection - Implementation correctly follows the gateway protocol as documented and matches patterns from the TypeScript client. The handshake flow includes proper timeout handling (8s), early message binding to prevent race conditions, clean state management on errors/disconnects, and appropriate promise-based async flow. The fix directly addresses the reported issue and includes validation. - No files require special attention <sub>Last reviewed commit: 6d012ed</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs