fix: enhance Windows compatibility in command execution and prompts

This commit is contained in:
Cheikh Seck committed 2026-06-30 20:32:10 +00:00
1 parent 9377f3b942
commit 9c1b185e40
3 files changed
+26 -10

No files matched your search

+15 -5
View File
@@ -2099,15 +2099,26 @@ func buildFullPrompt(nativeToolCalls bool, toolsSection, sessionContext, wd, inp
hiveInfo = fmt.Sprintf(`- Hive Instance ID: %s. You can't assign a task to yourself, but you can ask other hive workers to perform tasks for you.
`, hiveInstanceID)
}
osName := runtime.GOOS
base += fmt.Sprintf(`CRITICAL INFORMATION:
- Operating System: %s (%s)
- Current working directory: %s
%sUse this path when the user asks about "this folder", "current directory", or similar.
IMPORTANT: Execute tools FIRST, perform any action asked for by the user, then provide the final answer. Do NOT include any final answer, summary, or "FINAL_ANSWER:" until AFTER you have executed all necessary tools and received their results. If you need to run commands/tests to verify something, run them first before answering.
`, runtime.GOOS, runtime.GOARCH, wd, hiveInfo)
`, osName, runtime.GOARCH, wd, hiveInfo)
if !nativeToolCalls {
shellName := "sh"
shellLimits := `- Shell variables like $HOME, $PATH are NOT expanded - use absolute paths instead
- Interactive commands (vim, less, top) will NOT work - use non-interactive alternatives
- Shell aliases are NOT expanded - use full command names`
if osName == "windows" {
shellName = "cmd.exe"
shellLimits = `- Use cmd.exe syntax (e.g., %USERPROFILE% not $HOME, %PATH% not $PATH)
- PowerShell-specific commands may not work; prefer cmd.exe built-ins
- Interactive commands will NOT work - use non-interactive alternatives`
}
base = fmt.Sprintf(`You have access to these tools:
%s
@@ -2117,9 +2128,8 @@ IMPORTANT: When you need to read files, search, or get directory contents, you M
Do NOT use example paths like "/path/to/directory" - use the actual path: %s
BASH TOOL LIMITATIONS:
- Shell variables like $HOME, $PATH are NOT expanded - use absolute paths instead
- Interactive commands (vim, less, top) will NOT work - use non-interactive alternatives
- Shell aliases are NOT expanded - use full command names
- Commands run via `+"`"+`%s`+"`"+` (%s)
- %s
- NEVER run servers or long-running programs in foreground - they will hang. ALWAYS use background: true
- ALWAYS use background: true for any server, daemon, or program that doesn't exit immediately
- ALWAYS use background: true when starting a webserver or a long-running background task
@@ -2141,7 +2151,7 @@ Example:
`+"```"+`
IMPORTANT: Execute tools FIRST, perform any action asked for by the user, then provide the final answer. Do NOT include any final answer, summary, or "FINAL_ANSWER:" until AFTER you have executed all necessary tools and received their results. If you need to run commands/tests to verify something, run them first before answering.
`, toolsSection, base, wd)
`, toolsSection, base, wd, shellName, shellLimits)
}
if strings.TrimSpace(tree) != "" {
+9 -3
View File
@@ -10,6 +10,7 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"sync"
"syscall"
@@ -271,8 +272,8 @@ func NewBashServer(allowedPaths []string, autoConfirm bool) *BashServer {
jobTracker: NewJobTracker(),
tools: []Tool{
{
Name: "run_command",
Description: "Run a shell command and return its output. For servers/services/long-running processes, you MUST set background: true (killable via /kill or /killbg).",
Name: "run_command",
Description: "Run a shell command and return its output. Uses cmd.exe on Windows, sh on Unix. For servers/services/long-running processes, you MUST set background: true (killable via /kill or /killbg).",
InputSchema: json.RawMessage(`{"type":"object","properties":{"command":{"type":"string","description":"Shell command to run"},"timeout":{"type":"number","description":"Timeout in seconds (default 180)"},"background":{"type":"boolean","description":"Run in background as a goroutine (default false)"}},"required":["command"]}`),
},
{
@@ -594,7 +595,12 @@ func (s *BashServer) runSyncCommand(ctx context.Context, command string, timeout
ctx, cancel := context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "sh", "-c", command)
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.CommandContext(ctx, "cmd", "/c", command)
} else {
cmd = exec.CommandContext(ctx, "sh", "-c", command)
}
cmd.Stdin = nil // Close stdin to prevent interactive prompts from blocking
var stdout, stderr bytes.Buffer
+2 -2
View File
@@ -663,7 +663,7 @@ func (s *Scheduler) executeWithTools(ctx context.Context, task *ScheduledTask) (
}
func (s *Scheduler) buildInitialPrompt(input, toolsDesc string, toolCallFormat string, nativeToolCalls bool) string {
osInfo := "linux"
osInfo := runtime.GOOS
if s.os != "" {
osInfo = s.os
}
@@ -692,7 +692,7 @@ func (s *Scheduler) buildContinuePrompt(continuePrompt, toolsDesc string, toolCa
if currentRound > 0 {
roundInfo = fmt.Sprintf("\n\nNOTE: You are on round %d/%d. Only call more tools if absolutely necessary.", currentRound, maxRounds)
}
osInfo := "linux"
osInfo := runtime.GOOS
if s.os != "" {
osInfo = s.os
}