← Commit history

Publish 2.0.316

John Lauer ·d02d7e8922 ·1mo ago ·parent 878305d
3 files changed +62−11
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "pup-bridge",-  "version": "2.0.315",+  "version": "2.0.316",   "type": "app",   "description": "The pup SKILL PACK \u2014 the AI skills that teach a cloud/container AI how to drive the Adom Desktop Puppeteer (pup) bridge (browser_* verbs): the everyday `pup` skill plus focused sub-skills for windows/sessions/tabs, screenshots+recording, browsers+Chrome install, and driving the Adom wiki. Installs into ~/.claude/skills + ~/.codex/skills. DOCS ONLY \u2014 this is NOT the bridge runtime. The bridge itself (the Node program that drives the browser) runs on the DESKTOP: Adom Desktop bundles it and auto-installs/updates it, and it's published separately on the Releases tab as adom-bridge-puppeteer-v<ver>.zip. The pkg version is kept in lockstep with the Release version so the page's max version row always carries BOTH a pkg tarball (skills) and a runtime zip (bridge) \u2014 a skills-only or runtime-only bump on the top row breaks constraint installs. TL;DR: pkg install = the skills for your AI; the bridge = the Release zip, which Adom Desktop manages for you.",   "keywords": [
page.json+1−1
@@ -4,7 +4,7 @@   "slug": "pup-bridge",   "title": "Pup - Puppeteer Bridge",   "brief": "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.",-  "version": "2.0.315",+  "version": "2.0.316",   "tags": [     "skills",     "pup",
tools/pup-dashboard+60−9
@@ -127,6 +127,7 @@ const PROXY = (port) => `http://127.0.0.1:${port}/`; // user can see which one the lights describe. let _target = { at: 0, name: null, all: [] }; async function resolveTarget() {+  if (process.env.ADOM_DESKTOP_TARGET) return { name: process.env.ADOM_DESKTOP_TARGET, all: [process.env.ADOM_DESKTOP_TARGET], at: Date.now() };   if (_target.name && Date.now() - _target.at < 60000) return _target;   const d = await new Promise((resolve) => {     execFile('adom-bridge', ['targets'], { env: ENV, timeout: 8000 }, (err, stdout) => {@@ -333,19 +334,69 @@ load(); setInterval(load,15000);  // ── demo ──────────────────────────────────────────────────────────────────────────────────────── async function runDemo() {+  // The dock-card showcase (John: "shouldn't your pup demo be a bit cooler? show off your+  // annotation feature, your jump lists, how cool your icons are"). The user CLICKED Run the demo,+  // so the finale may come to their screen: the raise is captioned with exactly that reason.   const lines = [];   const sid = 'pup-dock-demo';-  lines.push('Opening a window in the BACKGROUND (pup never steals your screen)…');+  const sleep = (ms) => new Promise(r => setTimeout(r, ms));   const tgt = await resolveTarget();++  lines.push('1. Opening a window in the BACKGROUND. pup births it off-screen and parks it behind');+  lines.push('   your work in under 50ms, so it can never steal your screen or your keystrokes.');   const open = await ab('pup_open_window', { sessionId: sid, url: 'https://wiki.adom.inc/adom/pup-bridge', owner: 'pup dock demo' }, 120000, tgt.name);-  lines.push(open._err ? `  could not open: ${open._err}` : `  open: ${open.sessionId || sid}`);-  if (!open._err) {-    const shot = await ab('pup_screenshot', { sessionId: sid }, 60000, tgt.name);-    lines.push(shot._err ? `  screenshot failed: ${shot._err}` : `  screenshot: ${shot.width}x${shot.height}`);-    lines.push('Its taskbar button carries this thread\'s name and the page favicon.');-    lines.push('Ask your AI for the rest: recording (highFps for full-rate demo video), annotation, and the gliding cursor.');-    lines.push(`Close it when you are done: pup_close_window {"sessionId":"${sid}"}`);-  }+  if (open._err) { lines.push('   could not open: ' + open._err); return lines; }+  lines.push('   open: ' + (open.sessionId || sid));++  lines.push('');+  lines.push('2. LOOK AT YOUR TASKBAR right now. The new button is not a generic Chrome icon: it is');+  lines.push('   the Adom teal tile wearing this thread\'s NAME ("pup dock demo"), with the live page');+  lines.push('   favicon badged in the corner. Every AI thread gets its own named button, so your');+  lines.push('   taskbar reads as a list of your threads. While the icon lands you will see a small');+  lines.push('   PROGRESS BAR under the button: pup times every operation and fills the bar over how');+  lines.push('   long it usually takes, instead of flashing orange at you.');+  await sleep(3500);++  lines.push('');+  lines.push('3. Screenshot, without touching your screen: the window renders in the background and');+  lines.push('   pup reads the pixels off-screen (watch the button, the progress bar runs again).');+  const shot = await ab('pup_screenshot', { sessionId: sid }, 60000, tgt.name);+  lines.push(shot._err ? '   screenshot failed: ' + shot._err : '   screenshot: ' + shot.width + 'x' + shot.height + ' (the AI can read any page without disturbing you)');++  lines.push('');+  lines.push('4. RIGHT-CLICK that taskbar button when you get a moment: pup installs a jump list on');+  lines.push('   every window: Annotate this page, Switch to logged-in/public view (wiki windows),');+  lines.push('   Open pup dashboard, Move to my workspace, Close ALL Adom Pup windows.');+  await sleep(2500);++  lines.push('');+  lines.push('5. The finale: ANNOTATION, live. Bringing the window up (with the on-screen caption');+  lines.push('   pup always shows before a foreground, naming who and why), then drawing on the page.');+  await ab('pup_raise_os_window', { sessionId: sid, foregroundReason: 'you clicked Run the demo on the pup dashboard: watch the annotation feature draw on the page' }, 30000, tgt.name);+  await sleep(1200);+  const arm = await ab('pup_annotate', { sessionId: sid, tool: 'pen' }, 30000, tgt.name);+  if (!arm._err) {+    await sleep(600);+    const draw = "(async()=>{const r=document.getElementById('__pup_annotate');if(!r)return 'no overlay';const cv=r.querySelector('canvas');if(!cv)return 'no canvas';const mk=(t,x,y)=>new PointerEvent(t,{bubbles:true,cancelable:true,clientX:x,clientY:y,pointerId:1,isPrimary:true,button:0,buttons:t==='pointerup'?0:1});const cx=Math.round(innerWidth*0.35),cy=Math.round(innerHeight*0.4),rad=Math.min(140,Math.round(innerHeight*0.18));cv.dispatchEvent(mk('pointerdown',cx+rad,cy));for(let a=0.25;a<=6.55;a+=0.22){cv.dispatchEvent(mk('pointermove',cx+rad*Math.cos(a),cy+rad*Math.sin(a)));await new Promise(q=>setTimeout(q,16));}cv.dispatchEvent(mk('pointerup',cx+rad,cy));return 'drew';})()";+    const drew = await ab('pup_evaluate', { sessionId: sid, expression: draw }, 30000, tgt.name);+    const drewOk = !drew._err && String(drew.result || '') === 'drew';+    if (drewOk) {+      lines.push('   A red circle was just drawn on the page. On the pen-up, pup captured the marked');+      lines.push('   region, put the PNG ON YOUR CLIPBOARD with a caption strip naming the thread and');+      lines.push('   page (paste it into any AI chat), and showed the confirmation toast.');+    } else lines.push('   annotation draw did not run: ' + (drew._err || drew.result || 'unknown'));+  } else lines.push('   annotate did not arm: ' + arm._err);+  await sleep(3500);+  await ab('pup_lower_os_window', { sessionId: sid }, 20000, tgt.name);+  lines.push('');+  lines.push('6. And back to the background, out of your way. The drawing fades once captured (the');+  lines.push('   capture is what persists, on your clipboard). The window stays open: right-click its');+  lines.push('   taskbar button to explore the jump list, or close it there (or say: close the pup');+  lines.push('   demo window).');+  lines.push('');+  lines.push('Not shown: recording a window to video (full frame rate in the background with highFps),');+  lines.push('the credential vault that signs into sites with no Chrome popups, and the gliding Adom');+  lines.push('cursor that narrates what the AI is doing. Say "show me in pup" to any Adom AI.');   return lines; }