app
Pup - Puppeteer Bridge
Public Made by Adomby adom
pup is the AI's own browser: a real, full Chrome on the user's desktop that the AI fully controls (a sandbox, not the user's signed-in browser). Rides Bridge; pup_* verbs open windows and tabs, navigate, screenshot, and eval JS.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
// Adom Pup popup — thin trigger surface. Finds pup's loopback port (cached), resolves which pup
// session owns THIS tab's window, and fires the same /command verbs the taskbar jump lists use,
// with caller identity 'user-toolbar' (ownership-gate exempt on the pup side: USER_CALLERS).
const CANDIDATE_PORTS = [64230, 8851]; // ab-assigned stable port first, legacy default second
async function findPup() {
const { pupPort } = await chrome.storage.local.get('pupPort');
const ports = pupPort ? [pupPort, ...CANDIDATE_PORTS.filter(p => p !== pupPort)] : CANDIDATE_PORTS;
for (const port of ports) {
try {
const r = await fetch(`http://127.0.0.1:${port}/health`, { signal: AbortSignal.timeout(1200) });
const j = await r.json();
if (j && j.bridge === 'puppeteer') { chrome.storage.local.set({ pupPort: port }); return { port, health: j }; }
} catch (e) {}
}
return null;
}
async function cmd(port, command, args) {
const r = await fetch(`http://127.0.0.1:${port}/command`, {
method: 'POST',
headers: { 'content-type': 'application/json', 'x-adom-caller-thread': 'user-toolbar', 'x-adom-caller-reason': 'toolbar popup click' },
body: JSON.stringify({ command, args: { ...args, caller: { aiThread: 'user-toolbar' } } }),
});
return r.json();
}
(async () => {
const menu = document.getElementById('menu');
// render-first preview (?preview=1): mock state so the UI can be reviewed without a bridge
if (new URLSearchParams(location.search).get('preview')) {
document.getElementById('owner').innerHTML = 'owned by <b>kicad-dev</b>';
document.getElementById('foot').innerHTML = '<span class="dot">●</span> pup 2.0.50 · port 64230';
return;
}
const off = document.getElementById('off');
const foot = document.getElementById('foot');
const ownerEl = document.getElementById('owner');
const pup = await findPup();
if (!pup) { menu.style.display = 'none'; off.style.display = 'block'; foot.innerHTML = '<span style="color:#f87171">●</span> pup not reachable'; return; }
const { port, health } = pup;
// which session owns THIS window? Match the active tab's URL against pup's session list.
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
let sid = null, owner = null, view = null;
try {
const sessions = (health.sessions || []);
const hit = sessions.find(s => s.url && tab && tab.url && (s.url === tab.url || tab.url.startsWith((s.url || '').split('?')[0])));
if (hit) { sid = hit.sessionId; owner = hit.owner || null; }
} catch (e) {}
ownerEl.innerHTML = owner ? 'owned by <b>' + owner.replace(/</g, '<') + '</b>' : (sid ? sid : 'not a pup window');
// View toggle: label from the CHECKED auth state (pup verifies against the page, /health carries
// it), never from a cached belief. Non-wiki pages hide the toggle entirely.
const isWiki = !!(tab && tab.url && /https:\/\/wiki\.adom\.inc\//.test(tab.url));
const hit2 = (health.sessions || []).find(s2 => s2.sessionId === sid);
const authed = hit2 ? hit2.authed : null;
const viewBtn = document.querySelector('button[data-act="view"]');
if (!isWiki) { viewBtn.style.display = 'none'; }
else if (authed === true) { view = 'authed'; document.getElementById('viewLabel').textContent = 'Switch to public view'; }
else if (authed === false) { view = 'public'; document.getElementById('viewLabel').textContent = 'Switch to logged-in view'; }
else { view = null; document.getElementById('viewLabel').textContent = 'Toggle logged-in/public view'; }
foot.innerHTML = '<span class="dot">●</span> pup ' + (health.version || '') + ' · port ' + port;
menu.addEventListener('click', async (e) => {
const btn = e.target.closest('button.row');
if (!btn) return;
const act = btn.dataset.act;
try {
const base = sid ? { sessionId: sid } : { _tabUrl: tab && tab.url };
let r = null;
if (act === 'annotate') r = await cmd(port, 'pup_annotate', { ...base });
else if (act === 'snip') r = await cmd(port, 'pup_annotate', { ...base, tool: 'snip' });
else if (act === 'view') r = await cmd(port, 'pup_wiki_set_view', { ...base, view: view === 'authed' ? 'public' : 'authed' });
else if (act === 'dashboard') await cmd(port, 'pup_dashboard', {});
else if (act === 'info') r = await cmd(port, 'pup_window_info', { ...base });
else if (act === 'close') { if (confirm('Close ' + (owner ? owner + "'s" : 'this') + ' pup window?')) r = await cmd(port, 'pup_close_window', { ...base }); }
} catch (err) { r = { success: false, error: String(err) }; }
// every action answers back (design skill): show a failure instead of vanishing
if (r && r.success === false) {
ownerEl.textContent = (r.error || 'action failed').slice(0, 60);
ownerEl.style.color = '#f85149';
return; // keep the popup open so the user can read it
}
window.close();
});
})();