pi-browser-harness 0.4.0 โ 0.6.0
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/CHANGELOG.md +27 -0
- package/README.md +150 -56
- package/package.json +2 -1
- package/skills/pi-browser-harness/SKILL.md +24 -1
- package/src/cdp/console-buffer.ts +263 -0
- package/src/cdp/daemon-transport.ts +277 -0
- package/src/cdp/session.ts +124 -23
- package/src/client.ts +29 -10
- package/src/daemon/bridge.ts +411 -0
- package/src/daemon/index.ts +114 -0
- package/src/daemon/protocol.ts +162 -0
- package/src/daemon/server.ts +245 -0
- package/src/daemon/spawn.ts +85 -0
- package/src/domains/console.ts +173 -0
- package/src/domains/navigate.ts +17 -3
- package/src/domains/setup.ts +41 -0
- package/src/index.ts +46 -25
- package/src/prompt.ts +3 -0
- package/src/registry.ts +5 -0
- package/src/setup.ts +45 -39
- package/src/util/tool.ts +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to pi-browser-harness will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.6.0 โ 2026-06-21
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Per-tab isolation for multi-agent safety.** Each agent's browser session now operates in a dedicated Chrome window with tab ownership tracking. Tabs opened via `browser_open_urls` and `browser_new_tab` are automatically registered in the ownership registry and tagged with a ๐ข prefix in the document title for user visibility. `browser_list_tabs` scoped to `"owned"` (default) only shows the current session's tabs.
|
|
10
|
+
- **Unix socket daemon with auto-reconnect.** The browser daemon now binds to a Unix-domain socket (`pi-browser.sock`) in the harness temp directory instead of a TCP port. The transport layer reconnects automatically when Chrome restarts โ no manual `/browser-reload-daemon` needed.
|
|
11
|
+
- **On-demand browser initialization.** Chrome is no longer launched eagerly at harness startup. The harness attaches lazily on the first browser tool call, reducing resource usage when the agent isn't using the browser.
|
|
12
|
+
- **`browser_setup` as agent-callable tool.** The setup tool can now be called programmatically by agents, not just via slash command. Idempotent โ safe to call when already connected.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **Chrome detection on macOS** now matches by process-name substring instead of exact binary path comparison, fixing false negatives when Chrome is running from different installation paths (e.g. `/Applications/Google Chrome.app/` vs user-local copies).
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **`browser_console`** โ new tool. Reads JS errors and console messages from the active tab via two CDP sources merged into one buffer: `Runtime.consoleAPICalled` (page `console.*` calls and uncaught exceptions) and `Log.entryAdded` (browser-level entries โ CSP violations, mixed content, deprecations, network errors). Filters: `levels` (log/info/warn/error/debug), `textPattern` (substring; wrap in slashes for regex), `sinceMs`, `limit` (default 50, cap 500). Each record carries a monotonic `seq`; the response includes `nextCursor` so callers can pass `sinceSeq` to see only what's new since the previous drain โ the cursor pattern that makes "what did this action cause?" answerable in one call. Buffer is page-scoped (cleared on tab switch) and bounded at 500 records; `bufferOverflowed` flag reports drops since the last drain. Stack traces (top 3 frames) are preserved for error/warn records. Per-arg cap of 2 KB prevents a single `console.log(hugeBlob)` from blowing the buffer.
|
|
21
|
+
- **`Log` CDP domain enabled** alongside Page/DOM/Runtime/Network/Accessibility on every attach. (`Runtime` was already enabled, so `Runtime.consoleAPICalled` was reachable; this adds the missing domain for browser-level entries.)
|
|
22
|
+
- **`browser_console` ships with a custom `renderResult`** following the established pattern โ collapsed: header counts (`3 errors ยท 2 warnings ยท 47 logs`) + last 5 rows. Expanded: full list with stack traces inline as code fences. Appends `keyHint("app.tools.expand", ...)` so the binding label adapts to user remaps.
|
|
23
|
+
|
|
24
|
+
### Internal
|
|
25
|
+
|
|
26
|
+
- New pure module `src/cdp/console-buffer.ts` mirrors the `network-buffer.ts` pattern (insertion-ordered Map, FIFO eviction at capacity 500, overflow flag reset per drain). Wired into the existing single-consumer event loop in `src/cdp/session.ts`.
|
|
27
|
+
|
|
28
|
+
### Known follow-ups
|
|
29
|
+
|
|
30
|
+
- No tests added in this release. Verification is manual against real Chrome.
|
|
31
|
+
|
|
5
32
|
## 0.4.0 โ 2026-05-06
|
|
6
33
|
|
|
7
34
|
### Added
|
package/README.md
CHANGED
|
@@ -2,7 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
Full browser control for pi agents
|
|
5
|
+
Full browser control for pi agents in **your real Chrome** โ your sessions, your cookies, your tabs. Drives navigation, structured page reads, network capture, clicks, typing, screenshots, and arbitrary scripts via CDP.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Why pi-browser-harness?
|
|
10
|
+
|
|
11
|
+
| Capability | pi-browser-harness | Playwright MCP | Stagehand | Puppeteer MCP |
|
|
12
|
+
|---|:---:|:---:|:---:|:---:|
|
|
13
|
+
| **Drives your real Chrome** (logged-in sessions preserved) | โ
| โ launches its own browser | โ | โ |
|
|
14
|
+
| **Coordinate clicks** that work through iframes, shadow DOM, cross-origin | โ
| โ selector-based | โ selector-based | โ selector-based |
|
|
15
|
+
| **Inline TUI screenshot rendering** (Kitty/iTerm2/Ghostty/WezTerm) | โ
| โ | โ | โ |
|
|
16
|
+
| **Accessibility-tree snapshot with click coords `@(x,y)` per element** | โ
| โ
tree only, no coords | partial | โ |
|
|
17
|
+
| **Network request capture** with filters + body capture | โ
| โ
post-hoc list | โ | โ |
|
|
18
|
+
| **Parallel tool execution** with automatic mutation serialization | โ
| โ | โ | โ |
|
|
19
|
+
| **Temporary scripts** with daemon + full Node.js | โ
| โ | โ | โ |
|
|
20
|
+
| **Direct HTTP GET** outside the browser (10โ50ร faster for APIs) | โ
| โ | โ | โ |
|
|
21
|
+
| **Tab ownership isolation** โ never touches the user's other tabs | โ
| N/A | N/A | N/A |
|
|
22
|
+
| **Pi-native** โ no MCP/JSON-RPC overhead, no extra LLM API keys | โ
| โ MCP roundtrip | โ external LLM | โ MCP roundtrip |
|
|
23
|
+
| **TypeScript strict mode**, zero `any`, all CDP casts documented | โ
| unknown | unknown | unknown |
|
|
24
|
+
| Ctrl+O expand/collapse on tool output | โ
| โ | โ | โ |
|
|
25
|
+
| Compositor-level dispatch (works on every site, no flakey waits) | โ
| โ | โ | โ |
|
|
26
|
+
|
|
27
|
+
If you live in pi and you want an agent driving the same Chrome you're already signed into, this is the only one that fits.
|
|
6
28
|
|
|
7
29
|
---
|
|
8
30
|
|
|
@@ -29,84 +51,144 @@ pi install npm:pi-browser-harness
|
|
|
29
51
|
|
|
30
52
|
---
|
|
31
53
|
|
|
54
|
+
## Tool hierarchy โ read this first
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
What do you need to know?
|
|
58
|
+
|
|
59
|
+
โโ Page structure / what's clickable / labels?
|
|
60
|
+
โ โ browser_snapshot (DEFAULT โ AX tree with @(x,y) per interactive element)
|
|
61
|
+
โ
|
|
62
|
+
โโ A specific element's value / attribute / coords?
|
|
63
|
+
โ โ browser_execute_js (e.g. el.innerText, el.getBoundingClientRect())
|
|
64
|
+
โ
|
|
65
|
+
โโ Network behavior on the current page?
|
|
66
|
+
โ โ browser_network_requests
|
|
67
|
+
โ
|
|
68
|
+
โโ Visual rendering (layout / colors / chart drew correctly)?
|
|
69
|
+
โ browser_screenshot (LAST RESORT โ pixels only)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Pass `@(x,y)` from `browser_snapshot` straight to `browser_click`. **No screenshot round-trip needed** to find click targets โ the snapshot already has them.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
32
76
|
## Tools
|
|
33
77
|
|
|
78
|
+
### Page inspection (use these by default)
|
|
79
|
+
|
|
34
80
|
| Tool | Purpose |
|
|
35
81
|
|------|---------|
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
|
|
42
|
-
|
|
82
|
+
| `browser_snapshot` | **Default for page inspection.** Returns the CDP accessibility tree with click coords `@(x,y)` for every interactive element. Optional `includeScreenshot:true`. |
|
|
83
|
+
| `browser_execute_js` | Surgical DOM reads โ element text, attributes, `getBoundingClientRect()`. Cheapest, most precise. |
|
|
84
|
+
| `browser_network_requests` | List recent network requests on the current tab. Filter by url/method/status/type/recency; optional response-body capture. |
|
|
85
|
+
| `browser_page_info` | URL, title, viewport, scroll position, or pending dialog. |
|
|
86
|
+
| `browser_http_get` | Direct HTTP GET outside the browser โ 10-50ร faster for APIs. |
|
|
87
|
+
|
|
88
|
+
### Visual (last resort)
|
|
89
|
+
|
|
90
|
+
| Tool | Purpose |
|
|
91
|
+
|------|---------|
|
|
92
|
+
| `browser_screenshot` | Capture PNG/JPEG. Use only when you need to verify visual rendering. |
|
|
93
|
+
|
|
94
|
+
### Navigation
|
|
95
|
+
|
|
96
|
+
| Tool | Purpose |
|
|
97
|
+
|------|---------|
|
|
98
|
+
| `browser_navigate` / `browser_new_tab` | Navigate or open a tab |
|
|
43
99
|
| `browser_open_urls` | Open multiple URLs in parallel tabs |
|
|
44
100
|
| `browser_go_back` / `browser_go_forward` / `browser_reload` | History navigation |
|
|
45
|
-
| `
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
101
|
+
| `browser_list_tabs` / `browser_current_tab` / `browser_switch_tab` / `browser_close_tab` | Tab management (only tabs this session opened) |
|
|
102
|
+
|
|
103
|
+
### Interaction
|
|
104
|
+
|
|
105
|
+
| Tool | Purpose |
|
|
106
|
+
|------|---------|
|
|
107
|
+
| `browser_click` | Click at viewport coordinates (use `@(x,y)` from `browser_snapshot`) |
|
|
108
|
+
| `browser_type` | Type text into the focused element |
|
|
109
|
+
| `browser_press_key` | Press a key with optional modifiers |
|
|
110
|
+
| `browser_scroll` | Scroll the page by delta pixels |
|
|
111
|
+
|
|
112
|
+
### Utility
|
|
113
|
+
|
|
114
|
+
| Tool | Purpose |
|
|
115
|
+
|------|---------|
|
|
49
116
|
| `browser_wait` / `browser_wait_for_load` | Sleep, or wait for `readyState === 'complete'` |
|
|
50
117
|
| `browser_handle_dialog` | Accept or dismiss `alert` / `confirm` / `prompt` |
|
|
51
118
|
| `browser_run_script` | Execute a temporary script with daemon and Node.js access |
|
|
52
119
|
|
|
53
|
-
|
|
120
|
+
Three tools (`browser_snapshot`, `browser_network_requests`, `browser_execute_js`) ship custom TUI rendering with **Ctrl+O** (`app.tools.expand`) to toggle between compact and full output.
|
|
54
121
|
|
|
55
|
-
|
|
122
|
+
---
|
|
56
123
|
|
|
57
|
-
|
|
124
|
+
## Core patterns
|
|
58
125
|
|
|
59
|
-
###
|
|
126
|
+
### Page inspection
|
|
60
127
|
|
|
61
128
|
```
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
browser_screenshot()
|
|
129
|
+
browser_snapshot()
|
|
130
|
+
# โ AX outline with @(x,y) per button/link/input
|
|
65
131
|
```
|
|
66
132
|
|
|
67
|
-
### Form filling
|
|
133
|
+
### Form filling (no screenshots)
|
|
68
134
|
|
|
69
135
|
```
|
|
70
|
-
|
|
71
|
-
browser_click({ x
|
|
72
|
-
browser_type({ text: "query" })
|
|
73
|
-
browser_press_key({ key: "Enter" })
|
|
136
|
+
browser_snapshot() # find input @(x,y) and labels
|
|
137
|
+
browser_click({ x, y }) # click using snapshot's @(x,y)
|
|
138
|
+
browser_type({ text: "query" })
|
|
139
|
+
browser_press_key({ key: "Enter" })
|
|
74
140
|
browser_wait_for_load()
|
|
75
|
-
|
|
141
|
+
browser_snapshot() # verify next state
|
|
76
142
|
```
|
|
77
143
|
|
|
78
144
|
### Data extraction
|
|
79
145
|
|
|
80
|
-
```
|
|
146
|
+
```js
|
|
147
|
+
// One value
|
|
81
148
|
browser_execute_js({ expression: "document.querySelector('.price').innerText" })
|
|
82
149
|
|
|
150
|
+
// Direct API call outside the browser
|
|
83
151
|
browser_http_get({ url: "https://api.github.com/repos/amankumarsingh77/pi-browser-harness" })
|
|
84
152
|
|
|
85
153
|
// Structured arrays
|
|
86
|
-
browser_execute_js({ expression: `
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
154
|
+
browser_execute_js({ expression: `JSON.stringify(
|
|
155
|
+
Array.from(document.querySelectorAll('.result')).map(el => ({
|
|
156
|
+
title: el.querySelector('h3')?.textContent,
|
|
157
|
+
link: el.querySelector('a')?.href,
|
|
158
|
+
}))
|
|
159
|
+
)` })
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Network debugging
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
browser_navigate({ url: "https://app.example.com/feed" })
|
|
166
|
+
browser_wait_for_load()
|
|
167
|
+
browser_network_requests({
|
|
168
|
+
urlPattern: "/api/",
|
|
169
|
+
statusFilter: { min: 400 },
|
|
170
|
+
includeResponseBodies: true
|
|
171
|
+
})
|
|
90
172
|
```
|
|
91
173
|
|
|
92
174
|
### Research workflow
|
|
93
175
|
|
|
94
176
|
```
|
|
95
177
|
browser_navigate({ url: "https://google.com/search?q=..." })
|
|
96
|
-
// read search results
|
|
97
178
|
browser_open_urls({ urls: ["url1", "url2", "url3"] })
|
|
98
179
|
browser_list_tabs()
|
|
99
180
|
browser_switch_tab({ targetId: "..." })
|
|
100
|
-
|
|
181
|
+
browser_wait_for_load()
|
|
182
|
+
browser_snapshot()
|
|
101
183
|
browser_execute_js({ expression: "document.querySelector('.content').innerText" })
|
|
102
184
|
```
|
|
103
185
|
|
|
104
|
-
###
|
|
186
|
+
### Visual verification (only when pixels matter)
|
|
105
187
|
|
|
106
188
|
```
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
browser_screenshot()
|
|
189
|
+
browser_click({ x, y }) # got coords from browser_snapshot
|
|
190
|
+
browser_snapshot() # confirm the form transitioned
|
|
191
|
+
browser_screenshot() # ONLY if you need to verify a chart/modal/CSS rendered correctly
|
|
110
192
|
```
|
|
111
193
|
|
|
112
194
|
### Keyboard modifiers
|
|
@@ -118,55 +200,65 @@ browser_screenshot()
|
|
|
118
200
|
| Meta / Cmd | 4 |
|
|
119
201
|
| Shift | 8 |
|
|
120
202
|
|
|
121
|
-
Combine with bitwise OR:
|
|
122
203
|
```
|
|
123
204
|
browser_press_key({ key: "c", modifiers: 2 }) // Ctrl+C
|
|
124
205
|
browser_press_key({ key: "v", modifiers: 4 }) // Cmd+V
|
|
125
206
|
browser_press_key({ key: "T", modifiers: 10 }) // Ctrl+Shift+T
|
|
126
207
|
```
|
|
127
208
|
|
|
128
|
-
###
|
|
209
|
+
### Dialogs
|
|
129
210
|
|
|
130
|
-
`
|
|
211
|
+
JS dialogs freeze the page. Check `browser_page_info` first โ if it reports a dialog, handle it before anything else:
|
|
131
212
|
|
|
132
213
|
```
|
|
133
|
-
|
|
214
|
+
browser_handle_dialog({ action: "accept" }) // confirm
|
|
215
|
+
browser_handle_dialog({ action: "dismiss" }) // cancel
|
|
216
|
+
browser_handle_dialog({ action: "accept", promptText: "hello" }) // prompt
|
|
134
217
|
```
|
|
135
218
|
|
|
136
|
-
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Parallel execution
|
|
137
222
|
|
|
138
|
-
|
|
223
|
+
Observation tools run in parallel by default. Mutation tools (`click`, `type`, `scroll`, `navigate`, `switch_tab`, โฆ) are automatically serialized through a shared mutex โ emit them in the same turn and the harness FIFO-queues them.
|
|
139
224
|
|
|
140
225
|
```
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
226
|
+
# All three run concurrently
|
|
227
|
+
browser_snapshot()
|
|
228
|
+
browser_network_requests({ sinceMs: 5000 })
|
|
229
|
+
browser_http_get({ url: "..." })
|
|
144
230
|
```
|
|
145
231
|
|
|
146
232
|
---
|
|
147
233
|
|
|
148
|
-
##
|
|
234
|
+
## Tab ownership
|
|
149
235
|
|
|
150
|
-
|
|
236
|
+
The harness never touches tabs you didn't open through it. On first attach it spawns a dedicated Chrome window; subsequent `browser_new_tab` calls open inside that window. `browser_list_tabs` defaults to `scope:"owned"` (pass `scope:"all"` to see read-only listings of your other tabs); `browser_switch_tab` and `browser_close_tab` refuse non-owned tabs.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Temporary scripts
|
|
241
|
+
|
|
242
|
+
When the built-in tools aren't enough, write a script to disk and run it. Scripts get a `daemon` binding for direct CDP access โ much faster than chaining tool calls.
|
|
151
243
|
|
|
152
244
|
```js
|
|
153
|
-
// 1. Write the script
|
|
154
245
|
write("/tmp/scrape-pages.js", `
|
|
155
246
|
const results = [];
|
|
156
247
|
for (const url of params.urls) {
|
|
157
|
-
await daemon.
|
|
248
|
+
await daemon.session().call("Page.navigate", { url });
|
|
158
249
|
await new Promise(r => setTimeout(r, 2000));
|
|
159
|
-
const title = await daemon.
|
|
250
|
+
const title = await daemon.evaluateJs("document.title");
|
|
160
251
|
results.push({ url, title });
|
|
161
252
|
}
|
|
162
253
|
return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
|
|
163
254
|
`)
|
|
164
255
|
|
|
165
|
-
// 2. Execute it
|
|
166
256
|
browser_run_script({ path: "/tmp/scrape-pages.js", params: { urls: [...] } })
|
|
167
257
|
```
|
|
168
258
|
|
|
169
|
-
**
|
|
259
|
+
**Bindings:** `params`, `daemon`, `require`, `signal`, `onUpdate`, `ctx`, `console`, `fetch`, `JSON`, `Buffer`, `setTimeout`, `clearTimeout`.
|
|
260
|
+
|
|
261
|
+
`daemon` exposes: `evaluateJs`, `pageInfo`, `listTabs`, `switchTab`, `newTab`, `current`, and `session(targetId?)` for raw CDP via `session.call` / `session.callOnTarget` / `session.callBrowser` / `session.takeDialog`.
|
|
170
262
|
|
|
171
263
|
Scripts are written to disk โ auditable and re-runnable.
|
|
172
264
|
|
|
@@ -186,8 +278,9 @@ Scripts are written to disk โ auditable and re-runnable.
|
|
|
186
278
|
|
|
187
279
|
- Don't launch your own browser โ you're connected to the user's real Chrome
|
|
188
280
|
- Don't type credentials โ if you hit an auth wall, stop and ask
|
|
189
|
-
- Don't
|
|
190
|
-
- Don't
|
|
281
|
+
- Don't screenshot to understand the page โ `browser_snapshot` is the default
|
|
282
|
+
- Don't screenshot to find click coordinates โ `browser_snapshot`'s `@(x,y)` is exact
|
|
283
|
+
- Don't screenshot to read a value โ `browser_execute_js` is one round-trip
|
|
191
284
|
- Don't ignore dialogs โ check `browser_page_info` first
|
|
192
285
|
|
|
193
286
|
---
|
|
@@ -211,9 +304,10 @@ Temporary scripts run inside the harness process with full daemon and Node.js ac
|
|
|
211
304
|
|---------|-----|
|
|
212
305
|
| `DevToolsActivePort not found` | Open `chrome://inspect/#remote-debugging`, tick the checkbox, click Allow |
|
|
213
306
|
| Connection fails after Chrome restart | Run `/browser-reload-daemon` |
|
|
214
|
-
| Page seems loaded but content is missing | SPA โ
|
|
215
|
-
|
|
|
307
|
+
| Page seems loaded but content is missing | SPA โ call `browser_snapshot` again, or `browser_execute_js` for a specific element |
|
|
308
|
+
| JS dialog is blocking actions | `browser_page_info` will report it โ use `browser_handle_dialog` |
|
|
216
309
|
| Daemon not starting | Run `/browser-setup` to re-run guided setup |
|
|
310
|
+
| Snapshot didn't return `@(x,y)` for a target | Element wasn't recognized as interactive. Fall back to `browser_execute_js` with `getBoundingClientRect()` |
|
|
217
311
|
|
|
218
312
|
---
|
|
219
313
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-browser-harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Browser control extension for pi โ navigate, click, type, screenshot, and extract data from real Chrome via CDP",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"@mariozechner/pi-coding-agent": "*",
|
|
53
53
|
"@mariozechner/pi-tui": "*",
|
|
54
54
|
"@types/ws": "^8.18.1",
|
|
55
|
+
"tsx": "^4.22.4",
|
|
55
56
|
"typebox": "*",
|
|
56
57
|
"typescript": "^5.0.0"
|
|
57
58
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pi-browser-harness
|
|
3
|
-
description: Direct browser control via CDP. Use when the user wants to automate, scrape, test, or interact with web pages. Connects to the user
|
|
3
|
+
description: Direct browser control via CDP. Use when the user wants to automate, scrape, test, or interact with web pages. Connects to the user's already-running Chrome. Default to browser_snapshot for understanding pages and browser_execute_js for surgical reads โ browser_screenshot is for visual verification only.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# pi-browser-harness
|
|
@@ -21,16 +21,39 @@ What do you need to know?
|
|
|
21
21
|
โโ Network behavior on the current page?
|
|
22
22
|
โ โ browser_network_requests
|
|
23
23
|
โ
|
|
24
|
+
โโ JS errors / why did nothing happen after an action?
|
|
25
|
+
โ โ browser_console (DIAGNOSTIC โ only when something looks broken)
|
|
26
|
+
โ
|
|
24
27
|
โโ Visual rendering (layout / colors / chart drew correctly)?
|
|
25
28
|
โ browser_screenshot (LAST RESORT โ pixels only)
|
|
26
29
|
```
|
|
27
30
|
|
|
28
31
|
Pass `@(x,y)` from `browser_snapshot` straight to `browser_click`. No screenshot round-trip.
|
|
29
32
|
|
|
33
|
+
## Connection Setup
|
|
34
|
+
|
|
35
|
+
Browser control is **on-demand** โ the daemon does NOT start automatically.
|
|
36
|
+
If you try a browser tool and get a `not_connected` error, tell the user to
|
|
37
|
+
run `/browser-setup` first. This opens the daemon and connects to Chrome.
|
|
38
|
+
Once initialized, all subsequent sessions reuse the same connection silently.
|
|
39
|
+
|
|
40
|
+
**Before calling any browser tool**, the runtime checks for the daemon socket
|
|
41
|
+
at `/tmp/pi-browser-daemon.sock`. If the socket is missing (user hasn't run
|
|
42
|
+
`/browser-setup`), you get: `"Browser harness not initialized. Run /browser-setup first"`.
|
|
43
|
+
|
|
44
|
+
**Do not ask the user.** Call `browser_setup` directly โ it spawns the daemon,
|
|
45
|
+
connects to Chrome, and opens a test tab. The user sees a single "Allow Remote
|
|
46
|
+
Debugging" prompt the first time. After that, all sessions reuse the same connection.
|
|
47
|
+
`browser_setup` is idempotent โ safe to call even when already connected.
|
|
48
|
+
|
|
30
49
|
## Connection
|
|
31
50
|
|
|
32
51
|
You're attached to the user's real Chrome โ never launch your own. If auth is required, stop and ask the user. If `browser_page_info` returns a dialog, handle it first with `browser_handle_dialog`.
|
|
33
52
|
|
|
53
|
+
## Diagnosing a "nothing happened" moment
|
|
54
|
+
|
|
55
|
+
When an action runs but the page didn't change, capture `browser_console`'s `nextCursor` *before* the action, take the action, then call `browser_console({ sinceSeq: <cursor> })` after โ this isolates what your action caused from what was already there. Pair with `browser_network_requests({ sinceMs: 5000 })` to see if an API call fired and failed. The console buffer is page-scoped: it clears on tab switch, capacity 500.
|
|
56
|
+
|
|
34
57
|
## Temporary scripts
|
|
35
58
|
|
|
36
59
|
When a workflow repeats 3+ times or needs Node.js APIs, write a script to disk and run it with `browser_run_script`. Scripts get a `daemon` binding for direct CDP access โ much faster than chaining tool calls.
|