fix(win): use PowerShell instead of cmd.exe for bash tool on Windows

This commit is contained in:
zhayujie
2026-04-08 16:18:56 +08:00
parent a653ed07eb
commit 89251e603f

View File

@@ -18,9 +18,13 @@ from common.utils import expand_path
class Bash(BaseTool): class Bash(BaseTool):
"""Tool for executing bash commands""" """Tool for executing bash commands"""
_IS_WIN = sys.platform == "win32"
name: str = "bash" name: str = "bash"
description: str = f"""Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last {DEFAULT_MAX_LINES} lines or {DEFAULT_MAX_BYTES // 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. description: str = f"""Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last {DEFAULT_MAX_LINES} lines or {DEFAULT_MAX_BYTES // 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file.
{'''
PLATFORM: Windows (PowerShell).
''' if _IS_WIN else ''}
ENVIRONMENT: All API keys from env_config are auto-injected. Use $VAR_NAME directly. ENVIRONMENT: All API keys from env_config are auto-injected. Use $VAR_NAME directly.
SAFETY: SAFETY:
@@ -102,26 +106,36 @@ SAFETY:
else: else:
logger.debug(f"[Bash] Process User: {os.environ.get('USERNAME', os.environ.get('USER', 'unknown'))}") logger.debug(f"[Bash] Process User: {os.environ.get('USERNAME', os.environ.get('USER', 'unknown'))}")
# On Windows, convert $VAR references to %VAR% for cmd.exe if self._IS_WIN:
if sys.platform == "win32":
env["PYTHONIOENCODING"] = "utf-8" env["PYTHONIOENCODING"] = "utf-8"
command = self._convert_env_vars_for_windows(command, dotenv_vars) # Use PowerShell so that LLM-generated commands can use
if command and not command.strip().lower().startswith("chcp"): # Select-String, Select-Object, curl (Invoke-WebRequest alias),
command = f"chcp 65001 >nul 2>&1 && {command}" # etc. instead of Unix-only head/grep/tail.
result = subprocess.run(
# Execute command with inherited environment variables ["powershell.exe", "-NoProfile", "-NonInteractive",
result = subprocess.run( "-ExecutionPolicy", "Bypass", "-Command", command],
command, cwd=self.cwd,
shell=True, stdout=subprocess.PIPE,
cwd=self.cwd, stderr=subprocess.PIPE,
stdout=subprocess.PIPE, text=True,
stderr=subprocess.PIPE, encoding="utf-8",
text=True, errors="replace",
encoding="utf-8", timeout=timeout,
errors="replace", env=env,
timeout=timeout, )
env=env else:
) result = subprocess.run(
command,
shell=True,
cwd=self.cwd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
encoding="utf-8",
errors="replace",
timeout=timeout,
env=env,
)
logger.debug(f"[Bash] Exit code: {result.returncode}") logger.debug(f"[Bash] Exit code: {result.returncode}")
logger.debug(f"[Bash] Stdout length: {len(result.stdout)}") logger.debug(f"[Bash] Stdout length: {len(result.stdout)}")