tools

package
v0.0.0-...-20cd8ba Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: MIT Imports: 24 Imported by: 0

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

View Source
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.

View Source
const DefaultGrepLimit = 100

DefaultGrepLimit is the default cap on the number of matches returned by a single grep invocation. Matches pi's DEFAULT_LIMIT.

View Source
const DefaultMaxBytes = 512 * 1024

DefaultMaxBytes is the default per-result byte cap applied to tool output. 512 KiB matches the tools spec default.

View Source
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.

View Source
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.

View Source
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

View Source
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.

View Source
var ErrFindInvalidPattern = errors.New("tools/find: invalid pattern")

ErrFindInvalidPattern is returned by find when the pattern fails to compile as a doublestar glob.

View Source
var ErrFindPathNotFound = errors.New("tools/find: path not found")

ErrFindPathNotFound is returned by find when the target path does not exist.

View Source
var ErrGrepInvalidPattern = errors.New("tools/grep: invalid pattern")

ErrGrepInvalidPattern is returned by Grep when the pattern fails to compile as a regular expression.

View Source
var ErrGrepPathNotFound = errors.New("tools/grep: path not found")

ErrGrepPathNotFound is returned by Grep when the target path does not exist.

View Source
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.

View Source
var ErrLSPathNotFound = errors.New("tools/ls: path not found")

ErrLSPathNotFound is returned by ls when the target path does not exist.

View Source
var ErrNotFound = errors.New("tools/edit: oldString not found in file")

ErrNotFound is returned by Edit when oldString does not appear in the file.

View Source
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.

View Source
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.

View Source
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

func DetectImageMimeTypeFromBytes(buf []byte) string

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

func IsBinary(data []byte) bool

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

func ResolveWithinCwd(path, cwd string) (string, error)

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

func TruncateBytes(s string, maxBytes int) string

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

func TruncateHeadTail(s string, maxLines, maxBytes int) string

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

func (q *FileMutationQueue) Run(ctx context.Context, path string, fn func() error) error

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").

func (OSEditOperations) ReadFile

func (OSEditOperations) ReadFile(p string) ([]byte, error)

ReadFile delegates to os.ReadFile.

func (OSEditOperations) WriteFile

func (OSEditOperations) WriteFile(p string, content []byte) error

WriteFile writes content to a sibling temp file and renames it over the target. The temp file lives in the same directory so the rename is atomic on POSIX (same filesystem).

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.

func (OSLSOperations) ReadDir

func (OSLSOperations) ReadDir(p string) ([]fs.DirEntry, error)

ReadDir delegates to os.ReadDir.

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.

func (OSReadOperations) ReadFile

func (OSReadOperations) ReadFile(p string) ([]byte, error)

ReadFile delegates to os.ReadFile.

type OSWriteOperations

type OSWriteOperations struct{}

OSWriteOperations is the default WriteOperations backed by the real filesystem.

func (OSWriteOperations) Stat

Stat delegates to os.Stat.

func (OSWriteOperations) WriteFile

func (OSWriteOperations) WriteFile(p string, content []byte) error

WriteFile writes content to a sibling temp file and renames it over the target. The temp file lives in the same directory so the rename is atomic on POSIX.

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 NewRegistry

func NewRegistry() *Registry

NewRegistry returns an empty Registry.

func (*Registry) Len

func (r *Registry) Len() int

Len returns the number of registered tools.

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) Names

func (r *Registry) Names() []string

Names returns the registered tool names sorted alphabetically.

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.

func (*Theme) IndentN

func (t *Theme) IndentN(depth int) string

Indent returns the indentation string for the given depth.

func (*Theme) Wrap

func (t *Theme) Wrap(style, s string) string

Wrap returns s wrapped in the given style prefix and the theme's Reset suffix. If the style is empty, s is returned unchanged (no escape codes).

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL