@mearl/client 2.17.0 → 2.18.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/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
@@ -148,7 +149,7 @@ mearl yuque --version
148
149
  Provider 与插件仍可独立安装、更新和卸载,帮助聚合不会启动 Provider 或执行业务命令。
149
150
 
150
151
  目录默认使用 `scripts/main.mjs` 或 `scripts/main.py`;两者同时存在时使用 JavaScript 入口。JavaScript 入口默认导出 `register(app)`,Python 入口导出 `register(app)` 函数;两种入口都可声明简短的 `name` 和 `description`,并通过 `app.command(signature, handler, description?)`
151
- 注册动作、`app.invoke(action, payload, options?)` 复用当前浏览器上下文,并用 `app.progress(message)` 报告可选进度。Python 的 `app.invoke` 是同步调用,handler 可以是普通函数或 `async def`。Python 插件要求 `python3 >= 3.9`,可用 `MEARL_PYTHON` 指定解释器路径;Mearl 不安装 Python 或执行 `pip install`。调用另一个插件时,payload 使用 `{ command, input }` envelope;嵌套调用继承宿主选项并拒绝循环依赖。CLI 默认只输出最终结果,传入
152
+ 注册动作、`app.invoke(action, payload, options?)` 复用当前浏览器上下文,并用 `app.progress(message)` 报告可选进度。JavaScript 插件还可传入 `{ message, data }`,让工具页通过可 JSON 序列化的 `data` 获取稳定的阶段、对象 ID 等机器信息;CLI 仍只显示 `message`。Python 的 `app.invoke` 是同步调用,handler 可以是普通函数或 `async def`。Python 插件要求 `python3 >= 3.9`,可用 `MEARL_PYTHON` 指定解释器路径;Mearl 不安装 Python 或执行 `pip install`。调用另一个插件时,payload 使用 `{ command, input }` envelope;嵌套调用继承宿主选项并拒绝循环依赖。CLI 默认只输出最终结果,传入
152
153
  `--verbose` 时才把进度写入 stderr。handler 返回文本或 JSON,宿主统一处理 `--output`、连接和错误。写命令在用户调用后直接执行,业务模块负责目标、状态、幂等和结果校验。
153
154
  自动注册默认以 skill 安装目录名作为命令名,也可在入口声明 `name` 指定短名称。
154
155
  setup 会补齐缺失或低于自身版本的 client、native-host;安装参数透传给 Ali Skills,并固定全局共享安装。
