diff --git a/scripts/e2e/parallels-macos-smoke.sh b/scripts/e2e/parallels-macos-smoke.sh index 53a7f873153..0af5e9c29c7 100644 --- a/scripts/e2e/parallels-macos-smoke.sh +++ b/scripts/e2e/parallels-macos-smoke.sh @@ -49,7 +49,7 @@ BUILD_LOCK_DIR="${TMPDIR:-/tmp}/openclaw-parallels-build.lock" TIMEOUT_INSTALL_SITE_S=420 TIMEOUT_INSTALL_TGZ_S=420 TIMEOUT_INSTALL_REGISTRY_S=420 -TIMEOUT_UPDATE_DEV_S="${OPENCLAW_PARALLELS_MACOS_UPDATE_DEV_TIMEOUT_S:-1200}" +TIMEOUT_UPDATE_DEV_S="${OPENCLAW_PARALLELS_MACOS_UPDATE_DEV_TIMEOUT_S:-1800}" TIMEOUT_VERIFY_S=60 TIMEOUT_ONBOARD_S=180 TIMEOUT_GATEWAY_S=180 diff --git a/scripts/postinstall-bundled-plugins.mjs b/scripts/postinstall-bundled-plugins.mjs index b0ef9c53059..e3e32e8846d 100644 --- a/scripts/postinstall-bundled-plugins.mjs +++ b/scripts/postinstall-bundled-plugins.mjs @@ -21,6 +21,7 @@ import { unlinkSync, writeFileSync, } from "node:fs"; +import { tmpdir } from "node:os"; import { basename, dirname, isAbsolute, join, posix, relative } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import { resolveNpmRunner } from "./npm-runner.mjs"; @@ -861,6 +862,29 @@ function shouldRunBundledPluginPostinstall(params) { return true; } +export function pruneOpenClawCompileCache(params = {}) { + const env = params.env ?? process.env; + const pathExists = params.existsSync ?? existsSync; + const remove = params.rmSync ?? rmSync; + const log = params.log ?? console; + const baseDirs = [ + env.NODE_DISABLE_COMPILE_CACHE ? "" : env.NODE_COMPILE_CACHE, + join(tmpdir(), "node-compile-cache"), + ].filter((value, index, values) => value && values.indexOf(value) === index); + + for (const baseDir of baseDirs) { + const cacheRoot = join(baseDir, "openclaw"); + if (!pathExists(cacheRoot)) { + continue; + } + try { + remove(cacheRoot, { recursive: true, force: true, maxRetries: 2, retryDelay: 100 }); + } catch (error) { + log.warn?.(`[postinstall] could not prune OpenClaw compile cache: ${String(error)}`); + } + } +} + export function runBundledPluginPostinstall(params = {}) { const env = params.env ?? process.env; const packageRoot = params.packageRoot ?? DEFAULT_PACKAGE_ROOT; @@ -871,6 +895,12 @@ export function runBundledPluginPostinstall(params = {}) { if (env?.[DISABLE_POSTINSTALL_ENV]?.trim()) { return; } + pruneOpenClawCompileCache({ + env, + existsSync: pathExists, + rmSync: params.rmSync, + log, + }); if (isSourceCheckoutRoot({ packageRoot, existsSync: pathExists })) { try { pruneBundledPluginSourceNodeModules({ diff --git a/test/scripts/postinstall-bundled-plugins.test.ts b/test/scripts/postinstall-bundled-plugins.test.ts index 150234558ce..4ec4414577f 100644 --- a/test/scripts/postinstall-bundled-plugins.test.ts +++ b/test/scripts/postinstall-bundled-plugins.test.ts @@ -6,6 +6,7 @@ import { createBundledRuntimeDependencyInstallEnv, createNestedNpmInstallEnv, isDirectPostinstallInvocation, + pruneOpenClawCompileCache, pruneInstalledPackageDist, discoverBundledPluginRuntimeDeps, pruneBundledPluginSourceNodeModules, @@ -180,6 +181,31 @@ describe("bundled plugin postinstall", () => { expect(spawnSync).not.toHaveBeenCalled(); }); + it("prunes OpenClaw compile cache during package postinstall", () => { + const removed: string[] = []; + const existsSync = vi.fn((value: string) => + value.endsWith(path.join("openclaw-cache", "openclaw")), + ); + const rmSync = vi.fn((value: string) => { + removed.push(value); + }); + + pruneOpenClawCompileCache({ + env: { NODE_COMPILE_CACHE: path.join("/tmp", "openclaw-cache") }, + existsSync, + rmSync, + log: { warn: vi.fn() }, + }); + + expect(removed).toEqual([path.join("/tmp", "openclaw-cache", "openclaw")]); + expect(rmSync).toHaveBeenCalledWith(path.join("/tmp", "openclaw-cache", "openclaw"), { + recursive: true, + force: true, + maxRetries: 2, + retryDelay: 100, + }); + }); + it("prunes source-checkout bundled plugin node_modules", async () => { const packageRoot = await createTempDirAsync("openclaw-source-checkout-"); const extensionsDir = path.join(packageRoot, "extensions");