mirror of
https://github.com/Tencent/BrowserSkill.git
synced 2026-09-10 13:01:23 +08:00
8.0 KiB
8.0 KiB
browser-skill architecture
Developer-oriented overview of how the CLI, daemon, and extension fit together. Consolidates design §2, §3, §5, and §6.
System diagram
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.lockis absent or stale. - Speaks JSON Lines over
~/.bsk/daemon.sock(Unix) or a named pipe (Windows). - Renders human-readable output by default;
--jsonemits 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) andsessions(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
- Agent runs
bsk click @e1 --tab-id 42 --session ab12. - CLI ensures daemon is running, opens UDS, sends one JSON request line.
- Daemon resolves session
ab12→ browser client → forwardstool.clickover WS. - Extension dispatcher validates sandbox rules, invokes CDP via
BrowserDriver. - Response travels CLI ← daemon ← extension; CLI prints result and exits.
The scroll-to primitive reference documents tool.scroll_to,
including its CLI/plugin mappings, visible-bounds contract and cancellation
behavior. It follows the same routing path and is classified as a browser
mutation for session queueing and user-interruption gating.
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
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.
evaluaterestricted 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. Before browser dispatch it owns rollback of partially staged uploads; after dispatch, ownership moves to the session because a transport timeout cannot prove that Chrome did not attach the file. Download output becomes visible through one atomic commit, and replacement is opt-in without a pre-delete window. The extension never receives either agent-facing path.
- The daemon is the authority for storage capabilities and limits. It issues opaque session-scoped transfer IDs, stages bounded chunks in a private runtime directory, and injects only private staged upload paths. For download it mints one relative Chrome directory capability. Only after validating the reported path, file type, symlink boundary, and authoritative byte limit does it take ownership of browser-file cleanup and import the bytes.
- The extension owns only the browser transaction. Every transfer resolves one
ResolvedActionTarget. The default upload mechanism arms Chrome's chooser interception before clicking, then accepts either an exactPage.fileChooserOpenedinput node or an independent probe anchored in the trigger node's document; one verified input is committed withDOM.setFileInputFiles, while a non-input picker is rejected immediately. Explicit drop mode performs no click and never falls back to the chooser mechanism: after geometry resolution it temporarily excludes BrowserSkill's own overlay, verifies that the resolved drop zone still owns its local action point, and sends one nativedragEnter/dragOver/droptransaction to that node's CDP target before restoring the overlay. OOPIF drops use target-local coordinates rather than top-level click coordinates. Download correlates exact-target CDP intent andchrome.downloadsfilename candidates in either arrival order, claims only one unique match, and never cancels an unclaimed candidate. - Browser-side operations report
effect_state(none,committed, orunknown),phase, andcleanup_state. Confirmed success wins over a late cancel; an unknown effect is preserved across timeout or transport loss and must not be retried blindly. A transfer deadline sends cancellation to the extension and keeps the session queue occupied for bounded compensation rather than abandoning an in-flight browser effect. - Download staging is released after CLI commit. Upload staging remains until session teardown because the page may read an attached file only on a later form submission. Remaining staging is released on session stop/browser disconnect and on daemon startup after a crash. BrowserSkill does not inspect content or decide whether a transfer is appropriate.
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