@sparkleideas/browser 3.0.0-alpha.18
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 +730 -0
- package/agents/architect.yaml +11 -0
- package/agents/coder.yaml +11 -0
- package/agents/reviewer.yaml +10 -0
- package/agents/security-architect.yaml +10 -0
- package/agents/tester.yaml +10 -0
- package/docker/Dockerfile +22 -0
- package/docker/docker-compose.yml +52 -0
- package/docker/test-fixtures/index.html +61 -0
- package/package.json +56 -0
- package/skills/browser/SKILL.md +204 -0
- package/src/agent/index.ts +35 -0
- package/src/application/browser-service.ts +570 -0
- package/src/domain/types.ts +324 -0
- package/src/index.ts +156 -0
- package/src/infrastructure/agent-browser-adapter.ts +654 -0
- package/src/infrastructure/hooks-integration.ts +170 -0
- package/src/infrastructure/memory-integration.ts +449 -0
- package/src/infrastructure/reasoningbank-adapter.ts +282 -0
- package/src/infrastructure/security-integration.ts +528 -0
- package/src/infrastructure/workflow-templates.ts +479 -0
- package/src/mcp-tools/browser-tools.ts +1210 -0
- package/src/mcp-tools/index.ts +6 -0
- package/src/skill/index.ts +24 -0
- package/tests/agent-browser-adapter.test.ts +328 -0
- package/tests/browser-service.test.ts +137 -0
- package/tests/e2e/browser-e2e.test.ts +175 -0
- package/tests/memory-integration.test.ts +277 -0
- package/tests/reasoningbank-adapter.test.ts +219 -0
- package/tests/security-integration.test.ts +194 -0
- package/tests/workflow-templates.test.ts +231 -0
- package/tmp.json +0 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
# @claude-flow/browser
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@claude-flow/browser)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](./tests)
|
|
9
|
+
|
|
10
|
+
**AI-Optimized Browser Automation for Claude-Flow Swarms**
|
|
11
|
+
|
|
12
|
+
*Integrate [agent-browser](https://github.com/AugmentCode/agent-browser) with claude-flow for intelligent web automation, trajectory learning, security scanning, and multi-agent browser coordination.*
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Overview
|
|
19
|
+
|
|
20
|
+
`@claude-flow/browser` provides a comprehensive browser automation layer for AI agents, combining Vercel Labs' `agent-browser` CLI with claude-flow's learning, memory, and security capabilities. It enables agents to navigate websites, fill forms, extract data, and learn from successful interaction patterns.
|
|
21
|
+
|
|
22
|
+
### Architecture
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
Agent Request → Security Scan → Browser Adapter → agent-browser CLI → Playwright
|
|
26
|
+
↓ ↓
|
|
27
|
+
URL/PII Check Element Refs (@e1, @e2)
|
|
28
|
+
↓ ↓
|
|
29
|
+
Memory Store ← Trajectory ← Snapshot ← AI-Optimized DOM
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Key Features
|
|
33
|
+
|
|
34
|
+
🌐 **59 MCP Browser Tools** - Complete browser automation via MCP protocol with element refs, snapshots, forms, navigation, and JavaScript execution.
|
|
35
|
+
|
|
36
|
+
🔒 **Security-First Design** - Built-in URL validation, phishing detection, PII scanning, XSS/SQL injection prevention, and domain blocking.
|
|
37
|
+
|
|
38
|
+
🧠 **Trajectory Learning** - Records browser interactions for ReasoningBank/SONA learning. Successful patterns are stored and reused.
|
|
39
|
+
|
|
40
|
+
📊 **AI-Optimized Snapshots** - 93% context reduction using element refs (`@e1`, `@e2`) instead of full CSS selectors.
|
|
41
|
+
|
|
42
|
+
🐝 **Swarm Coordination** - Multi-session browser coordination for parallel scraping, testing, and validation tasks.
|
|
43
|
+
|
|
44
|
+
📋 **9 Workflow Templates** - Pre-built automation patterns for login, OAuth, scraping, form submission, and monitoring.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Install the package
|
|
52
|
+
npm install @claude-flow/browser
|
|
53
|
+
|
|
54
|
+
# Peer dependency (if not already installed)
|
|
55
|
+
npm install @claude-flow/cli@^3.0.0-alpha
|
|
56
|
+
|
|
57
|
+
# agent-browser CLI (required)
|
|
58
|
+
npm install -g agent-browser
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Requirements
|
|
62
|
+
|
|
63
|
+
- Node.js 18+
|
|
64
|
+
- `agent-browser` CLI installed globally
|
|
65
|
+
- Playwright browsers (installed automatically by agent-browser)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
|
|
71
|
+
### Basic Usage
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { createBrowserService, browserTools } from '@claude-flow/browser';
|
|
75
|
+
|
|
76
|
+
// Create a browser service with security and memory enabled
|
|
77
|
+
const browser = createBrowserService({
|
|
78
|
+
sessionId: 'my-session',
|
|
79
|
+
enableSecurity: true, // URL validation, PII detection
|
|
80
|
+
enableMemory: true, // Trajectory storage for learning
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Start tracking for learning
|
|
84
|
+
const trajectoryId = browser.startTrajectory('Login to dashboard');
|
|
85
|
+
|
|
86
|
+
// Navigate (automatically security-scanned)
|
|
87
|
+
await browser.open('https://example.com/login');
|
|
88
|
+
|
|
89
|
+
// Get AI-optimized snapshot with element refs
|
|
90
|
+
const snapshot = await browser.snapshot({ interactive: true });
|
|
91
|
+
// Returns: { refs: { '@e1': {role: 'textbox', name: 'Email'}, '@e2': ... } }
|
|
92
|
+
|
|
93
|
+
// Fill form using refs (93% less context than CSS selectors)
|
|
94
|
+
await browser.fill('@e1', 'user@example.com');
|
|
95
|
+
await browser.fill('@e2', 'password');
|
|
96
|
+
await browser.click('@e3'); // Submit button
|
|
97
|
+
|
|
98
|
+
// End trajectory and store for learning
|
|
99
|
+
const trajectory = await browser.endTrajectory(true, 'Login successful');
|
|
100
|
+
|
|
101
|
+
// Close browser
|
|
102
|
+
await browser.close();
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### MCP Integration
|
|
106
|
+
|
|
107
|
+
Register browser tools with claude-flow's MCP server:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { browserTools } from '@claude-flow/browser';
|
|
111
|
+
|
|
112
|
+
// browserTools contains 59 MCP-compatible tools
|
|
113
|
+
// Register with your MCP server
|
|
114
|
+
mcpServer.registerTools(browserTools);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Available MCP tools:
|
|
118
|
+
- `browser/open` - Navigate to URL
|
|
119
|
+
- `browser/snapshot` - Get AI-optimized accessibility tree
|
|
120
|
+
- `browser/click` - Click element by ref or selector
|
|
121
|
+
- `browser/fill` - Fill input field
|
|
122
|
+
- `browser/type` - Type text with keyboard events
|
|
123
|
+
- `browser/screenshot` - Capture page screenshot
|
|
124
|
+
- `browser/wait` - Wait for element/condition
|
|
125
|
+
- `browser/eval` - Execute JavaScript
|
|
126
|
+
- And 51 more...
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
<details>
|
|
131
|
+
<summary><strong>🎯 Core Concepts</strong></summary>
|
|
132
|
+
|
|
133
|
+
### Element Refs (`@e1`, `@e2`, etc.)
|
|
134
|
+
|
|
135
|
+
agent-browser generates AI-optimized element references that reduce context by 93%:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Traditional (verbose)
|
|
139
|
+
await page.click('body > div.container > form#login > button[type="submit"].btn.btn-primary');
|
|
140
|
+
|
|
141
|
+
// With element refs (compact)
|
|
142
|
+
await browser.click('@e3');
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Refs are generated from accessibility tree snapshots and map to interactive elements.
|
|
146
|
+
|
|
147
|
+
### Trajectory Tracking
|
|
148
|
+
|
|
149
|
+
Every browser session can record a trajectory for learning:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// Start tracking
|
|
153
|
+
const id = browser.startTrajectory('Complete checkout flow');
|
|
154
|
+
|
|
155
|
+
// All actions are recorded: open, click, fill, type, etc.
|
|
156
|
+
await browser.open('https://shop.example.com/cart');
|
|
157
|
+
await browser.click('@e1'); // Checkout button
|
|
158
|
+
await browser.fill('@e2', '4111111111111111'); // Card number
|
|
159
|
+
// ...
|
|
160
|
+
|
|
161
|
+
// End with verdict
|
|
162
|
+
const trajectory = await browser.endTrajectory(true, 'Checkout completed successfully');
|
|
163
|
+
|
|
164
|
+
// Trajectory contains:
|
|
165
|
+
// - goal: 'Complete checkout flow'
|
|
166
|
+
// - steps: [{action: 'open', input: {...}, result: {...}, snapshot: {...}}, ...]
|
|
167
|
+
// - success: true
|
|
168
|
+
// - verdict: 'Checkout completed successfully'
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Trajectories are automatically stored in memory and used by ReasoningBank for pattern learning.
|
|
172
|
+
|
|
173
|
+
### Security Scanning
|
|
174
|
+
|
|
175
|
+
All URLs are scanned before navigation:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Automatic scanning (enabled by default)
|
|
179
|
+
const result = await browser.open('http://suspicious-login.xyz');
|
|
180
|
+
// Returns: { success: false, error: 'Security scan failed: phishing detected' }
|
|
181
|
+
|
|
182
|
+
// Manual scanning
|
|
183
|
+
const scanResult = await browser.scanUrl('https://example.com');
|
|
184
|
+
// Returns: { safe: true, score: 1.0, threats: [], pii: [] }
|
|
185
|
+
|
|
186
|
+
// PII detection in form values
|
|
187
|
+
const piiResult = browser.scanForPII('SSN: 123-45-6789');
|
|
188
|
+
// Returns: { pii: [{type: 'ssn', masked: '***-**-6789', confidence: 0.95}] }
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
</details>
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
<details>
|
|
196
|
+
<summary><strong>🔌 Integrations</strong></summary>
|
|
197
|
+
|
|
198
|
+
### Memory Integration
|
|
199
|
+
|
|
200
|
+
Store and search browser patterns using HNSW-indexed memory:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { createMemoryManager } from '@claude-flow/browser';
|
|
204
|
+
|
|
205
|
+
const memory = createMemoryManager('session-1');
|
|
206
|
+
|
|
207
|
+
// Store a pattern
|
|
208
|
+
await memory.storePattern('login-github', 'Login to GitHub', [
|
|
209
|
+
{ action: 'fill', selector: '#login_field', value: '${username}' },
|
|
210
|
+
{ action: 'fill', selector: '#password', value: '${password}' },
|
|
211
|
+
{ action: 'click', selector: '[type="submit"]' },
|
|
212
|
+
], true);
|
|
213
|
+
|
|
214
|
+
// Find similar patterns (semantic search)
|
|
215
|
+
const similar = await memory.findSimilarTrajectories('Sign in to GitHub');
|
|
216
|
+
|
|
217
|
+
// Get session statistics
|
|
218
|
+
const stats = await memory.getSessionStats();
|
|
219
|
+
// { trajectories: 5, patterns: 12, snapshots: 23, errors: 1, successRate: 0.83 }
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Security Integration
|
|
223
|
+
|
|
224
|
+
Comprehensive threat detection:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
import { getSecurityScanner, isUrlSafe, containsPII } from '@claude-flow/browser';
|
|
228
|
+
|
|
229
|
+
const scanner = getSecurityScanner({
|
|
230
|
+
requireHttps: true,
|
|
231
|
+
blockedDomains: ['bit.ly', 'tinyurl.com'],
|
|
232
|
+
allowedDomains: ['github.com', 'google.com'],
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// URL scanning
|
|
236
|
+
const urlResult = await scanner.scanUrl('https://paypa1-secure.xyz/login');
|
|
237
|
+
// Detects: phishing (lookalike domain), suspicious TLD
|
|
238
|
+
|
|
239
|
+
// Content scanning
|
|
240
|
+
const contentResult = scanner.scanContent('Email: test@example.com, Card: 4111-1111-1111-1111');
|
|
241
|
+
// Detects: email, credit-card with masking
|
|
242
|
+
|
|
243
|
+
// Input validation (XSS, SQL injection)
|
|
244
|
+
const inputResult = scanner.validateInput('<script>alert(1)</script>', 'comment');
|
|
245
|
+
// Detects: xss threat
|
|
246
|
+
|
|
247
|
+
// Quick checks
|
|
248
|
+
await isUrlSafe('https://example.com'); // true
|
|
249
|
+
containsPII('My SSN is 123-45-6789'); // true
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Workflow Templates
|
|
253
|
+
|
|
254
|
+
Pre-built automation workflows:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { listWorkflows, getWorkflow, getWorkflowManager } from '@claude-flow/browser';
|
|
258
|
+
|
|
259
|
+
// List all templates
|
|
260
|
+
const workflows = listWorkflows();
|
|
261
|
+
// ['login-basic', 'login-oauth', 'logout', 'scrape-table', 'scrape-list',
|
|
262
|
+
// 'contact-form', 'visual-regression', 'smoke-test', 'uptime-check']
|
|
263
|
+
|
|
264
|
+
// Get specific template
|
|
265
|
+
const loginTemplate = getWorkflow('login-basic');
|
|
266
|
+
// {
|
|
267
|
+
// id: 'login-basic',
|
|
268
|
+
// name: 'Basic Login',
|
|
269
|
+
// category: 'authentication',
|
|
270
|
+
// variables: [{name: 'url', required: true}, {name: 'username'}, ...],
|
|
271
|
+
// steps: [{action: 'open', target: '${url}'}, {action: 'fill', ...}, ...]
|
|
272
|
+
// }
|
|
273
|
+
|
|
274
|
+
// Validate variables
|
|
275
|
+
const manager = getWorkflowManager();
|
|
276
|
+
const validation = manager.validateVariables('login-basic', {
|
|
277
|
+
url: 'https://example.com/login',
|
|
278
|
+
username: 'user',
|
|
279
|
+
password: 'pass',
|
|
280
|
+
});
|
|
281
|
+
// { valid: true, errors: [] }
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### Available Templates
|
|
285
|
+
|
|
286
|
+
| Template | Category | Description |
|
|
287
|
+
|----------|----------|-------------|
|
|
288
|
+
| `login-basic` | authentication | Standard username/password login |
|
|
289
|
+
| `login-oauth` | authentication | OAuth/SSO login flow (Google, GitHub) |
|
|
290
|
+
| `logout` | authentication | Standard logout flow |
|
|
291
|
+
| `scrape-table` | data-extraction | Extract data from HTML tables |
|
|
292
|
+
| `scrape-list` | data-extraction | Extract items from repeated elements |
|
|
293
|
+
| `contact-form` | form-submission | Fill and submit contact forms |
|
|
294
|
+
| `visual-regression` | testing | Screenshot-based visual testing |
|
|
295
|
+
| `smoke-test` | testing | Basic page load verification |
|
|
296
|
+
| `uptime-check` | monitoring | Page availability monitoring |
|
|
297
|
+
|
|
298
|
+
### Hooks Integration
|
|
299
|
+
|
|
300
|
+
Pre-browse and post-browse hooks for learning:
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
import { preBrowseHook, postBrowseHook, browserHooks } from '@claude-flow/browser';
|
|
304
|
+
|
|
305
|
+
// Before browsing - get recommendations
|
|
306
|
+
const preResult = await preBrowseHook({
|
|
307
|
+
goal: 'Login to admin panel',
|
|
308
|
+
url: 'https://example.com/admin',
|
|
309
|
+
});
|
|
310
|
+
// {
|
|
311
|
+
// recommendedSteps: [{action: 'fill', selector: '#username'}, ...],
|
|
312
|
+
// similarPatterns: 3,
|
|
313
|
+
// suggestedModel: 'sonnet',
|
|
314
|
+
// estimatedDuration: 5000,
|
|
315
|
+
// warnings: ['URL is not HTTPS - authentication data may be at risk']
|
|
316
|
+
// }
|
|
317
|
+
|
|
318
|
+
// After browsing - record outcome
|
|
319
|
+
const postResult = await postBrowseHook({
|
|
320
|
+
trajectoryId: 'traj-123',
|
|
321
|
+
success: true,
|
|
322
|
+
verdict: 'Login successful',
|
|
323
|
+
duration: 4500,
|
|
324
|
+
stepsCompleted: 5,
|
|
325
|
+
});
|
|
326
|
+
// { patternStored: true, patternId: 'pattern-traj-123', learnedFrom: true }
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
</details>
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
<details>
|
|
334
|
+
<summary><strong>🐝 Swarm Coordination</strong></summary>
|
|
335
|
+
|
|
336
|
+
Coordinate multiple browser sessions for parallel tasks:
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
import { createBrowserSwarm } from '@claude-flow/browser';
|
|
340
|
+
|
|
341
|
+
// Create a swarm coordinator
|
|
342
|
+
const swarm = createBrowserSwarm({
|
|
343
|
+
topology: 'hierarchical',
|
|
344
|
+
maxSessions: 5,
|
|
345
|
+
sessionPrefix: 'scraper',
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Spawn browser agents with specific roles
|
|
349
|
+
const navigator = await swarm.spawnAgent('navigator');
|
|
350
|
+
const scraper1 = await swarm.spawnAgent('scraper');
|
|
351
|
+
const scraper2 = await swarm.spawnAgent('scraper');
|
|
352
|
+
const validator = await swarm.spawnAgent('validator');
|
|
353
|
+
|
|
354
|
+
// Share data between agents
|
|
355
|
+
swarm.shareData('targetUrls', ['https://example.com/page1', 'https://example.com/page2']);
|
|
356
|
+
|
|
357
|
+
// Each agent can access shared data
|
|
358
|
+
const urls = swarm.getSharedData<string[]>('targetUrls');
|
|
359
|
+
|
|
360
|
+
// Get swarm stats
|
|
361
|
+
const stats = swarm.getStats();
|
|
362
|
+
// { activeSessions: 4, maxSessions: 5, topology: 'hierarchical' }
|
|
363
|
+
|
|
364
|
+
// Close all sessions
|
|
365
|
+
await swarm.closeAll();
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Agent Roles
|
|
369
|
+
|
|
370
|
+
| Role | Capabilities | Use Case |
|
|
371
|
+
|------|-------------|----------|
|
|
372
|
+
| `navigator` | Navigation, authentication, session management | Login, navigate to pages |
|
|
373
|
+
| `scraper` | Snapshots, extraction, pagination | Data collection |
|
|
374
|
+
| `validator` | Assertions, state checks, screenshots | Verify results |
|
|
375
|
+
| `tester` | Forms, interactions, assertions | E2E testing |
|
|
376
|
+
| `monitor` | Network, console, errors | Performance monitoring |
|
|
377
|
+
|
|
378
|
+
</details>
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
<details>
|
|
383
|
+
<summary><strong>📚 API Reference</strong></summary>
|
|
384
|
+
|
|
385
|
+
### BrowserService
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
interface BrowserServiceConfig {
|
|
389
|
+
sessionId?: string; // Browser session ID
|
|
390
|
+
enableMemory?: boolean; // Enable trajectory storage (default: true)
|
|
391
|
+
enableSecurity?: boolean; // Enable URL/PII scanning (default: true)
|
|
392
|
+
requireHttps?: boolean; // Require HTTPS URLs
|
|
393
|
+
blockedDomains?: string[]; // Block specific domains
|
|
394
|
+
allowedDomains?: string[]; // Allow only specific domains
|
|
395
|
+
defaultTimeout?: number; // Default operation timeout
|
|
396
|
+
headless?: boolean; // Run headless (default: true)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
class BrowserService {
|
|
400
|
+
// Trajectory tracking
|
|
401
|
+
startTrajectory(goal: string): string;
|
|
402
|
+
endTrajectory(success: boolean, verdict?: string): Promise<BrowserTrajectory | null>;
|
|
403
|
+
getCurrentTrajectory(): TrajectoryTracker | null;
|
|
404
|
+
|
|
405
|
+
// Navigation
|
|
406
|
+
open(url: string, options?: OpenOptions): Promise<ActionResult>;
|
|
407
|
+
close(): Promise<ActionResult>;
|
|
408
|
+
|
|
409
|
+
// Snapshots
|
|
410
|
+
snapshot(options?: SnapshotOptions): Promise<ActionResult<Snapshot>>;
|
|
411
|
+
getLatestSnapshot(): Snapshot | null;
|
|
412
|
+
|
|
413
|
+
// Interactions
|
|
414
|
+
click(target: string, options?: ClickOptions): Promise<ActionResult>;
|
|
415
|
+
fill(target: string, value: string, options?: FillOptions): Promise<ActionResult>;
|
|
416
|
+
type(target: string, text: string, options?: TypeOptions): Promise<ActionResult>;
|
|
417
|
+
press(key: string, delay?: number): Promise<ActionResult>;
|
|
418
|
+
|
|
419
|
+
// Waiting
|
|
420
|
+
wait(options: WaitOptions): Promise<ActionResult>;
|
|
421
|
+
|
|
422
|
+
// Data extraction
|
|
423
|
+
getText(target: string): Promise<ActionResult<string>>;
|
|
424
|
+
eval<T>(script: string): Promise<ActionResult<T>>;
|
|
425
|
+
extractData(refs: string[]): Promise<Record<string, string>>;
|
|
426
|
+
|
|
427
|
+
// Screenshots
|
|
428
|
+
screenshot(options?: ScreenshotOptions): Promise<ActionResult<string>>;
|
|
429
|
+
|
|
430
|
+
// Security
|
|
431
|
+
scanUrl(url: string): Promise<ThreatScanResult>;
|
|
432
|
+
scanForPII(content: string, context?: string): ThreatScanResult;
|
|
433
|
+
|
|
434
|
+
// Memory
|
|
435
|
+
findSimilarTrajectories(goal: string, topK?: number): Promise<BrowserTrajectory[]>;
|
|
436
|
+
getMemoryStats(): Promise<MemoryStats | null>;
|
|
437
|
+
|
|
438
|
+
// High-level operations
|
|
439
|
+
submitForm(fields: Array<{target: string, value: string}>, submitButton: string): Promise<ActionResult>;
|
|
440
|
+
navigateAndWait(url: string, selector: string, timeout?: number): Promise<ActionResult>;
|
|
441
|
+
authenticateWithHeaders(url: string, headers: Record<string, string>): Promise<ActionResult>;
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Security Scanner
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
interface SecurityConfig {
|
|
449
|
+
enableUrlValidation: boolean;
|
|
450
|
+
enablePIIDetection: boolean;
|
|
451
|
+
enableThreatScanning: boolean;
|
|
452
|
+
blockedDomains: string[];
|
|
453
|
+
allowedDomains: string[];
|
|
454
|
+
maxRedirects: number;
|
|
455
|
+
requireHttps: boolean;
|
|
456
|
+
piiMaskingEnabled: boolean;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
class BrowserSecurityScanner {
|
|
460
|
+
scanUrl(url: string): Promise<ThreatScanResult>;
|
|
461
|
+
scanContent(content: string, context?: string): ThreatScanResult;
|
|
462
|
+
validateInput(value: string, fieldType: string): ThreatScanResult;
|
|
463
|
+
sanitizeInput(value: string): string;
|
|
464
|
+
maskPII(value: string, type: PIIType): string;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
interface ThreatScanResult {
|
|
468
|
+
safe: boolean;
|
|
469
|
+
threats: Threat[];
|
|
470
|
+
pii: PIIMatch[];
|
|
471
|
+
score: number; // 0-1 (1 = safe)
|
|
472
|
+
scanDuration: number;
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Memory Manager
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
class BrowserMemoryManager {
|
|
480
|
+
storeTrajectory(trajectory: BrowserTrajectory): Promise<void>;
|
|
481
|
+
storePattern(id: string, goal: string, steps: PatternStep[], success: boolean): Promise<void>;
|
|
482
|
+
storeSnapshot(id: string, snapshot: Snapshot): Promise<void>;
|
|
483
|
+
storeError(id: string, error: Error, context: object): Promise<void>;
|
|
484
|
+
findSimilarTrajectories(goal: string, topK?: number): Promise<BrowserTrajectory[]>;
|
|
485
|
+
findPatterns(goal: string, successfulOnly?: boolean): Promise<MemorySearchResult[]>;
|
|
486
|
+
getSessionStats(): Promise<SessionStats>;
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
</details>
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
<details>
|
|
495
|
+
<summary><strong>🧪 Testing</strong></summary>
|
|
496
|
+
|
|
497
|
+
### Unit Tests
|
|
498
|
+
|
|
499
|
+
```bash
|
|
500
|
+
# Run all tests
|
|
501
|
+
npm test
|
|
502
|
+
|
|
503
|
+
# Run with watch mode
|
|
504
|
+
npm run test:watch
|
|
505
|
+
|
|
506
|
+
# Run specific test file
|
|
507
|
+
npm test -- tests/security-integration.test.ts
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### E2E Tests (Docker)
|
|
511
|
+
|
|
512
|
+
```bash
|
|
513
|
+
# Navigate to docker directory
|
|
514
|
+
cd docker
|
|
515
|
+
|
|
516
|
+
# Run E2E tests with browser
|
|
517
|
+
docker compose --profile e2e up browser-e2e
|
|
518
|
+
|
|
519
|
+
# Run in debug mode (keeps container running)
|
|
520
|
+
docker compose --profile debug up browser-debug
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### Test Coverage
|
|
524
|
+
|
|
525
|
+
| Component | Tests | Status |
|
|
526
|
+
|-----------|-------|--------|
|
|
527
|
+
| BrowserService | 18 | ✅ |
|
|
528
|
+
| AgentBrowserAdapter | 27 | ✅ |
|
|
529
|
+
| SecurityScanner | 30 | ✅ |
|
|
530
|
+
| MemoryManager | 16 | ✅ |
|
|
531
|
+
| WorkflowTemplates | 25 | ✅ |
|
|
532
|
+
| ReasoningBankAdapter | 12 | ✅ |
|
|
533
|
+
| **Total** | **128** | ✅ |
|
|
534
|
+
|
|
535
|
+
</details>
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
<details>
|
|
540
|
+
<summary><strong>⚙️ Configuration</strong></summary>
|
|
541
|
+
|
|
542
|
+
### TypeScript
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
// tsconfig.json
|
|
546
|
+
{
|
|
547
|
+
"compilerOptions": {
|
|
548
|
+
"target": "ES2022",
|
|
549
|
+
"module": "NodeNext",
|
|
550
|
+
"moduleResolution": "NodeNext",
|
|
551
|
+
"esModuleInterop": true,
|
|
552
|
+
"strict": true
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### Environment Variables
|
|
558
|
+
|
|
559
|
+
```bash
|
|
560
|
+
# Browser settings
|
|
561
|
+
BROWSER_HEADLESS=true
|
|
562
|
+
BROWSER_DEFAULT_TIMEOUT=30000
|
|
563
|
+
|
|
564
|
+
# Security settings
|
|
565
|
+
BROWSER_REQUIRE_HTTPS=true
|
|
566
|
+
BROWSER_BLOCKED_DOMAINS=bit.ly,tinyurl.com
|
|
567
|
+
|
|
568
|
+
# Memory settings
|
|
569
|
+
BROWSER_ENABLE_MEMORY=true
|
|
570
|
+
BROWSER_MEMORY_NAMESPACE=browser
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
</details>
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
<details>
|
|
578
|
+
<summary><strong>💡 Examples</strong></summary>
|
|
579
|
+
|
|
580
|
+
### Login and Extract Data
|
|
581
|
+
|
|
582
|
+
```typescript
|
|
583
|
+
import { createBrowserService } from '@claude-flow/browser';
|
|
584
|
+
|
|
585
|
+
const browser = createBrowserService();
|
|
586
|
+
|
|
587
|
+
async function loginAndExtract() {
|
|
588
|
+
browser.startTrajectory('Login and extract user data');
|
|
589
|
+
|
|
590
|
+
// Login
|
|
591
|
+
await browser.open('https://app.example.com/login');
|
|
592
|
+
await browser.fill('#email', 'user@example.com');
|
|
593
|
+
await browser.fill('#password', 'secretpassword');
|
|
594
|
+
await browser.click('#login-button');
|
|
595
|
+
|
|
596
|
+
// Wait for dashboard
|
|
597
|
+
await browser.wait({ selector: '.dashboard' });
|
|
598
|
+
|
|
599
|
+
// Get snapshot and extract data
|
|
600
|
+
const snapshot = await browser.snapshot({ interactive: true });
|
|
601
|
+
const data = await browser.extractData(['@e1', '@e2', '@e3']);
|
|
602
|
+
|
|
603
|
+
await browser.endTrajectory(true, 'Data extracted successfully');
|
|
604
|
+
await browser.close();
|
|
605
|
+
|
|
606
|
+
return data;
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
### Parallel Scraping
|
|
611
|
+
|
|
612
|
+
```typescript
|
|
613
|
+
import { createBrowserSwarm } from '@claude-flow/browser';
|
|
614
|
+
|
|
615
|
+
async function parallelScrape(urls: string[]) {
|
|
616
|
+
const swarm = createBrowserSwarm({ maxSessions: 5 });
|
|
617
|
+
const results: any[] = [];
|
|
618
|
+
|
|
619
|
+
// Spawn scrapers for each URL
|
|
620
|
+
const promises = urls.map(async (url) => {
|
|
621
|
+
const scraper = await swarm.spawnAgent('scraper');
|
|
622
|
+
await scraper.open(url);
|
|
623
|
+
const snapshot = await scraper.snapshot();
|
|
624
|
+
const text = await scraper.getText('main');
|
|
625
|
+
return { url, content: text.data };
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
const data = await Promise.all(promises);
|
|
629
|
+
await swarm.closeAll();
|
|
630
|
+
|
|
631
|
+
return data;
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### Security-First Automation
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
import { createBrowserService, getSecurityScanner } from '@claude-flow/browser';
|
|
639
|
+
|
|
640
|
+
async function secureAutomation(url: string, formData: Record<string, string>) {
|
|
641
|
+
const scanner = getSecurityScanner({ requireHttps: true });
|
|
642
|
+
|
|
643
|
+
// Pre-scan URL
|
|
644
|
+
const urlScan = await scanner.scanUrl(url);
|
|
645
|
+
if (!urlScan.safe) {
|
|
646
|
+
throw new Error(`Unsafe URL: ${urlScan.threats.map(t => t.description).join(', ')}`);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// Scan form data for sensitive info
|
|
650
|
+
for (const [field, value] of Object.entries(formData)) {
|
|
651
|
+
const piiScan = scanner.scanContent(value, field);
|
|
652
|
+
if (piiScan.pii.length > 0) {
|
|
653
|
+
console.log(`Warning: PII detected in ${field}:`, piiScan.pii.map(p => p.type));
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Proceed with automation
|
|
658
|
+
const browser = createBrowserService({ enableSecurity: true });
|
|
659
|
+
await browser.open(url);
|
|
660
|
+
|
|
661
|
+
for (const [selector, value] of Object.entries(formData)) {
|
|
662
|
+
await browser.fill(selector, value);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
await browser.close();
|
|
666
|
+
}
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
</details>
|
|
670
|
+
|
|
671
|
+
---
|
|
672
|
+
|
|
673
|
+
<details>
|
|
674
|
+
<summary><strong>🔧 Troubleshooting</strong></summary>
|
|
675
|
+
|
|
676
|
+
### Common Issues
|
|
677
|
+
|
|
678
|
+
**agent-browser not found**
|
|
679
|
+
```bash
|
|
680
|
+
npm install -g agent-browser
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
**Playwright browsers missing**
|
|
684
|
+
```bash
|
|
685
|
+
npx playwright install
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
**Security scan blocking legitimate URLs**
|
|
689
|
+
```typescript
|
|
690
|
+
const browser = createBrowserService({
|
|
691
|
+
allowedDomains: ['trusted-domain.com'],
|
|
692
|
+
// Or disable for specific navigations
|
|
693
|
+
});
|
|
694
|
+
await browser.open('http://trusted-domain.com', { skipSecurityCheck: true });
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
**Memory not persisting**
|
|
698
|
+
```typescript
|
|
699
|
+
// Ensure endTrajectory is called
|
|
700
|
+
const trajectory = await browser.endTrajectory(true); // Must await!
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
</details>
|
|
704
|
+
|
|
705
|
+
---
|
|
706
|
+
|
|
707
|
+
## Contributing
|
|
708
|
+
|
|
709
|
+
See [CONTRIBUTING.md](../../CONTRIBUTING.md) in the root repository.
|
|
710
|
+
|
|
711
|
+
## License
|
|
712
|
+
|
|
713
|
+
MIT License - see [LICENSE](../../LICENSE) for details.
|
|
714
|
+
|
|
715
|
+
## Links
|
|
716
|
+
|
|
717
|
+
- [GitHub Repository](https://github.com/ruvnet/claude-flow)
|
|
718
|
+
- [agent-browser](https://github.com/AugmentCode/agent-browser)
|
|
719
|
+
- [Claude-Flow Documentation](https://github.com/ruvnet/claude-flow#readme)
|
|
720
|
+
- [MCP Protocol](https://modelcontextprotocol.io)
|
|
721
|
+
|
|
722
|
+
---
|
|
723
|
+
|
|
724
|
+
<div align="center">
|
|
725
|
+
|
|
726
|
+
**Part of the [Claude-Flow](https://github.com/ruvnet/claude-flow) ecosystem**
|
|
727
|
+
|
|
728
|
+
Made with ❤️ by [ruvnet](https://github.com/ruvnet)
|
|
729
|
+
|
|
730
|
+
</div>
|