@vymalo/opencode-browser 0.11.0 → 0.14.0
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/dist/agent-client.d.ts +36 -36
- package/dist/agent-client.js +201 -189
- package/dist/agent-client.js.map +1 -1
- package/dist/broker.d.ts +85 -87
- package/dist/broker.js +614 -599
- package/dist/broker.js.map +1 -1
- package/dist/catalog.d.ts +76 -76
- package/dist/catalog.js +826 -596
- package/dist/catalog.js.map +1 -1
- package/dist/endpoint.d.ts +42 -42
- package/dist/endpoint.js +132 -131
- package/dist/endpoint.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib.js +1 -0
- package/dist/lib.js.map +1 -1
- package/dist/logging.d.ts +6 -6
- package/dist/logging.js +60 -63
- package/dist/logging.js.map +1 -1
- package/dist/node-transport.d.ts +6 -6
- package/dist/node-transport.js +48 -44
- package/dist/node-transport.js.map +1 -1
- package/dist/opencode.d.ts +10 -10
- package/dist/opencode.js +143 -146
- package/dist/opencode.js.map +1 -1
- package/dist/protocol.d.ts +127 -127
- package/dist/protocol.js +148 -128
- package/dist/protocol.js.map +1 -1
- package/dist/schema.d.ts +32 -32
- package/dist/schema.js +39 -44
- package/dist/schema.js.map +1 -1
- package/dist/token-file.d.ts +4 -4
- package/dist/token-file.js +68 -60
- package/dist/token-file.js.map +1 -1
- package/dist/tools.d.ts +11 -11
- package/dist/tools.js +128 -123
- package/dist/tools.js.map +1 -1
- package/dist/transport.d.ts +17 -17
- package/dist/transport.js +3 -9
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +61 -61
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
package/dist/catalog.js
CHANGED
|
@@ -1,619 +1,849 @@
|
|
|
1
1
|
export const TOOL_GROUPS = [
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
"page",
|
|
3
|
+
"control",
|
|
4
|
+
"debug",
|
|
5
|
+
"interactive"
|
|
6
6
|
];
|
|
7
7
|
/** Groups registered when the operator doesn't specify — `debug` and `interactive` are opt-in. */
|
|
8
8
|
export const DEFAULT_GROUPS = ["page", "control"];
|
|
9
9
|
// ─── reusable fields ─────────────────────────────────────────────────────────
|
|
10
10
|
const group = {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Named tab group the action targets. Created on first browser_open."
|
|
13
13
|
};
|
|
14
14
|
const tabId = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
type: "number",
|
|
16
|
+
optional: true,
|
|
17
|
+
description: "Specific tab id; defaults to the group's active tab."
|
|
18
18
|
};
|
|
19
19
|
const refField = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
type: "string",
|
|
21
|
+
optional: true,
|
|
22
|
+
description: "Element ref from a prior browser_snapshot."
|
|
23
|
+
};
|
|
24
|
+
const selectorField = {
|
|
25
|
+
type: "string",
|
|
26
|
+
optional: true,
|
|
27
|
+
description: "CSS selector."
|
|
23
28
|
};
|
|
24
|
-
const selectorField = { type: "string", optional: true, description: "CSS selector." };
|
|
25
29
|
// ─── helpers ─────────────────────────────────────────────────────────────────
|
|
26
30
|
function rec(value) {
|
|
27
|
-
|
|
31
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
28
32
|
}
|
|
29
33
|
function describeTarget(a) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
if (typeof a.ref === "string") {
|
|
35
|
+
return `ref ${a.ref}`;
|
|
36
|
+
}
|
|
37
|
+
if (typeof a.selector === "string") {
|
|
38
|
+
return `selector ${a.selector}`;
|
|
39
|
+
}
|
|
40
|
+
if (typeof a.x === "number" && typeof a.y === "number") {
|
|
41
|
+
return `(${a.x}, ${a.y})`;
|
|
42
|
+
}
|
|
43
|
+
return "element";
|
|
40
44
|
}
|
|
41
|
-
const text = (t) => ({
|
|
42
|
-
|
|
45
|
+
const text = (t) => ({
|
|
46
|
+
kind: "text",
|
|
47
|
+
text: t
|
|
48
|
+
});
|
|
49
|
+
const json = (data, t) => ({
|
|
50
|
+
kind: "json",
|
|
51
|
+
data,
|
|
52
|
+
text: t
|
|
53
|
+
});
|
|
43
54
|
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
* The single source of truth for the browser tool surface, shared by the
|
|
56
|
+
* OpenCode plugin and the MCP server. Filter by `group` to gate what an agent
|
|
57
|
+
* sees.
|
|
58
|
+
*/
|
|
48
59
|
export const BROWSER_TOOLS = [
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
60
|
+
{
|
|
61
|
+
name: "browser_open",
|
|
62
|
+
group: "control",
|
|
63
|
+
action: "open",
|
|
64
|
+
description: "Open a new browser tab inside a named tab group (creates the group if it doesn't exist yet). Returns the tab id, final URL and page title.",
|
|
65
|
+
input: {
|
|
66
|
+
group,
|
|
67
|
+
url: {
|
|
68
|
+
type: "string",
|
|
69
|
+
optional: true,
|
|
70
|
+
description: "URL to load. Omit for a blank tab."
|
|
71
|
+
},
|
|
72
|
+
focus: {
|
|
73
|
+
type: "boolean",
|
|
74
|
+
optional: true,
|
|
75
|
+
description: "Bring the tab to the foreground (default true)."
|
|
76
|
+
},
|
|
77
|
+
target: {
|
|
78
|
+
type: "string",
|
|
79
|
+
optional: true,
|
|
80
|
+
description: "Which browser to open in (label or id from browser_targets). Omit unless several browsers are connected."
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
result: (data, args) => {
|
|
84
|
+
const d = rec(data);
|
|
85
|
+
return {
|
|
86
|
+
kind: "json",
|
|
87
|
+
data: d,
|
|
88
|
+
text: `Opened tab in group "${args.group}": ${d.title ?? "(untitled)"} — ${d.url ?? args.url ?? "about:blank"}`
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "browser_navigate",
|
|
94
|
+
group: "control",
|
|
95
|
+
action: "navigate",
|
|
96
|
+
description: "Navigate an existing tab in the group to a new URL.",
|
|
97
|
+
input: {
|
|
98
|
+
group,
|
|
99
|
+
url: {
|
|
100
|
+
type: "string",
|
|
101
|
+
description: "URL to navigate to."
|
|
102
|
+
},
|
|
103
|
+
tabId
|
|
104
|
+
},
|
|
105
|
+
result: (data, args) => {
|
|
106
|
+
const d = rec(data);
|
|
107
|
+
return {
|
|
108
|
+
kind: "json",
|
|
109
|
+
data: d,
|
|
110
|
+
text: `Navigated to ${d.url ?? args.url} (${d.title ?? ""})`.trim()
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "browser_click",
|
|
116
|
+
group: "control",
|
|
117
|
+
action: "click",
|
|
118
|
+
description: "Click an element. Target it by `ref` (from browser_snapshot, most reliable), CSS `selector`, or absolute `x`/`y` coordinates.",
|
|
119
|
+
input: {
|
|
120
|
+
group,
|
|
121
|
+
ref: refField,
|
|
122
|
+
selector: selectorField,
|
|
123
|
+
x: {
|
|
124
|
+
type: "number",
|
|
125
|
+
optional: true,
|
|
126
|
+
description: "Absolute x coordinate (with y)."
|
|
127
|
+
},
|
|
128
|
+
y: {
|
|
129
|
+
type: "number",
|
|
130
|
+
optional: true,
|
|
131
|
+
description: "Absolute y coordinate (with x)."
|
|
132
|
+
},
|
|
133
|
+
button: {
|
|
134
|
+
type: "string",
|
|
135
|
+
optional: true,
|
|
136
|
+
enum: [
|
|
137
|
+
"left",
|
|
138
|
+
"middle",
|
|
139
|
+
"right"
|
|
140
|
+
],
|
|
141
|
+
description: "Mouse button (default left)."
|
|
142
|
+
},
|
|
143
|
+
tabId
|
|
144
|
+
},
|
|
145
|
+
result: (_data, args) => text(`Clicked ${describeTarget(args)} in group "${args.group}".`)
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "browser_double_click",
|
|
149
|
+
group: "control",
|
|
150
|
+
action: "double_click",
|
|
151
|
+
description: "Double-click an element, targeted by `ref`, CSS `selector`, or `x`/`y` coordinates.",
|
|
152
|
+
input: {
|
|
153
|
+
group,
|
|
154
|
+
ref: refField,
|
|
155
|
+
selector: selectorField,
|
|
156
|
+
x: {
|
|
157
|
+
type: "number",
|
|
158
|
+
optional: true
|
|
159
|
+
},
|
|
160
|
+
y: {
|
|
161
|
+
type: "number",
|
|
162
|
+
optional: true
|
|
163
|
+
},
|
|
164
|
+
tabId
|
|
165
|
+
},
|
|
166
|
+
result: (_data, args) => text(`Double-clicked ${describeTarget(args)} in group "${args.group}".`)
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "browser_type",
|
|
170
|
+
group: "control",
|
|
171
|
+
action: "type",
|
|
172
|
+
description: "Type text into the focused element (or first focus `ref`/`selector`). Optionally press Enter after.",
|
|
173
|
+
input: {
|
|
174
|
+
group,
|
|
175
|
+
text: {
|
|
176
|
+
type: "string",
|
|
177
|
+
description: "Text to type."
|
|
178
|
+
},
|
|
179
|
+
ref: refField,
|
|
180
|
+
selector: selectorField,
|
|
181
|
+
submit: {
|
|
182
|
+
type: "boolean",
|
|
183
|
+
optional: true,
|
|
184
|
+
description: "Press Enter after typing."
|
|
185
|
+
},
|
|
186
|
+
tabId
|
|
187
|
+
},
|
|
188
|
+
result: (_data, args) => text(`Typed ${String(args.text ?? "").length} character(s) into ${describeTarget(args)}${args.submit ? " and submitted" : ""}.`)
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: "browser_fill",
|
|
192
|
+
group: "control",
|
|
193
|
+
action: "fill",
|
|
194
|
+
description: "Fill several form fields in one call. Each field targets a `ref` or CSS `selector` and sets its `value`.",
|
|
195
|
+
input: {
|
|
196
|
+
group,
|
|
197
|
+
fields: {
|
|
198
|
+
type: "array",
|
|
199
|
+
description: "Fields to fill, in order.",
|
|
200
|
+
items: {
|
|
201
|
+
type: "object",
|
|
202
|
+
properties: {
|
|
203
|
+
ref: refField,
|
|
204
|
+
selector: selectorField,
|
|
205
|
+
value: { type: "string" }
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
tabId
|
|
210
|
+
},
|
|
211
|
+
result: (data, args) => {
|
|
212
|
+
const requested = Array.isArray(args.fields) ? args.fields.length : 0;
|
|
213
|
+
const filled = typeof rec(data).filled === "number" ? rec(data).filled : requested;
|
|
214
|
+
const missed = requested - filled;
|
|
215
|
+
return text(`Filled ${filled} of ${requested} field(s) in group "${args.group}".${missed > 0 ? ` (${missed} not found)` : ""}`);
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: "browser_select",
|
|
220
|
+
group: "control",
|
|
221
|
+
action: "select",
|
|
222
|
+
description: "Choose option(s) in a <select> element, or set the selection of a control.",
|
|
223
|
+
input: {
|
|
224
|
+
group,
|
|
225
|
+
ref: refField,
|
|
226
|
+
selector: selectorField,
|
|
227
|
+
value: {
|
|
228
|
+
type: "string",
|
|
229
|
+
optional: true,
|
|
230
|
+
description: "Single value to select."
|
|
231
|
+
},
|
|
232
|
+
values: {
|
|
233
|
+
type: "array",
|
|
234
|
+
optional: true,
|
|
235
|
+
description: "Multiple values (multi-select).",
|
|
236
|
+
items: { type: "string" }
|
|
237
|
+
},
|
|
238
|
+
tabId
|
|
239
|
+
},
|
|
240
|
+
result: (_data, args) => {
|
|
241
|
+
const chosen = Array.isArray(args.values) ? args.values.join(", ") : args.value ?? "";
|
|
242
|
+
return text(`Selected ${chosen} in ${describeTarget(args)}.`);
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: "browser_scroll",
|
|
247
|
+
group: "control",
|
|
248
|
+
action: "scroll",
|
|
249
|
+
description: "Scroll the page (or an element). Provide `deltaX`/`deltaY`, or `to: 'top' | 'bottom'`.",
|
|
250
|
+
input: {
|
|
251
|
+
group,
|
|
252
|
+
deltaX: {
|
|
253
|
+
type: "number",
|
|
254
|
+
optional: true
|
|
255
|
+
},
|
|
256
|
+
deltaY: {
|
|
257
|
+
type: "number",
|
|
258
|
+
optional: true
|
|
259
|
+
},
|
|
260
|
+
ref: {
|
|
261
|
+
type: "string",
|
|
262
|
+
optional: true,
|
|
263
|
+
description: "Scroll within this element instead of the page."
|
|
264
|
+
},
|
|
265
|
+
to: {
|
|
266
|
+
type: "string",
|
|
267
|
+
optional: true,
|
|
268
|
+
enum: ["top", "bottom"]
|
|
269
|
+
},
|
|
270
|
+
tabId
|
|
271
|
+
},
|
|
272
|
+
result: (_data, args) => text(`Scrolled in group "${args.group}".`)
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
name: "browser_press_key",
|
|
276
|
+
group: "control",
|
|
277
|
+
action: "press_key",
|
|
278
|
+
description: "Press a single key or chord (e.g. \"Enter\", \"Escape\", \"Control+a\").",
|
|
279
|
+
input: {
|
|
280
|
+
group,
|
|
281
|
+
key: {
|
|
282
|
+
type: "string",
|
|
283
|
+
description: "Key name, e.g. \"Enter\"."
|
|
284
|
+
},
|
|
285
|
+
tabId
|
|
286
|
+
},
|
|
287
|
+
result: (_data, args) => text(`Pressed ${args.key} in group "${args.group}".`)
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: "browser_wait",
|
|
291
|
+
group: "control",
|
|
292
|
+
action: "wait",
|
|
293
|
+
description: "Wait for a fixed delay (`ms`) or until a `selector` reaches `state` (visible/hidden/attached).",
|
|
294
|
+
input: {
|
|
295
|
+
group,
|
|
296
|
+
ms: {
|
|
297
|
+
type: "number",
|
|
298
|
+
optional: true,
|
|
299
|
+
description: "Fixed delay in milliseconds."
|
|
300
|
+
},
|
|
301
|
+
selector: {
|
|
302
|
+
type: "string",
|
|
303
|
+
optional: true,
|
|
304
|
+
description: "CSS selector to wait for."
|
|
305
|
+
},
|
|
306
|
+
state: {
|
|
307
|
+
type: "string",
|
|
308
|
+
optional: true,
|
|
309
|
+
enum: [
|
|
310
|
+
"visible",
|
|
311
|
+
"hidden",
|
|
312
|
+
"attached"
|
|
313
|
+
]
|
|
314
|
+
},
|
|
315
|
+
tabId
|
|
316
|
+
},
|
|
317
|
+
result: (_data, args) => text(args.selector ? `Waited for ${args.selector} (${args.state ?? "visible"}).` : `Waited ${args.ms ?? 0}ms.`)
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
name: "browser_close",
|
|
321
|
+
group: "control",
|
|
322
|
+
action: "close",
|
|
323
|
+
description: "Close a tab (pass `tabId`) or the whole group (omit `tabId`).",
|
|
324
|
+
input: {
|
|
325
|
+
group,
|
|
326
|
+
tabId
|
|
327
|
+
},
|
|
328
|
+
result: (_data, args) => text(args.tabId ? `Closed tab ${args.tabId} in group "${args.group}".` : `Closed group "${args.group}".`)
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
name: "browser_release",
|
|
332
|
+
group: "control",
|
|
333
|
+
action: "release",
|
|
334
|
+
description: "Release control of the browser: stop driving and detach the debugger (clears the 'being debugged' banner) without closing tabs. The next browser_* call re-attaches. Use this when you're done so the user gets their browser back.",
|
|
335
|
+
input: {},
|
|
336
|
+
result: () => text("Released browser control. Tabs are left open; the next browser_* action re-attaches.")
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
name: "browser_snapshot",
|
|
340
|
+
group: "page",
|
|
341
|
+
action: "snapshot",
|
|
342
|
+
description: "Capture an accessibility/DOM snapshot of the page with stable element refs. Prefer this over guessing selectors — pass the returned refs to browser_click/type/etc.",
|
|
343
|
+
input: {
|
|
344
|
+
group,
|
|
345
|
+
tabId
|
|
346
|
+
},
|
|
347
|
+
result: (data) => {
|
|
348
|
+
const d = rec(data);
|
|
349
|
+
return text(typeof d.snapshot === "string" ? d.snapshot : JSON.stringify(d, null, 2));
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
name: "browser_get_text",
|
|
354
|
+
group: "page",
|
|
355
|
+
action: "get_text",
|
|
356
|
+
description: "Extract the visible text / readable content of the group's active tab.",
|
|
357
|
+
input: {
|
|
358
|
+
group,
|
|
359
|
+
tabId
|
|
360
|
+
},
|
|
361
|
+
result: (data) => {
|
|
362
|
+
const d = rec(data);
|
|
363
|
+
return text(typeof d.text === "string" ? d.text : JSON.stringify(d));
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
name: "browser_tabs",
|
|
368
|
+
group: "page",
|
|
369
|
+
action: "tabs",
|
|
370
|
+
description: "List open tab groups and their tabs. Omit `group` to list everything.",
|
|
371
|
+
input: { group: {
|
|
372
|
+
type: "string",
|
|
373
|
+
optional: true,
|
|
374
|
+
description: "Restrict to one group."
|
|
375
|
+
} },
|
|
376
|
+
params: (args) => ({ group: args.group }),
|
|
377
|
+
result: (data) => ({
|
|
378
|
+
kind: "json",
|
|
379
|
+
data,
|
|
380
|
+
text: JSON.stringify(data, null, 2)
|
|
381
|
+
})
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: "browser_targets",
|
|
385
|
+
group: "page",
|
|
386
|
+
action: "targets",
|
|
387
|
+
description: "List the browsers (extensions) currently connected to the bridge, with their id, label, browser and owned groups. Use a returned id/label as `target` in browser_open when several are connected.",
|
|
388
|
+
input: {},
|
|
389
|
+
result: (data) => ({
|
|
390
|
+
kind: "json",
|
|
391
|
+
data,
|
|
392
|
+
text: JSON.stringify(data, null, 2)
|
|
393
|
+
})
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
name: "browser_screenshot",
|
|
397
|
+
group: "page",
|
|
398
|
+
action: "screenshot",
|
|
399
|
+
description: "Capture a screenshot of the group's active tab. Returns the image (the OpenCode plugin saves it to disk and returns the path — use the read tool to view it).",
|
|
400
|
+
input: {
|
|
401
|
+
group,
|
|
402
|
+
fullPage: {
|
|
403
|
+
type: "boolean",
|
|
404
|
+
optional: true,
|
|
405
|
+
description: "Capture the full scrollable page, not just the viewport."
|
|
406
|
+
},
|
|
407
|
+
tabId
|
|
408
|
+
},
|
|
409
|
+
result: (data) => {
|
|
410
|
+
const d = rec(data);
|
|
411
|
+
const width = Number(d.width ?? 0);
|
|
412
|
+
const height = Number(d.height ?? 0);
|
|
413
|
+
return {
|
|
414
|
+
kind: "image",
|
|
415
|
+
base64: String(d.base64 ?? ""),
|
|
416
|
+
mimeType: "image/png",
|
|
417
|
+
width,
|
|
418
|
+
height,
|
|
419
|
+
partial: Boolean(d.partial),
|
|
420
|
+
text: `screenshot ${width}×${height}`
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
(
|
|
425
|
+
// ─── navigation (control) ──────────────────────────────────────────────────
|
|
426
|
+
{
|
|
427
|
+
name: "browser_back",
|
|
428
|
+
group: "control",
|
|
429
|
+
action: "back",
|
|
430
|
+
description: "Go back in the tab's history.",
|
|
431
|
+
input: {
|
|
432
|
+
group,
|
|
433
|
+
tabId
|
|
434
|
+
},
|
|
435
|
+
result: (data) => json(rec(data), `Went back to ${rec(data).url ?? ""}`.trim())
|
|
436
|
+
}),
|
|
437
|
+
{
|
|
438
|
+
name: "browser_forward",
|
|
439
|
+
group: "control",
|
|
440
|
+
action: "forward",
|
|
441
|
+
description: "Go forward in the tab's history.",
|
|
442
|
+
input: {
|
|
443
|
+
group,
|
|
444
|
+
tabId
|
|
445
|
+
},
|
|
446
|
+
result: (data) => json(rec(data), `Went forward to ${rec(data).url ?? ""}`.trim())
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
name: "browser_reload",
|
|
450
|
+
group: "control",
|
|
451
|
+
action: "reload",
|
|
452
|
+
description: "Reload the group's active tab.",
|
|
453
|
+
input: {
|
|
454
|
+
group,
|
|
455
|
+
tabId
|
|
456
|
+
},
|
|
457
|
+
result: (data) => json(rec(data), `Reloaded ${rec(data).url ?? ""}`.trim())
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
name: "browser_activate",
|
|
461
|
+
group: "control",
|
|
462
|
+
action: "activate",
|
|
463
|
+
description: "Bring a group's tab to the foreground (focus its window and tab).",
|
|
464
|
+
input: {
|
|
465
|
+
group,
|
|
466
|
+
tabId
|
|
467
|
+
},
|
|
468
|
+
result: (data) => json(rec(data), `Activated tab ${rec(data).tabId ?? ""}`.trim())
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
name: "browser_hover",
|
|
472
|
+
group: "control",
|
|
473
|
+
action: "hover",
|
|
474
|
+
description: "Move the pointer over an element (reveals hover menus/tooltips). Target by `ref`, `selector`, or `x`/`y`.",
|
|
475
|
+
input: {
|
|
476
|
+
group,
|
|
477
|
+
ref: refField,
|
|
478
|
+
selector: selectorField,
|
|
479
|
+
x: {
|
|
480
|
+
type: "number",
|
|
481
|
+
optional: true
|
|
482
|
+
},
|
|
483
|
+
y: {
|
|
484
|
+
type: "number",
|
|
485
|
+
optional: true
|
|
486
|
+
},
|
|
487
|
+
tabId
|
|
488
|
+
},
|
|
489
|
+
result: (_d, args) => text(`Hovered ${describeTarget(args)} in group "${args.group}".`)
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
name: "browser_drag",
|
|
493
|
+
group: "control",
|
|
494
|
+
action: "drag",
|
|
495
|
+
description: "Drag from a source element to a target element (each by `ref` or `selector`).",
|
|
496
|
+
input: {
|
|
497
|
+
group,
|
|
498
|
+
fromRef: {
|
|
499
|
+
type: "string",
|
|
500
|
+
optional: true,
|
|
501
|
+
description: "Source element ref."
|
|
502
|
+
},
|
|
503
|
+
fromSelector: {
|
|
504
|
+
type: "string",
|
|
505
|
+
optional: true,
|
|
506
|
+
description: "Source CSS selector."
|
|
507
|
+
},
|
|
508
|
+
ref: {
|
|
509
|
+
type: "string",
|
|
510
|
+
optional: true,
|
|
511
|
+
description: "Target element ref."
|
|
512
|
+
},
|
|
513
|
+
selector: {
|
|
514
|
+
type: "string",
|
|
515
|
+
optional: true,
|
|
516
|
+
description: "Target CSS selector."
|
|
517
|
+
},
|
|
518
|
+
tabId
|
|
519
|
+
},
|
|
520
|
+
result: (_d, args) => text(`Dragged to ${describeTarget(args)} in group "${args.group}".`)
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
name: "browser_upload",
|
|
524
|
+
group: "control",
|
|
525
|
+
action: "upload",
|
|
526
|
+
description: "Set the files on a file <input>, by absolute path(s) on the machine running the bridge. CDP executor only (Chromium).",
|
|
527
|
+
input: {
|
|
528
|
+
group,
|
|
529
|
+
ref: refField,
|
|
530
|
+
selector: selectorField,
|
|
531
|
+
paths: {
|
|
532
|
+
type: "array",
|
|
533
|
+
description: "Absolute file path(s) to attach.",
|
|
534
|
+
items: { type: "string" }
|
|
535
|
+
},
|
|
536
|
+
tabId
|
|
537
|
+
},
|
|
538
|
+
result: (_d, args) => text(`Uploaded ${Array.isArray(args.paths) ? args.paths.length : 0} file(s) to ${describeTarget(args)}.`)
|
|
539
|
+
},
|
|
540
|
+
(
|
|
541
|
+
// ─── reading (page) ────────────────────────────────────────────────────────
|
|
542
|
+
{
|
|
543
|
+
name: "browser_get_html",
|
|
544
|
+
group: "page",
|
|
545
|
+
action: "get_html",
|
|
546
|
+
description: "Get the HTML of the page (or of a `ref`/`selector` element). `outer: false` for innerHTML.",
|
|
547
|
+
input: {
|
|
548
|
+
group,
|
|
549
|
+
ref: refField,
|
|
550
|
+
selector: selectorField,
|
|
551
|
+
outer: {
|
|
552
|
+
type: "boolean",
|
|
553
|
+
optional: true,
|
|
554
|
+
description: "Outer HTML (default true)."
|
|
555
|
+
},
|
|
556
|
+
tabId
|
|
557
|
+
},
|
|
558
|
+
result: (data) => text(String(rec(data).html ?? ""))
|
|
559
|
+
}),
|
|
560
|
+
{
|
|
561
|
+
name: "browser_get_attribute",
|
|
562
|
+
group: "page",
|
|
563
|
+
action: "get_attribute",
|
|
564
|
+
description: "Read an element's tag, text, value, checked state, bounding box, and attributes (or one named attribute).",
|
|
565
|
+
input: {
|
|
566
|
+
group,
|
|
567
|
+
ref: refField,
|
|
568
|
+
selector: selectorField,
|
|
569
|
+
name: {
|
|
570
|
+
type: "string",
|
|
571
|
+
optional: true,
|
|
572
|
+
description: "A single attribute name to read."
|
|
573
|
+
},
|
|
574
|
+
tabId
|
|
575
|
+
},
|
|
576
|
+
result: (data) => json(rec(data), JSON.stringify(rec(data), null, 2))
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
name: "browser_query",
|
|
580
|
+
group: "page",
|
|
581
|
+
action: "query",
|
|
582
|
+
description: "Find visible elements matching a CSS selector. Returns each with a stable ref you can pass to other tools.",
|
|
583
|
+
input: {
|
|
584
|
+
group,
|
|
585
|
+
selector: {
|
|
586
|
+
type: "string",
|
|
587
|
+
description: "CSS selector to match."
|
|
588
|
+
},
|
|
589
|
+
limit: {
|
|
590
|
+
type: "number",
|
|
591
|
+
optional: true,
|
|
592
|
+
description: "Max matches (default 50)."
|
|
593
|
+
},
|
|
594
|
+
tabId
|
|
595
|
+
},
|
|
596
|
+
result: (data) => json(rec(data), JSON.stringify(rec(data), null, 2))
|
|
597
|
+
},
|
|
598
|
+
(
|
|
599
|
+
// ─── debug (off by default) ────────────────────────────────────────────────
|
|
600
|
+
{
|
|
601
|
+
name: "browser_eval",
|
|
602
|
+
group: "debug",
|
|
603
|
+
action: "eval",
|
|
604
|
+
description: "Evaluate JavaScript in the page's DOM context and return the JSON-serializable result. Powerful — enabled only when the `debug` group is on.",
|
|
605
|
+
input: {
|
|
606
|
+
group,
|
|
607
|
+
code: {
|
|
608
|
+
type: "string",
|
|
609
|
+
description: "JavaScript to evaluate."
|
|
610
|
+
},
|
|
611
|
+
tabId
|
|
612
|
+
},
|
|
613
|
+
result: (data) => {
|
|
614
|
+
const r = rec(data).result;
|
|
615
|
+
return json(rec(data), typeof r === "string" ? r : JSON.stringify(r, null, 2));
|
|
616
|
+
}
|
|
617
|
+
}),
|
|
618
|
+
{
|
|
619
|
+
name: "browser_console",
|
|
620
|
+
group: "debug",
|
|
621
|
+
action: "console",
|
|
622
|
+
description: "Return recent console output (logs, warnings, errors). CDP executor only (Chromium).",
|
|
623
|
+
input: {
|
|
624
|
+
group,
|
|
625
|
+
tabId
|
|
626
|
+
},
|
|
627
|
+
result: (data) => {
|
|
628
|
+
const entries = rec(data).entries ?? [];
|
|
629
|
+
return json(rec(data), JSON.stringify(entries, null, 2));
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
name: "browser_network",
|
|
634
|
+
group: "debug",
|
|
635
|
+
action: "network",
|
|
636
|
+
description: "Return recent network requests (method, URL, status). CDP executor only (Chromium).",
|
|
637
|
+
input: {
|
|
638
|
+
group,
|
|
639
|
+
tabId
|
|
640
|
+
},
|
|
641
|
+
result: (data) => {
|
|
642
|
+
const entries = rec(data).entries ?? [];
|
|
643
|
+
return json(rec(data), JSON.stringify(entries, null, 2));
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
name: "browser_handle_dialog",
|
|
648
|
+
group: "debug",
|
|
649
|
+
action: "handle_dialog",
|
|
650
|
+
description: "Accept or dismiss a pending JavaScript dialog (alert/confirm/prompt). CDP executor only (Chromium).",
|
|
651
|
+
input: {
|
|
652
|
+
group,
|
|
653
|
+
accept: {
|
|
654
|
+
type: "boolean",
|
|
655
|
+
optional: true,
|
|
656
|
+
description: "Accept (default true) or dismiss."
|
|
657
|
+
},
|
|
658
|
+
promptText: {
|
|
659
|
+
type: "string",
|
|
660
|
+
optional: true,
|
|
661
|
+
description: "Text for a prompt() dialog."
|
|
662
|
+
},
|
|
663
|
+
tabId
|
|
664
|
+
},
|
|
665
|
+
result: (_d, args) => text(`${args.accept === false ? "Dismissed" : "Accepted"} the dialog.`)
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
name: "browser_set_viewport",
|
|
669
|
+
group: "debug",
|
|
670
|
+
action: "set_viewport",
|
|
671
|
+
description: "Emulate a viewport size / device metrics. CDP executor only (Chromium).",
|
|
672
|
+
input: {
|
|
673
|
+
group,
|
|
674
|
+
width: {
|
|
675
|
+
type: "number",
|
|
676
|
+
description: "Viewport width in CSS px."
|
|
677
|
+
},
|
|
678
|
+
height: {
|
|
679
|
+
type: "number",
|
|
680
|
+
description: "Viewport height in CSS px."
|
|
681
|
+
},
|
|
682
|
+
mobile: {
|
|
683
|
+
type: "boolean",
|
|
684
|
+
optional: true,
|
|
685
|
+
description: "Emulate a mobile device."
|
|
686
|
+
},
|
|
687
|
+
deviceScaleFactor: {
|
|
688
|
+
type: "number",
|
|
689
|
+
optional: true,
|
|
690
|
+
description: "Device pixel ratio (0 = default)."
|
|
691
|
+
},
|
|
692
|
+
tabId
|
|
693
|
+
},
|
|
694
|
+
result: (_d, args) => text(`Set viewport to ${args.width}×${args.height}.`)
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
name: "browser_cookies",
|
|
698
|
+
group: "debug",
|
|
699
|
+
action: "cookies",
|
|
700
|
+
description: "Read or modify cookies. `op`: get (by url+name), list (by url), set (url+name+value), clear (url+name).",
|
|
701
|
+
input: {
|
|
702
|
+
group: {
|
|
703
|
+
type: "string",
|
|
704
|
+
optional: true,
|
|
705
|
+
description: "Group (unused; cookies are profile-wide)."
|
|
706
|
+
},
|
|
707
|
+
op: {
|
|
708
|
+
type: "string",
|
|
709
|
+
enum: [
|
|
710
|
+
"get",
|
|
711
|
+
"list",
|
|
712
|
+
"set",
|
|
713
|
+
"clear"
|
|
714
|
+
],
|
|
715
|
+
description: "Operation."
|
|
716
|
+
},
|
|
717
|
+
url: {
|
|
718
|
+
type: "string",
|
|
719
|
+
optional: true,
|
|
720
|
+
description: "URL the cookie applies to."
|
|
721
|
+
},
|
|
722
|
+
name: {
|
|
723
|
+
type: "string",
|
|
724
|
+
optional: true
|
|
725
|
+
},
|
|
726
|
+
value: {
|
|
727
|
+
type: "string",
|
|
728
|
+
optional: true
|
|
729
|
+
},
|
|
730
|
+
domain: {
|
|
731
|
+
type: "string",
|
|
732
|
+
optional: true
|
|
733
|
+
},
|
|
734
|
+
path: {
|
|
735
|
+
type: "string",
|
|
736
|
+
optional: true
|
|
737
|
+
}
|
|
738
|
+
},
|
|
739
|
+
params: (args) => ({
|
|
740
|
+
op: args.op,
|
|
741
|
+
url: args.url,
|
|
742
|
+
name: args.name,
|
|
743
|
+
value: args.value,
|
|
744
|
+
domain: args.domain,
|
|
745
|
+
path: args.path
|
|
746
|
+
}),
|
|
747
|
+
result: (data) => json(rec(data), JSON.stringify(rec(data), null, 2))
|
|
748
|
+
},
|
|
749
|
+
{
|
|
750
|
+
name: "browser_request_feedback",
|
|
751
|
+
group: "interactive",
|
|
752
|
+
action: "request_feedback",
|
|
753
|
+
description: "Ask the human at the browser to respond on the page, and block until they do (or it times out). Use when you're unsure what the user means and a screenshot or snapshot isn't enough — e.g. 'which of these did you mean?'. `mode`: confirm (yes/no bar), choose (pick one of `options`), point (click one spot), element (hover-highlight then click one element), region (drag a box over an area), comment (point + a free-text note). point/element/region resolve to element ref(s) you can then click/snapshot. Returns the user's response; on timeout returns `{ timedOut: true }` so you can fall back. interactive group (opt-in).",
|
|
754
|
+
timeoutMs: 3e5,
|
|
755
|
+
input: {
|
|
756
|
+
group,
|
|
757
|
+
mode: {
|
|
758
|
+
type: "string",
|
|
759
|
+
enum: [
|
|
760
|
+
"confirm",
|
|
761
|
+
"choose",
|
|
762
|
+
"point",
|
|
763
|
+
"element",
|
|
764
|
+
"region",
|
|
765
|
+
"comment"
|
|
766
|
+
],
|
|
767
|
+
description: "Kind of prompt: confirm | choose | point | element | region | comment."
|
|
768
|
+
},
|
|
769
|
+
prompt: {
|
|
770
|
+
type: "string",
|
|
771
|
+
optional: true,
|
|
772
|
+
description: "Question/instruction shown to the user above the controls."
|
|
773
|
+
},
|
|
774
|
+
options: {
|
|
775
|
+
type: "array",
|
|
776
|
+
optional: true,
|
|
777
|
+
items: { type: "string" },
|
|
778
|
+
description: "Choices for `choose` mode (ignored otherwise)."
|
|
779
|
+
},
|
|
780
|
+
timeoutMs: {
|
|
781
|
+
type: "number",
|
|
782
|
+
optional: true,
|
|
783
|
+
description: "How long to wait for the user, in ms (default 120000, max 290000)."
|
|
784
|
+
},
|
|
785
|
+
tabId
|
|
786
|
+
},
|
|
787
|
+
params: (args) => {
|
|
788
|
+
const requested = typeof args.timeoutMs === "number" ? args.timeoutMs : 12e4;
|
|
789
|
+
return {
|
|
790
|
+
mode: args.mode,
|
|
791
|
+
prompt: args.prompt,
|
|
792
|
+
options: Array.isArray(args.options) ? args.options : undefined,
|
|
793
|
+
// Keep the overlay's own countdown below the broker deadline (300s) so it
|
|
794
|
+
// self-resolves into a clean `timedOut` result rather than being cancelled.
|
|
795
|
+
timeoutMs: Math.min(Math.max(requested, 1e3), 29e4),
|
|
796
|
+
tabId: args.tabId
|
|
797
|
+
};
|
|
798
|
+
},
|
|
799
|
+
result: (data) => {
|
|
800
|
+
const d = data;
|
|
801
|
+
if (d?.error) {
|
|
802
|
+
return json({
|
|
803
|
+
responded: false,
|
|
804
|
+
error: d.error,
|
|
805
|
+
annotations: []
|
|
806
|
+
}, `Couldn't ask the user on this page: ${d.error}. Fall back to a screenshot/snapshot.`);
|
|
807
|
+
}
|
|
808
|
+
if (!d || d.responded === false || d.timedOut) {
|
|
809
|
+
return json({
|
|
810
|
+
responded: false,
|
|
811
|
+
timedOut: true,
|
|
812
|
+
annotations: []
|
|
813
|
+
}, "No response from the user within the time limit.");
|
|
814
|
+
}
|
|
815
|
+
const annotations = Array.isArray(d.annotations) ? d.annotations : [];
|
|
816
|
+
return json({
|
|
817
|
+
responded: true,
|
|
818
|
+
annotations
|
|
819
|
+
}, summarizeAnnotations(annotations));
|
|
820
|
+
}
|
|
821
|
+
}
|
|
591
822
|
];
|
|
592
823
|
/** A short human-readable line describing what the user marked. */
|
|
593
824
|
function summarizeAnnotations(annotations) {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
})
|
|
617
|
-
.join(" ");
|
|
825
|
+
if (annotations.length === 0) {
|
|
826
|
+
return "User responded with no marks.";
|
|
827
|
+
}
|
|
828
|
+
return annotations.map((a) => {
|
|
829
|
+
const note = "text" in a && a.text ? ` — "${a.text}"` : "";
|
|
830
|
+
if (a.kind === "confirm") {
|
|
831
|
+
return `User ${a.value ? "confirmed" : "declined"}.`;
|
|
832
|
+
}
|
|
833
|
+
if (a.kind === "choice") {
|
|
834
|
+
return `User chose "${a.value}".`;
|
|
835
|
+
}
|
|
836
|
+
if (a.kind === "element") {
|
|
837
|
+
const what = a.ref ? `ref ${a.ref}` : a.selector ?? "an element";
|
|
838
|
+
return `User selected ${what}${note}.`;
|
|
839
|
+
}
|
|
840
|
+
if (a.kind === "region") {
|
|
841
|
+
const refs = a.refs.length ? ` covering ${a.refs.join(", ")}` : "";
|
|
842
|
+
return `User boxed a ${Math.round(a.rect.width)}×${Math.round(a.rect.height)} region${refs}${note}.`;
|
|
843
|
+
}
|
|
844
|
+
const where = a.ref ? `ref ${a.ref}` : `(${Math.round(a.x)}, ${Math.round(a.y)})`;
|
|
845
|
+
return `User pointed at ${where}${note}.`;
|
|
846
|
+
}).join(" ");
|
|
618
847
|
}
|
|
848
|
+
|
|
619
849
|
//# sourceMappingURL=catalog.js.map
|