@mearl/client 2.16.4 → 2.17.1

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/README.md CHANGED
@@ -47,8 +47,8 @@ mearl send_request --payload '{"url":"https://api.example.com","method":"GET"}'
47
47
  # 以 multipart/form-data 上传本地文件
48
48
  mearl send_request --payload '{"url":"https://api.example.com/upload","method":"POST","formData":{"folder":"assets"},"files":[{"fieldName":"file","filePath":"/absolute/path/image.png"}]}'
49
49
 
50
- # 截图并保存
51
- mearl page_screenshot --output ./screenshot.png
50
+ # 截图并保存(tabId 来自 tab_open 或 tab_list)
51
+ mearl page_screenshot --payload '{"tabId":12345}' --output ./screenshot.png
52
52
 
53
53
  # 从文件读取大体积参数(如 mock 数据)
54
54
  mearl set_mock --payload-file ./mock-data.json
@@ -90,7 +90,8 @@ mearl browser_launch --payload '{"provider":"brow","providerOptions":{}}'
90
90
  mearl browser_list
91
91
 
92
92
  # 后续操作使用 browser_list 返回的全局 Browser ID
93
- mearl page_snapshot --browser '<browserId>'
93
+ mearl tab_list --browser '<browserId>'
94
+ mearl page_snapshot --payload '{"tabId":12345}' --browser '<browserId>'
94
95
 
95
96
  npx @mearl/setup provider update brow
96
97
  npx @mearl/setup provider uninstall brow
