@openclaw/plugin-inspector 0.2.0 → 0.3.1
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 +38 -0
- package/README.md +66 -5
- package/docs/plugin-inspector-banner.jpg +0 -0
- package/examples/circleci-plugin-inspector.yml +19 -0
- package/examples/github-actions-code-scanning.yml +31 -0
- package/examples/github-actions-plugin-inspector.yml +1 -1
- package/examples/gitlab-ci-plugin-inspector.yml +11 -0
- package/examples/package-json-plugin-inspector.json +1 -1
- package/package.json +10 -2
- package/src/advanced.js +10 -0
- package/src/api.js +169 -3
- package/src/capture-api.js +41 -3
- package/src/cli.js +48 -15
- package/src/index.js +227 -0
- package/src/init.js +90 -13
- package/src/mock-sdk-capture-runner.js +12 -8
- package/src/report.js +60 -8
- package/src/sdk-mock.js +202 -9
- package/src/synthetic-probe-suite.js +19 -0
- package/src/synthetic-probes-cli.js +16 -12
- package/src/synthetic-probes.js +55 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.3.1 - 2026-04-28
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Add grouped root facades: `pluginRoot`, `fixtureSuites`, `staticInspection`, `reports`, `contracts`, `ci`, `runtime`, and `synthetic`.
|
|
10
|
+
- Expose contract capture, contract coverage, CI rollup, runtime profile, ref/profile diff, import-loop, and synthetic probe helpers from the root package API.
|
|
11
|
+
- Add a release follow-through guard that fails when Crabpot scripts regress to the legacy `advanced.js` bundle.
|
|
12
|
+
- Add a package-contents release guard for npm tarball entrypoints, examples, and README assets.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Move Crabpot integration scripts to the root public API while keeping Crabpot as the fixture corpus and report consumer.
|
|
17
|
+
- Keep generic artifact writing out of the root API; Crabpot-owned runner scripts write their own JSON outputs.
|
|
18
|
+
- Ship the README banner asset in the npm package so the published README does not reference a missing local image.
|
|
19
|
+
- Document the grouped root import path for embedding harnesses without turning the README into a full API dump.
|
|
20
|
+
|
|
21
|
+
## 0.3.0 - 2026-04-27
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Add `--allow-execute` as a cross-platform runtime capture opt-in flag.
|
|
26
|
+
- Add `plugin-inspector init --dry-run` for setup previews.
|
|
27
|
+
- Add `plugin-inspector init --json` for machine-readable setup summaries.
|
|
28
|
+
- Add `plugin-inspector init --scripts` for `plugin:check` and `plugin:ci` package scripts.
|
|
29
|
+
- Add public fixture-set report helpers and synthetic probe suite helpers for Crabpot and downstream compatibility suites.
|
|
30
|
+
- Add a Crabpot follow-through release checklist for source refs, package pins, and smoke commands.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Make generated runtime CI commands use `--allow-execute` instead of shell-specific inline environment syntax.
|
|
35
|
+
- Make `plugin-inspector init --ci` detect `packageManager` and common lockfiles before generating CI install/run commands.
|
|
36
|
+
- Make `plugin-inspector init` output repo-relative file paths and preflight generated files before writing.
|
|
37
|
+
- Make `plugin-inspector init` infer `sourceRoot: "src"` from package export maps like `"./src/index.js"`.
|
|
38
|
+
- Improve CLI failure summaries with report artifact paths and top blocking findings.
|
|
39
|
+
- Harden mock SDK capture by keeping generated loader fixtures available until subprocess exit.
|
|
40
|
+
|
|
3
41
|
## 0.2.0 - 2026-04-27
|
|
4
42
|
|
|
5
43
|
### Added
|
package/README.md
CHANGED
|
@@ -18,12 +18,25 @@ npx @openclaw/plugin-inspector
|
|
|
18
18
|
That runs `check`, writes report artifacts to `reports/`, and exits non-zero
|
|
19
19
|
when compatibility breakages are found.
|
|
20
20
|
|
|
21
|
+
Package-manager equivalents:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pnpm dlx @openclaw/plugin-inspector
|
|
25
|
+
yarn dlx @openclaw/plugin-inspector
|
|
26
|
+
bunx @openclaw/plugin-inspector
|
|
27
|
+
```
|
|
28
|
+
|
|
21
29
|
Add a local config and GitHub Actions workflow:
|
|
22
30
|
|
|
23
31
|
```bash
|
|
24
32
|
npx @openclaw/plugin-inspector init --ci
|
|
25
33
|
```
|
|
26
34
|
|
|
35
|
+
`init --ci` detects `packageManager` and common lockfiles. Pass
|
|
36
|
+
`--package-manager pnpm`, `npm`, `yarn`, or `bun` when you want to override it.
|
|
37
|
+
Add `--scripts` to write `plugin:check` and `plugin:ci` package scripts.
|
|
38
|
+
Use `--dry-run` to preview the files first.
|
|
39
|
+
|
|
27
40
|
Or install it as a dev dependency:
|
|
28
41
|
|
|
29
42
|
```bash
|
|
@@ -31,6 +44,18 @@ npm install --save-dev @openclaw/plugin-inspector
|
|
|
31
44
|
npx plugin-inspector check
|
|
32
45
|
```
|
|
33
46
|
|
|
47
|
+
With a local dev dependency, prefer package scripts so CI and local checks use
|
|
48
|
+
the same command:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"scripts": {
|
|
53
|
+
"plugin:check": "plugin-inspector inspect --no-openclaw",
|
|
54
|
+
"plugin:ci": "plugin-inspector ci --no-openclaw --runtime --mock-sdk --allow-execute"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
34
59
|
## Commands
|
|
35
60
|
|
|
36
61
|
```bash
|
|
@@ -40,6 +65,8 @@ npx @openclaw/plugin-inspector ci --no-openclaw
|
|
|
40
65
|
npx @openclaw/plugin-inspector config
|
|
41
66
|
npx @openclaw/plugin-inspector check --plugin-root ./plugins/weather
|
|
42
67
|
npx @openclaw/plugin-inspector init --ci --package-manager pnpm
|
|
68
|
+
npx @openclaw/plugin-inspector init --ci --scripts --dry-run
|
|
69
|
+
npx @openclaw/plugin-inspector init --ci --scripts --dry-run --json
|
|
43
70
|
```
|
|
44
71
|
|
|
45
72
|
`check` and `inspect` read the current directory as one plugin unless
|
|
@@ -132,7 +159,8 @@ For a single plugin package, the same config can live in `package.json`:
|
|
|
132
159
|
`.github/workflows/plugin-inspector.yml`. Copy-ready examples also live in
|
|
133
160
|
`examples/plugin-inspector.config.json` and
|
|
134
161
|
`examples/package-json-plugin-inspector.json` and
|
|
135
|
-
`examples/github-actions-plugin-inspector.yml`.
|
|
162
|
+
`examples/github-actions-plugin-inspector.yml`. SARIF/JUnit CI consumption
|
|
163
|
+
examples live alongside them.
|
|
136
164
|
|
|
137
165
|
## Runtime Capture
|
|
138
166
|
|
|
@@ -141,9 +169,13 @@ the registrations made during `register(api)`. It is opt-in because it executes
|
|
|
141
169
|
plugin code:
|
|
142
170
|
|
|
143
171
|
```bash
|
|
144
|
-
|
|
172
|
+
npx @openclaw/plugin-inspector check --runtime --mock-sdk --allow-execute
|
|
145
173
|
```
|
|
146
174
|
|
|
175
|
+
`--allow-execute` is the explicit guard for modes that import plugin code. The
|
|
176
|
+
older `PLUGIN_INSPECTOR_EXECUTE_ISOLATED=1` environment guard still works for
|
|
177
|
+
custom harnesses.
|
|
178
|
+
|
|
147
179
|
By default, runtime capture uses a generated mock for `openclaw/plugin-sdk` and
|
|
148
180
|
common external packages so plugin code can load in clean CI without OpenClaw
|
|
149
181
|
installed. Use `--real-sdk` only when the plugin workspace already has real SDK
|
|
@@ -157,7 +189,7 @@ Runtime capture writes:
|
|
|
157
189
|
You can also capture one entrypoint directly:
|
|
158
190
|
|
|
159
191
|
```bash
|
|
160
|
-
|
|
192
|
+
plugin-inspector capture ./dist/index.js --mock-sdk --allow-execute
|
|
161
193
|
```
|
|
162
194
|
|
|
163
195
|
## CI
|
|
@@ -168,7 +200,7 @@ Minimal package scripts:
|
|
|
168
200
|
{
|
|
169
201
|
"scripts": {
|
|
170
202
|
"plugin:check": "plugin-inspector inspect --no-openclaw",
|
|
171
|
-
"plugin:ci": "
|
|
203
|
+
"plugin:ci": "plugin-inspector ci --no-openclaw --runtime --mock-sdk --allow-execute"
|
|
172
204
|
}
|
|
173
205
|
}
|
|
174
206
|
```
|
|
@@ -193,7 +225,7 @@ jobs:
|
|
|
193
225
|
node-version: 24
|
|
194
226
|
cache: npm
|
|
195
227
|
- run: npm ci
|
|
196
|
-
- run:
|
|
228
|
+
- run: npx @openclaw/plugin-inspector ci --no-openclaw --runtime --mock-sdk --allow-execute
|
|
197
229
|
- uses: actions/upload-artifact@v5
|
|
198
230
|
if: always()
|
|
199
231
|
with:
|
|
@@ -204,6 +236,15 @@ jobs:
|
|
|
204
236
|
`ci` writes the normal report, CI summary, SARIF, and JUnit files by default.
|
|
205
237
|
Pass `--no-sarif` or `--no-junit` only if your CI surface cannot consume them.
|
|
206
238
|
|
|
239
|
+
For GitHub code scanning, use
|
|
240
|
+
`examples/github-actions-code-scanning.yml`; it uploads
|
|
241
|
+
`reports/plugin-inspector.sarif` through CodeQL's SARIF upload action.
|
|
242
|
+
|
|
243
|
+
For CI test-summary UIs, point JUnit ingestion at
|
|
244
|
+
`reports/plugin-inspector.junit.xml`. Copy-ready GitLab and CircleCI examples
|
|
245
|
+
live in `examples/gitlab-ci-plugin-inspector.yml` and
|
|
246
|
+
`examples/circleci-plugin-inspector.yml`.
|
|
247
|
+
|
|
207
248
|
## Fixture Suites
|
|
208
249
|
|
|
209
250
|
Fixture-set configs are still supported for crabpot-style compatibility suites:
|
|
@@ -215,6 +256,26 @@ plugin-inspector report --config crabpot.config.json --out reports
|
|
|
215
256
|
Use fixture suites when one repo wants to inspect many plugins. Use plugin-root
|
|
216
257
|
`check` for normal plugin CI.
|
|
217
258
|
|
|
259
|
+
## Library Use
|
|
260
|
+
|
|
261
|
+
Most plugin repos should use the CLI. Harnesses can import grouped root helpers
|
|
262
|
+
when they need to embed the inspector:
|
|
263
|
+
|
|
264
|
+
```js
|
|
265
|
+
import { pluginRoot, fixtureSuites, contracts, ci } from "@openclaw/plugin-inspector";
|
|
266
|
+
|
|
267
|
+
const { report } = await pluginRoot.runCheck({
|
|
268
|
+
pluginRoot: process.cwd(),
|
|
269
|
+
openclawPath: false,
|
|
270
|
+
});
|
|
271
|
+
const capture = contracts.buildCapture({ report });
|
|
272
|
+
const summary = await ci.buildSummary({ reports: { compatibility: report } });
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
The root package groups stable workflows as `pluginRoot`, `fixtureSuites`,
|
|
276
|
+
`staticInspection`, `reports`, `contracts`, `ci`, `runtime`, and `synthetic`.
|
|
277
|
+
Named exports remain available for existing automation.
|
|
278
|
+
|
|
218
279
|
## Mocking Model
|
|
219
280
|
|
|
220
281
|
Default inspection is static, offline, and credential-free. Runtime capture is
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
version: 2.1
|
|
2
|
+
|
|
3
|
+
jobs:
|
|
4
|
+
plugin-inspector:
|
|
5
|
+
docker:
|
|
6
|
+
- image: cimg/node:24.0
|
|
7
|
+
steps:
|
|
8
|
+
- checkout
|
|
9
|
+
- run: npm ci
|
|
10
|
+
- run: npx @openclaw/plugin-inspector ci --no-openclaw --runtime --mock-sdk --allow-execute
|
|
11
|
+
- store_test_results:
|
|
12
|
+
path: reports
|
|
13
|
+
- store_artifacts:
|
|
14
|
+
path: reports
|
|
15
|
+
|
|
16
|
+
workflows:
|
|
17
|
+
plugin-inspector:
|
|
18
|
+
jobs:
|
|
19
|
+
- plugin-inspector
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: plugin-inspector
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
security-events: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
check:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v5
|
|
17
|
+
- uses: actions/setup-node@v5
|
|
18
|
+
with:
|
|
19
|
+
node-version: 24
|
|
20
|
+
cache: npm
|
|
21
|
+
- run: npm ci
|
|
22
|
+
- run: npx @openclaw/plugin-inspector ci --no-openclaw --runtime --mock-sdk --allow-execute
|
|
23
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
24
|
+
if: always()
|
|
25
|
+
with:
|
|
26
|
+
sarif_file: reports/plugin-inspector.sarif
|
|
27
|
+
- uses: actions/upload-artifact@v5
|
|
28
|
+
if: always()
|
|
29
|
+
with:
|
|
30
|
+
name: plugin-inspector-reports
|
|
31
|
+
path: reports/plugin-inspector-*
|
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
node-version: 24
|
|
16
16
|
cache: npm
|
|
17
17
|
- run: npm ci
|
|
18
|
-
- run:
|
|
18
|
+
- run: npx @openclaw/plugin-inspector ci --no-openclaw --runtime --mock-sdk --allow-execute
|
|
19
19
|
- uses: actions/upload-artifact@v5
|
|
20
20
|
if: always()
|
|
21
21
|
with:
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
plugin_inspector:
|
|
2
|
+
image: node:24
|
|
3
|
+
script:
|
|
4
|
+
- npm ci
|
|
5
|
+
- npx @openclaw/plugin-inspector ci --no-openclaw --runtime --mock-sdk --allow-execute
|
|
6
|
+
artifacts:
|
|
7
|
+
when: always
|
|
8
|
+
paths:
|
|
9
|
+
- reports/plugin-inspector-*
|
|
10
|
+
reports:
|
|
11
|
+
junit: reports/plugin-inspector.junit.xml
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"scripts": {
|
|
3
3
|
"plugin:check": "plugin-inspector inspect --no-openclaw",
|
|
4
|
-
"plugin:ci": "
|
|
4
|
+
"plugin:ci": "plugin-inspector ci --no-openclaw --runtime --mock-sdk --allow-execute"
|
|
5
5
|
},
|
|
6
6
|
"pluginInspector": {
|
|
7
7
|
"version": 1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/plugin-inspector",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Offline compatibility inspector for OpenClaw plugins.",
|
|
6
6
|
"type": "module",
|
|
@@ -36,18 +36,26 @@
|
|
|
36
36
|
"./ref-diff": "./src/ref-diff.js",
|
|
37
37
|
"./runtime-capture-report": "./src/runtime-capture-report.js",
|
|
38
38
|
"./runtime-profile": "./src/runtime-profile.js",
|
|
39
|
+
"./synthetic-probe-suite": "./src/synthetic-probe-suite.js",
|
|
40
|
+
"./synthetic-probes": "./src/synthetic-probes.js",
|
|
39
41
|
"./workspace-plan": "./src/workspace-plan.js"
|
|
40
42
|
},
|
|
41
43
|
"files": [
|
|
42
44
|
"src",
|
|
43
45
|
"examples",
|
|
46
|
+
"docs/plugin-inspector-banner.jpg",
|
|
44
47
|
"README.md",
|
|
45
48
|
"CHANGELOG.md",
|
|
46
49
|
"LICENSE"
|
|
47
50
|
],
|
|
48
51
|
"scripts": {
|
|
49
|
-
"check": "npm test && npm
|
|
52
|
+
"check": "npm test && npm run release:contents",
|
|
53
|
+
"release:crabpot": "node scripts/check-crabpot-followthrough.mjs",
|
|
54
|
+
"release:contents": "node scripts/check-package-contents.mjs",
|
|
55
|
+
"release:plan": "node scripts/release-plan.mjs",
|
|
56
|
+
"release:readiness": "npm run release:local && npm run release:crabpot",
|
|
50
57
|
"release:local": "npm run check",
|
|
58
|
+
"release:notes": "node scripts/release-notes.mjs --unreleased",
|
|
51
59
|
"test": "node --test test/*.test.js"
|
|
52
60
|
},
|
|
53
61
|
"keywords": [
|
package/src/advanced.js
CHANGED
|
@@ -136,8 +136,10 @@ export {
|
|
|
136
136
|
} from "./config.js";
|
|
137
137
|
export {
|
|
138
138
|
buildPluginInspectorConfig,
|
|
139
|
+
defaultInitPackageScripts,
|
|
139
140
|
defaultInitConfigPath,
|
|
140
141
|
defaultInitWorkflowPath,
|
|
142
|
+
detectPackageManager,
|
|
141
143
|
renderGithubActionsWorkflow,
|
|
142
144
|
writePluginInspectorInit,
|
|
143
145
|
} from "./init.js";
|
|
@@ -196,6 +198,7 @@ export {
|
|
|
196
198
|
validateSyntheticProbePlan,
|
|
197
199
|
writeSyntheticProbePlan,
|
|
198
200
|
} from "./synthetic-probes.js";
|
|
201
|
+
export { buildSyntheticProbePlanFromReport } from "./synthetic-probe-suite.js";
|
|
199
202
|
export {
|
|
200
203
|
buildWorkspacePlan,
|
|
201
204
|
defaultWorkspacePlanOptions,
|
|
@@ -203,3 +206,10 @@ export {
|
|
|
203
206
|
validateWorkspacePlan,
|
|
204
207
|
writeWorkspacePlan,
|
|
205
208
|
} from "./workspace-plan.js";
|
|
209
|
+
export {
|
|
210
|
+
inspectCompatibilityFixtureSetConfig,
|
|
211
|
+
renderFixtureSetIssuesReport,
|
|
212
|
+
renderFixtureSetMarkdownReport,
|
|
213
|
+
runFixtureSetReport,
|
|
214
|
+
writeFixtureSetReports,
|
|
215
|
+
} from "./api.js";
|
package/src/api.js
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { createCaptureApi } from "./capture-api.js";
|
|
3
3
|
import { loadInspectorConfig, loadPluginRootConfig } from "./config.js";
|
|
4
|
+
import { renderCompatibilityIssuesReport, renderCompatibilityMarkdownReport } from "./compatibility-report.js";
|
|
4
5
|
import { writePluginInspectorInit } from "./init.js";
|
|
5
6
|
import { captureEntrypoint } from "./inspector.js";
|
|
6
7
|
import { renderTextSummary, writeCompatibilityReport } from "./report.js";
|
|
7
8
|
import { writeCiOutputArtifacts } from "./ci-outputs.js";
|
|
8
9
|
import { buildRuntimeCaptureReport, writeRuntimeCaptureReport } from "./runtime-capture-report.js";
|
|
9
10
|
import { inspectCompatibilityFixtureSet, inspectFixtureSet } from "./inspector.js";
|
|
11
|
+
import {
|
|
12
|
+
buildColdImportReadiness,
|
|
13
|
+
renderColdImportReadinessMarkdown,
|
|
14
|
+
validateColdImportReadiness,
|
|
15
|
+
writeColdImportReadiness,
|
|
16
|
+
} from "./cold-import-readiness.js";
|
|
17
|
+
import {
|
|
18
|
+
buildWorkspacePlan,
|
|
19
|
+
renderWorkspacePlanMarkdown,
|
|
20
|
+
validateWorkspacePlan,
|
|
21
|
+
writeWorkspacePlan,
|
|
22
|
+
} from "./workspace-plan.js";
|
|
23
|
+
import {
|
|
24
|
+
buildPlatformProbes,
|
|
25
|
+
renderPlatformProbesMarkdown,
|
|
26
|
+
validatePlatformProbes,
|
|
27
|
+
writePlatformProbes,
|
|
28
|
+
} from "./platform-probes.js";
|
|
10
29
|
|
|
11
30
|
export async function loadPluginConfig(options = {}) {
|
|
12
31
|
if (options.config) {
|
|
@@ -35,6 +54,15 @@ export async function inspectFixtureSetConfig(options = {}) {
|
|
|
35
54
|
return inspectFixtureSet(config, { generatedAt: options.generatedAt });
|
|
36
55
|
}
|
|
37
56
|
|
|
57
|
+
export async function inspectCompatibilityFixtureSetConfig(options = {}) {
|
|
58
|
+
const config = await loadFixtureSetConfig(options);
|
|
59
|
+
return inspectCompatibilityFixtureSet(config, {
|
|
60
|
+
generatedAt: options.generatedAt,
|
|
61
|
+
openclawPath: options.openclawPath,
|
|
62
|
+
targetOpenClaw: options.targetOpenClaw,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
38
66
|
export async function writePluginReports(report, options = {}) {
|
|
39
67
|
return writeCompatibilityReport(report, {
|
|
40
68
|
basename: options.basename,
|
|
@@ -45,6 +73,130 @@ export async function writePluginReports(report, options = {}) {
|
|
|
45
73
|
});
|
|
46
74
|
}
|
|
47
75
|
|
|
76
|
+
export async function writeFixtureSetReports(report, options = {}) {
|
|
77
|
+
return writeCompatibilityReport(report, {
|
|
78
|
+
basename: options.basename,
|
|
79
|
+
check: options.check,
|
|
80
|
+
cwd: options.cwd,
|
|
81
|
+
formatEvidence: options.formatEvidence,
|
|
82
|
+
issuesBasename: options.issuesBasename,
|
|
83
|
+
issuesPath: options.issuesPath,
|
|
84
|
+
issuesTitle: options.issuesTitle,
|
|
85
|
+
jsonPath: options.jsonPath,
|
|
86
|
+
markdownPath: options.markdownPath,
|
|
87
|
+
markdownTitle: options.markdownTitle,
|
|
88
|
+
outDir: options.outDir,
|
|
89
|
+
severityLabels: options.severityLabels,
|
|
90
|
+
title: options.title,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function renderFixtureSetMarkdownReport(report, options = {}) {
|
|
95
|
+
return renderCompatibilityMarkdownReport(report, options);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function renderFixtureSetIssuesReport(report, options = {}) {
|
|
99
|
+
return renderCompatibilityIssuesReport(report, options);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export async function runFixtureSetReport(options = {}) {
|
|
103
|
+
const report = await inspectCompatibilityFixtureSetConfig(options);
|
|
104
|
+
const paths = options.write === false ? null : await writeFixtureSetReports(report, options);
|
|
105
|
+
return { report, paths };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function buildFixtureSetColdImportReadiness(options = {}) {
|
|
109
|
+
const config = options.report ? null : await loadFixtureSetConfig(options);
|
|
110
|
+
const report =
|
|
111
|
+
options.report ??
|
|
112
|
+
(await inspectCompatibilityFixtureSet(config, {
|
|
113
|
+
generatedAt: options.generatedAt,
|
|
114
|
+
openclawPath: options.openclawPath,
|
|
115
|
+
targetOpenClaw: options.targetOpenClaw,
|
|
116
|
+
}));
|
|
117
|
+
|
|
118
|
+
return buildColdImportReadiness({
|
|
119
|
+
...options,
|
|
120
|
+
report,
|
|
121
|
+
rootDir: options.rootDir ?? config?.rootDir ?? options.cwd,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function renderFixtureSetColdImportReadinessMarkdown(readiness, options = {}) {
|
|
126
|
+
return renderColdImportReadinessMarkdown(readiness, options);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function writeFixtureSetColdImportReadiness(readiness, options = {}) {
|
|
130
|
+
return writeColdImportReadiness(readiness, options);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function runFixtureSetColdImportReadiness(options = {}) {
|
|
134
|
+
const readiness = await buildFixtureSetColdImportReadiness(options);
|
|
135
|
+
const paths = options.write === false ? null : await writeFixtureSetColdImportReadiness(readiness, options);
|
|
136
|
+
return { readiness, paths };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export async function buildFixtureSetWorkspacePlan(options = {}) {
|
|
140
|
+
const config = options.report ? null : await loadFixtureSetConfig(options);
|
|
141
|
+
const report =
|
|
142
|
+
options.report ??
|
|
143
|
+
(await inspectCompatibilityFixtureSet(config, {
|
|
144
|
+
generatedAt: options.generatedAt,
|
|
145
|
+
openclawPath: options.openclawPath,
|
|
146
|
+
targetOpenClaw: options.targetOpenClaw,
|
|
147
|
+
}));
|
|
148
|
+
const rootDir = options.rootDir ?? config?.rootDir ?? options.cwd;
|
|
149
|
+
const readiness = options.readiness ?? buildColdImportReadiness({ ...options, report, rootDir });
|
|
150
|
+
|
|
151
|
+
return buildWorkspacePlan({
|
|
152
|
+
...options,
|
|
153
|
+
report,
|
|
154
|
+
readiness,
|
|
155
|
+
rootDir,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function renderFixtureSetWorkspacePlanMarkdown(plan, options = {}) {
|
|
160
|
+
return renderWorkspacePlanMarkdown(plan, options);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function validateFixtureSetWorkspacePlan(plan, options = {}) {
|
|
164
|
+
return validateWorkspacePlan(plan, options);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export async function writeFixtureSetWorkspacePlan(plan, options = {}) {
|
|
168
|
+
return writeWorkspacePlan(plan, options);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export async function runFixtureSetWorkspacePlan(options = {}) {
|
|
172
|
+
const plan = await buildFixtureSetWorkspacePlan(options);
|
|
173
|
+
const paths = options.write === false ? null : await writeFixtureSetWorkspacePlan(plan, options);
|
|
174
|
+
return { plan, paths };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export async function buildFixtureSetPlatformProbes(options = {}) {
|
|
178
|
+
const plan = options.plan ?? (await buildFixtureSetWorkspacePlan(options));
|
|
179
|
+
return buildPlatformProbes({ ...options, plan });
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function renderFixtureSetPlatformProbesMarkdown(report, options = {}) {
|
|
183
|
+
return renderPlatformProbesMarkdown(report, options);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function validateFixtureSetPlatformProbes(report, options = {}) {
|
|
187
|
+
return validatePlatformProbes(report, options);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export async function writeFixtureSetPlatformProbes(report, options = {}) {
|
|
191
|
+
return writePlatformProbes(report, options);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export async function runFixtureSetPlatformProbes(options = {}) {
|
|
195
|
+
const report = await buildFixtureSetPlatformProbes(options);
|
|
196
|
+
const paths = options.write === false ? null : await writeFixtureSetPlatformProbes(report, options);
|
|
197
|
+
return { report, paths };
|
|
198
|
+
}
|
|
199
|
+
|
|
48
200
|
export async function runPluginCheck(options = {}) {
|
|
49
201
|
const outDir = options.outDir ?? "reports";
|
|
50
202
|
const config = await loadPluginConfig(options);
|
|
@@ -55,8 +207,8 @@ export async function runPluginCheck(options = {}) {
|
|
|
55
207
|
const mockSdk = options.mockSdk ?? config.capture?.mockSdk ?? true;
|
|
56
208
|
|
|
57
209
|
if (capture === true) {
|
|
58
|
-
if (
|
|
59
|
-
throw new Error("runtime capture imports plugin code; rerun with PLUGIN_INSPECTOR_EXECUTE_ISOLATED=1 in an isolated workspace");
|
|
210
|
+
if (!executionAllowed(options)) {
|
|
211
|
+
throw new Error("runtime capture imports plugin code; rerun with PLUGIN_INSPECTOR_EXECUTE_ISOLATED=1 or --allow-execute in an isolated workspace");
|
|
60
212
|
}
|
|
61
213
|
const runtimeCapture = await buildRuntimeCaptureReport({
|
|
62
214
|
mockSdk,
|
|
@@ -89,4 +241,18 @@ export async function setupPluginInspector(options = {}) {
|
|
|
89
241
|
return writePluginInspectorInit(options);
|
|
90
242
|
}
|
|
91
243
|
|
|
92
|
-
export { createCaptureApi, renderTextSummary, writeCiOutputArtifacts };
|
|
244
|
+
export { createCaptureApi, renderTextSummary, validateColdImportReadiness, writeCiOutputArtifacts };
|
|
245
|
+
|
|
246
|
+
function executionAllowed(options) {
|
|
247
|
+
return options.allowExecution === true || process.env.PLUGIN_INSPECTOR_EXECUTE_ISOLATED === "1";
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
async function loadFixtureSetConfig(options) {
|
|
251
|
+
if (options.config) {
|
|
252
|
+
return {
|
|
253
|
+
...options.config,
|
|
254
|
+
rootDir: options.config.rootDir ?? options.rootDir ?? options.cwd ?? process.cwd(),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return loadInspectorConfig(options.configPath, { cwd: options.cwd ?? options.rootDir });
|
|
258
|
+
}
|
package/src/capture-api.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const defaultCaptureApiRegistrarProfiles = {
|
|
2
2
|
registerChannel: {
|
|
3
|
-
returnValue: ({ args }) =>
|
|
3
|
+
returnValue: ({ args }) => channelRegistrationObject(args),
|
|
4
4
|
},
|
|
5
5
|
registerCli: {
|
|
6
6
|
returnValue: ({ args }) => registrationObject(args, { name: "cli" }),
|
|
@@ -12,7 +12,7 @@ export const defaultCaptureApiRegistrarProfiles = {
|
|
|
12
12
|
returnValue: ({ args }) => registrationObject(args, { id: "context-engine" }),
|
|
13
13
|
},
|
|
14
14
|
registerGatewayMethod: {
|
|
15
|
-
returnValue: ({ args }) =>
|
|
15
|
+
returnValue: ({ args }) => gatewayMethodRegistrationObject(args),
|
|
16
16
|
},
|
|
17
17
|
registerHook: {
|
|
18
18
|
returnValue: ({ api }) => api,
|
|
@@ -37,9 +37,10 @@ export const defaultCaptureApiRegistrarProfiles = {
|
|
|
37
37
|
},
|
|
38
38
|
registerService: {
|
|
39
39
|
returnValue: ({ args }) => ({
|
|
40
|
-
...registrationObject(args, { name: "service" }),
|
|
40
|
+
...registrationObject(args, { id: "service", name: "service" }),
|
|
41
41
|
start: async () => undefined,
|
|
42
42
|
stop: async () => undefined,
|
|
43
|
+
dispose: async () => undefined,
|
|
43
44
|
}),
|
|
44
45
|
},
|
|
45
46
|
registerSpeechProvider: {
|
|
@@ -125,6 +126,7 @@ export function createCaptureApi(options = {}) {
|
|
|
125
126
|
|
|
126
127
|
export function createCaptureContext(options = {}) {
|
|
127
128
|
return {
|
|
129
|
+
registrationMode: options.registrationMode ?? "full",
|
|
128
130
|
config: options.config ?? {},
|
|
129
131
|
logger: options.logger ?? console,
|
|
130
132
|
pluginConfig: options.pluginConfig ?? {},
|
|
@@ -142,6 +144,12 @@ export function createCaptureContext(options = {}) {
|
|
|
142
144
|
},
|
|
143
145
|
gateway: options.gateway ?? {
|
|
144
146
|
baseUrl: "http://127.0.0.1:0",
|
|
147
|
+
async call(method, params) {
|
|
148
|
+
return { ok: true, method, params };
|
|
149
|
+
},
|
|
150
|
+
respond(ok, result, error) {
|
|
151
|
+
return { ok, result, ...(error ? { error } : {}) };
|
|
152
|
+
},
|
|
145
153
|
registerRoute(route) {
|
|
146
154
|
return {
|
|
147
155
|
...route,
|
|
@@ -242,6 +250,36 @@ function registrationObject(args, defaults) {
|
|
|
242
250
|
return withCallableDefaults({ ...defaults }, callable);
|
|
243
251
|
}
|
|
244
252
|
|
|
253
|
+
function channelRegistrationObject(args) {
|
|
254
|
+
const first = args[0];
|
|
255
|
+
const registration = registrationObject(args, { id: "channel" });
|
|
256
|
+
if (first?.plugin && typeof first.plugin === "object") {
|
|
257
|
+
return {
|
|
258
|
+
...registration,
|
|
259
|
+
id: objectId(first.plugin) ?? registration.id,
|
|
260
|
+
plugin: first.plugin,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
return registration;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function gatewayMethodRegistrationObject(args) {
|
|
267
|
+
const [method, handler, options] = args;
|
|
268
|
+
const registration = registrationObject(args, { name: "gateway.method" });
|
|
269
|
+
if (typeof method !== "string") {
|
|
270
|
+
return registration;
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
...registration,
|
|
274
|
+
name: method,
|
|
275
|
+
method,
|
|
276
|
+
handler: typeof handler === "function" ? handler : registration.handler,
|
|
277
|
+
run: typeof handler === "function" ? handler : registration.run,
|
|
278
|
+
execute: typeof handler === "function" ? handler : registration.execute,
|
|
279
|
+
scope: options?.scope ?? registration.scope,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
245
283
|
function firstCallable(args) {
|
|
246
284
|
return args.find((arg) => typeof arg === "function");
|
|
247
285
|
}
|