@divebell/agent-browser 0.33.1-divebell.1 → 0.33.2-divebell.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -2
- package/bin/agent-browser-darwin-arm64 +0 -0
- package/bin/agent-browser-darwin-x64 +0 -0
- package/bin/agent-browser-linux-arm64 +0 -0
- package/bin/agent-browser-linux-musl-arm64 +0 -0
- package/bin/agent-browser-linux-musl-x64 +0 -0
- package/bin/agent-browser-linux-x64 +0 -0
- package/bin/agent-browser-win32-x64.exe +0 -0
- package/package.json +1 -1
- package/skill-data/core/SKILL.md +1 -0
- package/skill-data/core/references/commands.md +11 -0
- package/skill-data/core/references/streaming.md +104 -0
package/README.md
CHANGED
|
@@ -1043,7 +1043,7 @@ Create an `agent-browser.json` file to set persistent defaults instead of repeat
|
|
|
1043
1043
|
|
|
1044
1044
|
**Locations (lowest to highest priority):**
|
|
1045
1045
|
|
|
1046
|
-
1. `~/.agent-browser/config.json`: user-level defaults
|
|
1046
|
+
1. `~/.agent-browser/config.json`: user-level defaults (or `$AGENT_BROWSER_HOME/config.json`)
|
|
1047
1047
|
2. `./agent-browser.json`: project-level overrides (in working directory)
|
|
1048
1048
|
3. `AGENT_BROWSER_*` environment variables override config file values
|
|
1049
1049
|
4. CLI flags override everything
|
|
@@ -1075,6 +1075,15 @@ agent-browser --config ./ci-config.json open example.com
|
|
|
1075
1075
|
AGENT_BROWSER_CONFIG=./ci-config.json agent-browser open example.com
|
|
1076
1076
|
```
|
|
1077
1077
|
|
|
1078
|
+
For sandboxed agents whose home directory is read-only, set
|
|
1079
|
+
`AGENT_BROWSER_HOME` to a writable directory such as `/tmp/agent-browser`.
|
|
1080
|
+
This relocates agent-browser-owned configuration, session state, browser
|
|
1081
|
+
downloads, temporary artifacts, and daemon files without changing `HOME` for
|
|
1082
|
+
other tools. When no override is set and `~/.agent-browser` is not writable,
|
|
1083
|
+
agent-browser automatically uses a short per-user directory under `/tmp` on
|
|
1084
|
+
Unix. Sandboxes that prohibit local sockets or browser processes entirely
|
|
1085
|
+
still require a browser running outside the sandbox and a reachable CDP URL.
|
|
1086
|
+
|
|
1078
1087
|
All options from the table above can be set in the config file using camelCase keys (e.g., `--executable-path` becomes `"executablePath"`, `--proxy-bypass` becomes `"proxyBypass"`). Plugins are configured with the `"plugins"` array shown above. Unknown keys are ignored for forward compatibility.
|
|
1079
1088
|
|
|
1080
1089
|
A [JSON Schema](agent-browser.schema.json) is available for IDE autocomplete and validation. Add a `$schema` key to your config file to enable it:
|
|
@@ -1448,6 +1457,24 @@ To bind to a specific port, set `AGENT_BROWSER_STREAM_PORT`:
|
|
|
1448
1457
|
AGENT_BROWSER_STREAM_PORT=9223 agent-browser open example.com
|
|
1449
1458
|
```
|
|
1450
1459
|
|
|
1460
|
+
Frame encoding is daemon-wide:
|
|
1461
|
+
|
|
1462
|
+
| Variable | Default | Description |
|
|
1463
|
+
|---|---|---|
|
|
1464
|
+
| `AGENT_BROWSER_STREAM_QUALITY` | `80` | JPEG quality, 0 to 100 |
|
|
1465
|
+
| `AGENT_BROWSER_STREAM_MAX_WIDTH` | the viewport | Caps frame width in pixels |
|
|
1466
|
+
| `AGENT_BROWSER_STREAM_MAX_HEIGHT` | the viewport | Caps frame height in pixels |
|
|
1467
|
+
|
|
1468
|
+
Width and height cap the encoded frame and leave the page size alone, so a portrait or HiDPI viewport keeps its resolution unless you cap it. The live stream requests jpeg. An explicit `screencast_start` reconfigures the same screencast, so a client can see the format change mid-stream. On a busy page at 1280x720, quality 80 costs about 54 KB per frame, quality 20 about 25 KB, and quality 20 at 640x360 about 9 KB.
|
|
1469
|
+
|
|
1470
|
+
```bash
|
|
1471
|
+
# Cheaper frames for a constrained link
|
|
1472
|
+
AGENT_BROWSER_STREAM_QUALITY=20 \
|
|
1473
|
+
AGENT_BROWSER_STREAM_MAX_WIDTH=640 \
|
|
1474
|
+
AGENT_BROWSER_STREAM_MAX_HEIGHT=360 \
|
|
1475
|
+
agent-browser open example.com
|
|
1476
|
+
```
|
|
1477
|
+
|
|
1451
1478
|
You can also manage streaming at runtime with `stream enable`, `stream disable`, and `stream status`:
|
|
1452
1479
|
|
|
1453
1480
|
```bash
|
|
@@ -1466,6 +1493,7 @@ Connect to `ws://localhost:9223` to receive frames and send input:
|
|
|
1466
1493
|
```json
|
|
1467
1494
|
{
|
|
1468
1495
|
"type": "frame",
|
|
1496
|
+
"seq": 41,
|
|
1469
1497
|
"data": "<base64-encoded-jpeg>",
|
|
1470
1498
|
"metadata": {
|
|
1471
1499
|
"deviceWidth": 1280,
|
|
@@ -1473,11 +1501,14 @@ Connect to `ws://localhost:9223` to receive frames and send input:
|
|
|
1473
1501
|
"pageScaleFactor": 1,
|
|
1474
1502
|
"offsetTop": 0,
|
|
1475
1503
|
"scrollOffsetX": 0,
|
|
1476
|
-
"scrollOffsetY": 0
|
|
1504
|
+
"scrollOffsetY": 0,
|
|
1505
|
+
"timestamp": 1785038682238
|
|
1477
1506
|
}
|
|
1478
1507
|
}
|
|
1479
1508
|
```
|
|
1480
1509
|
|
|
1510
|
+
`seq` is a monotonic frame id, echoed back in an `ack` message under ack pacing. `metadata.timestamp` is the capture time in epoch milliseconds, so a client can tell how old a frame is by the time it draws it.
|
|
1511
|
+
|
|
1481
1512
|
**Send mouse events:**
|
|
1482
1513
|
|
|
1483
1514
|
```json
|
|
@@ -1512,6 +1543,17 @@ Connect to `ws://localhost:9223` to receive frames and send input:
|
|
|
1512
1543
|
}
|
|
1513
1544
|
```
|
|
1514
1545
|
|
|
1546
|
+
**Cap the frame rate (per client):**
|
|
1547
|
+
|
|
1548
|
+
```json
|
|
1549
|
+
{
|
|
1550
|
+
"type": "config",
|
|
1551
|
+
"maxFps": 10
|
|
1552
|
+
}
|
|
1553
|
+
```
|
|
1554
|
+
|
|
1555
|
+
Frames are delivered latest-first: the server picks the newest frame at send time, so frames produced while an earlier one is still being written are skipped rather than queued. `maxFps` (1 to 120, `0` = uncapped) limits delivery for that client only. A client that sends `{"type":"config","pacing":"ack"}` receives one frame at a time and acknowledges it with `{"type":"ack","seq":N}`, so nothing stale reaches the socket even if that client stalls; in the default push pacing, frames already handed to the transport are still delivered in order. Both settings can also be declared on the URL (`ws://127.0.0.1:<port>/?pacing=ack&maxFps=10`), which is the only way to cover the connection's opening frame. Input events are read on a dedicated task per connection, so clicks and keystrokes dispatch immediately even while frames are mid-write to a slow client. They are sent to the browser without waiting for its reply, so a click stays responsive behind a burst of mouse moves, and ordering is preserved.
|
|
1556
|
+
|
|
1515
1557
|
## Architecture
|
|
1516
1558
|
|
|
1517
1559
|
agent-browser uses a client-daemon architecture:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/skill-data/core/SKILL.md
CHANGED
|
@@ -513,6 +513,7 @@ That pulls in:
|
|
|
513
513
|
- `references/session-management.md` — persistence, multi-session workflows
|
|
514
514
|
- `references/profiling.md` — Chrome DevTools tracing and profiling
|
|
515
515
|
- `references/video-recording.md` — video capture options
|
|
516
|
+
- `references/streaming.md` covers live viewport streaming, remote input, per-client frame rate, and the encoding vars that set bandwidth cost
|
|
516
517
|
- `references/proxy-support.md` — proxy configuration
|
|
517
518
|
- `references/webgpu.md` — screenshots/video of WebGPU pages (three.js, Babylon.js), Linux/CI setup
|
|
518
519
|
- `templates/*` — starter shell scripts for auth, capture, form automation
|
|
@@ -328,6 +328,17 @@ agent-browser state save auth.json # Save cookies, storage, auth state
|
|
|
328
328
|
agent-browser state load auth.json # Restore saved state
|
|
329
329
|
```
|
|
330
330
|
|
|
331
|
+
## Live Streaming
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
agent-browser stream status --json # Enabled state, port, client count
|
|
335
|
+
agent-browser stream enable # Start the WebSocket stream server
|
|
336
|
+
agent-browser stream enable --port 9223
|
|
337
|
+
agent-browser stream disable # Stop it
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Clients connect to `ws://127.0.0.1:<port>` and receive `frame`, `status`, `tabs`, `url`, and `console` messages. They send `input_mouse`, `input_keyboard`, and `input_touch` to drive the page, `{"type":"config","maxFps":N}` (1 to 120, `0` = uncapped) to cap their own frame rate, and `{"type":"config","pacing":"ack"}` to receive one frame at a time, acknowledged with `{"type":"ack","seq":N}`. Both settings can be declared on the URL instead (`ws://127.0.0.1:<port>/?pacing=ack&maxFps=10`). See [streaming.md](streaming.md).
|
|
341
|
+
|
|
331
342
|
## MCP Server
|
|
332
343
|
|
|
333
344
|
```bash
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Live Streaming
|
|
2
|
+
|
|
3
|
+
Stream a session's viewport over WebSocket and drive it with remote input. This is what a remote preview or embedded dashboard connects to: the browser runs wherever the daemon runs (a sandbox, a container, a CI box), and the client renders frames and sends clicks back.
|
|
4
|
+
|
|
5
|
+
**Related**: [commands.md](commands.md) for full command reference, [SKILL.md](../SKILL.md) for quick start.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Enabling the stream](#enabling-the-stream)
|
|
10
|
+
- [Connecting](#connecting)
|
|
11
|
+
- [Messages from the server](#messages-from-the-server)
|
|
12
|
+
- [Messages from the client](#messages-from-the-client)
|
|
13
|
+
- [Frame rate and staleness](#frame-rate-and-staleness)
|
|
14
|
+
- [Limitations](#limitations)
|
|
15
|
+
|
|
16
|
+
## Enabling the stream
|
|
17
|
+
|
|
18
|
+
Streaming is always available; the server binds an OS-assigned localhost port unless told otherwise.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
agent-browser stream status --json # Report enabled state, port, client count
|
|
22
|
+
agent-browser stream enable # Create the server (--port to pin one)
|
|
23
|
+
agent-browser stream disable # Tear it down
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`AGENT_BROWSER_STREAM_PORT` pins the port for the whole daemon instead of passing `--port`.
|
|
27
|
+
|
|
28
|
+
Frame encoding is daemon-wide, read once at startup:
|
|
29
|
+
|
|
30
|
+
| Variable | Default | Notes |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `AGENT_BROWSER_STREAM_QUALITY` | `80` | 0 to 100, clamped |
|
|
33
|
+
| `AGENT_BROWSER_STREAM_MAX_WIDTH` | the viewport | caps the frame, does not resize the page |
|
|
34
|
+
| `AGENT_BROWSER_STREAM_MAX_HEIGHT` | the viewport | same |
|
|
35
|
+
|
|
36
|
+
The live stream requests jpeg, since a `frame` message carries no format field. An explicit `screencast_start` reconfigures the same underlying screencast, so a client can still see the format change mid-stream; sniff the bytes rather than assuming. Measured on a busy page at 1280x720: quality 80 gives ~54 KB per frame, quality 20 gives ~25 KB, and quality 20 at 640x360 gives ~9 KB. An unusable value leaves the default.
|
|
37
|
+
|
|
38
|
+
Read the port from `stream status --json` rather than assuming one; the OS-assigned default changes per daemon.
|
|
39
|
+
|
|
40
|
+
## Connecting
|
|
41
|
+
|
|
42
|
+
Connect a WebSocket client to `ws://127.0.0.1:<port>`. Frame delivery starts automatically once a client attaches, so there is no subscribe message. Browser clients must load from `localhost`, `127.0.0.1`, `::1` or `file://`. Any other origin gets a 403 on the upgrade and needs a proxy.
|
|
43
|
+
|
|
44
|
+
## Messages from the server
|
|
45
|
+
|
|
46
|
+
Every message is JSON text with a `type` field.
|
|
47
|
+
|
|
48
|
+
- `frame`: a viewport image plus its metadata. Delivered latest-first (see below).
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"type": "frame",
|
|
53
|
+
"seq": 41,
|
|
54
|
+
"data": "<base64-encoded-jpeg>",
|
|
55
|
+
"metadata": {
|
|
56
|
+
"deviceWidth": 1280, "deviceHeight": 720, "pageScaleFactor": 1,
|
|
57
|
+
"offsetTop": 0, "scrollOffsetX": 0, "scrollOffsetY": 0,
|
|
58
|
+
"timestamp": 1785038682238
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`seq` is a monotonic frame id, echoed back under ack pacing and stable across browser relaunches. `metadata.timestamp` is the capture time in epoch milliseconds, so `Date.now() - timestamp` is the age of the frame being drawn. The other message types:
|
|
64
|
+
|
|
65
|
+
- `status`: connection state, screencasting flag, viewport size, engine, recording flag. Sent once on connect and again on change.
|
|
66
|
+
- `tabs`: the current tab list, sent on connect when tabs are known and on change.
|
|
67
|
+
- `url`, `console`: navigation and console events.
|
|
68
|
+
|
|
69
|
+
Status, tabs, url, and console travel on an ordered channel: they are delivered in order and are never replaced by a newer message the way frames are. They are not unconditionally durable. A client that falls far enough behind can lag out of that channel and lose messages it never saw, so treat console output as a live feed, not an audit log.
|
|
70
|
+
|
|
71
|
+
## Messages from the client
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{"type": "input_mouse", "eventType": "mousePressed", "x": 40, "y": 40, "button": "left", "clickCount": 1}
|
|
75
|
+
{"type": "input_keyboard", "eventType": "keyDown", "key": "a", "text": "a"}
|
|
76
|
+
{"type": "input_touch", "eventType": "touchStart", "touchPoints": []}
|
|
77
|
+
{"type": "config", "maxFps": 10}
|
|
78
|
+
{"type": "config", "pacing": "ack"}
|
|
79
|
+
{"type": "ack", "seq": 41}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Input dispatches to the browser on a task of its own, separate from frame delivery, so a click is not queued behind a frame write. Events are sent to the browser without waiting for its reply, so a click stays responsive behind a burst of mouse moves. Ordering is preserved: press never overtakes move. Mouse, keyboard, and touch input also reset the daemon idle timer, so an actively driven preview is not shut down by the idle timeout.
|
|
83
|
+
|
|
84
|
+
`config` sets a per-client frame cap: 1 to 120, or `0` for uncapped (the default). It takes effect immediately, including when it loosens the cap. Each client's cap is its own; other connected clients are unaffected. A value above 120 is clamped to 120; a negative or non-numeric value is ignored, leaving the current cap in place. Neither rejects the connection.
|
|
85
|
+
|
|
86
|
+
Both settings can also be declared on the URL, which is the only way to have them cover the connection's opening frame: `ws://127.0.0.1:<port>/?pacing=ack&maxFps=10`. A `config` message sent after connecting still wins.
|
|
87
|
+
|
|
88
|
+
## Frame rate and staleness
|
|
89
|
+
|
|
90
|
+
The server holds only the newest frame per client and reads it at send time. A frame produced while an earlier one is still being written is skipped, not queued, so the application never builds a backlog.
|
|
91
|
+
|
|
92
|
+
Push pacing (the default) stops there, and the transport underneath is still ordered: frames already accepted by the socket are delivered in order, so a client that stalls drains whatever the kernel buffered before the writer blocked.
|
|
93
|
+
|
|
94
|
+
Ack pacing closes that gap. Send `{"type":"config","pacing":"ack"}` and the server keeps at most one frame in flight, waiting for `{"type":"ack","seq":N}` before sending the next. Every frame carries a monotonic `seq`; echo the one you finished rendering. Frames produced while an ack is outstanding replace each other and never reach the socket, so a client that stalls for ten seconds and resumes gets the current page, not ten seconds of history.
|
|
95
|
+
|
|
96
|
+
Under ack pacing one frame is in flight at a time, so the rate is one frame per transfer plus one acknowledgement round trip. Both the link's bandwidth and its latency bound it, and a link whose bandwidth-delay product exceeds a single frame goes underused. Ack pacing bounds one hop. With a proxy in the path, forward the renderer's acks; acks generated on receipt leave frames queued on the far side. Acks are cumulative, so acknowledging a newer id covers any older one. A client that opts in and then stops acking simply stops receiving frames; status, tabs, url, and console keep flowing.
|
|
97
|
+
|
|
98
|
+
The two settings compose: `pacing` bounds how much is in flight, `maxFps` bounds the rate. A constrained preview usually wants both.
|
|
99
|
+
|
|
100
|
+
## Limitations
|
|
101
|
+
|
|
102
|
+
- Localhost only. Exposing the stream beyond the machine is the embedder's job (tunnel, proxy, or port forward), and the origin allowlist applies to browser clients.
|
|
103
|
+
- Frames are images, not a video codec. Bandwidth scales with viewport size and page activity; cap the rate for constrained links.
|
|
104
|
+
- In push pacing the server cannot tell a slow renderer from a fast one beyond transport backpressure. Use ack pacing when that distinction matters.
|