UNPKG

@tanstack/ai

Version:

Core TanStack AI library - Open source AI SDK

131 lines (130 loc) 5.07 kB
import { CustomEvent, ModelMessage, RunFinishedEvent, Tool, ToolCall, ToolCallArgsEvent, ToolCallEndEvent, ToolCallStartEvent } from '../../../types.js'; import { AfterToolCallInfo, BeforeToolCallDecision } from '../middleware/types.js'; /** * Optional middleware hooks for tool execution. * When provided, these callbacks are invoked before/after each tool execution. */ export interface ToolExecutionMiddlewareHooks { onBeforeToolCall?: (toolCall: ToolCall, tool: Tool | undefined, args: unknown) => Promise<BeforeToolCallDecision>; onAfterToolCall?: (info: AfterToolCallInfo) => Promise<void>; } /** * Error thrown when middleware decides to abort the chat run during tool execution. */ export declare class MiddlewareAbortError extends Error { constructor(reason: string); } /** * Manages tool call accumulation and execution for the chat() method's automatic tool execution loop. * * Responsibilities: * - Accumulates streaming tool call events (ID, name, arguments) * - Validates tool calls (filters out incomplete ones) * - Executes tool `execute` functions with parsed arguments * - Emits `TOOL_CALL_END` events for client visibility * - Returns tool result messages for conversation history * * This class is used internally by the AI.chat() method to handle the automatic * tool execution loop. It can also be used independently for custom tool execution logic. * * @example * ```typescript * const manager = new ToolCallManager(tools); * * // During streaming, accumulate tool calls * for await (const chunk of stream) { * if (chunk.type === 'TOOL_CALL_START') { * manager.addToolCallStartEvent(chunk); * } else if (chunk.type === 'TOOL_CALL_ARGS') { * manager.addToolCallArgsEvent(chunk); * } * } * * // After stream completes, execute tools * if (manager.hasToolCalls()) { * const toolResults = yield* manager.executeTools(finishEvent); * messages = [...messages, ...toolResults]; * manager.clear(); * } * ``` */ export declare class ToolCallManager { private toolCallsMap; private tools; constructor(tools: ReadonlyArray<Tool>); /** * Add a TOOL_CALL_START event to begin tracking a tool call (AG-UI) */ addToolCallStartEvent(event: ToolCallStartEvent): void; /** * Add a TOOL_CALL_ARGS event to accumulate arguments (AG-UI) */ addToolCallArgsEvent(event: ToolCallArgsEvent): void; /** * Complete a tool call with its final input * Called when TOOL_CALL_END is received */ completeToolCall(event: ToolCallEndEvent): void; /** * Check if there are any complete tool calls to execute */ hasToolCalls(): boolean; /** * Get all complete tool calls (filtered for valid ID and name) */ getToolCalls(): Array<ToolCall>; /** * Execute all tool calls and return tool result messages * Yields TOOL_CALL_END events for streaming * @param finishEvent - RUN_FINISHED event from the stream */ executeTools(finishEvent: RunFinishedEvent): AsyncGenerator<ToolCallEndEvent, Array<ModelMessage>, void>; /** * Clear the tool calls map for the next iteration */ clear(): void; } export interface ToolResult { toolCallId: string; toolName: string; result: any; state?: 'output-available' | 'output-error'; /** Duration of tool execution in milliseconds (only for server-executed tools) */ duration?: number; } export interface ApprovalRequest { toolCallId: string; toolName: string; input: any; approvalId: string; } export interface ClientToolRequest { toolCallId: string; toolName: string; input: any; } interface ExecuteToolCallsResult { /** Tool results ready to send to LLM */ results: Array<ToolResult>; /** Tools that need user approval before execution */ needsApproval: Array<ApprovalRequest>; /** Tools that need client-side execution */ needsClientExecution: Array<ClientToolRequest>; } /** * Execute tool calls based on their configuration. * Yields CustomEvent chunks during tool execution for real-time progress updates. * * Handles three cases: * 1. Client tools (no execute) - request client to execute * 2. Server tools with approval - check approval before executing * 3. Normal server tools - execute immediately * * @param toolCalls - Tool calls from the LLM * @param tools - Available tools with their configurations * @param approvals - Map of approval decisions (approval.id -> approved boolean) * @param clientResults - Map of client-side execution results (toolCallId -> result) * @param createCustomEventChunk - Factory to create CustomEvent chunks (optional) */ export declare function executeToolCalls(toolCalls: Array<ToolCall>, tools: ReadonlyArray<Tool>, approvals?: Map<string, boolean>, clientResults?: Map<string, any>, createCustomEventChunk?: (eventName: string, value: Record<string, any>) => CustomEvent, middlewareHooks?: ToolExecutionMiddlewareHooks): AsyncGenerator<CustomEvent, ExecuteToolCallsResult, void>; export {};