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
Handoff: AD must expose notify_user/notify_response via direct-API + route to the attended device (blocks the Chrome-UAC notify flow)
1 file changed
+72
HANDOFF-notify-for-bridges.mdadded+72@@ -0,0 +1,72 @@+# Handoff to Adom Desktop: let bridges notify the user (and reach the attended device)++**From:** pup (adom-desktop-puppeteer-bridge)+**Why:** pup can now install real Google Chrome on a box that needs admin, but on a+locked-down machine (VM / managed device) that requires a **Windows UAC**. To be usable,+pup must (a) tell the user "click YES on the prompt" and (b) re-nudge if it expires — all+**without an AI turn**. A bridge's only channel back to AD is the loopback direct-API+(`127.0.0.1:47200`), and today that API does **not** expose `notify_user`. So the bridge+cannot notify at all. This is the blocker.++## What's broken (evidence, AD 1.9.79 on ADOMBASELINE)++`POST 127.0.0.1:47200/command` with every plausible namespace:++| body | result |+|---|---|+| `{app:"desktop", command:"notify_user", ...}` | `error: "Unknown desktop command: notify_user"` |+| `{app:"core"\|"adom"\|"cli", command:"notify_user"}` | `error: "Unknown app: <x>"` |+| `{app:"dynamic", command:"notify_user"}` | `errorCode: "unknown_verb" — no installed bridge claims this prefix` |+| `{command:"notify_user"}` (no app) | HTTP 400 |++`GET /commands` confirms it: the `desktop` app enumerates only the **`desktop_*`** verbs+(`list_windows, screenshot_*, ui_click, read_file, registry_*, process_*, launch_process,+…`). `notify_user` / `notify_response` / `ping` / `server_*` are **not in any namespace**.+(The `adom-desktop` skill docs claim `notify_user` is "safe to send directly" — that's+aspirational; the running build doesn't dispatch it.)++## Ask 1 — expose `notify_user` + `notify_response` on the direct-API++Route these two top-level verbs through `POST /command` (same dispatcher the CLI/WS path+uses, same rich payload: `buttons`, `id`, `scenario:"reminder"`, `level`, `progress`).+Simplest: add them to the `desktop` app's command table (so `{app:"desktop",+command:"notify_user"}` works), and list them in `GET /commands` so callers can+capability-probe. pup **already probes `/commands`** and will light up automatically the+moment they appear — no pup release needed for the local case.++Loopback-only, so no new external surface. `notify_response` must stay pollable by the+same process that fired the `id`.++## Ask 2 — deliver the notification to the ATTENDED device++The harder, important half. Real scenario: pup runs on **box A** (a hypervm), the UAC is+on **box A** (you can only approve it there), but the user is sitting at **box B** (their+laptop, a different connected AD). A toast on box A's own desktop is invisible to them.+The user must be **pinged on box B** — "Chrome needs approval on **A** — go click YES" —+while the actual UAC stays on A.++A bridge can only reach its *local* AD; cross-device routing is AD/relay-level. Options+(your call which):++- **`target` on `notify_user`**: `{command:"notify_user", args:{…, target:"attended"|"<clientName>"|"all"}}`. The local AD relays it over the relay to that AD, which renders the toast. `"attended"` = the AD AD judges the user is present at (most-recently-focused / input-active), falling back to broadcast.+- **Include the origin box** in the payload/label automatically (`"…on ADOMBASELINE"`) so a cross-device toast is actionable.+- **Cross-device `notify_response` round-trip**: the user taps **Approve now** on box B; that click must travel back so the **bridge on box A** learns of it (it polls its local AD; the relay carries the correlation A↔B). Then the bridge re-raises the UAC **on A**. Without this, the one-tap-retry can't work across devices — only the "go look at A" ping does.++If cross-device round-trip is too big for a first cut, **Ask 1 + a one-way `target`+ping (Ask 2 minus the round-trip)** already makes this usable: pup pings the attended+device to send the user to box A, and box A shows the UAC. The re-arm-on-tap is a+follow-up.++## What pup already does (so you know the bridge side is ready)++- Probes `GET /commands` for `notify_user`; caches capability (`chromeStableNotifyChannel`).+- **If reachable:** notify-FIRST — fires a sticky `reminder` toast with an **Approve now**+ button and **waits for the tap before raising the UAC** (raising first puts up the+ secure desktop, which hides the toast). Re-notifies + re-waits on expiry. Autonomous.+- **If NOT reachable (today):** raises the UAC **once**, sets `awaiting_uac` ++ `chromeStableNotifyChannel:false` + errorCode `chrome_stable_needs_approval_uncced`,+ and returns a hint telling the AI to relay "go click YES on box A". **No blind+ re-raise** (that was a 1.8.12 bug that spammed the UAC).+- The moment AD ships Ask 1, pup's local-case notify works with zero pup changes. Ask 2+ (attended-device `target`) will need pup to pass `target` — a tiny follow-up once the+ contract is decided.