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
The core goal made explicit + adom-you visibility + AUMID-consistent dashboard (three John asks). (1) Every work window in the dashboard now wears a prominent chip: green 'surfing as adom-you' (with a tooltip explaining that every login it makes enriches the shared credential store so pup can auto-fill it everywhere later) or amber 'NOT adom-you: <profile>' - and the header subject line counts N/M windows on adom-you, because the goal is as many as possible. (2) THE CORE GOAL is now written at the top of the pup user skill and the README, in John's framing: pup exists to be an AI-driven browser that can do everything it needs to for you, the best assistant in the world; the engine is the shared adom-you profile whose accumulated logins let pup automatically sign in to every site it has ever seen; isolation is the exception that builds nothing (the README's stale 'every session is a fresh isolated process' pre-durable-profile copy corrected too). (3) AUMID-mode consistency (John: 'if we're in aumid mode then the pup dashboard should be in that mode too'): instead of being exempt from stamping, the dashboard now stamps its own DEDICATED Adom.Pup.Dashboard identity - its own taskbar button in every mode (never absorbed by grouped), wearing the adom app tile so the taskbar reads as one consistent family.
4 files changed
+20−14
adom-bridge-puppeteer-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "puppeteer",- "version": "1.9.271",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.271/adom-bridge-puppeteer-v1.9.271.zip",- "sha256": "276c09f0e0fb63f36ca75ca7aeda9ebfd15227e55163361deb05a9974664b1f8",- "size": 615174,+ "version": "1.9.272",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.272/adom-bridge-puppeteer-v1.9.272.zip",+ "sha256": "12669e7133f786e9375bd02626025752b69693808b9b0d6a1e96952932d46e4d",+ "size": 615562, "verbPrefixes": [ "browser_", "desktop_recorder_",
src/BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.271+1.9.272
src/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "puppeteer", "displayName": "Puppeteer (Chrome for Testing + Native)",- "version": "1.9.271",+ "version": "1.9.272", "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−8@@ -2872,6 +2872,7 @@ function pupSessionAuthed(sessionId) { try { const s = sessionId && sessions.get(sessionId); return !!(s && s._wikiAuthed); } catch (e) { return false; } } function pupIconPath(sessionId) {+ if (sessionId === 'pup-dashboard') return path.join(__dirname, 'icons', PUP_CAT_ICONS.app || PUP_ICON_DEFAULT); // v1.9.261 (John): aumidIconStyle 'standard' = ONE icon for every AUMID window (the default pup // tile); 'category' = the custom per-category set (wiki signed-out, wiki signed-IN padlock, world // icon for the open web, adom app icon, mixed).@@ -2908,11 +2909,11 @@ async function ensurePupIdentityRegistered() { } catch (e) { console.log(`[identity] register threw: ${e.message}`); return false; } } async function stampPupIdentity(sessionId, opts) {- // v1.9.271 (John: "make the pup dashboard be its own taskbar icon so its not ganged with the- // other pup windows"): the dashboard is pup INFRASTRUCTURE, not a work window. It runs on its own- // profile (= its own Chrome process = its own taskbar button naturally), and stamping it with the- // shared/grouped AUMID is what ganged it onto the common button. Never stamp it, in any mode.- if (sessionId === 'pup-dashboard') return false;+ // v1.9.271: the dashboard must never gang onto the shared button. v1.9.272 (John: "if we're in+ // aumid mode then the pup dashboard should be in that mode too. right now you're being+ // inconsistent"): so in AUMID mode it gets its OWN DEDICATED identity (Adom.Pup.Dashboard) - own+ // button always, but wearing the same tile system as every other stamped window. The flag rides+ // to the appId computation below; grouped mode never absorbs it. // v1.9.185 minimal-touch: the AUMID stamp is the single most invasive thing pup does to a window // it does not own (Windows DESTROYS and RECREATES the taskbar button on an AppUserModelID change). // Gated at the choke point so no caller can leak it.@@ -2974,11 +2975,13 @@ async function stampPupIdentity(sessionId, opts) { } if (sess) sess._plainStampAttempts = 0; const cat = rawCat || 'plain';- const appId = grouped ? PUP_APP_ID : `${PUP_APP_ID}.${sessionId}.${cat}.${PUP_ICON_GEN}`;+ const _dashInfra = sessionId === 'pup-dashboard';+ const appId = _dashInfra ? `${PUP_APP_ID}.Dashboard.${PUP_ICON_GEN}`+ : grouped ? PUP_APP_ID : `${PUP_APP_ID}.${sessionId}.${cat}.${PUP_ICON_GEN}`; const prevAppId = sess && sess._curAppId; // Register the NEW appId BEFORE stamping (AD's verified order) so the fresh button resolves // its icon/name from the registry the moment it is created.- if (!grouped && prevAppId !== appId) {+ if ((!grouped || _dashInfra) && prevAppId !== appId) { try { await registerPupAumid(appId, sessionId); } catch (e) {} // v1.9.61 — ORDER MATTERS (the live-tile trap, from AD's window-identity skill): Win11 bakes a // taskbar button's art when the button is CREATED and never re-reads it. Stamping the new appId@@ -8342,6 +8345,7 @@ main{padding:14px 18px} .meta{color:#7d8f9f;font-size:12px} .tag{font-size:11px;border-radius:5px;padding:1px 7px;border:1px solid #23303c;color:#9fb0c0} .tag.fg{background:#00b8b11a;border-color:#00b8b1;color:#00b8b1}+.tag.ok{background:#3fb9501a;border-color:#3fb950;color:#3fb950} .tag.hf{background:#d299221a;border-color:#d29922;color:#e3b341} .tag.warn{background:#f851491a;border-color:#f85149;color:#ff7b72} .tag.vp{background:#a371f71a;border-color:#a371f7;color:#c297ff}@@ -8371,7 +8375,7 @@ footer{color:#5c6c7a;font-size:11px;padding:8px 18px 22px} <div class="vsep"></div> <div class="subject"> <span class="sname"><span class="dot" id="live"></span><span id="subjName">all windows</span></span>- <span class="smeta"><b id="cW">0</b> windows · <b id="cT">0</b> tabs · <b id="cB">0</b> icons · <span id="cLed" title="green: every taskbar button wears its real page-favicon overlay and no untracked pup windows exist. red: a window is bare or unmodeled."><span class="led red" id="cLedDot"></span> <b id="cLedTxt">?</b></span> · <span id="age"></span></span>+ <span class="smeta"><b id="cW">0</b> windows · <b id="cT">0</b> tabs · <b id="cB">0</b> icons · <span id="cAY" title="windows surfing on the shared adom-you profile / total work windows. More adom-you = a richer shared login store = pup auto-fills more sites for you over time.">?</span> adom-you · <span id="cLed" title="green: every taskbar button wears its real page-favicon overlay and no untracked pup windows exist. red: a window is bare or unmodeled."><span class="led red" id="cLedDot"></span> <b id="cLedTxt">?</b></span> · <span id="age"></span></span> </div> <div class="acts2"> <button class="ibtn" id="gear" title="pup settings" aria-label="settings"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h0a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h0a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v0a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></button>@@ -8426,6 +8430,7 @@ function render(){ if(d.bridge&&d.bridge.version&&d.bridge.version!==PAGE_VERSION){location.reload();return;} _q('#cW').textContent=d.counts.windows; _q('#cT').textContent=d.counts.tabs; _q('#cB').textContent=(d.taskbarButtons||[]).length; _q('#cV').textContent=d.bridge.version;+ (function(){const ws=(d.windows||[]).filter(w=>w.sessionId!=='pup-dashboard');const ay=ws.filter(w=>w.profile==='adom-you').length;_q('#cAY').textContent=ay+'/'+ws.length;})(); _q('#popMeta').textContent=d.bridge.platform+' \u00b7 bridge up '+ago(d.bridge.uptimeMs)+' \u00b7 deps '+(d.bridge.depsOk?'ok':'missing'); _q('#subjName').textContent=(_q('#f').value||'all windows'); for(const t of (d.toasts||[])){ if(t.id>SEENTOAST){SEENTOAST=t.id;toast(t.msg,t.type);} }@@ -8481,6 +8486,7 @@ function render(){ +'<img class="ico" src="'+badge(w.sessionId)+'" data-fallback="hide">' +'<span class="nm">'+esc(w.sessionId)+'</span>' +'<span class="tag '+(w.foreground?'fg':'')+'">'+(w.foreground?'FG':'bg')+'</span>'+ +(w.sessionId==='pup-dashboard'?'<span class="tag">dashboard</span>':(w.profile==='adom-you'?'<span class="tag ok" title="surfing on the shared adom-you profile: every login this window makes enriches the shared credential store, so pup can auto-fill it everywhere later">surfing as adom-you</span>':'<span class="tag warn" title="NOT on adom-you: logins made here do NOT build the shared credential store. Prefer adom-you unless isolation is genuinely needed.">NOT adom-you: '+esc(w.profile)+'</span>')) +(w.owner?'<span class="tag">'+esc(w.owner)+(w.ownerSource==='caller-identity'?' ✓':'')+'</span>':'<span class="tag warn">UNOWNED</span>') +(w.highFps?'<span class="tag hf">highFps '+w.highFpsMinutesLeft+'m</span>':'') +(w.emulatedViewport?'<span class="tag vp">vp '+w.emulatedViewport.width+'x'+w.emulatedViewport.height+'</span>':'')