























@@ -198,14 +198,26 @@ describe("prepareBundledPluginRuntimeRoot", () => {
198198}
199199200200const realReadFileSync = fs.readFileSync.bind(fs);
201+const realReaddirSync = fs.readdirSync.bind(fs);
201202const readPaths: string[] = [];
203+const readdirPaths: string[] = [];
202204vi.spyOn(fs, "readFileSync").mockImplementation(((target, options) => {
203205const targetPath = target.toString();
204206if (targetPath === rootChunk || targetPath === externalChunk) {
205207readPaths.push(targetPath);
206208}
207209return realReadFileSync(target, options as never);
208210}) as typeof fs.readFileSync);
211+vi.spyOn(fs, "readdirSync").mockImplementation(((target, options) => {
212+const targetPath = target.toString();
213+if (
214+targetPath === path.join(packageRoot, "dist") &&
215+new Error().stack?.includes("mirrorBundledRuntimeDistRootEntries")
216+) {
217+readdirPaths.push(targetPath);
218+}
219+return realReaddirSync(target, options as never);
220+}) as typeof fs.readdirSync);
209221210222for (const pluginId of ["alpha", "beta"]) {
211223const pluginRoot = path.join(packageRoot, "dist", "extensions", pluginId);
@@ -219,6 +231,75 @@ describe("prepareBundledPluginRuntimeRoot", () => {
219231220232expect(readPaths.filter((entry) => entry === rootChunk)).toHaveLength(1);
221233expect(readPaths.filter((entry) => entry === externalChunk)).toHaveLength(1);
234+expect(readdirPaths).toHaveLength(1);
235+});
236+237+it("does not memoize source-checkout dist mirrors", () => {
238+const packageRoot = makeTempRoot();
239+const stageDir = makeTempRoot();
240+const env = { ...process.env, OPENCLAW_PLUGIN_STAGE_DIR: stageDir };
241+fs.mkdirSync(path.join(packageRoot, ".git"), { recursive: true });
242+fs.mkdirSync(path.join(packageRoot, "src"), { recursive: true });
243+fs.mkdirSync(path.join(packageRoot, "extensions"), { recursive: true });
244+const pluginRoot = path.join(packageRoot, "dist", "extensions", "alpha");
245+fs.mkdirSync(pluginRoot, { recursive: true });
246+fs.writeFileSync(
247+path.join(packageRoot, "package.json"),
248+JSON.stringify({ name: "openclaw", version: "2026.4.27", type: "module" }),
249+"utf8",
250+);
251+fs.writeFileSync(path.join(packageRoot, "dist", "shared-runtime.js"), "export {};\n", "utf8");
252+fs.writeFileSync(
253+path.join(pluginRoot, "index.js"),
254+`import "../../shared-runtime.js"; export default { id: "alpha" };\n`,
255+"utf8",
256+);
257+fs.writeFileSync(
258+path.join(pluginRoot, "package.json"),
259+JSON.stringify(
260+{
261+name: "@openclaw/alpha",
262+version: "1.0.0",
263+type: "module",
264+dependencies: { "alpha-runtime": "1.0.0" },
265+openclaw: { extensions: ["./index.js"] },
266+},
267+null,
268+2,
269+),
270+"utf8",
271+);
272+const installRoot = resolveBundledRuntimeDependencyInstallRoot(pluginRoot, { env });
273+fs.mkdirSync(path.join(installRoot, "node_modules", "alpha-runtime"), { recursive: true });
274+fs.writeFileSync(
275+path.join(installRoot, "node_modules", "alpha-runtime", "package.json"),
276+JSON.stringify({ name: "alpha-runtime", version: "1.0.0", type: "module" }),
277+"utf8",
278+);
279+280+const realReaddirSync = fs.readdirSync.bind(fs);
281+const readdirPaths: string[] = [];
282+vi.spyOn(fs, "readdirSync").mockImplementation(((target, options) => {
283+const targetPath = target.toString();
284+if (
285+targetPath === path.join(packageRoot, "dist") &&
286+new Error().stack?.includes("mirrorBundledRuntimeDistRootEntries")
287+) {
288+readdirPaths.push(targetPath);
289+}
290+return realReaddirSync(target, options as never);
291+}) as typeof fs.readdirSync);
292+293+for (let index = 0; index < 2; index += 1) {
294+prepareBundledPluginRuntimeRoot({
295+pluginId: "alpha",
296+ pluginRoot,
297+modulePath: path.join(pluginRoot, "index.js"),
298+ env,
299+});
300+}
301+302+expect(readdirPaths).toHaveLength(2);
222303});
223304224305it("does not copy staged runtime mirror dist files onto themselves", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。