brave-real-browser-mcp-server 2.41.11 → 2.41.13

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.
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.41.11",
3
+ "version": "2.41.13",
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",
@@ -74,7 +74,7 @@
74
74
  "license": "ISC",
75
75
  "dependencies": {
76
76
  "@modelcontextprotocol/sdk": "^1.25.3",
77
- "brave-real-puppeteer-core": "^24.37.1-brave.10",
77
+ "brave-real-puppeteer-core": "^24.37.1-brave.12",
78
78
  "ghost-cursor": "^1.4.2",
79
79
  "puppeteer-extra": "^3.3.6",
80
80
  "puppeteer-extra-plugin-stealth": "^2.11.2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-blocker",
3
- "version": "1.17.11",
3
+ "version": "1.17.13",
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",
@@ -64,7 +64,7 @@
64
64
  "@types/adm-zip": "^0.5.5",
65
65
  "@types/fs-extra": "^11.0.4",
66
66
  "@types/node": "^20.0.0",
67
- "brave-real-puppeteer-core": "^24.37.1-brave.10",
67
+ "brave-real-puppeteer-core": "^24.37.1-brave.12",
68
68
  "mocha": "^10.4.0",
69
69
  "puppeteer-core": ">=24.0.0",
70
70
  "sinon": "^17.0.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-launcher",
3
- "version": "1.23.11",
3
+ "version": "1.23.13",
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.17.11",
57
+ "brave-real-blocker": "^1.17.13",
58
58
  "escape-string-regexp": "^5.0.0",
59
59
  "is-wsl": "^3.1.0",
60
60
  "which": "^6.0.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-playwright-core",
3
- "version": "1.59.11",
3
+ "version": "1.59.13",
4
4
  "description": "Brave-optimized Playwright Core (v1.57.0) with comprehensive stealth patches and error stack sanitization",
5
5
  "keywords": [
6
6
  "playwright",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-puppeteer-core",
3
- "version": "24.37.1-brave.10",
3
+ "version": "24.37.1-brave.12",
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",
@@ -134,13 +134,13 @@
134
134
  "test-version": "node ./scripts/test-version-management.js"
135
135
  },
136
136
  "dependencies": {
137
- "brave-real-launcher": "^1.23.11",
137
+ "brave-real-launcher": "^1.23.13",
138
138
  "get-east-asian-width": "^1.4.0",
139
139
  "yargs": "^18.0.0"
140
140
  },
141
141
  "optionalDependencies": {
142
- "playwright-core": "^1.58.2",
143
- "puppeteer-core": "^24.37.2"
142
+ "playwright-core": "^1.58.1",
143
+ "puppeteer-core": "^24.37.1"
144
144
  },
145
145
  "devDependencies": {
146
146
  "test": "^3.3.0"
@@ -12,38 +12,38 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
12
12
  const text = document.getText();
13
13
  const lines = text.split('\n');
14
14
  const diagnostics = [];
15
-
15
+
16
16
  // State tracking
17
17
  let browserInitialized = false;
18
18
  let browserClosed = false;
19
19
  let currentPage = null;
20
20
  let networkRecording = false;
21
-
21
+
22
22
  // Tool categories
23
23
  const browserRequiredTools = [
24
24
  'navigate', 'get_content', 'wait', 'click', 'type', 'solve_captcha',
25
25
  'random_scroll', 'find_element', 'save_content_as_markdown', 'search_regex',
26
26
  'extract_json', 'scrape_meta_tags', 'press_key', 'deep_analysis',
27
27
  'network_recorder', 'link_harvester', 'cookie_manager', 'iframe_handler',
28
- 'stream_extractor', 'js_scrape', 'execute_js', 'player_api_hook', 'form_automator',
28
+ 'stream_extractor', 'js_scrape', 'execute_js', 'player_api_hook',
29
29
  'redirect_tracer', 'file_downloader'
30
30
  ];
31
-
31
+
32
32
  const pageRequiredTools = [
33
33
  'get_content', 'click', 'type', 'random_scroll', 'find_element',
34
34
  'save_content_as_markdown', 'search_regex', 'extract_json', 'scrape_meta_tags',
35
35
  'deep_analysis', 'link_harvester', 'iframe_handler', 'stream_extractor',
36
- 'js_scrape', 'execute_js', 'player_api_hook', 'form_automator', 'press_key'
36
+ 'js_scrape', 'execute_js', 'player_api_hook', 'press_key'
37
37
  ];
38
-
38
+
39
39
  // Parse all tool calls with their parameters
40
40
  const toolCalls = parseAllToolCalls(text, lines, tools);
41
-
41
+
42
42
  for (const call of toolCalls) {
43
43
  if (diagnostics.length >= maxDiagnostics) break;
44
-
44
+
45
45
  const tool = tools.find(t => t.name === call.name);
46
-
46
+
47
47
  // 1. Unknown tool check
48
48
  if (!tool) {
49
49
  diagnostics.push({
@@ -56,7 +56,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
56
56
  });
57
57
  continue;
58
58
  }
59
-
59
+
60
60
  // 2. Browser state tracking
61
61
  if (call.name === 'browser_init') {
62
62
  if (browserInitialized && !browserClosed) {
@@ -71,7 +71,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
71
71
  browserInitialized = true;
72
72
  browserClosed = false;
73
73
  }
74
-
74
+
75
75
  if (call.name === 'browser_close') {
76
76
  if (!browserInitialized) {
77
77
  diagnostics.push({
@@ -85,11 +85,11 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
85
85
  browserClosed = true;
86
86
  currentPage = null;
87
87
  }
88
-
88
+
89
89
  if (call.name === 'navigate') {
90
90
  currentPage = call.params?.url || 'page';
91
91
  }
92
-
92
+
93
93
  // 3. Browser required check
94
94
  if (browserRequiredTools.includes(call.name) && !browserInitialized) {
95
95
  diagnostics.push({
@@ -100,7 +100,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
100
100
  code: 'browser-not-init'
101
101
  });
102
102
  }
103
-
103
+
104
104
  // 4. Browser closed check
105
105
  if (browserRequiredTools.includes(call.name) && browserClosed) {
106
106
  diagnostics.push({
@@ -111,7 +111,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
111
111
  code: 'browser-closed'
112
112
  });
113
113
  }
114
-
114
+
115
115
  // 5. Page required check (navigate must be called first)
116
116
  if (pageRequiredTools.includes(call.name) && !currentPage && browserInitialized) {
117
117
  diagnostics.push({
@@ -122,7 +122,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
122
122
  code: 'no-page-loaded'
123
123
  });
124
124
  }
125
-
125
+
126
126
  // 6. Network recorder state
127
127
  if (call.name === 'network_recorder') {
128
128
  if (call.params?.action === 'start') {
@@ -140,7 +140,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
140
140
  networkRecording = false;
141
141
  }
142
142
  }
143
-
143
+
144
144
  // 7. Required parameters check
145
145
  if (tool.inputSchema?.required) {
146
146
  for (const reqParam of tool.inputSchema.required) {
@@ -156,12 +156,12 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
156
156
  }
157
157
  }
158
158
  }
159
-
159
+
160
160
  // 8. Parameter validation
161
161
  if (call.params && tool.inputSchema?.properties) {
162
162
  for (const [paramName, paramValue] of Object.entries(call.params)) {
163
163
  const schema = tool.inputSchema.properties[paramName];
164
-
164
+
165
165
  // Unknown parameter
166
166
  if (!schema) {
167
167
  diagnostics.push({
@@ -174,7 +174,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
174
174
  });
175
175
  continue;
176
176
  }
177
-
177
+
178
178
  // Type validation
179
179
  const typeError = validateParamType(paramValue, schema, paramName);
180
180
  if (typeError) {
@@ -186,7 +186,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
186
186
  code: 'type-error'
187
187
  });
188
188
  }
189
-
189
+
190
190
  // Enum validation
191
191
  if (schema.enum && !schema.enum.includes(paramValue)) {
192
192
  diagnostics.push({
@@ -197,7 +197,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
197
197
  code: 'invalid-enum'
198
198
  });
199
199
  }
200
-
200
+
201
201
  // URL validation
202
202
  if (paramName === 'url' && typeof paramValue === 'string') {
203
203
  const urlError = validateUrl(paramValue);
@@ -211,7 +211,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
211
211
  });
212
212
  }
213
213
  }
214
-
214
+
215
215
  // Selector validation
216
216
  if (paramName === 'selector' && typeof paramValue === 'string') {
217
217
  const selectorError = validateSelector(paramValue);
@@ -225,7 +225,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
225
225
  });
226
226
  }
227
227
  }
