diff --git a/scripts/lib/bundled-plugin-root-runtime-mirrors.mjs b/scripts/lib/bundled-plugin-root-runtime-mirrors.mjs index 4d2347ddaec..c15d2b0a26a 100644 --- a/scripts/lib/bundled-plugin-root-runtime-mirrors.mjs +++ b/scripts/lib/bundled-plugin-root-runtime-mirrors.mjs @@ -190,6 +190,13 @@ export function collectRootDistBundledRuntimeMirrors(params) { export function collectBundledPluginRootRuntimeMirrorErrors(params) { const errors = []; const declaredRootRuntimeDeps = collectRuntimeDependencySpecs(params.rootPackageJson); + const declaredMirrorDeps = + params.rootPackageJson?.openclaw?.bundle?.mirroredRootRuntimeDependencies ?? []; + const declaredMirrorDepNames = new Set( + Array.isArray(declaredMirrorDeps) + ? declaredMirrorDeps.filter((dependencyName) => typeof dependencyName === "string") + : [], + ); for (const [dependencyName, record] of params.bundledRuntimeDependencySpecs) { for (const conflict of record.conflicts) { @@ -201,6 +208,14 @@ export function collectBundledPluginRootRuntimeMirrorErrors(params) { for (const [dependencyName, record] of params.requiredRootMirrors) { if (declaredRootRuntimeDeps.has(dependencyName)) { + if (!declaredMirrorDepNames.has(dependencyName)) { + const importerList = Array.from(record.importers) + .toSorted((left, right) => left.localeCompare(right)) + .join(", "); + errors.push( + `installed package root mirror '${dependencyName}' for dist importers: ${importerList} is missing from package.json openclaw.bundle.mirroredRootRuntimeDependencies. Add it there so packaged runtime installs the mirrored dependency, or keep imports under dist/extensions/${record.pluginIds[0]}/.`, + ); + } continue; } const importerList = Array.from(record.importers) diff --git a/test/release-check.test.ts b/test/release-check.test.ts index e8655ba205e..d951bdfd018 100644 --- a/test/release-check.test.ts +++ b/test/release-check.test.ts @@ -384,11 +384,39 @@ describe("bundled plugin root runtime mirrors", () => { }, ], ]), - rootPackageJson: { dependencies: { "@larksuiteoapi/node-sdk": "^1.61.0" } }, + rootPackageJson: { + dependencies: { "@larksuiteoapi/node-sdk": "^1.61.0" }, + openclaw: { + bundle: { + mirroredRootRuntimeDependencies: ["@larksuiteoapi/node-sdk"], + }, + }, + }, }), ).toEqual([]); }); + it("flags root mirrors omitted from mirrored root runtime metadata", () => { + expect( + collectBundledPluginRootRuntimeMirrorErrors({ + bundledRuntimeDependencySpecs: makeBundledSpecs(), + requiredRootMirrors: new Map([ + [ + "@larksuiteoapi/node-sdk", + { + importers: new Set(["probe-Cz2PiFtC.js"]), + pluginIds: ["feishu"], + spec: "^1.60.0", + }, + ], + ]), + rootPackageJson: { dependencies: { "@larksuiteoapi/node-sdk": "^1.60.0" } }, + }), + ).toEqual([ + "installed package root mirror '@larksuiteoapi/node-sdk' for dist importers: probe-Cz2PiFtC.js is missing from package.json openclaw.bundle.mirroredRootRuntimeDependencies. Add it there so packaged runtime installs the mirrored dependency, or keep imports under dist/extensions/feishu/.", + ]); + }); + it("accepts matching root mirrors for plugin deps imported by root dist", () => { expect( collectBundledPluginRootRuntimeMirrorErrors({ @@ -403,7 +431,14 @@ describe("bundled plugin root runtime mirrors", () => { }, ], ]), - rootPackageJson: { dependencies: { "@larksuiteoapi/node-sdk": "^1.60.0" } }, + rootPackageJson: { + dependencies: { "@larksuiteoapi/node-sdk": "^1.60.0" }, + openclaw: { + bundle: { + mirroredRootRuntimeDependencies: ["@larksuiteoapi/node-sdk"], + }, + }, + }, }), ).toEqual([]); });