@super-one/cli 0.57.5-alpha → 0.59.0-alpha

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 (3) hide show
  1. package/MANIFEST.json +2 -2
  2. package/lib/cli.mjs +885 -1508
  3. package/package.json +1 -1
package/lib/cli.mjs CHANGED
@@ -164,113 +164,10 @@ var init_host_actions = __esm({
164
164
  });
165
165
 
166
166
  // ../../packages/shared/src/environment/host-action-superone-descriptors.ts
167
- var deviceDescriptionProperty, deviceTargetProperty, deviceConditionSchema, deviceActionSchema, HOST_ACTION_SUPERONE_TOOL_DESCRIPTORS;
167
+ var HOST_ACTION_SUPERONE_TOOL_DESCRIPTORS;
168
168
  var init_host_action_superone_descriptors = __esm({
169
169
  "../../packages/shared/src/environment/host-action-superone-descriptors.ts"() {
170
170
  "use strict";
171
- deviceDescriptionProperty = {
172
- type: "string",
173
- minLength: 1,
174
- maxLength: 160,
175
- description: "A short human-friendly explanation of what this step accomplishes, phrased for the user watching (e.g. 'Open the profile tab', 'Check the order total'). Shown in the UI in place of refs and coordinates. Write it in the conversation's language."
176
- };
177
- deviceTargetProperty = {
178
- type: "string",
179
- description: "Which controlled device to act on \u2014 the id from device_list, or its name. Optional while this session controls exactly one device; required once it controls more than one (driving the wrong app there looks like a bug in the right one). Use device_request_control to be granted another."
180
- };
181
- deviceConditionSchema = {
182
- type: "object",
183
- properties: {
184
- kind: { type: "string", enum: ["exists", "notExists", "textEquals", "textContains"] },
185
- ref: {
186
- description: "Only valid within the snapshot it came from; prefer label or identifier when waiting.",
187
- type: "string"
188
- },
189
- label: { description: "Visible name of the element.", type: "string" },
190
- identifier: {
191
- description: "Developer-assigned id. Survives copy changes and translation \u2014 the most durable target.",
192
- type: "string"
193
- },
194
- text: {
195
- description: "The string textEquals/textContains compares against. Required by those two kinds, and NOT a way to name an element \u2014 use label for that.",
196
- type: "string",
197
- minLength: 1
198
- }
199
- },
200
- required: ["kind"],
201
- additionalProperties: false
202
- };
203
- deviceActionSchema = {
204
- type: "object",
205
- properties: {
206
- type: {
207
- type: "string",
208
- enum: ["tap", "doubleTap", "longPress", "swipe", "pinch", "press", "type", "key", "rotate", "keyboard"]
209
- },
210
- ref: { description: 'Element ref from the snapshot, e.g. "@e12". Preferred over coordinates.', type: "string" },
211
- x: {
212
- description: "Horizontal position as a fraction of the screen (0-1). Only when no ref fits.",
213
- type: "number",
214
- minimum: 0,
215
- maximum: 1
216
- },
217
- y: {
218
- description: "Vertical position as a fraction of the screen (0-1).",
219
- type: "number",
220
- minimum: 0,
221
- maximum: 1
222
- },
223
- direction: {
224
- description: 'swipe: which way the finger travels. Content moves the opposite way, so "up" scrolls down a list.',
225
- type: "string",
226
- enum: ["up", "down", "left", "right"]
227
- },
228
- distance: {
229
- description: "swipe: travel as a fraction of the screen. Default 0.6.",
230
- type: "number",
231
- minimum: 0.05,
232
- maximum: 1
233
- },
234
- toX: {
235
- description: "swipe: explicit destination instead of direction.",
236
- type: "number",
237
- minimum: 0,
238
- maximum: 1
239
- },
240
- toY: { type: "number", minimum: 0, maximum: 1 },
241
- scale: {
242
- description: "pinch: final separation factor. Below 1 pinches in (zoom out), above 1 spreads.",
243
- type: "number",
244
- minimum: 0.1,
245
- maximum: 5
246
- },
247
- durationMs: {
248
- description: "How long the gesture takes. Short swipes flick and coast; long ones drag and stop.",
249
- type: "integer",
250
- minimum: 16,
251
- maximum: 1e4
252
- },
253
- text: {
254
- description: "type: text to enter. Anything the simulated keyboard cannot spell (Chinese, emoji) is pasted automatically.",
255
- type: "string"
256
- },
257
- button: {
258
- type: "string",
259
- enum: ["home", "lock", "side", "volume-up", "volume-down", "back", "app-switch"],
260
- description: "key: a hardware button. `back` and `app-switch` are Android-only and are refused elsewhere."
261
- },
262
- orientation: {
263
- type: "string",
264
- enum: ["portrait", "landscape-left", "portrait-upside-down", "landscape-right"]
265
- },
266
- connected: {
267
- description: "keyboard: attach or detach the hardware keyboard. Detach it to make the on-screen keyboard appear.",
268
- type: "boolean"
269
- }
270
- },
271
- required: ["type"],
272
- additionalProperties: false
273
- };
274
171
  HOST_ACTION_SUPERONE_TOOL_DESCRIPTORS = [
275
172
  {
276
173
  "name": "session_collab_list_agents",
@@ -283,7 +180,7 @@ var init_host_action_superone_descriptors = __esm({
283
180
  },
284
181
  {
285
182
  "name": "session_collab_request",
286
- "description": 'Request user approval for collaboration launches: "spawn" (default) creates a nested child you keep messaging; "handoff" creates a top-level sibling that takes the task over one-way (no mailbox); "link" opens a mailbox with an existing sessionId. Spawn/handoff: list_agents; require agentId, name, role, summary, task; for cwd/worktree call read_manual({ domain: "product", topic: "collaboration" }); same-repo isolation belongs in config.worktree. Link: require sessionId + summary; optional task opening (turn-injected, not system prompt). User must approve; credential for session_collab_start.',
183
+ "description": 'Request user approval for collaboration launches. See the mode field for spawn vs handoff vs link. Spawn/handoff: pick an agentId from session_collab_list_agents; require name, role, summary, task. Link: require sessionId + summary. Read read_manual({ domain: "product", topic: "collaboration" }) before the first launch in a session. User must approve; returns the credential for session_collab_start.',
287
184
  "inputSchema": {
288
185
  "type": "object",
289
186
  "properties": {
@@ -305,7 +202,7 @@ var init_host_action_superone_descriptors = __esm({
305
202
  "handoff",
306
203
  "link"
307
204
  ],
308
- "description": '"spawn" (default) creates a new child session nested under this one, with a two-way mailbox. "handoff" creates a new top-level sibling session that receives the task and owns it from then on \u2014 no mailbox, no reply, not nested. Use it to pass work forward (fresh context, next phase, unattended follow-up) instead of supervising it. "link" connects to an already-existing SuperOne session (sessionId required).'
205
+ "description": '"spawn" (default) = nested child with a two-way mailbox. "handoff" = top-level sibling, not nested: it owns the task from then on, with no mailbox and no reply \u2014 pass work forward rather than supervise it. "link" = connect to an existing session (sessionId required).'
309
206
  },
310
207
  "sessionId": {
311
208
  "type": "string",
@@ -364,7 +261,7 @@ var init_host_action_superone_descriptors = __esm({
364
261
  "auto",
365
262
  "agent"
366
263
  ],
367
- "description": 'How autonomous the child session is. Prefer the most autonomous mode it can finish the task under \u2014 "bypassPermissions" (shown as Bypass on Claude-family harnesses, Full Access on Codex/Cursor), "agent" for Cursor, or "auto" for ACP agents. Nobody watches a child session, so a conservative mode strands it on an approval prompt that is never answered. Requesting an autonomous mode is safe by construction: nothing runs until the user approves this very request, and that approval dialog is where they downgrade permission or sandbox per launch. Pick "plan" or "default" only when stopping for human review is the point of the launch.'
264
+ "description": 'How autonomous the child session is. Nobody watches a child, so prefer the most autonomous mode it can finish under; "plan"/"default" only when stopping for human review is the point. Per-harness mode names, and why requesting autonomy is safe here: See read_manual({ domain: "product", topic: "collaboration" }).'
368
265
  },
369
266
  "sandboxMode": {
370
267
  "type": "string",
@@ -376,11 +273,11 @@ var init_host_action_superone_descriptors = __esm({
376
273
  },
377
274
  "cwd": {
378
275
  "type": "string",
379
- "description": 'Set only to a genuinely different project root. Omit for the current project. Never pass ~/.worktrees/... or another same-repo worktree leaf; use config.worktree for same-repo isolation. See read_manual({ domain: "product", topic: "collaboration" }).'
276
+ "description": 'Only for a genuinely different project root; omit for the current project. Never a same-repo worktree leaf \u2014 express isolation with config.worktree. See read_manual({ domain: "product", topic: "collaboration" }).'
380
277
  },
381
278
  "worktree": {
382
279
  "type": "object",
383
- "description": 'Request a host-managed worktree for same-repo isolation while cwd stays omitted or at the project root. Use for parallel implementers (mode branch + unique branchName), not for default read-only review of the current shared checkout. Use mode detach only when reviewing a feature branch another implementer already has checked out. See read_manual({ domain: "product", topic: "collaboration" }).',
280
+ "description": 'Host-managed worktree for same-repo isolation; leave cwd unset. For parallel implementers, not for read-only review of the shared checkout. See read_manual({ domain: "product", topic: "collaboration" }).',
384
281
  "properties": {
385
282
  "enabled": {
386
283
  "type": "boolean"
@@ -495,7 +392,7 @@ var init_host_action_superone_descriptors = __esm({
495
392
  },
496
393
  {
497
394
  "name": "read_manual",
498
- "description": "Read bundled SuperOne manuals. Omit domain to list all domains; pass domain to list its topics; pass domain with topic to read one topic. For widget, pass either topic or modules, never both. Use product/contribute for GitHub issues and PRs (issue-first, optional red\u2013green), product/debug for support and runtime paths, miniapp/overview before mini-app development, and media/overview before provider-specific options. Use config_read for live settings and widget_list_templates for saved widgets.",
395
+ "description": "Read bundled SuperOne manuals. Omit domain to list all domains; pass domain to list its topics; pass domain with topic to read one topic. For widget, pass either topic or modules, never both. Read product/collaboration before session_collab_request, product/automation before automation_apply, product/devices before device_request_control, product/browser before saving a browser action, miniapp/overview before mini-app development, and media/overview before provider-specific options. Use config_read for live settings and widget_list_templates for saved widgets.",
499
396
  "inputSchema": {
500
397
  "type": "object",
501
398
  "properties": {
@@ -533,9 +430,6 @@ var init_host_action_superone_descriptors = __esm({
533
430
  }
534
431
  },
535
432
  "additionalProperties": false
536
- },
537
- "_meta": {
538
- "anthropic/alwaysLoad": true
539
433
  }
540
434
  },
541
435
  {
@@ -765,11 +659,7 @@ var init_host_action_superone_descriptors = __esm({
765
659
  },
766
660
  {
767
661
  "name": "session_rename",
768
- "description": `Rename the current chat session to a concise topic label shown in the sidebar. Always pass tags (set): 1\u20134 short kebab-case labels you choose so session_list/session_search can find this chat. Reuse names from session_tag_list when they fit; invent one when they don't.
769
-
770
- Only the top-level agent talking directly to the user may call this. If you were launched as a Task/subagent worker, do NOT call it \u2014 you do not own the user-facing session title.
771
-
772
- If the tool returns an error containing "user_locked", the user has manually named this session \u2014 do not call session_rename again. Tags in the same call were still applied; use session_tag for later tag edits.`,
662
+ "description": "Rename the current chat session to a concise topic label shown in the sidebar. Always pass tags (set): 1\u20134 short kebab-case labels you choose so session_list/session_search can find this chat. Reuse names from session_tag_list when they fit; invent one when they don't. Top-level agent only \u2014 a Task/subagent worker does not own the user-facing title and must not call it.",
773
663
  "inputSchema": {
774
664
  "type": "object",
775
665
  "properties": {
@@ -781,7 +671,9 @@ If the tool returns an error containing "user_locked", the user has manually nam
781
671
  },
782
672
  "tags": {
783
673
  "type": "array",
784
- "items": { "type": "string" },
674
+ "items": {
675
+ "type": "string"
676
+ },
785
677
  "maxItems": 8,
786
678
  "description": "Replace this session's tags (set). Pass 1\u20134 short kebab-case labels you choose. Reuse names from session_tag_list when they fit; invent when they don't. Empty array clears. Applied even when the title is user_locked."
787
679
  }
@@ -894,7 +786,7 @@ If the tool returns an error containing "user_locked", the user has manually nam
894
786
  },
895
787
  {
896
788
  "name": "session_list",
897
- "description": "List SuperOne sessions (metadata only). Default: current project. Pass projectId (from project_list) or allProjects=true. Rows include projectId only \u2014 use project_list for path/name. Use before session_read/session_search. Filter by title query, harness, pin/hidden, dates, or tags + tagMatch (any=at least one, all=every tag; default any). Discover tags with session_tag_list. Sort with order (default last_active_desc; also created_*, message_count_*, size_*). When order is size_*, rows include sizeBytes (character length of message JSON, not disk bytes). Paginate with limit/offset. Not live collab or harness resume.",
789
+ "description": "List SuperOne sessions (metadata only). Default: current project. Pass projectId (from project_list) or allProjects=true. Rows include projectId only \u2014 use project_list for path/name. Filter by title query, harness, pin/hidden, dates or tags (discover them with session_tag_list). Use before session_read/session_search. Not live collab or harness resume.",
898
790
  "inputSchema": {
899
791
  "type": "object",
900
792
  "properties": {
@@ -934,13 +826,18 @@ If the tool returns an error containing "user_locked", the user has manually nam
934
826
  },
935
827
  "tags": {
936
828
  "type": "array",
937
- "items": { "type": "string" },
829
+ "items": {
830
+ "type": "string"
831
+ },
938
832
  "maxItems": 8,
939
833
  "description": "Tags from session_tag_list. Filter sessions that have these labels."
940
834
  },
941
835
  "tagMatch": {
942
836
  "type": "string",
943
- "enum": ["any", "all"],
837
+ "enum": [
838
+ "any",
839
+ "all"
840
+ ],
944
841
  "description": "any = at least one listed tag (default). all = every listed tag. Ignored when tags is omitted."
945
842
  },
946
843
  "projectId": {
@@ -1212,7 +1109,7 @@ If the tool returns an error containing "user_locked", the user has manually nam
1212
1109
  },
1213
1110
  {
1214
1111
  "name": "media_generate_video",
1215
- "description": 'Submit an asynchronous video generation after the user reviews its parameters. Stop on cancelled or error; use feedback before retrying a rejected proposal. After submission, poll media_video_status about every 30 seconds until generated or error. The finished video is displayed automatically; do not embed it again. Before provider-specific options, call media_list_providers with category "video" and read media/overview plus the matching provider topic. Check warnings for ignored options.',
1112
+ "description": 'Submit an asynchronous video generation after the user reviews its parameters. Stop on cancelled or error; use feedback before retrying. Poll media_video_status about every 30s until generated or error. The finished video is displayed automatically \u2014 do not embed it again. For provider options call media_list_providers(category:"video"), then read media/overview and the matching provider topic.',
1216
1113
  "inputSchema": {
1217
1114
  "type": "object",
1218
1115
  "properties": {
@@ -1314,446 +1211,48 @@ If the tool returns an error containing "user_locked", the user has manually nam
1314
1211
  }
1315
1212
  },
1316
1213
  {
1317
- "name": "browser_action_list",
1318
- "description": "List saved semantic browser actions. Omit domain to list all actions, or pass a domain for an exact normalized-domain match. Returns compact summaries by default; set includeSteps:true before replacing an existing action when you need its complete definition.",
1214
+ "name": "browser_tools_list",
1215
+ "description": "List WebMCP tools registered by the current secure page. Use this to discover page-provided actions and their input schemas, then call browser_tools_call with a returned name.",
1319
1216
  "inputSchema": {
1320
1217
  "type": "object",
1321
1218
  "properties": {
1322
- "domain": {
1323
- "description": "Optional domain filter, e.g. github.com. Scheme, path, case, and a trailing dot are normalized away.",
1219
+ "tab": {
1220
+ "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
1324
1221
  "type": "string"
1325
- },
1326
- "includeSteps": {
1327
- "default": false,
1328
- "description": "Include complete step definitions. Default false for a lean action catalog.",
1329
- "type": "boolean"
1330
1222
  }
1331
1223
  },
1332
- "required": [
1333
- "includeSteps"
1334
- ],
1335
1224
  "additionalProperties": false
1336
1225
  }
1337
1226
  },
1338
1227
  {
1339
- "name": "browser_action_save",
1340
- "description": 'Create or replace a reusable semantic browser action. Actions are global across projects and sessions and are keyed by normalized domain + name. Steps run sequentially and support kind:"tool", "action", "set", "if", "forEach", and "repeat". Tool/action steps may saveAs a shared variable. Templates in tool args and nested action input may reference ${input.*}, ${vars.*}, ${result.*}, ${item.*}, and ${index}. Structured expressions use literal scalars, {kind:"literal",value}, {kind:"ref",path}, or {kind:"op",op,args}; arbitrary code is not executed. This tool does not record prior browser calls.',
1228
+ "name": "browser_tools_call",
1229
+ "description": "Call one WebMCP tool registered by the current secure page. Use browser_tools_list first to get the tool name and input schema. The page is untrusted and the user may need to approve the call.",
1341
1230
  "inputSchema": {
1342
1231
  "type": "object",
1343
1232
  "properties": {
1344
- "domain": {
1345
- "type": "string",
1346
- "minLength": 1,
1347
- "maxLength": 500,
1348
- "description": "Semantic domain namespace, normally a hostname such as github.com."
1349
- },
1350
- "name": {
1351
- "type": "string",
1352
- "pattern": "^[a-z][a-z0-9_-]{0,63}$",
1353
- "description": "Stable lowercase action name using letters, numbers, underscores, or hyphens."
1233
+ "tab": {
1234
+ "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
1235
+ "type": "string"
1354
1236
  },
1355
1237
  "description": {
1356
- "type": "string",
1357
- "minLength": 1,
1358
- "maxLength": 1e3,
1359
- "description": "Concise explanation of the action outcome and when to use it. Do not embed credentials or other secrets in steps; pass them as action inputs."
1360
- },
1361
- "parameters": {
1362
- "default": [],
1363
- "description": "Inputs accepted by browser_action_do. Values are referenced in steps as ${input.name}.",
1364
- "maxItems": 50,
1365
- "type": "array",
1366
- "items": {
1367
- "type": "object",
1368
- "properties": {
1369
- "name": {
1370
- "type": "string",
1371
- "pattern": "^[A-Za-z_][A-Za-z0-9_-]{0,63}$",
1372
- "description": "Input name referenced in step templates as ${input.name}."
1373
- },
1374
- "description": {
1375
- "description": "What the caller should provide.",
1376
- "type": "string",
1377
- "minLength": 1,
1378
- "maxLength": 500
1379
- },
1380
- "type": {
1381
- "description": "Optional runtime type constraint.",
1382
- "type": "string",
1383
- "enum": [
1384
- "string",
1385
- "number",
1386
- "boolean",
1387
- "object",
1388
- "array"
1389
- ]
1390
- },
1391
- "required": {
1392
- "default": true,
1393
- "type": "boolean"
1394
- },
1395
- "default": {}
1396
- },
1397
- "required": [
1398
- "name",
1399
- "required"
1400
- ],
1401
- "additionalProperties": false
1402
- }
1403
- },
1404
- "steps": {
1405
- "minItems": 1,
1406
- "maxItems": 50,
1407
- "type": "array",
1408
- "items": {
1409
- "$ref": "#/$defs/__schema0"
1410
- },
1411
- "description": "Ordered flow steps. set writes to shared vars; if runs then or else; forEach exposes item and index; repeat exposes index. Loops allow at most 50 iterations, definitions at most 50 total steps, and execution at most 100 cumulative steps. Execution is fail-fast."
1412
- }
1413
- },
1414
- "required": [
1415
- "domain",
1416
- "name",
1417
- "description",
1418
- "parameters",
1419
- "steps"
1420
- ],
1421
- "additionalProperties": false,
1422
- "$defs": {
1423
- "__schema0": {
1424
- "description": "A sequential tool, nested action, set, if, forEach, or repeat step. Control-flow child steps execute in order and count toward execution limits.",
1425
- "oneOf": [
1426
- {
1427
- "type": "object",
1428
- "properties": {
1429
- "kind": {
1430
- "type": "string",
1431
- "const": "tool"
1432
- },
1433
- "tool": {
1434
- "type": "string",
1435
- "enum": [
1436
- "browser_snapshot",
1437
- "browser_query",
1438
- "browser_inspect",
1439
- "browser_screenshot",
1440
- "browser_click",
1441
- "browser_hover",
1442
- "browser_type",
1443
- "browser_navigate",
1444
- "browser_wait_for",
1445
- "browser_press",
1446
- "browser_scroll",
1447
- "browser_drag",
1448
- "browser_select",
1449
- "browser_open",
1450
- "browser_evaluate",
1451
- "browser_tabs",
1452
- "browser_resize",
1453
- "browser_network_start",
1454
- "browser_network_stop",
1455
- "browser_network_wait",
1456
- "browser_network_body",
1457
- "browser_cookies",
1458
- "browser_upload_file",
1459
- "browser_download",
1460
- "browser_list_downloads",
1461
- "browser_emulate",
1462
- "browser_mock"
1463
- ]
1464
- },
1465
- "args": {
1466
- "default": {},
1467
- "type": "object",
1468
- "propertyNames": {
1469
- "type": "string"
1470
- },
1471
- "additionalProperties": {}
1472
- },
1473
- "saveAs": {
1474
- "description": "Save the primitive tool result into vars under this name.",
1475
- "type": "string",
1476
- "pattern": "^[A-Za-z_][A-Za-z0-9_-]{0,63}$"
1477
- }
1478
- },
1479
- "required": [
1480
- "kind",
1481
- "tool",
1482
- "args"
1483
- ],
1484
- "additionalProperties": false
1485
- },
1486
- {
1487
- "type": "object",
1488
- "properties": {
1489
- "kind": {
1490
- "type": "string",
1491
- "const": "action"
1492
- },
1493
- "domain": {
1494
- "type": "string",
1495
- "minLength": 1,
1496
- "maxLength": 500
1497
- },
1498
- "name": {
1499
- "type": "string",
1500
- "pattern": "^[a-z][a-z0-9_-]{0,63}$"
1501
- },
1502
- "input": {
1503
- "default": {},
1504
- "type": "object",
1505
- "propertyNames": {
1506
- "type": "string"
1507
- },
1508
- "additionalProperties": {}
1509
- },
1510
- "saveAs": {
1511
- "description": "Save the nested action last result into vars under this name.",
1512
- "type": "string",
1513
- "pattern": "^[A-Za-z_][A-Za-z0-9_-]{0,63}$"
1514
- }
1515
- },
1516
- "required": [
1517
- "kind",
1518
- "domain",
1519
- "name",
1520
- "input"
1521
- ],
1522
- "additionalProperties": false
1523
- },
1524
- {
1525
- "type": "object",
1526
- "properties": {
1527
- "kind": {
1528
- "type": "string",
1529
- "const": "set"
1530
- },
1531
- "name": {
1532
- "type": "string",
1533
- "pattern": "^[A-Za-z_][A-Za-z0-9_-]{0,63}$"
1534
- },
1535
- "value": {
1536
- "$ref": "#/$defs/__schema1"
1537
- }
1538
- },
1539
- "required": [
1540
- "kind",
1541
- "name",
1542
- "value"
1543
- ],
1544
- "additionalProperties": false
1545
- },
1546
- {
1547
- "type": "object",
1548
- "properties": {
1549
- "kind": {
1550
- "type": "string",
1551
- "const": "if"
1552
- },
1553
- "condition": {
1554
- "$ref": "#/$defs/__schema1"
1555
- },
1556
- "then": {
1557
- "minItems": 1,
1558
- "type": "array",
1559
- "items": {
1560
- "$ref": "#/$defs/__schema0"
1561
- }
1562
- },
1563
- "else": {
1564
- "minItems": 1,
1565
- "type": "array",
1566
- "items": {
1567
- "$ref": "#/$defs/__schema0"
1568
- }
1569
- }
1570
- },
1571
- "required": [
1572
- "kind",
1573
- "condition",
1574
- "then"
1575
- ],
1576
- "additionalProperties": false
1577
- },
1578
- {
1579
- "type": "object",
1580
- "properties": {
1581
- "kind": {
1582
- "type": "string",
1583
- "const": "forEach"
1584
- },
1585
- "items": {
1586
- "$ref": "#/$defs/__schema1"
1587
- },
1588
- "steps": {
1589
- "minItems": 1,
1590
- "type": "array",
1591
- "items": {
1592
- "$ref": "#/$defs/__schema0"
1593
- }
1594
- }
1595
- },
1596
- "required": [
1597
- "kind",
1598
- "items",
1599
- "steps"
1600
- ],
1601
- "additionalProperties": false
1602
- },
1603
- {
1604
- "type": "object",
1605
- "properties": {
1606
- "kind": {
1607
- "type": "string",
1608
- "const": "repeat"
1609
- },
1610
- "times": {
1611
- "$ref": "#/$defs/__schema1"
1612
- },
1613
- "steps": {
1614
- "minItems": 1,
1615
- "type": "array",
1616
- "items": {
1617
- "$ref": "#/$defs/__schema0"
1618
- }
1619
- }
1620
- },
1621
- "required": [
1622
- "kind",
1623
- "times",
1624
- "steps"
1625
- ],
1626
- "additionalProperties": false
1627
- }
1628
- ]
1629
- },
1630
- "__schema1": {
1631
- "description": 'A literal JSON scalar, {kind:"literal",value:any JSON}, {kind:"ref",path:"input|vars|result|item|index..."}, or {kind:"op",op,args}. Operators: eq, ne, gt, gte, lt, lte, and, or, not, exists, contains, add, subtract, multiply, divide.',
1632
- "anyOf": [
1633
- {
1634
- "type": "string"
1635
- },
1636
- {
1637
- "type": "number"
1638
- },
1639
- {
1640
- "type": "boolean"
1641
- },
1642
- {
1643
- "type": "null"
1644
- },
1645
- {
1646
- "type": "object",
1647
- "properties": {
1648
- "kind": {
1649
- "type": "string",
1650
- "const": "literal"
1651
- },
1652
- "value": {}
1653
- },
1654
- "required": [
1655
- "kind",
1656
- "value"
1657
- ],
1658
- "additionalProperties": false
1659
- },
1660
- {
1661
- "type": "object",
1662
- "properties": {
1663
- "kind": {
1664
- "type": "string",
1665
- "const": "ref"
1666
- },
1667
- "path": {
1668
- "type": "string",
1669
- "pattern": "^(?:input|vars|result|item|index)(?:\\.[A-Za-z0-9_-]+)*$"
1670
- }
1671
- },
1672
- "required": [
1673
- "kind",
1674
- "path"
1675
- ],
1676
- "additionalProperties": false
1677
- },
1678
- {
1679
- "type": "object",
1680
- "properties": {
1681
- "kind": {
1682
- "type": "string",
1683
- "const": "op"
1684
- },
1685
- "op": {
1686
- "type": "string",
1687
- "enum": [
1688
- "eq",
1689
- "ne",
1690
- "gt",
1691
- "gte",
1692
- "lt",
1693
- "lte",
1694
- "and",
1695
- "or",
1696
- "not",
1697
- "exists",
1698
- "contains",
1699
- "add",
1700
- "subtract",
1701
- "multiply",
1702
- "divide"
1703
- ]
1704
- },
1705
- "args": {
1706
- "minItems": 1,
1707
- "maxItems": 20,
1708
- "type": "array",
1709
- "items": {
1710
- "$ref": "#/$defs/__schema1"
1711
- }
1712
- }
1713
- },
1714
- "required": [
1715
- "kind",
1716
- "op",
1717
- "args"
1718
- ],
1719
- "additionalProperties": false
1720
- }
1721
- ]
1722
- }
1723
- }
1724
- }
1725
- },
1726
- {
1727
- "name": "browser_action_do",
1728
- "description": "Execute one saved semantic browser action, including flow control and nested actions. Call browser_action_list first when you do not know its parameters. Variables are shared across nested actions for the duration of this call. Execution is sequential and fail-fast, detects recursive action cycles, and returns the last primitive tool result plus the actual step count. The domain is a semantic namespace only and does not restrict navigation.",
1729
- "inputSchema": {
1730
- "type": "object",
1731
- "properties": {
1732
- "domain": {
1733
- "type": "string",
1734
- "description": "Action domain namespace. Normalized before lookup."
1238
+ "description": "A short, human-friendly explanation of what this page tool call accomplishes, phrased for the end user watching (e.g. 'Add the shirt to the cart', 'Submit the quote request'). Shown in the UI next to the tool name. Write it in the conversation's language.",
1239
+ "type": "string"
1735
1240
  },
1736
1241
  "name": {
1737
- "type": "string",
1738
- "description": "Saved action name."
1242
+ "description": "Tool name from browser_tools_list. Required.",
1243
+ "type": "string"
1739
1244
  },
1740
1245
  "input": {
1741
1246
  "default": {},
1742
- "description": "Values for the action parameters.",
1247
+ "description": "Arguments; validated against the page-declared inputSchema at dispatch time.",
1743
1248
  "type": "object",
1744
1249
  "propertyNames": {
1745
1250
  "type": "string"
1746
1251
  },
1747
1252
  "additionalProperties": {}
1748
- },
1749
- "tab": {
1750
- "description": "Browser view id inherited by tab-scoped primitive steps unless a step sets its own tab.",
1751
- "type": "string"
1752
1253
  }
1753
1254
  },
1754
1255
  "required": [
1755
- "domain",
1756
- "name",
1757
1256
  "input"
1758
1257
  ],
1759
1258
  "additionalProperties": false
@@ -1761,7 +1260,7 @@ If the tool returns an error containing "user_locked", the user has manually nam
1761
1260
  },
1762
1261
  {
1763
1262
  "name": "browser_snapshot",
1764
- "description": "Inspect the current browser page. Pick which data sections to return via `include`: 'meta' (url/title/loading), 'elements' (flat list of top interactive elements + CSS selectors + total count), 'tree' (hierarchical accessibility tree of landmarks/headings/interactive nodes \u2014 use when you need page STRUCTURE and nesting, not just a flat list), 'text' (truncated visible text), 'console' (recent console entries, filterable). Default include is ['meta','elements','console'] (lean, warning+error console only). Fetch just logs with include:['console'] \u2014 that skips the DOM scan entirely. Call this first to orient. The result is TOON, not JSON: arrays render as a header row `name[N]{col,col}:` followed by one indented CSV-style row per item.",
1263
+ "description": "Inspect the current page. `include` picks sections: meta, elements (flat interactive + CSS selectors), tree (structure), text, console, screenshot. Default [meta, elements, console] (lean). include:[console] skips the DOM scan. include:[screenshot] saves a PNG and returns path \u2014 image is NOT loaded; Read the path if pixels matter. Result is TOON unless a screenshot is requested with other sections (then JSON {screenshot, page}). Prefer this before browser_act. Use browser_query when you already know the target.",
1765
1264
  "inputSchema": {
1766
1265
  "type": "object",
1767
1266
  "properties": {
@@ -1769,13 +1268,12 @@ If the tool returns an error containing "user_locked", the user has manually nam
1769
1268
  "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
1770
1269
  "type": "string"
1771
1270
  },
1271
+ "description": {
1272
+ "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching. Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1273
+ "type": "string"
1274
+ },
1772
1275
  "include": {
1773
- "default": [
1774
- "meta",
1775
- "elements",
1776
- "console"
1777
- ],
1778
- "description": "Which data sections to return. Default ['meta','elements','console'].",
1276
+ "description": "Which sections to return. Default ['meta','elements','console'].",
1779
1277
  "type": "array",
1780
1278
  "items": {
1781
1279
  "type": "string",
@@ -1784,48 +1282,42 @@ If the tool returns an error containing "user_locked", the user has manually nam
1784
1282
  "elements",
1785
1283
  "tree",
1786
1284
  "text",
1787
- "console"
1285
+ "console",
1286
+ "screenshot"
1788
1287
  ]
1789
1288
  }
1790
1289
  },
1791
1290
  "filter": {
1792
- "description": "Elements section only: case-insensitive substring; only return interactive elements whose name or role contains it.",
1793
1291
  "type": "string"
1794
1292
  },
1795
1293
  "max": {
1796
- "default": 40,
1797
- "description": "Elements section only: max interactive elements, ranked by viewport proximity. Default 40.",
1798
1294
  "type": "integer",
1799
1295
  "minimum": 1,
1800
1296
  "maximum": 200
1801
1297
  },
1802
1298
  "depth": {
1803
- "default": 12,
1804
- "description": "Tree section only: max nesting depth to descend. Default 12.",
1805
1299
  "type": "integer",
1806
1300
  "minimum": 1,
1807
1301
  "maximum": 30
1808
1302
  },
1809
1303
  "treeMax": {
1810
- "default": 150,
1811
- "description": "Tree section only: max nodes to emit (overload budget). When hit, the tree is cut and treeTruncated:true is returned. Default 150.",
1812
1304
  "type": "integer",
1813
1305
  "minimum": 1,
1814
1306
  "maximum": 500
1815
1307
  },
1816
1308
  "textMaxChars": {
1817
- "default": 4e3,
1818
- "description": "Text section only: truncate visible text to this many chars. Default 4000.",
1819
1309
  "type": "integer",
1820
1310
  "minimum": 0,
1821
1311
  "maximum": 2e4
1822
1312
  },
1313
+ "selector": {
1314
+ "description": "Element to screenshot when include contains screenshot.",
1315
+ "type": "string"
1316
+ },
1823
1317
  "console": {
1824
- "description": "Console section filtering. Only consulted when `include` contains 'console'.",
1825
1318
  "type": "object",
1826
1319
  "properties": {
1827
1320
  "level": {
1828
- "description": "Console levels to include. Default ['warning','error']. Pass all four for everything.",
1829
1321
  "type": "array",
1830
1322
  "items": {
1831
1323
  "type": "string",
@@ -1838,54 +1330,32 @@ If the tool returns an error containing "user_locked", the user has manually nam
1838
1330
  }
1839
1331
  },
1840
1332
  "grep": {
1841
- "description": "Only return console entries whose text matches this pattern (substring by default).",
1842
1333
  "type": "string"
1843
1334
  },
1844
1335
  "regex": {
1845
- "default": false,
1846
- "description": "Treat grep as a JS regular expression instead of a substring. Default false.",
1847
1336
  "type": "boolean"
1848
1337
  },
1849
1338
  "ignoreCase": {
1850
- "default": true,
1851
- "description": "Case-insensitive grep. Default true.",
1852
1339
  "type": "boolean"
1853
1340
  },
1854
1341
  "invert": {
1855
- "default": false,
1856
- "description": "Keep only entries that do NOT match grep (like grep -v). Default false.",
1857
1342
  "type": "boolean"
1858
1343
  },
1859
1344
  "max": {
1860
- "default": 50,
1861
- "description": "Return the most recent N matching entries. Default 50.",
1862
1345
  "type": "integer",
1863
1346
  "minimum": 1,
1864
1347
  "maximum": 200
1865
1348
  }
1866
1349
  },
1867
- "required": [
1868
- "regex",
1869
- "ignoreCase",
1870
- "invert",
1871
- "max"
1872
- ],
1873
1350
  "additionalProperties": false
1874
1351
  }
1875
1352
  },
1876
- "required": [
1877
- "include",
1878
- "max",
1879
- "depth",
1880
- "treeMax",
1881
- "textMaxChars"
1882
- ],
1883
1353
  "additionalProperties": false
1884
1354
  }
1885
1355
  },
1886
1356
  {
1887
1357
  "name": "browser_query",
1888
- "description": "Find elements on the page by structured criteria. Combine role, text, css selector, and attribute matchers. Returns matching elements with reusable selectors plus the total match count, as TOON (matches render as a `matches[N]{...}:` table + rows). Use this instead of snapshot when you already know what you are looking for.",
1358
+ "description": "Find or inspect elements. op=search (default) matches role / text / css / attributes and returns a TOON table of reusable selectors. op=inspect returns detail on one selector (fields: text, html, attributes, value, box, styles, context). Use this instead of snapshot when you already know what you are looking for. Do not use this to click or type (browser_act).",
1889
1359
  "inputSchema": {
1890
1360
  "type": "object",
1891
1361
  "properties": {
@@ -1894,23 +1364,28 @@ If the tool returns an error containing "user_locked", the user has manually nam
1894
1364
  "type": "string"
1895
1365
  },
1896
1366
  "description": {
1897
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1367
+ "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching. Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1898
1368
  "type": "string"
1899
1369
  },
1370
+ "op": {
1371
+ "description": "Default search.",
1372
+ "type": "string",
1373
+ "enum": [
1374
+ "search",
1375
+ "inspect"
1376
+ ]
1377
+ },
1900
1378
  "role": {
1901
- "description": "Match ARIA role or tag name, e.g. 'button', 'textbox', 'link'.",
1902
1379
  "type": "string"
1903
1380
  },
1904
1381
  "text": {
1905
- "description": "Case-insensitive substring in the element's accessible name or text.",
1906
1382
  "type": "string"
1907
1383
  },
1908
1384
  "selector": {
1909
- "description": "CSS selector to match. Combine with role/text or use alone.",
1385
+ "description": "CSS selector. Required for inspect.",
1910
1386
  "type": "string"
1911
1387
  },
1912
1388
  "attributes": {
1913
- "description": "Attribute equals matchers, e.g. { type: 'submit' }.",
1914
1389
  "type": "object",
1915
1390
  "propertyNames": {
1916
1391
  "type": "string"
@@ -1920,63 +1395,14 @@ If the tool returns an error containing "user_locked", the user has manually nam
1920
1395
  }
1921
1396
  },
1922
1397
  "visible": {
1923
- "default": true,
1924
- "description": "Only return visible elements. Default true.",
1925
1398
  "type": "boolean"
1926
1399
  },
1927
1400
  "max": {
1928
- "default": 20,
1929
1401
  "type": "integer",
1930
1402
  "minimum": 1,
1931
1403
  "maximum": 100
1932
1404
  },
1933
1405
  "fields": {
1934
- "description": "Extra per-match fields beyond the lean reference. Omit for the cheapest result.",
1935
- "type": "array",
1936
- "items": {
1937
- "type": "string",
1938
- "enum": [
1939
- "text",
1940
- "html",
1941
- "attributes",
1942
- "value",
1943
- "box"
1944
- ]
1945
- }
1946
- }
1947
- },
1948
- "required": [
1949
- "visible",
1950
- "max"
1951
- ],
1952
- "additionalProperties": false
1953
- }
1954
- },
1955
- {
1956
- "name": "browser_inspect",
1957
- "description": 'Get detail on one element identified by a CSS selector (typically from a snapshot or query result). Choose which fields to return; "context" adds the ancestor chain, associated labels, and the enclosing form.',
1958
- "inputSchema": {
1959
- "type": "object",
1960
- "properties": {
1961
- "tab": {
1962
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
1963
- "type": "string"
1964
- },
1965
- "description": {
1966
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1967
- "type": "string"
1968
- },
1969
- "selector": {
1970
- "type": "string",
1971
- "description": "CSS selector of the element to inspect."
1972
- },
1973
- "fields": {
1974
- "default": [
1975
- "text",
1976
- "attributes",
1977
- "box"
1978
- ],
1979
- "description": "Which detail fields to return.",
1980
1406
  "type": "array",
1981
1407
  "items": {
1982
1408
  "type": "string",
@@ -1992,24 +1418,17 @@ If the tool returns an error containing "user_locked", the user has manually nam
1992
1418
  }
1993
1419
  },
1994
1420
  "maxChars": {
1995
- "default": 4e3,
1996
- "description": "Truncate text/html to this many characters.",
1997
1421
  "type": "integer",
1998
1422
  "minimum": 0,
1999
1423
  "maximum": 2e4
2000
1424
  }
2001
1425
  },
2002
- "required": [
2003
- "selector",
2004
- "fields",
2005
- "maxChars"
2006
- ],
2007
1426
  "additionalProperties": false
2008
1427
  }
2009
1428
  },
2010
1429
  {
2011
- "name": "browser_screenshot",
2012
- "description": "Capture a PNG screenshot of the visible viewport (or one element when a selector is given), save it to disk, and return its file path plus width/height. Oversized files are JPEG-re-encoded (same dimensions) for cheaper Read. To capture content below the fold, scroll to it first (browser_scroll) and screenshot again. The image is NOT loaded into your context automatically \u2014 if you actually need to look at it, call Read on the returned path. Prefer the text tools (snapshot/query/inspect) first; use a screenshot when pixels matter or to leave a visual record for the user.",
1430
+ "name": "browser_wait_for",
1431
+ "description": "Block until the page reaches a desired state. Provide at least one condition; all are AND-combined: a css selector that must be visible, a selector that must be gone, a visible-text substring, and/or a URL substring. Use after browser_act or browser_tabs navigate when the page changes asynchronously. Defaults to 15s, max 60s. Do not sleep+poll with snapshot yourself.",
2013
1432
  "inputSchema": {
2014
1433
  "type": "object",
2015
1434
  "properties": {
@@ -2018,67 +1437,38 @@ If the tool returns an error containing "user_locked", the user has manually nam
2018
1437
  "type": "string"
2019
1438
  },
2020
1439
  "description": {
2021
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1440
+ "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching. Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2022
1441
  "type": "string"
2023
1442
  },
2024
1443
  "selector": {
2025
- "description": "CSS selector to screenshot just that element. Omit for the visible viewport.",
2026
- "type": "string"
2027
- }
2028
- },
2029
- "additionalProperties": false
2030
- }
2031
- },
2032
- {
2033
- "name": "browser_click",
2034
- "description": "Click one element. Prefer selector with a CSS selector from snapshot/query. Alternatively pass text to click the first matching visible element, or x/y viewport coordinates. Provide exactly one targeting mode.",
2035
- "inputSchema": {
2036
- "type": "object",
2037
- "properties": {
2038
- "tab": {
2039
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2040
- "type": "string"
2041
- },
2042
- "description": {
2043
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1444
+ "description": "CSS selector that must be present and visible.",
2044
1445
  "type": "string"
2045
1446
  },
2046
- "selector": {
2047
- "description": "CSS selector of the element to click.",
1447
+ "selectorGone": {
1448
+ "description": "CSS selector that must be absent or hidden.",
2048
1449
  "type": "string"
2049
1450
  },
2050
1451
  "text": {
2051
- "description": "Click the first visible element whose accessible name or text contains this substring.",
1452
+ "description": "Substring that must appear in visible document text.",
2052
1453
  "type": "string"
2053
1454
  },
2054
- "x": {
2055
- "description": "Viewport X coordinate in CSS pixels. Must be paired with y.",
2056
- "type": "number"
2057
- },
2058
- "y": {
2059
- "description": "Viewport Y coordinate in CSS pixels. Must be paired with x.",
2060
- "type": "number"
1455
+ "urlIncludes": {
1456
+ "description": "Substring that must appear in the current URL.",
1457
+ "type": "string"
2061
1458
  },
2062
- "engine": {
2063
- "default": "auto",
2064
- "description": "'auto' (default): trusted CDP click when the CDP setting is on, else synthetic. 'cdp': trusted click via the browser input pipeline \u2014 needed for pointer-event UIs (e.g. Radix), popups/window.open, file pickers, autoplay, canvas; errors if the CDP setting is off. 'synthetic': untrusted DOM mouse events only \u2014 fine for a plain button/link.",
2065
- "type": "string",
2066
- "enum": [
2067
- "auto",
2068
- "cdp",
2069
- "synthetic"
2070
- ]
1459
+ "timeoutMs": {
1460
+ "description": "Maximum wait in milliseconds. Default 15000, max 60000.",
1461
+ "type": "integer",
1462
+ "minimum": 100,
1463
+ "maximum": 6e4
2071
1464
  }
2072
1465
  },
2073
- "required": [
2074
- "engine"
2075
- ],
2076
1466
  "additionalProperties": false
2077
1467
  }
2078
1468
  },
2079
1469
  {
2080
- "name": "browser_hover",
2081
- "description": "Hover the pointer over one element without clicking. Reveals hover-triggered UI: dropdown/flyout menus, tooltips, and controls that only appear on mouseover. Prefer selector with a CSS selector from snapshot/query; alternatively pass text to match the first visible element, or x/y viewport coordinates. Provide exactly one targeting mode. After hovering, snapshot/query again to read whatever the hover revealed.",
1470
+ "name": "browser_evaluate",
1471
+ "description": "Evaluate a JavaScript expression in the page and return its serializable result. Prefer snapshot and browser_act; use evaluate only for inspection or interactions those tools cannot express. The expression may mutate page state. A returned Promise is awaited. A large result (>32KB) is spilled to a file as { spilled:true, path, bytes, preview }.",
2082
1472
  "inputSchema": {
2083
1473
  "type": "object",
2084
1474
  "properties": {
@@ -2087,113 +1477,60 @@ If the tool returns an error containing "user_locked", the user has manually nam
2087
1477
  "type": "string"
2088
1478
  },
2089
1479
  "description": {
2090
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2091
- "type": "string"
2092
- },
2093
- "selector": {
2094
- "description": "CSS selector of the element to hover.",
2095
- "type": "string"
2096
- },
2097
- "text": {
2098
- "description": "Hover the first visible element whose accessible name or text contains this substring.",
1480
+ "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching. Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2099
1481
  "type": "string"
2100
1482
  },
2101
- "x": {
2102
- "description": "Viewport X coordinate in CSS pixels. Must be paired with y.",
2103
- "type": "number"
2104
- },
2105
- "y": {
2106
- "description": "Viewport Y coordinate in CSS pixels. Must be paired with x.",
2107
- "type": "number"
2108
- },
2109
- "engine": {
2110
- "default": "auto",
2111
- "description": "'auto' (default): trusted CDP mouse move when the CDP setting is on, else synthetic. 'cdp': trusted hover via the browser input pipeline \u2014 needed for menus/tooltips gated on real pointer events (e.g. Radix, native title tooltips); errors if the CDP setting is off. 'synthetic': untrusted DOM pointer/mouse events only (pointerover/mouseover/mouseenter/mousemove) \u2014 fine for CSS :hover and most JS handlers.",
1483
+ "expression": {
2112
1484
  "type": "string",
2113
- "enum": [
2114
- "auto",
2115
- "cdp",
2116
- "synthetic"
2117
- ]
1485
+ "minLength": 1,
1486
+ "maxLength": 64e3,
1487
+ "description": "JavaScript expression to evaluate in the page."
2118
1488
  }
2119
1489
  },
2120
1490
  "required": [
2121
- "engine"
1491
+ "expression"
2122
1492
  ],
2123
1493
  "additionalProperties": false
2124
1494
  }
2125
1495
  },
2126
1496
  {
2127
- "name": "browser_type",
2128
- "description": "Type text into an input. Prefer selector with a CSS selector; if omitted, types into the currently focused element. Set clear=true to replace existing text. Dispatches native input/change events so framework-controlled inputs update.",
1497
+ "name": "browser_tabs",
1498
+ "description": "Discover and change browser tabs for this session. action=list (default) returns a TOON table of tab id / url / title / loading. action=open creates or reuses a tab (optional url). action=navigate|back|forward|reload changes that tab's page \u2014 pass url, or port (+ optional path) for localhost. Use the returned tab id as `tab` on other browser tools. Not for clicking or typing (browser_act).",
2129
1499
  "inputSchema": {
2130
1500
  "type": "object",
2131
1501
  "properties": {
2132
- "tab": {
2133
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2134
- "type": "string"
2135
- },
2136
1502
  "description": {
2137
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1503
+ "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching. Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2138
1504
  "type": "string"
2139
1505
  },
2140
- "text": {
2141
- "type": "string",
2142
- "description": "Literal text to insert."
2143
- },
2144
- "selector": {
2145
- "description": "CSS selector of the input. Omit to type into the focused element.",
2146
- "type": "string"
2147
- },
2148
- "clear": {
2149
- "default": false,
2150
- "description": "Clear the existing value before typing. Default false.",
2151
- "type": "boolean"
2152
- },
2153
- "engine": {
2154
- "default": "synthetic",
2155
- "description": "'synthetic' (default): sets the value natively and fires input/change \u2014 enough for ordinary framework-controlled inputs. 'cdp': trusted insert via the browser editing pipeline \u2014 use for rich editors (Monaco, CodeMirror, ProseMirror), masked/per-keystroke inputs, or logic gated on trusted events; requires the CDP setting. Neither engine emits per-character keydown.",
1506
+ "action": {
1507
+ "description": "Default list.",
2156
1508
  "type": "string",
2157
1509
  "enum": [
2158
- "synthetic",
2159
- "cdp"
1510
+ "list",
1511
+ "open",
1512
+ "navigate",
1513
+ "back",
1514
+ "forward",
1515
+ "reload"
2160
1516
  ]
2161
- }
2162
- },
2163
- "required": [
2164
- "text",
2165
- "clear",
2166
- "engine"
2167
- ],
2168
- "additionalProperties": false
2169
- }
2170
- },
2171
- {
2172
- "name": "browser_navigate",
2173
- "description": "Change the page the browser shows. Provide exactly one of: url (a website), port (a local dev-server on localhost), or action (back/forward/reload to move through history). Waits for the page to stop loading by default.",
2174
- "inputSchema": {
2175
- "type": "object",
2176
- "properties": {
2177
- "tab": {
2178
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2179
- "type": "string"
2180
1517
  },
2181
- "description": {
2182
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1518
+ "tab": {
1519
+ "description": "Existing tab id to reuse (open) or target (navigate/history).",
2183
1520
  "type": "string"
2184
1521
  },
2185
1522
  "url": {
2186
- "description": "Website URL, e.g. https://example.com. A schemeless host like 'example.com' gets https; loopback gets http.",
1523
+ "description": "Website URL for open/navigate. Schemeless host gets https; loopback gets http.",
2187
1524
  "type": "string"
2188
1525
  },
2189
1526
  "port": {
2190
- "description": "Local dev-server port on localhost.",
1527
+ "description": "Localhost port for navigate.",
2191
1528
  "type": "integer",
2192
1529
  "minimum": 1,
2193
1530
  "maximum": 65535
2194
1531
  },
2195
1532
  "path": {
2196
- "description": "Optional path/query for the port form, e.g. '/settings'.",
1533
+ "description": "Optional path/query for the port form.",
2197
1534
  "type": "string"
2198
1535
  },
2199
1536
  "protocol": {
@@ -2204,17 +1541,7 @@ If the tool returns an error containing "user_locked", the user has manually nam
2204
1541
  "https"
2205
1542
  ]
2206
1543
  },
2207
- "action": {
2208
- "description": "Move through history instead of loading a URL.",
2209
- "type": "string",
2210
- "enum": [
2211
- "back",
2212
- "forward",
2213
- "reload"
2214
- ]
2215
- },
2216
1544
  "readiness": {
2217
- "default": "load",
2218
1545
  "description": "'load' waits for loading to stop (default); 'none' returns immediately.",
2219
1546
  "type": "string",
2220
1547
  "enum": [
@@ -2223,59 +1550,12 @@ If the tool returns an error containing "user_locked", the user has manually nam
2223
1550
  ]
2224
1551
  }
2225
1552
  },
2226
- "required": [
2227
- "readiness"
2228
- ],
2229
- "additionalProperties": false
2230
- }
2231
- },
2232
- {
2233
- "name": "browser_wait_for",
2234
- "description": "Block until the page reaches a desired state, then return. Provide at least one condition; all are AND-combined: a css selector that must be visible, a selector that must be gone (e.g. a loading spinner), a visible-text substring, and/or a URL substring. Use after click/type/navigate when the page changes asynchronously. Defaults to 15s, max 60s.",
2235
- "inputSchema": {
2236
- "type": "object",
2237
- "properties": {
2238
- "tab": {
2239
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2240
- "type": "string"
2241
- },
2242
- "description": {
2243
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2244
- "type": "string"
2245
- },
2246
- "selector": {
2247
- "description": "CSS selector that must be present and visible.",
2248
- "type": "string"
2249
- },
2250
- "selectorGone": {
2251
- "description": "CSS selector that must be absent or hidden (e.g. a spinner that should disappear).",
2252
- "type": "string"
2253
- },
2254
- "text": {
2255
- "description": "Substring that must appear in visible document text.",
2256
- "type": "string"
2257
- },
2258
- "urlIncludes": {
2259
- "description": "Substring that must appear in the current URL.",
2260
- "type": "string"
2261
- },
2262
- "timeoutMs": {
2263
- "default": 15e3,
2264
- "description": "Maximum wait in milliseconds. Default 15000, max 60000.",
2265
- "type": "integer",
2266
- "minimum": 100,
2267
- "maximum": 6e4
2268
- }
2269
- },
2270
- "required": [
2271
- "timeoutMs"
2272
- ],
2273
1553
  "additionalProperties": false
2274
1554
  }
2275
1555
  },
2276
1556
  {
2277
- "name": "browser_press",
2278
- "description": "Press one keyboard key, e.g. { key: 'Enter' }, { key: 'Escape' }, or { key: 'a', modifiers: ['Meta'] }. Targets the element at selector, or the focused element if omitted. Enter submits the enclosing form when no modifiers are held.",
1557
+ "name": "browser_act",
1558
+ "description": "Act on the page: click, hover, type, press, scroll, drag, select, upload. Send ONE action per call by default. Batch 2\u201320 only for a sequence you would not stop between (fill a form then submit) \u2014 the user sees a batch as one step. Re-read the page between anything else. Prefer a CSS selector from snapshot/query; click/hover also accept text or x/y. engine=auto|cdp|synthetic (default auto). description is shown to the user instead of raw selectors. recording=true saves a video of just this transaction; expect holds it open until a page condition is met. Not for navigation (browser_tabs), waiting (browser_wait_for), or JS (browser_evaluate). Fail-fast: stops at the first error.",
2279
1559
  "inputSchema": {
2280
1560
  "type": "object",
2281
1561
  "properties": {
@@ -2284,284 +1564,189 @@ If the tool returns an error containing "user_locked", the user has manually nam
2284
1564
  "type": "string"
2285
1565
  },
2286
1566
  "description": {
2287
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1567
+ "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching. Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2288
1568
  "type": "string"
2289
1569
  },
2290
- "key": {
2291
- "type": "string",
2292
- "minLength": 1,
2293
- "description": "Key name such as Enter, Escape, Tab, ArrowDown, Backspace, or a single character."
2294
- },
2295
- "modifiers": {
2296
- "description": "Modifier keys held while pressing.",
1570
+ "actions": {
1571
+ "minItems": 1,
1572
+ "maxItems": 20,
2297
1573
  "type": "array",
2298
1574
  "items": {
2299
- "type": "string",
2300
- "enum": [
2301
- "Alt",
2302
- "Control",
2303
- "Meta",
2304
- "Shift"
2305
- ]
2306
- }
2307
- },
2308
- "selector": {
2309
- "description": "CSS selector of the key target. Omit to target the focused element.",
2310
- "type": "string"
2311
- },
2312
- "engine": {
2313
- "default": "synthetic",
2314
- "description": "'synthetic' (default): a DOM KeyboardEvent \u2014 enough for JS key handlers (shortcuts, Enter-to-submit, Escape) but untrusted, no native browser behavior. 'cdp': trusted key via the browser input pipeline \u2014 use when a key must move focus (Tab), type into a native input, trigger a browser shortcut, or when a synthetic press had no effect; requires the CDP setting.",
2315
- "type": "string",
2316
- "enum": [
2317
- "synthetic",
2318
- "cdp"
2319
- ]
2320
- }
2321
- },
2322
- "required": [
2323
- "key",
2324
- "engine"
2325
- ],
2326
- "additionalProperties": false
2327
- }
2328
- },
2329
- {
2330
- "name": "browser_scroll",
2331
- "description": "Scroll by CSS pixels. Positive deltaY scrolls down, positive deltaX scrolls right. Without a selector it scrolls the viewport; with one it scrolls that container. Provide at least one delta. Useful to trigger lazy-loading or reveal off-screen elements.",
2332
- "inputSchema": {
2333
- "type": "object",
2334
- "properties": {
2335
- "tab": {
2336
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2337
- "type": "string"
2338
- },
2339
- "description": {
2340
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2341
- "type": "string"
2342
- },
2343
- "deltaX": {
2344
- "description": "Horizontal scroll in CSS pixels. Positive scrolls right.",
2345
- "type": "number"
2346
- },
2347
- "deltaY": {
2348
- "description": "Vertical scroll in CSS pixels. Positive scrolls down.",
2349
- "type": "number"
2350
- },
2351
- "selector": {
2352
- "description": "CSS selector of a scrollable container. Omit to scroll the viewport.",
2353
- "type": "string"
2354
- }
2355
- },
2356
- "additionalProperties": false
2357
- }
2358
- },
2359
- {
2360
- "name": "browser_drag",
2361
- "description": "Drag from a source point to a destination point. Handles both pointer-driven gestures (sliders, sortable lists, canvas panning, drag-resize) and native HTML5 drag-and-drop (elements with draggable=true, e.g. kanban cards and file drop zones) \u2014 with the browser CDP setting on, it auto-detects which and drives trusted events for either. Target the source via `from` and the destination via `to`, each by selector, visible text, or x/y viewport coordinates. Tip: enable the browser CDP setting for reliable drags; without it, a best-effort synthetic fallback is used.",
2362
- "inputSchema": {
2363
- "type": "object",
2364
- "properties": {
2365
- "tab": {
2366
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2367
- "type": "string"
1575
+ "type": "object",
1576
+ "properties": {
1577
+ "type": {
1578
+ "type": "string",
1579
+ "enum": [
1580
+ "click",
1581
+ "hover",
1582
+ "type",
1583
+ "press",
1584
+ "scroll",
1585
+ "drag",
1586
+ "select",
1587
+ "upload"
1588
+ ]
1589
+ },
1590
+ "selector": {
1591
+ "type": "string"
1592
+ },
1593
+ "text": {
1594
+ "type": "string"
1595
+ },
1596
+ "x": {
1597
+ "type": "number"
1598
+ },
1599
+ "y": {
1600
+ "type": "number"
1601
+ },
1602
+ "clear": {
1603
+ "type": "boolean"
1604
+ },
1605
+ "key": {
1606
+ "type": "string"
1607
+ },
1608
+ "modifiers": {
1609
+ "type": "array",
1610
+ "items": {
1611
+ "type": "string",
1612
+ "enum": [
1613
+ "Alt",
1614
+ "Control",
1615
+ "Meta",
1616
+ "Shift"
1617
+ ]
1618
+ }
1619
+ },
1620
+ "deltaX": {
1621
+ "type": "number"
1622
+ },
1623
+ "deltaY": {
1624
+ "type": "number"
1625
+ },
1626
+ "from": {
1627
+ "type": "object",
1628
+ "properties": {
1629
+ "selector": {
1630
+ "type": "string"
1631
+ },
1632
+ "text": {
1633
+ "type": "string"
1634
+ },
1635
+ "x": {
1636
+ "type": "number"
1637
+ },
1638
+ "y": {
1639
+ "type": "number"
1640
+ }
1641
+ },
1642
+ "additionalProperties": false
1643
+ },
1644
+ "to": {
1645
+ "type": "object",
1646
+ "properties": {
1647
+ "selector": {
1648
+ "type": "string"
1649
+ },
1650
+ "text": {
1651
+ "type": "string"
1652
+ },
1653
+ "x": {
1654
+ "type": "number"
1655
+ },
1656
+ "y": {
1657
+ "type": "number"
1658
+ }
1659
+ },
1660
+ "additionalProperties": false
1661
+ },
1662
+ "steps": {
1663
+ "type": "integer",
1664
+ "minimum": -9007199254740991,
1665
+ "maximum": 9007199254740991
1666
+ },
1667
+ "holdMs": {
1668
+ "type": "integer",
1669
+ "minimum": -9007199254740991,
1670
+ "maximum": 9007199254740991
1671
+ },
1672
+ "humanize": {
1673
+ "type": "boolean"
1674
+ },
1675
+ "value": {
1676
+ "type": "string"
1677
+ },
1678
+ "label": {
1679
+ "type": "string"
1680
+ },
1681
+ "index": {
1682
+ "type": "integer",
1683
+ "minimum": -9007199254740991,
1684
+ "maximum": 9007199254740991
1685
+ },
1686
+ "checked": {
1687
+ "type": "boolean"
1688
+ },
1689
+ "files": {
1690
+ "type": "array",
1691
+ "items": {
1692
+ "type": "string"
1693
+ }
1694
+ },
1695
+ "engine": {
1696
+ "type": "string",
1697
+ "enum": [
1698
+ "auto",
1699
+ "cdp",
1700
+ "synthetic"
1701
+ ]
1702
+ }
1703
+ },
1704
+ "required": [
1705
+ "type"
1706
+ ],
1707
+ "additionalProperties": false
1708
+ },
1709
+ "description": "Normally one action. Use 2\u201320 only for a single uninterruptible sequence; they run in order, fail-fast."
2368
1710
  },
2369
- "description": {
2370
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2371
- "type": "string"
1711
+ "recording": {
1712
+ "description": "Save a video of only this action transaction. Default false.",
1713
+ "type": "boolean"
2372
1714
  },
2373
- "from": {
1715
+ "expect": {
1716
+ "description": "Explicit completion condition checked before recording stops.",
2374
1717
  "type": "object",
2375
1718
  "properties": {
2376
1719
  "selector": {
2377
- "description": "CSS selector of the element.",
2378
- "type": "string"
2379
- },
2380
- "text": {
2381
- "description": "Match the first visible element whose accessible name or text contains this substring.",
2382
1720
  "type": "string"
2383
1721
  },
2384
- "x": {
2385
- "description": "Viewport X coordinate in CSS pixels. Must be paired with y.",
2386
- "type": "number"
2387
- },
2388
- "y": {
2389
- "description": "Viewport Y coordinate in CSS pixels. Must be paired with x.",
2390
- "type": "number"
2391
- }
2392
- },
2393
- "additionalProperties": false,
2394
- "description": "Drag source. Provide exactly one targeting mode: selector, text, or x+y."
2395
- },
2396
- "to": {
2397
- "type": "object",
2398
- "properties": {
2399
- "selector": {
2400
- "description": "CSS selector of the element.",
1722
+ "selectorGone": {
2401
1723
  "type": "string"
2402
1724
  },
2403
1725
  "text": {
2404
- "description": "Match the first visible element whose accessible name or text contains this substring.",
2405
1726
  "type": "string"
2406
1727
  },
2407
- "x": {
2408
- "description": "Viewport X coordinate in CSS pixels. Must be paired with y.",
2409
- "type": "number"
2410
- },
2411
- "y": {
2412
- "description": "Viewport Y coordinate in CSS pixels. Must be paired with x.",
2413
- "type": "number"
1728
+ "urlIncludes": {
1729
+ "type": "string"
2414
1730
  }
2415
1731
  },
2416
- "additionalProperties": false,
2417
- "description": "Drag destination. Provide exactly one targeting mode: selector, text, or x+y."
2418
- },
2419
- "steps": {
2420
- "default": 10,
2421
- "description": "Number of intermediate move events between source and target. More steps = a slower, smoother drag (each step adds a small delay); fewer = a faster drag. Default 10.",
2422
- "type": "integer",
2423
- "minimum": 1,
2424
- "maximum": 50
2425
- },
2426
- "holdMs": {
2427
- "default": 0,
2428
- "description": "Time in milliseconds to pause on the target after arriving, before releasing/dropping. Some drop zones only register the drop after a hover. Default 0.",
2429
- "type": "integer",
2430
- "minimum": 0,
2431
- "maximum": 1e4
2432
- },
2433
- "humanize": {
2434
- "default": false,
2435
- "description": "When true, vary per-step timing and add positional jitter along an ease-in-out motion curve to mimic a human drag. Improves success on libraries that reject robotic linear moves. The final position is still exact. Default false.",
2436
- "type": "boolean"
2437
- }
2438
- },
2439
- "required": [
2440
- "from",
2441
- "to",
2442
- "steps",
2443
- "holdMs",
2444
- "humanize"
2445
- ],
2446
- "additionalProperties": false
2447
- }
2448
- },
2449
- {
2450
- "name": "browser_select",
2451
- "description": "Set the value of a <select> dropdown (by value, visible label, or index) or toggle a checkbox/radio (by checked). Provide the selector plus exactly one of value, label, index, or checked. Dispatches native change events.",
2452
- "inputSchema": {
2453
- "type": "object",
2454
- "properties": {
2455
- "tab": {
2456
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2457
- "type": "string"
2458
- },
2459
- "description": {
2460
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2461
- "type": "string"
2462
- },
2463
- "selector": {
2464
- "type": "string",
2465
- "description": "CSS selector of the <select>, checkbox, or radio."
2466
- },
2467
- "value": {
2468
- "description": "Option value to select (for <select>).",
2469
- "type": "string"
2470
- },
2471
- "label": {
2472
- "description": "Visible option text to select (for <select>); exact match preferred, falls back to substring.",
2473
- "type": "string"
1732
+ "additionalProperties": false
2474
1733
  },
2475
- "index": {
2476
- "description": "Zero-based option index (for <select>).",
1734
+ "timeoutMs": {
1735
+ "description": "Maximum wait for expect. Default 15000.",
2477
1736
  "type": "integer",
2478
- "minimum": 0,
2479
- "maximum": 9007199254740991
2480
- },
2481
- "checked": {
2482
- "description": "Desired checked state (for checkbox/radio). Defaults to true.",
2483
- "type": "boolean"
2484
- }
2485
- },
2486
- "required": [
2487
- "selector"
2488
- ],
2489
- "additionalProperties": false
2490
- }
2491
- },
2492
- {
2493
- "name": "browser_open",
2494
- "description": 'Open a new browser tab (optionally at a URL) and return its tab id. Use this when no browser is open yet, or to start a fresh page. Pass the returned tab id as the "tab" argument to the other browser tools. Waits for the page to stop loading by default.',
2495
- "inputSchema": {
2496
- "type": "object",
2497
- "properties": {
2498
- "description": {
2499
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2500
- "type": "string"
2501
- },
2502
- "url": {
2503
- "description": "Initial URL. A schemeless host like 'example.com' gets https; loopback gets http. Defaults to a blank tab.",
2504
- "type": "string"
2505
- },
2506
- "tab": {
2507
- "description": "Existing browser tab id to reuse/focus instead of creating a new one.",
2508
- "type": "string"
2509
- },
2510
- "readiness": {
2511
- "default": "load",
2512
- "description": "'load' waits for loading to stop (default); 'none' returns as soon as the tab exists.",
2513
- "type": "string",
2514
- "enum": [
2515
- "load",
2516
- "none"
2517
- ]
2518
- }
2519
- },
2520
- "required": [
2521
- "readiness"
2522
- ],
2523
- "additionalProperties": false
2524
- }
2525
- },
2526
- {
2527
- "name": "browser_evaluate",
2528
- "description": "Evaluate a JavaScript expression in the page and return its serializable result. Prefer snapshot and the semantic action tools; use evaluate only for inspection or interactions those tools cannot express. The expression runs in the page and may mutate its state. A returned Promise is awaited. A large result (>32KB serialized) is written to a temp file and returned as { spilled:true, path, bytes, preview } \u2014 Read/grep the path for the full value instead of it flooding context.",
2529
- "inputSchema": {
2530
- "type": "object",
2531
- "properties": {
2532
- "tab": {
2533
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2534
- "type": "string"
2535
- },
2536
- "description": {
2537
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2538
- "type": "string"
2539
- },
2540
- "expression": {
2541
- "type": "string",
2542
- "minLength": 1,
2543
- "maxLength": 64e3,
2544
- "description": 'JavaScript expression, e.g. document.title or (() => ({ items: [...document.querySelectorAll("li")].map(li => li.textContent) }))().'
1737
+ "minimum": 100,
1738
+ "maximum": 6e4
2545
1739
  }
2546
1740
  },
2547
1741
  "required": [
2548
- "expression"
1742
+ "actions"
2549
1743
  ],
2550
1744
  "additionalProperties": false
2551
1745
  }
2552
1746
  },
2553
1747
  {
2554
- "name": "browser_tabs",
2555
- "description": 'List the browser tabs available to this session, each with its tab id, url, title, and loading state (result in TOON: a `tabs[N]{...}:` table). Use the returned tab id as the "tab" argument to target a specific tab. Only tabs belonging to this session are listed.',
2556
- "inputSchema": {
2557
- "type": "object",
2558
- "properties": {},
2559
- "additionalProperties": false
2560
- }
2561
- },
2562
- {
2563
- "name": "browser_resize",
2564
- "description": "Resize the browser viewport to test responsive layouts \u2014 no CDP setting required. Pass a preset ('mobile' 375\xD7812, 'tablet' 768\xD71024, 'desktop' 1280\xD7800) or explicit width/height (CSS pixels). Pass reset:true to restore the panel's natural size. Only responsive pages (with a width=device-width viewport meta) reflow; non-responsive pages keep their wide layout. For device-pixel-ratio, touch emulation, user-agent, color scheme, timezone, or geolocation, use browser_emulate instead (it requires the CDP setting).",
1748
+ "name": "browser_network",
1749
+ "description": "Network, downloads, and page environment. Recording ladder: action=start \u2192 do an act/navigate \u2192 action=wait or stop (lean manifest) \u2192 action=body({requestId}) for one response. action=download fetches a URL through the session; action=downloads lists page-triggered captures. action=cookies|mock|emulate need CDP experimental settings, except emulate with only preset/width/height/reset. Prefer snapshot/query for page content.",
2565
1750
  "inputSchema": {
2566
1751
  "type": "object",
2567
1752
  "properties": {
@@ -2570,273 +1755,70 @@ If the tool returns an error containing "user_locked", the user has manually nam
2570
1755
  "type": "string"
2571
1756
  },
2572
1757
  "description": {
2573
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1758
+ "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching. Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2574
1759
  "type": "string"
2575
1760
  },
2576
- "preset": {
2577
- "description": "Named viewport size: mobile 375\xD7812, tablet 768\xD71024, desktop 1280\xD7800.",
1761
+ "action": {
2578
1762
  "type": "string",
2579
1763
  "enum": [
2580
- "mobile",
2581
- "tablet",
2582
- "desktop"
2583
- ]
2584
- },
2585
- "width": {
2586
- "description": "Explicit viewport width in CSS pixels (pair with height). Overrides preset.",
2587
- "type": "integer",
2588
- "minimum": 1,
2589
- "maximum": 1e4
2590
- },
2591
- "height": {
2592
- "description": "Explicit viewport height in CSS pixels (pair with width). Overrides preset.",
2593
- "type": "integer",
2594
- "minimum": 1,
2595
- "maximum": 1e4
1764
+ "start",
1765
+ "stop",
1766
+ "wait",
1767
+ "body",
1768
+ "download",
1769
+ "downloads",
1770
+ "cookies",
1771
+ "mock",
1772
+ "emulate"
1773
+ ],
1774
+ "description": "Which network/env operation to run."
2596
1775
  },
2597
- "reset": {
2598
- "description": "Restore the panel's natural size, clearing any resize.",
2599
- "type": "boolean"
2600
- }
2601
- },
2602
- "additionalProperties": false
2603
- }
2604
- },
2605
- {
2606
- "name": "browser_network_start",
2607
- "description": "Start recording network requests on a tab (requires the browser CDP setting). Nothing is captured until you start, and capture is torn down with zero overhead when you stop \u2014 so record only around the action you care about. Response bodies of matching requests are captured EAGERLY, so they are always readable later (never lost to the browser's cache eviction). Typical flow: browser_network_start \u2192 do an action (browser_click / browser_navigate) \u2192 browser_network_stop to collect exactly what that action triggered. Scope with `match` + `resourceTypes` to keep it lean.",
2608
- "inputSchema": {
2609
- "type": "object",
2610
- "properties": {
2611
- "tab": {
2612
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
1776
+ "recordingId": {
1777
+ "description": "From action=start. Required for stop/wait/body.",
2613
1778
  "type": "string"
2614
1779
  },
2615
- "description": {
2616
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1780
+ "requestId": {
1781
+ "description": "From a stop/wait manifest. Required for body.",
2617
1782
  "type": "string"
2618
1783
  },
2619
1784
  "match": {
2620
- "description": "Only record requests whose URL contains this substring. Omit to record everything (within resourceTypes).",
2621
1785
  "type": "string"
2622
1786
  },
2623
1787
  "resourceTypes": {
2624
- "description": "Resource types to record, case-insensitive: XHR, Fetch, Document, Script, Image, Stylesheet, Font, Media, WebSocket. Default ['XHR','Fetch'] (the app's own API calls). Pass ['*'] for all types.",
2625
1788
  "type": "array",
2626
1789
  "items": {
2627
1790
  "type": "string"
2628
1791
  }
2629
1792
  },
2630
1793
  "captureBodies": {
2631
- "default": true,
2632
- "description": "Capture response bodies of matching requests. Default true. Set false to record only metadata + headers (cheaper).",
2633
1794
  "type": "boolean"
2634
1795
  },
2635
1796
  "max": {
2636
- "default": 200,
2637
- "description": "Max requests to record before ignoring further ones. Default 200.",
2638
1797
  "type": "integer",
2639
- "minimum": 1,
2640
- "maximum": 1e3
2641
- }
2642
- },
2643
- "required": [
2644
- "captureBodies",
2645
- "max"
2646
- ],
2647
- "additionalProperties": false
2648
- }
2649
- },
2650
- {
2651
- "name": "browser_network_stop",
2652
- "description": "Stop a recording started with browser_network_start and return a lean manifest of what it captured, as TOON (a compact tabular format \u2014 read the rows top-to-bottom). Each row has requestId, method, status, resourceType, url, and bodyBytes \u2014 enough to scan and pick which requests matter. It deliberately does NOT include headers, the request payload, or the response body: read one request's full detail (headers + payload + response body) on demand with browser_network_body({ recordingId, requestId }), so a many-request recording never floods context. Bodies stay readable after stop (recent recordings are retained). Pass keep:true to read the manifest so far WITHOUT stopping (peek during a long-running action).",
2653
- "inputSchema": {
2654
- "type": "object",
2655
- "properties": {
2656
- "recordingId": {
2657
- "type": "string",
2658
- "description": "The id returned by browser_network_start."
1798
+ "minimum": -9007199254740991,
1799
+ "maximum": 9007199254740991
2659
1800
  },
2660
1801
  "keep": {
2661
- "default": false,
2662
- "description": "Keep recording (peek) instead of stopping. Default false: stop and tear down capture.",
1802
+ "description": "stop only: peek without tearing down.",
2663
1803
  "type": "boolean"
2664
- }
2665
- },
2666
- "required": [
2667
- "recordingId",
2668
- "keep"
2669
- ],
2670
- "additionalProperties": false
2671
- }
2672
- },
2673
- {
2674
- "name": "browser_network_wait",
2675
- "description": "Within an active recording, block until a recorded request whose URL contains the given substring finishes, then return its manifest row as TOON (requestId, method, status, resourceType, url, bodyBytes; read the full detail/body with browser_network_body via requestId). Use after an action that fires an async XHR/fetch, before browser_network_stop, instead of guessing a delay. Default timeout 15s, max 60s.",
2676
- "inputSchema": {
2677
- "type": "object",
2678
- "properties": {
2679
- "description": {
2680
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2681
- "type": "string"
2682
- },
2683
- "recordingId": {
2684
- "type": "string",
2685
- "description": "The id returned by browser_network_start."
2686
1804
  },
2687
1805
  "url": {
2688
- "type": "string",
2689
- "minLength": 1,
2690
- "description": "Substring the request URL must contain."
1806
+ "description": "wait: substring to match. download: absolute URL. mock: url substring.",
1807
+ "type": "string"
2691
1808
  },
2692
1809
  "timeoutMs": {
2693
- "default": 15e3,
2694
- "description": "Maximum wait in milliseconds. Default 15000.",
2695
1810
  "type": "integer",
2696
- "minimum": 100,
2697
- "maximum": 6e4
2698
- }
2699
- },
2700
- "required": [
2701
- "recordingId",
2702
- "url",
2703
- "timeoutMs"
2704
- ],
2705
- "additionalProperties": false
2706
- }
2707
- },
2708
- {
2709
- "name": "browser_network_body",
2710
- "description": "Read one recorded request's full detail on demand (result in TOON), by the requestId from a browser_network_stop / browser_network_wait manifest: method, url, status, mimeType, requestHeaders, requestBody (POST payload), responseHeaders, and the full response body. Reads from the recording's own captured store (not the browser's volatile cache), so it works even for large bodies long after the request finished. A large response body is written to a temp file and returned as { spilled:true, path, bytes, preview } \u2014 Read/grep the path. Works while the recording is active or after it has stopped (recent recordings are retained).",
2711
- "inputSchema": {
2712
- "type": "object",
2713
- "properties": {
2714
- "description": {
2715
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2716
- "type": "string"
2717
- },
2718
- "recordingId": {
2719
- "type": "string",
2720
- "description": "The id returned by browser_network_start."
2721
- },
2722
- "requestId": {
2723
- "type": "string",
2724
- "description": "The requestId of the entry (from the stop/wait manifest) whose detail to read."
2725
- }
2726
- },
2727
- "required": [
2728
- "recordingId",
2729
- "requestId"
2730
- ],
2731
- "additionalProperties": false
2732
- }
2733
- },
2734
- {
2735
- "name": "browser_cookies",
2736
- "description": "Read the cookies visible to the page (experimental; requires the browser CDP setting + cookie-access sub-setting). Returns name, value, domain, path, and key flags as TOON (a `cookies[N]{...}:` table). Long cookie values are truncated (a valueLength field carries the original length). Pass urls to scope to specific URLs.",
2737
- "inputSchema": {
2738
- "type": "object",
2739
- "properties": {
2740
- "tab": {
2741
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2742
- "type": "string"
2743
- },
2744
- "description": {
2745
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2746
- "type": "string"
2747
- },
2748
- "urls": {
2749
- "description": "Only return cookies that would be sent to these URLs. Omit for the current page.",
2750
- "type": "array",
2751
- "items": {
2752
- "type": "string"
2753
- }
2754
- }
2755
- },
2756
- "additionalProperties": false
2757
- }
2758
- },
2759
- {
2760
- "name": "browser_upload_file",
2761
- "description": "Set the files on a file <input> element (requires the browser CDP setting). This is the only way to attach files to an upload control, which cannot be driven by synthetic events. Provide the input selector and absolute file paths.",
2762
- "inputSchema": {
2763
- "type": "object",
2764
- "properties": {
2765
- "tab": {
2766
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2767
- "type": "string"
2768
- },
2769
- "description": {
2770
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2771
- "type": "string"
2772
- },
2773
- "selector": {
2774
- "type": "string",
2775
- "description": "CSS selector of the file <input> element (input[type=file])."
2776
- },
2777
- "files": {
2778
- "minItems": 1,
2779
- "type": "array",
2780
- "items": {
2781
- "type": "string"
2782
- },
2783
- "description": "Absolute paths of the files to attach."
2784
- }
2785
- },
2786
- "required": [
2787
- "selector",
2788
- "files"
2789
- ],
2790
- "additionalProperties": false
2791
- }
2792
- },
2793
- {
2794
- "name": "browser_download",
2795
- "description": "Fetch a file by URL and save it to disk through the browser session (cookies/auth apply, no CORS; data: URLs ok). Completes synchronously if finished within `timeoutMs`; otherwise continues in the background and returns status 'background' with a taskId \u2014 you will receive a task notification when it finishes. For downloads the page starts itself (export buttons, attachment links), click first then use browser_list_downloads. Files land in a temp dir \u2014 Read the path, or copy/move if the user wants it kept.",
2796
- "inputSchema": {
2797
- "type": "object",
2798
- "properties": {
2799
- "description": {
2800
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2801
- "type": "string"
2802
- },
2803
- "url": {
2804
- "type": "string",
2805
- "minLength": 1,
2806
- "description": "Absolute URL (or data: URL) of the file to download."
1811
+ "minimum": -9007199254740991,
1812
+ "maximum": 9007199254740991
2807
1813
  },
2808
1814
  "filename": {
2809
- "description": "Override the saved file name. Defaults to Content-Disposition or the URL path segment.",
2810
1815
  "type": "string"
2811
1816
  },
2812
- "timeoutMs": {
2813
- "default": 15e3,
2814
- "description": "How long to wait for a synchronous result before moving the job to the background. Default 15000.",
2815
- "type": "integer",
2816
- "minimum": 100,
2817
- "maximum": 12e4
2818
- }
2819
- },
2820
- "required": [
2821
- "url",
2822
- "timeoutMs"
2823
- ],
2824
- "additionalProperties": false
2825
- }
2826
- },
2827
- {
2828
- "name": "browser_list_downloads",
2829
- "description": "List files the page triggered for download in this session (export buttons, Content-Disposition links, etc.). Captures are saved automatically without a save dialog. Newest first. Use after browser_click on a download control. Set wait:true to block until at least one matching capture is terminal and nothing is still progressing (or until timeout). Filter with state. This is observation only \u2014 to fetch a known URL use browser_download.",
2830
- "inputSchema": {
2831
- "type": "object",
2832
- "properties": {
2833
- "description": {
2834
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1817
+ "dir": {
1818
+ "description": "download only: absolute directory to save into. Defaults to the configured download directory.",
2835
1819
  "type": "string"
2836
1820
  },
2837
1821
  "state": {
2838
- "default": "all",
2839
- "description": "Which captures to include. 'failed' = cancelled or interrupted. Default all.",
2840
1822
  "type": "string",
2841
1823
  "enum": [
2842
1824
  "all",
@@ -2846,67 +1828,71 @@ If the tool returns an error containing "user_locked", the user has manually nam
2846
1828
  ]
2847
1829
  },
2848
1830
  "wait": {
2849
- "default": false,
2850
- "description": "If true, wait for captures to settle (see timeoutMs). Default false (immediate snapshot).",
1831
+ "description": "downloads only: block until captures settle.",
2851
1832
  "type": "boolean"
2852
1833
  },
2853
- "timeoutMs": {
2854
- "default": 15e3,
2855
- "description": "Max wait when wait is true. Default 15000. Ignored when wait is false.",
1834
+ "urls": {
1835
+ "description": "cookies only.",
1836
+ "type": "array",
1837
+ "items": {
1838
+ "type": "string"
1839
+ }
1840
+ },
1841
+ "status": {
2856
1842
  "type": "integer",
2857
- "minimum": 0,
2858
- "maximum": 12e4
2859
- }
2860
- },
2861
- "required": [
2862
- "state",
2863
- "wait",
2864
- "timeoutMs"
2865
- ],
2866
- "additionalProperties": false
2867
- }
2868
- },
2869
- {
2870
- "name": "browser_emulate",
2871
- "description": "Emulate device and environment conditions for the page (experimental; requires the browser CDP setting + device-emulation sub-setting): viewport size, device scale, mobile mode, user agent, color scheme, timezone, locale, and geolocation. Pass reset:true to clear all overrides; they persist until reset or the tab is closed. width/height reflow only responsive pages (with a width=device-width viewport meta); non-responsive pages keep their wide layout.",
2872
- "inputSchema": {
2873
- "type": "object",
2874
- "properties": {
2875
- "tab": {
2876
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
1843
+ "minimum": -9007199254740991,
1844
+ "maximum": 9007199254740991
1845
+ },
1846
+ "body": {
2877
1847
  "type": "string"
2878
1848
  },
2879
- "description": {
2880
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
1849
+ "contentType": {
2881
1850
  "type": "string"
2882
1851
  },
1852
+ "headers": {
1853
+ "type": "object",
1854
+ "propertyNames": {
1855
+ "type": "string"
1856
+ },
1857
+ "additionalProperties": {
1858
+ "type": "string"
1859
+ }
1860
+ },
1861
+ "clear": {
1862
+ "type": "boolean"
1863
+ },
1864
+ "preset": {
1865
+ "description": "emulate: named viewport (no CDP).",
1866
+ "type": "string",
1867
+ "enum": [
1868
+ "mobile",
1869
+ "tablet",
1870
+ "desktop"
1871
+ ]
1872
+ },
2883
1873
  "width": {
2884
- "description": "Viewport width in CSS pixels (pair with height).",
2885
1874
  "type": "integer",
2886
- "minimum": 1,
1875
+ "minimum": -9007199254740991,
2887
1876
  "maximum": 9007199254740991
2888
1877
  },
2889
1878
  "height": {
2890
- "description": "Viewport height in CSS pixels (pair with width).",
2891
1879
  "type": "integer",
2892
- "minimum": 1,
1880
+ "minimum": -9007199254740991,
2893
1881
  "maximum": 9007199254740991
2894
1882
  },
1883
+ "reset": {
1884
+ "type": "boolean"
1885
+ },
2895
1886
  "deviceScaleFactor": {
2896
- "description": "Device pixel ratio. 0 keeps the default.",
2897
- "type": "number",
2898
- "minimum": 0
1887
+ "type": "number"
2899
1888
  },
2900
1889
  "mobile": {
2901
- "description": "Emulate a mobile device (touch, mobile viewport).",
2902
1890
  "type": "boolean"
2903
1891
  },
2904
1892
  "userAgent": {
2905
- "description": "Override the User-Agent header.",
2906
1893
  "type": "string"
2907
1894
  },
2908
1895
  "colorScheme": {
2909
- "description": "Emulate prefers-color-scheme.",
2910
1896
  "type": "string",
2911
1897
  "enum": [
2912
1898
  "light",
@@ -2915,152 +1901,128 @@ If the tool returns an error containing "user_locked", the user has manually nam
2915
1901
  ]
2916
1902
  },
2917
1903
  "timezone": {
2918
- "description": "IANA timezone id, e.g. 'America/New_York'.",
2919
1904
  "type": "string"
2920
1905
  },
2921
1906
  "locale": {
2922
- "description": "Locale, e.g. 'en-US' or 'ja-JP'.",
2923
1907
  "type": "string"
2924
1908
  },
2925
1909
  "latitude": {
2926
- "description": "Geolocation latitude (pair with longitude).",
2927
1910
  "type": "number"
2928
1911
  },
2929
1912
  "longitude": {
2930
- "description": "Geolocation longitude (pair with latitude).",
2931
1913
  "type": "number"
2932
- },
2933
- "reset": {
2934
- "description": "Clear all emulation overrides.",
2935
- "type": "boolean"
2936
1914
  }
2937
1915
  },
1916
+ "required": [
1917
+ "action"
1918
+ ],
2938
1919
  "additionalProperties": false
2939
1920
  }
2940
1921
  },
2941
1922
  {
2942
- "name": "browser_mock",
2943
- "description": "Intercept matching network requests and respond with a mocked response (experimental; requires the browser CDP setting + network-mocking sub-setting). Provide a url substring to match and the response to return. Pass clear:true to remove all mocks. WARNING: this can read and alter all page traffic \u2014 use only in trusted scenarios.",
1923
+ "name": "browser_action",
1924
+ "description": "Saved semantic browser actions (dynamic catalog \u2014 list then do). action=list (optional domain; includeSteps to see the full definition). action=do runs one saved action with input. action=save creates or replaces a named flow (domain+name) \u2014 read the manual first. This does not record prior browser calls. Use browser_act for one-off clicks/types.",
2944
1925
  "inputSchema": {
2945
1926
  "type": "object",
2946
1927
  "properties": {
2947
- "tab": {
2948
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2949
- "type": "string"
1928
+ "action": {
1929
+ "type": "string",
1930
+ "enum": [
1931
+ "list",
1932
+ "save",
1933
+ "do"
1934
+ ],
1935
+ "description": "list / save / do."
2950
1936
  },
2951
- "description": {
2952
- "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching (e.g. 'Fill in the login email', 'Submit the checkout form'). Shown in the UI in place of the raw selector. Write it in the conversation's language.",
2953
- "type": "string"
1937
+ "domain": {
1938
+ "type": "string",
1939
+ "minLength": 1,
1940
+ "maxLength": 500,
1941
+ "description": "Semantic domain namespace, normally a hostname such as github.com."
2954
1942
  },
2955
- "url": {
2956
- "description": "Substring; requests whose URL contains it are fulfilled with the mock. Required unless clear is set.",
1943
+ "name": {
2957
1944
  "type": "string"
2958
1945
  },
2959
- "status": {
2960
- "description": "HTTP status code to return (default 200).",
2961
- "type": "integer",
2962
- "minimum": 100,
2963
- "maximum": 599
2964
- },
2965
- "body": {
2966
- "description": "Response body to return (default empty).",
2967
- "type": "string"
1946
+ "includeSteps": {
1947
+ "type": "boolean"
2968
1948
  },
2969
- "contentType": {
2970
- "description": "Response Content-Type (default 'application/json').",
2971
- "type": "string"
1949
+ "description": {
1950
+ "type": "string",
1951
+ "minLength": 1,
1952
+ "maxLength": 1e3
2972
1953
  },
2973
- "headers": {
2974
- "description": "Extra response headers.",
2975
- "type": "object",
2976
- "propertyNames": {
2977
- "type": "string"
2978
- },
2979
- "additionalProperties": {
2980
- "type": "string"
1954
+ "parameters": {
1955
+ "default": [],
1956
+ "maxItems": 50,
1957
+ "type": "array",
1958
+ "items": {
1959
+ "type": "object",
1960
+ "properties": {
1961
+ "name": {
1962
+ "type": "string",
1963
+ "pattern": "^[A-Za-z_][A-Za-z0-9_-]{0,63}$",
1964
+ "description": "Input name referenced in step templates as ${input.name}."
1965
+ },
1966
+ "description": {
1967
+ "description": "What the caller should provide.",
1968
+ "type": "string",
1969
+ "minLength": 1,
1970
+ "maxLength": 500
1971
+ },
1972
+ "type": {
1973
+ "description": "Optional runtime type constraint.",
1974
+ "type": "string",
1975
+ "enum": [
1976
+ "string",
1977
+ "number",
1978
+ "boolean",
1979
+ "object",
1980
+ "array"
1981
+ ]
1982
+ },
1983
+ "required": {
1984
+ "default": true,
1985
+ "type": "boolean"
1986
+ },
1987
+ "default": {}
1988
+ },
1989
+ "required": [
1990
+ "name",
1991
+ "required"
1992
+ ],
1993
+ "additionalProperties": false
2981
1994
  }
2982
1995
  },
2983
- "clear": {
2984
- "description": "Remove all mock rules for this tab and stop intercepting.",
2985
- "type": "boolean"
2986
- }
2987
- },
2988
- "additionalProperties": false
2989
- }
2990
- },
2991
- {
2992
- "name": "browser_act",
2993
- "description": "Submit 1\u201320 page actions as one call: click, hover, type, press, scroll, drag, select, upload. Prefer a CSS selector from snapshot/query; click/hover also accept text or x/y. engine=auto|cdp|synthetic (default auto). description is shown to the user instead of raw selectors. Set recording=true to save a short video containing only this action transaction. Optional expect keeps the recording open until an explicit page condition is met. Do not use this to navigate (browser_tabs), wait (browser_wait_for), or run JS (browser_evaluate). Fail-fast: stops at the first error.",
2994
- "inputSchema": {
2995
- "type": "object",
2996
- "properties": {
2997
- "tab": { "type": "string" },
2998
- "description": { "type": "string" },
2999
- "actions": {
3000
- "type": "array",
1996
+ "steps": {
1997
+ "description": 'save only: 1-50 flow steps, each {kind:"tool"|"action"|"set"|"if"|"forEach"|"repeat"}. Read read_manual({ domain: "product", topic: "browser" }) for the grammar before writing them.',
3001
1998
  "minItems": 1,
3002
- "maxItems": 20,
1999
+ "maxItems": 50,
2000
+ "type": "array",
3003
2001
  "items": {
3004
2002
  "type": "object",
3005
- "properties": {
3006
- "type": { "type": "string", "enum": ["click", "hover", "type", "press", "scroll", "drag", "select", "upload"] }
2003
+ "propertyNames": {
2004
+ "type": "string"
3007
2005
  },
3008
- "required": ["type"],
3009
- "additionalProperties": true
2006
+ "additionalProperties": {}
3010
2007
  }
3011
2008
  },
3012
- "recording": { "type": "boolean", "description": "Save a video of only this action transaction. Default false." },
3013
- "expect": {
2009
+ "input": {
3014
2010
  "type": "object",
3015
- "properties": {
3016
- "selector": { "type": "string" },
3017
- "selectorGone": { "type": "string" },
3018
- "text": { "type": "string" },
3019
- "urlIncludes": { "type": "string" }
2011
+ "propertyNames": {
2012
+ "type": "string"
3020
2013
  },
3021
- "additionalProperties": false
2014
+ "additionalProperties": {}
3022
2015
  },
3023
- "timeoutMs": { "type": "integer", "minimum": 100, "maximum": 6e4 }
2016
+ "tab": {
2017
+ "type": "string"
2018
+ }
3024
2019
  },
3025
- "required": ["actions"],
2020
+ "required": [
2021
+ "action"
2022
+ ],
3026
2023
  "additionalProperties": false
3027
2024
  }
3028
2025
  },
3029
- {
3030
- "name": "browser_network",
3031
- "description": "Network, downloads, and page environment. Recording ladder: action=start \u2192 do an act/navigate \u2192 action=wait or stop (lean manifest) \u2192 action=body({requestId}) for one response. action=download fetches a URL through the session; action=downloads lists page-triggered captures. action=cookies|mock|emulate need CDP experimental settings. emulate with only preset/width/height/reset resizes without CDP. Prefer snapshot/query for page content.",
3032
- "inputSchema": {
3033
- "type": "object",
3034
- "properties": {
3035
- "action": {
3036
- "type": "string",
3037
- "enum": ["start", "stop", "wait", "body", "download", "downloads", "cookies", "mock", "emulate"]
3038
- },
3039
- "tab": { "type": "string" },
3040
- "description": { "type": "string" },
3041
- "recordingId": { "type": "string" },
3042
- "requestId": { "type": "string" },
3043
- "url": { "type": "string" }
3044
- },
3045
- "required": ["action"],
3046
- "additionalProperties": true
3047
- }
3048
- },
3049
- {
3050
- "name": "browser_action",
3051
- "description": "Saved semantic browser actions (dynamic catalog \u2014 list then do). action=list (optional domain; includeSteps to see the full definition). action=save creates or replaces a named flow (domain+name). action=do runs one saved action with input. This does not record prior browser calls. Use browser_act for one-off clicks/types.",
3052
- "inputSchema": {
3053
- "type": "object",
3054
- "properties": {
3055
- "action": { "type": "string", "enum": ["list", "save", "do"] },
3056
- "domain": { "type": "string" },
3057
- "name": { "type": "string" },
3058
- "input": { "type": "object", "additionalProperties": true }
3059
- },
3060
- "required": ["action"],
3061
- "additionalProperties": true
3062
- }
3063
- },
3064
2026
  {
3065
2027
  "name": "miniapp_list",
3066
2028
  "description": "List mini-apps authorized for this session and their tools. Omit appId for a compact catalog (tool names + one-line descriptions). Pass appId to inspect one app; includeSchema defaults true for that app's full tool definitions including inputSchema. Call this before miniapp_call when you do not know the tool names or parameters.",
@@ -3575,13 +2537,16 @@ If the tool returns an error containing "user_locked", the user has manually nam
3575
2537
  },
3576
2538
  {
3577
2539
  "name": "automation_apply",
3578
- "description": "Create or update a project automation. action=create needs name, prompt, schedule; agentConfig optional (defaults claude + bypassPermissions). action=update needs id plus any of name/prompt/enabled/schedule/agentConfig (toggle via enabled). Always set schedule.summary to a short natural-language phrase for the UI (user language). Always opens a user confirmation dialog; applies nothing without approval. Call automation_list first for ids. Delete with automation_delete.",
2540
+ "description": 'Create or update a project automation. create needs name, prompt, schedule; update needs id plus any field (pause via enabled=false). Call automation_list first for ids; remove with automation_delete. Always opens a user confirmation dialog and applies nothing without approval. For schedule and agentConfig shapes see read_manual({ domain: "product", topic: "automation" }).',
3579
2541
  "inputSchema": {
3580
2542
  "type": "object",
3581
2543
  "properties": {
3582
2544
  "action": {
3583
2545
  "type": "string",
3584
- "enum": ["create", "update"],
2546
+ "enum": [
2547
+ "create",
2548
+ "update"
2549
+ ],
3585
2550
  "description": "create a new automation, or update an existing one (including toggle enabled)."
3586
2551
  },
3587
2552
  "id": {
@@ -3602,11 +2567,14 @@ If the tool returns an error containing "user_locked", the user has manually nam
3602
2567
  },
3603
2568
  "schedule": {
3604
2569
  "type": "object",
3605
- "description": `When to run. one-time needs runAt (ISO). recurring needs cron (e.g. "0 9 * * *"). Always include summary: natural language for the confirm UI in the user's language (e.g. "Every weekday at 9:00 AM", "\u6BCF\u5929\u4E0A\u5348 9 \u70B9"). Machine fields still drive the scheduler.`,
2570
+ "description": 'When to run. one-time needs runAt (ISO); recurring needs cron. Always include summary. Preset fields and examples: read_manual({ domain: "product", topic: "automation" }).',
3606
2571
  "properties": {
3607
2572
  "type": {
3608
2573
  "type": "string",
3609
- "enum": ["one-time", "recurring"]
2574
+ "enum": [
2575
+ "one-time",
2576
+ "recurring"
2577
+ ]
3610
2578
  },
3611
2579
  "cron": {
3612
2580
  "type": "string",
@@ -3618,7 +2586,12 @@ If the tool returns an error containing "user_locked", the user has manually nam
3618
2586
  },
3619
2587
  "preset": {
3620
2588
  "type": "string",
3621
- "enum": ["hourly", "daily", "weekly", "custom"]
2589
+ "enum": [
2590
+ "hourly",
2591
+ "daily",
2592
+ "weekly",
2593
+ "custom"
2594
+ ]
3622
2595
  },
3623
2596
  "timeOfDay": {
3624
2597
  "type": "string",
@@ -3643,19 +2616,27 @@ If the tool returns an error containing "user_locked", the user has manually nam
3643
2616
  "type": "string",
3644
2617
  "minLength": 1,
3645
2618
  "maxLength": 200,
3646
- "description": `Natural-language schedule shown in the UI (list + confirm). Use the user's language. Examples: "Every weekday at 9:00 AM", "\u6BCF\u5929\u4E0A\u5348 9 \u70B9", "Once on May 1 at 3pm". Required for create.`
2619
+ "description": `Natural-language schedule shown in the list and confirm dialog, in the user's language (e.g. "Every weekday at 9:00 AM"). Required for create.`
3647
2620
  }
3648
2621
  },
3649
- "required": ["type", "summary"],
2622
+ "required": [
2623
+ "type",
2624
+ "summary"
2625
+ ],
3650
2626
  "additionalProperties": false
3651
2627
  },
3652
2628
  "agentConfig": {
3653
2629
  "type": "object",
3654
- "description": "Harness + model for the automation run. type is required (claude|codex|acp|opencode). Defaults on create: claude + bypassPermissions + sandbox off. Prefer unified fields: model, effort, permissionMode, sandboxMode, apiProviderId, acpAgentId.",
2630
+ "description": 'Harness for the run; only type is required. Create defaults to claude + bypassPermissions. Field-by-field: read_manual({ domain: "product", topic: "automation" }).',
3655
2631
  "properties": {
3656
2632
  "type": {
3657
2633
  "type": "string",
3658
- "enum": ["claude", "codex", "acp", "opencode"]
2634
+ "enum": [
2635
+ "claude",
2636
+ "codex",
2637
+ "acp",
2638
+ "opencode"
2639
+ ]
3659
2640
  },
3660
2641
  "agentName": {
3661
2642
  "type": "string",
@@ -3670,16 +2651,31 @@ If the tool returns an error containing "user_locked", the user has manually nam
3670
2651
  },
3671
2652
  "permissionMode": {
3672
2653
  "type": "string",
3673
- "enum": ["default", "acceptEdits", "bypassPermissions", "plan", "dontAsk", "auto", "agent"],
2654
+ "enum": [
2655
+ "default",
2656
+ "acceptEdits",
2657
+ "bypassPermissions",
2658
+ "plan",
2659
+ "dontAsk",
2660
+ "auto",
2661
+ "agent"
2662
+ ],
3674
2663
  "description": "Unified permission mode. Prefer bypassPermissions for unattended runs."
3675
2664
  },
3676
2665
  "sandboxMode": {
3677
2666
  "type": "string",
3678
- "enum": ["off", "on", "auto"],
2667
+ "enum": [
2668
+ "off",
2669
+ "on",
2670
+ "auto"
2671
+ ],
3679
2672
  "description": "Claude sandbox (ignored by other harnesses)."
3680
2673
  },
3681
2674
  "apiProviderId": {
3682
- "type": ["string", "null"],
2675
+ "type": [
2676
+ "string",
2677
+ "null"
2678
+ ],
3683
2679
  "description": "Optional third-party AI provider credential id (claude/codex)."
3684
2680
  },
3685
2681
  "acpAgentId": {
@@ -3688,20 +2684,37 @@ If the tool returns an error containing "user_locked", the user has manually nam
3688
2684
  },
3689
2685
  "reasoningEffort": {
3690
2686
  "type": "string",
3691
- "enum": ["minimal", "low", "medium", "high", "xhigh", "max", "ultra"],
2687
+ "enum": [
2688
+ "minimal",
2689
+ "low",
2690
+ "medium",
2691
+ "high",
2692
+ "xhigh",
2693
+ "max",
2694
+ "ultra"
2695
+ ],
3692
2696
  "description": "Codex legacy alias for effort."
3693
2697
  },
3694
2698
  "permissionPreset": {
3695
2699
  "type": "string",
3696
- "enum": ["read-only", "default", "auto-review", "full-access"],
2700
+ "enum": [
2701
+ "read-only",
2702
+ "default",
2703
+ "auto-review",
2704
+ "full-access"
2705
+ ],
3697
2706
  "description": "Codex legacy alias for permissionMode (full-access \u2248 bypassPermissions)."
3698
2707
  }
3699
2708
  },
3700
- "required": ["type"],
2709
+ "required": [
2710
+ "type"
2711
+ ],
3701
2712
  "additionalProperties": false
3702
2713
  }
3703
2714
  },
3704
- "required": ["action"],
2715
+ "required": [
2716
+ "action"
2717
+ ],
3705
2718
  "additionalProperties": false
3706
2719
  }
3707
2720
  },
@@ -3748,17 +2761,17 @@ If the tool returns an error containing "user_locked", the user has manually nam
3748
2761
  },
3749
2762
  {
3750
2763
  "name": "device_list",
3751
- "description": "Browse the devices this machine can offer, one tier at a time \u2014 a dev machine holds over a hundred simulators, so this never dumps them all. No arguments: what is running (attaching is instant; a cold boot costs ~20s), what this project used before, and which kinds exist. kind: that kind's models. model: that model's devices, one per runtime, with the ids. Prefer a running or recent device; ids only matter when you need a specific runtime, since device_request_control also takes a model name and picks its newest. Free and side-effect-free \u2014 it grants nothing and boots nothing.",
2764
+ "description": "Browse the devices this machine can offer, one tier at a time. No arguments: what is running, what this project used before, and which kinds exist. kind: its models. model: its devices, one per runtime, with ids. Prefer a running or recent one \u2014 attaching is instant, a cold boot costs ~20s. Free: it grants nothing and boots nothing.",
3752
2765
  "inputSchema": {
3753
2766
  "type": "object",
3754
2767
  "properties": {
3755
2768
  "kind": {
3756
- "type": "string",
3757
- "description": 'Narrow to one family: "iphone", "ipad", "watch", "tv", "vision". Returns its models.'
2769
+ "description": 'Narrow to one family: "iphone", "ipad", "watch", "tv", "vision". Returns its models.',
2770
+ "type": "string"
3758
2771
  },
3759
2772
  "model": {
3760
- "type": "string",
3761
- "description": 'A model name from the kind tier ("iPhone 17 Pro Max"). Returns one entry per runtime, with ids.'
2773
+ "description": 'A model name from the kind tier ("iPhone 17 Pro Max"). Returns one entry per runtime, with ids.',
2774
+ "type": "string"
3762
2775
  }
3763
2776
  },
3764
2777
  "additionalProperties": false
@@ -3766,14 +2779,19 @@ If the tool returns an error containing "user_locked", the user has manually nam
3766
2779
  },
3767
2780
  {
3768
2781
  "name": "device_request_control",
3769
- "description": "Ask the user to let this session control one specific device, and wait for their answer. Every other device_* tool needs that grant and fails with NO_DEVICE until this succeeds \u2014 call it first, not after a failure. Pick the device from device_list yourself; the user only approves or declines, and a decline carries their feedback (often naming a different device \u2014 read it before retrying). Returns it once bound and ready, booting it if it was not running; asking again for one this session already holds returns it without prompting. A session may hold several, and then every device_* call must name one with `device`. Install a build afterwards with `xcrun simctl install/launch`.",
2782
+ "description": 'Ask the user to let this session control one device, and wait for their answer. Every other device_* tool fails with NO_DEVICE until this succeeds \u2014 call it first, not after a failure. Pick the device from device_list yourself; a decline carries feedback that often names a different one. Returns it bound and booted. See read_manual({ domain: "product", topic: "devices" }).',
3770
2783
  "inputSchema": {
3771
2784
  "type": "object",
3772
2785
  "properties": {
3773
- "description": deviceDescriptionProperty,
2786
+ "description": {
2787
+ "type": "string",
2788
+ "minLength": 1,
2789
+ "maxLength": 160,
2790
+ "description": "Short explanation of this step for the user watching, in the conversation's language (e.g. 'Open the profile tab'). Shown in place of refs and coordinates."
2791
+ },
3774
2792
  "device": {
3775
2793
  "type": "string",
3776
- "description": 'The id from device_list. A device name ("iPhone 17 Pro Max") is matched loosely against the catalog as a fallback, but the id is what makes the approved device the one you meant.'
2794
+ "description": "The id from device_list. A name is matched loosely as a fallback, but the id is what makes the approved device the one you meant."
3777
2795
  }
3778
2796
  },
3779
2797
  "required": [
@@ -3785,13 +2803,29 @@ If the tool returns an error containing "user_locked", the user has manually nam
3785
2803
  },
3786
2804
  {
3787
2805
  "name": "device_snapshot",
3788
- "description": "Capture the screen and return a stateId later calls must quote. mode=semantic (default) returns the accessibility tree with @eN refs, labels, identifiers and bounds \u2014 prefer it: refs survive animation and rotation, coordinates do not. mode=visual saves a PNG and returns image.path (not pixels); Read it to look. fused returns both. Waits for animation to stop; settled=false means geometry is approximate. A region with no accessibility tree \u2014 a WebView, a canvas \u2014 has its text read from pixels and merged in, marked (ocr): tap those, never press. The reply says source=ocr or hybrid. Re-snapshot after anything that changes the screen \u2014 refs are positional and device_act rejects a stale stateId.",
2806
+ "description": 'Capture the screen and return a stateId later calls must quote. Waits for animation to stop. mode=semantic (default) returns the accessibility tree with @eN refs \u2014 prefer it: refs survive animation and rotation, coordinates do not. mode=visual saves a PNG and returns image.path (not pixels); Read it to look. fused returns both. Regions with no tree (WebView, canvas) are read from pixels and marked (ocr): tap those, never press. Re-snapshot after anything that changes the screen \u2014 refs are positional and device_act rejects a stale stateId. See read_manual({ domain: "product", topic: "devices" }).',
3789
2807
  "inputSchema": {
3790
2808
  "type": "object",
3791
2809
  "properties": {
3792
- "description": deviceDescriptionProperty,
3793
- "device": deviceTargetProperty,
3794
- "mode": { "description": "Default semantic", "type": "string", "enum": ["semantic", "visual", "fused"] },
2810
+ "description": {
2811
+ "type": "string",
2812
+ "minLength": 1,
2813
+ "maxLength": 160,
2814
+ "description": "Short explanation of this step for the user watching, in the conversation's language (e.g. 'Open the profile tab'). Shown in place of refs and coordinates."
2815
+ },
2816
+ "device": {
2817
+ "description": "Device id or name from device_list. Optional while this session controls exactly one; required once it holds more. Use device_request_control to be granted another.",
2818
+ "type": "string"
2819
+ },
2820
+ "mode": {
2821
+ "description": "Default semantic",
2822
+ "type": "string",
2823
+ "enum": [
2824
+ "semantic",
2825
+ "visual",
2826
+ "fused"
2827
+ ]
2828
+ },
3795
2829
  "maxNodes": {
3796
2830
  "description": "Ceiling on tree size. Default 500; truncated=true means the screen has more.",
3797
2831
  "type": "integer",
@@ -3799,54 +2833,295 @@ If the tool returns an error containing "user_locked", the user has manually nam
3799
2833
  "maximum": 2e3
3800
2834
  }
3801
2835
  },
3802
- "required": ["description"],
2836
+ "required": [
2837
+ "description"
2838
+ ],
3803
2839
  "additionalProperties": false
3804
2840
  }
3805
2841
  },
3806
2842
  {
3807
2843
  "name": "device_query",
3808
- "description": "Search or inspect an existing snapshot without re-capturing the device. Use this instead of taking another snapshot when you only need to find an element or read its details \u2014 it costs no device round trip and cannot race an animation. op=search matches text against labels, values and identifiers. op=inspect returns one element and its children.",
2844
+ "description": "Search or inspect an existing snapshot without re-capturing the device. Prefer it over another snapshot when you only need to find an element or read its details: no device round trip, and it cannot race an animation. op=search matches labels, values and identifiers; op=inspect returns one element and its children.",
3809
2845
  "inputSchema": {
3810
2846
  "type": "object",
3811
2847
  "properties": {
3812
- "description": deviceDescriptionProperty,
3813
- "device": deviceTargetProperty,
3814
- "stateId": { "type": "string", "description": "From a prior device_snapshot." },
3815
- "op": { "type": "string", "enum": ["search", "inspect"] },
3816
- "text": { "description": "For search.", "type": "string" },
3817
- "ref": { "description": 'For inspect, e.g. "@e12".', "type": "string" }
2848
+ "description": {
2849
+ "type": "string",
2850
+ "minLength": 1,
2851
+ "maxLength": 160,
2852
+ "description": "Short explanation of this step for the user watching, in the conversation's language (e.g. 'Open the profile tab'). Shown in place of refs and coordinates."
2853
+ },
2854
+ "device": {
2855
+ "description": "Device id or name from device_list. Optional while this session controls exactly one; required once it holds more. Use device_request_control to be granted another.",
2856
+ "type": "string"
2857
+ },
2858
+ "stateId": {
2859
+ "type": "string",
2860
+ "description": "From a prior device_snapshot."
2861
+ },
2862
+ "op": {
2863
+ "type": "string",
2864
+ "enum": [
2865
+ "search",
2866
+ "inspect"
2867
+ ]
2868
+ },
2869
+ "text": {
2870
+ "description": "For search.",
2871
+ "type": "string"
2872
+ },
2873
+ "ref": {
2874
+ "description": 'For inspect, e.g. "@e12".',
2875
+ "type": "string"
2876
+ }
3818
2877
  },
3819
- "required": ["description", "stateId", "op"],
2878
+ "required": [
2879
+ "description",
2880
+ "stateId",
2881
+ "op"
2882
+ ],
3820
2883
  "additionalProperties": false
3821
2884
  }
3822
2885
  },
3823
2886
  {
3824
2887
  "name": "device_act",
3825
- "description": "Run 1-10 touch actions against a snapshot, then re-observe to judge if they worked. Actions: tap, doubleTap, longPress, swipe(direction|toX/toY), pinch(scale), press(ref), type, key, rotate, keyboard. Prefer refs; press uses accessibility and is resilient to animation (use tap for source=ocr). Raw x/y is a last resort. The batch and stale stateId are validated before side effects. rotate must be last; re-snapshot afterwards. Set recording=true to save a short video containing only this action transaction. Returns worked|didnt|unknown. Pass expect to define and wait for success.",
2888
+ "description": 'Run 1-10 touch actions against a snapshot, then re-observe to judge if they worked. Prefer refs; press survives animation, but use tap for source=ocr and raw x/y only as a last resort. The batch and a stale stateId are validated before any side effect. rotate must be last, then re-snapshot. Returns worked|didnt|unknown; pass expect to define success. See read_manual({ domain: "product", topic: "devices" }).',
3826
2889
  "inputSchema": {
3827
2890
  "type": "object",
3828
2891
  "properties": {
3829
- "description": deviceDescriptionProperty,
3830
- "device": deviceTargetProperty,
3831
- "stateId": { "type": "string" },
3832
- "actions": { "minItems": 1, "maxItems": 10, "type": "array", "items": deviceActionSchema },
3833
- "expect": { "description": "Postcondition checked after the actions run.", ...deviceConditionSchema },
3834
- "timeoutMs": { "description": "Maximum wait for expect before the action is judged. Default 5000.", "type": "integer", "minimum": 100, "maximum": 6e4 },
3835
- "recording": { "description": "Save a video of only this action transaction. Default false.", "type": "boolean" }
2892
+ "description": {
2893
+ "type": "string",
2894
+ "minLength": 1,
2895
+ "maxLength": 160,
2896
+ "description": "Short explanation of this step for the user watching, in the conversation's language (e.g. 'Open the profile tab'). Shown in place of refs and coordinates."
2897
+ },
2898
+ "device": {
2899
+ "description": "Device id or name from device_list. Optional while this session controls exactly one; required once it holds more. Use device_request_control to be granted another.",
2900
+ "type": "string"
2901
+ },
2902
+ "stateId": {
2903
+ "type": "string"
2904
+ },
2905
+ "actions": {
2906
+ "minItems": 1,
2907
+ "maxItems": 10,
2908
+ "type": "array",
2909
+ "items": {
2910
+ "type": "object",
2911
+ "properties": {
2912
+ "type": {
2913
+ "type": "string",
2914
+ "enum": [
2915
+ "tap",
2916
+ "doubleTap",
2917
+ "longPress",
2918
+ "swipe",
2919
+ "pinch",
2920
+ "press",
2921
+ "type",
2922
+ "key",
2923
+ "rotate",
2924
+ "keyboard"
2925
+ ]
2926
+ },
2927
+ "ref": {
2928
+ "description": 'Element ref from the snapshot, e.g. "@e12". Preferred over coordinates.',
2929
+ "type": "string"
2930
+ },
2931
+ "x": {
2932
+ "description": "Horizontal position as a fraction of the screen (0-1). Only when no ref fits.",
2933
+ "type": "number",
2934
+ "minimum": 0,
2935
+ "maximum": 1
2936
+ },
2937
+ "y": {
2938
+ "description": "Vertical position as a fraction of the screen (0-1).",
2939
+ "type": "number",
2940
+ "minimum": 0,
2941
+ "maximum": 1
2942
+ },
2943
+ "direction": {
2944
+ "description": 'swipe: which way the finger travels. Content moves the opposite way, so "up" scrolls down a list.',
2945
+ "type": "string",
2946
+ "enum": [
2947
+ "up",
2948
+ "down",
2949
+ "left",
2950
+ "right"
2951
+ ]
2952
+ },
2953
+ "distance": {
2954
+ "description": "swipe: travel as a fraction of the screen. Default 0.6.",
2955
+ "type": "number",
2956
+ "minimum": 0.05,
2957
+ "maximum": 1
2958
+ },
2959
+ "toX": {
2960
+ "description": "swipe: explicit destination instead of direction.",
2961
+ "type": "number",
2962
+ "minimum": 0,
2963
+ "maximum": 1
2964
+ },
2965
+ "toY": {
2966
+ "type": "number",
2967
+ "minimum": 0,
2968
+ "maximum": 1
2969
+ },
2970
+ "scale": {
2971
+ "description": "pinch: final separation factor. Below 1 pinches in (zoom out), above 1 spreads.",
2972
+ "type": "number",
2973
+ "minimum": 0.1,
2974
+ "maximum": 5
2975
+ },
2976
+ "durationMs": {
2977
+ "description": "How long the gesture takes. Short swipes flick and coast; long ones drag and stop.",
2978
+ "type": "integer",
2979
+ "minimum": 16,
2980
+ "maximum": 1e4
2981
+ },
2982
+ "text": {
2983
+ "description": "type: text to enter. Anything the simulated keyboard cannot spell (Chinese, emoji) is pasted automatically.",
2984
+ "type": "string"
2985
+ },
2986
+ "button": {
2987
+ "description": "key: a hardware button. `back` and `app-switch` are Android-only and are refused elsewhere.",
2988
+ "type": "string",
2989
+ "enum": [
2990
+ "home",
2991
+ "lock",
2992
+ "side",
2993
+ "volume-up",
2994
+ "volume-down",
2995
+ "back",
2996
+ "app-switch"
2997
+ ]
2998
+ },
2999
+ "orientation": {
3000
+ "type": "string",
3001
+ "enum": [
3002
+ "portrait",
3003
+ "landscape-left",
3004
+ "portrait-upside-down",
3005
+ "landscape-right"
3006
+ ]
3007
+ },
3008
+ "connected": {
3009
+ "description": "keyboard: attach or detach the hardware keyboard. Detach it to make the on-screen keyboard appear.",
3010
+ "type": "boolean"
3011
+ }
3012
+ },
3013
+ "required": [
3014
+ "type"
3015
+ ],
3016
+ "additionalProperties": false
3017
+ }
3018
+ },
3019
+ "expect": {
3020
+ "description": "Postcondition checked after the actions run.",
3021
+ "type": "object",
3022
+ "properties": {
3023
+ "kind": {
3024
+ "type": "string",
3025
+ "enum": [
3026
+ "exists",
3027
+ "notExists",
3028
+ "textEquals",
3029
+ "textContains"
3030
+ ]
3031
+ },
3032
+ "ref": {
3033
+ "description": "Only valid within the snapshot it came from; prefer label or identifier when waiting.",
3034
+ "type": "string"
3035
+ },
3036
+ "label": {
3037
+ "description": "Visible name of the element.",
3038
+ "type": "string"
3039
+ },
3040
+ "identifier": {
3041
+ "description": "Developer-assigned id. Survives copy changes and translation \u2014 the most durable target.",
3042
+ "type": "string"
3043
+ },
3044
+ "text": {
3045
+ "description": "The string textEquals/textContains compares against. Required by those two kinds, and NOT a way to name an element \u2014 use label for that.",
3046
+ "type": "string",
3047
+ "minLength": 1
3048
+ }
3049
+ },
3050
+ "required": [
3051
+ "kind"
3052
+ ],
3053
+ "additionalProperties": false
3054
+ },
3055
+ "timeoutMs": {
3056
+ "description": "Maximum wait for expect before the action is judged. Default 5000.",
3057
+ "type": "integer",
3058
+ "minimum": 100,
3059
+ "maximum": 6e4
3060
+ },
3061
+ "recording": {
3062
+ "description": "Save a video of only this action transaction. Default false.",
3063
+ "type": "boolean"
3064
+ }
3836
3065
  },
3837
- "required": ["description", "stateId", "actions"],
3066
+ "required": [
3067
+ "description",
3068
+ "stateId",
3069
+ "actions"
3070
+ ],
3838
3071
  "additionalProperties": false
3839
3072
  }
3840
3073
  },
3841
3074
  {
3842
3075
  "name": "device_wait_for",
3843
- "description": "Wait until the screen satisfies a condition. Use this instead of snapshotting in a loop. Distinguishes preexisting (already true when asked) from verified (became true while waiting), so you can tell a real transition from a check that was never going to fail. Returns a fresh settled stateId and matching tree when successful. Target the element by label or identifier, not by ref: refs belong to one snapshot, and what you are waiting for usually does not exist yet. Every condition must name an element that way \u2014 text only says what to compare, it never selects.",
3076
+ "description": "Wait until the screen satisfies a condition, instead of snapshotting in a loop. Target the element by label or identifier, never by ref: refs belong to one snapshot and what you are waiting for usually does not exist yet \u2014 text only says what to compare, it never selects. Returns a fresh settled stateId and tree, and reports preexisting vs verified.",
3844
3077
  "inputSchema": {
3845
3078
  "type": "object",
3846
3079
  "properties": {
3847
- "description": deviceDescriptionProperty,
3848
- "device": deviceTargetProperty,
3849
- "condition": deviceConditionSchema,
3080
+ "description": {
3081
+ "type": "string",
3082
+ "minLength": 1,
3083
+ "maxLength": 160,
3084
+ "description": "Short explanation of this step for the user watching, in the conversation's language (e.g. 'Open the profile tab'). Shown in place of refs and coordinates."
3085
+ },
3086
+ "device": {
3087
+ "description": "Device id or name from device_list. Optional while this session controls exactly one; required once it holds more. Use device_request_control to be granted another.",
3088
+ "type": "string"
3089
+ },
3090
+ "condition": {
3091
+ "type": "object",
3092
+ "properties": {
3093
+ "kind": {
3094
+ "type": "string",
3095
+ "enum": [
3096
+ "exists",
3097
+ "notExists",
3098
+ "textEquals",
3099
+ "textContains"
3100
+ ]
3101
+ },
3102
+ "ref": {
3103
+ "description": "Only valid within the snapshot it came from; prefer label or identifier when waiting.",
3104
+ "type": "string"
3105
+ },
3106
+ "label": {
3107
+ "description": "Visible name of the element.",
3108
+ "type": "string"
3109
+ },
3110
+ "identifier": {
3111
+ "description": "Developer-assigned id. Survives copy changes and translation \u2014 the most durable target.",
3112
+ "type": "string"
3113
+ },
3114
+ "text": {
3115
+ "description": "The string textEquals/textContains compares against. Required by those two kinds, and NOT a way to name an element \u2014 use label for that.",
3116
+ "type": "string",
3117
+ "minLength": 1
3118
+ }
3119
+ },
3120
+ "required": [
3121
+ "kind"
3122
+ ],
3123
+ "additionalProperties": false
3124
+ },
3850
3125
  "timeoutMs": {
3851
3126
  "description": "Default 5000",
3852
3127
  "type": "integer",
@@ -3854,7 +3129,89 @@ If the tool returns an error containing "user_locked", the user has manually nam
3854
3129
  "maximum": 6e4
3855
3130
  }
3856
3131
  },
3857
- "required": ["description", "condition"],
3132
+ "required": [
3133
+ "description",
3134
+ "condition"
3135
+ ],
3136
+ "additionalProperties": false
3137
+ }
3138
+ },
3139
+ {
3140
+ "name": "browser_perf",
3141
+ "description": "Profile what a page (or SuperOne itself) burns CPU on: hotspot functions by self time, plus layout/style/heap deltas. Pass `action` to measure ONE interaction: the window opens and closes around it, and a ~1s ambient baseline is subtracted. Omit `action` to profile steady state for `sampleMs` (no baseline; the only mode for target='app'). The reply flags a truncated window or a non-script bottleneck when either applies.",
3142
+ "inputSchema": {
3143
+ "type": "object",
3144
+ "properties": {
3145
+ "tab": {
3146
+ "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
3147
+ "type": "string"
3148
+ },
3149
+ "description": {
3150
+ "description": "A short, human-friendly explanation of what this action accomplishes, phrased for the end user watching. Shown in the UI in place of the raw selector. Write it in the conversation's language.",
3151
+ "type": "string"
3152
+ },
3153
+ "target": {
3154
+ "description": "'tab' (default) = a browser view. 'app' = SuperOne's own renderer; sample mode only.",
3155
+ "type": "string",
3156
+ "enum": [
3157
+ "tab",
3158
+ "app"
3159
+ ]
3160
+ },
3161
+ "action": {
3162
+ "description": "Action mode: the action runs inside the profiling window. Omit for sample mode.",
3163
+ "type": "object",
3164
+ "properties": {
3165
+ "tool": {
3166
+ "type": "string",
3167
+ "description": "Browser primitive to measure, e.g. 'browser_click', 'browser_navigate', 'browser_scroll'."
3168
+ },
3169
+ "args": {
3170
+ "description": "Arguments for that tool, as you would pass them directly.",
3171
+ "type": "object",
3172
+ "propertyNames": {
3173
+ "type": "string"
3174
+ },
3175
+ "additionalProperties": {}
3176
+ }
3177
+ },
3178
+ "required": [
3179
+ "tool"
3180
+ ],
3181
+ "additionalProperties": false
3182
+ },
3183
+ "sampleMs": {
3184
+ "description": "Sample mode: how long to profile steady-state load. Default 3000.",
3185
+ "type": "integer",
3186
+ "minimum": -9007199254740991,
3187
+ "maximum": 9007199254740991
3188
+ },
3189
+ "until": {
3190
+ "description": "Action mode: explicit completion signal for an exact window.",
3191
+ "type": "object",
3192
+ "properties": {
3193
+ "urlContains": {
3194
+ "type": "string"
3195
+ },
3196
+ "selector": {
3197
+ "type": "string"
3198
+ }
3199
+ },
3200
+ "additionalProperties": false
3201
+ },
3202
+ "maxWaitMs": {
3203
+ "description": "Action mode: upper bound on the wait. Default 10000.",
3204
+ "type": "integer",
3205
+ "minimum": -9007199254740991,
3206
+ "maximum": 9007199254740991
3207
+ },
3208
+ "baselineMs": {
3209
+ "description": "Action mode: ambient-load sample length. Default 1000.",
3210
+ "type": "integer",
3211
+ "minimum": -9007199254740991,
3212
+ "maximum": 9007199254740991
3213
+ }
3214
+ },
3858
3215
  "additionalProperties": false
3859
3216
  }
3860
3217
  }
@@ -3911,7 +3268,8 @@ var init_host_action_browser_catalog = __esm({
3911
3268
  "browser_list_downloads",
3912
3269
  "browser_network_body",
3913
3270
  "browser_network_wait",
3914
- "browser_action_list"
3271
+ "browser_action_list",
3272
+ "browser_tools_list"
3915
3273
  ]);
3916
3274
  BROWSER_ACT_PREFIX = "browser_";
3917
3275
  COMPUTER_PREFIX = "computer_";
@@ -22427,7 +21785,10 @@ function isStaticHostOwnedSuperoneToolQualified(qualifiedName) {
22427
21785
  const bare = qualifiedName.slice(MCP_SUPERONE_TOOL_PREFIX.length);
22428
21786
  return isStaticHostOwnedSuperoneBareName(bare);
22429
21787
  }
22430
- var MCP_SUPERONE_TOOL_PREFIX, BROWSER_PRIMITIVE_TOOL_NAMES, BROWSER_ACTION_TOOL_NAMES, BROWSER_LEGACY_TOOL_NAMES, BROWSER_COMPACT_TOOL_NAMES, BROWSER_TOOL_NAMES, DEVICE_AGENT_TOOL_NAMES, BUILT_IN_SUPERONE_TOOL_NAMES, MOBILE_SHARE_FILE_TOOL_NAME, MINIAPP_LIST_BARE_NAME, MINIAPP_CALL_BARE_NAME, STATIC_HOST_OWNED_SUPERONE_QUALIFIED_TOOL_NAMES;
21788
+ function isNeverAutoAllowSuperoneBareName(bare) {
21789
+ return NEVER_AUTO_ALLOW_SUPERONE_BARE_NAMES.includes(bare);
21790
+ }
21791
+ var MCP_SUPERONE_TOOL_PREFIX, BROWSER_PRIMITIVE_TOOL_NAMES, BROWSER_ACTION_TOOL_NAMES, BROWSER_LEGACY_TOOL_NAMES, BROWSER_COMPACT_TOOL_NAMES, BROWSER_TOOL_NAMES, DEVICE_AGENT_TOOL_NAMES, BUILT_IN_SUPERONE_TOOL_NAMES, MOBILE_SHARE_FILE_TOOL_NAME, MINIAPP_LIST_BARE_NAME, MINIAPP_CALL_BARE_NAME, NEVER_AUTO_ALLOW_SUPERONE_BARE_NAMES, STATIC_HOST_OWNED_SUPERONE_QUALIFIED_TOOL_NAMES;
22431
21792
  var init_superone_host_owned_tools = __esm({
22432
21793
  "../../packages/shared/src/superone-host-owned-tools.ts"() {
22433
21794
  "use strict";
@@ -22460,7 +21821,9 @@ var init_superone_host_owned_tools = __esm({
22460
21821
  "browser_list_downloads",
22461
21822
  "browser_emulate",
22462
21823
  "browser_mock",
22463
- "browser_perf_measure"
21824
+ "browser_perf_measure",
21825
+ "browser_tools_list",
21826
+ "browser_tools_call"
22464
21827
  ];
22465
21828
  BROWSER_ACTION_TOOL_NAMES = [
22466
21829
  "browser_action_list",
@@ -22480,7 +21843,9 @@ var init_superone_host_owned_tools = __esm({
22480
21843
  "browser_evaluate",
22481
21844
  "browser_network",
22482
21845
  "browser_perf",
22483
- "browser_action"
21846
+ "browser_action",
21847
+ "browser_tools_list",
21848
+ "browser_tools_call"
22484
21849
  ];
22485
21850
  BROWSER_TOOL_NAMES = [
22486
21851
  ...BROWSER_LEGACY_TOOL_NAMES,
@@ -22532,12 +21897,13 @@ var init_superone_host_owned_tools = __esm({
22532
21897
  MOBILE_SHARE_FILE_TOOL_NAME = "mobile_share_file";
22533
21898
  MINIAPP_LIST_BARE_NAME = "miniapp_list";
22534
21899
  MINIAPP_CALL_BARE_NAME = "miniapp_call";
21900
+ NEVER_AUTO_ALLOW_SUPERONE_BARE_NAMES = ["browser_tools_call"];
22535
21901
  STATIC_HOST_OWNED_SUPERONE_QUALIFIED_TOOL_NAMES = [
22536
21902
  ...BUILT_IN_SUPERONE_TOOL_NAMES,
22537
21903
  MOBILE_SHARE_FILE_TOOL_NAME,
22538
21904
  MINIAPP_LIST_BARE_NAME,
22539
21905
  MINIAPP_CALL_BARE_NAME
22540
- ].map((bare) => `${MCP_SUPERONE_TOOL_PREFIX}${bare}`);
21906
+ ].filter((bare) => !isNeverAutoAllowSuperoneBareName(bare)).map((bare) => `${MCP_SUPERONE_TOOL_PREFIX}${bare}`);
22541
21907
  }
22542
21908
  });
22543
21909
 
@@ -24801,6 +24167,7 @@ function createNodeSessionEventMapper(ctx) {
24801
24167
  const toolName = asString2(payload.toolName) ?? "tool";
24802
24168
  const requestKind = asString2(payload.requestKind);
24803
24169
  const sessionAgentsConfirm = payload.sessionAgentsConfirm && typeof payload.sessionAgentsConfirm === "object" ? payload.sessionAgentsConfirm : void 0;
24170
+ const webmcpTrustConfirm = payload.webmcpTrustConfirm && typeof payload.webmcpTrustConfirm === "object" ? payload.webmcpTrustConfirm : void 0;
24804
24171
  const request = {
24805
24172
  requestId: interactionId,
24806
24173
  toolName,
@@ -24812,7 +24179,8 @@ function createNodeSessionEventMapper(ctx) {
24812
24179
  } : {},
24813
24180
  ...asString2(payload.serverName) ? { serverName: asString2(payload.serverName) } : {},
24814
24181
  ...asString2(payload.message) ? { message: asString2(payload.message) } : {},
24815
- ...sessionAgentsConfirm ? { sessionAgentsConfirm } : {}
24182
+ ...sessionAgentsConfirm ? { sessionAgentsConfirm } : {},
24183
+ ...webmcpTrustConfirm ? { webmcpTrustConfirm } : {}
24816
24184
  };
24817
24185
  push({ type: "permission_request", request });
24818
24186
  break;
@@ -70861,8 +70229,8 @@ import { fileURLToPath } from "node:url";
70861
70229
  function resolveCliReleaseVersion() {
70862
70230
  const fromEnv = process.env.SUPERONE_CLI_VERSION?.trim();
70863
70231
  if (fromEnv) return fromEnv;
70864
- if ("0.57.5-alpha".trim()) {
70865
- return "0.57.5-alpha".trim();
70232
+ if ("0.59.0-alpha".trim()) {
70233
+ return "0.59.0-alpha".trim();
70866
70234
  }
70867
70235
  const fromDist = readDistManifestVersion();
70868
70236
  if (fromDist) return fromDist;
@@ -78082,7 +77450,7 @@ import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as r
78082
77450
  import { arch as osArch2, platform as osPlatform2 } from "node:os";
78083
77451
  import { join as join26, resolve as resolve7 } from "node:path";
78084
77452
  var OFFICIAL_CLAUDE_SDK_VERSION = "0.3.246";
78085
- var OFFICIAL_CODEX_NPM_VERSION = "0.149.0";
77453
+ var OFFICIAL_CODEX_NPM_VERSION = "0.150.1";
78086
77454
  var OFFICIAL_CODEX_PACKAGE = "@openai/codex";
78087
77455
  function codexPlatformPackageVersion(baseVersion = OFFICIAL_CODEX_NPM_VERSION) {
78088
77456
  const platform2 = process.platform;
@@ -78724,11 +78092,12 @@ function resolveManagedTarballBinary(id, installRoot) {
78724
78092
  return resolveCodexNativeUnderPrefix(installRoot) ?? resolveOfficialInstallBinaryInRoot("codex", installRoot);
78725
78093
  }
78726
78094
  function readRuntimeVersionFromRoot(id, installRoot) {
78095
+ let metadataVersion = null;
78727
78096
  try {
78728
78097
  const metaPath = join27(installRoot, "install-meta.json");
78729
78098
  if (existsSync31(metaPath)) {
78730
78099
  const raw = JSON.parse(readFileSync17(metaPath, "utf8"));
78731
- if (raw.runtimeVersion) return raw.runtimeVersion;
78100
+ metadataVersion = raw.runtimeVersion?.trim() || null;
78732
78101
  }
78733
78102
  } catch {
78734
78103
  }
@@ -78742,7 +78111,7 @@ function readRuntimeVersionFromRoot(id, installRoot) {
78742
78111
  }
78743
78112
  } catch {
78744
78113
  }
78745
- return null;
78114
+ return metadataVersion;
78746
78115
  }
78747
78116
  async function resolveArtifactPin(id, channel, opts, fetchJson) {
78748
78117
  if (opts.artifactPin !== void 0) return opts.artifactPin;
@@ -78810,16 +78179,24 @@ function createManagedTarballInstaller(opts = {}) {
78810
78179
  }
78811
78180
  const channel = resolveHarnessManifestChannel(opts.channel, opts.releaseVersion);
78812
78181
  const artifactPin = await resolveArtifactPin(id, channel, opts, fetchJson);
78182
+ const compatibleArtifactPin = artifactPin && pins.packages.some(
78183
+ (pkg) => pkg.name === artifactPin.npmName && pkg.version === artifactPin.npmVersion
78184
+ ) ? artifactPin : null;
78185
+ if (artifactPin && !compatibleArtifactPin) {
78186
+ log2?.warn?.(
78187
+ `[harness] ignoring stale ${id} artifact ${artifactPin.npmName}@${artifactPin.npmVersion}; requested ${pins.packages.map((pkg) => `${pkg.name}@${pkg.version}`).join(", ")}`
78188
+ );
78189
+ }
78813
78190
  let packageSpec = "";
78814
78191
  let source = "npm-tarball";
78815
78192
  mkdirSync19(versionDir, { recursive: true });
78816
78193
  for (const pkg of pins.packages) {
78817
- const npmName = artifactPin?.npmName ?? pkg.name;
78818
- const npmVersion = artifactPin?.npmVersion ?? pkg.version;
78194
+ const npmName = compatibleArtifactPin?.npmName ?? pkg.name;
78195
+ const npmVersion = compatibleArtifactPin?.npmVersion ?? pkg.version;
78819
78196
  packageSpec = `${npmName}@${npmVersion}`;
78820
78197
  const downloadKey = harnessArtifactDownloadKey({
78821
78198
  harnessId: id,
78822
- digestSha256: artifactPin?.digestSha256,
78199
+ digestSha256: compatibleArtifactPin?.digestSha256,
78823
78200
  npmName,
78824
78201
  npmVersion
78825
78202
  });
@@ -78830,7 +78207,7 @@ function createManagedTarballInstaller(opts = {}) {
78830
78207
  destPath: partialPath,
78831
78208
  npmName,
78832
78209
  npmVersion,
78833
- pin: artifactPin,
78210
+ pin: compatibleArtifactPin,
78834
78211
  npmOnly: opts.npmOnly === true,
78835
78212
  fetchJson,
78836
78213
  downloadToFile,
@@ -78862,7 +78239,7 @@ function createManagedTarballInstaller(opts = {}) {
78862
78239
  packageSpec,
78863
78240
  source,
78864
78241
  channel,
78865
- digestSha256: artifactPin?.digestSha256 ?? null,
78242
+ digestSha256: compatibleArtifactPin?.digestSha256 ?? null,
78866
78243
  installedAt: Date.now()
78867
78244
  },
78868
78245
  null,
@@ -78889,7 +78266,7 @@ function createManagedTarballInstaller(opts = {}) {
78889
78266
  packageSpec,
78890
78267
  installPrefix: versionDir,
78891
78268
  channel,
78892
- digestSha256: artifactPin?.digestSha256,
78269
+ digestSha256: compatibleArtifactPin?.digestSha256,
78893
78270
  runtimeVersion: pins.runtimeVersion
78894
78271
  }
78895
78272
  };