@@ -185,6 +186,59 @@ MCP Server 通过固定工具 `mearl_plugin` 接受同样的 `plugin`、`command
185
186
  卸载清理命令。其他错误按实际原因处理。
186
187
  编写规范见 [Mearl Skill Creator 的 Skill 插件规范](../skills/mearl-skill-creator/references/cli-plugin.md)。
187
188
 
189
+ 插件可选导出 `toolbox`,注册后会出现在扩展 Popup 的工具箱中。页面资源放在 Skill 目录内,注册时由
190
+ Mearl 将入口 HTML 引用的本地 CSS、JavaScript 和图片内联为不可变页面包,不需要启动 HTTP 服务,
191
+ 也不要求普通 HTML/CSS/JS 页面自行构建:
192
+
193
+ ```javascript
194
+ export const toolbox = {
195
+ version: 1,
196
+ title: '迭代管理',
197
+ description: '查看多个仓库的改动与发布状态',
198
+ icon: 'git-branch',
199
+ locales: {
200
+ en: {
201
+ title: 'Iteration Management',
202
+ description: 'Track changes and release status across repositories',
203
+ },
204
+ },
205
+ agent: {
206
+ skill: 'iteration-manager',
207
+ layout: 'workspace',
208
+ },
209
+ page: {
210
+ type: 'sandbox',
211
+ runtime: 'preact',
212
+ entry: 'assets/toolbox/index.html',
213
+ commands: ['list', 'create', 'delete'],
214
+ },
215
+ order: 100,
216
+ };
217
+
218
+ export default function register(app) {
219
+ app.command('list', async () => ({ items: await listItems() }));
220
+ app.command('create <name>', async input => ({ item: await createItem(input.name) }));
221
+ app.command('delete <id>', async input => ({ item: await deleteItem(input.id) }));
222
+ }
223
+ ```
224
+
225
+ 声明 `agent` 后工具页可以把任务交给对话 Agent;`layout` 默认为 `drawer`,宿主会提供顶部入口。
226
+ 页面也可在 `setAgentPanelVisible` 或 `runAgentTask` 中为单次交互指定 `drawer` / `workspace`。带固定
227
+ 18rem 左侧导航的工作台可默认使用 `workspace`,由导航项切换 Agent,并占满导航栏以外的主内容区;详情页仍可按需唤起右侧抽屉。
228
+
229
+ 页面通过 `await window.mearl.ready()` 取得 `{ locale, theme, title, fontSize }`,通过
230
+ `window.mearl.invoke(command, input?)` 调用 `commands` 白名单中的同一插件命令。页面运行在无扩展
231
+ API、默认不可联网的 sandbox iframe 中;Native Host 校验插件身份、命令白名单和消息大小。页面包按
232
+ 内容哈希缓存并分块传输,因此不会增加 Popup 的启动开销。使用模块脚本时需先打包为不再包含 `import`
233
+ 的单文件;React、Vue 等工程可以把构建后的 `index.html` 作为 `entry`,注册流程仍负责最终资源封装。
234
+ 需要无构建的组件与状态管理时可声明 `page.runtime: 'preact'`,扩展会在页面完整性校验后注入固定的
235
+ Preact、Hooks 和 HTM 运行时。页面从 `window.mearl.ui` 读取 `html`、`render`、`useState` 等 API;
236
+ `window.mearl.ui.version` 仅用于诊断,插件不能选择运行时版本。
237
+ 宿主会同步扩展主题、字号,并注入 `--mearl-bg-primary`、`--mearl-bg-secondary`、
238
+ `--mearl-text-primary`、`--mearl-text-secondary`、`--mearl-border`、`--mearl-bg-hover` 和
239
+ `--mearl-accent` 等语义变量;主操作按钮使用 `--mearl-action-primary`、
240
+ `--mearl-action-primary-hover` 和 `--mearl-action-primary-text`,以保持与扩展按钮一致。
241
+
188
242
  需要 BUC 身份的内部 HTTP 接口通过官方 `buc` 插件调用。CLI 使用 `mearl buc request`,业务插件使用
189
243
  `app.invoke('buc', { command: 'request', input })`;当前身份和人员资料分别使用 `whoami` 与 `profile`
190
244
  子命令。BUC 插件按请求创建一次性凭据,只接受无 URL 凭据的 HTTPS 地址,过滤认证字段与 Cookie;
@@ -200,18 +254,28 @@ MCP Server 通过固定工具 `mearl_plugin` 接受同样的 `plugin`、`command
200
254
  | API 调试 | `tab_checkpoint` `get_requests` `get_logs` `get_events` |
201
255
  | Mock & 规则 | `set_mock` `get_mocks` `set_rule` `get_rules` |
202
256
  | 网络请求 | `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` |
257
+ | 标签页 | `tab_open` `tab_list` `tab_close` |
258
+ | 页面感知 | `page_snapshot` `page_inspect` `page_screenshot` `page_frames` |
259
+ | 页面操作 | `page_click` `page_drag` `page_type` `page_hover` `page_scroll` `page_press` `page_wait` `page_navigate` `page_upload` `page_eval` |
205
260
  | 组合调用 | `run_actions` |
206
- | 页面感知 | `page_snapshot` `page_screenshot` `page_selected_element` `page_frames` |
207
261
  | 环境与 Cookie | `set_device_emulation` `set_app_profile` `set_timezone` `get_cookie` `set_cookie` |
