diff --git a/scripts/run-node.mjs b/scripts/run-node.mjs index 56a63805e70..33317ae8797 100644 --- a/scripts/run-node.mjs +++ b/scripts/run-node.mjs @@ -6,8 +6,8 @@ import process from "node:process"; import { pathToFileURL } from "node:url"; import { runRuntimePostBuild } from "./runtime-postbuild.mjs"; -const compiler = "tsdown"; -const compilerArgs = ["exec", compiler, "--no-clean"]; +const buildScript = "scripts/tsdown-build.mjs"; +const compilerArgs = [buildScript, "--no-clean"]; const runNodeSourceRoots = ["src", "extensions"]; const runNodeConfigFiles = ["tsconfig.json", "package.json", "tsdown.config.ts"]; @@ -313,7 +313,6 @@ export async function runNodeMain(params = {}) { cwd: params.cwd ?? process.cwd(), args: params.args ?? process.argv.slice(2), env: params.env ? { ...params.env } : { ...process.env }, - platform: params.platform ?? process.platform, }; deps.distRoot = path.join(deps.cwd, "dist"); @@ -333,9 +332,8 @@ export async function runNodeMain(params = {}) { } logRunner("Building TypeScript (dist is stale).", deps); - const buildCmd = deps.platform === "win32" ? "cmd.exe" : "pnpm"; - const buildArgs = - deps.platform === "win32" ? ["/d", "/s", "/c", "pnpm", ...compilerArgs] : compilerArgs; + const buildCmd = deps.execPath; + const buildArgs = compilerArgs; const build = deps.spawn(buildCmd, buildArgs, { cwd: deps.cwd, env: deps.env, diff --git a/scripts/tsdown-build.mjs b/scripts/tsdown-build.mjs index ccd56a4aff0..1c346b54a78 100644 --- a/scripts/tsdown-build.mjs +++ b/scripts/tsdown-build.mjs @@ -3,9 +3,10 @@ import { spawnSync } from "node:child_process"; const logLevel = process.env.OPENCLAW_BUILD_VERBOSE ? "info" : "warn"; +const extraArgs = process.argv.slice(2); const result = spawnSync( "pnpm", - ["exec", "tsdown", "--config-loader", "unrun", "--logLevel", logLevel], + ["exec", "tsdown", "--config-loader", "unrun", "--logLevel", logLevel, ...extraArgs], { stdio: "inherit", shell: process.platform === "win32", diff --git a/src/infra/run-node.test.ts b/src/infra/run-node.test.ts index 59ac7cd0666..dfebf6c2ad2 100644 --- a/src/infra/run-node.test.ts +++ b/src/infra/run-node.test.ts @@ -33,10 +33,8 @@ async function writeRuntimePostBuildScaffold(tmp: string): Promise { await fs.utimes(pluginSdkAliasPath, baselineTime, baselineTime); } -function expectedBuildSpawn(platform: NodeJS.Platform = process.platform) { - return platform === "win32" - ? ["cmd.exe", "/d", "/s", "/c", "pnpm", "exec", "tsdown", "--no-clean"] - : ["pnpm", "exec", "tsdown", "--no-clean"]; +function expectedBuildSpawn() { + return [process.execPath, "scripts/tsdown-build.mjs", "--no-clean"]; } describe("run-node script", () => { @@ -44,7 +42,7 @@ describe("run-node script", () => { "preserves control-ui assets by building with tsdown --no-clean", async () => { await withTempDir(async (tmp) => { - const argsPath = path.join(tmp, ".pnpm-args.txt"); + const argsPath = path.join(tmp, ".build-args.txt"); const indexPath = path.join(tmp, "dist", "control-ui", "index.html"); await writeRuntimePostBuildScaffold(tmp); @@ -53,7 +51,7 @@ describe("run-node script", () => { const nodeCalls: string[][] = []; const spawn = (cmd: string, args: string[]) => { - if (cmd === "pnpm") { + if (cmd === process.execPath && args[0] === "scripts/tsdown-build.mjs") { fsSync.writeFileSync(argsPath, args.join(" "), "utf-8"); if (!args.includes("--no-clean")) { fsSync.rmSync(path.join(tmp, "dist", "control-ui"), { recursive: true, force: true }); @@ -87,9 +85,14 @@ describe("run-node script", () => { }); expect(exitCode).toBe(0); - await expect(fs.readFile(argsPath, "utf-8")).resolves.toContain("exec tsdown --no-clean"); + await expect(fs.readFile(argsPath, "utf-8")).resolves.toContain( + "scripts/tsdown-build.mjs --no-clean", + ); await expect(fs.readFile(indexPath, "utf-8")).resolves.toContain("sentinel"); - expect(nodeCalls).toEqual([[process.execPath, "openclaw.mjs", "--version"]]); + expect(nodeCalls).toEqual([ + [process.execPath, "scripts/tsdown-build.mjs", "--no-clean"], + [process.execPath, "openclaw.mjs", "--version"], + ]); }); }, ); @@ -151,8 +154,10 @@ describe("run-node script", () => { fs.readFile(path.join(tmp, "dist", "plugin-sdk", "root-alias.cjs"), "utf-8"), ).resolves.toContain("module.exports = {};"); await expect( - fs.readFile(path.join(tmp, "dist", "extensions", "demo", "openclaw.plugin.json"), "utf-8"), - ).resolves.toContain('"id":"demo"'); + fs + .readFile(path.join(tmp, "dist", "extensions", "demo", "openclaw.plugin.json"), "utf-8") + .then((raw) => JSON.parse(raw)), + ).resolves.toMatchObject({ id: "demo" }); await expect( fs.readFile(path.join(tmp, "dist", "extensions", "demo", "package.json"), "utf-8"), ).resolves.toContain( @@ -222,7 +227,7 @@ describe("run-node script", () => { it("returns the build exit code when the compiler step fails", async () => { await withTempDir(async (tmp) => { const spawn = (cmd: string, args: string[] = []) => { - if (cmd === "pnpm" || (cmd === "cmd.exe" && args.includes("pnpm"))) { + if (cmd === process.execPath && args[0] === "scripts/tsdown-build.mjs") { return createExitedProcess(23); } return createExitedProcess(0); @@ -501,7 +506,11 @@ describe("run-node script", () => { expect(exitCode).toBe(0); expect(spawnCalls).toEqual([[process.execPath, "openclaw.mjs", "status"]]); - await expect(fs.readFile(distManifestPath, "utf-8")).resolves.toContain('"id":"demo"'); + await expect( + fs.readFile(distManifestPath, "utf-8").then((raw) => JSON.parse(raw)), + ).resolves.toMatchObject({ + id: "demo", + }); }); }); @@ -567,7 +576,11 @@ describe("run-node script", () => { expect(exitCode).toBe(0); expect(spawnCalls).toEqual([[process.execPath, "openclaw.mjs", "status"]]); - await expect(fs.readFile(distManifestPath, "utf-8")).resolves.toContain('"id":"demo"'); + await expect( + fs.readFile(distManifestPath, "utf-8").then((raw) => JSON.parse(raw)), + ).resolves.toMatchObject({ + id: "demo", + }); }); });