← Commit history
bridge/BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.1.38\ No newline at end of file+0.1.39\ No newline at end of file
bridge/bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "native-browser",   "displayName": "Adom Browser Extension",-  "version": "0.1.38",+  "version": "0.1.39",   "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.38",+  "version": "0.1.39",   "private": true,   "description": "adom-desktop bridge for the Adom native-browser extension (Chrome + Edge)",   "main": "server.js",
bridge/server.js+7−14
@@ -1163,7 +1163,7 @@ const VERB_META = {   nbrowser_profiles: { hint: 'List every BROWSER x PROFILE you can drive + which is active. Each row carries browser (chrome|edge), email, displayName (the human label the user sees on the browser profile button, e.g. "John Personal" vs "adom.inc"), and profileDir. Pick work-vs-personal from the email DOMAIN + displayName, never from which window happens to be focused. Drive several in parallel with profile:"<key>".', related: ['nbrowser_use_profile', 'nbrowser_profile_block', 'nbrowser_resolve_profiles'], pitfalls: ['active is only the default when no profile is passed', 'an entry with unresolved:true has no email yet - nbrowser_resolve_profiles first, or you may drive the wrong account', 'the same email can live in Chrome AND Edge - match browser too', 'asleep:true = the profile exists (Local State) but has no open window so its extension is not running - it cannot be driven until the user opens a window in it; never claim a profile "does not exist" when it is merely asleep'] },   nbrowser_use_profile: { hint: 'Set the default profile that verbs target.', related: ['nbrowser_profiles', 'nbrowser_pin_session'], pitfalls: ['you can still override per-call with profile:"<email>"'] },   nbrowser_pin_session: { hint: 'Pin a sessionId to a profile so EVERY verb carrying that sessionId auto-routes to it (no cross-profile mistakes when driving several accounts). open_window pins automatically to the profile it opened in; use this to re-pin explicitly.', related: ['nbrowser_profiles', 'nbrowser_resolve_profiles', 'nbrowser_open_window'], pitfalls: ['pins are per-session; a verb with an explicit profile: still overrides the pin', 'if the pinned profile goes offline, verbs fall back to the active profile'] },-  nbrowser_open_os_window: { hint: 'EXTENSION-FREE: open a URL in the user\'s REAL browser profile (Chrome or Edge) when ABE is not installed there - the graceful-degradation path for flows where the USER does the clicking, above all OAuth consent (adom-google, Autodesk APS: they are already signed in; they just click Approve). BACKGROUND by default: brief blip, then minimized + ORANGE flashing taskbar button = "come click when ready". Registration (sessionId+thread+purpose) required like every window.', related: ['nbrowser_profiles', 'nbrowser_os_windows', 'nbrowser_force_close', 'nbrowser_wake_profile'], pitfalls: ['you CANNOT read, drive, or screenshot this window - no extension in that profile; poll the outcome out-of-band (OAuth token poll) or ask the user', 'if the extension IS installed in the profile, prefer wake_profile + open_window (full control, guards, cleanup)', 'foreground:true needs foregroundReason (+ notify_user first) - background+flash is almost always right', 'HARD-REFUSES (live_profile, no override) if the target browser is hosting the user\'s workspace / a live AI session - launching into that shared process can restart the browser and kill the running windows; use a DIFFERENT profile, pup, or install ABE (in-process window creation, no restart risk)', 'close it afterwards with nbrowser_force_close {hwnd} - never leave auth litter', 'every response nudges the ABE install - relay the upsell to the user at a natural moment, never mid-auth'] },+  nbrowser_open_os_window: { hint: 'EXTENSION-FREE: open a URL in the user\'s REAL browser profile (Chrome or Edge) when ABE is not installed there - the graceful-degradation path for flows where the USER does the clicking, above all OAuth consent (adom-google, Autodesk APS: they are already signed in; they just click Approve). BACKGROUND by default: brief blip, then minimized + ORANGE flashing taskbar button = "come click when ready". Registration (sessionId+thread+purpose) required like every window.', related: ['nbrowser_profiles', 'nbrowser_os_windows', 'nbrowser_force_close', 'nbrowser_wake_profile'], pitfalls: ['you CANNOT read, drive, or screenshot this window - no extension in that profile; poll the outcome out-of-band (OAuth token poll) or ask the user', 'if the extension IS installed in the profile, prefer wake_profile + open_window (full control, guards, cleanup)', 'foreground:true needs foregroundReason (+ notify_user first) - background+flash is almost always right', 'the background MINIMIZE never touches the workspace/editor window or another thread\'s live session (they are excluded); a plain new window just adds to the running browser, it does not restart it', 'close it afterwards with nbrowser_force_close {hwnd} - never leave auth litter', 'every response nudges the ABE install - relay the upsell to the user at a natural moment, never mid-auth'] },   nbrowser_os_windows: { hint: 'OS-level browser-window inventory measured ON the laptop by the bridge: every Chrome/Edge/pup window (hwnd, title, rect, z) annotated with the ABE session that owns it. THE reliable probe when your own desktop_list_windows returns 0/null (wrong --target, AD hiccup) or when a profile has no extension (Edge) so list_windows cannot see it.', related: ['nbrowser_force_close', 'nbrowser_list_windows', 'nbrowser_profiles'], pitfalls: ['a window with abeSession set belongs to a LIVE thread - never force-close it', 'ok:false = the bridge\'s AD link is down, meaning "unknown", NOT "no windows"'] },   nbrowser_wake_profile: { hint: 'Wake an ASLEEP profile (exists in nbrowser_profiles with asleep:true but not drivable) WITHOUT opening any window: launches the browser with --no-startup-window so the profile + its extension load in background mode - nothing foregrounds, no focus is stolen. When it returns woke:true, drive normally.', related: ['nbrowser_profiles', 'nbrowser_open_window', 'nbrowser_resolve_profiles'], pitfalls: ['NEVER launch a foreground browser window to wake a profile - this verb exists so waking honors background-by-default', 'woke:false usually means the Adom extension is not installed in THAT profile (extensions are per-profile)'] },   nbrowser_resolve_profiles: { hint: 'Force every connected extension to re-resolve its Google email and re-announce, so pending-N / empty-email keys eagerly become chrome:<email> / edge:<email> - call it up front so you never drive the wrong (unresolved) profile.', related: ['nbrowser_profiles', 'nbrowser_pin_session', 'nbrowser_whoami'], pitfalls: ['takes ~2.5s (waits for each re-announce)', 'a profile not signed into Google stays email-less - target it by id-key or browser:'] },@@ -1558,21 +1558,14 @@ function dispatch(verb, args) {       (async () => {       let curWins = [];       try { curWins = await chromeWindowsDetailed(); } catch {}+      // Opening a plain --new-window into a running browser just ADDS a window; it does not restart it+      // (verified live on the user's own single-profile Edge). We do NOT refuse the live profile. The one+      // real hazard is that the background MINIMIZE could grab the wrong window, so we compute the set of+      // windows that must NEVER be minimized/closed — the workspace/editor and any OTHER thread's live+      // session in this profile — and hand it to the watcher as an exclude list. That's the whole guard.       const protectedHwnds = new Set();-      const hostWins = [];-      for (const w of curWins) { const t = String(w.title || ''); if (BRAND.test(t) && WORKSPACE.test(t)) { protectedHwnds.add(w.hwnd); hostWins.push(t); } }-      // another THREAD's live extension-driven session pinned to this exact profile (not my own, not os-opened)+      for (const w of curWins) { const t = String(w.title || ''); if (BRAND.test(t) && WORKSPACE.test(t)) protectedHwnds.add(w.hwnd); }       for (const [sid, pk] of sessionProfile) { if (pk === kp.key && sid !== a.sessionId && !osOpened.has(sid)) { const h = sessionHwnd.get(sid); if (h) protectedHwnds.add(h); } }-      // HARD REFUSE — NO OVERRIDE. Launching a competing browser process into a profile whose browser-      // is currently hosting the user's workspace / an active AI session can make the browser do a-      // singleton takeover and RESTART that profile, destroying the running windows. This killed the-      // user's thread twice (2026-07-19), the second time because a confirmLiveProfile:true escape let-      // me click past this very check. That escape is GONE. The safe paths are in the hint.-      if (hostWins.length || protectedHwnds.size) {-        return resolve({ success: false, errorCode: 'live_profile',-          error: `live_profile: ${kp.browser} is currently hosting ${hostWins.length ? `the user's live Adom workspace (window: "${hostWins[0].slice(0, 60)}")` : 'an active AI session'}, and it shares ONE process across all its windows. Launching a window into it risks a singleton takeover that RESTARTS the browser and destroys the running windows. REFUSED (no override).`,-          _hint: `Never launch a browser into the process running the workspace/thread. Options: (1) a DIFFERENT ${kp.browser} profile that is NOT live; (2) pup (browser_open_window) for a fully isolated throwaway browser; (3) install the Adom extension in this profile (installing-the-extension) — with ABE, a window is created via chrome.windows.create FROM INSIDE the already-running browser, so there is NO process launch and NO restart risk, even on a single-profile browser. To open the user's REAL signed-in ${kp.browser} session in the background, ABE is the reliable path.` });-      }       const local = process.env.LOCALAPPDATA;       const exes = kp.browser === 'edge'         ? ['C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe', 'C:/Program Files/Microsoft/Edge/Application/msedge.exe']
native-browser-bridge-manifest.json+4−4
@@ -1,8 +1,8 @@ {   "manifest_version": 1,-  "version": "0.1.38",-  "url": "https://wiki.adom.inc/download/adom/adom-browser-extension/0.1.38/native-browser-bridge-v0.1.38.zip",-  "sha256": "ab6805b45617e61d9a86fe59e3ee58742004741b8f813075003ce40f3420b125",-  "size": 86661,+  "version": "0.1.39",+  "url": "https://wiki.adom.inc/download/adom/adom-browser-extension/0.1.39/native-browser-bridge-v0.1.39.zip",+  "sha256": "a23241bcd440b425e6b193b54ae3445fc3a268457b0edf09354c11d4d1b51ab5",+  "size": 86206,   "released_at": "2026-07-19T00:00:00Z" }