mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 12:14:46 +00:00
fix(gateway): include legacy runtime output checks
This commit is contained in:
committed by
Peter Steinberger
parent
31f74259cb
commit
d605efc17f
@@ -138,49 +138,14 @@ export function listOfficialChannelCatalogOutputs() {
|
||||
return [OFFICIAL_CHANNEL_CATALOG_OUTPUT];
|
||||
}
|
||||
|
||||
export function listStableRootRuntimeAliasOutputs(params = {}) {
|
||||
const rootDir = params.rootDir ?? ROOT;
|
||||
const distDir = path.join(rootDir, "dist");
|
||||
const fsImpl = params.fs ?? fs;
|
||||
function collectStableRootRuntimeAliasCandidates(params) {
|
||||
const distDir = params.distDir;
|
||||
const fsImpl = params.fs;
|
||||
let entries = [];
|
||||
try {
|
||||
entries = fsImpl.readdirSync(distDir, { withFileTypes: true });
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
|
||||
return entries
|
||||
.filter((entry) => entry.isFile())
|
||||
.map((entry) => entry.name.match(ROOT_RUNTIME_ALIAS_PATTERN)?.groups?.base)
|
||||
.filter((base) => typeof base === "string" && base.length > 0)
|
||||
.map((base) => `dist/${base}.js`)
|
||||
.toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
export function listLegacyCliExitCompatOutputs(params = {}) {
|
||||
const chunks = params.chunks ?? LEGACY_CLI_EXIT_COMPAT_CHUNKS;
|
||||
return chunks
|
||||
.map(({ dest }) => dest.replace(/\\/g, "/"))
|
||||
.toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
export function listCoreRuntimePostBuildOutputs(params = {}) {
|
||||
return [
|
||||
...listPluginSdkRootAliasOutputs(),
|
||||
...listOfficialChannelCatalogOutputs(),
|
||||
...listStableRootRuntimeAliasOutputs(params),
|
||||
...listLegacyCliExitCompatOutputs(params),
|
||||
].toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
export function writeStableRootRuntimeAliases(params = {}) {
|
||||
const rootDir = params.rootDir ?? ROOT;
|
||||
const distDir = path.join(rootDir, "dist");
|
||||
const fsImpl = params.fs ?? fs;
|
||||
let entries = [];
|
||||
try {
|
||||
entries = fsImpl.readdirSync(distDir, { withFileTypes: true });
|
||||
} catch {
|
||||
return;
|
||||
return new Map();
|
||||
}
|
||||
|
||||
const candidatesByAlias = new Map();
|
||||
@@ -197,42 +162,114 @@ export function writeStableRootRuntimeAliases(params = {}) {
|
||||
candidates.push(entry.name);
|
||||
candidatesByAlias.set(aliasFileName, candidates);
|
||||
}
|
||||
return candidatesByAlias;
|
||||
}
|
||||
|
||||
const resolveAliasCandidate = (aliasFileName, candidates) => {
|
||||
if (candidates.length === 1) {
|
||||
return candidates[0];
|
||||
function resolveStableRootRuntimeAliasCandidate(params) {
|
||||
const { aliasFileName, candidates, distDir, fsImpl } = params;
|
||||
if (candidates.length === 1) {
|
||||
return candidates[0];
|
||||
}
|
||||
if (aliasFileName === PLUGIN_INSTALL_RUNTIME_ALIAS.aliasFileName) {
|
||||
return resolveRootRuntimeCandidateByMarkers({
|
||||
distDir,
|
||||
fsImpl,
|
||||
aliasFileName,
|
||||
sourceIncludes: PLUGIN_INSTALL_RUNTIME_ALIAS.sourceIncludes,
|
||||
});
|
||||
}
|
||||
const candidateSet = new Set(candidates);
|
||||
const wrappers = candidates.filter((candidate) => {
|
||||
const filePath = path.join(distDir, candidate);
|
||||
let source;
|
||||
try {
|
||||
source = fsImpl.readFileSync(filePath, "utf8");
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
if (aliasFileName === PLUGIN_INSTALL_RUNTIME_ALIAS.aliasFileName) {
|
||||
return resolveRootRuntimeCandidateByMarkers({
|
||||
return candidates.some(
|
||||
(target) =>
|
||||
target !== candidate &&
|
||||
candidateSet.has(target) &&
|
||||
source.includes(`"./${target}"`) &&
|
||||
!source.includes("\n//#region "),
|
||||
);
|
||||
});
|
||||
return wrappers.length === 1 ? wrappers[0] : null;
|
||||
}
|
||||
|
||||
export function listStableRootRuntimeAliasOutputs(params = {}) {
|
||||
const rootDir = params.rootDir ?? ROOT;
|
||||
const distDir = path.join(rootDir, "dist");
|
||||
const fsImpl = params.fs ?? fs;
|
||||
return [...collectStableRootRuntimeAliasCandidates({ distDir, fs: fsImpl })]
|
||||
.filter(([aliasFileName, candidates]) =>
|
||||
resolveStableRootRuntimeAliasCandidate({
|
||||
distDir,
|
||||
fsImpl,
|
||||
aliasFileName,
|
||||
sourceIncludes: PLUGIN_INSTALL_RUNTIME_ALIAS.sourceIncludes,
|
||||
});
|
||||
}
|
||||
const candidateSet = new Set(candidates);
|
||||
const wrappers = candidates.filter((candidate) => {
|
||||
const filePath = path.join(distDir, candidate);
|
||||
let source;
|
||||
try {
|
||||
source = fsImpl.readFileSync(filePath, "utf8");
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
return candidates.some(
|
||||
(target) =>
|
||||
target !== candidate &&
|
||||
candidateSet.has(target) &&
|
||||
source.includes(`"./${target}"`) &&
|
||||
!source.includes("\n//#region "),
|
||||
);
|
||||
});
|
||||
return wrappers.length === 1 ? wrappers[0] : null;
|
||||
};
|
||||
candidates,
|
||||
}),
|
||||
)
|
||||
.map(([aliasFileName]) => `dist/${aliasFileName}`)
|
||||
.toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
export function listLegacyCliExitCompatOutputs(params = {}) {
|
||||
const chunks = params.chunks ?? LEGACY_CLI_EXIT_COMPAT_CHUNKS;
|
||||
return chunks
|
||||
.map(({ dest }) => dest.replace(/\\/g, "/"))
|
||||
.toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
export function listLegacyRootRuntimeCompatOutputs(params = {}) {
|
||||
const rootDir = params.rootDir ?? ROOT;
|
||||
const distDir = path.join(rootDir, "dist");
|
||||
const fsImpl = params.fs ?? fs;
|
||||
return [
|
||||
...LEGACY_ROOT_RUNTIME_COMPAT_ALIASES.map(([legacyFileName, aliasFileName]) => ({
|
||||
legacyFileName,
|
||||
aliasFileName,
|
||||
})),
|
||||
...LEGACY_PLUGIN_INSTALL_RUNTIME_COMPAT_ALIASES,
|
||||
]
|
||||
.filter((entry) =>
|
||||
resolveLegacyRootRuntimeCompatTarget({
|
||||
distDir,
|
||||
fsImpl,
|
||||
legacyFileName: entry.legacyFileName,
|
||||
aliasFileName: entry.aliasFileName,
|
||||
sourceIncludes: entry.sourceIncludes,
|
||||
}),
|
||||
)
|
||||
.map(({ legacyFileName }) => `dist/${legacyFileName}`)
|
||||
.toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
export function listCoreRuntimePostBuildOutputs(params = {}) {
|
||||
return [
|
||||
...listPluginSdkRootAliasOutputs(),
|
||||
...listOfficialChannelCatalogOutputs(),
|
||||
...listStableRootRuntimeAliasOutputs(params),
|
||||
...listLegacyRootRuntimeCompatOutputs(params),
|
||||
...listLegacyCliExitCompatOutputs(params),
|
||||
].toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
export function writeStableRootRuntimeAliases(params = {}) {
|
||||
const rootDir = params.rootDir ?? ROOT;
|
||||
const distDir = path.join(rootDir, "dist");
|
||||
const fsImpl = params.fs ?? fs;
|
||||
const candidatesByAlias = collectStableRootRuntimeAliasCandidates({ distDir, fs: fsImpl });
|
||||
|
||||
for (const [aliasFileName, candidates] of candidatesByAlias) {
|
||||
const aliasPath = path.join(distDir, aliasFileName);
|
||||
const candidate = resolveAliasCandidate(aliasFileName, candidates);
|
||||
const candidate = resolveStableRootRuntimeAliasCandidate({
|
||||
distDir,
|
||||
fsImpl,
|
||||
aliasFileName,
|
||||
candidates,
|
||||
});
|
||||
if (!candidate) {
|
||||
fsImpl.rmSync?.(aliasPath, { force: true });
|
||||
continue;
|
||||
|
||||
@@ -35,7 +35,10 @@ const DIST_CHANNEL_CATALOG = "dist/channel-catalog.json";
|
||||
const DIST_LEGACY_CLI_EXIT_COMPAT = "dist/memory-state-CcqRgDZU.js";
|
||||
const DIST_LEGACY_CLI_EXIT_COMPAT_ALT = "dist/memory-state-DwGdReW4.js";
|
||||
const DIST_STABLE_ROOT_RUNTIME_SOURCE = "dist/model-catalog.runtime-AbCd1234.js";
|
||||
const DIST_STABLE_ROOT_RUNTIME_SOURCE_ALT = "dist/model-catalog.runtime-EfGh5678.js";
|
||||
const DIST_STABLE_ROOT_RUNTIME_ALIAS = "dist/model-catalog.runtime.js";
|
||||
const DIST_LEGACY_ROOT_RUNTIME_TARGET = "dist/abort.runtime.js";
|
||||
const DIST_LEGACY_ROOT_RUNTIME_COMPAT = "dist/abort.runtime-DX6vo4yJ.js";
|
||||
const QA_LAB_PLUGIN_SDK_ENTRY = "dist/plugin-sdk/qa-lab.js";
|
||||
const QA_RUNTIME_PLUGIN_SDK_ENTRY = "dist/plugin-sdk/qa-runtime.js";
|
||||
const EXTENSION_INDEX = bundledPluginFile("demo", "index.ts");
|
||||
@@ -1911,6 +1914,7 @@ describe("run-node script", () => {
|
||||
DIST_CHANNEL_CATALOG,
|
||||
DIST_LEGACY_CLI_EXIT_COMPAT,
|
||||
DIST_STABLE_ROOT_RUNTIME_ALIAS,
|
||||
DIST_LEGACY_ROOT_RUNTIME_COMPAT,
|
||||
]) {
|
||||
await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => {
|
||||
await setupTrackedProject(tmp, {
|
||||
@@ -1919,6 +1923,8 @@ describe("run-node script", () => {
|
||||
[DIST_STABLE_ROOT_RUNTIME_SOURCE]: "export const value = 1;\n",
|
||||
[DIST_STABLE_ROOT_RUNTIME_ALIAS]:
|
||||
"export * from './model-catalog.runtime-AbCd1234.js';\n",
|
||||
[DIST_LEGACY_ROOT_RUNTIME_TARGET]: "export const aborted = true;\n",
|
||||
[DIST_LEGACY_ROOT_RUNTIME_COMPAT]: "export * from './abort.runtime.js';\n",
|
||||
[RUNTIME_POSTBUILD_STAMP]: '{"head":"abc123"}\n',
|
||||
},
|
||||
buildPaths: [
|
||||
@@ -1926,6 +1932,8 @@ describe("run-node script", () => {
|
||||
DIST_ENTRY,
|
||||
DIST_STABLE_ROOT_RUNTIME_SOURCE,
|
||||
DIST_STABLE_ROOT_RUNTIME_ALIAS,
|
||||
DIST_LEGACY_ROOT_RUNTIME_TARGET,
|
||||
DIST_LEGACY_ROOT_RUNTIME_COMPAT,
|
||||
BUILD_STAMP,
|
||||
RUNTIME_POSTBUILD_STAMP,
|
||||
],
|
||||
@@ -1947,6 +1955,39 @@ describe("run-node script", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("does not require ambiguous stable runtime aliases that postbuild cannot create", async () => {
|
||||
await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => {
|
||||
await setupTrackedProject(tmp, {
|
||||
files: {
|
||||
[ROOT_SRC]: "export const value = 1;\n",
|
||||
[DIST_STABLE_ROOT_RUNTIME_SOURCE]: "export const value = 1;\n",
|
||||
[DIST_STABLE_ROOT_RUNTIME_SOURCE_ALT]: "export const value = 2;\n",
|
||||
[RUNTIME_POSTBUILD_STAMP]: '{"head":"abc123"}\n',
|
||||
},
|
||||
buildPaths: [
|
||||
ROOT_SRC,
|
||||
DIST_ENTRY,
|
||||
DIST_STABLE_ROOT_RUNTIME_SOURCE,
|
||||
DIST_STABLE_ROOT_RUNTIME_SOURCE_ALT,
|
||||
BUILD_STAMP,
|
||||
RUNTIME_POSTBUILD_STAMP,
|
||||
],
|
||||
});
|
||||
|
||||
const requirement = resolveRuntimePostBuildRequirement(
|
||||
createBuildRequirementDeps(tmp, {
|
||||
gitHead: "abc123\n",
|
||||
gitStatus: "",
|
||||
}),
|
||||
);
|
||||
|
||||
expect(requirement).toEqual({
|
||||
shouldSync: false,
|
||||
reason: "clean",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("reports missing runtime skill outputs even when stamps match HEAD", async () => {
|
||||
await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => {
|
||||
await setupTrackedProject(tmp, {
|
||||
|
||||
Reference in New Issue
Block a user