From 11a268819e82b40ef697858f6da870ef7d719b30 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 1 May 2026 22:55:35 +0100 Subject: [PATCH] fix: exclude plugin dependency debris from package inventory --- .../.generated/plugin-sdk-api-baseline.sha256 | 4 +-- src/infra/package-dist-inventory.test.ts | 31 +++++++++++++++++++ src/infra/package-dist-inventory.ts | 23 +++++++++++++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256 index d76bc10c0bf..e12b9635017 100644 --- a/docs/.generated/plugin-sdk-api-baseline.sha256 +++ b/docs/.generated/plugin-sdk-api-baseline.sha256 @@ -1,2 +1,2 @@ -8edcfb8af9862c6681bbf7fcba335943128ca7883e6982d0299eabcdf62386d4 plugin-sdk-api-baseline.json -5252b562f850cfe078903d3a3373ae5aa82041f6af8ccbc00fb9c94a89736e55 plugin-sdk-api-baseline.jsonl +1973d093c4fe08bc3f41d8c80ed089bf9674b299648c8958e9ca513327a8d3f0 plugin-sdk-api-baseline.json +4ef761cd8ce9f163fcce09ca17bcf58dfe6ae901108218fb9994e7c297a394d1 plugin-sdk-api-baseline.jsonl diff --git a/src/infra/package-dist-inventory.test.ts b/src/infra/package-dist-inventory.test.ts index beaf9336532..35230b25053 100644 --- a/src/infra/package-dist-inventory.test.ts +++ b/src/infra/package-dist-inventory.test.ts @@ -113,6 +113,37 @@ describe("package dist inventory", () => { }); }); + it("keeps transient plugin dependency trees out of the inventory", async () => { + await withTempDir({ prefix: "openclaw-dist-inventory-plugin-deps-" }, async (packageRoot) => { + const realFile = path.join(packageRoot, "dist", "index.js"); + const rootDependencyPackage = path.join( + packageRoot, + "dist", + "extensions", + "node_modules", + "openclaw", + "package.json", + ); + const pluginDependencyPackage = path.join( + packageRoot, + "dist", + "extensions", + "slack", + "node_modules", + "left-pad", + "package.json", + ); + await fs.mkdir(path.dirname(realFile), { recursive: true }); + await fs.mkdir(path.dirname(rootDependencyPackage), { recursive: true }); + await fs.mkdir(path.dirname(pluginDependencyPackage), { recursive: true }); + await fs.writeFile(realFile, "export {};\n", "utf8"); + await fs.writeFile(rootDependencyPackage, "{}", "utf8"); + await fs.writeFile(pluginDependencyPackage, "{}", "utf8"); + + await expect(writePackageDistInventory(packageRoot)).resolves.toEqual(["dist/index.js"]); + }); + }); + it("reports runtime-created install staging dirs during installed dist verification", async () => { await withTempDir({ prefix: "openclaw-dist-inventory-stage-" }, async (packageRoot) => { const realFile = path.join(packageRoot, "dist", "real-AbC123.js"); diff --git a/src/infra/package-dist-inventory.ts b/src/infra/package-dist-inventory.ts index 3d9d541caa2..341df4a664f 100644 --- a/src/infra/package-dist-inventory.ts +++ b/src/infra/package-dist-inventory.ts @@ -46,6 +46,21 @@ function isInstallStageDirName(value: string): boolean { return INSTALL_STAGE_DEBRIS_DIR_PATTERN.test(value); } +function isLegacyPluginDependencyDirPath(relativePath: string): boolean { + const parts = normalizeRelativePath(relativePath).split("/"); + if (parts[0]?.toLowerCase() !== "dist" || parts[1]?.toLowerCase() !== "extensions") { + return false; + } + + const rootDependencyDir = parts[2] ?? ""; + if (rootDependencyDir.toLowerCase() === "node_modules") { + return true; + } + + const pluginDependencyDir = parts[3] ?? ""; + return pluginDependencyDir.toLowerCase() === "node_modules"; +} + export function isLegacyPluginDependencyInstallStagePath(relativePath: string): boolean { const parts = normalizeRelativePath(relativePath).split("/"); return ( @@ -61,6 +76,9 @@ function isPackagedDistPath(relativePath: string): boolean { if (!relativePath.startsWith("dist/")) { return false; } + if (isLegacyPluginDependencyDirPath(relativePath)) { + return false; + } if (relativePath === PACKAGE_DIST_INVENTORY_RELATIVE_PATH) { return false; } @@ -87,7 +105,10 @@ function isPackagedDistPath(relativePath: string): boolean { } function isOmittedDistSubtree(relativePath: string): boolean { - return OMITTED_DIST_SUBTREE_PATTERNS.some((pattern) => pattern.test(relativePath)); + return ( + isLegacyPluginDependencyDirPath(relativePath) || + OMITTED_DIST_SUBTREE_PATTERNS.some((pattern) => pattern.test(relativePath)) + ); } async function collectRelativeFiles(rootDir: string, baseDir: string): Promise {