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.
Files changed (73) hide show
  1. package/README.md +74 -185
  2. package/data/.gitkeep +2 -0
  3. package/package.json +2 -2
  4. package/packages/brave-real-blocker/package.json +5 -4
  5. package/packages/brave-real-launcher/package.json +5 -5
  6. package/packages/brave-real-puppeteer-core/package.json +4 -4
  7. package/src/ai/action-parser.js +274 -0
  8. package/src/ai/core.js +378 -0
  9. package/src/ai/element-finder.js +466 -0
  10. package/src/ai/error-collector.js +498 -0
  11. package/src/ai/hindi-suggester.js +505 -0
  12. package/src/ai/index.js +82 -0
  13. package/src/ai/page-analyzer.js +304 -0
  14. package/src/ai/pattern-learner.js +561 -0
  15. package/src/ai/result-validator.js +666 -0
  16. package/src/ai/selector-healer.js +236 -0
  17. package/src/mcp/handlers-fixed.js +2499 -0
  18. package/src/mcp/handlers.js +2816 -116
  19. package/test/esm/test.js +35 -13
  20. package/packages/brave-real-blocker/dist/index.d.mts +0 -2
  21. package/packages/brave-real-blocker/dist/index.d.ts +0 -2
  22. package/packages/brave-real-blocker/dist/index.js +0 -1634
  23. package/packages/brave-real-blocker/dist/index.js.map +0 -1
  24. package/packages/brave-real-blocker/dist/index.mjs +0 -1594
  25. package/packages/brave-real-blocker/dist/index.mjs.map +0 -1
  26. package/packages/brave-real-blocker/dist/singleton.d.mts +0 -190
  27. package/packages/brave-real-blocker/dist/singleton.d.ts +0 -190
  28. package/packages/brave-real-blocker/dist/singleton.js +0 -1618
  29. package/packages/brave-real-blocker/dist/singleton.js.map +0 -1
  30. package/packages/brave-real-blocker/dist/singleton.mjs +0 -1584
  31. package/packages/brave-real-blocker/dist/singleton.mjs.map +0 -1
  32. package/packages/brave-real-launcher/dist/blocker-integration.d.ts +0 -53
  33. package/packages/brave-real-launcher/dist/blocker-integration.js +0 -165
  34. package/packages/brave-real-launcher/dist/blocker-integration.mjs +0 -153
  35. package/packages/brave-real-launcher/dist/brave-finder.d.ts +0 -34
  36. package/packages/brave-real-launcher/dist/brave-finder.js +0 -477
  37. package/packages/brave-real-launcher/dist/brave-finder.mjs +0 -465
  38. package/packages/brave-real-launcher/dist/brave-installer.d.ts +0 -57
  39. package/packages/brave-real-launcher/dist/brave-installer.js +0 -373
  40. package/packages/brave-real-launcher/dist/brave-installer.mjs +0 -334
  41. package/packages/brave-real-launcher/dist/brave-launcher.d.ts +0 -117
  42. package/packages/brave-real-launcher/dist/brave-launcher.js +0 -715
  43. package/packages/brave-real-launcher/dist/brave-launcher.mjs +0 -672
  44. package/packages/brave-real-launcher/dist/chrome-launcher.d.ts +0 -96
  45. package/packages/brave-real-launcher/dist/chrome-launcher.js +0 -493
  46. package/packages/brave-real-launcher/dist/chrome-launcher.mjs +0 -452
  47. package/packages/brave-real-launcher/dist/chrome-version.d.ts +0 -75
  48. package/packages/brave-real-launcher/dist/chrome-version.js +0 -163
  49. package/packages/brave-real-launcher/dist/chrome-version.mjs +0 -154
  50. package/packages/brave-real-launcher/dist/errors.d.ts +0 -104
  51. package/packages/brave-real-launcher/dist/errors.js +0 -252
  52. package/packages/brave-real-launcher/dist/errors.mjs +0 -233
  53. package/packages/brave-real-launcher/dist/flags.d.ts +0 -5
  54. package/packages/brave-real-launcher/dist/flags.js +0 -121
  55. package/packages/brave-real-launcher/dist/flags.mjs +0 -119
  56. package/packages/brave-real-launcher/dist/index.d.ts +0 -14
  57. package/packages/brave-real-launcher/dist/index.js +0 -90
  58. package/packages/brave-real-launcher/dist/index.mjs +0 -22
  59. package/packages/brave-real-launcher/dist/logger.d.ts +0 -31
  60. package/packages/brave-real-launcher/dist/logger.js +0 -75
  61. package/packages/brave-real-launcher/dist/logger.mjs +0 -73
  62. package/packages/brave-real-launcher/dist/random-port.d.ts +0 -4
  63. package/packages/brave-real-launcher/dist/random-port.js +0 -24
  64. package/packages/brave-real-launcher/dist/random-port.mjs +0 -22
  65. package/packages/brave-real-launcher/dist/stealth-utils.d.ts +0 -209
  66. package/packages/brave-real-launcher/dist/stealth-utils.js +0 -837
  67. package/packages/brave-real-launcher/dist/stealth-utils.mjs +0 -827
  68. package/packages/brave-real-launcher/dist/utils.d.ts +0 -61
  69. package/packages/brave-real-launcher/dist/utils.js +0 -253
  70. package/packages/brave-real-launcher/dist/utils.mjs +0 -233
  71. package/packages/brave-real-launcher/dist/xvfb-support.d.ts +0 -58
  72. package/packages/brave-real-launcher/dist/xvfb-support.js +0 -226
  73. 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
- ### VS Code Setup
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
- Create `.vscode/settings.json` in your project:
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
- "braveRealBrowser.language": "en",
162
- "braveRealBrowser.maxDiagnostics": 100,
163
- "braveRealBrowser.enableSnippets": true,
164
- "braveRealBrowser.enableSimulation": true,
165
- "braveRealBrowser.enableRefactoring": true
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
- ### Diagnostic Features
170
-
171
- The LSP detects common issues:
220
+ For advanced usage, you can access AI features directly:
172
221
 
173
- - Missing `browser_init()` before page operations
174
- - Missing `navigate()` before content extraction
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
- When diagnostics are detected, quick fixes are offered:
225
+ // Get AI Core instance
226
+ const ai = getAICore();
183
227
 
184
- - Add `browser_init()` at start
185
- - Add `navigate()` before page tools
186
- - Add `browser_close()` at end
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
@@ -0,0 +1,2 @@
1
+ # This folder stores learned patterns for self-healing
2
+ # Files are auto-generated and should not be committed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.37.0",
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.0",
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.0",
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.23.8",
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.2.0",
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.0",
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.0",
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.0",
58
- "escape-string-regexp": "^4.0.0",
59
- "is-wsl": "^2.2.0",
60
- "which": "^4.0.0"
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.0",
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.0",
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.57.0",
141
- "puppeteer-core": "^24.34.0"
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;