@sparkleideas/browser 3.0.0-alpha.7 → 3.0.0-alpha.9

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 (67) hide show
  1. package/.agentic-flow/intelligence.json +17 -0
  2. package/agents/architect.yaml +1 -1
  3. package/agents/coder.yaml +1 -1
  4. package/agents/reviewer.yaml +1 -1
  5. package/agents/security-architect.yaml +1 -1
  6. package/agents/tester.yaml +1 -1
  7. package/dist/agent/index.d.ts +25 -0
  8. package/dist/agent/index.d.ts.map +1 -0
  9. package/dist/agent/index.js +33 -0
  10. package/dist/agent/index.js.map +1 -0
  11. package/dist/application/browser-service.d.ts +228 -0
  12. package/dist/application/browser-service.d.ts.map +1 -0
  13. package/dist/application/browser-service.js +470 -0
  14. package/dist/application/browser-service.js.map +1 -0
  15. package/dist/domain/types.d.ts +428 -0
  16. package/dist/domain/types.d.ts.map +1 -0
  17. package/dist/domain/types.js +95 -0
  18. package/dist/domain/types.js.map +1 -0
  19. package/dist/index.d.ts +131 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +84 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/infrastructure/agent-browser-adapter.d.ts +134 -0
  24. package/dist/infrastructure/agent-browser-adapter.d.ts.map +1 -0
  25. package/dist/infrastructure/agent-browser-adapter.js +551 -0
  26. package/dist/infrastructure/agent-browser-adapter.js.map +1 -0
  27. package/dist/infrastructure/hooks-integration.d.ts +109 -0
  28. package/dist/infrastructure/hooks-integration.d.ts.map +1 -0
  29. package/dist/infrastructure/hooks-integration.js +111 -0
  30. package/dist/infrastructure/hooks-integration.js.map +1 -0
  31. package/dist/infrastructure/memory-integration.d.ts +149 -0
  32. package/dist/infrastructure/memory-integration.d.ts.map +1 -0
  33. package/dist/infrastructure/memory-integration.js +335 -0
  34. package/dist/infrastructure/memory-integration.js.map +1 -0
  35. package/dist/infrastructure/reasoningbank-adapter.d.ts +90 -0
  36. package/dist/infrastructure/reasoningbank-adapter.d.ts.map +1 -0
  37. package/dist/infrastructure/reasoningbank-adapter.js +224 -0
  38. package/dist/infrastructure/reasoningbank-adapter.js.map +1 -0
  39. package/dist/infrastructure/security-integration.d.ts +80 -0
  40. package/dist/infrastructure/security-integration.d.ts.map +1 -0
  41. package/dist/infrastructure/security-integration.js +404 -0
  42. package/dist/infrastructure/security-integration.js.map +1 -0
  43. package/dist/infrastructure/workflow-templates.d.ts +95 -0
  44. package/dist/infrastructure/workflow-templates.d.ts.map +1 -0
  45. package/dist/infrastructure/workflow-templates.js +366 -0
  46. package/dist/infrastructure/workflow-templates.js.map +1 -0
  47. package/dist/mcp-tools/browser-tools.d.ts +18 -0
  48. package/dist/mcp-tools/browser-tools.d.ts.map +1 -0
  49. package/dist/mcp-tools/browser-tools.js +1163 -0
  50. package/dist/mcp-tools/browser-tools.js.map +1 -0
  51. package/dist/mcp-tools/index.d.ts +6 -0
  52. package/dist/mcp-tools/index.d.ts.map +1 -0
  53. package/dist/mcp-tools/index.js +6 -0
  54. package/dist/mcp-tools/index.js.map +1 -0
  55. package/dist/skill/index.d.ts +15 -0
  56. package/dist/skill/index.d.ts.map +1 -0
  57. package/dist/skill/index.js +23 -0
  58. package/dist/skill/index.js.map +1 -0
  59. package/package.json +3 -4
  60. package/src/application/browser-service.ts +1 -1
  61. package/src/domain/types.ts +1 -1
  62. package/src/index.ts +2 -2
  63. package/src/infrastructure/hooks-integration.ts +1 -1
  64. package/src/infrastructure/memory-integration.ts +2 -2
  65. package/src/infrastructure/reasoningbank-adapter.ts +1 -1
  66. package/src/mcp-tools/browser-tools.ts +1 -1
  67. package/src/skill/index.ts +1 -1
