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
v2.0.292: Settings audit/consolidation (John): collapse openFlash + autoFlash + agentActivity + fgWatch into the single taskbarActivity control (progress|flash|off) + notMineCaption. fgWatch's foreground-STEAL purpose died with off-screen birth; its 20s self-foreground caption now honors notMineCaption. Fixed stale titleTag description (resolution is the SetProp tag now, not the title). Removed the 4 rows + their whitelist/defaults.
4 files changed
+27−32
adom-bridge-puppeteer-manifest.json+5−5@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "puppeteer",- "version": "2.0.291",- "url": "https://wiki.adom.inc/download/adom/pup-bridge/2.0.291/adom-bridge-puppeteer-v2.0.291.zip",- "sha256": "f21d35d92e43a4ba0162916a360a7f964fe90ceb62cdb838fdb2101c61e415cc",- "size": 996120,+ "version": "2.0.292",+ "url": "https://wiki.adom.inc/download/adom/pup-bridge/2.0.292/adom-bridge-puppeteer-v2.0.292.zip",+ "sha256": "a6b8ab90a27b1f0cad2e7dbb5c2cec51eb107b118a3b4316a5aab86d5f5910a9",+ "size": 996148, "verbPrefixes": [ "browser_", "desktop_recorder_",@@ -12,5 +12,5 @@ ], "healthEndpoint": "/status", "statusVerb": "browser_readiness",- "released_at": "2026-08-23T10:59:29.395433Z"+ "released_at": "2026-08-23T11:21:20.850287Z" }
src/BRIDGE_VERSION+1−1@@ -1 +1 @@-2.0.291+2.0.292
src/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "puppeteer", "displayName": "Puppeteer (Chrome for Testing + Native)",- "version": "2.0.291",+ "version": "2.0.292", "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+20−25@@ -3549,8 +3549,8 @@ function pupSettings() { // that is resolved, so a FRESH user now gets the good experience John runs with, not the old // all-windows-stacked-under-one-button mode. (Existing users' explicit choices are untouched — // the _chosen tracking means flipping a default only moves users who never set the key.)- const D = { aumidIcons: 'on', jumpLists: 'on', fgWatch: 'on', fgCaption: 'on', fgCaptionMs: 2000,- overlayBadges: 'on', autoFlash: 'off', sleepRecovery: 'on', openFlash: 'off',+ const D = { aumidIcons: 'on', jumpLists: 'on', fgCaption: 'on', fgCaptionMs: 2000,+ overlayBadges: 'on', sleepRecovery: 'on', // v2.0.262 (John): the badge at full size covers the BOTTOM LINE of the thread tile's // name, and that text is the whole point of thread tiles ("i'm finding that the text is // super valuable so i want to be able to see it"). '50' composites the same badge at half@@ -3569,16 +3569,12 @@ function pupSettings() { // favorite"): now ON by default, and the first row in the Settings dialog. _chosen // tracking means this only moves users who never set the key themselves. threadTiles: 'on' };- D.openFlash = 'on'; // v1.9.262 (John: "why did you default it to off when its defaulted to on")- if (_pupSettings.openFlash === 'off' && !_pupSettings._openFlashChosen) _pupSettings.openFlash = 'on';- // v1.9.268 (John on autoFlash: "this should be on by default")- D.autoFlash = 'on';- const chosen = _pupSettings._chosen || {};- if (_pupSettings.autoFlash === 'off' && !chosen.autoFlash) _pupSettings.autoFlash = 'on';+ // v2.0.292: openFlash / autoFlash / agentActivity / fgWatch REMOVED — collapsed into taskbarActivity+ // (progress|flash|off) and notMineCaption. Their gates now read taskbarActivity/notMineCaption. // v1.9.268 (John on autoLogin: "this should be on by default" - and it always WAS behavior-default // on via the !== 'off' checks, but the dialog rendered the unset key as an OFF toggle: a display // lie). Legacy keys get explicit defaults so the dialog reflects actual behavior.- D.autoLogin = 'on'; D.reportIssues = 'on'; D.agentActivity = 'on';+ D.autoLogin = 'on'; D.reportIssues = 'on'; // v2.0.289 (John): how pup signals activity on a window's taskbar button. 'progress' = a DETERMINATE // progress bar sized to the running-average time of the operation (icon-apply, screenshot, ...) — // the new default, replacing the orange flash. 'flash' = the old orange taskbar highlight@@ -5819,7 +5815,7 @@ async function toastForeground(sessionId, reason) { } function markSessionBusy(sessionId) { if (process.platform !== 'win32' || !sessionId) return;- if (pupSettings().agentActivity === 'off') return; // user opt-out via pup_configure+ if (taskbarActivityMode() !== 'progress') return; // v2.0.292: driving-strip folded into taskbarActivity='progress' if (!sessions.has(sessionId)) return; let st = _busyState.get(sessionId); if (!st) { st = { busy: false, timer: null }; _busyState.set(sessionId, st); }@@ -9794,7 +9790,7 @@ const _flashState = new Map(); // sessionId -> last flash ts const _openFlashDone = new Map(); // sessionId -> ts of the launch flash for the current open function scheduleAutoFlash(session, opts) { opts = opts || {};- if (pupSettings().autoFlash !== 'on') return; // v1.9.259: explicit pref (default off = old minimal-touch behavior)+ if (taskbarActivityMode() !== 'flash') return; // v2.0.292: autoFlash folded into taskbarActivity='flash' if (process.platform !== 'win32' || !session || !session._sessionId) return; if (opts.silent || session._flashSilent) return; const key = session._sessionId;@@ -10838,7 +10834,7 @@ async function launchSession(sessionId, url, { freshProfile = false, profile, st // the open handler's later scheduleAutoFlash debounces (no double flash). Fire-and-forget. if (!foreground && !silent && process.platform === 'win32') { // v1.9.185 minimal-touch: no taskbar flash at all (and no log noise pretending one fired).- if (pupSettings().openFlash === 'on') { try { _flashState.set(sessionId, Date.now()); _openFlashDone.set(sessionId, Date.now()); console.log(`[flash] "${sessionId}" (launch)`); flashViaAD(sessionId, { force: true }); } catch (e) {} }+ if (taskbarActivityMode() === 'flash') { try { _flashState.set(sessionId, Date.now()); _openFlashDone.set(sessionId, Date.now()); console.log(`[flash] "${sessionId}" (launch)`); flashViaAD(sessionId, { force: true }); } catch (e) {} } // v2.0.292: openFlash folded into taskbarActivity='flash' } if (url) {@@ -12631,7 +12627,7 @@ const SETTINGS_DEF=[ {k:'overlayBadges',l:'Favicon overlay badges',d:'Paint each pup taskbar icon with the favicon of its active tab plus the Adom mark.'}, {k:'overlaySize',l:'Badge size',d:'Percent of full size for the badge. Smaller keeps it clear of the tile\u2019s text.',sel:['50','66','75','100'],selLabels:{'50':'50% \u2014 smallest, maximum text clearance','66':'66%','75':'75% \u2014 balanced (default)','100':'100% \u2014 full size'},dep:'overlayBadges'}, {k:'taskbarGrouping',l:'AUMID grouping',d:'Only applies when AUMID icons are on. split = one taskbar button per window. grouped = windows grouped BY CATEGORY when icon-style is "category" (up to 5 buttons: signed-in wiki, public wiki, open web, Adom app, plain — e.g. all your signed-in-wiki windows collapse under the one padlock button); with icon-style "standard" grouped collapses everything under a single Adom Pup button.',sel:['split','grouped'],depMode:'aumid',imgBy:{split:'groupsplit',grouped:'groupgrouped'}},- {k:'taskbarActivity',l:'Taskbar activity signal',d:'How pup shows it is working on a window, on that window’s taskbar button. "progress" (default): a determinate progress bar sized to how long the operation usually takes (applying the window icon, taking a screenshot, ...); pup keeps a per-operation running average and fills the bar over it. "flash": the older orange taskbar highlight. "off": neither. Windows only. The example switches with your choice.',sel:['progress','flash','off'],selLabels:{'progress':'progress bar (default)','flash':'orange flash (old)','off':'off'},imgBy:{progress:'tbactprogress',flash:'tbactflash',off:'tbactoff'}},+ {k:'taskbarActivity',l:'Taskbar activity signal',d:'The single control for how pup signals it is working on a window, on that window’s taskbar button. "progress" (default): a determinate progress bar sized to how long the operation usually takes (applying the window icon, taking a screenshot) plus a strip while an AI actively drives the window; pup keeps a per-operation running average and fills the bar over it. "flash": the older orange Windows attention flash, when a window opens and when an AI changes it. "off": neither. Windows only. The example switches with your choice.',sel:['progress','flash','off'],selLabels:{'progress':'progress bar (default)','flash':'orange flash (old)','off':'off'},imgBy:{progress:'tbactprogress',flash:'tbactflash',off:'tbactoff'}}, {k:'aumidIconStyle',l:'AUMID icon style',d:'Only applies when AUMID icons are on: standard = one pup tile for every window; category = the custom set (wiki signed-out, wiki signed-in padlock, world icon for the open web, adom app icon, mixed).',sel:['standard','category'],depMode:'aumid',imgBy:{standard:'iconstylestd',category:'iconstylecat'}}, {k:'jumpLists',l:'Jump lists',d:'The menu Windows shows when you right-click a pup taskbar icon (real screenshot below, captured on this machine). Requires AUMID icons on. Off by default. Quirk: the FIRST right-click can blip the menu closed — right-click again ~1s later and it holds (a Windows shell timing race, not a pup bug).',img:'jumplist'}, {k:'jlViewTasks',l:'',d:'Wiki view tasks: Switch to logged-in view / Switch to public view on every wiki window.',dep:'jumpLists',subtgl:1,img:'jlviewtasks'},@@ -12643,20 +12639,16 @@ const SETTINGS_DEF=[ {k:'tbSnipHotkey',l:'',d:'Alt+Shift+A starts annotate (red pen) on the current pup window.',dep:'toolbarExtension',subtgl:1}, {k:'tbFloatyPencil',l:'',d:'The tiny pencil in the upper-right corner of each page: one click starts annotate. Off by default: the corner hover zone can fight buttons in app headers, and the toolbar pen button covers discovery.',dep:'toolbarExtension',subtgl:1}, {k:'floatyHitPx',l:'',d:'Pencil corner hit area (px): how big the invisible top-right target is that reveals the pencil. Applies to open pages immediately.',slider:[6,120,2],dep:'tbFloatyPencil'},- {k:'fgWatch',l:'20s foreground watch',d:'For 20s after a window opens or navigates in the background, watch whether something (JavaScript, Chrome, a focus change) brings it to the foreground, and caption that it was not Adom. Never moves the window.'}, {k:'fgCaption',l:'Caption on AI foreground',d:'When an AI brings a window to your screen, show its stated reason as an on-screen caption. The AI is always forced to give a reason; this shows it to you.'}, {k:'fgCaptionMs',l:'',d:'',slider:[500,5000,250],dep:'fgCaption',test:1},- {k:'openFlash',l:'Taskbar flash on new window',d:'Flash the taskbar button (the Windows attention flash; accent-colored, salmon on your theme) when a new pup window opens, so you can spot it.',testflash:1},- {k:'autoFlash',l:'Taskbar flash on agent activity',d:'Flash a window taskbar button when an AI changes that window (navigate, click, type). One flash per burst.'},- {k:'agentActivity',l:'Taskbar progress bar',d:'Show a progress strip on a window taskbar button while an AI is actively driving it.'}, {k:'sleepRecovery',l:'Sleep and crash recovery',d:'After the laptop wakes or Chrome dies, automatically bring every pup window back at its last page, signed in. Never restarts a live Chrome.'}, {k:'autoLogin',l:'Auto-fill saved logins',d:'Fill a matching saved login when a login page loads in a pup window (background, no Chrome dropdown). pup never submits on its own: submitting a stored password is reason-gated and confirms the live domain first, to guard against lookalike/phishing sites.'}, {k:'captureLogins',l:'Capture logins to the vault',d:'As you sign into sites in pup windows, store the username and password in the OS keychain (encrypted at rest, never logged) so return visits auto-fill. This is how the shared adom-you identity grows over time.'}, {k:'reportIssues',l:'Issue-report hints',d:'Let pup invite AIs to file a wiki issue when they hit something broken.'},- {k:'titleTag',l:'ai-thread tag in the window title',d:'Append "(ai-thread: <name>)" to each window title so pup (and you) can tell windows apart from the title bar. Off by default because it can look like the page mangled its own title; pup still resolves windows without it (transiently, while off-screen).'},+ {k:'titleTag',l:'ai-thread tag in the window title',d:'Append "(ai-thread: <name>)" to each window title so YOU can tell windows apart from the title bar. Off by default because it can look like the page mangled its own title. Purely cosmetic now: pup identifies its own windows by a Win32 property tag it writes at birth, so it never needs the title.'}, {k:'titlePrefix',l:'Thread name prefixed to the title',d:'Prepend the owning thread (and wiki logged-in/out state) to the start of each window title. Off by default.'}, {k:'ownerChip',l:'Floating owner chip in each window',d:'Show a tiny non-interactive chip in the bottom-left of each pup window naming the AI thread that owns it and its profile. It cannot be clicked through to (pointer-events off) and lives in an isolated layer so it never affects the page. Turn off if you do not want any overlay in your windows.'},- {k:'notMineCaption',l:'"Not foregrounded by Adom" caption',d:'Low importance. When a window comes to the front on its own (JavaScript, a focus change, Chrome), briefly caption that Adom did NOT do it. It stays SILENT when YOU raised the window (detected via recent taskbar/keyboard input), so your own clicks never trigger it. Default on.'},+ {k:'notMineCaption',l:'"Not foregrounded by Adom" caption',d:'When a window comes to the front on its own (a page’s JavaScript, a focus change, Chrome — e.g. a PDF viewer self-activating), briefly caption that Adom did NOT do it. Stays SILENT when YOU raised the window (detected via recent taskbar/keyboard input). This is the single control for self-foreground captions, including the 20s right after a window opens. Off by default.'}, {k:'minimalTouch',l:'Minimal-touch mode',d:'The safety mode from the Chrome crash hunt. ON means pup keeps its hands off your windows: it only opens them and drives the pages inside, and skips the extra Windows machinery (identity stamps, window sweeps, shell churn) that was suspected of freezing Chrome. The toggles above are the real per-feature controls now and they win over this switch. Rule of thumb: leave this ON; if pup ever gets crashy, make sure it is ON and turn features back on one at a time to find the culprit.'}, ]; // Import-logins picker (the adom-you seed). Discovery runs today via pup_import_scan; the@@ -13147,9 +13139,9 @@ const server = http.createServer(async (req, res) => { if (act === 'set-setting') { // v1.9.259: the dashboard settings dialog. Whitelisted keys only; values validated. const ALLOWED = {- aumidIcons: ['on', 'off'], jumpLists: ['on', 'off'], fgWatch: ['on', 'off'],- fgCaption: ['on', 'off'], overlayBadges: ['on', 'off'], overlaySize: ['50', '66', '75', '100'], autoFlash: ['on', 'off'],- openFlash: ['on', 'off'], sleepRecovery: ['on', 'off'], agentActivity: ['on', 'off'],+ aumidIcons: ['on', 'off'], jumpLists: ['on', 'off'],+ fgCaption: ['on', 'off'], overlayBadges: ['on', 'off'], overlaySize: ['50', '66', '75', '100'],+ sleepRecovery: ['on', 'off'], reportIssues: ['on', 'off'], autoLogin: ['on', 'off', 'submit', 'fill'], captureLogins: ['on', 'off'], minimalTouch: ['on', 'off'], taskbarGrouping: ['split', 'grouped'], taskbarActivity: ['progress', 'flash', 'off'],@@ -13918,7 +13910,7 @@ const server = http.createServer(async (req, res) => { V('desktop_record_status', 'Status of the desktop screen recorder + any active clip.', {}, 10, {}), V('desktop_record_list', 'List completed desktop recordings on disk.', {}, 10, {}), V('desktop_recorder_close', 'Close the desktop screen-recorder UI.', {}, 15, {}),- V('pup_configure', 'Get/set user-facing pup preferences (persisted across bridge updates). taskbarGrouping: "split" (default — one taskbar button PER WINDOW, each badged with its own tab count; best for telling AI threads apart) | "grouped" (all pup windows stack under ONE "Adom Pup" button, badge shows window count; tidy taskbar). Applies to live windows immediately. Ask the USER which they prefer before changing it — this is their taskbar. WINDOWS ONLY: macOS has no taskbar, so the setting is stored but INERT there; the reply carries platform + taskbarSupported so branch on those, not on this text.', { taskbarGrouping: 'optional "split"|"grouped"', agentActivity: 'optional "on"|"off" — the taskbar progress bar marking which window a thread is driving', reportIssues: 'optional "on"|"off" — pup\'s bug-report invitation (_reportIssues), on by default', autoLogin: 'optional "on"|"off" — auto-fill a vault-matched login form on page load (fill only, never submits), on by default', overlaySize: 'optional "50"|"100" — how big the favicon badge is drawn on the taskbar button. "50" (the DEFAULT) draws it at half size so it stays clear of the thread tile\'s bottom line of text; "100" is the older, larger badge' }, 15, { taskbarGrouping: 'grouped' }),+ V('pup_configure', 'Get/set user-facing pup preferences (persisted across bridge updates). taskbarGrouping: "split" (default — one taskbar button PER WINDOW, each badged with its own tab count; best for telling AI threads apart) | "grouped" (all pup windows stack under ONE "Adom Pup" button, badge shows window count; tidy taskbar). Applies to live windows immediately. Ask the USER which they prefer before changing it — this is their taskbar. WINDOWS ONLY: macOS has no taskbar, so the setting is stored but INERT there; the reply carries platform + taskbarSupported so branch on those, not on this text.', { taskbarGrouping: 'optional "split"|"grouped"', taskbarActivity: 'optional "progress"|"flash"|"off" — how pup signals it is working on a window, on that window\'s taskbar button: a determinate progress bar sized to the operation\'s running-average time (default), the old orange flash, or nothing. Replaces the former openFlash/autoFlash/agentActivity toggles.', reportIssues: 'optional "on"|"off" — pup\'s bug-report invitation (_reportIssues), on by default', autoLogin: 'optional "on"|"off" — auto-fill a vault-matched login form on page load (fill only, never submits), on by default', overlaySize: 'optional "50"|"100" — how big the favicon badge is drawn on the taskbar button. "50" (the DEFAULT) draws it at half size so it stays clear of the thread tile\'s bottom line of text; "100" is the older, larger badge' }, 15, { taskbarGrouping: 'grouped' }), V('pup_describe', 'This list — the bridge\'s verbs + schemas, for AD\'s Verbs tab.', {}, 10, {}), ] }); return;@@ -18884,7 +18876,10 @@ const _onPupBound = async () => { // disclaimer caption (2s), mark it foreground (the IRON LAW: whatever raised it, it stays up), // disarm. NEVER a knockback - that variant shipped as 1.9.252 and was rightly killed same day. setInterval(async () => {- if (process.platform !== 'win32' || pupSettings().fgWatch !== 'on') return;+ // v2.0.292: fgWatch removed (its foreground-STEAL purpose died with off-screen birth; it was+ // caption-only, a 20s-scoped duplicate of notMineCaption). The 20s self-foreground caption now+ // honors notMineCaption — the single control for "a window fronted itself, Adom did not do it".+ if (process.platform !== 'win32' || pupSettings().notMineCaption !== 'on') return; try { const now = Date.now(); const watched = [...sessions].filter(([, s2]) => s2._fgWatchUntil && s2._fgWatchUntil > now && !s2._foreground && !s2._lostBrowser);@@ -19107,7 +19102,7 @@ setInterval(async () => { // forever — with 10 windows that was 30 pointless PS invocations a minute pounding the machine pup // is supposed to stay invisible on. Steady-state is now zero calls. setInterval(async () => {- if (process.platform !== 'win32' || pupSettings().agentActivity === 'off') return;+ if (process.platform !== 'win32' || taskbarActivityMode() !== 'progress') return; // v2.0.292 for (const [sid, sess] of [...sessions]) { const st = _busyState.get(sid); if ((!st || !st.busy) && sess && sess._progressSince) { try { await setSessionProgress(sid, false); } catch (e) {} }