← Commit history

0.3.6: demo bounded (never hangs) + skips a pointless 2.4s pre-close

John Lauer ·38c5aa35a9 ·2mo ago ·parent 19781c3
5 files changed +19−11
bridge/BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.3.5+0.3.6
bridge/bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "native-browser",   "displayName": "Adom Native Browser",-  "version": "0.3.5",+  "version": "0.3.6",   "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.5",+  "version": "0.3.6",   "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+11−3
@@ -1932,15 +1932,23 @@ function dispatch(verb, args) {         let profile = da.profile;         if (!profile) { const ps = await callSelf('nbrowser_profiles'); const live = (ps.profiles || []).find((p) => p.live && p.email) || (ps.profiles || []).find((p) => p.email); profile = live && live.profile; steps.push({ step: 'resolve profile', ok: !!profile, profile }); }         if (!profile) return resolve({ success: false, error: 'no drivable profile found', _hint: 'Run nbrowser_readiness: if state is needs-extension, offer the nbe install (installing-the-extension).', steps });-        await callSelf('nbrowser_close_window', { sessionId: sid });               // idempotent re-run+        // idempotent re-run, but only if we actually track it: close_window on an unknown session costs+        // ~2.4s to tell us it is unknown, and a showcase verb should not pay that on every call.+        if (sessionHwnd.has(sid) || sessionProfile.has(sid)) await callSelf('nbrowser_close_window', { sessionId: sid });         const open = await callSelf('nbrowser_open_window', { sessionId: sid, thread: da.thread || 'nbrowser_demo', purpose: 'nb demo: show the AI driving the real signed-in browser', profile, url });         steps.push({ step: 'open in real browser (background)', ok: open.ok === true, hwnd: open.hwnd, tabId: open.tabId });         if (open.ok !== true) return resolve({ success: false, error: open.error || 'open failed', steps });         await new Promise((r) => setTimeout(r, 1200));-        const shot = await callSelf('nbrowser_screenshot', { sessionId: sid });-        steps.push({ step: 'screenshot the exact window', ok: !!shot.base64, bytes: shot.sizeKB });+        // BOUND the capture: a page still loading (or a window that died) must degrade to "opened, no+        // shot" rather than hanging the caller past its CLI timeout with nothing to show.+        const shot = await Promise.race([+          callSelf('nbrowser_screenshot', { sessionId: sid }),+          new Promise((r) => setTimeout(() => r({ __timeout: true }), Math.min(Number(da.screenshotTimeoutMs) || 12000, 25000))),+        ]);+        steps.push({ step: 'screenshot the exact window', ok: !!shot.base64, bytes: shot.sizeKB, timedOut: !!shot.__timeout });         resolve({ success: true, output: JSON.stringify({ ok: true, sessionId: sid, profile, url, hwnd: open.hwnd || null, tabId: open.tabId || null,           base64: shot.base64 || null, width: shot.width, height: shot.height, steps,+          screenshotError: shot.base64 ? null : (shot.__timeout ? 'capture timed out - the window IS open (see hwnd); retry nbrowser_screenshot {sessionId} once it finishes loading' : (shot.error || null)),           _hint: `Opened ${url} in the user's REAL signed-in browser (profile ${profile}) in the BACKGROUND, badged as AI-driven, and captured that EXACT window - no title matching anywhere. Render base64 inline. Clean up with nbrowser_close_window {sessionId:"${sid}"} when the demo is done.`,           _next: 'nbrowser_close_window' }) });       });
native-browser-bridge-manifest.json+5−5
@@ -1,8 +1,8 @@ {   "manifest_version": 1,-  "version": "0.3.5",-  "url": "https://wiki.adom.inc/download/adom/nb-bridge/0.3.5/native-browser-bridge-v0.3.5.zip",-  "sha256": "65ebfd4ab939f918ba1dacc894a1b73e62575a709a2d68216c64a267ba6ffc55",-  "size": 107771,-  "released_at": "2026-08-19T08:49:54Z"+  "version": "0.3.6",+  "url": "https://wiki.adom.inc/download/adom/nb-bridge/0.3.6/native-browser-bridge-v0.3.6.zip",+  "sha256": "b91738dcddd78af2df12ee32da172676bab9c6b1b3d734b050682654f8c90bcf",+  "size": 108026,+  "released_at": "2026-08-19T08:53:31Z" }