mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix(server): use shell on Windows for all provider spawns
Windows npm shims (e.g. C:\nvm4w\nodejs\codex) fail with ENOENT when spawned without shell. Use `shell: true` on win32 for all provider launches instead of the overly complex shouldUseWindowsShell function.
This commit is contained in:
@@ -175,6 +175,7 @@ function checkProviderBinary(binary: string): { path: string | null; version: st
|
|||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
stdio: ["ignore", "pipe", "pipe"],
|
stdio: ["ignore", "pipe", "pipe"],
|
||||||
env,
|
env,
|
||||||
|
shell: process.platform === "win32",
|
||||||
}).trim();
|
}).trim();
|
||||||
return { path: binaryPath, version: output || null };
|
return { path: binaryPath, version: output || null };
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -168,6 +168,24 @@ describe("findExecutable", () => {
|
|||||||
expect(env.Path).toContain("C:\\Users\\boudr\\.local\\bin");
|
expect(env.Path).toContain("C:\\Users\\boudr\\.local\\bin");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("on Windows, preserves the first where.exe match", () => {
|
||||||
|
findExecutableDependencies.platform = vi.fn(() => "win32");
|
||||||
|
process.env.Path = "C:\\Windows\\System32";
|
||||||
|
findExecutableDependencies.execFileSync.mockImplementation(
|
||||||
|
((command: string) => {
|
||||||
|
if (command === "powershell") {
|
||||||
|
return "C:\\Windows\\System32\r\nC:\\nvm4w\\nodejs\r\n";
|
||||||
|
}
|
||||||
|
if (command === "where.exe") {
|
||||||
|
return "C:\\nvm4w\\nodejs\\codex\r\nC:\\nvm4w\\nodejs\\codex.cmd\r\n";
|
||||||
|
}
|
||||||
|
throw new Error(`unexpected command ${command}`);
|
||||||
|
}) as any,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(findExecutable("codex", findExecutableDependencies)).toBe("C:\\nvm4w\\nodejs\\codex");
|
||||||
|
});
|
||||||
|
|
||||||
test("uses the last line from login-shell which output", () => {
|
test("uses the last line from login-shell which output", () => {
|
||||||
findExecutableDependencies.shell = "/bin/zsh";
|
findExecutableDependencies.shell = "/bin/zsh";
|
||||||
findExecutableDependencies.execSync.mockReturnValue(
|
findExecutableDependencies.execSync.mockReturnValue(
|
||||||
|
|||||||
@@ -187,7 +187,10 @@ export function applyProviderEnv(
|
|||||||
* user opened a terminal and typed the command. If that fails (e.g. the login
|
* user opened a terminal and typed the command. If that fails (e.g. the login
|
||||||
* shell itself errors) we fall back to a plain `which`.
|
* shell itself errors) we fall back to a plain `which`.
|
||||||
*
|
*
|
||||||
* On Windows the system PATH is always available, so `where.exe` is sufficient.
|
* On Windows we augment the daemon PATH with machine/user registry PATH values
|
||||||
|
* and return the first `where.exe` match. Launch-time execution decides whether
|
||||||
|
* the resolved path needs `cmd.exe` semantics (for example npm shims under
|
||||||
|
* nvm4w such as `C:\nvm4w\nodejs\codex`).
|
||||||
*/
|
*/
|
||||||
export function findExecutable(
|
export function findExecutable(
|
||||||
name: string,
|
name: string,
|
||||||
@@ -228,8 +231,12 @@ export function findExecutable(
|
|||||||
Path: resolvedPath,
|
Path: resolvedPath,
|
||||||
};
|
};
|
||||||
const out = deps.execFileSync("where.exe", [trimmed], { encoding: "utf8", env }).trim();
|
const out = deps.execFileSync("where.exe", [trimmed], { encoding: "utf8", env }).trim();
|
||||||
const firstLine = out.split(/\r?\n/)[0]?.trim();
|
return (
|
||||||
return firstLine || null;
|
out
|
||||||
|
.split(/\r?\n/)
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.find((line) => line.length > 0) ?? null
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ function applyRuntimeSettingsToClaudeOptions(
|
|||||||
...applyProviderEnv(spawnOptions.env, runtimeSettings),
|
...applyProviderEnv(spawnOptions.env, runtimeSettings),
|
||||||
...(launchEnv ?? {}),
|
...(launchEnv ?? {}),
|
||||||
},
|
},
|
||||||
|
shell: process.platform === "win32",
|
||||||
signal: spawnOptions.signal,
|
signal: spawnOptions.signal,
|
||||||
stdio: ["pipe", "pipe", "pipe"],
|
stdio: ["pipe", "pipe", "pipe"],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3421,6 +3421,7 @@ export class CodexAppServerAgentClient implements AgentClient {
|
|||||||
);
|
);
|
||||||
return spawn(launchPrefix.command, [...launchPrefix.args, "app-server"], {
|
return spawn(launchPrefix.command, [...launchPrefix.args, "app-server"], {
|
||||||
detached: process.platform !== "win32",
|
detached: process.platform !== "win32",
|
||||||
|
shell: process.platform === "win32",
|
||||||
stdio: ["pipe", "pipe", "pipe"],
|
stdio: ["pipe", "pipe", "pipe"],
|
||||||
env: buildCodexAppServerEnv(this.runtimeSettings, launchEnv),
|
env: buildCodexAppServerEnv(this.runtimeSettings, launchEnv),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -336,6 +336,7 @@ export class OpenCodeServerManager {
|
|||||||
launchPrefix.command,
|
launchPrefix.command,
|
||||||
[...launchPrefix.args, "serve", "--port", String(this.port)],
|
[...launchPrefix.args, "serve", "--port", String(this.port)],
|
||||||
{
|
{
|
||||||
|
shell: process.platform === "win32",
|
||||||
stdio: ["ignore", "pipe", "pipe"],
|
stdio: ["ignore", "pipe", "pipe"],
|
||||||
env: applyProviderEnv(process.env, this.runtimeSettings),
|
env: applyProviderEnv(process.env, this.runtimeSettings),
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user