@openclaw/plugin-inspector 0.3.4 → 0.3.6
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/CHANGELOG.md +22 -0
- package/package.json +1 -1
- package/src/advanced.js +5 -0
- package/src/api.js +4 -0
- package/src/artifacts.js +1 -1
- package/src/ci-policy.js +3 -1
- package/src/ci-summary.js +50 -3
- package/src/compatibility-report.js +39 -3
- package/src/config.js +35 -5
- package/src/contract-capture.js +1 -0
- package/src/contract-probes.js +25 -0
- package/src/fixture-summary.js +406 -0
- package/src/import-loop-profile.js +262 -8
- package/src/index.js +7 -0
- package/src/inspector.js +49 -4
- package/src/issues.js +66 -1
- package/src/openclaw-target.js +79 -2
- package/src/platform-probes.js +29 -6
- package/src/process-profile.js +40 -19
- package/src/prune-workspace-dev-deps-cli.js +23 -0
- package/src/report.js +19 -1
- package/src/runtime-profile.js +67 -15
- package/src/runtime-reconciliation.js +124 -0
- package/src/sdk-mock.js +64 -6
- package/src/synthetic-probes.js +51 -0
- package/src/workspace-plan.js +19 -4
package/src/sdk-mock.js
CHANGED
|
@@ -254,9 +254,20 @@ export async function createMockSdkPackage(rootDir, options = {}) {
|
|
|
254
254
|
)}\n`,
|
|
255
255
|
"utf8",
|
|
256
256
|
);
|
|
257
|
-
|
|
257
|
+
const rootExportNames = new Set([
|
|
258
|
+
...mockSdkExportNames,
|
|
259
|
+
...(imports.bySpecifier.get("openclaw/plugin-sdk") ?? []),
|
|
260
|
+
]);
|
|
261
|
+
await writeFile(path.join(pluginSdkDir, "index.js"), mockSdkSource(rootExportNames), "utf8");
|
|
258
262
|
for (const [subpath, exportNames] of Object.entries(mockSdkSubpathExports)) {
|
|
259
|
-
|
|
263
|
+
const specifier = `openclaw/plugin-sdk/${subpath}`;
|
|
264
|
+
await writeFile(
|
|
265
|
+
path.join(pluginSdkDir, `${subpath}.js`),
|
|
266
|
+
mockSdkSubpathSource(exportNames, imports.bySpecifier.get(specifier) ?? new Set(), {
|
|
267
|
+
zod: subpath === "zod",
|
|
268
|
+
}),
|
|
269
|
+
"utf8",
|
|
270
|
+
);
|
|
260
271
|
}
|
|
261
272
|
for (const specifier of imports.openclawSdkSpecifiers) {
|
|
262
273
|
if (specifier === "openclaw/plugin-sdk") {
|
|
@@ -428,6 +439,9 @@ export async function resolve(specifier, context, nextResolve) {
|
|
|
428
439
|
const subpath = specifier.slice("openclaw/plugin-sdk/".length);
|
|
429
440
|
return moduleUrl(path.join(pluginSdkDir, \`\${subpath}.js\`));
|
|
430
441
|
}
|
|
442
|
+
if (externalMap.has(specifier)) {
|
|
443
|
+
return moduleUrl(externalMap.get(specifier));
|
|
444
|
+
}
|
|
431
445
|
try {
|
|
432
446
|
return await nextResolve(specifier, context);
|
|
433
447
|
} catch (error) {
|
|
@@ -531,6 +545,12 @@ function genericExportStatement(name) {
|
|
|
531
545
|
if (["createChatChannelPlugin", "createPlugin", "defineChannelPluginEntry", "definePlugin", "definePluginEntry", "defineSetupPluginEntry"].includes(name)) {
|
|
532
546
|
return name === "definePluginEntry" ? "export { definePluginEntry };" : `export const ${name} = definePluginEntry;`;
|
|
533
547
|
}
|
|
548
|
+
if (name === "defineBundledChannelEntry") {
|
|
549
|
+
return "export { defineBundledChannelEntry };";
|
|
550
|
+
}
|
|
551
|
+
if (name === "defineBundledChannelSetupEntry") {
|
|
552
|
+
return "export { defineBundledChannelSetupEntry };";
|
|
553
|
+
}
|
|
534
554
|
if (/^[A-Z].*Schema$/u.test(name)) {
|
|
535
555
|
return `export const ${name} = createSchema();`;
|
|
536
556
|
}
|
|
@@ -547,9 +567,41 @@ function genericMockRuntimeSource(options = {}) {
|
|
|
547
567
|
}
|
|
548
568
|
return typeof entry === "function" ? { register: entry } : entry;
|
|
549
569
|
}
|
|
570
|
+
|
|
571
|
+
function defineBundledChannelEntry(entry = {}) {
|
|
572
|
+
return {
|
|
573
|
+
...entry,
|
|
574
|
+
kind: "bundled-channel-entry",
|
|
575
|
+
register(api) {
|
|
576
|
+
if (api?.registrationMode === "cli-metadata") {
|
|
577
|
+
return entry.registerCliMetadata?.(api);
|
|
578
|
+
}
|
|
579
|
+
if (api?.registrationMode !== "tool-discovery") {
|
|
580
|
+
api?.registerChannel?.({
|
|
581
|
+
id: entry.id,
|
|
582
|
+
name: entry.name,
|
|
583
|
+
description: entry.description,
|
|
584
|
+
plugin: { id: entry.id, name: entry.name },
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
entry.registerCliMetadata?.(api);
|
|
588
|
+
return entry.registerFull?.(api);
|
|
589
|
+
},
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
function defineBundledChannelSetupEntry(entry = {}) {
|
|
594
|
+
return {
|
|
595
|
+
...entry,
|
|
596
|
+
kind: "bundled-channel-setup-entry",
|
|
597
|
+
};
|
|
598
|
+
}
|
|
550
599
|
` : ""}
|
|
551
600
|
function createMockValue(name) {
|
|
552
601
|
function fn(...args) {
|
|
602
|
+
if (name === "resolvePreferredOpenClawTmpDir") {
|
|
603
|
+
return process.env.TMPDIR || "/tmp";
|
|
604
|
+
}
|
|
553
605
|
if (name.startsWith("normalize")) {
|
|
554
606
|
return typeof args[0] === "string" ? args[0] : "";
|
|
555
607
|
}
|
|
@@ -728,7 +780,8 @@ function createTypeNamespace() {
|
|
|
728
780
|
`;
|
|
729
781
|
}
|
|
730
782
|
|
|
731
|
-
function mockSdkSource() {
|
|
783
|
+
function mockSdkSource(exportNames = mockSdkExportNames) {
|
|
784
|
+
const dynamicExportNames = [...exportNames].filter((name) => !mockSdkExportNames.includes(name));
|
|
732
785
|
return `function normalizeEntry(entry) {
|
|
733
786
|
return typeof entry === "function" ? { register: entry } : entry;
|
|
734
787
|
}
|
|
@@ -1538,15 +1591,20 @@ export const OPENAI_RESPONSES_STREAM_HOOKS = buildProviderStreamFamilyHooks("ope
|
|
|
1538
1591
|
export const OPENROUTER_THINKING_STREAM_HOOKS = buildProviderStreamFamilyHooks("openrouter-thinking");
|
|
1539
1592
|
export const TOOL_STREAM_DEFAULT_ON_HOOKS = buildProviderStreamFamilyHooks("tool-stream-default");
|
|
1540
1593
|
export const pluginSdkMock = true;
|
|
1594
|
+
${dynamicExportNames.map(genericExportStatement).join("\n")}
|
|
1541
1595
|
|
|
1542
1596
|
export default {
|
|
1543
|
-
${
|
|
1597
|
+
${[...exportNames].map((name) => ` ${name},`).join("\n")}
|
|
1544
1598
|
};
|
|
1545
1599
|
`;
|
|
1546
1600
|
}
|
|
1547
1601
|
|
|
1548
|
-
function mockSdkSubpathSource(
|
|
1549
|
-
|
|
1602
|
+
function mockSdkSubpathSource(staticExportNames, importedExportNames, options = {}) {
|
|
1603
|
+
const staticNames = new Set(staticExportNames);
|
|
1604
|
+
const dynamicNames = [...importedExportNames].filter((name) => !staticNames.has(name));
|
|
1605
|
+
return `${[...staticNames].map((name) => `export { ${name} } from "./index.js";`).join("\n")}
|
|
1606
|
+
${dynamicNames.length > 0 ? genericMockRuntimeSource({ includeSdkRuntime: true, zod: options.zod }) : ""}
|
|
1607
|
+
${dynamicNames.map(genericExportStatement).join("\n")}
|
|
1550
1608
|
export { default } from "./index.js";
|
|
1551
1609
|
`;
|
|
1552
1610
|
}
|
package/src/synthetic-probes.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { renderPaddedMarkdownTable, writeJsonMarkdownArtifacts } from "./artifacts.js";
|
|
2
2
|
|
|
3
3
|
export const syntheticRegistrationExecutionProfiles = {
|
|
4
|
+
createChatChannelPlugin: {
|
|
5
|
+
mode: "metadata-only",
|
|
6
|
+
callableProperties: [],
|
|
7
|
+
reason: "channel plugin factory metadata is captured before channel runtime execution",
|
|
8
|
+
},
|
|
4
9
|
defineChannelPluginEntry: {
|
|
5
10
|
mode: "metadata-only",
|
|
6
11
|
callableProperties: [],
|
|
7
12
|
reason: "entry wrapper metadata is captured before channel runtime execution",
|
|
8
13
|
},
|
|
14
|
+
defineBundledChannelEntry: {
|
|
15
|
+
mode: "metadata-only",
|
|
16
|
+
callableProperties: [],
|
|
17
|
+
reason: "bundled channel entry metadata is captured before channel runtime execution",
|
|
18
|
+
},
|
|
9
19
|
definePluginEntry: {
|
|
10
20
|
mode: "metadata-only",
|
|
11
21
|
callableProperties: [],
|
|
@@ -21,6 +31,11 @@ export const syntheticRegistrationExecutionProfiles = {
|
|
|
21
31
|
callableProperties: [],
|
|
22
32
|
reason: "agent harness factories are captured as registration metadata; agent runtime execution remains isolated opt-in",
|
|
23
33
|
},
|
|
34
|
+
registerAgentEventSubscription: {
|
|
35
|
+
mode: "metadata-only",
|
|
36
|
+
callableProperties: [],
|
|
37
|
+
reason: "agent event subscriptions are captured as registration metadata before agent event dispatch",
|
|
38
|
+
},
|
|
24
39
|
registerAgentToolResultMiddleware: {
|
|
25
40
|
mode: "metadata-only",
|
|
26
41
|
callableProperties: [],
|
|
@@ -64,6 +79,11 @@ export const syntheticRegistrationExecutionProfiles = {
|
|
|
64
79
|
callableProperties: [],
|
|
65
80
|
reason: "context engine factories are captured as registration metadata; engine startup remains isolated opt-in",
|
|
66
81
|
},
|
|
82
|
+
registerControlUiDescriptor: {
|
|
83
|
+
mode: "metadata-only",
|
|
84
|
+
callableProperties: [],
|
|
85
|
+
reason: "control UI descriptors are captured as registration metadata before UI composition",
|
|
86
|
+
},
|
|
67
87
|
registerDetachedTaskRuntime: {
|
|
68
88
|
mode: "metadata-only",
|
|
69
89
|
callableProperties: [],
|
|
@@ -151,6 +171,11 @@ export const syntheticRegistrationExecutionProfiles = {
|
|
|
151
171
|
callableProperties: [],
|
|
152
172
|
reason: "node host commands are captured as registration metadata before host process execution",
|
|
153
173
|
},
|
|
174
|
+
registerNodeInvokePolicy: {
|
|
175
|
+
mode: "metadata-only",
|
|
176
|
+
callableProperties: [],
|
|
177
|
+
reason: "node invoke policies are captured as registration metadata before host authorization checks",
|
|
178
|
+
},
|
|
154
179
|
registerProvider: {
|
|
155
180
|
mode: "metadata-only",
|
|
156
181
|
callableProperties: [],
|
|
@@ -171,6 +196,11 @@ export const syntheticRegistrationExecutionProfiles = {
|
|
|
171
196
|
callableProperties: [],
|
|
172
197
|
reason: "reload handlers are captured as registration metadata before runtime reload execution",
|
|
173
198
|
},
|
|
199
|
+
registerRuntimeLifecycle: {
|
|
200
|
+
mode: "metadata-only",
|
|
201
|
+
callableProperties: [],
|
|
202
|
+
reason: "runtime lifecycle handlers are captured as registration metadata before lifecycle dispatch",
|
|
203
|
+
},
|
|
174
204
|
registerSecurityAuditCollector: {
|
|
175
205
|
mode: "metadata-only",
|
|
176
206
|
callableProperties: [],
|
|
@@ -181,6 +211,16 @@ export const syntheticRegistrationExecutionProfiles = {
|
|
|
181
211
|
callableProperties: ["start", "stop", "dispose"],
|
|
182
212
|
option: "includeLifecycle",
|
|
183
213
|
},
|
|
214
|
+
registerSessionExtension: {
|
|
215
|
+
mode: "metadata-only",
|
|
216
|
+
callableProperties: [],
|
|
217
|
+
reason: "session extensions are captured as registration metadata before session runtime execution",
|
|
218
|
+
},
|
|
219
|
+
registerSessionSchedulerJob: {
|
|
220
|
+
mode: "metadata-only",
|
|
221
|
+
callableProperties: [],
|
|
222
|
+
reason: "session scheduler jobs are captured as registration metadata before scheduler execution",
|
|
223
|
+
},
|
|
184
224
|
registerSpeechProvider: {
|
|
185
225
|
mode: "provider-opt-in",
|
|
186
226
|
callableProperties: ["speak", "synthesize", "tts"],
|
|
@@ -190,6 +230,11 @@ export const syntheticRegistrationExecutionProfiles = {
|
|
|
190
230
|
mode: "direct",
|
|
191
231
|
callableProperties: ["run", "handler", "execute"],
|
|
192
232
|
},
|
|
233
|
+
registerToolMetadata: {
|
|
234
|
+
mode: "metadata-only",
|
|
235
|
+
callableProperties: [],
|
|
236
|
+
reason: "tool metadata descriptors are captured as registration metadata before tool runtime execution",
|
|
237
|
+
},
|
|
193
238
|
registerTextTransforms: {
|
|
194
239
|
mode: "metadata-only",
|
|
195
240
|
callableProperties: [],
|
|
@@ -200,6 +245,11 @@ export const syntheticRegistrationExecutionProfiles = {
|
|
|
200
245
|
callableProperties: [],
|
|
201
246
|
reason: "video generation providers are captured as registration metadata before provider runtime execution",
|
|
202
247
|
},
|
|
248
|
+
registerTrustedToolPolicy: {
|
|
249
|
+
mode: "metadata-only",
|
|
250
|
+
callableProperties: [],
|
|
251
|
+
reason: "trusted tool policies are captured as registration metadata before trust-policy enforcement",
|
|
252
|
+
},
|
|
203
253
|
registerWebFetchProvider: {
|
|
204
254
|
mode: "metadata-only",
|
|
205
255
|
callableProperties: [],
|
|
@@ -326,6 +376,7 @@ export const defaultSyntheticHookContexts = {
|
|
|
326
376
|
};
|
|
327
377
|
|
|
328
378
|
export const defaultSyntheticRegistrationArguments = {
|
|
379
|
+
createChatChannelPlugin: [{ base: { id: "fixture-channel" }, outbound: { sendText: "function" } }],
|
|
329
380
|
defineChannelPluginEntry: [{ id: "fixture-channel", setup: "function", receive: "function" }],
|
|
330
381
|
definePluginEntry: [{ id: "fixture-plugin", register: "function" }],
|
|
331
382
|
registerChannel: [{ id: "fixture-channel", send: "function", receive: "function" }],
|
package/src/workspace-plan.js
CHANGED
|
@@ -71,6 +71,7 @@ export async function buildWorkspacePlan(options = {}) {
|
|
|
71
71
|
installStepCount: allSteps.filter((step) => step.kind === "install").length,
|
|
72
72
|
auditStepCount: allSteps.filter((step) => step.kind === "audit").length,
|
|
73
73
|
buildStepCount: allSteps.filter((step) => step.kind === "build").length,
|
|
74
|
+
pruneDevWorkspaceDependencyStepCount: allSteps.filter((step) => step.kind === "prune-dev-workspace-deps").length,
|
|
74
75
|
artifactStepCount: allSteps.filter((step) => step.kind === "prepare-artifacts").length,
|
|
75
76
|
captureStepCount: allSteps.filter((step) => step.kind === "capture").length,
|
|
76
77
|
syntheticProbeStepCount: allSteps.filter((step) => step.kind === "synthetic-probe").length,
|
|
@@ -179,6 +180,7 @@ export function renderWorkspacePlanMarkdown(plan, options = {}) {
|
|
|
179
180
|
["Artifact dirs", plan.summary.artifactStepCount],
|
|
180
181
|
["Install steps", plan.summary.installStepCount],
|
|
181
182
|
["Audit steps", plan.summary.auditStepCount],
|
|
183
|
+
["Prune dev workspace dependency steps", plan.summary.pruneDevWorkspaceDependencyStepCount],
|
|
182
184
|
["Build steps", plan.summary.buildStepCount],
|
|
183
185
|
["Capture steps", plan.summary.captureStepCount],
|
|
184
186
|
["Synthetic probe steps", plan.summary.syntheticProbeStepCount],
|
|
@@ -248,6 +250,14 @@ async function buildEntrypointPlan({ fixtureId, entrypoint, packageSummary, pack
|
|
|
248
250
|
}
|
|
249
251
|
|
|
250
252
|
if (requiredCapabilities.includes("dependency-install")) {
|
|
253
|
+
if (hasWorkspaceProtocolDevDependencies(packageJson)) {
|
|
254
|
+
steps.push({
|
|
255
|
+
kind: "prune-dev-workspace-deps",
|
|
256
|
+
command: `node ${helperScript(settings, workspacePath, settings.pruneWorkspaceDevDepsScript, "prune-workspace-dev-deps-cli.js")}`,
|
|
257
|
+
cwd: workspacePath,
|
|
258
|
+
reason: "remove workspace: devDependencies from the isolated runtime install; the mock SDK supplies OpenClaw host imports",
|
|
259
|
+
});
|
|
260
|
+
}
|
|
251
261
|
steps.push({
|
|
252
262
|
kind: "install",
|
|
253
263
|
command: installCommand(packageManager),
|
|
@@ -319,6 +329,7 @@ function workspaceSettings(options) {
|
|
|
319
329
|
resultsRoot: repoRelative(options.resultsRoot ?? defaultWorkspacePlanOptions.resultsRoot),
|
|
320
330
|
rootDir: path.resolve(options.rootDir ?? process.cwd()),
|
|
321
331
|
syntheticProbeScript: options.syntheticProbeScript ?? defaultWorkspacePlanOptions.syntheticProbeScript,
|
|
332
|
+
pruneWorkspaceDevDepsScript: options.pruneWorkspaceDevDepsScript,
|
|
322
333
|
workspaceRoot: repoRelative(options.workspaceRoot ?? defaultWorkspacePlanOptions.workspaceRoot),
|
|
323
334
|
};
|
|
324
335
|
}
|
|
@@ -377,6 +388,12 @@ function hasHostLinkedOpenClawDependency(packageSummary) {
|
|
|
377
388
|
].includes("openclaw");
|
|
378
389
|
}
|
|
379
390
|
|
|
391
|
+
function hasWorkspaceProtocolDevDependencies(packageJson) {
|
|
392
|
+
return Object.values(packageJson.devDependencies ?? {}).some(
|
|
393
|
+
(value) => typeof value === "string" && value.startsWith("workspace:"),
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
380
397
|
function detectPackageManager(rootDir, packageDir, packageJson) {
|
|
381
398
|
const declared = typeof packageJson.packageManager === "string" ? packageJson.packageManager.split("@")[0] : null;
|
|
382
399
|
if (declared) {
|
|
@@ -458,15 +475,13 @@ function runCommand(packageManager, script) {
|
|
|
458
475
|
}
|
|
459
476
|
|
|
460
477
|
function captureCommand(settings, fixtureId, entrypoint, workspacePath) {
|
|
461
|
-
const loader = entrypoint.blockers.some((blocker) => blocker.code === "ts-loader-required") ? " --import tsx" : "";
|
|
462
478
|
const script = helperScript(settings, workspacePath, settings.captureScript, "capture-cli.js");
|
|
463
|
-
return `${settings.optInEnv} node
|
|
479
|
+
return `${settings.optInEnv} node ${script} ${entrypoint.specifier} --mock-sdk --output ${workspaceArtifactPath(settings, fixtureId, entrypoint, workspacePath, "capture")}`;
|
|
464
480
|
}
|
|
465
481
|
|
|
466
482
|
function syntheticProbeCommand(settings, fixtureId, entrypoint, workspacePath) {
|
|
467
|
-
const loader = entrypoint.blockers.some((blocker) => blocker.code === "ts-loader-required") ? " --import tsx" : "";
|
|
468
483
|
const script = helperScript(settings, workspacePath, settings.syntheticProbeScript, "synthetic-probes-cli.js");
|
|
469
|
-
return `${settings.optInEnv} node
|
|
484
|
+
return `${settings.optInEnv} node ${script} --entrypoint ${entrypoint.specifier} --mock-sdk --output ${workspaceArtifactPath(settings, fixtureId, entrypoint, workspacePath, "synthetic")}`;
|
|
470
485
|
}
|
|
471
486
|
|
|
472
487
|
function helperScript(settings, workspacePath, configuredScript, helperFileName) {
|