app
Pup - the AI's own browser
Public Made by Adomby adom
pup gives your AI a real browser on your desktop that it drives completely, in the background, signed in as you: windows that never jump in front of your work, one shared profile that learns your logins, and every window labeled on the taskbar with its AI thread's name.
← Commit history
1.8.98: move profiles/sessions out of the clobbered bridge cache to ~/.adom so persistence actually persists
6 files changed
+46−13
CHANGELOG.md+10@@ -1,5 +1,15 @@ # Changelog — Adom Desktop Puppeteer Bridge +## 1.8.98 — 2026-07-19 — Profiles live OUTSIDE the bridge cache (persistence actually persists)++Root-cause fix behind "the wiki login didn't survive": PROFILES_DIR/SESSIONS_DIR were inside the+bridge dir (bridges-cache\puppeteer), which AD CLOBBERS on every bridge_install — so every pup+update wiped every persistent profile, including the wiki-auth session. Moved both to the stable+~/.adom zone (pup-profiles / pup-sessions) with a one-time best-effort migration. Now "log in+once" genuinely lasts across updates, restarts, and reboots — for the wiki-auth vault and any+user profile. (The dev-skill "persistent profile = automatic 30-day storage" claim was only true+once this landed; a restart_bridge never clobbered, a bridge_install always did, which masked it.)+ ## 1.8.97 — 2026-07-19 — Gentle in-tab wiki mode indicator The AI picks the wiki view, so the user needs to SEE which one. A leading glyph on the TAB TITLE
adom-bridge-puppeteer-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "puppeteer",- "version": "1.8.97",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.8.97/adom-bridge-puppeteer-v1.8.97.zip",- "sha256": "0e288a765b96eb1e846ec3df27ebd8354879631510d980a12c3e77a140048922",- "size": 208002,+ "version": "1.8.98",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.8.98/adom-bridge-puppeteer-v1.8.98.zip",+ "sha256": "fb0002d79707b49c7ce12f4421082118cff3f8f5e29c96fafb12893d68057605",+ "size": 208384, "verbPrefixes": [ "browser_", "desktop_recorder_",
dev-skills/pup-bridge-dev/SKILL.md+9@@ -36,6 +36,15 @@ STOP: that decision is pup's, and the code that should change is in this repo. (The same test, run in reverse, is CLAUDE.md's existing rule: don't re-absorb AD capabilities into pup. The two directions together: mechanisms live in AD, decisions live here.) +## ⚠ STABLE PROFILE STORAGE (v1.8.98) — never put persistent state in the bridge dir++`PROFILES_DIR`/`SESSIONS_DIR` MUST live in `~/.adom` (pup-profiles / pup-sessions), NOT under+`__dirname`. `__dirname` is `bridges-cache\\puppeteer`, which AD CLOBBERS on every bridge_install —+so any persistent state stored there is wiped on every pup update. This silently destroyed every+persistent profile (incl. the wiki-auth 30-day login) until 1.8.98. It hid for a while because+`restart_bridge` does NOT clobber (only `bridge_install` does), so logins survived restarts but+died on the next version deploy. Rule: user-visible durable state → `~/.adom`, never the bridge dir.+ ## The THREE artifacts — know which is which (this is the #1 confusion) A user installs TWO different things from this one page. They are not the same:
src/BRIDGE_VERSION+1−1@@ -1 +1 @@-1.8.97+1.8.98
src/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "puppeteer", "displayName": "Puppeteer (Chrome for Testing + Native)",- "version": "1.8.97",+ "version": "1.8.98", "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.", "homepage": "https://wiki.adom.inc/adom/adom-desktop", "author": "Adom Inc.",
src/server.js+21−7@@ -119,15 +119,29 @@ const PUP_DEEP_HELPERS = `(function(){ async function ensureDeepHelpers(page) { try { await page.evaluate(PUP_DEEP_HELPERS); } catch (e) {} } -// Persistent Chrome profiles — each session gets its own userDataDir-// so IndexedDB, cookies, localStorage survive across restarts-const PROFILES_DIR = path.join(__dirname, 'profiles');+// Persistent Chrome profiles — each session gets its own userDataDir so IndexedDB, cookies,+// localStorage survive across restarts. v1.8.98: these live OUTSIDE the bridge dir, in the+// stable ~/.adom zone. __dirname is bridges-cache\puppeteer, which AD CLOBBERS on every+// bridge_install — storing profiles there wiped every persistent login (incl. the wiki-auth+// session) on every pup update. A stable home makes "log in once" actually last (across updates,+// restarts, reboots). One-time migration: pull an existing in-cache profiles/ dir over if present.+const ADOM_STATE_DIR = path.join(os.homedir(), '.adom');+const PROFILES_DIR = path.join(ADOM_STATE_DIR, 'pup-profiles');+const SESSIONS_DIR = path.join(ADOM_STATE_DIR, 'pup-sessions'); fs.mkdirSync(PROFILES_DIR, { recursive: true });--// Persistent session files — survive bridge restarts-// Each session gets a JSON file: sessions/<sessionId>.json-const SESSIONS_DIR = path.join(__dirname, 'sessions'); fs.mkdirSync(SESSIONS_DIR, { recursive: true });+// One-time migration from the old clobber-prone in-bridge locations (best-effort).+try {+ for (const [oldRel, dest] of [['profiles', PROFILES_DIR], ['sessions', SESSIONS_DIR]]) {+ const oldDir = path.join(__dirname, oldRel);+ if (fs.existsSync(oldDir) && fs.readdirSync(dest).length === 0) {+ for (const entry of fs.readdirSync(oldDir)) {+ try { fs.renameSync(path.join(oldDir, entry), path.join(dest, entry)); } catch (e) {}+ }+ console.log(`[migrate] moved ${oldRel}/ from the bridge cache to ${dest}`);+ }+ }+} catch (e) {} // Multi-session state: sessions are tabs within shared Chrome browsers // One Chrome process per profile (userDataDir), multiple tabs per Chrome.