@mearl/client 2.6.0 → 2.7.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
@@ -67,6 +67,7 @@ mearl browser_launch --payload '{"name":"account-a","accountId":12345}'
67
67
  mearl browser_launch --payload '{"name":"account-b","query":"test_account"}'
68
68
  mearl browser_launch --payload '{"name":"cookie-copy","copyCookieDomains":["example.com"]}'
69
69
  mearl browser_launch --payload '{"name":"cloud-login","provider":"agentbay","persistent":true,"userAgentMode":"desktop","copyCookieDomains":["example.com"],"url":"https://example.com/account"}'
70
+ mearl browser_launch --browser '<控制浏览器 browserId>' --payload '{"name":"cloud-login","provider":"agentbay","reuse":"require","copyCookieDomains":["example.com"]}'
70
71
  mearl browser_launch --payload '{"name":"figma","userAgentMode":"desktop","copyCookieDomains":["figma.com"]}'
71
72
  mearl browser_list
72
73
  mearl browser_release
@@ -74,35 +75,35 @@ mearl browser_release
74
75
 
75
76
  **通用选项:**
76
77
 
77
- | 选项 | 说明 |
78
- | ----------------------- | ------------------------ |
79
- | `--payload <json>` | 直接传入 JSON 参数 |
80
- | `--payload-file <path>` | 从文件读取 JSON 参数 |
81
- | `--timeout <seconds>` | 请求超时时间 |
82
- | `--compact` | 紧凑输出 |
83
- | `--output <path>` | 将结果写入文件(如截图) |
84
- | `--browser <id\|名称>` | 指定目标浏览器 |
78
+ | 选项 | 说明 |
79
+ | ------------------------ | ------------------------ |
80
+ | `--payload <json>` | 直接传入 JSON 参数 |
81
+ | `--payload-file <path>` | 从文件读取 JSON 参数 |
82
+ | `--timeout <seconds>` | 请求超时时间 |
83
+ | `--compact` | 紧凑输出 |
84
+ | `--output <path>` | 将结果写入文件(如截图) |
85
+ | `--browser <id\|名称>` | 指定目标浏览器 |
85
86
  | `--connector <id\|名称>` | 限制到一台远端机器 |
86
- | `--local` | 只使用当前机器 |
87
- | `--server <url>` | 覆盖 cloud-server 地址 |
87
+ | `--local` | 只使用当前机器 |
88
+ | `--server <url>` | 覆盖 cloud-server 地址 |
88
89
 
89
90
  ## 支持的操作
90
91
 
