tools

package
v0.0.0-...-26e635b Latest Latest
Warning

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

Go to latest
Published: Dec 22, 2025 License: MIT Imports: 22 Imported by: 0

README

Tools Package

Secure AI agent toolkit with structured error handling and zero-global-state design.

繁體中文


Design Philosophy

The Tools building maintainable, testable, and LLM-friendly agent tools.

Core Principles

1. Config Struct Pattern All dependencies injected via KitConfig structure—no global state, explicit dependencies, testable by design.

2. Functional Options Pattern Optional features (logging, metrics) configured through functional options, preserving backward compatibility.

3. Structured Results Standardized Result{Status, Data, Error} format enables consistent LLM interaction and rich error context.

4. Error Semantics: Agent vs System

  • Agent Errors: Recoverable failures (file not found, permission denied) returned in Result → LLM can retry
  • System Errors: Infrastructure failures (database down, OOM) returned as Go error → requires human intervention

5. Zero Maintenance Tool Registry Leverages genkit.ListTools() API—single source of truth, no manual list synchronization.


Architecture

graph TD
    Kit[Kit - Tool Collection<br/>Config Struct Pattern<br/>Functional Options<br/>No Global State]

    Kit --> FileTools[File Tools]
    Kit --> SystemTools[System Tools]
    Kit --> NetworkTools[Network Tools]
    Kit --> KnowledgeTools[Knowledge Tools]

    FileTools --> ReadFile[readFile]
    FileTools --> WriteFile[writeFile]
    FileTools --> ListFiles[listFiles]
    FileTools --> DeleteFile[deleteFile]
    FileTools --> GetFileInfo[getFileInfo]

    SystemTools --> ExecuteCommand[executeCommand]
    SystemTools --> GetEnv[getEnv]
    SystemTools --> CurrentTime[currentTime]

    NetworkTools --> HTTPGet[httpGet<br/>SSRF Protection]

    KnowledgeTools --> SearchHistory[searchHistory]
    KnowledgeTools --> SearchDocuments[searchDocuments]
    KnowledgeTools --> SearchSystemKnowledge[searchSystemKnowledge]

12 tools across 4 categories: File (5) • System (3) • Network (1) • Knowledge (3)


Design Decisions

Why Structured Result over Raw Returns?

Problem: Inconsistent error handling across tools makes LLM interaction unpredictable.

Solution: Standardized Result type with status, data, and structured errors.

Benefits:

  • LLM can parse status semantically
  • Rich debugging context through error codes
  • Consistent interface across all tools
  • Enables programmatic error handling
Why Distinguish Agent Error from System Error?

Problem: Treating all errors equally prevents LLM from recovering gracefully.

Solution: Agent errors in Result (LLM-visible), system errors as Go error (human-visible).

Benefits:

  • LLM can retry on agent errors (wrong path, missing permission)
  • System errors halt execution (database failure requires ops intervention)
  • Genkit framework handles each type appropriately
Why Zero Tool List Maintenance?

Problem: Manual tool lists drift out of sync with registrations, causing runtime failures.

Solution: Use Genkit's ListTools() API as single source of truth.

Benefits:

  • DRY principle—register once, enumerate anywhere
  • No sync bugs when adding/removing tools
  • Runtime tool discovery support

Security Model

All tools enforce defense-in-depth validation:

  • Path Validation: Prevents traversal attacks, enforces allow-list directories, resolves symlinks
  • Command Validation: Blocks dangerous commands (rm -rf, dd, format, sudo, ...)
  • Environment Filtering: Blocks sensitive variables (API keys, passwords, tokens)
  • HTTP Protection: SSRF defense (blocks internal IPs, localhost, metadata services), size limits, timeouts

Security Philosophy: Fail closed—deny by default, allow explicitly validated operations only.


Design Influences

Genkit Framework

Source: Firebase Genkit - Google's AI framework for building production-ready AI agents

