← Commit history
Update 5 file(s)
5 files changed
+36−8
bridge/BRIDGE_VERSION+1−1@@ -1 +1 @@-0.1.45+0.1.46
bridge/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "native-browser", "displayName": "Adom Browser Extension",- "version": "0.1.45",+ "version": "0.1.46", "expectedExtensionVersion": "0.1.3", "description": "Drives the user's REAL signed-in Chrome/Edge. MOST verbs require the Adom extension installed in that browser profile (CDP driving: navigate/click/read/screenshot). TWO verbs need NO extension at all and work on any machine: nbrowser_open_os_window (open a URL in the user's real profile, background+flashing - the OAuth/consent path) and nbrowser_os_windows (enumerate browser windows). Also extension-free: nbrowser_profiles, nbrowser_wake_profile, nbrowser_force_close. The bridge binds an ephemeral loopback port and the native-messaging host pumps stdio <-> bridge.", "homepage": "https://wiki.adom.inc/adom/adom-browser-extension",
bridge/package.json+1−1@@ -1,6 +1,6 @@ { "name": "adom-native-browser-bridge",- "version": "0.1.45",+ "version": "0.1.46", "private": true, "description": "adom-desktop bridge for the Adom native-browser extension (Chrome + Edge)", "main": "server.js",
bridge/server.js+29−1@@ -1689,11 +1689,20 @@ function dispatch(verb, args) { } } if (a.foreground === true) announceForeground(a.foregroundReason, a.sessionId);+ else if (!hwnd) {+ // BACKGROUND WAS REQUESTED BUT COULD NOT BE HONORED: no new window was created (the browser+ // grouped the page into an existing one), so there is nothing to minimize and the page lands+ // in front of the user. Tell them what appeared and why - John, 2026-07-22: a sign-in page+ // showing up unannounced is the failure, whether or not the AI asked for foreground.+ announceForeground(`opened ${(() => { try { return new URL(url).hostname; } catch { return 'a page'; } })()} in your browser${a.purpose ? ' - ' + String(a.purpose).slice(0, 90) : ''}`, a.sessionId);+ } // LAYER-1 BADGE (hollow): mark the window Adom OPENED even though it cannot drive it - provenance // matters most on an OAuth consent page. Uses applyBadge so the normal 3-min idle expiry restores // the native avatar; nothing lingers. if (hwnd) applyBadge(a.sessionId, hwnd, kp.key, 'hollow');- logActivity({ verb: 'nbrowser_open_os_window', sessionId: a.sessionId, thread: a.thread, profile: kp.key, ok: !!hwnd, errorCode: hwnd ? null : 'hwnd_not_found' });+ logActivity({ verb: 'nbrowser_open_os_window', sessionId: a.sessionId, thread: a.thread, profile: kp.key, ok: true,+ ops: `fg=${a.foreground === true}·hwndResolved=${!!hwnd}·minimized=${minimized}`, hwnd: hwnd || undefined,+ errorCode: hwnd ? null : 'grouped_into_existing_window' }); sessionThread.set(a.sessionId, a.thread); sessionPurpose.set(a.sessionId, a.purpose); sessionProfile.set(a.sessionId, kp.key); if (hwnd) sessionHwnd.set(a.sessionId, hwnd); osOpened.add(a.sessionId); persistSessions(); const upsell = extSt && extSt.installed ? `NOTE: the Adom extension IS installed in this profile${extSt.enabled ? '' : ' (but DISABLED)'} - you could have FULL control instead: nbrowser_wake_profile then nbrowser_open_window gives you navigation, reading, clicking, screenshots, and ownership guards. Prefer that path.`@@ -2352,4 +2361,23 @@ async function resetStaleBadgesOnStartup(attempt = 0) { if (hit && !seen.has(w.hwnd)) { seen.add(w.hwnd); nativeOverlay(w.hwnd, hit.key); } } }+// ── REAP USER-CLOSED WINDOWS (John, 2026-07-22): "if a user closes the ai created nb window, you should+// detect that and remove your overlay icon." A closed window's taskbar button disappears with it, but the+// BRIDGE would still think it owns that hwnd - it would keep arming idle timers, re-painting a dead+// window, and reporting it in nbrowser_owned. Poll the live browser-window set and forget what is gone.+async function reapClosedWindows() {+ if (!sessionHwnd.size && !spawnHwnd.size) return;+ let live;+ try { live = new Set((await chromeWindowsDetailed()).map((w) => w.hwnd)); } catch { return; }+ if (!live.size) return; // AD blind - never reap on no data+ let reaped = 0;+ for (const [sid, h] of [...sessionHwnd]) {+ if (live.has(h)) continue;+ sessionHwnd.delete(sid); clearBadge(sid); osOpened.delete(sid); reaped++;+ logActivity({ verb: '_window_reaped', sessionId: sid, thread: sessionThread.get(sid) || null, profile: sessionProfile.get(sid) || null, hwnd: h, ops: 'closed_by_user', ok: true, internal: true });+ }+ for (const [wid, h] of [...spawnHwnd]) { if (!live.has(h)) { spawnHwnd.delete(wid); reaped++; } }+ if (reaped) persistSessions();+}+setInterval(() => { reapClosedWindows().catch(() => {}); }, 30000).unref(); setTimeout(() => resetStaleBadgesOnStartup(), 4000);
native-browser-bridge-manifest.json+4−4@@ -1,8 +1,8 @@ { "manifest_version": 1,- "version": "0.1.45",- "url": "https://wiki.adom.inc/download/adom/adom-browser-extension/0.1.45/native-browser-bridge-v0.1.45.zip",- "sha256": "123bfbecf98722eb394ae84a03fc5a2d8d2112bcb999cff19fe35a6cb8150fbe",- "size": 94856,+ "version": "0.1.46",+ "url": "https://wiki.adom.inc/download/adom/adom-browser-extension/0.1.46/native-browser-bridge-v0.1.46.zip",+ "sha256": "bd12662cad4b58d66d70e61fa78d1448203b6230ba8179043df05edce4b0d730",+ "size": 95531, "released_at": "2026-07-22T00:00:00Z" }