@mearl/client 2.13.0 → 2.15.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 +43 -20
- package/dist/actionTimeouts.js +2 -4
- package/dist/browserRegistry.d.ts +8 -6
- package/dist/buc.d.ts +65 -0
- package/dist/buc.js +533 -0
- package/dist/check.d.ts +9 -9
- package/dist/check.js +9 -7
- package/dist/cli.js +94 -18
- package/dist/commands.d.ts +22 -122
- package/dist/commands.js +21 -125
- package/dist/generated-browser-action-protocol.d.ts +117 -94
- package/dist/generated-browser-action-protocol.js +0 -9
- package/dist/index.d.ts +3 -5
- package/dist/index.js +1 -10
- package/dist/plugin.d.ts +26 -2
- package/dist/plugin.js +52 -3
- package/dist/pluginRegistry.d.ts +5 -1
- package/dist/pluginRegistry.js +15 -3
- package/dist/socket.js +33 -18
- package/dist/unified.d.ts +3 -0
- package/dist/unified.js +25 -13
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -63,15 +63,10 @@ npx @mearl/setup update --local
|
|
|
63
63
|
# 查看某个 action 的帮助
|
|
64
64
|
mearl <action> --help
|
|
65
65
|
|
|
66
|
-
# 启动两个隔离的 headless Chrome
|
|
67
|
-
mearl browser_launch --payload '{"name":"
|
|
68
|
-
mearl browser_launch --payload '{"name":"
|
|
66
|
+
# 启动两个隔离的 headless Chrome
|
|
67
|
+
mearl browser_launch --payload '{"name":"browser-a","url":"https://example.com"}'
|
|
68
|
+
mearl browser_launch --payload '{"name":"browser-b","persistent":true}'
|
|
69
69
|
mearl browser_launch --payload '{"name":"cookie-copy","copyCookieDomains":["example.com"]}'
|
|
70
|
-
mearl browser_launch --payload '{"name":"cloud-login","provider":"agentbay","persistent":true,"userAgentMode":"desktop","copyCookieDomains":["example.com"],"url":"https://example.com/account"}'
|
|
71
|
-
mearl browser_launch --browser '<控制浏览器 browserId>' --payload '{"name":"cloud-login","provider":"agentbay","reuse":"require","copyCookieDomains":["example.com"]}'
|
|
72
|
-
mearl browser_launch --browser '<本地来源 browserId>' --payload '{"sessionId":"<其他设备创建的 AgentBay sessionId>","copyCookieDomains":["example.com"]}'
|
|
73
|
-
mearl browser_launch --payload '{"name":"cloud-tools","provider":"agentbay","copyCookieDomains":"mearl-services"}'
|
|
74
|
-
mearl browser_launch --payload '{"name":"cloud-tools-plus","provider":"agentbay","copyCookieDomains":{"presets":["mearl-services"],"domains":["figma.com"]}}'
|
|
75
70
|
mearl browser_launch --payload '{"name":"figma","userAgentMode":"desktop","copyCookieDomains":["figma.com"]}'
|
|
76
71
|
mearl browser_list
|
|
77
72
|
mearl browser_release
|
|
@@ -79,16 +74,19 @@ mearl browser_release
|
|
|
79
74
|
|
|
80
75
|
### 外部浏览器 Provider
|
|
81
76
|
|
|
82
|
-
Provider 浏览器与扩展、CDP
|
|
77
|
+
Provider 浏览器与扩展、CDP 浏览器一起出现在 `browser_list` 中,并使用同一个
|
|
83
78
|
全局 `browserId` 参与路由。Provider 的安装、更新和卸载由 `@mearl/setup` 管理:
|
|
84
79
|
|
|
85
80
|
```bash
|
|
86
81
|
npx @mearl/setup provider install @ali/mearl-provider-brow
|
|
82
|
+
npx @mearl/setup provider install @ali/mearl-provider-agentbay
|
|
87
83
|
|
|
88
|
-
#
|
|
89
|
-
mearl
|
|
84
|
+
# 查看 Provider 当前版本的能力、参数与使用流程
|
|
85
|
+
mearl brow
|
|
86
|
+
mearl agentbay --help
|
|
90
87
|
|
|
91
|
-
#
|
|
88
|
+
# Provider 启动参数统一放在 providerOptions
|
|
89
|
+
mearl browser_launch --payload '{"provider":"brow","providerOptions":{}}'
|
|
92
90
|
mearl browser_list
|
|
93
91
|
|
|
94
92
|
# 后续操作使用 browser_list 返回的全局 Browser ID
|
|
@@ -130,7 +128,7 @@ Mearl 默认聚合当前机器和已配置 cloud-server 下的浏览器,并通
|
|
|
130
128
|
`browser_list --help` 和 `browser_launch --help` 会按场景展示宿主选择参数;连接或传输排障运行
|
|
131
129
|
`mearl check --help`。其中 `--json` 仅用于输出机器可读的检查结果。
|
|
132
130
|
|
|
133
|
-
## Skill
|
|
131
|
+
## Skill 插件
|
|
134
132
|
|
|
135
133
|
安装 skill 并自动注册命令,或直接注册已有入口:
|
|
136
134
|
|
|
@@ -158,19 +156,44 @@ setup 会补齐缺失或低于自身版本的 client、native-host;安装参
|
|
|
158
156
|
插件接受位置参数或包含 command/input 的 `--payload`,两种形式不能混用。JSON 保留业务字段类型;正文等文件输入
|
|
159
157
|
按具体 skill 的字段约定处理。插件不使用上表中内置 action 的 `--payload-file` 入口。
|
|
160
158
|
|
|
159
|
+
注册后的插件也可从 SDK 调用;实例方法 `client.invokePlugin` 复用既有连接和默认浏览器:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { invokePlugin } from '@mearl/client';
|
|
163
|
+
|
|
164
|
+
const result = await invokePlugin(
|
|
165
|
+
'yuque',
|
|
166
|
+
{ command: 'read', input: { url: 'https://aliyuque.antfin.com/group/book/doc' } },
|
|
167
|
+
{ browser: 'work' },
|
|
168
|
+
);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
MCP Server 通过固定工具 `mearl_plugin` 接受同样的 `plugin`、`command` 和 `input`,不会把插件子命令动态扩展成 MCP 工具。SDK 与 MCP 都只解析本机 registry 中已注册的名称,不接受任意入口路径。
|
|
172
|
+
|
|
161
173
|
注册记录在 `~/.mearl/plugins/<name>.json`,保存入口路径和可选的简短描述;skill 业务代码原地更新直接生效,换路径或更新描述后重新注册。
|
|
162
174
|
`plugin uninstall <name>` 会对 `~/.agents/skills` 中的全局 Skill 调用 `ali-skills remove --global --yes`,
|
|
163
175
|
成功后清除相关注册;即使入口目录已被手动删除,也会完成 Ali Skills 跟踪记录的清理。
|
|
164
176
|
手工路径只解除注册并保留源码。
|
|
165
177
|
`PLUGIN_NOT_REGISTERED` 表示插件尚未注册。`PLUGIN_ENTRY_MISSING` 会显示失效入口,并给出带有实际插件名的
|
|
166
178
|
卸载清理命令。其他错误按实际原因处理。
|
|
167
|
-
编写规范见 [Mearl Skill Creator 的
|
|
179
|
+
编写规范见 [Mearl Skill Creator 的 Skill 插件规范](../skills/mearl-skill-creator/references/cli-plugin.md)。
|
|
180
|
+
|
|
181
|
+
插件通过 `app.buc.request({ app, auth, url, ... })` 调用需要 BUC 身份的内部 HTTP 接口。`auth` 支持
|
|
182
|
+
`id-token`(默认)、`ticket-header` 和兼容旧服务的 `ticket-query`。Mearl 按请求创建一次性凭据并注入
|
|
183
|
+
`Authorization` + `DPoP`、`SSO-TICKET` Header 或 `SSO_TICKET` Query,只允许访问 HTTPS
|
|
184
|
+
`alibaba-inc.com` 域名;凭据不会返回给插件,也不会复用到下一次请求,调用方也不能自行传入这些认证字段。
|
|
185
|
+
`app.buc.whoami()` 返回当前身份的
|
|
186
|
+
`empId` 和姓名,并在 Agent 身份场景返回 `agentId`;仅在确实需要部门等详细字段时使用
|
|
187
|
+
`app.buc.profile()`,它通过一次性 `alineiwai` Ticket
|
|
188
|
+
建立内存会话、校验资料属于当前员工,并只返回白名单字段,Ticket 与 Cookie 均不暴露给插件。
|
|
189
|
+
缺少 BUC CLI 时 Mearl 会从官方 CLI Hub 安装后重试。这些方法与 `app.invoke` 一样,只能在插件 handler
|
|
190
|
+
执行期间调用。BUC 请求始终在运行 CLI、SDK 或 MCP Server 的机器上执行,不会随浏览器或 connector 转发到远端浏览器宿主。
|
|
168
191
|
|
|
169
192
|
## 支持的操作
|
|
170
193
|
|
|
171
194
|
| 分类 | Actions |
|
|
172
195
|
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
173
|
-
| API 调试 | `tab_checkpoint` `get_requests` `get_logs` `get_events`
|
|
196
|
+
| API 调试 | `tab_checkpoint` `get_requests` `get_logs` `get_events` |
|
|
174
197
|
| Mock & 规则 | `set_mock` `get_mocks` `set_rule` `get_rules` |
|
|
175
198
|
| 网络请求 | `send_request` `send_mtop_request` `request_domain_permission` |
|
|
176
199
|
| 标签页 | `tab_open` `tab_close` `tab_list` |
|
|
@@ -178,9 +201,7 @@ setup 会补齐缺失或低于自身版本的 client、native-host;安装参
|
|
|
178
201
|
| 组合调用 | `run_actions` |
|
|
179
202
|
| 页面感知 | `page_snapshot` `page_screenshot` `page_selected_element` `page_frames` |
|
|
180
203
|
| 环境与 Cookie | `set_device_emulation` `set_app_profile` `set_timezone` `get_cookie` `set_cookie` |
|
|
181
|
-
| 用户信息 | `get_user_info` |
|
|
182
204
|
| 录制 | `record_start` `record_stop` |
|
|
183
|
-
| TDBank | `tdbank_account` |
|
|
184
205
|
| 浏览器 | `browser_list` `browser_release` `browser_launch` `browser_close` |
|
|
185
206
|
|
|
186
207
|
页面交互动作(`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` 默认裸执行,可按需开启观察或诊断。
|
|
@@ -193,9 +214,11 @@ setup 会补齐缺失或低于自身版本的 client、native-host;安装参
|
|
|
193
214
|
`regular` / `managed`,`status` 区分 `connected` / `pairing` / `running_disconnected` /
|
|
194
215
|
`stopped`;只有 `connected` 的浏览器可作为常规操作目标。
|
|
195
216
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
217
|
+
`browser_release` 仅在用户明确要求结束调试、退出接管或清理会话资源时调用;它会释放
|
|
218
|
+
debugger/CDP 控制和会话级临时状态,保留浏览器及全部标签页。托管实例的启动、关闭、持久化、
|
|
219
|
+
接入和登录态同步语义由各 Provider 声明;运行 `mearl <providerId>` 获取当前说明。访问入口不在
|
|
220
|
+
`browser_list` 中,需要时显式运行 `mearl check --browser <id|名称>`,并把返回的
|
|
221
|
+
`browserAccess.url` 按敏感信息处理。
|
|
199
222
|
|
|
200
223
|
## 架构
|
|
201
224
|
|
package/dist/actionTimeouts.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { PAGE_ACT_ACTIONS } from './generated-browser-action-protocol.js';
|
|
2
2
|
const SEND_REQUEST_FILE_TRANSFER_TIMEOUT_MS = 120_000;
|
|
3
|
-
//
|
|
3
|
+
// Remote Providers may stage files before forwarding a page upload.
|
|
4
4
|
const PAGE_UPLOAD_FILE_TRANSFER_TIMEOUT_MS = 180_000;
|
|
5
|
-
//
|
|
5
|
+
// Persistent Providers may need to synchronize remote state before closing an instance.
|
|
6
6
|
const BROWSER_CLOSE_TIMEOUT_SEC = 18 * 60;
|
|
7
7
|
function boundedNumber(value, fallback, minimum, maximum) {
|
|
8
8
|
const numeric = Number(value);
|
|
@@ -41,8 +41,6 @@ export function resolveActionTimeoutSec(action, data, fallback = 15) {
|
|
|
41
41
|
return Math.max(fallback, 90);
|
|
42
42
|
if (action === 'browser_close')
|
|
43
43
|
return Math.max(fallback, BROWSER_CLOSE_TIMEOUT_SEC);
|
|
44
|
-
if (action === 'tdbank_account')
|
|
45
|
-
return Math.max(fallback, 20);
|
|
46
44
|
if (action === 'run_actions') {
|
|
47
45
|
const actions = Array.isArray(data.actions) ? data.actions : [{}];
|
|
48
46
|
const timeoutSec = actions.reduce((total, step) => {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* registry directory and record shape; reading scans every *.json in the dir,
|
|
9
9
|
* so it never needs to replicate daemon-core's filename hashing.
|
|
10
10
|
*/
|
|
11
|
-
import type { BrowserCapabilities, BrowserPairingInfo, BrowserTransport } from './generated-browser-action-protocol.js';
|
|
11
|
+
import type { BrowserCapabilities, BrowserDetails, BrowserPairingInfo, BrowserProviderIdentity, BrowserProviderOperation, BrowserReference, BrowserTransport } from './generated-browser-action-protocol.js';
|
|
12
12
|
export interface LiveBrowser {
|
|
13
13
|
pid: number;
|
|
14
14
|
browserId: string;
|
|
@@ -18,13 +18,15 @@ export interface LiveBrowser {
|
|
|
18
18
|
nativeHostVersion?: string;
|
|
19
19
|
transport?: BrowserTransport;
|
|
20
20
|
providerBrowserId?: string;
|
|
21
|
-
|
|
22
|
-
providerName?: string;
|
|
23
|
-
providerVersion?: string;
|
|
24
|
-
providerProtocolVersion?: number;
|
|
21
|
+
provider?: BrowserProviderIdentity;
|
|
25
22
|
capabilities?: BrowserCapabilities;
|
|
26
|
-
status?: 'connected' | 'pairing';
|
|
23
|
+
status?: 'connected' | 'pairing' | 'running_disconnected' | 'stopped';
|
|
24
|
+
ownership?: 'owned' | 'attached';
|
|
25
|
+
persistence?: 'ephemeral' | 'persistent';
|
|
26
|
+
operations?: BrowserProviderOperation[];
|
|
27
27
|
pairing?: BrowserPairingInfo;
|
|
28
|
+
references?: BrowserReference[];
|
|
29
|
+
details?: BrowserDetails;
|
|
28
30
|
lastFocusedAt?: number;
|
|
29
31
|
updatedAt?: number;
|
|
30
32
|
}
|
package/dist/buc.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
interface ProgramResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
}
|
|
5
|
+
export interface BucIdentity {
|
|
6
|
+
agentId?: string;
|
|
7
|
+
empId: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface BucProfile extends BucIdentity {
|
|
11
|
+
bucUserId?: string;
|
|
12
|
+
gid?: string;
|
|
13
|
+
empType?: string;
|
|
14
|
+
photoPath?: string;
|
|
15
|
+
displayName?: string;
|
|
16
|
+
nickName?: string;
|
|
17
|
+
deptId?: string;
|
|
18
|
+
admin?: boolean;
|
|
19
|
+
buName?: string;
|
|
20
|
+
buNo?: string;
|
|
21
|
+
deptDesc?: string;
|
|
22
|
+
lang?: string;
|
|
23
|
+
cid?: string;
|
|
24
|
+
jobDesc?: string;
|
|
25
|
+
loginWorkNo?: string;
|
|
26
|
+
}
|
|
27
|
+
export type BucRequestFormValue = string | number | boolean;
|
|
28
|
+
export type BucRequestAuth = 'id-token' | 'ticket-header' | 'ticket-query';
|
|
29
|
+
export interface BucRequestParams {
|
|
30
|
+
app: string;
|
|
31
|
+
url: string;
|
|
32
|
+
auth?: BucRequestAuth;
|
|
33
|
+
method?: string;
|
|
34
|
+
headers?: Record<string, string>;
|
|
35
|
+
params?: Record<string, string | number | boolean | null | undefined>;
|
|
36
|
+
body?: unknown;
|
|
37
|
+
formData?: Record<string, BucRequestFormValue>;
|
|
38
|
+
responseType?: 'json' | 'text' | 'auto';
|
|
39
|
+
timeoutMs?: number;
|
|
40
|
+
}
|
|
41
|
+
export interface BucRequestResult {
|
|
42
|
+
status: number;
|
|
43
|
+
statusText: string;
|
|
44
|
+
headers: Record<string, string>;
|
|
45
|
+
body: unknown;
|
|
46
|
+
}
|
|
47
|
+
export interface BucApi {
|
|
48
|
+
request(params: BucRequestParams): Promise<BucRequestResult>;
|
|
49
|
+
whoami(): Promise<BucIdentity>;
|
|
50
|
+
profile(): Promise<BucProfile>;
|
|
51
|
+
}
|
|
52
|
+
export type BucCommandRunner = (args: string[]) => Promise<ProgramResult>;
|
|
53
|
+
export interface BucDependencies {
|
|
54
|
+
fetch?: typeof fetch;
|
|
55
|
+
installBuc?: () => Promise<void>;
|
|
56
|
+
runBuc?: BucCommandRunner;
|
|
57
|
+
}
|
|
58
|
+
export declare const runBucCommand: BucCommandRunner;
|
|
59
|
+
export declare function installBucCli(): Promise<void>;
|
|
60
|
+
export declare function bucWhoami(dependencies?: BucDependencies): Promise<BucIdentity>;
|
|
61
|
+
export declare function bucProfile(dependencies?: BucDependencies): Promise<BucProfile>;
|
|
62
|
+
/** Executes one internal request with a fresh credential in the selected BUC authentication mode. */
|
|
63
|
+
export declare function bucRequest(input: BucRequestParams, dependencies?: BucDependencies): Promise<BucRequestResult>;
|
|
64
|
+
export declare const buc: BucApi;
|
|
65
|
+
export {};
|