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)