yunti-browser-runtime 0.1.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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +256 -0
  3. package/bin/yunti-browser-runtime.js +86 -0
  4. package/docs/EXECUTION_PLAN.md +1278 -0
  5. package/docs/INSTALL.md +205 -0
  6. package/docs/PROJECT_INTENT.md +44 -0
  7. package/docs/PROJECT_STATUS.md +263 -0
  8. package/docs/PUBLISHING_BLOCKERS.md +110 -0
  9. package/docs/RELEASE.md +148 -0
  10. package/docs/ROADMAP.md +42 -0
  11. package/docs/SECURITY.md +56 -0
  12. package/docs/TOOL_GUIDE.md +69 -0
  13. package/extension/background.js +55 -0
  14. package/extension/cdp.js +582 -0
  15. package/extension/content.css +9 -0
  16. package/extension/content.js +946 -0
  17. package/extension/manifest.json +35 -0
  18. package/extension/network-monitor.js +140 -0
  19. package/extension/popup.css +66 -0
  20. package/extension/popup.html +30 -0
  21. package/extension/popup.js +55 -0
  22. package/extension/session-manager.js +332 -0
  23. package/extension/settings.js +94 -0
  24. package/extension/tool-handlers.js +1158 -0
  25. package/lib/runtime-paths.js +39 -0
  26. package/mcp/bridge-hub.js +604 -0
  27. package/mcp/http-server.js +326 -0
  28. package/mcp/json-rpc.js +35 -0
  29. package/mcp/memory.js +126 -0
  30. package/mcp/redaction.js +94 -0
  31. package/mcp/server.js +269 -0
  32. package/mcp/tools.js +1092 -0
  33. package/package.json +60 -0
  34. package/scripts/check-package-metadata.js +131 -0
  35. package/scripts/check-published-package.js +113 -0
  36. package/scripts/doctor.js +163 -0
  37. package/scripts/package-extension.js +137 -0
  38. package/scripts/print-config.js +116 -0
  39. package/scripts/release-check.js +472 -0
  40. package/skills/yunti-browser-runtime/SKILL.md +77 -0
