← Commit history
Update 5 file(s)
5 files changed
+45−26
bridge/BRIDGE_VERSION+1−1@@ -1 +1 @@-0.1.33+0.1.34
bridge/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "native-browser", "displayName": "Adom Browser Extension",- "version": "0.1.33",+ "version": "0.1.34", "expectedExtensionVersion": "0.1.3", "description": "Drives the user's REAL signed-in Chrome/Edge via an installed extension (native-messaging transport). Mirrors the puppeteer bridge's verb surface as nbrowser_* but runs inside the actual logged-in profile, so cookies/SSO/saved-logins/captcha human-trust all work. The bridge binds an ephemeral loopback port (PORTS.md compliant) and writes a discovery file; the native-messaging host pumps stdio <-> this bridge; the extension never touches a TCP port.", "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.33",+ "version": "0.1.34", "private": true, "description": "adom-desktop bridge for the Adom native-browser extension (Chrome + Edge)", "main": "server.js",
bridge/server.js+38−19@@ -1554,29 +1554,48 @@ function dispatch(verb, args) { if (!exe) return resolve({ success: false, error: `${kp.browser} executable not found at a standard path` }); const extSt = adomExtStateForProfile(kp.browser, kp.profileDir); (async () => {- let pre = new Set();- try { pre = new Set((await chromeWindowsDetailed()).map((w) => w.hwnd)); } catch {}- adCommand('desktop', 'launch_process', { path: exe, args: [`--profile-directory=${kp.profileDir}`, '--new-window', url] });- // find the new hwnd (diff, like open_window)- let hwnd = null; const t0 = Date.now();- while (!hwnd && Date.now() - t0 < 8000) {- await new Promise((r) => setTimeout(r, 500));- try { const list = await chromeWindowsDetailed(); hwnd = list.map((w) => w.hwnd).find((h) => !pre.has(h)) || null; } catch {}- }- let minimized = false, flashed = false;- if (hwnd && a.foreground !== true) {- // BACKGROUND: post-launch minimize (returns focus to whatever the user had) + orange flash so- // the user knows exactly which taskbar button to click when they are ready to do their part.+ let hwnd = null, minimized = false, flashed = false;+ if (a.foreground !== true) {+ // BACKGROUND with a near-zero blip: one LAPTOP-SIDE script does snapshot -> launch -> watch at+ // 30ms resolution -> minimize the new window the instant it exists (often before first paint).+ // v1 orchestrated launch + demote from the bridge as two round-trips = a visible ~200ms flash+ // of the window; doing it all in-process on the laptop shrinks that to imperceptible.+ const argStr = `--profile-directory=\"${kp.profileDir}\" --new-window \"${url.replace(/"/g, '')}\"`; const psBody = [ 'Add-Type @"',- 'using System;using System.Runtime.InteropServices;',- 'public class SWM { [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr h, int c); }',+ 'using System;using System.Text;using System.Collections.Generic;using System.Runtime.InteropServices;',+ 'public class WWatch {',+ ' [DllImport("user32.dll")] static extern bool EnumWindows(Func<IntPtr,IntPtr,bool> cb, IntPtr l);',+ ' [DllImport("user32.dll")] static extern int GetClassName(IntPtr h, StringBuilder sb, int max);',+ ' [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr h, int c);',+ ' public static List<long> Browsers() { var o = new List<long>(); EnumWindows((h, l) => { var sb = new StringBuilder(64); GetClassName(h, sb, 64); if (sb.ToString().StartsWith("Chrome_WidgetWin")) o.Add((long)h); return true; }, IntPtr.Zero); return o; }',+ '}', '"@',- `[SWM]::ShowWindow([IntPtr]${hwnd},6)`,+ '$pre = [WWatch]::Browsers()',+ `Start-Process -FilePath "${exe}" -ArgumentList '${argStr}'`,+ '$deadline = (Get-Date).AddSeconds(10)',+ '$found = 0',+ 'while ((Get-Date) -lt $deadline) {',+ ' $now = [WWatch]::Browsers()',+ ' foreach ($h in $now) { if ($pre -notcontains $h) { [WWatch]::ShowWindow([IntPtr]$h, 6) | Out-Null; $found = $h; break } }',+ ' if ($found -ne 0) { break }',+ ' Start-Sleep -Milliseconds 30',+ '}',+ 'Write-Output ("HWND=" + $found)', ].join(String.fromCharCode(13, 10));- const rr = await adCommand(null, 'run_script', { interpreter: 'powershell', body: psBody, timeoutSeconds: 15 });- minimized = !!(rr && rr.body && (rr.body.success === true || rr.body.ok === true));- try { await taskbar(hwnd, { flash: 'until_focused' }); flashed = true; } catch {}+ const rr = await adCommand(null, 'run_script', { interpreter: 'powershell', body: psBody, timeoutSeconds: 25 });+ const m = String((rr && rr.body && rr.body.stdout) || '').match(/HWND=(\d+)/);+ if (m && m[1] !== '0') { hwnd = Number(m[1]); minimized = true; }+ if (hwnd) { try { await taskbar(hwnd, { flash: 'until_focused' }); flashed = true; } catch {} }+ } else {+ let pre = new Set();+ try { pre = new Set((await chromeWindowsDetailed()).map((w) => w.hwnd)); } catch {}+ adCommand('desktop', 'launch_process', { path: exe, args: [`--profile-directory=${kp.profileDir}`, '--new-window', url] });+ const t0 = Date.now();+ while (!hwnd && Date.now() - t0 < 8000) {+ await new Promise((r) => setTimeout(r, 500));+ try { const list = await chromeWindowsDetailed(); hwnd = list.map((w) => w.hwnd).find((h) => !pre.has(h)) || null; } catch {}+ } } logActivity({ verb: 'nbrowser_open_os_window', sessionId: a.sessionId, thread: a.thread, profile: kp.key, ok: !!hwnd, errorCode: hwnd ? null : 'hwnd_not_found' }); 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();
native-browser-bridge-manifest.json+4−4@@ -1,8 +1,8 @@ { "manifest_version": 1,- "version": "0.1.33",- "url": "https://wiki.adom.inc/download/adom/adom-browser-extension/0.1.33/native-browser-bridge-v0.1.33.zip",- "sha256": "5659d68fe707bebbfe350298117df10611cbf1bdbe42c15b2b35b473ed9ef285",- "size": 84376,+ "version": "0.1.34",+ "url": "https://wiki.adom.inc/download/adom/adom-browser-extension/0.1.34/native-browser-bridge-v0.1.34.zip",+ "sha256": "cbd288d4befd58258f27bfb940eb949e1ed09974724c11b7912c16220c57d1cf",+ "size": 85094, "released_at": "2026-07-19T00:00:00Z" }