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
Switch to public view on a shared-profile window no longer logs every thread out. John asked what should happen clicking the jump-list view toggle on a multi-tab window; the code answer was a browser-wide cookie wipe (CDP clearBrowserCookies) that silently signed out every window of every thread, then reloaded only the active tab, because the shared-profile guard tested the legacy adom-wiki-authed profile name and never matched today's shared adom-you. The guard now uses ground truth (any other live session on the same profile, plus the known shared names), so a shared-profile public switch takes the tab-preserving relaunch path: the whole window with all its tabs moves to a logged-out profile and no other window is touched. Also ships the quieted 60s overlay re-assert logging staged earlier
4 files changed
+28−9
adom-bridge-puppeteer-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "puppeteer",- "version": "2.0.47",- "url": "https://wiki.adom.inc/download/adom/pup-bridge/2.0.47/adom-bridge-puppeteer-v2.0.47.zip",- "sha256": "48a4b71c36598371e28661de400376d17992fdb4d3fbff562fd5d41c7b68e695",- "size": 650037,+ "version": "2.0.48",+ "url": "https://wiki.adom.inc/download/adom/pup-bridge/2.0.48/adom-bridge-puppeteer-v2.0.48.zip",+ "sha256": "02f08c6ef2a42774473c32e6da887899a919a38de377a1947579143df1e46cbb",+ "size": 650601, "verbPrefixes": [ "browser_", "desktop_recorder_",
src/BRIDGE_VERSION+1−1@@ -1 +1 @@-2.0.47+2.0.48
src/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "puppeteer", "displayName": "Puppeteer (Chrome for Testing + Native)",- "version": "2.0.47",+ "version": "2.0.48", "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. pup_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. pup_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, pup_alert_window posts a native toast whose click focuses the window, pup_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-bridge", "author": "Adom Inc.",
src/server.js+22−3@@ -11479,8 +11479,18 @@ const server = http.createServer(async (req, res) => { // Guard: only wipe cookies when this window owns its profile. The shared authed profile // backs OTHER windows too and clearing it would silently log them all out — fall through // to the legacy relaunch in that case.- const _sharedAuthed = /adom-wiki-authed/i.test(session.profileName || '');- const _canInPlace = (view === 'authed') ? true : !_sharedAuthed;+ // v2.0.48 (John: "what should happen when i click this if there are multiple tabs in that+ // window?"): the unit is the WINDOW — but cookies are per PROFILE and CDP's+ // Network.clearBrowserCookies is BROWSER-wide, so on a SHARED profile the in-place public+ // switch wiped EVERY thread's cookies (silent global logout) and reloaded only one tab.+ // The old guard tested the LEGACY profile name (adom-wiki-authed) and never matched+ // today's shared adom-you. Ground truth instead: the profile is shared if ANY other live+ // session rides it (plus the known shared names). A shared-profile public switch now takes+ // the tab-preserving RELAUNCH path: the whole window (all tabs) moves to a logged-out+ // profile; every other window keeps its login.+ let _profileShared = /adom-wiki-authed|adom-you/i.test(session.profileName || '');+ try { for (const [k5, s5] of sessions) { if (k5 !== sessionId && s5 && s5.profileName === session.profileName) { _profileShared = true; break; } } } catch (e) {}+ const _canInPlace = (view === 'authed') ? true : !_profileShared; if (_canInPlace) { try { let targetUrl = null;@@ -14550,6 +14560,7 @@ const _onPupBound = async () => { if (s2._appOverlay && Date.now() - (s2._overlayReassertAt || 0) > 60000) { s2._overlayReassertAt = Date.now(); s2._lastPaintSig = null; s2._appOverlay = false;+ s2._overlayReassertQuiet = true; // v2.0.48: periodic re-assert, not a real bare-heal — log quietly } const bare = !s2._appOverlay; // A window whose page genuinely has NO favicon anywhere sits on the generic glyph forever, and@@ -14576,7 +14587,15 @@ const _onPupBound = async () => { s2._overlayGenericTries = (s2._overlayGenericTries || 0) + 1; if (s2._overlayGenericTries >= 3) { s2._overlayGenericFinal = true; console.log(`[overlay] "${sid2}" still has no favicon after 3 upgrade attempts — accepting generic glyph as final; will retry on next navigation`); } }- else if (bare) console.log(`[overlay] "${sid2}" ENFORCED (was bare) — every pup window must wear its overlay`);+ else if (bare) {+ // v2.0.48 (John saw "ENFORCED (was bare)" spam every minute): the 60s ground-truth+ // re-assert is EXPECTED repainting, not a heal — don't announce it as one. Log a real+ // bare-heal loudly, and the periodic re-assert only once per ~10 min per window.+ if (s2._overlayReassertQuiet) {+ s2._overlayReassertQuiet = false;+ if (!s2._reassertLogAt || Date.now() - s2._reassertLogAt > 600000) { s2._reassertLogAt = Date.now(); console.log(`[overlay] "${sid2}" periodic ground-truth re-assert (60s cycle; logged at most every 10 min)`); }+ } else console.log(`[overlay] "${sid2}" ENFORCED (was bare) — every pup window must wear its overlay`);+ } }).catch(() => {}); } } catch (e) {}