@browserbridge/bbx 1.7.8 → 1.9.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/PRIVACY.md +57 -12
- package/README.md +19 -8
- package/SECURITY.md +12 -0
- package/package.json +15 -6
- package/packages/agent-client/src/cli-args.js +59 -0
- package/packages/agent-client/src/cli-batch.js +121 -58
- package/packages/agent-client/src/cli-output.js +8 -1
- package/packages/agent-client/src/cli.js +272 -70
- package/packages/agent-client/src/client.js +296 -8
- package/packages/agent-client/src/command-registry.js +64 -55
- package/packages/agent-client/src/config.js +195 -0
- package/packages/agent-client/src/content-extract.js +198 -0
- package/packages/agent-client/src/npm-self-update.js +305 -0
- package/packages/agent-client/src/remotes.js +4 -2
- package/packages/agent-client/src/runtime.js +864 -39
- package/packages/agent-client/src/types.ts +169 -6
- package/packages/mcp-server/src/guidance.js +1 -1
- package/packages/mcp-server/src/handlers-capture.js +69 -6
- package/packages/mcp-server/src/handlers-dom.js +61 -4
- package/packages/mcp-server/src/handlers-navigation.js +2 -1
- package/packages/mcp-server/src/handlers-page.js +211 -54
- package/packages/mcp-server/src/handlers-utils.js +101 -10
- package/packages/mcp-server/src/handlers.js +14 -7
- package/packages/mcp-server/src/server.js +176 -11
- package/packages/native-host/src/artifact-store.js +353 -0
- package/packages/native-host/src/config.js +9 -1
- package/packages/native-host/src/daemon-logger.js +3 -1
- package/packages/native-host/src/daemon.js +701 -33
- package/packages/native-host/src/native-host.js +28 -3
- package/packages/protocol/src/capability-values.js +2 -0
- package/packages/protocol/src/defaults.js +31 -0
- package/packages/protocol/src/errors.js +102 -6
- package/packages/protocol/src/incidental-sanitizer.js +197 -0
- package/packages/protocol/src/index.js +2 -0
- package/packages/protocol/src/protocol.js +612 -6
- package/packages/protocol/src/recovery-telemetry.js +302 -0
- package/packages/protocol/src/registry.js +206 -38
- package/packages/protocol/src/summary.js +203 -30
- package/packages/protocol/src/types.ts +721 -2
- package/skills/browser-bridge/SKILL.md +54 -19
- package/skills/browser-bridge/references/interaction.md +55 -11
- package/skills/browser-bridge/references/patch-workflow.md +2 -0
- package/skills/browser-bridge/references/protocol.md +265 -86
- package/skills/browser-bridge/references/token-efficiency.md +29 -13
|
@@ -13,13 +13,13 @@ Permission prompts are controlled by the host agent, not by Browser Bridge. In p
|
|
|
13
13
|
|
|
14
14
|
Skill name: `browser-bridge` (also known as `bbx`). In GitHub Copilot, invoke as `/browser-bridge`. `bbx` is the CLI command used throughout this skill.
|
|
15
15
|
When the runtime supports subagents, delegate bridge inspection to a smaller, lower-cost worker and return only concise findings to the parent.
|
|
16
|
-
For open-ended investigation, start with structured reads (`page.get_state`, `dom.query`, `page.get_text`, `styles.get_computed`, and `bbx batch` for CLI or `browser_batch` for MCP) and escalate to screenshots or debugger-backed methods only when structured evidence is insufficient. `browser_call` accepts one protocol method at a time; `batch` is not a valid `browser_call` method.
|
|
16
|
+
For open-ended investigation, start with structured reads (`page.get_state`, `dom.query`, `page.get_text`, `page.extract_content`, `styles.get_computed`, and `bbx batch` for CLI or `browser_batch` for MCP) and escalate to screenshots or debugger-backed methods only when structured evidence is insufficient. `browser_call` accepts one protocol method at a time; `batch` is not a valid `browser_call` method.
|
|
17
17
|
|
|
18
18
|
## CLI
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
bbx status # daemon + extension health
|
|
22
|
-
bbx doctor #
|
|
22
|
+
bbx doctor # consolidated local diagnostics (does not probe remotes)
|
|
23
23
|
bbx access-request # ask user to enable access for the focused window
|
|
24
24
|
bbx restart # start/restart the daemon and running MCP servers
|
|
25
25
|
bbx call <method> '{...}' # any RPC method (raw output)
|
|
@@ -58,18 +58,22 @@ bbx a11y-tree [maxNodes] [maxDepth] # accessibility tree
|
|
|
58
58
|
```bash
|
|
59
59
|
bbx eval [--await] <expression> # JS eval (--await for promises, - for stdin)
|
|
60
60
|
bbx console [level] # console output
|
|
61
|
-
bbx network [limit] #
|
|
61
|
+
bbx network [limit] # recent fetch/XHR requests
|
|
62
|
+
bbx har [options] [outPath] # export armed CDP capture as sanitized HAR 1.2
|
|
62
63
|
bbx intercept add <pattern> [--respond <body>] [--status <code>] [--block] # intercept matching requests
|
|
63
64
|
bbx intercept list|remove <id>|clear # manage interception rules
|
|
64
65
|
bbx page-text [budget] # full page text
|
|
65
|
-
bbx storage [local|session] [keys] #
|
|
66
|
-
bbx
|
|
66
|
+
bbx storage [local|session] [keys] # storage key/presence metadata
|
|
67
|
+
bbx call sensitive.read '{"source":"local_storage","key":"name"}' # deliberate exact value
|
|
68
|
+
bbx perf # raw Chrome/CDP counter point sample
|
|
67
69
|
bbx navigate <url> # navigate to URL
|
|
68
70
|
bbx reload # reload current page
|
|
69
71
|
bbx back # navigate back
|
|
70
72
|
bbx forward # navigate forward
|
|
71
73
|
bbx scroll <top> [left] # scroll viewport
|
|
72
74
|
bbx resize <width> <height> # resize viewport
|
|
75
|
+
bbx call page.wait_for_load_state '{"url":"/dashboard","urlMatch":"contains","waitForLoad":false}'
|
|
76
|
+
bbx call page.handle_dialog '{"action":"inspect"}' # inspect current JS dialog; never auto-accept
|
|
73
77
|
```
|
|
74
78
|
|
|
75
79
|
### Interact & Patch
|
|
@@ -83,11 +87,12 @@ bbx press-key <key> [ref] # send key event
|
|
|
83
87
|
bbx cdp-press-key --tab <id> Escape # CDP key event without foreground focus
|
|
84
88
|
bbx hover <ref> # hover over element
|
|
85
89
|
bbx call input.scroll_into_view '{"target":{"elementRef":"el_123"}}' # ensure target is visible
|
|
90
|
+
bbx call input.click '{"target":{"elementRef":"el_123"},"executionMode":"cdp"}' # optional native click
|
|
86
91
|
bbx patch-style <ref> prop=val... # apply style patch
|
|
87
92
|
bbx patch-text <ref> <text...> # apply text patch
|
|
88
93
|
bbx patches # list active patches
|
|
89
94
|
bbx rollback <patchId> # rollback a patch
|
|
90
|
-
bbx screenshot <ref> [outPath]
|
|
95
|
+
bbx screenshot [--format png|jpeg|webp] [--quality 0-100] <ref> [outPath] # complete element capture
|
|
91
96
|
bbx call screenshot.capture_full_page '{}' # raw base64; avoid unless document context matters
|
|
92
97
|
```
|
|
93
98
|
|
|
@@ -104,6 +109,8 @@ bbx dom-query "#app" --remote <name>
|
|
|
104
109
|
|
|
105
110
|
In MCP mode, pass `destinationId` on any browser tool call instead; `browser_status` lists all destinations with reachability. Only use remotes the user has configured; local remains the default.
|
|
106
111
|
|
|
112
|
+
`bbx doctor` is intentionally local-only. It reports how many remotes are configured, but marks their status `not_probed_local_only` and credentials `unverified`; use `bbx remote test <name>` when the user wants a remote probe.
|
|
113
|
+
|
|
107
114
|
## Access Flow
|
|
108
115
|
|
|
109
116
|
Browser Bridge access is window-scoped. The user turns it on once for the current browser window in the popup or side panel.
|
|
@@ -132,9 +139,15 @@ After access is enabled:
|
|
|
132
139
|
| ------------------------- | -------- | ----------------------------------------------------------------------------------------- |
|
|
133
140
|
| `ACCESS_DENIED` | No | Failed call already surfaced an `Enable` cue; ask user to click `Enable`, then retry once |
|
|
134
141
|
| `ELEMENT_STALE` | No | Re-query with `dom.query` or `dom.find_by_text` to get a fresh ref |
|
|
142
|
+
| `ELEMENT_AMBIGUOUS` | No | Narrow the selector or use an explicit `elementRef`; do not guess |
|
|
143
|
+
| `ELEMENT_NOT_ACTIONABLE` | No | Inspect hidden/disabled/inert state with `dom.describe` |
|
|
144
|
+
| `ELEMENT_OBSCURED` | No | Inspect bounded blocker details or use `layout.hit_test` |
|
|
145
|
+
| `INPUT_FOCUS_CHANGED` | No | Inspect focus handlers; do not replay native text automatically |
|
|
146
|
+
| `DIALOG_NOT_OPEN` | No | Trigger or inspect the dialog again |
|
|
147
|
+
| `DIALOG_ACTION_CONFLICT` | No | Inspect current dialog state; never auto-repeat accept/dismiss |
|
|
135
148
|
| `TAB_MISMATCH` | No | Tab closed or not found - use `tabs.list` to find an available tab |
|
|
136
149
|
| `TIMEOUT` | Once | Retry once; if still failing, simplify (smaller `maxNodes`, narrower selector) |
|
|
137
|
-
| `
|
|
150
|
+
| `CONTENT_SCRIPT_UNAVAILABLE` | No | Switch to a normal http(s) page in the enabled window |
|
|
138
151
|
| `EXTENSION_DISCONNECTED` | After 3s | Check Chrome is running; `bbx status` to verify, then retry |
|
|
139
152
|
| `NATIVE_HOST_UNAVAILABLE` | No | Run `bbx doctor` to diagnose the installation |
|
|
140
153
|
| `INTERNAL_ERROR` | Once | Retry once; if persistent, check `page.get_console` for details |
|
|
@@ -144,6 +157,13 @@ After access is enabled:
|
|
|
144
157
|
|
|
145
158
|
Error responses now include a machine-readable `error.recovery` field with `retry`, `retryAfterMs`, `alternativeMethod`, and `hint`.
|
|
146
159
|
|
|
160
|
+
`health.ping`, `daemon.metrics`, and `bbx doctor` also expose process-local
|
|
161
|
+
five-minute recovery summaries for six fixed, content-free categories. Three
|
|
162
|
+
failures in the same hidden group within 60 seconds marks an active loop. Stop
|
|
163
|
+
repeating the action and follow Doctor's fixed category guidance. Extension
|
|
164
|
+
summaries reset on service-worker restart and daemon summaries on daemon restart;
|
|
165
|
+
they contain no page data, URLs, selectors, payloads, errors, or group names.
|
|
166
|
+
|
|
147
167
|
## Core Rules
|
|
148
168
|
|
|
149
169
|
1. **Work in existing tabs** - Never create new tabs unless the user explicitly asks for it, or the task absolutely requires a fresh page (e.g., testing a clean state, comparing across URLs). Prefer `tabs.list` to find an appropriate existing tab.
|
|
@@ -157,14 +177,21 @@ Error responses now include a machine-readable `error.recovery` field with `retr
|
|
|
157
177
|
9. **Batch reads** - combine independent reads with `bbx batch` in CLI mode or `browser_batch` in MCP mode; do not pass `batch` as a `browser_call` method.
|
|
158
178
|
10. **Avoid debugger first** - prefer DOM/content-script methods (`dom.*`, `styles.*`, `layout.get_box_model`, `page.get_console`, `page.get_text`, `page.get_storage`, `page.get_network`) before any debugger-backed method. Escalate to CDP only when those cannot answer the question.
|
|
159
179
|
11. **Evaluate only when needed** - `page.evaluate` is powerful but debugger-backed; use it only when DOM, storage, console, network, or text reads cannot expose the needed state.
|
|
160
|
-
12. **
|
|
180
|
+
12. **Treat exact storage as sensitive** - use `page.get_storage` for metadata first. Call `sensitive.read` for one exact key only when necessary; never batch or automatically retry it, and never repeat a failed attempt without new evidence.
|
|
181
|
+
12. **Debugger-backed methods are last resort** - treat `page.evaluate`, `page.handle_dialog`, `dom.get_accessibility_tree`, `page.get_network` with `source: 'cdp'`, input with `executionMode: 'cdp'`, `viewport.resize`, `performance.get_metrics`, `screenshot.capture_*`, and all `cdp.*` methods as escalation steps because they attach `chrome.debugger`. `performance.get_metrics` is a raw browser-maintained CDP counter point sample, not Web Vitals.
|
|
161
182
|
13. **Wait after change** - after editing source, wait for expected new text, a selector matching the changed attribute, or a detach/attach remount; waiting for `attached` on a selector that already exists does not prove HMR ran. Use `page.wait_for_load_state` for navigation, not HMR.
|
|
162
|
-
14. **Prime event buffers** - before reproducing a console or
|
|
183
|
+
14. **Prime event buffers** - before reproducing a console or fetch/XHR issue, call `page.get_console` and default `page.get_network` once with `clear: true`; then reproduce and read without clearing. CDP all-resource capture instead requires explicit `start`, reproduce, `read`, and `stop` calls.
|
|
163
184
|
15. **Semantic finding** - use `dom.find_by_text` / `dom.find_by_role` when you know the label but not the selector.
|
|
164
|
-
16. **Text extraction** - use `page.
|
|
185
|
+
16. **Text extraction** - use `page.extract_content` for articles/documentation, or `page.get_text` for all visible UI text, instead of `dom.query` on body.
|
|
165
186
|
17. **Network monitoring** - use `page.get_network` to inspect API calls; auto-installs interceptor.
|
|
166
187
|
18. **Accessibility tree only when necessary** - `dom.get_accessibility_tree` is debugger-backed; use it when semantic structure cannot be inferred from DOM queries and role/text search.
|
|
167
188
|
19. **Tailwind-aware** - when `page.get_state` returns `hints.tailwind: true`, load `references/tailwind.md`; avoid selecting by utility classes, prefer `find_by_text`/`find_by_role`; `dom.query` auto-escapes `[]` brackets.
|
|
189
|
+
20. **Verify after input** - a dispatched DOM or CDP event does not prove application state changed. Follow it with the cheapest relevant wait or structured read.
|
|
190
|
+
21. **Do not guess input targets** - for targeted click, focus, type, fill, press-key, checked-state, option-selection, hover, and drag calls, honor actionability errors and returned `resolution` metadata. `cdp_press_key` and `scroll_into_view` use separate contracts. `executionMode` is only `dom` or `cdp`; `input.fill.mode: auto` is a separate DOM setter/keystroke strategy.
|
|
191
|
+
22. **Stale recovery stays opt-in** - prefer re-querying. Use `recoverStale: true` once only when the same document/URL and a strong unique semantic descriptor should still identify the target; inspect `recovered`, old/new refs, and matched fields. A scan with more than 100 same-tag candidates fails as `ELEMENT_AMBIGUOUS`/`scan_incomplete` because uniqueness is not provable.
|
|
192
|
+
23. **Dialogs are explicit** - inspect first, then accept or dismiss only when intended. `expectedDialogId` is a pre-dispatch stale-decision check, not an atomic CDP binding; never auto-repeat `DIALOG_ACTION_CONFLICT`.
|
|
193
|
+
24. **DOM diffs use explicit baselines** - call `dom.baseline.create` before the action, `dom.baseline.compare` afterward, then `dom.baseline.release`. Use a narrow selector and bounded evidence. Never substitute unrelated DOM reads for the retained baseline, and recreate it after `DOM_BASELINE_INVALIDATED`.
|
|
194
|
+
25. **HAR export reads an armed capture** - use CDP capture `start`, reproduce, `network.export_har`/`bbx har`, then `stop`. Export never starts, stops, or clears capture. Inspect truncation plus `dropped`, `abandoned`, and `inflight` before claiming completeness.
|
|
168
195
|
|
|
169
196
|
## Token Budget Quick Rules
|
|
170
197
|
|
|
@@ -172,7 +199,7 @@ Error responses now include a machine-readable `error.recovery` field with `retr
|
|
|
172
199
|
2. **Use `attributeAllowlist`** - filter irrelevant attributes (e.g. `['class', 'href', 'data-testid']`)
|
|
173
200
|
3. **Batch independent reads** - combine into a single `bbx batch` / `browser_batch` call
|
|
174
201
|
4. **Refresh refs after pruning** - if `dom.query` returns `_registryPruned: true`, old refs may have been evicted; re-query before reusing them
|
|
175
|
-
5. **Watch overflow counters** - `page.get_console` and `page.get_network` return `dropped` when hot pages overflow the 200-entry buffers
|
|
202
|
+
5. **Watch overflow counters** - `page.get_console` and `page.get_network` return `dropped` when hot pages overflow the 200-entry buffers; CDP network also reports `abandoned` and capture lifecycle state
|
|
176
203
|
|
|
177
204
|
## Investigate Workflow
|
|
178
205
|
|
|
@@ -235,12 +262,13 @@ bbx page-text 2000 # extract page content
|
|
|
235
262
|
| Inspect | `dom.query`, `dom.describe`, `dom.get_html`, `styles.get_computed`, `layout.get_box_model` |
|
|
236
263
|
| Find | `dom.find_by_text`, `dom.find_by_role`, `dom.wait_for`, `dom.get_accessibility_tree` |
|
|
237
264
|
| Page State | `page.get_console`, `page.get_storage`, `page.get_text`, `page.wait_for_load_state`, `page.evaluate` (debugger-backed) |
|
|
238
|
-
|
|
|
265
|
+
| Dialogs | `page.handle_dialog` (debugger-backed; explicit inspect/accept/dismiss only) |
|
|
266
|
+
| Network | `page.get_network` (fetch/XHR default; optional CDP lifecycle), `network.export_har`, `network.intercept.add/remove/list/clear` (debugger-backed) |
|
|
239
267
|
| Interact | `input.click`, `input.type`, `input.fill`, `input.focus`, `input.press_key`, `cdp.dispatch_key_event`, `input.hover`, `input.drag`, `input.scroll_into_view` |
|
|
240
268
|
| Tabs | `tabs.list` (preferred), `tabs.create` (avoid unless necessary), `tabs.close`, `tabs.activate` |
|
|
241
269
|
| Patch | `patch.apply_styles`, `patch.apply_dom`, `patch.rollback` |
|
|
242
270
|
| Navigate | `navigation.navigate`, `viewport.scroll`, `viewport.resize` |
|
|
243
|
-
| Performance | `performance.get_metrics` (debugger-backed)
|
|
271
|
+
| Performance | `performance.get_metrics` (raw Chrome/CDP counter point sample; debugger-backed) |
|
|
244
272
|
| Escalate | `dom.get_accessibility_tree`, `screenshot.capture_element`, `screenshot.capture_region` (tight crops only), `screenshot.capture_full_page`, `cdp.*` |
|
|
245
273
|
|
|
246
274
|
## Dev-Server Workflow (HMR-aware)
|
|
@@ -273,8 +301,8 @@ page.get_state → page.get_console(clear: true) + page.get_network(clear: true)
|
|
|
273
301
|
|
|
274
302
|
```
|
|
275
303
|
dom.find_by_role('button', 'Login') → input.click
|
|
304
|
+
→ page.wait_for_load_state({url: '/dashboard', urlMatch: 'contains', waitForLoad: false})
|
|
276
305
|
→ dom.wait_for('.dashboard', {state: 'visible', timeoutMs: 10000})
|
|
277
|
-
→ page.get_state (verify URL changed)
|
|
278
306
|
→ page.get_console (check for errors)
|
|
279
307
|
→ dom.query('.dashboard', {maxNodes: 15}) (inspect result)
|
|
280
308
|
```
|
|
@@ -291,6 +319,8 @@ dom.find_by_role('button', 'Login') → input.click
|
|
|
291
319
|
|
|
292
320
|
`bbx a11y-tree` and `dom.get_accessibility_tree` are sensitive to `maxDepth` and `maxNodes`. Shallow runs can undercount interactive nodes on real pages, so widen those limits before treating a low interactive count as a bug.
|
|
293
321
|
|
|
322
|
+
For control discovery, prefer `compact: true` or `interactiveOnly: true`, then use role/name with `dom.find_by_role` to obtain an input ref. AX `interactive` means semantic/focusable, not currently visible, unobscured, or otherwise actionable; AX results are depth-limited partial topology and include truncation metadata even when `maxNodes` was not reached.
|
|
323
|
+
|
|
294
324
|
> **MCP mode:** If Browser Bridge is connected via MCP (tools named `browser_dom`, `browser_capture`, etc.), use the MCP tools directly - do not shell out to `bbx`. The MCP tools map 1:1 to CLI capabilities. In prompts, `BB MCP` and `Browser Bridge MCP` both work. Do not treat `bbx-mcp` as a skill alias.
|
|
295
325
|
>
|
|
296
326
|
> For open-ended MCP inspection tasks, prefer `browser_investigate` first. It is read-only, designed for cheaper delegated investigation, and falls back to a deterministic sequence when the client cannot delegate. Escalate to `browser_capture` only when the structured investigation is not enough.
|
|
@@ -306,7 +336,7 @@ Every CLI shortcut command produces consistent `{ok, summary, evidence}` JSON. U
|
|
|
306
336
|
## CLI Raw Params Gotchas
|
|
307
337
|
|
|
308
338
|
- Use `selector`, not `scope`, to narrow `dom.find_by_text` and `dom.find_by_role`.
|
|
309
|
-
- Wrap
|
|
339
|
+
- Wrap targeted DOM input as `target: { elementRef }` or `target: { selector }`; `input.press_key` may omit the target to use the active element, `input.scroll_into_view` also accepts `target`, and `cdp.dispatch_key_event` targets the tab. **Do not pass `ref` or `elementRef` at the top level**:
|
|
310
340
|
```bash
|
|
311
341
|
# CORRECT
|
|
312
342
|
bbx call input.click '{"target":{"elementRef":"el_xxx"}}'
|
|
@@ -316,7 +346,11 @@ Every CLI shortcut command produces consistent `{ok, summary, evidence}` JSON. U
|
|
|
316
346
|
bbx call input.click '{"elementRef":"el_xxx"}'
|
|
317
347
|
```
|
|
318
348
|
- `input.drag` uses `source`, `destination`, and optional destination offsets `offsetX` / `offsetY`.
|
|
319
|
-
-
|
|
349
|
+
- `executionMode` accepts `dom` or `cdp` and defaults to `dom`; CDP supports only click, hover, drag, type, and fill. `input.fill.mode` (`auto`, `setter`, `keystrokes`) is a separate DOM strategy.
|
|
350
|
+
- `page.get_network` defaults to low-cost fetch/XHR instrumentation. All-resource CDP capture must be armed before the activity with `source: "cdp", capture: "start"`, read later, and explicitly stopped.
|
|
351
|
+
- `network.export_har` requires that explicit capture to still be armed. Params are `limit` (1-200), sanitized-URL substring `urlPattern`, and `delivery` (`auto`, `inline`, `artifact`). Inline bounds remove whole oldest entries; export never changes capture state. `bbx har` uses the same client to download, length/SHA-256 verify, delete, validate, and atomically write artifacts locally.
|
|
352
|
+
- `page.handle_dialog` mutations are not atomically bound to `expectedDialogId`; treat `commandDispatched` as dispatch evidence and verify follow-up state.
|
|
353
|
+
- Raw screenshot calls default to inline base64. Use `delivery: "auto"` for size-aware artifact fallback, or explicit `inline` when MCP image content is required; prefer `bbx screenshot <ref> [outPath]` when one element is enough because the CLI downloads and verifies artifacts locally.
|
|
320
354
|
|
|
321
355
|
## Response Shapes
|
|
322
356
|
|
|
@@ -324,7 +358,7 @@ The summarizer auto-detects response types and produces concise summaries:
|
|
|
324
358
|
|
|
325
359
|
Shortcut commands intentionally expose only the common case. Use `bbx call <method> '{...}'` when you need method-specific fields that are not surfaced by a shortcut, such as `tabs.create.active`.
|
|
326
360
|
|
|
327
|
-
`dom.query` results include `registrySize` and may include `_registryPruned: true` after element-ref eviction. `page.get_console` and `page.get_network` include `dropped` when older buffered entries were discarded.
|
|
361
|
+
`dom.query` results include `registrySize` and may include `_registryPruned: true` after element-ref eviction. `page.get_console` and `page.get_network` include `dropped` when older buffered entries were discarded. Targeted click, focus, type, fill, press-key, checked-state, option-selection, hover, and drag results include bounded `resolution` and `execution` metadata; `cdp_press_key` and `scroll_into_view` use separate contracts.
|
|
328
362
|
|
|
329
363
|
| Response Type | Detection | Summary Format |
|
|
330
364
|
| ---------------- | -------------------------------- | ------------------------------------------------------------ |
|
|
@@ -338,14 +372,15 @@ Shortcut commands intentionally expose only the common case. Use `bbx call <meth
|
|
|
338
372
|
| Element describe | `result.tag + elementRef + bbox` | `Element tag#id: text.` |
|
|
339
373
|
| Computed styles | `result.properties + elementRef` | `Computed N style(s) for ref.` |
|
|
340
374
|
| Box model | `result.content + border` | `Box model: W×H at (x, y).` |
|
|
341
|
-
| Network | `entries
|
|
375
|
+
| Network | `result.source + entries` | `Network: N requests.` |
|
|
376
|
+
| HAR export | `result.format === "har"` | `HAR export delivered mode: N/M entries.` |
|
|
342
377
|
| Console | `entries` (no type field) | `Console: N entries.` |
|
|
343
378
|
| Logs | `entries[0].at + method` | `Log: N entries.` |
|
|
344
379
|
| Patch apply | `result.patchId` | `Patch id applied.` |
|
|
345
380
|
| Patch rollback | `result.rolled_back` | `Patch rolled back.` |
|
|
346
381
|
| Patch list | `result.patches` | `N active patch(es).` |
|
|
347
382
|
| HTML | `result.html` | `HTML fragment: N chars.` |
|
|
348
|
-
| Performance | `result.metrics` | `
|
|
383
|
+
| Performance | `result.metrics` | `Raw CDP performance counters: N collected; Web Vitals not measured.` |
|
|
349
384
|
| Storage | `result.type + count + entries` | `Storage (type): N entries.` |
|
|
350
385
|
| Click/Focus/Type | `result.clicked/focused/typed` | `Clicked/Focused/Typed ref.` |
|
|
351
386
|
| Key press | `result.pressed` | `Key pressed (key).` |
|
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
| Method | CLI Shortcut | Purpose |
|
|
6
6
|
| ------------------------ | ------------------------------------- | ----------------------------------------------------------- |
|
|
7
|
-
| `input.click` | `click <ref> [button]` |
|
|
7
|
+
| `input.click` | `click <ref> [button]` | Actionability-aware DOM click; optional CDP native click |
|
|
8
8
|
| `input.focus` | `focus <ref>` | Focus an element |
|
|
9
|
-
| `input.type` | `type <ref> <text>` |
|
|
10
|
-
| `input.fill` | `fill <ref> <value>` |
|
|
9
|
+
| `input.type` | `type <ref> <text>` | DOM key sequence; optional CDP native text insertion |
|
|
10
|
+
| `input.fill` | `fill <ref> <value>` | DOM fill strategy; optional CDP clear and text insertion |
|
|
11
11
|
| `input.press_key` | `press-key <key> [ref]` | Send keyboard key (Enter, Backspace, etc.) |
|
|
12
12
|
| `cdp.dispatch_key_event` | `cdp-press-key --tab <id> <key>` | CDP keyDown/keyUp without focusing the target tab |
|
|
13
13
|
| `input.set_checked` | `call input.set_checked '{...}'` | Toggle checkbox/radio |
|
|
14
14
|
| `input.select_option` | `call input.select_option '{...}'` | Select native `<select>` by value/label/index |
|
|
15
|
-
| `input.hover` | `hover <ref>` |
|
|
16
|
-
| `input.drag` | `call input.drag '{...}'` |
|
|
15
|
+
| `input.hover` | `hover <ref>` | DOM hover events or optional CDP pointer move |
|
|
16
|
+
| `input.drag` | `call input.drag '{...}'` | DOM drag events or optional CDP pointer drag |
|
|
17
17
|
| `input.scroll_into_view` | `call input.scroll_into_view '{...}'` | Ensure a target is visible before inspect/capture |
|
|
18
18
|
|
|
19
19
|
## Navigation
|
|
@@ -29,6 +29,14 @@ bbx call navigation.go_forward
|
|
|
29
29
|
- `waitForLoad` defaults `true`; set `false` for long-lived pages.
|
|
30
30
|
- If navigation times out, retry with larger `timeoutMs` or check with `page.get_state`.
|
|
31
31
|
|
|
32
|
+
For a navigation or SPA route caused by input, use event-aware URL conditions instead of polling:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
bbx call page.wait_for_load_state '{"url":"/dashboard","urlMatch":"contains","waitForLoad":false,"timeoutMs":10000}'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The current URL is checked first. The wait then observes full navigation, tab URL/status updates, `pushState`, `replaceState`, `popstate`, and hash changes. It returns the final URL, elapsed time, and observed navigation kind. `waitForLoad: true` means Chrome tab status `complete`, not `networkidle`. Regex mode is deliberately restricted to a bounded linear subset without grouping, alternation, quantifiers, or backreferences.
|
|
39
|
+
|
|
32
40
|
## Viewport
|
|
33
41
|
|
|
34
42
|
```bash
|
|
@@ -78,15 +86,17 @@ Typical workflow - compare two pages (only when comparison is required):
|
|
|
78
86
|
|
|
79
87
|
## Accessibility Tree
|
|
80
88
|
|
|
81
|
-
Retrieve
|
|
89
|
+
Retrieve a depth-limited accessibility tree for the page. Useful for understanding semantic structure, finding interactive elements, and accessibility audits.
|
|
82
90
|
|
|
83
91
|
```bash
|
|
84
92
|
bbx a11y-tree # default limits
|
|
85
93
|
bbx a11y-tree 50 3 # max 50 nodes, depth 3
|
|
86
94
|
bbx call dom.get_accessibility_tree '{"maxNodes":100,"maxDepth":5}'
|
|
95
|
+
bbx call dom.get_accessibility_tree '{"maxNodes":100,"maxDepth":6,"compact":true}'
|
|
96
|
+
bbx call dom.get_accessibility_tree '{"maxNodes":100,"maxDepth":6,"interactiveOnly":true}'
|
|
87
97
|
```
|
|
88
98
|
|
|
89
|
-
Each node
|
|
99
|
+
Each node includes semantic state plus `interactive`, `semanticInteractive`, `focusable`, `focusableAndEnabled`, `ignored`, and `childIds`. `interactive` is not a current actionability guarantee. Compact and interactive-only filters run before `maxNodes`; results report partial depth topology, missing children, and continuation guidance. AX nodes do not become page refs, so use `dom.find_by_role` before input.
|
|
90
100
|
|
|
91
101
|
Typical workflow - find interactive controls:
|
|
92
102
|
|
|
@@ -151,7 +161,7 @@ bbx network 50 # newly captured requests
|
|
|
151
161
|
bbx console error # newly captured errors
|
|
152
162
|
```
|
|
153
163
|
|
|
154
|
-
|
|
164
|
+
Default fetch/XHR entries are retained in capture order and contain `method`, `url`, `status`, `duration`, `type`, `ts`, and `size`.
|
|
155
165
|
|
|
156
166
|
Typical workflow - debug API calls:
|
|
157
167
|
|
|
@@ -161,6 +171,17 @@ Typical workflow - debug API calls:
|
|
|
161
171
|
4. Cross-reference with `page.get_console` for errors
|
|
162
172
|
5. Use `page.evaluate` only if lighter evidence cannot expose the needed response state
|
|
163
173
|
|
|
174
|
+
For document, script, stylesheet, image, WebSocket, WebTransport, and other resource metadata, explicitly arm CDP before reproducing:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
bbx call page.get_network '{"source":"cdp","capture":"start"}'
|
|
178
|
+
# reproduce activity
|
|
179
|
+
bbx call page.get_network '{"source":"cdp","capture":"read","limit":50}'
|
|
180
|
+
bbx call page.get_network '{"source":"cdp","capture":"stop"}'
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This holds debugger ownership and is more expensive than default instrumentation. A plain read cannot recover events from before `start`. CDP results report armed/ownership/inflight/drop state and redact URL credentials, fragments, and query values; bodies, cookies, authorization values, and complete headers are excluded.
|
|
184
|
+
|
|
164
185
|
## Network Interception
|
|
165
186
|
|
|
166
187
|
Block, stub, or modify matching requests via CDP (debugger-backed). Patterns are globs: `*` matches any characters, `?` matches one character.
|
|
@@ -204,6 +225,28 @@ bbx type el_123 hello # simulate per-character keystrokes
|
|
|
204
225
|
|
|
205
226
|
Prefer `fill` for setting form values: it uses the native prototype setter plus `input`/`change`/`blur` events, which React, Vue, and Angular pick up reliably. `mode` defaults to `auto` (setter first, keystroke fallback if the value did not stick); pass `"mode":"keystrokes"` via `bbx call input.fill` for components that only react to per-key events. Use `type` when page logic depends on individual key events (autocomplete, masked inputs).
|
|
206
227
|
|
|
228
|
+
`mode` is not `executionMode`. The latter accepts only `dom` or `cdp`, defaults to `dom` for compatibility, and selects the dispatch path. CDP execution is available only for click, hover, drag, type, and fill; unsupported combinations fail with `INPUT_UNSUPPORTED` instead of silently changing paths.
|
|
229
|
+
|
|
230
|
+
## Actionability And Stale Refs
|
|
231
|
+
|
|
232
|
+
Input selectors preserve the first match when it is actionable. Otherwise Browser Bridge evaluates at most 25 candidates and proceeds only when one is uniquely preferable. It scrolls the selected target as needed, then rechecks rendered bounds, hidden/disabled/inert state, and pointer hit testing. Expect structured `ELEMENT_NOT_FOUND`, `ELEMENT_NOT_ACTIONABLE`, `ELEMENT_OBSCURED`, or `ELEMENT_AMBIGUOUS` errors rather than best-effort retargeting.
|
|
233
|
+
|
|
234
|
+
Successful targeted click, focus, type, fill, press-key, checked-state, option-selection, hover, and drag results report `resolution` and `execution` metadata. `cdp_press_key` and `scroll_into_view` use separate contracts. Explicit refs preserve exact identity. Stale refs fail by default; `recoverStale: true` allows a single same-document, unchanged-URL recovery only from a strong unique semantic descriptor, and reports old/new refs and matched fields. The recovery scan evaluates at most 100 same-tag candidates and returns `ELEMENT_AMBIGUOUS` with `reason: "scan_incomplete"` whenever additional candidates make uniqueness unprovable. Prefer a fresh query unless this strict recovery contract clearly applies.
|
|
235
|
+
|
|
236
|
+
After any DOM or CDP input, verify the intended application outcome with a targeted wait or structured read. Event dispatch alone is not proof that application state changed.
|
|
237
|
+
|
|
238
|
+
## JavaScript Dialogs
|
|
239
|
+
|
|
240
|
+
Dialogs are never accepted or dismissed automatically:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
bbx call page.handle_dialog '{"action":"inspect"}'
|
|
244
|
+
bbx call page.handle_dialog '{"action":"accept","expectedDialogId":"00000000-0000-4000-8000-000000000000:1"}' # replace with inspected dialogId
|
|
245
|
+
bbx call page.handle_dialog '{"action":"dismiss","expectedDialogId":"00000000-0000-4000-8000-000000000000:1"}' # replace with inspected dialogId
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`expectedDialogId` is checked immediately before the CDP command, but Chrome cannot atomically bind that command to the observation. A successful mutation reports `commandDispatched: true` and `atomicDialogBinding: false`. On `DIALOG_ACTION_CONFLICT`, inspect again and do not automatically repeat the mutation. Dialog text is returned only to the caller and is excluded from persisted action logs.
|
|
249
|
+
|
|
207
250
|
## Hover
|
|
208
251
|
|
|
209
252
|
Dispatch mouse events to trigger CSS `:hover` rules, tooltip display, dropdown menus, etc.
|
|
@@ -297,7 +340,7 @@ Use after clicking navigation links.
|
|
|
297
340
|
|
|
298
341
|
## Raw `bbx call` for Interaction Methods
|
|
299
342
|
|
|
300
|
-
|
|
343
|
+
Targeted DOM input methods require the target wrapped in a `target` object; `input.press_key` may omit it to use the active element. Do not pass `ref` or `elementRef` at the top level. `cdp.dispatch_key_event` targets the tab, while `input.scroll_into_view` accepts `target` but does not return actionability/execution metadata:
|
|
301
344
|
|
|
302
345
|
```bash
|
|
303
346
|
# CORRECT
|
|
@@ -318,5 +361,6 @@ The CLI shortcuts (`bbx click el_xxx`) handle this wrapping automatically, but `
|
|
|
318
361
|
1. **Find target**: `dom.find_by_text`, `dom.find_by_role`, or `dom.query` → get `elementRef`
|
|
319
362
|
2. **Focus** if needed: `input.focus` (for keyboard input)
|
|
320
363
|
3. **Act**: `click`, `type`, `press_key`, `hover`, `drag`, `scroll_into_view`, etc.
|
|
321
|
-
4. **
|
|
322
|
-
5. **
|
|
364
|
+
4. **Inspect metadata**: confirm resolution strategy, hit test, stale recovery, and actual execution path
|
|
365
|
+
5. **Wait**: use `dom.wait_for` or an event-aware URL wait if the action triggers async updates
|
|
366
|
+
6. **Verify**: `dom.describe`, `styles.get_computed`, `page.get_state`, or `page.get_console`; never infer app success from dispatch alone
|
|
@@ -41,3 +41,5 @@ After any patch:
|
|
|
41
41
|
|
|
42
42
|
- Roll back every patch before finishing.
|
|
43
43
|
- If multiple patches are active, list them before rolling back so the subagent can explain what was tested.
|
|
44
|
+
- Rollback records live in the current document. Browser Bridge attempts to roll them back when access is disabled or switched to another window; navigation or document replacement removes the page-side registry and may make old patch IDs unusable.
|
|
45
|
+
- `patch.commit_session_baseline` keeps the current DOM/style changes but clears their rollback records. Use it only when the user intentionally wants those live changes to become the new patch baseline; it does not write source files or grant a longer-lived browser session.
|