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.8.39: remove in-bridge ITaskbarList3 overlay (in-process-only, doesn't badge the browser's window) — taskbar badge is an AD-core desktop_taskbar capability; filing a pup-distinct-badge request to AD instead
4 files changed
+12−70
adom-bridge-puppeteer-manifest.json+5−5@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "puppeteer",- "version": "1.8.38",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.8.38/adom-bridge-puppeteer-v1.8.38.zip",- "sha256": "a3b886b72f4d949e3fdc8ac7c69ee7d18fbb3aba04a4285322e38451ccd71f96",- "size": 160192,+ "version": "1.8.39",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.8.39/adom-bridge-puppeteer-v1.8.39.zip",+ "sha256": "766c0aa6a3d4ba0848122cca8946b07088a4224fdb5287f0a93047ba3713a53b",+ "size": 159297, "verbPrefixes": [ "browser_", "desktop_recorder_",@@ -12,5 +12,5 @@ ], "healthEndpoint": "/status", "statusVerb": "browser_readiness",- "released_at": "2026-07-14T21:05:46Z"+ "released_at": "2026-07-14T21:16:15Z" }
src/BRIDGE_VERSION+1−1@@ -1 +1 @@-1.8.38+1.8.39
src/bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "puppeteer", "displayName": "Puppeteer (Chrome for Testing + Native)",- "version": "1.8.38",+ "version": "1.8.39", "description": "Drives a browser ALREADY on the machine — installed Chrome, else Microsoft Edge (every Windows PC ships with Edge) — 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 → Edge → 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, …). 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 — 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 — a separate bridge, not pup's job.", "homepage": "https://wiki.adom.inc/adom/adom-desktop", "author": "Adom Inc.",
src/server.js+5−63@@ -1520,62 +1520,11 @@ function osGetForegroundWindow() { } catch (e) { return null; } } -// v1.8.38: badge each pup window's TASKBAR BUTTON with the white Adom leaves, so the user-// can tell a pup-driven Chrome/Edge window apart from their own browser at a glance (same-// idea the nbrowser_* extension uses on the real browser). Uses the Windows shell-// ITaskbarList3::SetOverlayIcon API — a small badge on the bottom-right of the taskbar-// button (does NOT replace the browser icon). Best-effort + hidden PS; no-op off Windows.-function osSetTaskbarOverlay(profileName, cdpPort) {- if (process.platform !== 'win32') return 'skip';- try {- const be = browsers.get(profileName);- const pid = (be && be.browser && (be.browser._detachedPid || (be.browser.process() && be.browser.process().pid))) || null;- if (!pid && !cdpPort) return 'no-pid';- const iconPath = path.join(__dirname, 'icons', 'pup-overlay-32.png').replace(/\\/g, '\\\\');- const scriptPath = path.join(require('os').tmpdir(), `_adom_overlay_${pid || cdpPort}.ps1`);- const ps = [- 'Add-Type -AssemblyName System.Drawing',- 'Add-Type @"',- 'using System; using System.Runtime.InteropServices;',- '[ComImport, Guid("56FDF344-FD6D-11d0-958A-006097C9A090")] public class CTaskbarList {}',- '[ComImport, Guid("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]',- 'public interface ITaskbarList3 {',- ' void HrInit(); void AddTab(IntPtr h); void DeleteTab(IntPtr h); void ActivateTab(IntPtr h); void SetActiveAlt(IntPtr h);',- ' void MarkFullscreenWindow(IntPtr h, [MarshalAs(UnmanagedType.Bool)] bool ff);',- ' void SetProgressValue(IntPtr h, ulong c, ulong t); void SetProgressState(IntPtr h, int f);',- ' void RegisterTab(IntPtr h, IntPtr m); void UnregisterTab(IntPtr h); void SetTabOrder(IntPtr h, IntPtr b); void SetTabActive(IntPtr h, IntPtr m, int f);',- ' void ThumbBarAddButtons(IntPtr h, uint n, IntPtr p); void ThumbBarUpdateButtons(IntPtr h, uint n, IntPtr p); void ThumbBarSetImageList(IntPtr h, IntPtr l);',- ' void SetOverlayIcon(IntPtr h, IntPtr icon, [MarshalAs(UnmanagedType.LPWStr)] string desc);',- ' void SetThumbnailTooltip(IntPtr h, [MarshalAs(UnmanagedType.LPWStr)] string tip); void SetThumbnailClip(IntPtr h, IntPtr rc);',- '}',- 'public class Ov {',- ' [DllImport("user32.dll")] public static extern int GetSystemMetrics(int i);',- ' public static IntPtr Load(string p){ var bmp=new System.Drawing.Bitmap(p); return bmp.GetHicon(); }',- '}',- '"@',- `$targetPid = ${Number(pid) || 0}`,- `$cdpPort = ${Number(cdpPort) || 0}`,- '$pids = New-Object System.Collections.ArrayList',- 'if ($targetPid -ne 0) { [void]$pids.Add($targetPid) }',- 'if ($cdpPort -ne 0) { try { $own = Get-NetTCPConnection -LocalPort $cdpPort -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty OwningProcess; if ($own) { [void]$pids.Add([int]$own) } } catch {} }',- '$handles = New-Object System.Collections.ArrayList',- 'foreach ($tp in $pids) {',- ' $p = Get-Process -Id $tp -ErrorAction SilentlyContinue',- ' if ($p -and $p.MainWindowHandle -ne 0) { [void]$handles.Add($p.MainWindowHandle) }',- ' Get-CimInstance Win32_Process -Filter "ParentProcessId=$tp" -ErrorAction SilentlyContinue | Where-Object { $_.Name -in @("chrome.exe","msedge.exe") } | ForEach-Object { $cp = Get-Process -Id $_.ProcessId -ErrorAction SilentlyContinue; if ($cp -and $cp.MainWindowHandle -ne 0) { [void]$handles.Add($cp.MainWindowHandle) } }',- '}',- 'if ($handles.Count -eq 0) { Write-Output "no-window"; exit }',- `$hicon = [Ov]::Load("${iconPath}")`,- '$tbl = [ITaskbarList3]([Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"56FDF344-FD6D-11d0-958A-006097C9A090")))',- '$tbl.HrInit()',- 'foreach($h in $handles){ try { $tbl.SetOverlayIcon($h, $hicon, "Adom pup") } catch {} }',- 'Write-Output "overlaid"',- ].join('\r\n');- fs.writeFileSync(scriptPath, ps);- const out = runPsHidden(scriptPath, { timeout: 8000 }).trim();- return out || 'error';- } catch (e) { console.error(`[overlay] ${profileName}: ${e.message}`); return 'error'; }-}+// NOTE: taskbar badge/overlay is an AD-CORE capability (desktop_taskbar, AD ≥1.8.152) — the+// nbrowser_* extension uses it and AD does the cross-process work natively. pup must NOT+// reimplement it (an in-bridge ITaskbarList3::SetOverlayIcon is in-process-only and fails on+// the browser's out-of-process window). A pup-distinct badge (white Adom leaves) is an AD+// feature request on desktop_taskbar; pup will call that verb via direct-API once it exists. // v1.8.26: THE real "background by default" enforcement, done RIGHT. A freshly-launched // --start-maximized browser grabs foreground; osSendWindowToBack only lowers z-order and@@ -2069,13 +2018,6 @@ async function getOrLaunchBrowser(profileName, { freshProfile = false, strictPer setTimeout(() => { try { b._bgResult = osBackgroundWindowByPid(child.pid, debugPort, priorForeground); } catch (e) {} }, delay); } }- // v1.8.38: stamp the Adom-leaves badge on the taskbar button (once it exists), so pup- // windows are visually distinct from the user's own browser. Fire for foreground too.- if (process.platform === 'win32') {- for (const delay of [1500, 3500]) {- setTimeout(() => { try { osSetTaskbarOverlay(profileName, debugPort); } catch (e) {} }, delay);- }- } return b; };