228
-
228
+
229
229
  // Timeout validation
230
230
  if (paramName === 'timeout' && typeof paramValue === 'number') {
231
231
  if (paramValue < 0) {
@@ -246,7 +246,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
246
246
  });
247
247
  }
248
248
  }
249
-
249
+
250
250
  // Delay validation
251
251
  if (paramName === 'delay' && typeof paramValue === 'number') {
252
252
  if (paramValue < 0) {
@@ -269,7 +269,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
269
269
  }
270
270
  }
271
271
  }
272
-
272
+
273
273
  // 9. Tool-specific validations
274
274
  if (call.name === 'type' && call.params?.text === '') {
275
275
  diagnostics.push({
@@ -280,7 +280,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
280
280
  code: 'empty-text'
281
281
  });
282
282
  }
283
-
283
+
284
284
  if (call.name === 'wait' && call.params?.type === 'timeout') {
285
285
  const waitValue = parseInt(call.params?.value);
286
286
  if (waitValue > 30000) {
@@ -293,7 +293,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
293
293
  });
294
294
  }
295
295
  }
296
-
296
+
297
297
  if (call.name === 'execute_js' && call.params?.code) {
298
298
  const jsCode = call.params.code;
299
299
  if (jsCode.includes('eval(') || jsCode.includes('Function(')) {
@@ -306,7 +306,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
306
306
  });
