Summary
Our current shell execution architecture (ShellExecutionService.ts) relies on spawn({ shell: true }) on Windows. This approach is unpredictable, typically defaults to the legacy cmd.exe (even when PowerShell is available), and prevents us from managing PowerShell Execution Policies (we cannot inject -ExecutionPolicy Bypass).
We should refactor the architecture to use Explicit Shell Invocation (shell: false).
Motivation
- Reliability: Ensure scripts run reliably by injecting
-ExecutionPolicy Bypass and -NonInteractive.
- Capability: Prioritize PowerShell (
pwsh.exe or powershell.exe) over cmd.exe on Windows, as LLMs are more proficient with modern PowerShell syntax.
- Predictability: Remove reliance on the ambiguous
shell: true behavior.
Implementation Plan
This requires coordinated changes across several modules.
1. Configuration (shell-utils.ts)
- Install the
which dependency.
- Refactor
getShellConfiguration() to proactively search the PATH (using which).
- Prioritization on Windows:
pwsh.exe > powershell.exe > cmd.exe.
- Ensure PowerShell configurations include the required automation flags:
['-ExecutionPolicy', 'Bypass', '-NonInteractive', '-NoProfile', '-Command'].
2. Execution (ShellExecutionService.ts)
- Import and use
getShellConfiguration().
- Change the
spawn call to use explicit invocation:
const shellConfig = getShellConfiguration();
const args = [...shellConfig.argsPrefix, commandToExecute];
spawn(shellConfig.executable, args, { shell: false, /* ... other options ... */ });
- Ensure platform checks use a centralized
isWindows() utility rather than os.platform().
3. Consumers (shell.ts, shellCommandProcessor.ts)
shell.ts (Agent Tool):
- Dynamic Advertisement: Update
getShellToolDescription to dynamically inform the LLM which shell (Bash, PowerShell, or CMD) is active. This prevents syntax mismatches.
- Logic Compatibility: The
pgrep wrapper is Bash-specific. This logic must be conditionalized based on the detected shell (if (shellConfig.shell === 'bash')), not just the OS.
shellCommandProcessor.ts (User Shell Mode):
- Logic Compatibility: The
pwd > file wrapper is Bash-specific. This logic must also be conditionalized based on the detected shell. (We should also implement the PowerShell equivalent: (Get-Location).Path).
NOTE: We should also check the system instructions in prompts.ts to ensure we are not providing misleading examples or instructions
Summary
Our current shell execution architecture (
ShellExecutionService.ts) relies onspawn({ shell: true })on Windows. This approach is unpredictable, typically defaults to the legacycmd.exe(even when PowerShell is available), and prevents us from managing PowerShell Execution Policies (we cannot inject-ExecutionPolicy Bypass).We should refactor the architecture to use Explicit Shell Invocation (
shell: false).Motivation
-ExecutionPolicy Bypassand-NonInteractive.pwsh.exeorpowershell.exe) overcmd.exeon Windows, as LLMs are more proficient with modern PowerShell syntax.shell: truebehavior.Implementation Plan
This requires coordinated changes across several modules.
1. Configuration (
shell-utils.ts)whichdependency.getShellConfiguration()to proactively search the PATH (usingwhich).pwsh.exe>powershell.exe>cmd.exe.['-ExecutionPolicy', 'Bypass', '-NonInteractive', '-NoProfile', '-Command'].2. Execution (
ShellExecutionService.ts)getShellConfiguration().spawncall to use explicit invocation:isWindows()utility rather thanos.platform().3. Consumers (
shell.ts,shellCommandProcessor.ts)shell.ts(Agent Tool):getShellToolDescriptionto dynamically inform the LLM which shell (Bash, PowerShell, or CMD) is active. This prevents syntax mismatches.pgrepwrapper is Bash-specific. This logic must be conditionalized based on the detected shell (if (shellConfig.shell === 'bash')), not just the OS.shellCommandProcessor.ts(User Shell Mode):pwd > filewrapper is Bash-specific. This logic must also be conditionalized based on the detected shell. (We should also implement the PowerShell equivalent:(Get-Location).Path).NOTE: We should also check the system instructions in
prompts.tsto ensure we are not providing misleading examples or instructions