@mearl/client 2.19.2 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/commands.js CHANGED
@@ -6,13 +6,79 @@ const PAGE_DIAGNOSTICS_PARAM = {
6
6
  name: 'diagnostics',
7
7
  type: 'object | boolean',
8
8
  description: '默认关闭;传 true 返回动作期间新增的 error logs/业务 requests,或传对象自定义通道与过滤',
9
+ details: [
10
+ 'logs: boolean | { level, limit, filter };true 默认采集 error 日志',
11
+ 'requests: boolean | { count, filter, source, includeBody, includeHeaders, maxBodySize, fields, keysOnly }',
12
+ 'events: boolean | { source, event_type, filter, limit, includeRaw };埋点需显式开启',
13
+ '各通道过滤字段同 get_logs / get_requests / get_events;observe=false 时仍返回诊断增量,但不等待 DOM/导航稳定',
14
+ ],
9
15
  };
10
16
  const PAGE_OBSERVE_PARAM = {
11
17
  name: 'observe',
12
18
  type: 'object | false',
13
19
  description: '默认开启 DOM/导航观察;传 false 关闭,不影响显式请求的 diagnostics',
20
+ details: [
21
+ 'quietMs: number,DOM 变化后的稳定窗口,默认 100ms',
22
+ 'firstChangeTimeoutMs: number,无 DOM 变化时的观察窗口,默认 500ms',
23
+ 'timeoutMs: number,DOM 观察阶段最大时间,默认 3000ms',
24
+ 'navigationGraceMs: number,低信息量点击/按键的导航宽限,默认 1000ms;相关网络活动可延长宽限',
25
+ 'navigationTimeoutMs: number,导航就绪最大等待时间,默认 15000ms',
26
+ 'networkIdleMs: number,文档完成且相关请求归零后的静默时间,默认 500ms',
27
+ 'contentReadyAfterMs: number,结构稳定兜底保护期,默认 min(5000, navigationTimeoutMs / 2),并限制在导航超时前',
28
+ ],
14
29
  };
