@browserbridge/bbx 1.0.0 → 1.1.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.
Files changed (72) hide show
  1. package/README.md +6 -4
  2. package/package.json +53 -53
  3. package/packages/agent-client/src/cli-helpers.js +43 -5
  4. package/packages/agent-client/src/cli.js +176 -171
  5. package/packages/agent-client/src/client.js +66 -21
  6. package/packages/agent-client/src/command-registry.js +104 -69
  7. package/packages/agent-client/src/detect.js +162 -54
  8. package/packages/agent-client/src/install.js +34 -28
  9. package/packages/agent-client/src/mcp-config.js +40 -40
  10. package/packages/agent-client/src/runtime.js +41 -20
  11. package/packages/agent-client/src/setup-status.js +23 -30
  12. package/packages/mcp-server/src/bin.js +57 -5
  13. package/packages/mcp-server/src/handlers.js +573 -256
  14. package/packages/mcp-server/src/server.js +568 -257
  15. package/packages/native-host/bin/bridge-daemon.js +39 -6
  16. package/packages/native-host/bin/install-manifest.js +26 -4
  17. package/packages/native-host/bin/postinstall.js +4 -2
  18. package/packages/native-host/src/config.js +142 -13
  19. package/packages/native-host/src/daemon-process.js +396 -0
  20. package/packages/native-host/src/daemon.js +350 -150
  21. package/packages/native-host/src/framing.js +131 -11
  22. package/packages/native-host/src/install-manifest.js +194 -29
  23. package/packages/native-host/src/native-host.js +154 -102
  24. package/packages/protocol/src/budget.js +3 -7
  25. package/packages/protocol/src/capabilities.js +6 -3
  26. package/packages/protocol/src/defaults.js +1 -0
  27. package/packages/protocol/src/errors.js +15 -11
  28. package/packages/protocol/src/payload-cost.js +19 -6
  29. package/packages/protocol/src/protocol.js +242 -73
  30. package/packages/protocol/src/registry.js +311 -45
  31. package/packages/protocol/src/summary.js +260 -109
  32. package/packages/protocol/src/types.js +29 -4
  33. package/skills/browser-bridge/SKILL.md +3 -2
  34. package/skills/browser-bridge/agents/openai.yaml +3 -3
  35. package/skills/browser-bridge/references/interaction.md +34 -11
  36. package/skills/browser-bridge/references/patch-workflow.md +3 -0
  37. package/skills/browser-bridge/references/protocol.md +127 -71
  38. package/skills/browser-bridge/references/tailwind.md +12 -11
  39. package/skills/browser-bridge/references/token-efficiency.md +23 -22
  40. package/skills/browser-bridge/references/ui-workflows.md +8 -0
  41. package/CHANGELOG.md +0 -55
  42. package/assets/banner.jpg +0 -0
  43. package/assets/logo.png +0 -0
  44. package/assets/logo.svg +0 -65
  45. package/docs/api-reference.md +0 -157
  46. package/docs/cli-guide.md +0 -128
  47. package/docs/index.md +0 -25
  48. package/docs/manual-setup.md +0 -140
  49. package/docs/mcp-vs-cli.md +0 -258
  50. package/docs/publishing.md +0 -114
  51. package/docs/quickstart.md +0 -104
  52. package/docs/troubleshooting.md +0 -59
  53. package/docs/usage-scenarios.md +0 -136
  54. package/manifest.json +0 -52
  55. package/packages/extension/assets/icon-128.png +0 -0
  56. package/packages/extension/assets/icon-16.png +0 -0
  57. package/packages/extension/assets/icon-32.png +0 -0
  58. package/packages/extension/assets/icon-48.png +0 -0
  59. package/packages/extension/src/background-helpers.js +0 -459
  60. package/packages/extension/src/background-routing.js +0 -91
  61. package/packages/extension/src/background.js +0 -3227
  62. package/packages/extension/src/content-script-helpers.js +0 -281
  63. package/packages/extension/src/content-script.js +0 -1977
  64. package/packages/extension/src/debugger-coordinator.js +0 -188
  65. package/packages/extension/src/sidepanel-helpers.js +0 -102
  66. package/packages/extension/ui/offscreen.html +0 -6
  67. package/packages/extension/ui/offscreen.js +0 -61
  68. package/packages/extension/ui/popup.html +0 -35
  69. package/packages/extension/ui/popup.js +0 -279
  70. package/packages/extension/ui/sidepanel.html +0 -102
  71. package/packages/extension/ui/sidepanel.js +0 -1854
  72. package/packages/extension/ui/ui.css +0 -1159
