























@@ -10,6 +10,7 @@ import {
1010discoverBundledPluginRuntimeDeps,
1111pruneBundledPluginSourceNodeModules,
1212runBundledPluginPostinstall,
13+runPluginRegistryPostinstallMigration,
1314restoreLegacyUpdaterCompatSidecars,
1415} from "../../scripts/postinstall-bundled-plugins.mjs";
1516import { NPM_UPDATE_COMPAT_SIDECARS } from "../../src/infra/npm-update-compat-sidecars.ts";
@@ -247,6 +248,95 @@ describe("bundled plugin postinstall", () => {
247248await expect(fs.stat(path.join(extensionsDir, "acpx", "node_modules"))).resolves.toBeTruthy();
248249});
249250251+it("migrates the plugin registry during postinstall from built dist contracts", async () => {
252+const packageRoot = await createTempDirAsync("openclaw-postinstall-registry-");
253+const log = { log: vi.fn(), warn: vi.fn() };
254+const readBestEffortConfig = vi.fn(async () => ({
255+plugins: {
256+installs: {
257+demo: {
258+source: "npm",
259+resolvedName: "@vendor/demo",
260+resolvedVersion: "1.0.0",
261+},
262+},
263+},
264+}));
265+const ensurePluginRegistryMigrated = vi.fn(async () => ({
266+migrated: true,
267+current: {
268+plugins: [{ pluginId: "demo" }],
269+},
270+}));
271+const importModule = vi.fn(async (specifier: string) => {
272+if (specifier.endsWith("/dist/config/config.js")) {
273+return { readBestEffortConfig };
274+}
275+if (specifier.endsWith("/dist/plugins/plugin-registry.js")) {
276+return { ensurePluginRegistryMigrated };
277+}
278+throw new Error(`unexpected import: ${specifier}`);
279+});
280+281+const result = await runPluginRegistryPostinstallMigration({
282+ packageRoot,
283+existsSync: vi.fn(
284+(filePath: string) =>
285+filePath.endsWith(path.join("dist", "config", "config.js")) ||
286+filePath.endsWith(path.join("dist", "plugins", "plugin-registry.js")),
287+),
288+ importModule,
289+env: { OPENCLAW_HOME: "/tmp/home" },
290+ log,
291+});
292+293+expect(result).toMatchObject({ status: "migrated" });
294+expect(readBestEffortConfig).toHaveBeenCalled();
295+expect(ensurePluginRegistryMigrated).toHaveBeenCalledWith({
296+config: {
297+plugins: {
298+installs: {
299+demo: {
300+source: "npm",
301+resolvedName: "@vendor/demo",
302+resolvedVersion: "1.0.0",
303+},
304+},
305+},
306+},
307+env: { OPENCLAW_HOME: "/tmp/home" },
308+ packageRoot,
309+});
310+expect(log.log).toHaveBeenCalledWith(
311+"[postinstall] migrated plugin registry: 1 plugin(s) indexed",
312+);
313+});
314+315+it("keeps plugin registry postinstall migration non-fatal when dist entries are unavailable", async () => {
316+const warn = vi.fn();
317+318+await expect(
319+runPluginRegistryPostinstallMigration({
320+packageRoot: "/pkg",
321+existsSync: vi.fn(() => false),
322+log: { log: vi.fn(), warn },
323+}),
324+).resolves.toEqual({
325+status: "skipped",
326+reason: "missing-dist-entry",
327+});
328+expect(warn).not.toHaveBeenCalled();
329+});
330+331+it("honors plugin registry postinstall migration disable env", async () => {
332+await expect(
333+runPluginRegistryPostinstallMigration({
334+env: { OPENCLAW_DISABLE_PLUGIN_REGISTRY_MIGRATION: "1" },
335+log: { log: vi.fn(), warn: vi.fn() },
336+}),
337+).resolves.toEqual({ status: "disabled" });
338+});
339+250340it("prunes stale dist files from packaged installs", async () => {
251341const packageRoot = await createTempDirAsync("openclaw-packaged-install-");
252342const currentFile = path.join(packageRoot, "dist", "channel-BOa4MfoC.js");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。