30
+ const PAGE_ACTION_RESULT = [
31
+ '默认返回 { action, observation };action.success 只表示动作成功,业务效果需结合 observation 和目标状态判断。',
32
+ 'observe=false 且未开启 diagnostics 时返回裸动作结果(如 { clicked: true }),没有 action/observation;开启 diagnostics 时返回 { action, diagnostics }。',
33
+ '包装结果中的 action.stage=precondition 表示未派发,省略 observation/diagnostics;dispatch-uncertain 表示可能已派发,先查看 action.attempt 与可用观察或最小快照核验,避免重复提交。失败以退出码 1 结束。',
34
+ 'observation.effects 返回通知、控件和焦点增量,可直接复用 node.ref/selector;changed=true 且 effects 为空不表示失败。',
35
+ 'fullSnapshotRecommended/snapshotReasons 提示是否补充快照;openedTabs 返回可继续操作的 tabId 和 ready。navigation 模式的 ready 表示新页面就绪。',
36
+ '显式开启的诊断通道在 diagnostics 中返回动作期间增量,与 observe 独立。',
37
+ ];
15
38
  export const COMMANDS = [
39
+ {
40
+ name: 'browser_control',
41
+ description: '把控制会话交给用户;用户在 Mearl 浏览器管理页交还后重新观察页面',
42
+ params: [
43
+ {
44
+ name: 'operation',
45
+ type: '"handoff" | "resume"',
46
+ required: true,
47
+ description: '交给用户操作;resume 仅在用户明确交还后使用',
48
+ },
49
+ { name: 'tabId', type: 'number', description: '可选的目标页面' },
50
+ { name: 'reason', type: 'string', description: '用户需要处理的事项' },
51
+ ],
52
+ notes: ['必须携带 --session;接管停止后续派发,已经发出的操作可能仍然生效。'],
53
+ },
54
+ {
55
+ name: 'page_download',
56
+ description: '先监听再点击,等待下载完成并创建浏览器文件产物',
57
+ outputFlag: true,
58
+ params: [
59
+ { name: 'tabId', type: 'number', required: true, description: '下载来源页面' },
60
+ {
61
+ name: 'trigger',
62
+ type: 'object',
63
+ required: true,
64
+ description: 'page_click 参数,不含 tabId',
65
+ },
66
+ {
67
+ name: 'url',
68
+ type: 'string',
69
+ description: '预期下载 URL;扩展无法通过 referrer 归属时需显式指定',
70
+ },
71
+ {
72
+ name: 'timeout',
73
+ type: 'number',
74
+ description: '下载等待毫秒,默认 30000,范围 1000–300000',
75
+ },
76
+ ],
77
+ notes: [
78
+ '--output 把文件分块保存到调用方机器;未指定时返回 artifactId,可供 page_upload 复用。',
79
+ '共享 CDP 浏览器保持原下载目录;Chrome 未返回文件路径时明确报错。超时不能直接重复点击。',
80
+ ],
81
+ },
16
82
  // ── API 调试 ──────────────────────────────────────────────────────────────
17
83
  {
18
84
  name: 'tab_checkpoint',
@@ -56,6 +122,13 @@ export const COMMANDS = [
56
122
  { name: 'fields', type: 'string[]', description: '从响应体提取指定字段路径,最多 100 个' },
57
123
  { name: 'keysOnly', type: 'boolean', description: '只返回数据结构,不返回叶子值' },
58
124
  ],
125
+ notes: [
126
+ '流式请求开始后即进入缓冲区;页面及 App 桥代发的 MTop SSE 都归入 mtop。无法归属当前页面 target 的 Service Worker 请求不在采集范围内。',
127
+ ],
128
+ result: [
129
+ 'nextCursor 用于同类查询续读,hasMore 表示还有数据,gap 表示缓冲区淘汰造成缺口;checkpoint cursor 可分别用于三类查询的初始边界。',
130
+ 'isPending 标记未完成请求;SSE 的 responseBody 保存按序到达的 event/data/timestamp/duration 分片。敏感请求头返回脱敏值。',
131
+ ],
59
132
  examples: [
60
133
  `get_requests --payload '{"tabId":12345,"count":5}'`,
61
134
  `get_requests --payload '{"tabId":12345,"source":"mtop","filter":"cart"}'`,
@@ -81,6 +154,9 @@ export const COMMANDS = [
81
154
  description: '只返回指定 tab checkpoint 或同类查询 cursor 之后的日志',
82
155
  },
83
156
  ],
157
+ result: [
158
+ 'nextCursor 用于同类查询续读,hasMore 表示还有数据,gap 表示缓冲区淘汰造成缺口;checkpoint cursor 可分别用于三类查询的初始边界。',
159
+ ],
84
160
  examples: [`get_logs --payload '{"tabId":12345,"limit":10,"level":"error"}'`],
85
161
  },
86
162
  {
@@ -109,6 +185,13 @@ export const COMMANDS = [
109
185
  description: '返回完整 URL、_raw 和 _context;默认 false',
110
186
  },
111
187
  ],
188
+ notes: [
189
+ 'tab_open 新页从首屏采集;既有页面首次查询才启用采集,需要刷新或重新触发埋点。同批事件不会被 limit 拆开。',
190
+ ],
191
+ result: [
192
+ 'nextCursor 用于同类查询续读,hasMore 表示还有数据,gap 表示缓冲区淘汰造成缺口;checkpoint cursor 可分别用于三类查询的初始边界。',
193
+ 'captureStatus 为 armed/active/inactive;空结果附 hint 时按提示刷新或触发。默认去除 tracking URL query 与 _raw/_context,includeRaw=true 时保留。',
194
+ ],
112
195
  examples: [
113
196
  `get_events --payload '{"tabId":12345,"source":"aplus","event_type":"CLK","limit":10}'`,
114
197
  `get_events --payload '{"tabId":12345,"filter":"order","includeRaw":true,"limit":1}'`,
@@ -149,6 +232,11 @@ export const COMMANDS = [
149
232
  description: '请求 query/body 字段子集匹配;$index 从 0 开始指定调用顺序',
150
233
  },
151
234
  ],
235
+ notes: [
236
+ '启用时至少提供 mockData 或非空 fields;非空 fields 优先。fields 每项 { path: string, value: any },path 支持点号和数组索引。',
237
+ '相同 apiName 的多条无条件 Mock 会覆盖;conditions 子集匹配 query/body(含 data 内层),不同条件可共存;$index 从 0 起控制调用顺序,不参与字段匹配。',
238
+ '大字段可用顶层 @<绝对路径> 文件引用或 --payload-file;文件展开后仍受 Native Messaging 单条消息大小限制。',
239
+ ],
152
240
  examples: [
153
241
  `set_mock --payload '{"tabId":12345,"apiName":"mtop.cart.query","mockData":{"ret":["SUCCESS::调用成功"]}}'`,
154
242
  `set_mock --payload-file ./mock-data.json`,
@@ -185,17 +273,26 @@ export const COMMANDS = [
185
273
  name: 'requestHeaders',
186
274
  type: 'array',
187
275
  description: 'modifyHeaders 动作的请求头修改列表',
276
+ details: [
277
+ '每项 { header: string, operation: "set" | "append" | "remove", value?: string };set/append 需 value',
278
+ ],
188
279
  },
189
280
  {
190
281
  name: 'responseHeaders',
191
282
  type: 'array',
192
283
  description: 'modifyHeaders 动作的响应头修改列表',
284
+ details: [
285
+ '每项 { header: string, operation: "set" | "append" | "remove", value?: string };set/append 需 value',
286
+ ],
193
287
  },
194
288
  { name: 'initiatorDomains', type: 'string', description: '发起方域名过滤' },
195
289
  { name: 'resourceTypes', type: 'string[]', description: '资源类型过滤' },
196
290
  { name: 'priority', type: 'number', description: '规则优先级' },
197
291
  { name: 'description', type: 'string', description: '规则说明' },
198
292
  ],
293
+ notes: [
294
+ '扩展模式规则持久化;CDP 仅支持会话级 modifyHeaders 请求头 set,不支持响应头、initiatorDomains 或其他动作。Provider 是否支持以其能力声明为准。',
295
+ ],
199
296
  examples: [
200
297
  `set_rule --payload '{"actionType":"block","filter":"^https://example\\\\.com/ads/.*"}'`,
201
298
  `set_rule --payload '{"ruleId":42,"enabled":false}'`,
@@ -225,6 +322,11 @@ export const COMMANDS = [
225
322
  name: 'files',
226
323
  type: 'SendRequestFile[]',
227
324
  description: 'multipart 文件,最多 20 个、总计不超过 40 MiB;Base64 文件总计不超过 7 MiB。每项传 fieldName 和绝对 filePath,或传 base64 + filename',
325
+ details: [
326
+ 'fieldName: string(必填);filePath: string 与 base64: string 二选一',
327
+ 'filename: string,base64 时必填,filePath 时默认文件 basename',
328
+ 'contentType: string(可选),默认按文件名推断 MIME,否则 application/octet-stream',
329
+ ],
228
330
  },
229
331
  { name: 'withCookies', type: 'boolean', description: '是否附加浏览器 Cookie,默认 true' },
230
332
  {
@@ -234,6 +336,14 @@ export const COMMANDS = [
234
336
  },
235
337
  { name: 'timeout', type: 'number', description: '超时毫秒数,默认 30000' },
236
338
  ],
339
+ notes: [
340
+ '仅用于非 BUC 请求;BUC 接口使用 mearl buc,不手工传 Token、DPoP 或 Ticket。',
341
+ 'body 不能与 formData/files 组合;multipart 不手工设置 Content-Type,由 Mearl 生成 boundary。',
342
+ 'filePath 属于 native-host 所在机器;无法引用远端路径时用 base64。BUC 上传的路径属于插件执行宿主。',
343
+ ],
344
+ result: [
345
+ '返回 status、statusText、headers、body、bodyType、attachedCookieCount;bodyType 为 json/text/base64,二进制 body 需解码后保存。',
346
+ ],
237
347
  examples: [
238
348
  `send_request --payload '{"url":"https://api.example.com/data","method":"GET"}'`,
239
349
  `send_request --payload '{"url":"https://api.example.com/upload","method":"POST","formData":{"folder":"assets"},"files":[{"fieldName":"file","filePath":"/absolute/path/image.png"}]}'`,
@@ -251,6 +361,11 @@ export const COMMANDS = [
251
361
  { name: 'env', type: '"prod" | "pre"', description: '请求环境,默认 prod' },
252
362
  { name: 'timeout', type: 'number', description: '超时毫秒数,默认 10000' },
253
363
  ],
364
+ notes: [
365
+ '需要目标浏览器有对应登录态;Mearl 自动处理签名,不依赖页面脚本。api 以 mopen. 开头时使用 mopen 协议。',
366
+ 'env=prod 使用 h5api.m.taobao.com,pre 使用 h5api.wapa.taobao.com。',
367
+ ],
368
+ result: ['返回 success、response、requestData;业务成功需检查 response.ret。'],
254
369
  examples: [
255
370
  `send_mtop_request --payload '{"api":"mtop.trade.order.detail","data":{"orderId":"123"}}'`,
256
371
  ],
@@ -265,6 +380,31 @@ export const COMMANDS = [
265
380
  {
266
381
  name: 'browser_release',
267
382
  description: '释放当前浏览器的调试控制和会话级临时效果(含设备/时区模拟);不用于普通任务收尾,Provider 实例的行为以 mearl <providerId> 为准',
383
+ params: [
384
+ {
385
+ name: 'closeCreatedTabs',
386
+ type: 'boolean',
387
+ description: '带 --session 时关闭会话创建的过程页,默认 false',
388
+ },
389
+ {
390
+ name: 'keepTabIds',
391
+ type: 'number[]',
392
+ description: '保留的结果页面;复用的用户页面始终保留',
393
+ },
394
+ {
395
+ name: 'preserveEnvironment',
396
+ type: 'boolean',
397
+ description: '带 --session 时默认 true,保留 Mock 与模拟现场;false 清理这些页面的环境',
398
+ },
399
+ {
400
+ name: 'keepArtifactIds',
401
+ type: 'string[]',
402
+ description: '保留在浏览器宿主的文件产物;其余会话临时文件删除',
403
+ },
404
+ ],
405
+ notes: [
406
+ '带 --session 时可用于任务收尾,只释放该会话;未带会话时保留原浏览器级释放行为,活动会话存在时拒绝全局释放。',
407
+ ],
268
408
  summary: '释放浏览器调试控制和会话级临时效果',
269
409
  examples: ['browser_release', 'browser_release --browser chrome-a'],
270
410
  },
@@ -400,6 +540,15 @@ export const COMMANDS = [
400
540
  description: '与 appProfile 配合;声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}}',
401
541
  },
402
542
  ],
543
+ notes: [
544
+ 'emulation / appProfile 只应用到新建 Tab;复用 Tab 要切换状态时用对应设置 action。',
545
+ 'closeExisting 不能与复用或 openerTabId 组合;多匹配默认报错,match.onMultiple=first 可显式选择第一个。',
546
+ ],
547
+ result: [
548
+ '返回 tabId、url、title、opened/reused;reused=true 的既有页面应保留。',
549
+ 'active=true 时 activation 包含 tabActive、windowFocused、windowState、visibilityState;emulation 返回实际生效配置。',
550
+ 'capture.cursor 是导航前诊断边界,可分别用于 get_logs/get_requests/get_events 的 after。',
551
+ ],
403
552
  examples: [
404
553
  `tab_open --payload '{"url":"https://example.com"}'`,
405
554
  `tab_open --payload '{"url":"https://example.com/page","reuse":"prefer","match":{"ignoreSearch":true}}'`,
@@ -500,6 +649,11 @@ export const COMMANDS = [
500
649
  PAGE_DIAGNOSTICS_PARAM,
501
650
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
502
651
  ],
652
+ result: PAGE_ACTION_RESULT,
653
+ notes: [
654
+ 'selector / text / point 必须且只能提供一个。隐藏页 auto 使用 DOM;只有明确依赖真实用户手势时才激活页面。',
655
+ '原生 select 可按 option 文本点击;checkbox/radio 返回 controlState.checkedBefore/checkedAfter。',
656
+ ],
503
657
  examples: [
504
658
  `page_click --payload '{"tabId":12345,"text":"提交"}'`,
505
659
  `page_click --payload '{"tabId":12345,"text":"退款明细","role":"button"}'`,
@@ -541,6 +695,10 @@ export const COMMANDS = [
541
695
  PAGE_DIAGNOSTICS_PARAM,
542
696
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
543
697
  ],
698
+ result: PAGE_ACTION_RESULT,
699
+ notes: [
700
+ '起点会自动滚入视口,终点必须同时位于当前视口;否则先滚动页面。隐藏页 auto 使用 DOM,不切换活动页。',
701
+ ],
544
702
  examples: [
545
703
  `page_drag --payload '{"tabId":12345,"from":{"x":350,"y":80},"to":{"x":80,"y":80}}'`,
546
704
  `page_drag --payload '{"tabId":12345,"from":"@e3","to":"#drop-zone","dragMode":"mouse"}'`,
@@ -562,6 +720,7 @@ export const COMMANDS = [
562
720
  PAGE_DIAGNOSTICS_PARAM,
563
721
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
564
722
  ],
723
+ result: PAGE_ACTION_RESULT,
565
724
  examples: [`page_type --payload '{"tabId":12345,"selector":"@e6","text":"搜索关键词"}'`],
566
725
  },
567
726
  {
@@ -578,6 +737,7 @@ export const COMMANDS = [
578
737
  PAGE_DIAGNOSTICS_PARAM,
579
738
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
580
739
  ],
740
+ result: PAGE_ACTION_RESULT,
581
741
  examples: [`page_hover --payload '{"tabId":12345,"selector":".nav-menu"}'`],
582
742
  },
583
743
  {
@@ -605,6 +765,10 @@ export const COMMANDS = [
605
765
  PAGE_DIAGNOSTICS_PARAM,
606
766
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
607
767
  ],
768
+ result: [
769
+ ...PAGE_ACTION_RESULT,
770
+ 'action.data 返回 moved、atTop/atBottom、scrollYBefore/After、maxScrollY、resolvedContainer 和 ancestorDistance;自动发现的内部容器提供可复用 containerSelector。',
771
+ ],
608
772
  examples: [
609
773
  `page_scroll --payload '{"tabId":12345,"direction":"down"}'`,
610
774
  `page_scroll --payload '{"tabId":12345,"direction":"bottom"}'`,
@@ -623,13 +787,22 @@ export const COMMANDS = [
623
787
  description: '表达式返回 Promise 时等待完成,默认 true',
624
788
  },
625
789
  {
626
- name: 'observe',
790
+ name: 'frameId',
791
+ type: 'string',
792
+ description: 'page_frames 返回的目标 frame ID,扩展/CDP 均支持;省略时容器/设备外壳使用当前业务 frame,普通页面使用主 frame',
793
+ },
794
+ {
795
+ ...PAGE_OBSERVE_PARAM,
627
796
  type: 'object',
628
797
  description: '仅在表达式会修改页面且需要观察结果时显式传入;不传保持轻量裸执行',
629
798
  },
630
799
  PAGE_DIAGNOSTICS_PARAM,
631
800
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
632
801
  ],
802
+ notes: ['优先使用结构化 action;仅在其无法表达需求时执行最小范围脚本。'],
803
+ result: [
804
+ '默认返回 { result };observe 对象启用观察并返回 { action, observation };仅开启 diagnostics 时返回 { action, diagnostics }。diagnostics=false 不启用包装。失败阶段语义同 page_click。',
805
+ ],
633
806
  examples: [`page_eval --payload '{"tabId":12345,"expression":"document.title"}'`],
634
807
  },
635
808
  {
@@ -663,6 +836,10 @@ export const COMMANDS = [
663
836
  },
664
837
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
665
838
  ],
839
+ result: [
840
+ 'matches[] 包含 boundingBox、computedStyle、hitTest、scroll 溢出量及可用的 scrollContainer。receivesPointerEvents=false 时读取 occludedBy。',
841
+ '$0 还返回 resolvedSelector、属性、XPath 和可用框架信息。',
842
+ ],
666
843
  examples: [
667
844
  `page_inspect --payload '{"tabId":12345,"selector":".form-field","styles":["display","width"]}'`,
668
845
  `page_inspect --payload '{"tabId":12345,"selector":"@e8"}'`,
@@ -691,6 +868,13 @@ export const COMMANDS = [
691
868
  PAGE_DIAGNOSTICS_PARAM,
692
869
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
693
870
  ],
871
+ notes: [
872
+ '隐藏页 DOM 模式支持 Tab 焦点移动、原生控件 Enter/Space 激活和输入框 Enter 提交;编辑、选择、方向键和页面滚动等原生行为需可见页与 pressMode=keyboard。',
873
+ ],
874
+ result: [
875
+ ...PAGE_ACTION_RESULT,
876
+ 'action.data.dispatchMode / fallbackReason / defaultAction 说明实际输入路径。',
877
+ ],
694
878
  examples: [`page_press --payload '{"tabId":12345,"key":"Enter"}'`],
695
879
  },
696
880
  {
@@ -723,6 +907,9 @@ export const COMMANDS = [
723
907
  { name: 'interval', type: 'number', description: '轮询间隔毫秒数,默认 200' },
724
908
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
725
909
  ],
910
+ notes: [
911
+ 'time / selector / text / condition 必须且只能提供一个;time 范围 0–60000ms。页面交互已有内置观察,仅在需要独立等待条件时使用。',
912
+ ],
726
913
  examples: [
727
914
  `page_wait --payload '{"tabId":12345,"time":1000}'`,
728
915
  `page_wait --payload '{"tabId":12345,"selector":".dialog","state":"visible"}'`,
@@ -752,6 +939,7 @@ export const COMMANDS = [
752
939
  },
753
940
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
754
941
  ],
942
+ notes: ['url / refresh=true / history 必须且只能提供一个。'],
755
943
  examples: [
756
944
  `page_navigate --payload '{"tabId":12345,"url":"https://example.com/page2"}'`,
757
945
  `page_navigate --payload '{"tabId":12345,"refresh":true}'`,
@@ -762,17 +950,30 @@ export const COMMANDS = [
762
950
  name: 'page_upload',
763
951
  description: '向 <input type="file"> 元素上传一个或多个文件',
764
952
  params: [
953
+ {
954
+ name: 'files',
955
+ type: 'object[]',
956
+ description: '调用方绝对路径 {filePath} 或浏览器产物 {artifactId};与 filePaths 二选一',
957
+ },
765
958
  {
766
959
  name: 'selector',
767
960
  type: 'string',
768
961
  required: true,
769
962
  description: '原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 @eN ref(必须带 @ 前缀),必须指向 input[type=file]',
770
963
  },
771
- { name: 'filePaths', type: 'string[]', required: true, description: '本地文件路径数组' },
964
+ {
965
+ name: 'filePaths',
966
+ type: 'string[]',
967
+ description: '浏览器宿主上的绝对路径数组;与 files 二选一',
968
+ },
772
969
  PAGE_OBSERVE_PARAM,
773
970
  PAGE_DIAGNOSTICS_PARAM,
774
971
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
775
972
  ],
973
+ result: PAGE_ACTION_RESULT,
974
+ notes: [
975
+ '直接写入 input[type=file],不依赖 file chooser;隐藏的文件节点也可上传。外部 Provider 的文件中转能力查询 mearl <providerId>。',
976
+ ],
776
977
  examples: [
777
978
  `page_upload --payload '{"tabId":12345,"selector":"#file-input","filePaths":["/Users/me/photo.jpg"]}'`,
778
979
  ],
@@ -816,6 +1017,14 @@ export const COMMANDS = [
816
1017
  },
817
1018
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
818
1019
  ],
1020
+ notes: [
1021
+ 'query.text / query.role 至少提供一个;query.exact 默认 true。每次快照刷新有效 ref 集合。',
1022
+ 'interactive 无 AX 控件时回退到 viewport,不会自动改用 dom;Canvas 内容需截图。',
1023
+ ],
1024
+ result: [
1025
+ '返回 snapshot、elementCount、outputNodeCount、mode;截断时 truncated=true。',
1026
+ 'query 返回 matches 与完整 matchCount,matches 最多 100 项,裁剪时 matchesTruncated=true。容器/iframe 的视口裁剪返回 outerViewport、contentViewport 和滚动位置。',
1027
+ ],
819
1028
  examples: [
820
1029
  `page_snapshot --payload '{"tabId":12345}'`,
821
1030
  `page_snapshot --payload '{"tabId":1,"mode":"viewport"}'`,
@@ -835,6 +1044,12 @@ export const COMMANDS = [
835
1044
  { name: 'quality', type: 'number', description: 'JPEG 压缩质量(0-100),默认 80' },
836
1045
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
837
1046
  ],
1047
+ notes: [
1048
+ '使用 --output <path> 保存图片;省略时 stdout 返回含 base64 data 的 JSON,避免直接将其加载为文本。',
1049
+ ],
1050
+ result: [
1051
+ 'meta 包含 format、width、height、size、url、title;宽高为物理像素(CSS 尺寸 × DPR)。',
1052
+ ],
838
1053
  examples: [
839
1054
  `page_screenshot --payload '{"tabId":12345}' --output ./screenshot.png`,
840
1055
  `page_screenshot --payload '{"tabId":12345,"selector":".product-card"}' --output ./card.png`,
@@ -885,6 +1100,13 @@ export const COMMANDS = [
885
1100
  { name: 'reload', type: 'boolean', description: '启用后是否重载页面,默认 true' },
886
1101
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
887
1102
  ],
1103
+ notes: [
1104
+ '无 preset 时 width/height 必须成对提供且 userAgent 必填;mobile 默认 true,touch 跟随 mobile。',
1105
+ 'deviceShell 开启/移除时必须重载;splitScreen 仅在已启用 App 档案、deviceShell=true、横屏时生效。',
1106
+ ],
1107
+ result: [
1108
+ '返回实际 viewport(width/height/deviceScaleFactor/scale)、UA、mobile、touch、orientation、deviceShell、splitScreen 和 reloaded;应以响应确认生效状态。',
1109
+ ],
888
1110
  examples: [
889
1111
  `set_device_emulation --payload '{"tabId":12345,"enabled":true,"preset":"iphone-17-pro"}'`,
890
1112
  `set_device_emulation --payload '{"tabId":12345,"enabled":true,"preset":"pixel-11","orientation":"landscape"}'`,
@@ -928,6 +1150,14 @@ export const COMMANDS = [
928
1150
  { name: 'reload', type: 'boolean', description: '应用/清除后是否重载页面,默认 true' },
929
1151
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
930
1152
  ],
1153
+ notes: [
1154
+ '只有用户明确要求 App/客户端/容器/JSBridge 模拟时启用。移动视口或普通 H5 调试使用 set_device_emulation。',
1155
+ 'emulation={} 使用档案推荐设备;enabled=false 时省略 emulation 只清除 App 注入,传 {} 同时清除设备模拟。',
1156
+ 'bridgeConfig.methods 按方法声明 behavior / response / noop 三选一,可传 silent;只支持受控行为、固定 JSON 回包或成功空实现,不执行配置脚本。',
1157
+ ],
1158
+ result: [
1159
+ '返回 enabled、profile、label、userAgent、os、mtopEnv、reloaded;联动设备时额外返回实际 emulation。',
1160
+ ],
931
1161
  examples: [
932
1162
  `set_app_profile --payload '{"tabId":12345,"enabled":true,"profile":"fliggy"}'`,
933
1163
  `set_app_profile --payload '{"tabId":12345,"enabled":true,"profile":"fliggy","mtopEnv":"pre"}'`,
@@ -960,7 +1190,11 @@ export const COMMANDS = [
960
1190
  name: 'get_cookie',
961
1191
  description: '从目标浏览器读取一个指定非分区 Cookie;拒绝返回 HttpOnly Cookie',
962
1192
  params: [
963
- { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
1193
+ {
1194
+ name: 'tabId',
1195
+ type: 'number',
1196
+ description: '可选;指定标签页的 Cookie 存储区,省略时使用浏览器默认存储区',
1197
+ },
964
1198
  {
965
1199
  name: 'name',
966
1200
  type: 'string',
@@ -970,7 +1204,7 @@ export const COMMANDS = [
970
1204
  {
971
1205
  name: 'url',
972
1206
  type: 'string',
973
- description: '可选 Cookie 查询 URL;省略时使用当前标签页 URL',
1207
+ description: 'Cookie 查询 URL;未传 tabId 时必填,省略时使用指定标签页 URL',
974
1208
  },
975
1209
  {
976
1210
  name: 'domain',
@@ -979,17 +1213,31 @@ export const COMMANDS = [
979
1213
  },
980
1214
  { name: 'path', type: 'string', description: '可选精确 path 过滤' },
981
1215
  ],
1216
+ notes: [
1217
+ '只读取指定非分区 Cookie,不列举全部、不回退分区 Cookie,拒绝 HttpOnly;禁止读取认证 Token。指定 url 不导航,指定 tabId 仅选择存储区时不启动采集。',
1218
+ ],
1219
+ result: ['找到时 found=true 并返回 value/domain/path;不存在时 found=false。'],
982
1220
  examples: [
983
1221
  `get_cookie --payload '{"tabId":12345,"name":"feature_flag"}'`,
1222
+ `get_cookie --payload '{"url":"https://www.taobao.com/","name":"tracknick"}'`,
984
1223
  `get_cookie --payload '{"tabId":12345,"name":"edith_switch_br.rx-vehicle-search_home","domain":"taobao.com"}'`,
985
1224
  `get_cookie --payload '{"tabId":12345,"name":"tracknick","url":"https://www.taobao.com/","domain":"taobao.com","path":"/"}'`,
986
1225
  ],
987
1226
  },
988
1227
  {
989
1228
  name: 'set_cookie',
990
- description: '设置当前标签页域下的一个指定非分区 session Cookie,可选刷新页面',
1229
+ description: '在目标浏览器设置一个指定非分区 session Cookie,可选刷新指定页面',
991
1230
  params: [
992
- { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
1231
+ {
1232
+ name: 'tabId',
1233
+ type: 'number',
1234
+ description: '可选;指定标签页的 Cookie 存储区,reload=true 时必填',
1235
+ },
1236
+ {
1237
+ name: 'url',
1238
+ type: 'string',
1239
+ description: 'Cookie 目标 URL;未传 tabId 时必填,省略时使用指定标签页 URL',
1240
+ },
993
1241
  {
994
1242
  name: 'name',
995
1243
  type: 'string',
@@ -1005,13 +1253,20 @@ export const COMMANDS = [
1005
1253
  {
1006
1254
  name: 'domain',
1007
1255
  type: 'string',
1008
- description: 'Cookie 域,默认当前 host;只允许当前 host 或其父域',
1256
+ description: 'Cookie 域,默认目标 URL 的 host;只允许目标 host 或其父域',
1009
1257
  },
1010
1258
  { name: 'path', type: 'string', description: 'Cookie path,默认 /' },
1011
- { name: 'reload', type: 'boolean', description: '设置后是否刷新页面,默认 false' },
1259
+ {
1260
+ name: 'reload',
1261
+ type: 'boolean',
1262
+ description: '设置后是否刷新指定 tabId,默认 false;true 时必须传 tabId',
1263
+ },
1012
1264
  ],
1265
+ notes: ['仅写非分区 session Cookie,不支持删除。reload=true 时校验目标域与刷新页域的授权。'],
1266
+ result: ['返回 url/name/domain/path/reloaded,指定标签页时包含 tabId;不回显 Cookie 值。'],
1013
1267
  examples: [
1014
1268
  `set_cookie --payload '{"tabId":12345,"name":"feature_flag","value":"enabled"}'`,
1269
+ `set_cookie --payload '{"url":"https://www.taobao.com/","name":"feature_flag","value":"enabled"}'`,
1015
1270
  `set_cookie --payload '{"tabId":12345,"name":"edith_switch_br.rx-vehicle-search_home","value":"3.6.63","domain":"taobao.com","reload":true}'`,
1016
1271
  ],
1017
1272
  },
@@ -1020,6 +1275,9 @@ export const COMMANDS = [
1020
1275
  name: 'page_frames',
1021
1276
  description: '获取页面主 frame 与所有 iframe 列表',
1022
1277
  params: [{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' }],
1278
+ result: [
1279
+ 'frames[] 包含 frameId、url、name 和 isMainFrame;frameId 可用于 page_eval 等支持 frame 定位的 action。',
1280
+ ],
1023
1281
  examples: [`page_frames --payload '{"tabId":12345}'`],
1024
1282
  },
1025
1283
  {
@@ -1033,6 +1291,11 @@ export const COMMANDS = [
1033
1291
  description: '需要授权的域名,如 example.com',
1034
1292
  },
1035
1293
  ],
1294
+ notes: [
1295
+ 'domain 使用纯主机名,不传 URL。仅在非 BUC send_request 报域权限缺失时申请,BUC 不使用浏览器域权限。',
1296
+ '弹窗等待用户选择,90 秒超时或关闭按拒绝处理;granted=true 后才重试原请求。',
1297
+ ],
1298
+ result: ['返回 granted、domain,授权成功时包含 origin。'],
1036
1299
  examples: [`request_domain_permission --payload '{"domain":"example.com"}'`],
1037
1300
  },
1038
1301
  // ── 组合调用 ────────────────────────────────────────────────────────────────
@@ -1054,8 +1317,12 @@ export const COMMANDS = [
1054
1317
  description: '所有步骤共享的 tabId,步骤自身指定的优先',
1055
1318
  },
1056
1319
  ],
1320
+ notes: ['最多 50 步,不允许嵌套 run_actions;需要根据每步效果决策时逐步调用普通 action。'],
1321
+ result: [
1322
+ '返回 results、completedSteps、totalSteps;失败时包含 error/failedStep,后续步骤未执行。',
1323
+ ],
1057
1324
  examples: [
1058
- `run_actions --payload '{"tabId":12345,"actions":[{"action":"page_scroll","data":{"direction":"down"}},{"action":"page_wait","data":{"time":500}},{"action":"page_screenshot"}]}'`,
1325
+ `run_actions --payload '{"tabId":12345,"actions":[{"action":"page_hover","data":{"selector":"#menu"}},{"action":"page_click","data":{"selector":"#menu-item"}}]}'`,
1059
1326
  ],
1060
1327
  },
1061
1328
  ];