91
- | 分类 | Actions |
92
- | ----------- | --------------------------------------------------------------------------------------------------------- |
93
- | API 调试 | `capture_checkpoint` `get_requests` `get_logs` `get_events` `get_api_schema` |
94
- | Mock & 规则 | `set_mock` `get_mocks` `set_rule` `get_rules` |
95
- | 网络代理 | `send_request` `send_mtop_request` |
96
- | 标签页 | `tab_open` `tab_close` `tab_list` |
97
- | 页面操作 | `page_click` `page_type` `page_scroll` `page_eval` `page_press` `page_wait` `page_navigate` `page_upload` |
98
- | 页面感知 | `page_snapshot` `page_screenshot` `page_selected_element` `page_frames` |
99
- | 环境与状态 | `set_device_emulation` `set_timezone` `get_cookie` `set_cookie` |
100
- | 用户信息 | `get_user_info` |
101
- | 录制 | `record_start` `record_stop` |
102
- | TDBank | `tdbank_account` |
103
- | 浏览器 | `browser_list` `browser_release` `browser_launch` `browser_close` |
104
-
105
- 页面交互动作(`page_click` / `page_type` / `page_hover` / `page_scroll` / `page_press` / `page_upload`)默认内置观察与原子诊断:同一次调用内执行动作、等待异步稳定,并返回 `{ action, observation, diagnostics }`;`diagnostics` 默认包含新增 error logs 和全部业务 requests。传 `observe: false` 只关闭 DOM/导航观察并保留诊断;同时传 `diagnostics: false` 才仅执行裸动作。观察结果不替代完整页面理解:`mode: "delta"` 只返回主文档中的 `effects.notifications`、`effects.interactives` 和 `effects.focus` 等高置信度信号,并明确携带 `scope: "main-document"`;可交互节点会尽量携带真实 backend `node.ref`,后续动作优先使用 ref,缺少 ref 时使用 `node.selector`。`mode: "navigation"` 且 `ready: true` 时,页面已通过网络静默、骨架状态或保守的内容稳定判定,可在新页面重建快照。动作直接打开新标签页时,`observation.openedTabs` 返回新标签页的 `tabId`、URL、标题和加载状态,可直接把该 `tabId` 用于后续操作,不必调用 `tab_list`。通常仅在 `fullSnapshotRecommended` 为 true 时根据 `snapshotReasons` 回退;滚动后若下一步需要读取新视口内容,可按需获取 viewport 快照。`page_eval` 默认裸执行;显式传 `observe` 对象可启用观察,传 `diagnostics: true` 或对象可启用原子诊断。
92
+ | 分类 | Actions |
93
+ | ----------- | --------------------------------------------------------------------------------------------------------------------- |
94
+ | API 调试 | `capture_checkpoint` `get_requests` `get_logs` `get_events` `get_api_schema` |
95
+ | Mock & 规则 | `set_mock` `get_mocks` `set_rule` `get_rules` |
96
+ | 网络代理 | `send_request` `send_mtop_request` |
97
+ | 标签页 | `tab_open` `tab_close` `tab_list` |
98
+ | 页面操作 | `page_click` `page_drag` `page_type` `page_scroll` `page_eval` `page_press` `page_wait` `page_navigate` `page_upload` |
99
+ | 页面感知 | `page_snapshot` `page_screenshot` `page_selected_element` `page_frames` |
100
+ | 环境与状态 | `set_device_emulation` `set_timezone` `get_cookie` `set_cookie` |
101
+ | 用户信息 | `get_user_info` |
102
+ | 录制 | `record_start` `record_stop` |
103
+ | TDBank | `tdbank_account` |
104
+ | 浏览器 | `browser_list` `browser_release` `browser_launch` `browser_close` |
105
+
106
+ 页面交互动作(`page_click` / `page_drag` / `page_type` / `page_hover` / `page_scroll` / `page_press` / `page_upload`)默认内置观察与原子诊断:同一次调用内执行动作、等待异步稳定,并返回 `{ action, observation, diagnostics }`;`diagnostics` 默认包含新增 error logs 和全部业务 requests。传 `observe: false` 只关闭 DOM/导航观察并保留诊断;同时传 `diagnostics: false` 才仅执行裸动作。观察结果不替代完整页面理解:`mode: "delta"` 只返回主文档中的 `effects.notifications`、`effects.interactives` 和 `effects.focus` 等高置信度信号,并明确携带 `scope: "main-document"`;可交互节点会尽量携带真实 backend `node.ref`,后续动作优先使用 ref,缺少 ref 时使用 `node.selector`。`mode: "navigation"` 且 `ready: true` 时,页面已通过网络静默、骨架状态或保守的内容稳定判定,可在新页面重建快照。动作直接打开新标签页时,`observation.openedTabs` 返回新标签页的 `tabId`、URL、标题和加载状态,可直接把该 `tabId` 用于后续操作,不必调用 `tab_list`。通常仅在 `fullSnapshotRecommended` 为 true 时根据 `snapshotReasons` 回退;滚动后若下一步需要读取新视口内容,可按需获取 viewport 快照。`page_eval` 默认裸执行;显式传 `observe` 对象可启用观察,传 `diagnostics: true` 或对象可启用原子诊断。
106
107
 
107
108
  `page_snapshot` 默认返回完整 AX Tree;长列表可传 `mode: "viewport"`,只需要当前视口内的控件时传 `mode: "interactive"`,已知 CSS 区域时传 `rootSelector`,已有 ref 时传 `rootRef`(可用 `ancestorDepth` 向上补充上下文),只查找特定文案或角色时传 `query`。视口内缺少 AX 控件语义时,`interactive` 会自动回退到 viewport,并返回 `fallbackMode: "viewport"`。`maxNodes` / `maxChars` 截断会同时保留首尾内容。
108
109
 
@@ -112,7 +113,7 @@ mearl browser_release
112
113
 
113
114
  `browser_release` 仅在用户明确要求结束调试、退出接管或清理会话资源时使用,不作为普通任务收尾。它会释放当前目标浏览器的 debugger/CDP 控制和会话级临时状态(包括设备/时区模拟),保留浏览器及全部标签页;后续浏览器操作可自动重新建立控制。
114
115
 
