@mearl/client 3.0.0-beta.0 → 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 +333 -255
- package/README.zh-CN.md +612 -0
- package/dist/actionTimeouts.js +0 -3
- package/dist/autoUpdate.js +3 -1
- package/dist/bin.js +12 -5
- package/dist/capabilityHelp.d.ts +4 -0
- package/dist/capabilityHelp.js +68 -0
- package/dist/check.d.ts +5 -6
- package/dist/check.js +2 -5
- package/dist/cli.js +29 -56
- package/dist/commandHelp.d.ts +3 -0
- package/dist/commandHelp.js +79 -0
- package/dist/commandSuggestions.d.ts +3 -0
- package/dist/commandSuggestions.js +16 -5
- package/dist/commands.d.ts +70 -65
- package/dist/commands.js +60 -55
- package/dist/guide.d.ts +46 -0
- package/dist/guide.js +80 -0
- package/dist/guides/api-browser-setup.md +93 -0
- package/dist/guides/api-page-automation.md +140 -0
- package/dist/guides/api-page-debugging.md +39 -0
- package/dist/guides/api-page-environment.md +37 -0
- package/dist/guides/api-request-debugging.md +54 -0
- package/dist/guides/browser-tool-cooperation.md +23 -0
- package/dist/guides/core.md +60 -0
- package/dist/guides/related-skills.md +51 -0
- package/dist/guides/scripting.md +21 -0
- package/dist/guides/troubleshooting.md +170 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +8 -5
- package/dist/nativeHost.d.ts +2 -2
- package/dist/nativeHost.js +2 -4
- package/dist/plugins/clients/pluginHostConnection.d.ts +2 -0
- package/dist/plugins/clients/pluginHostConnection.js +3 -1
- package/dist/plugins/officialPluginInstaller.js +2 -1
- package/dist/plugins/pluginRegistry.d.ts +1 -1
- package/dist/plugins/pluginRegistry.js +21 -7
- package/dist/plugins/runtime/pluginCommandWorker.js +8 -6
- package/dist/plugins/runtime/pluginDiagnostics.js +1 -1
- package/dist/plugins/runtime/pluginExecutor.d.ts +5 -0
- package/dist/plugins/runtime/pluginExecutor.js +15 -2
- package/dist/plugins/runtime/pluginExecutorProtocol.d.ts +4 -0
- package/dist/plugins/runtime/pluginExecutorSupervisor.js +2 -1
- package/dist/plugins/runtime/pluginHostServer.js +5 -1
- package/dist/plugins/runtime/pluginPageManager.js +2 -6
- package/dist/plugins/runtime/pluginRevision.js +0 -51
- package/dist/plugins/runtime/pluginStateManager.js +1 -1
- package/dist/plugins/runtime/pluginStateStore.js +3 -8
- package/dist/plugins/runtime/pluginTaskManager.js +5 -9
- package/dist/plugins/sdk/plugin.d.ts +9 -0
- package/dist/plugins/sdk/plugin.js +22 -9
- package/dist/plugins/sdk/pluginModelDefinition.js +0 -6
- package/dist/plugins/sdk/pluginPageDefinition.d.ts +0 -1
- package/dist/plugins/sdk/pluginPageDefinition.js +2 -18
- package/dist/plugins/sdk/pluginRecoveryDefinition.js +0 -3
- package/dist/plugins/sdk/pluginStateDefinition.d.ts +0 -1
- package/dist/plugins/sdk/pluginStateDefinition.js +0 -11
- package/dist/runtimePaths.d.ts +1 -0
- package/dist/runtimePaths.js +1 -0
- package/dist/script.d.ts +30 -0
- package/dist/script.js +261 -0
- package/dist/scriptCli.d.ts +1 -0
- package/dist/scriptCli.js +94 -0
- package/dist/scriptErrors.d.ts +8 -0
- package/dist/scriptErrors.js +21 -0
- package/dist/scriptWorker.d.ts +1 -0
- package/dist/scriptWorker.js +50 -0
- package/dist/sdkMethods.d.ts +3 -0
- package/dist/sdkMethods.js +9 -0
- package/dist/socket.js +33 -8
- package/dist/unified.js +11 -1
- package/dist/unifiedConfig.d.ts +4 -0
- package/dist/unifiedConfig.js +11 -0
- package/package.json +18 -11
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export { UnifiedClient, UnifiedClient as MearlClient, decodeBrowserTarget, invok
|
|
|
13
13
|
export type { UnifiedClientOptions, UnifiedInvokeOptions, UnifiedInvokeOptions as InvokeOptions, } from './unified.js';
|
|
14
14
|
export type { PluginInvocation, PluginInvokeOptions, PluginProgress, StructuredPluginProgress, } from './plugins/sdk/plugin.js';
|
|
15
15
|
export { APP_PROFILE_NAMES, BROWSER_DEVICE_PRESET_NAMES, BROWSER_ACTIONS, BROWSER_CAPABILITY_ACTIONS, BROWSER_COMMAND_ACTIONS, EXTENSION_BROWSER_ACTIONS, PAGE_ACT_ACTIONS, SEND_REQUEST_MAX_FILES, SEND_REQUEST_MAX_TOTAL_BASE64_FILE_BYTES, SEND_REQUEST_MAX_TOTAL_FILE_BYTES, isBrowserAction, isBrowserCapabilityAction, isBrowserCommandAction, isExtensionBrowserAction, } from '@mearl/browser-core';
|
|
16
|
-
export type { ActionStep, AppProfileName, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCapabilities, BrowserCapabilityAction, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserJsonValue, BrowserLaunchParams, BrowserProviderOperation, BrowserListResult, BrowserPairingInfo, BrowserReleaseFailure, BrowserReleaseResult, BrowserProviderDefinition, BrowserProviderIdentity, BrowserProviderInputSchema, BrowserProviderListResult, BrowserReference, BrowserDetails, BrowserSource, BrowserStatus, BrowserScreenshotKind, BrowserTransport, CaptureCheckpointParams, CaptureCheckpointResult, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, ManagedBrowserInfo, PageClickParams, PageDragEndpoint, PageDragParams, PageDragPoint, PageActAction, PageDiagnosticsOptions, PageDiagnosticsSetting, PageEvalParams, PageFramesParams, PageHoverParams, PageInspectFilter, PageInspectParams, PageNavigateParams, PageObservationWaitOptions, PagePressParams, PageScreenshotParams, PageScrollParams, PageSnapshotParams, PageSnapshotQuery, PageTypeParams, PageUploadParams, PageWaitParams, RegularBrowserInfo,
|
|
16
|
+
export type { ActionStep, AppProfileName, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCapabilities, BrowserCapabilityAction, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserJsonValue, BrowserLaunchParams, BrowserProviderOperation, BrowserListResult, BrowserListParams, BrowserPairingInfo, BrowserReleaseFailure, BrowserReleaseResult, BrowserProviderDefinition, BrowserProviderIdentity, BrowserProviderInputSchema, BrowserProviderListResult, BrowserReference, BrowserDetails, BrowserSource, BrowserStatus, BrowserScreenshotKind, BrowserTransport, CaptureCheckpointParams, CaptureCheckpointResult, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, ManagedBrowserInfo, PageClickParams, PageDragEndpoint, PageDragParams, PageDragPoint, PageActAction, PageDiagnosticsOptions, PageDiagnosticsSetting, PageEvalParams, PageFramesParams, PageHoverParams, PageInspectFilter, PageInspectParams, PageNavigateParams, PageObservationWaitOptions, PagePressParams, PageScreenshotParams, PageScrollParams, PageSnapshotParams, PageSnapshotQuery, PageTypeParams, PageUploadParams, PageWaitParams, RegularBrowserInfo, RequestPermissionParams, RulesResult, RunActionName, RunActionsParams, SelectBrowserParams, SelectBrowserResult, SendRequestFile, SendRequestBinaryBody, SendRequestFormValue, SendRequestParams, SetAppProfileParams, SetCookieParams, SetCookieResult, SetDeviceEmulationParams, SetMockParams, SetRuleParams, SetTimezoneParams, SetTimezoneResult, TabCloseParams, TabOpenParams, } from '@mearl/browser-core';
|
|
17
17
|
import { type UnifiedInvokeOptions } from './unified.js';
|
|
18
18
|
import type * as Protocol from '@mearl/browser-core';
|
|
19
19
|
export declare function tabCheckpoint(params: Protocol.CaptureCheckpointParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_checkpoint'>>;
|
|
@@ -25,8 +25,8 @@ export declare function getEvents(params: Protocol.GetEventsParams, options?: Un
|
|
|
25
25
|
export declare function setMock(params: Protocol.SetMockParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'set_mock'>>;
|
|
26
26
|
export declare function getMocks(params: Protocol.GetMocksParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'get_mocks'>>;
|
|
27
27
|
export declare function sendRequest(params: Protocol.SendRequestParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'send_request'>>;
|
|
28
|
-
export declare function sendMtopRequest(params: Protocol.SendMtopRequestParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'send_mtop_request'>>;
|
|
29
28
|
export declare function browserList(options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'browser_list'>>;
|
|
29
|
+
export declare function browserList(params: Protocol.BrowserListParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'browser_list'>>;
|
|
30
30
|
export declare function selectBrowser(params?: Protocol.SelectBrowserParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'browser_select_browser'>>;
|
|
31
31
|
export declare function browserRelease(options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'browser_release'>>;
|
|
32
32
|
export declare function browserRelease(params: Protocol.BrowserReleaseParams, options: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'browser_release'>>;
|
|
@@ -37,6 +37,7 @@ export declare function getRules(options?: UnifiedInvokeOptions): Promise<Protoc
|
|
|
37
37
|
export declare function pageScreenshot(params: Protocol.PageScreenshotParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_screenshot'>>;
|
|
38
38
|
export declare function tabOpen(params: Protocol.TabOpenParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_open'>>;
|
|
39
39
|
export declare function tabClose(params: Protocol.TabCloseParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_close'>>;
|
|
40
|
+
export declare function getCapabilities(params?: Protocol.GetCapabilitiesParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'get_capabilities'>>;
|
|
40
41
|
export declare function tabList(options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_list'>>;
|
|
41
42
|
export declare function tabGroup(params: Protocol.TabGroupParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_group'>>;
|
|
42
43
|
export declare function pageClick(params: Protocol.PageClickParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'page_click'>>;
|
|
@@ -69,3 +70,5 @@ export declare function saveArtifact(artifact: Protocol.BrowserArtifact & {
|
|
|
69
70
|
export { PluginStateClient } from './plugins/clients/pluginState.js';
|
|
70
71
|
export { PluginModelClient } from './plugins/clients/pluginModels.js';
|
|
71
72
|
export type * from '@mearl/browser-core';
|
|
73
|
+
export { getStructure as structure, type StructureOptions } from '@mearl/browser-core';
|
|
74
|
+
export type { GetCapabilitiesParams, BrowserCapabilityCatalog, AppCapability, AppProfileUsage } from '@mearl/browser-core';
|
package/dist/index.js
CHANGED
|
@@ -36,11 +36,10 @@ export function getMocks(params, options) {
|
|
|
36
36
|
export function sendRequest(params, options) {
|
|
37
37
|
return invoke('send_request', params, options);
|
|
38
38
|
}
|
|
39
|
-
export function
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return invoke('browser_list', {}, options);
|
|
39
|
+
export function browserList(paramsOrOptions = {}, options) {
|
|
40
|
+
return 'provider' in paramsOrOptions || 'launchForm' in paramsOrOptions
|
|
41
|
+
? invoke('browser_list', paramsOrOptions, options)
|
|
42
|
+
: invoke('browser_list', {}, paramsOrOptions);
|
|
44
43
|
}
|
|
45
44
|
export function selectBrowser(params = {}, options) {
|
|
46
45
|
return invoke('browser_select_browser', params, options);
|
|
@@ -71,6 +70,9 @@ export function tabOpen(params, options) {
|
|
|
71
70
|
export function tabClose(params, options) {
|
|
72
71
|
return invoke('tab_close', params, options);
|
|
73
72
|
}
|
|
73
|
+
export function getCapabilities(params = {}, options) {
|
|
74
|
+
return invoke('get_capabilities', params, options);
|
|
75
|
+
}
|
|
74
76
|
export function tabList(options) {
|
|
75
77
|
return invoke('tab_list', {}, options);
|
|
76
78
|
}
|
|
@@ -146,3 +148,4 @@ export async function saveArtifact(artifact, outputPath, options = {}) {
|
|
|
146
148
|
}
|
|
147
149
|
export { PluginStateClient } from './plugins/clients/pluginState.js';
|
|
148
150
|
export { PluginModelClient } from './plugins/clients/pluginModels.js';
|
|
151
|
+
export { getStructure as structure } from '@mearl/browser-core';
|
package/dist/nativeHost.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import { MEARL_NATIVE_HOST_NAMES, type NativeHostIntegrationMode } from '@mearl/browser-core';
|
|
2
|
+
export { MEARL_NATIVE_HOST_NAMES, type NativeHostIntegrationMode };
|
|
3
3
|
export interface NativeHostDirectoryOptions {
|
|
4
4
|
env?: NodeJS.ProcessEnv;
|
|
5
5
|
homedir?: () => string;
|
package/dist/nativeHost.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
mcp: 'com.alibaba.mearl.mcp',
|
|
7
|
-
};
|
|
4
|
+
import { MEARL_NATIVE_HOST_NAMES } from '@mearl/browser-core';
|
|
5
|
+
export { MEARL_NATIVE_HOST_NAMES };
|
|
8
6
|
export function resolveNativeHostDirectory(options = {}) {
|
|
9
7
|
const env = options.env ?? process.env;
|
|
10
8
|
const home = (options.homedir ?? os.homedir)();
|
|
@@ -243,7 +243,9 @@ export class PluginHostConnection {
|
|
|
243
243
|
this.connection = undefined;
|
|
244
244
|
});
|
|
245
245
|
}
|
|
246
|
-
|
|
246
|
+
const connection = await this.connection;
|
|
247
|
+
// The handshake protocol defines compatibility; build identity is diagnostic metadata.
|
|
248
|
+
return connection.request(method, input, timeoutMs);
|
|
247
249
|
}
|
|
248
250
|
disconnect() {
|
|
249
251
|
this.generation++;
|
|
@@ -2,6 +2,7 @@ import { closeSync, mkdirSync, openSync, rmSync, statSync, writeFileSync } from
|
|
|
2
2
|
import { CLIENT_VERSION } from '../runtimePaths.js';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { spawn } from 'node:child_process';
|
|
5
|
+
import { npmExecEnvironment } from '@mearl/daemon-core';
|
|
5
6
|
import { findOfficialPlugin, readOfficialPluginCatalog } from './officialPluginCatalog.js';
|
|
6
7
|
import { findPluginRegistration, pluginDirectory } from './pluginRegistry.js';
|
|
7
8
|
const INSTALL_TIMEOUT_MS = 180_000;
|
|
@@ -60,7 +61,7 @@ function appendOutput(current, chunk) {
|
|
|
60
61
|
function installWithSetup(name) {
|
|
61
62
|
return new Promise((resolve, reject) => {
|
|
62
63
|
const command = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
63
|
-
const child = spawn(command, ['-y', `@mearl/setup@${CLIENT_VERSION}`, 'plugin', 'ensure', name], { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
|
|
64
|
+
const child = spawn(command, ['-y', '--@mearl:registry=https://registry.npmjs.org', `@mearl/setup@${CLIENT_VERSION}`, 'plugin', 'ensure', name], { env: npmExecEnvironment(), stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
|
|
64
65
|
let stdout = '';
|
|
65
66
|
let stderr = '';
|
|
66
67
|
let settled = false;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AppProfileContribution } from '@mearl/browser-core';
|
|
2
2
|
export declare class PluginError extends Error {
|
|
3
3
|
readonly code: string;
|
|
4
|
-
constructor(code: string, message: string);
|
|
4
|
+
constructor(code: string, message: string, options?: ErrorOptions);
|
|
5
5
|
}
|
|
6
6
|
export interface PluginToolboxSandboxPage {
|
|
7
7
|
type: 'sandbox';
|
|
@@ -8,17 +8,24 @@ import { COMMAND_MAP } from '../commands.js';
|
|
|
8
8
|
import { buildPluginPageBundle, PLUGIN_PAGE_CHUNK_BYTES, PLUGIN_PAGE_RUNTIME_HASH, } from './pluginPageBundle.js';
|
|
9
9
|
import { pluginFileVersion } from './pluginSource.js';
|
|
10
10
|
const RESERVED_NAMES = new Set([
|
|
11
|
+
'guide',
|
|
11
12
|
'check',
|
|
13
|
+
'run',
|
|
12
14
|
'help',
|
|
13
15
|
'connector_list',
|
|
14
16
|
'capture_checkpoint',
|
|
15
17
|
'plugin',
|
|
16
18
|
'plugins',
|
|
19
|
+
'plugin_state',
|
|
20
|
+
'plugin_model',
|
|
21
|
+
'plugin_page',
|
|
22
|
+
'plugin_invoke_child',
|
|
23
|
+
'plugin_task_checkpoint',
|
|
17
24
|
]);
|
|
18
25
|
export class PluginError extends Error {
|
|
19
26
|
code;
|
|
20
|
-
constructor(code, message) {
|
|
21
|
-
super(`${code}: ${message}
|
|
27
|
+
constructor(code, message, options) {
|
|
28
|
+
super(`${code}: ${message}`, options);
|
|
22
29
|
this.code = code;
|
|
23
30
|
}
|
|
24
31
|
}
|
|
@@ -110,7 +117,7 @@ function persistPluginPageBundle(name, bundle) {
|
|
|
110
117
|
}
|
|
111
118
|
}
|
|
112
119
|
export function assertPluginName(name) {
|
|
113
|
-
if (!/^[a-z][a-z0-
|
|
120
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(name) || RESERVED_NAMES.has(name) || COMMAND_MAP.has(name)) {
|
|
114
121
|
throw new PluginError('PLUGIN_INVALID_NAME', `不可用的插件名称: ${name}`);
|
|
115
122
|
}
|
|
116
123
|
}
|
|
@@ -345,7 +352,7 @@ export function unregisterPlugin(name) {
|
|
|
345
352
|
}
|
|
346
353
|
}
|
|
347
354
|
export function findPluginRegistration(name) {
|
|
348
|
-
if (!/^[a-z][a-z0-
|
|
355
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(name))
|
|
349
356
|
return undefined;
|
|
350
357
|
const file = join(pluginDirectory(), `${name}.json`);
|
|
351
358
|
let content;
|
|
@@ -405,8 +412,15 @@ export function findPluginRegistration(name) {
|
|
|
405
412
|
...(source ? { source } : {}),
|
|
406
413
|
};
|
|
407
414
|
}
|
|
408
|
-
catch {
|
|
409
|
-
|
|
415
|
+
catch (cause) {
|
|
416
|
+
const reason = cause instanceof SyntaxError
|
|
417
|
+
? 'JSON 格式错误'
|
|
418
|
+
: cause instanceof Error
|
|
419
|
+
? cause.message
|
|
420
|
+
: '未知校验错误';
|
|
421
|
+
throw new PluginError('PLUGIN_REGISTRY_INVALID', `无效的插件记录: ${file} (${reason})`, {
|
|
422
|
+
cause,
|
|
423
|
+
});
|
|
410
424
|
}
|
|
411
425
|
}
|
|
412
426
|
export function readPluginPageBundleChunk(name, hash, index) {
|
|
@@ -462,7 +476,7 @@ export function findPluginEntry(name) {
|
|
|
462
476
|
export function listPluginNames() {
|
|
463
477
|
try {
|
|
464
478
|
return readdirSync(pluginDirectory())
|
|
465
|
-
.filter(file => /^[a-z][a-z0-
|
|
479
|
+
.filter(file => /^[a-z][a-z0-9_-]*\.json$/.test(file))
|
|
466
480
|
.map(file => file.slice(0, -5))
|
|
467
481
|
.sort();
|
|
468
482
|
}
|
|
@@ -31,7 +31,7 @@ async function run(message) {
|
|
|
31
31
|
: message.access === 'toolbox'
|
|
32
32
|
? invokeRegisteredToolboxPlugin
|
|
33
33
|
: invokeRegisteredPlugin;
|
|
34
|
-
const declaration = message.describe
|
|
34
|
+
const declaration = message.describe || message.help
|
|
35
35
|
? await loadPlugin(message.entry, {
|
|
36
36
|
options: {},
|
|
37
37
|
progress: () => { },
|
|
@@ -63,11 +63,13 @@ async function run(message) {
|
|
|
63
63
|
const value = migration
|
|
64
64
|
? await migration.runMigration(message.invocation)
|
|
65
65
|
: declaration
|
|
66
|
-
?
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
? message.help
|
|
67
|
+
? declaration.help(message.help.namespace, message.help.command)
|
|
68
|
+
: {
|
|
69
|
+
pageRuntime: declaration.pageRuntime,
|
|
70
|
+
stateStorage: declaration.stateStorage,
|
|
71
|
+
taskRecovery: declaration.taskRecovery,
|
|
72
|
+
}
|
|
71
73
|
: message.model
|
|
72
74
|
? await (await import('@mearl/agent-runtime/codex')).runCodexModel(message.model, {
|
|
73
75
|
signal: controller.signal,
|
|
@@ -26,7 +26,7 @@ export function normalizeDiagnosticOptions(value) {
|
|
|
26
26
|
throw new Error('Invalid diagnostic instance ID');
|
|
27
27
|
if (input.plugin !== undefined &&
|
|
28
28
|
(typeof input.plugin !== 'string' ||
|
|
29
|
-
!/^[a-z][a-z0-
|
|
29
|
+
!/^[a-z][a-z0-9_-]*$/.test(input.plugin) ||
|
|
30
30
|
input.plugin.length > 128))
|
|
31
31
|
throw new Error('Invalid diagnostic plugin');
|
|
32
32
|
for (const key of ['includeErrorMessages', 'includeLocalPaths'])
|
|
@@ -6,6 +6,11 @@ export interface PluginExecutorDependencies {
|
|
|
6
6
|
registration?: PluginRegistration;
|
|
7
7
|
}
|
|
8
8
|
export interface PluginExecutorOptions extends PluginInvokeOptions {
|
|
9
|
+
help?: {
|
|
10
|
+
namespace: string;
|
|
11
|
+
command?: string;
|
|
12
|
+
};
|
|
13
|
+
onOutput?: (stream: 'stdout' | 'stderr', chunk: Buffer) => void;
|
|
9
14
|
describe?: boolean;
|
|
10
15
|
model?: PluginModelRequest;
|
|
11
16
|
recovery?: boolean;
|
|
@@ -8,7 +8,7 @@ import { stopPluginProcessTree } from './pluginProcessTree.js';
|
|
|
8
8
|
import { processIdentity } from '@mearl/daemon-core';
|
|
9
9
|
/** Executes registered trusted code in a process whose lifetime belongs to this invocation. */
|
|
10
10
|
export async function executeRegisteredPlugin(plugin, invocation, context, options = {}, dependencies = {}) {
|
|
11
|
-
const { signal, onProgress, source, access = 'public', executionTimeoutMs, cancellationGraceMs = 1000, workerPath, cwd, environment, describe, model, recovery, migration, expectedRecovery, onExecutorStarted, onExecutorStopped, onDiagnostic, ...invokeOptions } = options;
|
|
11
|
+
const { signal, onProgress, source, access = 'public', executionTimeoutMs, cancellationGraceMs = 1000, workerPath, cwd, environment, describe, help, onOutput, model, recovery, migration, expectedRecovery, onExecutorStarted, onExecutorStopped, onDiagnostic, ...invokeOptions } = options;
|
|
12
12
|
for (const [name, value] of [
|
|
13
13
|
['executionTimeoutMs', executionTimeoutMs],
|
|
14
14
|
['cancellationGraceMs', cancellationGraceMs],
|
|
@@ -25,7 +25,7 @@ export async function executeRegisteredPlugin(plugin, invocation, context, optio
|
|
|
25
25
|
const entryVersion = pluginFileVersion(registration.entry);
|
|
26
26
|
return new Promise((resolve, reject) => {
|
|
27
27
|
const child = fork(workerPath ?? PLUGIN_WORKER_PATH, [], {
|
|
28
|
-
stdio: ['ignore', 'ignore', 'pipe', 'ipc'],
|
|
28
|
+
stdio: ['ignore', onOutput ? 'pipe' : 'ignore', 'pipe', 'ipc'],
|
|
29
29
|
serialization: 'advanced',
|
|
30
30
|
execArgv: [],
|
|
31
31
|
detached: process.platform !== 'win32',
|
|
@@ -46,6 +46,18 @@ export async function executeRegisteredPlugin(plugin, invocation, context, optio
|
|
|
46
46
|
child.stderr?.on('data', chunk => {
|
|
47
47
|
stderr = `${stderr}${chunk}`.slice(-65536);
|
|
48
48
|
});
|
|
49
|
+
if (onOutput) {
|
|
50
|
+
for (const stream of ['stdout', 'stderr']) {
|
|
51
|
+
child[stream]?.on('data', chunk => {
|
|
52
|
+
try {
|
|
53
|
+
onOutput(stream, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
stop(error instanceof Error ? error : new Error(String(error)));
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
49
61
|
const send = (message) => {
|
|
50
62
|
if (!child.connected || exited)
|
|
51
63
|
return;
|
|
@@ -209,6 +221,7 @@ export async function executeRegisteredPlugin(plugin, invocation, context, optio
|
|
|
209
221
|
entryVersion,
|
|
210
222
|
access,
|
|
211
223
|
describe,
|
|
224
|
+
help,
|
|
212
225
|
model,
|
|
213
226
|
recovery,
|
|
214
227
|
migration,
|
|
@@ -13,6 +13,10 @@ export type PluginWorkerRequest = {
|
|
|
13
13
|
access: 'public' | 'toolbox' | 'runtime';
|
|
14
14
|
registration?: PluginRegistration;
|
|
15
15
|
describe?: boolean;
|
|
16
|
+
help?: {
|
|
17
|
+
namespace: string;
|
|
18
|
+
command?: string;
|
|
19
|
+
};
|
|
16
20
|
model?: PluginModelRequest;
|
|
17
21
|
recovery?: boolean;
|
|
18
22
|
migration?: boolean;
|
|
@@ -3,13 +3,14 @@ import { fileURLToPath } from 'node:url';
|
|
|
3
3
|
/** Ownership monitoring runs outside the event loop that executes plugin code. */
|
|
4
4
|
export function supervisePluginExecutor(workerUrl) {
|
|
5
5
|
const child = fork(fileURLToPath(workerUrl), ['--command'], {
|
|
6
|
-
stdio: ['ignore', '
|
|
6
|
+
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
|
|
7
7
|
serialization: 'advanced',
|
|
8
8
|
execArgv: [],
|
|
9
9
|
});
|
|
10
10
|
let ending = false;
|
|
11
11
|
let forwarded = Promise.resolve();
|
|
12
12
|
child.stderr?.on('data', chunk => process.stderr.write(chunk));
|
|
13
|
+
child.stdout?.on('data', chunk => process.stdout.write(chunk));
|
|
13
14
|
const terminate = () => {
|
|
14
15
|
if (process.platform === 'win32') {
|
|
15
16
|
try {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CLIENT_VERSION } from '../../runtimePaths.js';
|
|
1
2
|
import { randomUUID } from 'node:crypto';
|
|
2
3
|
import { createServer } from 'node:net';
|
|
3
4
|
import { chmodSync, rmSync } from 'node:fs';
|
|
@@ -17,6 +18,7 @@ export async function startPluginHostServer(configuration = {}) {
|
|
|
17
18
|
const owner = {
|
|
18
19
|
pid: process.pid,
|
|
19
20
|
protocolVersion: PLUGIN_TASK_PROTOCOL_VERSION,
|
|
21
|
+
version: CLIENT_VERSION,
|
|
20
22
|
processIdentity: processIdentity(process.pid),
|
|
21
23
|
};
|
|
22
24
|
if (!claimRecord(paths.lease, owner))
|
|
@@ -89,7 +91,7 @@ export async function startPluginHostServer(configuration = {}) {
|
|
|
89
91
|
!['service', 'caller'].includes(String(input.bridge)) ||
|
|
90
92
|
!['cli', 'sdk', 'mcp', 'toolbox', 'runtime'].includes(String(input.source)) ||
|
|
91
93
|
(input.plugin !== undefined &&
|
|
92
|
-
(typeof input.plugin !== 'string' || !/^[a-z][a-z0-
|
|
94
|
+
(typeof input.plugin !== 'string' || !/^[a-z][a-z0-9_-]*$/.test(input.plugin))) ||
|
|
93
95
|
(input.scopeId !== undefined &&
|
|
94
96
|
(typeof input.scopeId !== 'string' || input.scopeId.length > 256)) ||
|
|
95
97
|
(input.access !== 'public' && (!input.plugin || input.bridge !== 'caller')))
|
|
@@ -103,6 +105,7 @@ export async function startPluginHostServer(configuration = {}) {
|
|
|
103
105
|
};
|
|
104
106
|
return {
|
|
105
107
|
protocolVersion: PLUGIN_TASK_PROTOCOL_VERSION,
|
|
108
|
+
version: CLIENT_VERSION,
|
|
106
109
|
host: manager.host,
|
|
107
110
|
pid: process.pid,
|
|
108
111
|
};
|
|
@@ -112,6 +115,7 @@ export async function startPluginHostServer(configuration = {}) {
|
|
|
112
115
|
if (method === 'status')
|
|
113
116
|
return {
|
|
114
117
|
protocolVersion: PLUGIN_TASK_PROTOCOL_VERSION,
|
|
118
|
+
version: CLIENT_VERSION,
|
|
115
119
|
host: manager.host,
|
|
116
120
|
pid: process.pid,
|
|
117
121
|
};
|
|
@@ -5,7 +5,6 @@ import { readFileSync, statSync } from 'node:fs';
|
|
|
5
5
|
import { isAbsolute, join } from 'node:path';
|
|
6
6
|
import { capturePluginRevision } from './pluginRevision.js';
|
|
7
7
|
import { findPluginRegistration } from '../sdk/plugin.js';
|
|
8
|
-
import { compilePluginPageSchema } from '../sdk/pluginPageDefinition.js';
|
|
9
8
|
import { UnifiedClient, decodeBrowserTarget } from '../../unified.js';
|
|
10
9
|
import { pluginHostPaths } from './pluginHostPaths.js';
|
|
11
10
|
import { serializePluginExecutionError, pluginExecutionError } from './pluginExecutorProtocol.js';
|
|
@@ -273,7 +272,7 @@ export class PluginPageManager {
|
|
|
273
272
|
execution.signal?.throwIfAborted();
|
|
274
273
|
if (!input || typeof input !== 'object' || Array.isArray(input))
|
|
275
274
|
throw new Error('Invalid plugin page request');
|
|
276
|
-
if (!/^[a-z][a-z0-
|
|
275
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(plugin) ||
|
|
277
276
|
(bridge.scope.plugin && bridge.scope.plugin !== plugin))
|
|
278
277
|
throw new Error('Invalid plugin page scope');
|
|
279
278
|
const operation = input.operation;
|
|
@@ -657,7 +656,7 @@ export class PluginPageManager {
|
|
|
657
656
|
async receive(plugin, input, bridge, options = {}) {
|
|
658
657
|
if (input.kind === 'sync') {
|
|
659
658
|
if (this.closed ||
|
|
660
|
-
!/^[a-z][a-z0-
|
|
659
|
+
!/^[a-z][a-z0-9_-]*$/.test(plugin) ||
|
|
661
660
|
(bridge.scope.plugin && bridge.scope.plugin !== plugin) ||
|
|
662
661
|
!Array.isArray(input.instances) ||
|
|
663
662
|
input.instances.length > 32)
|
|
@@ -726,9 +725,6 @@ export class PluginPageManager {
|
|
|
726
725
|
const binding = record.runtime.events?.[name];
|
|
727
726
|
if (!binding || Buffer.byteLength(JSON.stringify(input.payload ?? null)) > 32 * 1024)
|
|
728
727
|
throw new Error('Page event is not declared or exceeds 32 KiB');
|
|
729
|
-
const validate = compilePluginPageSchema(binding.schema);
|
|
730
|
-
if (!validate(input.payload))
|
|
731
|
-
throw failure('PLUGIN_PAGE_EVENT_INVALID', 'Page event payload does not match its schema');
|
|
732
728
|
const waiting = record.deliveries.filter(item => item.name === name && item.state === 'queued');
|
|
733
729
|
if (binding.policy === 'latest') {
|
|
734
730
|
for (const previous of waiting) {
|
|
@@ -2,13 +2,10 @@ import { createHash, randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
3
3
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
4
4
|
import { claimRecord, readRecord, writeRecord } from '@mearl/daemon-core';
|
|
5
|
-
import { isBuiltin } from 'node:module';
|
|
6
|
-
import { parse } from 'acorn';
|
|
7
5
|
import { pluginHostPaths } from './pluginHostPaths.js';
|
|
8
6
|
import { skillManifestPath } from '../skillManifest.js';
|
|
9
7
|
import { findPluginRegistration, PluginError } from '../pluginRegistry.js';
|
|
10
8
|
const MAX_REVISION_BYTES = 64 * 1024 * 1024;
|
|
11
|
-
const validatedSources = new Set();
|
|
12
9
|
function within(root, file) {
|
|
13
10
|
const path = relative(root, file);
|
|
14
11
|
return path === '' || (!path.startsWith(`..${sep}`) && path !== '..' && !isAbsolute(path));
|
|
@@ -68,48 +65,6 @@ function readSources(root) {
|
|
|
68
65
|
visit(root, new Set());
|
|
69
66
|
return files;
|
|
70
67
|
}
|
|
71
|
-
function validateDependencies(files) {
|
|
72
|
-
const paths = new Set(files.map(file => file.path));
|
|
73
|
-
for (const file of files) {
|
|
74
|
-
if (!/\.[cm]?js$/.test(file.path))
|
|
75
|
-
continue;
|
|
76
|
-
const tree = parse(file.bytes.toString('utf8'), {
|
|
77
|
-
ecmaVersion: 'latest',
|
|
78
|
-
sourceType: 'module',
|
|
79
|
-
allowReturnOutsideFunction: true,
|
|
80
|
-
});
|
|
81
|
-
const check = (specifier) => {
|
|
82
|
-
if (typeof specifier !== 'string' || isBuiltin(specifier))
|
|
83
|
-
return;
|
|
84
|
-
if (!specifier.startsWith('./') && !specifier.startsWith('../'))
|
|
85
|
-
throw new PluginError('PLUGIN_SOURCE_NOT_SELF_CONTAINED', `后台任务需要自包含 Skill,请先打包依赖: ${file.path}: ${specifier}`);
|
|
86
|
-
const local = resolve('/source', dirname(file.path), specifier);
|
|
87
|
-
const normalized = relative('/source', local).split(sep).join('/');
|
|
88
|
-
if (!within('/source', local) ||
|
|
89
|
-
![normalized, `${normalized}.js`, `${normalized}.json`, `${normalized}/index.js`].some(path => paths.has(path)))
|
|
90
|
-
throw new PluginError('PLUGIN_SOURCE_NOT_SELF_CONTAINED', `依赖不在 Skill 快照中: ${file.path}: ${specifier}`);
|
|
91
|
-
};
|
|
92
|
-
const visit = (node) => {
|
|
93
|
-
if (!node || typeof node !== 'object')
|
|
94
|
-
return;
|
|
95
|
-
if (['ImportDeclaration', 'ExportNamedDeclaration', 'ExportAllDeclaration'].includes(node.type))
|
|
96
|
-
check(node.source?.value);
|
|
97
|
-
if (node.type === 'ImportExpression')
|
|
98
|
-
check(node.source?.value);
|
|
99
|
-
if (node.type === 'CallExpression' &&
|
|
100
|
-
node.callee?.type === 'Identifier' &&
|
|
101
|
-
node.callee.name === 'require')
|
|
102
|
-
check(node.arguments[0]?.value);
|
|
103
|
-
for (const value of Object.values(node)) {
|
|
104
|
-
if (Array.isArray(value))
|
|
105
|
-
value.forEach(visit);
|
|
106
|
-
else if (value && typeof value === 'object')
|
|
107
|
-
visit(value);
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
visit(tree);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
68
|
function fingerprint(files, entry) {
|
|
114
69
|
return createHash('sha256')
|
|
115
70
|
.update(JSON.stringify({ entry, files: files.map(file => [file.path, file.hash, file.executable]) }))
|
|
@@ -139,12 +94,6 @@ export function capturePluginRevision(plugin) {
|
|
|
139
94
|
const relativeEntry = relative(root, entry).split(sep).join('/');
|
|
140
95
|
const files = readSources(root);
|
|
141
96
|
const revision = fingerprint(files, relativeEntry);
|
|
142
|
-
if (!validatedSources.has(revision)) {
|
|
143
|
-
validateDependencies(files);
|
|
144
|
-
if (validatedSources.size >= 64)
|
|
145
|
-
validatedSources.delete(validatedSources.values().next().value);
|
|
146
|
-
validatedSources.add(revision);
|
|
147
|
-
}
|
|
148
97
|
const revisionRoot = join(paths.revisions, installation.installationId, revision);
|
|
149
98
|
if (!existsSync(revisionRoot)) {
|
|
150
99
|
const temporary = `${revisionRoot}.${randomUUID()}.tmp`;
|
|
@@ -29,7 +29,7 @@ export class PluginStateManager {
|
|
|
29
29
|
async call(plugin, input, bridge, options = {}, binding) {
|
|
30
30
|
this.controller.signal.throwIfAborted();
|
|
31
31
|
binding?.signal?.throwIfAborted();
|
|
32
|
-
if (!/^[a-z][a-z0-
|
|
32
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(plugin) ||
|
|
33
33
|
(bridge.scope.plugin && bridge.scope.plugin !== plugin) ||
|
|
34
34
|
!input ||
|
|
35
35
|
typeof input !== 'object' ||
|
|
@@ -3,7 +3,6 @@ import { existsSync, readFileSync, readdirSync, statSync, rmSync } from 'node:fs
|
|
|
3
3
|
import { join, sep } from 'node:path';
|
|
4
4
|
import { pluginHostPaths } from './pluginHostPaths.js';
|
|
5
5
|
import { writePluginHostFile } from './pluginHostFiles.js';
|
|
6
|
-
import { compilePluginStateSchema } from '../sdk/pluginStateDefinition.js';
|
|
7
6
|
function fail(code, message) {
|
|
8
7
|
throw Object.assign(new Error(message), { code });
|
|
9
8
|
}
|
|
@@ -316,7 +315,6 @@ export class PluginStateStore {
|
|
|
316
315
|
else
|
|
317
316
|
delete entry.expiresAt;
|
|
318
317
|
}
|
|
319
|
-
const validate = compilePluginStateSchema(definition.schema);
|
|
320
318
|
for (const operation of input.operations) {
|
|
321
319
|
key(operation.key);
|
|
322
320
|
if (names.has(operation.key) ||
|
|
@@ -328,9 +326,9 @@ export class PluginStateStore {
|
|
|
328
326
|
delete entries[operation.key];
|
|
329
327
|
continue;
|
|
330
328
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
fail('
|
|
329
|
+
const json = JSON.stringify(operation.value);
|
|
330
|
+
if (json === undefined || Buffer.byteLength(json) > 256 * 1024)
|
|
331
|
+
fail('PLUGIN_STATE_INVALID', 'State value must be JSON within 256 KiB');
|
|
334
332
|
const ttl = operation.ttlMs ?? definition.ttlMs ?? 86400000;
|
|
335
333
|
if (definition.storage === 'persistent' && operation.ttlMs !== undefined)
|
|
336
334
|
fail('PLUGIN_STATE_INVALID', 'Persistent state does not accept TTL');
|
|
@@ -342,9 +340,6 @@ export class PluginStateStore {
|
|
|
342
340
|
...(definition.storage !== 'persistent' ? { expiresAt: now + ttl } : {}),
|
|
343
341
|
};
|
|
344
342
|
}
|
|
345
|
-
for (const entry of Object.values(entries))
|
|
346
|
-
if (!validate(entry.value))
|
|
347
|
-
fail('PLUGIN_STATE_SCHEMA_INVALID', 'Migration leaves entries incompatible with the target schema');
|
|
348
343
|
const commit = {
|
|
349
344
|
revision,
|
|
350
345
|
schemaVersion: definition.schemaVersion,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { normalizeModelDiagnostic, diagnosticBinding } from './pluginDiagnostics.js';
|
|
2
2
|
import { pluginModelCapabilities, normalizePluginModel, validatePluginModelResult, } from '../sdk/pluginModelDefinition.js';
|
|
3
3
|
import { pluginRecoverySignature } from '../sdk/pluginRecoveryDefinition.js';
|
|
4
|
-
import { compilePluginStateSchema } from '../sdk/pluginStateDefinition.js';
|
|
5
4
|
import { createHash, randomUUID } from 'node:crypto';
|
|
6
5
|
import { EventEmitter } from 'node:events';
|
|
7
6
|
import { isAbsolute, join, relative, sep } from 'node:path';
|
|
@@ -206,7 +205,7 @@ export class PluginTaskManager {
|
|
|
206
205
|
executionTimeoutMs: request.executionTimeoutMs ?? 120000,
|
|
207
206
|
};
|
|
208
207
|
}
|
|
209
|
-
if (!/^[a-z][a-z0-
|
|
208
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(request.plugin) || !/^[a-z][a-z0-9-]*$/.test(request.command))
|
|
210
209
|
throw new Error('Invalid plugin task command');
|
|
211
210
|
if (bridge.scope.plugin && request.plugin !== bridge.scope.plugin)
|
|
212
211
|
throw error('PLUGIN_COMMAND_NOT_ALLOWED', 'Plugin task is outside the caller scope');
|
|
@@ -482,8 +481,7 @@ export class PluginTaskManager {
|
|
|
482
481
|
signal.throwIfAborted();
|
|
483
482
|
if (!sourceDefinition ||
|
|
484
483
|
sourceDefinition.checkpointVersion !== record.checkpoint.version ||
|
|
485
|
-
digest(sourceDefinition.schema) !== record.checkpoint.schemaHash
|
|
486
|
-
!compilePluginStateSchema(sourceDefinition.schema)(record.checkpoint.data))
|
|
484
|
+
digest(sourceDefinition.schema) !== record.checkpoint.schemaHash)
|
|
487
485
|
throw error('PLUGIN_TASK_RECOVERY_UNAVAILABLE', 'Checkpoint does not match the retained recovery declaration');
|
|
488
486
|
let checkpoint = structuredClone(record.checkpoint);
|
|
489
487
|
let declarationHash = pluginRecoverySignature(sourceDefinition);
|
|
@@ -542,8 +540,6 @@ export class PluginTaskManager {
|
|
|
542
540
|
data: JSON.parse(json),
|
|
543
541
|
};
|
|
544
542
|
}
|
|
545
|
-
if (!compilePluginStateSchema(target.schema)(checkpoint.data))
|
|
546
|
-
throw error('PLUGIN_TASK_CHECKPOINT_INVALID', 'Migrated checkpoint does not match the target schema');
|
|
547
543
|
}
|
|
548
544
|
signal.throwIfAborted();
|
|
549
545
|
// Admission is synchronous after both immutable snapshots and execution ownership are verified.
|
|
@@ -809,8 +805,8 @@ export class PluginTaskManager {
|
|
|
809
805
|
if (declaration &&
|
|
810
806
|
payload.expectedDeclaration !== pluginRecoverySignature(declaration))
|
|
811
807
|
throw error('PLUGIN_RECOVERY_DECLARATION_CHANGED', 'Checkpoint declaration differs from the executing command');
|
|
812
|
-
if (!declaration
|
|
813
|
-
throw error('PLUGIN_TASK_CHECKPOINT_INVALID', 'Checkpoint is undeclared
|
|
808
|
+
if (!declaration)
|
|
809
|
+
throw error('PLUGIN_TASK_CHECKPOINT_INVALID', 'Checkpoint is undeclared');
|
|
814
810
|
const current = this.store.read(taskId);
|
|
815
811
|
if (current.task.state !== 'running' ||
|
|
816
812
|
payload.expectedSequence !== (current.checkpoint?.sequence ?? 0))
|
|
@@ -888,7 +884,7 @@ export class PluginTaskManager {
|
|
|
888
884
|
});
|
|
889
885
|
}
|
|
890
886
|
if (restrictedTarget &&
|
|
891
|
-
!['send_request', '
|
|
887
|
+
!['send_request', 'browser_list', 'connector_list'].includes(action))
|
|
892
888
|
throw error('PLUGIN_PAGE_TARGET_CHANGED', 'Runtime tasks must access the document through context.page');
|
|
893
889
|
this.assertRouting(options, request.options);
|
|
894
890
|
if (client) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CommandRunner } from '@mearl/daemon-core';
|
|
1
2
|
import type { PluginTaskRecoveryDeclaration, PluginTaskCheckpoint, PluginCheckpointMigrationInput } from '@mearl/browser-core';
|
|
2
3
|
import type { PluginStateDeclaration } from '@mearl/browser-core';
|
|
3
4
|
import type { PluginModelRequest, PluginModelResult } from '@mearl/browser-core';
|
|
@@ -71,7 +72,11 @@ export declare function loadPlugin(entry: string, context: Pick<PluginApp, 'opti
|
|
|
71
72
|
onInvocation?: (identity: PluginInvocationIdentity | undefined) => void;
|
|
72
73
|
}, pluginName?: string): Promise<{
|
|
73
74
|
name: string | undefined;
|
|
75
|
+
setup: ((context: {
|
|
76
|
+
runCommand: CommandRunner;
|
|
77
|
+
}) => unknown | Promise<unknown>) | undefined;
|
|
74
78
|
description: string | undefined;
|
|
79
|
+
defaultCommand: string | undefined;
|
|
75
80
|
toolbox: PluginToolboxContribution | undefined;
|
|
76
81
|
pageRuntime: PluginPageRuntime | undefined;
|
|
77
82
|
stateStorage: PluginStateDeclaration | undefined;
|
|
@@ -89,7 +94,11 @@ export declare function loadPlugin(entry: string, context: Pick<PluginApp, 'opti
|
|
|
89
94
|
}>;
|
|
90
95
|
export declare function loadRegisteredPlugin(name: string, context: PluginExecutionContext, options?: PluginInvokeOptions): Promise<{
|
|
91
96
|
name: string | undefined;
|
|
97
|
+
setup: ((context: {
|
|
98
|
+
runCommand: CommandRunner;
|
|
99
|
+
}) => unknown | Promise<unknown>) | undefined;
|
|
92
100
|
description: string | undefined;
|
|
101
|
+
defaultCommand: string | undefined;
|
|
93
102
|
toolbox: PluginToolboxContribution | undefined;
|
|
94
103
|
pageRuntime: PluginPageRuntime | undefined;
|
|
95
104
|
stateStorage: PluginStateDeclaration | undefined;
|