Design Philosophy:

  • Tool-centric: AI agents invoke tools to interact with the world
  • Registry pattern: Central tool registry (ListTools(), LookupTool()) eliminates manual list maintenance
  • Structured I/O: Typed inputs/outputs with JSON schema validation
  • Framework-managed lifecycle: Genkit handles tool registration, discovery, and invocation

Why we adopted it:

  • Zero boilerplate—register once, use anywhere
  • Type-safe tool definitions with schema validation
  • Built-in observability and tracing
  • Production-ready error handling

Documentation

Overview

Package tools provides AI agent tools for file, system, network, and knowledge operations.

Overview

This package implements tools that allow AI agents to interact with the system. All tools include built-in security validations and return structured results for consistent LLM handling.

Architecture

Tools are organized into four categories:

  • FileTools: File operations (read, write, list, delete, info)
  • SystemTools: System operations (time, command execution, environment)
  • NetworkTools: Network operations (web search, web fetch)
  • knowledgeTools: Knowledge base operations (semantic search)

Each tool struct is created with a constructor, then registered with Genkit.

Available Tools

File tools (FileTools):

  • read_file: Read file contents (max 10MB)
  • write_file: Write or create files
  • list_files: List directory contents
  • delete_file: Delete a file
  • get_file_info: Get file metadata

System tools (SystemTools):

  • current_time: Get current system time
  • execute_command: Execute shell commands (whitelist enforced)
  • get_env: Read environment variables (secrets protected)

Network tools (NetworkTools):

  • web_search: Search via SearXNG
  • web_fetch: Fetch web content with SSRF protection

Knowledge tools (knowledgeTools):

  • search_history: Search conversation history
  • search_documents: Search indexed documents
  • search_system_knowledge: Search system knowledge base

Security

All tools integrate security validators from the security package:

  • Path validation prevents directory traversal attacks (CWE-22)
  • Command validation blocks dangerous commands like rm -rf (CWE-78)
  • SSRF protection blocks private IPs and cloud metadata endpoints
  • Environment variable protection blocks *KEY*, *SECRET*, *TOKEN* patterns

Result Type

All tools return the unified Result type:

type Result struct {
    Status  Status  // StatusSuccess or StatusError
    Data    any     // Tool output data
    Error   *Error  // Structured error (nil on success)
}

Results are constructed using struct literals directly:

// Success
return Result{Status: StatusSuccess, Data: map[string]any{"path": path}}, nil

// Error
return Result{Status: StatusError, Error: &Error{Code: ErrCodeSecurity, Message: "blocked"}}, nil

Error Handling

Tools distinguish between business errors and infrastructure errors:

Business errors are returned in Result.Error with err = nil:

  • Security validation failures (blocked path, dangerous command)
  • Resource not found
  • Permission denied
  • Invalid input

Infrastructure errors are returned as Go errors:

  • Context cancellation
  • System failures

This allows the LLM to handle expected error conditions gracefully.

Event Emission

Tools support lifecycle events for SSE streaming via the WithEvents wrapper:

wrapped := WithEvents("tool_name", handler)

Events emitted:

  • OnToolStart: Before tool execution begins
  • OnToolComplete: After successful execution
  • OnToolError: After execution returns Go error

Usage Example

// Create tools with security validators
pathVal, _ := security.NewPath([]string{"/allowed/path"})
fileTools, err := tools.NewFileTools(pathVal, logger)
if err != nil {
    return err
}

// Register with Genkit
fileToolList, _ := tools.RegisterFileTools(g, fileTools)

Package tools provides tool abstractions for AI agent interactions.

Package tools provides tool types and result helpers for agent tool operations.

Error Handling:

  • All tools return Result with structured error information
  • Business errors (validation, not found, etc.) use Result.Error
  • Only infrastructure errors (context cancellation) return Go error

Index

Constants

View Source
const (
	ToolReadFile    = "read_file"
	ToolWriteFile   = "write_file"
	ToolListFiles   = "list_files"
	ToolDeleteFile  = "delete_file"
	ToolGetFileInfo = "get_file_info"
)
View Source
const (
	ToolSearchHistory         = "search_history"
	ToolSearchDocuments       = "search_documents"
	ToolSearchSystemKnowledge = "search_system_knowledge"
)
View Source
const (
	DefaultHistoryTopK         = 3
	DefaultDocumentsTopK       = 5
	DefaultSystemKnowledgeTopK = 3
	MaxTopK                    = 10
)

