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 with its AI thread's name in your taskbar or dock.
← Commit history
dev skill: add the outbound bridge->AD notify recipe (direct-API, AD 1.9.84 full verb surface, bridge token, cross-AD target, notify-first ordering); pkg 1.8.16
2 files changed
+38−1
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-desktop-puppeteer-bridge",- "version": "1.8.14",+ "version": "1.8.16", "type": "app", "description": "CONTAINER-SIDE install \u2014 the pup skill pack in the wiki skillpack layout: the everyday `pup` user skill PLUS two bundled developer sub-skills (pup-bridge-dev, pup-bridge-publish; user-invocable:false, DEVELOPER-only descriptions so they never trigger for everyday users), all dropped into ~/.claude/skills/ AND ~/.codex/skills/ by an explicit install.sh list. It does NOT contain the bridge runtime: the bridge (Node + browser driving) lives on the DESKTOP \u2014 bundled inside Adom Desktop and published on the Releases tab as adom-bridge-puppeteer-v<ver>.zip, which Adom Desktop streams into its bridges-cache. TL;DR: pkg install = the skill pack; the bridge = the Release zip + bundled in Adom Desktop.", "keywords": [
skills/pup-bridge-dev/SKILL.md+37@@ -51,6 +51,43 @@ The full chain when a user on a fresh container says *"open my app in pup"*: `null`** (`AD_CORE_SKILL_BRIDGES = ["puppeteer"]` in `bridge_registry.rs`, from when pup's skill lived in the AD-core pkg). That must be removed now that the skill ships from this page — it's in the AD handoff. +## Calling AD back (outbound) — notify the user from inside the bridge (AD ≥ 1.9.84)++Everything above is AD → pup. The reverse — **pup → AD** — matters when the bridge must+reach the *user* on its own, mid-verb, with no AI turn. The canonical case: pup installs+real Chrome on a locked-down box that needs a **UAC**, and has to say "click YES" (and+re-nudge if it expires). See `chrome.js` `_elevatedInstallWithNotify` for the live impl.++**The channel.** A bridge's only callback is AD's loopback direct-API. Resolve it:+`ADOM_DIRECT_API_URL` env → else read `%USERPROFILE%\.adom\direct-api-port` (`host:port`) →+else `127.0.0.1:47200`. Then `POST /command`.++**AD ≥ 1.9.84 exposes the FULL verb surface to bridges** (before that, only `desktop_*` ++other bridges' verbs — `notify_user` returned *"Unknown desktop command"*, which is why the+degraded path exists). Contract:+- **`app` is inferred** — send `{ "command": "<verb>", "args": {…} }`, no `app`.+- **Token (optional, attribution only):** send the spawn-time `ADOM_BRIDGE_TOKEN` env as+ the `X-Adom-Bridge-Token` header → AD badges the call `bridge` in its Activity Log. A+ **stale token → 403**; on 403 retry once WITHOUT the header. Omitting it entirely is fine+ (a bridge is trusted-by-install; calls run ungated).+- **Capability-probe, don't hardcode:** `GET /commands` → `notify_user` appears in+ `.topLevel` on ≥1.9.84. Gate the notify flow on that; fall back to raise-UAC-once ++ a relay hint on older AD. pup caches this as `readiness.chromeStableNotifyChannel`.+- **Cross-AD `target`:** add `"target": "<clientName>" | "all"` to ANY `/command` to route+ it to a PEER AD via the relay — e.g. pup runs on a VM, the user is on their laptop, so+ ping the laptop while the UAC stays on the VM. `"attended"` (input-active box) is **not+ resolvable yet** → enumerate peers and fan out.+- **`targets` gotcha:** returns `{ clients: [...] }` and **includes self** (NOT+ `{ targets: [...] }`). Read `clients`, drop your own `os.hostname()`, dedupe.++**The two UX rules the impl bakes in (both were real bugs first):**+1. **Notify-FIRST, then raise the UAC.** Raising the UAC puts up the secure desktop, which+ *hides* any toast. So fire the sticky `scenario:"reminder"` toast with an `Approve now`+ button, poll `notify_response {id}` for the tap, and only THEN elevate.+2. **Never spam prompts you can't explain.** If the notify channel is unreachable, raise the+ UAC **once** and surface `awaiting_uac` + a hint for the AI to relay — do NOT loop+ re-raising a UAC the user is never told about.+ ## Repo layout - `src/` — the runnable bridge (what the release zip contains, at zip-root). `server.js`, `chrome.js`,