← Commit history
bridge 0.0.26 (AD v1.9.79 contracts): declare timeouts (wait/fetch_url/input_dispatch=120, screenshot*/record*=120 via prefixes; statusVerb=nbrowser_status) so long verbs aren't cut at 60s; align describe timeouts; detect intentionally omitted (extension-connected is authoritative; Chrome-only detect would misreport Edge-only machines)
5 files changed
+34−16
bridge/BRIDGE_VERSION+1−1@@ -1 +1 @@-0.0.25+0.0.26
bridge/bridge.json+20−2@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "native-browser", "displayName": "Adom Native Browser (Chrome + Edge)",- "version": "0.0.25",+ "version": "0.0.26", "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", "author": "Adom Inc.",@@ -93,5 +93,23 @@ } }, "statusVerb": "nbrowser_status",- "updateManifestUrl": "https://wiki.adom.inc/api/pages/adom/adom-browser-extension/files/native-browser-bridge-manifest.json"+ "updateManifestUrl": "https://wiki.adom.inc/api/pages/adom/adom-browser-extension/files/native-browser-bridge-manifest.json",+ "timeouts": {+ "default": 60,+ "verbs": {+ "wait": 125,+ "fetch_url": 120,+ "input_dispatch": 120+ },+ "prefixes": [+ {+ "prefix": "screenshot",+ "seconds": 120+ },+ {+ "prefix": "record",+ "seconds": 120+ }+ ]+ } }
bridge/package.json+1−1@@ -1,6 +1,6 @@ { "name": "adom-native-browser-bridge",- "version": "0.0.25",+ "version": "0.0.26", "private": true, "description": "adom-desktop bridge for the Adom native-browser extension (Chrome + Edge)", "main": "server.js",
bridge/server.js+7−7@@ -532,20 +532,20 @@ function dispatch(verb, args) { d('nbrowser_reload', 'Reload the tab.', { sessionId: S, tabId: 'optional str' }, { ok: 'bool' }, 45, { example: { sessionId: 'work' } }), d('nbrowser_back', 'History back.', { sessionId: S, tabId: 'optional str' }, { ok: 'bool' }, 30, { example: { sessionId: 'work' } }), d('nbrowser_forward', 'History forward.', { sessionId: S, tabId: 'optional str' }, { ok: 'bool' }, 30, { example: { sessionId: 'work' } }),- d('nbrowser_wait', 'Sleep server-side for ms (or wait on the tab).', { sessionId: S, ms: 'optional int' }, { ok: 'bool' }, 60, { example: { ms: 1000 } }),- d('nbrowser_screenshot', 'Screenshot the tab via CDP (captures a BACKGROUND/occluded window; resized <=1568).', { profile: P, sessionId: S, tabId: 'optional str', maxWidth: 'optional int' }, { ok: 'bool', base64: 'str', filePath: 'str?' }, 45, { example: { sessionId: 'work', maxWidth: 1500 } }),- d('nbrowser_screenshot_full_res', 'Full-resolution / full-page screenshot via CDP.', { profile: P, sessionId: S, tabId: 'optional str', fullPage: 'optional bool' }, { ok: 'bool', base64: 'str' }, 60, { example: { sessionId: 'work', fullPage: true } }),+ d('nbrowser_wait', 'Sleep server-side for ms (or wait on the tab).', { sessionId: S, ms: 'optional int' }, { ok: 'bool' }, 125, { example: { ms: 1000 } }),+ d('nbrowser_screenshot', 'Screenshot the tab via CDP (captures a BACKGROUND/occluded window; resized <=1568).', { profile: P, sessionId: S, tabId: 'optional str', maxWidth: 'optional int' }, { ok: 'bool', base64: 'str', filePath: 'str?' }, 120, { example: { sessionId: 'work', maxWidth: 1500 } }),+ d('nbrowser_screenshot_full_res', 'Full-resolution / full-page screenshot via CDP.', { profile: P, sessionId: S, tabId: 'optional str', fullPage: 'optional bool' }, { ok: 'bool', base64: 'str' }, 120, { example: { sessionId: 'work', fullPage: true } }), d('nbrowser_eval', 'Run JS in the page context and return the result.', { sessionId: S, tabId: 'optional str', expression: 'required str (JS)' }, { ok: 'bool', result: 'any' }, 45, { example: { sessionId: 'work', expression: 'document.title' } }), d('nbrowser_evaluate', 'Alias of nbrowser_eval.', { sessionId: S, tabId: 'optional str', expression: 'required str (JS)' }, { ok: 'bool', result: 'any' }, 45, { example: { sessionId: 'work', expression: '1+1' } }),- d('nbrowser_input_dispatch', 'Low-level isTrusted CDP input.', { sessionId: S, tabId: 'optional str', type: 'required "click"|"move"|"type"|"key"', x: 'int?', y: 'int?', text: 'str?', key: 'str?' }, { ok: 'bool' }, 30, { example: { sessionId: 'work', type: 'click', x: 200, y: 300 } }),+ d('nbrowser_input_dispatch', 'Low-level isTrusted CDP input.', { sessionId: S, tabId: 'optional str', type: 'required "click"|"move"|"type"|"key"', x: 'int?', y: 'int?', text: 'str?', key: 'str?' }, { ok: 'bool' }, 120, { example: { sessionId: 'work', type: 'click', x: 200, y: 300 } }), d('nbrowser_click', 'Click by visible text / selector / xy; optional gliding cursor + intent label.', { sessionId: S, tabId: 'optional str', text: 'optional str', selector: 'optional str', x: 'int?', y: 'int?', cursor: 'optional bool', intent: 'optional str' }, { ok: 'bool', clicked: 'bool' }, 30, { example: { sessionId: 'work', text: 'Sign in', cursor: true, intent: 'Clicking Sign in' } }), d('nbrowser_type', 'Type text into the focused field (isTrusted).', { sessionId: S, tabId: 'optional str', text: 'required str' }, { ok: 'bool' }, 30, { example: { sessionId: 'work', text: 'hello world' } }), d('nbrowser_press_key', 'Press a key (Enter, Tab, etc.).', { sessionId: S, tabId: 'optional str', key: 'required str' }, { ok: 'bool' }, 30, { example: { sessionId: 'work', key: 'Enter' } }),- d('nbrowser_fetch_url', "Fetch a URL using the profile's real cookies/session; optional save to desktop.", { url: 'required str', profile: P, desktopSaveTo: 'optional Windows path' }, { ok: 'bool', status: 'int', body: 'str?', savedTo: 'str?' }, 60, { longRunning: true, example: { url: 'https://example.com/api.json' } }),+ d('nbrowser_fetch_url', "Fetch a URL using the profile's real cookies/session; optional save to desktop.", { url: 'required str', profile: P, desktopSaveTo: 'optional Windows path' }, { ok: 'bool', status: 'int', body: 'str?', savedTo: 'str?' }, 120, { longRunning: true, example: { url: 'https://example.com/api.json' } }), d('nbrowser_errors', 'Return buffered page/console errors for the tab.', { sessionId: S, tabId: 'optional str' }, { ok: 'bool', errors: '[...]' }, 20, { example: { sessionId: 'work' } }), d('nbrowser_close', 'Detach the debugger / close managed windows. No sessionId = all.', { sessionId: 'optional str' }, { ok: 'bool' }, 20, { example: {} }),- d('nbrowser_record_start', '⭐ Record a browser window. STRONGLY prefer method:"wgc" (delegates to the core adom-desktop verb desktop_record_window_start: background, up to 60fps, NO picker, NO banner, captures occluded windows, no focus theft). method:"getdisplaymedia"/"tabcapture" is a LAST-RESORT fallback (Chrome forces a manual share picker + banner) and is REFUSED unless you also pass fallbackConfirmed:true. Calling with no method returns the WGC guidance hint.', { method: 'required "wgc" (recommended) | "getdisplaymedia" | "tabcapture"', hwnd: 'int? (or titleContains)', titleContains: 'str?', fps: 'optional int (default 30)', codec: 'optional "h264"|"hevc"', fallbackConfirmed: 'required true ONLY for getdisplaymedia/tabcapture, to acknowledge the picker/banner tradeoff' }, { ok: 'bool', recordingId: 'str', path: 'str' }, 60, { statusVerb: 'nbrowser_record_status', longRunning: true, example: { method: 'wgc', titleContains: 'chip-fetcher' } }),- d('nbrowser_record_stop', 'Stop a recording and finalize the mp4.', { method: 'required "wgc"', recordingId: 'required str' }, { ok: 'bool', path: 'str', frames: 'int' }, 60, { example: { method: 'wgc', recordingId: 'rec-...' } }),+ d('nbrowser_record_start', '⭐ Record a browser window. STRONGLY prefer method:"wgc" (delegates to the core adom-desktop verb desktop_record_window_start: background, up to 60fps, NO picker, NO banner, captures occluded windows, no focus theft). method:"getdisplaymedia"/"tabcapture" is a LAST-RESORT fallback (Chrome forces a manual share picker + banner) and is REFUSED unless you also pass fallbackConfirmed:true. Calling with no method returns the WGC guidance hint.', { method: 'required "wgc" (recommended) | "getdisplaymedia" | "tabcapture"', hwnd: 'int? (or titleContains)', titleContains: 'str?', fps: 'optional int (default 30)', codec: 'optional "h264"|"hevc"', fallbackConfirmed: 'required true ONLY for getdisplaymedia/tabcapture, to acknowledge the picker/banner tradeoff' }, { ok: 'bool', recordingId: 'str', path: 'str' }, 120, { statusVerb: 'nbrowser_record_status', longRunning: true, example: { method: 'wgc', titleContains: 'chip-fetcher' } }),+ d('nbrowser_record_stop', 'Stop a recording and finalize the mp4.', { method: 'required "wgc"', recordingId: 'required str' }, { ok: 'bool', path: 'str', frames: 'int' }, 120, { example: { method: 'wgc', recordingId: 'rec-...' } }), d('nbrowser_record_status', 'Poll a recording.', { method: 'required "wgc"', recordingId: 'optional str' }, { ok: 'bool', status: 'str' }, 20, { example: { method: 'wgc' } }), d('nbrowser_record_list', 'List recent recordings.', {}, { ok: 'bool', recordings: '[...]' }, 20, { example: {} }), d('nbrowser_flash', "Flash the driven window's taskbar button ('come look' cue).", { sessionId: 'required str' }, { ok: 'bool' }, 15, { example: { sessionId: 'work' } }),
native-browser-bridge-manifest.json+5−5@@ -1,8 +1,8 @@ { "manifest_version": 1,- "version": "0.0.25",- "url": "native-browser-bridge-v0.0.25.bin",- "sha256": "15252f37d4a83a60707d6a6ed212b5a392c68711f35a8fcd1b2233382b19e88c",- "size": 28710,- "released_at": "2026-07-04T14:27:40Z"+ "version": "0.0.26",+ "url": "native-browser-bridge-v0.0.26.bin",+ "sha256": "d0214fdea5ea8c757bdf4227040130553fc12f83a9f71eb0e9ce3d62f385e10a",+ "size": 28792,+ "released_at": "2026-07-04T17:43:20Z" }