@mearl/provider 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.
- package/README.md +147 -102
- package/README.zh-CN.md +248 -0
- package/dist/app-resources.d.ts +15 -0
- package/dist/app-resources.js +55 -0
- package/dist/control-host.d.ts +10 -0
- package/dist/control-host.js +5 -0
- package/dist/control-rpc.d.ts +7 -0
- package/dist/control-rpc.js +66 -0
- package/dist/enhancements.d.ts +19 -0
- package/dist/enhancements.js +100 -0
- package/dist/host.d.ts +1 -1
- package/dist/host.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/launcher.js +18 -7
- package/dist/protocol.d.ts +2 -0
- package/dist/protocol.js +5 -0
- package/dist/provider-runtime.js +67 -1
- package/dist/registry.js +3 -1
- package/dist/server.js +44 -6
- package/dist/types.d.ts +16 -3
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,37 +1,39 @@
|
|
|
1
1
|
# @mearl/provider
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Provider 使用相同的 `BrowserProviderDefinition`;区别只在于运行时位于 Native Host 进程内,
|
|
5
|
-
还是通过本地 Provider Socket 接入。
|
|
3
|
+
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
`@mearl/provider` defines Mearl's unified browser Provider contracts and runtime. Built-in Local Chrome and external
|
|
6
|
+
Providers share `BrowserProviderDefinition`; the runtime either runs inside Native Host
|
|
7
|
+
or connects through a local Provider Socket.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The action catalog directly reuses `@mearl/browser-core/browserActionProtocol`, without a separately generated copy.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Core model
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Mearl manages control sessions by default. Providers receive target instances, pages, and ordinary actions, without handling session IDs, resource ownership, or human handoff state. Release with `--session` ends only Mearl task control; instance closure, detachment, and Cookie synchronization use Provider lifecycle methods. Upload and download require `page_upload` and `page_download`, respectively, in `capabilities.actions`.
|
|
14
14
|
|
|
15
|
-
`
|
|
15
|
+
Mearl appends `session` to ordinary action responses with routing and control state only; `browser_control` handoff also includes session pages. Text refs from `page_snapshot` are directly actionable. Providers retain locator mappings in their runtime rather than exposing internal node-ID dictionaries.
|
|
16
16
|
|
|
17
|
-
Provider
|
|
17
|
+
`page_upload` receives `filePaths` on the execution host; Mearl stages caller files and browser artifacts. `page_download` receives `{ tabId, trigger, url?, timeout? }`: listen for downloads before clicking, wait for completion, then return `ProviderDownloadResult`: `{ filename, filePath, action, owned? }`. `filePath` is absolute on the local Provider process host; Providers retrieve remote files. `action` is the click result; `owned:true` lets Mearl delete the staged file after import. Mearl converts it to a browser artifact for saving, later upload, and session cleanup. Return an error on timeout or uncertain provenance without clicking again.
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
- `control`:页面操作由 Provider 自己处理、由宿主的 Extension/CDP 处理,或当前没有控制通道。
|
|
19
|
+
Provider v2 separates instance status from control mode:
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
`
|
|
24
|
-
也不需要伪装成已连接浏览器。
|
|
21
|
+
- `status`: `connected`, `pairing`, `running_disconnected`, or `stopped`.
|
|
22
|
+
- `control`: Page actions are handled by the Provider, by the host's Extension/CDP, or have no current control channel.
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
Instances also declare `ownership`, `persistence`, currently permitted resource `operations`, stable
|
|
25
|
+
`references`, and publicly displayable `details`. Provider identity is independent of control transport, and persistent instances
|
|
26
|
+
need not pretend to be connected browsers.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
## External Provider installation
|
|
29
|
+
|
|
30
|
+
External Provider packages declare `@mearl/provider` as a runtime dependency:
|
|
29
31
|
|
|
30
32
|
```bash
|
|
31
33
|
pnpm add @mearl/provider
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
`package.json#mearl.provider` declares the protocol entry, browser type, and structured launch arguments:
|
|
35
37
|
|
|
36
38
|
```json
|
|
37
39
|
{
|
|
@@ -63,13 +65,13 @@ pnpm add @mearl/provider
|
|
|
63
65
|
}
|
|
64
66
|
```
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
`browserType.configuration.inputSchema
|
|
68
|
-
`mearl <providerId> --help`
|
|
69
|
-
CLI
|
|
70
|
-
`local`
|
|
68
|
+
Schemas support string, number, boolean, array, and recursive object. Provider configuration can use
|
|
69
|
+
`browserType.configuration.inputSchema`. `mearl <providerId>` and
|
|
70
|
+
`mearl <providerId> --help` display `browserType.help`, so operation guidance evolves with the package version. If a same-name Skill plugin is registered,
|
|
71
|
+
the CLI appends a plugin command summary automatically; do not duplicate that list in `browserType.help`.
|
|
72
|
+
`local` is a reserved built-in ID.
|
|
71
73
|
|
|
72
|
-
##
|
|
74
|
+
## Minimal external runtime
|
|
73
75
|
|
|
74
76
|
```ts
|
|
75
77
|
import { createProviderServer, type BrowserProviderDefinition } from '@mearl/provider';
|
|
@@ -114,73 +116,73 @@ server.updateBrowsers([
|
|
|
114
116
|
]);
|
|
115
117
|
```
|
|
116
118
|
|
|
117
|
-
|
|
118
|
-
`status: "stopped"`
|
|
119
|
+
Pairing devices use `status: "pairing"` with `pairing`; stopped persistent instances use
|
|
120
|
+
`status: "stopped"` and `control: { kind: "none" }`. Running instances without connected control use
|
|
119
121
|
`status: "running_disconnected"`。
|
|
120
|
-
|
|
121
|
-
`capabilities.actions`
|
|
122
|
-
`start
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
`browser_list.browsers[]
|
|
127
|
-
|
|
128
|
-
Local
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
`not`
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
`formHideOptional`
|
|
141
|
-
`browserType.documentationUrl`
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
`browserType.launchForm`
|
|
147
|
-
|
|
148
|
-
`dynamicFields`
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
`browser_providers`
|
|
153
|
-
|
|
154
|
-
- `inputSchema`
|
|
155
|
-
- `variants`
|
|
156
|
-
- `values`
|
|
157
|
-
-
|
|
158
|
-
|
|
159
|
-
- `refreshOn`
|
|
160
|
-
|
|
161
|
-
- `message`
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
`details`
|
|
170
|
-
`cdpPort`
|
|
171
|
-
`copiedCookies`
|
|
172
|
-
`references`
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
##
|
|
176
|
-
|
|
177
|
-
Native Host
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
122
|
+
The runtime validates schemas, state machines, operations, and page-action capabilities before calling implementations.
|
|
123
|
+
`capabilities.actions` must explicitly list implemented and verified actions. Do not derive it from all actions minus exclusions, which could falsely advertise new SDK actions. Forwarding adapters may automatically reconnect and retry only if a connection failure proves the request was never sent. Sent requests with missing responses and business execution failures must not be replayed automatically.
|
|
124
|
+
Optional implementations such as `start`, `detach`, `getAccess`, and `syncCookies` must match declared instance operations;
|
|
125
|
+
the Provider runtime coordinates these lifecycle methods while browser actions use the unified Mearl protocol.
|
|
126
|
+
|
|
127
|
+
Public `browser_launch` accepts `{ provider, providerOptions }` for all Providers and returns
|
|
128
|
+
the same `ManagedBrowserInfo` as `browser_list.browsers[]`: object-form Provider identity, state,
|
|
129
|
+
persistence policy, operations, and security metadata. Internal manager fields, control connections, and temporary access URLs are excluded.
|
|
130
|
+
Local top-level CLI arguments are convenience inputs. External Provider arguments must use `providerOptions`; the two cannot be mixed.
|
|
131
|
+
|
|
132
|
+
Built-in browsers retain local launch interactions; external Provider inputs are generated from `browserType.inputSchema`.
|
|
133
|
+
Both submit the same `providerOptions` structure.
|
|
134
|
+
Top-level schema `oneOf` can declare multiple complete object constraints,
|
|
135
|
+
such as creating or attaching sessions. Each branch has a `title`; the runtime requires input to match exactly one branch.
|
|
136
|
+
`not` excludes forbidden combinations. `default` initializes forms without implicitly modifying caller arguments.
|
|
137
|
+
Object field `copyCookieDomains` uses the `{ presets?, domains? }` Cookie scope convention.
|
|
138
|
+
With `component: "cookie-sync"`, the browser manager uses the shared Cookie
|
|
139
|
+
scope selector and requests selected-site permissions before submission. Without it, the field renders as an ordinary object.
|
|
140
|
+
`component: "switch"` renders compact boolean switches. `formHidden` hides advanced CLI/API-only
|
|
141
|
+
fields; `formWidth` controls width; `formDefault` initializes forms without changing runtime defaults;
|
|
142
|
+
`formHideOptional` hides only the optional marker, not validation; `formVisibleWhen` controls display and submission based on another field's emptiness.
|
|
143
|
+
`browserType.documentationUrl` declares an HTTP(S) documentation URL. `configuration.inputSchema` declares configuration inputs,
|
|
144
|
+
passed only to the selected Provider's `configure`, without page-local persistence.
|
|
145
|
+
|
|
146
|
+
Providers querying device pools, existing sessions, or dynamic options declare `browserType.dynamicLaunchForm: true`
|
|
147
|
+
and implement read-only `getLaunchForm({ variant?, values }, context)`.
|
|
148
|
+
`browserType.launchForm` can supply an initial form without network access, rendering fields and modes immediately.
|
|
149
|
+
Each `variants[]` entry can override mode defaults through `inputSchema/values/refreshOn/dynamicFields`.
|
|
150
|
+
`dynamicFields` identifies fields disabled during asynchronous queries; other fields and mode selection remain usable. A form status row shows loading.
|
|
151
|
+
The initial query carries static defaults and sends only parseable fields; final launch still validates all inputs strictly.
|
|
152
|
+
Input entered while waiting is retained. Mode or environment changes invalidate previous requests.
|
|
153
|
+
The manager uses the internal
|
|
154
|
+
`browser_providers` `launch_form` operation to obtain `ProviderLaunchForm`, without recognizing Provider IDs or business fields:
|
|
155
|
+
|
|
156
|
+
- `inputSchema` describes user inputs for the current mode; `required` controls required markers and submission validation.
|
|
157
|
+
- `variants` uses `id/title/description` for connection modes, with `variant` selecting the current mode.
|
|
158
|
+
- `values` contains fixed, non-sensitive Provider launch arguments, merged with user inputs on submission.
|
|
159
|
+
- String-field `options` use `{ value, label, description?, disabled? }`.
|
|
160
|
+
Disabled options are display-only. Provider `launch` revalidates final resource state.
|
|
161
|
+
- `refreshOn` identifies fields requiring a form query; changes clear selections in other option fields.
|
|
162
|
+
Refresh retains inputs and still-valid option selections; switching modes reapplies that mode's defaults.
|
|
163
|
+
- `message` displays query results; `blocked` prevents submission without resources or valid sessions.
|
|
164
|
+
|
|
165
|
+
Queries must not create or rent resources or return credentials. The runtime validates returned schemas, options,
|
|
166
|
+
modes, and fixed arguments. Final `launch` still validates against `browserType.inputSchema`; dynamic forms do not change CLI/API
|
|
167
|
+
argument contracts. Providers without dynamic forms use static schemas.
|
|
168
|
+
For local integration, link a local `@mearl/provider` build containing this public contract. Distribution requires matching releases
|
|
169
|
+
of the SDK, Mearl host, and Provider supporting dynamic forms.
|
|
170
|
+
|
|
171
|
+
Common `details` keys have fixed types: `headless` is boolean, `createdAt` is a parseable timestamp,
|
|
172
|
+
`cdpPort` is a valid port, `account` contains `nickname` and optional string `accountId/loginId`,
|
|
173
|
+
and `copiedCookies` contains string-array `domains` and nonnegative integer `count`. Other keys may contain non-sensitive JSON and are also displayed.
|
|
174
|
+
`references.kind` identifies resource categories, `id` is opaque, and `label` is the display name.
|
|
175
|
+
Common categories include `profile/session/image/context/context-name`; Providers may define others.
|
|
176
|
+
|
|
177
|
+
## Built-in runtime
|
|
178
|
+
|
|
179
|
+
Native Host runs Local directly with `createProviderRuntime(definition)`, without a Socket
|
|
180
|
+
or installation record. Built-in and external implementations share schema validation, state machines, and lifecycle dispatch. In-process host services can use `ProviderContext.host`; Provider contracts do not depend on Extension, Native Messaging, or
|
|
181
|
+
specific browser service SDKs.
|
|
182
|
+
|
|
183
|
+
Launching, configuring, or querying dynamic forms for a specific Provider starts only that Provider; full discovery checks all installed Providers. Mearl's control host manages queues and actions against caller absolute deadlines. Callers without deadlines use action-derived waits; persistent closure and long waits have no fixed two-minute limit. Adapter forwarding must cover the action's time budget and preserve uncertain-execution semantics when waiting fails.
|
|
184
|
+
|
|
185
|
+
setup manages external Provider installation, discovery, and startup:
|
|
184
186
|
|
|
185
187
|
```bash
|
|
186
188
|
npx @mearl/setup provider install <package>
|
|
@@ -188,16 +190,59 @@ npx @mearl/setup provider update <provider-id>
|
|
|
188
190
|
npx @mearl/setup provider uninstall <provider-id>
|
|
189
191
|
```
|
|
190
192
|
|
|
191
|
-
## Socket
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
- `browser_providers
|
|
197
|
-
- `browser_instances
|
|
198
|
-
- `browser_launch
|
|
199
|
-
- `browser_sessions
|
|
200
|
-
|
|
201
|
-
SDK
|
|
202
|
-
`browser_release`
|
|
203
|
-
|
|
193
|
+
## Socket protocol
|
|
194
|
+
|
|
195
|
+
The current Provider protocol version is **3**; request envelopes carry `protocolVersion`. Installation metadata,
|
|
196
|
+
runtime descriptors, running processes, and callers must match. Update the relevant packages and restart processes on mismatch.
|
|
197
|
+
|
|
198
|
+
- `browser_providers`: `operation: "configure"` carries `options`; `operation: "launch_form"` carries `variant?` and `values`.
|
|
199
|
+
- `browser_instances`: `operation: "start" | "detach" | "sync_cookies"`; synchronization carries `scope`, and envelope `browserId` selects the instance.
|
|
200
|
+
- `browser_launch`, `browser_close`, and `get_browser_access_url` retain their separate responsibilities.
|
|
201
|
+
- Mearl's control process handles `browser_sessions`, without forwarding to external Providers. Session release and instance `detach` are separate.
|
|
202
|
+
|
|
203
|
+
The SDK dispatches Socket requests to methods such as `configure/getLaunchForm/start/detach/syncCookies`.
|
|
204
|
+
The ordinary `browser_release` action does not detach instances; Mearl converts public CLI release without a session to `detach`.
|
|
205
|
+
Providers bundling the SDK must update it and rebuild. Editing installation metadata cannot replace running code.
|
|
206
|
+
|
|
207
|
+
## External task control and page enhancement
|
|
208
|
+
|
|
209
|
+
Providers managing their own task ownership and human handoffs can declare
|
|
210
|
+
`["external"]` in `browserType.controlSessionModes` and return `controlSessionMode: "external"` in instance `control.capabilities`.
|
|
211
|
+
The SDK checks Mearl host support at startup and before operations; unsupported hosts reject explicitly.
|
|
212
|
+
An instance's control mode is fixed within a runtime. External mode rejects Mearl `--session`; external tools own page ownership and handoff.
|
|
213
|
+
Providers omitting this field retain default behavior.
|
|
214
|
+
|
|
215
|
+
External Providers can bind Mearl Extension environment enhancement to authorized pages through
|
|
216
|
+
`createProviderEnhancementClient(providerId, browserId)`, calling `bind`, `invoke`, and `release`. Only device, App, and time-zone enhancement is allowed,
|
|
217
|
+
as advertised by the Extension. The current Extension exposes only time zones.
|
|
218
|
+
The channel applies domain authorization and page-control conflict checks without registering automation pages or granting ordinary page actions, arbitrary code execution, or closure.
|
|
219
|
+
Independent packages use `@mearl/provider-<id>`. EgoLite has native Space management and human handoff. The [mearl-ego Skill](../../skills/mearl-ego/SKILL.md) uses existing tools with the Mearl extension for simulation and debugging, without this Provider enhancement channel.
|
|
220
|
+
|
|
221
|
+
Implement read-only `getEnhancementTarget({ browserId, tabId }, context)`. Under external user control, return
|
|
222
|
+
`{ tabId, ready: false }`; when Agent control is confirmed, return
|
|
223
|
+
`{ tabId, ready: true, mainFrameId, url }`. A current physical `targetId` may replace `mainFrameId`.
|
|
224
|
+
Identity must come from the current browser target. When both are given, the host verifies both. Target-ID-only mode requires host target verification support.
|
|
225
|
+
URL narrows candidates but cannot alone prove page identity.
|
|
226
|
+
This callback and `listBrowsers` must be reentrant while `handleAction` awaits enhancement, without acquiring that operation's lock or claiming user pages.
|
|
227
|
+
|
|
228
|
+
Calls may carry the original request's absolute `deadline`, outside the business payload. Binding handles are scoped to pages, connection generations, and allowed actions;
|
|
229
|
+
process restarts or page identity changes require revalidation. After a mutation response is lost, later writes are isolated and cannot be replayed or rerouted through ordinary actions.
|
|
230
|
+
Explicit rebinding only revalidates identity; the execution host must resolve environment recovery conflicts that remain unconfirmed.
|
|
231
|
+
|
|
232
|
+
## Installed App resources
|
|
233
|
+
|
|
234
|
+
External-control Providers can read locally accepted App definitions and runtimes using
|
|
235
|
+
`createProviderAppResourceClient(providerId, browserId)`. `catalog(params?, deadline?)` returns catalog summaries only;
|
|
236
|
+
`resolve({providerTabId, profile, options?}, deadline?)` revalidates page control and identity, then returns compiled configuration,
|
|
237
|
+
capability/installation revisions, and exact runtime bindings and source. It does not install pages or execute business host services.
|
|
238
|
+
|
|
239
|
+
The full Native capability service resolves resources; Skill catalogs read registered snapshots without re-executing source files for discovery.
|
|
240
|
+
A resource protocol declaration only indicates an available reader. Explicit reads refresh and validate installation; slow or failed module initialization does not block ordinary Provider control-host startup.
|
|
241
|
+
Profiles containing bridges or globals without an explicit runtime use installed `app.defaultPageRuntime`. Missing runtimes are rejected,
|
|
242
|
+
without downgrading the profile into a fully prepared UA configuration. The SDK rechecks definition revisions, page proof, and source SHA-256.
|
|
243
|
+
The separate resource message limit is 16 MiB to accommodate JSON-encoded runtimes; ordinary enhancement remains limited to 1 MiB.
|
|
244
|
+
|
|
245
|
+
Providers store and reference verified code within their own instance/page scopes, preserving existing quotas and cleanup rules.
|
|
246
|
+
A Space listing is not the full physical browser target list and cannot justify reclaiming others' resources.
|
|
247
|
+
Obtaining resources does not establish backend support for root containers, bridge callbacks, or real authorization. Advertise App capabilities only after individual verification.
|
|
248
|
+
Hosts without the resource protocol declaration reject explicitly, without falling back to ordinary actions or arbitrary Node execution.
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# @mearl/provider
|
|
2
|
+
|
|
3
|
+
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
`@mearl/provider` 是 Mearl 的统一浏览器 Provider 契约与运行时。内置 Local Chrome 和外部
|
|
6
|
+
Provider 使用相同的 `BrowserProviderDefinition`;区别只在于运行时位于 Native Host 进程内,
|
|
7
|
+
还是通过本地 Provider Socket 接入。
|
|
8
|
+
|
|
9
|
+
action 清单直接复用 `@mearl/browser-core/browserActionProtocol` 的能力动作合同,不维护独立生成副本。
|
|
10
|
+
|
|
11
|
+
## 核心模型
|
|
12
|
+
|
|
13
|
+
默认由 Mearl 管理控制会话。Provider 继续接收目标实例、页面与普通 action,无需处理控制会话 ID、资源归属或人工交接状态。带 `--session` 的释放只结束 Mearl 任务控制;实例关闭、退出接管与 Cookie 同步仍使用 Provider 的生命周期方法。上传与下载分别按 `capabilities.actions` 中的 `page_upload`、`page_download` 声明使用。
|
|
14
|
+
|
|
15
|
+
普通 action 响应中的 `session` 由 Mearl 附加,只包含路由与控制状态;`browser_control` 交接时还包含会话页面清单。`page_snapshot` 的文本 ref 可直接用于后续操作,Provider 应在自身运行时保存其定位映射,不在响应中输出内部节点 ID 字典。
|
|
16
|
+
|
|
17
|
+
`page_upload` 接收执行宿主上的 `filePaths`,Mearl 负责中转调用方文件与浏览器产物。`page_download` 接收 `{ tabId, trigger, url?, timeout? }`;Provider 先监听下载,再执行点击,等待文件完成后返回 `ProviderDownloadResult`:`{ filename, filePath, action, owned? }`。`filePath` 是本地 Provider 进程宿主上的绝对路径,云端文件由 Provider 取回;`action` 是点击结果,`owned:true` 允许 Mearl 在导入后删除该中转文件。Mearl 将结果转为统一的浏览器产物,支持调用方保存、后续上传与会话清理。下载超时或来源不确定时返回错误,不重复点击。
|
|
18
|
+
|
|
19
|
+
Provider v2 分开表达实例状态与控制方式:
|
|
20
|
+
|
|
21
|
+
- `status`:实例处于 `connected`、`pairing`、`running_disconnected` 或 `stopped`。
|
|
22
|
+
- `control`:页面操作由 Provider 自己处理、由宿主的 Extension/CDP 处理,或当前没有控制通道。
|
|
23
|
+
|
|
24
|
+
实例还会声明 `ownership`、`persistence`、当前允许的资源 `operations`、稳定
|
|
25
|
+
`references` 和可公开展示的 `details`。因此 Provider identity 不再等同于控制传输,持久化实例
|
|
26
|
+
也不需要伪装成已连接浏览器。
|
|
27
|
+
|
|
28
|
+
## 外部 Provider 安装
|
|
29
|
+
|
|
30
|
+
外部 Provider 包将 `@mearl/provider` 声明为运行依赖:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm add @mearl/provider
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
包的 `package.json#mearl.provider` 声明协议入口、浏览器类型和结构化启动参数:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"name": "@example/mearl-provider-device",
|
|
41
|
+
"version": "1.0.0",
|
|
42
|
+
"type": "module",
|
|
43
|
+
"mearl": {
|
|
44
|
+
"provider": {
|
|
45
|
+
"providerId": "example-device",
|
|
46
|
+
"name": "Example device provider",
|
|
47
|
+
"protocolVersion": 3,
|
|
48
|
+
"entry": "./dist/runtime.js",
|
|
49
|
+
"browserType": {
|
|
50
|
+
"name": "Device",
|
|
51
|
+
"help": ["Pair a device, then use its browserId with Mearl actions."],
|
|
52
|
+
"inputSchema": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"properties": {
|
|
55
|
+
"code": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"title": "Pairing code",
|
|
58
|
+
"placeholder": "Generated by default"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Schema 支持 string、number、boolean、array 和递归 object;Provider 配置也可通过
|
|
69
|
+
`browserType.configuration.inputSchema` 声明。`browserType.help` 由 `mearl <providerId>` 和
|
|
70
|
+
`mearl <providerId> --help` 展示,让 Provider 的操作说明随独立包版本演进。同名 Skill 插件已注册时,
|
|
71
|
+
CLI 会在其后自动追加插件命令摘要,Provider 不需要在 `browserType.help` 中重复维护命令清单。
|
|
72
|
+
`local` 是内置保留 ID。
|
|
73
|
+
|
|
74
|
+
## 最小外部运行时
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { createProviderServer, type BrowserProviderDefinition } from '@mearl/provider';
|
|
78
|
+
|
|
79
|
+
const definition: BrowserProviderDefinition = {
|
|
80
|
+
descriptor: {
|
|
81
|
+
providerId: 'example-device',
|
|
82
|
+
name: 'Example device provider',
|
|
83
|
+
version: '1.0.0',
|
|
84
|
+
},
|
|
85
|
+
browserType: {
|
|
86
|
+
name: 'Device',
|
|
87
|
+
inputSchema: {
|
|
88
|
+
type: 'object',
|
|
89
|
+
properties: { code: { type: 'string', title: 'Pairing code' } },
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
launch: async options => createDevice(String(options.code ?? '')),
|
|
93
|
+
close: async ({ browserId }) => removeDevice(browserId),
|
|
94
|
+
handleAction: async ({ browserId, action, data }) =>
|
|
95
|
+
dispatchDeviceAction(browserId, action, data),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const server = createProviderServer({ definition });
|
|
99
|
+
await server.start();
|
|
100
|
+
server.updateBrowsers([
|
|
101
|
+
{
|
|
102
|
+
browserId: 'device-1',
|
|
103
|
+
name: 'Example device',
|
|
104
|
+
status: 'connected',
|
|
105
|
+
control: {
|
|
106
|
+
kind: 'provider',
|
|
107
|
+
capabilities: {
|
|
108
|
+
actions: ['tab_list', 'page_snapshot', 'page_click'],
|
|
109
|
+
screenshot: 'none',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
ownership: 'owned',
|
|
113
|
+
persistence: 'persistent',
|
|
114
|
+
operations: ['close'],
|
|
115
|
+
},
|
|
116
|
+
]);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
配对中的设备使用 `status: "pairing"` 并提供 `pairing`;停止的持久化实例使用
|
|
120
|
+
`status: "stopped"` 和 `control: { kind: "none" }`。运行但尚未接通控制链路时使用
|
|
121
|
+
`status: "running_disconnected"`。
|
|
122
|
+
Runtime 会统一校验 schema、状态机、操作能力和页面 action capability,校验通过后才调用实现。
|
|
123
|
+
`capabilities.actions` 应明确列出适配器已经实现并验证的动作,避免通过全量动作减排除项生成清单,使 SDK 新增动作被误报为可用。适配器转发请求时,只有能证明请求尚未发送的连接失败才可自动重连重试;已经发送、响应丢失或业务执行失败的动作不应自动重放。
|
|
124
|
+
`start`、`detach`、`getAccess`、`syncCookies` 等可选实现必须与实例声明的 operation 对应;
|
|
125
|
+
这些生命周期方法由 Provider runtime 协调,浏览器动作使用统一的 Mearl 协议。
|
|
126
|
+
|
|
127
|
+
公共 `browser_launch` 对所有 Provider 接收 `{ provider, providerOptions }`,返回与
|
|
128
|
+
`browser_list.browsers[]` 相同的 `ManagedBrowserInfo`(对象形式的 Provider identity、状态、
|
|
129
|
+
持久化策略、操作和安全元数据)。管理器内部字段、控制连接和临时访问地址不进入该结果。
|
|
130
|
+
Local 的 CLI 顶层参数是便捷输入;外部 Provider 参数必须放在 `providerOptions`,两者不得混用。
|
|
131
|
+
|
|
132
|
+
内置浏览器保留本地启动交互;外部 Provider 根据 `browserType.inputSchema` 生成输入项。
|
|
133
|
+
两者提交同一结构的 `providerOptions`。
|
|
134
|
+
Schema 的顶层 `oneOf` 可声明多个完整对象约束,
|
|
135
|
+
例如创建与接管会话;每个分支用 `title` 命名,Runtime 要求输入恰好匹配一个分支,
|
|
136
|
+
`not` 可排除不允许的字段组合。`default` 是表单初始值,不会隐式修改调用方参数。
|
|
137
|
+
对象字段 `copyCookieDomains` 约定使用 `{ presets?, domains? }` Cookie 范围结构。
|
|
138
|
+
为这个字段声明 `component: "cookie-sync"` 后,Mearl 浏览器管理器会使用统一的 Cookie
|
|
139
|
+
范围选择组件,并在提交前申请所选站点权限;未声明组件时仍按普通 object 字段渲染。
|
|
140
|
+
Provider 可用 `component: "switch"` 渲染紧凑布尔开关;`formHidden` 隐藏仅供 CLI/API
|
|
141
|
+
使用的高级字段,`formWidth` 控制字段宽度,`formDefault` 设置不影响运行时默认值的表单初值,
|
|
142
|
+
`formHideOptional` 只隐藏可选标识而不改变校验,`formVisibleWhen` 根据另一个字段是否为空控制显示与提交。
|
|
143
|
+
`browserType.documentationUrl` 声明 HTTP(S) 文档地址;`configuration.inputSchema` 声明配置参数,
|
|
144
|
+
配置只传给所选 Provider 的 `configure`,不存入页面本地存储。
|
|
145
|
+
|
|
146
|
+
Provider 需要查询设备池、已有会话或动态候选项时,声明 `browserType.dynamicLaunchForm: true`
|
|
147
|
+
并实现只读的 `getLaunchForm({ variant?, values }, context)`。
|
|
148
|
+
`browserType.launchForm` 可提供无网络依赖的初始表单,弹窗立即渲染其字段和模式;
|
|
149
|
+
各 `variants[]` 可用 `inputSchema/values/refreshOn/dynamicFields` 覆盖该模式的初值。
|
|
150
|
+
`dynamicFields` 指定异步查询期间需要禁用的字段,其余字段与模式选择保持可操作;加载状态在表单状态行显示。
|
|
151
|
+
初次查询携带静态表单默认值;查询只传入可解析的字段,最终启动仍严格校验全部输入。
|
|
152
|
+
用户在等待期间输入的内容会保留,切换模式或环境会使旧请求失效。
|
|
153
|
+
管理器通过内部
|
|
154
|
+
`browser_providers` 的 `launch_form` operation 获取 `ProviderLaunchForm`,不识别 Provider ID 或业务字段:
|
|
155
|
+
|
|
156
|
+
- `inputSchema` 描述当前模式的用户输入,`required` 决定必填标识与提交校验。
|
|
157
|
+
- `variants` 的 `id/title/description` 描述连接方式,`variant` 指定当前方式。
|
|
158
|
+
- `values` 是 Provider 给出的固定启动参数,提交时与用户输入合并;只包含非敏感参数。
|
|
159
|
+
- 字符串字段的 `options` 使用 `{ value, label, description?, disabled? }` 描述候选项。
|
|
160
|
+
禁用项只供展示;运行时的最终资源状态由 Provider 的 `launch` 再次核验。
|
|
161
|
+
- `refreshOn` 指定需要重新查询表单的字段;字段变化会清空其他选项字段的选择。
|
|
162
|
+
刷新时保留已有输入,选项字段仅保留仍有效的选择;切换模式重新使用该模式默认值。
|
|
163
|
+
- `message` 展示查询结果,`blocked` 阻止无资源、无有效会话等情况下的提交。
|
|
164
|
+
|
|
165
|
+
查询过程不得创建或租用资源,也不得返回凭据。Runtime 会校验返回的 schema、候选项、
|
|
166
|
+
模式与固定参数。最终 `launch` 仍使用 `browserType.inputSchema` 校验,动态表单不改变 CLI/API
|
|
167
|
+
参数契约。未声明动态表单的 Provider 继续使用静态 schema。
|
|
168
|
+
开发联调时,Provider 应链接包含该公开契约的本地 `@mearl/provider` 构建;分发时需配套发布
|
|
169
|
+
包含动态表单能力的 SDK、Mearl 宿主与 Provider。
|
|
170
|
+
|
|
171
|
+
`details` 中的通用键具有固定类型:`headless` 为布尔值,`createdAt` 为可解析时间字符串,
|
|
172
|
+
`cdpPort` 为有效端口,`account` 包含 `nickname` 和可选的字符串 `accountId/loginId`,
|
|
173
|
+
`copiedCookies` 包含字符串数组 `domains` 和非负整数 `count`。其余键允许非敏感 JSON,界面同样展示。
|
|
174
|
+
`references` 的 `kind` 表示资源类别,`id` 为不透明标识,`label` 为展示名;
|
|
175
|
+
通用类别包括 `profile/session/image/context/context-name`,也允许 Provider 自定义类别。
|
|
176
|
+
|
|
177
|
+
## 内置运行时
|
|
178
|
+
|
|
179
|
+
Native Host 使用 `createProviderRuntime(definition)` 直接运行内置 Local Provider,不需要创建 Socket
|
|
180
|
+
或注册安装记录。内置与外部实现共享同一份 schema 校验、状态机和生命周期派发逻辑;需要宿主服务的进程内调用可通过 `ProviderContext.host` 注入,Provider 合同本身不依赖 Extension、Native Messaging 或
|
|
181
|
+
具体浏览器服务 SDK。
|
|
182
|
+
|
|
183
|
+
指定 Provider 的启动、配置和动态表单查询只启动该 Provider;完整浏览器发现仍检查所有已安装 Provider。Mearl 的 Provider 控制宿主按调用方绝对期限管理排队及后续动作,旧调用方使用按动作推导的等待时间,持久化关闭和长时间等待不受固定两分钟限制。适配器自己的转发链路也应覆盖对应动作的时间预算,并在等待失败时保留执行结果不确定的语义。
|
|
184
|
+
|
|
185
|
+
外部 Provider 的安装、发现与启动仍由 `@mearl/setup` 管理:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
npx @mearl/setup provider install <package>
|
|
189
|
+
npx @mearl/setup provider update <provider-id>
|
|
190
|
+
npx @mearl/setup provider uninstall <provider-id>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Socket 协议
|
|
194
|
+
|
|
195
|
+
当前 Provider 协议版本为 **3**,请求 envelope 携带 `protocolVersion`。安装元数据、
|
|
196
|
+
运行时 descriptor、运行中进程与调用方必须使用相同协议;不匹配时更新相关包并重启进程。
|
|
197
|
+
|
|
198
|
+
- `browser_providers`:`operation: "configure"` 携带 `options`,`operation: "launch_form"` 携带 `variant?` 和 `values`。
|
|
199
|
+
- `browser_instances`:`operation: "start" | "detach" | "sync_cookies"`;同步携带 `scope`,目标实例由 envelope 的 `browserId` 选择。
|
|
200
|
+
- `browser_launch`、`browser_close`、`get_browser_access_url` 保留各自职责。
|
|
201
|
+
- `browser_sessions` 由 Mearl 控制进程处理,不转交外部 Provider;会话释放与实例 `detach` 分开执行。
|
|
202
|
+
|
|
203
|
+
SDK 负责将 Socket 请求分发到 `configure/getLaunchForm/start/detach/syncCookies` 等方法。
|
|
204
|
+
`browser_release` 普通 action 不承担实例解绑;公开 CLI 的无会话释放由 Mearl 转换为 `detach`。
|
|
205
|
+
打包 SDK 的 Provider 必须更新 SDK 并重新构建,修改安装元数据不能替换运行中的旧代码。
|
|
206
|
+
|
|
207
|
+
## 外部任务控制与页面增强
|
|
208
|
+
|
|
209
|
+
已自行管理任务归属、人工交接的 Provider,可在 `browserType.controlSessionModes` 中声明
|
|
210
|
+
`["external"]`,并在实例的 `control.capabilities` 中返回 `controlSessionMode: "external"`。
|
|
211
|
+
SDK 在服务启动和操作前确认 Mearl 控制宿主支持此模式;旧宿主会明确拒绝。
|
|
212
|
+
同一运行时内实例的控制模式固定。该模式不接受 Mearl `--session`,页面归属和交接仍由外部工具负责。
|
|
213
|
+
未声明该字段的 Provider 保持原有行为。
|
|
214
|
+
|
|
215
|
+
外部 Provider 可用 `createProviderEnhancementClient(providerId, browserId)` 为已获准页面绑定 Mearl
|
|
216
|
+
Extension 的环境增强,依次调用 `bind`、`invoke`、`release`。这条通道只允许设备、App、时区类增强,
|
|
217
|
+
具体范围取决于 Extension 返回的能力;当前 Extension 实现仅开放时区。
|
|
218
|
+
它沿用域授权和现有页面控制冲突检查,不登记自动化页面,不提供普通页面操作、任意代码执行或关闭权限。
|
|
219
|
+
独立 Provider 包使用 `@mearl/provider-<id>` 命名。EgoLite 已有原生 Space 管理和人工交接,通过 [mearl-ego Skill](../../skills/mearl-ego/SKILL.md) 配合 Mearl 扩展进行端模拟与调试;该流程直接调用现有工具,不使用本节的 Provider 增强通道。
|
|
220
|
+
|
|
221
|
+
实现必须提供只读的 `getEnhancementTarget({ browserId, tabId }, context)`:外部用户控制时返回
|
|
222
|
+
`{ tabId, ready: false }`;确认 Agent 可操作时返回
|
|
223
|
+
`{ tabId, ready: true, mainFrameId, url }`,也可用当前物理 `targetId` 代替 `mainFrameId`。
|
|
224
|
+
身份必须来自当前浏览器目标;提供两项时,当前宿主同时核验两项。仅提供 target ID 时,需要宿主具备相应的目标核验能力。
|
|
225
|
+
URL 仅用于缩小候选范围,不能单独证明双方是同一页面。
|
|
226
|
+
此回调和 `listBrowsers` 必须能在 `handleAction` 等待增强结果期间重入,不应获取该操作持有的锁或认领用户页面。
|
|
227
|
+
|
|
228
|
+
调用可传入原请求的绝对 `deadline`,它不属于业务 payload。绑定句柄有页面、连接代次和动作范围限制;
|
|
229
|
+
进程重启或页面身份变化后需要重新核验。变更响应丢失后,后续写入会被隔离,不能自动重放或改走普通 action。
|
|
230
|
+
显式重新绑定只完成核验;无法确认的环境仍须由执行宿主处理恢复冲突。
|
|
231
|
+
|
|
232
|
+
## 已安装 App 资源
|
|
233
|
+
|
|
234
|
+
外部控制 Provider 可通过 `createProviderAppResourceClient(providerId, browserId)` 读取本机已接受的
|
|
235
|
+
App 定义与运行时。`catalog(params?, deadline?)` 只返回目录摘要;
|
|
236
|
+
`resolve({providerTabId, profile, options?}, deadline?)` 在重新核验页面控制和身份后返回编译配置、
|
|
237
|
+
能力/安装 revision,以及必要运行时的确切 binding 与源码。它不执行页面安装或业务宿主服务。
|
|
238
|
+
|
|
239
|
+
资源由完整 Native 能力服务解析,Skill 目录读取已注册快照;不会为发现目录重新执行 Skill 源文件。
|
|
240
|
+
资源协议声明只表示读取口存在;显式读取时才刷新和校验安装,能力模块的慢初始化或失败不阻塞普通 Provider 控制宿主启动。
|
|
241
|
+
含桥或全局变量且未显式指定运行时的档案,沿用已安装的 `app.defaultPageRuntime`;缺少运行时直接拒绝,
|
|
242
|
+
不将其降级为已完整准备的 UA 配置。SDK 会再次核验定义 revision、页面证明和源码 SHA-256。
|
|
243
|
+
独立的资源消息上限为 16 MiB,以容纳合法运行时的 JSON 编码;普通增强通道仍限 1 MiB。
|
|
244
|
+
|
|
245
|
+
Provider 应在自己的实例/页面范围中保存并引用已核验代码,保持原有资源配额与清理规则;
|
|
246
|
+
Space 清单不等于整个物理浏览器的目标清单,不能据此回收别人的资源。
|
|
247
|
+
获得资源不代表后端已支持其根容器、桥回调或真实授权,只有逐项验证后才声明对应 App 能力。
|
|
248
|
+
旧宿主缺少资源协议声明时明确拒绝,不回退到普通 action 或任意 Node 执行。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ProviderAppResourceRequest, type ProviderAppResourceResponse } from '@mearl/browser-core';
|
|
2
|
+
export interface ProviderAppResourceClient {
|
|
3
|
+
catalog(params?: Extract<ProviderAppResourceRequest, {
|
|
4
|
+
operation: 'catalog';
|
|
5
|
+
}>['params'], deadline?: number): Promise<Extract<ProviderAppResourceResponse, {
|
|
6
|
+
catalog: unknown;
|
|
7
|
+
}>>;
|
|
8
|
+
resolve(request: Omit<Extract<ProviderAppResourceRequest, {
|
|
9
|
+
operation: 'resolve';
|
|
10
|
+
}>, 'operation'>, deadline?: number): Promise<Extract<ProviderAppResourceResponse, {
|
|
11
|
+
config: unknown;
|
|
12
|
+
}>>;
|
|
13
|
+
}
|
|
14
|
+
/** Reads accepted installed resources. It never installs code in a page or runs host services. */
|
|
15
|
+
export declare function createProviderAppResourceClient(providerId: string, providerBrowserId: string): ProviderAppResourceClient;
|