From 80bac5a2395bcd31c0b4a8c0e4aa5180023926fa Mon Sep 17 00:00:00 2001 From: CXin <89342487+ChenXin-2009@users.noreply.github.com> Date: Mon, 29 Jun 2026 20:09:51 +0800 Subject: [PATCH 1/2] fix: fall back to cmd.exe when PowerShell unavailable on Windows (#11960) --- .../implementations/runTerminalCommand.ts | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/core/tools/implementations/runTerminalCommand.ts b/core/tools/implementations/runTerminalCommand.ts index 8f6201bd12c..673d2f53f7f 100644 --- a/core/tools/implementations/runTerminalCommand.ts +++ b/core/tools/implementations/runTerminalCommand.ts @@ -21,13 +21,34 @@ function getDecodedOutput(data: Buffer): string { } else { return data.toString(); } -} // Simple helper function to use login shell on Unix/macOS and PowerShell on Windows +} +// Try to detect if PowerShell is available on Windows +function isPowerShellAvailable(): boolean { + try { + childProcess.execFileSync("powershell.exe", ["-NoProfile", "-Command", "exit"], { + timeout: 3000, + windowsHide: true, + }); + return true; + } catch { + return false; + } +} + +// Helper function to use login shell on Unix/macOS and PowerShell on Windows +// Falls back to cmd.exe when PowerShell is unavailable (e.g., corporate policy) function getShellCommand(command: string): { shell: string; args: string[] } { if (process.platform === "win32") { - // Windows: Use PowerShell + if (isPowerShellAvailable()) { + return { + shell: "powershell.exe", + args: ["-NoLogo", "-ExecutionPolicy", "Bypass", "-Command", command], + }; + } + const cmd = process.env.COMSPEC || "cmd.exe"; return { - shell: "powershell.exe", - args: ["-NoLogo", "-ExecutionPolicy", "Bypass", "-Command", command], + shell: cmd, + args: ["/C", command], }; } else { // Unix/macOS: Use login shell to source .bashrc/.zshrc etc. From 89d3d31f990522fae752f9a3403e0b9fda2d5a73 Mon Sep 17 00:00:00 2001 From: CXin <89342487+ChenXin-2009@users.noreply.github.com> Date: Mon, 29 Jun 2026 20:27:10 +0800 Subject: [PATCH 2/2] cache PowerShell availability check to avoid repeated 3s probe (#11960) --- .../implementations/runTerminalCommand.ts | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/core/tools/implementations/runTerminalCommand.ts b/core/tools/implementations/runTerminalCommand.ts index 673d2f53f7f..25b302b9bd9 100644 --- a/core/tools/implementations/runTerminalCommand.ts +++ b/core/tools/implementations/runTerminalCommand.ts @@ -22,17 +22,28 @@ function getDecodedOutput(data: Buffer): string { return data.toString(); } } -// Try to detect if PowerShell is available on Windows +// Cached result of PowerShell availability check +let _powerShellAvailable: boolean | undefined; + +// Try to detect if PowerShell is available on Windows (result is cached) function isPowerShellAvailable(): boolean { + if (_powerShellAvailable !== undefined) { + return _powerShellAvailable; + } try { - childProcess.execFileSync("powershell.exe", ["-NoProfile", "-Command", "exit"], { - timeout: 3000, - windowsHide: true, - }); - return true; + childProcess.execFileSync( + "powershell.exe", + ["-NoProfile", "-Command", "exit"], + { + timeout: 3000, + windowsHide: true, + }, + ); + _powerShellAvailable = true; } catch { - return false; + _powerShellAvailable = false; } + return _powerShellAvailable; } // Helper function to use login shell on Unix/macOS and PowerShell on Windows