fix(ls): fix path expand on ls tool

Andrey Nering created

Change summary

internal/fsext/expand.go | 29 +++++++++++++++++++++++++++++
internal/llm/tools/ls.go | 10 ++++------
2 files changed, 33 insertions(+), 6 deletions(-)

Detailed changes

internal/fsext/expand.go 🔗

@@ -0,0 +1,29 @@
+package fsext
+
+import (
+	"os"
+	"strings"
+
+	"mvdan.cc/sh/v3/expand"
+	"mvdan.cc/sh/v3/syntax"
+)
+
+// Expand is a wrapper around [expand.Literal]. It will escape the input
+// string, expand any shell symbols (such as '~') and resolve any environment
+// variables.
+func Expand(s string) (string, error) {
+	if s == "" {
+		return "", nil
+	}
+	p := syntax.NewParser()
+	word, err := p.Document(strings.NewReader(s))
+	if err != nil {
+		return "", err
+	}
+	cfg := &expand.Config{
+		Env:      expand.FuncEnviron(os.Getenv),
+		ReadDir2: os.ReadDir,
+		GlobStar: true,
+	}
+	return expand.Literal(cfg, word)
+}

internal/llm/tools/ls.go 🔗

@@ -121,12 +121,10 @@ func (l *lsTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) {
 		searchPath = l.workingDir
 	}
 
-	if searchPath == "~" {
-		homeDir, err := os.UserHomeDir()
-		if err != nil {
-			return ToolResponse{}, fmt.Errorf("error resolving home directory: %w", err)
-		}
-		searchPath = homeDir
+	var err error
+	searchPath, err = fsext.Expand(searchPath)
+	if err != nil {
+		return ToolResponse{}, fmt.Errorf("error expanding path: %w", err)
 	}
 
 	if !filepath.IsAbs(searchPath) {