package/mcp/tools.js ADDED
@@ -0,0 +1,1092 @@
1
+ export const TOOLS = [
2
+ {
3
+ name: "yunti_get_tool_usage_hints",
4
+ description:
5
+ "Return current Yunti Browser Runtime MCP tool usage hints, required parameters, common mistakes, and recommended workflows. With no arguments it returns core rules and key tools; pass tool for one tool's schema/hints, or topic for a filtered group. Use this before retrying a failed or uncertain yunti_* tool call.",
6
+ inputSchema: {
7
+ type: "object",
8
+ properties: {
9
+ tool: {
10
+ type: "string",
11
+ description:
12
+ "Optional tool name to focus on, for example yunti_evaluate_script or yunti_close_page.",
13
+ },
14
+ topic: {
15
+ type: "string",
16
+ enum: ["all", "browser", "cdp", "tabs", "memory", "network", "console"],
17
+ description: "Optional topic filter. Defaults to all.",
18
+ },
19
+ },
20
+ },
21
+ },
22
+ {
23
+ name: "yunti_get_page_snapshot",
24
+ description:
25
+ "Read a lightweight current-user browser page snapshot: URL, title, auth state, selected text, visible text excerpt, browserSessionId, and optional element summaries. Does not read raw cookies.",
26
+ inputSchema: {
27
+ type: "object",
28
+ properties: {
29
+ browserSessionId: {
30
+ type: "string",
31
+ description:
32
+ "Optional target Yunti browser session owned by the required userId. Use the browserSessionId returned by yunti_get_page_snapshot or the current Yunti browser route for stable current-tab routing.",
33
+ },
34
+ mode: {
35
+ type: "string",
36
+ enum: ["light", "detailed"],
37
+ description:
38
+ "Use light for session/auth/page overview. Use detailed only when element summaries are needed.",
39
+ },
40
+ includeElements: {
41
+ type: "boolean",
42
+ description:
43
+ "Include forms, buttons, inputs, links, and tables. Defaults to true only when mode is detailed.",
44
+ },
45
+ maxTextLength: {
46
+ type: "integer",
47
+ minimum: 0,
48
+ maximum: 60000,
49
+ description: "Maximum visible text characters to return.",
50
+ },
51
+ },
52
+ },
53
+ },
54
+ {
55
+ name: "yunti_get_selected_context",
56
+ description:
57
+ "Read the current selection and nearest DOM context from the active browser page.",
58
+ inputSchema: {
59
+ type: "object",
60
+ properties: {
61
+ browserSessionId: { type: "string" },
62
+ },
63
+ },
64
+ },
65
+ {
66
+ name: "yunti_fetch_with_cookie",
67
+ description:
68
+ "Ask the browser extension to fetch an internal platform URL with the current browser login cookies. Cookie values are never returned.",
69
+ inputSchema: {
70
+ type: "object",
71
+ required: ["url"],
72
+ properties: {
73
+ browserSessionId: { type: "string" },
74
+ url: { type: "string" },
75
+ method: { type: "string", default: "GET" },
76
+ headers: { type: "object", additionalProperties: { type: "string" } },
77
+ body: { type: "string" },
78
+ maxBytes: { type: "integer", minimum: 1024, maximum: 1000000 },
79
+ confirmed: {
80
+ type: "boolean",
81
+ description: "Set true only after the user approved a dangerous non-read request.",
82
+ },
83
+ },
84
+ },
85
+ },
86
+ {
87
+ name: "yunti_get_network_log",
88
+ description:
89
+ "Read recent sanitized internal platform network observations captured by the browser extension. Does not include raw cookies, auth headers, or response bodies.",
90
+ inputSchema: {
91
+ type: "object",
92
+ properties: {
93
+ browserSessionId: { type: "string" },
94
+ allSessions: { type: "boolean" },
95
+ limit: { type: "integer", minimum: 1, maximum: 500 },
96
+ sinceId: { type: "integer", minimum: 1 },
97
+ method: { type: "string" },
98
+ urlContains: { type: "string" },
99
+ },
100
+ },
101
+ },
102
+ {
103
+ name: "yunti_clear_network_log",
104
+ description:
105
+ "Clear sanitized Yunti network observations for the active tab, a selected session, or all sessions.",
106
+ inputSchema: {
107
+ type: "object",
108
+ properties: {
109
+ browserSessionId: { type: "string" },
110
+ allSessions: { type: "boolean" },
111
+ },
112
+ },
113
+ },
114
+ {
115
+ name: "yunti_clear_network_requests",
116
+ description:
117
+ "Clear structured network request observations for the active tab, a selected session, or all sessions. Alias of yunti_clear_network_log with network-request naming.",
118
+ inputSchema: {
119
+ type: "object",
120
+ properties: {
121
+ browserSessionId: { type: "string" },
122
+ allSessions: { type: "boolean" },
123
+ },
124
+ },
125
+ },
126
+ {
127
+ name: "yunti_list_network_requests",
128
+ description:
129
+ "List network requests captured from the active browser page with request ids, resource type, status, timing, and sanitized summaries.",
130
+ inputSchema: {
131
+ type: "object",
132
+ properties: {
133
+ browserSessionId: { type: "string" },
134
+ allSessions: { type: "boolean" },
135
+ limit: { type: "integer", minimum: 1, maximum: 500 },
136
+ sinceId: { type: "integer", minimum: 1 },
137
+ method: { type: "string" },
138
+ urlContains: { type: "string" },
139
+ },
140
+ },
141
+ },
142
+ {
143
+ name: "yunti_get_network_request",
144
+ description:
145
+ "Get a single network request by its event id (from yunti_list_network_requests). Returns URL, method, status, timing, request body summary, and sanitized headers.",
146
+ inputSchema: {
147
+ type: "object",
148
+ required: ["eventId"],
149
+ properties: {
150
+ browserSessionId: { type: "string" },
151
+ eventId: { type: "integer", description: "The event id from yunti_list_network_requests or yunti_get_network_log." },
152
+ },
153
+ },
154
+ },
155
+ {
156
+ name: "yunti_remember_learning",
157
+ description:
158
+ "Store an auditable Yunti learning memory such as an API pattern, workflow step, selector, field mapping, or gotcha. Do not store secrets or raw cookies.",
159
+ inputSchema: {
160
+ type: "object",
161
+ required: ["title", "detail"],
162
+ properties: {
163
+ userId: {
164
+ type: "string",
165
+ description:
166
+ "Optional local route user id. Defaults to YUNTI_BROWSER_USER_ID or local.",
167
+ },
168
+ kind: { type: "string" },
169
+ title: { type: "string" },
170
+ detail: { type: "string" },
171
+ tags: { type: "array", items: { type: "string" } },
172
+ confidence: { type: "number", minimum: 0, maximum: 1 },
173
+ source: { type: "string" },
174
+ relatedNetworkEventIds: { type: "array", items: { type: "integer" } },
175
+ },
176
+ },
177
+ },
178
+ {
179
+ name: "yunti_get_learning_memory",
180
+ description: "Search auditable Yunti learning memories recorded by agents.",
181
+ inputSchema: {
182
+ type: "object",
183
+ properties: {
184
+ userId: {
185
+ type: "string",
186
+ description:
187
+ "Optional local route user id. Defaults to YUNTI_BROWSER_USER_ID or local.",
188
+ },
189
+ query: { type: "string" },
190
+ kind: { type: "string" },
191
+ tags: { type: "array", items: { type: "string" } },
192
+ limit: { type: "integer", minimum: 1, maximum: 100 },
193
+ },
194
+ },
195
+ },
196
+ {
197
+ name: "yunti_forget_learning_memory",
198
+ description: "Delete one Yunti learning memory by id, or all memories when confirmed.",
199
+ inputSchema: {
200
+ type: "object",
201
+ properties: {
202
+ userId: {
203
+ type: "string",
204
+ description:
205
+ "Optional local route user id. Defaults to YUNTI_BROWSER_USER_ID or local.",
206
+ },
207
+ id: { type: "string" },
208
+ all: { type: "boolean" },
209
+ confirmed: { type: "boolean" },
210
+ },
211
+ },
212
+ },
213
+ {
214
+ name: "yunti_apply_preview_patch",
215
+ description:
216
+ "Apply temporary DOM patches to the current browser page. Patches are preview-only and disappear after refresh.",
217
+ inputSchema: {
218
+ type: "object",
219
+ required: ["patches"],
220
+ properties: {
221
+ browserSessionId: { type: "string" },
222
+ patchId: { type: "string" },
223
+ patches: {
224
+ type: "array",
225
+ items: {
226
+ type: "object",
227
+ required: ["selector"],
228
+ properties: {
229
+ selector: { type: "string" },
230
+ text: { type: "string" },
231
+ html: { type: "string" },
232
+ value: { type: "string" },
233
+ appendHtml: { type: "string" },
234
+ beforeHtml: { type: "string" },
235
+ afterHtml: { type: "string" },
236
+ style: { type: "object", additionalProperties: { type: "string" } },
237
+ attributes: { type: "object", additionalProperties: { type: "string" } },
238
+ className: { type: "string" },
239
+ },
240
+ },
241
+ },
242
+ },
243
+ },
244
+ },
245
+ {
246
+ name: "yunti_capture_visible_tab",
247
+ description:
248
+ "Capture a PNG screenshot of the visible area of the active Yunti browser tab through the extension. Reuses the user's current browser without requiring a separate debugging setup.",
249
+ inputSchema: {
250
+ type: "object",
251
+ properties: {
252
+ browserSessionId: { type: "string" },
253
+ },
254
+ },
255
+ },
256
+ {
257
+ name: "yunti_list_browser_targets",
258
+ description:
259
+ "List all Chrome/Edge browser targets visible inside the current user's local browser instance through Yunti Browser Runtime. This is the canonical whole-browser inventory for tab/page counts and target overviews.",
260
+ inputSchema: {
261
+ type: "object",
262
+ properties: {
263
+ browserSessionId: {
264
+ type: "string",
265
+ description:
266
+ "Optional connected Yunti browser session used as the local extension route. Pass the current session id when available.",
267
+ },
268
+ },
269
+ },
270
+ },
271
+ {
272
+ name: "yunti_get_browser_target",
273
+ description:
274
+ "Get one Chrome/Edge browser target from the current user's local browser instance by targetId or tabId. Use this after yunti_list_browser_targets for detailed target inspection without switching browser sessions.",
275
+ inputSchema: {
276
+ type: "object",
277
+ properties: {
278
+ browserSessionId: {
279
+ type: "string",
280
+ description:
281
+ "Optional connected Yunti browser session used as the local extension route. Pass the current session id when available.",
282
+ },
283
+ targetId: {
284
+ type: "string",
285
+ description: "Target id returned by yunti_list_browser_targets.",
286
+ },
287
+ tabId: {
288
+ type: "integer",
289
+ description: "Chrome/Edge tab id returned by yunti_list_browser_targets.",
290
+ },
291
+ },
292
+ },
293
+ },
294
+ {
295
+ name: "yunti_cdp_send_command",
296
+ description:
297
+ "Forward one low-level browser protocol command through the installed Yunti extension. The required userId is the isolation scope; browserSessionId routes the request to that user's extension/browser instance. Optional tabId or targetId selects the concrete Chrome/Edge target inside that browser, including targets listed by yunti_list_browser_targets that are not registered Yunti sessions. Browser method names such as Target.activateTarget, Runtime.evaluate, Page.navigate, Network.enable, and DOM.* are not terminal/shell commands; call them here through the method and params fields. For current-page or multi-step operations, pass both userId and browserSessionId from yunti_get_page_snapshot or the current Yunti browser route so Runtime.evaluate and follow-up calls stay on the same tab. For switching to a specific tab, use yunti_list_browser_targets with userId/browserSessionId to find tabId or targetId, then call Target.activateTarget through this tool.",
298
+ inputSchema: {
299
+ type: "object",
300
+ required: ["method"],
301
+ properties: {
302
+ browserSessionId: {
303
+ type: "string",
304
+ description:
305
+ "Routes the request to this user's connected Yunti extension session. This is the browser channel, not necessarily the final CDP target when tabId/targetId is set.",
306
+ },
307
+ tabId: {
308
+ type: "number",
309
+ description:
310
+ "Optional Chrome/Edge tab id returned by yunti_list_browser_targets. When set, CDP is sent to this tab even if it is not a registered Yunti page.",
311
+ },
312
+ targetId: {
313
+ type: "string",
314
+ description:
315
+ "Optional target id returned by yunti_list_browser_targets, or tab-<tabId>. When set, CDP is sent to the resolved tab even if it is not a registered Yunti page.",
316
+ },
317
+ method: {
318
+ type: "string",
319
+ description: "Browser protocol method name, for example Runtime.evaluate or Page.captureScreenshot.",
320
+ },
321
+ params: {
322
+ type: "object",
323
+ description: "Raw CDP command parameters.",
324
+ additionalProperties: true,
325
+ },
326
+ protocolVersion: {
327
+ type: "string",
328
+ description: "Debugger protocol version for first attach. Defaults to 1.3.",
329
+ },
330
+ attach: {
331
+ type: "boolean",
332
+ description: "Attach before sending. Defaults to true.",
333
+ },
334
+ },
335
+ },
336
+ },
337
+ {
338
+ name: "yunti_cdp_detach",
339
+ description:
340
+ "Detach the Yunti extension from the active browser tab's low-level browser protocol target.",
341
+ inputSchema: {
342
+ type: "object",
343
+ properties: {
344
+ browserSessionId: { type: "string" },
345
+ },
346
+ },
347
+ },
348
+ {
349
+ name: "yunti_get_cdp_events",
350
+ description:
351
+ "Read raw low-level browser protocol events forwarded by the browser extension for the active tab. First internal version does not redact event payloads.",
352
+ inputSchema: {
353
+ type: "object",
354
+ properties: {
355
+ browserSessionId: { type: "string" },
356
+ allSessions: { type: "boolean" },
357
+ limit: { type: "integer", minimum: 1, maximum: 500 },
358
+ sinceId: { type: "integer", minimum: 1 },
359
+ method: { type: "string" },
360
+ },
361
+ },
362
+ },
363
+ {
364
+ name: "yunti_clear_cdp_events",
365
+ description:
366
+ "Clear raw CDP events for the active tab, a selected session, or all sessions.",
367
+ inputSchema: {
368
+ type: "object",
369
+ properties: {
370
+ browserSessionId: { type: "string" },
371
+ allSessions: { type: "boolean" },
372
+ },
373
+ },
374
+ },
375
+ {
376
+ name: "yunti_click_at",
377
+ description:
378
+ "Click a viewport coordinate in the current browser page through the extension. Useful when selector tools are brittle. Dangerous targets require confirmation.",
379
+ inputSchema: {
380
+ type: "object",
381
+ required: ["x", "y"],
382
+ properties: {
383
+ browserSessionId: { type: "string" },
384
+ x: { type: "number", description: "Viewport x coordinate in CSS pixels." },
385
+ y: { type: "number", description: "Viewport y coordinate in CSS pixels." },
386
+ confirmed: { type: "boolean" },
387
+ },
388
+ },
389
+ },
390
+ {
391
+ name: "yunti_type_text",
392
+ description:
393
+ "Type or set text in the focused element, a selector target, a uid target (from yunti_take_snapshot), or a coordinate target on the current browser page.",
394
+ inputSchema: {
395
+ type: "object",
396
+ required: ["text"],
397
+ properties: {
398
+ browserSessionId: { type: "string" },
399
+ uid: { type: "string", description: "Stable uid from yunti_take_snapshot." },
400
+ text: { type: "string" },
401
+ selector: { type: "string" },
402
+ x: { type: "number" },
403
+ y: { type: "number" },
404
+ clear: { type: "boolean", description: "Replace existing text instead of appending." },
405
+ },
406
+ },
407
+ },
408
+ {
409
+ name: "yunti_press_key",
410
+ description:
411
+ "Send a keyboard key event to the focused element, a uid target (from yunti_take_snapshot), a selector target, or a coordinate target on the current browser page.",
412
+ inputSchema: {
413
+ type: "object",
414
+ required: ["key"],
415
+ properties: {
416
+ browserSessionId: { type: "string" },
417
+ uid: { type: "string", description: "Stable uid from yunti_take_snapshot." },
418
+ key: { type: "string", description: "Examples: Enter, Escape, Tab, ArrowDown, Backspace." },
419
+ selector: { type: "string" },
420
+ x: { type: "number" },
421
+ y: { type: "number" },
422
+ },
423
+ },
424
+ },
425
+ {
426
+ name: "yunti_scroll",
427
+ description:
428
+ "Scroll the current browser page or the scrollable container under a viewport coordinate through the extension.",
429
+ inputSchema: {
430
+ type: "object",
431
+ properties: {
432
+ browserSessionId: { type: "string" },
433
+ x: { type: "number" },
434
+ y: { type: "number" },
435
+ deltaX: { type: "number", default: 0 },
436
+ deltaY: { type: "number", default: 600 },
437
+ },
438
+ },
439
+ },
440
+ {
441
+ name: "yunti_drag",
442
+ description:
443
+ "Drag from one viewport coordinate to another. Uses CDP Input.dispatchMouseEvent sequence: press → move → release. Useful for sliders, sortable lists, and drag-and-drop UI.",
444
+ inputSchema: {
445
+ type: "object",
446
+ required: ["fromX", "fromY", "toX", "toY"],
447
+ properties: {
448
+ browserSessionId: { type: "string" },
449
+ fromX: { type: "number", description: "Start viewport x coordinate." },
450
+ fromY: { type: "number", description: "Start viewport y coordinate." },
451
+ toX: { type: "number", description: "End viewport x coordinate." },
452
+ toY: { type: "number", description: "End viewport y coordinate." },
453
+ steps: { type: "integer", minimum: 1, maximum: 50, description: "Number of intermediate move events. Defaults to 10." },
454
+ },
455
+ },
456
+ },
457
+ {
458
+ name: "yunti_upload_file",
459
+ description:
460
+ "Set files on a file input element by uid (from yunti_take_snapshot) or selector. Uses CDP DOM.setFileInputFiles. Paths must be accessible to the browser.",
461
+ inputSchema: {
462
+ type: "object",
463
+ required: ["filePaths"],
464
+ properties: {
465
+ browserSessionId: { type: "string" },
466
+ uid: { type: "string", description: "Stable uid from yunti_take_snapshot for the file input." },
467
+ selector: { type: "string", description: "CSS selector for the file input element." },
468
+ filePaths: { type: "array", items: { type: "string" }, description: "Absolute file paths to upload." },
469
+ },
470
+ },
471
+ },
472
+ {
473
+ name: "yunti_rollback_preview_patch",
474
+ description:
475
+ "Rollback one temporary preview patch by patchId, or all preview patches if patchId is omitted.",
476
+ inputSchema: {
477
+ type: "object",
478
+ properties: {
479
+ browserSessionId: { type: "string" },
480
+ patchId: { type: "string" },
481
+ },
482
+ },
483
+ },
484
+ {
485
+ name: "yunti_click",
486
+ description:
487
+ "Click an element on the current browser page using a uid from yunti_take_snapshot, a CSS selector, or viewport coordinates. Prefer uid for reliability. For coordinate-only clicks, yunti_click_at is the clearer dedicated tool. Dangerous labels require user confirmation.",
488
+ inputSchema: {
489
+ type: "object",
490
+ properties: {
491
+ browserSessionId: { type: "string" },
492
+ uid: { type: "string", description: "Stable uid from yunti_take_snapshot (e.g. yunti-1). Takes precedence over selector." },
493
+ selector: { type: "string", description: "CSS selector. Used when uid is not provided." },
494
+ x: { type: "number", description: "Viewport x coordinate fallback. Use together with y; yunti_click_at is preferred for coordinate-only clicks." },
495
+ y: { type: "number", description: "Viewport y coordinate fallback. Use together with x; yunti_click_at is preferred for coordinate-only clicks." },
496
+ confirmed: { type: "boolean" },
497
+ },
498
+ },
499
+ },
500
+ {
501
+ name: "yunti_hover",
502
+ description:
503
+ "Hover over an element on the current browser page using a uid from yunti_take_snapshot, a CSS selector, or viewport coordinates. Useful for triggering tooltips, dropdowns, and hover menus.",
504
+ inputSchema: {
505
+ type: "object",
506
+ properties: {
507
+ browserSessionId: { type: "string" },
508
+ uid: { type: "string", description: "Stable uid from yunti_take_snapshot (e.g. yunti-1). Takes precedence over selector." },
509
+ selector: { type: "string", description: "CSS selector fallback. The element center is resolved and hovered through CDP." },
510
+ x: { type: "number", description: "Viewport x coordinate fallback. Use together with y." },
511
+ y: { type: "number", description: "Viewport y coordinate fallback. Use together with x." },
512
+ },
513
+ },
514
+ },
515
+ {
516
+ name: "yunti_fill",
517
+ description:
518
+ "Fill an input, textarea, select, or contenteditable element using a uid from yunti_take_snapshot or a CSS selector. Prefer uid for reliability.",
519
+ inputSchema: {
520
+ type: "object",
521
+ required: ["value"],
522
+ properties: {
523
+ browserSessionId: { type: "string" },
524
+ uid: { type: "string", description: "Stable uid from yunti_take_snapshot (e.g. yunti-3). Takes precedence over selector." },
525
+ selector: { type: "string", description: "CSS selector. Used when uid is not provided." },
526
+ value: { type: "string" },
527
+ },
528
+ },
529
+ },
530
+ {
531
+ name: "yunti_list_console_messages",
532
+ description:
533
+ "List console messages (console.log, console.error, console.warn, etc.) captured from the active browser page via CDP Runtime/Log events. Supports filtering by level and pagination.",
534
+ inputSchema: {
535
+ type: "object",
536
+ properties: {
537
+ browserSessionId: { type: "string" },
538
+ allSessions: { type: "boolean" },
539
+ level: { type: "string", enum: ["error", "warning", "info", "debug", "log", "verbose"] },
540
+ source: { type: "string", enum: ["console-api", "javascript", "network", "other"] },
541
+ limit: { type: "integer", minimum: 1, maximum: 500 },
542
+ sinceId: { type: "integer", minimum: 1 },
543
+ },
544
+ },
545
+ },
546
+ {
547
+ name: "yunti_get_console_message",
548
+ description:
549
+ "Get a single console message by its msgid from yunti_list_console_messages. Returns full detail including stack trace.",
550
+ inputSchema: {
551
+ type: "object",
552
+ required: ["msgId"],
553
+ properties: {
554
+ browserSessionId: { type: "string" },
555
+ msgId: { type: "integer", description: "The message id from yunti_list_console_messages." },
556
+ },
557
+ },
558
+ },
559
+ {
560
+ name: "yunti_clear_console_messages",
561
+ description:
562
+ "Clear cached console messages for a session, or all sessions.",
563
+ inputSchema: {
564
+ type: "object",
565
+ properties: {
566
+ browserSessionId: { type: "string" },
567
+ allSessions: { type: "boolean" },
568
+ },
569
+ },
570
+ },
571
+ {
572
+ name: "yunti_select",
573
+ description: "Select an option in a select element on the current browser page.",
574
+ inputSchema: {
575
+ type: "object",
576
+ required: ["selector", "value"],
577
+ properties: {
578
+ browserSessionId: { type: "string" },
579
+ selector: { type: "string" },
580
+ value: { type: "string" },
581
+ },
582
+ },
583
+ },
584
+ {
585
+ name: "yunti_fill_form",
586
+ description:
587
+ "Fill multiple form fields at once. Each field specifies a uid (from yunti_take_snapshot) or a selector, and its value. More efficient than calling yunti_fill repeatedly.",
588
+ inputSchema: {
589
+ type: "object",
590
+ required: ["fields"],
591
+ properties: {
592
+ browserSessionId: { type: "string" },
593
+ fields: {
594
+ type: "array",
595
+ items: {
596
+ type: "object",
597
+ required: ["value"],
598
+ properties: {
599
+ uid: { type: "string", description: "Stable uid from yunti_take_snapshot." },
600
+ selector: { type: "string", description: "CSS selector fallback." },
601
+ value: { type: "string", description: "Value to fill." },
602
+ },
603
+ },
604
+ },
605
+ },
606
+ },
607
+ },
608
+ {
609
+ name: "yunti_handle_dialog",
610
+ description:
611
+ "Handle a JavaScript dialog (alert, confirm, prompt) on the page. Use 'accept' to dismiss or 'dismiss' to cancel. For prompts, provide promptText.",
612
+ inputSchema: {
613
+ type: "object",
614
+ required: ["action"],
615
+ properties: {
616
+ browserSessionId: { type: "string" },
617
+ action: { type: "string", enum: ["accept", "dismiss"], description: "accept = click OK, dismiss = click Cancel." },
618
+ promptText: { type: "string", description: "Text to enter for prompt dialogs." },
619
+ },
620
+ },
621
+ },
622
+ {
623
+ name: "yunti_resize_page",
624
+ description:
625
+ "Resize the browser page viewport to the specified dimensions. Uses CDP Emulation.setDeviceMetricsOverride.",
626
+ inputSchema: {
627
+ type: "object",
628
+ properties: {
629
+ browserSessionId: { type: "string" },
630
+ width: { type: "integer", minimum: 100, maximum: 10000, description: "Viewport width in CSS pixels." },
631
+ height: { type: "integer", minimum: 100, maximum: 10000, description: "Viewport height in CSS pixels." },
632
+ deviceScaleFactor: { type: "number", minimum: 0.5, maximum: 3, description: "Device pixel ratio. Defaults to 1." },
633
+ },
634
+ },
635
+ },
636
+ {
637
+ name: "yunti_emulate",
638
+ description:
639
+ "Emulate a device, user agent, or network/CPU conditions. Uses low-level browser emulation APIs.",
640
+ inputSchema: {
641
+ type: "object",
642
+ properties: {
643
+ browserSessionId: { type: "string" },
644
+ deviceName: { type: "string", description: "Device name preset: 'iPhone 12', 'Pixel 5', 'iPad', etc." },
645
+ userAgent: { type: "string", description: "Custom user agent string." },
646
+ viewport: { type: "object", properties: { width: { type: "integer" }, height: { type: "integer" }, deviceScaleFactor: { type: "number" } } },
647
+ cpuThrottleRate: { type: "number", minimum: 1, maximum: 20, description: "CPU slowdown factor." },
648
+ networkConditions: { type: "string", enum: ["offline", "slow3g", "fast3g", "slow4g", "none"], description: "Network throttling preset." },
649
+ clear: { type: "boolean", description: "Set to true to clear all emulation overrides." },
650
+ },
651
+ },
652
+ },
653
+ {
654
+ name: "yunti_performance_start_trace",
655
+ description:
656
+ "Start a performance trace on the selected page. Uses the browser tracing API to capture timeline events. Call yunti_performance_stop_trace to end and collect results.",
657
+ inputSchema: {
658
+ type: "object",
659
+ properties: {
660
+ browserSessionId: { type: "string" },
661
+ categories: { type: "string", description: "Comma-separated trace categories. Default: 'blink,loading,rendering,page'." },
662
+ },
663
+ },
664
+ },
665
+ {
666
+ name: "yunti_performance_stop_trace",
667
+ description:
668
+ "Stop the active performance trace and return captured events. Uses the browser tracing API.",
669
+ inputSchema: {
670
+ type: "object",
671
+ properties: {
672
+ browserSessionId: { type: "string" },
673
+ },
674
+ },
675
+ },
676
+ {
677
+ name: "yunti_new_page",
678
+ description:
679
+ "Create a new browser tab and optionally navigate to a URL. Returns the new tab's browserSessionId for subsequent tool calls.",
680
+ inputSchema: {
681
+ type: "object",
682
+ properties: {
683
+ url: { type: "string", description: "URL to navigate the new tab to." },
684
+ active: { type: "boolean", description: "Whether to activate the new tab. Defaults to true." },
685
+ },
686
+ },
687
+ },
688
+ {
689
+ name: "yunti_close_page",
690
+ description:
691
+ "Close a browser tab identified by its browserSessionId. The last connected tab cannot be closed to prevent losing the agent's browser context.",
692
+ inputSchema: {
693
+ type: "object",
694
+ required: ["browserSessionId"],
695
+ properties: {
696
+ browserSessionId: { type: "string" },
697
+ },
698
+ },
699
+ },
700
+ {
701
+ name: "yunti_wait_for",
702
+ description:
703
+ "Wait for a condition to be met on the page: text appears, a selector becomes visible, the URL changes, or the DOM/network becomes idle. Returns when the condition is met or times out.",
704
+ inputSchema: {
705
+ type: "object",
706
+ properties: {
707
+ browserSessionId: { type: "string" },
708
+ text: { type: "string", description: "Wait for this text to appear on the page." },
709
+ selector: { type: "string", description: "Wait for this CSS selector to be visible." },
710
+ urlContains: { type: "string", description: "Wait until the page URL contains this string." },
711
+ timeoutMs: { type: "integer", minimum: 100, maximum: 30000, description: "Max wait time. Defaults to 5000." },
712
+ },
713
+ },
714
+ },
715
+ {
716
+ name: "yunti_list_pages",
717
+ description:
718
+ "List current browser pages/tabs visible inside the current user's local browser instance. Compatibility alias for yunti_list_browser_targets; results come from the same live Chrome/Edge target inventory rather than stale Yunti registration records.",
719
+ inputSchema: {
720
+ type: "object",
721
+ properties: {
722
+ browserSessionId: {
723
+ type: "string",
724
+ description:
725
+ "Optional connected Yunti browser session used as the local extension route. Pass the current session id when available.",
726
+ },
727
+ userId: {
728
+ type: "string",
729
+ description:
730
+ "Required current Yunti user id. Used as the isolation scope for the browser route.",
731
+ },
732
+ },
733
+ },
734
+ },
735
+ {
736
+ name: "yunti_select_page",
737
+ description:
738
+ "Select a connected Yunti browser page as the active session for subsequent session-scoped tool calls. The page must already be registered by Yunti Browser Runtime. Do not pass raw Chrome targetIds here; for whole-browser targets returned by yunti_list_browser_targets, use yunti_cdp_send_command with tabId or targetId instead.",
739
+ inputSchema: {
740
+ type: "object",
741
+ required: ["browserSessionId"],
742
+ properties: {
743
+ browserSessionId: {
744
+ type: "string",
745
+ description:
746
+ "A registered Yunti browserSessionId from yunti_get_page_snapshot or a known Yunti session. Do not pass raw targetId or tabId from browser target inventory here.",
747
+ },
748
+ },
749
+ },
750
+ },
751
+ {
752
+ name: "yunti_navigate_page",
753
+ description:
754
+ "Navigate the selected browser page to a URL, reload, or go back/forward. URL/reload use browser tab APIs; back/forward prefer CDP history entries and fall back to window.history when SPA/hash history is not represented by CDP.",
755
+ inputSchema: {
756
+ type: "object",
757
+ properties: {
758
+ browserSessionId: { type: "string", description: "Target browser session." },
759
+ url: { type: "string", description: "URL to navigate to. Required when action is 'url'." },
760
+ action: {
761
+ type: "string",
762
+ enum: ["url", "reload", "back", "forward"],
763
+ description: "Navigation action. Defaults to 'url'.",
764
+ },
765
+ },
766
+ },
767
+ },
768
+ {
769
+ name: "yunti_take_screenshot",
770
+ description:
771
+ "Capture a PNG screenshot of the selected browser page. Supports viewport and full-page modes via CDP Page.captureScreenshot.",
772
+ inputSchema: {
773
+ type: "object",
774
+ properties: {
775
+ browserSessionId: { type: "string", description: "Target browser session." },
776
+ format: { type: "string", enum: ["png", "jpeg"], description: "Image format. Defaults to png." },
777
+ quality: { type: "integer", minimum: 0, maximum: 100, description: "JPEG quality (0-100). Ignored for PNG." },
778
+ fullPage: { type: "boolean", description: "Capture full scrollable page. Defaults to false (viewport only)." },
779
+ clip: {
780
+ type: "object",
781
+ properties: {
782
+ x: { type: "number" },
783
+ y: { type: "number" },
784
+ width: { type: "number" },
785
+ height: { type: "number" },
786
+ scale: { type: "number" },
787
+ },
788
+ },
789
+ },
790
+ },
791
+ },
792
+ {
793
+ name: "yunti_evaluate_script",
794
+ description:
795
+ "Evaluate a JavaScript expression in the selected browser page and return the result. Uses CDP Runtime.evaluate. The result is serialized and length-limited.",
796
+ inputSchema: {
797
+ type: "object",
798
+ required: ["expression"],
799
+ properties: {
800
+ browserSessionId: { type: "string", description: "Target browser session." },
801
+ expression: { type: "string", description: "JavaScript expression to evaluate." },
802
+ awaitPromise: { type: "boolean", description: "Wait for the returned promise to resolve. Defaults to false." },
803
+ maxLength: { type: "integer", minimum: 0, maximum: 100000, description: "Max result length. Defaults to 10000." },
804
+ },
805
+ },
806
+ },
807
+ {
808
+ name: "yunti_take_snapshot",
809
+ description:
810
+ "Take an accessibility-tree-based snapshot of the current page. Returns stable uids (yunti-1, yunti-2, ...) for each interactive element. Use these uids with yunti_click, yunti_fill, and yunti_hover. Prefer this over raw selectors or coordinates.",
811
+ inputSchema: {
812
+ type: "object",
813
+ properties: {
814
+ browserSessionId: { type: "string", description: "Target browser session." },
815
+ maxElements: { type: "integer", minimum: 1, maximum: 500, description: "Max elements to return. Defaults to 200." },
816
+ includeHidden: { type: "boolean", description: "Include hidden/invisible elements. Defaults to false." },
817
+ },
818
+ },
819
+ },
820
+ {
821
+ name: "yunti_request_user_confirmation",
822
+ description:
823
+ "Ask the browser user to confirm an action in the browser page before the agent proceeds.",
824
+ inputSchema: {
825
+ type: "object",
826
+ required: ["message"],
827
+ properties: {
828
+ browserSessionId: { type: "string" },
829
+ message: { type: "string" },
830
+ detail: { type: "string" },
831
+ },
832
+ },
833
+ },
834
+ ]
835
+
836
+ export const BRIDGE_LOCAL_TOOLS = new Set([
837
+ "yunti_get_network_log",
838
+ "yunti_clear_network_log",
839
+ "yunti_get_cdp_events",
840
+ "yunti_clear_cdp_events",
841
+ "yunti_select_page",
842
+ "yunti_clear_network_requests",
843
+ "yunti_list_console_messages",
844
+ "yunti_get_console_message",
845
+ "yunti_clear_console_messages",
846
+ "yunti_list_network_requests",
847
+ "yunti_get_network_request",
848
+ ])
849
+
850
+ export const MEMORY_LOCAL_TOOLS = new Set([
851
+ "yunti_remember_learning",
852
+ "yunti_get_learning_memory",
853
+ "yunti_forget_learning_memory",
854
+ ])
855
+
856
+ export const META_LOCAL_TOOLS = new Set([
857
+ "yunti_get_tool_usage_hints",
858
+ ])
859
+
860
+ export const BROWSER_SCOPED_TOOLS = new Set(
861
+ TOOLS.map((tool) => tool.name).filter((name) => !MEMORY_LOCAL_TOOLS.has(name) && !META_LOCAL_TOOLS.has(name))
862
+ )
863
+
864
+ installBrowserIsolationSchemas()
865
+
866
+ function installBrowserIsolationSchemas() {
867
+ for (const tool of TOOLS) {
868
+ if (MEMORY_LOCAL_TOOLS.has(tool.name)) continue
869
+ const schema = tool.inputSchema || { type: "object" }
870
+ schema.properties = schema.properties || {}
871
+ schema.properties.userId = {
872
+ type: "string",
873
+ description:
874
+ "Optional local route user id. Defaults to YUNTI_BROWSER_USER_ID or local in the standalone runtime.",
875
+ }
876
+ tool.inputSchema = schema
877
+ }
878
+ }
879
+
880
+
881
+
882
+ export function schemaForTool(name) {
883
+ return TOOLS.find((tool) => tool.name === name)?.inputSchema || null
884
+ }
885
+
886
+ export function toolUsageHints(args = {}) {
887
+ const requestedTool = String(args.tool || "").trim()
888
+ const topic = String(args.topic || "all").trim() || "all"
889
+ const tools = {
890
+ yunti_get_page_snapshot: {
891
+ purpose: "Establish the current Yunti browser route and read lightweight page state.",
892
+ required: [],
893
+ recommended: ["browserSessionId"],
894
+ notes: [
895
+ "Use this first for current-page work when browserSessionId is unknown.",
896
+ "Keep the returned browserSessionId for follow-up current-tab tools.",
897
+ "If an old browserSessionId fails, call yunti_list_browser_targets to refresh the live route inventory.",
898
+ ],
899
+ },
900
+ yunti_list_browser_targets: {
901
+ purpose: "Canonical live Chrome/Edge tab and target inventory.",
902
+ required: [],
903
+ recommended: ["browserSessionId"],
904
+ notes: [
905
+ "Use for page counts, all tabs, finding a tab, or choosing a CDP target.",
906
+ "tabId and targetId are selectors; route CDP through the current user's browserSessionId.",
907
+ "Use this to recover when a stored browserSessionId is stale.",
908
+ ],
909
+ },
910
+ yunti_list_pages: {
911
+ purpose: "Compatibility alias for the same live target inventory as yunti_list_browser_targets.",
912
+ required: [],
913
+ recommended: ["browserSessionId"],
914
+ notes: [
915
+ "Do not treat this as a separate Yunti registration registry.",
916
+ "Prefer yunti_list_browser_targets in new prompts and workflows.",
917
+ ],
918
+ },
919
+ yunti_cdp_send_command: {
920
+ purpose: "Send one low-level browser protocol command through the current user's browser route.",
921
+ required: ["method"],
922
+ recommended: ["browserSessionId", "method", "params"],
923
+ examples: [
924
+ {
925
+ browserSessionId: "yunti-...",
926
+ tabId: 123,
927
+ method: "Target.activateTarget",
928
+ params: {},
929
+ },
930
+ {
931
+ browserSessionId: "yunti-...",
932
+ method: "Runtime.evaluate",
933
+ params: { expression: "document.title", returnByValue: true },
934
+ },
935
+ ],
936
+ commonMistakes: [
937
+ "Do not run CDP method names in a shell.",
938
+ "params must be an object when provided; do not pass a string or array.",
939
+ "For tab operations, pass top-level tabId or targetId together with browserSessionId.",
940
+ "For Target.closeTarget, call yunti_list_browser_targets first, then pass a returned top-level tabId or targetId.",
941
+ "If browserSessionId is stale, refresh with yunti_list_browser_targets before retrying.",
942
+ ],
943
+ },
944
+ yunti_evaluate_script: {
945
+ purpose: "Evaluate JavaScript in the selected browser page.",
946
+ required: ["expression"],
947
+ aliases: { script: "expression" },
948
+ examples: [
949
+ {
950
+ browserSessionId: "yunti-...",
951
+ expression: "document.title",
952
+ awaitPromise: false,
953
+ },
954
+ ],
955
+ commonMistakes: ["Use expression, not script."],
956
+ },
957
+ yunti_new_page: {
958
+ purpose: "Create a new browser tab.",
959
+ required: [],
960
+ recommended: ["browserSessionId", "url", "active"],
961
+ notes: [
962
+ "Returns a new browserSessionId for the created tab.",
963
+ "Use the returned browserSessionId for follow-up yunti_* calls on the new tab.",
964
+ ],
965
+ },
966
+ yunti_close_page: {
967
+ purpose: "Close a registered Yunti browser page by browserSessionId.",
968
+ required: ["browserSessionId"],
969
+ commonMistakes: [
970
+ "This tool does not accept tabId or targetId.",
971
+ "Passing tabId or targetId will be rejected instead of selecting the close target.",
972
+ ],
973
+ alternatives: [
974
+ "To close by tabId or targetId, route through yunti_cdp_send_command with the current browserSessionId and Target.closeTarget.",
975
+ ],
976
+ },
977
+ yunti_select_page: {
978
+ purpose: "Select a registered Yunti browser session.",
979
+ required: ["browserSessionId"],
980
+ commonMistakes: [
981
+ "Do not pass raw Chrome targetId or tabId here.",
982
+ "Use yunti_cdp_send_command for raw browser targets from yunti_list_browser_targets.",
983
+ ],
984
+ },
985
+ yunti_forget_learning_memory: {
986
+ purpose: "Delete one learning memory by id, or delete all memories when confirmed.",
987
+ required: [],
988
+ recommended: ["id"],
989
+ notes: [
990
+ "Call yunti_get_learning_memory first to find the memory id.",
991
+ "Use all=true and confirmed=true only when deleting every memory for this user.",
992
+ "If the returned deleted count is 0, refresh the memory list and retry with an existing id.",
993
+ ],
994
+ commonMistakes: ["Use id, not title."],
995
+ },
996
+ yunti_click: {
997
+ purpose: "Click by snapshot uid, CSS selector, or viewport coordinates.",
998
+ required: [],
999
+ recommended: ["browserSessionId", "uid"],
1000
+ notes: [
1001
+ "Prefer uid from yunti_take_snapshot for reliability.",
1002
+ "Use selector when uid is unavailable.",
1003
+ "Coordinate mode requires both x and y; yunti_click_at is clearer for coordinate-only clicks.",
1004
+ ],
1005
+ },
1006
+ yunti_hover: {
1007
+ purpose: "Hover by snapshot uid, CSS selector, or viewport coordinates.",
1008
+ required: [],
1009
+ recommended: ["browserSessionId", "uid"],
1010
+ notes: [
1011
+ "Prefer uid from yunti_take_snapshot for reliability.",
1012
+ "Selector mode resolves the element center and dispatches CDP mouse move.",
1013
+ "Coordinate mode requires both x and y.",
1014
+ ],
1015
+ },
1016
+ yunti_fill: {
1017
+ purpose: "Fill an input-like element by snapshot uid or CSS selector.",
1018
+ required: ["value"],
1019
+ recommended: ["browserSessionId", "uid", "value"],
1020
+ notes: [
1021
+ "value is required and may be an empty string when intentionally clearing a field.",
1022
+ "Prefer uid from yunti_take_snapshot for reliability.",
1023
+ "Use selector when uid is unavailable.",
1024
+ "Coordinate-only fill is not supported; use uid or selector.",
1025
+ ],
1026
+ commonMistakes: [
1027
+ "Do not omit value.",
1028
+ "Do not pass only x/y coordinates to yunti_fill.",
1029
+ ],
1030
+ },
1031
+ }
1032
+ const topicMap = {
1033
+ browser: ["yunti_get_page_snapshot", "yunti_list_browser_targets", "yunti_list_pages"],
1034
+ cdp: ["yunti_cdp_send_command", "yunti_evaluate_script"],
1035
+ tabs: ["yunti_new_page", "yunti_close_page", "yunti_select_page", "yunti_list_browser_targets"],
1036
+ memory: ["yunti_get_learning_memory", "yunti_remember_learning", "yunti_forget_learning_memory"],
1037
+ network: ["yunti_get_network_log", "yunti_list_network_requests", "yunti_get_network_request", "yunti_clear_network_requests"],
1038
+ console: ["yunti_list_console_messages", "yunti_get_console_message", "yunti_clear_console_messages"],
1039
+ }
1040
+ const selectedNames = requestedTool
1041
+ ? [requestedTool]
1042
+ : topic !== "all" && topicMap[topic]
1043
+ ? topicMap[topic]
1044
+ : Object.keys(tools)
1045
+ const selectedTools = {}
1046
+ for (const name of selectedNames) {
1047
+ selectedTools[name] = {
1048
+ ...(tools[name] || {
1049
+ purpose: "No specialized hint is available for this tool. Use the schema field below.",
1050
+ }),
1051
+ schema: schemaForTool(name),
1052
+ }
1053
+ }
1054
+ return {
1055
+ version: "2026-07-02",
1056
+ coreRules: [
1057
+ "Every browser-facing yunti_* tool call requires userId.",
1058
+ "browserSessionId is the current user's browser route; tabId and targetId are selectors, not permissions.",
1059
+ "yunti_list_browser_targets is the canonical live browser inventory.",
1060
+ "yunti_list_pages is a compatibility alias for the same live target inventory.",
1061
+ "If an old browserSessionId is disconnected or stale, call yunti_list_browser_targets with the current userId to recover the latest browserSessionId and live targets.",
1062
+ "After yunti_new_page, use the returned browserSessionId for follow-up calls on the new tab.",
1063
+ "Sessions expire quickly when the extension stops polling; stale-session errors include the reason and recovery hint.",
1064
+ "If a tool call fails due to parameters, inspect this hint output and the tool schema before retrying.",
1065
+ ],
1066
+ workflows: {
1067
+ newPage: [
1068
+ "Call yunti_new_page with userId and optional current browserSessionId.",
1069
+ "Store the returned browserSessionId.",
1070
+ "Use that returned browserSessionId for navigate/evaluate/screenshot/close on the new tab.",
1071
+ ],
1072
+ closePage: [
1073
+ "If you have the target page's browserSessionId, call yunti_close_page with userId and that browserSessionId.",
1074
+ "If you only have tabId or targetId, use yunti_cdp_send_command routed through the current browserSessionId.",
1075
+ ],
1076
+ recoverRoute: [
1077
+ "When a saved browserSessionId fails as disconnected, stale, or not registered, do not keep retrying it.",
1078
+ "Call yunti_list_browser_targets with the current userId; it can route through the current active browser session and returns the latest browserSessionId.",
1079
+ "Use the returned browserSessionId as the route for subsequent yunti_* calls.",
1080
+ ],
1081
+ evaluate: [
1082
+ "Use yunti_evaluate_script with expression.",
1083
+ "Use yunti_cdp_send_command Runtime.evaluate only when raw CDP options are required.",
1084
+ ],
1085
+ memoryDelete: [
1086
+ "Call yunti_get_learning_memory to find the id.",
1087
+ "Call yunti_forget_learning_memory with that id.",
1088
+ ],
1089
+ },
1090
+ tools: selectedTools,
1091
+ }
1092
+ }