115
- 托管浏览器使用独立 Profile。控制浏览器需先登录 TDBank;生成的 SSO 地址在本地内部传递,本地实例可以使用 `headless: true`(默认)完成测试账号登录。AgentBay 固定为非 headless,传 `headless: true` 会被拒绝;`imageId` 可指定镜像别名或具体镜像 ID,省略时使用已验证的 Linux Browser Use 内网镜像。`persistent: true` 会让本地实例保留 Profile,让 AgentBay 同名实例绑定稳定的云端 Browser Context;正常关闭时同步 Cookie、LocalStorage、IndexedDB 等状态,下次启动无需再次复制本地登录态。`deleteProfile: true` 会显式删除对应 Profile 或 Context。`copyCookieDomains` 可在首次启动或需要刷新登录态时把控制浏览器指定域的 Cookie 复制到新实例,Cookie 值不会经过 cloud-server,也不会出现在命令结果或日志中;`userAgentMode: "desktop"` 让本地实例使用匹配本机 Chrome 版本的桌面 UA,AgentBay 则复用当前控制浏览器的桌面 UA。`browser_list` 仅通过 `agentbayImageId`、`agentbayContextId` 和 `agentbayContextName` 返回 AgentBay 实例的稳定配置。无影浏览器串流入口包含临时访问凭据且会过期,因此不会写入实例记录或列表结果;需要时运行 `mearl check --browser <id|名称>` 实时获取,并按敏感信息处理。完整设计见 [托管浏览器与 TDBank 多账号设计](../../docs/managed-browsers.md)。
116
+ 托管浏览器使用独立 Profile。控制浏览器需先登录 TDBank;生成的 SSO 地址在本地内部传递,本地实例可以使用 `headless: true`(默认)完成测试账号登录。AgentBay 固定为非 headless,传 `headless: true` 会被拒绝;`imageId` 可指定镜像别名或具体镜像 ID,省略时使用已验证的 Linux Browser Use 内网镜像。`persistent: true` 会让本地实例保留 Profile,让 AgentBay 同名实例绑定稳定的云端 Browser Context;正常关闭时同步 Cookie、LocalStorage、IndexedDB 等状态,下次启动无需再次复制本地登录态。`deleteProfile: true` 会显式删除对应 Profile 或 Context。AgentBay 的 `reuse` 支持 `never`(默认)、`prefer` 和 `require`:`prefer` 存在运行实例时复用、否则创建,`require` 只复用且不会意外创建计费会话。`copyCookieDomains` 可在首次启动或复用运行实例时把控制浏览器指定域的 Cookie 写入目标,Cookie 值不会经过 cloud-server,也不会出现在命令结果或日志中;`userAgentMode: "desktop"` 让本地实例使用匹配本机 Chrome 版本的桌面 UA,AgentBay 则复用当前控制浏览器的桌面 UA。`browser_list` 仅通过 `agentbayImageId`、`agentbayContextId` 和 `agentbayContextName` 返回 AgentBay 实例的稳定配置。无影浏览器串流入口包含临时访问凭据且会过期,因此不会写入实例记录或列表结果;需要时运行 `mearl check --browser <id|名称>` 实时获取,并按敏感信息处理。完整设计见 [托管浏览器与 TDBank 多账号设计](../../docs/managed-browsers.md)。
116
117
 
117
118
  ## 架构
118
119
 
package/dist/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/bin.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { runMearlCli } from './cli.js';
3
+ process.exitCode = await runMearlCli(process.argv.slice(2));
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env node
2
1
  export interface MearlCliOptions {
3
2
  commandName?: string;
4
3
  clientVersion?: string;
package/dist/cli.js CHANGED
@@ -1,7 +1,5 @@
1
- #!/usr/bin/env node
2
1
  import { readFileSync, writeFileSync } from 'node:fs';
3
- import path, { resolve } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
2
+ import { resolve } from 'node:path';
5
3
  import { resolveActionTimeoutSec } from './actionTimeouts.js';
6
4
  import { runUnifiedCheck, parseCheckTimeout } from './check.js';
7
5
  import { COMMAND_MAP } from './commands.js';
@@ -310,7 +308,3 @@ export async function runMearlCli(args, options = {}) {
310
308
  client.disconnect();
311
309
  }
312
310
  }
