Pup - Puppeteer Bridge
Public Made by Adomby adom
pup is the AI's own browser: a real, full Chrome on the user's desktop that the AI fully controls (a sandbox, not the user's signed-in browser). Rides Bridge; pup_* verbs open windows and tabs, navigate, screenshot, and eval JS.
AD bridge-lifecycle: (1) re-run npm install when a bridge's lockfile changes on re-sync [blocks fleet dep bumps], (2) cap/rotate bridge stdout logs, (3) bridge_log_read mixes AD lifecycle lines with bridge output
Three AD-core bridge-lifecycle gaps, all hit live 2026-07-24 while trying to ship a puppeteer bump (24.39.1 -> 24.43.1) to move the fleet's Chrome-for-Testing off the stale 146 onto 148. The bump is correct and verified on one box, but it will NOT reach the fleet until item 1 is fixed AD-side.
1. (BLOCKER) Re-run npm install on re-sync when the lockfile changed
preserve_client_deps() (added AD 1.9.169 to stop the MODULE_NOT_FOUND loop by carrying node_modules
across a source-only bridge re-sync) also preserves node_modules when a bridge's DEPENDENCIES change —
so a dependency bump silently never applies. Measured: bridge code re-synced to the new version
(BRIDGE_VERSION + package.json both updated to ^24.43.1), but the running bridge kept puppeteer
24.39.1 and Chrome 146. The only way to apply it was to manually bridge_kill, delete
node_modules, and respawn to force a fresh npm install (which then correctly installed 24.43.1 / CfT
148). This is the exact edge flagged when 1.9.169 shipped: "a preserved node_modules is stale if a
future bridge version changes its deps."
Ask: on re-sync, hash-compare the incoming package-lock.json against the installed one.
- unchanged -> preserve node_modules (today's fast path; the MODULE_NOT_FOUND fix stays intact)
- changed -> run
npm install/npm ciagainst the new lock, THEN continuenpm installis incremental, so an unchanged tree stays cheap. Without this, a bridge author cannot ship ANY dependency upgrade to the fleet — the CfT-148 bump reached exactly one machine.
2. Cap + rotate the bridge's captured stdout logs
AD captures each bridge's stdout into bridge-stdout.log / bridge-stderr.log with no visible size cap (AD's own startup.log was already ~725 KB). A long-running bridge grows them unbounded. This must live in AD: a bridge cannot rotate a file another process opened and holds, and every bridge (incl. third-party) needs bounded logs. Suggest a size cap + rotation (e.g. 5 MB, keep 2-3). We deliberately did NOT have pup write its own parallel log (two sources of truth, double the disk).
3. bridge_log_read interleaves AD lifecycle lines with the bridge's own output
bridge_log_read {name:"puppeteer"} returns the bridge's stdout MIXED with AD lifecycle lines like
[AD 2026-07-21 15:00:41] spawned process pid 16220 (node.exe). Reading "the puppeteer log" should
return the puppeteer bridge's output. Debugging repeatedly meant filtering AD's lines out of a bridge
log, and the tail was often ALL AD lifecycle lines, hiding the bridge output entirely. Either scope the
read to that bridge's stream, or return the two as separate labelled sections.
Related (nice-to-have, from the original staleness note)
- On AD self-update / a user clicking "Install now", force a re-check of every installed bridge's updateManifestUrl rather than waiting for the periodic poll.
- Surface bridge staleness:
status/ footer should show per-bridge installed-vs-latest + a stale flag; abridge_check_updatesverb to force it.
Not an AD bug, noting to avoid conflation: the puppeteer/CfT choice and the freeze diagnostics are ours (pup bridge). Only the three lifecycle items above are AD-core.