← Commit history
0.3.3: state reports only YOUR live sessions (was listing other threads' + dead ones); all:true to inspect
5 files changed
+27−15
bridge/BRIDGE_VERSION+1−1@@ -1 +1 @@-0.3.2+0.3.3
bridge/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "native-browser", "displayName": "Adom Native Browser",- "version": "0.3.2",+ "version": "0.3.3", "expectedExtensionVersion": "0.2.0", "description": "Drives the user's REAL signed-in Chrome/Edge, in two layers. Layer 1 (nb) needs NOTHING installed and works on any machine: nbrowser_open_os_window (open a URL in the user's real profile, background+flashing, the OAuth/consent path), nbrowser_os_windows, nbrowser_profiles, nbrowser_wake_profile, nbrowser_force_close. Layer 2 (nbe, the Adom Native Browser Extension) unlocks the rest: CDP driving (navigate/click/read/screenshot) inside their logged-in profile. The bridge binds an ephemeral loopback port and the native-messaging host pumps stdio <-> bridge.", "homepage": "https://wiki.adom.inc/adom/nb-bridge",
bridge/package.json+1−1@@ -1,6 +1,6 @@ { "name": "adom-native-browser-bridge",- "version": "0.3.2",+ "version": "0.3.3", "private": true, "description": "Native-browser bridge for Bridge (ab): layer 1 (nb) plus layer 2 via nbe, the Adom Native Browser Extension (Chrome + Edge).", "main": "server.js",
bridge/server.js+19−7@@ -1857,20 +1857,31 @@ function dispatch(verb, args) { const sa = args || {}; guarded(resolve, 'nbrowser_state', async () => { const want = sa.sessionId;- const mine = [...new Set([...sessionHwnd.keys(), ...sessionProfile.keys(), ...sessionThread.keys()])]- .filter((sid) => !want || sid === want);+ // OWNERSHIP: the bridge tracks every session ANY thread registered (they persist across+ // restarts). Reporting them all told this caller it was "driving" nine windows, most dead and+ // several belonging to other AI threads (amex-benefits, aa-flight-check, ah-kimi-auth...).+ // Default view = sessions THIS thread registered that still have a live window. all:true shows+ // every tracked session (with owner + alive flags) for debugging a shared desktop.+ const me = (() => { try { const c = callerLabel(); return c && (c.thread || c); } catch { return null; } })(); let live = []; try { const w = await callSelf('nbrowser_list_windows', { mine: true }); live = (w.windows || w.sessions || []).filter((r) => r && r.sessionId && r.owner !== 'user'); } catch {}- const sessions = mine.map((sid) => {+ const liveIds = new Set(live.map((r) => r.sessionId));+ const tracked = [...new Set([...sessionHwnd.keys(), ...sessionProfile.keys(), ...sessionThread.keys()])];+ const rows = tracked.map((sid) => { const r = live.find((x) => x.sessionId === sid) || {};+ const thread = sessionThread.get(sid) || null; return { sessionId: sid, hwnd: sessionHwnd.get(sid) || r.hwnd || null, windowId: r.windowId ?? null, tabId: r.tabId ?? r.activeTabId ?? null, url: r.url || null, title: r.title || null,- profile: sessionProfile.get(sid) || r.profile || null, thread: sessionThread.get(sid) || null,- purpose: sessionPurpose.get(sid) || null, osOpened: osOpened.has(sid) };+ profile: sessionProfile.get(sid) || r.profile || null, thread, purpose: sessionPurpose.get(sid) || null,+ osOpened: osOpened.has(sid), alive: liveIds.has(sid) || !!sessionHwnd.get(sid),+ yours: !me || !thread || thread === me }; });+ const sessions = (sa.all === true ? rows : rows.filter((r) => r.alive && r.yours))+ .filter((r) => !want || r.sessionId === want);+ const hidden = rows.length - sessions.length; let shot = null; const shotSid = want || (sessions[0] && sessions[0].sessionId); if (sa.screenshot && shotSid) {@@ -1878,9 +1889,10 @@ function dispatch(verb, args) { if (s && s.base64) shot = { sessionId: shotSid, base64: s.base64, width: s.width, height: s.height }; } resolve({ success: true, output: JSON.stringify({ ok: true, count: sessions.length, sessions, screenshot: shot,+ hiddenCount: hidden, _hint: sessions.length- ? `The EXACT windows THIS bridge opened - hwnd is authoritative, so never match a browser window by TITLE (a title is the active tab, it changes while loading, and several windows share substrings - that is what broke the web-control demo, issue #22). The user's OWN windows are deliberately excluded (nbrowser_os_windows shows every browser window on the machine, with ownership attribution). screenshot:true returns the page bitmap inline in this same call.`- : 'This bridge is driving NO windows right now. Open one with nbrowser_open_window {sessionId, thread, purpose, profile, url} - it returns the hwnd + tabId of exactly that window.' }) });+ ? `The EXACT windows THIS bridge opened for YOU${hidden ? ` (${hidden} other/dead session(s) hidden - pass all:true to see every tracked session with owner + alive flags)` : ''} - hwnd is authoritative, so never match a browser window by TITLE (a title is the active tab, it changes while loading, and several windows share substrings - that is what broke the web-control demo, issue #22). The user's OWN windows are deliberately excluded (nbrowser_os_windows shows every browser window on the machine, with ownership attribution). screenshot:true returns the page bitmap inline in this same call.`+ : `This bridge is driving NO live windows for you right now${hidden ? ` (${hidden} tracked session(s) belong to other threads or are dead - all:true to inspect)` : ''}. Open one with nbrowser_open_window {sessionId, thread, purpose, profile, url} - it returns the hwnd + tabId of exactly that window.` }) }); }); return; }
native-browser-bridge-manifest.json+5−5@@ -1,8 +1,8 @@ { "manifest_version": 1,- "version": "0.3.2",- "url": "https://wiki.adom.inc/download/adom/nb-bridge/0.3.2/native-browser-bridge-v0.3.2.zip",- "sha256": "1e4c38dc7a08130301db381609f62f9415efeeb064589be65756dfa3275be372",- "size": 106310,- "released_at": "2026-08-19T08:20:40Z"+ "version": "0.3.3",+ "url": "https://wiki.adom.inc/download/adom/nb-bridge/0.3.3/native-browser-bridge-v0.3.3.zip",+ "sha256": "f5093fba6e21a23392d10dac1716bb0702d77f1efacceca604243befd80c902e",+ "size": 106751,+ "released_at": "2026-08-19T08:23:02Z" }