From 87345c066766537d3a4457a1b0d8f69cab708c48 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Apr 2026 23:52:46 +0100 Subject: [PATCH] fix: narrow bundled runtime mirror materialization --- src/plugins/bundled-runtime-deps.ts | 29 +++++++++++++++++++++++- src/plugins/bundled-runtime-root.test.ts | 8 +++++++ src/plugins/loader.test.ts | 8 +++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/plugins/bundled-runtime-deps.ts b/src/plugins/bundled-runtime-deps.ts index e20ea282e0f..816aa119f8e 100644 --- a/src/plugins/bundled-runtime-deps.ts +++ b/src/plugins/bundled-runtime-deps.ts @@ -71,6 +71,9 @@ const BUNDLED_RUNTIME_MIRROR_MATERIALIZED_EXTENSIONS = new Set([".cjs", ".js", " const BUNDLED_EXTENSION_DIST_DIR = "extensions"; const MIRRORED_CORE_RUNTIME_DEP_NAMES = ["tslog"] as const; const MIRRORED_PACKAGE_RUNTIME_DEP_PLUGIN_ID = "openclaw-core"; +const BUNDLED_RUNTIME_MIRROR_PLUGIN_REGION_RE = /(?:^|\n)\/\/#region extensions\/[^/\s]+(?:\/|$)/u; +const BUNDLED_RUNTIME_MIRROR_IMPORT_SPECIFIER_RE = + /(?:^|[;\n])\s*(?:import|export)\s+(?:[^'"()]+?\s+from\s+)?["']([^"']+)["']|\bimport\(\s*["']([^"']+)["']\s*\)|\brequire\(\s*["']([^"']+)["']\s*\)/g; const registeredBundledRuntimeDepNodePaths = new Set(); @@ -81,7 +84,31 @@ export type BundledRuntimeDepsNpmRunner = { }; export function shouldMaterializeBundledRuntimeMirrorDistFile(sourcePath: string): boolean { - return BUNDLED_RUNTIME_MIRROR_MATERIALIZED_EXTENSIONS.has(path.extname(sourcePath)); + if (!BUNDLED_RUNTIME_MIRROR_MATERIALIZED_EXTENSIONS.has(path.extname(sourcePath))) { + return false; + } + let source: string; + try { + source = fs.readFileSync(sourcePath, "utf8"); + } catch { + return false; + } + if (BUNDLED_RUNTIME_MIRROR_PLUGIN_REGION_RE.test(source)) { + return true; + } + for (const match of source.matchAll(BUNDLED_RUNTIME_MIRROR_IMPORT_SPECIFIER_RE)) { + const specifier = match[1] ?? match[2] ?? match[3] ?? ""; + if ( + specifier !== "" && + !specifier.startsWith(".") && + !specifier.startsWith("/") && + !specifier.startsWith("node:") && + !specifier.includes(":") + ) { + return false; + } + } + return true; } export function materializeBundledRuntimeMirrorDistFile( diff --git a/src/plugins/bundled-runtime-root.test.ts b/src/plugins/bundled-runtime-root.test.ts index b39f332483a..8f625721ef6 100644 --- a/src/plugins/bundled-runtime-root.test.ts +++ b/src/plugins/bundled-runtime-root.test.ts @@ -51,6 +51,11 @@ describe("prepareBundledPluginRuntimeRoot", () => { "export const shared = 'mirrored-without-region';\n", "utf8", ); + fs.writeFileSync( + path.join(packageRoot, "dist", "config-runtime.js"), + "import JSON5 from 'json5'; export const parse = JSON5.parse;\n", + "utf8", + ); fs.writeFileSync( path.join(pluginRoot, "index.js"), `import { marker } from "../../pw-ai.js"; export default { id: "browser", marker };\n`, @@ -118,6 +123,9 @@ describe("prepareBundledPluginRuntimeRoot", () => { expect(fs.lstatSync(path.join(installRoot, "dist", "shared-runtime.js")).isSymbolicLink()).toBe( false, ); + expect(fs.lstatSync(path.join(installRoot, "dist", "config-runtime.js")).isSymbolicLink()).toBe( + true, + ); }); it("does not copy staged runtime mirror dist files onto themselves", () => { diff --git a/src/plugins/loader.test.ts b/src/plugins/loader.test.ts index 47071154581..b2168c56d3f 100644 --- a/src/plugins/loader.test.ts +++ b/src/plugins/loader.test.ts @@ -1745,6 +1745,11 @@ module.exports = { "export const shared = 'mirrored-without-region';\n", "utf-8", ); + fs.writeFileSync( + path.join(packageRoot, "dist", "config-runtime.js"), + "import JSON5 from 'json5'; export const parse = JSON5.parse;\n", + "utf-8", + ); fs.writeFileSync( path.join(pluginRoot, "index.js"), [ @@ -1841,6 +1846,9 @@ module.exports = { expect( fs.lstatSync(path.join(actualInstallRoot, "dist", "shared-runtime.js")).isSymbolicLink(), ).toBe(false); + expect( + fs.lstatSync(path.join(actualInstallRoot, "dist", "config-runtime.js")).isSymbolicLink(), + ).toBe(true); }); it("loads bundled plugins with plugin-sdk imports from an external stage dir", () => {