From 70a6d40d37efb01debf7ddac8dd3debc9cf89651 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 16 Mar 2026 02:10:28 +0000 Subject: [PATCH] fix: remove stale dist plugin dirs --- scripts/copy-bundled-plugin-metadata.mjs | 11 +----- .../copy-bundled-plugin-metadata.test.ts | 38 +++++++++++++------ 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/scripts/copy-bundled-plugin-metadata.mjs b/scripts/copy-bundled-plugin-metadata.mjs index f5eac7ba513..b4be20dfae4 100644 --- a/scripts/copy-bundled-plugin-metadata.mjs +++ b/scripts/copy-bundled-plugin-metadata.mjs @@ -135,13 +135,6 @@ export function copyBundledPluginMetadata(params = {}) { } const sourcePluginDirs = new Set(); - const removeGeneratedPluginArtifacts = (distPluginDir) => { - removeFileIfExists(path.join(distPluginDir, "openclaw.plugin.json")); - removeFileIfExists(path.join(distPluginDir, "package.json")); - removePathIfExists(path.join(distPluginDir, GENERATED_BUNDLED_SKILLS_DIR)); - removePathIfExists(path.join(distPluginDir, "node_modules")); - }; - for (const dirent of fs.readdirSync(extensionsRoot, { withFileTypes: true })) { if (!dirent.isDirectory()) { continue; @@ -154,7 +147,7 @@ export function copyBundledPluginMetadata(params = {}) { const distManifestPath = path.join(distPluginDir, "openclaw.plugin.json"); const distPackageJsonPath = path.join(distPluginDir, "package.json"); if (!fs.existsSync(manifestPath)) { - removeGeneratedPluginArtifacts(distPluginDir); + removePathIfExists(distPluginDir); continue; } @@ -203,7 +196,7 @@ export function copyBundledPluginMetadata(params = {}) { continue; } const distPluginDir = path.join(distExtensionsRoot, dirent.name); - removeGeneratedPluginArtifacts(distPluginDir); + removePathIfExists(distPluginDir); } } diff --git a/src/plugins/copy-bundled-plugin-metadata.test.ts b/src/plugins/copy-bundled-plugin-metadata.test.ts index 88da85b0dda..8f4187a8937 100644 --- a/src/plugins/copy-bundled-plugin-metadata.test.ts +++ b/src/plugins/copy-bundled-plugin-metadata.test.ts @@ -258,6 +258,11 @@ describe("copyBundledPluginMetadata", () => { "node_modules", ); fs.mkdirSync(staleNodeModulesDir, { recursive: true }); + fs.writeFileSync( + path.join(repoRoot, "dist", "extensions", "removed-plugin", "index.js"), + "export default {}\n", + "utf8", + ); writeJson(path.join(repoRoot, "dist", "extensions", "removed-plugin", "openclaw.plugin.json"), { id: "removed-plugin", configSchema: { type: "object" }, @@ -270,17 +275,26 @@ describe("copyBundledPluginMetadata", () => { copyBundledPluginMetadata({ repoRoot }); - expect( - fs.existsSync( - path.join(repoRoot, "dist", "extensions", "removed-plugin", "openclaw.plugin.json"), - ), - ).toBe(false); - expect( - fs.existsSync(path.join(repoRoot, "dist", "extensions", "removed-plugin", "package.json")), - ).toBe(false); - expect( - fs.existsSync(path.join(repoRoot, "dist", "extensions", "removed-plugin", "bundled-skills")), - ).toBe(false); - expect(fs.existsSync(staleNodeModulesDir)).toBe(false); + expect(fs.existsSync(path.join(repoRoot, "dist", "extensions", "removed-plugin"))).toBe(false); + }); + + it("removes stale dist outputs when a source extension directory no longer has a manifest", () => { + const repoRoot = makeRepoRoot("openclaw-bundled-plugin-manifestless-source-"); + const sourcePluginDir = path.join(repoRoot, "extensions", "google-gemini-cli-auth"); + fs.mkdirSync(path.join(sourcePluginDir, "node_modules"), { recursive: true }); + const staleDistDir = path.join(repoRoot, "dist", "extensions", "google-gemini-cli-auth"); + fs.mkdirSync(staleDistDir, { recursive: true }); + fs.writeFileSync(path.join(staleDistDir, "index.js"), "export default {}\n", "utf8"); + writeJson(path.join(staleDistDir, "openclaw.plugin.json"), { + id: "google-gemini-cli-auth", + configSchema: { type: "object" }, + }); + writeJson(path.join(staleDistDir, "package.json"), { + name: "@openclaw/google-gemini-cli-auth", + }); + + copyBundledPluginMetadata({ repoRoot }); + + expect(fs.existsSync(staleDistDir)).toBe(false); }); });