@mearl/provider 2.13.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -83
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/provider-runtime.d.ts +5 -0
- package/dist/provider-runtime.js +501 -0
- package/dist/registry.d.ts +25 -11
- package/dist/registry.js +31 -24
- package/dist/runtime.d.ts +1 -0
- package/dist/runtime.js +1 -0
- package/dist/server.js +59 -122
- package/dist/types.d.ts +142 -29
- package/dist/types.js +1 -1
- package/package.json +3 -3
package/dist/server.js
CHANGED
|
@@ -4,6 +4,7 @@ import { chmodSync, rmSync } from 'node:fs';
|
|
|
4
4
|
import { dirname } from 'node:path';
|
|
5
5
|
import { ensureDir } from '@mearl/daemon-core';
|
|
6
6
|
import { isProviderAction } from './generated-provider-actions.js';
|
|
7
|
+
import { createProviderRuntime } from './provider-runtime.js';
|
|
7
8
|
import { PROVIDER_START_TOKEN_ENV, claimProviderStart, providerBrowserKey, providerSocketPath, publishLiveProvider, publishProviderBrowsers, readLiveProvider, releaseProviderStart, removeStaleProviderSocket, touchProviderBrowser, unpublishLiveProvider, unpublishProviderBrowsers, } from './registry.js';
|
|
8
9
|
import { MEARL_PROVIDER_PROTOCOL_VERSION } from './types.js';
|
|
9
10
|
const MAX_REQUEST_BYTES = 16 * 1024 * 1024;
|
|
@@ -28,153 +29,89 @@ function isProviderActionRequest(value) {
|
|
|
28
29
|
(request.controlSource === undefined || typeof request.controlSource === 'string'));
|
|
29
30
|
}
|
|
30
31
|
export function createProviderServer(options) {
|
|
31
|
-
const
|
|
32
|
+
const runtime = createProviderRuntime(options.definition);
|
|
33
|
+
const descriptor = options.definition.descriptor;
|
|
34
|
+
const socketPath = options.socketPath ?? providerSocketPath(descriptor.providerId);
|
|
32
35
|
let server = null;
|
|
33
36
|
let browserIds = new Set();
|
|
34
37
|
let browsers = [];
|
|
35
38
|
let state = 'idle';
|
|
36
39
|
let stopPromise = null;
|
|
37
40
|
const connections = new Set();
|
|
38
|
-
function
|
|
39
|
-
const { providerId, name, version, protocolVersion } = options.descriptor;
|
|
40
|
-
if (typeof providerId !== 'string' || !providerId.trim()) {
|
|
41
|
-
throw new Error('providerId is required');
|
|
42
|
-
}
|
|
43
|
-
if (typeof name !== 'string' || !name.trim())
|
|
44
|
-
throw new Error('provider name is required');
|
|
45
|
-
if (typeof version !== 'string' || !version.trim()) {
|
|
46
|
-
throw new Error('provider version is required');
|
|
47
|
-
}
|
|
48
|
-
if (protocolVersion !== undefined && protocolVersion !== MEARL_PROVIDER_PROTOCOL_VERSION) {
|
|
49
|
-
throw new Error(`Unsupported provider protocol ${protocolVersion}; expected ${MEARL_PROVIDER_PROTOCOL_VERSION}`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function assertBrowsers(nextBrowsers) {
|
|
53
|
-
const seen = new Set();
|
|
54
|
-
for (const browser of nextBrowsers) {
|
|
55
|
-
if (typeof browser.browserId !== 'string' || !browser.browserId.trim()) {
|
|
56
|
-
throw new Error('provider browserId is required');
|
|
57
|
-
}
|
|
58
|
-
if (typeof browser.name !== 'string' || !browser.name.trim()) {
|
|
59
|
-
throw new Error(`Provider browser ${browser.browserId} needs a name`);
|
|
60
|
-
}
|
|
61
|
-
if (seen.has(browser.browserId)) {
|
|
62
|
-
throw new Error(`Duplicate provider browserId: ${browser.browserId}`);
|
|
63
|
-
}
|
|
64
|
-
seen.add(browser.browserId);
|
|
65
|
-
if (!Array.isArray(browser.capabilities?.actions)) {
|
|
66
|
-
throw new Error(`Provider browser ${browser.browserId} needs an actions capability list`);
|
|
67
|
-
}
|
|
68
|
-
for (const action of browser.capabilities.actions) {
|
|
69
|
-
if (!isProviderAction(action)) {
|
|
70
|
-
throw new Error(`Unsupported provider capability action: ${String(action)}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (new Set(browser.capabilities.actions).size !== browser.capabilities.actions.length) {
|
|
74
|
-
throw new Error(`Provider browser ${browser.browserId} has duplicate capability actions`);
|
|
75
|
-
}
|
|
76
|
-
if (!['native', 'reconstructed', 'none'].includes(browser.capabilities.screenshot)) {
|
|
77
|
-
throw new Error(`Unsupported screenshot capability: ${browser.capabilities.screenshot}`);
|
|
78
|
-
}
|
|
79
|
-
const supportsScreenshot = browser.capabilities.actions.includes('page_screenshot');
|
|
80
|
-
if (supportsScreenshot === (browser.capabilities.screenshot === 'none')) {
|
|
81
|
-
throw new Error(`Provider browser ${browser.browserId} has inconsistent screenshot capabilities`);
|
|
82
|
-
}
|
|
83
|
-
if (browser.status !== undefined && !['connected', 'pairing'].includes(browser.status)) {
|
|
84
|
-
throw new Error(`Unsupported provider browser status: ${String(browser.status)}`);
|
|
85
|
-
}
|
|
86
|
-
assertPairing(browser.status, browser.pairing, browser.browserId);
|
|
87
|
-
if (browser.lastFocusedAt !== undefined &&
|
|
88
|
-
(!Number.isFinite(browser.lastFocusedAt) || browser.lastFocusedAt < 0)) {
|
|
89
|
-
throw new Error(`Provider browser ${browser.browserId} has invalid lastFocusedAt`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function providerBrowserId(requested) {
|
|
41
|
+
async function providerBrowserId(requested) {
|
|
94
42
|
if (requested)
|
|
95
43
|
return requested;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
44
|
+
const available = await runtime.listBrowsers();
|
|
45
|
+
if (available.length === 1)
|
|
46
|
+
return available[0].browserId;
|
|
47
|
+
if (available.length === 0)
|
|
48
|
+
throw new Error('Provider has no browser instances');
|
|
100
49
|
throw new Error('browserId is required when the provider has multiple browsers');
|
|
101
50
|
}
|
|
102
51
|
async function dispatch(request) {
|
|
103
52
|
if (request.action === 'browser_launch') {
|
|
104
53
|
if (request.browserId)
|
|
105
54
|
throw new Error('browser_launch does not accept browserId');
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
catch {
|
|
123
|
-
throw new Error('Provider returned an invalid browser creation result');
|
|
124
|
-
}
|
|
125
|
-
return created;
|
|
55
|
+
return runtime.launch(request.data ?? {}, { controlSource: request.controlSource });
|
|
56
|
+
}
|
|
57
|
+
if (request.action === 'browser_provider_configure') {
|
|
58
|
+
if (request.browserId)
|
|
59
|
+
throw new Error('Provider configuration does not accept browserId');
|
|
60
|
+
return runtime.configure(request.data ?? {}, { controlSource: request.controlSource });
|
|
61
|
+
}
|
|
62
|
+
if (request.action === 'browser_manager_start') {
|
|
63
|
+
return runtime.start({ browserId: await providerBrowserId(request.browserId) }, { controlSource: request.controlSource });
|
|
64
|
+
}
|
|
65
|
+
if (request.action === 'browser_manager_sync_cookies') {
|
|
66
|
+
return runtime.syncCookies({
|
|
67
|
+
browserId: await providerBrowserId(request.browserId),
|
|
68
|
+
scope: request.data?.scope,
|
|
69
|
+
}, { controlSource: request.controlSource });
|
|
126
70
|
}
|
|
127
71
|
if (request.action !== 'get_versions' &&
|
|
128
72
|
request.action !== 'browser_close' &&
|
|
73
|
+
request.action !== 'get_browser_access_url' &&
|
|
129
74
|
!isProviderAction(request.action)) {
|
|
130
75
|
throw new Error(`Unsupported provider action: ${String(request.action)}`);
|
|
131
76
|
}
|
|
132
|
-
const browserId = providerBrowserId(request.browserId);
|
|
133
|
-
const found = browsers.find(browser => browser.browserId === browserId);
|
|
134
|
-
if (!found)
|
|
135
|
-
throw new Error(`Provider browser not found: ${browserId}`);
|
|
77
|
+
const browserId = await providerBrowserId(request.browserId);
|
|
136
78
|
if (request.action === 'browser_close') {
|
|
137
|
-
return
|
|
79
|
+
return runtime.close({ browserId, deleteData: request.data?.deleteProfile === true }, { controlSource: request.controlSource });
|
|
80
|
+
}
|
|
81
|
+
if (request.action === 'get_browser_access_url') {
|
|
82
|
+
return {
|
|
83
|
+
browserAccess: await runtime.getAccess({ browserId }, { controlSource: request.controlSource }),
|
|
84
|
+
};
|
|
138
85
|
}
|
|
139
86
|
if (request.action === 'get_versions') {
|
|
87
|
+
const found = (await runtime.listBrowsers()).find(browser => browser.browserId === browserId);
|
|
88
|
+
if (!found)
|
|
89
|
+
throw new Error(`Provider browser not found: ${browserId}`);
|
|
140
90
|
return {
|
|
141
91
|
provider: {
|
|
142
|
-
|
|
143
|
-
name:
|
|
144
|
-
|
|
145
|
-
|
|
92
|
+
id: descriptor.providerId,
|
|
93
|
+
name: descriptor.name,
|
|
94
|
+
builtin: descriptor.builtin === true,
|
|
95
|
+
version: descriptor.version,
|
|
96
|
+
protocolVersion: descriptor.protocolVersion ?? MEARL_PROVIDER_PROTOCOL_VERSION,
|
|
146
97
|
},
|
|
147
|
-
capabilities: found.capabilities,
|
|
98
|
+
capabilities: found.control.kind === 'provider' ? found.control.capabilities : undefined,
|
|
148
99
|
};
|
|
149
100
|
}
|
|
150
|
-
if (
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
101
|
+
if (request.action === 'browser_release') {
|
|
102
|
+
const found = (await runtime.listBrowsers()).find(browser => browser.browserId === browserId);
|
|
103
|
+
if (found?.operations.includes('detach')) {
|
|
104
|
+
return runtime.detach({ browserId }, { controlSource: request.controlSource });
|
|
105
|
+
}
|
|
155
106
|
}
|
|
156
|
-
touchProviderBrowser(providerBrowserKey(
|
|
157
|
-
return
|
|
107
|
+
touchProviderBrowser(providerBrowserKey(descriptor.providerId, browserId));
|
|
108
|
+
return runtime.invokeAction({
|
|
158
109
|
browserId,
|
|
159
110
|
action: request.action,
|
|
160
111
|
data: request.data ?? {},
|
|
161
112
|
controlSource: request.controlSource,
|
|
162
113
|
});
|
|
163
114
|
}
|
|
164
|
-
function assertPairing(status, pairing, browserId) {
|
|
165
|
-
if (status === 'pairing' &&
|
|
166
|
-
(pairing?.kind !== 'qr' || typeof pairing.url !== 'string' || !pairing.url.trim())) {
|
|
167
|
-
throw new Error(`Pairing browser ${browserId} needs a pairing URL`);
|
|
168
|
-
}
|
|
169
|
-
if (status !== 'pairing' && pairing) {
|
|
170
|
-
throw new Error(`Pairing metadata requires status "pairing": ${browserId}`);
|
|
171
|
-
}
|
|
172
|
-
if (pairing &&
|
|
173
|
-
((pairing.code !== undefined && typeof pairing.code !== 'string') ||
|
|
174
|
-
(pairing.label !== undefined && typeof pairing.label !== 'string'))) {
|
|
175
|
-
throw new Error(`Provider browser ${browserId} has invalid pairing metadata`);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
115
|
function handleConnection(socket) {
|
|
179
116
|
connections.add(socket);
|
|
180
117
|
socket.once('close', () => connections.delete(socket));
|
|
@@ -216,22 +153,22 @@ export function createProviderServer(options) {
|
|
|
216
153
|
}
|
|
217
154
|
return {
|
|
218
155
|
socketPath,
|
|
156
|
+
runtime,
|
|
219
157
|
async start() {
|
|
220
158
|
if (state !== 'idle')
|
|
221
159
|
throw new Error(`Provider server is already ${state}`);
|
|
222
|
-
|
|
223
|
-
const providerId = options.descriptor.providerId;
|
|
160
|
+
const providerId = descriptor.providerId;
|
|
224
161
|
if (activeProviderIds.has(providerId)) {
|
|
225
162
|
throw new Error(`Provider ${providerId} is already running in this process`);
|
|
226
163
|
}
|
|
227
164
|
state = 'starting';
|
|
228
165
|
activeProviderIds.add(providerId);
|
|
229
166
|
const startToken = process.env[PROVIDER_START_TOKEN_ENV] || randomUUID();
|
|
230
|
-
const existing = readLiveProvider(
|
|
167
|
+
const existing = readLiveProvider(descriptor.providerId);
|
|
231
168
|
if (existing) {
|
|
232
169
|
state = 'idle';
|
|
233
170
|
activeProviderIds.delete(providerId);
|
|
234
|
-
throw new Error(`Provider ${
|
|
171
|
+
throw new Error(`Provider ${descriptor.providerId} is already running (pid ${existing.pid})`);
|
|
235
172
|
}
|
|
236
173
|
if (!claimProviderStart(providerId, startToken)) {
|
|
237
174
|
state = 'idle';
|
|
@@ -256,7 +193,7 @@ export function createProviderServer(options) {
|
|
|
256
193
|
});
|
|
257
194
|
if (process.platform !== 'win32')
|
|
258
195
|
chmodSync(socketPath, 0o600);
|
|
259
|
-
publishLiveProvider(
|
|
196
|
+
publishLiveProvider(descriptor, socketPath);
|
|
260
197
|
releaseProviderStart(providerId, startToken);
|
|
261
198
|
state = 'running';
|
|
262
199
|
}
|
|
@@ -281,9 +218,9 @@ export function createProviderServer(options) {
|
|
|
281
218
|
updateBrowsers(nextBrowsers) {
|
|
282
219
|
if (state !== 'running')
|
|
283
220
|
throw new Error('Provider server is not running');
|
|
284
|
-
|
|
221
|
+
runtime.updateBrowsers(nextBrowsers);
|
|
285
222
|
browsers = [...nextBrowsers];
|
|
286
|
-
browserIds = publishProviderBrowsers(
|
|
223
|
+
browserIds = publishProviderBrowsers(descriptor, socketPath, browsers, browserIds);
|
|
287
224
|
},
|
|
288
225
|
touchBrowser(browserId) {
|
|
289
226
|
if (state !== 'running')
|
|
@@ -291,7 +228,7 @@ export function createProviderServer(options) {
|
|
|
291
228
|
if (!browsers.some(browser => browser.browserId === browserId)) {
|
|
292
229
|
throw new Error(`Provider browser not found: ${browserId}`);
|
|
293
230
|
}
|
|
294
|
-
touchProviderBrowser(providerBrowserKey(
|
|
231
|
+
touchProviderBrowser(providerBrowserKey(descriptor.providerId, browserId));
|
|
295
232
|
},
|
|
296
233
|
async stop() {
|
|
297
234
|
if (state === 'idle')
|
|
@@ -314,9 +251,9 @@ export function createProviderServer(options) {
|
|
|
314
251
|
browsers = [];
|
|
315
252
|
if (process.platform !== 'win32')
|
|
316
253
|
rmSync(socketPath, { force: true });
|
|
317
|
-
unpublishLiveProvider(
|
|
254
|
+
unpublishLiveProvider(descriptor.providerId);
|
|
318
255
|
})().finally(() => {
|
|
319
|
-
activeProviderIds.delete(
|
|
256
|
+
activeProviderIds.delete(descriptor.providerId);
|
|
320
257
|
stopPromise = null;
|
|
321
258
|
state = 'idle';
|
|
322
259
|
});
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { ProviderAction } from './generated-provider-actions.js';
|
|
2
|
-
export declare const MEARL_PROVIDER_PROTOCOL_VERSION =
|
|
2
|
+
export declare const MEARL_PROVIDER_PROTOCOL_VERSION = 2;
|
|
3
3
|
export type { ProviderAction } from './generated-provider-actions.js';
|
|
4
|
+
export type JsonPrimitive = string | number | boolean | null;
|
|
5
|
+
export type JsonValue = JsonPrimitive | JsonValue[] | JsonObject;
|
|
6
|
+
export interface JsonObject {
|
|
7
|
+
[key: string]: JsonValue;
|
|
8
|
+
}
|
|
4
9
|
export type ProviderScreenshotKind = 'native' | 'reconstructed' | 'none';
|
|
5
10
|
export interface ProviderCapabilities {
|
|
6
11
|
actions: ProviderAction[];
|
|
@@ -17,27 +22,104 @@ export interface ProviderDescriptor {
|
|
|
17
22
|
name: string;
|
|
18
23
|
version: string;
|
|
19
24
|
protocolVersion?: number;
|
|
25
|
+
builtin?: boolean;
|
|
20
26
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
label: string;
|
|
24
|
-
required?: boolean;
|
|
25
|
-
placeholder?: string;
|
|
27
|
+
interface ProviderSchemaBase {
|
|
28
|
+
title?: string;
|
|
26
29
|
description?: string;
|
|
30
|
+
default?: JsonValue;
|
|
31
|
+
}
|
|
32
|
+
export interface ProviderStringSchema extends ProviderSchemaBase {
|
|
33
|
+
type: 'string';
|
|
34
|
+
secret?: boolean;
|
|
35
|
+
enum?: readonly string[];
|
|
36
|
+
minLength?: number;
|
|
37
|
+
maxLength?: number;
|
|
38
|
+
pattern?: string;
|
|
39
|
+
placeholder?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface ProviderNumberSchema extends ProviderSchemaBase {
|
|
42
|
+
type: 'number';
|
|
43
|
+
integer?: boolean;
|
|
44
|
+
minimum?: number;
|
|
45
|
+
maximum?: number;
|
|
46
|
+
}
|
|
47
|
+
export interface ProviderBooleanSchema extends ProviderSchemaBase {
|
|
48
|
+
type: 'boolean';
|
|
49
|
+
}
|
|
50
|
+
export interface ProviderArraySchema extends ProviderSchemaBase {
|
|
51
|
+
type: 'array';
|
|
52
|
+
items: ProviderInputSchema;
|
|
53
|
+
minItems?: number;
|
|
54
|
+
maxItems?: number;
|
|
55
|
+
}
|
|
56
|
+
export interface ProviderObjectSchema extends ProviderSchemaBase {
|
|
57
|
+
type: 'object';
|
|
58
|
+
properties: Record<string, ProviderInputSchema>;
|
|
59
|
+
required?: readonly string[];
|
|
60
|
+
oneOf?: readonly ProviderObjectSchema[];
|
|
61
|
+
not?: ProviderObjectSchema;
|
|
62
|
+
additionalProperties?: boolean;
|
|
63
|
+
}
|
|
64
|
+
export type ProviderInputSchema = ProviderStringSchema | ProviderNumberSchema | ProviderBooleanSchema | ProviderArraySchema | ProviderObjectSchema;
|
|
65
|
+
export interface ProviderConfigurationDefinition {
|
|
66
|
+
inputSchema: ProviderObjectSchema;
|
|
27
67
|
}
|
|
28
68
|
export interface ProviderBrowserType {
|
|
29
69
|
name: string;
|
|
30
|
-
|
|
70
|
+
documentationUrl?: string;
|
|
71
|
+
inputSchema: ProviderObjectSchema;
|
|
72
|
+
configuration?: ProviderConfigurationDefinition;
|
|
73
|
+
}
|
|
74
|
+
export type ProviderBrowserStatus = 'connected' | 'pairing' | 'running_disconnected' | 'stopped';
|
|
75
|
+
export type ProviderOwnership = 'owned' | 'attached';
|
|
76
|
+
export type ProviderPersistence = 'ephemeral' | 'persistent';
|
|
77
|
+
export type ProviderBrowserOperation = 'start' | 'close' | 'detach' | 'deleteData' | 'access' | 'syncCookies';
|
|
78
|
+
export type ProviderBrowserControl = {
|
|
79
|
+
kind: 'provider';
|
|
80
|
+
capabilities: ProviderCapabilities;
|
|
81
|
+
} | {
|
|
82
|
+
kind: 'host';
|
|
83
|
+
transport: 'extension' | 'cdp';
|
|
84
|
+
browserId: string;
|
|
85
|
+
capabilities?: ProviderCapabilities;
|
|
86
|
+
} | {
|
|
87
|
+
kind: 'none';
|
|
88
|
+
};
|
|
89
|
+
/** Common safe metadata; additional Provider-specific keys must also be non-secret JSON. */
|
|
90
|
+
export type ProviderBrowserDetails = JsonObject & {
|
|
91
|
+
headless?: boolean;
|
|
92
|
+
createdAt?: string;
|
|
93
|
+
cdpPort?: number;
|
|
94
|
+
account?: {
|
|
95
|
+
nickname: string;
|
|
96
|
+
accountId?: string;
|
|
97
|
+
loginId?: string;
|
|
98
|
+
};
|
|
99
|
+
copiedCookies?: {
|
|
100
|
+
domains: string[];
|
|
101
|
+
count: number;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
export interface ProviderBrowserReference {
|
|
105
|
+
kind: string;
|
|
106
|
+
id: string;
|
|
107
|
+
label?: string;
|
|
31
108
|
}
|
|
32
109
|
export interface ProviderBrowser {
|
|
33
|
-
/** Stable within this provider. Mearl
|
|
110
|
+
/** Stable within this provider. Mearl adds the Provider namespace globally. */
|
|
34
111
|
browserId: string;
|
|
35
112
|
name: string;
|
|
36
|
-
status
|
|
113
|
+
status: ProviderBrowserStatus;
|
|
114
|
+
control: ProviderBrowserControl;
|
|
115
|
+
ownership?: ProviderOwnership;
|
|
116
|
+
persistence: ProviderPersistence;
|
|
117
|
+
operations: ProviderBrowserOperation[];
|
|
37
118
|
lastFocusedAt?: number;
|
|
38
|
-
capabilities: ProviderCapabilities;
|
|
39
|
-
/** Pairing metadata is valid only while status is pairing. */
|
|
40
119
|
pairing?: ProviderPairingInfo;
|
|
120
|
+
references?: ProviderBrowserReference[];
|
|
121
|
+
/** Safe, non-secret metadata suitable for browser_list and remote connectors. */
|
|
122
|
+
details?: ProviderBrowserDetails;
|
|
41
123
|
}
|
|
42
124
|
export interface InstalledProviderManifest extends ProviderDescriptor {
|
|
43
125
|
protocolVersion: number;
|
|
@@ -56,7 +138,7 @@ export interface ProviderPackageMetadata {
|
|
|
56
138
|
export interface ProviderActionRequest {
|
|
57
139
|
id: string;
|
|
58
140
|
action: string;
|
|
59
|
-
data?:
|
|
141
|
+
data?: JsonObject;
|
|
60
142
|
/** Provider-local browser id selected by the Mearl client. */
|
|
61
143
|
browserId?: string;
|
|
62
144
|
version?: string;
|
|
@@ -65,32 +147,63 @@ export interface ProviderActionRequest {
|
|
|
65
147
|
export interface ProviderActionContext {
|
|
66
148
|
browserId: string;
|
|
67
149
|
action: ProviderAction;
|
|
68
|
-
data:
|
|
150
|
+
data: JsonObject;
|
|
69
151
|
controlSource?: string;
|
|
70
152
|
}
|
|
71
|
-
export
|
|
72
|
-
|
|
153
|
+
export interface ProviderHostServices {
|
|
154
|
+
request<T = JsonValue>(method: string, data?: JsonObject): Promise<T>;
|
|
155
|
+
}
|
|
156
|
+
export interface ProviderContext {
|
|
157
|
+
host?: ProviderHostServices;
|
|
158
|
+
controlSource?: string;
|
|
159
|
+
}
|
|
160
|
+
export interface ProviderInstanceRequest {
|
|
73
161
|
browserId: string;
|
|
74
|
-
name: string;
|
|
75
162
|
}
|
|
76
|
-
export
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
163
|
+
export interface ProviderCloseRequest extends ProviderInstanceRequest {
|
|
164
|
+
deleteData?: boolean;
|
|
165
|
+
}
|
|
166
|
+
export interface ProviderSyncCookiesRequest extends ProviderInstanceRequest {
|
|
167
|
+
scope: JsonObject;
|
|
168
|
+
}
|
|
169
|
+
export interface ProviderAccess {
|
|
170
|
+
kind: string;
|
|
171
|
+
url: string;
|
|
172
|
+
sensitive: true;
|
|
173
|
+
}
|
|
174
|
+
export interface BrowserProviderDefinition {
|
|
86
175
|
descriptor: ProviderDescriptor;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
176
|
+
browserType: ProviderBrowserType;
|
|
177
|
+
listBrowsers?: (context: ProviderContext) => ProviderBrowser[] | Promise<ProviderBrowser[]>;
|
|
178
|
+
launch: (options: JsonObject, context: ProviderContext) => Promise<ProviderBrowser>;
|
|
179
|
+
start?: (request: ProviderInstanceRequest, context: ProviderContext) => Promise<ProviderBrowser>;
|
|
180
|
+
close: (request: ProviderCloseRequest, context: ProviderContext) => Promise<unknown>;
|
|
181
|
+
detach?: (request: ProviderInstanceRequest, context: ProviderContext) => Promise<unknown>;
|
|
182
|
+
syncCookies?: (request: ProviderSyncCookiesRequest, context: ProviderContext) => Promise<unknown>;
|
|
183
|
+
getAccess?: (request: ProviderInstanceRequest, context: ProviderContext) => Promise<ProviderAccess>;
|
|
184
|
+
configure?: (options: JsonObject, context: ProviderContext) => Promise<unknown>;
|
|
185
|
+
handleAction?: (context: ProviderActionContext) => Promise<unknown>;
|
|
186
|
+
}
|
|
187
|
+
export interface ProviderRuntime {
|
|
188
|
+
readonly definition: BrowserProviderDefinition;
|
|
189
|
+
listBrowsers(context?: ProviderContext): Promise<ProviderBrowser[]>;
|
|
190
|
+
updateBrowsers(browsers: ProviderBrowser[]): void;
|
|
191
|
+
launch(options: JsonObject, context?: ProviderContext): Promise<ProviderBrowser>;
|
|
192
|
+
start(request: ProviderInstanceRequest, context?: ProviderContext): Promise<ProviderBrowser>;
|
|
193
|
+
close(request: ProviderCloseRequest, context?: ProviderContext): Promise<unknown>;
|
|
194
|
+
detach(request: ProviderInstanceRequest, context?: ProviderContext): Promise<unknown>;
|
|
195
|
+
syncCookies(request: ProviderSyncCookiesRequest, context?: ProviderContext): Promise<unknown>;
|
|
196
|
+
getAccess(request: ProviderInstanceRequest, context?: ProviderContext): Promise<ProviderAccess>;
|
|
197
|
+
configure(options: JsonObject, context?: ProviderContext): Promise<unknown>;
|
|
198
|
+
invokeAction(context: ProviderActionContext): Promise<unknown>;
|
|
199
|
+
}
|
|
200
|
+
export interface ProviderServerOptions {
|
|
201
|
+
definition: BrowserProviderDefinition;
|
|
90
202
|
socketPath?: string;
|
|
91
203
|
}
|
|
92
204
|
export interface ProviderServer {
|
|
93
205
|
readonly socketPath: string;
|
|
206
|
+
readonly runtime: ProviderRuntime;
|
|
94
207
|
start(): Promise<void>;
|
|
95
208
|
updateBrowsers(browsers: ProviderBrowser[]): void;
|
|
96
209
|
touchBrowser(browserId: string): void;
|
package/dist/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const MEARL_PROVIDER_PROTOCOL_VERSION =
|
|
1
|
+
export const MEARL_PROVIDER_PROTOCOL_VERSION = 2;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/provider",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.14.0",
|
|
4
|
+
"description": "Unified contracts and runtime utilities for built-in and external Mearl browser providers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"registry": "https://registry.npmjs.org"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@mearl/daemon-core": "2.
|
|
38
|
+
"@mearl/daemon-core": "2.14.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^24.9.1",
|