Default TopK values for knowledge searches.

View Source
const (
	ToolWebSearch = "web_search"
	ToolWebFetch  = "web_fetch"
)
View Source
const (
	// MaxURLsPerRequest is the maximum number of URLs allowed per web_fetch request.
	MaxURLsPerRequest = 10
	// MaxContentLength is the maximum content length per URL (50KB).
	MaxContentLength = 50000
	// MaxSearchResults is the maximum number of search results allowed.
	MaxSearchResults = 50
	// DefaultSearchResults is the default number of search results.
	DefaultSearchResults = 10
	// MaxRedirects is the maximum number of HTTP redirects to follow.
	MaxRedirects = 5
)

Content limits.

View Source
const (
	ToolCurrentTime    = "current_time"
	ToolExecuteCommand = "execute_command"
	ToolGetEnv         = "get_env"
)
View Source
const MaxReadFileSize = 10 * 1024 * 1024

MaxReadFileSize is the maximum file size allowed for ReadFile (10 MB). This prevents OOM when reading large files into memory.

Variables

This section is empty.

Functions

func ContextWithEmitter

func ContextWithEmitter(ctx context.Context, emitter ToolEventEmitter) context.Context

ContextWithEmitter stores ToolEventEmitter in context. Per architecture-master: Per-request binding via context.Context.

func GetAllToolMetadata

func GetAllToolMetadata() map[string]ToolMetadata

GetAllToolMetadata returns a copy of all tool metadata. Useful for documentation generation and validation.

func IsDangerous

func IsDangerous(toolName string) bool

IsDangerous returns true if the tool is classified as DangerLevelDangerous or DangerLevelCritical. This is a convenience function for quick safety checks.

Usage:

if tools.IsDangerous(tools.ToolDeleteFile) {
    // Require confirmation
}

func RegisterFileTools

func RegisterFileTools(g *genkit.Genkit, ft *FileTools) ([]ai.Tool, error)

RegisterFileTools registers all file operation tools with Genkit.

func RegisterKnowledgeTools

func RegisterKnowledgeTools(g *genkit.Genkit, kt *KnowledgeTools) ([]ai.Tool, error)

RegisterKnowledgeTools registers all knowledge search tools with Genkit. Tools are registered with event emission wrappers for streaming support.

func RegisterNetworkTools

func RegisterNetworkTools(g *genkit.Genkit, nt *NetworkTools) ([]ai.Tool, error)

RegisterNetworkTools registers all network operation tools with Genkit. Tools are registered with event emission wrappers for streaming support.

func RegisterNetworkToolsForTesting

func RegisterNetworkToolsForTesting(g *genkit.Genkit, cfg NetworkConfig, logger log.Logger) ([]ai.Tool, error)

RegisterNetworkToolsForTesting creates network tools with SSRF protection disabled. This should ONLY be used in tests.

func RegisterSystemTools

func RegisterSystemTools(g *genkit.Genkit, st *SystemTools) ([]ai.Tool, error)

RegisterSystemTools registers all system operation tools with Genkit. Tools are registered with event emission wrappers for streaming support.

func RequiresConfirmation

func RequiresConfirmation(toolName string, params map[string]any) bool

RequiresConfirmation returns true if the tool requires user confirmation before execution. Considers both static RequiresConfirmation flag and dynamic IsDangerousFunc.

Usage:

if tools.RequiresConfirmation(tools.ToolWriteFile, params) {
    // Must call request_confirmation first
}

func WithEvents

func WithEvents[In, Out any](name string, fn func(*ai.ToolContext, In) (Out, error)) func(*ai.ToolContext, In) (Out, error)

WithEvents wraps a typed tool handler to emit lifecycle events. This generic version works directly with genkit.DefineTool().

