@super-one/cli 0.58.0-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 +856 -1539
  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": {
@@ -1313,452 +1210,6 @@ If the tool returns an error containing "user_locked", the user has manually nam
1313
1210
  "additionalProperties": false
1314
1211
  }
1315
1212
  },
1316
- {
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.",
1319
- "inputSchema": {
1320
- "type": "object",
1321
- "properties": {
1322
- "domain": {
1323
- "description": "Optional domain filter, e.g. github.com. Scheme, path, case, and a trailing dot are normalized away.",
1324
- "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
- }
1331
- },
1332
- "required": [
1333
- "includeSteps"
1334
- ],
1335
- "additionalProperties": false
1336
- }
1337
- },
1338
- {
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.',
1341
- "inputSchema": {
1342
- "type": "object",
1343
- "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."
1354
- },
1355
- "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."
1735
- },
1736
- "name": {
1737
- "type": "string",
1738
- "description": "Saved action name."
1739
- },
1740
- "input": {
1741
- "default": {},
1742
- "description": "Values for the action parameters.",
1743
- "type": "object",
1744
- "propertyNames": {
1745
- "type": "string"
1746
- },
1747
- "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
- }
1753
- },
1754
- "required": [
1755
- "domain",
1756
- "name",
1757
- "input"
1758
- ],
1759
- "additionalProperties": false
1760
- }
1761
- },
1762
1213
  {
1763
1214
  "name": "browser_tools_list",
1764
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.",
@@ -1788,8 +1239,8 @@ If the tool returns an error containing "user_locked", the user has manually nam
1788
1239
  "type": "string"
1789
1240
  },
1790
1241
  "name": {
1791
- "type": "string",
1792
- "description": "Tool name from browser_tools_list."
1242
+ "description": "Tool name from browser_tools_list. Required.",
1243
+ "type": "string"
1793
1244
  },
1794
1245
  "input": {
1795
1246
  "default": {},
@@ -1802,7 +1253,6 @@ If the tool returns an error containing "user_locked", the user has manually nam
1802
1253
  }
1803
1254
  },
1804
1255
  "required": [
1805
- "name",
1806
1256
  "input"
1807
1257
  ],
1808
1258
  "additionalProperties": false
@@ -1810,7 +1260,7 @@ If the tool returns an error containing "user_locked", the user has manually nam
1810
1260
  },
1811
1261
  {
1812
1262
  "name": "browser_snapshot",
1813
- "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.",
1814
1264
  "inputSchema": {
1815
1265
  "type": "object",
1816
1266
  "properties": {
@@ -1818,13 +1268,12 @@ If the tool returns an error containing "user_locked", the user has manually nam
1818
1268
  "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
1819
1269
  "type": "string"
1820
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
+ },
1821
1275
  "include": {
1822
- "default": [
1823
- "meta",
1824
- "elements",
1825
- "console"
1826
- ],
1827
- "description": "Which data sections to return. Default ['meta','elements','console'].",
1276
+ "description": "Which sections to return. Default ['meta','elements','console'].",
1828
1277
  "type": "array",
1829
1278
  "items": {
1830
1279
  "type": "string",
@@ -1833,48 +1282,42 @@ If the tool returns an error containing "user_locked", the user has manually nam
1833
1282
  "elements",
1834
1283
  "tree",
1835
1284
  "text",
1836
- "console"
1285
+ "console",
1286
+ "screenshot"
1837
1287
  ]
1838
1288
  }
1839
1289
  },
1840
1290
  "filter": {
1841
- "description": "Elements section only: case-insensitive substring; only return interactive elements whose name or role contains it.",
1842
1291
  "type": "string"
1843
1292
  },
1844
1293
  "max": {
1845
- "default": 40,
1846
- "description": "Elements section only: max interactive elements, ranked by viewport proximity. Default 40.",
1847
1294
  "type": "integer",
1848
1295
  "minimum": 1,
1849
1296
  "maximum": 200
1850
1297
  },
1851
1298
  "depth": {
1852
- "default": 12,
1853
- "description": "Tree section only: max nesting depth to descend. Default 12.",
1854
1299
  "type": "integer",
1855
1300
  "minimum": 1,
1856
1301
  "maximum": 30
1857
1302
  },
1858
1303
  "treeMax": {
1859
- "default": 150,
1860
- "description": "Tree section only: max nodes to emit (overload budget). When hit, the tree is cut and treeTruncated:true is returned. Default 150.",
1861
1304
  "type": "integer",
1862
1305
  "minimum": 1,
1863
1306
  "maximum": 500
1864
1307
  },
1865
1308
  "textMaxChars": {
1866
- "default": 4e3,
1867
- "description": "Text section only: truncate visible text to this many chars. Default 4000.",
1868
1309
  "type": "integer",
1869
1310
  "minimum": 0,
1870
1311
  "maximum": 2e4
1871
1312
  },
1313
+ "selector": {
1314
+ "description": "Element to screenshot when include contains screenshot.",
1315
+ "type": "string"
1316
+ },
1872
1317
  "console": {
1873
- "description": "Console section filtering. Only consulted when `include` contains 'console'.",
1874
1318
  "type": "object",
1875
1319
  "properties": {
1876
1320
  "level": {
1877
- "description": "Console levels to include. Default ['warning','error']. Pass all four for everything.",
1878
1321
  "type": "array",
1879
1322
  "items": {
1880
1323
  "type": "string",
@@ -1887,54 +1330,32 @@ If the tool returns an error containing "user_locked", the user has manually nam
1887
1330
  }
1888
1331
  },
1889
1332
  "grep": {
1890
- "description": "Only return console entries whose text matches this pattern (substring by default).",
1891
1333
  "type": "string"
1892
1334
  },
1893
1335
  "regex": {
1894
- "default": false,
1895
- "description": "Treat grep as a JS regular expression instead of a substring. Default false.",
1896
1336
  "type": "boolean"
1897
1337
  },
1898
1338
  "ignoreCase": {
1899
- "default": true,
1900
- "description": "Case-insensitive grep. Default true.",
1901
1339
  "type": "boolean"
1902
1340
  },
1903
1341
  "invert": {
1904
- "default": false,
1905
- "description": "Keep only entries that do NOT match grep (like grep -v). Default false.",
1906
1342
  "type": "boolean"
1907
1343
  },
1908
1344
  "max": {
1909
- "default": 50,
1910
- "description": "Return the most recent N matching entries. Default 50.",
1911
1345
  "type": "integer",
1912
1346
  "minimum": 1,
1913
1347
  "maximum": 200
1914
1348
  }
1915
1349
  },
1916
- "required": [
1917
- "regex",
1918
- "ignoreCase",
1919
- "invert",
1920
- "max"
1921
- ],
1922
1350
  "additionalProperties": false
1923
1351
  }
1924
1352
  },
1925
- "required": [
1926
- "include",
1927
- "max",
1928
- "depth",
1929
- "treeMax",
1930
- "textMaxChars"
1931
- ],
1932
1353
  "additionalProperties": false
1933
1354
  }
1934
1355
  },
