← Commit history

v0.16.30 (insiders): screenshot files are named with the timestamp last, so ab's pulled copies carry the real capture time; the dashboard reads the pulled file; docs describe the file contract

John Lauer ·26ab5a84c7 ·1mo ago ·parent 88ec693
8 files changed +20−12
README.md+1−1
@@ -417,7 +417,7 @@ Driving the user's real browser, verified end-to-end:   the element's `getBoundingClientRect` to compute its xy - DOM-truth, not pixel-guessing. - **The gliding Adom cursor** - `cursor:true` + `intent:"Clicking the Pay button"` shows a teal arrow +   pulsing ring that glides to the target while **narrating its intention** (trust-building, mimics Hydrogen).-- **Screenshots** - `screenshot {toFile:true}` → pull the PNG (avoids relay base64 timeouts).+- **Screenshots** - replies carry `fullPath` (+ a 1568 px `safePath` when wider); ab pulls the PNG to your machine automatically. - **Authed `fetch_url`** - uses the user's REAL cookies, so it grabs files behind a login. - **Taskbar status** - `flash`/`taskbar` paint a "come look" flash, a progress bar   (green/yellow-for-human-gates/red), and an **"Adom is driving" overlay badge** on the real browser's
bin/nb-dashboard+5−2
@@ -20,7 +20,7 @@ const { execFile, spawn } = require('child_process'); const fs = require('fs'); const crypto = require('crypto'); -const VERSION = '0.16.29';           // keep in lockstep with package.json (pkg version)+const VERSION = '0.16.30';           // keep in lockstep with package.json (pkg version) // SEND TO AI IS UN-PARKED (John: "yeah, we are re-enabling the send to ai. it seems to be good now"). // The ah build thread certified the crash family dead on the gate-fixed build and the delivery leg is // proven end to end. The park const is DELETED rather than flipped, so no dead branch can resurrect it.@@ -219,7 +219,10 @@ async function demoStep(id) {     }     if (step.action === 'shot') {       const r = await cli(['--target', t, '--ai-thread', 'nb-dashboard', 'nbrowser_screenshot', JSON.stringify({ sessionId: DEMO_SID })], 60000);-      return { ok: r.ok === true, detail: 'captured ' + (r.width || '?') + 'x' + (r.height || '?') + ' without foregrounding', shot: r.base64 ? 'data:image/png;base64,' + r.base64 : null };+      // nb-bridge#49: the reply is a file (fullPath) that the CLI pulls here; read the pulled copy.+      const local = [r.localSafePath, r.localFullPath, r.savedTo].find((f) => f && fs.existsSync(f));+      const shot = r.base64 ? 'data:image/png;base64,' + r.base64 : (local ? 'data:image/png;base64,' + fs.readFileSync(local).toString('base64') : null);+      return { ok: r.ok === true || r.status === 'ok', detail: 'captured ' + (r.fullWidth || r.width || '?') + 'px wide without foregrounding', shot };     }     if (step.action === 'click') {       await cli(['--target', t, '--ai-thread', 'nb-dashboard', 'nbrowser_navigate', JSON.stringify({ sessionId: DEMO_SID, url: HARNESS_URL })], 30000);
bridge/BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.16.29\ No newline at end of file+0.16.30\ No newline at end of file
bridge/bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "native-browser",   "displayName": "Adom Native Browser",-  "version": "0.16.29",+  "version": "0.16.30",   "expectedExtensionVersion": "0.2.15",   "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.16.29",+  "version": "0.16.30",   "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+2−1
@@ -2992,7 +2992,8 @@ async function decorateReply(p, frame, payloadIn, setPayload) {           const want = (typeof p.toFile === 'string' && /^[a-zA-Z]:[\\/]|^\\\\|^\//.test(p.toFile)) ? path.normalize(p.toFile) : null;           const dir = want ? path.dirname(want) : path.join(process.env.TEMP || os.tmpdir(), 'adom-nbrowser-shots');           fs.mkdirSync(dir, { recursive: true });-          const stem = `shot-${Date.now()}-${Math.floor(Math.random() * 1e4)}`;+          // ab derives the local copy's timestamp from the LAST number in the name, so the epoch-ms goes last.+          const stem = `nbrowser-${Math.floor(Math.random() * 1e4)}-${Date.now()}`;           const fullPath = want || path.join(dir, `${stem}.png`);           const bytes = Buffer.from(payload.base64, 'base64');           fs.writeFileSync(fullPath, bytes);
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "nb-bridge",-  "version": "0.16.29",+  "version": "0.16.30",   "type": "app",   "title": "NB - Native Browser Bridge",   "description": "This package installs the SKILLS into your container so your AI knows how to drive your real signed-in Chrome and Edge; Bridge loads the bridge runtime itself from the release zip.",
skills/driving-the-extension/SKILL.md+8−4
@@ -400,12 +400,16 @@ Three ways to "see", and the choice matters:   other work, is imprecise, and usually implies foregrounding. There is always a targeted option above.   (`nbrowser_screenshot_full_res` is full-**PAGE**, not full-monitor - it still only sees the page.) ```bash-adom-bridge -t AdomLapper nbrowser_screenshot '{"sessionId":"s1","toFile":true}'   # PAGE bitmap → laptop PNG path (fixed dir %LOCALAPPDATA%\Temp\adom-nbrowser-shots); toFile:"C:/abs/path.png" writes THERE (bridge 0.16.2, nb-bridge#41)+adom-bridge -t AdomLapper nbrowser_screenshot '{"sessionId":"s1"}'                 # PAGE bitmap, delivered to YOUR machine as a file adom-bridge -t AdomLapper desktop_screenshot_window '{"hwnd":<from open_window>}'   # WINDOW + chrome + child popups-# then: adom-bridge -t AdomLapper pull_file '{"filePaths":["<path>"],"saveTo":"/tmp"}' ```-Screenshots are large base64 - over the relay they can time out, so **prefer `toFile:true` + `pull_file`**-(binary, chunked). `screenshot_full_res` is unresized; default resizes ≤1568 for the model.+**Screenshots arrive as files, never inline base64 (bridge 0.16.29, nb-bridge#49).** The PNG is written on+the desktop and the reply carries `fullPath` (+ `safePath`, a copy at most 1568 px wide, whenever the image+is wider). ab pulls both to the caller and adds `localFullPath` / `localSafePath` / `savedTo`: **read+`localSafePath` if present, else `localFullPath`.** No `pull_file` step, no base64 through the relay.+`nbrowser_screenshot` is already resized to 1568 px wide, so it has no separate safe copy.+`nbrowser_screenshot_full_res` is unresized and comes with one. `toFile:"C:/abs/path.png"` chooses where the+desktop copy is written, and `inline:true` returns the old base64 reply for a caller that truly needs it.  Every screenshot response carries a **`viewport`** coordinate-map sampled at capture time, so you can turn a screenshot pixel into a click coordinate EXACTLY without a separate `window.innerWidth`/`dpr` probe (and