diff --git a/pkg/tools/builtin/filesystem.go b/pkg/tools/builtin/filesystem.go index 34e250a85..1423985e2 100644 --- a/pkg/tools/builtin/filesystem.go +++ b/pkg/tools/builtin/filesystem.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io/fs" "log/slog" @@ -51,6 +52,9 @@ var ( _ tools.Instructable = (*FilesystemTool)(nil) ) +// allowAllPaths is a no-op path filter that permits every path. +func allowAllPaths(_ string) error { return nil } + type FileSystemOpt func(*FilesystemTool) func WithPostEditCommands(postEditCommands []PostEditConfig) FileSystemOpt { @@ -375,11 +379,7 @@ func (t *FilesystemTool) shouldIgnorePath(path string) bool { // Lazily initialize the gitignore matcher on first use t.initGitignoreMatcher() - if t.repoMatcher != nil && t.repoMatcher.ShouldIgnore(path) { - return true - } - - return false + return t.repoMatcher != nil && t.repoMatcher.ShouldIgnore(path) } // Handler implementations @@ -387,11 +387,7 @@ func (t *FilesystemTool) shouldIgnorePath(path string) bool { func (t *FilesystemTool) handleDirectoryTree(ctx context.Context, args DirectoryTreeArgs) (*tools.ToolCallResult, error) { resolvedPath := t.resolvePath(args.Path) - isPathAllowed := func(_ string) error { - return nil - } - - tree, err := fsx.DirectoryTree(ctx, resolvedPath, isPathAllowed, t.shouldIgnorePath, maxFiles) + tree, err := fsx.DirectoryTree(ctx, resolvedPath, allowAllPaths, t.shouldIgnorePath, maxFiles) if err != nil { return tools.ResultError(fmt.Sprintf("Error building directory tree: %s", err)), nil } @@ -512,7 +508,7 @@ func (t *FilesystemTool) handleReadFile(_ context.Context, args ReadFileArgs) (* info, err := os.Stat(resolvedPath) if err != nil { var errMsg string - if os.IsNotExist(err) { + if errors.Is(err, fs.ErrNotExist) { errMsg = "not found" } else { errMsg = err.Error() @@ -543,24 +539,22 @@ func (t *FilesystemTool) handleReadFile(_ context.Context, args ReadFileArgs) (* }, nil } + text := string(content) + return &tools.ToolCallResult{ - Output: string(content), + Output: text, Meta: ReadFileMeta{ - LineCount: strings.Count(string(content), "\n") + 1, + LineCount: strings.Count(text, "\n") + 1, }, }, nil } // readImageFile reads an image file and returns it as base64-encoded image content. +// The caller must ensure the file exists (e.g. via os.Stat) before calling this method. func (t *FilesystemTool) readImageFile(resolvedPath, originalPath string) (*tools.ToolCallResult, error) { data, err := os.ReadFile(resolvedPath) if err != nil { - var errMsg string - if os.IsNotExist(err) { - errMsg = "not found" - } else { - errMsg = err.Error() - } + errMsg := err.Error() return &tools.ToolCallResult{ Output: errMsg, IsError: true, @@ -627,7 +621,7 @@ func (t *FilesystemTool) handleReadMultipleFiles(ctx context.Context, args ReadM content, err := os.ReadFile(resolvedPath) if err != nil { errMsg := err.Error() - if os.IsNotExist(err) { + if errors.Is(err, fs.ErrNotExist) { errMsg = "not found" } contents = append(contents, PathContent{ @@ -639,12 +633,13 @@ func (t *FilesystemTool) handleReadMultipleFiles(ctx context.Context, args ReadM continue } + text := string(content) contents = append(contents, PathContent{ Path: path, - Content: string(content), + Content: text, }) - entry.Content = string(content) - entry.LineCount = strings.Count(string(content), "\n") + 1 + entry.Content = text + entry.LineCount = strings.Count(text, "\n") + 1 meta.Files = append(meta.Files, entry) }