Skip to content

Commit 6a4b5fa

Browse files
committed
fix: harden windows cli launch
1 parent 83511c0 commit 6a4b5fa

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

src/agents/shell-utils.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
13
import { spawn } from "node:child_process";
24

5+
function resolvePowerShellPath(): string {
6+
const systemRoot = process.env.SystemRoot || process.env.WINDIR;
7+
if (systemRoot) {
8+
const candidate = path.join(
9+
systemRoot,
10+
"System32",
11+
"WindowsPowerShell",
12+
"v1.0",
13+
"powershell.exe",
14+
);
15+
if (fs.existsSync(candidate)) return candidate;
16+
}
17+
return "powershell.exe";
18+
}
19+
320
export function getShellConfig(): { shell: string; args: string[] } {
421
if (process.platform === "win32") {
522
// Use PowerShell instead of cmd.exe on Windows.
@@ -8,7 +25,7 @@ export function getShellConfig(): { shell: string; args: string[] } {
825
// When Node.js spawns cmd.exe with piped stdio, these utilities produce no output.
926
// PowerShell properly captures and redirects their output to stdout.
1027
return {
11-
shell: "powershell.exe",
28+
shell: resolvePowerShellPath(),
1229
args: ["-NoProfile", "-NonInteractive", "-Command"],
1330
};
1431
}

src/entry.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env node
22
import { spawn } from "node:child_process";
3+
import path from "node:path";
34
import process from "node:process";
45

56
import { applyCliProfileEnv, parseCliProfileArgs } from "./cli/profile.js";
@@ -56,6 +57,24 @@ function ensureExperimentalWarningSuppressed(): boolean {
5657
return true;
5758
}
5859

60+
function normalizeWindowsArgv(argv: string[]): string[] {
61+
if (process.platform !== "win32") return argv;
62+
if (argv.length < 3) return argv;
63+
const execBase = path.basename(process.execPath).toLowerCase();
64+
const arg1 = path.basename(argv[1] ?? "").toLowerCase();
65+
const arg2 = path.basename(argv[2] ?? "").toLowerCase();
66+
const looksLikeEntry = arg1 === "entry.ts" || arg1 === "entry.js";
67+
if (arg1 === execBase) {
68+
return [argv[0], ...argv.slice(2)];
69+
}
70+
if (looksLikeEntry && arg2 === execBase) {
71+
return [argv[0], argv[1], ...argv.slice(3)];
72+
}
73+
return argv;
74+
}
75+
76+
process.argv = normalizeWindowsArgv(process.argv);
77+
5978
if (!ensureExperimentalWarningSuppressed()) {
6079
const parsed = parseCliProfileArgs(process.argv);
6180
if (!parsed.ok) {

0 commit comments

Comments
 (0)