The wrapper:

  1. Retrieves emitter from context (may be nil for non-streaming calls)
  2. Emits OnToolStart before execution
  3. Calls the original handler function
  4. Emits OnToolComplete or OnToolError after execution

If no emitter is in context, the wrapper simply passes through to the original function. This allows graceful degradation for non-streaming code paths.

Types

type CurrentTimeInput

type CurrentTimeInput struct{}

CurrentTimeInput defines input for current_time tool (no input needed).

type DangerLevel

type DangerLevel int

DangerLevel indicates the risk level of a tool operation.

const (
	// DangerLevelSafe represents read-only operations with no state modification.
	// Examples: read_file, list_files, get_file_info, current_time, web_fetch, get_env
	DangerLevelSafe DangerLevel = iota

	// DangerLevelWarning represents operations that modify state but are generally reversible.
	// Examples: write_file (can be overwritten)
	// These operations may require caution but don't typically cause data loss
	DangerLevelWarning

	// DangerLevelDangerous represents irreversible or destructive operations.
	// Examples: delete_file, execute_command (with rm, DROP DATABASE, etc.)
	// These operations MUST trigger request_confirmation before execution
	DangerLevelDangerous

	// DangerLevelCritical represents system-level destructive operations.
	// Examples: Format disk, shutdown system, delete entire directories
	// Reserved for future use - not currently assigned to any tool
	DangerLevelCritical
)

func GetDangerLevel

func GetDangerLevel(toolName string) DangerLevel

GetDangerLevel returns the danger level of a tool. Returns DangerLevelSafe for unknown tools (fail-safe default).

func (DangerLevel) String

func (d DangerLevel) String() string

String returns the human-readable name of the danger level.

type DeleteFileInput

type DeleteFileInput struct {
	Path string `json:"path" jsonschema_description:"The file path to delete"`
}

DeleteFileInput defines input for delete_file tool.

type Error

type Error struct {
	Code    ErrorCode `json:"code" jsonschema_description:"Error code"`
	Message string    `json:"message" jsonschema_description:"Detailed error message"`
	Details any       `json:"details,omitempty" jsonschema_description:"Additional error context"`
}

Error provides structured error information for JSON responses.

type ErrorCode

type ErrorCode string

ErrorCode represents standardized error codes for LLM-facing JSON responses. These are kept for backward compatibility and structured LLM responses.

const (
	ErrCodeSecurity   ErrorCode = "SecurityError"
	ErrCodeNotFound   ErrorCode = "NotFound"
	ErrCodePermission ErrorCode = "PermissionDenied"
	ErrCodeIO         ErrorCode = "IOError"
	ErrCodeExecution  ErrorCode = "ExecutionError"
	ErrCodeTimeout    ErrorCode = "TimeoutError"
	ErrCodeNetwork    ErrorCode = "NetworkError"
	ErrCodeValidation ErrorCode = "ValidationError"
)

Standardized error codes for tool responses.

type ExecuteCommandInput

type ExecuteCommandInput struct {
	Command string   `json:"command" jsonschema_description:"The command to execute (e.g., 'ls', 'git')"`
	Args    []string `json:"args,omitempty" jsonschema_description:"Command arguments as separate array elements"`
}

ExecuteCommandInput defines input for execute_command tool.

type FailedURL

type FailedURL struct {
	URL        string `json:"url"`
	Reason     string `json:"reason"`
	StatusCode int    `json:"status_code,omitempty"` // HTTP status code if available
}

FailedURL represents a URL that failed to fetch.

type FetchInput

type FetchInput struct {
	// URLs is one or more URLs to fetch. Required, max 10.
	URLs []string `json:"urls" jsonschema_description:"One or more URLs to fetch (required, max 10)"`

	// Selector is an optional CSS selector to extract specific content.
	// If empty, attempts to extract main content automatically using Readability.
	Selector string `` /* 128-byte string literal not displayed */
}

FetchInput defines the input for web_fetch tool.

type FetchOutput

