@mearl/client 3.0.0-beta.1 → 3.0.0-beta.10

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.
Files changed (72) hide show
  1. package/README.md +333 -246
  2. package/README.zh-CN.md +612 -0
  3. package/dist/actionTimeouts.js +0 -3
  4. package/dist/autoUpdate.js +3 -1
  5. package/dist/bin.js +12 -5
  6. package/dist/capabilityHelp.d.ts +4 -0
  7. package/dist/capabilityHelp.js +68 -0
  8. package/dist/check.d.ts +5 -6
  9. package/dist/check.js +2 -5
  10. package/dist/cli.js +29 -56
  11. package/dist/commandHelp.d.ts +3 -0
  12. package/dist/commandHelp.js +79 -0
  13. package/dist/commandSuggestions.d.ts +3 -0
  14. package/dist/commandSuggestions.js +16 -5
  15. package/dist/commands.d.ts +70 -65
  16. package/dist/commands.js +60 -55
  17. package/dist/guide.d.ts +46 -0
  18. package/dist/guide.js +80 -0
  19. package/dist/guides/api-browser-setup.md +93 -0
  20. package/dist/guides/api-page-automation.md +140 -0
  21. package/dist/guides/api-page-debugging.md +39 -0
  22. package/dist/guides/api-page-environment.md +37 -0
  23. package/dist/guides/api-request-debugging.md +54 -0
  24. package/dist/guides/browser-tool-cooperation.md +23 -0
  25. package/dist/guides/core.md +60 -0
  26. package/dist/guides/related-skills.md +51 -0
  27. package/dist/guides/scripting.md +21 -0
  28. package/dist/guides/troubleshooting.md +170 -0
  29. package/dist/index.d.ts +5 -2
  30. package/dist/index.js +8 -5
  31. package/dist/plugins/clients/pluginHostConnection.d.ts +2 -0
  32. package/dist/plugins/clients/pluginHostConnection.js +3 -1
  33. package/dist/plugins/officialPluginInstaller.js +2 -1
  34. package/dist/plugins/pluginRegistry.d.ts +1 -1
  35. package/dist/plugins/pluginRegistry.js +21 -7
  36. package/dist/plugins/runtime/pluginCommandWorker.js +8 -6
  37. package/dist/plugins/runtime/pluginDiagnostics.js +1 -1
  38. package/dist/plugins/runtime/pluginExecutor.d.ts +5 -0
  39. package/dist/plugins/runtime/pluginExecutor.js +15 -2
  40. package/dist/plugins/runtime/pluginExecutorProtocol.d.ts +4 -0
  41. package/dist/plugins/runtime/pluginExecutorSupervisor.js +2 -1
  42. package/dist/plugins/runtime/pluginHostServer.js +5 -1
  43. package/dist/plugins/runtime/pluginPageManager.js +2 -6
  44. package/dist/plugins/runtime/pluginRevision.js +0 -51
  45. package/dist/plugins/runtime/pluginStateManager.js +1 -1
  46. package/dist/plugins/runtime/pluginStateStore.js +3 -8
  47. package/dist/plugins/runtime/pluginTaskManager.js +5 -9
  48. package/dist/plugins/sdk/plugin.d.ts +9 -0
  49. package/dist/plugins/sdk/plugin.js +22 -9
  50. package/dist/plugins/sdk/pluginModelDefinition.js +0 -6
  51. package/dist/plugins/sdk/pluginPageDefinition.d.ts +0 -1
  52. package/dist/plugins/sdk/pluginPageDefinition.js +2 -18
  53. package/dist/plugins/sdk/pluginRecoveryDefinition.js +0 -3
  54. package/dist/plugins/sdk/pluginStateDefinition.d.ts +0 -1
  55. package/dist/plugins/sdk/pluginStateDefinition.js +0 -11
  56. package/dist/runtimePaths.d.ts +1 -0
  57. package/dist/runtimePaths.js +1 -0
  58. package/dist/script.d.ts +30 -0
  59. package/dist/script.js +261 -0
  60. package/dist/scriptCli.d.ts +1 -0
  61. package/dist/scriptCli.js +94 -0
  62. package/dist/scriptErrors.d.ts +8 -0
  63. package/dist/scriptErrors.js +21 -0
  64. package/dist/scriptWorker.d.ts +1 -0
  65. package/dist/scriptWorker.js +50 -0
  66. package/dist/sdkMethods.d.ts +3 -0
  67. package/dist/sdkMethods.js +9 -0
  68. package/dist/socket.js +33 -8
  69. package/dist/unified.js +11 -1
  70. package/dist/unifiedConfig.d.ts +4 -0
  71. package/dist/unifiedConfig.js +11 -0
  72. package/package.json +14 -12
package/README.md CHANGED
@@ -1,25 +1,31 @@
1
1
  # @mearl/client
2
2
 
3
- 本仓库仍在迁移完整宿主。此包已可独立构建和测试,setup/native-host/extension 的公开发行接入尚未完成;下列产品命令描述其现有合同,不代表已发布 3.0。
3
+ [English](README.md) | [简体中文](README.zh-CN.md)
4
4
 
5
- 统一浏览器 SDK 与 CLI。它会发现当前机器及已配置 cloud-server 下所有 connector 的浏览器,并根据 `browser_list` 返回的全局 `browserId` 自动选择本地 Socket 或云端 WebSocket 链路。
5
+ CLI, TypeScript SDK, and scripting entry points share browser routing and plugin runtimes. `@mearl/setup` manages installation and runtime connections.
6
6
 
7
- 提供两种用法:类型安全的具名方法(`getRequests`、`sendRequest` 等),以及灵活的底层 `invoke(action, payload)`。
7
+ Run `mearl guide` for the core workflow in this version; `mearl guide --list` lists topics. For example, `mearl guide run` covers SDK composition and `mearl guide environment` covers devices/Apps. Guides read bundled npm resources without browser connections, plugin loading, installation, or automatic updates. Use `mearl <action> --help` for arguments and existing catalogs for installed target capabilities.
8
8
 
9
- ## 安装
9
+ Guide content is maintained only in this package's `guides/`, copied to `dist/guides/` at build time, and checked by `pnpm check:skills`. CLI output converts local document links into guide commands. `skills/mearl/` distributes only a compact `SKILL.md`, without guide copies. MCP-only clients unable to run CLI use current tool descriptions/schemas. Organization-specific distributions supply installation, authentication, and business guidance through separate Skills.
10
+
11
+ A unified browser SDK and CLI discovering browsers on this machine and all connectors under configured cloud-server instances. Global `browserId` from `browser_list` selects local Socket or cloud WebSocket routing automatically.
12
+
13
+ Use type-safe named methods such as `getRequests` and `sendRequest`, or the flexible low-level `invoke(action, payload)`.
14
+
15
+ ## Installation
10
16
 
11
17
  ```bash
12
- npm install @mearl/client
13
- # 或
14
- pnpm add @mearl/client
18
+ npm install @mearl/client@beta
19
+ # Or
20
+ pnpm add @mearl/client@beta
15
21
  ```
16
22
 
17
- ## SDK 使用
23
+ ## SDK usage
18
24
 
19
25
  ```typescript
20
26
  import * as client from '@mearl/client';
21
27
 
22
- // 具名方法(类型安全)
28
+ // Type-safe named methods
23
29
  const requests = await client.getRequests({ tabId: 12345, count: 5 });
24
30
  const result = await client.sendRequest({
25
31
  url: 'https://api.example.com',
@@ -27,45 +33,45 @@ const result = await client.sendRequest({
27
33
  withCookies: true,
28
34
  });
29
35
 
30
- // 底层通用方法(灵活扩展)
36
+ // Flexible low-level invocation
31
37
  const data = await client.invoke('send_request', { url: '...' });
32
38
 
33
- // browser_list 默认聚合本机和所有远端 connector
39
+ // browser_list aggregates local and all remote connectors by default
34
40
  const browsers = await client.browserList();
35
41
  await client.getLogs({ tabId: 12345 }, { browser: browsers.browsers[0].browserId });
36
42
  ```
37
43
 
38
- ## CLI 使用
44
+ ## CLI usage
39
45
 
40
- 安装后提供 `mearl` 命令:
46
+ Installation provides the `mearl` command:
41
47
 
42
48
  ```bash
43
- # 获取最近 5 个请求
49
+ # Get the five latest requests
44
50
  mearl get_requests --payload '{"tabId":12345,"count":5}'
45
51
 
46
- # 代理一个 HTTP 请求
52
+ # Proxy an HTTP request
47
53
  mearl send_request --payload '{"url":"https://api.example.com","method":"GET"}'
48
54
 
49
- # 以 multipart/form-data 上传本地文件
55
+ # Upload a local file with multipart/form-data
50
56
  mearl send_request --payload '{"url":"https://api.example.com/upload","method":"POST","formData":{"folder":"assets"},"files":[{"fieldName":"file","filePath":"/absolute/path/image.png"}]}'
51
57
 
52
- # 截图并保存(tabId 来自 tab_open 或 tab_list)
58
+ # Save a screenshot; tabId comes from tab_open or tab_list
53
59
  mearl page_screenshot --payload '{"tabId":12345}' --output ./screenshot.png
54
60
 
55
- # 从文件读取大体积参数(mock-data.json 需包含 tabId)
61
+ # Read large parameters from a file; mock-data.json must include tabId
56
62
  mearl set_mock --payload-file ./mock-data.json
57
63
 
58
- # 环境自检
64
+ # Check the environment
59
65
  mearl check
60
66
  mearl check --local --json
61
67
 
62
- # 更新本地环境
63
- npx @mearl/setup update --local
68
+ # Update the local environment
69
+ npx @mearl/setup@beta update --local
64
70
 
65
- # 查看某个 action 的帮助
71
+ # Show action help
66
72
  mearl <action> --help
67
73
 
68
- # 启动两个隔离的 headless Chrome
74
+ # Launch isolated headless Chrome instances
69
75
  mearl browser_launch --payload '{"name":"browser-a","url":"https://example.com"}'
70
76
  mearl browser_launch --payload '{"name":"browser-b","persistent":true}'
71
77
  mearl browser_launch --payload '{"name":"cookie-copy","copyCookieDomains":["example.com"]}'
@@ -74,47 +80,120 @@ mearl browser_list
74
80
  mearl browser_release
75
81
  ```
76
82
 
77
- ### 控制会话与文件
83
+ ### Agent scripts
84
+
85
+ `mearl run` reads JavaScript from stdin or `--file <path>`, injects the `mearl` SDK, and supports top-level `await`, conditions, loops, and data processing without task-directory dependencies:
86
+
87
+ ```bash
88
+ mearl run --session new <<'JS'
89
+ const tab = await mearl.tabOpen({ url: 'https://example.com', reuse: 'prefer' });
90
+ console.log({ tabId: tab.tabId, session: mearl.session });
91
+ console.log(await mearl.pageSnapshot({ tabId: tab.tabId, mode: 'viewport' }));
92
+ JS
93
+
94
+ mearl run --session '<sessionId>' --file /absolute/path/next-step.mjs
95
+ ```
96
+
97
+ Method names match the SDK, such as `mearl.pageClick(params, options?)`, `mearl.getRequests(params, options?)`,
98
+ and `mearl.tabList(options?)`. Use `mearl.invoke(action, payload, options?)` for generic calls.
99
+ Arguments/results match ordinary actions; consult `mearl <action> --help`. Action failures still use `action.success`,
100
+ `stage`, and `attempt`; scripts decide subsequent logic. Print needed results with `console.log` and diagnostics with `console.error`.
101
+ Returned data is not printed automatically. `run_actions` fits tight sequences without decisions; scripts fit workflows whose results code can evaluate.
102
+ When a model must interpret the page, print minimal observations and continue in the next round.
103
+
104
+ Scripts query command definitions through `help` and print returned text as needed. CLI `--help` shares arguments, results, constraints, and examples.
105
+
106
+ ```javascript
107
+ console.log(await mearl.help()); // Methods and registered plugins
108
+ console.log(await mearl.help('pageClick')); // Also accepts page_click
109
+ console.log(await mearl.help({ plugin: 'notes', command: 'search' }));
110
+
111
+ const result = await mearl.invokePlugin('notes', { command: 'search', input: { query: 'project' } });
112
+ console.log(mearl.structure(result));
113
+ ```
114
+
115
+ `structure(value, options?)` synchronously extracts an existing result's structure, replacing leaves with types. Defaults: depth 5, 50 keys per object,
116
+ one sample per array, 2000 total nodes. Adjust with `maxDepth`, `maxKeys`, `arraySamples`, and `maxNodes`.
117
+ Output includes array lengths/samples and marks cycles, accessors, and limits. Samples need not cover all optional fields or heterogeneous elements;
118
+ command help defines business meaning. The ordinary SDK also exports `structure`, sharing extraction logic with request `keysOnly`.
119
+ `keysOnly` follows the same default key/node limits and marks truncation.
120
+ Plugin help loads registration in isolated processes without executing the queried business command.
121
+
122
+ Compose registered Skill commands using names and inputs from plugin `--help`:
123
+
124
+ ```javascript
125
+ const result = await mearl.invokePlugin('notes', {
126
+ command: 'search',
127
+ input: { query: 'project' },
128
+ });
129
+ console.log(result);
130
+ ```
131
+
132
+ Browser APIs and plugin calls inherit script `--browser`, `--session`, `--connector`, `--local`, and `--cdp`;
133
+ individual `options` may override them. `--server` selects cloud-server. After `--session new` establishes a session,
134
+ later calls use its returned ID automatically; `mearl.session` and CLI stderr report session information.
135
+ First await a session-establishing browser call before concurrency or Skill commands. Script completion disconnects SDK connections but retains control sessions;
136
+ explicitly call `mearl.browserRelease` according to task lifetime. JavaScript variables reset each round; continue with returned `sessionId` and `tabId`.
78
137
 