1935
1356
  {
1936
1357
  "name": "browser_query",
1937
- "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).",
1938
1359
  "inputSchema": {
1939
1360
  "type": "object",
1940
1361
  "properties": {
@@ -1943,23 +1364,28 @@ If the tool returns an error containing "user_locked", the user has manually nam
1943
1364
  "type": "string"
1944
1365
  },
1945
1366
  "description": {
1946
- "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.",
1947
1368
  "type": "string"
1948
1369
  },
1370
+ "op": {
1371
+ "description": "Default search.",
1372
+ "type": "string",
1373
+ "enum": [
1374
+ "search",
1375
+ "inspect"
1376
+ ]
1377
+ },
1949
1378
  "role": {
1950
- "description": "Match ARIA role or tag name, e.g. 'button', 'textbox', 'link'.",
1951
1379
  "type": "string"
1952
1380
  },
1953
1381
  "text": {
1954
- "description": "Case-insensitive substring in the element's accessible name or text.",
1955
1382
  "type": "string"
1956
1383
  },
1957
1384
  "selector": {
1958
- "description": "CSS selector to match. Combine with role/text or use alone.",
1385
+ "description": "CSS selector. Required for inspect.",
1959
1386
  "type": "string"
1960
1387
  },
1961
1388
  "attributes": {
1962
- "description": "Attribute equals matchers, e.g. { type: 'submit' }.",
1963
1389
  "type": "object",
1964
1390
  "propertyNames": {
1965
1391
  "type": "string"
@@ -1969,63 +1395,14 @@ If the tool returns an error containing "user_locked", the user has manually nam
1969
1395
  }
1970
1396
  },
1971
1397
  "visible": {
1972
- "default": true,
1973
- "description": "Only return visible elements. Default true.",
1974
1398
  "type": "boolean"
1975
1399
  },
1976
1400
  "max": {
1977
- "default": 20,
1978
1401
  "type": "integer",
1979
1402
  "minimum": 1,
1980
1403
  "maximum": 100
1981
1404
  },
1982
1405
  "fields": {
1983
- "description": "Extra per-match fields beyond the lean reference. Omit for the cheapest result.",
1984
- "type": "array",
1985
- "items": {
1986
- "type": "string",
1987
- "enum": [
1988
- "text",
1989
- "html",
1990
- "attributes",
1991
- "value",
1992
- "box"
1993
- ]
1994
- }
1995
- }
1996
- },
1997
- "required": [
1998
- "visible",
1999
- "max"
2000
- ],
2001
- "additionalProperties": false
2002
- }
2003
- },
2004
- {
2005
- "name": "browser_inspect",
2006
- "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.',
2007
- "inputSchema": {
2008
- "type": "object",
2009
- "properties": {
2010
- "tab": {
2011
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2012
- "type": "string"
2013
- },
2014
- "description": {
2015
- "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.",
2016
- "type": "string"
2017
- },
2018
- "selector": {
2019
- "type": "string",
2020
- "description": "CSS selector of the element to inspect."
2021
- },
2022
- "fields": {
2023
- "default": [
2024
- "text",
2025
- "attributes",
2026
- "box"
2027
- ],
2028
- "description": "Which detail fields to return.",
2029
1406
  "type": "array",
2030
1407
  "items": {
2031
1408
  "type": "string",
@@ -2041,24 +1418,17 @@ If the tool returns an error containing "user_locked", the user has manually nam
2041
1418
  }
2042
1419
  },
2043
1420
  "maxChars": {
2044
- "default": 4e3,
2045
- "description": "Truncate text/html to this many characters.",
2046
1421
  "type": "integer",
2047
1422
  "minimum": 0,
2048
1423
  "maximum": 2e4
2049
1424
  }
2050
1425
  },
2051
- "required": [
2052
- "selector",
2053
- "fields",
2054
- "maxChars"
2055
- ],
2056
1426
  "additionalProperties": false
2057
1427
  }
2058
1428
  },