@@ -200,18 +201,28 @@ MCP Server 通过固定工具 `mearl_plugin` 接受同样的 `plugin`、`command
200
201
  | API 调试 | `tab_checkpoint` `get_requests` `get_logs` `get_events` |
201
202
  | Mock & 规则 | `set_mock` `get_mocks` `set_rule` `get_rules` |
202
203
  | 网络请求 | `send_request` `send_mtop_request` `request_domain_permission` |
203
- | 标签页 | `tab_open` `tab_close` `tab_list` |
204
- | 页面操作 | `page_click` `page_drag` `page_type` `page_hover` `page_scroll` `page_eval` `page_press` `page_wait` `page_navigate` `page_upload` |
204
+ | 标签页 | `tab_open` `tab_list` `tab_close` |
205
+ | 页面感知 | `page_snapshot` `page_inspect` `page_screenshot` `page_frames` |
206
+ | 页面操作 | `page_click` `page_drag` `page_type` `page_hover` `page_scroll` `page_press` `page_wait` `page_navigate` `page_upload` `page_eval` |
205
207
  | 组合调用 | `run_actions` |
206
- | 页面感知 | `page_snapshot` `page_screenshot` `page_selected_element` `page_frames` |
207
208
  | 环境与 Cookie | `set_device_emulation` `set_app_profile` `set_timezone` `get_cookie` `set_cookie` |
208
- | 浏览器 | `browser_list` `browser_release` `browser_launch` `browser_close` |
209
+ | 浏览器 | `browser_list` `browser_launch` `browser_release` `browser_close` |
209
210
 
210
- 页面交互动作(`page_click` / `page_drag` / `page_type` / `page_hover` / `page_scroll` / `page_press` / `page_upload`)默认等待异步稳定并返回 `{ action, observation }`。参数、ref 或目标解析在派发前失败时返回 `action.stage: "precondition"`,省略无意义的 `observation` / `diagnostics`,CLI 退出码为 1。传 `observe: false` 可执行裸动作;需要同一动作期间的新增 error logs 和业务 requests 时传 `diagnostics: true`,埋点通过 `diagnostics.events` 按需开启。`page_eval` 默认裸执行,可按需开启观察或诊断。
211
+ 页面交互动作(`page_click` / `page_drag` / `page_type` / `page_hover` / `page_scroll` / `page_press` / `page_upload`)默认等待异步稳定并返回 `{ action, observation }`。参数、ref 或目标解析在派发前失败时返回 `action.stage: "precondition"`,省略无意义的 `observation` / `diagnostics`;浏览器可能已收到输入但确认超时时返回 `action.stage: "dispatch-uncertain"`,并保留 observation 供核验当前状态。能够在超时前确定的目标、命中、坐标、派发模式和输入序列状态保存在 `action.attempt`,它是诊断证据,不表示动作已经生效。失败时 CLI 退出码为 1。传 `observe: false` 可执行裸动作;需要同一动作期间的新增 error logs 和业务 requests 时传 `diagnostics: true`,埋点通过 `diagnostics.events` 按需开启。`page_eval` 默认裸执行,可按需开启观察或诊断。
211
212
 
212
- `page_snapshot` 默认返回完整 AX Tree;长列表可传 `mode: "viewport"`,只需要当前视口内的控件时传 `mode: "interactive"`,已知 CSS 区域时传 `rootSelector`,已有 ref 时传 `rootRef`(可用 `ancestorDepth` 向上补充上下文),只查找特定文案或角色时传 `query`。视口内缺少 AX 控件语义时,`interactive` 会自动回退到 viewport,并返回 `fallbackMode: "viewport"`。`maxNodes` / `maxChars` 截断会同时保留首尾内容。
213
+ `tab_open active:true` 会激活目标 Tab、恢复最小化窗口,并通过 `activation` 返回实际标签页、窗口和 `visibilityState`;依赖可信触摸时先确认页面为 `visible`。页面动作的稳定观察会在有限预算内等待有限时长 CSS 动画。selector/ref 点击遇到嵌套滚动裁剪时会先滚动目标,仍不可见时才以明确的裁剪错误停止。
213
214
 
214
- 重复文本点击可用 `page_click.scope` 限定 CSS / ref 子树;浏览器扩展后端中,容器或 iframe 内的点坐标使用 `coordinateSpace: "active-frame"`,CSS/text 查询可用 `frameId` 显式指定 frame。点击结果通过 `requestedTarget`、`resolvedTarget`、`dispatchTarget`、`hitTarget` 和 `coordinates` 区分请求语义、DOM 解析、派发节点与可信输入实际命中;ref 指向滚动容器内的子节点时,可用 `page_scroll.containerPolicy: "nearest"` 自动解析最近可滚动祖先。
215
+ `page_click` 默认 `auto` 在隐藏页使用 DOM fallback,selector、文本、ref 和坐标定位都保持可用,并通过 `dispatchMode: "dom"`、`fallbackReason: "page-hidden"` 明确说明实际路径。普通后台任务不需要为了点击主动激活页面;只有站点明确拒绝非可信事件时才切换到可见页并强制 `mouse` / `touch`。
216
+
217
+ `observation.effects.interactives` 会把内容未变化但 DOM 节点被框架重建的控件标记为 `recreated`,保留 selector/ref 与语义信息供后续定位,同时省略未变化的 value 和状态字段;值或状态确实变化时仍返回完整差异。
218
+
219
+ `page_press.pressMode` 支持 `auto` / `dom` / `keyboard`。默认 `auto` 在隐藏页使用 DOM 键盘事件,并通过返回的 `dispatchMode`、`fallbackReason` 和 `defaultAction` 说明实际派发及默认行为模拟结果;依赖浏览器原生编辑、选择或滚动行为时使用可见页面和 `keyboard`。
220
+
221
+ `page_snapshot` 默认返回完整 AX Tree;长列表可传 `mode: "viewport"`,只需要当前视口内的控件时传 `mode: "interactive"`,AX 信息为空或过于稀疏时可显式传 `mode: "dom"`,返回实际渲染文本、原生控件、显式 role 和高置信 clickable 节点。DOM 模式同样返回可供后续动作使用的 `@ref`,但不会猜测任意容器的业务语义。已知 CSS 区域时传 `rootSelector`,已有 ref 时传 `rootRef`(可用 `ancestorDepth` 向上补充上下文),只查找特定文案或角色时传 `query`。`interactive` 在视口内缺少 AX 控件语义时仍只回退到 AX viewport,并返回 `fallbackMode: "viewport"`,不会自动切换数据来源。`maxNodes` / `maxChars` 截断会同时保留首尾内容。
222
+
223
+ `page_inspect` 用 CSS、snapshot `@ref` 或 DevTools 当前选中元素 `$0` 返回命中数、边框盒、指定计算样式、中心点遮挡、横纵溢出像素和最近滚动容器。省略 selector 并传 `filter: "horizontal-overflow"` / `"vertical-overflow"` / `"scrollable"` 可直接做全页布局诊断。按文本定位时先用 `page_snapshot.query` 取得 `matches` / `matchCount` 和 ref,再把 ref 交给 `page_inspect`,不需要手写 `page_eval`。
224
+
225
+ 重复文本点击可用 `page_click.scope` 限定 CSS / ref 子树;浏览器扩展后端中,容器或 iframe 内的点坐标使用 `coordinateSpace: "active-frame"`,CSS/text 查询可用 `frameId` 显式指定 frame。点击结果通过 `requestedTarget`、`resolvedTarget`、`dispatchTarget`、`hitTarget` 和 `coordinates` 区分请求语义、DOM 解析、派发节点与可信输入实际命中;selector/ref 目标被嵌套滚动容器裁剪时会自动滚动到可点击区域,只有仍被 overflow 裁剪时才要求显式处理。需要主动浏览列表时,`page_scroll.containerPolicy: "nearest"` 可自动解析最近可滚动祖先。未指定 selector 时,`page_scroll` 会优先选择代表性视口位置命中的最近内部滚动容器,再使用文档滚动区域或层级最高且可视面积最大的滚动容器。
215
226
 
216
227
  `browser_list` 统一列出普通浏览器、Provider 浏览器和托管浏览器。`type` 区分
217
228
  `regular` / `managed`,`status` 区分 `connected` / `pairing` / `running_disconnected` /
package/dist/cli.js CHANGED
@@ -21,7 +21,11 @@ const CATEGORIES = [
21
21
  title: '网络请求',
22
22
  names: ['send_request', 'send_mtop_request', 'request_domain_permission'],
23
23
  },
24
- { title: '标签页', names: ['tab_open', 'tab_close', 'tab_list'] },
24
+ { title: '标签页', names: ['tab_open', 'tab_list', 'tab_close'] },
25
+ {
26
+ title: '页面感知',
27
+ names: ['page_snapshot', 'page_inspect', 'page_screenshot', 'page_frames'],
28
+ },
25
29
  {
26
30
  title: '页面操作',
27
31
  names: [
@@ -30,25 +34,21 @@ const CATEGORIES = [
30
34
  'page_type',
31
35
  'page_hover',
32
36
  'page_scroll',
33
- 'page_eval',
34
37
  'page_press',
35
38
  'page_wait',
36
39
  'page_navigate',
37
40
  'page_upload',
41
+ 'page_eval',
38
42
  ],
39
43
  },
40
44
  { title: '组合调用', names: ['run_actions'] },
41
- {
42
- title: '页面感知',
43
- names: ['page_snapshot', 'page_screenshot', 'page_selected_element', 'page_frames'],
44
- },
45
45
  {
46
46
  title: '环境与 Cookie',
47
47
  names: ['set_device_emulation', 'set_app_profile', 'set_timezone', 'get_cookie', 'set_cookie'],
48
48
  },
49
49
  {
50
50
  title: '浏览器',
51
- names: ['browser_list', 'browser_release', 'browser_launch', 'browser_close'],
51
+ names: ['browser_list', 'browser_launch', 'browser_release', 'browser_close'],
52
52
  },
53
53
  ];
54
54
  const BUILTIN_COMMANDS = [
@@ -111,10 +111,6 @@ function printUsage(commandName, version) {
111
111
  ` ${commandName} <action> --help`,
112
112
  ` ${commandName} check [选项]`,
113
113
  '',
114
- '统一目标发现:',
115
- ' browser_list 默认聚合当前机器及已配置 cloud-server 下的浏览器。',
116
- ' 后续操作通过 --browser <browserId> 指定目标,客户端会自动选择本地或远端传输。',
117
- '',
118
114
  '常用选项:',
119
115
  ' --payload <json> 直接传入 JSON 参数',
120
116
  ' --payload-file <path> 从文件读取整个 JSON 参数',
@@ -162,7 +158,6 @@ function printUsage(commandName, version) {
162
158
  if (providers.length) {
163
159
  lines.push('', '已注册 Provider:', ...providers.map(provider => ` ${provider.providerId.padEnd(TOP_LEVEL_COMMAND_NAME_WIDTH)}${provider.name} v${provider.version} (${provider.packageName})`));
164
160
  }
165
- lines.push('', `运行 ${commandName} <action> --help 查看 action 参数。`);
166
161
  console.error(lines.join('\n'));
167
162
  }
168
163
  function providerSchemaLine(name, schema, required, indent = 2) {
@@ -554,9 +549,6 @@ function screenshotData(action, result) {
554
549
  }
555
550
  if (action === 'page_screenshot' && typeof result?.data === 'string')
556
551
  return result.data;
557
- if (action === 'page_selected_element' && typeof result?.screenshot?.data === 'string') {
558
- return result.screenshot.data;
559
- }
560
552
  return null;
561
553
  }
562
554
  function writeOutput(action, result, outputPath) {
@@ -659,9 +651,6 @@ export async function runMearlCli(args, options = {}) {
659
651
  }
660
652
  return (await runUnifiedCheck(checkOptions)) ? 0 : 1;
661
653
  }
662
- if (parsed.action === 'page_selected_element' && parsed.outputPath) {
663
- parsed.payload = { ...parsed.payload, includeScreenshot: true };
664
- }
665
654
  const client = new UnifiedClient({
666
655
  ...(parsed.serverUrl ? { serverUrl: parsed.serverUrl } : {}),
667
656
  requestTimeoutSec: parsed.timeoutSec,
@@ -308,8 +308,8 @@ export declare const COMMANDS: readonly [{
308
308
  readonly description: "签名使用的 appKey,默认 12574478";
309
309
  }, {
310
310
  readonly name: "env";
311
- readonly type: "\"online\" | \"pre\"";
312
- readonly description: "请求环境,默认 online";
311
+ readonly type: "\"prod\" | \"pre\"";
312
+ readonly description: "请求环境,默认 prod";
313
313
  }, {
314
314
  readonly name: "timeout";
315
315
  readonly type: "number";
@@ -393,7 +393,7 @@ export declare const COMMANDS: readonly [{
393
393
  }, {
394
394
  readonly name: "active";
395
395
  readonly type: "boolean";
396
- readonly description: "是否激活新 Tab,默认 false";
396
+ readonly description: "是否激活目标 Tab 并恢复最小化窗口,默认 false;响应返回 activation 验证结果";
397
397
  }, {
398
398
  readonly name: "openerTabId";
399
399
  readonly type: "number";
@@ -497,7 +497,7 @@ export declare const COMMANDS: readonly [{
497
497
  readonly required: true;
498
498
  readonly description: "目标标签页 ID";
499
499
  }];
500
- readonly examples: ["page_click --payload '{\"text\":\"提交\"}'", "page_click --payload '{\"text\":\"退款明细\",\"role\":\"button\"}'", "page_click --payload '{\"text\":\"确定\",\"scope\":\"@e12\"}'", "page_click --payload '{\"selector\":\"@e3\"}'", "page_click --payload '{\"selector\":\".submit-btn\"}'", "page_click --payload '{\"selector\":\".gesture-btn\",\"clickMode\":\"touch\"}'", "page_click --payload '{\"point\":{\"x\":336,\"y\":117}}'", "page_click --payload '{\"point\":{\"x\":196,\"y\":240},\"coordinateSpace\":\"active-frame\"}'"];
500
+ readonly examples: ["page_click --payload '{\"tabId\":12345,\"text\":\"提交\"}'", "page_click --payload '{\"tabId\":12345,\"text\":\"退款明细\",\"role\":\"button\"}'", "page_click --payload '{\"tabId\":12345,\"text\":\"确定\",\"scope\":\"@e12\"}'", "page_click --payload '{\"tabId\":12345,\"selector\":\"@e3\"}'", "page_click --payload '{\"tabId\":12345,\"selector\":\".submit-btn\"}'", "page_click --payload '{\"tabId\":12345,\"selector\":\".gesture-btn\",\"clickMode\":\"touch\"}'", "page_click --payload '{\"tabId\":12345,\"point\":{\"x\":336,\"y\":117}}'", "page_click --payload '{\"tabId\":12345,\"point\":{\"x\":196,\"y\":240},\"coordinateSpace\":\"active-frame\"}'"];
501
501
  }, {
502
502
  readonly name: "page_drag";
503
503
  readonly description: "拖动页面元素或视口坐标,适用于轮播图、滑块和拖放";
@@ -525,7 +525,7 @@ export declare const COMMANDS: readonly [{
525
525
  readonly required: true;
526
526
  readonly description: "目标标签页 ID";
527
527
  }];
528
- readonly examples: ["page_drag --payload '{\"from\":{\"x\":350,\"y\":80},\"to\":{\"x\":80,\"y\":80}}'", "page_drag --payload '{\"from\":\"@e3\",\"to\":\"#drop-zone\",\"dragMode\":\"mouse\"}'"];
528
+ readonly examples: ["page_drag --payload '{\"tabId\":12345,\"from\":{\"x\":350,\"y\":80},\"to\":{\"x\":80,\"y\":80}}'", "page_drag --payload '{\"tabId\":12345,\"from\":\"@e3\",\"to\":\"#drop-zone\",\"dragMode\":\"mouse\"}'"];
529
529
  }, {
530
530
  readonly name: "page_type";
531
531
  readonly description: "向输入框填写文本,兼容 React 受控组件";
@@ -549,7 +549,7 @@ export declare const COMMANDS: readonly [{
549
549
  readonly required: true;
550
550
  readonly description: "目标标签页 ID";
551
551
  }];
552
- readonly examples: ["page_type --payload '{\"selector\":\"@e6\",\"text\":\"搜索关键词\"}'"];
552
+ readonly examples: ["page_type --payload '{\"tabId\":12345,\"selector\":\"@e6\",\"text\":\"搜索关键词\"}'"];
553
553
  }, {
554
554
  readonly name: "page_hover";
555
555
  readonly description: "将鼠标悬停在页面元素上";
@@ -564,10 +564,10 @@ export declare const COMMANDS: readonly [{
564
564
  readonly required: true;
565
565
  readonly description: "目标标签页 ID";
566
566
  }];
567
- readonly examples: ["page_hover --payload '{\"selector\":\".nav-menu\"}'"];
567
+ readonly examples: ["page_hover --payload '{\"tabId\":12345,\"selector\":\".nav-menu\"}'"];
568
568
  }, {
569
569
  readonly name: "page_scroll";
570
- readonly description: "滚动页面或指定容器";
570
+ readonly description: "滚动页面或指定容器;页面根不可滚动时自动发现活动滚动区";
571
571
  readonly params: [{
572
572
  readonly name: "direction";
573
573
  readonly type: "\"up\" | \"down\" | \"top\" | \"bottom\"";
@@ -591,7 +591,7 @@ export declare const COMMANDS: readonly [{
591
591
  readonly required: true;
592
592
  readonly description: "目标标签页 ID";
593
593
  }];
594
- readonly examples: ["page_scroll --payload '{\"direction\":\"down\"}'", "page_scroll --payload '{\"direction\":\"bottom\"}'", "page_scroll --payload '{\"selector\":\".virtual-list\",\"direction\":\"down\",\"distance\":800}'", "page_scroll --payload '{\"selector\":\"@e8\",\"containerPolicy\":\"nearest\",\"direction\":\"bottom\"}'"];
594
+ readonly examples: ["page_scroll --payload '{\"tabId\":12345,\"direction\":\"down\"}'", "page_scroll --payload '{\"tabId\":12345,\"direction\":\"bottom\"}'", "page_scroll --payload '{\"tabId\":12345,\"selector\":\".virtual-list\",\"direction\":\"down\",\"distance\":800}'", "page_scroll --payload '{\"tabId\":12345,\"selector\":\"@e8\",\"containerPolicy\":\"nearest\",\"direction\":\"bottom\"}'"];
595
595
  }, {
596
596
  readonly name: "page_eval";
597
597
  readonly description: "在页面上下文中执行任意 JavaScript 表达式";
@@ -614,7 +614,37 @@ export declare const COMMANDS: readonly [{
614
614
  readonly required: true;
615
615
  readonly description: "目标标签页 ID";
616
616
  }];
617
- readonly examples: ["page_eval --payload '{\"expression\":\"document.title\"}'"];
617
+ readonly examples: ["page_eval --payload '{\"tabId\":12345,\"expression\":\"document.title\"}'"];
618
+ }, {
619
+ readonly name: "page_inspect";
620
+ readonly description: "查询 DOM 元素的数量、边框盒、计算样式、遮挡、溢出和最近滚动容器";
621
+ readonly params: [{
622
+ readonly name: "selector";
623
+ readonly type: "string";
624
+ readonly description: "原生 CSS、page_snapshot 返回的 @eN ref,或 DevTools Elements 当前选区 $0;做全页溢出诊断时可省略";
625
+ }, {
626
+ readonly name: "filter";
627
+ readonly type: "\"all\" | \"overflowing\" | \"horizontal-overflow\" | \"vertical-overflow\" | \"scrollable\"";
628
+ readonly description: "结果过滤;省略 selector 时必须指定非 all 的过滤条件";
629
+ }, {
630
+ readonly name: "styles";
631
+ readonly type: "string[]";
632
+ readonly description: "要返回的计算样式属性,默认 display/position/box-sizing/overflow-x/overflow-y";
633
+ }, {
634
+ readonly name: "maxResults";
635
+ readonly type: "number";
636
+ readonly description: "最多返回的明细数,默认 20,最大 100;未触发 scanTruncated 时 count 为完整命中数";
637
+ }, {
638
+ readonly name: "includeOuterHTML";
639
+ readonly type: "boolean";
640
+ readonly description: "是否返回 outerHTML(最多 3000 字符);$0 默认 true,其他目标默认 false";
641
+ }, {
642
+ readonly name: "tabId";
643
+ readonly type: "number";
644
+ readonly required: true;
645
+ readonly description: "目标标签页 ID";
646
+ }];
647
+ readonly examples: ["page_inspect --payload '{\"tabId\":12345,\"selector\":\".form-field\",\"styles\":[\"display\",\"width\"]}'", "page_inspect --payload '{\"tabId\":12345,\"selector\":\"@e8\"}'", "page_inspect --payload '{\"tabId\":12345,\"selector\":\"$0\"}'", "page_inspect --payload '{\"tabId\":12345,\"filter\":\"horizontal-overflow\"}'", "page_inspect --payload '{\"tabId\":12345,\"filter\":\"scrollable\"}'"];
618
648
  }, {
619
649
  readonly name: "page_press";
620
650
  readonly description: "在页面中按下键盘按键或组合键";
@@ -627,24 +657,40 @@ export declare const COMMANDS: readonly [{
627
657
  readonly name: "modifiers";
628
658
  readonly type: "string[]";
629
659
  readonly description: "修饰键数组:ctrl/alt/shift/meta/cmd";
660
+ }, {
661
+ readonly name: "pressMode";
662
+ readonly type: "\"auto\" | \"dom\" | \"keyboard\"";
663
+ readonly description: "派发模式;auto 默认在隐藏页降级为 DOM 键盘事件";
630
664
  }, ParamDef, ParamDef, {
631
665
  readonly name: "tabId";
632
666
  readonly type: "number";
633
667
  readonly required: true;
634
668
  readonly description: "目标标签页 ID";
635
669
  }];
636
- readonly examples: ["page_press --payload '{\"key\":\"Enter\"}'"];
670
+ readonly examples: ["page_press --payload '{\"tabId\":12345,\"key\":\"Enter\"}'"];
637
671
  }, {
638
672
  readonly name: "page_wait";
639
- readonly description: "等待指定时间、元素出现或页面条件成立";
673
+ readonly description: "等待指定时间、元素状态、可见文本或页面条件成立";
640
674
  readonly params: [{
641
675
  readonly name: "time";
642
676
  readonly type: "number";
643
- readonly description: "等待毫秒数(与 selector 二选一)";
677
+ readonly description: "等待毫秒数(与 selector/text/condition 四选一)";
644
678
  }, {
645
679
  readonly name: "selector";
646
680
  readonly type: "string";
647
- readonly description: "等待元素出现的 CSS 选择器(与 time/condition 三选一)";
681
+ readonly description: "目标 CSS 选择器(与 time/text/condition 四选一)";
682
+ }, {
683
+ readonly name: "state";
684
+ readonly type: "\"attached\" | \"detached\" | \"visible\" | \"hidden\"";
685
+ readonly description: "selector 的目标状态,默认 attached";
686
+ }, {
687
+ readonly name: "text";
688
+ readonly type: "string";
689
+ readonly description: "等待页面出现的可见文本";
690
+ }, {
691
+ readonly name: "exact";
692
+ readonly type: "boolean";
693
+ readonly description: "text 是否精确匹配,默认 false";
648
694
  }, {
649
695
  readonly name: "condition";
650
696
  readonly type: "string";
@@ -663,7 +709,7 @@ export declare const COMMANDS: readonly [{
663
709
  readonly required: true;
664
710
  readonly description: "目标标签页 ID";
665
711
  }];
666
- readonly examples: ["page_wait --payload '{\"time\":1000}'", "page_wait --payload '{\"selector\":\".loaded\"}'", "page_wait --payload '{\"condition\":\"window.appReady === true\",\"timeout\":30000}'"];
712
+ readonly examples: ["page_wait --payload '{\"tabId\":12345,\"time\":1000}'", "page_wait --payload '{\"tabId\":12345,\"selector\":\".dialog\",\"state\":\"visible\"}'", "page_wait --payload '{\"tabId\":12345,\"selector\":\".loading\",\"state\":\"hidden\"}'", "page_wait --payload '{\"tabId\":12345,\"text\":\"提交成功\"}'", "page_wait --payload '{\"tabId\":12345,\"condition\":\"window.appReady === true\",\"timeout\":30000}'"];
667
713
  }, {
668
714
  readonly name: "page_navigate";
669
715
  readonly description: "在当前标签页内导航到 URL、刷新页面,或沿浏览历史后退/前进";
@@ -705,26 +751,26 @@ export declare const COMMANDS: readonly [{
705
751
  readonly required: true;
706
752
  readonly description: "目标标签页 ID";
707
753
  }];
708
- readonly examples: ["page_upload --payload '{\"selector\":\"#file-input\",\"filePaths\":[\"/Users/me/photo.jpg\"]}'"];
754
+ readonly examples: ["page_upload --payload '{\"tabId\":12345,\"selector\":\"#file-input\",\"filePaths\":[\"/Users/me/photo.jpg\"]}'"];
709
755
  }, {
710
756
  readonly name: "page_snapshot";
711
- readonly description: "获取页面无障碍树快照,支持完整、交互元素或当前视口范围(含 @ref)";
757
+ readonly description: "获取带 @ref 的页面结构快照,默认使用无障碍树,也可显式读取渲染 DOM";
712
758
  readonly params: [{
713
759
  readonly name: "depth";
714
760
  readonly type: "number";
715
761
  readonly description: "树深度,默认 15,复杂页面可调大";
716
762
  }, {
717
763
  readonly name: "mode";
718
- readonly type: "\"full\" | \"interactive\" | \"viewport\"";
719
- readonly description: "输出范围,默认 full;interactive 只保留当前视口内的语义控件;长列表优先使用 viewport";
764
+ readonly type: "\"full\" | \"interactive\" | \"viewport\" | \"dom\"";
765
+ readonly description: "默认 full;interactive/viewport 裁剪 AX 树;AX 信息缺失时可显式使用 dom 读取渲染 DOM";
720
766
  }, {
721
767
  readonly name: "rootSelector";
722
768
  readonly type: "string";
723
- readonly description: "只获取指定 CSS 元素的 AX 子树,可与 mode 组合;与 rootRef 互斥";
769
+ readonly description: "只获取指定 CSS 元素的局部子树,可与 mode 组合;与 rootRef 互斥";
724
770
  }, {
725
771
  readonly name: "rootRef";
726
772
  readonly type: "string";
727
- readonly description: "以已有 @eN ref 为根获取局部 AX 子树;与 rootSelector 互斥";
773
+ readonly description: "以已有 @eN ref 为根获取局部子树;与 rootSelector 互斥";
728
774
  }, {
729
775
  readonly name: "ancestorDepth";
730
776
  readonly type: "number";
@@ -732,7 +778,7 @@ export declare const COMMANDS: readonly [{
732
778
  }, {
733
779
  readonly name: "query";
734
780
  readonly type: "{ text?: string; role?: string; exact?: boolean }";
735
- readonly description: "服务端过滤 AX 树,只保留按 accessibility name / role 命中的节点及祖先路径";
781
+ readonly description: "服务端按 name / role 过滤当前模式的树,只保留命中节点及祖先路径";
736
782
  }, {
737
783
  readonly name: "maxNodes";
738
784
  readonly type: "number";
@@ -747,7 +793,7 @@ export declare const COMMANDS: readonly [{
747
793
  readonly required: true;
748
794
  readonly description: "目标标签页 ID";
749
795
  }];
750
- readonly examples: ["page_snapshot", "page_snapshot --payload '{\"tabId\":1,\"mode\":\"viewport\"}'", "page_snapshot --payload '{\"tabId\":1,\"rootSelector\":\"[role=dialog]\"}'", "page_snapshot --payload '{\"tabId\":1,\"rootRef\":\"@e8\",\"ancestorDepth\":1}'", "page_snapshot --payload '{\"tabId\":1,\"query\":{\"text\":\"保存\",\"role\":\"button\"}}'"];
796
+ readonly examples: ["page_snapshot --payload '{\"tabId\":12345}'", "page_snapshot --payload '{\"tabId\":1,\"mode\":\"viewport\"}'", "page_snapshot --payload '{\"tabId\":1,\"mode\":\"dom\"}'", "page_snapshot --payload '{\"tabId\":1,\"rootSelector\":\"[role=dialog]\"}'", "page_snapshot --payload '{\"tabId\":1,\"rootRef\":\"@e8\",\"ancestorDepth\":1}'", "page_snapshot --payload '{\"tabId\":1,\"query\":{\"text\":\"保存\",\"role\":\"button\"}}'"];
751
797
  }, {
752
798
  readonly name: "page_screenshot";
753
799
  readonly description: "获取当前视口或指定元素截图";
@@ -770,26 +816,7 @@ export declare const COMMANDS: readonly [{
770
816
  readonly required: true;
771
817
  readonly description: "目标标签页 ID";
772
818
  }];
773
- readonly examples: ["page_screenshot --output ./screenshot.png", "page_screenshot --payload '{\"selector\":\".product-card\"}' --output ./card.png"];
774
- }, {
775
- readonly name: "page_selected_element";
776
- readonly description: "获取 DevTools Elements 面板当前选中元素的详细信息";
777
- readonly outputFlag: true;
778
- readonly params: [{
779
- readonly name: "includeOuterHTML";
780
- readonly type: "boolean";
781
- readonly description: "是否返回 outerHTML(最多 3000 字符),默认 true";
782
- }, {
783
- readonly name: "includeScreenshot";
784
- readonly type: "boolean";
785
- readonly description: "是否附带元素截图,默认 false;指定 --output 时自动开启";
786
- }, {
787
- readonly name: "tabId";
788
- readonly type: "number";
789
- readonly required: true;
790
- readonly description: "目标标签页 ID";
791
- }];
792
- readonly examples: ["page_selected_element", "page_selected_element --output ./element.png"];
819
+ readonly examples: ["page_screenshot --payload '{\"tabId\":12345}' --output ./screenshot.png", "page_screenshot --payload '{\"tabId\":12345,\"selector\":\".product-card\"}' --output ./card.png"];
793
820
  }, {
794
821
  readonly name: "set_device_emulation";
795
822
  readonly description: "把目标 tab 切换为移动端模拟(视口/DPR/UA/触摸/视觉比例),等价 DevTools 设备工具栏,作用域 per-tab;需保持调试控制才持续生效";
@@ -853,10 +880,10 @@ export declare const COMMANDS: readonly [{
853
880
  readonly required: true;
854
881
  readonly description: "目标标签页 ID";
855
882
  }];
856
- readonly examples: ["set_device_emulation --payload '{\"enabled\":true,\"preset\":\"iphone-17-pro\"}'", "set_device_emulation --payload '{\"enabled\":true,\"preset\":\"pixel-11\",\"orientation\":\"landscape\"}'", "set_device_emulation --payload '{\"enabled\":true,\"preset\":\"ipad-mini-a17-pro\",\"orientation\":\"landscape\",\"deviceShell\":true,\"splitScreen\":true}'", "set_device_emulation --payload '{\"enabled\":false}'"];
883
+ readonly examples: ["set_device_emulation --payload '{\"tabId\":12345,\"enabled\":true,\"preset\":\"iphone-17-pro\"}'", "set_device_emulation --payload '{\"tabId\":12345,\"enabled\":true,\"preset\":\"pixel-11\",\"orientation\":\"landscape\"}'", "set_device_emulation --payload '{\"tabId\":12345,\"enabled\":true,\"preset\":\"ipad-mini-a17-pro\",\"orientation\":\"landscape\",\"deviceShell\":true,\"splitScreen\":true}'", "set_device_emulation --payload '{\"tabId\":12345,\"enabled\":false}'"];
857
884
  }, {
858
885
  readonly name: "set_app_profile";
859
- readonly description: "设置 App 客户端环境与 JSBridge;传 emulation 时由同一个命令联动设备模拟,省略时不改变设备状态";
886
+ readonly description: "设置 App 客户端环境与 JSBridge;可同时设置 MTop 页面接口环境,传 emulation 时联动设备模拟";
860
887
  readonly summary: "设置或清除目标标签页的 App 容器模拟";
861
888
  readonly params: [{
862
889
  readonly name: "enabled";
@@ -883,6 +910,10 @@ export declare const COMMANDS: readonly [{
883
910
  readonly name: "bridgeConfig";
884
911
  readonly type: "object";
885
912
  readonly description: "声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}};不执行配置脚本";
913
+ }, {
914
+ readonly name: "mtopEnv";
915
+ readonly type: "\"default\" | \"prod\" | \"pre\"";
916
+ readonly description: "可选 MTop 页面接口环境;default 关闭环境改写,省略时保持当前设置。扩展模式全局生效,CDP 模式仅作用于目标 tab";
886
917
  }, {
887
918
  readonly name: "emulation";
888
919
  readonly type: "object";
@@ -897,7 +928,7 @@ export declare const COMMANDS: readonly [{
897
928
  readonly required: true;
898
929
  readonly description: "目标标签页 ID";
899
930
  }];
900
- readonly examples: ["set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\"}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\",\"emulation\":{}}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"alipay\",\"emulation\":{\"preset\":\"pixel-11\",\"deviceShell\":true}}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\",\"emulation\":{\"preset\":\"ipad-mini-a17-pro\",\"orientation\":\"landscape\",\"deviceShell\":true,\"splitScreen\":true}}'", "set_app_profile --payload '{\"enabled\":false}'", "set_app_profile --payload '{\"enabled\":false,\"emulation\":{}}'"];
931
+ readonly examples: ["set_app_profile --payload '{\"tabId\":12345,\"enabled\":true,\"profile\":\"fliggy\"}'", "set_app_profile --payload '{\"tabId\":12345,\"enabled\":true,\"profile\":\"fliggy\",\"mtopEnv\":\"pre\"}'", "set_app_profile --payload '{\"tabId\":12345,\"enabled\":false,\"mtopEnv\":\"prod\"}'", "set_app_profile --payload '{\"tabId\":12345,\"enabled\":true,\"profile\":\"fliggy\",\"emulation\":{}}'", "set_app_profile --payload '{\"tabId\":12345,\"enabled\":true,\"profile\":\"alipay\",\"emulation\":{\"preset\":\"pixel-11\",\"deviceShell\":true}}'", "set_app_profile --payload '{\"tabId\":12345,\"enabled\":true,\"profile\":\"fliggy\",\"emulation\":{\"preset\":\"ipad-mini-a17-pro\",\"orientation\":\"landscape\",\"deviceShell\":true,\"splitScreen\":true}}'", "set_app_profile --payload '{\"tabId\":12345,\"enabled\":false}'", "set_app_profile --payload '{\"tabId\":12345,\"enabled\":false,\"emulation\":{}}'"];
901
932
  }, {
902
933
  readonly name: "set_timezone";
903
934
  readonly description: "覆盖目标 tab 的时区,传空字符串恢复浏览器默认时区";
package/dist/commands.js CHANGED
@@ -214,7 +214,7 @@ export const COMMANDS = [
214
214
  { name: 'version', type: 'string', description: 'API 版本,默认 1.0' },
215
215
  { name: 'method', type: 'string', description: 'HTTP 方法,默认 GET' },
216
216
  { name: 'appKey', type: 'string', description: '签名使用的 appKey,默认 12574478' },
217
- { name: 'env', type: '"online" | "pre"', description: '请求环境,默认 online' },
217
+ { name: 'env', type: '"prod" | "pre"', description: '请求环境,默认 prod' },
218
218
  { name: 'timeout', type: 'number', description: '超时毫秒数,默认 10000' },
219
219
  ],
220
220
  examples: [
@@ -310,7 +310,11 @@ export const COMMANDS = [
310
310
  aliases: ['tab_new', 'new_tab', 'tab_create', 'create_tab'],
311
311
  params: [
312
312
  { name: 'url', type: 'string', required: true, description: '要打开的 URL' },
313
- { name: 'active', type: 'boolean', description: '是否激活新 Tab,默认 false' },
313
+ {
314
+ name: 'active',
315
+ type: 'boolean',
316
+ description: '是否激活目标 Tab 并恢复最小化窗口,默认 false;响应返回 activation 验证结果',
317
+ },
314
318
  {
315
319
  name: 'openerTabId',
316
320
  type: 'number',
@@ -440,14 +444,14 @@ export const COMMANDS = [
440
444
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
441
445
  ],
442
446
  examples: [
443
- `page_click --payload '{"text":"提交"}'`,
444
- `page_click --payload '{"text":"退款明细","role":"button"}'`,
445
- `page_click --payload '{"text":"确定","scope":"@e12"}'`,
446
- `page_click --payload '{"selector":"@e3"}'`,
447
- `page_click --payload '{"selector":".submit-btn"}'`,
448
- `page_click --payload '{"selector":".gesture-btn","clickMode":"touch"}'`,
449
- `page_click --payload '{"point":{"x":336,"y":117}}'`,
450
- `page_click --payload '{"point":{"x":196,"y":240},"coordinateSpace":"active-frame"}'`,
447
+ `page_click --payload '{"tabId":12345,"text":"提交"}'`,
448
+ `page_click --payload '{"tabId":12345,"text":"退款明细","role":"button"}'`,
449
+ `page_click --payload '{"tabId":12345,"text":"确定","scope":"@e12"}'`,
450
+ `page_click --payload '{"tabId":12345,"selector":"@e3"}'`,
451
+ `page_click --payload '{"tabId":12345,"selector":".submit-btn"}'`,
452
+ `page_click --payload '{"tabId":12345,"selector":".gesture-btn","clickMode":"touch"}'`,
453
+ `page_click --payload '{"tabId":12345,"point":{"x":336,"y":117}}'`,
454
+ `page_click --payload '{"tabId":12345,"point":{"x":196,"y":240},"coordinateSpace":"active-frame"}'`,
451
455
  ],
452
456
  },
453
457
  {
@@ -481,8 +485,8 @@ export const COMMANDS = [
481
485
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
482
486
  ],
483
487
  examples: [
484
- `page_drag --payload '{"from":{"x":350,"y":80},"to":{"x":80,"y":80}}'`,
485
- `page_drag --payload '{"from":"@e3","to":"#drop-zone","dragMode":"mouse"}'`,
488
+ `page_drag --payload '{"tabId":12345,"from":{"x":350,"y":80},"to":{"x":80,"y":80}}'`,
489
+ `page_drag --payload '{"tabId":12345,"from":"@e3","to":"#drop-zone","dragMode":"mouse"}'`,
486
490
  ],
487
491
  },
488
492
  {
@@ -501,7 +505,7 @@ export const COMMANDS = [
501
505
  PAGE_DIAGNOSTICS_PARAM,
502
506
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
503
507
  ],
504
- examples: [`page_type --payload '{"selector":"@e6","text":"搜索关键词"}'`],
508
+ examples: [`page_type --payload '{"tabId":12345,"selector":"@e6","text":"搜索关键词"}'`],
505
509
  },
506
510
  {
507
511
  name: 'page_hover',
@@ -517,11 +521,11 @@ export const COMMANDS = [
517
521
  PAGE_DIAGNOSTICS_PARAM,
518
522
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
519
523
  ],
520
- examples: [`page_hover --payload '{"selector":".nav-menu"}'`],
524
+ examples: [`page_hover --payload '{"tabId":12345,"selector":".nav-menu"}'`],
521
525
  },
522
526
  {
523
527
  name: 'page_scroll',
524
- description: '滚动页面或指定容器',
528
+ description: '滚动页面或指定容器;页面根不可滚动时自动发现活动滚动区',
525
529
  params: [
526
530
  {
527
531
  name: 'direction',
@@ -545,10 +549,10 @@ export const COMMANDS = [
545
549
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
546
550
  ],
547
551
  examples: [
548
- `page_scroll --payload '{"direction":"down"}'`,
549
- `page_scroll --payload '{"direction":"bottom"}'`,
550
- `page_scroll --payload '{"selector":".virtual-list","direction":"down","distance":800}'`,
551
- `page_scroll --payload '{"selector":"@e8","containerPolicy":"nearest","direction":"bottom"}'`,
552
+ `page_scroll --payload '{"tabId":12345,"direction":"down"}'`,
553
+ `page_scroll --payload '{"tabId":12345,"direction":"bottom"}'`,
554
+ `page_scroll --payload '{"tabId":12345,"selector":".virtual-list","direction":"down","distance":800}'`,
555
+ `page_scroll --payload '{"tabId":12345,"selector":"@e8","containerPolicy":"nearest","direction":"bottom"}'`,
552
556
  ],
553
557
  },
554
558
  {
@@ -569,7 +573,46 @@ export const COMMANDS = [
569
573
  PAGE_DIAGNOSTICS_PARAM,
570
574
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
571
575
  ],
572
- examples: [`page_eval --payload '{"expression":"document.title"}'`],
576
+ examples: [`page_eval --payload '{"tabId":12345,"expression":"document.title"}'`],
577
+ },
578
+ {
579
+ name: 'page_inspect',
580
+ description: '查询 DOM 元素的数量、边框盒、计算样式、遮挡、溢出和最近滚动容器',
581
+ params: [
582
+ {
583
+ name: 'selector',
584
+ type: 'string',
585
+ description: '原生 CSS、page_snapshot 返回的 @eN ref,或 DevTools Elements 当前选区 $0;做全页溢出诊断时可省略',
586
+ },
587
+ {
588
+ name: 'filter',
589
+ type: '"all" | "overflowing" | "horizontal-overflow" | "vertical-overflow" | "scrollable"',
590
+ description: '结果过滤;省略 selector 时必须指定非 all 的过滤条件',
591
+ },
592
+ {
593
+ name: 'styles',
594
+ type: 'string[]',
595
+ description: '要返回的计算样式属性,默认 display/position/box-sizing/overflow-x/overflow-y',
596
+ },
597
+ {
598
+ name: 'maxResults',
599
+ type: 'number',
600
+ description: '最多返回的明细数,默认 20,最大 100;未触发 scanTruncated 时 count 为完整命中数',
601
+ },
602
+ {
603
+ name: 'includeOuterHTML',
604
+ type: 'boolean',
605
+ description: '是否返回 outerHTML(最多 3000 字符);$0 默认 true,其他目标默认 false',
606
+ },
607
+ { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
608
+ ],
609
+ examples: [
610
+ `page_inspect --payload '{"tabId":12345,"selector":".form-field","styles":["display","width"]}'`,
611
+ `page_inspect --payload '{"tabId":12345,"selector":"@e8"}'`,
612
+ `page_inspect --payload '{"tabId":12345,"selector":"$0"}'`,
613
+ `page_inspect --payload '{"tabId":12345,"filter":"horizontal-overflow"}'`,
614
+ `page_inspect --payload '{"tabId":12345,"filter":"scrollable"}'`,
615
+ ],
573
616
  },
574
617
  {
575
618
  name: 'page_press',
@@ -582,22 +625,38 @@ export const COMMANDS = [
582
625
  description: '按键名称:Enter/Tab/Escape/Backspace 等',
583
626
  },
584
627
  { name: 'modifiers', type: 'string[]', description: '修饰键数组:ctrl/alt/shift/meta/cmd' },
628
+ {
629
+ name: 'pressMode',
630
+ type: '"auto" | "dom" | "keyboard"',
631
+ description: '派发模式;auto 默认在隐藏页降级为 DOM 键盘事件',
632
+ },
585
633
  PAGE_OBSERVE_PARAM,
586
634
  PAGE_DIAGNOSTICS_PARAM,
587
635
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
588
636
  ],
589
- examples: [`page_press --payload '{"key":"Enter"}'`],
637
+ examples: [`page_press --payload '{"tabId":12345,"key":"Enter"}'`],
590
638
  },
591
639
  {
592
640
  name: 'page_wait',
593
- description: '等待指定时间、元素出现或页面条件成立',
641
+ description: '等待指定时间、元素状态、可见文本或页面条件成立',
594
642
  params: [
595
- { name: 'time', type: 'number', description: '等待毫秒数(与 selector 二选一)' },
643
+ {
644
+ name: 'time',
645
+ type: 'number',
646
+ description: '等待毫秒数(与 selector/text/condition 四选一)',
647
+ },
596
648
  {
597
649
  name: 'selector',
598
650
  type: 'string',
599
- description: '等待元素出现的 CSS 选择器(与 time/condition 三选一)',
651
+ description: '目标 CSS 选择器(与 time/text/condition 四选一)',
600
652
  },
653
+ {
654
+ name: 'state',
655
+ type: '"attached" | "detached" | "visible" | "hidden"',
656
+ description: 'selector 的目标状态,默认 attached',
657
+ },
658
+ { name: 'text', type: 'string', description: '等待页面出现的可见文本' },
659
+ { name: 'exact', type: 'boolean', description: 'text 是否精确匹配,默认 false' },
601
660
  {
602
661
  name: 'condition',
603
662
  type: 'string',
@@ -608,9 +667,11 @@ export const COMMANDS = [
608
667
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
609
668
  ],
610
669
  examples: [
611
- `page_wait --payload '{"time":1000}'`,
612
- `page_wait --payload '{"selector":".loaded"}'`,
613
- `page_wait --payload '{"condition":"window.appReady === true","timeout":30000}'`,
670
+ `page_wait --payload '{"tabId":12345,"time":1000}'`,
671
+ `page_wait --payload '{"tabId":12345,"selector":".dialog","state":"visible"}'`,
672
+ `page_wait --payload '{"tabId":12345,"selector":".loading","state":"hidden"}'`,
673
+ `page_wait --payload '{"tabId":12345,"text":"提交成功"}'`,
674
+ `page_wait --payload '{"tabId":12345,"condition":"window.appReady === true","timeout":30000}'`,
614
675
  ],
615
676
  },
616
677
  {
@@ -656,29 +717,29 @@ export const COMMANDS = [
656
717
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
657
718
  ],
658
719
  examples: [
659
- `page_upload --payload '{"selector":"#file-input","filePaths":["/Users/me/photo.jpg"]}'`,
720
+ `page_upload --payload '{"tabId":12345,"selector":"#file-input","filePaths":["/Users/me/photo.jpg"]}'`,
660
721
  ],
661
722
  },
662
723
  // ── 页面感知 ──────────────────────────────────────────────────────────────
663
724
  {
664
725
  name: 'page_snapshot',
665
- description: '获取页面无障碍树快照,支持完整、交互元素或当前视口范围(含 @ref)',
726
+ description: '获取带 @ref 的页面结构快照,默认使用无障碍树,也可显式读取渲染 DOM',
666
727
  params: [
667
728
  { name: 'depth', type: 'number', description: '树深度,默认 15,复杂页面可调大' },
668
729
  {
669
730
  name: 'mode',
670
- type: '"full" | "interactive" | "viewport"',
671
- description: '输出范围,默认 full;interactive 只保留当前视口内的语义控件;长列表优先使用 viewport',
731
+ type: '"full" | "interactive" | "viewport" | "dom"',
732
+ description: '默认 full;interactive/viewport 裁剪 AX 树;AX 信息缺失时可显式使用 dom 读取渲染 DOM',
672
733
  },
673
734
  {
674
735
  name: 'rootSelector',
675
736
  type: 'string',
676
- description: '只获取指定 CSS 元素的 AX 子树,可与 mode 组合;与 rootRef 互斥',
737
+ description: '只获取指定 CSS 元素的局部子树,可与 mode 组合;与 rootRef 互斥',
677
738
  },
678
739
  {
679
740
  name: 'rootRef',
680
741
  type: 'string',
681
- description: '以已有 @eN ref 为根获取局部 AX 子树;与 rootSelector 互斥',
742
+ description: '以已有 @eN ref 为根获取局部子树;与 rootSelector 互斥',
682
743
  },
683
744
  {
684
745
  name: 'ancestorDepth',
@@ -688,7 +749,7 @@ export const COMMANDS = [
688
749
  {
689
750
  name: 'query',
690
751
  type: '{ text?: string; role?: string; exact?: boolean }',
691
- description: '服务端过滤 AX 树,只保留按 accessibility name / role 命中的节点及祖先路径',
752
+ description: '服务端按 name / role 过滤当前模式的树,只保留命中节点及祖先路径',
692
753
  },
693
754
  { name: 'maxNodes', type: 'number', description: '最多输出节点数,0 表示不限制' },
694
755
  {
@@ -699,8 +760,9 @@ export const COMMANDS = [
699
760
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
700
761
  ],
701
762
  examples: [
702
- 'page_snapshot',
763
+ `page_snapshot --payload '{"tabId":12345}'`,
703
764
  `page_snapshot --payload '{"tabId":1,"mode":"viewport"}'`,
765
+ `page_snapshot --payload '{"tabId":1,"mode":"dom"}'`,
704
766
  `page_snapshot --payload '{"tabId":1,"rootSelector":"[role=dialog]"}'`,
705
767
  `page_snapshot --payload '{"tabId":1,"rootRef":"@e8","ancestorDepth":1}'`,
706
768
  `page_snapshot --payload '{"tabId":1,"query":{"text":"保存","role":"button"}}'`,
@@ -717,29 +779,10 @@ export const COMMANDS = [
717
779
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
718
780
  ],
719
781
  examples: [
720
- 'page_screenshot --output ./screenshot.png',
721
- `page_screenshot --payload '{"selector":".product-card"}' --output ./card.png`,
782
+ `page_screenshot --payload '{"tabId":12345}' --output ./screenshot.png`,
783
+ `page_screenshot --payload '{"tabId":12345,"selector":".product-card"}' --output ./card.png`,
722
784
  ],
723
785
  },
724
- {
725
- name: 'page_selected_element',
726
- description: '获取 DevTools Elements 面板当前选中元素的详细信息',
727
- outputFlag: true,
728
- params: [
729
- {
730
- name: 'includeOuterHTML',
731
- type: 'boolean',
732
- description: '是否返回 outerHTML(最多 3000 字符),默认 true',
733
- },
734
- {
735
- name: 'includeScreenshot',
736
- type: 'boolean',
737
- description: '是否附带元素截图,默认 false;指定 --output 时自动开启',
738
- },
739
- { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
740
- ],
741
- examples: ['page_selected_element', 'page_selected_element --output ./element.png'],
742
- },
743
786
  // ── 移动端模拟 ────────────────────────────────────────────────────────────
744
787
  {
745
788
  name: 'set_device_emulation',
@@ -786,15 +829,15 @@ export const COMMANDS = [
786
829
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
787
830
  ],
788
831
  examples: [
789
- `set_device_emulation --payload '{"enabled":true,"preset":"iphone-17-pro"}'`,
790
- `set_device_emulation --payload '{"enabled":true,"preset":"pixel-11","orientation":"landscape"}'`,
791
- `set_device_emulation --payload '{"enabled":true,"preset":"ipad-mini-a17-pro","orientation":"landscape","deviceShell":true,"splitScreen":true}'`,
792
- `set_device_emulation --payload '{"enabled":false}'`,
832
+ `set_device_emulation --payload '{"tabId":12345,"enabled":true,"preset":"iphone-17-pro"}'`,
833
+ `set_device_emulation --payload '{"tabId":12345,"enabled":true,"preset":"pixel-11","orientation":"landscape"}'`,
834
+ `set_device_emulation --payload '{"tabId":12345,"enabled":true,"preset":"ipad-mini-a17-pro","orientation":"landscape","deviceShell":true,"splitScreen":true}'`,
835
+ `set_device_emulation --payload '{"tabId":12345,"enabled":false}'`,
793
836
  ],
794
837
  },
795
838
  {
796
839
  name: 'set_app_profile',
797
- description: '设置 App 客户端环境与 JSBridge;传 emulation 时由同一个命令联动设备模拟,省略时不改变设备状态',
840
+ description: '设置 App 客户端环境与 JSBridge;可同时设置 MTop 页面接口环境,传 emulation 时联动设备模拟',
798
841
  summary: '设置或清除目标标签页的 App 容器模拟',
799
842
  params: [
800
843
  { name: 'enabled', type: 'boolean', required: true, description: 'true=启用,false=清除' },
@@ -815,6 +858,11 @@ export const COMMANDS = [
815
858
  type: 'object',
816
859
  description: '声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}};不执行配置脚本',
817
860
  },
861
+ {
862
+ name: 'mtopEnv',
863
+ type: '"default" | "prod" | "pre"',
864
+ description: '可选 MTop 页面接口环境;default 关闭环境改写,省略时保持当前设置。扩展模式全局生效,CDP 模式仅作用于目标 tab',
865
+ },
818
866
  {
819
867
  name: 'emulation',
820
868
  type: 'object',
@@ -824,12 +872,14 @@ export const COMMANDS = [
824
872
  { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
825
873
  ],
826
874
  examples: [
827
- `set_app_profile --payload '{"enabled":true,"profile":"fliggy"}'`,
828
- `set_app_profile --payload '{"enabled":true,"profile":"fliggy","emulation":{}}'`,
829
- `set_app_profile --payload '{"enabled":true,"profile":"alipay","emulation":{"preset":"pixel-11","deviceShell":true}}'`,
830
- `set_app_profile --payload '{"enabled":true,"profile":"fliggy","emulation":{"preset":"ipad-mini-a17-pro","orientation":"landscape","deviceShell":true,"splitScreen":true}}'`,
831
- `set_app_profile --payload '{"enabled":false}'`,
832
- `set_app_profile --payload '{"enabled":false,"emulation":{}}'`,
875
+ `set_app_profile --payload '{"tabId":12345,"enabled":true,"profile":"fliggy"}'`,
876
+ `set_app_profile --payload '{"tabId":12345,"enabled":true,"profile":"fliggy","mtopEnv":"pre"}'`,
877
+ `set_app_profile --payload '{"tabId":12345,"enabled":false,"mtopEnv":"prod"}'`,
878
+ `set_app_profile --payload '{"tabId":12345,"enabled":true,"profile":"fliggy","emulation":{}}'`,
879
+ `set_app_profile --payload '{"tabId":12345,"enabled":true,"profile":"alipay","emulation":{"preset":"pixel-11","deviceShell":true}}'`,
880
+ `set_app_profile --payload '{"tabId":12345,"enabled":true,"profile":"fliggy","emulation":{"preset":"ipad-mini-a17-pro","orientation":"landscape","deviceShell":true,"splitScreen":true}}'`,
881
+ `set_app_profile --payload '{"tabId":12345,"enabled":false}'`,
882
+ `set_app_profile --payload '{"tabId":12345,"enabled":false,"emulation":{}}'`,
833
883
  ],
834
884
  },
835
885
  {
@@ -95,13 +95,15 @@ export interface SendRequestParams {
95
95
  responseType?: 'json' | 'text' | 'auto';
96
96
  timeout?: number;
97
97
  }
98
+ export type MtopEnvironmentTarget = 'prod' | 'pre';
99
+ export type MtopEnvironment = 'default' | MtopEnvironmentTarget;
98
100
  export interface SendMtopRequestParams {
99
101
  api: string;
100
102
  data?: unknown;
101
103
  version?: string;
102
104
  method?: string;
103
105
  appKey?: string;
104
- env?: string;
106
+ env?: MtopEnvironmentTarget;
105
107
  timeout?: number;
106
108
  headers?: Record<string, string>;
107
109
  ttid?: string;
@@ -341,16 +343,11 @@ export interface RulesResult {
341
343
  rules: Array<Record<string, unknown>>;
342
344
  }
343
345
  export interface PageScreenshotParams {
344
- tabId?: number;
346
+ tabId: number;
345
347
  selector?: string;
346
348
  format?: 'png' | 'jpeg';
347
349
  quality?: number;
348
350
  }
349
- export interface PageSelectedElementParams {
350
- tabId?: number;
351
- includeOuterHTML?: boolean;
352
- includeScreenshot?: boolean;
353
- }
354
351
  export declare const BROWSER_DEVICE_PRESET_NAMES: readonly ["iphone-17-pro", "iphone-17e", "pixel-11", "ipad-mini-a17-pro", "galaxy-s26", "pura-x-max", "iphone-15-pro", "iphone-se", "pixel-8", "ipad-mini", "galaxy-s23"];
355
352
  export type BrowserDevicePresetName = (typeof BROWSER_DEVICE_PRESET_NAMES)[number];
356
353
  export interface BrowserEmulationOptions {
@@ -417,7 +414,7 @@ export interface TabOpenParams {
417
414
  export declare const APP_PROFILE_NAMES: readonly ["fliggy", "taobao", "wechat", "tmall", "alipay", "koubei", "taobao-tj", "taobao-live", "xianyu", "etao", "eleme", "damai", "btrip", "amap", "qianwen", "lingyou", "didi", "easybike"];
418
415
  export type AppProfileName = (typeof APP_PROFILE_NAMES)[number];
419
416
  export interface SetAppProfileParams {
420
- tabId?: number;
417
+ tabId: number;
421
418
  /** false 时清除该 tab 的容器模拟并刷新 */
422
419
  enabled: boolean;
423
420
  /** 容器档案名(enabled=true 时必填) */
@@ -427,6 +424,11 @@ export interface SetAppProfileParams {
427
424
  deviceModel?: string;
428
425
  /** 按方法覆盖档案内置桥配置,仅支持受控行为、固定 JSON 回包和成功空实现 */
429
426
  bridgeConfig?: AppBridgeConfig;
427
+ /**
428
+ * 可选 MTop 接口环境。default 关闭环境改写;省略时保持当前设置。
429
+ * 扩展模式与插件设置页共享并全局生效;CDP 模式仅作用于目标 tab。
430
+ */
431
+ mtopEnv?: MtopEnvironment;
430
432
  /**
431
433
  * 可选设备联动参数。传入时显式字段覆盖档案推荐设备,空对象使用推荐设备且默认开启
432
434
  * deviceShell;省略时不设置或清除该 tab 的设备状态。
@@ -454,7 +456,7 @@ export interface PageDiagnosticsOptions {
454
456
  }
455
457
  export type PageDiagnosticsSetting = PageDiagnosticsOptions | boolean;
456
458
  export interface PageClickParams {
457
- tabId?: number;
459
+ tabId: number;
458
460
  selector?: string;
459
461
  text?: string;
460
462
  point?: {
@@ -478,7 +480,7 @@ export interface PageDragPoint {
478
480
  }
479
481
  export type PageDragEndpoint = string | PageDragPoint;
480
482
  export interface PageDragParams {
481
- tabId?: number;
483
+ tabId: number;
482
484
  from: PageDragEndpoint;
483
485
  to: PageDragEndpoint;
484
486
  dragMode?: 'auto' | 'dom' | 'mouse' | 'touch';
@@ -487,7 +489,7 @@ export interface PageDragParams {
487
489
  diagnostics?: PageDiagnosticsSetting;
488
490
  }
489
491
  export interface PageTypeParams {
490
- tabId?: number;
492
+ tabId: number;
491
493
  selector: string;
492
494
  text: string;
493
495
  clearFirst?: boolean;
@@ -495,7 +497,7 @@ export interface PageTypeParams {
495
497
  diagnostics?: PageDiagnosticsSetting;
496
498
  }
497
499
  export interface PageScrollParams {
498
- tabId?: number;
500
+ tabId: number;
499
501
  direction: 'up' | 'down' | 'top' | 'bottom';
500
502
  distance?: number;
501
503
  selector?: string;
@@ -504,13 +506,13 @@ export interface PageScrollParams {
504
506
  diagnostics?: PageDiagnosticsSetting;
505
507
  }
506
508
  export interface PageHoverParams {
507
- tabId?: number;
509
+ tabId: number;
508
510
  selector: string;
509
511
  observe?: PageObservationWaitOptions | false;
510
512
  diagnostics?: PageDiagnosticsSetting;
511
513
  }
512
514
  export interface PageEvalParams {
513
- tabId?: number;
515
+ tabId: number;
514
516
  expression: string;
515
517
  frameId?: string;
516
518
  awaitPromise?: boolean;
@@ -523,7 +525,7 @@ export interface PageSnapshotQuery {
523
525
  exact?: boolean;
524
526
  }
525
527
  export interface PageSnapshotParams {
526
- tabId?: number;
528
+ tabId: number;
527
529
  depth?: number;
528
530
  maxChars?: number;
529
531
  maxNodes?: number;
@@ -531,46 +533,65 @@ export interface PageSnapshotParams {
531
533
  rootRef?: string;
532
534
  ancestorDepth?: number;
533
535
  query?: PageSnapshotQuery;
534
- mode?: 'full' | 'interactive' | 'viewport';
536
+ mode?: 'full' | 'interactive' | 'viewport' | 'dom';
537
+ }
538
+ export type PageInspectFilter = 'all' | 'overflowing' | 'horizontal-overflow' | 'vertical-overflow' | 'scrollable';
539
+ export interface PageInspectParams {
540
+ tabId: number;
541
+ /** Native CSS selector, a page_snapshot @ref, or DevTools' current selection ($0). */
542
+ selector?: string;
543
+ /** Limit results after filtering. Defaults to 20, maximum 100. */
544
+ maxResults?: number;
545
+ /** Computed-style properties to return. Defaults to common layout properties. */
546
+ styles?: string[];
547
+ /** Page-wide or selector-scoped layout filter. Defaults to all. */
548
+ filter?: PageInspectFilter;
549
+ /** Include a trimmed outerHTML string for returned matches. Defaults to true for $0. */
550
+ includeOuterHTML?: boolean;
535
551
  }
536
552
  export interface PagePressParams {
537
- tabId?: number;
553
+ tabId: number;
538
554
  key: string;
539
555
  modifiers?: string[];
556
+ /** Dispatch strategy. Auto uses DOM events when the page is hidden. */
557
+ pressMode?: 'auto' | 'dom' | 'keyboard';
540
558
  observe?: PageObservationWaitOptions | false;
541
559
  diagnostics?: PageDiagnosticsSetting;
542
560
  }
543
561
  export interface PageWaitParams {
544
- tabId?: number;
562
+ tabId: number;
545
563
  time?: number;
546
564
  selector?: string;
565
+ state?: 'attached' | 'detached' | 'visible' | 'hidden';
566
+ text?: string;
567
+ exact?: boolean;
547
568
  condition?: string;
548
569
  timeout?: number;
549
570
  interval?: number;
550
571
  }
551
572
  export interface PageNavigateParams {
552
- tabId?: number;
573
+ tabId: number;
553
574
  url?: string;
554
575
  refresh?: boolean;
555
576
  history?: 'back' | 'forward';
556
577
  }
557
578
  export interface PageUploadParams {
558
- tabId?: number;
579
+ tabId: number;
559
580
  selector: string;
560
581
  filePaths: string[];
561
582
  observe?: PageObservationWaitOptions | false;
562
583
  diagnostics?: PageDiagnosticsSetting;
563
584
  }
564
585
  export interface PageFramesParams {
565
- tabId?: number;
586
+ tabId: number;
566
587
  }
567
588
  export interface SetDeviceEmulationParams extends BrowserEmulationOptions {
568
- tabId?: number;
589
+ tabId: number;
569
590
  enabled: boolean;
570
591
  reload?: boolean;
571
592
  }
572
593
  export interface SetTimezoneParams {
573
- tabId?: number;
594
+ tabId: number;
574
595
  timezone: string;
575
596
  }
576
597
  export interface SetTimezoneResult {
@@ -578,7 +599,7 @@ export interface SetTimezoneResult {
578
599
  timezone: string | null;
579
600
  }
580
601
  export interface GetCookieParams {
581
- tabId?: number;
602
+ tabId: number;
582
603
  name: string;
583
604
  /** Cookie lookup URL; defaults to the current tab URL. */
584
605
  url?: string;
@@ -595,7 +616,7 @@ export interface GetCookieResult {
595
616
  path?: string;
596
617
  }
597
618
  export interface SetCookieParams {
598
- tabId?: number;
619
+ tabId: number;
599
620
  name: string;
600
621
  value: string;
601
622
  domain?: string;
@@ -692,10 +713,6 @@ export interface BrowserActionMap {
692
713
  request: PageScreenshotParams;
693
714
  response: unknown;
694
715
  };
695
- page_selected_element: {
696
- request: PageSelectedElementParams;
697
- response: unknown;
698
- };
699
716
  tab_open: {
700
717
  request: TabOpenParams;
701
718
  response: unknown;
@@ -732,6 +749,10 @@ export interface BrowserActionMap {
732
749
  request: PageEvalParams;
733
750
  response: unknown;
734
751
  };
752
+ page_inspect: {
753
+ request: PageInspectParams;
754
+ response: unknown;
755
+ };
735
756
  page_snapshot: {
736
757
  request: PageSnapshotParams;
737
758
  response: unknown;
@@ -790,6 +811,10 @@ export type BrowserActionRequest<A extends BrowserAction> = BrowserActionMap[A][
790
811
  export type BrowserActionResponse<A extends BrowserAction> = BrowserActionMap[A]['response'];
791
812
  export type BrowserCommandAction = Exclude<BrowserAction, 'browser_select_browser'>;
792
813
  export type ExtensionBrowserAction = Exclude<BrowserCommandAction, 'browser_list' | 'browser_launch' | 'browser_close'>;
814
+ export declare const TAB_ID_REQUIRED_ACTIONS: readonly ["page_screenshot", "tab_close", "page_click", "page_drag", "page_type", "page_scroll", "page_hover", "page_eval", "page_inspect", "page_snapshot", "page_press", "page_wait", "page_navigate", "page_upload", "page_frames", "set_device_emulation", "set_app_profile", "set_timezone", "get_cookie", "set_cookie", "run_actions"];
815
+ export type TabIdRequiredAction = (typeof TAB_ID_REQUIRED_ACTIONS)[number];
816
+ export declare function actionRequiresTabId(action: unknown): action is TabIdRequiredAction;
817
+ export declare function validateRequiredActionTabId(action: string, data: unknown): void;
793
818
  export declare const PAGE_ACT_ACTIONS: readonly ["page_click", "page_drag", "page_type", "page_hover", "page_scroll", "page_press", "page_upload", "page_eval"];
794
819
  export type PageActAction = (typeof PAGE_ACT_ACTIONS)[number];
795
820
  export declare const BROWSER_ACTIONS: {
@@ -810,7 +835,6 @@ export declare const BROWSER_ACTIONS: {
810
835
  readonly browser_launch: true;
811
836
  readonly browser_close: true;
812
837
  readonly page_screenshot: true;
813
- readonly page_selected_element: true;
814
838
  readonly tab_open: true;
815
839
  readonly tab_close: true;
816
840
  readonly tab_list: true;
@@ -820,6 +844,7 @@ export declare const BROWSER_ACTIONS: {
820
844
  readonly page_scroll: true;
821
845
  readonly page_hover: true;
822
846
  readonly page_eval: true;
847
+ readonly page_inspect: true;
823
848
  readonly page_snapshot: true;
824
849
  readonly page_press: true;
825
850
  readonly page_wait: true;
@@ -851,7 +876,6 @@ export declare const BROWSER_COMMAND_ACTIONS: {
851
876
  readonly browser_launch: true;
852
877
  readonly browser_close: true;
853
878
  readonly page_screenshot: true;
854
- readonly page_selected_element: true;
855
879
  readonly tab_open: true;
856
880
  readonly tab_close: true;
857
881
  readonly tab_list: true;
@@ -861,6 +885,7 @@ export declare const BROWSER_COMMAND_ACTIONS: {
861
885
  readonly page_scroll: true;
862
886
  readonly page_hover: true;
863
887
  readonly page_eval: true;
888
+ readonly page_inspect: true;
864
889
  readonly page_snapshot: true;
865
890
  readonly page_press: true;
866
891
  readonly page_wait: true;
@@ -889,7 +914,6 @@ export declare const EXTENSION_BROWSER_ACTIONS: {
889
914
  readonly send_mtop_request: true;
890
915
  readonly browser_release: true;
891
916
  readonly page_screenshot: true;
892
- readonly page_selected_element: true;
893
917
  readonly tab_open: true;
894
918
  readonly tab_close: true;
895
919
  readonly tab_list: true;
@@ -899,6 +923,7 @@ export declare const EXTENSION_BROWSER_ACTIONS: {
899
923
  readonly page_scroll: true;
900
924
  readonly page_hover: true;
901
925
  readonly page_eval: true;
926
+ readonly page_inspect: true;
902
927
  readonly page_snapshot: true;
903
928
  readonly page_press: true;
904
929
  readonly page_wait: true;
@@ -48,6 +48,43 @@ export const APP_PROFILE_NAMES = [
48
48
  'didi',
49
49
  'easybike',
50
50
  ];
51
+ export const TAB_ID_REQUIRED_ACTIONS = [
52
+ 'page_screenshot',
53
+ 'tab_close',
54
+ 'page_click',
55
+ 'page_drag',
56
+ 'page_type',
57
+ 'page_scroll',
58
+ 'page_hover',
59
+ 'page_eval',
60
+ 'page_inspect',
61
+ 'page_snapshot',
62
+ 'page_press',
63
+ 'page_wait',
64
+ 'page_navigate',
65
+ 'page_upload',
66
+ 'page_frames',
67
+ 'set_device_emulation',
68
+ 'set_app_profile',
69
+ 'set_timezone',
70
+ 'get_cookie',
71
+ 'set_cookie',
72
+ 'run_actions',
73
+ ];
74
+ const TAB_ID_REQUIRED_ACTION_SET = new Set(TAB_ID_REQUIRED_ACTIONS);
75
+ export function actionRequiresTabId(action) {
76
+ return typeof action === 'string' && TAB_ID_REQUIRED_ACTION_SET.has(action);
77
+ }
78
+ export function validateRequiredActionTabId(action, data) {
79
+ if (!actionRequiresTabId(action))
80
+ return;
81
+ const tabId = data && typeof data === 'object' && !Array.isArray(data)
82
+ ? data.tabId
83
+ : undefined;
84
+ if (typeof tabId !== 'number' || !Number.isSafeInteger(tabId) || tabId < 0) {
85
+ throw new Error(`${action} requires a numeric tabId. Call tab_open or tab_list to obtain a tabId.`);
86
+ }
87
+ }
51
88
  export const PAGE_ACT_ACTIONS = [
52
89
  'page_click',
53
90
  'page_drag',
@@ -76,7 +113,6 @@ export const BROWSER_ACTIONS = {
76
113
  browser_launch: true,
77
114
  browser_close: true,
78
115
  page_screenshot: true,
79
- page_selected_element: true,
80
116
  tab_open: true,
81
117
  tab_close: true,
82
118
  tab_list: true,
@@ -86,6 +122,7 @@ export const BROWSER_ACTIONS = {
86
122
  page_scroll: true,
87
123
  page_hover: true,
88
124
  page_eval: true,
125
+ page_inspect: true,
89
126
  page_snapshot: true,
90
127
  page_press: true,
91
128
  page_wait: true,
@@ -117,7 +154,6 @@ export const BROWSER_COMMAND_ACTIONS = {
117
154
  browser_launch: true,
118
155
  browser_close: true,
119
156
  page_screenshot: true,
120
- page_selected_element: true,
121
157
  tab_open: true,
122
158
  tab_close: true,
123
159
  tab_list: true,
@@ -127,6 +163,7 @@ export const BROWSER_COMMAND_ACTIONS = {
127
163
  page_scroll: true,
128
164
  page_hover: true,
129
165
  page_eval: true,
166
+ page_inspect: true,
130
167
  page_snapshot: true,
131
168
  page_press: true,
132
169
  page_wait: true,
@@ -155,7 +192,6 @@ export const EXTENSION_BROWSER_ACTIONS = {
155
192
  send_mtop_request: true,
156
193
  browser_release: true,
157
194
  page_screenshot: true,
158
- page_selected_element: true,
159
195
  tab_open: true,
160
196
  tab_close: true,
161
197
  tab_list: true,
@@ -165,6 +201,7 @@ export const EXTENSION_BROWSER_ACTIONS = {
165
201
  page_scroll: true,
166
202
  page_hover: true,
167
203
  page_eval: true,
204
+ page_inspect: true,
168
205
  page_snapshot: true,
169
206
  page_press: true,
170
207
  page_wait: true,
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ export { UnifiedClient, UnifiedClient as MearlClient, decodeBrowserTarget, invok
8
8
  export type { UnifiedClientOptions, UnifiedInvokeOptions, UnifiedInvokeOptions as InvokeOptions, } from './unified.js';
9
9
  export type { PluginInvocation, PluginInvokeOptions } from './plugin.js';
10
10
  export { APP_PROFILE_NAMES, BROWSER_DEVICE_PRESET_NAMES, BROWSER_ACTIONS, BROWSER_COMMAND_ACTIONS, EXTENSION_BROWSER_ACTIONS, PAGE_ACT_ACTIONS, SEND_REQUEST_MAX_FILES, SEND_REQUEST_MAX_TOTAL_BASE64_FILE_BYTES, SEND_REQUEST_MAX_TOTAL_FILE_BYTES, isBrowserAction, isBrowserCapabilityAction, isBrowserCommandAction, isExtensionBrowserAction, } from './generated-browser-action-protocol.js';
11
- export type { ActionStep, AppProfileName, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCapabilities, BrowserCapabilityAction, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserJsonValue, BrowserLaunchParams, BrowserProviderOperation, BrowserListResult, BrowserPairingInfo, BrowserReleaseFailure, BrowserReleaseResult, BrowserProviderDefinition, BrowserProviderIdentity, BrowserProviderInputSchema, BrowserProviderListResult, BrowserReference, BrowserDetails, BrowserSource, BrowserStatus, BrowserScreenshotKind, BrowserTransport, CaptureCheckpointParams, CaptureCheckpointResult, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, ManagedBrowserInfo, PageClickParams, PageDragEndpoint, PageDragParams, PageDragPoint, PageActAction, PageDiagnosticsOptions, PageDiagnosticsSetting, PageEvalParams, PageFramesParams, PageHoverParams, PageNavigateParams, PageObservationWaitOptions, PagePressParams, PageScreenshotParams, PageScrollParams, PageSelectedElementParams, PageSnapshotParams, PageSnapshotQuery, PageTypeParams, PageUploadParams, PageWaitParams, RegularBrowserInfo, RequestDomainPermissionParams, RulesResult, RunActionName, RunActionsParams, SelectBrowserParams, SelectBrowserResult, SendRequestFile, SendRequestFormValue, SendMtopRequestParams, SendRequestParams, SetAppProfileParams, SetCookieParams, SetCookieResult, SetDeviceEmulationParams, SetMockParams, SetRuleParams, SetTimezoneParams, SetTimezoneResult, TabCloseParams, TabOpenParams, } from './generated-browser-action-protocol.js';
11
+ export type { ActionStep, AppProfileName, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCapabilities, BrowserCapabilityAction, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserJsonValue, BrowserLaunchParams, BrowserProviderOperation, BrowserListResult, BrowserPairingInfo, BrowserReleaseFailure, BrowserReleaseResult, BrowserProviderDefinition, BrowserProviderIdentity, BrowserProviderInputSchema, BrowserProviderListResult, BrowserReference, BrowserDetails, BrowserSource, BrowserStatus, BrowserScreenshotKind, BrowserTransport, CaptureCheckpointParams, CaptureCheckpointResult, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, ManagedBrowserInfo, PageClickParams, PageDragEndpoint, PageDragParams, PageDragPoint, PageActAction, PageDiagnosticsOptions, PageDiagnosticsSetting, PageEvalParams, PageFramesParams, PageHoverParams, PageInspectFilter, PageInspectParams, PageNavigateParams, PageObservationWaitOptions, PagePressParams, PageScreenshotParams, PageScrollParams, PageSnapshotParams, PageSnapshotQuery, PageTypeParams, PageUploadParams, PageWaitParams, RegularBrowserInfo, RequestDomainPermissionParams, RulesResult, RunActionName, RunActionsParams, SelectBrowserParams, SelectBrowserResult, SendRequestFile, SendRequestFormValue, SendMtopRequestParams, SendRequestParams, SetAppProfileParams, SetCookieParams, SetCookieResult, SetDeviceEmulationParams, SetMockParams, SetRuleParams, SetTimezoneParams, SetTimezoneResult, TabCloseParams, TabOpenParams, } from './generated-browser-action-protocol.js';
12
12
  import { type UnifiedInvokeOptions } from './unified.js';
13
13
  import type * as Protocol from './generated-browser-action-protocol.js';
14
14
  export declare function tabCheckpoint(params?: Protocol.CaptureCheckpointParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_checkpoint'>>;
@@ -29,7 +29,6 @@ export declare function browserClose(params: Protocol.BrowserCloseParams, option
29
29
  export declare function setRule(params: Protocol.SetRuleParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'set_rule'>>;
30
30
  export declare function getRules(options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'get_rules'>>;
31
31
  export declare function pageScreenshot(params: Protocol.PageScreenshotParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_screenshot'>>;
32
- export declare function pageSelectedElement(params: Protocol.PageSelectedElementParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_selected_element'>>;
33
32
  export declare function tabOpen(params: Protocol.TabOpenParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_open'>>;
34
33
  export declare function tabClose(params: Protocol.TabCloseParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_close'>>;
35
34
  export declare function tabList(options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_list'>>;
@@ -39,6 +38,7 @@ export declare function pageType(params: Protocol.PageTypeParams, options?: Unif
39
38
  export declare function pageScroll(params: Protocol.PageScrollParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_scroll'>>;
40
39
  export declare function pageHover(params: Protocol.PageHoverParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_hover'>>;
41
40
  export declare function pageEval(params: Protocol.PageEvalParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_eval'>>;
41
+ export declare function pageInspect(params: Protocol.PageInspectParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_inspect'>>;
42
42
  export declare function pageSnapshot(params: Protocol.PageSnapshotParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_snapshot'>>;
43
43
  export declare function pagePress(params: Protocol.PagePressParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_press'>>;
44
44
  export declare function pageWait(params: Protocol.PageWaitParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_wait'>>;
package/dist/index.js CHANGED
@@ -59,9 +59,6 @@ export function getRules(options) {
59
59
  export function pageScreenshot(params, options) {
60
60
  return invoke('page_screenshot', params, options);
61
61
  }
62
- export function pageSelectedElement(params, options) {
63
- return invoke('page_selected_element', params, options);
64
- }
65
62
  export function tabOpen(params, options) {
66
63
  return invoke('tab_open', params, options);
67
64
  }
@@ -89,6 +86,9 @@ export function pageHover(params, options) {
89
86
  export function pageEval(params, options) {
90
87
  return invoke('page_eval', params, options);
91
88
  }
89
+ export function pageInspect(params, options) {
90
+ return invoke('page_inspect', params, options);
91
+ }
92
92
  export function pageSnapshot(params, options) {
93
93
  return invoke('page_snapshot', params, options);
94
94
  }
package/dist/socket.js CHANGED
@@ -117,6 +117,9 @@ function supportsAction(browser, action, data) {
117
117
  const required = data.deleteProfile === true ? 'deleteData' : 'close';
118
118
  return browser.operations?.includes(required) === true;
119
119
  }
120
+ if (action === 'browser_release') {
121
+ return browser.transport !== 'provider' || browser.operations?.includes('detach') === true;
122
+ }
120
123
  if (!isConnectedBrowser(browser))
121
124
  return false;
122
125
  return (browser.transport !== 'provider' ||
@@ -282,7 +285,10 @@ async function dispatchInvoke(action, data, timeoutSec, transport, selector, con
282
285
  if (transport === 'cdp' && match.transport === 'provider') {
283
286
  throw new Error(`Browser ${describeBrowser(match)} does not support the CDP transport`);
284
287
  }
285
- if (match.status === 'pairing' && action !== 'get_versions' && action !== 'browser_close') {
288
+ if (match.status === 'pairing' &&
289
+ action !== 'get_versions' &&
290
+ action !== 'browser_close' &&
291
+ action !== 'browser_release') {
286
292
  throw new Error(`Browser ${describeBrowser(match)} is waiting for device pairing`);
287
293
  }
288
294
  if (!supportsAction(match, action, data)) {
package/dist/unified.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import WebSocket from 'ws';
2
2
  import { DEFAULT_CONNECT_TIMEOUT, DEFAULT_HEARTBEAT_INTERVAL, DEFAULT_REQUEST_TIMEOUT, MAX_BUFFER_SIZE, isHeartbeatMessage, resolveCloudConnectorSelector, } from '@mearl/cloud-types';
3
3
  import { resolveActionTimeoutSec } from './actionTimeouts.js';
4
+ import { validateRequiredActionTabId, } from './generated-browser-action-protocol.js';
4
5
  import { invoke as invokeLocalBrowser } from './socket.js';
5
6
  import { loadCloudServerConfig, loadLocalConnectorId } from './unifiedConfig.js';
6
7
  const RESPONSE_GRACE_MS = 1_000;
@@ -126,6 +127,7 @@ export class UnifiedClient {
126
127
  }, options);
127
128
  }
128
129
  async invoke(action, data = {}, options = {}) {
130
+ validateRequiredActionTabId(action, data);
129
131
  const timeoutSec = options.timeoutSec ?? resolveActionTimeoutSec(action, data, this.options.requestTimeoutSec);
130
132
  if (action === 'connector_list')
131
133
  return this.listConnectors(timeoutSec);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mearl/client",
3
- "version": "2.16.4",
3
+ "version": "2.17.1",
4
4
  "description": "Unified Mearl SDK & CLI for local and remote browsers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -59,8 +59,8 @@
59
59
  "commander": "^15.0.0",
60
60
  "fastest-levenshtein": "^1.0.16",
61
61
  "ws": "^8.18.0",
62
- "@mearl/cloud-types": "2.16.4",
63
- "@mearl/provider": "2.16.4"
62
+ "@mearl/cloud-types": "2.17.1",
63
+ "@mearl/provider": "2.17.1"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@types/node": "^24.9.1",