type FetchOutput struct {
	// Results contains the fetched content for each URL.
	Results []FetchResult `json:"results"`

	// FailedURLs lists URLs that failed to fetch with reasons.
	FailedURLs []FailedURL `json:"failed_urls,omitempty"`

	// Error contains validation error for LLM to understand.
	Error string `json:"error,omitempty"`
}

FetchOutput defines the output for web_fetch tool.

type FetchResult

type FetchResult struct {
	URL         string `json:"url"`
	Title       string `json:"title"`
	Content     string `json:"content"`
	ContentType string `json:"content_type"` // e.g., "text/html", "application/json", "text/plain"
}

FetchResult represents successfully fetched content from a single URL.

type FileEntry

type FileEntry struct {
	Name string `json:"name"`
	Type string `json:"type"` // "file" or "directory"
}

FileEntry represents a single file or directory entry in ListFiles output.

type FileTools

type FileTools struct {
	// contains filtered or unexported fields
}

FileTools provides file operation handlers. Use NewFileTools to create an instance, then either: - Call methods directly (for MCP) - Use RegisterFileTools to register with Genkit

func NewFileTools

func NewFileTools(pathVal *security.Path, logger log.Logger) (*FileTools, error)

NewFileTools creates a FileTools instance.

func (*FileTools) DeleteFile

func (f *FileTools) DeleteFile(_ *ai.ToolContext, input DeleteFileInput) (Result, error)

DeleteFile permanently deletes a file with security validation.

func (*FileTools) GetFileInfo

func (f *FileTools) GetFileInfo(_ *ai.ToolContext, input GetFileInfoInput) (Result, error)

GetFileInfo gets file metadata.

func (*FileTools) ListFiles

func (f *FileTools) ListFiles(_ *ai.ToolContext, input ListFilesInput) (Result, error)

ListFiles lists files in a directory.

func (*FileTools) ReadFile

func (f *FileTools) ReadFile(_ *ai.ToolContext, input ReadFileInput) (Result, error)

ReadFile reads and returns the complete content of a file with security validation.

func (*FileTools) WriteFile

func (f *FileTools) WriteFile(_ *ai.ToolContext, input WriteFileInput) (Result, error)

WriteFile writes content to a file with security validation.

type GetEnvInput

type GetEnvInput struct {
	Key string `json:"key" jsonschema_description:"The environment variable name"`
}

GetEnvInput defines input for get_env tool.

type GetFileInfoInput

type GetFileInfoInput struct {
	Path string `json:"path" jsonschema_description:"The file path to get info for"`
}

GetFileInfoInput defines input for get_file_info tool.

type KnowledgeSearchInput

type KnowledgeSearchInput struct {
	Query string `json:"query" jsonschema_description:"The search query string"`
	TopK  int    `json:"topK,omitempty" jsonschema_description:"Maximum results to return (1-10)"`
}

KnowledgeSearchInput defines input for all knowledge search tools. The default TopK varies by tool: history=3, documents=5, system=3.

type KnowledgeTools

type KnowledgeTools struct {
	// contains filtered or unexported fields
}

KnowledgeTools holds dependencies for knowledge operation handlers.

func NewKnowledgeTools

func NewKnowledgeTools(retriever ai.Retriever, logger log.Logger) (*KnowledgeTools, error)

NewKnowledgeTools creates a KnowledgeTools instance.

func (*KnowledgeTools) SearchDocuments

func (k *KnowledgeTools) SearchDocuments(ctx *ai.ToolContext, input KnowledgeSearchInput) (Result, error)

SearchDocuments searches indexed documents using semantic similarity.

func (*KnowledgeTools) SearchHistory

func (k *KnowledgeTools) SearchHistory(ctx *ai.ToolContext, input KnowledgeSearchInput) (Result, error)

SearchHistory searches conversation history using semantic similarity.

func (*KnowledgeTools) SearchSystemKnowledge

func (k *KnowledgeTools) SearchSystemKnowledge(ctx *ai.ToolContext, input KnowledgeSearchInput) (Result, error)

