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.
master
John Lauer
rust: Phase 3 complete (vault, cards, wiki auto-sign + view flip, annotate, tab + screen recording, highFps lease, down…
4869577
2mo ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
((sid, minimal, label, tagOn) => {
// v1.9.185: carry minimal-touch into the page so the title observer below can skip installing
// itself (see the note at `observe`). Read at document-start, before any page script runs.
try { if (minimal) window.__pupMinimalTouch = true; } catch (e) {}
// TOLERANT marker check (v1.8.19): a tab's own suffix may be
// " (session: <sid>)" OR " (session: <sid> | <tabId>)". This injector must
// only ADD a marker when NONE is present — if it enforced an exact
// " (session: <sid>)" it would fight addTabToSession's " | <tabId>" suffix:
// two MutationObservers appending different strings ping-pong forever, peg the
// renderer, and flood the CDP pipe (which HUNG pup_open_tab on Edge and
// poisoned the whole bridge). Matching on the marker PREFIX makes it cooperate.
const LBL = label || 'ai-thread';
const MARKER = ' (' + LBL + ': ' + sid; // no closing paren — matches both forms
const BASE = ' (' + LBL + ': ' + sid + ')';
// v1.9.49: do NOT require a pre-existing title. This guard used to be
// if (document.title && ...)
// so a page that never sets a <title> (plenty of app routes and SPA shells serve one) kept an
// EMPTY title, the session marker was never injected, and the OS window title stayed a bare
// "Google Chrome for Testing". AD resolves pup windows by their "(session: <id>)" suffix, so
// that window became INVISIBLE to every branding call: identity stamp, category flip, overlay
// and jump list all failed with "No visible window with title containing (session: ...)".
// That is the failure behind icons that look stale or never update — the window was findable
// right up until it navigated to a title-less page. An empty title must still get the marker.
// v1.9.56: SELF-HEALING against DUPLICATES. The old check only asked "is my marker absent?",
// so once a second copy appeared it was never collapsed — measured live as
// "○ Public · Hydrogen Desktop - Adom Wiki (session: hdr-wiki) (session: hdr-wiki)"
// (107-char title). Two independent MutationObservers touch this title (this session-suffix
// injector and the wiki state-glyph injector); a page that rewrites its own title can let both
// fire before either sees the other's write, and each appends. Duplicated tags bloat the
// taskbar-thumbnail CAPTION (the surface we want for status) and, worse, AD resolves pup windows
// by "(session: <id>" — the same duplicate-tag class that previously made branding land on the
// WRONG window. So: count OUR OWN tag and normalise to exactly one. Only our own sid is touched,
// so an adopted tab's re-tag (retagSessionTitle) is never fought.
const RE_MINE = new RegExp('\\s*\\((?:session|ai-thread): ' + sid.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '(?:[^)]*)\\)', 'g');
const ensure = () => {
try {
const cur = String(document.title || '');
if (!tagOn) { const clean = cur.replace(RE_MINE, ''); if (clean !== cur) document.title = clean; return; } // OFF: keep title clean
const n = (cur.match(RE_MINE) || []).length;
if (n === 1) return; // already exactly one — leave it alone
if (n === 0) { document.title = cur + BASE; return; } // none — add ours
document.title = cur.replace(RE_MINE, '') + BASE; // duplicates — collapse to one
} catch (e) {}
};
const observe = () => {
// v1.9.288: when the tag is OFF we strip once (above) but must NOT run a stripping observer -
// it would instantly remove the TRANSIENT tag pup adds to resolve the window's hwnd, forcing
// ambiguous geometry (two same-profile windows share a rect => same hwnd, John's dup-hwnd bug).
if (!tagOn) return true;
// v2.0.20: ONLY a real <title> node. The old head/documentElement fallback observed the
// ENTIRE document subtree on titleless pages (raw JSON/API views), firing ensure() on every
// DOM mutation — a renderer-pegging cost on exactly the pages least able to afford it. A
// titleless page keeps its once-stamped tag; continuous enforcement is not worth a freeze.
const t = document.querySelector('title');
if (!t) return true;
// v1.9.185 minimal-touch: in MINIMAL mode we stamp the title ONCE and do NOT install a
// MutationObserver. On a heavy SPA (Google Slides/Sheets rewrite document.title constantly)
// this observer re-fired on every one of those writes, each time writing the title BACK —
// an in-page write loop pup itself created, on the exact windows John saw freeze. The
// window still carries the tag from the initial stamp; only the continuous re-enforcement
// is dropped. (window.name, set below, is the durable identity anyway.)
if (window.__pupMinimalTouch) return true;
try { window.__pupTagObs = new MutationObserver(ensure); window.__pupTagObs.observe(t, { childList: true, subtree: true, characterData: true }); } catch (e) {}
return true;
};
ensure();
if (!observe()) document.addEventListener('DOMContentLoaded', () => { observe(); ensure(); });
})(__SID__, __MINIMAL__, __LABEL__, __TAGON__);