/** * Core types for tools that AI agents can use */ /** * JSON Schema for tool input parameters */ export interface ToolInputSchema { type: 'object'; properties: Record; required?: string[]; } /** * Tool definition - describes a tool the AI can call */ export interface ToolDefinition { name: string; description: string; inputSchema: ToolInputSchema; } /** * Result of executing a tool */ export interface ToolExecutionResult { success: boolean; result?: unknown; error?: string; /** * Optional image blocks to inject alongside the tool result. * When present, these are added as sibling content blocks in the * tool result message, enabling vision-capable LLMs to see images. * Used by tools like view_image that return visual content. */ imageBlocks?: Array<{ data: string; mediaType: string; filename?: string; width?: number; height?: number; }>; } /** * Context passed to tool execution for streaming output */ export interface ToolExecutionContext { /** * Callback for streaming output (e.g., bash stdout/stderr) * @param output - The output text * @param stream - Which stream the output came from */ onOutput?: (output: string, stream?: 'stdout' | 'stderr') => void; /** * Tool use ID for correlation with events */ toolUseId?: string; /** * AbortSignal for cancelling/backgrounding the tool execution. * When aborted with reason 'background', the bash tool should move the * process to ShellManager instead of terminating. */ abortSignal?: AbortSignal; /** * Callback to notify when a process has been moved to background. * Called by bash tool when user presses Ctrl+B (abortSignal with 'background' reason). * @param shellId - The shell ID in ShellManager for later retrieval * @param partialOutput - Output collected so far (stdout + stderr) */ onBackground?: (shellId: string, partialOutput: string) => void; } /** * Tool handler function type * @param input - The tool input parameters * @param context - Optional execution context for streaming */ export type ToolHandler = (input: T, context?: ToolExecutionContext) => Promise; /** * A tool that the agent can call during conversations. * * Tools are the primary way agents interact with the outside world — reading * files, running commands, querying APIs, etc. Each tool has a definition * (name, description, parameters) that the LLM sees, and an execute function * that runs when the LLM decides to call it. * * Use `defineTool()` to create tools with type-safe parameters. * * @typeParam T - The type of the tool's input parameters * * @example * ```typescript * const readFileTool: Tool<{ path: string }> = { * definition: { * name: 'read_file', * description: 'Read the contents of a file', * parameters: { * type: 'object', * properties: { path: { type: 'string', description: 'File path' } }, * required: ['path'], * }, * }, * execute: async ({ path }) => { * const content = await fs.readFile(path, 'utf-8'); * return { content }; * }, * readonly: true, // Safe for parallel execution * }; * ``` */ export interface Tool { definition: ToolDefinition; execute: ToolHandler; /** * If true, multiple calls to this tool can execute in parallel. * When the LLM requests multiple parallel-safe tools in one response, * they will be executed concurrently using Promise.all. * Default: false (sequential execution) */ parallel?: boolean; /** * If true, this tool runs silently without spinner updates or result output. * Used for internal housekeeping tools like todo_read, suggest, etc. * Default: false (normal visibility) */ silent?: boolean; /** * If true, this tool performs no side effects (only reads data). * Read-only tools are automatically batched for parallel execution * even in a mixed batch with write tools. * Default: false */ readonly?: boolean; /** * If true, this tool is exempt from tool-loop detection — repeated identical * calls are always legitimate (e.g. genuinely idempotent pollers). Most * polling tools do NOT need this: loop detection is result-aware, so calls * that return changing output don't trip. Default: false. */ repeatable?: boolean; } /** * Fallback handler for tools not found in the primary registry. * Used by meta-tools to transparently route calls to a secondary registry. * * @param name - Tool name that was not found * @param input - Tool input parameters * @param context - Optional execution context * @returns Result if handled, or null to return the default "not found" error */ export type ToolFallbackHandler = (name: string, input: Record, context?: ToolExecutionContext) => Promise; /** * Tool registry for managing available tools */ export interface ToolRegistry { /** * Register a tool */ register(tool: Tool): void; /** * Get a tool by name */ get(name: string): Tool | undefined; /** * Get all tool definitions (for sending to LLM) */ getDefinitions(): ToolDefinition[]; /** * Execute a tool by name with given input * @param name - Tool name * @param input - Tool input parameters * @param context - Optional execution context for streaming */ execute(name: string, input: Record, context?: ToolExecutionContext): Promise; /** * Set a fallback handler for tools not found in the primary registry. * Enables transparent routing to secondary registries (e.g., meta-tools). */ setFallbackHandler(handler: ToolFallbackHandler | null): void; }