feat: list, inspect, and navigate tabs in a dedicated browser #163
- IA
First browser slice for #50; it doesn't close #50. Three tools list, navigate, and inspect tabs in a dedicated development browser on the execution host, over direct Chrome DevTools Protocol on loopback.
- **Wiring.** A runtime-neutral `Browser` capability (`packages/channel/src/browser.ts`) is injected at `Channel.open` by the local worker, the workspace `Link`/`serve`, and the hosted object. Pi stores the results; there is no new store. - **Dedicated browser only.** `apps/host/src/browser.ts` reads `DevToolsActivePort` only from `$ACE_HOME/browser` and checks the port and browser path. It never reaches personal browsers or other debugging sessions, and it doesn't launch the browser. Refusals include a macOS or Linux launch command. - **Exact targets.** A target is the browser instance ID plus Chrome's target ID. Every call refuses a replaced browser or a closed or non-page tab before dispatch. Tabs are never chosen by URL, title, or position, and prerender targets are not listed. - **`browser_inspect`** returns: - the main frame's accessibility tree, capped at 32 KB of UTF-8 with 400-byte fields; - an unresized viewport JPEG of at most 4096 px per side and 900 KB; - the loader ID before and after, so the result says whether the document changed.
A screenshot, deadline, or 16 MB per-command failure keeps the other evidence. Results stay under 2 MB. - **`browser_navigate`** (http/https only) runs sequentially and is unsafe to replay. Chrome's answer comes back as `started`, `same_document`, `download` (keeping the error text), or `failed`, never as readiness. An uncertain dispatch or answer is `unknown`, and dispatch may have happened.
### Validation
`bun types` and `bun run ci` pass. CI passed on `0ee3f53`. The runtime checks exercised the same host behavior before the final wording and launch-hint edits (`8ff9cd2`, `8f227e1`, and the Linux hint), not every check on the exact final head. Detailed logs are kept privately.
- **Real Chrome for Testing 153 and Chrome 154,** each with its own temporary profile: - Same-title tabs stayed distinct. - Closed, replaced, and stale targets were refused. - Normal, hash, failed, and download navigation returned the expected statuses. - Cancelling before dispatch was refused. Cancelling after dispatch was `unknown`, and the navigation still happened. - A wide accessibility tree was bounded as expected. An oversized tree failed only its own command and kept the screenshot. - A zoomed, scrolled viewport capture was checked. - **Real Anthropic model in a native channel:** - Tabs, navigate, and inspect worked on the rendered Ace app shell. It showed the disconnected-host banner; this was not an authenticated workflow. - The screenshot was stored in history. - After I killed the worker mid-navigation, the reopened worker reported it interrupted and did not repeat it. - Tool results and usage stayed identical through a fresh worker reopen. - **Compiled Ace Helper:** the worker reopened without replay. Fresh tools completed once the key was passed into that disposable worker's environment. Its first run stalled before admission, likely on the Keychain lookup. - **Workspace forwarding:** real `Link`/`serve` over a WebSocket. While disconnected, navigation was refused and inspection failed. After reconnecting, the same browser identity worked. A drop during navigation was `unknown`.
### Limits
- I did not run a deployed or `wrangler dev` hosted object. - Still open in #50: DOM input and element references, console and network inspection, uploads, viewport and mobile emulation, managed browser launch, iframe content, Browser Preview, and reproducing, fixing, and verifying a real defect end to end. - Cleanup is done: the owned processes are stopped, and the temporary profiles, host data, project, and helper are deleted. One smoke download had landed outside the profile, at `/Users/natebutler/Downloads/x.bin`. A direct-path check confirmed it was 4 bytes containing `data`, and I removed it.
### Built in Ace
Implementation, validation, commits, and this PR were done by the native Ace channel `browser-pages`, using Ace's lane, shell, file, and model tools. External Codex did read-only architecture research coordination and review, and passed notes into the channel, because Ace lacks external-harness support (#9). No code or validation ran outside Ace.
iamnbutlerreferenced this in Inspect and debug browser pages from an Ace channel #50last month on GitHub
iamnbutlermerged 8ae23e4ce459last month on GitHub
iamnbutlerreferenced this in Open a lane's dev server from its channel #16last month on GitHub
iamnbutlerreferenced this in [Meta] Dogfood Ace end to end #5last month on GitHub
iamnbutlerreferenced this in [Meta] Complete native computer use in Ace #8last month on GitHub