Documentation
¶
Overview ¶
Package file provides file operation tools for the Aleutian Trace CLI.
This package implements five core file tools:
- Read: Read file contents with line numbers and pagination
- Write: Create new files with atomic writes
- Edit: Make surgical edits via old_string → new_string replacement
- Glob: Find files by glob pattern
- Grep: Search file contents with regex
All tools integrate with the tool registry and support the 2-LLM architecture where the micro LLM (Granite4) routes queries to appropriate tools.
Thread Safety: All tools are safe for concurrent use.
Index ¶
- Constants
- Variables
- func IsSensitivePath(path string) bool
- func RegisterFileTools(registry *tools.Registry, config *Config)
- func ResolveAndValidatePath(path string, config *Config) (string, error)
- func StaticFileToolDefinitions() []tools.ToolDefinition
- type Config
- type DiffParams
- type DiffResult
- type DiffTool
- type EditError
- type EditParams
- type EditResult
- type EditTool
- type FileInfo
- type GlobParams
- type GlobResult
- type GlobTool
- type GraphRefresher
- type GrepMatch
- type GrepParams
- type GrepResult
- type GrepTool
- type JSONParams
- type JSONResult
- type JSONTool
- type LSPReleaser
- type ReadParams
- type ReadResult
- type ReadTool
- type TreeParams
- type TreeResult
- type TreeTool
- type WriteParams
- type WriteResult
- type WriteTool
Constants ¶
const ( // Read tool limits DefaultReadLimit = 2000 MaxReadLimit = 10000 MaxFileSizeBytes = 10 * 1024 * 1024 // 10MB max file size for read MaxLineLengthChars = 2000 // Write tool limits MaxWriteContentSize = 5 * 1024 * 1024 // 5MB max write content // Edit tool limits MaxEditFileSize = 10 * 1024 * 1024 // 10MB max file size for edit // Glob tool limits DefaultGlobLimit = 100 MaxGlobLimit = 1000 MaxPatternLength = 256 // Grep tool limits DefaultGrepLimit = 100 MaxGrepLimit = 500 MaxContextLines = 10 MaxGrepPattern = 1024 )
const MaxFuzzyErrors = 5
MaxFuzzyErrors is the maximum allowed edit distance for approximate matching.
const MaxTreeDepth = 10
MaxTreeDepth is the maximum allowed tree depth.
Variables ¶
var ( ErrNoMatch = errors.New("old_string not found in file") ErrMultipleMatch = errors.New("old_string matches multiple times; use replace_all=true or provide more context") ErrFileNotRead = errors.New("file must be read before editing") ErrConflict = errors.New("file was modified externally since last read; re-read and retry") )
Edit errors for specific failure modes.
var DefaultExclusions = []string{
".git",
"node_modules",
"vendor",
"__pycache__",
".venv",
"venv",
".idea",
".vscode",
"dist",
"build",
".next",
"target",
}
Default exclusion patterns for glob and grep operations.
var SensitivePaths = []string{
"/etc/passwd",
"/etc/shadow",
"/etc/hosts",
"/.ssh/",
"/.gnupg/",
"/.aws/credentials",
"/.env",
"/id_rsa",
"/id_ed25519",
}
SensitivePaths contains paths that should never be written to.
Functions ¶
func IsSensitivePath ¶
IsSensitivePath checks if a path is sensitive and should not be written.
func RegisterFileTools ¶
RegisterFileTools registers all file operation tools with the registry.
Description:
Registers all file tools (Read, Write, Edit, Glob, Grep, Diff, Tree, JSON) with the provided tool registry. These tools require a Config that specifies the working directory and allowed paths.
Inputs:
registry - The tool registry to register with config - Configuration for file tools (working directory, allowed paths)
Example:
registry := tools.NewRegistry()
config := file.NewConfig("/path/to/project")
file.RegisterFileTools(registry, config)
Thread Safety: This function is safe to call once during initialization.
func ResolveAndValidatePath ¶
ResolveAndValidatePath resolves symlinks and validates the path is allowed.
func StaticFileToolDefinitions ¶
func StaticFileToolDefinitions() []tools.ToolDefinition
StaticFileToolDefinitions returns tool definitions without requiring config.
Description:
Returns the definitions for all file tools. These can be used for query classification without initializing the full tool system. The definitions include tool names, descriptions, and parameter schemas.
Outputs:
[]tools.ToolDefinition - The static tool definitions.
Example:
defs := file.StaticFileToolDefinitions() // Use defs for LLM tool routing
Thread Safety: This function is safe for concurrent use.
Types ¶
type Config ¶
type Config struct {
// AllowedPaths is a list of paths that file operations are allowed in.
// If empty, only the working directory and its subdirectories are allowed.
AllowedPaths []string
// WorkingDir is the current working directory.
WorkingDir string
// ReadTracking tracks which files have been read (for Edit validation).
// Maps file path to read time (Unix milliseconds UTC).
ReadTracking map[string]int64
// ContentHashes stores content hashes for optimistic locking.
// When a file is read, its hash is stored. During edit, we verify
// the hash matches to detect external modifications.
ContentHashes map[string]string
// LSPReleaser coordinates file access with LSP servers.
// Optional. If nil, no LSP coordination is performed.
// Required for Windows to avoid "Access is denied" errors during atomic writes.
LSPReleaser LSPReleaser
// GraphRefresher provides synchronous graph updates after file writes.
// Optional. If nil, no synchronous refresh is performed.
// Recommended to prevent event storms and stale graph queries.
GraphRefresher GraphRefresher
}
Config holds configuration for file tools.
func NewConfig ¶
NewConfig creates a new Config with the given working directory. The working directory is resolved to its real path (symlinks followed).
func (*Config) ClearContentHash ¶
ClearContentHash removes the stored hash for a file after successful write.
func (*Config) GetContentHash ¶
GetContentHash retrieves the stored content hash for a file. Returns empty string if no hash was stored.
func (*Config) IsPathAllowed ¶
IsPathAllowed checks if a path is within allowed directories. The path is resolved through symlinks before checking.
func (*Config) MarkFileRead ¶
MarkFileRead records that a file has been read.
func (*Config) StoreContentHash ¶
StoreContentHash records the content hash of a file when read. This enables optimistic locking during edits.
func (*Config) WasFileRead ¶
WasFileRead checks if a file was previously read.
type DiffParams ¶
type DiffParams struct {
// FileA is the first file to compare.
FileA string `json:"file_a"`
// FileB is the second file to compare.
FileB string `json:"file_b"`
// ContextLines is the number of context lines around changes.
ContextLines int `json:"context_lines,omitempty"`
}
DiffParams defines parameters for the Diff tool.
func (*DiffParams) Validate ¶
func (p *DiffParams) Validate() error
Validate checks that DiffParams are valid. Note: Relative paths are allowed and should be resolved by the tool against the working directory.
type DiffResult ¶
type DiffResult struct {
// Diff is the unified diff output.
Diff string `json:"diff"`
// LinesAdded is the number of lines added.
LinesAdded int `json:"lines_added"`
// LinesRemoved is the number of lines removed.
LinesRemoved int `json:"lines_removed"`
// FilesIdentical indicates if the files are the same.
FilesIdentical bool `json:"files_identical"`
}
DiffResult contains the outcome of a Diff operation.
type DiffTool ¶
type DiffTool struct {
// contains filtered or unexported fields
}
DiffTool implements the Diff file comparison operation.
Thread Safety: DiffTool is safe for concurrent use.
func NewDiffTool ¶
NewDiffTool creates a new Diff tool with the given configuration.
func (*DiffTool) Category ¶
func (t *DiffTool) Category() tools.ToolCategory
Category returns the tool category.
func (*DiffTool) Definition ¶
func (t *DiffTool) Definition() tools.ToolDefinition
Definition returns the tool's parameter schema.
type EditError ¶
type EditError struct {
// Err is the underlying error.
Err error
// MatchCount is the number of matches found.
MatchCount int
// Suggestion provides guidance for fixing the error.
Suggestion string
}
EditError provides detailed error information for edit failures.
type EditParams ¶
type EditParams struct {
// FilePath is the absolute path to the file to edit.
FilePath string `json:"file_path"`
// OldString is the exact text to replace.
OldString string `json:"old_string"`
// NewString is the replacement text.
NewString string `json:"new_string"`
// ReplaceAll replaces all occurrences if true.
ReplaceAll bool `json:"replace_all,omitempty"`
}
EditParams defines parameters for the Edit tool.
func (*EditParams) Validate ¶
func (p *EditParams) Validate() error
Validate checks that EditParams are valid. Note: Relative paths are allowed and should be resolved by the tool against the working directory.
type EditResult ¶
type EditResult struct {
// Success indicates if the edit succeeded.
Success bool `json:"success"`
// Replacements is the number of replacements made.
Replacements int `json:"replacements"`
// Diff is the unified diff of the changes.
Diff string `json:"diff"`
// Path is the absolute path of the edited file.
Path string `json:"path"`
}
EditResult contains the outcome of an Edit operation.
type EditTool ¶
type EditTool struct {
// contains filtered or unexported fields
}
EditTool implements the Edit file operation.
Thread Safety: EditTool is safe for concurrent use.
func NewEditTool ¶
NewEditTool creates a new Edit tool with the given configuration.
func (*EditTool) Category ¶
func (t *EditTool) Category() tools.ToolCategory
Category returns the tool category.
func (*EditTool) Definition ¶
func (t *EditTool) Definition() tools.ToolDefinition
Definition returns the tool's parameter schema.
type FileInfo ¶
type FileInfo struct {
// Path is the absolute path to the file.
Path string `json:"path"`
// RelPath is the path relative to the search root.
RelPath string `json:"rel_path,omitempty"`
// Size is the file size in bytes.
Size int64 `json:"size"`
// ModTime is the last modification time (Unix milliseconds UTC).
ModTime int64 `json:"mod_time"`
// IsDir indicates if this is a directory.
IsDir bool `json:"is_dir,omitempty"`
}
FileInfo contains metadata about a file.
type GlobParams ¶
type GlobParams struct {
// Pattern is the glob pattern to match (e.g., "**/*.go").
Pattern string `json:"pattern"`
// Path is the directory to search in. Defaults to current working directory.
Path string `json:"path,omitempty"`
// Limit is the maximum number of results. Defaults to DefaultGlobLimit.
Limit int `json:"limit,omitempty"`
}
GlobParams defines parameters for the Glob tool.
func (*GlobParams) Validate ¶
func (p *GlobParams) Validate() error
Validate checks that GlobParams are valid.
type GlobResult ¶
type GlobResult struct {
// Files is the list of matching files.
Files []FileInfo `json:"files"`
// Count is the total number of matches found.
Count int `json:"count"`
// Truncated indicates if results were truncated due to limit.
Truncated bool `json:"truncated"`
// SearchPath is the directory that was searched.
SearchPath string `json:"search_path"`
}
GlobResult contains the outcome of a Glob operation.
type GlobTool ¶
type GlobTool struct {
// contains filtered or unexported fields
}
GlobTool implements the Glob file search operation.
Thread Safety: GlobTool is safe for concurrent use.
func NewGlobTool ¶
NewGlobTool creates a new Glob tool with the given configuration.
func (*GlobTool) Category ¶
func (t *GlobTool) Category() tools.ToolCategory
Category returns the tool category.
func (*GlobTool) Definition ¶
func (t *GlobTool) Definition() tools.ToolDefinition
Definition returns the tool's parameter schema.
type GraphRefresher ¶
type GraphRefresher interface {
// RefreshFiles synchronously refreshes the graph for the given file paths.
// Returns after the graph is updated. If an error occurs, the graph may
// be partially updated but should not corrupt existing data.
RefreshFiles(ctx context.Context, paths []string) error
}
GraphRefresher provides synchronous graph updates after file writes.
Description:
When the agent writes a file, the code graph becomes stale. Instead of waiting for fsnotify to detect the change and trigger an asynchronous refresh (which can cause event storms and stale queries), this interface allows the WriteTool to refresh the graph synchronously BEFORE returning. This prevents the "event storm loop" where: 1. Agent writes file 2. fsnotify fires, graph refresher starts parsing 3. Agent writes again (before refresh completes) 4. Agent queries graph - gets STALE version 5. Agent thinks fix didn't work, writes again → infinite loop
Thread Safety:
Implementations must be safe for concurrent use.
type GrepMatch ¶
type GrepMatch struct {
// File is the absolute path to the file containing the match.
File string `json:"file"`
// Line is the 1-indexed line number of the match.
Line int `json:"line"`
// Content is the matching line content.
Content string `json:"content"`
// ContextBefore contains lines before the match.
ContextBefore []string `json:"context_before,omitempty"`
// ContextAfter contains lines after the match.
ContextAfter []string `json:"context_after,omitempty"`
}
GrepMatch represents a single match from a grep operation.
type GrepParams ¶
type GrepParams struct {
// Pattern is the regex pattern to search for.
Pattern string `json:"pattern"`
// Path is the file or directory to search in.
Path string `json:"path,omitempty"`
// Glob is an optional file pattern filter (e.g., "*.go").
Glob string `json:"glob,omitempty"`
// ContextLines is the number of lines to show before and after each match.
ContextLines int `json:"context_lines,omitempty"`
// CaseInsensitive enables case-insensitive matching.
CaseInsensitive bool `json:"case_insensitive,omitempty"`
// Limit is the maximum number of matches. Defaults to DefaultGrepLimit.
Limit int `json:"limit,omitempty"`
// Fuzzy enables fzf-style fuzzy matching where characters must appear
// in order but not necessarily adjacent. Example: "prsfil" matches "parseFile".
Fuzzy bool `json:"fuzzy,omitempty"`
// Approximate enables agrep-style approximate matching using Levenshtein
// distance. Example: "functon" matches "function" with MaxErrors=1.
Approximate bool `json:"approximate,omitempty"`
// MaxErrors is the maximum edit distance for approximate matching.
// Only used when Approximate=true. Default: 2, Max: 5.
MaxErrors int `json:"max_errors,omitempty"`
}
GrepParams defines parameters for the Grep tool.
func (*GrepParams) Validate ¶
func (p *GrepParams) Validate() error
Validate checks that GrepParams are valid.
type GrepResult ¶
type GrepResult struct {
// Matches is the list of matching lines.
Matches []GrepMatch `json:"matches"`
// Count is the total number of matches found.
Count int `json:"count"`
// Truncated indicates if results were truncated due to limit.
Truncated bool `json:"truncated"`
// FilesSearched is the number of files searched.
FilesSearched int `json:"files_searched"`
// SearchPath is the directory or file that was searched.
SearchPath string `json:"search_path"`
}
GrepResult contains the outcome of a Grep operation.
type GrepTool ¶
type GrepTool struct {
// contains filtered or unexported fields
}
GrepTool implements the Grep content search operation.
Thread Safety: GrepTool is safe for concurrent use.
func NewGrepTool ¶
NewGrepTool creates a new Grep tool with the given configuration.
func (*GrepTool) Category ¶
func (t *GrepTool) Category() tools.ToolCategory
Category returns the tool category.
func (*GrepTool) Definition ¶
func (t *GrepTool) Definition() tools.ToolDefinition
Definition returns the tool's parameter schema.
type JSONParams ¶
type JSONParams struct {
// FilePath is the JSON file to query/validate.
FilePath string `json:"file_path"`
// Query is a jq-style path (e.g., ".users[0].name").
Query string `json:"query,omitempty"`
// Validate only validates JSON, doesn't query.
Validate bool `json:"validate,omitempty"`
}
JSONParams defines parameters for the JSON tool.
func (*JSONParams) ValidateParams ¶
func (p *JSONParams) ValidateParams() error
JSONParamsValidate checks that JSONParams are valid. Note: Relative paths are allowed and should be resolved by the tool against the working directory.
type JSONResult ¶
type JSONResult struct {
// Value is the query result.
Value any `json:"value,omitempty"`
// Valid indicates if the JSON is valid.
Valid bool `json:"valid"`
// Error contains the parse error if invalid.
Error string `json:"error,omitempty"`
// Path is the file path.
Path string `json:"path"`
}
JSONResult contains the outcome of a JSON operation.
type JSONTool ¶
type JSONTool struct {
// contains filtered or unexported fields
}
JSONTool implements JSON file querying and validation.
Thread Safety: JSONTool is safe for concurrent use.
func NewJSONTool ¶
NewJSONTool creates a new JSON tool with the given configuration.
func (*JSONTool) Category ¶
func (t *JSONTool) Category() tools.ToolCategory
Category returns the tool category.
func (*JSONTool) Definition ¶
func (t *JSONTool) Definition() tools.ToolDefinition
Definition returns the tool's parameter schema.
type LSPReleaser ¶
type LSPReleaser interface {
// ReleaseFile tells LSP servers to close the file.
// Called before atomic writes on Windows.
ReleaseFile(ctx context.Context, filePath string) error
// ReopenFile tells LSP servers to reopen the file with new content.
// Called after atomic writes on Windows.
ReopenFile(ctx context.Context, filePath string, content string, languageID string) error
}
LSPReleaser provides methods to coordinate file access with LSP servers.
Description:
On Windows, LSP servers (like gopls) hold file handles open, which prevents atomic file operations (os.Rename). This interface allows the WriteTool to notify LSP servers to release file handles before writing, and reopen them afterward.
Thread Safety:
Implementations must be safe for concurrent use.
type ReadParams ¶
type ReadParams struct {
// FilePath is the absolute path to the file to read.
FilePath string `json:"file_path"`
// Offset is the line number to start reading from (1-indexed).
// If 0 or not provided, reads from the beginning.
Offset int `json:"offset,omitempty"`
// Limit is the maximum number of lines to read.
// Defaults to DefaultReadLimit if not provided.
Limit int `json:"limit,omitempty"`
}
ReadParams defines parameters for the Read tool.
func (*ReadParams) Validate ¶
func (p *ReadParams) Validate() error
Validate checks that ReadParams are valid. Note: Relative paths are allowed and should be resolved by the tool against the working directory.
type ReadResult ¶
type ReadResult struct {
// Content is the file content with line numbers.
Content string `json:"content"`
// TotalLines is the total number of lines in the file.
TotalLines int `json:"total_lines"`
// LinesRead is the number of lines actually read.
LinesRead int `json:"lines_read"`
// Truncated indicates if output was truncated due to limits.
Truncated bool `json:"truncated"`
// TruncatedAt is the line number where truncation occurred.
TruncatedAt int `json:"truncated_at,omitempty"`
// BytesRead is the number of bytes read from the file.
BytesRead int64 `json:"bytes_read"`
// FileType indicates the detected file type.
FileType string `json:"file_type,omitempty"`
}
ReadResult contains the outcome of a Read operation.
type ReadTool ¶
type ReadTool struct {
// contains filtered or unexported fields
}
ReadTool implements the Read file operation.
Thread Safety: ReadTool is safe for concurrent use.
func NewReadTool ¶
NewReadTool creates a new Read tool with the given configuration.
func (*ReadTool) Category ¶
func (t *ReadTool) Category() tools.ToolCategory
Category returns the tool category.
func (*ReadTool) Definition ¶
func (t *ReadTool) Definition() tools.ToolDefinition
Definition returns the tool's parameter schema.
type TreeParams ¶
type TreeParams struct {
// Path is the directory to visualize.
Path string `json:"path,omitempty"`
// Depth is the maximum depth to traverse (default: 3, max: 10).
Depth int `json:"depth,omitempty"`
// ShowHidden includes dotfiles/dotdirs.
ShowHidden bool `json:"show_hidden,omitempty"`
// DirsOnly shows only directories, not files.
DirsOnly bool `json:"dirs_only,omitempty"`
}
TreeParams defines parameters for the Tree tool.
func (*TreeParams) Validate ¶
func (p *TreeParams) Validate() error
Validate checks that TreeParams are valid.
type TreeResult ¶
type TreeResult struct {
// Tree is the ASCII tree output.
Tree string `json:"tree"`
// TotalDirs is the number of directories found.
TotalDirs int `json:"total_dirs"`
// TotalFiles is the number of files found.
TotalFiles int `json:"total_files"`
// Truncated indicates if depth limit was hit.
Truncated bool `json:"truncated"`
}
TreeResult contains the outcome of a Tree operation.
type TreeTool ¶
type TreeTool struct {
// contains filtered or unexported fields
}
TreeTool implements the Tree directory visualization operation.
Thread Safety: TreeTool is safe for concurrent use.
func NewTreeTool ¶
NewTreeTool creates a new Tree tool with the given configuration.
func (*TreeTool) Category ¶
func (t *TreeTool) Category() tools.ToolCategory
Category returns the tool category.
func (*TreeTool) Definition ¶
func (t *TreeTool) Definition() tools.ToolDefinition
Definition returns the tool's parameter schema.
type WriteParams ¶
type WriteParams struct {
// FilePath is the absolute path for the new file.
FilePath string `json:"file_path"`
// Content is the file content to write.
Content string `json:"content"`
}
WriteParams defines parameters for the Write tool.
func (*WriteParams) Validate ¶
func (p *WriteParams) Validate() error
Validate checks that WriteParams are valid. Note: Relative paths are allowed and should be resolved by the tool against the working directory.
type WriteResult ¶
type WriteResult struct {
// Success indicates if the write succeeded.
Success bool `json:"success"`
// BytesWritten is the number of bytes written.
BytesWritten int64 `json:"bytes_written"`
// Path is the absolute path of the written file.
Path string `json:"path"`
// Created indicates if a new file was created (vs overwritten).
Created bool `json:"created"`
}
WriteResult contains the outcome of a Write operation.
type WriteTool ¶
type WriteTool struct {
// contains filtered or unexported fields
}
WriteTool implements the Write file operation.
Thread Safety: WriteTool is safe for concurrent use.
func NewWriteTool ¶
NewWriteTool creates a new Write tool with the given configuration.
func (*WriteTool) Category ¶
func (t *WriteTool) Category() tools.ToolCategory
Category returns the tool category.
func (*WriteTool) Definition ¶
func (t *WriteTool) Definition() tools.ToolDefinition
Definition returns the tool's parameter schema.