btcp-browser-agent 0.1.12 → 0.1.16

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 CHANGED
@@ -1,338 +1,338 @@
1
- # btcp-browser-agent
2
-
3
- Give AI agents the power to see and control any browser.
4
-
5
- A lightweight foundation for building AI systems that need browser access — automation, testing, web agents, or any browser-based workflow.
6
-
7
- ## Why This Package?
8
-
9
- AI agents struggle with browsers because:
10
- - Raw HTML is too noisy (thousands of nodes)
11
- - CSS selectors break when layouts change
12
- - No stable way to reference elements across turns
13
-
14
- **Browser Agent solves this with smart snapshots:**
15
-
16
- ```
17
- BUTTON "Submit" [@ref:0]
18
- TEXTBOX "Email" [required] [@ref:1]
19
- LINK "Forgot password?" [@ref:2]
20
- ```
21
-
22
- One command gives your agent a clean, semantic view of any page. Stable `@ref` markers let it interact without fragile selectors.
23
-
24
- ## Features
25
-
26
- - **Smart Snapshots** - Accessibility tree format optimized for AI comprehension
27
- - **Stable Element Refs** - `@ref:N` markers that survive DOM changes within a session
28
- - **Full Browser Control** - Navigation, tabs, screenshots, keyboard/mouse
29
- - **46 DOM Actions** - Click, type, fill, scroll, hover, and more
30
- - **Two Modes** - Chrome extension (full control) or standalone (same-origin)
31
-
32
- ## Quick Example
33
-
34
- ```typescript
35
- import { createClient } from 'btcp-browser-agent/extension';
36
-
37
- const agent = createClient();
38
-
39
- // Navigate and understand the page
40
- await agent.navigate('https://example.com');
41
- const snapshot = await agent.snapshot();
42
- // Returns: BUTTON "Login" [@ref:0], TEXTBOX "Email" [@ref:1], ...
43
-
44
- // Interact using refs - no CSS selectors needed
45
- await agent.fill('@ref:1', 'user@example.com');
46
- await agent.click('@ref:0');
47
- ```
48
-
49
- ## Use Cases
50
-
51
- - **AI Assistants** - Let LLMs browse the web and complete tasks for users
52
- - **Browser Agents** - Foundation for autonomous web agents that research, navigate, and act
53
- - **Automated Testing** - Reliable UI tests with stable element refs that don't break on layout changes
54
- - **Web Automation** - Form filling, data extraction, multi-step workflow automation
55
- - **Web Scraping** - Extract structured data with semantic understanding of page content
56
-
57
- ## Installation
58
-
59
- ```bash
60
- npm install btcp-browser-agent
61
- ```
62
-
63
- ## Usage Modes
64
-
65
- ### Extension Mode (Full Browser Control)
66
-
67
- For Chrome extensions with cross-origin access, tab management, and screenshots.
68
-
69
- **Background Script:**
70
- ```typescript
71
- import { BackgroundAgent, setupMessageListener } from 'btcp-browser-agent/extension';
72
-
73
- // Option 1: Just set up message routing
74
- setupMessageListener();
75
-
76
- // Option 2: Use BackgroundAgent directly for programmatic control
77
- const agent = new BackgroundAgent();
78
- await agent.navigate('https://example.com');
79
- await agent.screenshot();
80
- ```
81
-
82
- **Content Script:**
83
- ```typescript
84
- import { createContentAgent } from 'btcp-browser-agent';
85
-
86
- const agent = createContentAgent();
87
-
88
- // Take a snapshot
89
- const { data } = await agent.execute({ action: 'snapshot' });
90
- console.log(data.tree); // Accessibility tree with refs
91
-
92
- // Click an element using ref from snapshot
93
- await agent.execute({ action: 'click', selector: '@ref:5' });
94
- ```
95
-
96
- **Popup (sending commands via messaging):**
97
- ```typescript
98
- import { createClient } from 'btcp-browser-agent';
99
-
100
- const client = createClient();
101
-
102
- // Navigate and interact
103
- await client.navigate('https://example.com');
104
- const snapshot = await client.snapshot();
105
- await client.click('@ref:5');
106
- const screenshot = await client.screenshot();
107
- ```
108
-
109
- ### Standalone Mode (No Extension)
110
-
111
- For use directly in a web page (limited to same-origin, no tab management):
112
-
113
- ```typescript
114
- import { createContentAgent } from 'btcp-browser-agent';
115
-
116
- const agent = createContentAgent();
117
-
118
- // Take a snapshot
119
- const { data } = await agent.execute({ action: 'snapshot' });
120
-
121
- // Interact with elements
122
- await agent.execute({ action: 'click', selector: '@ref:5' });
123
- await agent.execute({ action: 'fill', selector: '@ref:3', value: 'Hello' });
124
- ```
125
-
126
- ## API Reference
127
-
128
- ### BackgroundAgent (Extension Background Script)
129
-
130
- High-level browser orchestrator that runs in the extension's background script.
131
-
132
- ```typescript
133
- import { BackgroundAgent } from 'btcp-browser-agent/extension';
134
-
135
- const agent = new BackgroundAgent();
136
-
137
- // Tab Management
138
- await agent.newTab({ url: 'https://example.com' });
139
- await agent.switchTab(tabId);
140
- await agent.closeTab(tabId);
141
- const tabs = await agent.listTabs();
142
-
143
- // Navigation
144
- await agent.navigate('https://example.com');
145
- await agent.back();
146
- await agent.forward();
147
- await agent.reload();
148
-
149
- // Screenshots
150
- const screenshot = await agent.screenshot({ format: 'png' });
151
-
152
- // Execute commands (routes to ContentAgent for DOM operations)
153
- await agent.execute({ action: 'click', selector: '#submit' });
154
- ```
155
-
156
- #### Multi-Tab Operations
157
-
158
- ```typescript
159
- // Open tabs
160
- const tab1 = await agent.newTab({ url: 'https://google.com' });
161
- const tab2 = await agent.newTab({ url: 'https://github.com', active: false });
162
-
163
- // Method 1: tab() handle - interact without switching
164
- const githubTab = agent.tab(tab2.id);
165
- await githubTab.snapshot();
166
- await githubTab.click('@ref:5');
167
-
168
- // Method 2: Specify tabId in execute
169
- await agent.execute(
170
- { action: 'getText', selector: 'h1' },
171
- { tabId: tab2.id }
172
- );
173
-
174
- // Active tab stays tab1 (no switching needed)
175
- ```
176
-
177
- ### ContentAgent (Content Script)
178
-
179
- DOM automation agent that runs in content scripts or web pages.
180
-
181
- ```typescript
182
- import { createContentAgent } from 'btcp-browser-agent';
183
-
184
- const agent = createContentAgent();
185
-
186
- // Execute commands
187
- const response = await agent.execute({ action: 'snapshot' });
188
- ```
189
-
190
- #### Available Actions
191
-
192
- **DOM Reading:**
193
- | Action | Description |
194
- |--------|-------------|
195
- | `snapshot` | Get accessibility tree with element refs |
196
- | `getText` | Get element text content |
197
- | `getAttribute` | Get element attribute value |
198
- | `isVisible` | Check if element is visible |
199
- | `isEnabled` | Check if element is enabled |
200
- | `isChecked` | Check if checkbox/radio is checked |
201
- | `getBoundingBox` | Get element dimensions |
202
-
203
- **Element Interaction:**
204
- | Action | Description |
205
- |--------|-------------|
206
- | `click` | Click an element |
207
- | `dblclick` | Double-click an element |
208
- | `type` | Type text (keystroke by keystroke) |
209
- | `fill` | Fill input (instant) |
210
- | `clear` | Clear input value |
211
- | `check` | Check checkbox |
212
- | `uncheck` | Uncheck checkbox |
213
- | `select` | Select dropdown option |
214
- | `hover` | Hover over element |
215
- | `focus` | Focus element |
216
- | `blur` | Remove focus |
217
-
218
- **Keyboard/Mouse:**
219
- | Action | Description |
220
- |--------|-------------|
221
- | `press` | Press a key |
222
- | `keyDown` | Key down event |
223
- | `keyUp` | Key up event |
224
-
225
- **Other:**
226
- | Action | Description |
227
- |--------|-------------|
228
- | `scroll` | Scroll page or element |
229
- | `scrollIntoView` | Scroll element into view |
230
- | `wait` | Wait for element state |
231
- | `evaluate` | Execute JavaScript |
232
-
233
- ### Element Refs
234
-
235
- The `snapshot` action returns element references for stable selection:
236
-
237
- ```typescript
238
- const { data } = await agent.execute({ action: 'snapshot' });
239
- // data.tree: "BUTTON 'Submit' [@ref:5]\nTEXTBOX 'Email' [@ref:3]"
240
-
241
- // Use refs in subsequent commands
242
- await agent.execute({ action: 'click', selector: '@ref:5' });
243
- ```
244
-
245
- ### Script Injection
246
-
247
- Inject custom JavaScript into the page's main world and communicate with it:
248
-
249
- ```typescript
250
- // Inject a helper script
251
- await client.scriptInject(`
252
- window.addEventListener('message', (e) => {
253
- if (e.data?.type === 'btcp:script-command') {
254
- const { commandId, payload } = e.data;
255
- // Handle command and respond
256
- window.postMessage({
257
- type: 'btcp:script-ack',
258
- commandId,
259
- result: { /* your data */ }
260
- }, '*');
261
- }
262
- });
263
- `, { scriptId: 'helper' });
264
-
265
- // Send commands to injected script
266
- const result = await client.scriptSend(
267
- { action: 'getData', id: '123' },
268
- { scriptId: 'helper' }
269
- );
270
- ```
271
-
272
- **Why script injection?**
273
- - Access page-level APIs (fetch with page cookies, window globals)
274
- - Interact with page frameworks (React state, etc.)
275
- - Execute code with full page context
276
-
277
- ## Architecture
278
-
279
- The package provides a clean separation between browser-level and DOM-level operations:
280
-
281
- ```
282
- ┌─────────────────────────────────────────────────────────────────┐
283
- │ Background Script (Extension Service Worker) │
284
- │ ┌─────────────────────────────────────────────────────────────┐│
285
- │ │ BackgroundAgent ││
286
- │ │ - Tab management (create, close, switch, list) ││
287
- │ │ - Navigation (goto, back, forward, reload) ││
288
- │ │ - Screenshots (chrome.tabs.captureVisibleTab) ││
289
- │ │ - Routes DOM commands → ContentAgent ││
290
- │ └─────────────────────────────────────────────────────────────┘│
291
- └─────────────────────────────────────────────────────────────────┘
292
-
293
- chrome.tabs.sendMessage
294
-
295
- ┌─────────────────────────────────────────────────────────────────┐
296
- │ Content Script (Per Tab) │
297
- │ ┌─────────────────────────────────────────────────────────────┐│
298
- │ │ ContentAgent ││
299
- │ │ - DOM snapshot (accessibility tree) ││
300
- │ │ - Element interaction (click, type, fill, hover) ││
301
- │ │ - DOM queries (getText, getAttribute, isVisible) ││
302
- │ │ - Keyboard/mouse events ││
303
- │ └─────────────────────────────────────────────────────────────┘│
304
- └─────────────────────────────────────────────────────────────────┘
305
- ```
306
-
307
- ## Package Structure
308
-
309
- ```
310
- btcp-browser-agent/
311
- ├── @btcp/core # ContentAgent - DOM operations
312
- │ ├── createContentAgent()
313
- │ ├── DOMActions
314
- │ └── createSnapshot()
315
-
316
- ├── @btcp/extension # BackgroundAgent - Browser operations
317
- │ ├── BackgroundAgent
318
- │ ├── setupMessageListener()
319
- │ └── createClient()
320
-
321
- └── btcp-browser-agent # Main package - re-exports both
322
- ```
323
-
324
- ## Capabilities Comparison
325
-
326
- | Capability | ContentAgent (Standalone) | BackgroundAgent (Extension) |
327
- |------------|--------------------------|--------------------------|
328
- | DOM Snapshot | Yes | Yes (via ContentAgent) |
329
- | Element Clicks | Yes | Yes (via ContentAgent) |
330
- | Form Filling | Yes | Yes (via ContentAgent) |
331
- | Cross-origin | Same-origin only | Any page |
332
- | Tab Management | No | Yes |
333
- | Navigation | No | Yes |
334
- | Screenshots | No | Yes |
335
-
336
- ## License
337
-
338
- Apache-2.0
1
+ # btcp-browser-agent
2
+
3
+ Give AI agents the power to see and control any browser.
4
+
5
+ A lightweight foundation for building AI systems that need browser access — automation, testing, web agents, or any browser-based workflow.
6
+
7
+ ## Why This Package?
8
+
9
+ AI agents struggle with browsers because:
10
+ - Raw HTML is too noisy (thousands of nodes)
11
+ - CSS selectors break when layouts change
12
+ - No stable way to reference elements across turns
13
+
14
+ **Browser Agent solves this with smart snapshots:**
15
+
16
+ ```
17
+ BUTTON "Submit" [@ref:0]
18
+ TEXTBOX "Email" [required] [@ref:1]
19
+ LINK "Forgot password?" [@ref:2]
20
+ ```
21
+
22
+ One command gives your agent a clean, semantic view of any page. Stable `@ref` markers let it interact without fragile selectors.
23
+
24
+ ## Features
25
+
26
+ - **Smart Snapshots** - Accessibility tree format optimized for AI comprehension
27
+ - **Stable Element Refs** - `@ref:N` markers that survive DOM changes within a session
28
+ - **Full Browser Control** - Navigation, tabs, screenshots, keyboard/mouse
29
+ - **46 DOM Actions** - Click, type, fill, scroll, hover, and more
30
+ - **Two Modes** - Chrome extension (full control) or standalone (same-origin)
31
+
32
+ ## Quick Example
33
+
34
+ ```typescript
35
+ import { createClient } from 'btcp-browser-agent/extension';
36
+
37
+ const agent = createClient();
38
+
39
+ // Navigate and understand the page
40
+ await agent.navigate('https://example.com');
41
+ const snapshot = await agent.snapshot();
42
+ // Returns: BUTTON "Login" [@ref:0], TEXTBOX "Email" [@ref:1], ...
43
+
44
+ // Interact using refs - no CSS selectors needed
45
+ await agent.fill('@ref:1', 'user@example.com');
46
+ await agent.click('@ref:0');
47
+ ```
48
+
49
+ ## Use Cases
50
+
51
+ - **AI Assistants** - Let LLMs browse the web and complete tasks for users
52
+ - **Browser Agents** - Foundation for autonomous web agents that research, navigate, and act
53
+ - **Automated Testing** - Reliable UI tests with stable element refs that don't break on layout changes
54
+ - **Web Automation** - Form filling, data extraction, multi-step workflow automation
55
+ - **Web Scraping** - Extract structured data with semantic understanding of page content
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ npm install btcp-browser-agent
61
+ ```
62
+
63
+ ## Usage Modes
64
+
65
+ ### Extension Mode (Full Browser Control)
66
+
67
+ For Chrome extensions with cross-origin access, tab management, and screenshots.
68
+
69
+ **Background Script:**
70
+ ```typescript
71
+ import { BackgroundAgent, setupMessageListener } from 'btcp-browser-agent/extension';
72
+
73
+ // Option 1: Just set up message routing
74
+ setupMessageListener();
75
+
76
+ // Option 2: Use BackgroundAgent directly for programmatic control
77
+ const agent = new BackgroundAgent();
78
+ await agent.navigate('https://example.com');
79
+ await agent.screenshot();
80
+ ```
81
+
82
+ **Content Script:**
83
+ ```typescript
84
+ import { createContentAgent } from 'btcp-browser-agent';
85
+
86
+ const agent = createContentAgent();
87
+
88
+ // Take a snapshot
89
+ const { data } = await agent.execute({ action: 'snapshot' });
90
+ console.log(data.tree); // Accessibility tree with refs
91
+
92
+ // Click an element using ref from snapshot
93
+ await agent.execute({ action: 'click', selector: '@ref:5' });
94
+ ```
95
+
96
+ **Popup (sending commands via messaging):**
97
+ ```typescript
98
+ import { createClient } from 'btcp-browser-agent';
99
+
100
+ const client = createClient();
101
+
102
+ // Navigate and interact
103
+ await client.navigate('https://example.com');
104
+ const snapshot = await client.snapshot();
105
+ await client.click('@ref:5');
106
+ const screenshot = await client.screenshot();
107
+ ```
108
+
109
+ ### Standalone Mode (No Extension)
110
+
111
+ For use directly in a web page (limited to same-origin, no tab management):
112
+
113
+ ```typescript
114
+ import { createContentAgent } from 'btcp-browser-agent';
115
+
116
+ const agent = createContentAgent();
117
+
118
+ // Take a snapshot
119
+ const { data } = await agent.execute({ action: 'snapshot' });
120
+
121
+ // Interact with elements
122
+ await agent.execute({ action: 'click', selector: '@ref:5' });
123
+ await agent.execute({ action: 'fill', selector: '@ref:3', value: 'Hello' });
124
+ ```
125
+
126
+ ## API Reference
127
+
128
+ ### BackgroundAgent (Extension Background Script)
129
+
130
+ High-level browser orchestrator that runs in the extension's background script.
131
+
132
+ ```typescript
133
+ import { BackgroundAgent } from 'btcp-browser-agent/extension';
134
+
135
+ const agent = new BackgroundAgent();
136
+
137
+ // Tab Management
138
+ await agent.newTab({ url: 'https://example.com' });
139
+ await agent.switchTab(tabId);
140
+ await agent.closeTab(tabId);
141
+ const tabs = await agent.listTabs();
142
+
143
+ // Navigation
144
+ await agent.navigate('https://example.com');
145
+ await agent.back();
146
+ await agent.forward();
147
+ await agent.reload();
148
+
149
+ // Screenshots
150
+ const screenshot = await agent.screenshot({ format: 'png' });
151
+
152
+ // Execute commands (routes to ContentAgent for DOM operations)
153
+ await agent.execute({ action: 'click', selector: '#submit' });
154
+ ```
155
+
156
+ #### Multi-Tab Operations
157
+
158
+ ```typescript
159
+ // Open tabs
160
+ const tab1 = await agent.newTab({ url: 'https://google.com' });
161
+ const tab2 = await agent.newTab({ url: 'https://github.com', active: false });
162
+
163
+ // Method 1: tab() handle - interact without switching
164
+ const githubTab = agent.tab(tab2.id);
165
+ await githubTab.snapshot();
166
+ await githubTab.click('@ref:5');
167
+
168
+ // Method 2: Specify tabId in execute
169
+ await agent.execute(
170
+ { action: 'getText', selector: 'h1' },
171
+ { tabId: tab2.id }
172
+ );
173
+
174
+ // Active tab stays tab1 (no switching needed)
175
+ ```
176
+
177
+ ### ContentAgent (Content Script)
178
+
179
+ DOM automation agent that runs in content scripts or web pages.
180
+
181
+ ```typescript
182
+ import { createContentAgent } from 'btcp-browser-agent';
183
+
184
+ const agent = createContentAgent();
185
+
186
+ // Execute commands
187
+ const response = await agent.execute({ action: 'snapshot' });
188
+ ```
189
+
190
+ #### Available Actions
191
+
192
+ **DOM Reading:**
193
+ | Action | Description |
194
+ |--------|-------------|
195
+ | `snapshot` | Get accessibility tree with element refs |
196
+ | `getText` | Get element text content |
197
+ | `getAttribute` | Get element attribute value |
198
+ | `isVisible` | Check if element is visible |
199
+ | `isEnabled` | Check if element is enabled |
200
+ | `isChecked` | Check if checkbox/radio is checked |
201
+ | `getBoundingBox` | Get element dimensions |
202
+
203
+ **Element Interaction:**
204
+ | Action | Description |
205
+ |--------|-------------|
206
+ | `click` | Click an element |
207
+ | `dblclick` | Double-click an element |
208
+ | `type` | Type text (keystroke by keystroke) |
209
+ | `fill` | Fill input (instant) |
210
+ | `clear` | Clear input value |
211
+ | `check` | Check checkbox |
212
+ | `uncheck` | Uncheck checkbox |
213
+ | `select` | Select dropdown option |
214
+ | `hover` | Hover over element |
215
+ | `focus` | Focus element |
216
+ | `blur` | Remove focus |
217
+
218
+ **Keyboard/Mouse:**
219
+ | Action | Description |
220
+ |--------|-------------|
221
+ | `press` | Press a key |
222
+ | `keyDown` | Key down event |
223
+ | `keyUp` | Key up event |
224
+
225
+ **Other:**
226
+ | Action | Description |
227
+ |--------|-------------|
228
+ | `scroll` | Scroll page or element |
229
+ | `scrollIntoView` | Scroll element into view |
230
+ | `wait` | Wait for element state |
231
+ | `evaluate` | Execute JavaScript |
232
+
233
+ ### Element Refs
234
+
235
+ The `snapshot` action returns element references for stable selection:
236
+
237
+ ```typescript
238
+ const { data } = await agent.execute({ action: 'snapshot' });
239
+ // data.tree: "BUTTON 'Submit' [@ref:5]\nTEXTBOX 'Email' [@ref:3]"
240
+
241
+ // Use refs in subsequent commands
242
+ await agent.execute({ action: 'click', selector: '@ref:5' });
243
+ ```
244
+
245
+ ### Script Injection
246
+
247
+ Inject custom JavaScript into the page's main world and communicate with it:
248
+
249
+ ```typescript
250
+ // Inject a helper script
251
+ await client.scriptInject(`
252
+ window.addEventListener('message', (e) => {
253
+ if (e.data?.type === 'btcp:script-command') {
254
+ const { commandId, payload } = e.data;
255
+ // Handle command and respond
256
+ window.postMessage({
257
+ type: 'btcp:script-ack',
258
+ commandId,
259
+ result: { /* your data */ }
260
+ }, '*');
261
+ }
262
+ });
263
+ `, { scriptId: 'helper' });
264
+
265
+ // Send commands to injected script
266
+ const result = await client.scriptSend(
267
+ { action: 'getData', id: '123' },
268
+ { scriptId: 'helper' }
269
+ );
270
+ ```
271
+
272
+ **Why script injection?**
273
+ - Access page-level APIs (fetch with page cookies, window globals)
274
+ - Interact with page frameworks (React state, etc.)
275
+ - Execute code with full page context
276
+
277
+ ## Architecture
278
+
279
+ The package provides a clean separation between browser-level and DOM-level operations:
280
+
281
+ ```
282
+ ┌─────────────────────────────────────────────────────────────────┐
283
+ │ Background Script (Extension Service Worker) │
284
+ │ ┌─────────────────────────────────────────────────────────────┐│
285
+ │ │ BackgroundAgent ││
286
+ │ │ - Tab management (create, close, switch, list) ││
287
+ │ │ - Navigation (goto, back, forward, reload) ││
288
+ │ │ - Screenshots (chrome.tabs.captureVisibleTab) ││
289
+ │ │ - Routes DOM commands → ContentAgent ││
290
+ │ └─────────────────────────────────────────────────────────────┘│
291
+ └─────────────────────────────────────────────────────────────────┘
292
+
293
+ chrome.tabs.sendMessage
294
+
295
+ ┌─────────────────────────────────────────────────────────────────┐
296
+ │ Content Script (Per Tab) │
297
+ │ ┌─────────────────────────────────────────────────────────────┐│
298
+ │ │ ContentAgent ││
299
+ │ │ - DOM snapshot (accessibility tree) ││
300
+ │ │ - Element interaction (click, type, fill, hover) ││
301
+ │ │ - DOM queries (getText, getAttribute, isVisible) ││
302
+ │ │ - Keyboard/mouse events ││
303
+ │ └─────────────────────────────────────────────────────────────┘│
304
+ └─────────────────────────────────────────────────────────────────┘
305
+ ```
306
+
307
+ ## Package Structure
308
+
309
+ ```
310
+ btcp-browser-agent/
311
+ ├── @btcp/core # ContentAgent - DOM operations
312
+ │ ├── createContentAgent()
313
+ │ ├── DOMActions
314
+ │ └── createSnapshot()
315
+
316
+ ├── @btcp/extension # BackgroundAgent - Browser operations
317
+ │ ├── BackgroundAgent
318
+ │ ├── setupMessageListener()
319
+ │ └── createClient()
320
+
321
+ └── btcp-browser-agent # Main package - re-exports both
322
+ ```
323
+
324
+ ## Capabilities Comparison
325
+
326
+ | Capability | ContentAgent (Standalone) | BackgroundAgent (Extension) |
327
+ |------------|--------------------------|--------------------------|
328
+ | DOM Snapshot | Yes | Yes (via ContentAgent) |
329
+ | Element Clicks | Yes | Yes (via ContentAgent) |
330
+ | Form Filling | Yes | Yes (via ContentAgent) |
331
+ | Cross-origin | Same-origin only | Any page |
332
+ | Tab Management | No | Yes |
333
+ | Navigation | No | Yes |
334
+ | Screenshots | No | Yes |
335
+
336
+ ## License
337
+
338
+ Apache-2.0