@@ -0,0 +1,1163 @@
1
+ /**
2
+ * @sparkleideas/browser - MCP Tools
3
+ * 50+ browser automation tools for claude-flow MCP server
4
+ */
5
+ import { AgentBrowserAdapter } from '../infrastructure/agent-browser-adapter.js';
6
+ // Session registry for multi-agent coordination
7
+ const sessions = new Map();
8
+ function getAdapter(sessionId) {
9
+ const id = sessionId || 'default';
10
+ if (!sessions.has(id)) {
11
+ sessions.set(id, new AgentBrowserAdapter({ session: id }));
12
+ }
13
+ return sessions.get(id);
14
+ }
15
+ // ============================================================================
16
+ // Navigation Tools
17
+ // ============================================================================
18
+ const navigationTools = [
19
+ {
20
+ name: 'browser/open',
21
+ description: 'Navigate to a URL. Returns page title and final URL after redirects.',
22
+ category: 'browser-navigation',
23
+ inputSchema: {
24
+ type: 'object',
25
+ properties: {
26
+ url: { type: 'string', description: 'URL to navigate to' },
27
+ session: { type: 'string', description: 'Session ID for isolated browser instance' },
28
+ waitUntil: {
29
+ type: 'string',
30
+ enum: ['load', 'domcontentloaded', 'networkidle'],
31
+ description: 'When to consider navigation complete',
32
+ },
33
+ headers: {
34
+ type: 'object',
35
+ description: 'HTTP headers to set (scoped to URL origin)',
36
+ additionalProperties: { type: 'string' },
37
+ },
38
+ },
39
+ required: ['url'],
40
+ },
41
+ handler: async (input) => {
42
+ const adapter = getAdapter(input.session);
43
+ return adapter.open({
44
+ url: input.url,
45
+ waitUntil: input.waitUntil,
46
+ headers: input.headers,
47
+ });
48
+ },
49
+ },
50
+ {
51
+ name: 'browser/back',
52
+ description: 'Navigate back in browser history',
53
+ category: 'browser-navigation',
54
+ inputSchema: {
55
+ type: 'object',
56
+ properties: {
57
+ session: { type: 'string', description: 'Session ID' },
58
+ },
59
+ },
60
+ handler: async (input) => {
61
+ const adapter = getAdapter(input.session);
62
+ return adapter.back();
63
+ },
64
+ },
65
+ {
66
+ name: 'browser/forward',
67
+ description: 'Navigate forward in browser history',
68
+ category: 'browser-navigation',
69
+ inputSchema: {
70
+ type: 'object',
71
+ properties: {
72
+ session: { type: 'string', description: 'Session ID' },
73
+ },
74
+ },
75
+ handler: async (input) => {
76
+ const adapter = getAdapter(input.session);
77
+ return adapter.forward();
78
+ },
79
+ },
80
+ {
81
+ name: 'browser/reload',
82
+ description: 'Reload the current page',
83
+ category: 'browser-navigation',
84
+ inputSchema: {
85
+ type: 'object',
86
+ properties: {
87
+ session: { type: 'string', description: 'Session ID' },
88
+ },
89
+ },
90
+ handler: async (input) => {
91
+ const adapter = getAdapter(input.session);
92
+ return adapter.reload();
93
+ },
94
+ },
95
+ {
96
+ name: 'browser/close',
97
+ description: 'Close the browser session',
98
+ category: 'browser-navigation',
99
+ inputSchema: {
100
+ type: 'object',
101
+ properties: {
102
+ session: { type: 'string', description: 'Session ID' },
103
+ },
104
+ },
105
+ handler: async (input) => {
106
+ const adapter = getAdapter(input.session);
107
+ const result = await adapter.close();
108
+ sessions.delete(input.session || 'default');
109
+ return result;
110
+ },
111
+ },
112
+ ];
113
+ // ============================================================================
114
+ // Snapshot Tools (AI-Optimized)
115
+ // ============================================================================
116
+ const snapshotTools = [
117
+ {
118
+ name: 'browser/snapshot',
119
+ description: 'Get accessibility tree with element refs (@e1, @e2). Best for AI - use refs to interact with elements. Returns structured tree with interactive elements highlighted.',
120
+ category: 'browser-snapshot',
121
+ inputSchema: {
122
+ type: 'object',
123
+ properties: {
124
+ session: { type: 'string', description: 'Session ID' },
125
+ interactive: { type: 'boolean', description: 'Only show interactive elements (buttons, links, inputs)', default: true },
126
+ compact: { type: 'boolean', description: 'Remove empty structural elements', default: true },
127
+ depth: { type: 'number', description: 'Limit tree depth (e.g., 3 levels)' },
128
+ selector: { type: 'string', description: 'Scope snapshot to CSS selector' },
129
+ },
130
+ },
131
+ handler: async (input) => {
132
+ const adapter = getAdapter(input.session);
133
+ return adapter.snapshot({
134
+ interactive: input.interactive !== false,
135
+ compact: input.compact !== false,
136
+ depth: input.depth,
137
+ selector: input.selector,
138
+ });
139
+ },
140
+ },
141
+ {
142
+ name: 'browser/screenshot',
143
+ description: 'Capture screenshot. Returns base64 PNG if no path specified.',
144
+ category: 'browser-snapshot',
145
+ inputSchema: {
146
+ type: 'object',
147
+ properties: {
148
+ session: { type: 'string', description: 'Session ID' },
149
+ path: { type: 'string', description: 'File path to save (optional, returns base64 if omitted)' },
150
+ fullPage: { type: 'boolean', description: 'Capture full scrollable page', default: false },
151
+ },
152
+ },
153
+ handler: async (input) => {
154
+ const adapter = getAdapter(input.session);
155
+ return adapter.screenshot({
156
+ path: input.path,
157
+ fullPage: input.fullPage,
158
+ });
159
+ },
160
+ },
161
+ {
162
+ name: 'browser/pdf',
163
+ description: 'Save page as PDF',
164
+ category: 'browser-snapshot',
165
+ inputSchema: {
166
+ type: 'object',
167
+ properties: {
168
+ session: { type: 'string', description: 'Session ID' },
169
+ path: { type: 'string', description: 'File path to save PDF' },
170
+ },
171
+ required: ['path'],
172
+ },
173
+ handler: async (input) => {
174
+ const adapter = getAdapter(input.session);
175
+ return adapter.pdf(input.path);
176
+ },
177
+ },
178
+ ];
179
+ // ============================================================================
180
+ // Interaction Tools
181
+ // ============================================================================
182
+ const interactionTools = [
183
+ {
184
+ name: 'browser/click',
185
+ description: 'Click an element. Use @e1 refs from snapshot or CSS selectors.',
186
+ category: 'browser-interaction',
187
+ inputSchema: {
188
+ type: 'object',
189
+ properties: {
190
+ session: { type: 'string', description: 'Session ID' },
191
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
192
+ button: { type: 'string', enum: ['left', 'right', 'middle'], default: 'left' },
193
+ clickCount: { type: 'number', description: 'Number of clicks (2 for double-click)' },
194
+ force: { type: 'boolean', description: 'Force click even if element is not visible' },
195
+ },
196
+ required: ['target'],
197
+ },
198
+ handler: async (input) => {
199
+ const adapter = getAdapter(input.session);
200
+ return adapter.click({
201
+ target: input.target,
202
+ button: input.button,
203
+ clickCount: input.clickCount,
204
+ force: input.force,
205
+ });
206
+ },
207
+ },
208
+ {
209
+ name: 'browser/fill',
210
+ description: 'Clear and fill an input field. Use @e1 refs from snapshot.',
211
+ category: 'browser-interaction',
212
+ inputSchema: {
213
+ type: 'object',
214
+ properties: {
215
+ session: { type: 'string', description: 'Session ID' },
216
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
217
+ value: { type: 'string', description: 'Text to fill' },
218
+ force: { type: 'boolean', description: 'Force fill even if element is not visible' },
219
+ },
220
+ required: ['target', 'value'],
221
+ },
222
+ handler: async (input) => {
223
+ const adapter = getAdapter(input.session);
224
+ return adapter.fill({
225
+ target: input.target,
226
+ value: input.value,
227
+ force: input.force,
228
+ });
229
+ },
230
+ },
231
+ {
232
+ name: 'browser/type',
233
+ description: 'Type text character by character (with key events). Slower than fill but simulates real typing.',
234
+ category: 'browser-interaction',
235
+ inputSchema: {
236
+ type: 'object',
237
+ properties: {
238
+ session: { type: 'string', description: 'Session ID' },
239
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
240
+ text: { type: 'string', description: 'Text to type' },
241
+ delay: { type: 'number', description: 'Delay between keystrokes in ms' },
242
+ },
243
+ required: ['target', 'text'],
244
+ },
245
+ handler: async (input) => {
246
+ const adapter = getAdapter(input.session);
247
+ return adapter.type({
248
+ target: input.target,
249
+ text: input.text,
250
+ delay: input.delay,
251
+ });
252
+ },
253
+ },
254
+ {
255
+ name: 'browser/press',
256
+ description: 'Press a keyboard key (Enter, Tab, Escape, Control+a, etc.)',
257
+ category: 'browser-interaction',
258
+ inputSchema: {
259
+ type: 'object',
260
+ properties: {
261
+ session: { type: 'string', description: 'Session ID' },
262
+ key: { type: 'string', description: 'Key to press (Enter, Tab, Control+a, etc.)' },
263
+ delay: { type: 'number', description: 'Key hold duration in ms' },
264
+ },
265
+ required: ['key'],
266
+ },
267
+ handler: async (input) => {
268
+ const adapter = getAdapter(input.session);
269
+ return adapter.press(input.key, input.delay);
270
+ },
271
+ },
272
+ {
273
+ name: 'browser/hover',
274
+ description: 'Hover over an element',
275
+ category: 'browser-interaction',
276
+ inputSchema: {
277
+ type: 'object',
278
+ properties: {
279
+ session: { type: 'string', description: 'Session ID' },
280
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
281
+ },
282
+ required: ['target'],
283
+ },
284
+ handler: async (input) => {
285
+ const adapter = getAdapter(input.session);
286
+ return adapter.hover(input.target);
287
+ },
288
+ },
289
+ {
290
+ name: 'browser/select',
291
+ description: 'Select dropdown option by value',
292
+ category: 'browser-interaction',
293
+ inputSchema: {
294
+ type: 'object',
295
+ properties: {
296
+ session: { type: 'string', description: 'Session ID' },
297
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
298
+ value: { type: 'string', description: 'Option value to select' },
299
+ },
300
+ required: ['target', 'value'],
301
+ },
302
+ handler: async (input) => {
303
+ const adapter = getAdapter(input.session);
304
+ return adapter.select(input.target, input.value);
305
+ },
306
+ },
307
+ {
308
+ name: 'browser/check',
309
+ description: 'Check a checkbox',
310
+ category: 'browser-interaction',
311
+ inputSchema: {
312
+ type: 'object',
313
+ properties: {
314
+ session: { type: 'string', description: 'Session ID' },
315
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
316
+ },
317
+ required: ['target'],
318
+ },
319
+ handler: async (input) => {
320
+ const adapter = getAdapter(input.session);
321
+ return adapter.check(input.target);
322
+ },
323
+ },
324
+ {
325
+ name: 'browser/uncheck',
326
+ description: 'Uncheck a checkbox',
327
+ category: 'browser-interaction',
328
+ inputSchema: {
329
+ type: 'object',
330
+ properties: {
331
+ session: { type: 'string', description: 'Session ID' },
332
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
333
+ },
334
+ required: ['target'],
335
+ },
336
+ handler: async (input) => {
337
+ const adapter = getAdapter(input.session);
338
+ return adapter.uncheck(input.target);
339
+ },
340
+ },
341
+ {
342
+ name: 'browser/scroll',
343
+ description: 'Scroll the page or element',
344
+ category: 'browser-interaction',
345
+ inputSchema: {
346
+ type: 'object',
347
+ properties: {
348
+ session: { type: 'string', description: 'Session ID' },
349
+ direction: { type: 'string', enum: ['up', 'down', 'left', 'right'], description: 'Scroll direction' },
350
+ pixels: { type: 'number', description: 'Pixels to scroll (default: viewport height)' },
351
+ },
352
+ required: ['direction'],
353
+ },
354
+ handler: async (input) => {
355
+ const adapter = getAdapter(input.session);
356
+ return adapter.scroll(input.direction, input.pixels);
357
+ },
358
+ },
359
+ {
360
+ name: 'browser/upload',
361
+ description: 'Upload files to a file input',
362
+ category: 'browser-interaction',
363
+ inputSchema: {
364
+ type: 'object',
365
+ properties: {
366
+ session: { type: 'string', description: 'Session ID' },
367
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
368
+ files: { type: 'array', items: { type: 'string' }, description: 'File paths to upload' },
369
+ },
370
+ required: ['target', 'files'],
371
+ },
372
+ handler: async (input) => {
373
+ const adapter = getAdapter(input.session);
374
+ return adapter.upload(input.target, input.files);
375
+ },
376
+ },
377
+ ];
378
+ // ============================================================================
379
+ // Get Info Tools
380
+ // ============================================================================
381
+ const getInfoTools = [
382
+ {
383
+ name: 'browser/get-text',
384
+ description: 'Get text content of an element',
385
+ category: 'browser-info',
386
+ inputSchema: {
387
+ type: 'object',
388
+ properties: {
389
+ session: { type: 'string', description: 'Session ID' },
390
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
391
+ },
392
+ required: ['target'],
393
+ },
394
+ handler: async (input) => {
395
+ const adapter = getAdapter(input.session);
396
+ return adapter.getText(input.target);
397
+ },
398
+ },
399
+ {
400
+ name: 'browser/get-html',
401
+ description: 'Get innerHTML of an element',
402
+ category: 'browser-info',
403
+ inputSchema: {
404
+ type: 'object',
405
+ properties: {
406
+ session: { type: 'string', description: 'Session ID' },
407
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
408
+ },
409
+ required: ['target'],
410
+ },
411
+ handler: async (input) => {
412
+ const adapter = getAdapter(input.session);
413
+ return adapter.getHtml(input.target);
414
+ },
415
+ },
416
+ {
417
+ name: 'browser/get-value',
418
+ description: 'Get value of an input element',
419
+ category: 'browser-info',
420
+ inputSchema: {
421
+ type: 'object',
422
+ properties: {
423
+ session: { type: 'string', description: 'Session ID' },
424
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
425
+ },
426
+ required: ['target'],
427
+ },
428
+ handler: async (input) => {
429
+ const adapter = getAdapter(input.session);
430
+ return adapter.getValue(input.target);
431
+ },
432
+ },
433
+ {
434
+ name: 'browser/get-attr',
435
+ description: 'Get an attribute value from an element',
436
+ category: 'browser-info',
437
+ inputSchema: {
438
+ type: 'object',
439
+ properties: {
440
+ session: { type: 'string', description: 'Session ID' },
441
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
442
+ attribute: { type: 'string', description: 'Attribute name (href, src, data-*, etc.)' },
443
+ },
444
+ required: ['target', 'attribute'],
445
+ },
446
+ handler: async (input) => {
447
+ const adapter = getAdapter(input.session);
448
+ return adapter.getAttr(input.target, input.attribute);
449
+ },
450
+ },
451
+ {
452
+ name: 'browser/get-title',
453
+ description: 'Get the page title',
454
+ category: 'browser-info',
455
+ inputSchema: {
456
+ type: 'object',
457
+ properties: {
458
+ session: { type: 'string', description: 'Session ID' },
459
+ },
460
+ },
461
+ handler: async (input) => {
462
+ const adapter = getAdapter(input.session);
463
+ return adapter.getTitle();
464
+ },
465
+ },
466
+ {
467
+ name: 'browser/get-url',
468
+ description: 'Get the current page URL',
469
+ category: 'browser-info',
470
+ inputSchema: {
471
+ type: 'object',
472
+ properties: {
473
+ session: { type: 'string', description: 'Session ID' },
474
+ },
475
+ },
476
+ handler: async (input) => {
477
+ const adapter = getAdapter(input.session);
478
+ return adapter.getUrl();
479
+ },
480
+ },
481
+ {
482
+ name: 'browser/get-count',
483
+ description: 'Count elements matching a selector',
484
+ category: 'browser-info',
485
+ inputSchema: {
486
+ type: 'object',
487
+ properties: {
488
+ session: { type: 'string', description: 'Session ID' },
489
+ selector: { type: 'string', description: 'CSS selector to count' },
490
+ },
491
+ required: ['selector'],
492
+ },
493
+ handler: async (input) => {
494
+ const adapter = getAdapter(input.session);
495
+ return adapter.getCount(input.selector);
496
+ },
497
+ },
498
+ ];
499
+ // ============================================================================
500
+ // State Check Tools
501
+ // ============================================================================
502
+ const stateTools = [
503
+ {
504
+ name: 'browser/is-visible',
505
+ description: 'Check if an element is visible',
506
+ category: 'browser-state',
507
+ inputSchema: {
508
+ type: 'object',
509
+ properties: {
510
+ session: { type: 'string', description: 'Session ID' },
511
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
512
+ },
513
+ required: ['target'],
514
+ },
515
+ handler: async (input) => {
516
+ const adapter = getAdapter(input.session);
517
+ return adapter.isVisible(input.target);
518
+ },
519
+ },
520
+ {
521
+ name: 'browser/is-enabled',
522
+ description: 'Check if an element is enabled',
523
+ category: 'browser-state',
524
+ inputSchema: {
525
+ type: 'object',
526
+ properties: {
527
+ session: { type: 'string', description: 'Session ID' },
528
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
529
+ },
530
+ required: ['target'],
531
+ },
532
+ handler: async (input) => {
533
+ const adapter = getAdapter(input.session);
534
+ return adapter.isEnabled(input.target);
535
+ },
536
+ },
537
+ {
538
+ name: 'browser/is-checked',
539
+ description: 'Check if a checkbox is checked',
540
+ category: 'browser-state',
541
+ inputSchema: {
542
+ type: 'object',
543
+ properties: {
544
+ session: { type: 'string', description: 'Session ID' },
545
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
546
+ },
547
+ required: ['target'],
548
+ },
549
+ handler: async (input) => {
550
+ const adapter = getAdapter(input.session);
551
+ return adapter.isChecked(input.target);
552
+ },
553
+ },
554
+ ];
555
+ // ============================================================================
556
+ // Wait Tools
557
+ // ============================================================================
558
+ const waitTools = [
559
+ {
560
+ name: 'browser/wait',
561
+ description: 'Wait for element, time, text, URL, or load state',
562
+ category: 'browser-wait',
563
+ inputSchema: {
564
+ type: 'object',
565
+ properties: {
566
+ session: { type: 'string', description: 'Session ID' },
567
+ selector: { type: 'string', description: 'Wait for element to be visible' },
568
+ timeout: { type: 'number', description: 'Wait for milliseconds' },
569
+ text: { type: 'string', description: 'Wait for text to appear on page' },
570
+ url: { type: 'string', description: 'Wait for URL pattern (glob)' },
571
+ load: { type: 'string', enum: ['load', 'domcontentloaded', 'networkidle'], description: 'Wait for load state' },
572
+ fn: { type: 'string', description: 'Wait for JavaScript condition to be true' },
573
+ },
574
+ },
575
+ handler: async (input) => {
576
+ const adapter = getAdapter(input.session);
577
+ return adapter.wait({
578
+ selector: input.selector,
579
+ timeout: input.timeout,
580
+ text: input.text,
581
+ url: input.url,
582
+ load: input.load,
583
+ fn: input.fn,
584
+ });
585
+ },
586
+ },
587
+ ];
588
+ // ============================================================================
589
+ // JavaScript Execution
590
+ // ============================================================================
591
+ const evalTools = [
592
+ {
593
+ name: 'browser/eval',
594
+ description: 'Execute JavaScript in the page context',
595
+ category: 'browser-eval',
596
+ inputSchema: {
597
+ type: 'object',
598
+ properties: {
599
+ session: { type: 'string', description: 'Session ID' },
600
+ script: { type: 'string', description: 'JavaScript code to execute' },
601
+ },
602
+ required: ['script'],
603
+ },
604
+ handler: async (input) => {
605
+ const adapter = getAdapter(input.session);
606
+ return adapter.eval({ script: input.script });
607
+ },
608
+ },
609
+ ];
610
+ // ============================================================================
611
+ // Storage Tools
612
+ // ============================================================================
613
+ const storageTools = [
614
+ {
615
+ name: 'browser/cookies-get',
616
+ description: 'Get all cookies for the current page',
617
+ category: 'browser-storage',
618
+ inputSchema: {
619
+ type: 'object',
620
+ properties: {
621
+ session: { type: 'string', description: 'Session ID' },
622
+ },
623
+ },
624
+ handler: async (input) => {
625
+ const adapter = getAdapter(input.session);
626
+ return adapter.getCookies();
627
+ },
628
+ },
629
+ {
630
+ name: 'browser/cookies-set',
631
+ description: 'Set a cookie',
632
+ category: 'browser-storage',
633
+ inputSchema: {
634
+ type: 'object',
635
+ properties: {
636
+ session: { type: 'string', description: 'Session ID' },
637
+ name: { type: 'string', description: 'Cookie name' },
638
+ value: { type: 'string', description: 'Cookie value' },
639
+ },
640
+ required: ['name', 'value'],
641
+ },
642
+ handler: async (input) => {
643
+ const adapter = getAdapter(input.session);
644
+ return adapter.setCookie(input.name, input.value);
645
+ },
646
+ },
647
+ {
648
+ name: 'browser/cookies-clear',
649
+ description: 'Clear all cookies',
650
+ category: 'browser-storage',
651
+ inputSchema: {
652
+ type: 'object',
653
+ properties: {
654
+ session: { type: 'string', description: 'Session ID' },
655
+ },
656
+ },
657
+ handler: async (input) => {
658
+ const adapter = getAdapter(input.session);
659
+ return adapter.clearCookies();
660
+ },
661
+ },
662
+ {
663
+ name: 'browser/localstorage-get',
664
+ description: 'Get localStorage value (or all if no key)',
665
+ category: 'browser-storage',
666
+ inputSchema: {
667
+ type: 'object',
668
+ properties: {
669
+ session: { type: 'string', description: 'Session ID' },
670
+ key: { type: 'string', description: 'Key to get (omit for all)' },
671
+ },
672
+ },
673
+ handler: async (input) => {
674
+ const adapter = getAdapter(input.session);
675
+ return adapter.getLocalStorage(input.key);
676
+ },
677
+ },
678
+ {
679
+ name: 'browser/localstorage-set',
680
+ description: 'Set localStorage value',
681
+ category: 'browser-storage',
682
+ inputSchema: {
683
+ type: 'object',
684
+ properties: {
685
+ session: { type: 'string', description: 'Session ID' },
686
+ key: { type: 'string', description: 'Key to set' },
687
+ value: { type: 'string', description: 'Value to set' },
688
+ },
689
+ required: ['key', 'value'],
690
+ },
691
+ handler: async (input) => {
692
+ const adapter = getAdapter(input.session);
693
+ return adapter.setLocalStorage(input.key, input.value);
694
+ },
695
+ },
696
+ ];
697
+ // ============================================================================
698
+ // Network Tools
699
+ // ============================================================================
700
+ const networkTools = [
701
+ {
702
+ name: 'browser/network-route',
703
+ description: 'Intercept, block, or mock network requests',
704
+ category: 'browser-network',
705
+ inputSchema: {
706
+ type: 'object',
707
+ properties: {
708
+ session: { type: 'string', description: 'Session ID' },
709
+ urlPattern: { type: 'string', description: 'URL pattern to match (glob)' },
710
+ abort: { type: 'boolean', description: 'Block matching requests' },
711
+ body: { type: 'string', description: 'Mock response body (JSON string)' },
712
+ status: { type: 'number', description: 'Mock response status code' },
713
+ },
714
+ required: ['urlPattern'],
715
+ },
716
+ handler: async (input) => {
717
+ const adapter = getAdapter(input.session);
718
+ return adapter.networkRoute({
719
+ urlPattern: input.urlPattern,
720
+ abort: input.abort,
721
+ body: input.body,
722
+ status: input.status,
723
+ });
724
+ },
725
+ },
726
+ {
727
+ name: 'browser/network-unroute',
728
+ description: 'Remove network route',
729
+ category: 'browser-network',
730
+ inputSchema: {
731
+ type: 'object',
732
+ properties: {
733
+ session: { type: 'string', description: 'Session ID' },
734
+ urlPattern: { type: 'string', description: 'URL pattern to remove (omit for all)' },
735
+ },
736
+ },
737
+ handler: async (input) => {
738
+ const adapter = getAdapter(input.session);
739
+ return adapter.networkUnroute(input.urlPattern);
740
+ },
741
+ },
742
+ {
743
+ name: 'browser/network-requests',
744
+ description: 'Get tracked network requests',
745
+ category: 'browser-network',
746
+ inputSchema: {
747
+ type: 'object',
748
+ properties: {
749
+ session: { type: 'string', description: 'Session ID' },
750
+ filter: { type: 'string', description: 'Filter by URL substring' },
751
+ },
752
+ },
753
+ handler: async (input) => {
754
+ const adapter = getAdapter(input.session);
755
+ return adapter.networkRequests(input.filter);
756
+ },
757
+ },
758
+ ];
759
+ // ============================================================================
760
+ // Tab & Session Tools
761
+ // ============================================================================
762
+ const tabTools = [
763
+ {
764
+ name: 'browser/tab-list',
765
+ description: 'List all open tabs',
766
+ category: 'browser-tabs',
767
+ inputSchema: {
768
+ type: 'object',
769
+ properties: {
770
+ session: { type: 'string', description: 'Session ID' },
771
+ },
772
+ },
773
+ handler: async (input) => {
774
+ const adapter = getAdapter(input.session);
775
+ return adapter.listTabs();
776
+ },
777
+ },
778
+ {
779
+ name: 'browser/tab-new',
780
+ description: 'Open a new tab',
781
+ category: 'browser-tabs',
782
+ inputSchema: {
783
+ type: 'object',
784
+ properties: {
785
+ session: { type: 'string', description: 'Session ID' },
786
+ url: { type: 'string', description: 'URL to open in new tab' },
787
+ },
788
+ },
789
+ handler: async (input) => {
790
+ const adapter = getAdapter(input.session);
791
+ return adapter.newTab(input.url);
792
+ },
793
+ },
794
+ {
795
+ name: 'browser/tab-switch',
796
+ description: 'Switch to a specific tab',
797
+ category: 'browser-tabs',
798
+ inputSchema: {
799
+ type: 'object',
800
+ properties: {
801
+ session: { type: 'string', description: 'Session ID' },
802
+ index: { type: 'number', description: 'Tab index (0-based)' },
803
+ },
804
+ required: ['index'],
805
+ },
806
+ handler: async (input) => {
807
+ const adapter = getAdapter(input.session);
808
+ return adapter.switchTab(input.index);
809
+ },
810
+ },
811
+ {
812
+ name: 'browser/tab-close',
813
+ description: 'Close a tab',
814
+ category: 'browser-tabs',
815
+ inputSchema: {
816
+ type: 'object',
817
+ properties: {
818
+ session: { type: 'string', description: 'Session ID' },
819
+ index: { type: 'number', description: 'Tab index to close (current if omitted)' },
820
+ },
821
+ },
822
+ handler: async (input) => {
823
+ const adapter = getAdapter(input.session);
824
+ return adapter.closeTab(input.index);
825
+ },
826
+ },
827
+ {
828
+ name: 'browser/session-list',
829
+ description: 'List all active browser sessions',
830
+ category: 'browser-session',
831
+ inputSchema: {
832
+ type: 'object',
833
+ properties: {},
834
+ },
835
+ handler: async () => {
836
+ const adapter = getAdapter();
837
+ return adapter.listSessions();
838
+ },
839
+ },
840
+ ];
841
+ // ============================================================================
842
+ // Settings Tools
843
+ // ============================================================================
844
+ const settingsTools = [
845
+ {
846
+ name: 'browser/set-viewport',
847
+ description: 'Set browser viewport size',
848
+ category: 'browser-settings',
849
+ inputSchema: {
850
+ type: 'object',
851
+ properties: {
852
+ session: { type: 'string', description: 'Session ID' },
853
+ width: { type: 'number', description: 'Viewport width' },
854
+ height: { type: 'number', description: 'Viewport height' },
855
+ },
856
+ required: ['width', 'height'],
857
+ },
858
+ handler: async (input) => {
859
+ const adapter = getAdapter(input.session);
860
+ return adapter.setViewport(input.width, input.height);
861
+ },
862
+ },
863
+ {
864
+ name: 'browser/set-device',
865
+ description: 'Emulate a device (iPhone 14, Pixel 5, etc.)',
866
+ category: 'browser-settings',
867
+ inputSchema: {
868
+ type: 'object',
869
+ properties: {
870
+ session: { type: 'string', description: 'Session ID' },
871
+ device: { type: 'string', description: 'Device name (e.g., "iPhone 14", "Pixel 5")' },
872
+ },
873
+ required: ['device'],
874
+ },
875
+ handler: async (input) => {
876
+ const adapter = getAdapter(input.session);
877
+ return adapter.setDevice(input.device);
878
+ },
879
+ },
880
+ {
881
+ name: 'browser/set-geolocation',
882
+ description: 'Set geolocation',
883
+ category: 'browser-settings',
884
+ inputSchema: {
885
+ type: 'object',
886
+ properties: {
887
+ session: { type: 'string', description: 'Session ID' },
888
+ latitude: { type: 'number', description: 'Latitude' },
889
+ longitude: { type: 'number', description: 'Longitude' },
890
+ },
891
+ required: ['latitude', 'longitude'],
892
+ },
893
+ handler: async (input) => {
894
+ const adapter = getAdapter(input.session);
895
+ return adapter.setGeolocation(input.latitude, input.longitude);
896
+ },
897
+ },
898
+ {
899
+ name: 'browser/set-offline',
900
+ description: 'Toggle offline mode',
901
+ category: 'browser-settings',
902
+ inputSchema: {
903
+ type: 'object',
904
+ properties: {
905
+ session: { type: 'string', description: 'Session ID' },
906
+ enabled: { type: 'boolean', description: 'Enable offline mode' },
907
+ },
908
+ required: ['enabled'],
909
+ },
910
+ handler: async (input) => {
911
+ const adapter = getAdapter(input.session);
912
+ return adapter.setOffline(input.enabled);
913
+ },
914
+ },
915
+ {
916
+ name: 'browser/set-media',
917
+ description: 'Emulate color scheme (dark/light mode)',
918
+ category: 'browser-settings',
919
+ inputSchema: {
920
+ type: 'object',
921
+ properties: {
922
+ session: { type: 'string', description: 'Session ID' },
923
+ scheme: { type: 'string', enum: ['dark', 'light'], description: 'Color scheme' },
924
+ },
925
+ required: ['scheme'],
926
+ },
927
+ handler: async (input) => {
928
+ const adapter = getAdapter(input.session);
929
+ return adapter.setMedia(input.scheme);
930
+ },
931
+ },
932
+ ];
933
+ // ============================================================================
934
+ // Debug Tools
935
+ // ============================================================================
936
+ const debugTools = [
937
+ {
938
+ name: 'browser/trace-start',
939
+ description: 'Start recording a trace for debugging',
940
+ category: 'browser-debug',
941
+ inputSchema: {
942
+ type: 'object',
943
+ properties: {
944
+ session: { type: 'string', description: 'Session ID' },
945
+ path: { type: 'string', description: 'Path to save trace' },
946
+ },
947
+ },
948
+ handler: async (input) => {
949
+ const adapter = getAdapter(input.session);
950
+ return adapter.traceStart(input.path);
951
+ },
952
+ },
953
+ {
954
+ name: 'browser/trace-stop',
955
+ description: 'Stop recording trace and save',
956
+ category: 'browser-debug',
957
+ inputSchema: {
958
+ type: 'object',
959
+ properties: {
960
+ session: { type: 'string', description: 'Session ID' },
961
+ path: { type: 'string', description: 'Path to save trace' },
962
+ },
963
+ },
964
+ handler: async (input) => {
965
+ const adapter = getAdapter(input.session);
966
+ return adapter.traceStop(input.path);
967
+ },
968
+ },
969
+ {
970
+ name: 'browser/console',
971
+ description: 'Get console messages',
972
+ category: 'browser-debug',
973
+ inputSchema: {
974
+ type: 'object',
975
+ properties: {
976
+ session: { type: 'string', description: 'Session ID' },
977
+ clear: { type: 'boolean', description: 'Clear console after getting messages' },
978
+ },
979
+ },
980
+ handler: async (input) => {
981
+ const adapter = getAdapter(input.session);
982
+ if (input.clear) {
983
+ return adapter.clearConsole();
984
+ }
985
+ return adapter.getConsole();
986
+ },
987
+ },
988
+ {
989
+ name: 'browser/errors',
990
+ description: 'Get page errors',
991
+ category: 'browser-debug',
992
+ inputSchema: {
993
+ type: 'object',
994
+ properties: {
995
+ session: { type: 'string', description: 'Session ID' },
996
+ clear: { type: 'boolean', description: 'Clear errors after getting' },
997
+ },
998
+ },
999
+ handler: async (input) => {
1000
+ const adapter = getAdapter(input.session);
1001
+ if (input.clear) {
1002
+ return adapter.clearErrors();
1003
+ }
1004
+ return adapter.getErrors();
1005
+ },
1006
+ },
1007
+ {
1008
+ name: 'browser/highlight',
1009
+ description: 'Highlight an element on the page (for visual debugging)',
1010
+ category: 'browser-debug',
1011
+ inputSchema: {
1012
+ type: 'object',
1013
+ properties: {
1014
+ session: { type: 'string', description: 'Session ID' },
1015
+ target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
1016
+ },
1017
+ required: ['target'],
1018
+ },
1019
+ handler: async (input) => {
1020
+ const adapter = getAdapter(input.session);
1021
+ return adapter.highlight(input.target);
1022
+ },
1023
+ },
1024
+ {
1025
+ name: 'browser/state-save',
1026
+ description: 'Save authentication state (cookies, localStorage) to file',
1027
+ category: 'browser-debug',
1028
+ inputSchema: {
1029
+ type: 'object',
1030
+ properties: {
1031
+ session: { type: 'string', description: 'Session ID' },
1032
+ path: { type: 'string', description: 'Path to save state file' },
1033
+ },
1034
+ required: ['path'],
1035
+ },
1036
+ handler: async (input) => {
1037
+ const adapter = getAdapter(input.session);
1038
+ return adapter.saveState(input.path);
1039
+ },
1040
+ },
1041
+ {
1042
+ name: 'browser/state-load',
1043
+ description: 'Load authentication state from file',
1044
+ category: 'browser-debug',
1045
+ inputSchema: {
1046
+ type: 'object',
1047
+ properties: {
1048
+ session: { type: 'string', description: 'Session ID' },
1049
+ path: { type: 'string', description: 'Path to state file' },
1050
+ },
1051
+ required: ['path'],
1052
+ },
1053
+ handler: async (input) => {
1054
+ const adapter = getAdapter(input.session);
1055
+ return adapter.loadState(input.path);
1056
+ },
1057
+ },
1058
+ ];
1059
+ // ============================================================================
1060
+ // Semantic Locator Tools (Find Commands)
1061
+ // ============================================================================
1062
+ const findTools = [
1063
+ {
1064
+ name: 'browser/find-role',
1065
+ description: 'Find element by ARIA role and perform action',
1066
+ category: 'browser-find',
1067
+ inputSchema: {
1068
+ type: 'object',
1069
+ properties: {
1070
+ session: { type: 'string', description: 'Session ID' },
1071
+ role: { type: 'string', description: 'ARIA role (button, link, textbox, etc.)' },
1072
+ action: { type: 'string', enum: ['click', 'fill', 'check', 'hover', 'text'], description: 'Action to perform' },
1073
+ name: { type: 'string', description: 'Accessible name to match' },
1074
+ value: { type: 'string', description: 'Value for fill action' },
1075
+ exact: { type: 'boolean', description: 'Exact text match' },
1076
+ },
1077
+ required: ['role', 'action'],
1078
+ },
1079
+ handler: async (input) => {
1080
+ const adapter = getAdapter(input.session);
1081
+ return adapter.findByRole(input.role, input.action, {
1082
+ name: input.name,
1083
+ exact: input.exact,
1084
+ });
1085
+ },
1086
+ },
1087
+ {
1088
+ name: 'browser/find-text',
1089
+ description: 'Find element by text content and perform action',
1090
+ category: 'browser-find',
1091
+ inputSchema: {
1092
+ type: 'object',
1093
+ properties: {
1094
+ session: { type: 'string', description: 'Session ID' },
1095
+ text: { type: 'string', description: 'Text to find' },
1096
+ action: { type: 'string', enum: ['click', 'hover', 'text'], description: 'Action to perform' },
1097
+ },
1098
+ required: ['text', 'action'],
1099
+ },
1100
+ handler: async (input) => {
1101
+ const adapter = getAdapter(input.session);
1102
+ return adapter.findByText(input.text, input.action);
1103
+ },
1104
+ },
1105
+ {
1106
+ name: 'browser/find-label',
1107
+ description: 'Find input by label and perform action',
1108
+ category: 'browser-find',
1109
+ inputSchema: {
1110
+ type: 'object',
1111
+ properties: {
1112
+ session: { type: 'string', description: 'Session ID' },
1113
+ label: { type: 'string', description: 'Label text' },
1114
+ action: { type: 'string', enum: ['click', 'fill', 'check', 'hover', 'text'], description: 'Action to perform' },
1115
+ value: { type: 'string', description: 'Value for fill action' },
1116
+ },
1117
+ required: ['label', 'action'],
1118
+ },
1119
+ handler: async (input) => {
1120
+ const adapter = getAdapter(input.session);
1121
+ return adapter.findByLabel(input.label, input.action, input.value);
1122
+ },
1123
+ },
1124
+ {
1125
+ name: 'browser/find-testid',
1126
+ description: 'Find element by data-testid and perform action',
1127
+ category: 'browser-find',
1128
+ inputSchema: {
1129
+ type: 'object',
1130
+ properties: {
1131
+ session: { type: 'string', description: 'Session ID' },
1132
+ testId: { type: 'string', description: 'data-testid value' },
1133
+ action: { type: 'string', enum: ['click', 'fill', 'check', 'hover', 'text'], description: 'Action to perform' },
1134
+ value: { type: 'string', description: 'Value for fill action' },
1135
+ },
1136
+ required: ['testId', 'action'],
1137
+ },
1138
+ handler: async (input) => {
1139
+ const adapter = getAdapter(input.session);
1140
+ return adapter.findByTestId(input.testId, input.action, input.value);
1141
+ },
1142
+ },
1143
+ ];
1144
+ // ============================================================================
1145
+ // Export All Tools
1146
+ // ============================================================================
1147
+ export const browserTools = [
1148
+ ...navigationTools,
1149
+ ...snapshotTools,
1150
+ ...interactionTools,
1151
+ ...getInfoTools,
1152
+ ...stateTools,
1153
+ ...waitTools,
1154
+ ...evalTools,
1155
+ ...storageTools,
1156
+ ...networkTools,
1157
+ ...tabTools,
1158
+ ...settingsTools,
1159
+ ...debugTools,
1160
+ ...findTools,
1161
+ ];
1162
+ export default browserTools;
1163
+ //# sourceMappingURL=browser-tools.js.map