diff --git a/scripts/run-node.mjs b/scripts/run-node.mjs index f32bba6b7dd..ab12d30494f 100644 --- a/scripts/run-node.mjs +++ b/scripts/run-node.mjs @@ -617,6 +617,7 @@ const RUN_NODE_FILTER_SYNC_IO_STDERR_ENV = "OPENCLAW_RUN_NODE_FILTER_SYNC_IO_STD const RUN_NODE_BUILD_LOCK_TIMEOUT_ENV = "OPENCLAW_RUN_NODE_BUILD_LOCK_TIMEOUT_MS"; const RUN_NODE_BUILD_LOCK_POLL_ENV = "OPENCLAW_RUN_NODE_BUILD_LOCK_POLL_MS"; const RUN_NODE_BUILD_LOCK_STALE_ENV = "OPENCLAW_RUN_NODE_BUILD_LOCK_STALE_MS"; +const RUN_NODE_SKIP_DTS_BUILD_ENV = "OPENCLAW_RUN_NODE_SKIP_DTS_BUILD"; const DEFAULT_BUILD_LOCK_TIMEOUT_MS = 5 * 60 * 1000; const DEFAULT_BUILD_LOCK_POLL_MS = 100; const DEFAULT_BUILD_LOCK_STALE_MS = 10 * 60 * 1000; @@ -1354,7 +1355,10 @@ export async function runNodeMain(params = {}) { const build = deps.spawn(buildCmd, compilerArgs, { cwd: deps.cwd, - env: deps.env, + env: { + ...deps.env, + [RUN_NODE_SKIP_DTS_BUILD_ENV]: deps.env[RUN_NODE_SKIP_DTS_BUILD_ENV] ?? "1", + }, stdio: shouldPipeSpawnedOutput(deps) ? ["inherit", "pipe", "pipe"] : "inherit", }); pipeSpawnedOutput(build, deps); diff --git a/src/infra/run-node.test.ts b/src/infra/run-node.test.ts index 1245f60a871..bcc4f8efc55 100644 --- a/src/infra/run-node.test.ts +++ b/src/infra/run-node.test.ts @@ -464,6 +464,50 @@ describe("run-node script", () => { }); }); + it("skips DTS generation only for launcher-triggered local builds", async () => { + await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => { + await writeRuntimePostBuildScaffold(tmp); + const spawnCalls: Array<{ + args: string[]; + env: Record; + }> = []; + const spawn = (_cmd: string, args: string[], options?: unknown) => { + const opts = options as { env?: NodeJS.ProcessEnv } | undefined; + spawnCalls.push({ + args, + env: { ...opts?.env }, + }); + return createExitedProcess(0); + }; + + const exitCode = await runNodeMain({ + cwd: tmp, + args: ["status"], + env: { + ...process.env, + OPENCLAW_FORCE_BUILD: "1", + OPENCLAW_RUNNER_LOG: "0", + }, + spawn, + execPath: process.execPath, + platform: process.platform, + }); + + expect(exitCode).toBe(0); + expect(spawnCalls).toHaveLength(3); + expect(spawnCalls[0]?.args).toEqual([ + "scripts/bundled-plugin-assets.mjs", + "--phase", + "build", + ]); + expect(spawnCalls[1]?.args).toEqual(["scripts/tsdown-build.mjs", "--no-clean"]); + expect(spawnCalls[2]?.args).toEqual(["openclaw.mjs", "status"]); + expect(spawnCalls[0]?.env.OPENCLAW_RUN_NODE_SKIP_DTS_BUILD).toBeUndefined(); + expect(spawnCalls[1]?.env.OPENCLAW_RUN_NODE_SKIP_DTS_BUILD).toBe("1"); + expect(spawnCalls[2]?.env.OPENCLAW_RUN_NODE_SKIP_DTS_BUILD).toBeUndefined(); + }); + }); + it("tees launcher output into the requested generic output log", async () => { await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => { await setupTrackedProject(tmp); diff --git a/tsdown.config.ts b/tsdown.config.ts index 89b5c69309e..7e517d97610 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -33,6 +33,7 @@ const env = { NODE_ENV: "production", }; const OUTPUT_SOURCE_MAPS = process.env.OUTPUT_SOURCE_MAPS === "1"; +const RUN_NODE_SKIP_DTS_BUILD = process.env.OPENCLAW_RUN_NODE_SKIP_DTS_BUILD === "1"; const SUPPRESSED_EVAL_WARNING_PATHS = [ "@protobufjs/inquire/index.js", @@ -334,6 +335,7 @@ export default defineConfig([ // Build core entrypoints, plugin-sdk subpaths, bundled plugin entrypoints, // and bundled hooks in one graph so runtime singletons are emitted once. clean: true, + dts: RUN_NODE_SKIP_DTS_BUILD ? false : undefined, entry: buildUnifiedDistEntries(), deps: { alwaysBundle: shouldAlwaysBundleDependency,