79
- 多步骤任务首次 `tab_open` 或 `page_snapshot` 使用 `--session new`,响应在原结果旁附带 `session`,后续用其 `sessionId` 自动路由,无需额外创建/查询 action。Session 绑定一个浏览器与传输;页面首次使用自动关联,复用页面与新建页面分别记录。同一页面只允许一个会话控制,旧调用不能绕过占用;Session 不隔离 Cookie 或存储。
138
+ Scripts run in separate Node.js processes inheriting caller cwd/environment with host Node.js permissions;
139
+ they are not security sandboxes. Load modules through dynamic imports such as `await import('node:fs/promises')`.
140
+ `--file` also executes as a script function without static `import` / `export`. Prefer absolute file URLs for local modules.
141
+ `window` / `document` exist only in page expressions through `mearl.pageEval`. Plugin registries, local files, and authentication belong to the CLI host.
80
142
 
81
- `sessionId` 是形如 `s_aB3d_E-f` 的短 ID。会话及其浏览器、传输映射保存在常驻控制宿主的内存中;新的 CLI 进程会内部查询本机和远端宿主完成路由,无需调用方保存或传递路由信息,也不写入会话映射文件。控制宿主退出后会话失效。
143
+ `--timeout <seconds>` limits the complete script, default 60 seconds. API `options.timeoutSec` limits individual calls.
144
+ Combined stdout/stderr allows 256 KiB; source allows 1 MiB. Await every SDK call. Missing await, timeout, cancellation, or script exceptions exit 1;
145
+ input errors exit 2. Cancellation/timeouts stop scripts and process groups and propagate signals to pending Skill calls. Dispatched browser/business operations may still take effect;
146
+ use `pendingActions` / `mayHaveLateEffects` to determine reconciliation needs, without directly rerunning the entire script.
147
+ Skill commands use existing isolated executors; their stdout/stderr counts toward the script limit. Exception diagnostics are also bounded.
148
+ Result `success` means normal script completion only. Code must check action and business outcomes.
82
149
 
83
- 旧调用不必传 `--session`,现有动作、`run_actions` 批次和上传 `filePaths` 参数继续可用。活动会话存在时,旧调用不能操作其占用页面、执行浏览器级释放/关闭或修改共享设置;旧批次中的开页/关闭浏览器需改为独立调用。CDP Mock 按标签页生效,跨页使用同一 Mock 时需分别配置。
150
+ SDK hosts can import `executeScript(code, options)` from `@mearl/client/script`, returning
151
+ `{ success, stdout, stderr, session?, error?, executionStopped, mayHaveLateEffects, pendingActions }`。
152
+ It supports `signal` cancellation and `executionTimeoutSec`, sharing executors with CLI/MCP.
153
+
154
+ ### Control sessions and files
155
+
156
+ For multi-step tasks, use `--session new` on the first `tab_open` or `page_snapshot`. The response adds `session` alongside ordinary results; later `sessionId` routes automatically without separate creation/query actions. Sessions bind one browser/transport and associate pages on first use, tracking reused and created pages separately. One session controls a page at a time; sessionless calls cannot bypass ownership. Sessions do not isolate Cookies/storage.
157
+
158
+ `sessionId` is a short ID such as `s_aB3d_E-f`. The resident control host keeps sessions/browser/transport mappings in memory. New CLI processes internally query local/remote hosts for routing, without caller-managed routing or mapping files. Control-host exit invalidates sessions.
159
+
160
+ Calls may omit `--session`; existing actions, `run_actions`, and upload `filePaths` remain available. With active sessions, sessionless calls cannot manipulate owned pages, release/close browsers, or modify shared settings. Opening pages/closing browsers inside sessionless batches requires separate calls. CDP mocks are tab-scoped and must be configured per tab.
84
161
 
85
162
  ```bash
86
163
  mearl tab_open --session new --payload '{"url":"https://example.com"}'
87
164
  mearl page_snapshot --session '<sessionId>' --payload '{"tabId":12345}'
88
- mearl browser_control --session '<sessionId>' --payload '{"operation":"handoff","reason":"请完成扫码"}'
165
+ mearl browser_control --session '<sessionId>' --payload '{"operation":"handoff","reason":"Please scan the QR code"}'
89
166
  mearl page_download --session '<sessionId>' --payload '{"tabId":12345,"trigger":{"selector":"#export"}}' --output /absolute/path/report.csv
90
167
  mearl page_upload --session '<sessionId>' --payload '{"tabId":12345,"selector":"input[type=file]","files":[{"filePath":"/absolute/path/report.csv"}]}'
91
168
  mearl browser_release --session '<sessionId>' --payload '{"closeCreatedTabs":true,"keepTabIds":[12345]}'
92
169
  ```
93
170
 
94
- 用户在 Popup 的浏览器管理页接管、交还或结束会话。交接后排队旧请求和批次后续步骤停止;已派发动作可能仍然生效。交还后重新取快照。CDP-only 环境可在用户明确确认后用同一 `browser_control` 的 `operation:"resume"` 交还,无需额外 action。会话跨 CLI 连接保留,宿主进程退出后失效;不会根据空闲时间清理用户正在操作的会话。
171
+ Users take over, return, or end sessions in Popup browser management. Handoff stops queued stale requests and later batch steps; dispatched actions may still apply. Take a fresh snapshot after return. CDP-only environments can use the same `browser_control` with `operation:"resume"` after explicit user confirmation. Sessions survive CLI connections, expire on host exit, and are not idle-cleaned while users work.
95
172
 
96
- 带 Session 的释放只影响该会话,默认保留页面及环境;`closeCreatedTabs` 只关闭新建页,`keepTabIds` 保留结果页,复用的用户页面始终保留。`preserveEnvironment:false` 清理这些页面的环境。活动会话存在时,浏览器级释放与关闭会被拒绝。
173
+ New extension background tabs join a collapsed `Mearl` group; foreground tabs join the expanded `Mearl · 待操作` group. Both reuse one existing window and merge same-name managed groups. Subsequent opened tabs enter that window and inherit source-group expansion. Closing the work window selects another existing window without creating one. Explicit `tab_open.group` overrides grouping; reused ordinary pages retain windows/groups. Handoff moves only managed session pages into the pending group; return moves those still pending into `Mearl`. Groups remain expanded if users view other grouped pages or the window has no other visible page.
97
174
 
98
- `page_download` 先监听再点击,返回浏览器文件产物;CLI `--output` 或 SDK `saveArtifact(artifact, absolutePath, { session })` 以 256 KiB 分块导出到调用方。`page_upload.files` 接受调用方绝对路径 `{filePath}` 或浏览器 `{artifactId}`,`filePaths` 仍指浏览器宿主路径。单文件最多 256 MiB;保存到调用方的结果独立于临时产物。会话释放清理临时产物,`keepArtifactIds` 可保留指定产物;无会话产物空闲一小时回收,宿主退出清理暂存。
175
+ Session release affects only that session and keeps pages/environments by default. `closeCreatedTabs` closes only created pages; `keepTabIds` retains results. Reused user pages always remain. `preserveEnvironment:false` clears those pages' environment. Active sessions block browser-wide release/close.
99
176
 
100
- 扩展捕获下载需要匹配来源页 referrer 或明确的预期 `url`,无法归属时不会认领最近下载。CDP 只在托管浏览器中使用临时下载目录,共享浏览器保持默认目录,Chrome 未返回完成文件路径时明确报错。下载超时可能已经触发,需检查现场再决定下一步。当前会话与下载适配 Extension/CDP;直接处理页面动作的外部 Provider 对不支持的能力明确报错。
177
+ `page_download` listens before clicking and returns a browser artifact. CLI `--output` or SDK `saveArtifact(artifact, absolutePath, { session })` exports in 256 KiB chunks. `page_upload.files` accepts caller absolute `{filePath}` or browser `{artifactId}`; `filePaths` remains browser-host paths. Files are limited to 256 MiB. Caller-saved outputs are independent of temporary artifacts. Session release cleans temporary artifacts; `keepArtifactIds` retains selected ones. Sessionless artifacts expire after one idle hour; host exit clears staging.
101
178
 
102
- ### 外部浏览器 Provider
179
+ Extension downloads require matching page referrers or an explicit expected `url`; unowned downloads are not guessed from recent files. CDP uses temporary directories only for managed browsers; shared browsers retain defaults and fail explicitly if Chrome provides no completed path. Timeouts may follow triggered downloads: inspect state before continuing. Session/download adapters support Extension/CDP; external action-handling Providers reject unsupported capabilities explicitly.
103
180
 
104
- Provider 浏览器与扩展、CDP 浏览器一起出现在 `browser_list` 中,并使用同一个
105
- 全局 `browserId` 参与路由。Provider 的安装、更新和卸载由 `@mearl/setup` 管理:
181
+ ### External browser Providers
182
+
183
+ Provider browsers appear beside Extension/CDP browsers in `browser_list` and use the same
184
+ global `browserId` routing. `@mearl/setup` manages installation, updates, and removal:
106
185
 
107
186
  ```bash
108
187
  npx @mearl/setup provider install @example/mearl-provider-device
109
188
 
110
- # 查看 Provider 当前版本的能力、参数与使用流程
189
+ # Inspect this Provider version's capabilities, arguments, and workflow
111
190
  mearl example-device --help
112
191
 
113
- # Provider 启动参数统一放在 providerOptions
192
+ # Provider launch arguments use providerOptions
114
193
  mearl browser_launch --payload '{"provider":"example-device","providerOptions":{}}'
115
194
  mearl browser_list
116
195
 
117
- # 后续操作使用 browser_list 返回的全局 Browser ID
196
+ # Use global Browser IDs returned by browser_list for later operations
118
197
  mearl tab_list --browser '<browserId>'
119
198
  mearl page_snapshot --payload '{"tabId":12345}' --browser '<browserId>'
120
199
 
@@ -122,58 +201,62 @@ npx @mearl/setup provider update brow
122
201
  npx @mearl/setup provider uninstall brow
123
202
  ```
124
203
 
125
- `browser_launch` 创建 `pairing` 实例时会直接返回 `pairing.url` 和可选的配对码;Agent 应把 URL 直接渲染为
126
- 二维码交给用户,扫码后确认同一 Browser ID 变为 `connected`,再开始页面操作。在设备连入前
127
- 该实例不会成为默认操作目标;可用 `browser_close` 删除对应 Provider 实例。每个 Provider
128
- 只接收它为该浏览器显式声明支持的 actions,截图能力同时标明为原生截图、重建画面或不支持。
204
+ Creating a `pairing` instance with `browser_launch` returns `pairing.url` and an optional pairing code. Agents should render the URL directly as
205
+ a QR code, then confirm the same Browser ID becomes `connected` before page operations. Until the device connects,
206
+ it cannot become the default target. Use `browser_close` to delete the Provider instance. Each Provider
207
+ receives only explicitly supported actions; screenshot support distinguishes native captures, reconstructed images, and unsupported.
129
208
 
