fix(plugins): harden install ledger path handling

This commit is contained in:
Vincent Koc
2026-04-25 11:46:06 -07:00
parent dc19069d71
commit 9bd348fdec
6 changed files with 101 additions and 10 deletions

View File

@@ -273,6 +273,7 @@ describe("updateNpmInstalledPlugins", () => {
});
afterEach(() => {
vi.unstubAllEnvs();
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
}
@@ -410,6 +411,47 @@ describe("updateNpmInstalledPlugins", () => {
]);
});
it("expands home-relative install paths before checking installed npm versions", async () => {
const home = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-plugin-update-home-"));
tempDirs.push(home);
const installPath = path.join(home, ".openclaw", "extensions", "lossless-claw");
fs.mkdirSync(installPath, { recursive: true });
fs.writeFileSync(
path.join(installPath, "package.json"),
JSON.stringify({ name: "@martian-engineering/lossless-claw", version: "0.9.0" }),
);
vi.stubEnv("HOME", home);
mockNpmViewMetadata({
name: "@martian-engineering/lossless-claw",
version: "0.9.0",
integrity: "sha512-same",
shasum: "same",
});
installPluginFromNpmSpecMock.mockRejectedValue(new Error("installer should not run"));
const result = await updateNpmInstalledPlugins({
config: createNpmInstallConfig({
pluginId: "lossless-claw",
spec: "@martian-engineering/lossless-claw",
installPath: "~/.openclaw/extensions/lossless-claw",
resolvedName: "@martian-engineering/lossless-claw",
resolvedSpec: "@martian-engineering/lossless-claw@0.9.0",
integrity: "sha512-same",
}),
pluginIds: ["lossless-claw"],
});
expect(installPluginFromNpmSpecMock).not.toHaveBeenCalled();
expect(result.changed).toBe(false);
expect(result.outcomes).toEqual([
expect.objectContaining({
pluginId: "lossless-claw",
status: "unchanged",
currentVersion: "0.9.0",
}),
]);
});
it("falls through to npm reinstall when the recorded integrity differs", async () => {
const installPath = createInstalledPackageDir({
name: "@martian-engineering/lossless-claw",

View File

@@ -523,7 +523,9 @@ export async function updateNpmInstalledPlugins(params: {
let installPath: string;
try {
installPath = record.installPath ?? resolvePluginInstallDir(pluginId);
installPath = resolveUserPath(
record.installPath?.trim() || resolvePluginInstallDir(pluginId),
);
} catch (err) {
outcomes.push({
pluginId,