brave-real-browser-mcp-server 2.37.0 → 2.37.2
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 +74 -185
- package/data/.gitkeep +2 -0
- package/package.json +2 -2
- package/packages/brave-real-blocker/package.json +5 -4
- package/packages/brave-real-launcher/package.json +5 -5
- package/packages/brave-real-puppeteer-core/package.json +4 -4
- package/src/ai/action-parser.js +274 -0
- package/src/ai/core.js +378 -0
- package/src/ai/element-finder.js +466 -0
- package/src/ai/error-collector.js +498 -0
- package/src/ai/hindi-suggester.js +505 -0
- package/src/ai/index.js +82 -0
- package/src/ai/page-analyzer.js +304 -0
- package/src/ai/pattern-learner.js +561 -0
- package/src/ai/result-validator.js +666 -0
- package/src/ai/selector-healer.js +236 -0
- package/src/mcp/handlers-fixed.js +2499 -0
- package/src/mcp/handlers.js +2816 -116
- package/test/esm/test.js +35 -13
- package/packages/brave-real-blocker/dist/index.d.mts +0 -2
- package/packages/brave-real-blocker/dist/index.d.ts +0 -2
- package/packages/brave-real-blocker/dist/index.js +0 -1634
- package/packages/brave-real-blocker/dist/index.js.map +0 -1
- package/packages/brave-real-blocker/dist/index.mjs +0 -1594
- package/packages/brave-real-blocker/dist/index.mjs.map +0 -1
- package/packages/brave-real-blocker/dist/singleton.d.mts +0 -190
- package/packages/brave-real-blocker/dist/singleton.d.ts +0 -190
- package/packages/brave-real-blocker/dist/singleton.js +0 -1618
- package/packages/brave-real-blocker/dist/singleton.js.map +0 -1
- package/packages/brave-real-blocker/dist/singleton.mjs +0 -1584
- package/packages/brave-real-blocker/dist/singleton.mjs.map +0 -1
- package/packages/brave-real-launcher/dist/blocker-integration.d.ts +0 -53
- package/packages/brave-real-launcher/dist/blocker-integration.js +0 -165
- package/packages/brave-real-launcher/dist/blocker-integration.mjs +0 -153
- package/packages/brave-real-launcher/dist/brave-finder.d.ts +0 -34
- package/packages/brave-real-launcher/dist/brave-finder.js +0 -477
- package/packages/brave-real-launcher/dist/brave-finder.mjs +0 -465
- package/packages/brave-real-launcher/dist/brave-installer.d.ts +0 -57
- package/packages/brave-real-launcher/dist/brave-installer.js +0 -373
- package/packages/brave-real-launcher/dist/brave-installer.mjs +0 -334
- package/packages/brave-real-launcher/dist/brave-launcher.d.ts +0 -117
- package/packages/brave-real-launcher/dist/brave-launcher.js +0 -715
- package/packages/brave-real-launcher/dist/brave-launcher.mjs +0 -672
- package/packages/brave-real-launcher/dist/chrome-launcher.d.ts +0 -96
- package/packages/brave-real-launcher/dist/chrome-launcher.js +0 -493
- package/packages/brave-real-launcher/dist/chrome-launcher.mjs +0 -452
- package/packages/brave-real-launcher/dist/chrome-version.d.ts +0 -75
- package/packages/brave-real-launcher/dist/chrome-version.js +0 -163
- package/packages/brave-real-launcher/dist/chrome-version.mjs +0 -154
- package/packages/brave-real-launcher/dist/errors.d.ts +0 -104
- package/packages/brave-real-launcher/dist/errors.js +0 -252
- package/packages/brave-real-launcher/dist/errors.mjs +0 -233
- package/packages/brave-real-launcher/dist/flags.d.ts +0 -5
- package/packages/brave-real-launcher/dist/flags.js +0 -121
- package/packages/brave-real-launcher/dist/flags.mjs +0 -119
- package/packages/brave-real-launcher/dist/index.d.ts +0 -14
- package/packages/brave-real-launcher/dist/index.js +0 -90
- package/packages/brave-real-launcher/dist/index.mjs +0 -22
- package/packages/brave-real-launcher/dist/logger.d.ts +0 -31
- package/packages/brave-real-launcher/dist/logger.js +0 -75
- package/packages/brave-real-launcher/dist/logger.mjs +0 -73
- package/packages/brave-real-launcher/dist/random-port.d.ts +0 -4
- package/packages/brave-real-launcher/dist/random-port.js +0 -24
- package/packages/brave-real-launcher/dist/random-port.mjs +0 -22
- package/packages/brave-real-launcher/dist/stealth-utils.d.ts +0 -209
- package/packages/brave-real-launcher/dist/stealth-utils.js +0 -837
- package/packages/brave-real-launcher/dist/stealth-utils.mjs +0 -827
- package/packages/brave-real-launcher/dist/utils.d.ts +0 -61
- package/packages/brave-real-launcher/dist/utils.js +0 -253
- package/packages/brave-real-launcher/dist/utils.mjs +0 -233
- package/packages/brave-real-launcher/dist/xvfb-support.d.ts +0 -58
- package/packages/brave-real-launcher/dist/xvfb-support.js +0 -226
- package/packages/brave-real-launcher/dist/xvfb-support.mjs +0 -187
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ A production-ready MCP (Model Context Protocol) server that combines Puppeteer w
|
|
|
16
16
|
|---------|-------------|
|
|
17
17
|
| **MCP Server** | Model Context Protocol compatible server with 28 tools |
|
|
18
18
|
| **LSP Server** | Language Server Protocol for IDE code intelligence |
|
|
19
|
+
| **AI Core** | Automatic AI enhancement for all tools (auto-healing, smart retry) |
|
|
19
20
|
| Brave Browser | Uses Brave instead of Chromium for better privacy |
|
|
20
21
|
| 50+ Stealth Features | Passes all major bot detectors |
|
|
21
22
|
| Built-in Ad Blocker | uBlock Origin filters with auto-update |
|
|
@@ -152,40 +153,81 @@ npm run lsp
|
|
|
152
153
|
| **Simulation** | Workflow simulation in IDE |
|
|
153
154
|
| **Multi-language** | English & Hindi support |
|
|
154
155
|
|
|
155
|
-
|
|
156
|
+
## AI Core (Automatic Enhancement)
|
|
157
|
+
|
|
158
|
+
All 28 tools are automatically enhanced with AI capabilities. No configuration needed - AI features work transparently.
|
|
159
|
+
|
|
160
|
+
### How It Works
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
AI Agent calls any tool (e.g., click, type, find_element)
|
|
164
|
+
│
|
|
165
|
+
▼
|
|
166
|
+
┌───────────────────┐
|
|
167
|
+
│ AI Core Check │
|
|
168
|
+
│ (Lazy initialize) │
|
|
169
|
+
└───────────────────┘
|
|
170
|
+
│
|
|
171
|
+
▼
|
|
172
|
+
Execute Original Tool
|
|
173
|
+
│
|
|
174
|
+
┌───────┴───────┐
|
|
175
|
+
│ │
|
|
176
|
+
Success Failed (selector not found)
|
|
177
|
+
│ │
|
|
178
|
+
▼ ▼
|
|
179
|
+
Return result ┌─────────────────┐
|
|
180
|
+
with _ai meta │ AI Auto-Healing │
|
|
181
|
+
│ - Find alts │
|
|
182
|
+
│ - Try healed │
|
|
183
|
+
│ - Retry op │
|
|
184
|
+
└─────────────────┘
|
|
185
|
+
│
|
|
186
|
+
▼
|
|
187
|
+
Return healed result
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### AI Features
|
|
156
191
|
|
|
157
|
-
|
|
192
|
+
| Feature | Description |
|
|
193
|
+
|---------|-------------|
|
|
194
|
+
| **Auto-Healing Selectors** | If a CSS selector fails, AI finds alternative selectors |
|
|
195
|
+
| **Smart Retry** | Failed operations are automatically retried with AI assistance |
|
|
196
|
+
| **Confidence Scoring** | AI provides confidence scores for healed selectors |
|
|
197
|
+
| **Caching** | Healed selectors are cached for performance |
|
|
198
|
+
| **Zero Configuration** | Works out of the box with all 28 tools |
|
|
199
|
+
|
|
200
|
+
### Example Response with AI Metadata
|
|
201
|
+
|
|
202
|
+
When AI heals a broken selector:
|
|
158
203
|
|
|
159
204
|
```json
|
|
160
205
|
{
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
|
|
206
|
+
"success": true,
|
|
207
|
+
"selector": "#new-login-btn",
|
|
208
|
+
"clicked": true,
|
|
209
|
+
"_ai": {
|
|
210
|
+
"enabled": true,
|
|
211
|
+
"healed": true,
|
|
212
|
+
"originalSelector": "#old-login-button",
|
|
213
|
+
"healedSelector": "#new-login-btn",
|
|
214
|
+
"duration": 245
|
|
215
|
+
}
|
|
166
216
|
}
|
|
167
217
|
```
|
|
218
|
+
### Programmatic Access
|
|
168
219
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
The LSP detects common issues:
|
|
220
|
+
For advanced usage, you can access AI features directly:
|
|
172
221
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
- Invalid selectors and URLs
|
|
176
|
-
- Missing required parameters
|
|
177
|
-
- Unclosed browser sessions
|
|
178
|
-
- Security issues (eval usage, etc.)
|
|
179
|
-
|
|
180
|
-
### Quick Fixes
|
|
222
|
+
```javascript
|
|
223
|
+
const { getAICore, aiEnhancedSelector } = require('./src/mcp/handlers');
|
|
181
224
|
|
|
182
|
-
|
|
225
|
+
// Get AI Core instance
|
|
226
|
+
const ai = getAICore();
|
|
183
227
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
- Wrap in try-catch
|
|
188
|
-
- Extract to function
|
|
228
|
+
// Use AI-enhanced selector finding
|
|
229
|
+
const { element, selector, healed } = await aiEnhancedSelector(page, '#old-selector', 'click');
|
|
230
|
+
```
|
|
189
231
|
|
|
190
232
|
---
|
|
191
233
|
|
|
@@ -197,9 +239,16 @@ Both MCP and LSP servers share the same tool definitions:
|
|
|
197
239
|
src/
|
|
198
240
|
├── shared/
|
|
199
241
|
│ └── tools.js # Single source of truth (28 tools)
|
|
242
|
+
├── ai/ # AI Core Module (Auto-enhancement)
|
|
243
|
+
│ ├── index.js # AI module exports
|
|
244
|
+
│ ├── core.js # AI Core singleton
|
|
245
|
+
│ ├── element-finder.js# Smart element finding
|
|
246
|
+
│ ├── selector-healer.js# Auto-heal selectors
|
|
247
|
+
│ ├── page-analyzer.js # Page analysis
|
|
248
|
+
│ └── action-parser.js # NL command parsing
|
|
200
249
|
├── mcp/
|
|
201
250
|
│ ├── server.js # MCP server for AI agents
|
|
202
|
-
│ └── handlers.js # Tool implementations
|
|
251
|
+
│ └── handlers.js # Tool implementations + AI integration
|
|
203
252
|
├── lsp/
|
|
204
253
|
│ ├── server.js # LSP server for IDEs
|
|
205
254
|
│ └── capabilities/ # Autocomplete, hover, diagnostics, etc.
|
|
@@ -221,21 +270,6 @@ node src/index.js lsp
|
|
|
221
270
|
# Show help
|
|
222
271
|
node src/index.js --help
|
|
223
272
|
```
|
|
224
|
-
|
|
225
|
-
### Tool Categories
|
|
226
|
-
|
|
227
|
-
| Category | Tools | Description |
|
|
228
|
-
|----------|-------|-------------|
|
|
229
|
-
| **Browser** | 3 | Browser lifecycle (init, close, cookies) |
|
|
230
|
-
| **Navigation** | 1 | Page navigation |
|
|
231
|
-
| **Interaction** | 8 | User actions (click, type, scroll, etc.) |
|
|
232
|
-
| **Extraction** | 10 | Content scraping (HTML, JSON, links, etc.) |
|
|
233
|
-
| **Network** | 3 | Network operations (recorder, download, trace) |
|
|
234
|
-
| **Analysis** | 1 | Page analysis (SEO, performance, etc.) |
|
|
235
|
-
| **Utility** | 2 | Helpers (wait, progress tracker) |
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
273
|
## Monorepo Ecosystem
|
|
240
274
|
|
|
241
275
|
```
|
|
@@ -302,53 +336,6 @@ All packages published to NPM automatically
|
|
|
302
336
|
```bash
|
|
303
337
|
npm install brave-real-browser-mcp-server
|
|
304
338
|
```
|
|
305
|
-
|
|
306
|
-
For Linux (required for headless mode):
|
|
307
|
-
```bash
|
|
308
|
-
sudo apt-get install xvfb
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
---
|
|
312
|
-
|
|
313
|
-
## Quick Start
|
|
314
|
-
|
|
315
|
-
### CommonJS
|
|
316
|
-
|
|
317
|
-
```javascript
|
|
318
|
-
const { connect } = require('brave-real-browser-mcp-server');
|
|
319
|
-
|
|
320
|
-
(async () => {
|
|
321
|
-
const { browser, page, blocker } = await connect({
|
|
322
|
-
headless: false,
|
|
323
|
-
turnstile: true, // Auto-solve Cloudflare
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
await page.goto('https://example.com');
|
|
327
|
-
|
|
328
|
-
// Human-like click with ghost-cursor
|
|
329
|
-
await page.realClick('#button');
|
|
330
|
-
|
|
331
|
-
await browser.close();
|
|
332
|
-
})();
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
### ESM
|
|
336
|
-
|
|
337
|
-
```javascript
|
|
338
|
-
import { connect } from 'brave-real-browser-mcp-server';
|
|
339
|
-
|
|
340
|
-
const { browser, page, blocker } = await connect({
|
|
341
|
-
headless: false,
|
|
342
|
-
turnstile: true,
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
await page.goto('https://example.com');
|
|
346
|
-
await page.realClick('#button');
|
|
347
|
-
await browser.close();
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
---
|
|
351
|
-
|
|
352
339
|
## Connect Options
|
|
353
340
|
|
|
354
341
|
| Option | Type | Default | Description |
|
|
@@ -403,104 +390,6 @@ const { browser, page } = await connect({
|
|
|
403
390
|
});
|
|
404
391
|
```
|
|
405
392
|
|
|
406
|
-
### Custom Brave Path
|
|
407
|
-
|
|
408
|
-
```javascript
|
|
409
|
-
const { browser, page } = await connect({
|
|
410
|
-
customConfig: {
|
|
411
|
-
bravePath: 'C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe',
|
|
412
|
-
userDataDir: './my-profile'
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
### Disable Blocker
|
|
418
|
-
|
|
419
|
-
```javascript
|
|
420
|
-
const { browser, page } = await connect({
|
|
421
|
-
enableBlocker: false, // Disable all blocking
|
|
422
|
-
});
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
### Custom Blocker Options
|
|
426
|
-
|
|
427
|
-
```javascript
|
|
428
|
-
const { browser, page, blocker } = await connect({
|
|
429
|
-
blockerOptions: {
|
|
430
|
-
enableAdBlocking: true,
|
|
431
|
-
enableStealth: true,
|
|
432
|
-
enableCosmeticFiltering: true,
|
|
433
|
-
enableRedirectBlocking: true,
|
|
434
|
-
enableScriptlets: true,
|
|
435
|
-
customFiltersPath: './my-filters.txt',
|
|
436
|
-
enableFilterAutoUpdate: true,
|
|
437
|
-
}
|
|
438
|
-
});
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
### Real Cursor (Ghost-Cursor)
|
|
442
|
-
|
|
443
|
-
Built-in ghost-cursor for human-like mouse movements:
|
|
444
|
-
|
|
445
|
-
```javascript
|
|
446
|
-
const { browser, page } = await connect();
|
|
447
|
-
|
|
448
|
-
// Human-like click
|
|
449
|
-
await page.realClick('#submit-button');
|
|
450
|
-
|
|
451
|
-
// Full cursor control
|
|
452
|
-
await page.realCursor.move('#element');
|
|
453
|
-
await page.realCursor.click('#button');
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
### Turnstile Auto-Solver
|
|
457
|
-
|
|
458
|
-
Automatically solves Cloudflare Turnstile challenges:
|
|
459
|
-
|
|
460
|
-
```javascript
|
|
461
|
-
const { browser, page } = await connect({
|
|
462
|
-
turnstile: true
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
await page.goto('https://site-with-turnstile.com');
|
|
466
|
-
// Turnstile is automatically solved!
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
### Puppeteer-Extra Plugins
|
|
470
|
-
|
|
471
|
-
```javascript
|
|
472
|
-
const clickAndWait = require('puppeteer-extra-plugin-click-and-wait')();
|
|
473
|
-
|
|
474
|
-
const { browser, page } = await connect({
|
|
475
|
-
plugins: [clickAndWait]
|
|
476
|
-
});
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
### Singleton Blocker Usage
|
|
480
|
-
|
|
481
|
-
The blocker is a singleton - only one instance is created and shared:
|
|
482
|
-
|
|
483
|
-
```javascript
|
|
484
|
-
// From brave-real-blocker package
|
|
485
|
-
import {
|
|
486
|
-
getBraveBlockerSingleton,
|
|
487
|
-
initBraveBlockerSingleton,
|
|
488
|
-
isBraveBlockerInitialized
|
|
489
|
-
} from 'brave-real-blocker/singleton';
|
|
490
|
-
|
|
491
|
-
// Initialize once at startup
|
|
492
|
-
const blocker = await initBraveBlockerSingleton({
|
|
493
|
-
enableAdBlocking: true,
|
|
494
|
-
enableStealth: true,
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
// Get the same instance anywhere else
|
|
498
|
-
const sameBlocker = getBraveBlockerSingleton();
|
|
499
|
-
console.log(blocker === sameBlocker); // true
|
|
500
|
-
```
|
|
501
|
-
|
|
502
|
-
---
|
|
503
|
-
|
|
504
393
|
## Commands
|
|
505
394
|
|
|
506
395
|
### Root Level
|
package/data/.gitkeep
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-browser-mcp-server",
|
|
3
|
-
"version": "2.37.
|
|
3
|
+
"version": "2.37.2",
|
|
4
4
|
"description": "MCP Server for Brave Real Browser - Puppeteer with Brave Browser, Stealth Mode, Ad Blocker, and Turnstile Auto-Solver for undetectable web automation.",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/esm/index.mjs",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"license": "ISC",
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
74
|
-
"brave-real-puppeteer-core": "^24.52.
|
|
74
|
+
"brave-real-puppeteer-core": "^24.52.2",
|
|
75
75
|
"ghost-cursor": "^1.4.2",
|
|
76
76
|
"puppeteer-extra": "^3.3.6",
|
|
77
77
|
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-blocker",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.2",
|
|
4
4
|
"description": "Advanced uBlock Origin management and stealth features for Brave Real Browser",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -53,17 +53,18 @@
|
|
|
53
53
|
},
|
|
54
54
|
"homepage": "https://github.com/codeiva4u/Brave-Real-Browser/tree/main/packages/brave-real-blocker",
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@cliqz/adblocker-puppeteer": "^1.
|
|
56
|
+
"@cliqz/adblocker-puppeteer": "^1.34.0",
|
|
57
|
+
"@ghostery/adblocker-puppeteer": "^2.13.4",
|
|
57
58
|
"adm-zip": "^0.5.10",
|
|
58
59
|
"cross-fetch": "^4.1.0",
|
|
59
|
-
"fs-extra": "^11.
|
|
60
|
+
"fs-extra": "^11.3.3",
|
|
60
61
|
"got": "^13.0.0"
|
|
61
62
|
},
|
|
62
63
|
"devDependencies": {
|
|
63
64
|
"@types/adm-zip": "^0.5.5",
|
|
64
65
|
"@types/fs-extra": "^11.0.4",
|
|
65
66
|
"@types/node": "^20.0.0",
|
|
66
|
-
"brave-real-puppeteer-core": "^24.52.
|
|
67
|
+
"brave-real-puppeteer-core": "^24.52.2",
|
|
67
68
|
"mocha": "^10.4.0",
|
|
68
69
|
"puppeteer-core": "^24.35.0",
|
|
69
70
|
"sinon": "^17.0.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-launcher",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.2",
|
|
4
4
|
"description": "Launch Brave Browser with ease from node. Based on chrome-launcher with Brave-specific support.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
"typescript": "^5.0.0"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"brave-real-blocker": "^1.13.
|
|
58
|
-
"escape-string-regexp": "^
|
|
59
|
-
"is-wsl": "^
|
|
60
|
-
"which": "^
|
|
57
|
+
"brave-real-blocker": "^1.13.2",
|
|
58
|
+
"escape-string-regexp": "^5.0.0",
|
|
59
|
+
"is-wsl": "^3.1.0",
|
|
60
|
+
"which": "^6.0.0"
|
|
61
61
|
},
|
|
62
62
|
"types": "./dist/index.d.ts",
|
|
63
63
|
"repository": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-puppeteer-core",
|
|
3
|
-
"version": "24.52.
|
|
3
|
+
"version": "24.52.2",
|
|
4
4
|
"description": "🦁 Brave Real-World Optimized Puppeteer & Playwright Core with 1-5ms ultra-fast timing, 50+ professional stealth features, intelligent browser auto-detection, and 100% bot detection bypass. Features cross-platform Brave browser integration, comprehensive anti-detection, and breakthrough performance improvements.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -132,13 +132,13 @@
|
|
|
132
132
|
"test-version": "node ./scripts/test-version-management.js"
|
|
133
133
|
},
|
|
134
134
|
"dependencies": {
|
|
135
|
-
"brave-real-launcher": "^1.19.
|
|
135
|
+
"brave-real-launcher": "^1.19.2",
|
|
136
136
|
"get-east-asian-width": "^1.4.0",
|
|
137
137
|
"yargs": "^18.0.0"
|
|
138
138
|
},
|
|
139
139
|
"optionalDependencies": {
|
|
140
|
-
"playwright-core": "^1.
|
|
141
|
-
"puppeteer-core": "^24.
|
|
140
|
+
"playwright-core": "^1.58.1",
|
|
141
|
+
"puppeteer-core": "^24.36.1"
|
|
142
142
|
},
|
|
143
143
|
"devDependencies": {
|
|
144
144
|
"test": "^3.3.0"
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Action Parser - Parse natural language commands into actions
|
|
3
|
+
*
|
|
4
|
+
* Converts commands like:
|
|
5
|
+
* - "click the login button" -> { type: 'click', target: 'login button' }
|
|
6
|
+
* - "type hello in the search box" -> { type: 'type', target: 'search box', text: 'hello' }
|
|
7
|
+
* - "scroll down" -> { type: 'scroll', direction: 'down' }
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
class ActionParser {
|
|
11
|
+
constructor() {
|
|
12
|
+
// Action patterns
|
|
13
|
+
this.actionPatterns = [
|
|
14
|
+
// Click patterns
|
|
15
|
+
{
|
|
16
|
+
pattern: /^(click|tap|press|hit|select)\s+(?:on\s+)?(?:the\s+)?(.+)/i,
|
|
17
|
+
type: 'click',
|
|
18
|
+
extract: (match) => ({ target: match[2].trim() })
|
|
19
|
+
},
|
|
20
|
+
// Type patterns
|
|
21
|
+
{
|
|
22
|
+
pattern: /^(type|enter|write|input)\s+["']?([^"']+)["']?\s+(?:in|into|in the|into the)\s+(.+)/i,
|
|
23
|
+
type: 'type',
|
|
24
|
+
extract: (match) => ({ text: match[2].trim(), target: match[3].trim() })
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
pattern: /^(type|enter|write|input)\s+(.+)\s+(?:in|into)\s+["']?([^"']+)["']?/i,
|
|
28
|
+
type: 'type',
|
|
29
|
+
extract: (match) => ({ target: match[2].trim(), text: match[3].trim() })
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
pattern: /^(fill|fill in|complete)\s+(?:the\s+)?(.+)\s+(?:with|as)\s+["']?([^"']+)["']?/i,
|
|
33
|
+
type: 'type',
|
|
34
|
+
extract: (match) => ({ target: match[2].trim(), text: match[3].trim() })
|
|
35
|
+
},
|
|
36
|
+
// Navigate patterns
|
|
37
|
+
{
|
|
38
|
+
pattern: /^(go to|navigate to|open|visit)\s+(.+)/i,
|
|
39
|
+
type: 'navigate',
|
|
40
|
+
extract: (match) => {
|
|
41
|
+
let url = match[2].trim();
|
|
42
|
+
if (!url.startsWith('http')) {
|
|
43
|
+
url = 'https://' + url;
|
|
44
|
+
}
|
|
45
|
+
return { url };
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
// Scroll patterns
|
|
49
|
+
{
|
|
50
|
+
pattern: /^scroll\s+(up|down|left|right)(?:\s+(\d+)\s*(?:px|pixels)?)?/i,
|
|
51
|
+
type: 'scroll',
|
|
52
|
+
extract: (match) => ({
|
|
53
|
+
direction: match[1].toLowerCase(),
|
|
54
|
+
amount: parseInt(match[2]) || 300
|
|
55
|
+
})
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
pattern: /^scroll\s+to\s+(?:the\s+)?(top|bottom|footer|header)/i,
|
|
59
|
+
type: 'scroll',
|
|
60
|
+
extract: (match) => {
|
|
61
|
+
const target = match[1].toLowerCase();
|
|
62
|
+
return {
|
|
63
|
+
direction: target === 'top' || target === 'header' ? 'up' : 'down',
|
|
64
|
+
amount: 10000,
|
|
65
|
+
scrollTo: target
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
// Wait patterns
|
|
70
|
+
{
|
|
71
|
+
pattern: /^wait\s+(?:for\s+)?(\d+)\s*(?:ms|milliseconds?|s|seconds?)?/i,
|
|
72
|
+
type: 'wait',
|
|
73
|
+
extract: (match) => {
|
|
74
|
+
let duration = parseInt(match[1]);
|
|
75
|
+
const unit = match[0].toLowerCase();
|
|
76
|
+
if (unit.includes('s') && !unit.includes('ms')) {
|
|
77
|
+
duration *= 1000;
|
|
78
|
+
}
|
|
79
|
+
return { duration };
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
pattern: /^wait\s+(?:for\s+)?(?:the\s+)?(.+?)(?:\s+to\s+(?:appear|load|show))?$/i,
|
|
84
|
+
type: 'waitFor',
|
|
85
|
+
extract: (match) => ({ target: match[1].trim() })
|
|
86
|
+
},
|
|
87
|
+
// Find/Search patterns
|
|
88
|
+
{
|
|
89
|
+
pattern: /^(find|search|look for|locate)\s+(?:the\s+)?(.+)/i,
|
|
90
|
+
type: 'find',
|
|
91
|
+
extract: (match) => ({ query: match[2].trim() })
|
|
92
|
+
},
|
|
93
|
+
// Hover patterns
|
|
94
|
+
{
|
|
95
|
+
pattern: /^(hover|mouse over|move to)\s+(?:the\s+)?(.+)/i,
|
|
96
|
+
type: 'hover',
|
|
97
|
+
extract: (match) => ({ target: match[2].trim() })
|
|
98
|
+
},
|
|
99
|
+
// Clear patterns
|
|
100
|
+
{
|
|
101
|
+
pattern: /^(clear|empty|delete)\s+(?:the\s+)?(.+)/i,
|
|
102
|
+
type: 'clear',
|
|
103
|
+
extract: (match) => ({ target: match[2].trim() })
|
|
104
|
+
},
|
|
105
|
+
// Submit patterns
|
|
106
|
+
{
|
|
107
|
+
pattern: /^submit\s+(?:the\s+)?(?:form)?(.*)$/i,
|
|
108
|
+
type: 'submit',
|
|
109
|
+
extract: (match) => ({ target: match[1].trim() || 'form' })
|
|
110
|
+
},
|
|
111
|
+
// Screenshot patterns
|
|
112
|
+
{
|
|
113
|
+
pattern: /^(take|capture)\s+(?:a\s+)?screenshot/i,
|
|
114
|
+
type: 'screenshot',
|
|
115
|
+
extract: () => ({})
|
|
116
|
+
},
|
|
117
|
+
// Go back/forward patterns
|
|
118
|
+
{
|
|
119
|
+
pattern: /^go\s+(back|forward)/i,
|
|
120
|
+
type: 'navigation',
|
|
121
|
+
extract: (match) => ({ direction: match[1].toLowerCase() })
|
|
122
|
+
},
|
|
123
|
+
// Refresh patterns
|
|
124
|
+
{
|
|
125
|
+
pattern: /^(refresh|reload)\s*(?:the\s+)?(?:page)?/i,
|
|
126
|
+
type: 'refresh',
|
|
127
|
+
extract: () => ({})
|
|
128
|
+
}
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
// Context variable patterns (for substitution)
|
|
132
|
+
this.variablePattern = /\{(\w+)\}/g;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Parse a natural language command
|
|
137
|
+
*/
|
|
138
|
+
async parse(command, context = {}) {
|
|
139
|
+
// Substitute context variables
|
|
140
|
+
let processedCommand = command.replace(this.variablePattern, (match, varName) => {
|
|
141
|
+
return context[varName] !== undefined ? context[varName] : match;
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Trim and normalize
|
|
145
|
+
processedCommand = processedCommand.trim();
|
|
146
|
+
|
|
147
|
+
// Try each pattern
|
|
148
|
+
for (const pattern of this.actionPatterns) {
|
|
149
|
+
const match = processedCommand.match(pattern.pattern);
|
|
150
|
+
if (match) {
|
|
151
|
+
const extracted = pattern.extract(match);
|
|
152
|
+
return {
|
|
153
|
+
type: pattern.type,
|
|
154
|
+
...extracted,
|
|
155
|
+
originalCommand: command,
|
|
156
|
+
confidence: 0.9
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Fallback: Try to guess action from keywords
|
|
162
|
+
const fallback = this.guessFallback(processedCommand);
|
|
163
|
+
if (fallback) {
|
|
164
|
+
return {
|
|
165
|
+
...fallback,
|
|
166
|
+
originalCommand: command,
|
|
167
|
+
confidence: 0.5
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Could not parse
|
|
172
|
+
return {
|
|
173
|
+
type: 'unknown',
|
|
174
|
+
originalCommand: command,
|
|
175
|
+
confidence: 0,
|
|
176
|
+
error: 'Could not understand command'
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Try to guess action from keywords
|
|
182
|
+
*/
|
|
183
|
+
guessFallback(command) {
|
|
184
|
+
const lower = command.toLowerCase();
|
|
185
|
+
|
|
186
|
+
// Check for action keywords
|
|
187
|
+
if (lower.includes('button') || lower.includes('link') || lower.includes('click')) {
|
|
188
|
+
return { type: 'click', target: command };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (lower.includes('type') || lower.includes('enter') || lower.includes('input')) {
|
|
192
|
+
return { type: 'find', query: command, suggestedAction: 'type' };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (lower.includes('search') || lower.includes('find') || lower.includes('look')) {
|
|
196
|
+
return { type: 'find', query: command };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (lower.includes('scroll')) {
|
|
200
|
+
return { type: 'scroll', direction: 'down', amount: 300 };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Default to find
|
|
204
|
+
return { type: 'find', query: command };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Parse multiple commands (separated by 'then', 'and', or newlines)
|
|
209
|
+
*/
|
|
210
|
+
async parseMultiple(commands, context = {}) {
|
|
211
|
+
// Split by separators
|
|
212
|
+
const parts = commands.split(/\s+(?:then|and)\s+|\n|;/i).filter(p => p.trim());
|
|
213
|
+
|
|
214
|
+
const results = [];
|
|
215
|
+
for (const part of parts) {
|
|
216
|
+
const parsed = await this.parse(part.trim(), context);
|
|
217
|
+
results.push(parsed);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return results;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get suggestions for incomplete commands
|
|
225
|
+
*/
|
|
226
|
+
getSuggestions(partialCommand) {
|
|
227
|
+
const lower = partialCommand.toLowerCase();
|
|
228
|
+
const suggestions = [];
|
|
229
|
+
|
|
230
|
+
if (lower.startsWith('click')) {
|
|
231
|
+
suggestions.push(
|
|
232
|
+
'click the login button',
|
|
233
|
+
'click the submit button',
|
|
234
|
+
'click the link',
|
|
235
|
+
'click the menu'
|
|
236
|
+
);
|
|
237
|
+
} else if (lower.startsWith('type')) {
|
|
238
|
+
suggestions.push(
|
|
239
|
+
'type "text" in the search box',
|
|
240
|
+
'type "username" in the login field',
|
|
241
|
+
'type "hello" in the input'
|
|
242
|
+
);
|
|
243
|
+
} else if (lower.startsWith('go')) {
|
|
244
|
+
suggestions.push(
|
|
245
|
+
'go to google.com',
|
|
246
|
+
'go back',
|
|
247
|
+
'go forward'
|
|
248
|
+
);
|
|
249
|
+
} else if (lower.startsWith('scroll')) {
|
|
250
|
+
suggestions.push(
|
|
251
|
+
'scroll down',
|
|
252
|
+
'scroll up',
|
|
253
|
+
'scroll to the bottom',
|
|
254
|
+
'scroll to the top'
|
|
255
|
+
);
|
|
256
|
+
} else if (lower.startsWith('wait')) {
|
|
257
|
+
suggestions.push(
|
|
258
|
+
'wait 2 seconds',
|
|
259
|
+
'wait for the button to appear',
|
|
260
|
+
'wait 500ms'
|
|
261
|
+
);
|
|
262
|
+
} else if (lower.startsWith('find')) {
|
|
263
|
+
suggestions.push(
|
|
264
|
+
'find the login button',
|
|
265
|
+
'find the search input',
|
|
266
|
+
'find all links'
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return suggestions;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
module.exports = ActionParser;
|