313
- const currentFile = fileURLToPath(import.meta.url);
314
- if (process.argv[1] && path.resolve(process.argv[1]) === currentFile) {
315
- process.exitCode = await runMearlCli(process.argv.slice(2));
316
- }
@@ -302,7 +302,7 @@ export declare const COMMANDS: readonly [{
302
302
  readonly examples: ["browser_release", "browser_release --browser chrome-a"];
303
303
  }, {
304
304
  readonly name: "browser_launch";
305
- readonly description: "启动本地 Chrome 或 AgentBay 云浏览器,并通过 CDP 接入 Mearl";
305
+ readonly description: "启动本地 Chrome,或创建/显式复用 AgentBay 云浏览器,并通过 CDP 接入 Mearl";
306
306
  readonly params: [{
307
307
  readonly name: "name";
308
308
  readonly type: "string";
@@ -312,6 +312,10 @@ export declare const COMMANDS: readonly [{
312
312
  readonly name: "provider";
313
313
  readonly type: "\"local\" | \"agentbay\"";
314
314
  readonly description: "运行环境,默认 local;agentbay 从 AGENTBAY_KEY 创建云浏览器";
315
+ }, {
316
+ readonly name: "reuse";
317
+ readonly type: "\"never\" | \"prefer\" | \"require\"";
318
+ readonly description: "AgentBay 运行实例复用策略:never 默认不复用;prefer 同名运行实例存在则复用、无记录则创建;require 只复用、不创建";
315
319
  }, {
316
320
  readonly name: "imageId";
317
321
  readonly type: "string";
@@ -359,9 +363,9 @@ export declare const COMMANDS: readonly [{
359
363
  }, {
360
364
  readonly name: "copyCookieDomains";
361
365
  readonly type: "string[]";
362
- readonly description: "从控制浏览器复制到本地或 AgentBay 新实例的 Cookie 域名列表,可与本地 TDBank 登录组合";
366
+ readonly description: "从控制浏览器复制到本地新实例或 AgentBay 新建/复用实例的 Cookie 域名列表,可与本地 TDBank 登录组合";
363
367
  }];
364
- readonly examples: ["browser_launch --payload '{\"name\":\"cloud-a\",\"provider\":\"agentbay\",\"userAgentMode\":\"desktop\",\"url\":\"https://example.com\"}'", "browser_launch --payload '{\"name\":\"cloud-public\",\"provider\":\"agentbay\",\"imageId\":\"browser_latest\",\"url\":\"https://example.com\"}'", "browser_launch --payload '{\"name\":\"cloud-login\",\"provider\":\"agentbay\",\"persistent\":true,\"copyCookieDomains\":[\"example.com\"],\"url\":\"https://example.com/account\"}'", "browser_launch --payload '{\"name\":\"account-a\",\"headless\":true,\"accountId\":12345}'", "browser_launch --payload '{\"name\":\"figma\",\"userAgentMode\":\"desktop\",\"copyCookieDomains\":[\"figma.com\"]}'", "browser_launch --payload '{\"name\":\"account-b\",\"query\":\"test_account\",\"url\":\"https://www.taobao.com\"}'", "browser_launch --payload '{\"name\":\"with-cookies\",\"copyCookieDomains\":[\"example.com\",\"sub.example.org\"]}'"];
368
+ readonly examples: ["browser_launch --payload '{\"name\":\"cloud-a\",\"provider\":\"agentbay\",\"userAgentMode\":\"desktop\",\"url\":\"https://example.com\"}'", "browser_launch --payload '{\"name\":\"cloud-public\",\"provider\":\"agentbay\",\"imageId\":\"browser_latest\",\"url\":\"https://example.com\"}'", "browser_launch --payload '{\"name\":\"cloud-login\",\"provider\":\"agentbay\",\"persistent\":true,\"copyCookieDomains\":[\"example.com\"],\"url\":\"https://example.com/account\"}'", "browser_launch --payload '{\"name\":\"cloud-login\",\"provider\":\"agentbay\",\"reuse\":\"require\",\"copyCookieDomains\":[\"example.com\"]}'", "browser_launch --payload '{\"name\":\"account-a\",\"headless\":true,\"accountId\":12345}'", "browser_launch --payload '{\"name\":\"figma\",\"userAgentMode\":\"desktop\",\"copyCookieDomains\":[\"figma.com\"]}'", "browser_launch --payload '{\"name\":\"account-b\",\"query\":\"test_account\",\"url\":\"https://www.taobao.com\"}'", "browser_launch --payload '{\"name\":\"with-cookies\",\"copyCookieDomains\":[\"example.com\",\"sub.example.org\"]}'"];
365
369
  }, {
366
370
  readonly name: "browser_close";
367
371
  readonly description: "关闭指定托管浏览器并按策略保留或清理本地 Profile / AgentBay Context";
@@ -474,6 +478,38 @@ export declare const COMMANDS: readonly [{
474
478
  readonly description: "目标标签页 ID";
475
479
  }];
476
480
  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}}'"];
481
+ }, {
482
+ readonly name: "page_drag";
483
+ readonly description: "在页面内执行可信拖动手势;from/to 均可使用视口坐标或 CSS/@ref,auto 按设备模拟状态选择 mouse/touch,并默认观察拖动后的页面变化";
484
+ readonly params: [{
485
+ readonly name: "from";
486
+ readonly type: "string | { x: number; y: number }";
487
+ readonly required: true;
488
+ readonly description: "起点:原生 CSS、@eN ref,或 { x, y } 视口坐标(CSS 像素)";
489
+ }, {
490
+ readonly name: "to";
491
+ readonly type: "string | { x: number; y: number }";
492
+ readonly required: true;
493
+ readonly description: "终点:原生 CSS、@eN ref,或 { x, y } 视口坐标(CSS 像素)";
494
+ }, {
495
+ readonly name: "dragMode";
496
+ readonly type: "\"auto\" | \"mouse\" | \"touch\"";
497
+ readonly description: "拖动输入类型;默认 auto,移动模拟页使用 touch,其余使用 mouse";
498
+ }, {
499
+ readonly name: "durationMs";
500
+ readonly type: "number";
501
+ readonly description: "拖动持续时间,0–5000ms,默认 400ms;内部自动分段移动";
502
+ }, {
503
+ readonly name: "observe";
504
+ readonly type: "object | false";
505
+ readonly description: "观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回";
506
+ }, ParamDef, {
507
+ readonly name: "tabId";
508
+ readonly type: "number";
509
+ readonly required: true;
510
+ readonly description: "目标标签页 ID";
511
+ }];
512
+ 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\"}'"];
477
513
  }, {
478
514
  readonly name: "page_type";
479
515
  readonly description: "向输入框填写文本,兼容 React 受控组件;默认观察校验提示等异步变化";
package/dist/commands.js CHANGED
@@ -220,7 +220,7 @@ export const COMMANDS = [
220
220
  },
221
221
  {
222
222
  name: 'browser_launch',
223
- description: '启动本地 Chrome 或 AgentBay 云浏览器,并通过 CDP 接入 Mearl',
223
+ description: '启动本地 Chrome,或创建/显式复用 AgentBay 云浏览器,并通过 CDP 接入 Mearl',
224
224
  params: [
225
225
  { name: 'name', type: 'string', required: true, description: '实例名称,最多 64 个字符' },
226
226
  {
@@ -228,6 +228,11 @@ export const COMMANDS = [
228
228
  type: '"local" | "agentbay"',
229
229
  description: '运行环境,默认 local;agentbay 从 AGENTBAY_KEY 创建云浏览器',
230
230
  },
231
+ {
232
+ name: 'reuse',
233
+ type: '"never" | "prefer" | "require"',
234
+ description: 'AgentBay 运行实例复用策略:never 默认不复用;prefer 同名运行实例存在则复用、无记录则创建;require 只复用、不创建',
235
+ },
231
236
  {
232
237
  name: 'imageId',
233
238
  type: 'string',
@@ -266,13 +271,14 @@ export const COMMANDS = [
266
271
  {
267
272
  name: 'copyCookieDomains',
268
273
  type: 'string[]',
269
- description: '从控制浏览器复制到本地或 AgentBay 新实例的 Cookie 域名列表,可与本地 TDBank 登录组合',
274
+ description: '从控制浏览器复制到本地新实例或 AgentBay 新建/复用实例的 Cookie 域名列表,可与本地 TDBank 登录组合',
270
275
  },
271
276
  ],
272
277
  examples: [
273
278
  `browser_launch --payload '{"name":"cloud-a","provider":"agentbay","userAgentMode":"desktop","url":"https://example.com"}'`,
274
279
  `browser_launch --payload '{"name":"cloud-public","provider":"agentbay","imageId":"browser_latest","url":"https://example.com"}'`,
275
280
  `browser_launch --payload '{"name":"cloud-login","provider":"agentbay","persistent":true,"copyCookieDomains":["example.com"],"url":"https://example.com/account"}'`,
281
+ `browser_launch --payload '{"name":"cloud-login","provider":"agentbay","reuse":"require","copyCookieDomains":["example.com"]}'`,
276
282
  `browser_launch --payload '{"name":"account-a","headless":true,"accountId":12345}'`,
277
283
  `browser_launch --payload '{"name":"figma","userAgentMode":"desktop","copyCookieDomains":["figma.com"]}'`,
278
284
  `browser_launch --payload '{"name":"account-b","query":"test_account","url":"https://www.taobao.com"}'`,
@@ -420,6 +426,45 @@ export const COMMANDS = [
420
426
  `page_click --payload '{"point":{"x":336,"y":117}}'`,
421
427
  ],
422
428
  },
429
+ {
430
+ name: 'page_drag',
431
+ description: '在页面内执行可信拖动手势;from/to 均可使用视口坐标或 CSS/@ref,auto 按设备模拟状态选择 mouse/touch,并默认观察拖动后的页面变化',
432
+ params: [
433
+ {
434
+ name: 'from',
435
+ type: 'string | { x: number; y: number }',
436
+ required: true,
437
+ description: '起点:原生 CSS、@eN ref,或 { x, y } 视口坐标(CSS 像素)',
438
+ },
439
+ {
440
+ name: 'to',
441
+ type: 'string | { x: number; y: number }',
442
+ required: true,
443
+ description: '终点:原生 CSS、@eN ref,或 { x, y } 视口坐标(CSS 像素)',
444
+ },
445
+ {
446
+ name: 'dragMode',
447
+ type: '"auto" | "mouse" | "touch"',
448
+ description: '拖动输入类型;默认 auto,移动模拟页使用 touch,其余使用 mouse',
449
+ },
450
+ {
451
+ name: 'durationMs',
452
+ type: 'number',
453
+ description: '拖动持续时间,0–5000ms,默认 400ms;内部自动分段移动',
454
+ },
455
+ {
456
+ name: 'observe',
457
+ type: 'object | false',
458
+ description: '观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回',
459
+ },
460
+ PAGE_DIAGNOSTICS_PARAM,
461
+ { name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
462
+ ],
463
+ examples: [
464
+ `page_drag --payload '{"from":{"x":350,"y":80},"to":{"x":80,"y":80}}'`,
465
+ `page_drag --payload '{"from":"@e3","to":"#drop-zone","dragMode":"mouse"}'`,
466
+ ],
467
+ },
423
468
  {
424
469
  name: 'page_type',
425
470
  description: '向输入框填写文本,兼容 React 受控组件;默认观察校验提示等异步变化',
@@ -199,6 +199,8 @@ export interface BrowserLaunchParams {
199
199
  name: string;
200
200
  /** Browser runtime provider. Defaults to local Chrome. */
201
201
  provider?: 'local' | 'agentbay';
202
+ /** AgentBay running-session reuse policy. Defaults to never. */
203
+ reuse?: 'never' | 'prefer' | 'require';
202
204
  /** AgentBay image alias or concrete image ID. Only supported by the AgentBay provider. */
203
205
  imageId?: string;
204
206
  /** Local Chrome defaults to true. AgentBay is fixed to false and rejects true. */
@@ -213,7 +215,7 @@ export interface BrowserLaunchParams {
213
215
  site?: string | number;
214
216
  query?: string;
215
217
  tabId?: number;
216
- /** Copy matching cookies from the selected control browser before opening url. */
218
+ /** Copy matching cookies from the selected control browser into a new or reused instance. */
217
219
  copyCookieDomains?: string[];
218
220
  }
219
221
  export interface BrowserCloseParams {
@@ -314,6 +316,20 @@ export interface PageClickParams {
314
316
  observe?: PageObservationWaitOptions | false;
315
317
  diagnostics?: PageDiagnosticsSetting;
316
318
  }
319
+ export interface PageDragPoint {
320
+ x: number;
321
+ y: number;
322
+ }
323
+ export type PageDragEndpoint = string | PageDragPoint;
324
+ export interface PageDragParams {
325
+ tabId?: number;
326
+ from: PageDragEndpoint;
327
+ to: PageDragEndpoint;
328
+ dragMode?: 'auto' | 'mouse' | 'touch';
329
+ durationMs?: number;
330
+ observe?: PageObservationWaitOptions | false;
331
+ diagnostics?: PageDiagnosticsSetting;
332
+ }
317
333
  export interface PageTypeParams {
318
334
  tabId?: number;
319
335
  selector: string;
@@ -547,6 +563,10 @@ export interface BrowserActionMap {
547
563
  request: PageClickParams;
548
564
  response: unknown;
549
565
  };
566
+ page_drag: {
567
+ request: PageDragParams;
568
+ response: unknown;
569
+ };
550
570
  page_type: {
551
571
  request: PageTypeParams;
552
572
  response: unknown;
@@ -629,7 +649,7 @@ export type BrowserActionRequest<A extends BrowserAction> = BrowserActionMap[A][
629
649
  export type BrowserActionResponse<A extends BrowserAction> = BrowserActionMap[A]['response'];
630
650
  export type BrowserCommandAction = Exclude<BrowserAction, 'browser_select_browser'>;
631
651
  export type ExtensionBrowserAction = Exclude<BrowserCommandAction, 'browser_list' | 'browser_launch' | 'browser_close'>;
632
- export declare const PAGE_ACT_ACTIONS: readonly ["page_click", "page_type", "page_hover", "page_scroll", "page_press", "page_upload", "page_eval"];
652
+ export declare const PAGE_ACT_ACTIONS: readonly ["page_click", "page_drag", "page_type", "page_hover", "page_scroll", "page_press", "page_upload", "page_eval"];
633
653
  export type PageActAction = (typeof PAGE_ACT_ACTIONS)[number];
634
654
  export declare const BROWSER_ACTIONS: {
635
655
  readonly capture_checkpoint: true;
@@ -655,6 +675,7 @@ export declare const BROWSER_ACTIONS: {
655
675
  readonly tab_close: true;
656
676
  readonly tab_list: true;
657
677
  readonly page_click: true;
678
+ readonly page_drag: true;
658
679
  readonly page_type: true;
659
680
  readonly page_scroll: true;
660
681
  readonly page_hover: true;
@@ -698,6 +719,7 @@ export declare const BROWSER_COMMAND_ACTIONS: {
698
719
  readonly tab_close: true;
699
720
  readonly tab_list: true;
700
721
  readonly page_click: true;
722
+ readonly page_drag: true;
701
723
  readonly page_type: true;
702
724
  readonly page_scroll: true;
703
725
  readonly page_hover: true;
@@ -738,6 +760,7 @@ export declare const EXTENSION_BROWSER_ACTIONS: {
738
760
  readonly tab_close: true;
739
761
  readonly tab_list: true;
740
762
  readonly page_click: true;
763
+ readonly page_drag: true;
741
764
  readonly page_type: true;
742
765
  readonly page_scroll: true;
743
766
  readonly page_hover: true;
@@ -8,6 +8,7 @@ export const SEND_REQUEST_MAX_TOTAL_FILE_BYTES = 40 * 1024 * 1024;
8
8
  export const SEND_REQUEST_MAX_TOTAL_BASE64_FILE_BYTES = 7 * 1024 * 1024;
9
9
  export const PAGE_ACT_ACTIONS = [
10
10
  'page_click',
11
+ 'page_drag',
11
12
  'page_type',
12
13
  'page_hover',
13
14
  'page_scroll',
@@ -39,6 +40,7 @@ export const BROWSER_ACTIONS = {
39
40
  tab_close: true,
40
41
  tab_list: true,
41
42
  page_click: true,
43
+ page_drag: true,
42
44
  page_type: true,
43
45
  page_scroll: true,
44
46
  page_hover: true,
@@ -82,6 +84,7 @@ export const BROWSER_COMMAND_ACTIONS = {
82
84
  tab_close: true,
83
85
  tab_list: true,
84
86
  page_click: true,
87
+ page_drag: true,
85
88
  page_type: true,
86
89
  page_scroll: true,
87
90
  page_hover: true,
@@ -122,6 +125,7 @@ export const EXTENSION_BROWSER_ACTIONS = {
122
125
  tab_close: true,
123
126
  tab_list: true,
124
127
  page_click: true,
128
+ page_drag: true,
125
129
  page_type: true,
126
130
  page_scroll: true,
127
131
  page_hover: true,
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  export { UnifiedClient, UnifiedClient as MearlClient, decodeBrowserTarget, invoke, listCloudConnectors, } from './unified.js';
8
8
  export type { UnifiedClientOptions, UnifiedInvokeOptions, UnifiedInvokeOptions as InvokeOptions, } from './unified.js';
9
9
  export { 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, isBrowserCommandAction, isExtensionBrowserAction, } from './generated-browser-action-protocol.js';
10
- export type { ActionStep, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserLaunchParams, BrowserListResult, BrowserReleaseFailure, BrowserReleaseResult, BrowserSource, BrowserStatus, CaptureCheckpointParams, CaptureCheckpointResult, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetApiSchemaParams, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, GetUserInfoParams, ManagedBrowserAccount, ManagedBrowserInfo, PageClickParams, PageActAction, PageDiagnosticsOptions, PageDiagnosticsSetting, PageEvalParams, PageFramesParams, PageHoverParams, PageNavigateParams, PageObservationWaitOptions, PagePressParams, PageScreenshotParams, PageScrollParams, PageSelectedElementParams, PageSnapshotParams, PageSnapshotQuery, PageTypeParams, PageUploadParams, PageWaitParams, RecordParams, RegularBrowserInfo, RequestDomainPermissionParams, RulesResult, RunActionName, RunActionsParams, SelectBrowserParams, SelectBrowserResult, SendRequestFile, SendRequestFormValue, SendMtopRequestParams, SendRequestParams, SetCookieParams, SetCookieResult, SetDeviceEmulationParams, SetMockParams, SetRuleParams, SetTimezoneParams, SetTimezoneResult, TabCloseParams, TabOpenParams, TdbankAccountParams, } from './generated-browser-action-protocol.js';
10
+ export type { ActionStep, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserLaunchParams, BrowserListResult, BrowserReleaseFailure, BrowserReleaseResult, BrowserSource, BrowserStatus, CaptureCheckpointParams, CaptureCheckpointResult, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetApiSchemaParams, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, GetUserInfoParams, ManagedBrowserAccount, ManagedBrowserInfo, PageClickParams, PageDragEndpoint, PageDragParams, PageDragPoint, PageActAction, PageDiagnosticsOptions, PageDiagnosticsSetting, PageEvalParams, PageFramesParams, PageHoverParams, PageNavigateParams, PageObservationWaitOptions, PagePressParams, PageScreenshotParams, PageScrollParams, PageSelectedElementParams, PageSnapshotParams, PageSnapshotQuery, PageTypeParams, PageUploadParams, PageWaitParams, RecordParams, RegularBrowserInfo, RequestDomainPermissionParams, RulesResult, RunActionName, RunActionsParams, SelectBrowserParams, SelectBrowserResult, SendRequestFile, SendRequestFormValue, SendMtopRequestParams, SendRequestParams, SetCookieParams, SetCookieResult, SetDeviceEmulationParams, SetMockParams, SetRuleParams, SetTimezoneParams, SetTimezoneResult, TabCloseParams, TabOpenParams, TdbankAccountParams, } from './generated-browser-action-protocol.js';
11
11
  import { type UnifiedInvokeOptions } from './unified.js';
12
12
  import type * as Protocol from './generated-browser-action-protocol.js';
13
13
  export declare function captureCheckpoint(params?: Protocol.CaptureCheckpointParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'capture_checkpoint'>>;
@@ -33,6 +33,7 @@ export declare function tabOpen(params: Protocol.TabOpenParams, options?: Unifie
33
33
  export declare function tabClose(params: Protocol.TabCloseParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_close'>>;
34
34
  export declare function tabList(options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_list'>>;
35
35
  export declare function pageClick(params: Protocol.PageClickParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_click'>>;
36
+ export declare function pageDrag(params: Protocol.PageDragParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_drag'>>;
36
37
  export declare function pageType(params: Protocol.PageTypeParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_type'>>;
37
38
  export declare function pageScroll(params: Protocol.PageScrollParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_scroll'>>;
38
39
  export declare function pageHover(params: Protocol.PageHoverParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_hover'>>;
package/dist/index.js CHANGED
@@ -76,6 +76,9 @@ export function tabList(options) {
76
76
  export function pageClick(params, options) {
77
77
  return invoke('page_click', params, options);
78
78
  }
79
+ export function pageDrag(params, options) {
80
+ return invoke('page_drag', params, options);
81
+ }
79
82
  export function pageType(params, options) {
80
83
  return invoke('page_type', params, options);
81
84
  }
package/dist/socket.d.ts CHANGED
@@ -13,6 +13,8 @@ export declare const CLIENT_VERSION: string;
13
13
  * (or the pre-ping startup window) and is what auto-spawn targets.
14
14
  */
15
15
  export declare const SOCKET_PATH: string;
16
+ export type ControlSource = 'local' | 'remote';
17
+ type CompatibleControlSource = ControlSource | 'cloud';
16
18
  export interface InvokeOptions {
17
19
  /** 超时时间(秒),默认 15 */
18
20
  timeoutSec?: number;
@@ -20,8 +22,8 @@ export interface InvokeOptions {
20
22
  transport?: 'cdp';
21
23
  /** Target a specific browser by id / name (see the browser registry). */
22
24
  browser?: string;
23
- /** Identifies whether browser control originated locally or through the cloud connector. */
24
- controlSource?: 'local' | 'cloud';
25
+ /** Identifies whether browser control originated on this machine or through a remote connector. */
26
+ controlSource?: CompatibleControlSource;
25
27
  }
26
28
  /** Pin the default target browser for subsequent invokes (undefined clears it). */
27
29
  export declare function setDefaultBrowser(selector: string | undefined): void;
@@ -35,3 +37,4 @@ export declare function decorateBrowserListResult(result: Record<string, any>):
35
37
  * legacy well-known socket,并在 socket 不存在(ENOENT)时自动拉起 native host。
36
38
  */
37
39
  export declare function invoke(action: string, data?: Record<string, any>, options?: InvokeOptions): Promise<any>;
40
+ export {};
package/dist/socket.js CHANGED
@@ -25,6 +25,9 @@ const MAX_SOCKET_BUFFER_SIZE = 64 * 1024 * 1024;
25
25
  export const SOCKET_PATH = process.platform === 'win32'
26
26
  ? '\\\\.\\pipe\\mearl-agent'
27
27
  : path.join(os.tmpdir(), 'mearl-agent.sock');
28
+ function toControlSourceWireValue(source) {
29
+ return source === 'remote' || source === 'cloud' ? 'cloud' : 'local';
30
+ }
28
31
  /**
29
32
  * Process-wide default browser selector. Lets a long-lived host (e.g. the MCP
30
33
  * server) pin a target once via `select_browser` without threading it through
@@ -266,7 +269,7 @@ function invokeOnce(action, data, timeoutSec, transport, socketPath, controlSour
266
269
  action,
267
270
  data,
268
271
  version: CLIENT_VERSION,
269
- controlSource,
272
+ controlSource: toControlSourceWireValue(controlSource),
270
273
  };
271
274
  if (transport)
272
275
  message.transport = transport;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mearl/client",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "description": "Unified Mearl SDK & CLI for local and remote browsers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,7 +32,7 @@
32
32
  }
33
33
  },
34
34
  "bin": {
35
- "mearl": "./dist/cli.js"
35
+ "mearl": "./dist/bin.js"
36
36
  },
37
37
  "files": [
38
38
  "dist"
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "ws": "^8.18.0",
52
- "@mearl/cloud-types": "2.6.0"
52
+ "@mearl/cloud-types": "2.7.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@types/node": "^24.9.1",
@@ -57,7 +57,7 @@
57
57
  "typescript": "^5.8.3"
58
58
  },
59
59
  "scripts": {
60
- "build": "node ../../scripts/generate-client-action-protocol.mjs --check && rm -rf dist/ && tsc && chmod +x dist/cli.js",
60
+ "build": "node ../../scripts/generate-client-action-protocol.mjs --check && rm -rf dist/ && tsc && chmod +x dist/bin.js",
61
61
  "dev": "tsc --watch",
62
62
  "typecheck": "node ../../scripts/generate-client-action-protocol.mjs --check && tsc --noEmit",
63
63
  "test": "vitest run"