307
307
  }
308
308
  }
309
-
309
+
310
310
  if (call.name === 'file_downloader' && call.params?.directory) {
311
311
  const dir = call.params.directory;
312
312
  if (dir.includes('..') || dir.startsWith('/')) {
@@ -320,7 +320,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
320
320
  }
321
321
  }
322
322
  }
323
-
323
+
324
324
  // 10. Document-level checks
325
325
  if (browserInitialized && !browserClosed) {
326
326
  diagnostics.push({
@@ -331,7 +331,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
331
331
  code: 'missing-cleanup'
332
332
  });
333
333
  }
334
-
334
+
335
335
  if (networkRecording) {
336
336
  diagnostics.push({
337
337
  severity: DiagnosticSeverity.Information,
@@ -341,7 +341,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
341
341
  code: 'network-not-stopped'
342
342
  });
343
343
  }
344
-
344
+
345
345
  // 11. Check for duplicate tool calls (potential bugs)
346
346
  const navigateCalls = toolCalls.filter(c => c.name === 'navigate');
347
347
  if (navigateCalls.length > 5) {
@@ -353,7 +353,7 @@ function getDiagnostics(document, tools, lang, maxDiagnostics = 100) {
353
353
  code: 'many-navigates'
354
354
  });
355
355
  }
356
-
356
+
357
357
  return diagnostics.slice(0, maxDiagnostics);
358
358
  }
359
359
 
@@ -364,15 +364,15 @@ function parseAllToolCalls(text, lines, tools) {
364
364
  const calls = [];
365
365
  const toolNames = tools.map(t => t.name);
366
366
  const toolRegex = new RegExp(`(${toolNames.join('|')})\\s*\\(\\s*(\\{[^}]*\\})?`, 'g');
367
-
367
+
368
368
  for (let lineNum = 0; lineNum < lines.length; lineNum++) {
369
369
  const line = lines[lineNum];
370
370
  let match;
371
-
371
+
372
372
  while ((match = toolRegex.exec(line)) !== null) {
373
373
  const name = match[1];
374
374
  const paramsStr = match[2];
375
-
375
+
376
376
  calls.push({
377
377
  name,
378
378
  params: paramsStr ? parseParams(paramsStr) : null,
@@ -383,10 +383,10 @@ function parseAllToolCalls(text, lines, tools) {
383
383
  }
384
384
  });
385
385
  }
386
-
386
+
387
387
  toolRegex.lastIndex = 0;
388
388
  }
389
-
389
+
390
390
  return calls;
391
391
  }
