

















@@ -1714,6 +1714,110 @@ module.exports = {
17141714expect(registry?.plugins.find((entry) => entry.id === "alpha")?.status).toBe("loaded");
17151715});
171617161717+it("materializes plugin-owned root chunks in external runtime mirrors", () => {
1718+const packageRoot = makeTempDir();
1719+const stageDir = makeTempDir();
1720+const bundledDir = path.join(packageRoot, "dist", "extensions");
1721+const pluginRoot = path.join(bundledDir, "browser");
1722+fs.mkdirSync(pluginRoot, { recursive: true });
1723+fs.writeFileSync(
1724+path.join(packageRoot, "package.json"),
1725+JSON.stringify({ name: "openclaw", version: "2026.4.24", type: "module" }),
1726+"utf-8",
1727+);
1728+fs.writeFileSync(
1729+path.join(packageRoot, "dist", "pw-ai.js"),
1730+[
1731+`//#region extensions/browser/src/pw-ai.ts`,
1732+`import { marker } from "playwright-core";`,
1733+`export { marker };`,
1734+`//#endregion`,
1735+"",
1736+].join("\n"),
1737+"utf-8",
1738+);
1739+fs.writeFileSync(
1740+path.join(pluginRoot, "index.js"),
1741+[
1742+`import { marker } from "../../pw-ai.js";`,
1743+`export default {`,
1744+` id: "browser",`,
1745+` register(api) {`,
1746+` api.registerCommand({ name: "browser-marker", handler: () => marker });`,
1747+` },`,
1748+`};`,
1749+"",
1750+].join("\n"),
1751+"utf-8",
1752+);
1753+fs.writeFileSync(
1754+path.join(pluginRoot, "package.json"),
1755+JSON.stringify(
1756+{
1757+name: "@openclaw/browser",
1758+version: "1.0.0",
1759+type: "module",
1760+dependencies: {
1761+"playwright-core": "1.0.0",
1762+},
1763+openclaw: { extensions: ["./index.js"] },
1764+},
1765+null,
1766+2,
1767+),
1768+"utf-8",
1769+);
1770+fs.writeFileSync(
1771+path.join(pluginRoot, "openclaw.plugin.json"),
1772+JSON.stringify(
1773+{
1774+id: "browser",
1775+enabledByDefault: true,
1776+configSchema: EMPTY_PLUGIN_SCHEMA,
1777+},
1778+null,
1779+2,
1780+),
1781+"utf-8",
1782+);
1783+process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = bundledDir;
1784+process.env.OPENCLAW_PLUGIN_STAGE_DIR = stageDir;
1785+1786+let actualInstallRoot = "";
1787+let stagedMirrorChunk = "";
1788+const registry = loadOpenClawPlugins({
1789+cache: false,
1790+config: {
1791+plugins: {
1792+enabled: true,
1793+},
1794+},
1795+bundledRuntimeDepsInstaller: ({ installRoot }) => {
1796+actualInstallRoot = installRoot;
1797+stagedMirrorChunk = path.join(installRoot, "dist", "pw-ai.js");
1798+fs.mkdirSync(path.dirname(stagedMirrorChunk), { recursive: true });
1799+fs.symlinkSync(path.join(packageRoot, "dist", "pw-ai.js"), stagedMirrorChunk, "file");
1800+const depRoot = path.join(installRoot, "node_modules", "playwright-core");
1801+fs.mkdirSync(depRoot, { recursive: true });
1802+fs.writeFileSync(
1803+path.join(depRoot, "package.json"),
1804+JSON.stringify({
1805+name: "playwright-core",
1806+version: "1.0.0",
1807+type: "module",
1808+exports: "./index.js",
1809+}),
1810+"utf-8",
1811+);
1812+fs.writeFileSync(path.join(depRoot, "index.js"), "export const marker = 'stage-ok';\n");
1813+},
1814+});
1815+1816+expect(actualInstallRoot).not.toBe("");
1817+expect(registry.plugins.find((entry) => entry.id === "browser")?.status).toBe("loaded");
1818+expect(fs.lstatSync(stagedMirrorChunk).isSymbolicLink()).toBe(false);
1819+});
1820+17171821it("loads bundled plugins with plugin-sdk imports from an external stage dir", () => {
17181822const packageRoot = makeTempDir();
17191823const stageDir = makeTempDir();
@@ -1913,6 +2017,17 @@ module.exports = {
19132017);
19142018fs.mkdirSync(pluginRoot, { recursive: true });
19152019fs.mkdirSync(canonicalPluginRoot, { recursive: true });
2020+fs.writeFileSync(
2021+path.join(packageRoot, "dist", "pw-ai.js"),
2022+[
2023+`//#region extensions/acpx/src/pw-ai.ts`,
2024+`import runtimeDep from "external-runtime";`,
2025+`export const marker = runtimeDep.marker;`,
2026+`//#endregion`,
2027+"",
2028+].join("\n"),
2029+"utf-8",
2030+);
19162031fs.writeFileSync(
19172032path.join(pluginRoot, "index.js"),
19182033[
@@ -1926,11 +2041,11 @@ module.exports = {
19262041fs.writeFileSync(
19272042path.join(canonicalPluginRoot, "index.js"),
19282043[
1929-`import runtimeDep from "external-runtime";`,
2044+`import { marker } from "../../pw-ai.js";`,
19302045`export default {`,
19312046` id: "acpx",`,
19322047` register(api) {`,
1933-` api.registerCommand({ name: "external-runtime", handler: () => runtimeDep.marker });`,
2048+` api.registerCommand({ name: "external-runtime", handler: () => marker });`,
19342049` },`,
19352050`};`,
19362051"",
@@ -1970,6 +2085,7 @@ module.exports = {
19702085"utf-8",
19712086);
197220872088+let actualInstallRoot = "";
19732089const registry = loadOpenClawPlugins({
19742090cache: false,
19752091config: {
@@ -1978,6 +2094,7 @@ module.exports = {
19782094},
19792095},
19802096bundledRuntimeDepsInstaller: ({ installRoot }) => {
2097+actualInstallRoot = installRoot;
19812098const depRoot = path.join(installRoot, "node_modules", "external-runtime");
19822099fs.mkdirSync(depRoot, { recursive: true });
19832100fs.writeFileSync(
@@ -1999,6 +2116,10 @@ module.exports = {
19992116});
2000211720012118expect(registry.plugins.find((entry) => entry.id === "acpx")?.status).toBe("loaded");
2119+expect(fs.lstatSync(path.join(actualInstallRoot, "dist")).isSymbolicLink()).toBe(false);
2120+expect(fs.lstatSync(path.join(actualInstallRoot, "dist", "pw-ai.js")).isSymbolicLink()).toBe(
2121+false,
2122+);
20022123});
2003212420042125it("loads source-checkout bundled runtime deps without mirroring the repo tree", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。