From a11fae3912e820ae74385d646009f862556550a2 Mon Sep 17 00:00:00 2001 From: AuroraAeon Date: Wed, 23 Sep 2026 16:18:31 +0800 Subject: [PATCH] fix: run the bundle build's npm spawn through npm's CLI entry point build-coding-agent-bundle.mjs spawns `execFileSync("npm", ...)`, which fails on Windows: ENOENT because the npm.cmd shim is not resolved, EINVAL when npm.cmd is passed without a shell, and with shell:true the unquoted `--prefix ` argument splits on spaces in the repo path, so ./test.sh cannot complete its build step from a fresh checkout. Resolve npm's JS entry via npm_execpath (set by npm/pnpm lifecycle scripts), falling back to the npm-cli.js beside node.exe and then to the previous PATH spawn (shell-resolved on win32 only). POSIX behavior is unchanged. --- scripts/build-coding-agent-bundle.mjs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/scripts/build-coding-agent-bundle.mjs b/scripts/build-coding-agent-bundle.mjs index fa8d4333..0cc25512 100644 --- a/scripts/build-coding-agent-bundle.mjs +++ b/scripts/build-coding-agent-bundle.mjs @@ -178,7 +178,29 @@ function outputBytes(metafiles) { // stays self-contained despite the entry now living in the app package. Always // rebuild rather than trusting a pre-existing dist/main.js: a stale app compile // from an earlier checkout would otherwise be baked into the bundle. -execFileSync("npm", ["--prefix", appEntryDir, "run", "build"], { stdio: "inherit", cwd: repoRoot }); +// Run npm's CLI entry point through the current Node binary instead of +// spawning the `npm` command, which fails on Windows in every naive form: +// `execFileSync("npm")` cannot resolve the `npm.cmd` shim (ENOENT), Node +// rejects spawning `.cmd` files without a shell (EINVAL), and a +// `shell: true` retry splits `--prefix ` on spaces (the argument is +// passed to cmd.exe unquoted). +// 1. npm/pnpm lifecycle scripts expose their own entry via `npm_execpath`. +// 2. The standard Windows installer ships npm-cli.js next to node.exe. +// 3. Otherwise fall back to spawning `npm` (shell-resolved on win32 only), +// matching profile-coding-agent-node.mjs. +function resolveNpmEntryPoint() { + const fromEnv = process.env.npm_execpath; + if (fromEnv && fromEnv.endsWith(".js") && existsSync(fromEnv)) return fromEnv; + const besideNode = join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js"); + return existsSync(besideNode) ? besideNode : undefined; +} +const npmBuildArgs = ["--prefix", appEntryDir, "run", "build"]; +const npmEntryPoint = resolveNpmEntryPoint(); +if (npmEntryPoint) { + execFileSync(process.execPath, [npmEntryPoint, ...npmBuildArgs], { stdio: "inherit", cwd: repoRoot }); +} else { + execFileSync("npm", npmBuildArgs, { stdio: "inherit", cwd: repoRoot, shell: process.platform === "win32" }); +} for (const entry of [ join(appEntryDistDir, "main.js"),