perf: avoid redundant runtime postbuild sync

This commit is contained in:
Peter Steinberger
2026-05-27 02:44:38 +01:00
parent 6290ed52ff
commit a67ee0f7a2
2 changed files with 93 additions and 0 deletions

View File

@@ -414,6 +414,37 @@ const listRequiredBundledPluginRuntimeOverlayOutputs = (deps) => {
return [...new Set(runtimePaths)].toSorted((left, right) => left.localeCompare(right));
};
const isSafePluginSdkSubpathSegment = (subpath) => /^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(subpath);
const readPackageJsonPluginSdkAliasFileNames = (deps) => {
let packageJson;
try {
packageJson = JSON.parse(deps.fs.readFileSync(path.join(deps.cwd, "package.json"), "utf8"));
} catch {
return null;
}
const packageExports = packageJson?.exports;
if (!packageExports || typeof packageExports !== "object" || Array.isArray(packageExports)) {
return null;
}
const fileNames = new Set();
for (const exportKey of Object.keys(packageExports)) {
if (exportKey === "./plugin-sdk") {
fileNames.add("index.js");
continue;
}
if (!exportKey.startsWith("./plugin-sdk/")) {
continue;
}
const subpath = exportKey.slice("./plugin-sdk/".length);
if (isSafePluginSdkSubpathSegment(subpath)) {
fileNames.add(`${subpath}.js`);
}
}
return fileNames.size > 0 ? fileNames : null;
};
const listRequiredOpenClawExtensionAliasOutputs = (deps) => {
const distRoot = resolveRuntimePostBuildDistRoot(deps);
const distExtensionsRoot = path.join(distRoot, "extensions");
@@ -428,11 +459,15 @@ const listRequiredOpenClawExtensionAliasOutputs = (deps) => {
return [];
}
const exportedPluginSdkFileNames = readPackageJsonPluginSdkAliasFileNames(deps);
const aliasDir = path.join(distRoot, "extensions", "node_modules", "openclaw");
return [
path.join(aliasDir, "package.json"),
...dirents
.filter((dirent) => dirent.isFile() && path.extname(dirent.name) === ".js")
.filter(
(dirent) => !exportedPluginSdkFileNames || exportedPluginSdkFileNames.has(dirent.name),
)
.map((dirent) => path.join(aliasDir, "plugin-sdk", dirent.name)),
].toSorted((left, right) => left.localeCompare(right));
};

View File

@@ -59,6 +59,8 @@ 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 DIST_OPENCLAW_ALIAS_PLUGIN_SDK_STRING_COERCE =
"dist/extensions/node_modules/openclaw/plugin-sdk/string-coerce-runtime.js";
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";
@@ -2193,6 +2195,62 @@ describe("run-node script", () => {
});
});
it("does not require private OpenClaw SDK dist files that package exports omit", async () => {
await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => {
await setupTrackedProject(tmp, {
files: {
[ROOT_SRC]: "export const value = 1;\n",
[ROOT_PACKAGE]: JSON.stringify(
{
name: "openclaw-test",
exports: {
"./plugin-sdk": "./dist/plugin-sdk/index.js",
"./plugin-sdk/string-coerce-runtime": "./dist/plugin-sdk/string-coerce-runtime.js",
},
},
null,
2,
),
[DIST_PLUGIN_SDK_INDEX]: "export * from './core.js';\n",
"dist/plugin-sdk/string-coerce-runtime.js": "export const publicRuntime = true;\n",
"dist/plugin-sdk/ssrf-runtime-internal.js": "export const internal = true;\n",
[DIST_OPENCLAW_ALIAS_PACKAGE]:
'{"name":"openclaw","type":"module","exports":{"./plugin-sdk":"./plugin-sdk/index.js","./plugin-sdk/string-coerce-runtime":"./plugin-sdk/string-coerce-runtime.js"}}\n',
[DIST_OPENCLAW_ALIAS_PLUGIN_SDK_INDEX]:
"export * from '../../../../plugin-sdk/index.js';\n",
[DIST_OPENCLAW_ALIAS_PLUGIN_SDK_STRING_COERCE]:
"export * from '../../../../plugin-sdk/string-coerce-runtime.js';\n",
[RUNTIME_POSTBUILD_STAMP]: '{"head":"abc123"}\n',
},
buildPaths: [
ROOT_SRC,
ROOT_PACKAGE,
DIST_ENTRY,
DIST_PLUGIN_SDK_INDEX,
"dist/plugin-sdk/string-coerce-runtime.js",
"dist/plugin-sdk/ssrf-runtime-internal.js",
DIST_OPENCLAW_ALIAS_PACKAGE,
DIST_OPENCLAW_ALIAS_PLUGIN_SDK_INDEX,
DIST_OPENCLAW_ALIAS_PLUGIN_SDK_STRING_COERCE,
BUILD_STAMP,
RUNTIME_POSTBUILD_STAMP,
],
});
const requirement = resolveRuntimePostBuildRequirement(
createBuildRequirementDeps(tmp, {
gitHead: "abc123\n",
gitStatus: "",
}),
);
expect(requirement).toEqual({
shouldSync: false,
reason: "clean",
});
});
});
it("reports missing static runtime postbuild asset outputs when runtime stamps match HEAD", async () => {
await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => {
await setupTrackedProject(tmp, {