@mearl/client 3.0.0-beta.8 → 3.0.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.en.md +616 -0
- package/README.md +22 -14
- package/dist/bin.js +1 -1
- package/dist/capabilityHelp.js +3 -3
- package/dist/commands.d.ts +12 -12
- package/dist/commands.js +12 -12
- package/dist/guide.d.ts +4 -4
- package/dist/guide.js +13 -4
- package/dist/guides/api-page-environment.md +4 -4
- package/dist/guides/browser-tool-cooperation.md +1 -1
- package/dist/guides/core.md +2 -2
- package/dist/guides/related-skills.md +22 -3
- package/dist/guides/troubleshooting.md +7 -7
- package/dist/plugins/pluginRegistry.d.ts +2 -3
- package/dist/plugins/pluginRegistry.js +9 -2
- package/dist/plugins/runtime/pluginPageManager.js +15 -4
- package/dist/plugins/sdk/plugin.d.ts +7 -0
- package/dist/plugins/sdk/plugin.js +5 -0
- package/dist/plugins/sdk/pluginPageDefinition.js +2 -0
- package/package.json +7 -6
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { diagnosticBinding } from './pluginDiagnostics.js';
|
|
2
2
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
3
|
import { EventEmitter } from 'node:events';
|
|
4
|
-
import { readFileSync, statSync } from 'node:fs';
|
|
5
|
-
import { isAbsolute, join } from 'node:path';
|
|
4
|
+
import { lstatSync, readFileSync, statSync } from 'node:fs';
|
|
5
|
+
import { dirname, isAbsolute, join } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { keyedDir } from '@mearl/daemon-core';
|
|
6
8
|
import { capturePluginRevision } from './pluginRevision.js';
|
|
7
9
|
import { findPluginRegistration } from '../sdk/plugin.js';
|
|
8
10
|
import { UnifiedClient, decodeBrowserTarget } from '../../unified.js';
|
|
@@ -361,6 +363,14 @@ export class PluginPageManager {
|
|
|
361
363
|
throw failure('PLUGIN_PAGE_TARGET_CHANGED', 'Nested plugin must use the inherited document');
|
|
362
364
|
if (!matchesPluginPageURL(runtime.matches, target.url))
|
|
363
365
|
throw failure('PLUGIN_PAGE_URL_NOT_ALLOWED', 'Plugin page URL is outside its declared matches');
|
|
366
|
+
if (target.url.startsWith('file:')) {
|
|
367
|
+
const file = fileURLToPath(target.url);
|
|
368
|
+
const directory = keyedDir(join('plugin-previews', plugin));
|
|
369
|
+
if (dirname(file) !== directory ||
|
|
370
|
+
!lstatSync(directory, { throwIfNoEntry: false })?.isDirectory() ||
|
|
371
|
+
!lstatSync(file, { throwIfNoEntry: false })?.isFile())
|
|
372
|
+
throw failure('PLUGIN_PAGE_URL_NOT_ALLOWED', 'Local preview must be a regular file in the plugin preview directory');
|
|
373
|
+
}
|
|
364
374
|
const existing = [...this.instances.values()].find(item => item.value.state === 'active' &&
|
|
365
375
|
item.value.plugin === plugin &&
|
|
366
376
|
sameTarget(item.value.target, target));
|
|
@@ -781,7 +791,7 @@ export class PluginPageManager {
|
|
|
781
791
|
try {
|
|
782
792
|
await this.validate(record);
|
|
783
793
|
const binding = record.runtime.events[delivery.name];
|
|
784
|
-
const started = this.start(record, binding.command, { event: { name: delivery.name, payload: delivery.payload, sequence: delivery.sequence } }, `page:${record.value.instanceId}:${delivery.sequence}
|
|
794
|
+
const started = this.start(record, binding.command, { event: { name: delivery.name, payload: delivery.payload, sequence: delivery.sequence } }, `page:${record.value.instanceId}:${delivery.sequence}`, undefined, binding.executionTimeoutMs);
|
|
785
795
|
delivery.taskId = started.taskId;
|
|
786
796
|
this.append(record, {
|
|
787
797
|
type: 'running',
|
|
@@ -813,7 +823,7 @@ export class PluginPageManager {
|
|
|
813
823
|
});
|
|
814
824
|
}
|
|
815
825
|
}
|
|
816
|
-
start(record, command, input, key, parentIdentity) {
|
|
826
|
+
start(record, command, input, key, parentIdentity, executionTimeoutMs) {
|
|
817
827
|
// The runtime delegates through the instance's current connection. Its identity follows
|
|
818
828
|
// that connection so binding cannot replace the connection with this forwarding proxy.
|
|
819
829
|
const bridge = {
|
|
@@ -838,6 +848,7 @@ export class PluginPageManager {
|
|
|
838
848
|
environment: record.execution.environment,
|
|
839
849
|
options: record.options,
|
|
840
850
|
idempotencyKey: key,
|
|
851
|
+
executionTimeoutMs,
|
|
841
852
|
}, bridge, {
|
|
842
853
|
...(parentIdentity?.taskId ? { parentTaskId: parentIdentity.taskId, parentIdentity } : {}),
|
|
843
854
|
revision: record.revision,
|
|
@@ -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,6 +72,9 @@ 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;
|
|
75
79
|
defaultCommand: string | undefined;
|
|
76
80
|
toolbox: PluginToolboxContribution | undefined;
|
|
@@ -90,6 +94,9 @@ export declare function loadPlugin(entry: string, context: Pick<PluginApp, 'opti
|
|
|
90
94
|
}>;
|
|
91
95
|
export declare function loadRegisteredPlugin(name: string, context: PluginExecutionContext, options?: PluginInvokeOptions): Promise<{
|
|
92
96
|
name: string | undefined;
|
|
97
|
+
setup: ((context: {
|
|
98
|
+
runCommand: CommandRunner;
|
|
99
|
+
}) => unknown | Promise<unknown>) | undefined;
|
|
93
100
|
description: string | undefined;
|
|
94
101
|
defaultCommand: string | undefined;
|
|
95
102
|
toolbox: PluginToolboxContribution | undefined;
|
|
@@ -153,6 +153,7 @@ export async function loadPlugin(entry, context, pluginName) {
|
|
|
153
153
|
let taskRecovery;
|
|
154
154
|
let appProfiles;
|
|
155
155
|
let profileSources;
|
|
156
|
+
let setup;
|
|
156
157
|
const registerCommand = (signature, handler, description = '', examples = [], toolboxOnly = false, runtimeOnly = false) => {
|
|
157
158
|
if (!registering)
|
|
158
159
|
throw new Error('命令只能在入口注册阶段声明');
|
|
@@ -313,6 +314,9 @@ export async function loadPlugin(entry, context, pluginName) {
|
|
|
313
314
|
if (module.description !== undefined && typeof module.description !== 'string')
|
|
314
315
|
throw new Error('入口的 description 导出必须为字符串');
|
|
315
316
|
description = module.description;
|
|
317
|
+
if (module.setup !== undefined && typeof module.setup !== 'function')
|
|
318
|
+
throw new Error('入口的 setup 导出必须为函数');
|
|
319
|
+
setup = module.setup;
|
|
316
320
|
if (module.defaultCommand !== undefined && typeof module.defaultCommand !== 'string')
|
|
317
321
|
throw new Error('入口的 defaultCommand 导出必须为字符串');
|
|
318
322
|
defaultCommand = module.defaultCommand;
|
|
@@ -535,6 +539,7 @@ export async function loadPlugin(entry, context, pluginName) {
|
|
|
535
539
|
};
|
|
536
540
|
return {
|
|
537
541
|
name,
|
|
542
|
+
setup,
|
|
538
543
|
description,
|
|
539
544
|
defaultCommand,
|
|
540
545
|
toolbox,
|
|
@@ -37,6 +37,8 @@ export function normalizePluginPageRuntime(value) {
|
|
|
37
37
|
(!Number.isSafeInteger(event.maxPending) ||
|
|
38
38
|
event.maxPending < 1 ||
|
|
39
39
|
event.maxPending > 64)) ||
|
|
40
|
+
(event.executionTimeoutMs !== undefined &&
|
|
41
|
+
(!Number.isSafeInteger(event.executionTimeoutMs) || event.executionTimeoutMs < 1 || event.executionTimeoutMs > 300000)) ||
|
|
40
42
|
event.schema.$async)
|
|
41
43
|
throw new Error(`Invalid page event binding: ${name}`);
|
|
42
44
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/client",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Unified Mearl SDK & CLI for local and remote browsers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"mearl": "./dist/bin.js"
|
|
48
48
|
},
|
|
49
49
|
"files": [
|
|
50
|
+
"README.en.md",
|
|
50
51
|
"dist",
|
|
51
52
|
"!dist/**/*.map"
|
|
52
53
|
],
|
|
@@ -67,11 +68,11 @@
|
|
|
67
68
|
"commander": "^14.0.3",
|
|
68
69
|
"fastest-levenshtein": "^1.0.16",
|
|
69
70
|
"ws": "^8.18.0",
|
|
70
|
-
"@mearl/daemon-core": "3.0.0
|
|
71
|
-
"@mearl/cloud-types": "3.0.0
|
|
72
|
-
"@mearl/
|
|
73
|
-
"@mearl/agent-runtime": "3.0.0
|
|
74
|
-
"@mearl/
|
|
71
|
+
"@mearl/daemon-core": "3.0.0",
|
|
72
|
+
"@mearl/cloud-types": "3.0.0",
|
|
73
|
+
"@mearl/browser-core": "3.0.0",
|
|
74
|
+
"@mearl/agent-runtime": "3.0.0",
|
|
75
|
+
"@mearl/provider": "3.0.0"
|
|
75
76
|
},
|
|
76
77
|
"devDependencies": {
|
|
77
78
|
"@types/node": "^24.9.1",
|