130
- 输入不存在或拼写有误的 action 时,CLI 会基于可用命令和常见别名直接返回最多三个候选及调用示例,
131
- 不连接浏览器,也不会自动执行推荐命令。例如 `mearl tab new` 会优先推荐 `mearl tab_open`。
209
+ Unknown or misspelled actions return up to three candidates and examples based on available commands/common aliases,
210
+ without connecting to browsers or executing suggestions. For example, `mearl tab new` prefers `mearl tab_open`.
132
211
 
133
- **常用选项:**
212
+ **Common options:**
134
213
 
135
- | 选项 | 说明 |
214
+ | Option | Description |
136
215
  | ------------------------ | ------------------------ |
137
- | `--payload <json>` | 直接传入 JSON 参数 |
138
- | `--payload-file <path>` | 从文件读取 JSON 参数 |
139
- | `--timeout <seconds>` | 请求超时时间 |
140
- | `--compact` | 强制 stdout 紧凑输出 |
141
- | `--output <path>` | 将结果写入文件(如截图) |
142
- | `--browser <id\|名称>` | 指定目标浏览器 |
143
-
144
- CLI、SDK、MCP 使用同一返回结构。快照中的 `@eN` 可直接用于操作,内部节点映射只保存在运行时。
145
- 常规响应的 `session` 包含会话 ID、浏览器、传输、状态和代次;标签页清单通过 `tab_list` 查询,
146
- `browser_control` 的交接结果还包含会话页面的 `tabs`。`run_actions` 的步骤使用各 action 的返回结构。
147
- stdout 在管道或重定向时默认输出紧凑 JSON,在交互终端默认美化;`--compact` 可强制紧凑排版,不改变返回字段和值。快照会折叠无名称、无 ref 且无状态的分组,控件状态与文本内容完整保留。
148
-
149
- `get_requests` 指定非空 `fields` 时默认省略请求体和响应体,只返回提取字段及请求元数据;
150
- 需要同时读取全文时显式传 `includeBody:true`。省略正文时不返回 `postData` / `responseBody` 字段;
151
- 未指定字段时默认返回正文。
152
-
153
- Mearl 默认聚合当前机器和已配置 cloud-server 下的浏览器,并通过 `browser_list` 返回的全局
154
- `browserId` 自动路由。以下覆盖参数仅在限定宿主或连接、传输排障时使用,因此不出现在默认 help:
155
-
156
- | 选项 | 说明 |
216
+ | `--payload <json>` | JSON arguments |
217
+ | `--payload-file <path>` | Read JSON from a file |
218
+ | `--timeout <seconds>` | Request timeout |
219
+ | `--compact` | Force compact stdout |
220
+ | `--output <path>` | Save output, such as screenshots |
221
+ | `--browser <id\|name>` | Target browser |
222
+
223
+ CLI, SDK, and MCP share return structures. Snapshot `@eN` refs are directly actionable; internal mappings remain runtime-local.
224
+ Ordinary `session` includes session ID, browser, transport, state, and generation. Query tabs with `tab_list`;
225
+ `browser_control` handoff also returns session `tabs`. `run_actions` steps preserve individual action results.
226
+ stdout defaults to compact JSON in pipes/redirection and pretty output in interactive terminals. `--compact` forces compact layout without changing values. Snapshots collapse unnamed, stateless groups without refs while preserving control states and text.
227
+
228
+ With nonempty `fields`, `get_requests` omits request/response bodies by default, returning extracted fields and metadata;
229
+ pass `includeBody:true` for full bodies too. Omitted bodies exclude `postData` / `responseBody`;
230
+ without field selection, bodies are returned by default.
231
+
232
+ `send_request` includes ordinary Cookies matching the full target URL and CHIPS Cookies for its first-party site. For example, `https://app.example.com/` uses the `https://example.com` partition independently of open pages. Sites use schemes and the public suffix list including private suffixes, excluding other sites/schemes, cross-site ancestors, and opaque partitions. Same-name Cookies on different paths remain; parent-site host-only Cookies are not added. Third-party partitions embedded elsewhere, page signatures, or complete page identities require requests through the target page's `page_eval`.
233
+ Response `Set-Cookie` updates the original browser for later calls; `withCookies:false` disables both automatic inclusion and writeback. Chrome handles extension response Cookies. CDP Node requests write back through the original browser connection before returning, supporting HttpOnly, default paths, expiry, and deletion. CDP responses with `Set-Cookie` include `cookieSync: { updatedCount, rejectedCount, failedCount }` without values. Partitioned Cookies with unknown partitions count as rejected. Sync failures cannot undo completed HTTP operations: inspect state rather than resending business requests. Ordinary/streaming Protocol requests use the same refresh mechanism.
234
+ Extension temporary credentials match only the original full request URL; Chrome selects redirect Cookies for the new URL. CDP Node requests, including Protocol streams, do not automatically follow redirects, preventing original Cookies/signatures from reaching other addresses.
235
+
236
+ Mearl aggregates local and configured cloud-server browsers by default, routing automatically with global
237
+ `browserId` from `browser_list`. The overrides below restrict hosts/connections or troubleshoot transport, so default help omits them:
238
+
239
+ | Option | Description |
157
240
  | ------------------------ | ------------------------------------- |
158
- | `--connector <id\|名称>` | 限制到一台远端机器 |
159
- | `--local` | 只使用当前机器 |
160
- | `--cdp` | 当前机器强制使用 CDP;清单只列 CDP 浏览器,并隐含 `--local` |
161
- | `--server <url>` | 覆盖自动读取的 cloud-server 地址 |
162
-
163
- `browser_list --help` 和 `browser_launch --help` 会按场景展示宿主选择参数;连接或传输排障运行
164
- `mearl check --help`。`mearl check` 检查连接与浏览器状态;`mearl check --updates` 还会并发查询
165
- client、native-host、cloud-connector 和扩展的最新发布版本。发布版本查询最长等待约 1.5 秒,
166
- 无法访问发布源时会提示无法确认更新,不影响浏览器可用性检查。`--json` 输出机器可读的检查结果,
167
- 与 `--updates` 同用时包含更新状态。发现更新时会提示适用的命令:client/native-host 使用
168
- `npx @mearl/setup update`,setup 管理的扩展使用 `npx @mearl/setup extension`。
169
-
170
- 全局安装的 `mearl` CLI 默认在每天首次使用后启动独立后台进程,查询最新发布版本,并比较
171
- client、native-host、cloud-server 和 MCP server 的已安装版本。发现更新时调用
172
- `@mearl/setup update --yes --skip-skill` 更新版本落后的运行环境及其共享 client,也支持独立安装的 CLI。
173
- 当前命令不等待网络或安装;检查和安装结果记录在
174
- `~/.mearl/cli-auto-update-state.json`。项目依赖和临时 `npx` 副本不会被自动修改。
175
- 浏览器扩展沿用其独立的更新入口。
176
- 在 `~/.mearl/config.json` 中设置间隔天数或关闭自动更新:
241
+ | `--connector <id\|name>` | Restrict to one remote machine |
242
+ | `--local` | Current machine only |
243
+ | `--cdp` | Force local CDP; list only CDP browsers and imply `--local` |
244
+ | `--server <url>` | Override the automatically read cloud-server URL |
245
+
246
+ `browser_list --help` and `browser_launch --help` show scenario-specific host options. For connection/transport troubleshooting, use
247
+ `mearl check --help`. `mearl check` checks connection/browser status. `mearl check --updates` also concurrently queries
248
+ latest client, native-host, cloud-connector, and extension releases. Release queries wait about 1.5 seconds at most;
249
+ unreachable sources report unconfirmed updates without affecting browser checks. `--json` returns machine-readable results,
250
+ including updates when combined with `--updates`. Available updates show appropriate commands: client/native-host use
251
+ `npx @mearl/setup@beta update`; setup-managed extensions use `npx @mearl/setup extension`.
252
+
253
+ By default, globally installed `mearl` launches an independent background updater after the first use each day to query releases and compare
254
+ installed client, native-host, cloud-server, and MCP server versions. When needed, it invokes
255
+ `@mearl/setup update --yes --skip-skill` for outdated environments and their shared client, including standalone CLI installations.
256
+ The current command waits for neither network nor installation. Outcomes persist in
257
+ `~/.mearl/cli-auto-update-state.json`. Project dependencies and temporary `npx` copies are not modified automatically.
258
+ The browser extension retains its separate update entry.
259
+ Configure the interval or disable updates in `~/.mearl/config.json`:
177
260
 
178
261
  ```json
179
262
  { "cliAutoUpdate": { "intervalDays": 7 } }
@@ -183,14 +266,14 @@ client、native-host、cloud-server 和 MCP server 的已安装版本。发现
183
266
  { "cliAutoUpdate": false }
184
267
  ```
185
268
 
186
- 间隔按本地日历日计算。需要立即检查各组件的发布版本时,仍可运行 `mearl check --updates`。
269
+ Intervals use local calendar days. Run `mearl check --updates` for immediate release checks.
187
270
 
188
- ## Skill 插件
271
+ ## Skill plugins
189
272
 
190
- 安装 skill 并自动注册命令,或直接注册已有入口:
273
+ Install a Skill and automatically register commands, or register an existing entry:
191
274
 
192
275
  ```bash
193
- npx @mearl/setup plugin install https://github.com/F-loat/mearl --skill browser-tab-manager --yes
276
+ npx @mearl/setup plugin install https://github.com/mearlhq/mearl --skill browser-tab-manager --yes
194
277
  npx @mearl/setup plugin /absolute/path/to/browser-tab-manager
195
278
  npx @mearl/setup plugin uninstall tabs
196
279
  mearl tabs summary
@@ -199,28 +282,30 @@ mearl tabs --help
199
282
  mearl tabs --version
200
283
  ```
201
284
 
202
- 当已注册插件与 Provider 使用同一名称时,`mearl <name> --help` 会先显示 Provider 的启动和生命周期说明,
203
- 再自动追加插件注册的扩展命令;`mearl <name> <command> --help` 继续显示单个插件命令的详细帮助。
204
- Provider 与插件仍可独立安装、更新和卸载,帮助聚合不会启动 Provider 或执行业务命令。
285
+ If a plugin and Provider share a name, `mearl <name> --help` shows Provider launch/lifecycle guidance first,
286
+ then appends registered plugin commands. `mearl <name> <command> --help` retains detailed command help.
287
+ Providers/plugins install, update, and uninstall independently. Help aggregation starts no Providers and executes no business commands.
288
+
289
+ Directories default to `scripts/main.mjs` or `scripts/main.py`, preferring JavaScript if both exist. JavaScript default-exports `register(app)`; Python exports a `register(app)` function. Both may declare short `name`/`description` metadata and use `app.command(signature, handler, description?)`
290
+ to register actions, `app.invoke(action, payload, options?)` for current-browser context, and `app.progress(message)` for progress. JS may pass `{ message, data }` with JSON-serializable stage/object metadata for tools; CLI shows only `message`. Python `app.invoke` is synchronous; handlers may be ordinary functions or `async def`. Python requires `python3 >= 3.9`, optionally selected by `MEARL_PYTHON`; Mearl neither installs Python nor runs pip. Cross-plugin payloads use `{ command, input }`, inheriting host options and rejecting cycles. CLI prints final results only unless
291
+ `--verbose` writes progress to stderr. Handlers return text/JSON; hosts manage `--output`, connections, and errors. User-invoked writes execute directly; business modules validate targets, state, idempotency, and outcomes.
292
+ Names prefer explicit registration, then entry `name`, then Skill directory. Normal registration needs only a path.
293
+ setup supplies missing client/native-host versions or upgrades those older than itself. Its Skills installer handles arguments using global shared installation.
205
294
 
