← Commit history

v1.2.0: Tier-1 prewarm for AD v1.9.47 — bridge.json prewarm:[chrome-for-testing]; gate detect-only (defer fetch to AD-core, non-blocking {installing:true}); browser_readiness read-only; skill points 'is it ready' at bridge_readiness not browser_status

John Lauer ·9978f16b10 · ·parent 924fa29
5 files changed +60−43
SKILL.md+22−13
@@ -1,7 +1,7 @@ --- name: pup user-invocable: true-description: "Drive Chrome browser windows on the user's desktop via the adom-desktop CLI (the Puppeteer bridge): open/close windows + tabs, navigate, screenshot, eval JS, record, drive the user's REAL signed-in Chrome/Edge/Brave. Includes COLD-START SELF-HEAL — on a fresh PC the bridge auto-installs Chrome for Testing; poll browser_readiness. Trigger words: pup, puppeteer, browser window, open in pup, browser screenshot, browser reload, browser eval, visual debug, browser_open_window, browser_screenshot, browser_readiness, browser_prewarm, chrome for testing, open in browser."+description: "Drive Chrome browser windows on the user's desktop via the adom-desktop CLI (the Puppeteer bridge): open/close windows + tabs, navigate, screenshot, eval JS, record, drive the user's REAL signed-in Chrome/Edge/Brave. Cold-start: on a fresh PC Adom Desktop background-fetches Chrome for Testing (Tier-1 prewarm); for 'is it ready' poll AD's bridge_readiness (not browser_status). Trigger words: pup, puppeteer, browser window, open in pup, browser screenshot, browser reload, browser eval, visual debug, browser_open_window, browser_screenshot, browser_readiness, browser_prewarm, chrome for testing, open in browser." ---  # Pup — Puppeteer Browser Control (with cold-start self-heal)@@ -25,27 +25,36 @@ When you run `browser_open_window` on a cold PC, one of these happens — handle | Response | What it means | What you do | |---|---|---| | `errorCode: "node_not_found"` | Node.js isn't installed (the bridge can't even start). | Run `adom-desktop desktop_install_node '{}'`, wait for it, then retry the `browser_open_window`. |-| `errorCode: "chrome_for_testing_installing"` (`installing:true`) | **Chrome for Testing is missing; the bridge is auto-downloading it now (~150 MB, one time).** This is EXPECTED on a fresh PC — NOT a failure. | **Poll `browser_readiness` until `ready:true`** (usually 1–3 min), THEN re-issue the exact same `browser_open_window`. You do NOT install anything yourself. Do NOT report failure to the user. |+| `errorCode: "chrome_for_testing_installing"` (`installing:true`) | **Chrome for Testing isn't cached yet; Adom Desktop is fetching it in the BACKGROUND (Tier-1 prewarm, ~150 MB, one time).** The bridge did NOT block. EXPECTED on a fresh PC — NOT a failure. | **Poll AD's `bridge_readiness` until Chrome reports ready** (usually 1–3 min), THEN re-issue the exact same `browser_open_window`. You do NOT install anything yourself. Do NOT report failure. (If it never becomes ready, `browser_prewarm` makes the bridge fetch it itself.) | | `errorCode: "chrome_install_failed"` / `chrome_download_failed` | The Chrome download itself failed. | Read `readiness.lastError`. It's almost always no network / a proxy blocking `storage.googleapis.com`, or low disk — NOT a Node problem. Retry `browser_prewarm`; if it persists, surface `lastError` to the user. Fallback: drive their real browser via native mode (below). | | `ok:true` / a real session | Everything was already warm. | Proceed normally. | +### "What do I have / is it ready?" → ask AD's `bridge_readiness` (NOT `browser_status`)++For "is pup ready / what's installed," call **`adom-desktop bridge_readiness`** — AD-core's readiness probe.+It reports server-up + Chrome-for-Testing readiness, including AD's **Tier-1 prewarm** progress.+`browser_status` only lists open sessions — it is NOT a readiness check.+ ### The clean cold-start recipe  ```bash-# 1) (optional but nice) Warm Chrome for Testing WITHOUT opening a window first:-adom-desktop browser_prewarm '{}'              # returns fast; kicks off the install--# 2) Poll readiness until ready (the bridge installs CfT itself):-adom-desktop browser_readiness '{}'            # → {ready:false, installing:true, installProgressPct:42, ...}-#    ...wait a few seconds, poll again until → {ready:true, chromeForTestingInstalled:true}+# 1) Ask AD if pup is ready (poll until Chrome shows ready):+adom-desktop bridge_readiness '{}' -# 3) Now open the window — it's instant:+# 2) Once ready, open the window — it's instant: adom-desktop browser_open_window '{"sessionId":"chip-fetcher","profile":"chip-fetcher","url":"<url>"}' ``` -`browser_prewarm` and `browser_readiness` are the two cold-start verbs. `browser_prewarm '{"wait":true}'`-blocks until the install finishes instead of returning immediately. **Always surface a verb's `_hint`-field verbatim to the user when something isn't ready** — it tells you (and them) exactly what's happening.+On a fresh PC, **Adom Desktop fetches Chrome for Testing in the background** (the bridge declares+`prewarm:["chrome-for-testing"]`); `browser_open_window` returns a non-blocking `{installing:true}` until+it's cached — it never blocks or crashes. So: poll `bridge_readiness` → then open. You never run an+installer yourself.++- **`bridge_readiness`** (AD-core) — THE readiness question: server-up + Chrome cached (+ prewarm progress).+- **`browser_readiness`** (this bridge) — pup's own **READ-ONLY** detail (Chrome build id, fetch phase). Never downloads.+- **`browser_prewarm`** — explicit fallback: have the bridge fetch Chrome itself if AD's prewarm didn't.++**Always surface a verb's `_hint` verbatim** when something isn't ready.  > Why this matters: before v1.1.0, a fresh PC with no Chrome for Testing made `browser_open_window` > fail with a generic "Failed to launch Chrome after 3 attempts" and no actionable hint — the AI@@ -97,7 +106,7 @@ adom-desktop browser_alert_window '{"sessionId":"job"}'      # non-intrusive "do | `browser_screenshot` | Capture the page (lossless PNG) | `sessionId`, `fullPage?` | | `browser_eval` | Run JS in the page, return the result | `sessionId`, `expr` | | `browser_errors` | Console/page errors | `sessionId` |-| `browser_status` | All sessions + chrome readiness | none |+| `browser_status` | List open pup sessions (NOT a readiness check — use AD's `bridge_readiness`) | none | | `browser_reload` | Reload + clear error log | `sessionId` | | `browser_open_tab` / `browser_switch_tab` / `browser_close_tab` / `browser_list_tabs` | Tabs within one session/window | `sessionId`, `tabId?` | | `browser_record_start` / `browser_record_stop` | Record a video of a window/tab | `sessionId` |
adom-bridge-puppeteer-manifest.json+11−6
@@ -1,10 +1,10 @@ {   "manifest_version": 1,   "name": "puppeteer",-  "version": "1.1.0",-  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.1.0/adom-bridge-puppeteer-v1.1.0.zip",-  "sha256": "525eabb0350ea0eaf52a949e9b3026f5a4a035868afe9546a7478298b9539b8c",-  "size": 127135,+  "version": "1.2.0",+  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.2.0/adom-bridge-puppeteer-v1.2.0.zip",+  "sha256": "57d27ac4bb22b9bea1138c4b8260224e14ff0e680f5a731a8356005b510bf469",+  "size": 127304,   "verbPrefixes": [     "browser_",     "desktop_recorder_",@@ -12,5 +12,10 @@   ],   "healthEndpoint": "/status",   "statusVerb": "browser_readiness",-  "released_at": "2026-06-29T20:30:00Z"-}+  "prewarm": {+    "assets": [+      "chrome-for-testing"+    ]+  },+  "released_at": "2026-06-30T00:00:00Z"+}\ No newline at end of file
src/BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.1.0\ No newline at end of file+1.2.0\ No newline at end of file
src/bridge.json+5−2
@@ -2,8 +2,8 @@   "manifest_version": 1,   "name": "puppeteer",   "displayName": "Puppeteer (Chrome for Testing + Native)",-  "version": "1.1.0",-  "description": "Cold-start self-heal (v1.1.0): on a fresh PC the bridge DETECTS that Chrome for Testing is missing, AUTO-INSTALLS it (programmatically via the bundled @puppeteer/browsers — no npx), and reports progress via browser_readiness / browser_prewarm, so a first-ever 'open in pup' works hands-off instead of failing. Headful browser automation. Default path drives Chrome for Testing (CfT) with managed pup profiles. v1.0.6+ optional native-drive: pass nativeBrowser+nativeProfile (from desktop_list_browsers) to browser_open_window to drive the user's REAL Chrome/Edge/Brave with the actual signed-in account + org policies + device enrollment intact. Smart flow: if the browser is CLOSED, AD launches it fresh immediately with NO prompt (nothing to disrupt) and reports back ready-to-drive (launchedFresh:true); if it's OPEN without the port, AD returns errorCode:'native_relaunch_required' so the caller asks the user, then re-call with nativeRelaunch:true. AD then closes only that browser's own PIDs cleanly (WM_CLOSE — Sessions saved; CfT bridge sessions + other Chromium left untouched) and relaunches with --restore-last-session so every tab/window comes back. If the debug port is policy-blocked (e.g. Google Workspace's RemoteDebuggingAllowed disabled — affects Chrome browser-wide, all profiles), native drive returns errorCode:'native_cdp_blocked' with a `diagnosis` of the likely cause (local registry policy vs cloud-managed) plus an `alternatives` list of other installed browsers — Edge usually escapes Google management — so the caller can ask the user which to use; AD won't close that browser again for it. The generic CfT path (browser_open_window with no nativeBrowser) always works as a fallback.",+  "version": "1.2.0",+  "description": "Tier-1 cold-start (v1.2.0, for AD v1.9.47+ two-tier model): pup brings its OWN browser (Chrome for Testing), so it needs no detect-block. It declares prewarm:[chrome-for-testing] so Adom Desktop fetches Chrome in the BACKGROUND and reports readiness via bridge_readiness. The bridge server starts fine WITHOUT Chrome; browser_readiness is a READ-ONLY probe (ready = server-up AND Chrome cached; never triggers a download); browser_open returns a non-blocking {installing:true} (never blocks/crashes) until Chrome is cached; browser_prewarm is an explicit bridge-side fetch fallback. Headful browser automation. Default path drives Chrome for Testing (CfT) with managed pup profiles. v1.0.6+ optional native-drive: pass nativeBrowser+nativeProfile (from desktop_list_browsers) to browser_open_window to drive the user's REAL Chrome/Edge/Brave with the actual signed-in account + org policies + device enrollment intact. Smart flow: if the browser is CLOSED, AD launches it fresh immediately with NO prompt (nothing to disrupt) and reports back ready-to-drive (launchedFresh:true); if it's OPEN without the port, AD returns errorCode:'native_relaunch_required' so the caller asks the user, then re-call with nativeRelaunch:true. AD then closes only that browser's own PIDs cleanly (WM_CLOSE — Sessions saved; CfT bridge sessions + other Chromium left untouched) and relaunches with --restore-last-session so every tab/window comes back. If the debug port is policy-blocked (e.g. Google Workspace's RemoteDebuggingAllowed disabled — affects Chrome browser-wide, all profiles), native drive returns errorCode:'native_cdp_blocked' with a `diagnosis` plus an `alternatives` list of other installed browsers — Edge usually escapes Google management. The generic CfT path (browser_open_window with no nativeBrowser) always works as a fallback.",   "homepage": "https://github.com/adom-inc/adom-desktop",   "author": "Adom Inc.",   "license": "MIT",@@ -15,6 +15,9 @@     "stopMethod": "kill",     "killImageName": "node.exe"   },+  "prewarm": {+    "assets": ["chrome-for-testing"]+  },   "verbPrefixes": [     "browser_",     "desktop_recorder_",
src/server.js+21−21
@@ -2930,25 +2930,24 @@ const server = http.createServer(async (req, res) => {           // `profile` arg. Default (no native args) is byte-for-byte the same           // CfT path as v1.0.4 — strictly additive, no regressions.           const wantsNative = !!(args.nativeBrowser || args.nativeProfile);-          // ── Cold-start self-heal (CfT path only) ─────────────────────────────-          // The default (non-native) path drives Chrome for Testing. On a fresh PC-          // — HD bundled AD, and the installer pre-installed NEITHER Node NOR CfT —-          // this is the #1 failure ("open in pup did nothing"). Detect + auto-install-          // CfT (non-blocking) and return a POLLABLE structured status instead of-          // blindly spawning a missing binary 3× then throwing a dev-string.+          // ── Tier-1 cold-start gate (CfT path only) — READ-ONLY, never blocks ──+          // pup brings its own browser (Chrome for Testing). AD v1.9.47+ backgrounds+          // the Chrome-for-Testing fetch via this bridge's prewarm:["chrome-for-testing"]+          // declaration, so this gate does NOT trigger a download itself (no racing+          // AD-core) and NEVER blocks: if Chrome isn't cached yet it returns a pollable+          // {installing:true}. The explicit bridge-side fetch fallback is browser_prewarm.           // Native drive uses the user's REAL browser (not CfT), so it skips this.           if (!wantsNative) {-            const r = await chrome.ensureChromeReady({ background: true });-            if (!r.ready) {-              const rd = chrome.readiness();+            const rd = chrome.readiness();   // detect-only; never downloads+            if (!rd.ready) {               if (rd.installPhase === 'failed') {                 sendJSON(res, {                   success: false,                   errorCode: rd.lastErrorCode || 'chrome_install_failed',-                  error: `Chrome for Testing (the browser pup drives) could not be installed: ${rd.lastError}`,+                  error: `Chrome for Testing (the browser pup drives) failed to install: ${rd.lastError}`,                   chromeForTestingInstalled: false,                   readiness: rd,-                  _hint: 'Chrome for Testing failed to download. This is almost always no network / a proxy blocking storage.googleapis.com, or low disk — NOT a Node problem (Node is fine; the bridge is running). Retry with browser_prewarm; if it keeps failing, surface readiness.lastError to the user. As a fallback you can drive the user\'s real browser via browser_open_window with nativeBrowser+nativeProfile (run desktop_list_browsers first).',+                  _hint: 'A prior Chrome-for-Testing fetch failed (usually no network / a proxy blocking storage.googleapis.com, or low disk — NOT a Node problem). Retry `browser_prewarm`; if it keeps failing, surface readiness.lastError to the user. Fallback: drive the user\'s real browser via browser_open_window with nativeBrowser+nativeProfile.',                 });                 return;               }@@ -2956,12 +2955,11 @@ const server = http.createServer(async (req, res) => {                 success: false,                 errorCode: 'chrome_for_testing_installing',                 installing: true,-                progressPct: rd.installProgressPct,                 chromeForTestingInstalled: false,-                statusVerb: 'browser_readiness',+                statusVerb: 'bridge_readiness',                 readiness: rd,-                error: 'Chrome for Testing (the browser pup drives) is not installed on this machine yet — the bridge is downloading it now (~150 MB, one time).',-                _hint: 'FIRST-TIME SETUP on this PC: pup needs Chrome for Testing and is installing it for you in the background — you do NOT need to install anything yourself. Poll `browser_readiness` until {ready:true} (typically 1–3 min on a normal connection), THEN re-issue this exact browser_open_window call. Do not report failure; this is expected on a fresh machine.',+                error: 'Chrome for Testing is not cached yet — Adom Desktop is fetching it in the background (Tier-1 prewarm).',+                _hint: 'FIRST-TIME on this PC: AD is downloading Chrome for Testing in the background (the bridge declares prewarm:["chrome-for-testing"]); the bridge did NOT block on it. Poll AD\'s `bridge_readiness` until Chrome reports ready, THEN re-issue this exact browser_open_window. Do NOT report failure — this is expected on a fresh machine. (If it never becomes ready, call `browser_prewarm` to have the bridge fetch Chrome itself.)',               });               return;             }@@ -4043,20 +4041,22 @@ const server = http.createServer(async (req, res) => {           return;         }         case 'browser_readiness': {-          // Cold-start readiness probe: is Chrome for Testing installed / installing?-          // The AI polls this on a fresh PC before/after browser_open_window.+          // READ-ONLY readiness probe. NEVER triggers a download. `ready` reflects both+          // server-up (this verb answered) AND Chrome-for-Testing cached. For the general+          // "what do I have / is it ready" question prefer AD's `bridge_readiness` (it also+          // reports AD-core's Tier-1 prewarm progress); this verb is pup's own detailed view.           const rd = chrome.readiness();           sendJSON(res, {             success: true,             output: JSON.stringify(rd),             ...rd,             _hint: rd.ready-              ? 'Ready — Chrome for Testing is installed and pup can open windows. Proceed with browser_open_window.'+              ? 'Ready — Chrome for Testing is cached and the server is up; pup can open windows. Proceed with browser_open_window.'               : rd.installing-                ? `Chrome for Testing is installing (${rd.installProgressPct}%). Poll browser_readiness until ready:true (usually 1–3 min), then browser_open_window.`+                ? `Chrome for Testing is being fetched (${rd.installProgressPct}%). Poll bridge_readiness (or this verb) until ready:true, then browser_open_window.`                 : rd.installPhase === 'failed'-                  ? `Chrome for Testing install FAILED: ${rd.lastError}. Retry browser_prewarm; if it persists, surface this to the user (usually network/proxy blocking the download, or low disk).`-                  : 'Chrome for Testing is not installed yet. Call browser_prewarm (or just browser_open_window — it self-installs) to fetch it.',+                  ? `Chrome for Testing fetch FAILED: ${rd.lastError}. Retry browser_prewarm; if it persists, surface this to the user (usually network/proxy blocking the download, or low disk).`+                  : 'Chrome for Testing is not cached yet. Adom Desktop fetches it in the background (Tier-1 prewarm) — poll AD\'s bridge_readiness; or call browser_prewarm to have the bridge fetch it.',           });           return;         }