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
v1.9.14: revert overlay padlock (favicons keep that slot), put wiki login state on the main icon as a solid green filled browser glyph
6 files changed
+27−52
CHANGELOG.md+16@@ -1,5 +1,21 @@ # Changelog — Adom Desktop Puppeteer Bridge +## 1.9.14 — 2026-07-19 — Login state on the MAIN icon; overlay stays favicons (reverted 1.9.13)++REVERTED 1.9.13's overlay-slot padlock. John was explicit: the overlay is for FAVICONS ("i LOVE+seeing those favicons in that overlay") and the login indicator belongs on the MAIN icon. That was+his instruction from the start and I should not have moved it. The overlay is favicon-only again,+exactly as it was in 1.9.0.++The main-icon indicator is now what he actually asked for - the lower-right browser-window glyph+FILLED IN SOLID when signed in - with one deviation for legibility: it fills with signed-in GREEN+rather than dark. Rendered at true 24px (what Windows actually paints), a dark fill blended into+the glyph's own dark stroke; the colour flip is what survives downscaling. Geometry is identical+between the two icons so they register perfectly and only the fill changes.+ adom-pup-browser3.ico - browser-window glyph, teal/hollow = logged OUT / non-wiki window+ adom-pup-wiki-authed2.ico - same glyph FILLED SOLID GREEN = signed in to the Adom wiki+Also dropped the 1.9.12 padlock variant: changing SHAPE is exactly the detail that dies at 24px.+ ## 1.9.13 — 2026-07-19 — Login state moves to the OVERLAY slot (readable at real taskbar size) Honest follow-up to 1.9.12: the base-icon corner glyph (browser outline vs padlock) works
adom-bridge-puppeteer-manifest.json+5−5@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "puppeteer",- "version": "1.9.13",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.13/adom-bridge-puppeteer-v1.9.13.zip",- "sha256": "a8787ddf23c0e708756fd0b35a285fdcebb9f8ccb7a8825e1e96273b79b9dae1",- "size": 238353,+ "version": "1.9.14",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.14/adom-bridge-puppeteer-v1.9.14.zip",+ "sha256": "078a72b32d2261681c1323437900077b74c71250d76cd15d245a22d6224ab71a",+ "size": 235627, "verbPrefixes": [ "browser_", "desktop_recorder_",@@ -12,5 +12,5 @@ ], "healthEndpoint": "/status", "statusVerb": "browser_readiness",- "released_at": "2026-07-19T23:45:00Z"+ "released_at": "2026-07-20T00:00:00Z" }
src/BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.13+1.9.14
src/adom-pup-wiki-authed.svg+3−3@@ -1,4 +1,4 @@-<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 244 244"><defs><style>.cls-1{fill:none;}.cls-1,.cls-2,.cls-3,.cls-4{stroke-width:0px;}.cls-2{fill:#00b8b0;}.cls-3{fill:#fff;}.cls-4{fill:#003d40;}.cls-5{clip-path:url(#clippath);}</style><clipPath id="clippath"><rect class="cls-1" x="2.33" y="2.33" width="239.33" height="239.33"/></clipPath></defs><path class="cls-3" d="M184.3,59.7c-16.95-16.95-41.26-20.14-54.29-7.11-5.29,5.29-7.9,12.43-8.01,20.18h0s0,0,0,0c0,.03,0,.05,0,.08v48.09c0,.58.47,1.05,1.05,1.05h47.57-.01c7.99,0,15.37-2.6,20.79-8.02,13.03-13.03,9.84-37.33-7.11-54.29Z"/><path class="cls-3" d="M59.7,184.3c16.95,16.95,41.26,20.14,54.29,7.11,5.29-5.29,7.9-12.43,8.01-20.18h0s0,0,0,0c0-.03,0-.05,0-.08v-48.09c0-.58-.47-1.05-1.05-1.05h-47.57.01c-7.99,0-15.37,2.6-20.79,8.02-13.03,13.03-9.84,37.33,7.11,54.29Z"/><g class="cls-5"><path class="cls-2" d="M206.67,241.67H37.33c-19.33,0-34.99-15.67-34.99-34.99V37.33C2.33,18,18,2.33,37.33,2.33h169.34c19.33,0,34.99,15.67,34.99,34.99v169.34c0,19.33-15.67,34.99-34.99,34.99"/><path class="cls-4" d="M173.76,70.24c-14.09-14.09-34.28-16.73-45.1-5.91-4.39,4.39-6.56,10.33-6.66,16.77h0v40.03c0,.48.39.88.88.88h39.52,0c6.64,0,12.77-2.16,17.28-6.66,10.82-10.82,8.18-31.02-5.91-45.1"/><path class="cls-4" d="M70.24,173.76c14.09,14.09,34.28,16.73,45.1,5.91,4.39-4.39,6.56-10.33,6.66-16.77h0v-40.03c0-.48-.39-.88-.88-.88h-39.52,0c-6.64,0-12.77,2.16-17.28,6.66-10.82,10.82-8.18,31.02,5.91,45.1"/></g><g id="pup-lock-solid">- <path d="M 172 182 V 168 A 15 15 0 0 1 202 168 V 182" fill="none" stroke="#003d40" stroke-width="12" stroke-linecap="round"/>- <rect x="156" y="180" width="62" height="44" rx="11" fill="#003d40"/>+<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 244 244"><defs><style>.cls-1{fill:none;}.cls-1,.cls-2,.cls-3,.cls-4{stroke-width:0px;}.cls-2{fill:#00b8b0;}.cls-3{fill:#fff;}.cls-4{fill:#003d40;}.cls-5{clip-path:url(#clippath);}</style><clipPath id="clippath"><rect class="cls-1" x="2.33" y="2.33" width="239.33" height="239.33"/></clipPath></defs><path class="cls-3" d="M184.3,59.7c-16.95-16.95-41.26-20.14-54.29-7.11-5.29,5.29-7.9,12.43-8.01,20.18h0s0,0,0,0c0,.03,0,.05,0,.08v48.09c0,.58.47,1.05,1.05,1.05h47.57-.01c7.99,0,15.37-2.6,20.79-8.02,13.03-13.03,9.84-37.33-7.11-54.29Z"/><path class="cls-3" d="M59.7,184.3c16.95,16.95,41.26,20.14,54.29,7.11,5.29-5.29,7.9-12.43,8.01-20.18h0s0,0,0,0c0-.03,0-.05,0-.08v-48.09c0-.58-.47-1.05-1.05-1.05h-47.57.01c-7.99,0-15.37,2.6-20.79,8.02-13.03,13.03-9.84,37.33,7.11,54.29Z"/><g class="cls-5"><path class="cls-2" d="M206.67,241.67H37.33c-19.33,0-34.99-15.67-34.99-34.99V37.33C2.33,18,18,2.33,37.33,2.33h169.34c19.33,0,34.99,15.67,34.99,34.99v169.34c0,19.33-15.67,34.99-34.99,34.99"/><path class="cls-4" d="M173.76,70.24c-14.09-14.09-34.28-16.73-45.1-5.91-4.39,4.39-6.56,10.33-6.66,16.77h0v40.03c0,.48.39.88.88.88h39.52,0c6.64,0,12.77-2.16,17.28-6.66,10.82-10.82,8.18-31.02-5.91-45.1"/><path class="cls-4" d="M70.24,173.76c14.09,14.09,34.28,16.73,45.1,5.91,4.39-4.39,6.56-10.33,6.66-16.77h0v-40.03c0-.48-.39-.88-.88-.88h-39.52,0c-6.64,0-12.77,2.16-17.28,6.66-10.82,10.82-8.18,31.02,5.91,45.1"/></g><g id="pup-browser-solid-authed">+ <rect x="152" y="156" width="70" height="58" rx="10" fill="#22c55e" stroke="#003d40" stroke-width="11"/>+ <line x1="152" y1="178" x2="222" y2="178" stroke="#003d40" stroke-width="9"/> </g></svg>
src/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "puppeteer", "displayName": "Puppeteer (Chrome for Testing + Native)",- "version": "1.9.13",+ "version": "1.9.14", "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+1−42@@ -1703,7 +1703,7 @@ let _jumplistSupported = null; // null = unprobed (desktop_set_window_jumplist // The OVERLAY slot is NOT used for this — it belongs to the active tab's favicon (v1.9.0). // NEW FILENAME on any art change, always: the shell + AD cache HICONs by PATH (stale-tile trap). const PUP_ICON_DEFAULT = 'adom-pup-browser3.ico';-const PUP_ICON_WIKI_AUTHED = 'adom-pup-wiki-authed1.ico';+const PUP_ICON_WIKI_AUTHED = 'adom-pup-wiki-authed2.ico'; function pupSessionAuthed(sessionId) { try { const s = sessionId && sessions.get(sessionId); return !!(s && s._wikiAuthed); } catch (e) { return false; } }@@ -1823,7 +1823,6 @@ async function setWikiAuthedState(session, sessionId, authed) { console.log(`[identity] "${sessionId}" wiki login state -> ${next ? 'LOGGED IN (green closed padlock)' : 'logged out (slate open padlock)'}`); try { await stampPupIdentity(sessionId); } catch (e) {} try { await registerPerSessionAumid(`${PUP_APP_ID}.${sessionId}`); } catch (e) {}- try { await updateTabCountBadge(session, sessionId); } catch (e) {} // repaint the lock overlay return true; } // v1.9.3 (AD #208 — desktop_set_window_jumplist, AD ≥1.9.139): give each WIKI pup window a@@ -1924,32 +1923,6 @@ async function dualBadgeB64(wins, tabs) { } catch (e) { return null; } } -// v1.9.12b: LOGIN-STATE OVERLAY for Adom wiki windows. The overlay slot is the one surface-// Windows actually designs for status (painted ~16px bottom-right of the taskbar button), and it-// is far more legible than the corner glyph baked into the 24px base icon. On an ADOM WIKI window-// the favicon that normally rides here is the ADOM LOGO — redundant with the pup base icon, which-// is already Adom — so the slot is free to carry real information. Non-Adom sites (ti.com,-// digikey, ...) keep their favicon, which genuinely tells you where you are.-// GREEN + closed padlock = signed in to the Adom wiki-// SLATE + open padlock = logged out / public view-const _wikiLockB64 = new Map();-function wikiLockOverlay(authed) {- const key = authed ? 'locked' : 'unlocked';- if (_wikiLockB64.has(key)) return _wikiLockB64.get(key);- try {- const b = fs.readFileSync(path.join(__dirname, 'icons', 'wiki-lock', `${key}-32.png`)).toString('base64');- _wikiLockB64.set(key, b);- return b;- } catch (e) { return null; }-}-// Is this session currently showing an Adom URL (so the lock, not the favicon, owns the slot)?-function sessionOnAdomUrl(session) {- try {- const t = (session.tabs || []).find(x => x.tabId === session.activeTabId) || (session.tabs || [])[0];- const pg = (t && t.page) || session.page;- return isAdomUrl(pg && pg.url());- } catch (e) { return false; }-} async function updateTabCountBadge(session, sessionId) { if (process.platform !== 'win32' || _identitySupported !== true) return; // overlay busy with brand badge on old AD try {@@ -1975,20 +1948,6 @@ async function updateTabCountBadge(session, sessionId) { // rides in the hover tooltip. Only if the active page has NO favicon do we fall back to a // plain count badge (so a many-tab faviconless window isn't a blank Adom tile). const count = (session.tabs || []).length;- // v1.9.12b: Adom wiki window -> the LOCK owns the overlay (its favicon would just repeat the- // Adom mark already in the base icon). This is the readable login indicator.- if (sessionOnAdomUrl(session)) {- const authed = !!session._wikiAuthed;- const lock = wikiLockOverlay(authed);- if (lock) {- await chrome.adCommand('desktop_taskbar', {- titleContains: `(session: ${sessionId}`,- overlay: { icon: lock, tooltip: `Adom Pup — Adom wiki: ${authed ? 'SIGNED IN' : 'public / logged out'} · ${count} tab${count === 1 ? '' : 's'}` },- }, { timeoutMs: 5000 });- session._appOverlay = true;- return;- }- } const worn = await applyAppOverlay(session, sessionId); // active tab's favicon + count in tooltip if (worn) return; session._appOverlay = false;