diff --git a/scripts/postinstall-bundled-plugins.mjs b/scripts/postinstall-bundled-plugins.mjs index 8dc2ba5832d..553fe9cfbe9 100644 --- a/scripts/postinstall-bundled-plugins.mjs +++ b/scripts/postinstall-bundled-plugins.mjs @@ -117,6 +117,11 @@ const BAILEYS_MEDIA_ONCE_IMPORT_RE = /import\s+\{\s*once\s*\}\s+from\s+['"]event const BAILEYS_MEDIA_ASYNC_CONTEXT_RE = /async\s+function\s+encryptedStream|encryptedStream\s*=\s*async/u; +function hasEnvFlag(env, key) { + const value = env?.[key]?.trim().toLowerCase(); + return Boolean(value && value !== "0" && value !== "false" && value !== "no"); +} + function readJson(filePath) { return JSON.parse(readFileSync(filePath, "utf8")); } @@ -666,7 +671,7 @@ export async function runPluginRegistryPostinstallMigration(params = {}) { const packageRoot = params.packageRoot ?? DEFAULT_PACKAGE_ROOT; const env = params.env ?? process.env; - if (env[DISABLE_PLUGIN_REGISTRY_MIGRATION_ENV]?.trim()) { + if (hasEnvFlag(env, DISABLE_PLUGIN_REGISTRY_MIGRATION_ENV)) { return { status: "disabled", migrated: false, reason: "disabled-env" }; } diff --git a/src/commands/doctor/shared/plugin-registry-migration.test.ts b/src/commands/doctor/shared/plugin-registry-migration.test.ts index 3511a025650..413a0dfa1f5 100644 --- a/src/commands/doctor/shared/plugin-registry-migration.test.ts +++ b/src/commands/doctor/shared/plugin-registry-migration.test.ts @@ -12,6 +12,7 @@ import { makeTrackedTempDir, } from "../../../plugins/test-helpers/fs-fixtures.js"; import { + DISABLE_PLUGIN_REGISTRY_MIGRATION_ENV, FORCE_PLUGIN_REGISTRY_MIGRATION_ENV, migratePluginRegistryForInstall, preflightPluginRegistryInstallMigration, @@ -268,4 +269,23 @@ describe("plugin registry install migration", () => { ], }); }); + + it("treats falsey env flag strings as unset", async () => { + const stateDir = makeTempDir(); + await writePersistedInstalledPluginIndex(createCurrentIndex(), { stateDir }); + + expect( + preflightPluginRegistryInstallMigration({ + stateDir, + env: hermeticEnv({ + [DISABLE_PLUGIN_REGISTRY_MIGRATION_ENV]: "0", + [FORCE_PLUGIN_REGISTRY_MIGRATION_ENV]: "false", + }), + }), + ).toMatchObject({ + action: "skip-existing", + force: false, + deprecationWarnings: [], + }); + }); }); diff --git a/src/commands/doctor/shared/plugin-registry-migration.ts b/src/commands/doctor/shared/plugin-registry-migration.ts index 8feb62a6713..f94e34bca5e 100644 --- a/src/commands/doctor/shared/plugin-registry-migration.ts +++ b/src/commands/doctor/shared/plugin-registry-migration.ts @@ -57,7 +57,8 @@ export type PluginRegistryInstallMigrationParams = LoadInstalledPluginIndexParam }; function hasEnvFlag(env: NodeJS.ProcessEnv | undefined, key: string): boolean { - return Boolean(env?.[key]?.trim()); + const value = env?.[key]?.trim().toLowerCase(); + return Boolean(value && value !== "0" && value !== "false" && value !== "no"); } function forceDeprecationWarning(): string { diff --git a/test/scripts/postinstall-bundled-plugins.test.ts b/test/scripts/postinstall-bundled-plugins.test.ts index ee0d08f9a7f..63a9b5152da 100644 --- a/test/scripts/postinstall-bundled-plugins.test.ts +++ b/test/scripts/postinstall-bundled-plugins.test.ts @@ -349,6 +349,33 @@ describe("bundled plugin postinstall", () => { expect(importModule).not.toHaveBeenCalled(); }); + it("does not disable plugin registry migration for falsey env flag strings", async () => { + const migratePluginRegistryForInstall = vi.fn(async () => ({ + status: "skip-existing", + migrated: false, + preflight: {}, + })); + const importModule = vi.fn(async () => ({ migratePluginRegistryForInstall })); + + await expect( + runPluginRegistryPostinstallMigration({ + packageRoot: "/pkg", + env: { OPENCLAW_DISABLE_PLUGIN_REGISTRY_MIGRATION: "0" }, + existsSync: vi.fn(() => true), + importModule, + log: { log: vi.fn(), warn: vi.fn() }, + }), + ).resolves.toMatchObject({ + status: "skip-existing", + migrated: false, + }); + expect(importModule).toHaveBeenCalledOnce(); + expect(migratePluginRegistryForInstall).toHaveBeenCalledWith({ + env: { OPENCLAW_DISABLE_PLUGIN_REGISTRY_MIGRATION: "0" }, + packageRoot: "/pkg", + }); + }); + it("prunes stale dist files from packaged installs", async () => { const packageRoot = await createTempDirAsync("openclaw-packaged-install-"); const currentFile = path.join(packageRoot, "dist", "channel-BOa4MfoC.js");