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 'NOT foregrounded by Adom' caption now stays silent when JOHN raised the window (John: 'i tend to click the taskbar icon to bring the window to the foreground, then you show this message. i only want to see it if it was some other reason'). YES pup can differentiate: a taskbar click is recent USER INPUT the OS records (GetLastInputInfo); a JavaScript/Chrome self-raise has none. The no-fault watch now checks time-since-last-input before captioning - if input happened within the last 1.5s, it assumes the user raised it and stays silent; only a raise with NO recent input (genuinely not the user) gets the caption. Errs toward silence (a JS raise coinciding with the user typing elsewhere is also suppressed - the polite direction), so the caption never fires on his click while still catching real non-user raises. Setting kept ON with its description updated.
5 files changed
+41−9
adom-bridge-puppeteer-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "puppeteer",- "version": "1.9.291",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.291/adom-bridge-puppeteer-v1.9.291.zip",- "sha256": "a992cbd0321f466c25a273671c4325cd2841790c8e8bb2a266d48c0cc2472712",- "size": 718788,+ "version": "1.9.292",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.292/adom-bridge-puppeteer-v1.9.292.zip",+ "sha256": "7ba8083aa2fec0b26e4472105ba921868474ba2af6e0ea13409a6e6b538dba6d",+ "size": 719508, "verbPrefixes": [ "browser_", "desktop_recorder_",
src/BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.291+1.9.292
src/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "puppeteer", "displayName": "Puppeteer (Chrome for Testing + Native)",- "version": "1.9.291",+ "version": "1.9.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. 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/package.json+1−1@@ -1,6 +1,6 @@ { "name": "adom-puppeteer-bridge",- "version": "1.9.290",+ "version": "1.9.291", "description": "Puppeteer Bridge \u2014 persistent browser instance for visual debugging via Adom Desktop", "main": "server.js", "scripts": {
src/server.js+34−2@@ -2516,6 +2516,31 @@ function osSendWindowToBack(profileName) { // v1.8.34: capture the user's CURRENT foreground window (decimal HWND string) right // before we launch a pup browser, so the backgrounder can hand keyboard focus back to it.+function osIdleMs() {+ // v1.9.292 (John: differentiate HIS taskbar click from a JS/Chrome raise). Windows records the+ // time of the last user input (keyboard/mouse). A taskbar click that raised a window = very recent+ // input; a programmatic raise = none. Returns ms since the last input, or null if unknown.+ if (process.platform !== 'win32') return null;+ try {+ const scriptPath = path.join(require('os').tmpdir(), `_adom_idle_${process.pid}.ps1`);+ const ps = [+ 'Add-Type @"',+ 'using System; using System.Runtime.InteropServices;',+ 'public struct LASTINPUTINFO { public uint cbSize; public uint dwTime; }',+ 'public class WinIdle {',+ ' [DllImport("user32.dll")] public static extern bool GetLastInputInfo(ref LASTINPUTINFO p);',+ ' [DllImport("kernel32.dll")] public static extern uint GetTickCount();',+ ' public static long Idle() { var l = new LASTINPUTINFO(); l.cbSize = (uint)Marshal.SizeOf(l); if (!GetLastInputInfo(ref l)) return -1; return (long)(GetTickCount() - l.dwTime); }',+ '}',+ '"@',+ 'Write-Output ([WinIdle]::Idle())',+ ].join('\r\n');+ fs.writeFileSync(scriptPath, ps);+ const out = (runPsHidden(scriptPath, { timeout: 4000 }) || '').trim();+ const ms = Number(out);+ return Number.isFinite(ms) && ms >= 0 ? ms : null;+ } catch (e) { return null; }+} function osGetForegroundWindow() { if (process.platform !== 'win32') return null; try {@@ -8955,7 +8980,7 @@ const SETTINGS_DEF=[ {k:'titleTag',l:'Session 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:'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, or your own click), briefly caption that Adom did NOT do it. Default on so you can see it; turn off once you trust that pup keeps windows in the background.'},+ {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:'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.'}, ]; function renderDlg(){@@ -13148,8 +13173,15 @@ server.listen(PORT, BIND_HOST, async () => { // caption every 10s, so it can NEVER be held open by a re-issue storm. if (pupSettings().notMineCaption !== 'on') break; if (Date.now() - (globalThis._lastNoFaultCaptionAt || 0) < 10000) break;+ // v1.9.292 (John: "i tend to click the taskbar icon to bring the window to the foreground...+ // i only want to see this message if it was some other reason other than me raising it").+ // A taskbar click is RECENT user input; a JS/Chrome raise has none. If input happened within+ // the last 1.5s, assume the USER raised it and stay SILENT. Errs toward silence (a JS raise+ // that coincides with the user typing elsewhere is also suppressed — the polite direction).+ const _idle = osIdleMs();+ if (_idle != null && _idle < 1500) { console.log(`[fg-watch] "${sid2}" surfaced with recent user input (${_idle}ms idle) — assuming USER raised it, no caption`); break; } globalThis._lastNoFaultCaptionAt = Date.now();- console.log(`[fg-watch] "${sid2}" surfaced with no pup raise — no-fault caption (2s, deduped)`);+ console.log(`[fg-watch] "${sid2}" surfaced with no pup raise and no recent input (idle ${_idle}ms) — no-fault caption (2s, deduped)`); pupCaption(`This window was NOT foregrounded by Adom: JavaScript, a focus change, Chrome itself, or your own click raised "${sid2}". Not me!`, 2000, 'pup-nofault').catch(() => {}); break; } catch (e) {}