brave-real-browser-mcp-server 2.36.0 → 2.37.1
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 +210 -1
- package/data/.gitkeep +2 -0
- package/package.json +4 -3
- package/packages/brave-real-blocker/package.json +2 -2
- package/packages/brave-real-launcher/package.json +2 -2
- package/packages/brave-real-puppeteer-core/package.json +2 -2
- 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/index.js +66 -28
- package/src/lsp/server.js +160 -54
- package/src/mcp/handlers.js +390 -19
- 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
|
@@ -14,7 +14,9 @@ A production-ready MCP (Model Context Protocol) server that combines Puppeteer w
|
|
|
14
14
|
|
|
15
15
|
| Feature | Description |
|
|
16
16
|
|---------|-------------|
|
|
17
|
-
| MCP Server | Model Context Protocol compatible server |
|
|
17
|
+
| **MCP Server** | Model Context Protocol compatible server with 28 tools |
|
|
18
|
+
| **LSP Server** | Language Server Protocol for IDE code intelligence |
|
|
19
|
+
| **AI Core** | Automatic AI enhancement for all tools (auto-healing, smart retry) |
|
|
18
20
|
| Brave Browser | Uses Brave instead of Chromium for better privacy |
|
|
19
21
|
| 50+ Stealth Features | Passes all major bot detectors |
|
|
20
22
|
| Built-in Ad Blocker | uBlock Origin filters with auto-update |
|
|
@@ -25,6 +27,7 @@ A production-ready MCP (Model Context Protocol) server that combines Puppeteer w
|
|
|
25
27
|
| Auto-Install | Brave auto-installs if missing |
|
|
26
28
|
| TypeScript Support | Full type definitions included |
|
|
27
29
|
| ESM + CJS | Dual module support |
|
|
30
|
+
| **Multi-language** | English & Hindi language support |
|
|
28
31
|
| **Auto-Update** | Daily automatic dependency updates |
|
|
29
32
|
| **Auto-Publish** | Automatic NPM publishing on updates |
|
|
30
33
|
| **Monorepo** | npm workspaces with linked packages |
|
|
@@ -127,6 +130,209 @@ AI: [Calls file_downloader with url="..."] -> Downloaded to ./downloads/image.pn
|
|
|
127
130
|
|
|
128
131
|
---
|
|
129
132
|
|
|
133
|
+
## LSP Server (Language Server Protocol)
|
|
134
|
+
|
|
135
|
+
This package also includes a full-featured **LSP Server** for IDE code intelligence when writing browser automation scripts.
|
|
136
|
+
|
|
137
|
+
### Quick Start LSP Server
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Start the LSP server
|
|
141
|
+
npm run lsp
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### LSP Capabilities
|
|
145
|
+
|
|
146
|
+
| Feature | Description |
|
|
147
|
+
|---------|-------------|
|
|
148
|
+
| **Autocomplete** | Tool names, parameters, and enum values |
|
|
149
|
+
| **Hover** | Full documentation on hover |
|
|
150
|
+
| **Diagnostics** | Error & warning detection (missing browser_init, etc.) |
|
|
151
|
+
| **Snippets** | Code templates for common workflows |
|
|
152
|
+
| **Refactoring** | Quick fixes (add browser_init, try-catch, etc.) |
|
|
153
|
+
| **Simulation** | Workflow simulation in IDE |
|
|
154
|
+
| **Multi-language** | English & Hindi support |
|
|
155
|
+
|
|
156
|
+
### VS Code Setup
|
|
157
|
+
|
|
158
|
+
Create `.vscode/settings.json` in your project:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"braveRealBrowser.language": "en",
|
|
163
|
+
"braveRealBrowser.maxDiagnostics": 100,
|
|
164
|
+
"braveRealBrowser.enableSnippets": true,
|
|
165
|
+
"braveRealBrowser.enableSimulation": true,
|
|
166
|
+
"braveRealBrowser.enableRefactoring": true
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Diagnostic Features
|
|
171
|
+
|
|
172
|
+
The LSP detects common issues:
|
|
173
|
+
|
|
174
|
+
- Missing `browser_init()` before page operations
|
|
175
|
+
- Missing `navigate()` before content extraction
|
|
176
|
+
- Invalid selectors and URLs
|
|
177
|
+
- Missing required parameters
|
|
178
|
+
- Unclosed browser sessions
|
|
179
|
+
- Security issues (eval usage, etc.)
|
|
180
|
+
|
|
181
|
+
### Quick Fixes
|
|
182
|
+
|
|
183
|
+
When diagnostics are detected, quick fixes are offered:
|
|
184
|
+
|
|
185
|
+
- Add `browser_init()` at start
|
|
186
|
+
- Add `navigate()` before page tools
|
|
187
|
+
- Add `browser_close()` at end
|
|
188
|
+
- Wrap in try-catch
|
|
189
|
+
- Extract to function
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## AI Core (Automatic Enhancement)
|
|
194
|
+
|
|
195
|
+
All 28 tools are automatically enhanced with AI capabilities. No configuration needed - AI features work transparently.
|
|
196
|
+
|
|
197
|
+
### How It Works
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
AI Agent calls any tool (e.g., click, type, find_element)
|
|
201
|
+
│
|
|
202
|
+
▼
|
|
203
|
+
┌───────────────────┐
|
|
204
|
+
│ AI Core Check │
|
|
205
|
+
│ (Lazy initialize) │
|
|
206
|
+
└───────────────────┘
|
|
207
|
+
│
|
|
208
|
+
▼
|
|
209
|
+
Execute Original Tool
|
|
210
|
+
│
|
|
211
|
+
┌───────┴───────┐
|
|
212
|
+
│ │
|
|
213
|
+
Success Failed (selector not found)
|
|
214
|
+
│ │
|
|
215
|
+
▼ ▼
|
|
216
|
+
Return result ┌─────────────────┐
|
|
217
|
+
with _ai meta │ AI Auto-Healing │
|
|
218
|
+
│ - Find alts │
|
|
219
|
+
│ - Try healed │
|
|
220
|
+
│ - Retry op │
|
|
221
|
+
└─────────────────┘
|
|
222
|
+
│
|
|
223
|
+
▼
|
|
224
|
+
Return healed result
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### AI Features
|
|
228
|
+
|
|
229
|
+
| Feature | Description |
|
|
230
|
+
|---------|-------------|
|
|
231
|
+
| **Auto-Healing Selectors** | If a CSS selector fails, AI finds alternative selectors |
|
|
232
|
+
| **Smart Retry** | Failed operations are automatically retried with AI assistance |
|
|
233
|
+
| **Confidence Scoring** | AI provides confidence scores for healed selectors |
|
|
234
|
+
| **Caching** | Healed selectors are cached for performance |
|
|
235
|
+
| **Zero Configuration** | Works out of the box with all 28 tools |
|
|
236
|
+
|
|
237
|
+
### Example Response with AI Metadata
|
|
238
|
+
|
|
239
|
+
When AI heals a broken selector:
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"success": true,
|
|
244
|
+
"selector": "#new-login-btn",
|
|
245
|
+
"clicked": true,
|
|
246
|
+
"_ai": {
|
|
247
|
+
"enabled": true,
|
|
248
|
+
"healed": true,
|
|
249
|
+
"originalSelector": "#old-login-button",
|
|
250
|
+
"healedSelector": "#new-login-btn",
|
|
251
|
+
"duration": 245
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### AI Modules
|
|
257
|
+
|
|
258
|
+
| Module | Description |
|
|
259
|
+
|--------|-------------|
|
|
260
|
+
| `AICore` | Central AI intelligence singleton |
|
|
261
|
+
| `ElementFinder` | Smart element finding with multiple strategies |
|
|
262
|
+
| `SelectorHealer` | Auto-fix broken CSS selectors |
|
|
263
|
+
| `PageAnalyzer` | Page structure analysis |
|
|
264
|
+
| `ActionParser` | Natural language command parsing |
|
|
265
|
+
|
|
266
|
+
### Programmatic Access
|
|
267
|
+
|
|
268
|
+
For advanced usage, you can access AI features directly:
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
const { getAICore, aiEnhancedSelector } = require('./src/mcp/handlers');
|
|
272
|
+
|
|
273
|
+
// Get AI Core instance
|
|
274
|
+
const ai = getAICore();
|
|
275
|
+
|
|
276
|
+
// Use AI-enhanced selector finding
|
|
277
|
+
const { element, selector, healed } = await aiEnhancedSelector(page, '#old-selector', 'click');
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Unified Architecture
|
|
283
|
+
|
|
284
|
+
Both MCP and LSP servers share the same tool definitions:
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
src/
|
|
288
|
+
├── shared/
|
|
289
|
+
│ └── tools.js # Single source of truth (28 tools)
|
|
290
|
+
├── ai/ # AI Core Module (Auto-enhancement)
|
|
291
|
+
│ ├── index.js # AI module exports
|
|
292
|
+
│ ├── core.js # AI Core singleton
|
|
293
|
+
│ ├── element-finder.js# Smart element finding
|
|
294
|
+
│ ├── selector-healer.js# Auto-heal selectors
|
|
295
|
+
│ ├── page-analyzer.js # Page analysis
|
|
296
|
+
│ └── action-parser.js # NL command parsing
|
|
297
|
+
├── mcp/
|
|
298
|
+
│ ├── server.js # MCP server for AI agents
|
|
299
|
+
│ └── handlers.js # Tool implementations + AI integration
|
|
300
|
+
├── lsp/
|
|
301
|
+
│ ├── server.js # LSP server for IDEs
|
|
302
|
+
│ └── capabilities/ # Autocomplete, hover, diagnostics, etc.
|
|
303
|
+
└── index.js # Unified entry point
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Unified CLI
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# List all tools
|
|
310
|
+
node src/index.js --list
|
|
311
|
+
|
|
312
|
+
# Start MCP server (default)
|
|
313
|
+
node src/index.js mcp
|
|
314
|
+
|
|
315
|
+
# Start LSP server
|
|
316
|
+
node src/index.js lsp
|
|
317
|
+
|
|
318
|
+
# Show help
|
|
319
|
+
node src/index.js --help
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Tool Categories
|
|
323
|
+
|
|
324
|
+
| Category | Tools | Description |
|
|
325
|
+
|----------|-------|-------------|
|
|
326
|
+
| **Browser** | 3 | Browser lifecycle (init, close, cookies) |
|
|
327
|
+
| **Navigation** | 1 | Page navigation |
|
|
328
|
+
| **Interaction** | 8 | User actions (click, type, scroll, etc.) |
|
|
329
|
+
| **Extraction** | 10 | Content scraping (HTML, JSON, links, etc.) |
|
|
330
|
+
| **Network** | 3 | Network operations (recorder, download, trace) |
|
|
331
|
+
| **Analysis** | 1 | Page analysis (SEO, performance, etc.) |
|
|
332
|
+
| **Utility** | 2 | Helpers (wait, progress tracker) |
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
130
336
|
## Monorepo Ecosystem
|
|
131
337
|
|
|
132
338
|
```
|
|
@@ -398,9 +604,12 @@ console.log(blocker === sameBlocker); // true
|
|
|
398
604
|
|
|
399
605
|
| Command | Description |
|
|
400
606
|
|---------|-------------|
|
|
607
|
+
| `npm start` | Start unified server (MCP by default) |
|
|
401
608
|
| `npm run dev` | Start MCP server |
|
|
402
609
|
| `npm run mcp` | Start MCP server (alias) |
|
|
403
610
|
| `npm run mcp:verbose` | Start MCP server with tool details |
|
|
611
|
+
| `npm run lsp` | Start LSP server for IDE intelligence |
|
|
612
|
+
| `npm run list` | List all 28 tools with categories |
|
|
404
613
|
| `npm install` | Install all dependencies with workspace linking |
|
|
405
614
|
| `npm test` | Run all tests (CJS + ESM) |
|
|
406
615
|
| `npm run cjs_test` | Run CommonJS tests only |
|
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.
|
|
3
|
+
"version": "2.37.1",
|
|
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",
|
|
@@ -28,10 +28,11 @@
|
|
|
28
28
|
},
|
|
29
29
|
"scripts": {
|
|
30
30
|
"start": "node src/index.js",
|
|
31
|
-
"dev": "node src/index.js
|
|
31
|
+
"dev": "node src/index.js",
|
|
32
32
|
"mcp": "node src/index.js mcp",
|
|
33
33
|
"mcp:verbose": "node src/index.js mcp --verbose",
|
|
34
34
|
"lsp": "node src/index.js lsp",
|
|
35
|
+
"lsp:tcp": "node src/lsp/server.js --tcp",
|
|
35
36
|
"list": "node src/index.js --list",
|
|
36
37
|
"build": "echo 'Root package uses pre-built lib/ - no build needed'",
|
|
37
38
|
"build:self": "echo 'Root package uses pre-built lib/ - no build needed'",
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
"license": "ISC",
|
|
71
72
|
"dependencies": {
|
|
72
73
|
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
73
|
-
"brave-real-puppeteer-core": "^24.
|
|
74
|
+
"brave-real-puppeteer-core": "^24.52.1",
|
|
74
75
|
"ghost-cursor": "^1.4.2",
|
|
75
76
|
"puppeteer-extra": "^3.3.6",
|
|
76
77
|
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-blocker",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.1",
|
|
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",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"@types/adm-zip": "^0.5.5",
|
|
64
64
|
"@types/fs-extra": "^11.0.4",
|
|
65
65
|
"@types/node": "^20.0.0",
|
|
66
|
-
"brave-real-puppeteer-core": "^24.
|
|
66
|
+
"brave-real-puppeteer-core": "^24.52.1",
|
|
67
67
|
"mocha": "^10.4.0",
|
|
68
68
|
"puppeteer-core": "^24.35.0",
|
|
69
69
|
"sinon": "^17.0.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-launcher",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.1",
|
|
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,7 +54,7 @@
|
|
|
54
54
|
"typescript": "^5.0.0"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"brave-real-blocker": "^1.
|
|
57
|
+
"brave-real-blocker": "^1.13.1",
|
|
58
58
|
"escape-string-regexp": "^4.0.0",
|
|
59
59
|
"is-wsl": "^2.2.0",
|
|
60
60
|
"which": "^4.0.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-puppeteer-core",
|
|
3
|
-
"version": "24.
|
|
3
|
+
"version": "24.52.1",
|
|
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,7 +132,7 @@
|
|
|
132
132
|
"test-version": "node ./scripts/test-version-management.js"
|
|
133
133
|
},
|
|
134
134
|
"dependencies": {
|
|
135
|
-
"brave-real-launcher": "^1.
|
|
135
|
+
"brave-real-launcher": "^1.19.1",
|
|
136
136
|
"get-east-asian-width": "^1.4.0",
|
|
137
137
|
"yargs": "^18.0.0"
|
|
138
138
|
},
|
|
@@ -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;
|