@@ -7,7 +7,7 @@ export {};
7
7
  */
8
8
 
9
9
  /**
10
- * @typedef {'page.read' | 'page.evaluate' | 'dom.read' | 'styles.read' | 'layout.read' | 'viewport.control' | 'navigation.control' | 'screenshot.partial' | 'patch.dom' | 'patch.styles' | 'cdp.dom_snapshot' | 'cdp.box_model' | 'cdp.styles' | 'automation.input' | 'tabs.manage' | 'performance.read' | 'network.read'} Capability
10
+ * @typedef {'page.read' | 'page.evaluate' | 'dom.read' | 'styles.read' | 'layout.read' | 'viewport.control' | 'navigation.control' | 'screenshot.partial' | 'patch.dom' | 'patch.styles' | 'cdp.dom_snapshot' | 'cdp.box_model' | 'cdp.styles' | 'cdp.input' | 'automation.input' | 'tabs.manage' | 'performance.read' | 'network.read'} Capability
11
11
  */
12
12
 
13
13
  /**
@@ -15,7 +15,7 @@ export {};
15
15
  */
16
16
 
17
17
  /**
18
- * @typedef {'access.request' | 'tabs.list' | 'tabs.create' | 'tabs.close' | 'skill.get_runtime_context' | 'setup.get_status' | 'setup.install' | 'page.get_state' | 'page.evaluate' | 'page.get_console' | 'page.wait_for_load_state' | 'page.get_storage' | 'page.get_text' | 'page.get_network' | 'navigation.navigate' | 'navigation.reload' | 'navigation.go_back' | 'navigation.go_forward' | 'dom.query' | 'dom.describe' | 'dom.get_text' | 'dom.get_attributes' | 'dom.wait_for' | 'dom.find_by_text' | 'dom.find_by_role' | 'dom.get_html' | 'dom.get_accessibility_tree' | 'layout.get_box_model' | 'layout.hit_test' | 'styles.get_computed' | 'styles.get_matched_rules' | 'viewport.scroll' | 'viewport.resize' | 'input.click' | 'input.focus' | 'input.type' | 'input.press_key' | 'input.set_checked' | 'input.select_option' | 'input.hover' | 'input.drag' | 'input.scroll_into_view' | 'screenshot.capture_region' | 'screenshot.capture_element' | 'screenshot.capture_full_page' | 'patch.apply_styles' | 'patch.apply_dom' | 'patch.list' | 'patch.rollback' | 'patch.commit_session_baseline' | 'cdp.get_document' | 'cdp.get_dom_snapshot' | 'cdp.get_box_model' | 'cdp.get_computed_styles_for_node' | 'performance.get_metrics' | 'log.tail' | 'health.ping'} BridgeMethod
18
+ * @typedef {'access.request' | 'tabs.list' | 'tabs.create' | 'tabs.close' | 'skill.get_runtime_context' | 'setup.get_status' | 'setup.install' | 'page.get_state' | 'page.evaluate' | 'page.get_console' | 'page.wait_for_load_state' | 'page.get_storage' | 'page.get_text' | 'page.get_network' | 'navigation.navigate' | 'navigation.reload' | 'navigation.go_back' | 'navigation.go_forward' | 'dom.query' | 'dom.describe' | 'dom.get_text' | 'dom.get_attributes' | 'dom.wait_for' | 'dom.find_by_text' | 'dom.find_by_role' | 'dom.get_html' | 'dom.get_accessibility_tree' | 'layout.get_box_model' | 'layout.hit_test' | 'styles.get_computed' | 'styles.get_matched_rules' | 'viewport.scroll' | 'viewport.resize' | 'input.click' | 'input.focus' | 'input.type' | 'input.press_key' | 'input.set_checked' | 'input.select_option' | 'input.hover' | 'input.drag' | 'input.scroll_into_view' | 'screenshot.capture_region' | 'screenshot.capture_element' | 'screenshot.capture_full_page' | 'patch.apply_styles' | 'patch.apply_dom' | 'patch.list' | 'patch.rollback' | 'patch.commit_session_baseline' | 'cdp.get_document' | 'cdp.get_dom_snapshot' | 'cdp.get_box_model' | 'cdp.get_computed_styles_for_node' | 'cdp.dispatch_key_event' | 'performance.get_metrics' | 'log.tail' | 'health.ping'} BridgeMethod
19
19
  */
