fix(line): resolve dist runtime contract path

This commit is contained in:
Vincent Koc
2026-04-01 15:43:40 +09:00
committed by Ayaan Zaidi
parent facdeb3432
commit d4643e06bd
2 changed files with 85 additions and 4 deletions

View File

@@ -0,0 +1,76 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { afterEach, describe, expect, it } from "vitest";
import { loadSiblingRuntimeModuleSync } from "./local-runtime-module.js";
const tempDirs = new Set<string>();
function createTempDir(): string {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-local-runtime-module-"));
tempDirs.add(dir);
return dir;
}
function writeFile(filePath: string, content: string): void {
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, content);
}
afterEach(() => {
for (const dir of tempDirs) {
fs.rmSync(dir, { recursive: true, force: true });
}
tempDirs.clear();
});
describe("loadSiblingRuntimeModuleSync", () => {
it("loads a sibling runtime module from the caller directory", () => {
const root = createTempDir();
const moduleUrl = pathToFileURL(
path.join(root, "src", "plugins", "runtime", "runtime-line.js"),
).href;
writeFile(
path.join(root, "src", "plugins", "runtime", "runtime-line.contract.js"),
"module.exports = { runtimeLine: { source: 'sibling' } };",
);
const loaded = loadSiblingRuntimeModuleSync<{ runtimeLine: { source: string } }>({
moduleUrl,
relativeBase: "./runtime-line.contract",
});
expect(loaded.runtimeLine.source).toBe("sibling");
});
it("falls back to the built plugins/runtime dist layout", () => {
const root = createTempDir();
const moduleUrl = pathToFileURL(path.join(root, "dist", "runtime-9DLN_Ai5.js")).href;
writeFile(
path.join(root, "dist", "plugins", "runtime", "runtime-line.contract.js"),
"module.exports = { runtimeLine: { source: 'dist-runtime' } };",
);
const loaded = loadSiblingRuntimeModuleSync<{ runtimeLine: { source: string } }>({
moduleUrl,
relativeBase: "./runtime-line.contract",
});
expect(loaded.runtimeLine.source).toBe("dist-runtime");
});
it("throws when no candidate runtime module exists", () => {
const root = createTempDir();
const moduleUrl = pathToFileURL(path.join(root, "dist", "runtime-9DLN_Ai5.js")).href;
expect(() =>
loadSiblingRuntimeModuleSync({
moduleUrl,
relativeBase: "./runtime-line.contract",
}),
).toThrow("Unable to resolve runtime module ./runtime-line.contract");
});
});

View File

@@ -13,10 +13,15 @@ const jitiLoaders = new Map<string, ReturnType<typeof createJiti>>();
function resolveSiblingRuntimeModulePath(moduleUrl: string, relativeBase: string): string {
const baseDir = path.dirname(fileURLToPath(moduleUrl));
for (const ext of RUNTIME_MODULE_EXTENSIONS) {
const candidate = path.resolve(baseDir, `${relativeBase}${ext}`);
if (fs.existsSync(candidate)) {
return candidate;
const baseName = relativeBase.replace(/^\.\//, "");
const candidateDirs = [baseDir, path.resolve(baseDir, "plugins", "runtime")];
for (const dir of candidateDirs) {
for (const ext of RUNTIME_MODULE_EXTENSIONS) {
const candidate = path.resolve(dir, `${baseName}${ext}`);
if (fs.existsSync(candidate)) {
return candidate;
}
}
}
throw new Error(`Unable to resolve runtime module ${relativeBase} from ${moduleUrl}`);