2059
1429
  {
2060
- "name": "browser_screenshot",
2061
- "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.",
2062
1432
  "inputSchema": {
2063
1433
  "type": "object",
2064
1434
  "properties": {
@@ -2067,67 +1437,38 @@ If the tool returns an error containing "user_locked", the user has manually nam
2067
1437
  "type": "string"
2068
1438
  },
2069
1439
  "description": {
2070
- "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.",
2071
1441
  "type": "string"
2072
1442
  },
2073
1443
  "selector": {
2074
- "description": "CSS selector to screenshot just that element. Omit for the visible viewport.",
2075
- "type": "string"
2076
- }
2077
- },
2078
- "additionalProperties": false
2079
- }
2080
- },
2081
- {
2082
- "name": "browser_click",
2083
- "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.",
2084
- "inputSchema": {
2085
- "type": "object",
2086
- "properties": {
2087
- "tab": {
2088
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2089
- "type": "string"
2090
- },
2091
- "description": {
2092
- "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.",
2093
1445
  "type": "string"
2094
1446
  },
2095
- "selector": {
2096
- "description": "CSS selector of the element to click.",
1447
+ "selectorGone": {
1448
+ "description": "CSS selector that must be absent or hidden.",
2097
1449
  "type": "string"
2098
1450
  },
2099
1451
  "text": {
2100
- "description": "Click the first visible element whose accessible name or text contains this substring.",
1452
+ "description": "Substring that must appear in visible document text.",
2101
1453
  "type": "string"
2102
1454
  },
2103
- "x": {
2104
- "description": "Viewport X coordinate in CSS pixels. Must be paired with y.",
2105
- "type": "number"
2106
- },
2107
- "y": {
2108
- "description": "Viewport Y coordinate in CSS pixels. Must be paired with x.",
2109
- "type": "number"
1455
+ "urlIncludes": {
1456
+ "description": "Substring that must appear in the current URL.",
1457
+ "type": "string"
2110
1458
  },
2111
- "engine": {
2112
- "default": "auto",
2113
- "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.",
2114
- "type": "string",
2115
- "enum": [
2116
- "auto",
2117
- "cdp",
2118
- "synthetic"
2119
- ]
1459
+ "timeoutMs": {
1460
+ "description": "Maximum wait in milliseconds. Default 15000, max 60000.",
1461
+ "type": "integer",
1462
+ "minimum": 100,
1463
+ "maximum": 6e4
2120
1464
  }
2121
1465
  },
2122
- "required": [
2123
- "engine"
2124
- ],
2125
1466
  "additionalProperties": false
2126
1467
  }
2127
1468
  },
2128
1469
  {
2129
- "name": "browser_hover",
2130
- "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 }.",
2131
1472
  "inputSchema": {
2132
1473
  "type": "object",
2133
1474
  "properties": {
@@ -2136,113 +1477,60 @@ If the tool returns an error containing "user_locked", the user has manually nam
2136
1477
  "type": "string"
2137
1478
  },
2138
1479
  "description": {
2139
- "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.",
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.",
2140
1481
  "type": "string"
2141
1482
  },
2142
- "selector": {
2143
- "description": "CSS selector of the element to hover.",
2144
- "type": "string"
2145
- },
2146
- "text": {
2147
- "description": "Hover the first visible element whose accessible name or text contains this substring.",
2148
- "type": "string"
2149
- },
2150
- "x": {
2151
- "description": "Viewport X coordinate in CSS pixels. Must be paired with y.",
2152
- "type": "number"
2153
- },
2154
- "y": {
2155
- "description": "Viewport Y coordinate in CSS pixels. Must be paired with x.",
2156
- "type": "number"
2157
- },
2158
- "engine": {
2159
- "default": "auto",
2160
- "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": {
2161
1484
  "type": "string",
2162
- "enum": [
2163
- "auto",
2164
- "cdp",
2165
- "synthetic"
2166
- ]
1485
+ "minLength": 1,
1486
+ "maxLength": 64e3,
1487
+ "description": "JavaScript expression to evaluate in the page."
2167
1488
  }
2168
1489
  },
2169
1490
  "required": [
2170
- "engine"
1491
+ "expression"
2171
1492
  ],
2172
1493
  "additionalProperties": false
2173
1494
  }
2174
1495
  },
2175
1496
  {
2176
- "name": "browser_type",
2177
- "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).",
2178
1499
  "inputSchema": {
2179
1500
  "type": "object",
2180
1501
  "properties": {
2181
- "tab": {
2182
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2183
- "type": "string"
2184
- },
2185
1502
  "description": {
2186
- "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.",
2187
1504
  "type": "string"
2188
1505
  },
2189
- "text": {
2190
- "type": "string",
2191
- "description": "Literal text to insert."
2192
- },
2193
- "selector": {
2194
- "description": "CSS selector of the input. Omit to type into the focused element.",
2195
- "type": "string"
2196
- },
2197
- "clear": {
2198
- "default": false,
2199
- "description": "Clear the existing value before typing. Default false.",
2200
- "type": "boolean"
2201
- },
2202
- "engine": {
2203
- "default": "synthetic",
2204
- "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.",
2205
1508
  "type": "string",
2206
1509
  "enum": [
2207
- "synthetic",
2208
- "cdp"
1510
+ "list",
1511
+ "open",
1512
+ "navigate",
1513
+ "back",
1514
+ "forward",
1515
+ "reload"
2209
1516
  ]
2210
- }
2211
- },
2212
- "required": [
2213
- "text",
2214
- "clear",
2215
- "engine"
2216
- ],
2217
- "additionalProperties": false
2218
- }
2219
- },
2220
- {
2221
- "name": "browser_navigate",
2222
- "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.",
2223
- "inputSchema": {
2224
- "type": "object",
2225
- "properties": {
2226
- "tab": {
2227
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2228
- "type": "string"
2229
1517
  },
2230
- "description": {
2231
- "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).",
2232
1520
  "type": "string"
2233
1521
  },
2234
1522
  "url": {
2235
- "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.",
2236
1524
  "type": "string"
2237
1525
  },
2238
1526
  "port": {
2239
- "description": "Local dev-server port on localhost.",
1527
+ "description": "Localhost port for navigate.",
2240
1528
  "type": "integer",
2241
1529
  "minimum": 1,
2242
1530
  "maximum": 65535
2243
1531
  },
2244
1532
  "path": {
2245
- "description": "Optional path/query for the port form, e.g. '/settings'.",
1533
+ "description": "Optional path/query for the port form.",
2246
1534
  "type": "string"
2247
1535
  },
2248
1536
  "protocol": {
@@ -2253,17 +1541,7 @@ If the tool returns an error containing "user_locked", the user has manually nam
2253
1541
  "https"
2254
1542
  ]
2255
1543
  },
2256
- "action": {
2257
- "description": "Move through history instead of loading a URL.",
2258
- "type": "string",
2259
- "enum": [
2260
- "back",
2261
- "forward",
2262
- "reload"
2263
- ]
2264
- },
2265
1544
  "readiness": {
2266
- "default": "load",
2267
1545
  "description": "'load' waits for loading to stop (default); 'none' returns immediately.",
2268
1546
  "type": "string",
2269
1547
  "enum": [
@@ -2272,59 +1550,12 @@ If the tool returns an error containing "user_locked", the user has manually nam
2272
1550
  ]
2273
1551
  }
2274
1552
  },
2275
- "required": [
2276
- "readiness"
2277
- ],
2278
1553
  "additionalProperties": false
2279
1554
  }
2280
1555
  },
2281
1556
  {
2282
- "name": "browser_wait_for",
2283
- "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.",
2284
- "inputSchema": {
2285
- "type": "object",
2286
- "properties": {
2287
- "tab": {
2288
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2289
- "type": "string"
2290
- },
2291
- "description": {
2292
- "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.",
2293
- "type": "string"
2294
- },
2295
- "selector": {
2296
- "description": "CSS selector that must be present and visible.",
2297
- "type": "string"
2298
- },
2299
- "selectorGone": {
2300
- "description": "CSS selector that must be absent or hidden (e.g. a spinner that should disappear).",
2301
- "type": "string"
2302
- },
2303
- "text": {
2304
- "description": "Substring that must appear in visible document text.",
2305
- "type": "string"
2306
- },
2307
- "urlIncludes": {
2308
- "description": "Substring that must appear in the current URL.",
2309
- "type": "string"
2310
- },
2311
- "timeoutMs": {
2312
- "default": 15e3,
2313
- "description": "Maximum wait in milliseconds. Default 15000, max 60000.",
2314
- "type": "integer",
2315
- "minimum": 100,
2316
- "maximum": 6e4
2317
- }
2318
- },
2319
- "required": [
2320
- "timeoutMs"
2321
- ],
2322
- "additionalProperties": false
2323
- }
2324
- },
2325
- {
2326
- "name": "browser_press",
2327
- "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.",
2328
1559
  "inputSchema": {
2329
1560
  "type": "object",
2330
1561
  "properties": {
@@ -2333,284 +1564,189 @@ If the tool returns an error containing "user_locked", the user has manually nam
2333
1564
  "type": "string"
2334
1565
  },
2335
1566
  "description": {
2336
- "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.",
2337
1568
  "type": "string"
2338
1569
  },
2339
- "key": {
2340
- "type": "string",
2341
- "minLength": 1,
2342
- "description": "Key name such as Enter, Escape, Tab, ArrowDown, Backspace, or a single character."
2343
- },
2344
- "modifiers": {
2345
- "description": "Modifier keys held while pressing.",
1570
+ "actions": {
1571
+ "minItems": 1,
1572
+ "maxItems": 20,
2346
1573
  "type": "array",
2347
1574
  "items": {
2348
- "type": "string",
2349
- "enum": [
2350
- "Alt",
2351
- "Control",
2352
- "Meta",
2353
- "Shift"
2354
- ]
2355
- }
2356
- },
2357
- "selector": {
2358
- "description": "CSS selector of the key target. Omit to target the focused element.",
2359
- "type": "string"
2360
- },
2361
- "engine": {
2362
- "default": "synthetic",
2363
- "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.",
2364
- "type": "string",
2365
- "enum": [
2366
- "synthetic",
2367
- "cdp"
2368
- ]
2369
- }
2370
- },
2371
- "required": [
2372
- "key",
2373
- "engine"
2374
- ],
2375
- "additionalProperties": false
2376
- }
2377
- },
2378
- {
2379
- "name": "browser_scroll",
2380
- "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.",
2381
- "inputSchema": {
2382
- "type": "object",
2383
- "properties": {
2384
- "tab": {
2385
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2386
- "type": "string"
2387
- },
2388
- "description": {
2389
- "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.",
2390
- "type": "string"
2391
- },
2392
- "deltaX": {
2393
- "description": "Horizontal scroll in CSS pixels. Positive scrolls right.",
2394
- "type": "number"
2395
- },
2396
- "deltaY": {
2397
- "description": "Vertical scroll in CSS pixels. Positive scrolls down.",
2398
- "type": "number"
2399
- },
2400
- "selector": {
2401
- "description": "CSS selector of a scrollable container. Omit to scroll the viewport.",
2402
- "type": "string"
2403
- }
2404
- },
2405
- "additionalProperties": false
2406
- }
2407
- },
2408
- {
2409
- "name": "browser_drag",
2410
- "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.",
2411
- "inputSchema": {
2412
- "type": "object",
2413
- "properties": {
2414
- "tab": {
2415
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2416
- "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."
2417
1710
  },
2418
- "description": {
2419
- "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.",
2420
- "type": "string"
1711
+ "recording": {
1712
+ "description": "Save a video of only this action transaction. Default false.",
1713
+ "type": "boolean"
2421
1714
  },
2422
- "from": {
1715
+ "expect": {
1716
+ "description": "Explicit completion condition checked before recording stops.",
2423
1717
  "type": "object",
2424
1718
  "properties": {
2425
1719
  "selector": {
2426
- "description": "CSS selector of the element.",
2427
1720
  "type": "string"
2428
1721
  },
2429
- "text": {
2430
- "description": "Match the first visible element whose accessible name or text contains this substring.",
2431
- "type": "string"
2432
- },
2433
- "x": {
2434
- "description": "Viewport X coordinate in CSS pixels. Must be paired with y.",
2435
- "type": "number"
2436
- },
2437
- "y": {
2438
- "description": "Viewport Y coordinate in CSS pixels. Must be paired with x.",
2439
- "type": "number"
2440
- }
2441
- },
2442
- "additionalProperties": false,
2443
- "description": "Drag source. Provide exactly one targeting mode: selector, text, or x+y."
2444
- },
2445
- "to": {
2446
- "type": "object",
2447
- "properties": {
2448
- "selector": {
2449
- "description": "CSS selector of the element.",
1722
+ "selectorGone": {
2450
1723
  "type": "string"
2451
1724
  },
2452
1725
  "text": {
2453
- "description": "Match the first visible element whose accessible name or text contains this substring.",
2454
1726
  "type": "string"
2455
1727
  },
2456
- "x": {
2457
- "description": "Viewport X coordinate in CSS pixels. Must be paired with y.",
2458
- "type": "number"
2459
- },
2460
- "y": {
2461
- "description": "Viewport Y coordinate in CSS pixels. Must be paired with x.",
2462
- "type": "number"
1728
+ "urlIncludes": {
1729
+ "type": "string"
2463
1730
  }
2464
1731
  },
2465
- "additionalProperties": false,
2466
- "description": "Drag destination. Provide exactly one targeting mode: selector, text, or x+y."
2467
- },
2468
- "steps": {
2469
- "default": 10,
2470
- "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.",
2471
- "type": "integer",
2472
- "minimum": 1,
2473
- "maximum": 50
2474
- },
2475
- "holdMs": {
2476
- "default": 0,
2477
- "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.",
2478
- "type": "integer",
2479
- "minimum": 0,
2480
- "maximum": 1e4
2481
- },
2482
- "humanize": {
2483
- "default": false,
2484
- "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.",
2485
- "type": "boolean"
2486
- }
2487
- },
2488
- "required": [
2489
- "from",
2490
- "to",
2491
- "steps",
2492
- "holdMs",
2493
- "humanize"
2494
- ],
2495
- "additionalProperties": false
2496
- }
2497
- },
2498
- {
2499
- "name": "browser_select",
2500
- "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.",
2501
- "inputSchema": {
2502
- "type": "object",
2503
- "properties": {
2504
- "tab": {
2505
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2506
- "type": "string"
2507
- },
2508
- "description": {
2509
- "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.",
2510
- "type": "string"
2511
- },
2512
- "selector": {
2513
- "type": "string",
2514
- "description": "CSS selector of the <select>, checkbox, or radio."
2515
- },
2516
- "value": {
2517
- "description": "Option value to select (for <select>).",
2518
- "type": "string"
2519
- },
2520
- "label": {
2521
- "description": "Visible option text to select (for <select>); exact match preferred, falls back to substring.",
2522
- "type": "string"
1732
+ "additionalProperties": false
2523
1733
  },
2524
- "index": {
2525
- "description": "Zero-based option index (for <select>).",
1734
+ "timeoutMs": {
1735
+ "description": "Maximum wait for expect. Default 15000.",
2526
1736
  "type": "integer",
2527
- "minimum": 0,
2528
- "maximum": 9007199254740991
2529
- },
2530
- "checked": {
2531
- "description": "Desired checked state (for checkbox/radio). Defaults to true.",
2532
- "type": "boolean"
2533
- }
2534
- },
2535
- "required": [
2536
- "selector"
2537
- ],
2538
- "additionalProperties": false
2539
- }
2540
- },
2541
- {
2542
- "name": "browser_open",
2543
- "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.',
2544
- "inputSchema": {
2545
- "type": "object",
2546
- "properties": {
2547
- "description": {
2548
- "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.",
2549
- "type": "string"
2550
- },
2551
- "url": {
2552
- "description": "Initial URL. A schemeless host like 'example.com' gets https; loopback gets http. Defaults to a blank tab.",
2553
- "type": "string"
2554
- },
2555
- "tab": {
2556
- "description": "Existing browser tab id to reuse/focus instead of creating a new one.",
2557
- "type": "string"
2558
- },
2559
- "readiness": {
2560
- "default": "load",
2561
- "description": "'load' waits for loading to stop (default); 'none' returns as soon as the tab exists.",
2562
- "type": "string",
2563
- "enum": [
2564
- "load",
2565
- "none"
2566
- ]
2567
- }
2568
- },
2569
- "required": [
2570
- "readiness"
2571
- ],
2572
- "additionalProperties": false
2573
- }
2574
- },
2575
- {
2576
- "name": "browser_evaluate",
2577
- "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.",
2578
- "inputSchema": {
2579
- "type": "object",
2580
- "properties": {
2581
- "tab": {
2582
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2583
- "type": "string"
2584
- },
2585
- "description": {
2586
- "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.",
2587
- "type": "string"
2588
- },
2589
- "expression": {
2590
- "type": "string",
2591
- "minLength": 1,
2592
- "maxLength": 64e3,
2593
- "description": 'JavaScript expression, e.g. document.title or (() => ({ items: [...document.querySelectorAll("li")].map(li => li.textContent) }))().'
1737
+ "minimum": 100,
1738
+ "maximum": 6e4
2594
1739
  }
2595
1740
  },
2596
1741
  "required": [
2597
- "expression"
1742
+ "actions"
2598
1743
  ],
2599
1744
  "additionalProperties": false
2600
1745
  }
2601
1746
  },
2602
1747
  {
2603
- "name": "browser_tabs",
2604
- "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.',
2605
- "inputSchema": {
2606
- "type": "object",
2607
- "properties": {},
2608
- "additionalProperties": false
2609
- }
2610
- },
2611
- {
2612
- "name": "browser_resize",
2613
- "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.",
2614
1750
  "inputSchema": {
2615
1751
  "type": "object",
2616
1752
  "properties": {
@@ -2619,273 +1755,70 @@ If the tool returns an error containing "user_locked", the user has manually nam
2619
1755
  "type": "string"
2620
1756
  },
2621
1757
  "description": {
2622
- "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.",
2623
1759
  "type": "string"
2624
1760
  },
2625
- "preset": {
2626
- "description": "Named viewport size: mobile 375\xD7812, tablet 768\xD71024, desktop 1280\xD7800.",
1761
+ "action": {
2627
1762
  "type": "string",
2628
1763
  "enum": [
2629
- "mobile",
2630
- "tablet",
2631
- "desktop"
2632
- ]
2633
- },
2634
- "width": {
2635
- "description": "Explicit viewport width in CSS pixels (pair with height). Overrides preset.",
2636
- "type": "integer",
2637
- "minimum": 1,
2638
- "maximum": 1e4
2639
- },
2640
- "height": {
2641
- "description": "Explicit viewport height in CSS pixels (pair with width). Overrides preset.",
2642
- "type": "integer",
2643
- "minimum": 1,
2644
- "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."
2645
1775
  },
2646
- "reset": {
2647
- "description": "Restore the panel's natural size, clearing any resize.",
2648
- "type": "boolean"
2649
- }
2650
- },
2651
- "additionalProperties": false
2652
- }
2653
- },
2654
- {
2655
- "name": "browser_network_start",
2656
- "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.",
2657
- "inputSchema": {
2658
- "type": "object",
2659
- "properties": {
2660
- "tab": {
2661
- "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.",
2662
1778
  "type": "string"
2663
1779
  },
2664
- "description": {
2665
- "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.",
2666
1782
  "type": "string"
2667
1783
  },
2668
1784
  "match": {
2669
- "description": "Only record requests whose URL contains this substring. Omit to record everything (within resourceTypes).",
2670
1785
  "type": "string"
2671
1786
  },
2672
1787
  "resourceTypes": {
2673
- "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.",
2674
1788
  "type": "array",
2675
1789
  "items": {
2676
1790
  "type": "string"
2677
1791
  }
2678
1792
  },
2679
1793
  "captureBodies": {
2680
- "default": true,
2681
- "description": "Capture response bodies of matching requests. Default true. Set false to record only metadata + headers (cheaper).",
2682
1794
  "type": "boolean"
2683
1795
  },
2684
1796
  "max": {
2685
- "default": 200,
2686
- "description": "Max requests to record before ignoring further ones. Default 200.",
2687
1797
  "type": "integer",
2688
- "minimum": 1,
2689
- "maximum": 1e3
2690
- }
2691
- },
2692
- "required": [
2693
- "captureBodies",
2694
- "max"
2695
- ],
2696
- "additionalProperties": false
2697
- }
2698
- },
2699
- {
2700
- "name": "browser_network_stop",
2701
- "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).",
2702
- "inputSchema": {
2703
- "type": "object",
2704
- "properties": {
2705
- "recordingId": {
2706
- "type": "string",
2707
- "description": "The id returned by browser_network_start."
1798
+ "minimum": -9007199254740991,
1799
+ "maximum": 9007199254740991
2708
1800
  },
2709
1801
  "keep": {
2710
- "default": false,
2711
- "description": "Keep recording (peek) instead of stopping. Default false: stop and tear down capture.",
1802
+ "description": "stop only: peek without tearing down.",
2712
1803
  "type": "boolean"
2713
- }
2714
- },
2715
- "required": [
2716
- "recordingId",
2717
- "keep"
2718
- ],
2719
- "additionalProperties": false
2720
- }
2721
- },
2722
- {
2723
- "name": "browser_network_wait",
2724
- "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.",
2725
- "inputSchema": {
2726
- "type": "object",
2727
- "properties": {
2728
- "description": {
2729
- "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.",
2730
- "type": "string"
2731
- },
2732
- "recordingId": {
2733
- "type": "string",
2734
- "description": "The id returned by browser_network_start."
2735
1804
  },
2736
1805
  "url": {
2737
- "type": "string",
2738
- "minLength": 1,
2739
- "description": "Substring the request URL must contain."
1806
+ "description": "wait: substring to match. download: absolute URL. mock: url substring.",
1807
+ "type": "string"
2740
1808
  },
2741
1809
  "timeoutMs": {
2742
- "default": 15e3,
2743
- "description": "Maximum wait in milliseconds. Default 15000.",
2744
1810
  "type": "integer",
2745
- "minimum": 100,
2746
- "maximum": 6e4
2747
- }
2748
- },
2749
- "required": [
2750
- "recordingId",
2751
- "url",
2752
- "timeoutMs"
2753
- ],
2754
- "additionalProperties": false
2755
- }
2756
- },
2757
- {
2758
- "name": "browser_network_body",
2759
- "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).",
2760
- "inputSchema": {
2761
- "type": "object",
2762
- "properties": {
2763
- "description": {
2764
- "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.",
2765
- "type": "string"
2766
- },
2767
- "recordingId": {
2768
- "type": "string",
2769
- "description": "The id returned by browser_network_start."
2770
- },
2771
- "requestId": {
2772
- "type": "string",
2773
- "description": "The requestId of the entry (from the stop/wait manifest) whose detail to read."
2774
- }
2775
- },
2776
- "required": [
2777
- "recordingId",
2778
- "requestId"
2779
- ],
2780
- "additionalProperties": false
2781
- }
2782
- },
2783
- {
2784
- "name": "browser_cookies",
2785
- "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.",
2786
- "inputSchema": {
2787
- "type": "object",
2788
- "properties": {
2789
- "tab": {
2790
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2791
- "type": "string"
2792
- },
2793
- "description": {
2794
- "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.",
2795
- "type": "string"
2796
- },
2797
- "urls": {
2798
- "description": "Only return cookies that would be sent to these URLs. Omit for the current page.",
2799
- "type": "array",
2800
- "items": {
2801
- "type": "string"
2802
- }
2803
- }
2804
- },
2805
- "additionalProperties": false
2806
- }
2807
- },
2808
- {
2809
- "name": "browser_upload_file",
2810
- "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.",
2811
- "inputSchema": {
2812
- "type": "object",
2813
- "properties": {
2814
- "tab": {
2815
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2816
- "type": "string"
2817
- },
2818
- "description": {
2819
- "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.",
2820
- "type": "string"
2821
- },
2822
- "selector": {
2823
- "type": "string",
2824
- "description": "CSS selector of the file <input> element (input[type=file])."
2825
- },
2826
- "files": {
2827
- "minItems": 1,
2828
- "type": "array",
2829
- "items": {
2830
- "type": "string"
2831
- },
2832
- "description": "Absolute paths of the files to attach."
2833
- }
2834
- },
2835
- "required": [
2836
- "selector",
2837
- "files"
2838
- ],
2839
- "additionalProperties": false
2840
- }
2841
- },
2842
- {
2843
- "name": "browser_download",
2844
- "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.",
2845
- "inputSchema": {
2846
- "type": "object",
2847
- "properties": {
2848
- "description": {
2849
- "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.",
2850
- "type": "string"
2851
- },
2852
- "url": {
2853
- "type": "string",
2854
- "minLength": 1,
2855
- "description": "Absolute URL (or data: URL) of the file to download."
1811
+ "minimum": -9007199254740991,
1812
+ "maximum": 9007199254740991
2856
1813
  },
2857
1814
  "filename": {
2858
- "description": "Override the saved file name. Defaults to Content-Disposition or the URL path segment.",
2859
1815
  "type": "string"
2860
1816
  },
2861
- "timeoutMs": {
2862
- "default": 15e3,
2863
- "description": "How long to wait for a synchronous result before moving the job to the background. Default 15000.",
2864
- "type": "integer",
2865
- "minimum": 100,
2866
- "maximum": 12e4
2867
- }
2868
- },
2869
- "required": [
2870
- "url",
2871
- "timeoutMs"
2872
- ],
2873
- "additionalProperties": false
2874
- }
2875
- },
2876
- {
2877
- "name": "browser_list_downloads",
2878
- "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.",
2879
- "inputSchema": {
2880
- "type": "object",
2881
- "properties": {
2882
- "description": {
2883
- "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.",
2884
1819
  "type": "string"
2885
1820
  },
2886
1821
  "state": {
2887
- "default": "all",
2888
- "description": "Which captures to include. 'failed' = cancelled or interrupted. Default all.",
2889
1822
  "type": "string",
2890
1823
  "enum": [
2891
1824
  "all",
@@ -2895,67 +1828,71 @@ If the tool returns an error containing "user_locked", the user has manually nam
2895
1828
  ]
2896
1829
  },
2897
1830
  "wait": {
2898
- "default": false,
2899
- "description": "If true, wait for captures to settle (see timeoutMs). Default false (immediate snapshot).",
1831
+ "description": "downloads only: block until captures settle.",
2900
1832
  "type": "boolean"
2901
1833
  },
2902
- "timeoutMs": {
2903
- "default": 15e3,
2904
- "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": {
2905
1842
  "type": "integer",
2906
- "minimum": 0,
2907
- "maximum": 12e4
2908
- }
2909
- },
2910
- "required": [
2911
- "state",
2912
- "wait",
2913
- "timeoutMs"
2914
- ],
2915
- "additionalProperties": false
2916
- }
2917
- },
2918
- {
2919
- "name": "browser_emulate",
2920
- "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.",
2921
- "inputSchema": {
2922
- "type": "object",
2923
- "properties": {
2924
- "tab": {
2925
- "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": {
2926
1847
  "type": "string"
2927
1848
  },
2928
- "description": {
2929
- "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": {
2930
1850
  "type": "string"
2931
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
+ },
2932
1873
  "width": {
2933
- "description": "Viewport width in CSS pixels (pair with height).",
2934
1874
  "type": "integer",
2935
- "minimum": 1,
1875
+ "minimum": -9007199254740991,
2936
1876
  "maximum": 9007199254740991
2937
1877
  },
2938
1878
  "height": {
2939
- "description": "Viewport height in CSS pixels (pair with width).",
2940
1879
  "type": "integer",
2941
- "minimum": 1,
1880
+ "minimum": -9007199254740991,
2942
1881
  "maximum": 9007199254740991
2943
1882
  },
1883
+ "reset": {
1884
+ "type": "boolean"
1885
+ },
2944
1886
  "deviceScaleFactor": {
2945
- "description": "Device pixel ratio. 0 keeps the default.",
2946
- "type": "number",
2947
- "minimum": 0
1887
+ "type": "number"
2948
1888
  },
2949
1889
  "mobile": {
2950
- "description": "Emulate a mobile device (touch, mobile viewport).",
2951
1890
  "type": "boolean"
2952
1891
  },
2953
1892
  "userAgent": {
2954
- "description": "Override the User-Agent header.",
2955
1893
  "type": "string"
2956
1894
  },
2957
1895
  "colorScheme": {
2958
- "description": "Emulate prefers-color-scheme.",
2959
1896
  "type": "string",
2960
1897
  "enum": [
2961
1898
  "light",
@@ -2964,152 +1901,128 @@ If the tool returns an error containing "user_locked", the user has manually nam
2964
1901
  ]
2965
1902
  },
2966
1903
  "timezone": {
2967
- "description": "IANA timezone id, e.g. 'America/New_York'.",
2968
1904
  "type": "string"
2969
1905
  },
2970
1906
  "locale": {
2971
- "description": "Locale, e.g. 'en-US' or 'ja-JP'.",
2972
1907
  "type": "string"
2973
1908
  },
2974
1909
  "latitude": {
2975
- "description": "Geolocation latitude (pair with longitude).",
2976
1910
  "type": "number"
2977
1911
  },
2978
1912
  "longitude": {
2979
- "description": "Geolocation longitude (pair with latitude).",
2980
1913
  "type": "number"
2981
- },
2982
- "reset": {
2983
- "description": "Clear all emulation overrides.",
2984
- "type": "boolean"
2985
1914
  }
2986
1915
  },
1916
+ "required": [
1917
+ "action"
1918
+ ],
2987
1919
  "additionalProperties": false
2988
1920
  }
2989
1921
  },
2990
1922
  {
2991
- "name": "browser_mock",
2992
- "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.",
2993
1925
  "inputSchema": {
2994
1926
  "type": "object",
2995
1927
  "properties": {
2996
- "tab": {
2997
- "description": "Browser view id. Omit to target the focused browser view (errors if multiple are open).",
2998
- "type": "string"
1928
+ "action": {
1929
+ "type": "string",
1930
+ "enum": [
1931
+ "list",
1932
+ "save",
1933
+ "do"
1934
+ ],
1935
+ "description": "list / save / do."
2999
1936
  },
3000
- "description": {
3001
- "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.",
3002
- "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."
3003
1942
  },
3004
- "url": {
3005
- "description": "Substring; requests whose URL contains it are fulfilled with the mock. Required unless clear is set.",
1943
+ "name": {
3006
1944
  "type": "string"
3007
1945
  },
3008
- "status": {
3009
- "description": "HTTP status code to return (default 200).",
3010
- "type": "integer",
3011
- "minimum": 100,
3012
- "maximum": 599
3013
- },
3014
- "body": {
3015
- "description": "Response body to return (default empty).",
3016
- "type": "string"
1946
+ "includeSteps": {
1947
+ "type": "boolean"
3017
1948
  },
3018
- "contentType": {
3019
- "description": "Response Content-Type (default 'application/json').",
3020
- "type": "string"
1949
+ "description": {
1950
+ "type": "string",
1951
+ "minLength": 1,
1952
+ "maxLength": 1e3
3021
1953
  },
3022
- "headers": {
3023
- "description": "Extra response headers.",
3024
- "type": "object",
3025
- "propertyNames": {
3026
- "type": "string"
3027
- },
3028
- "additionalProperties": {
3029
- "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
3030
1994
  }
3031
1995
  },
3032
- "clear": {
3033
- "description": "Remove all mock rules for this tab and stop intercepting.",
3034
- "type": "boolean"
3035
- }
3036
- },
3037
- "additionalProperties": false
3038
- }
3039
- },
3040
- {
3041
- "name": "browser_act",
3042
- "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.",
3043
- "inputSchema": {
3044
- "type": "object",
3045
- "properties": {
3046
- "tab": { "type": "string" },
3047
- "description": { "type": "string" },
3048
- "actions": {
3049
- "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.',
3050
1998
  "minItems": 1,
3051
- "maxItems": 20,
1999
+ "maxItems": 50,
2000
+ "type": "array",
3052
2001
  "items": {
3053
2002
  "type": "object",
3054
- "properties": {
3055
- "type": { "type": "string", "enum": ["click", "hover", "type", "press", "scroll", "drag", "select", "upload"] }
2003
+ "propertyNames": {
2004
+ "type": "string"
3056
2005
  },
3057
- "required": ["type"],
3058
- "additionalProperties": true
2006
+ "additionalProperties": {}
3059
2007
  }
3060
2008
  },
3061
- "recording": { "type": "boolean", "description": "Save a video of only this action transaction. Default false." },
3062
- "expect": {
2009
+ "input": {
3063
2010
  "type": "object",
3064
- "properties": {
3065
- "selector": { "type": "string" },
3066
- "selectorGone": { "type": "string" },
3067
- "text": { "type": "string" },
3068
- "urlIncludes": { "type": "string" }
2011
+ "propertyNames": {
2012
+ "type": "string"
3069
2013
  },
3070
- "additionalProperties": false
2014
+ "additionalProperties": {}
3071
2015
  },
3072
- "timeoutMs": { "type": "integer", "minimum": 100, "maximum": 6e4 }
2016
+ "tab": {
2017
+ "type": "string"
2018
+ }
3073
2019
  },
3074
- "required": ["actions"],
2020
+ "required": [
2021
+ "action"
2022
+ ],
3075
2023
  "additionalProperties": false
3076
2024
  }
3077
2025
  },
3078
- {
3079
- "name": "browser_network",
3080
- "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.",
3081
- "inputSchema": {
3082
- "type": "object",
3083
- "properties": {
3084
- "action": {
3085
- "type": "string",
3086
- "enum": ["start", "stop", "wait", "body", "download", "downloads", "cookies", "mock", "emulate"]
3087
- },
3088
- "tab": { "type": "string" },
3089
- "description": { "type": "string" },
3090
- "recordingId": { "type": "string" },
3091
- "requestId": { "type": "string" },
3092
- "url": { "type": "string" }
3093
- },
3094
- "required": ["action"],
3095
- "additionalProperties": true
3096
- }
3097
- },
3098
- {
3099
- "name": "browser_action",
3100
- "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.",
3101
- "inputSchema": {
3102
- "type": "object",
3103
- "properties": {
3104
- "action": { "type": "string", "enum": ["list", "save", "do"] },
3105
- "domain": { "type": "string" },
3106
- "name": { "type": "string" },
3107
- "input": { "type": "object", "additionalProperties": true }
3108
- },
3109
- "required": ["action"],
3110
- "additionalProperties": true
3111
- }
3112
- },
3113
2026
  {
3114
2027
  "name": "miniapp_list",
3115
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.",
@@ -3624,13 +2537,16 @@ If the tool returns an error containing "user_locked", the user has manually nam
3624
2537
  },
3625
2538
  {
3626
2539
  "name": "automation_apply",
3627
- "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" }).',
3628
2541
  "inputSchema": {
3629
2542
  "type": "object",
3630
2543
  "properties": {
3631
2544
  "action": {
3632
2545
  "type": "string",
3633
- "enum": ["create", "update"],
2546
+ "enum": [
2547
+ "create",
2548
+ "update"
2549
+ ],
3634
2550
  "description": "create a new automation, or update an existing one (including toggle enabled)."
3635
2551
  },
3636
2552
  "id": {
@@ -3651,11 +2567,14 @@ If the tool returns an error containing "user_locked", the user has manually nam
3651
2567
  },
3652
2568
  "schedule": {
3653
2569
  "type": "object",
3654
- "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" }).',
3655
2571
  "properties": {
3656
2572
  "type": {
3657
2573
  "type": "string",
3658
- "enum": ["one-time", "recurring"]
2574
+ "enum": [
2575
+ "one-time",
2576
+ "recurring"
2577
+ ]
3659
2578
  },
3660
2579
  "cron": {
3661
2580
  "type": "string",
@@ -3667,7 +2586,12 @@ If the tool returns an error containing "user_locked", the user has manually nam
3667
2586
  },
3668
2587
  "preset": {
3669
2588
  "type": "string",
3670
- "enum": ["hourly", "daily", "weekly", "custom"]
2589
+ "enum": [
2590
+ "hourly",
2591
+ "daily",
2592
+ "weekly",
2593
+ "custom"
2594
+ ]
3671
2595
  },
3672
2596
  "timeOfDay": {
3673
2597
  "type": "string",
@@ -3692,19 +2616,27 @@ If the tool returns an error containing "user_locked", the user has manually nam
3692
2616
  "type": "string",
3693
2617
  "minLength": 1,
3694
2618
  "maxLength": 200,
3695
- "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.`
3696
2620
  }
3697
2621
  },
3698
- "required": ["type", "summary"],
2622
+ "required": [
2623
+ "type",
2624
+ "summary"
2625
+ ],
3699
2626
  "additionalProperties": false
3700
2627
  },
3701
2628
  "agentConfig": {
3702
2629
  "type": "object",
3703
- "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" }).',
3704
2631
  "properties": {
3705
2632
  "type": {
3706
2633
  "type": "string",
3707
- "enum": ["claude", "codex", "acp", "opencode"]
2634
+ "enum": [
2635
+ "claude",
2636
+ "codex",
2637
+ "acp",
2638
+ "opencode"
2639
+ ]
3708
2640
  },
3709
2641
  "agentName": {
3710
2642
  "type": "string",
@@ -3719,16 +2651,31 @@ If the tool returns an error containing "user_locked", the user has manually nam
3719
2651
  },
3720
2652
  "permissionMode": {
3721
2653
  "type": "string",
3722
- "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
+ ],
3723
2663
  "description": "Unified permission mode. Prefer bypassPermissions for unattended runs."
3724
2664
  },
3725
2665
  "sandboxMode": {
3726
2666
  "type": "string",
3727
- "enum": ["off", "on", "auto"],
2667
+ "enum": [
2668
+ "off",
2669
+ "on",
2670
+ "auto"
2671
+ ],
3728
2672
  "description": "Claude sandbox (ignored by other harnesses)."
3729
2673
  },
3730
2674
  "apiProviderId": {
3731
- "type": ["string", "null"],
2675
+ "type": [
2676
+ "string",
2677
+ "null"
2678
+ ],
3732
2679
  "description": "Optional third-party AI provider credential id (claude/codex)."
3733
2680
  },
3734
2681
  "acpAgentId": {
@@ -3737,20 +2684,37 @@ If the tool returns an error containing "user_locked", the user has manually nam
3737
2684
  },
3738
2685
  "reasoningEffort": {
3739
2686
  "type": "string",
3740
- "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
+ ],
3741
2696
  "description": "Codex legacy alias for effort."
3742
2697
  },
3743
2698
  "permissionPreset": {
3744
2699
  "type": "string",
3745
- "enum": ["read-only", "default", "auto-review", "full-access"],
2700
+ "enum": [
2701
+ "read-only",
2702
+ "default",
2703
+ "auto-review",
2704
+ "full-access"
2705
+ ],
3746
2706
  "description": "Codex legacy alias for permissionMode (full-access \u2248 bypassPermissions)."
3747
2707
  }
3748
2708
  },
3749
- "required": ["type"],
2709
+ "required": [
2710
+ "type"
2711
+ ],
3750
2712
  "additionalProperties": false
3751
2713
  }
3752
2714
  },
3753
- "required": ["action"],
2715
+ "required": [
2716
+ "action"
2717
+ ],
3754
2718
  "additionalProperties": false
3755
2719
  }
3756
2720
  },
@@ -3797,17 +2761,17 @@ If the tool returns an error containing "user_locked", the user has manually nam
3797
2761
  },
3798
2762
  {
3799
2763
  "name": "device_list",
3800
- "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.",
3801
2765
  "inputSchema": {
3802
2766
  "type": "object",
3803
2767
  "properties": {
3804
2768
  "kind": {
3805
- "type": "string",
3806
- "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"
3807
2771
  },
3808
2772
  "model": {
3809
- "type": "string",
3810
- "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"
3811
2775
  }
3812
2776
  },
3813
2777
  "additionalProperties": false
@@ -3815,14 +2779,19 @@ If the tool returns an error containing "user_locked", the user has manually nam
3815
2779
  },
3816
2780
  {
3817
2781
  "name": "device_request_control",
3818
- "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" }).',
3819
2783
  "inputSchema": {
3820
2784
  "type": "object",
3821
2785
  "properties": {
3822
- "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
+ },
3823
2792
  "device": {
3824
2793
  "type": "string",
3825
- "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."
3826
2795
  }
3827
2796
  },
3828
2797
  "required": [
@@ -3834,13 +2803,29 @@ If the tool returns an error containing "user_locked", the user has manually nam
3834
2803
  },
3835
2804
  {
3836
2805
  "name": "device_snapshot",
3837
- "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" }).',
3838
2807
  "inputSchema": {
3839
2808
  "type": "object",
3840
2809
  "properties": {
3841
- "description": deviceDescriptionProperty,
3842
- "device": deviceTargetProperty,
3843
- "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
+ },
3844
2829
  "maxNodes": {
3845
2830
  "description": "Ceiling on tree size. Default 500; truncated=true means the screen has more.",
3846
2831
  "type": "integer",
@@ -3848,54 +2833,295 @@ If the tool returns an error containing "user_locked", the user has manually nam
3848
2833
  "maximum": 2e3
3849
2834
  }
3850
2835
  },
3851
- "required": ["description"],
2836
+ "required": [
2837
+ "description"
2838
+ ],
3852
2839
  "additionalProperties": false
3853
2840
  }
3854
2841
  },
3855
2842
  {
3856
2843
  "name": "device_query",
3857
- "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.",
3858
2845
  "inputSchema": {
3859
2846
  "type": "object",
3860
2847
  "properties": {
3861
- "description": deviceDescriptionProperty,
3862
- "device": deviceTargetProperty,
3863
- "stateId": { "type": "string", "description": "From a prior device_snapshot." },
3864
- "op": { "type": "string", "enum": ["search", "inspect"] },
3865
- "text": { "description": "For search.", "type": "string" },
3866
- "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
+ }
3867
2877
  },
3868
- "required": ["description", "stateId", "op"],
2878
+ "required": [
2879
+ "description",
2880
+ "stateId",
2881
+ "op"
2882
+ ],
3869
2883
  "additionalProperties": false
3870
2884
  }
3871
2885
  },
3872
2886
  {
3873
2887
  "name": "device_act",
3874
- "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" }).',
3875
2889
  "inputSchema": {
3876
2890
  "type": "object",
3877
2891
  "properties": {
3878
- "description": deviceDescriptionProperty,
3879
- "device": deviceTargetProperty,
3880
- "stateId": { "type": "string" },
3881
- "actions": { "minItems": 1, "maxItems": 10, "type": "array", "items": deviceActionSchema },
3882
- "expect": { "description": "Postcondition checked after the actions run.", ...deviceConditionSchema },
3883
- "timeoutMs": { "description": "Maximum wait for expect before the action is judged. Default 5000.", "type": "integer", "minimum": 100, "maximum": 6e4 },
3884
- "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
+ }
3885
3065
  },
3886
- "required": ["description", "stateId", "actions"],
3066
+ "required": [
3067
+ "description",
3068
+ "stateId",
3069
+ "actions"
3070
+ ],
3887
3071
  "additionalProperties": false
3888
3072
  }
3889
3073
  },
3890
3074
  {
3891
3075
  "name": "device_wait_for",
3892
- "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.",
3893
3077
  "inputSchema": {
3894
3078
  "type": "object",
3895
3079
  "properties": {
3896
- "description": deviceDescriptionProperty,
3897
- "device": deviceTargetProperty,
3898
- "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
+ },
3899
3125
  "timeoutMs": {
3900
3126
  "description": "Default 5000",
3901
3127
  "type": "integer",
@@ -3903,7 +3129,89 @@ If the tool returns an error containing "user_locked", the user has manually nam
3903
3129
  "maximum": 6e4
3904
3130
  }
3905
3131
  },
3906
- "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
+ },
3907
3215
  "additionalProperties": false
3908
3216
  }
