Files
BrowserSkill/docs/architecture.md
T

166 lines
6.5 KiB
Markdown

# browser-skill architecture
Developer-oriented overview of how the CLI, daemon, and extension fit together.
Consolidates design §2, §3, §5, and §6.
## System diagram
```mermaid
flowchart TB
subgraph harness [Agent harness]
Agent[Claude Code / Cursor / Codex]
end
subgraph host [Developer machine]
Agent -->|shell: bsk ...| CLI[bsk CLI]
CLI <-->|JSON Lines / UDS| Daemon[bsk daemon]
Daemon <-->|WebSocket JSON| Ext[bsk extension MV3]
end
subgraph browser [Chromium]
Ext -->|CDP + WebExt| Tabs[User tabs + Agent Windows]
end
Skill[SKILL.md] -.->|documents workflow| Agent
```
## Components
### bsk CLI (`crates/bsk-cli`)
- Parses verb-noun subcommands (`bsk session start`, `bsk click`, …).
- On first use, **auto-spawns** the daemon if `~/.bsk/daemon.lock` is absent or stale.
- Speaks JSON Lines over `~/.bsk/daemon.sock` (Unix) or a named pipe (Windows).
- Renders human-readable output by default; `--json` emits structured responses.
Key modules:
| Module | Role |
| --- | --- |
| `cli/` | Clap command tree, per-tool handlers |
| `ipc_client.rs` | UDS client, line framing |
| `daemon/` | WS server, session routing, idle shutdown |
### bsk daemon (same binary: `bsk daemon`)
- Listens on loopback WebSocket (default **52800**) for extensions.
- Validates `Origin: chrome-extension://…` on handshake.
- Maintains `browsers` (connected extensions) and `sessions` (Agent Window bindings).
- **Per-session queue** serializes tool calls targeting one session.
- Forwards `tool.*` RPCs to the correct extension connection.
State files under `~/.bsk/`:
| File | Purpose |
| --- | --- |
| `daemon.lock` | Advisory lock — single daemon instance |
| `daemon.json` | `{ sock_path, pid, ws_port, version }` |
| `daemon.log` | Rolling trace log |
| `daemon.pid` | PID for status/doctor |
### bsk extension (`apps/extension`)
WXT / MV3 Chromium extension. Built with React popup and a service worker background.
| Directory | Responsibility |
| --- | --- |
| `transport/` | Pluggable `Transport` (v1: `WSTransport`) |
| `tools/` | `ToolDispatcher` → 21 tool handlers |
| `session-manager/` | Sessions, Agent Window, ref-store (`@e1`) |
| `browser-driver/` | CDP-backed browser operations |
| `entrypoints/popup/` | Connection status UI |
| `content/` | Control overlay in Agent Windows |
### bsk-protocol (`crates/bsk-protocol`)
Shared Rust types + JSON Schema generation. TypeScript mirrors frame shapes in
`apps/extension/src/transport/types.ts` (kept in sync via tests and schema dumps).
## Typical tool call
1. Agent runs `bsk click @e1 --tab-id 42 --session ab12`.
2. CLI ensures daemon is running, opens UDS, sends one JSON request line.
3. Daemon resolves session `ab12` → browser client → forwards `tool.click` over WS.
4. Extension dispatcher validates sandbox rules, invokes CDP via `BrowserDriver`.
5. Response travels CLI ← daemon ← extension; CLI prints result and exits.
## Session and sandbox model
- **Session** = opaque ID (4 lowercase letters in v0.1) + dedicated **Agent Window**
+ session-scoped ref-store + borrow table.
- **Sandbox-only**: write tools require tabs inside the Agent Window unless the tab
was **borrowed** from the user profile.
- **Session stop is mandatory** in agent workflows (`bsk session stop`); idle timeout
(default 5 min) is a safety net only.
- Multiple sessions on one browser → multiple Agent Windows, fully isolated.
### tab_list scopes
| `scope` | Visible tabs |
| --- | --- |
| `user` | User profile windows (default) |
| `agent` | Current session's Agent Window only |
| `all` | Agent Window + user windows for this session |
## Concurrency
| Scope | Policy |
| --- | --- |
| Same session | Daemon serializes RPCs (ref-store safety) |
| Different sessions | Parallel |
| Multiple browsers | `bsk session start --browser <id>` when >1 extension connected |
## Module dependency graph
```mermaid
flowchart LR
subgraph rust [Rust workspace]
CLI[bsk CLI crate]
Proto[bsk-protocol]
CLI --> Proto
end
subgraph ts [Extension]
BG[background]
T[Transport]
D[ToolDispatcher]
SM[SessionManager]
BD[BrowserDriver]
BG --> T
BG --> D
D --> SM
D --> BD
SM --> BD
end
CLI <-->|JSON protocol| T
```
## Security (v1)
- Daemon and WebSocket bind to **loopback** only.
- Extension origin allow-list at WS upgrade.
- No credential storage in bsk — cookies stay in the user's browser profile.
- `evaluate` restricted to Agent Window tabs in sandbox mode.
### File-transfer boundary
- The invoking agent/harness decides whether a transfer is authorized and supplies the task-local source or destination path.
- The CLI is the only component that reads an upload source or writes the final download destination. The extension never receives either agent-facing path.
- The daemon issues opaque, session-scoped transfer IDs and stages bounded chunks in a private runtime directory. For upload it injects only its private staged paths. For download it mints a relative Chrome directory capability, validates the reported completed path against that capability, rejects symlinks and oversized/non-regular files, then imports the bytes into private staging.
- The extension only performs the browser-side mechanism, scoped to the requested session and exact Agent Window target. Upload installs a transaction-scoped DOM guard that records the one `<input type="file">` actually activated by the requested click while cancelling its native default action, then uses `DOM.setFileInputFiles`. File System Access picker entry points are intercepted only for that transaction and return a structured fallback. Download requires an exact-target `Page.downloadWillBegin` intent before a matching `chrome.downloads` item is routed into the daemon-minted relative directory. The extension does not classify content or make policy decisions.
- Download staging is released after the CLI commits the file. Upload staging remains until session teardown because the page may read an attached file only on a later form submission. All staging is released on session stop/browser disconnect and on daemon startup after a crash. Existing download destinations are not overwritten unless the CLI caller explicitly opts in.
## Repository layout
```
browser-skill/
├── apps/extension/ # WXT Chromium extension
├── crates/
│ ├── bsk-cli/ # `bsk` binary (CLI + daemon)
│ └── bsk-protocol/ # Wire types + schemas
├── install.sh # CLI installer (GitHub Releases)
├── skill/SKILL.md # Agent harness instructions
└── docs/ # architecture, guides
```