Skip to content

Commit d221d7b

Browse files
ProspectOresteipete
authored andcommitted
fix(plugins): isolate peer-link repair failures
1 parent 4d248b8 commit d221d7b

2 files changed

Lines changed: 93 additions & 6 deletions

File tree

src/plugins/update.test.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,87 @@ describe("updateNpmInstalledPlugins", () => {
994994
}
995995
});
996996

997+
it("continues repairing sibling openclaw peer links after one recorded npm install cannot be relinked", async () => {
998+
const plugins = [
999+
{ pluginId: "brave", packageName: "@openclaw/brave-plugin" },
1000+
{ pluginId: "codex", packageName: "@openclaw/codex" },
1001+
];
1002+
const { installPaths, peerLinkPath, linkPeer } = createOpenClawPeerLinkFixtures(plugins);
1003+
const brokenInstallPath = createInstalledPackageDir({
1004+
name: "@openclaw/broken-plugin",
1005+
version: "2026.5.4",
1006+
peerDependencies: { openclaw: ">=2026.5.4" },
1007+
});
1008+
fs.writeFileSync(path.join(brokenInstallPath, "node_modules"), "not a directory");
1009+
linkPeer("brave");
1010+
mockNpmViewMetadata({
1011+
name: "@openclaw/codex",
1012+
version: "2026.5.4",
1013+
integrity: "sha512-same",
1014+
shasum: "same",
1015+
});
1016+
installPluginFromNpmSpecMock.mockImplementation(() => {
1017+
for (const { pluginId } of plugins) {
1018+
fs.rmSync(peerLinkPath(pluginId), { recursive: true, force: true });
1019+
}
1020+
linkPeer("codex");
1021+
return Promise.resolve(
1022+
createSuccessfulNpmUpdateResult({
1023+
pluginId: "codex",
1024+
targetDir: installPaths.codex,
1025+
version: "2026.5.4",
1026+
npmResolution: {
1027+
name: "@openclaw/codex",
1028+
version: "2026.5.4",
1029+
resolvedSpec: "@openclaw/codex@2026.5.4",
1030+
},
1031+
}),
1032+
);
1033+
});
1034+
const warnMessages: string[] = [];
1035+
1036+
await updateNpmInstalledPlugins({
1037+
config: {
1038+
plugins: {
1039+
installs: {
1040+
broken: {
1041+
source: "npm",
1042+
spec: "@openclaw/broken-plugin",
1043+
installPath: brokenInstallPath,
1044+
resolvedName: "@openclaw/broken-plugin",
1045+
resolvedVersion: "2026.5.4",
1046+
resolvedSpec: "@openclaw/broken-plugin@2026.5.4",
1047+
},
1048+
...Object.fromEntries(
1049+
plugins.map(({ pluginId, packageName }) => [
1050+
pluginId,
1051+
{
1052+
source: "npm",
1053+
spec: packageName,
1054+
installPath: installPaths[pluginId],
1055+
resolvedName: packageName,
1056+
resolvedVersion: "2026.5.4",
1057+
resolvedSpec: `${packageName}@2026.5.4`,
1058+
integrity: "sha512-same",
1059+
shasum: "same",
1060+
},
1061+
]),
1062+
),
1063+
},
1064+
},
1065+
},
1066+
pluginIds: ["codex"],
1067+
logger: { warn: (message) => warnMessages.push(message) },
1068+
});
1069+
1070+
expect(installPluginFromNpmSpecMock).toHaveBeenCalledTimes(1);
1071+
expect(fs.existsSync(peerLinkPath("brave"))).toBe(true);
1072+
expect(fs.existsSync(peerLinkPath("codex"))).toBe(true);
1073+
expect(warnMessages).toContainEqual(
1074+
expect.stringContaining('Could not repair openclaw peer link for "broken"'),
1075+
);
1076+
});
1077+
9971078
it("refreshes legacy npm install records before skipping unchanged artifacts", async () => {
9981079
const installPath = createInstalledPackageDir({
9991080
name: "@martian-engineering/lossless-claw",

src/plugins/update.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,12 +791,18 @@ async function repairOpenClawPeerLinksForNpmInstalls(params: {
791791
continue;
792792
}
793793

794-
await linkOpenClawPeerDependencies({
795-
installedDir: installPath,
796-
peerDependencies,
797-
logger: params.logger,
798-
});
799-
repaired = !installedPackageNeedsOpenClawPeerLinkRepair(installPath) || repaired;
794+
try {
795+
await linkOpenClawPeerDependencies({
796+
installedDir: installPath,
797+
peerDependencies,
798+
logger: params.logger,
799+
});
800+
repaired = !installedPackageNeedsOpenClawPeerLinkRepair(installPath) || repaired;
801+
} catch (err) {
802+
params.logger.warn?.(
803+
`Could not repair openclaw peer link for "${pluginId}" at ${installPath}: ${String(err)}`,
804+
);
805+
}
800806
}
801807
return repaired;
802808
}

0 commit comments

Comments
 (0)