206
- 目录默认使用 `scripts/main.mjs` 或 `scripts/main.py`;两者同时存在时使用 JavaScript 入口。JavaScript 入口默认导出 `register(app)`,Python 入口导出 `register(app)` 函数;两种入口都可声明简短的 `name` 和 `description`,并通过 `app.command(signature, handler, description?)`
207
- 注册动作、`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 默认只输出最终结果,传入
208
- `--verbose` 时才把进度写入 stderr。handler 返回文本或 JSON,宿主统一处理 `--output`、连接和错误。写命令在用户调用后直接执行,业务模块负责目标、状态、幂等和结果校验。
209
- 注册名优先使用显式名称,其次读取入口的 `name` metadata,最后回退到 skill 目录名;常规注册只传路径。
210
- setup 会补齐缺失或低于自身版本的 client、native-host;安装参数由 setup 的 Skills 安装器处理,并固定全局共享安装。
295
+ JavaScript entries may export `setup({ runCommand })` to prepare Skill-owned dependencies. Both setup installation paths await this hook before registration; failures stop registration. Help, entry loading and ordinary calls do not execute it. Skills check their own dependencies on first use. Runtime code and resources belong inside the Skill.
211
296
 
212
- 需要单独检查插件时运行 `mearl <name> --version`。命令会解析注册记录并加载入口,但不连接浏览器;
213
- 退出码为 0 表示插件已注册且入口可加载,stdout 返回同目录 `SKILL.md` 的版本,缺少版本元数据时返回 `unknown`。
214
- 未注册、入口丢失或加载失败会以退出码 2 和对应的 `PLUGIN_*` 错误结束。普通业务调用无需预先检查,直接处理同样的错误即可。
297
+ For isolated checks, run `mearl <name> --version`. It resolves registration and loads the entry without browser connections;
298
+ exit 0 means registered/loadable. stdout shows the adjacent `SKILL.md` version or `unknown` without metadata.
299
+ Missing registration/entry or loading errors exit 2 with `PLUGIN_*`. Ordinary calls can handle these directly without a precheck.
215
300
 
216
- 插件接受位置参数、字符串业务选项或包含 command/input 的 `--payload`。业务选项推荐写成
217
- `--name=value`,也接受 `--name value`,字段名与 handler 的 input 一致且不依赖位置顺序;同一字段不能同时
218
- 使用位置参数和业务选项,`--payload` 不能与前两种形式混用。JSON 保留业务字段类型;正文等文件输入按具体
219
- skill 的字段约定处理。`browser`、`timeout`、`output` 等宿主选项保留原有含义;同名业务字段以及数字、
220
- 布尔值、对象和数组通过 `--payload` 传入。插件不使用上表中内置 action 的 `--payload-file` 入口。
221
- 业务选项名称支持字母开头的字母、数字和下划线组合,下划线原样传递。
301
+ Plugins accept positional arguments, string business options, or `--payload` with command/input. Prefer
302
+ `--name=value`; `--name value` is also supported. Fields match handler input independent of order. One field cannot use both
303
+ positional and business options; `--payload` cannot mix with either. JSON preserves field types. File/body inputs follow each
304
+ Skill's contract. Host options such as `browser`, `timeout`, and `output` keep their meaning. Same-name business fields, numbers,
305
+ booleans, objects, and arrays use `--payload`. Plugins do not use built-in actions' `--payload-file` entry.
306
+ Business option names begin with a letter and contain letters, digits, or underscores, preserving underscores.
222
307
 
223
- 注册后的插件也可从 SDK 调用;实例方法 `client.invokePlugin` 复用既有连接和默认浏览器:
308
+ Registered plugins are also SDK-callable; instance `client.invokePlugin` reuses connections/default browsers:
224
309
 
225
310
  ```typescript
226
311
  import { invokePlugin } from '@mearl/client';
@@ -232,16 +317,16 @@ const result = await invokePlugin(
232
317
  );
233
318
  ```
234
319
 
235
- MCP Server 通过固定工具 `plugin_invoke` 接受同样的 `plugin`、`command` 和 `input`,不会把插件子命令动态扩展成 MCP 工具。SDK 与 MCP 不接受任意入口路径;本地受管理目录中的插件未注册时,会通过匹配当前 client 版本的 setup 自动安装并重试一次。目录由安装宿主显式保存,核心没有组织专属名单;其他未注册名称返回 `PLUGIN_NOT_REGISTERED`。
320
+ MCP uses fixed `plugin_invoke` with `plugin`, `command`, and `input`. SDK/MCP use registered plugins. The installation-host-managed catalog may trigger setup matching the client version and one retry; other unregistered names return `PLUGIN_NOT_REGISTERED`.
236
321
 
237
- 长命令使用本机持久任务服务。服务按注册目录隔离并自动启动,CLI、SDK、MCP 与工具箱共享任务记录;调用方退出不取消执行。服务重启后将未完成任务标记为 `interrupted`,不自动重放。后台任务固定接受时的源码快照、工作目录与环境;静态第三方 JS 依赖需要预先打包进 Skill,状态文件放在源码目录之外。
322
+ Long commands use auto-starting local persistent task services isolated by registry directory. CLI/SDK/MCP/toolbox share records; caller exit does not cancel execution. Restart marks unfinished work `interrupted` without replay. Background tasks pin accepted source snapshots, cwd, and environment. Bundle third-party JS dependencies into Skills and keep state outside source directories. Snapshots pin source/relative resources without pre-resolving JS dependencies; executors report missing dependencies/syntax errors on load.
238
323
 
239
324
  ```ts
240
325
  import { PluginTaskClient } from '@mearl/client';
241
326
 
242
327
  const tasks = new PluginTaskClient();