392
392
 
@@ -401,7 +401,7 @@ function parseParams(paramsStr) {
401
401
  .replace(/(\w+)\s*:/g, '"$1":')
402
402
  .replace(/,\s*}/g, '}')
403
403
  .replace(/\n/g, ' ');
404
-
404
+
405
405
  return JSON.parse(jsonStr);
406
406
  } catch (e) {
407
407
  return null;
@@ -414,7 +414,7 @@ function parseParams(paramsStr) {
414
414
  function validateParamType(value, schema, paramName) {
415
415
  const expectedType = schema.type;
416
416
  const actualType = typeof value;
417
-
417
+
418
418
  if (expectedType === 'string' && actualType !== 'string') {
419
419
  return `Parameter ${paramName}: Expected string, got ${actualType}`;
420
420
  }
@@ -430,7 +430,7 @@ function validateParamType(value, schema, paramName) {
430
430
  if (expectedType === 'object' && (actualType !== 'object' || value === null || Array.isArray(value))) {
431
431
  return `Parameter ${paramName}: Expected object, got ${actualType}`;
432
432
  }
433
-
433
+
434
434
  return null;
435
435
  }
436
436
 
@@ -441,7 +441,7 @@ function validateUrl(url) {
441
441
  if (!url || url.trim() === '') {
442
442
  return 'URL cannot be empty';
443
443
  }
444
-
444
+
445
445
  try {
446
446
  const parsed = new URL(url);
447
447
  if (!['http:', 'https:'].includes(parsed.protocol)) {
@@ -450,7 +450,7 @@ function validateUrl(url) {
450
450
  } catch (e) {
451
451
  return 'Invalid URL format. Example: https://example.com';
452
452
  }
453
-
453
+
454
454
  return null;
455
455
  }
456
456
 
@@ -461,20 +461,20 @@ function validateSelector(selector) {
461
461
  if (!selector || selector.trim() === '') {
462
462
  return 'Selector cannot be empty';
463
463
  }
464
-
464
+
465
465
  // Check for common mistakes
466
466
  if (selector.includes(' ')) {
467
467
  return 'Selector contains multiple consecutive spaces';
468
468
  }
469
-
469
+
470
470
  if (/^[0-9]/.test(selector) && !selector.startsWith('[')) {
471
471
  return 'Selector cannot start with a number (unless in attribute selector)';
472
472
  }
473
-
473
+
474
474
  // Check balanced brackets
475
475
  const brackets = { '[': ']', '(': ')' };
476
476
  const stack = [];
477
-
477
+
478
478
  for (const char of selector) {
479
479
  if (char in brackets) {
480
480
  stack.push(brackets[char]);
@@ -484,16 +484,16 @@ function validateSelector(selector) {
484
484
  }
485
485
  }
486
486
  }
487
-
487
+
488
488
  if (stack.length > 0) {
489
489
  return 'Unclosed bracket in selector';
490
490
  }
491
-
491
+
492
492
  // Check for empty attribute selector
493
493
  if (selector.includes('[]')) {
494
494
  return 'Empty attribute selector []';
495
495
  }
496
-
496
+
497
497
  return null;
498
498
  }
499
499
 
@@ -502,7 +502,7 @@ function validateSelector(selector) {
502
502
  */
503
503
  function findSimilarTools(name, tools) {
504
504
  const lowerName = name.toLowerCase();
505
-
505
+
506
506
  return tools
507
507
  .map(t => ({
508
508
  name: t.name,
@@ -520,14 +520,14 @@ function findSimilarTools(name, tools) {
520
520
  function calculateSimilarity(s1, s2) {
521
521
  const longer = s1.length > s2.length ? s1 : s2;
522
522
  const shorter = s1.length > s2.length ? s2 : s1;
523
-
523
+
524
524
  if (longer.length === 0) return 1.0;
525
-
525
+
526
526
  // Quick check for common prefix
527
527
  if (longer.startsWith(shorter) || shorter.startsWith(longer.substring(0, 3))) {
528
528
  return 0.8;
529
529
  }
530
-
530
+
531
531
  // Levenshtein distance
532
532
  const costs = [];
533
533
  for (let i = 0; i <= s1.length; i++) {
@@ -546,7 +546,7 @@ function calculateSimilarity(s1, s2) {
546
546
  }
547
547
  if (i > 0) costs[s2.length] = lastValue;
548
548
  }
549
-
549
+
550
550
  return (longer.length - costs[s2.length]) / longer.length;
551
551
  }
552
552
 
@@ -21,7 +21,7 @@ module.exports = {
21
21
  click: { label: 'Click Element', detail: 'Click with human-like behavior', documentation: 'Clicks on an element using ghost-cursor.', parameters: { selector: 'Element selector', humanLike: 'Use realistic movement', clickCount: 'Number of clicks', delay: 'Click delay' } },
22
22
  type: { label: 'Type Text', detail: 'Type into input field', documentation: 'Types text with realistic keystroke delays.', parameters: { selector: 'Input selector', text: 'Text to type', delay: 'Keystroke delay', clear: 'Clear first' } },
23
23
  browser_close: { label: 'Close Browser', detail: 'Close and cleanup', documentation: 'Closes the browser.', parameters: { force: 'Force close' } },
24
- solve_captcha: { label: 'Solve CAPTCHA', detail: 'Auto-solve CAPTCHAs', documentation: 'Automatically solves Turnstile, reCAPTCHA, hCaptcha.', parameters: { type: 'CAPTCHA type', timeout: 'Max solve time' } },
24
+ solve_captcha: { label: 'Solve CAPTCHA + Form', detail: 'Auto-solve + Fill forms', documentation: 'Solves CAPTCHAs and fills forms with AI field matching.', parameters: { type: 'CAPTCHA type', timeout: 'Max time', formData: 'Form data', submit: 'Submit form' } },
25
25
  random_scroll: { label: 'Random Scroll', detail: 'Human-like scrolling', documentation: 'Scrolls with human-like behavior.', parameters: { direction: 'Scroll direction', amount: 'Scroll amount', smooth: 'Smooth scrolling' } },
26
26
  find_element: { label: 'Find Element', detail: 'Locate elements', documentation: 'Finds elements by selector/xpath/text.', parameters: { selector: 'CSS selector', xpath: 'XPath', text: 'Text content', multiple: 'Return all' } },
27
27
  save_content_as_markdown: { label: 'Save as Markdown', detail: 'Export to MD', documentation: 'Saves page as Markdown file.', parameters: { filename: 'Output filename', selector: 'Content selector', includeImages: 'Include images', includeMeta: 'Include meta' } },
@@ -40,8 +40,7 @@ module.exports = {
40
40
  stream_extractor: { label: 'Extract Streams', detail: 'Get video/audio', documentation: 'Extracts stream URLs.', parameters: { types: 'Stream types', quality: 'Quality' } },
41
41
  js_scrape: { label: 'JS Scrape', detail: 'Scrape JS content', documentation: 'Scrapes JS-rendered content.', parameters: { selector: 'CSS selector', waitForJS: 'Wait for JS', timeout: 'Max wait' } },
42
42
  execute_js: { label: 'Execute JS', detail: 'Run JavaScript', documentation: 'Executes custom JavaScript.', parameters: { code: 'JS code', returnValue: 'Return result' } },
43
- player_api_hook: { label: 'Player API Hook', detail: 'Video player control', documentation: 'Hooks into video players.', parameters: { playerType: 'Player type', action: 'Action' } },
44
- form_automator: { label: 'Automate Form', detail: 'Fill and submit', documentation: 'Auto-fills and submits forms.', parameters: { selector: 'Form selector', data: 'Form data', submit: 'Submit', humanLike: 'Human delays' } }
43
+ player_api_hook: { label: 'Player API Hook', detail: 'Video player control', documentation: 'Hooks into video players.', parameters: { playerType: 'Player type', action: 'Action' } }
45
44
  },
46
45
  diagnostics: {
47
46
  browserNotInit: 'Browser not initialized. Call browser_init first.',
@@ -11,7 +11,7 @@ module.exports = {
11
11
  click: { label: 'क्लिक करें', detail: 'मानव-जैसा क्लिक', documentation: 'ghost-cursor से क्लिक करता है।', parameters: { selector: 'एलीमेंट selector', humanLike: 'वास्तविक मूवमेंट', clickCount: 'क्लिक संख्या', delay: 'देरी' } },
12
12
  type: { label: 'टाइप करें', detail: 'इनपुट में टाइप', documentation: 'वास्तविक कीस्ट्रोक के साथ टाइप करता है।', parameters: { selector: 'इनपुट selector', text: 'टेक्स्ट', delay: 'कीस्ट्रोक देरी', clear: 'पहले साफ करें' } },
13
13
  browser_close: { label: 'ब्राउज़र बंद करें', detail: 'बंद और क्लीनअप', documentation: 'ब्राउज़र बंद करता है।', parameters: { force: 'फोर्स क्लोज़' } },
14
- solve_captcha: { label: 'CAPTCHA हल करें', detail: 'ऑटो-सॉल्व', documentation: 'Turnstile, reCAPTCHA हल करता है।', parameters: { type: 'CAPTCHA प्रकार', timeout: 'अधिकतम समय' } },
14
+ solve_captcha: { label: 'CAPTCHA + फॉर्म', detail: 'ऑटो-सॉल्व + फॉर्म भरें', documentation: 'CAPTCHA हल करता है और फॉर्म भी भरता है।', parameters: { type: 'CAPTCHA प्रकार', timeout: 'अधिकतम समय', formData: 'फॉर्म डेटा', submit: 'सबमिट करें' } },
15
15
  random_scroll: { label: 'रैंडम स्क्रॉल', detail: 'मानव-जैसा स्क्रॉल', documentation: 'रैंडम स्क्रॉल करता है।', parameters: { direction: 'दिशा', amount: 'मात्रा', smooth: 'स्मूथ' } },
16
16
  find_element: { label: 'एलीमेंट खोजें', detail: 'पेज पर खोजें', documentation: 'selector/xpath से खोजता है।', parameters: { selector: 'CSS selector', xpath: 'XPath', text: 'टेक्स्ट', multiple: 'सभी लौटाएं' } },
17
17
  save_content_as_markdown: { label: 'MD में सेव', detail: 'Markdown एक्सपोर्ट', documentation: 'Markdown फाइल में सेव करता है।', parameters: { filename: 'फाइलनेम', selector: 'कंटेंट selector', includeImages: 'इमेज शामिल', includeMeta: 'मेटा शामिल' } },
@@ -30,8 +30,7 @@ module.exports = {
30
30
  stream_extractor: { label: 'स्ट्रीम निकालें', detail: 'वीडियो/ऑडियो URL', documentation: 'स्ट्रीम URLs निकालता है।', parameters: { types: 'प्रकार', quality: 'क्वालिटी' } },
31
31
  js_scrape: { label: 'JS स्क्रैप', detail: 'JS कंटेंट', documentation: 'JS-रेंडर्ड कंटेंट।', parameters: { selector: 'selector', waitForJS: 'JS इंतजार', timeout: 'अधिकतम' } },
32
32
  execute_js: { label: 'JS चलाएं', detail: 'JavaScript रन', documentation: 'कस्टम JS चलाता है।', parameters: { code: 'कोड', returnValue: 'रिज़ल्ट लौटाएं' } },
33
- player_api_hook: { label: 'Player Hook', detail: 'वीडियो प्लेयर', documentation: 'प्लेयर में हुक करता है।', parameters: { playerType: 'प्लेयर', action: 'एक्शन' } },
34
- form_automator: { label: 'फॉर्म ऑटोमेट', detail: 'फॉर्म भरें', documentation: 'फॉर्म भरता और सबमिट करता है।', parameters: { selector: 'फॉर्म selector', data: 'डेटा', submit: 'सबमिट', humanLike: 'मानव देरी' } }
33
+ player_api_hook: { label: 'Player Hook', detail: 'वीडियो प्लेयर', documentation: 'प्लेयर में हुक करता है।', parameters: { playerType: 'प्लेयर', action: 'एक्शन' } }
35
34
  },
36
35
  diagnostics: {
37
36
  browserNotInit: 'ब्राउज़र इनिशियलाइज़ नहीं। पहले browser_init करें।',