208
- | 浏览器 | `browser_list` `browser_release` `browser_launch` `browser_close` |
262
+ | 浏览器 | `browser_list` `browser_launch` `browser_release` `browser_close` |
263
+
264
+ 页面交互动作(`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` 默认裸执行,可按需开启观察或诊断。
265
+
266
+ `tab_open active:true` 会激活目标 Tab、恢复最小化窗口,并通过 `activation` 返回实际标签页、窗口和 `visibilityState`;依赖可信触摸时先确认页面为 `visible`。页面动作的稳定观察会在有限预算内等待有限时长 CSS 动画。selector/ref 点击遇到嵌套滚动裁剪时会先滚动目标,仍不可见时才以明确的裁剪错误停止。
267
+
268
+ `page_click` 默认 `auto` 在隐藏页使用 DOM fallback,selector、文本、ref 和坐标定位都保持可用,并通过 `dispatchMode: "dom"`、`fallbackReason: "page-hidden"` 明确说明实际路径。普通后台任务不需要为了点击主动激活页面;只有站点明确拒绝非可信事件时才切换到可见页并强制 `mouse` / `touch`。
269
+
270
+ `observation.effects.interactives` 会把内容未变化但 DOM 节点被框架重建的控件标记为 `recreated`,保留 selector/ref 与语义信息供后续定位,同时省略未变化的 value 和状态字段;值或状态确实变化时仍返回完整差异。
271
+
272
+ `page_press.pressMode` 支持 `auto` / `dom` / `keyboard`。默认 `auto` 在隐藏页使用 DOM 键盘事件,并通过返回的 `dispatchMode`、`fallbackReason` 和 `defaultAction` 说明实际派发及默认行为模拟结果;依赖浏览器原生编辑、选择或滚动行为时使用可见页面和 `keyboard`。
209
273
 
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` 默认裸执行,可按需开启观察或诊断。
274
+ `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` 截断会同时保留首尾内容。
211
275
 
212
- `page_snapshot` 默认返回完整 AX Tree;长列表可传 `mode: "viewport"`,只需要当前视口内的控件时传 `mode: "interactive"`,已知 CSS 区域时传 `rootSelector`,已有 ref 时传 `rootRef`(可用 `ancestorDepth` 向上补充上下文),只查找特定文案或角色时传 `query`。视口内缺少 AX 控件语义时,`interactive` 会自动回退到 viewport,并返回 `fallbackMode: "viewport"`。`maxNodes` / `maxChars` 截断会同时保留首尾内容。
276
+ `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`。
213
277
 
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"` 自动解析最近可滚动祖先。
278
+ 重复文本点击可用 `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
279
 
216
280
  `browser_list` 统一列出普通浏览器、Provider 浏览器和托管浏览器。`type` 区分
217
281
  `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) {
@@ -509,7 +504,8 @@ async function runPluginCli(args, commandName) {
509
504
  ...invokeOptions,
510
505
  ...(parsed.verbose
511
506
  ? {
512
- onProgress(message) {
507
+ onProgress(progress) {
508
+ const message = typeof progress === 'string' ? progress : progress.message;
513
509
  process.stderr.write(message.endsWith('\n') ? message : `${message}\n`);
514
510
  },
515
511
  }
@@ -554,9 +550,6 @@ function screenshotData(action, result) {
554
550
  }
555
551
  if (action === 'page_screenshot' && typeof result?.data === 'string')
556
552
  return result.data;
557
- if (action === 'page_selected_element' && typeof result?.screenshot?.data === 'string') {
558
- return result.screenshot.data;
559
- }
560
553
  return null;
561
554
  }
562
555
  function writeOutput(action, result, outputPath) {
@@ -659,9 +652,6 @@ export async function runMearlCli(args, options = {}) {
659
652
  }
660
653
  return (await runUnifiedCheck(checkOptions)) ? 0 : 1;
661
654
  }
662
- if (parsed.action === 'page_selected_element' && parsed.outputPath) {
663
- parsed.payload = { ...parsed.payload, includeScreenshot: true };
664
- }
665
655
  const client = new UnifiedClient({
666
656
  ...(parsed.serverUrl ? { serverUrl: parsed.serverUrl } : {}),
667
657
  requestTimeoutSec: parsed.timeoutSec,
@@ -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,7 +880,7 @@ 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
886
  readonly description: "设置 App 客户端环境与 JSBridge;可同时设置 MTop 页面接口环境,传 emulation 时联动设备模拟";
@@ -901,7 +928,7 @@ export declare const COMMANDS: readonly [{
901
928
  readonly required: true;
902
929
  readonly description: "目标标签页 ID";
903
930
  }];
904
- readonly examples: ["set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\"}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\",\"mtopEnv\":\"pre\"}'", "set_app_profile --payload '{\"enabled\":false,\"mtopEnv\":\"prod\"}'", "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\":{}}'"];
905
932
  }, {
906
933
  readonly name: "set_timezone";
907
934
  readonly description: "覆盖目标 tab 的时区,传空字符串恢复浏览器默认时区";