243
328
  try {
244
- const accepted = await tasks.start('example', { command: 'read', input: {} }, {
329
+ const accepted = await tasks.start('example', { command: 'search', input: {} }, {
245
330
  executionTimeoutMs: 120000,
246
331
  idempotencyKey: 'document-123',
247
332
  });
@@ -252,37 +337,39 @@ try {
252
337
  }
253
338
  ```
254
339
 
255
- `wait` 超时或其 signal 中止只结束等待;`cancel(taskId)` 才取消执行。浏览器任务需显式传 `browser`,名称会在接受前解析为固定 ID。`get/list` 返回任务快照与结果引用,`list` 返回有界分页及 `nextCursor`;`events` 返回游标、缺口标记和最新快照,`subscribe` 封装长轮询。`result(taskId)` 分块读取并校验完整业务结果,最大 64 MiB;终态记录和结果保留 7 天。
340
+ `wait` timeout or signal abort ends waiting only; `cancel(taskId)` cancels execution. Browser tasks require explicit `browser`, resolved to fixed IDs before acceptance. `get/list` return snapshots/result references; `list` has bounded pagination/`nextCursor`; `events` provides cursors, gaps, and snapshots; `subscribe` wraps long polling. `result(taskId)` losslessly reads and verifies chunks up to 64 MiB. Terminal records/results remain seven days.
341
+
342
+ Handshakes and `tasks.status()` return `version/buildId`; build IDs identify running code, while protocol versions determine compatibility. With matching protocols, different/missing version/build IDs do not interrupt tasks, models, pages, or state. To switch builds, confirm no active tasks/page operations, call `tasks.stopHost()`, and let the next business call start the current build. Reregistration does not restart services. After local client/host changes, root `pnpm build` generates matching fingerprints and both artifacts; `tsc --watch` alone does not.
256
343
 
257
- 任务能力由 SDK `PluginTaskClient` 与工具箱 `host.task.*` 使用。对外命令由具体插件按业务需要提供,CLI 使用 `mearl <plugin> <command>`,MCP 使用 `plugin_invoke`。任务、模型、状态、页面实例和宿主诊断不单独暴露为全局 CLI/MCP 命令。仅注册工具箱内部命令的插件不会列入 CLI 插件列表;直接运行其名称会提示工具的打开位置。工具页可用 `window.mearl.waitTask(taskId)`、`readTaskResult(taskId)`、`listTasks()`,范围限定为所属插件的工具箱任务。
344
+ SDK `PluginTaskClient` and toolbox `host.task.*` expose tasks. Plugins provide business commands through `mearl <plugin> <command>` or MCP `plugin_invoke`; there are no separate global task/model/state/page/diagnostic CLI/MCP tools. Toolbox-only plugins are absent from CLI lists; invoking their name shows where to open the tool. Tool pages use `window.mearl.waitTask(taskId)`, `readTaskResult(taskId)`, and `listTasks()` only for their own toolbox tasks.
258
345
 
259
- `tasks.diagnose({ taskId?, plugin?, instanceId?, includeErrorMessages?, includeLocalPaths? })` 读取当前调用范围内的有界诊断报告。默认不包含业务输入、提示词、进度正文、检查点数据、结果正文、完整 URL、环境变量和凭证,也省略错误消息及本地路径;后两项可显式选择包含。报告的 coverage 和历史 gap 表示采集范围及保留历史限制。
346
+ `tasks.diagnose({ taskId?, plugin?, instanceId?, includeErrorMessages?, includeLocalPaths? })` reads bounded diagnostics within caller scope. Defaults exclude input, prompts, progress/checkpoint/result bodies, full URLs, environment, credentials, errors, and local paths. Error messages/paths may be explicitly included. coverage/history gaps describe collection and retention limits.
260
347
 
261
- 注册记录在 `~/.mearl/plugins/<name>.json`,保存入口路径和可选的简短描述;skill 业务代码原地更新直接生效,换路径或更新描述后重新注册。
262
- `plugin uninstall <name>` 会对 `~/.agents/skills` 中的全局 Skill 调用 Skills 安装器执行全局卸载,
263
- 成功后清除相关注册;即使入口目录已被手动删除,也会完成 Skills 跟踪记录的清理。
264
- 手工路径只解除注册并保留源码。
265
- `PLUGIN_NOT_REGISTERED` 表示插件尚未注册。`PLUGIN_ENTRY_MISSING` 会显示失效入口,并给出带有实际插件名的
266
- 卸载清理命令。其他错误按实际原因处理。
267
- 下文描述插件工具箱、页面、状态与任务的通用合同。
348
+ Records at `~/.mearl/plugins/<name>.json` save entry paths/optional descriptions. In-place business-code edits apply directly; path/description changes require registration again.
349
+ `plugin uninstall <name>` globally removes Skills under `~/.agents/skills` through the Skills installer,
350
+ then clears registrations, including tracking cleanup when entry directories were manually deleted.
351
+ Manual paths unregister without source deletion.
352
+ `PLUGIN_NOT_REGISTERED` means no registration. `PLUGIN_ENTRY_MISSING` shows the stale path and a cleanup
353
+ command with the actual plugin name. Other failures retain their specific cause.
354
+ The following sections describe toolbox, page, state, and task contracts.
268
355
 
269
- 插件可选导出 `toolbox`,注册后会出现在扩展 Popup 的工具箱中。页面资源放在 Skill 目录内,注册时由
270
- Mearl 将入口 HTML 引用的本地 CSS、JavaScript 和图片内联为不可变页面包,不需要启动 HTTP 服务,
271
- 也不要求普通 HTML/CSS/JS 页面自行构建。
356
+ Plugins may export `toolbox`, appearing in extension Popup after registration. Resources live within the Skill directory. Registration
357
+ inlines local CSS, JavaScript, and images referenced by entry HTML into an immutable page bundle, without HTTP services
358
+ or requiring builds for ordinary HTML/CSS/JS pages.
272
359
 
273
- 右键工具箱中的工具可单独禁用或启用对应 Skill;禁用状态显示在标题右侧,工具页面和命令仍可使用。禁用将该目录的
274
- `SKILL.md` 重命名为 `SKILL.md.mearl-disabled`,启用时恢复,作用于共享此目录的所有 Agent;
275
- 软链接安装会作用于源目录。已有会话可能仍保留已载入的 Skill,需要重启 Agent 或新建会话。
276
- 工具箱内更新和重新安装会保留禁用状态;外部安装器的更新不受此状态管理,若出现两份清单,需先处理冲突。
277
- 独立复制安装的同名 Skill 需分别禁用。没有 Skill 清单的普通插件不显示此开关。
360
+ Right-click tools to enable/disable their Skills individually. Disabled status appears beside titles; tool pages/commands remain usable. Disabling renames
361
+ `SKILL.md` to `SKILL.md.mearl-disabled`, restored on enablement, affecting every Agent sharing that directory.
362
+ Symlink installs affect source directories. Existing sessions may retain loaded Skills until Agent restart/new sessions.
363
+ Toolbox updates/reinstalls preserve disabled state; external installers do not. Duplicate manifests require conflict resolution first.
364
+ Independent copies of same-name Skills disable separately. Plugins without Skill manifests show no toggle.
278
365
 
279
- 工具箱元数据示例:
366
+ Example toolbox metadata:
280
367
 
281
368
  ```javascript
282
369
  export const toolbox = {
283
370
  version: 1,
284
- title: '迭代管理',
285
- description: '查看多个仓库的改动与发布状态',
371
+ title: 'Iteration Management',
372
+ description: 'Track changes and release status across repositories',
286
373
  icon: 'git-branch',
287
374
  locales: {
288
375
  en: {
@@ -310,146 +397,146 @@ export default function register(app) {
310
397
  }
311
398
  ```
312
399
 
313
- `app.command(signature, handler, description?, examples?)` 注册 CLI、SDK 和 Agent 可调用的业务命令。
400
+ `app.command(signature, handler, description?, examples?)` registers business commands for CLI, SDK, and Agent.
314
401
 
315
- `toolbox.icon` 支持以下字符串形式,工具列表、切换菜单与网站安装目录使用同一格式:
402
+ `toolbox.icon` supports the following strings, shared by tool lists, switch menus, and website catalogs:
316
403
 
317
404
  ```js
318
- icon: 'git-branch' // 内置图标名称,最多 40 字符,随主题变色
319
- icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 4h16v16H4z"/></svg>' // 单色 SVG,随主题和交互变色
405
+ icon: 'git-branch' // Built-in icon, at most 40 characters, follows theme
406
+ icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 4h16v16H4z"/></svg>' // Monochrome SVG follows theme and interaction
320
407
  icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#2563eb" d="M4 4h16v16H4z"/></svg>'
321
- icon: 'https://example.com/tool-icon.svg' // HTTP(S) 图片地址,支持 SVG、PNG 等图片
408
+ icon: 'https://example.com/tool-icon.svg' // HTTP(S) image URL, including SVG and PNG
322
409
  icon: 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%2F%3E'
323
410
  ```
324
411
 
325
- 图标字符串最多 32768 字符。SVG 源码使用 `currentColor` 时,按单色遮罩渲染,继承与内置图标相同的主题、悬停和选中颜色;建议用 `fill="none" stroke="currentColor"` 绘制线框图标。显式指定颜色的 SVG、多色 Data URL 和远程图片按原图渲染。SVG 不注入扩展 DOM。远程图片使用无 referrer 请求;不接受带账号密码的 URL,加载失败或名称未知时显示通用图标。相对文件路径不在此字段的支持范围内。
326
-
327
- `app.toolboxCommand(signature, handler, description?, examples?)` 注册仅供工具页面调用的命令,参数和 handler 契约相同;
328
- 它不出现在 CLI 帮助中,CLI(包括 JSON payload)、SDK、MCP 及插件间的 `app.invoke` 都不能调用。
329
- 工具页面通过 `window.mearl.invoke(command, input)` 或 `window.mearl.invoke('host.task.start', { command, input })` 执行;两类命令都必须显式列在 `toolbox.page.commands` 中才能供页面调用。
330
- 注册的 `toolboxCommand` 若没有列入该白名单,插件加载会失败。分块上传、分块读取和页面临时资源释放适合使用它;
331
- 对 Agent 有独立业务价值的查询、导入、压缩、比较等完整操作使用 `app.command`。
332
- Python 入口也支持 `app.toolboxCommand(...)`,包括 `@app.toolboxCommand(..., description="...")` 装饰器。
333
-
334
- 声明 `agent` 后工具页可以把任务交给对话 Agent;`layout` 默认为 `drawer`,宿主会提供顶部入口。
335
- 页面也可在 `setAgentPanelVisible` 或 `runAgentTask` 中为单次交互指定 `drawer` / `workspace` / `inline`;
336
- Agent 对话会保存在 Codex 会话历史中。带固定
337
- 18rem 左侧导航的工作台可默认使用 `workspace`,由导航项切换 Agent,并占满导航栏以外的主内容区;详情页仍可按需唤起右侧抽屉。
338
- `inline` 用于把 Agent 嵌入工具页中的卡片或分区,调用时同时传入作为占位区域的 `anchor` 元素和稳定的
339
- `key`;宿主会跟随该元素的滚动与尺寸变化同步面板位置。`key` 也可用于抽屉或工作区布局,为不同业务对象
340
- 隔离会话与输入草稿;`setAgentPanelVisible` 可同时传入绝对路径 `cwd`,让首次创建的会话直接绑定该目录。
341
- 传入 `context` 可为面板提供不显示为聊天消息的背景上下文;它会在用户首次发送消息、创建会话时作为
342
- developer instructions 交给 Agent。
343
-
344
- 页面通过 `await window.mearl.ready()` 取得 `{ locale, theme, title, fontSize }`,通过
345
- `window.mearl.invoke(command, input?)` 调用 `commands` 白名单中的同一插件命令。页面运行在无扩展
346
- API、默认不可联网的 sandbox iframe 中;Native Host 校验插件身份、命令白名单和消息大小。页面包按
347
- 内容哈希缓存并分块传输,因此不会增加 Popup 的启动开销。使用模块脚本时需先打包为不再包含 `import`
348
- 的单文件;React、Vue 等工程可以把构建后的 `index.html` 作为 `entry`,注册流程仍负责最终资源封装。
349
- 需要无构建的组件与状态管理时可声明 `page.runtime: 'preact'`,扩展会在页面完整性校验后注入固定的
350
- Preact、Hooks 和 HTM 运行时。页面从 `window.mearl.ui` 读取 `html`、`render`、`useState` 等 API;
351
- `window.mearl.ui.version` 仅用于诊断,插件不能选择运行时版本。
352
- 宿主会同步扩展主题、字号,并注入 `--mearl-bg-primary`、`--mearl-bg-secondary`、
353
- `--mearl-text-primary`、`--mearl-text-secondary`、`--mearl-border`、`--mearl-bg-hover` 和
354
- `--mearl-accent` 等语义变量;主操作按钮使用 `--mearl-action-primary`、
355
- `--mearl-action-primary-hover` 和 `--mearl-action-primary-text`,以保持与扩展按钮一致。
356
-
357
- 工具箱面向人,CLI 面向 Agent:复用业务操作、保持结果一致即可,不要求共享中间态。表单草稿、选择、预览等纯 UI 状态默认放浏览器内存;确需刷新或重新打开后恢复时再用浏览器存储。sandbox 页不能假定可直接访问 `localStorage`、IndexedDB 或 `chrome.storage`,应使用宿主提供的能力。只有业务记录、关闭页面后继续的任务、安全重试回执或受消息大小限制的资源传输才需要 Node 状态,并说明其生命周期及清理方式。
358
-
359
- 组织认证及业务请求由已安装的 Skill 插件提供。CLI 使用 `mearl <plugin> <command>`,业务插件通过 `app.invoke(plugin, { command, input })` 复用同一操作;插件名称、认证方式、请求字段和上传约定以对应 Skill 的契约为准。
360
-
361
- Node 插件在运行 CLI、SDK 或 MCP Server 的宿主上执行,不随浏览器或 connector 转发。插件读取的文件路径属于该执行宿主;需要浏览器执行的操作应使用明确的浏览器目标。核心不内置组织认证插件或平台来源,安装宿主可通过能力目录提供按需安装信息。
362
-
363
- ## 支持的操作
364
-
365
- | 分类 | Actions |
412
+ Icon strings allow 32768 characters. SVG using `currentColor` renders as a monochrome mask, inheriting built-in theme/hover/selection colors; prefer `fill="none" stroke="currentColor"` for outlines. Explicitly colored SVGs, multicolor data URLs, and remote images retain colors. SVG never injects into extension DOM. Remote images omit referrers; credentialed URLs are rejected. Unknown names/load failures show generic icons. Relative file paths are unsupported.
413
+
414
+ `app.toolboxCommand(signature, handler, description?, examples?)` registers tool-page-only commands with the same parameter/handler contract;
415
+ they do not appear in CLI help and cannot be called by CLI (including JSON), SDK, MCP, or cross-plugin `app.invoke`.
416
+ Tool pages use `window.mearl.invoke(command, input)` or `window.mearl.invoke('host.task.start', { command, input })`. Both command types must be explicitly listed in `toolbox.page.commands`.
417
+ Registered toolboxCommands absent from that allowlist fail plugin loading. Use them for chunked uploads/reads and temporary page-resource release;
418
+ use `app.command` for complete operations independently useful to Agents, such as queries, import, compression, or comparison.
419
+ Python also supports `app.toolboxCommand(...)` and `@app.toolboxCommand(..., description="...")` decorators.
420
+
421
+ Declaring `agent` lets tools delegate tasks to the conversational Agent. `layout` defaults to `drawer`, with a host-provided top entry.
422
+ Pages may select `drawer` / `workspace` / `inline` per interaction through `setAgentPanelVisible` or `runAgentTask`.
423
+ Agent conversations persist in Codex history. Workbenches with a fixed
424
+ 18rem left navigation can default to `workspace`, switch Agent through navigation, and fill the remaining main area; detail pages can still open right drawers.
425
+ `inline` embeds the Agent in a card/section, requiring an `anchor` element and stable
426
+ `key`. Hosts track anchor scrolling/resizing. `key` also isolates conversations and drafts by business object in drawer/workspace layouts;
427
+ `setAgentPanelVisible` may pass absolute `cwd` to bind newly created conversations to a directory.
428
+ `context` supplies background information without showing it as a chat message. On the first user message and session creation,
429
+ it is delivered as developer instructions.
430
+
431
+ `await window.mearl.ready()` returns `{ locale, theme, title, fontSize }`. Use
432
+ `window.mearl.invoke(command, input?)` for same-plugin allowlisted commands. Pages run in sandbox iframes without extension
433
+ APIs or network access by default. Native Host validates identity, command allowlists, and message size. Page bundles use
434
+ content-hash caches and chunked transfer without increasing Popup startup cost. Module scripts must first bundle into one file without
435
+ `import`. React/Vue projects may use built `index.html` as `entry`; registration performs final packaging.
436
+ For build-free components/state, declare `page.runtime: 'preact'`. After integrity checks, extensions inject pinned
437
+ Preact, Hooks, and HTM. Read `html`, `render`, `useState`, etc. from `window.mearl.ui`.
438
+ `window.mearl.ui.version` is diagnostic only; plugins cannot select runtime versions.
439
+ Hosts synchronize theme/font size and inject semantic variables including `--mearl-bg-primary`, `--mearl-bg-secondary`,
440
+ `--mearl-text-primary`, `--mearl-text-secondary`, `--mearl-border`, `--mearl-bg-hover`, and
441
+ `--mearl-accent`. Primary buttons use `--mearl-action-primary`,
442
+ `--mearl-action-primary-hover`, and `--mearl-action-primary-text` to match extension controls.
443
+
444
+ Toolboxes serve people; CLI serves Agents. Reuse business operations and consistent results without requiring shared intermediate state. Drafts, selections, previews, and other UI state default to browser memory. Use browser storage only for concrete refresh/reopen recovery needs. Sandboxes cannot assume localStorage, IndexedDB, or chrome.storage; use host capabilities. Node state is for business records, tasks continuing after close, safe retry receipts, or message-limited resource staging, with explicit lifetimes/cleanup.
445
+
446
+ Skill plugins can provide custom requests/data processing. CLI uses `mearl <plugin> <command>`; plugins reuse operations with `app.invoke(plugin, { command, input })`. Skill contracts define names, authentication, fields, and uploads.
447
+
448
+ Node plugins execute on the CLI/SDK/MCP Server host, never forwarded with browsers/connectors. File paths belong to that host. Browser operations require explicit targets. Installation hosts may provide on-demand installation through capability catalogs.
449
+
450
+ ## Supported actions
451
+
452
+ | Category | Actions |
366
453
  | ------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
367
- | API 调试 | `tab_checkpoint` `get_requests` `get_logs` `get_events` |
368
- | Mock & 规则 | `set_mock` `get_mocks` `set_rule` `get_rules` |
369
- | 网络请求 | `send_request` `send_mtop_request` `request_domain_permission` |
370
- | 标签页 | `tab_open` `tab_list` `tab_close` |
371
- | 页面感知 | `page_snapshot` `page_inspect` `page_screenshot` `page_frames` |
372
- | 页面操作 | `page_click` `page_drag` `page_type` `page_hover` `page_scroll` `page_press` `page_wait` `page_navigate` `page_upload` `page_eval` |
373
- | 页面运行时 | `page_runtime`(内部文档适配,插件使用 `app.page`) |
374
- | 组合调用 | `run_actions` |
375
- | 环境与 Cookie | `set_device_emulation` `set_app_profile` `set_timezone` `get_cookie` `set_cookie` |
376
- | 浏览器 | `browser_list` `browser_launch` `browser_release` `browser_close` |
454
+ | API debugging | `tab_checkpoint` `get_requests` `get_logs` `get_events` |
455
+ | Mocks and rules | `set_mock` `get_mocks` `set_rule` `get_rules` |
456
+ | Network requests | `send_request` `request_permission` |
457
+ | Tabs | `tab_open` `tab_list` `tab_close` |
458
+ | Page observation | `page_snapshot` `page_inspect` `page_screenshot` `page_frames` |
459
+ | Page actions | `page_click` `page_drag` `page_type` `page_hover` `page_scroll` `page_press` `page_wait` `page_navigate` `page_upload` `page_eval` |
460
+ | Page runtimes | `page_runtime` (internal document adapter; plugins use `app.page`) |
461
+ | Composition | `run_actions` |
462
+ | Environment and Cookies | `set_device_emulation` `set_app_profile` `set_timezone` `get_cookie` `set_cookie` |
463
+ | Browsers | `browser_list` `browser_launch` `browser_release` `browser_close` |
377
464
 
378
- 页面交互动作(`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` 默认裸执行,可按需开启观察或诊断。
465
+ Interactive actions (`page_click` / `page_drag` / `page_type` / `page_hover` / `page_scroll` / `page_press` / `page_upload`) wait for asynchronous stability by default and return `{ action, observation }`. Pre-dispatch argument/ref/target failures return `action.stage: "precondition"`, omitting meaningless observation/diagnostics. Potentially dispatched input with confirmation timeout returns `action.stage: "dispatch-uncertain"` and observations for reconciliation. Known targets, hits, coordinates, dispatch modes, and input sequences appear in `action.attempt` as diagnostic evidence, not proof of effect. CLI failures exit 1. `observe: false` performs bare actions; `diagnostics: true` collects new error logs/business requests during the action, with analytics optionally enabled through `diagnostics.events`. `page_eval` defaults to bare execution and permits observation/diagnostics.
379
466
 
380
- `tab_open active:true` 请求激活目标页。扩展免打扰默认开启:HTTP(S) 页面在首次导航前启用后台焦点模拟,不切换标签页或窗口;关闭免打扰才会真实激活并恢复最小化窗口。`activation.mode` 区分 `background` / `foreground`,模拟后的 `visibilityState` 不代表窗口在前台。焦点模拟在交接、释放控制或扩展连接断开时关闭,`preserveEnvironment` 不保留它;交还后按需对同 URL 使用 `reuse:"require", active:true` 再次激活。不带会话时通过 `browser_release` 收尾。纯 CDP 和外部 Provider 遵循各自的激活能力。页面动作的稳定观察会在有限预算内等待有限时长 CSS 动画。selector/ref 点击遇到嵌套滚动裁剪时会先滚动目标,仍不可见时才以明确的裁剪错误停止。
467
+ `tab_open active:true` requests activation. Extension do-not-disturb defaults on: HTTP(S) pages get background-focus emulation before first navigation without switching tabs/windows. Disabling it activates/restores windows. `activation.mode` distinguishes `background` / `foreground`; emulated visibilityState does not prove foreground. Handoff, release, and disconnect disable focus emulation regardless of preserveEnvironment. After return, reactivate the same URL with `reuse:"require", active:true` if needed. Sessionless tasks finish with browser_release. Pure CDP/external Providers follow their own activation support. Stability observation waits for bounded-duration CSS animations within budget. Selector/ref clicks first scroll targets clipped by nested containers, failing explicitly only if still clipped.
381
468
 
382
- `page_click` 默认 `auto` 在隐藏页使用 DOM fallback,selector、文本、ref 和坐标定位都保持可用,并通过 `dispatchMode: "dom"`、`fallbackReason: "page-hidden"` 明确说明实际路径。普通后台任务不需要为了点击主动激活页面;只有站点明确拒绝非可信事件时才切换到可见页并强制 `mouse` / `touch`。
469
+ Default `page_click` auto uses DOM fallback on hidden pages, supporting selectors, text, refs, and coordinates and returning `dispatchMode: "dom"`, `fallbackReason: "page-hidden"`. Ordinary background tasks need no activation for clicks. Only sites rejecting untrusted events require visible pages and forced `mouse` / `touch`.
383
470
 
384
- `observation.effects.interactives` 会把内容未变化但 DOM 节点被框架重建的控件标记为 `recreated`,保留 selector/ref 与语义信息供后续定位,同时省略未变化的 value 和状态字段;值或状态确实变化时仍返回完整差异。
471
+ `observation.effects.interactives` marks controls `recreated` when frameworks replace DOM nodes without content changes. It retains selectors/refs/semantics but omits unchanged values/states. Actual value/state changes still return full differences.
385
472
 
386
- `observation.effects.texts` 按需返回普通可见叶子文本的当前值 `{ selector, text }`,覆盖独立计数、金额等非控件文字。结果最多 8 项,每项 text 最多 160 字符;同一节点连续更新只保留最终值。非空文字的 Range 矩形必须完整处于视口和祖先滚动/裁剪框内,并通过命中检查;CSS 掩码文本不进入该通道。空文本使用元素框检查。结果不作为可交互控件或业务成功信号。复杂结构、不可读内容及预算溢出仍保留快照回退;该通道不改变导航等待策略。
473
+ Optional `observation.effects.texts` returns current visible leaf text as `{ selector, text }`, including counters/amounts outside controls. Limits: eight entries, 160 characters each; repeated node changes retain final values. Nonempty text Range rectangles must be entirely within viewport/ancestor clipping and pass hit testing. CSS-masked text is excluded; empty text uses element boxes. These are neither interactive controls nor business-success signals. Complex/unreadable content and budget overflow retain snapshot fallback without changing navigation waits.
387
474
 
388
- `page_press.pressMode` 支持 `auto` / `dom` / `keyboard`。默认 `auto` 在隐藏页使用 DOM 键盘事件,并通过返回的 `dispatchMode`、`fallbackReason` 和 `defaultAction` 说明实际派发及默认行为模拟结果;依赖浏览器原生编辑、选择或滚动行为时使用可见页面和 `keyboard`。
475
+ `page_press.pressMode` accepts `auto` / `dom` / `keyboard`. Default auto uses DOM key events on hidden pages, reporting `dispatchMode`, `fallbackReason`, and simulated `defaultAction`. Use visible pages and keyboard for native editing, selection, or scrolling.
389
476
 
390
- `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` 截断会同时保留首尾内容。
477
+ `page_snapshot` defaults to full AX Tree. Use `mode: "viewport"` for long lists, `"interactive"` for viewport controls, or explicit `"dom"` when AX is empty/sparse. DOM returns rendered text, native controls, explicit roles, and high-confidence clickable nodes with actionable `@ref`, without inferring arbitrary business semantics. Scope with `rootSelector` or `rootRef` (optionally ancestorDepth), and search text/roles with query. interactive lacking AX control semantics falls back only to AX viewport with `fallbackMode: "viewport"`, never automatically switching sources. `maxNodes` / `maxChars` truncation preserves both beginning and end.
391
478
 
392
- `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`。
479
+ `page_inspect` uses CSS, snapshot `@ref`, or DevTools `$0` to return counts, bounding boxes, selected computed styles, center occlusion, horizontal/vertical overflow pixels, and nearest scroll containers. Omit selectors with `filter: "horizontal-overflow"` / `"vertical-overflow"` / `"scrollable"` for page-wide diagnosis. For text, first get `matches` / `matchCount` and refs through `page_snapshot.query`, then inspect refs without custom page_eval.
393
480
 
394
- 重复文本点击可用 `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` 会优先选择代表性视口位置命中的最近内部滚动容器,再使用文档滚动区域或层级最高且可视面积最大的滚动容器。
481
+ Disambiguate repeated text through `page_click.scope` CSS/ref subtrees. Extension coordinates in containers/iframes use `coordinateSpace: "active-frame"`; CSS/text queries accept frameId. Results distinguish requested semantics, resolved DOM, dispatch node, trusted hit, and coordinates through `requestedTarget`, `resolvedTarget`, `dispatchTarget`, `hitTarget`, and `coordinates`. Nested-clipped selector/ref targets scroll into view automatically; only remaining overflow clipping requires explicit handling. `page_scroll.containerPolicy: "nearest"` selects the nearest scrollable ancestor. Without selector, scrolling first chooses an inner container hit at representative viewport positions, then document scrolling or the topmost largest-visible container.
395
482
 
396
- `browser_list` 统一列出普通浏览器、Provider 浏览器和托管浏览器。`type` 区分
397
- `regular` / `managed`,`status` 区分 `connected` / `pairing` / `running_disconnected` /
398
- `stopped`;只有 `connected` 的浏览器可作为常规操作目标。本机没有已连接的插件浏览器时,
399
- `browser_list` 会自动探测默认 CDP 端点,即使已有 Provider 配对记录也无需传 `--cdp`。
400
- `browser_list --cdp` 在没有已注册的普通 CDP 浏览器时会主动探测该端点,并只返回 CDP 浏览器;
401
- 插件浏览器已连接也不影响这次探测。设置 `MEARL_SOCKET_PATH` 时,清单请求沿用该实例 Socket。
402
- `check --cdp` 也只检查这些 CDP 浏览器。
483
+ `browser_list` lists ordinary, Provider, and managed browsers. `type` distinguishes
484
+ `regular` / `managed`; `status` distinguishes `connected` / `pairing` / `running_disconnected` /
485
+ `stopped`. Only connected browsers are ordinary operation targets. Without a connected local extension browser,
486
+ browser_list automatically probes default CDP, even with Provider pairing records, without requiring --cdp.
487
+ `browser_list --cdp` actively probes if no ordinary CDP browser is registered and returns CDP browsers only;
488
+ connected extension browsers do not prevent this probe. With `MEARL_SOCKET_PATH`, inventory requests use that instance Socket.
489
+ `check --cdp` likewise checks only those CDP browsers.
403
490
 
404
- `browser_release` 仅在用户明确要求结束调试、退出接管或清理会话资源时调用;它会释放
405
- debugger/CDP 控制和会话级临时状态,保留浏览器及全部标签页。托管实例的启动、关闭、持久化、
406
- 接入和登录态同步语义由各 Provider 声明;运行 `mearl <providerId>` 获取当前说明。访问入口不在
407
- `browser_list` 中,需要时显式运行 `mearl check --browser <id|名称>`,并把返回的
408
- `browserAccess.url` 按敏感信息处理。
491
+ Call `browser_release` only on explicit user requests to end debugging, detach, or clean session resources. It releases
492
+ debugger/CDP control and temporary session state while keeping browsers/tabs. Providers declare managed-instance launch, close, persistence,
493
+ access, and sign-in synchronization semantics; run `mearl <providerId>`. Access URLs are excluded from
494
+ `browser_list`; explicitly run `mearl check --browser <id|name>` when needed and treat returned
495
+ `browserAccess.url` as sensitive.
409
496
 
410
- ## 架构
497
+ ## Architecture
411
498
 
412
499
  ```
413
500
  @mearl/client (CLI / SDK)
414
- ├─ 本机 → @mearl/native-host → Chrome Extension / CDP
415
- ├─ 本机 → @mearl/provider runtime → External Provider
501
+ ├─ Local → @mearl/native-host → Chrome Extension / CDP
502
+ ├─ Local → @mearl/provider runtime → External Provider
416
503
  └─ WebSocket → @mearl/cloud-server → @mearl/cloud-connector
417
504
  ├─ @mearl/native-host → Chrome Extension / CDP
418
505
  └─ @mearl/provider runtime → External Provider
419
506
  ```
420
507
 
421
- 基础设施组件必须避免递归路由:`@mearl/cloud-connector` 使用 `@mearl/client/local` 子路径直连所在机器的 native-host。普通 Agent、CLI 与 MCP 集成均使用包根入口。
508
+ Infrastructure must avoid recursive routing: `@mearl/cloud-connector` directly connects to local native-host through `@mearl/client/local`. Ordinary Agent, CLI, and MCP integrations use the package root.
422
509
 
423
- 插件代码按职责组织在 `src/plugins/`:
510
+ Plugin code is organized by responsibility in `src/plugins/`:
424
511
 
425
- | 目录 | 职责 |
512
+ | Directory | Responsibility |
426
513
  | --- | --- |
427
- | `sdk/` | 插件声明、命令接口及页面、模型、状态和恢复声明的校验 |
428
- | `clients/` | 插件服务连接及任务、模型、页面、状态的调用接口 |
429
- | `runtime/` | 服务组装、任务调度、存储、代码快照、执行器和进程清理 |
430
- | 插件目录根部 | 注册、资源打包、官方插件安装及调用端与服务端共享的通信协议 |
514
+ | `sdk/` | Plugin declarations, command interfaces, and page/model/state/recovery validation |
515
+ | `clients/` | Service connections and task/model/page/state clients |
516
+ | `runtime/` | Service assembly, scheduling, storage, snapshots, executors, and cleanup |
517
+ | Plugin directory root | Registration, resource packaging, official plugin installation, and shared client/server protocol |
431
518
 
432
- 测试位于各模块附近的 `__tests__/`。对外通过 `@mearl/client` 和 `@mearl/client/plugin` 导出;包根部的 `plugin.ts` 是插件公开入口。三个进程入口 `plugin-worker.ts`、`plugin-task-host.ts` 和 `pluginModelSessionWorker.ts` 保留在 `src/` 根部,`runtimePaths.ts` 统一定位包版本和进程入口,使逐文件编译与 Native Host 打包使用相同的入口布局。生成协议仍由 `browser-core` 同步到 `src/generated/`。
519
+ Tests live in nearby `__tests__/`. Public exports use `@mearl/client` and `@mearl/client/plugin`; root `plugin.ts` is the public entry. Process entries `plugin-worker.ts`, `plugin-task-host.ts`, and `pluginModelSessionWorker.ts` remain in the `src/` root. `runtimePaths.ts` locates package versions and entries consistently for per-file compilation and Native Host bundling. `browser-core` still synchronizes generated protocol into `src/generated/`.
433
520
 
434
- ## 构建
521
+ ## Build
435
522
 
436
523
  ```bash
437
- pnpm build # tsc 编译到 dist/,并赋予 cli.js 执行权限
524
+ pnpm build # Compile with tsc into dist/ and make cli.js executable
438
525
  pnpm dev # tsc --watch
439
- pnpm typecheck # 仅类型检查
526
+ pnpm typecheck # Type checking only
440
527
  ```
441
528
 
442
529
  ## License
443
530
 
444
531
  Apache-2.0
445
532
 
446
- ### 插件页面实例
533
+ ### Plugin page instances
447
534
 
448
- `PluginPageClient` 通过本地插件服务管理 attach/get/list/send/detach/events/activation。插件导出独立 `pageRuntime` 声明并用 `app.page()` 调用。扩展与纯 CDP 共用实例、事件、激活和文档运行时;实例绑定 documentId,同插件同文档的所有入口共享初始化,导航后旧实例失效,启用的激活规则负责重建。`frame` 接受 `main`、`business` 或 `page_frames` 返回的 frame ID(扩展为数字,CDP 为字符串)。外部 Provider 仍须明确声明 `page_runtime` 能力。
535
+ `PluginPageClient` manages attach/get/list/send/detach/events/activation through local plugin services. Plugins declare independent `pageRuntime` and use `app.page()`. Hosts syntax-check code expressions with Node's compiler without executing them. Browser evaluation must produce self-contained functions; nonfunctions/external-reference errors appear at page runtime. Extension/pure CDP share instances, events, activation, and document runtimes. documentId binds instances; same-plugin/same-document entries share initialization. Navigation invalidates instances; activation rules rebuild them. `frame` accepts `main`, `business`, or `page_frames` IDs (numeric Extension, string CDP). External Providers must declare `page_runtime`.
449
536
 
450
- 显式手动 `attach` 复用自动激活的实例时,实例转为手动归属,初始化与在途任务继续复用;随后收窄自动激活范围不会清理该实例。
537
+ Explicit manual `attach` reusing an automatic instance changes ownership to manual while preserving initialization and running tasks. Later narrowing automatic scopes does not remove it.
451
538
 
452
- 独立修改匹配范围时,可传 `enabled: true, matchPatch: { add?: string[], remove?: string[] }`,与 `matches` 互斥。宿主原子增删范围,避免并发调用覆盖其他范围;删除最后一个范围会关闭自动激活,保留手动挂载的页面实例。`persistence: 'persistent'` 在浏览器重启后保留,初始化 handler 可读取最新插件偏好,不必将易变配置复制到规则 input。
539
+ To change matching scope independently, pass `enabled: true, matchPatch: { add?: string[], remove?: string[] }`, mutually exclusive with `matches`. Hosts atomically add/remove scopes to avoid concurrent overwrites. Removing the final scope disables automatic activation while retaining manually attached instances. `persistence: 'persistent'` survives browser restarts. Initialization handlers can read current plugin preferences instead of copying volatile settings into rule input.
453
540
 
454
541
  ```typescript
455
542
  const pages = new PluginPageClient();
@@ -459,13 +546,13 @@ try {
459
546
  } finally { pages.disconnect(); }
460
547
  ```
461
548
 
462
- 后台事件声明 schema 和串行、latest 合并或有限并发策略,处理器用 `app.runtimeCommand()` 注册并通过 `context.page` 访问固定文档。文档绑定任务可用 `app.page('activation')` 只读查询本插件激活规则,不允许设置或关闭规则。页面消息/结果各上限 24 MiB,宿主自动分块并校验;事件负载上限 32 KiB。工具箱使用 `host.page.*`,UI 订阅实例历史与后台执行独立。完整契约见 [插件宿主能力](../../docs/plugin-runtime.md#页面运行时和事件)。
549
+ Background events declare schemas and serial, latest-coalescing, or bounded-concurrency policies. app.runtimeCommand handlers use `context.page` for fixed documents. Document-bound tasks may read their plugin's activation rules with `app.page('activation')` but cannot modify them. Messages/results allow 24 MiB each with automatic chunks/checks; events allow 32 KiB. Toolbox uses `host.page.*`; UI history subscription is independent of execution. See [plugin host capabilities](../../docs/plugin-runtime.md#page-runtimes-and-events).
463
550
 
464
- Python 入口同样导出 `pageRuntime` 字典,其中 `code` 仍是运行于网页中的 JavaScript 函数字符串;后台初始化与事件处理器通过 `app.runtimeCommand(...)` 或其装饰器注册。`app.page(operation, payload)`、`context.page.send(message)` 和 `context.page.get()` 都是同步调用,后两者仅在绑定页面实例的处理器中可用。JS 和 Python 的 `context.page.send(message, {timeoutSec: 120})` 可指定单次响应超时(大于 0 且最多 300 秒,Python 使用字典);`app.page("send", {instanceId, message, timeoutSec})` 和 SDK `pages.send(plugin, instanceId, message, {timeoutSec})` 同样支持。该设置不改变其他请求,任务取消和文档解绑仍立即中断执行,传输失败也会取消对应网页请求。runtime-only 命令不出现在公开命令帮助中,也不能由 CLI 或工具箱直接执行;声明在页面事件中的普通 `app.command` 仍保留公开调用能力。
551
+ Python exports the same `pageRuntime` dictionary, with `code` as browser-side JavaScript function strings. Register initialization/events through app.runtimeCommand or decorators. `app.page(operation, payload)`, `context.page.send(message)`, and `context.page.get()` are synchronous; the latter two require instance-bound handlers. JS/Python `context.page.send(message, {timeoutSec: 120})` sets per-response timeouts above 0 and at most 300 seconds (Python uses dictionaries). `app.page("send", {instanceId, message, timeoutSec})` and SDK `pages.send(plugin, instanceId, message, {timeoutSec})` also support it. Other requests are unaffected. Cancellation/detach still interrupts immediately; transport failures cancel the page request. Runtime-only commands remain hidden and inaccessible through CLI/toolbox; ordinary `app.command` event handlers remain publicly callable.
465
552
 
466
- ### 模型任务与声明状态
553
+ ### Model tasks and declared state
467
554
 
468
- `PluginModelClient` 使用本机 Codex,不依赖浏览器连接;模型任务和命令任务共享查询、取消与无损结果通道,分别调度。先查询 `capabilities()`;当前只支持显式只读 Agent,严格无工具生成请求会失败。
555
+ `PluginModelClient` uses local Codex without browsers. Model/command tasks share querying, cancellation, and lossless results with separate scheduling. Query `capabilities()` first; only explicit read-only Agent mode is supported, and strictly tool-free generation fails.
469
556
 
470
557
  ```typescript
471
558
  import { PluginModelClient, PluginStateClient } from '@mearl/client';
@@ -479,9 +566,9 @@ try {
479
566
  } finally { models.disconnect(); }
480
567
  ```
481
568
 
482
- `start` 返回持久 taskId;`run` 的 signal 取消模型执行并等待清理。`app.model(request, { onProgress })` / `context.model(request, { onProgress })` 可订阅当前这一次调用的 `model.delta`,并发调用的回调互相隔离;Python 使用 `context.model(request, on_progress=callback)`。增量 `data` 含 `delta/index/partial`,可用时带 `itemId/phase`;按消息隔离、跳过 commentary,序号缺失时回退到最终结果。增量只供临时展示,最终结果来自成功 turn 的完整消息并经过宿主 schema 校验;临时显示必须在失败时撤回,不能直接作为缓存或业务成功依据。模型目录与执行通过 `PluginModelClient` 或插件上下文使用。工具页使用 `host.model.capabilities/list/start` 和 `waitTask`。
569
+ `start` returns persistent taskId; `run` signals cancel execution and await cleanup. `app.model(request, { onProgress })` / `context.model(request, { onProgress })` subscribe to that call's `model.delta`, isolated across concurrent calls; Python uses `context.model(request, on_progress=callback)`. Incremental `data` contains `delta/index/partial` and optional `itemId/phase`. Isolate messages, skip commentary, and fall back to final results on sequence gaps. Deltas are temporary display only; final results come from successful turns' complete messages. outputSchema passes to Providers; hosts parse JSON; plugins validate structure/business constraints. Retract temporary output on failure; never cache it or infer success. Use `PluginModelClient`/context for catalogs/execution; toolbox uses `host.model.capabilities/list/start` and `waitTask`.
483
570
 
484
- 插件入口声明状态集合,然后从命令上下文访问:
571
+ Declare collections in plugin entries, then access them from command contexts:
485
572
 
486
573
  ```javascript
487
574
  export const stateStorage = { version: 1, collections: {
@@ -495,31 +582,31 @@ export default app => app.command('save', async (input, context) => {
495
582
  });
496
583
  ```
497
584
 
498
- SDK `PluginStateClient.get/getMany/list/transact` 与工具箱 `host.state.*` 共享集合。每次写入需 CAS,冲突后重新读取、合并再重试;`schemaVersion` 升级用显式迁移事务。浏览器会话/实例可声明 `cache` 或 `memory`,页面身份由宿主验证。`memory` 只保存在插件执行宿主进程中,支持同样的 CAS、schema、TTL 与分块值限制;刷新文档时保留浏览器会话范围,浏览器会话变化后隔离,执行宿主重启时清空。内存状态全宿主合计最多 128 MiB / 512 个集合命名空间,按需占用;单集合 `maxBytes` 最大 128 MiB,实例结束释放其内存。容量、TTL 和完整契约见[插件宿主能力](../../docs/plugin-runtime.md#状态和激活)。二进制资产继续使用文件或资源通道。
585
+ SDK `PluginStateClient.get/getMany/list/transact` and toolbox `host.state.*` share collections. Writes require CAS; conflicts require reread/merge/retry. `schemaVersion` upgrades use explicit migrations. Browser-session/instance scopes support `cache` or `memory` with host-verified page identities. `memory` resides only in the execution host, sharing CAS/schema/TTL/chunk limits. Browser-session scope survives document refresh and isolates new sessions; host restart clears it. Host-wide memory allows 128 MiB/512 namespaces on demand; `maxBytes` per collection allows 128 MiB. Instance end releases memory. See [plugin host capabilities](../../docs/plugin-runtime.md#state-and-activation) for quotas/TTL. Binary assets still use files/resource channels.
499
586
 
500
- ### 显式任务恢复
587
+ ### Explicit task recovery
501
588
 
502
- 插件声明 `taskRecovery`(每个命令的 checkpointVersion/schema)并注册 `app.recoveryCommand(command, handler)`,命令通过 `context.checkpoint(data, expectedSequence)` 保存最多 64 KiB 的恢复依据。检查点数据、版本、宿主 schemaHash、序号和事件与任务记录原子写入;写入必须 CAS。
589
+ Plugins declare `taskRecovery` with per-command checkpointVersion/schema and register `app.recoveryCommand(command, handler)`. `context.checkpoint(data, expectedSequence)` saves up to 64 KiB. Data, version, host schemaHash, sequence, and events atomically commit with tasks using CAS. Schemas establish identity/format compatibility; plugins validate checkpoint/migration structures.
503
590
 
504
- `tasks.checkpoint(taskId)` 读取检查点;`tasks.resume(taskId, { environment?, revision? })` 为终态根命令建立新 attempt,保持旧任务终态,固定原安装、源码快照、输入、目录和路由。默认提交调用进程的新环境,旧环境不持久化。恢复入口读取 `context.recovery`,先核对外部操作状态;宿主不重放原 handler,也不保证外部提交与检查点原子。
591
+ `tasks.checkpoint(taskId)` reads checkpoints. `tasks.resume(taskId, { environment?, revision? })` creates new attempts for terminal root commands, retaining old terminal tasks and original installation, snapshot, input, directory, and route. Default environment comes freshly from the caller; old environments are not persisted. Recovery handlers read `context.recovery` and check external state first. Hosts neither replay original handlers nor guarantee atomic external submissions/checkpoints.
505
592
 
506
- SDK 使用 `tasks.checkpoint(taskId)` / `tasks.resume(taskId)`。当前仅支持 public/service 根命令,拒绝模型、子任务、页面绑定和 caller 路由恢复,且必须确认原执行树已经停止。默认固定原代码;显式 `revision: 'current'` 选择请求进入时的当前快照。同格式版本需 schema 相同,跨格式版本需目标 `taskRecovery` 声明 `migrateFrom: [{ version, schema }]` 并注册隐藏 `app.checkpointMigration(command, handler)`,返回目标检查点数据。宿主先核验历史 schemaHash,禁止转换中的宿主及嵌套插件 API,以 10 秒期限管理进程;转换必须可重试、无副作用,可信代码不构成 OS 沙箱。并发恢复合并为一个转换与后继任务,旧任务和数据保持不变。完整资格与故障域见[检查点与显式恢复](../../docs/plugin-runtime.md#检查点与显式恢复)。
593
+ Use `tasks.checkpoint(taskId)` / `tasks.resume(taskId)`. Only public/service roots qualify; models, children, page bindings, and caller routing reject recovery, and original trees must be confirmed stopped. Original code is the default; explicit `revision: 'current'` pins request-time snapshots. Same-version schemas must match. Cross-version targets declare `taskRecovery` `migrateFrom: [{ version, schema }]` and hidden `app.checkpointMigration(command, handler)`, returning target checkpoint data. Hosts verify historical schemaHash, forbid host/nested-plugin APIs during migration, and manage processes with 10-second deadlines. Conversion must be retryable and side-effect-free; trusted code is not an OS sandbox. Concurrent recovery coalesces into one conversion/successor; original tasks/data remain. See [checkpoints and explicit recovery](../../docs/plugin-runtime.md#checkpoints-and-explicit-recovery).
507
594
 
508
- 插件 CLI 调用失败以非零退出码和 stderr JSON `{ "error": { "code", "message" } }` 返回,保留 SDK/MCP 的 code,不输出任意异常附加字段。`PLUGIN_TASK_WAIT_TIMEOUT` 仅停止等待;`PLUGIN_EXECUTION_CANCELLED` / `PLUGIN_EXECUTION_DEADLINE` 表示执行取消或到期;`PLUGIN_PAGE_TARGET_CHANGED` / `PLUGIN_PAGE_INVALIDATED` 要求重新获取页面实例;`PLUGIN_STATE_CONFLICT` 需重新读取 CAS 版本;`PLUGIN_MODEL_CAPABILITY_UNSUPPORTED` 表示声明能力不支持;`PLUGIN_INVOCATION_CYCLE` / `PLUGIN_INVOCATION_DEPTH` 拒绝循环或过深组合。进程树无法确认停止时保留失败记录并拒绝恢复。
595
+ Plugin CLI failures return nonzero and stderr JSON `{ "error": { "code", "message" } }`, preserving SDK/MCP codes without arbitrary exception extras. `PLUGIN_TASK_WAIT_TIMEOUT` stops observation only; `PLUGIN_EXECUTION_CANCELLED` / `PLUGIN_EXECUTION_DEADLINE` indicate cancellation/deadline; `PLUGIN_PAGE_TARGET_CHANGED` / `PLUGIN_PAGE_INVALIDATED` require new instances; `PLUGIN_STATE_CONFLICT` requires fresh CAS reads; `PLUGIN_MODEL_CAPABILITY_UNSUPPORTED` means unsupported capabilities; `PLUGIN_INVOCATION_CYCLE` / `PLUGIN_INVOCATION_DEPTH` reject cycles/depth. Unconfirmed process-tree termination retains failure records and rejects recovery.
509
596
 
510
- 开发环境可运行 `pnpm verify:plugin-host:default` 验证 SDK 与 PATH CLI 在原配置、原认证和默认模型下的完整执行;原配置保持不变。工具箱内显式页面 attach 缺少站点授权时会申请权限,由用户确认后继续;后台页面运行时不会自动弹窗申请。
597
+ Explicit toolbox page attach requests missing site permissions and continues after user confirmation. Background page runtimes never prompt automatically.
511
598
 
512
- 模型列表可通过 SDK `PluginModelClient.list()` 或工具箱 `host.model.list` 查询。模型项携带可用时的 `reasoningEfforts` 和 `defaultReasoningEffort`,界面按模型支持范围提供思考级别。宿主合并并发发现请求,已有模型目录立即返回,过期后后台刷新;刷新失败保留可用目录并短暂退避,不创建推理会话。状态批量读取使用 `get-many` 和 `keys`(SDK `getMany`、工具箱 `host.state.getMany`),一次读取同一 revision 的最多 128 个键,含缺失键的 CAS version,结果上限 1 MiB。
599
+ Query models through SDK `PluginModelClient.list()` or toolbox `host.model.list`. Entries include supported `reasoningEfforts` and `defaultReasoningEffort` where available; UI restricts choices accordingly. Hosts coalesce discovery, immediately return existing catalogs, and refresh stale data in background. Failures retain usable catalogs with short backoff and create no inference sessions. Batch state reads use `get-many` and `keys` (SDK `getMany`, toolbox `host.state.getMany`) for up to 128 `keys` at one revision, including missing keys' CAS versions, limited to 1 MiB.
513
600
 
514
601
 
515
- 插件宿主由 `PluginHost` 组装任务、状态、页面与模型目录服务,统一关闭和诊断。`PluginTaskManager` 接收明确的服务依赖并管理执行树;页面和状态服务不反向修改调度器。SDK 的连接、服务发现、握手、重连和调用桥接由 `PluginHostConnection` 管理。需要共享连接时,在 Task/Model/State 客户端构造选项中传入 `connection`,Page 客户端通过第二个构造参数传入;注入连接由创建者关闭,各客户端的 `disconnect()` 只关闭自己创建的连接。连接始终绑定单个调用范围,不能跨插件、交互渠道或来源复用。
602
+ `PluginHost` assembles tasks, state, pages, and model catalogs with shutdown/diagnostics. `PluginTaskManager` receives explicit dependencies and owns execution trees; page/state services do not mutate schedulers. `PluginHostConnection` manages RPC, discovery, handshake, reconnection, and bridging. Share connections through Task/Model/State constructor `connection` options or Page's second constructor argument. Creators close injected connections; client `disconnect()` closes only owned connections. Connections bind one caller scope and cannot cross plugins, interaction channels, or sources.
516
603
 
517
- 后台连续模型调用可以显式传 `conversation`(1–80 个字母、数字或 `:_-`)。同名会话仅在当前页面实例或宿主管理的当前命令执行内复用;插件、版本、模型、指令、环境和调用归属分别隔离。未指定时每次调用独立。页面解除绑定或命令结束会释放会话;取消、失败和超时会销毁当前会话,空闲 5 分钟释放,每 32 轮重新建立临时会话以限制历史增长。会话仅驻留内存,不新增顶层 CLI/MCP 命令。
604
+ Continuous background model calls may specify `conversation` (1–80 letters, digits, or `:_-`). Same-name reuse is limited to the current page instance or current host-managed command. Plugin, revision, model, instructions, environment, and ownership isolate sessions. Omission creates independent calls. Detach/command end releases conversations; cancel/failure/timeout destroys them. Idle expiry is five minutes; temporary sessions restart every 32 turns to bound history. Conversations are memory-only with no new global CLI/MCP commands.
518
605
 
519
- ## 受管理插件目录
606
+ ## Managed plugin catalog
520
607
 
521
- 安装宿主可通过 client/plugin 的 replaceOfficialPluginCatalog(revision, plugins) 保存已选 preset 的插件目录。revision 为确切清单摘要,每项声明 description、skill 和安装器参数 installArgs,可选 setup 分组。目录以原子文件替换保存于当前插件注册目录的 .official-catalog.json;默认不存在任何预装组织项。安装源码与 preset 的信任校验由安装宿主负责,目录本身不触发安装。
608
+ Installation hosts use client/plugin replaceOfficialPluginCatalog(revision, plugins) to save selected-preset catalogs. revision is the exact manifest digest; entries contain description, skill, installer installArgs, and optional setup grouping. Atomic replacement saves .official-catalog.json in the registry directory; catalogs default empty. Hosts own source/preset trust checks; catalogs alone do not install.
522
609
 
523
- findOfficialPlugin/listOfficialPluginNames 每次读取当前目录,继续复用同一 setup 入口完成缺失插件安装。readOfficialPluginCatalog 向安装状态页报告损坏;普通插件和浏览器命令忽略损坏的可选目录,不影响已注册能力。OFFICIAL_PLUGINS 兼容导出反映本进程最近读取的目录。
610
+ findOfficialPlugin/listOfficialPluginNames reread current catalogs and reuse setup for missing plugins. readOfficialPluginCatalog reports corruption to installation status; ordinary plugin/browser commands ignore corrupt optional catalogs without affecting registered capabilities. Compatibility export OFFICIAL_PLUGINS reflects the most recently read catalog in the process.
524
611
 
525
- 扩展版本检查默认读取 GitHub 最新正式发行物中的 config.json;发行宿主可用 MEARL_EXTENSION_CONFIG_URL 提供返回 version 或 latestVersion 的配置端点。尚未上传扩展发行元数据时,更新信息显示不可用,核心源码版本不作为已发布扩展版本;检查失败仅影响更新提示。
612
+ Extension update checks default to config.json from GitHub's latest stable release. Distribution hosts may set MEARL_EXTENSION_CONFIG_URL to an endpoint returning version or latestVersion. Until extension metadata is uploaded, update data is unavailable; source versions are not published extension versions. Check failures affect notifications only.