20
20
 
21
21
  /**
@@ -38,7 +38,7 @@ export {};
38
38
  * budget_applied?: boolean,
39
39
  * budget_truncated?: boolean,
40
40
  * continuation_hint?: string | null,
41
- * [key: string]: unknown
41
+ * [key: string]: unknown
42
42
  * }} BridgeMeta
43
43
  */
44
44
 
@@ -52,11 +52,20 @@ export {};
52
52
  * }} BridgeRequest
53
53
  */
54
54
 
55
+ /**
56
+ * @typedef {{
57
+ * hint: string,
58
+ * retry?: boolean,
59
+ * retryAfterMs?: number
60
+ * }} BridgeRecovery
61
+ */
62
+
55
63
  /**
56
64
  * @typedef {{
57
65
  * code: ErrorCode,
58
66
  * message: string,
59
- * details: unknown
67
+ * details: unknown,
68
+ * recovery?: BridgeRecovery
60
69
  * }} BridgeFailure
61
70
  */
62
71
 
@@ -187,6 +196,22 @@ export {};
187
196
  * }} NormalizedInputAction
188
197
  */
189
198
 
199
+ /**
200
+ * @typedef {{
201
+ * key?: string,
202
+ * code?: string,
203
+ * modifiers?: string[] | number
204
+ * }} CdpDispatchKeyEventParams
205
+ */
206
+
207
+ /**
208
+ * @typedef {{
209
+ * key: string,
210
+ * code: string,
211
+ * modifiers: string[] | number
212
+ * }} NormalizedCdpDispatchKeyEventParams
213
+ */
214
+
190
215
  /**
191
216
  * @typedef {{
192
217
  * target?: InputTarget,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: browser-bridge
3
- description: "Token-efficient Chrome tab inspection, interaction, and patching via local bridge extension (CLI: bbx). Reads live DOM, styles, console, network, and storage from a real Chrome tab with lower token cost than screenshots."
3
+ description: 'Token-efficient Chrome tab inspection, interaction, and patching via local bridge extension (CLI: bbx). Reads live DOM, styles, console, network, and storage from a real Chrome tab with lower token cost than screenshots.'
4
4
  ---
5
5
 
6
6
  # Browser Bridge
@@ -69,6 +69,7 @@ bbx click <ref> [button] # click element
69
69
  bbx focus <ref> # focus element
70
70
  bbx type <ref> <text...> # type into element
71
71
  bbx press-key <key> [ref] # send key event
72
+ bbx cdp-press-key --tab <id> Escape # CDP key event without foreground focus
72
73
  bbx hover <ref> # hover over element
73
74
  bbx call input.scroll_into_view '{"target":{"elementRef":"el_123"}}' # ensure target is visible
74
75
  bbx patch-style <ref> prop=val... # apply style patch
@@ -202,7 +203,7 @@ bbx page-text 2000 # extract page content
202
203
  | Find | `dom.find_by_text`, `dom.find_by_role`, `dom.wait_for`, `dom.get_accessibility_tree` |
203
204
  | Page State | `page.get_console`, `page.get_storage`, `page.get_text`, `page.wait_for_load_state`, `page.evaluate` (debugger-backed) |
204
205
  | Network | `page.get_network` |
205
- | Interact | `input.click`, `input.type`, `input.focus`, `input.press_key`, `input.hover`, `input.drag`, `input.scroll_into_view` |
206
+ | Interact | `input.click`, `input.type`, `input.focus`, `input.press_key`, `cdp.dispatch_key_event`, `input.hover`, `input.drag`, `input.scroll_into_view` |
206
207
  | Tabs | `tabs.list` (preferred), `tabs.create` (avoid unless necessary), `tabs.close` |
207
208
  | Patch | `patch.apply_styles`, `patch.apply_dom`, `patch.rollback` |
208
209
  | Navigate | `navigation.navigate`, `viewport.scroll`, `viewport.resize` |
@@ -1,4 +1,4 @@
1
1
  interface:
2
- display_name: "Browser Bridge"
3
- short_description: "Token-efficient Chrome tab inspection, interaction, and patching via local bridge"
4
- default_prompt: "Use the browser-bridge skill for Chrome tab inspection, interaction, and patching. Start with `bbx status` to confirm connectivity. If ACCESS_DENIED, ask the user to click Enable in the extension popup/side panel, then retry. Default routing follows the active tab; use `--tab` only for a different tab. Prefer structured reads (`dom.query`, `styles.get_computed`) over screenshots. Batch independent reads with `bbx batch`. Use `bbx skill` for runtime presets."
2
+ display_name: 'Browser Bridge'
3
+ short_description: 'Token-efficient Chrome tab inspection, interaction, and patching via local bridge'
4
+ default_prompt: 'Use the browser-bridge skill for Chrome tab inspection, interaction, and patching. Start with `bbx status` to confirm connectivity. If ACCESS_DENIED, ask the user to click Enable in the extension popup/side panel, then retry. Default routing follows the active tab; use `--tab` only for a different tab. Prefer structured reads (`dom.query`, `styles.get_computed`) over screenshots. Batch independent reads with `bbx batch`. Use `bbx skill` for runtime presets.'
@@ -2,17 +2,18 @@
2
2
 
3
3
  ## Input Methods
4
4
 
5
- | Method | CLI Shortcut | Purpose |
6
- |--------|-------------|---------|
7
- | `input.click` | `click <ref> [button]` | DOM-level click |
8
- | `input.focus` | `focus <ref>` | Focus an element |
9
- | `input.type` | `type <ref> <text>` | Type into input/textarea/contenteditable |
10
- | `input.press_key` | `press-key <key> [ref]` | Send keyboard key (Enter, Backspace, etc.) |
11
- | `input.set_checked` | `call input.set_checked '{...}'` | Toggle checkbox/radio |
12
- | `input.select_option` | `call input.select_option '{...}'` | Select native `<select>` by value/label/index |
13
- | `input.hover` | `hover <ref>` | Trigger CSS `:hover` state (mouseenter/mouseover/mousemove) |
14
- | `input.drag` | `call input.drag '{...}'` | Full drag-and-drop event sequence |
15
- | `input.scroll_into_view` | `call input.scroll_into_view '{...}'` | Ensure a target is visible before inspect/capture |
5
+ | Method | CLI Shortcut | Purpose |
6
+ | ------------------------ | ------------------------------------- | ----------------------------------------------------------- |
7
+ | `input.click` | `click <ref> [button]` | DOM-level click |
8
+ | `input.focus` | `focus <ref>` | Focus an element |
9
+ | `input.type` | `type <ref> <text>` | Type into input/textarea/contenteditable |
10
+ | `input.press_key` | `press-key <key> [ref]` | Send keyboard key (Enter, Backspace, etc.) |
11
+ | `cdp.dispatch_key_event` | `cdp-press-key --tab <id> <key>` | CDP keyDown/keyUp without focusing the target tab |
12
+ | `input.set_checked` | `call input.set_checked '{...}'` | Toggle checkbox/radio |
13
+ | `input.select_option` | `call input.select_option '{...}'` | Select native `<select>` by value/label/index |
14
+ | `input.hover` | `hover <ref>` | Trigger CSS `:hover` state (mouseenter/mouseover/mousemove) |
15
+ | `input.drag` | `call input.drag '{...}'` | Full drag-and-drop event sequence |
16
+ | `input.scroll_into_view` | `call input.scroll_into_view '{...}'` | Ensure a target is visible before inspect/capture |
16
17
 
17
18
  ## Navigation
18
19
 
@@ -39,6 +40,7 @@ Scrolls the window or a specific scrollable element.
39
40
  ### Resize Viewport
40
41
 
41
42
  Set device viewport dimensions (useful for responsive testing):
43
+
42
44
  ```bash
43
45
  bbx resize 375 812 # iPhone-size
44
46
  bbx resize 1024 768 # tablet
@@ -50,6 +52,7 @@ Uses CDP device emulation - the page re-renders at the new size immediately.
50
52
  ## Tab Management
51
53
 
52
54
  **IMPORTANT: Prefer existing tabs.** Never create new tabs unless:
55
+
53
56
  - The user explicitly requests opening a new page
54
57
  - The task requires a clean/fresh page state (e.g., testing initial load)
55
58
  - You need to compare multiple pages simultaneously
@@ -65,6 +68,7 @@ bbx call tabs.create '{"url":"https://example.com","active":false}'
65
68
  ```
66
69
 
67
70
  Typical workflow - compare two pages (only when comparison is required):
71
+
68
72
  1. `tabs.list` to see current tabs
69
73
  2. `tabs.create` with second URL
70
74
  3. Inspect both tabs (`--tab <id>` or MCP `tabId` only when you need the non-active tab)
@@ -83,6 +87,7 @@ bbx call dom.get_accessibility_tree '{"maxNodes":100,"maxDepth":5}'
83
87
  Each node: `role`, `name`, `description`, `value`, `focused`, `required`, `checked`, `disabled`, `interactive`, `childIds`.
84
88
 
85
89
  Typical workflow - find interactive controls:
90
+
86
91
  1. `dom.get_accessibility_tree` with small `maxNodes`
87
92
  2. Scan for nodes with `interactive: true`
88
93
  3. Use role/name to identify the right control
@@ -103,6 +108,7 @@ bbx call --tab 200 dom.query '{"selector":"main"}'
103
108
  ```
104
109
 
105
110
  Open a new tab programmatically:
111
+
106
112
  ```bash
107
113
  bbx tab-create https://example.com # creates a new tab in the enabled window
108
114
  bbx call --tab <new-tabId> page.get_state
@@ -127,6 +133,7 @@ Scrolls the window by default. Pass an `elementRef` to scroll an inner scrollabl
127
133
  ### Scroll target into view
128
134
 
129
135
  Use this when the page has nested containers or when you want the target centered before a screenshot or hover:
136
+
130
137
  ```bash
131
138
  bbx call input.scroll_into_view '{"target":{"elementRef":"el_123"}}'
132
139
  bbx call input.scroll_into_view '{"target":{"selector":"[data-testid=\"submit-button\"]"}}'
@@ -143,6 +150,7 @@ bbx call page.get_network '{"limit":20,"clear":true}'
143
150
  Each entry: `method`, `url`, `status`, `duration`, `initiator`.
144
151
 
145
152
  Typical workflow - debug API calls:
153
+
146
154
  1. `page.get_network` to see recent requests
147
155
  2. Filter by URL pattern or status code
148
156
  3. Cross-reference with `page.get_console` for errors
@@ -151,11 +159,13 @@ Typical workflow - debug API calls:
151
159
  ## Form Controls
152
160
 
153
161
  **Checkbox/radio:**
162
+
154
163
  ```bash
155
164
  bbx call input.set_checked '{"target":{"elementRef":"el_123"},"checked":true}'
156
165
  ```
157
166
 
158
167
  **Select dropdown:**
168
+
159
169
  ```bash
160
170
  bbx call input.select_option '{"target":{"elementRef":"el_456"},"values":["us"]}'
161
171
  ```
@@ -172,11 +182,13 @@ bbx call input.hover '{"target":{"elementRef":"el_abc123"}}'
172
182
  ```
173
183
 
174
184
  **Hold hover for inspection:** set `duration` (ms) to keep hover active before auto-releasing with `mouseleave`:
185
+
175
186
  ```bash
176
187
  bbx call input.hover '{"target":{"elementRef":"el_abc123"},"duration":2000}'
177
188
  ```
178
189
 
179
190
  Typical workflow - inspect a tooltip:
191
+
180
192
  1. `dom.query` to find the trigger element → `elementRef`
181
193
  2. `input.hover` with `duration: 2000`
182
194
  3. While hover holds, `dom.query` for tooltip content (e.g. `[role="tooltip"]`)
@@ -191,6 +203,7 @@ bbx call input.drag '{"source":{"elementRef":"el_src"},"destination":{"elementRe
191
203
  ```
192
204
 
193
205
  With pixel offsets for precise positioning:
206
+
194
207
  ```bash
195
208
  bbx call input.drag '{"source":{"elementRef":"el_src"},"destination":{"elementRef":"el_dst"},"sourceOffset":{"x":10,"y":10},"destinationOffset":{"x":5,"y":5}}'
196
209
  ```
@@ -198,6 +211,7 @@ bbx call input.drag '{"source":{"elementRef":"el_src"},"destination":{"elementRe
198
211
  Event sequence: `mousedown → dragstart → drag → dragenter → dragover → drop → dragend → mouseup`.
199
212
 
200
213
  Typical workflow - reorder a list:
214
+
201
215
  1. `dom.query` to find draggable items → get source and destination `elementRef` values
202
216
  2. `input.drag` from source to destination
203
217
  3. `dom.wait_for` to confirm the DOM updated
@@ -206,16 +220,21 @@ Typical workflow - reorder a list:
206
220
  ## Finding Elements
207
221
 
208
222
  ### By text content
223
+
209
224
  Find elements matching visible text. Faster than `dom.query` when you know the label:
225
+
210
226
  ```bash
211
227
  bbx find 'Submit Order'
212
228
  bbx call dom.find_by_text '{"text":"Add to Cart","scope":"button","exact":false}'
213
229
  ```
230
+
214
231
  - `scope`: optional CSS selector to narrow search (e.g. `"button"`, `".sidebar"`)
215
232
  - `exact`: `true` for exact match, `false` (default) for substring/case-insensitive
216
233
 
217
234
  ### By ARIA role
235
+
218
236
  Find elements by explicit `role` attribute or implicit HTML role (e.g. `<nav>` → `navigation`):
237
+
219
238
  ```bash
220
239
  bbx find-role button 'Save'
221
240
  bbx call dom.find_by_role '{"role":"navigation"}'
@@ -225,19 +244,23 @@ bbx call dom.find_by_role '{"role":"heading","name":"Dashboard"}'
225
244
  ## Waiting
226
245
 
227
246
  ### Wait for DOM condition
247
+
228
248
  ```bash
229
249
  bbx wait '.success-message' 10000
230
250
  bbx call dom.wait_for '{"selector":".modal","state":"visible","timeoutMs":10000}'
231
251
  bbx call dom.wait_for '{"selector":".spinner","state":"detached","timeoutMs":5000}'
232
252
  ```
253
+
233
254
  - `state`: `attached` (exists in DOM), `detached` (removed), `visible` (non-zero size), `hidden`
234
255
  - Uses MutationObserver + 250 ms polling fallback
235
256
  - Returns `{found, elementRef, duration}` - NOT an error on timeout
236
257
 
237
258
  ### Wait for page load
259
+
238
260
  ```bash
239
261
  bbx call page.wait_for_load_state '{"timeoutMs":10000}'
240
262
  ```
263
+
241
264
  Use after clicking navigation links.
242
265
 
243
266
  ## Interaction Flow
@@ -12,6 +12,7 @@ Use this order for layout or styling issues:
12
12
  6. `patch.rollback`
13
13
 
14
14
  Prefer style patches for:
15
+
15
16
  - overflow fixes
16
17
  - spacing adjustments
17
18
  - flex or grid tuning
@@ -21,6 +22,7 @@ Prefer style patches for:
21
22
  ## DOM patch loop
22
23
 
23
24
  Use DOM patches for:
25
+
24
26
  - text replacement
25
27
  - setting or removing an attribute
26
28
  - toggling a class
@@ -30,6 +32,7 @@ Keep DOM patches minimal and reversible.
30
32
  ## Verification
31
33
 
32
34
  After any patch:
35
+
33
36
  - compare box metrics when geometry matters
34
37
  - compare computed styles when appearance matters
35
38
  - capture a cropped screenshot only when the visual outcome is still unclear