Documentation
¶
Overview ¶
Package tools defines the Tool interface, Registry, and built-in tools.
The Tool interface is the single abstraction used by both built-in tools and plugin-exposed tools. Every tool receives a typed ToolCall and returns a typed ToolResult; the agent loop is unaware of the tool's internal mechanics.
Tools that touch the filesystem or spawn subprocesses expose an Operations interface (e.g., ReadOperations, BashOperations). The default implementation uses the real OS; tests inject fake implementations to avoid side effects.
Index ¶
- Constants
- Variables
- func DetectImageMimeTypeFromBytes(buf []byte) string
- func GenericRenderCall(headless HeadlessTool, args json.RawMessage) string
- func GenericRenderResult(headless HeadlessTool, result ToolResult) string
- func IsBinary(data []byte) bool
- func ParseJSONSchema(raw string) jsonschema.Schema
- func ReflectSchema(sample any) jsonschema.Schema
- func RenderCallOrFallback(headless HeadlessTool, args json.RawMessage, theme *Theme) string
- func RenderContentBlocks(blocks []llm.ContentBlock, theme *Theme) string
- func RenderResultOrFallback(headless HeadlessTool, result ToolResult, theme *Theme) string
- func ResolveWithinCwd(path, cwd string) (string, error)
- func TruncateBytes(s string, maxBytes int) string
- func TruncateHeadTail(s string, maxLines, maxBytes int) string
- type BashExecOptions
- type BashExecResult
- type BashOperations
- type EditOperations
- type FileMutationQueue
- type FindOperations
- type GrepOperations
- type HeadlessTool
- type LSOperations
- type NoRender
- type OSBashOperations
- type OSEditOperations
- type OSFindOperations
- type OSGrepOperations
- type OSLSOperations
- type OSReadOperations
- type OSWriteOperations
- type ReadOperations
- type Registry
- type Theme
- type Tool
- type ToolCall
- type ToolResult
- type WriteOperations
Constants ¶
const DefaultFindLimit = 1000
DefaultFindLimit caps the number of paths returned by a single find invocation. Find output is one path per line; thousands of matches would crowd the LLM context. The user can override via the limit parameter.
const DefaultGrepLimit = 100
DefaultGrepLimit is the default cap on the number of matches returned by a single grep invocation. Matches pi's DEFAULT_LIMIT.
const DefaultMaxBytes = 512 * 1024
DefaultMaxBytes is the default per-result byte cap applied to tool output. 512 KiB matches the tools spec default.
const DefaultMaxLines = 500
DefaultMaxLines is the default per-result line cap applied to tool output before it reaches the LLM. 500 lines matches the tools spec default.
const GrepMaxLineLength = 2000
GrepMaxLineLength is the per-line character cap applied to grep output before it reaches the LLM. Lines longer than this are truncated with an ellipsis marker so a single pathological match cannot blow the context budget. Matches pi's GREP_MAX_LINE_LENGTH.
const LSTimeLayout = "2006-01-02 15:04"
LSTimeLayout is the timestamp format used in ls output. Picked to be compact and unambiguous across locales; the model can parse it directly.
Variables ¶
var ErrDuplicateTool = errors.New("tools: duplicate tool name")
ErrDuplicateTool is returned by Register when another tool with the same name is already registered. First-registration wins so plugin-load order is deterministic.
var ErrFindInvalidPattern = errors.New("tools/find: invalid pattern")
ErrFindInvalidPattern is returned by find when the pattern fails to compile as a doublestar glob.
var ErrFindPathNotFound = errors.New("tools/find: path not found")
ErrFindPathNotFound is returned by find when the target path does not exist.
var ErrGrepInvalidPattern = errors.New("tools/grep: invalid pattern")
ErrGrepInvalidPattern is returned by Grep when the pattern fails to compile as a regular expression.
var ErrGrepPathNotFound = errors.New("tools/grep: path not found")
ErrGrepPathNotFound is returned by Grep when the target path does not exist.
var ErrLSNotADirectory = errors.New("tools/ls: not a directory")
ErrLSNotADirectory is returned by ls when the target path is not a directory. ls lists the contents of a single directory; use read for individual files.
var ErrLSPathNotFound = errors.New("tools/ls: path not found")
ErrLSPathNotFound is returned by ls when the target path does not exist.
var ErrNotFound = errors.New("tools/edit: oldString not found in file")
ErrNotFound is returned by Edit when oldString does not appear in the file.
var ErrNotUnique = errors.New("tools/edit: oldString is not unique in file")
ErrNotUnique is returned by Edit when oldString appears zero or multiple times in the file. The agent loop surfaces this as an IsError result.
var ErrOutOfCwd = errors.New("tools/write: path is outside cwd (set allowOutOfCwd to override)")
ErrOutOfCwd is returned by Write when the target path is outside the agent's working directory and the caller did not opt in via allowOutOfCwd.
var ErrUnknownTool = errors.New("tools: unknown tool")
ErrUnknownTool is returned by Lookup when no tool with the given name is registered. The agent loop catches this and synthesizes a ToolResult with IsError=true so the model sees a clear error rather than a generic "internal error".
Functions ¶
func DetectImageMimeTypeFromBytes ¶
DetectImageMimeTypeFromBytes sniffs the leading bytes of a file for known image signatures. Returns "" for non-images or unsupported image types. Supported: PNG (with IHDR sanity check), JPEG (excluding JPEG 2000), GIF (any version), WebP (RIFF/WEBP).
func GenericRenderCall ¶
func GenericRenderCall(headless HeadlessTool, args json.RawMessage) string
GenericRenderCall produces a non-empty, plain-text representation of a tool invocation when the registered tool does not supply its own RenderCall. The output is "tool <name>: <args>" where <args> is the raw JSON arguments payload verbatim (or "<no args>" when args is empty). Callers SHOULD pass the result through their theme wrapper; the helper itself emits no ANSI codes.
func GenericRenderResult ¶
func GenericRenderResult(headless HeadlessTool, result ToolResult) string
GenericRenderResult produces a non-empty, plain-text representation of a tool's output when the registered tool does not supply its own RenderResult. The output mirrors the success/error status, includes the tool's name when supplied, and joins every TextContent block with a separator. Non-text content blocks are summarised by their Go type name.
func IsBinary ¶
IsBinary returns true if data contains a NUL byte within its first 8 KiB. This matches git's heuristic: text files effectively never contain NUL, while binary files almost always do within the first few kilobytes.
func ParseJSONSchema ¶
func ParseJSONSchema(raw string) jsonschema.Schema
ParseJSONSchema unmarshals a JSON-Schema document produced by a plugin into the jsonschema.Schema shape. Used by PluginTool.Parameters() to surface plugin-declared schemas in the same struct form built-in tools use. Returns a minimal object schema on parse failure rather than an error: the tool is still callable, the model just gets a degenerate schema; the caller surfaces the parse error via a diagnostic.
func ReflectSchema ¶
func ReflectSchema(sample any) jsonschema.Schema
ReflectSchema builds a flat (no $ref) JSON Schema from a sample struct. The reflector-generated $schema, $id, and $defs keys are stripped so the result can be embedded directly into a provider tool definition without confusing draft-2020-12 validators.
This is the primary constructor for built-in tools whose parameters are typed Go structs with json and jsonschema tags.
func RenderCallOrFallback ¶
func RenderCallOrFallback(headless HeadlessTool, args json.RawMessage, theme *Theme) string
RenderCallOrFallback invokes t.RenderCall when t satisfies Tool and returns a non-empty string; otherwise it falls back to GenericRenderCall. TUI consumers SHOULD prefer this helper over a raw type assertion so they handle both the "not a Tool" and "is a Tool but returned empty" cases with one call.
func RenderContentBlocks ¶
func RenderContentBlocks(blocks []llm.ContentBlock, theme *Theme) string
RenderContentBlocks is the exported form of renderContentBlocks for use by the plugins package's PluginTool wrapper. Defined here because all built-in tools reach for the same helper.
func RenderResultOrFallback ¶
func RenderResultOrFallback(headless HeadlessTool, result ToolResult, theme *Theme) string
RenderResultOrFallback invokes t.RenderResult when t satisfies Tool and returns a non-empty string; otherwise it falls back to GenericRenderResult. TUI consumers SHOULD prefer this helper over a raw type assertion.
func ResolveWithinCwd ¶
ResolveWithinCwd resolves a possibly-relative path against cwd and returns the cleaned absolute path. If path is already absolute, it is returned cleaned. An empty cwd with a relative path is an error.
func TruncateBytes ¶
TruncateBytes caps s to at most maxBytes bytes. If truncation occurs, the result is the head of s plus an ellipsis marker describing the elision. Use this when only a byte cap (no line structure) is desired.
func TruncateHeadTail ¶
TruncateHeadTail caps s to at most maxLines lines AND at most maxBytes bytes. When truncation happens, the output is split head/tail with an ellipsis marker describing the elision count. The default 500-line / 512 KiB values preserve the first and last 250 lines (or 256 KiB) so the model sees both the start and end of long output.
When s already fits both limits, it is returned unchanged.
maxLines or maxBytes <= 0 disables that dimension (use 0 to apply only the other cap). To apply the spec defaults, pass DefaultMaxLines and DefaultMaxBytes.
Types ¶
type BashExecOptions ¶
type BashExecOptions struct {
// OnData is invoked with each chunk of stdout/stderr output as it
// arrives. Chunks are NOT line-buffered; they reflect the underlying
// pipe buffer boundaries. May be nil.
OnData func(chunk []byte)
// Timeout, if greater than zero, kills the process after the
// duration. A zero value means no timeout.
Timeout time.Duration
// Env overrides the process environment. If nil, the current
// process environment is inherited.
Env []string
}
BashExecOptions controls the runtime behavior of a BashOperations.Exec call. The callbacks (if non-nil) receive streaming output as it is produced; the final accumulated bytes are always returned in the result.
type BashExecResult ¶
type BashExecResult struct {
// ExitCode is the process exit code. -1 indicates the process was
// killed (by signal, timeout, or context cancellation).
ExitCode int
// Stdout is the accumulated stdout bytes.
Stdout []byte
// Stderr is the accumulated stderr bytes.
Stderr []byte
// Signal is the signal name that killed the process, if any (e.g.
// "KILL", "TERM"). Empty for normal exits.
Signal string
}
BashExecResult is the terminal state of an Exec call.
type BashOperations ¶
type BashOperations interface {
// Exec runs command in cwd and returns the accumulated output and
// exit code. Streaming output (if opts.OnData is set) is delivered
// as it arrives. ctx cancellation kills the process tree.
Exec(ctx context.Context, command, cwd string, opts BashExecOptions) (BashExecResult, error)
}
BashOperations abstracts the I/O surface of the bash tool. The default implementation uses the real OS; tests inject fake implementations.
type EditOperations ¶
type EditOperations interface {
// ReadFile returns the file's current content.
ReadFile(absolutePath string) ([]byte, error)
// WriteFile replaces the file's content atomically (temp + rename).
// The mode of the existing file (if any) is preserved; new files use
// mode 0644.
WriteFile(absolutePath string, content []byte) error
// Access verifies the file is readable AND writable.
Access(absolutePath string) error
}
EditOperations abstracts the I/O surface of the edit tool. The default implementation uses the real OS; tests inject fake implementations.
type FileMutationQueue ¶
type FileMutationQueue struct {
// contains filtered or unexported fields
}
FileMutationQueue serializes file-mutating tool calls per path. Two concurrent edits to the SAME file run in arrival order; two concurrent edits to DIFFERENT files run in parallel.
Non-mutating tools (read, grep, find, ls, bash) bypass the queue. The queue is per session (or per agent runtime); it has no global state.
The zero value is usable; construct via NewFileMutationQueue for clarity.
func NewFileMutationQueue ¶
func NewFileMutationQueue() *FileMutationQueue
NewFileMutationQueue returns an empty queue.
func (*FileMutationQueue) Run ¶
Run executes fn while holding the per-path lock. Other Run calls for the same path block until fn returns; calls for any other path proceed in parallel. fn runs uncanceled unless ctx is canceled.
The path is normalized via filepath.Clean so "foo.txt" and "./foo.txt" share a lock.
type FindOperations ¶
type FindOperations interface {
// IsDirectory returns true if absolutePath exists and is a directory.
// Returns os.ErrNotExist (wrapped) if the path is missing.
IsDirectory(absolutePath string) (bool, error)
// WalkDir walks the file tree rooted at root, invoking fn for each
// file and directory. Implementations MUST honor gitignore-style
// external filtering (the caller applies gitignore internally); this
// is just a directory traversal primitive.
WalkDir(root string, fn fs.WalkDirFunc) error
}
FindOperations abstracts the I/O surface of the find tool. The default implementation uses the real OS; tests inject fake implementations to avoid filesystem side effects.
type GrepOperations ¶
type GrepOperations interface {
// IsDirectory returns true if absolutePath exists and is a directory.
// Returns os.ErrNotExist (wrapped) if the path is missing.
IsDirectory(absolutePath string) (bool, error)
// ReadFile returns the full content of the file at absolutePath.
ReadFile(absolutePath string) ([]byte, error)
// WalkDir walks the file tree rooted at root, invoking fn for each
// file and directory. Implementations MUST honor gitignore-style
// external filtering (the caller applies gitignore internally); this
// is just a directory traversal primitive.
WalkDir(root string, fn fs.WalkDirFunc) error
// LookPath searches for the named executable on PATH. Returns the
// full path on success, or an error matching exec.ErrNotFound on
// failure. Used to detect whether ripgrep is installed.
LookPath(name string) (string, error)
}
GrepOperations abstracts the I/O surface of the grep tool. The default implementation uses the real OS and shells out to ripgrep when available; tests inject fake implementations to avoid filesystem and process side effects.
type HeadlessTool ¶
type HeadlessTool interface {
// Name is the unique tool identifier. Lowercase ASCII, words
// separated by dots (e.g., "read", "git.status"). The Registry
// rejects duplicate names.
Name() string
// Description is a human- and model-readable summary of what the
// tool does. Providers embed this verbatim in the tool definition.
Description() string
// Parameters returns the input JSON Schema. The schema MUST be
// draft-2020-12 compliant so the provider can embed it directly.
Parameters() jsonschema.Schema
// Execute runs the tool. The context carries cancellation and
// deadlines; tools MUST honor ctx.Done() promptly.
//
// call.Args is the raw JSON arguments payload from the model. Tools
// validate it against their own Parameters() before running; a
// validation failure produces a ToolResult with IsError=true and a
// descriptive message rather than a returned error.
//
// A non-nil error is reserved for infrastructure failures (panic,
// context cancellation, internal bug). Application-level failures
// (file not found, command exit non-zero, validation error) are
// returned as ToolResult.IsError=true.
Execute(ctx context.Context, call ToolCall) (ToolResult, error)
}
HeadlessTool is the functional contract for a tool: the methods an embedder needs to implement in order to plug a tool into the agent loop. A headless embedder (batch evaluator, CI bot, daemon) implements only HeadlessTool and never has to think about TUI rendering.
Implementations MUST be safe for concurrent use: the agent loop may invoke multiple Execute calls on the same HeadlessTool instance in parallel when Settings.SteeringMode is "all".
type LSOperations ¶
type LSOperations interface {
// IsDirectory returns true if absolutePath exists and is a directory.
IsDirectory(absolutePath string) (bool, error)
// ReadDir returns the entries within absolutePath, sorted by name.
// The returned entries expose Name, IsDir, and Info via fs.DirEntry.
ReadDir(absolutePath string) ([]fs.DirEntry, error)
}
LSOperations abstracts the I/O surface of the ls tool. The default implementation uses the real OS; tests inject fake implementations to avoid filesystem side effects.
type NoRender ¶
type NoRender struct{}
NoRender is a mixin whose RenderCall and RenderResult return the empty string. Embed NoRender in a HeadlessTool to satisfy the Tool interface without writing real rendering code; the TUI's generic-render fallback kicks in for the empty strings.
Example:
type myTool struct{ NoRender }
func (myTool) Name() string { return "my" }
// ... other HeadlessTool methods ...
// myTool now satisfies both HeadlessTool and Tool.
func (NoRender) RenderCall ¶
func (NoRender) RenderCall(args json.RawMessage, theme *Theme) string
RenderCall implements Tool by returning the empty string. The TUI substitutes its generic representation when the rendered string is empty.
func (NoRender) RenderResult ¶
func (NoRender) RenderResult(result ToolResult, theme *Theme) string
RenderResult implements Tool by returning the empty string. The TUI substitutes its generic representation when the rendered string is empty.
type OSBashOperations ¶
type OSBashOperations struct{}
OSBashOperations is the default BashOperations backed by the user's shell. It uses /bin/sh on POSIX and cmd.exe on Windows; detached descendants are killed on ctx cancellation via process-group signaling.
func (OSBashOperations) Exec ¶
func (OSBashOperations) Exec(ctx context.Context, command, cwd string, opts BashExecOptions) (BashExecResult, error)
Exec runs command via the platform shell and streams output.
type OSEditOperations ¶
type OSEditOperations struct{}
OSEditOperations is the default EditOperations backed by the real filesystem.
func (OSEditOperations) Access ¶
func (OSEditOperations) Access(p string) error
Access verifies the file is readable and writable. For a missing file, it returns os.ErrNotExist (callers must distinguish "file doesn't exist yet, refuse to create" from "file exists but is read-only").
type OSFindOperations ¶
type OSFindOperations struct{}
OSFindOperations is the default FindOperations backed by the real OS.
func (OSFindOperations) IsDirectory ¶
func (OSFindOperations) IsDirectory(p string) (bool, error)
IsDirectory delegates to os.Stat and reports IsDir.
func (OSFindOperations) WalkDir ¶
func (OSFindOperations) WalkDir(root string, fn fs.WalkDirFunc) error
WalkDir delegates to filepath.WalkDir.
type OSGrepOperations ¶
type OSGrepOperations struct{}
OSGrepOperations is the default GrepOperations backed by the real OS.
func (OSGrepOperations) IsDirectory ¶
func (OSGrepOperations) IsDirectory(p string) (bool, error)
IsDirectory delegates to os.Stat and reports IsDir.
func (OSGrepOperations) LookPath ¶
func (OSGrepOperations) LookPath(name string) (string, error)
LookPath delegates to exec.LookPath.
func (OSGrepOperations) ReadFile ¶
func (OSGrepOperations) ReadFile(p string) ([]byte, error)
ReadFile delegates to os.ReadFile.
func (OSGrepOperations) WalkDir ¶
func (OSGrepOperations) WalkDir(root string, fn fs.WalkDirFunc) error
WalkDir delegates to filepath.WalkDir.
type OSLSOperations ¶
type OSLSOperations struct{}
OSLSOperations is the default LSOperations backed by the real OS.
func (OSLSOperations) IsDirectory ¶
func (OSLSOperations) IsDirectory(p string) (bool, error)
IsDirectory delegates to os.Stat and reports IsDir.
type OSReadOperations ¶
type OSReadOperations struct{}
OSReadOperations is the default ReadOperations backed by the real filesystem.
func (OSReadOperations) Access ¶
func (OSReadOperations) Access(p string) error
Access opens the file for reading to verify it exists and is readable. The file is closed immediately; subsequent operations re-open it.
func (OSReadOperations) DetectImageMimeType ¶
func (OSReadOperations) DetectImageMimeType(p string) (string, error)
DetectImageMimeType reads the first 16 bytes and sniffs for known image signatures (PNG, JPEG, GIF, WebP). Returns "" for non-images or unsupported image types.
type OSWriteOperations ¶
type OSWriteOperations struct{}
OSWriteOperations is the default WriteOperations backed by the real filesystem.
type ReadOperations ¶
type ReadOperations interface {
// ReadFile returns the raw bytes of the file at absolutePath.
ReadFile(absolutePath string) ([]byte, error)
// Access verifies the file is readable. Returns a descriptive error
// (wrapping os.ErrNotExist, os.ErrPermission, etc.) if not.
Access(absolutePath string) error
// DetectImageMimeType returns the image MIME type (e.g. "image/png")
// if the file at absolutePath is a supported image format, or "" if
// it is not. A nil error with an empty string means "not an image";
// the caller then falls through to the text/binary path.
DetectImageMimeType(absolutePath string) (string, error)
}
ReadOperations abstracts the I/O surface of the read tool. The default implementation uses the real OS; tests inject fake implementations to avoid filesystem side effects.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry maps tool names to HeadlessTool implementations. Lookup is O(1) via a map; Schemas() returns all schemas sorted by name for deterministic LLM request construction.
The Registry stores HeadlessTool rather than Tool so a headless embedder (one who does not implement the TUI rendering methods) can register and execute tools without satisfying the larger Tool interface. The TUI type-asserts to Tool when it needs to render.
The zero value is NOT usable; construct via NewRegistry.
func (*Registry) Lookup ¶
func (r *Registry) Lookup(name string) (HeadlessTool, error)
Lookup returns the tool registered under name, or ErrUnknownTool.
func (*Registry) MustRegister ¶
func (r *Registry) MustRegister(t HeadlessTool)
MustRegister is a convenience wrapper that panics on registration error. Intended for use in init() blocks where failure indicates a programming bug (duplicate name, nil tool).
func (*Registry) Register ¶
func (r *Registry) Register(t HeadlessTool) error
Register adds a tool. Returns ErrDuplicateTool if a tool with the same name is already registered.
func (*Registry) Schemas ¶
func (r *Registry) Schemas() []llm.ToolSchema
Schemas returns the llm.ToolSchema for every registered tool, sorted by tool name. The agent loop embeds this in every LLM request.
type Theme ¶
type Theme struct {
// Primary is the main accent color (tool name in call rendering).
Primary string
// Secondary is a supporting color (argument names, metadata keys).
Secondary string
// Accent is a high-attention color (active spinners, leaf indicators).
Accent string
// Success marks a successful (non-error) tool result.
Success string
// Error marks an errored tool result.
Error string
// Warning marks truncated output, partial results.
Warning string
// Muted is for low-priority text (timestamps, sizes).
Muted string
// Reset is the SGR reset sequence. Defaults to "\x1b[0m"; an empty
// value is treated as the empty string for non-TTY themes.
Reset string
// Indent is the per-level indentation string used in rendered output.
// Defaults to two spaces.
Indent string
}
Theme controls how RenderCall and RenderResult format their output. The tools package uses ANSI escape codes directly so it has no dependency on the TUI layer; Phase 10's richer Theme converts to this shape when invoking tool rendering.
All color fields are full SGR sequences (e.g., "\x1b[31m" for red) so they can be concatenated into rendered strings without parsing. An empty field means "no styling" — output is plain text suitable for non-TTY contexts (testing, JSON mode, redirected output).
func ColorTheme ¶
func ColorTheme() *Theme
ColorTheme is a basic dark-background Theme suitable for an interactive TTY. It uses the standard 16-color palette so it works on any terminal without truecolor support.
func PlainTheme ¶
func PlainTheme() *Theme
PlainTheme is the zero-ANSI Theme used for non-TTY rendering (tests, JSON mode, redirected output). All style fields are empty; rendered text is plain.
type Tool ¶
type Tool interface {
HeadlessTool
// RenderCall produces a human-readable representation of the tool
// invocation for the TUI. The theme controls color/indentation; the
// tools package uses ANSI codes directly so it has no TUI dependency.
RenderCall(args json.RawMessage, theme *Theme) string
// RenderResult produces a human-readable representation of the
// tool's output. Used by the TUI when displaying completed tool
// calls; never sent to the LLM.
RenderResult(result ToolResult, theme *Theme) string
}
Tool is the contract the TUI consumes: every method on HeadlessTool plus the two rendering hooks the TUI needs to display a call and its result. Tools that ship as built-ins implement Tool directly so the TUI gets rich rendering; headless embedders implement HeadlessTool and the TUI falls back to a generic representation when a type assertion to Tool fails.
Every existing Tool implementation satisfies HeadlessTool — the split is source-compatible. Callers that need a rendering-aware tool can also embed NoRender to satisfy the rendering methods with no-op fallbacks.
func NewBashTool ¶
func NewBashTool(ops BashOperations) Tool
NewBashTool returns a bash Tool backed by ops. A nil ops defaults to OSBashOperations.
func NewEditTool ¶
func NewEditTool(ops EditOperations) Tool
NewEditTool returns an edit Tool backed by ops. Calls are serialized per-file through a FileMutationQueue so concurrent edits to the same file don't race. A nil ops defaults to OSEditOperations.
func NewFindTool ¶
func NewFindTool(ops FindOperations) Tool
NewFindTool returns a find Tool backed by ops. The tool walks the search root, applies gitignore rules in-process, and matches the user's pattern via bmatcuk/doublestar. A nil ops defaults to OSFindOperations.
func NewGrepTool ¶
func NewGrepTool(ops GrepOperations) Tool
NewGrepTool returns a grep Tool backed by ops. When ops.LookPath("rg") succeeds, Execute shells out to ripgrep (which honors .gitignore by default). Otherwise a pure-Go matcher walks the tree and applies the same gitignore rules in-process. A nil ops defaults to OSGrepOperations.
func NewLSTool ¶
func NewLSTool(ops LSOperations) Tool
NewLSTool returns an ls Tool backed by ops. A nil ops defaults to OSLSOperations.
func NewReadTool ¶
func NewReadTool(ops ReadOperations) Tool
NewReadTool returns a read Tool backed by the given operations. Pass OSReadOperations{} for production use, or a fake implementation in tests. A nil ops defaults to OSReadOperations.
func NewWriteTool ¶
func NewWriteTool(ops WriteOperations) Tool
NewWriteTool returns a write Tool backed by ops. Calls are serialized per-file through a FileMutationQueue. A nil ops defaults to OSWriteOperations.
type ToolCall ¶
type ToolCall struct {
// ID is the provider-assigned tool-use id. Echoed in ToolResult so
// the provider can correlate results with calls.
ID string `json:"id"`
// Name is the tool name (matches Tool.Name()).
Name string `json:"name"`
// Args is the raw JSON arguments payload from the model. Tools parse
// this against their own schema.
Args json.RawMessage `json:"args,omitempty"`
// Cwd is the working directory the agent loop has chosen for the
// session. Tools that operate on files resolve relative paths
// against this; tools that spawn subprocesses chdir here.
Cwd string `json:"cwd,omitempty"`
}
ToolCall is the runtime invocation of a tool. The agent loop constructs this from a provider-side ToolUse block.
type ToolResult ¶
type ToolResult struct {
// Content is the LLM-facing content. Typically a single TextContent;
// image-returning tools (read on a PNG/JPG) use ImageContent.
Content []llm.ContentBlock `json:"content"`
// IsError indicates the tool failed. The provider renders this as a
// tool-call failure to the model. Set when the tool detected an
// application-level error (file missing, validation failed,
// command exit non-zero).
IsError bool `json:"isError"`
// Metadata carries tool-specific data for UI rendering (exit codes,
// line counts, paths). Not sent to the LLM. Keys are tool-defined;
// see each tool's doc for the shape.
Metadata map[string]any `json:"metadata,omitempty"`
}
ToolResult is the output of a tool execution. The agent loop wraps this in an llm.ToolResult block for the LLM context.
func NewErrorResult ¶
func NewErrorResult(text string) ToolResult
NewErrorResult is a convenience constructor for an error result. The text describes the failure for the model.
func NewTextResult ¶
func NewTextResult(text string) ToolResult
NewTextResult is a convenience constructor for a successful single-block text result. Most tools produce this shape.
func ParseArgs ¶
func ParseArgs(raw json.RawMessage, dst any, toolName string) *ToolResult
ParseArgs is a helper for tools to validate their arguments. It decodes raw into dst and returns a descriptive ToolResult on failure (rather than an error). The caller writes:
var args ReadArgs
if bad := ParseArgs(call.Args, &args, "read"); bad != nil {
return *bad, nil
}
dst MUST be a pointer.
func (ToolResult) AsLLMResult ¶
func (r ToolResult) AsLLMResult(toolUseID string) llm.ToolResult
AsLLMResult converts the ToolResult to the llm-package ToolResult shape, correlating it with the originating tool-use id. The agent loop uses this when appending the result to the state tree.
type WriteOperations ¶
type WriteOperations interface {
// WriteFile writes content atomically (temp + rename). The mode of
// the existing file (if any) is preserved; new files use mode 0644.
WriteFile(absolutePath string, content []byte) error
// Stat returns the os.FileInfo for the path, or os.ErrNotExist if
// the path does not exist. Used to detect overwrites and to refuse
// to write to directories.
Stat(absolutePath string) (fs.FileInfo, error)
}
WriteOperations abstracts the I/O surface of the write tool. The default implementation uses the real OS; tests inject fake ones.