SearchSystemKnowledge searches system knowledge base using semantic similarity.

type ListFilesInput

type ListFilesInput struct {
	Path string `json:"path" jsonschema_description:"The directory path to list"`
}

ListFilesInput defines input for list_files tool.

type NetworkConfig

type NetworkConfig struct {
	SearchBaseURL    string
	FetchParallelism int
	FetchDelay       time.Duration
	FetchTimeout     time.Duration
}

NetworkConfig holds configuration for network tools.

type NetworkTools

type NetworkTools struct {
	// contains filtered or unexported fields
}

NetworkTools holds dependencies for network operation handlers. Use NewNetworkTools to create an instance, then either: - Call methods directly (for MCP) - Use RegisterNetworkTools to register with Genkit

func NewNetworkTools

func NewNetworkTools(cfg NetworkConfig, logger log.Logger) (*NetworkTools, error)

NewNetworkTools creates a NetworkTools instance.

func NewNetworkToolsForTesting

func NewNetworkToolsForTesting(cfg NetworkConfig, logger log.Logger) (*NetworkTools, error)

NewNetworkToolsForTesting creates a NetworkTools instance with SSRF protection disabled. This should ONLY be used in tests.

func (*NetworkTools) Fetch

func (n *NetworkTools) Fetch(ctx *ai.ToolContext, input FetchInput) (FetchOutput, error)

Fetch retrieves and extracts content from one or more URLs. Includes SSRF protection to block private IPs and cloud metadata endpoints.

func (*NetworkTools) Search

func (n *NetworkTools) Search(ctx *ai.ToolContext, input SearchInput) (SearchOutput, error)

Search performs web search via SearXNG.

type ReadFileInput

type ReadFileInput struct {
	Path string `json:"path" jsonschema_description:"The file path to read (absolute or relative)"`
}

ReadFileInput defines input for read_file tool.

type Result

type Result struct {
	Status Status `json:"status" jsonschema_description:"The execution status"`
	Data   any    `json:"data,omitempty" jsonschema_description:"The tool's output data"`
	Error  *Error `json:"error,omitempty" jsonschema_description:"Error information if failed"`
}

Result is the standard return format for all tools.

type SearchInput

type SearchInput struct {
	// Query is the search query string. Required.
	Query string `json:"query" jsonschema_description:"The search query (required)"`

	// Categories filters results by type. Optional.
	Categories []string `json:"categories,omitempty" jsonschema_description:"Search categories: general, news, images, videos, science"`

	// Language specifies the preferred language. Optional.
	Language string `json:"language,omitempty" jsonschema_description:"Language code (e.g. en, zh-TW, ja)"`

	// MaxResults limits the number of results. Optional, default 10, max 50.
	MaxResults int `json:"max_results,omitempty" jsonschema_description:"Maximum results to return (default 10, max 50)"`
}

SearchInput defines the input for web_search tool.

type SearchOutput

type SearchOutput struct {
	Results []SearchResult `json:"results,omitempty"`
	Query   string         `json:"query"`
	Error   string         `json:"error,omitempty"` // Business error for LLM
}

SearchOutput defines the output for web_search tool.

type SearchResult

type SearchResult struct {
	Title       string `json:"title"`
	URL         string `json:"url"`
	Content     string `json:"content"`
	Engine      string `json:"engine,omitempty"`
	PublishedAt string `json:"published_at,omitempty"`
}

SearchResult represents a single search result.

type Status

type Status string

Status represents the execution status of a tool.

const (
	StatusSuccess Status = "success" // Tool completed successfully
	StatusError   Status = "error"   // Tool failed with an error
)

Tool execution status constants.

type SystemTools

type SystemTools struct {
	// contains filtered or unexported fields
}

SystemTools holds dependencies for system operation handlers. Use NewSystemTools to create an instance, then either: - Call methods directly (for MCP) - Use RegisterSystemTools to register with Genkit

func NewSystemTools

func NewSystemTools(cmdVal *security.Command, envVal *security.Env, logger log.Logger) (*SystemTools, error)