3909
3217
  }
@@ -70921,8 +70229,8 @@ import { fileURLToPath } from "node:url";
70921
70229
  function resolveCliReleaseVersion() {
70922
70230
  const fromEnv = process.env.SUPERONE_CLI_VERSION?.trim();
70923
70231
  if (fromEnv) return fromEnv;
70924
- if ("0.58.0-alpha".trim()) {
70925
- return "0.58.0-alpha".trim();
70232
+ if ("0.59.0-alpha".trim()) {
70233
+ return "0.59.0-alpha".trim();
70926
70234
  }
70927
70235
  const fromDist = readDistManifestVersion();
70928
70236
  if (fromDist) return fromDist;
@@ -78142,7 +77450,7 @@ import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as r
78142
77450
  import { arch as osArch2, platform as osPlatform2 } from "node:os";
78143
77451
  import { join as join26, resolve as resolve7 } from "node:path";
78144
77452
  var OFFICIAL_CLAUDE_SDK_VERSION = "0.3.246";
78145
- var OFFICIAL_CODEX_NPM_VERSION = "0.149.0";
77453
+ var OFFICIAL_CODEX_NPM_VERSION = "0.150.1";
78146
77454
  var OFFICIAL_CODEX_PACKAGE = "@openai/codex";
78147
77455
  function codexPlatformPackageVersion(baseVersion = OFFICIAL_CODEX_NPM_VERSION) {
78148
77456
  const platform2 = process.platform;
@@ -78784,11 +78092,12 @@ function resolveManagedTarballBinary(id, installRoot) {
78784
78092
  return resolveCodexNativeUnderPrefix(installRoot) ?? resolveOfficialInstallBinaryInRoot("codex", installRoot);
78785
78093
  }
78786
78094
  function readRuntimeVersionFromRoot(id, installRoot) {
78095
+ let metadataVersion = null;
78787
78096
  try {
78788
78097
  const metaPath = join27(installRoot, "install-meta.json");
78789
78098
  if (existsSync31(metaPath)) {
78790
78099
  const raw = JSON.parse(readFileSync17(metaPath, "utf8"));
78791
- if (raw.runtimeVersion) return raw.runtimeVersion;
78100
+ metadataVersion = raw.runtimeVersion?.trim() || null;
78792
78101
  }
78793
78102
  } catch {
78794
78103
  }
@@ -78802,7 +78111,7 @@ function readRuntimeVersionFromRoot(id, installRoot) {
78802
78111
  }
78803
78112
  } catch {
78804
78113
  }
78805
- return null;
78114
+ return metadataVersion;
78806
78115
  }
78807
78116
  async function resolveArtifactPin(id, channel, opts, fetchJson) {
78808
78117
  if (opts.artifactPin !== void 0) return opts.artifactPin;
@@ -78870,16 +78179,24 @@ function createManagedTarballInstaller(opts = {}) {
78870
78179
  }
78871
78180
  const channel = resolveHarnessManifestChannel(opts.channel, opts.releaseVersion);
78872
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
+ }
78873
78190
  let packageSpec = "";
78874
78191
  let source = "npm-tarball";
78875
78192
  mkdirSync19(versionDir, { recursive: true });
78876
78193
  for (const pkg of pins.packages) {
78877
- const npmName = artifactPin?.npmName ?? pkg.name;
78878
- const npmVersion = artifactPin?.npmVersion ?? pkg.version;
78194
+ const npmName = compatibleArtifactPin?.npmName ?? pkg.name;
78195
+ const npmVersion = compatibleArtifactPin?.npmVersion ?? pkg.version;
78879
78196
  packageSpec = `${npmName}@${npmVersion}`;
78880
78197
  const downloadKey = harnessArtifactDownloadKey({
78881
78198
  harnessId: id,
78882
- digestSha256: artifactPin?.digestSha256,
78199
+ digestSha256: compatibleArtifactPin?.digestSha256,
78883
78200
  npmName,
78884
78201
  npmVersion
78885
78202
  });
@@ -78890,7 +78207,7 @@ function createManagedTarballInstaller(opts = {}) {
78890
78207
  destPath: partialPath,
78891
78208
  npmName,
78892
78209
  npmVersion,
78893
- pin: artifactPin,
78210
+ pin: compatibleArtifactPin,
78894
78211
  npmOnly: opts.npmOnly === true,
78895
78212
  fetchJson,
78896
78213
  downloadToFile,
@@ -78922,7 +78239,7 @@ function createManagedTarballInstaller(opts = {}) {
78922
78239
  packageSpec,
78923
78240
  source,
78924
78241
  channel,
78925
- digestSha256: artifactPin?.digestSha256 ?? null,
78242
+ digestSha256: compatibleArtifactPin?.digestSha256 ?? null,
78926
78243
  installedAt: Date.now()
78927
78244
  },
78928
78245
  null,
@@ -78949,7 +78266,7 @@ function createManagedTarballInstaller(opts = {}) {
78949
78266
  packageSpec,
78950
78267
  installPrefix: versionDir,
78951
78268
  channel,
78952
- digestSha256: artifactPin?.digestSha256,
78269
+ digestSha256: compatibleArtifactPin?.digestSha256,
78953
78270
  runtimeVersion: pins.runtimeVersion
78954
78271
  }
78955
78272
  };