mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-10 12:32:27 +00:00
fix(gateway): cover restored watch artifacts
This commit is contained in:
committed by
Peter Steinberger
parent
6b5296d4d4
commit
e40ddf9b02
@@ -34,6 +34,21 @@ function listExtensionPackageDirs(rootDir, fsImpl) {
|
||||
.toSorted((left, right) => left.dirName.localeCompare(right.dirName));
|
||||
}
|
||||
|
||||
function listDistExtensionPackageDirs(rootDir, fsImpl) {
|
||||
const extensionsRoot = path.join(rootDir, "dist", "extensions");
|
||||
if (!fsImpl.existsSync(extensionsRoot)) {
|
||||
return [];
|
||||
}
|
||||
return fsImpl
|
||||
.readdirSync(extensionsRoot, { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory() && entry.name !== "node_modules")
|
||||
.map((entry) => ({
|
||||
dirName: entry.name,
|
||||
packageDir: path.join(extensionsRoot, entry.name),
|
||||
}))
|
||||
.toSorted((left, right) => left.dirName.localeCompare(right.dirName));
|
||||
}
|
||||
|
||||
function readPackageStaticAssetEntries(packageJson) {
|
||||
const entries = packageJson.openclaw?.build?.staticAssets;
|
||||
return Array.isArray(entries) ? entries : [];
|
||||
@@ -65,6 +80,33 @@ export function discoverStaticExtensionAssets(params = {}) {
|
||||
return assets.toSorted((left, right) => left.dest.localeCompare(right.dest));
|
||||
}
|
||||
|
||||
function discoverStaticExtensionRuntimeOverlayAssets(params = {}) {
|
||||
const rootDir = params.rootDir ?? process.cwd();
|
||||
const fsImpl = params.fs ?? fs;
|
||||
const assetsByDest = new Map();
|
||||
for (const asset of params.assets ?? discoverStaticExtensionAssets({ rootDir, fs: fsImpl })) {
|
||||
assetsByDest.set(asset.dest, asset);
|
||||
}
|
||||
for (const { dirName, packageDir } of listDistExtensionPackageDirs(rootDir, fsImpl)) {
|
||||
const packageJsonPath = path.join(packageDir, "package.json");
|
||||
if (!fsImpl.existsSync(packageJsonPath)) {
|
||||
continue;
|
||||
}
|
||||
const packageJson = readJsonFile(packageJsonPath, fsImpl);
|
||||
for (const entry of readPackageStaticAssetEntries(packageJson)) {
|
||||
const output = normalizePackageRelativePath(entry?.output);
|
||||
if (!output) {
|
||||
continue;
|
||||
}
|
||||
const dest = toPosixPath(path.posix.join("dist", "extensions", dirName, output));
|
||||
if (!assetsByDest.has(dest)) {
|
||||
assetsByDest.set(dest, { pluginDir: dirName, src: dest, dest });
|
||||
}
|
||||
}
|
||||
}
|
||||
return [...assetsByDest.values()].toSorted((left, right) => left.dest.localeCompare(right.dest));
|
||||
}
|
||||
|
||||
export function listStaticExtensionAssetOutputs(params = {}) {
|
||||
const assets = params.assets ?? discoverStaticExtensionAssets(params);
|
||||
return assets
|
||||
@@ -99,7 +141,7 @@ export function copyStaticExtensionAssets(params = {}) {
|
||||
export function copyStaticExtensionAssetsToRuntimeOverlay(params = {}) {
|
||||
const rootDir = params.rootDir ?? process.cwd();
|
||||
const fsImpl = params.fs ?? fs;
|
||||
const assets = params.assets ?? discoverStaticExtensionAssets({ rootDir, fs: fsImpl });
|
||||
const assets = discoverStaticExtensionRuntimeOverlayAssets({ ...params, rootDir, fs: fsImpl });
|
||||
const runtimeExtensionsRoot = path.join(rootDir, "dist-runtime", "extensions");
|
||||
if (!fsImpl.existsSync(runtimeExtensionsRoot)) {
|
||||
return;
|
||||
@@ -111,10 +153,12 @@ export function copyStaticExtensionAssetsToRuntimeOverlay(params = {}) {
|
||||
continue;
|
||||
}
|
||||
const srcPath = path.join(rootDir, src);
|
||||
const distPath = path.join(rootDir, dest);
|
||||
const copySourcePath = fsImpl.existsSync(srcPath) ? srcPath : distPath;
|
||||
const destPath = path.join(rootDir, "dist-runtime", normalizedDest.slice("dist/".length));
|
||||
if (fsImpl.existsSync(srcPath)) {
|
||||
if (fsImpl.existsSync(copySourcePath)) {
|
||||
fsImpl.mkdirSync(path.dirname(destPath), { recursive: true });
|
||||
fsImpl.copyFileSync(srcPath, destPath);
|
||||
fsImpl.copyFileSync(copySourcePath, destPath);
|
||||
} else {
|
||||
warn(`[runtime-postbuild] static asset not found, skipping: ${src}`);
|
||||
}
|
||||
|
||||
@@ -59,16 +59,10 @@ const DIST_RUNTIME_EXTENSION_SKILL = "dist-runtime/extensions/demo/skills/SKILL.
|
||||
const DIST_OPENCLAW_ALIAS_PACKAGE = "dist/extensions/node_modules/openclaw/package.json";
|
||||
const DIST_OPENCLAW_ALIAS_PLUGIN_SDK_INDEX =
|
||||
"dist/extensions/node_modules/openclaw/plugin-sdk/index.js";
|
||||
const ACPX_PACKAGE = "extensions/acpx/package.json";
|
||||
const ACPX_MCP_PROXY_SOURCE = "extensions/acpx/src/runtime-internals/mcp-proxy.mjs";
|
||||
const DIST_ACPX_MCP_PROXY = "dist/extensions/acpx/mcp-proxy.mjs";
|
||||
const ACPX_ERROR_FORMAT_SOURCE = "extensions/acpx/src/runtime-internals/error-format.mjs";
|
||||
const DIST_ACPX_ERROR_FORMAT = "dist/extensions/acpx/error-format.mjs";
|
||||
const ACPX_MCP_COMMAND_LINE_SOURCE = "extensions/acpx/src/runtime-internals/mcp-command-line.mjs";
|
||||
const DIST_ACPX_MCP_COMMAND_LINE = "dist/extensions/acpx/mcp-command-line.mjs";
|
||||
const DIFFS_PACKAGE = "extensions/diffs/package.json";
|
||||
const DIFFS_VIEWER_RUNTIME_SOURCE = "extensions/diffs/assets/viewer-runtime.js";
|
||||
const DIST_DIFFS_VIEWER_RUNTIME = "dist/extensions/diffs/assets/viewer-runtime.js";
|
||||
const DIST_RUNTIME_DIFFS_VIEWER_RUNTIME = "dist-runtime/extensions/diffs/assets/viewer-runtime.js";
|
||||
const DIST_EXTENSION_MANIFEST = bundledDistPluginFile("demo", "openclaw.plugin.json");
|
||||
const DIST_EXTENSION_PACKAGE = bundledDistPluginFile("demo", "package.json");
|
||||
|
||||
@@ -1904,38 +1898,25 @@ describe("run-node script", () => {
|
||||
await setupTrackedProject(tmp, {
|
||||
files: {
|
||||
[ROOT_SRC]: "export const value = 1;\n",
|
||||
[ACPX_PACKAGE]:
|
||||
'{"openclaw":{"build":{"staticAssets":[{"source":"./src/runtime-internals/mcp-proxy.mjs","output":"mcp-proxy.mjs"},{"source":"./src/runtime-internals/error-format.mjs","output":"error-format.mjs"},{"source":"./src/runtime-internals/mcp-command-line.mjs","output":"mcp-command-line.mjs"}]}}}\n',
|
||||
[ACPX_MCP_PROXY_SOURCE]: "export {};\n",
|
||||
[DIST_ACPX_MCP_PROXY]: "export {};\n",
|
||||
[ACPX_ERROR_FORMAT_SOURCE]: "export {};\n",
|
||||
[DIST_ACPX_ERROR_FORMAT]: "export {};\n",
|
||||
[ACPX_MCP_COMMAND_LINE_SOURCE]: "export {};\n",
|
||||
[DIST_ACPX_MCP_COMMAND_LINE]: "export {};\n",
|
||||
[DIFFS_PACKAGE]:
|
||||
'{"openclaw":{"build":{"staticAssets":[{"source":"./assets/viewer-runtime.js","output":"assets/viewer-runtime.js"}]}}}\n',
|
||||
[DIFFS_VIEWER_RUNTIME_SOURCE]: "export {};\n",
|
||||
[DIST_DIFFS_VIEWER_RUNTIME]: "export {};\n",
|
||||
[DIST_RUNTIME_DIFFS_VIEWER_RUNTIME]: "export {};\n",
|
||||
[RUNTIME_POSTBUILD_STAMP]: '{"head":"abc123"}\n',
|
||||
},
|
||||
buildPaths: [
|
||||
ROOT_SRC,
|
||||
ACPX_PACKAGE,
|
||||
ACPX_MCP_PROXY_SOURCE,
|
||||
DIST_ACPX_MCP_PROXY,
|
||||
ACPX_ERROR_FORMAT_SOURCE,
|
||||
DIST_ACPX_ERROR_FORMAT,
|
||||
ACPX_MCP_COMMAND_LINE_SOURCE,
|
||||
DIST_ACPX_MCP_COMMAND_LINE,
|
||||
DIFFS_PACKAGE,
|
||||
DIFFS_VIEWER_RUNTIME_SOURCE,
|
||||
DIST_DIFFS_VIEWER_RUNTIME,
|
||||
DIST_RUNTIME_DIFFS_VIEWER_RUNTIME,
|
||||
DIST_ENTRY,
|
||||
BUILD_STAMP,
|
||||
RUNTIME_POSTBUILD_STAMP,
|
||||
],
|
||||
});
|
||||
await fs.rm(resolvePath(tmp, DIST_ACPX_MCP_COMMAND_LINE));
|
||||
await fs.rm(resolvePath(tmp, DIST_DIFFS_VIEWER_RUNTIME));
|
||||
|
||||
const requirement = resolveRuntimePostBuildRequirement(
|
||||
createBuildRequirementDeps(tmp, {
|
||||
@@ -1951,6 +1932,32 @@ describe("run-node script", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("does not require static asset outputs when the declared source is absent", async () => {
|
||||
await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => {
|
||||
await setupTrackedProject(tmp, {
|
||||
files: {
|
||||
[ROOT_SRC]: "export const value = 1;\n",
|
||||
[DIFFS_PACKAGE]:
|
||||
'{"openclaw":{"build":{"staticAssets":[{"source":"./assets/viewer-runtime.js","output":"assets/viewer-runtime.js"}]}}}\n',
|
||||
[RUNTIME_POSTBUILD_STAMP]: '{"head":"abc123"}\n',
|
||||
},
|
||||
buildPaths: [ROOT_SRC, DIFFS_PACKAGE, DIST_ENTRY, BUILD_STAMP, RUNTIME_POSTBUILD_STAMP],
|
||||
});
|
||||
|
||||
const requirement = resolveRuntimePostBuildRequirement(
|
||||
createBuildRequirementDeps(tmp, {
|
||||
gitHead: "abc123\n",
|
||||
gitStatus: "",
|
||||
}),
|
||||
);
|
||||
|
||||
expect(requirement).toEqual({
|
||||
shouldSync: false,
|
||||
reason: "clean",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("reports missing core runtime postbuild outputs when runtime stamps match HEAD", async () => {
|
||||
for (const missingPath of [
|
||||
DIST_PLUGIN_SDK_ROOT_ALIAS,
|
||||
|
||||
@@ -139,6 +139,50 @@ describe("runtime postbuild static assets", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves restored dist static assets when plugin sources are absent", async () => {
|
||||
const rootDir = createTempDir("openclaw-runtime-postbuild-");
|
||||
const output = "assets/viewer-runtime.js";
|
||||
const distPluginDir = path.join(rootDir, "dist", "extensions", "diffs");
|
||||
const runtimeAsset = path.join(rootDir, "dist-runtime", "extensions", "diffs", output);
|
||||
|
||||
await fs.mkdir(path.join(rootDir, "src", "plugin-sdk"), { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(rootDir, "src", "plugin-sdk", "root-alias.cjs"),
|
||||
"module.exports = {};\n",
|
||||
"utf8",
|
||||
);
|
||||
await fs.mkdir(path.join(distPluginDir, "assets"), { recursive: true });
|
||||
await fs.writeFile(path.join(distPluginDir, "index.js"), "export default {};\n", "utf8");
|
||||
await fs.writeFile(
|
||||
path.join(distPluginDir, "openclaw.plugin.json"),
|
||||
'{"id":"diffs"}\n',
|
||||
"utf8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(distPluginDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@openclaw/diffs",
|
||||
openclaw: {
|
||||
extensions: ["./index.js"],
|
||||
build: {
|
||||
staticAssets: [{ source: `./${output}`, output }],
|
||||
},
|
||||
},
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
await fs.writeFile(path.join(distPluginDir, output), "console.log('viewer');\n", "utf8");
|
||||
|
||||
runRuntimePostBuild({
|
||||
cwd: rootDir,
|
||||
repoRoot: rootDir,
|
||||
rootDir,
|
||||
timings: false,
|
||||
});
|
||||
|
||||
await expect(fs.readFile(runtimeAsset, "utf8")).resolves.toBe("console.log('viewer');\n");
|
||||
});
|
||||
|
||||
it("skips runtime overlay asset copies when the runtime extension root is absent", async () => {
|
||||
const rootDir = createTempDir("openclaw-runtime-postbuild-");
|
||||
await fs.mkdir(path.join(rootDir, "extensions", "demo", "assets"), { recursive: true });
|
||||
|
||||
Reference in New Issue
Block a user