← Back to PRs

#13942: Fix: chrome-extension: make relay reconnect reliable with one tab

by gabepsilva open 2026-02-11 07:34 View on GitHub →
stale
## Summary - simplify browser extension recovery to a single reconnect candidate tab instead of per-tab queueing - detach existing debugger sessions on relay close and reconnect only the most recently attached tab - replace async interval retries with a serialized retry pass to avoid overlapping attach attempts and race conditions ## Test plan [V] restart gateway and confirm tab transitions to connecting and auto-recovers back to ON [V] attach extension to a tab and confirm badge shows ON [V] close the candidate tab during reconnect window and confirm retries stop cleanly [V] manual click attach/detach still works as expected ## Checklist **[Title]** Mark as AI-assisted in the PR title or description **[fully]** Note the degree of testing (untested / lightly tested / fully tested) **[included planning and files changed]** Include prompts or session logs if possible (super helpful!) **[I confirm]** Confirm you understand what the code does # Session Plan ``` ## Problem When the OpenClaw Gateway restarts (browser relay), the Chrome extension loses connection and goes into a "connecting" state (yellow `…` badge). Currently requires manual clicking the extension icon on each tab to re-attach. This is annoying during development when the gateway restarts frequently. ## Conversation Context **Date:** 2026-02-10 **User Question:** "Why not automate the relay attachment automatic?" **Finding:** Manual attachment is intentional security design, but auto-reconnect after transient failures is reasonable. From reviewing `background.js` and `extension-relay.ts`: ### What Happens on Restart 1. Gateway stops → WebSocket closes 2. `onRelayClosed()` fires → clears all tab attachments 3. Extension shows yellow `…` badge 4. **Gap:** No auto-retry for previously-attached tabs ### Why Not Fully Automatic (Security) - `chrome.debugger.attach()` grants CDP access (network intercept, JS execution) - Chrome requires user gesture per tab - Extension doesn't know if YOU want that specific tab re-attached **However:** Re-attaching previously-authorized tabs after transient disconnect is reasonable. --- ## Proposed Solution Add persistent attachment tracking with auto-reconnect: ### Changes to `background.js` 1. **Track attachment history:** // Store tab IDs that were attached before disconnect const recentlyDetached = new Map<number, {targetId: string, retryCount: number}>() 2. **On disconnect, queue for retry:** function onRelayClosed(reason) { // ... existing cleanup ... // Queue recently-attached tabs for auto-retry for (const [tabId, tab] of tabs.entries()) { if (tab.state === 'connected') { recentlyDetached.set(tabId, { targetId: tab.targetId, retryCount: 0 }) } } // Start auto-reconnect loop startAutoReconnect() } 3. **Auto-reconnect loop:** let autoReconnectTimer: number | null = null function startAutoReconnect() { if (autoReconnectTimer) return autoReconnectTimer = setInterval(async () => { // Check if relay is back try { await fetch(`http://127.0.0.1:${await getRelayPort()}/`, { method: 'HEAD', signal: AbortSignal.timeout(1000) }) } catch { return // Relay still down } // Try re-attaching queued tabs for (const [tabId, state] of recentlyDetached.entries()) { if (state.retryCount > 3) { recentlyDetached.delete(tabId) // Give up continue } try { await attachTab(tabId, { skipAttachedEvent: false }) recentlyDetached.delete(tabId) // Success } catch { state.retryCount++ } } if (recentlyDetached.size === 0) { clearInterval(autoReconnectTimer!) autoReconnectTimer = null } }, 2000) // Check every 2 seconds } ### Optional: Per-Tab Setting Add to `options.js`: // Allow users to disable auto-reconnect const settings = { autoReconnect: true, // Default: enabled maxRetries: 3, retryDelayMs: 2000 } --- ## Implementation Notes ### Files to Modify - `assets/chrome-extension/background.js` - Core logic - `assets/chrome-extension/options.js` - Settings UI - `assets/chrome-extension/options.html` - Toggle checkbox ### Security Considerations - Only re-attach tabs that were previously attached in this session - Don't auto-attach tabs that were never manually attached - Respect Chrome's debugger permission model (no bypass) - Clear retry queue on browser restart (don't persist) ### Edge Cases - Tab closed while retry queued → skip gracefully - Tab navigated to different URL → still re-attach (user intent) - Multiple tabs attached → retry all - Relay flapping (start/stop rapidly) → exponential backoff --- ## Tab Lifecycle & Authorization **Key Principle:** Authorization is **per tab instance**, not per URL or browser session. ```

Most Similar PRs