NewSystemTools creates a SystemTools instance.

func (*SystemTools) CurrentTime

func (s *SystemTools) CurrentTime(_ *ai.ToolContext, _ CurrentTimeInput) (Result, error)

CurrentTime returns the current system date and time in multiple formats.

func (*SystemTools) ExecuteCommand

func (s *SystemTools) ExecuteCommand(ctx *ai.ToolContext, input ExecuteCommandInput) (Result, error)

ExecuteCommand executes a system shell command with security validation. Dangerous commands like rm -rf, sudo, and shutdown are blocked. Business errors (blocked commands, execution failures) are returned in Result.Error. Only context cancellation returns a Go error.

func (*SystemTools) GetEnv

func (s *SystemTools) GetEnv(_ *ai.ToolContext, input GetEnvInput) (Result, error)

GetEnv reads an environment variable value with security protection. Sensitive variables containing KEY, SECRET, or TOKEN in the name are blocked. Business errors (sensitive variable blocked) are returned in Result.Error.

type ToolEventEmitter

type ToolEventEmitter interface {
	// OnToolStart signals that a tool has started execution.
	// name: tool name (e.g., "web_search")
	// UI presentation (messages, icons) handled by web layer.
	OnToolStart(name string)

	// OnToolComplete signals that a tool completed successfully.
	// name: tool name
	OnToolComplete(name string)

	// OnToolError signals that a tool execution failed.
	// name: tool name
	// UI error messages handled by web layer.
	OnToolError(name string)
}

ToolEventEmitter receives tool lifecycle events. Interface is minimal - only tool name, no UI concerns. Per architecture-master: Interface for loose coupling between tools and SSE layer. UI presentation logic moved to web/handlers layer.

Usage:

  1. Handler creates emitter bound to SSE writer
  2. Handler stores emitter in context via ContextWithEmitter()
  3. Wrapped tool retrieves emitter via EmitterFromContext()
  4. Tool calls OnToolStart/Complete/Error during execution

func EmitterFromContext

func EmitterFromContext(ctx context.Context) ToolEventEmitter

EmitterFromContext retrieves ToolEventEmitter from context. Returns nil if not set, allowing graceful degradation (no events emitted). Per architecture-master: Non-streaming code paths won't have emitter set.

type ToolMetadata

type ToolMetadata struct {
	// Name is the unique identifier of the tool.
	Name string

	// Description provides a brief explanation of what the tool does.
	Description string

	// RequiresConfirmation indicates if the tool MUST call requestConfirmation before execution.
	// This is true for all DangerLevelDangerous and DangerLevelCritical tools.
	RequiresConfirmation bool

	// DangerLevel classifies the safety level of the tool.
	DangerLevel DangerLevel

	// IsDangerousFunc is an optional function that dynamically determines if specific
	// parameters make this tool call dangerous.
	// Example: writeFile to /etc/passwd is more dangerous than writeFile to /tmp/test.txt
	// If nil, danger level is static (determined by DangerLevel field only).
	IsDangerousFunc func(params map[string]any) bool

	// Category organizes tools by domain (File, System, Network, Meta).
	Category string
}

ToolMetadata defines business properties for tools.

func GetToolMetadata

func GetToolMetadata(toolName string) (ToolMetadata, bool)

GetToolMetadata retrieves metadata for a specific tool. Returns the metadata and a boolean indicating if the tool was found.

Usage:

if meta, ok := tools.GetToolMetadata(tools.ToolDeleteFile); ok {
    if meta.RequiresConfirmation {
        // Must call request_confirmation first
    }
}

func ListToolsByDangerLevel

func ListToolsByDangerLevel(level DangerLevel) []ToolMetadata

ListToolsByDangerLevel returns all tools matching the specified danger level. Useful for generating documentation or validation checks.

type WriteFileInput

type WriteFileInput struct {
	Path    string `json:"path" jsonschema_description:"The file path to write"`
	Content string `json:"content" jsonschema_description:"The content to write to the file"`
}

WriteFileInput defines input for write_file tool.