From b33bd6aaeb90fe220cbbd19538146814e2afd8fd Mon Sep 17 00:00:00 2001 From: myfunc Date: Sun, 11 Jan 2026 16:35:21 -0800 Subject: [PATCH] fix(bash): use PowerShell on Windows to capture system utility output Windows system utilities like ipconfig, systeminfo, etc. write directly to the console via WriteConsole API instead of stdout. When Node.js spawns cmd.exe with piped stdio, these utilities produce empty output. Changes: - Switch from cmd.exe to PowerShell on Windows (properly redirects output) - Disable detached mode on Windows (PowerShell doesn't pipe stdout when detached) - Add windowsHide option to prevent console window flashing - Update tests to use PowerShell-compatible syntax (Start-Sleep, semicolons) --- src/agents/bash-tools.test.ts | 11 ++++++----- src/agents/bash-tools.ts | 6 ++++-- src/agents/shell-utils.ts | 11 +++++++++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/agents/bash-tools.test.ts b/src/agents/bash-tools.test.ts index 16c0850fa..56cff37fe 100644 --- a/src/agents/bash-tools.test.ts +++ b/src/agents/bash-tools.test.ts @@ -9,11 +9,12 @@ import { import { sanitizeBinaryOutput } from "./shell-utils.js"; const isWin = process.platform === "win32"; -const shortDelayCmd = isWin ? "ping -n 2 127.0.0.1 > nul" : "sleep 0.05"; -const yieldDelayCmd = isWin ? "ping -n 3 127.0.0.1 > nul" : "sleep 0.2"; -const longDelayCmd = isWin ? "ping -n 4 127.0.0.1 > nul" : "sleep 2"; -const joinCommands = (commands: string[]) => - commands.join(isWin ? " & " : "; "); +// PowerShell: Start-Sleep for delays, ; for command separation, $null for null device +const shortDelayCmd = isWin ? "Start-Sleep -Milliseconds 50" : "sleep 0.05"; +const yieldDelayCmd = isWin ? "Start-Sleep -Milliseconds 200" : "sleep 0.2"; +const longDelayCmd = isWin ? "Start-Sleep -Seconds 2" : "sleep 2"; +// Both PowerShell and bash use ; for command separation +const joinCommands = (commands: string[]) => commands.join("; "); const echoAfterDelay = (message: string) => joinCommands([shortDelayCmd, `echo ${message}`]); const echoLines = (lines: string[]) => diff --git a/src/agents/bash-tools.ts b/src/agents/bash-tools.ts index 0f37afe40..1d1175373 100644 --- a/src/agents/bash-tools.ts +++ b/src/agents/bash-tools.ts @@ -265,15 +265,17 @@ export function createBashTool( { cwd: workdir, env: process.env, - detached: true, + detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"], + windowsHide: true, }, ) : spawn(shell, [...shellArgs, params.command], { cwd: workdir, env, - detached: true, + detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"], + windowsHide: true, }); const session = { diff --git a/src/agents/shell-utils.ts b/src/agents/shell-utils.ts index 6302b51d3..27ac5bf21 100644 --- a/src/agents/shell-utils.ts +++ b/src/agents/shell-utils.ts @@ -2,8 +2,15 @@ import { spawn } from "node:child_process"; export function getShellConfig(): { shell: string; args: string[] } { if (process.platform === "win32") { - const shell = process.env.COMSPEC?.trim() || "cmd.exe"; - return { shell, args: ["/d", "/s", "/c"] }; + // Use PowerShell instead of cmd.exe on Windows. + // Problem: Many Windows system utilities (ipconfig, systeminfo, etc.) write + // directly to the console via WriteConsole API, bypassing stdout pipes. + // When Node.js spawns cmd.exe with piped stdio, these utilities produce no output. + // PowerShell properly captures and redirects their output to stdout. + return { + shell: "powershell.exe", + args: ["-NoProfile", "-NonInteractive", "-Command"], + }; } const shell = process.env.SHELL?.trim() || "sh";