← Commit history

Sweep the caller-identity requirement EVERYWHERE instead of waiting for John to find each instance (his words: 'then look for that issue everywhere instead of waiting for me to discover it'). AD (>=1.9.183) refuses any command lacking caller identity, and I had only fixed the bridge's own outbound calls in 1.9.114. Audited all four categories where pup causes or teaches an AD command: (A) adCommand — 33 call sites, already unconditional since 1.9.114; (B) commands pup composes for WINDOWS to run — the jump-list TASKS and the relaunch/pin command carried no identity, so clicking 'Switch to logged-in view' was refused and silently did NOTHING (reproduced by running the exact CLI line a task runs); both now pass --ai-thread 'user: pup taskbar menu'/'...launcher', which is honest because a human clicked; (C) no other CLI invocations exist in the bridge (verified); (D) the category I would have missed — pup's own HINTS and its user SKILL.md handed out 9 example commands with no --ai-thread, so any caller copying them verbatim got refused; all now show the flag, and the skill documents why it is per-call and why exporting ADOM_AI_THREAD is wrong.

John Lauer ·c8bd8586da ·3mo ago ·parent 73dda30
4 files changed +20−11
adom-bridge-puppeteer-manifest.json+4−4
@@ -1,10 +1,10 @@ {   "manifest_version": 1,   "name": "puppeteer",-  "version": "1.9.114",-  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.114/adom-bridge-puppeteer-v1.9.114.zip",-  "sha256": "67de6002c4f84d33aba95e1e564f9d29a5c00e00b59d34d48fffe5211e72998f",-  "size": 382598,+  "version": "1.9.115",+  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.115/adom-bridge-puppeteer-v1.9.115.zip",+  "sha256": "3788a12548781338bbdfb733725d3a1b22b69a6953de9c811043ba239cfec61d",+  "size": 383013,   "verbPrefixes": [     "browser_",     "desktop_recorder_",
src/BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.9.114+1.9.115
src/bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "puppeteer",   "displayName": "Puppeteer (Chrome for Testing + Native)",-  "version": "1.9.114",+  "version": "1.9.115",   "description": "Drives a browser ALREADY on the machine \u2014 installed Chrome, else Microsoft Edge (every Windows PC ships with Edge) \u2014 launched with a FRESH isolated profile, so the common case has NO ~150 MB Chrome-for-Testing download and it never touches the user's real tabs/logins. Binds its local server to LOOPBACK (127.0.0.1) only, so no Windows Firewall 'allow Node through the firewall' prompt ever pops. Chrome for Testing is fetched only as a LAST RESORT if the machine has no Chromium browser at all. SPAWN-VERIFIED fallback: pup tries each detected browser (Chrome \u2192 Edge \u2192 CfT) and actually launches it, falling through to the next if one won't start (and handling browsers like Edge that relaunch onto another PID), so a corrupt/partial install never hard-fails an open. The browser that launches is cached as the default (persisted across restarts) so it isn't re-probed each time. On spawn the bridge SELF-WARMS: detects browsers + disk, and only if the box has no Chrome/Edge and no cached CfT does it background-fetch CfT so the first open is instant. browser_use pins a specific browser (chrome | edge | cft | auto); {browser:'chrome',install:true} downloads & installs REAL Google Chrome (user-scoped, no admin) on an Edge-only box. browser_readiness (READ-ONLY) reports which browser will be used + the full candidate list + the default + free disk. Every failure returns a specific errorCode + _hint (chrome_install_no_disk, chrome_download_network, chrome_install_permission, chrome_stable_not_detected, \u2026). Launches with FULL browser permissions by default for full debug (strictPermissions:true opts out). Headful automation: open/close windows+tabs, navigate, screenshot, eval JS, record. pup is a GENERIC, non-profile browser only \u2014 every session is a fresh isolated Chrome/Edge process, never the user's real signed-in browser; profile defaults to sessionId. To drive the user's REAL Chrome/Edge (their profile, cookies, SSO), use the Adom browser EXTENSION's nbrowser_* verbs \u2014 a separate bridge, not pup's job. macOS (v1.9.74+): full parity with mac-native mechanics \u2014 background-by-default is the app-level hide (windows stay drivable/screenshottable while hidden), raise/lower map to unhide+activate/hide, browser_alert_window posts a native toast whose click focuses the window, browser_use {browser:'chrome',install:true} installs Chrome from the official dmg, and taskbar identity/badging remains Windows-only.",   "homepage": "https://wiki.adom.inc/adom/adom-desktop",   "author": "Adom Inc.",
src/server.js+14−5
@@ -2129,7 +2129,9 @@ function pupIconPath(sessionId) { function pupRelaunchCommand(sessionId) {   const cli = path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), 'Adom Desktop', 'adom-desktop-cli.exe');   const payload = JSON.stringify({ sessionId, foregroundReason: 'user clicked the Adom Pup taskbar header or pinned launcher' }).replace(/"/g, '\\"');-  return `"${cli}" browser_focus_window "${payload}"`;+  // v1.9.115: same as the task commands — this runs when the user clicks the jump-list HEADER row or a+  // pinned pup launcher, so it needs identity or AD refuses it and the click does nothing.+  return `"${cli}" --ai-thread "user: pup taskbar launcher" browser_focus_window "${payload}"`; } function _isUnknownVerb(r, raw) { return /unknown (desktop )?command|unknown verb/i.test(((r && r.error) || '') + ' ' + (raw || '')); } async function ensurePupIdentityRegistered() {@@ -2448,7 +2450,14 @@ async function updateWikiJumplist(session, sessionId, opts) {   // parsed by the CLI's argv parser, which STRIPS unescaped double quotes, so raw JSON arrived   // mangled and the CLI died with `Invalid JSON args`. Wrap JSON in quotes with the inner quotes   // BACKSLASH-escaped so argv delivers it intact as ONE argument. Any JSON-carrying task MUST use this.-  const jarg = (verb, obj) => `${verb} "${JSON.stringify(obj).replace(/"/g, '\\"')}"`;+  // v1.9.115 — TASK COMMANDS MUST CARRY IDENTITY. AD (>=1.9.183) refuses ANY command with no caller+  // identity, and a jump-list task is a real CLI command that pup composes. Without --ai-thread John's+  // click on "Switch to logged-in view" was refused with caller_identity_required and silently did+  // NOTHING. Same root cause as the un-branded windows, in the one call path I failed to enumerate:+  // I fixed the bridge's OUTBOUND calls (adCommand) and forgot the commands pup hands to WINDOWS.+  // The thread name is honest here — a human clicked a taskbar menu, so that is who is asking, and it+  // is what the user will recognise in their own Activity Log.+  const jarg = (verb, obj) => `--ai-thread "user: pup taskbar menu" ${verb} "${JSON.stringify(obj).replace(/"/g, '\\"')}"`;   const taskArgs = (v) => jarg('browser_wiki_set_view', { sessionId, view: v });   // v1.9.51: a CLOSE-ALL task on every pup window (John: "i have like 8 open right now"). It calls   // browser_close with no sessionId, which kills every pup Chrome + clears every session. The empty@@ -5875,7 +5884,7 @@ function renderVerifyHint(sessionId, url, rc) {     const ex = rc.excerpt ? ' The page says: "' + String(rc.excerpt).replace(/\s+/g, ' ').slice(0, 140) + '".' : '';     return 'THIS PAGE DID NOT RENDER CORRECTLY — pup checked it, so do NOT report success. Detected: '       + sig + st + '.' + ex-      + ' See it yourself: `adom-desktop browser_screenshot {"sessionId":"' + sid + '"}`.'+      + ' See it yourself: `adom-desktop --ai-thread "<your thread>" browser_screenshot {"sessionId":"' + sid + '"}`.'       + ' Then FIX THE CAUSE: a 404 or "Cannot GET" usually means the dev server is not running, is on a'       + ' different port, or the path is wrong; unstyled HTML means the CSS 404d; a stack trace means the'       + ' app threw. After fixing, `browser_reload` and re-check until this response comes back clean.'@@ -5885,7 +5894,7 @@ function renderVerifyHint(sessionId, url, rc) {     ? 'THIS LOOKS LIKE CONTENT YOU JUST BUILT OR EDITED — SCREENSHOT IT AND LOOK BEFORE YOU CLAIM IT WORKS.'     : 'VERIFY WHAT YOU JUST PUT ON SCREEN — do not assume it rendered.';   return `${lead} ok:true means the NAVIGATION succeeded; it says NOTHING about whether the page actually painted. `-    + `Take a screenshot and READ the image: \`adom-desktop browser_screenshot {"sessionId":"${sid}"}\` — it returns a real PNG path you can open. `+    + `Take a screenshot and READ the image: \`adom-desktop --ai-thread "<your thread>" browser_screenshot {"sessionId":"${sid}"}\` — it returns a real PNG path you can open. `     + `Look for: a blank or white page, an unstyled flash of plain HTML (CSS never loaded), a stack trace or framework error overlay, `     + `missing images, a broken or overlapping layout, content cut off past the fold, a dev-server "Cannot GET /" page, or the wrong build entirely. `     + `If it is wrong: fix the source, \`browser_reload\`, and screenshot AGAIN — ralph-test that loop until the render is genuinely correct, `@@ -9671,7 +9680,7 @@ async function desktopRecordStartImpl(opts) {       'pass confirmDesktopNotTabRecording: true and resend the call.'     );     err.code = 'desktop_record_needs_confirmation';-    err.hint = 'For pup tab recording: adom-desktop browser_record_start \'{"sessionId":"<id>","fps":30}\'. ' ++    err.hint = 'For pup tab recording: adom-desktop --ai-thread "<your thread>" browser_record_start \'{"sessionId":"<id>","fps":30}\'. ' +                'For Hydrogen-driven desktop recording: hydrogen recording start --share screen. ' +                'For a parallel desktop clip alongside Hydrogen tab capture: re-call with confirmDesktopNotTabRecording: true.';     throw err;