fix(build): strip local workspace deps from staged plugin manifests

This commit is contained in:
Vincent Koc
2026-04-07 09:40:38 +01:00
parent fb64ba7bf7
commit eac6e2d42d
2 changed files with 54 additions and 13 deletions

View File

@@ -143,25 +143,55 @@ function shouldStageRuntimeDeps(packageJson) {
return packageJson.openclaw?.bundle?.stageRuntimeDependencies === true;
}
function removeSanitizedDependencyEntries(entries, shouldRemove) {
if (!entries || typeof entries !== "object") {
return { changed: false, nextEntries: entries };
}
const nextEntries = Object.fromEntries(
Object.entries(entries).filter(([depName, spec]) => !shouldRemove(depName, spec)),
);
const changed = Object.keys(nextEntries).length !== Object.keys(entries).length;
return {
changed,
nextEntries: changed
? Object.keys(nextEntries).length > 0
? nextEntries
: undefined
: entries,
};
}
function shouldRemoveLocalWorkspaceDependency(depName, spec) {
return depName === "openclaw" || (typeof spec === "string" && spec.startsWith("workspace:"));
}
function sanitizeBundledManifestForRuntimeInstall(pluginDir) {
const manifestPath = path.join(pluginDir, "package.json");
const packageJson = readJson(manifestPath);
let changed = false;
if (packageJson.peerDependencies?.openclaw) {
const nextPeerDependencies = { ...packageJson.peerDependencies };
delete nextPeerDependencies.openclaw;
if (Object.keys(nextPeerDependencies).length === 0) {
delete packageJson.peerDependencies;
} else {
const { changed: peerDependenciesChanged, nextEntries: nextPeerDependencies } =
removeSanitizedDependencyEntries(
packageJson.peerDependencies,
shouldRemoveLocalWorkspaceDependency,
);
if (peerDependenciesChanged) {
if (nextPeerDependencies) {
packageJson.peerDependencies = nextPeerDependencies;
} else {
delete packageJson.peerDependencies;
}
changed = true;
}
if (packageJson.peerDependenciesMeta?.openclaw) {
const nextPeerDependenciesMeta = { ...packageJson.peerDependenciesMeta };
delete nextPeerDependenciesMeta.openclaw;
if (peerDependenciesChanged && packageJson.peerDependenciesMeta) {
const allowedPeerNames = new Set(Object.keys(packageJson.peerDependencies ?? {}));
const nextPeerDependenciesMeta = Object.fromEntries(
Object.entries(packageJson.peerDependenciesMeta).filter(([depName]) =>
allowedPeerNames.has(depName),
),
);
if (Object.keys(nextPeerDependenciesMeta).length === 0) {
delete packageJson.peerDependenciesMeta;
} else {

View File

@@ -29,11 +29,20 @@ describe("stageBundledPluginRuntimeDeps", () => {
name: "@openclaw/fixture-plugin",
version: "1.0.0",
dependencies: { "left-pad": "1.3.0" },
peerDependencies: { openclaw: "^1.0.0" },
peerDependenciesMeta: { openclaw: { optional: true } },
devDependencies: {
openclaw: "^1.0.0",
peerDependencies: {
"@openclaw/plugin-sdk": "workspace:*",
openclaw: "^1.0.0",
react: "^19.0.0",
},
peerDependenciesMeta: {
"@openclaw/plugin-sdk": { optional: true },
openclaw: { optional: true },
react: { optional: true },
},
devDependencies: {
"@openclaw/plugin-sdk": "workspace:*",
openclaw: "^1.0.0",
typescript: "^5.9.0",
},
openclaw: { bundle: { stageRuntimeDependencies: true } },
},
@@ -67,6 +76,8 @@ describe("stageBundledPluginRuntimeDeps", () => {
name: "@openclaw/fixture-plugin",
version: "1.0.0",
dependencies: { "left-pad": "1.3.0" },
peerDependencies: { react: "^19.0.0" },
peerDependenciesMeta: { react: { optional: true } },
openclaw: { bundle: { stageRuntimeDependencies: true } },
});
});