diff --git a/internal/agent/prompt/prompt.go b/internal/agent/prompt/prompt.go index b40c0eaa554eb4ca3cce32cd9c4214afc5633e61..d10fbcae3c3a37f295ec9f9de637cb130d9b6abc 100644 --- a/internal/agent/prompt/prompt.go +++ b/internal/agent/prompt/prompt.go @@ -167,7 +167,7 @@ func (p *Prompt) promptData(ctx context.Context, provider, model string, cfg con Provider: provider, Model: model, Config: cfg, - WorkingDir: workingDir, + WorkingDir: filepath.ToSlash(workingDir), IsGitRepo: isGit, Platform: platform, Date: p.now().Format("1/2/2006"), diff --git a/internal/agent/tools/bash.go b/internal/agent/tools/bash.go index 8b01887f4de2051aeeca5034c747a1adf744a039..e646e14d9aa4ee6f4690adeeb256678540c249c8 100644 --- a/internal/agent/tools/bash.go +++ b/internal/agent/tools/bash.go @@ -6,6 +6,9 @@ import ( _ "embed" "fmt" "html/template" + "os" + "path/filepath" + "runtime" "strings" "time" @@ -289,7 +292,7 @@ func NewBashTool(permissions permission.Service, workingDir string, attribution if stdout == "" { return fantasy.WithResponseMetadata(fantasy.NewTextResponse(BashNoOutput), metadata), nil } - stdout += fmt.Sprintf("\n\n%s", currentWorkingDir) + stdout += fmt.Sprintf("\n\n%s", normalizeWorkingDir(currentWorkingDir)) return fantasy.WithResponseMetadata(fantasy.NewTextResponse(stdout), metadata), nil }) } @@ -313,3 +316,15 @@ func countLines(s string) int { } return len(strings.Split(s, "\n")) } + +func normalizeWorkingDir(path string) string { + if runtime.GOOS == "windows" { + cwd, err := os.Getwd() + if err != nil { + cwd = "C:" + } + path = strings.ReplaceAll(path, filepath.VolumeName(cwd), "") + } + + return filepath.ToSlash(path) +} diff --git a/internal/agent/tools/glob.go b/internal/agent/tools/glob.go index 29396dbd969787889a44a013f75a4f8fcc781354..3f56d9dcb6437d5ad6c9ca3b8416ae45c6eb7969 100644 --- a/internal/agent/tools/glob.go +++ b/internal/agent/tools/glob.go @@ -53,6 +53,7 @@ func NewGlobTool(workingDir string) fantasy.AgentTool { if len(files) == 0 { output = "No files found" } else { + normalizeFilePaths(files) output = strings.Join(files, "\n") if truncated { output += "\n\n(Results are truncated. Consider using a more specific path or pattern.)" @@ -116,3 +117,9 @@ func runRipgrep(cmd *exec.Cmd, searchRoot string, limit int) ([]string, error) { } return matches, nil } + +func normalizeFilePaths(paths []string) { + for i, p := range paths { + paths[i] = filepath.ToSlash(p) + } +} diff --git a/internal/agent/tools/grep.go b/internal/agent/tools/grep.go index 9a084131b29fb7e654a0c5284b1981cd9d367e63..3111a3f56872f72bb1735f314637d5d530a4447b 100644 --- a/internal/agent/tools/grep.go +++ b/internal/agent/tools/grep.go @@ -150,7 +150,7 @@ func NewGrepTool(workingDir string) fantasy.AgentTool { output.WriteString("\n") } currentFile = match.path - fmt.Fprintf(&output, "%s:\n", match.path) + fmt.Fprintf(&output, "%s:\n", filepath.ToSlash(match.path)) } if match.lineNum > 0 { lineText := match.lineText diff --git a/internal/agent/tools/ls.go b/internal/agent/tools/ls.go index 2ee7695ed3e2bc9495c00f650f0e9bdca86197d7..21ad0cbc80c51d253d391306a5a1621dd3c29671 100644 --- a/internal/agent/tools/ls.go +++ b/internal/agent/tools/ls.go @@ -210,9 +210,9 @@ func printTree(tree []*TreeNode, rootPath string) string { var result strings.Builder result.WriteString("- ") - result.WriteString(rootPath) + result.WriteString(filepath.ToSlash(rootPath)) if rootPath[len(rootPath)-1] != '/' { - result.WriteByte(filepath.Separator) + result.WriteByte('/') } result.WriteByte('\n') @@ -228,7 +228,7 @@ func printNode(builder *strings.Builder, node *TreeNode, level int) { nodeName := node.Name if node.Type == "directory" { - nodeName = nodeName + string(filepath.Separator) + nodeName = nodeName + "/" } fmt.Fprintf(builder, "%s- %s\n", indent, nodeName)