UNPKG

ai-functions

Version:

Core AI primitives for building intelligent applications

453 lines 12.9 kB
/** * Agentic Tool Orchestration * * Provides multi-turn model→tools→model loop orchestration for complex AI workflows. * * Key components: * - AgenticLoop: Orchestrates multi-turn conversations with tool execution * - ToolRouter: Routes tool calls to registered handlers * - ToolValidator: Validates tool arguments before execution * * @packageDocumentation */ import { z, type ZodTypeAny } from 'zod'; /** * A tool that can be executed by the agentic loop */ export interface Tool<TParams extends ZodTypeAny = ZodTypeAny, TResult = unknown> { /** Unique name for the tool */ name: string; /** Human-readable description */ description: string; /** Zod schema for parameters */ parameters: TParams; /** Execute the tool with validated parameters */ execute: (params: z.infer<TParams>) => Promise<TResult>; } /** * A tool call from the model */ export interface ToolCall { /** Name of the tool to call */ name: string; /** Arguments for the tool */ arguments: Record<string, unknown>; /** Optional ID for tracking */ id?: string; } /** * Result of a tool execution */ export interface ToolResult<T = unknown> { /** Whether execution succeeded */ success: boolean; /** The result value if successful */ result?: T; /** Error message if failed */ error?: string; /** The original tool call */ toolCall?: ToolCall; /** Number of retries attempted */ retryCount?: number; } /** * Formatted tool result for model consumption */ export interface FormattedToolResult { /** Role is always 'tool' */ role: 'tool'; /** String content of the result */ content: string; /** Tool call ID for correlation */ tool_call_id?: string; /** Whether this is an error result */ isError?: boolean; } /** * Validation result for tool arguments */ export interface ValidationResult { /** Whether validation passed */ valid: boolean; /** Validation errors if any */ errors?: string[]; /** Validated and parsed arguments */ parsedArgs?: unknown; } /** * Model response from a generation */ export interface ModelResponse { /** Generated text (if no tool calls) */ text?: string; /** Tool calls requested by the model */ toolCalls?: ToolCall[]; /** Why generation stopped */ finishReason: 'stop' | 'tool_call' | 'length' | 'content_filter' | 'error'; /** Token usage */ usage?: { promptTokens: number; completionTokens: number; totalTokens: number; }; } /** * Message in the conversation */ export interface Message { role: 'user' | 'assistant' | 'system' | 'tool'; content: string; tool_calls?: ToolCall[]; tool_call_id?: string; isError?: boolean; } /** * Step information for callbacks */ export interface StepInfo { /** Step number (1-indexed) */ stepNumber: number; /** Tool calls in this step */ toolCalls: Array<ToolCall & { result?: unknown; error?: string; }>; /** Model response */ response: ModelResponse; /** Current messages */ messages: Message[]; } /** * Options for creating an AgenticLoop */ export interface LoopOptions { /** Available tools */ tools: Tool[]; /** Maximum number of steps before stopping */ maxSteps: number; /** Whether to throw error when maxSteps is exceeded */ strictMaxSteps?: boolean; /** Whether to execute tool calls in parallel */ parallelExecution?: boolean; /** Maximum concurrent tool calls when parallel execution is enabled */ maxParallelCalls?: number; /** Whether to retry failed tool calls */ retryFailedTools?: boolean; /** Maximum retries per tool call */ maxToolRetries?: number; /** Whether to continue when a tool fails */ continueOnError?: boolean; /** Timeout for individual tool execution (ms) */ toolTimeout?: number; /** Track token usage across steps */ trackUsage?: boolean; /** Callback for each step */ onStep?: (step: StepInfo) => void; } /** * Model generation options passed to the model */ export interface ModelGenerationOptions { /** Messages for the conversation */ messages: Message[]; /** Tools available for use */ tools: Record<string, { description: string; parameters: unknown; execute: (args: unknown) => Promise<unknown>; }>; } /** * Options for running the loop */ export interface RunOptions { /** Model to use for generation */ model: { generate: (options: ModelGenerationOptions) => Promise<ModelResponse>; }; /** Initial prompt */ prompt: string; /** System message */ system?: string; /** Abort signal */ abortSignal?: AbortSignal; } /** * Extended tool call result with metadata */ export interface ToolCallResult { /** Tool name */ name: string; /** Arguments passed */ arguments: Record<string, unknown>; /** Result if successful */ result?: unknown; /** Error if failed */ error?: string; /** Number of retries */ retryCount?: number; } /** * Tool result for SDK compatibility */ export interface SDKToolResult { /** Tool name */ toolName: string; /** Tool call ID */ toolCallId?: string; /** Result value */ result: unknown; } /** * Result of running the agentic loop */ export interface LoopResult { /** Final text output */ text: string; /** Number of steps executed */ steps: number; /** All tool calls made */ toolCalls: ToolCallResult[]; /** Tool results in SDK format */ toolResults: SDKToolResult[]; /** Why the loop stopped */ stopReason: 'stop' | 'max_steps' | 'error' | 'aborted'; /** Token usage if tracked */ usage?: { promptTokens: number; completionTokens: number; totalTokens: number; }; /** Conversation messages */ messages: Message[]; } /** * Validates tool arguments before execution */ export declare class ToolValidator { private tools; /** * Register a tool for validation */ register(tool: Tool): void; /** * Validate arguments for a tool */ validate(toolName: string, args: unknown): ValidationResult; /** * Validate multiple tool calls at once */ validateAll(calls: ToolCall[]): ValidationResult[]; } /** * Routes tool calls to registered handlers * * @deprecated Phase C Week 2 — `ToolRouter` has zero production callers in * primitives.org.ai (audited 2026-05-06; see `bd show aip-ibid`). Only the * `ai-primitives` umbrella re-export tests reference it. AI SDK 6's native * tool-routing under `generateText({ tools })` and `Agent` / `ToolLoopAgent` * cover the same surface. Will be removed in the Phase C semver bump * alongside `AgenticLoop` and `createAgenticLoop`. */ export declare class ToolRouter { private tools; private validator; /** * Register a tool */ register(tool: Tool): void; /** * Route a single tool call */ route(call: ToolCall): Promise<ToolResult>; /** * Route multiple tool calls sequentially */ routeAll(calls: ToolCall[]): Promise<ToolResult[]>; /** * Route multiple tool calls in parallel */ routeAllParallel(calls: ToolCall[]): Promise<ToolResult[]>; /** * Format a tool result for model consumption */ formatResult(result: ToolResult): FormattedToolResult; } /** * Orchestrates multi-turn model→tools→model loops * * @deprecated Phase C Week 2 — `AgenticLoop` has zero production callers in * primitives.org.ai (audited 2026-05-06; see `bd show aip-ibid`). Only the * `ai-primitives` umbrella re-export tests reference it. The production * cascade walker (`services-as-software/v3/invoke/cascade-walker.ts:178`) * already uses AI SDK 6's `generateText({ tools, maxSteps: 10 })` directly * for agentic steps — no consumer code paths through this class. AI SDK 6's * `Agent` / `ToolLoopAgent` (`stopWhen: stepCountIs(N)`) are the going- * forward primitives. Will be removed in the Phase C semver bump. */ export declare class AgenticLoop { private options; private router; private validator; constructor(options: LoopOptions); /** * Get tools in AI SDK format */ getToolsForSDK(): Record<string, { description: string; parameters: unknown; execute: (args: unknown) => Promise<unknown>; }>; /** * Execute a tool call with timeout and retry support */ private executeToolCall; /** * Execute multiple tool calls */ private executeToolCalls; /** * Build messages for the next model call */ private buildMessages; /** * Run the agentic loop */ run(runOptions: RunOptions): Promise<LoopResult>; /** * Run the agentic loop with streaming support * * Returns an async generator that yields step events as they occur. */ stream(runOptions: RunOptions): AsyncGenerator<LoopStreamEvent, LoopResult>; } /** * Events emitted during streaming loop execution */ export type LoopStreamEvent = { type: 'start'; prompt: string; timestamp: number; } | { type: 'step_start'; stepNumber: number; timestamp: number; } | { type: 'step_end'; stepNumber: number; hasToolCalls: boolean; timestamp: number; } | { type: 'text'; text: string; stepNumber: number; timestamp: number; } | { type: 'tool_calls'; toolCalls: ToolCall[]; stepNumber: number; timestamp: number; } | { type: 'tool_result'; toolName: string; result?: unknown; error?: string; stepNumber: number; timestamp: number; } | { type: 'max_steps'; steps: number; timestamp: number; } | { type: 'aborted'; steps: number; timestamp: number; } | { type: 'error'; error: string; timestamp: number; } | { type: 'end'; steps: number; stopReason: LoopResult['stopReason']; timestamp: number; }; /** * Create a tool from a simple function */ export declare function createTool<TParams extends z.ZodRawShape, TResult>(config: { name: string; description: string; parameters: TParams; execute: (params: z.infer<z.ZodObject<TParams>>) => Promise<TResult>; }): Tool<z.ZodObject<TParams>, TResult>; /** * Compose multiple tools into a single toolset */ export declare function createToolset(...tools: Tool[]): Tool[]; /** * Create a tool that wraps another tool with middleware */ export declare function wrapTool<T extends Tool>(tool: T, middleware: { before?: (params: unknown) => Promise<unknown> | unknown; after?: (result: unknown) => Promise<unknown> | unknown; onError?: (error: Error) => Promise<unknown> | unknown; }): Tool; /** * Options for cachedTool */ export interface CachedToolOptions { /** Time-to-live in milliseconds (default: 60000) */ ttl?: number; /** Function to generate cache key from params (default: JSON.stringify) */ keyFn?: (params: unknown) => string; /** Interval in ms for automatic cleanup of expired entries (default: 0 = disabled) */ cleanupIntervalMs?: number; /** Maximum cache size before LRU eviction kicks in (default: 0 = unlimited) */ maxSize?: number; } /** * Extended tool interface with cache management methods */ export interface CachedTool extends Tool { /** Get the current number of entries in the cache */ cacheSize(): number; /** Clear all cache entries */ clearCache(): void; /** Stop cleanup timer and clear cache */ destroy(): void; } /** * Create a tool with caching support * * Features: * - TTL-based expiration * - Optional periodic cleanup of expired entries (prevents memory leaks) * - Optional max size with LRU eviction * - Manual cache control (clear, destroy) */ export declare function cachedTool<T extends Tool>(tool: T, options?: CachedToolOptions): CachedTool; /** * Create a tool with rate limiting */ export declare function rateLimitedTool<T extends Tool>(tool: T, options: { maxCalls: number; windowMs: number; }): Tool; /** * Create a tool that times out after a specified duration */ export declare function timeoutTool<T extends Tool>(tool: T, timeoutMs: number): Tool; /** * Create an agentic loop with sensible defaults * * @deprecated Phase C Week 2 — `createAgenticLoop` has zero production * callers in primitives.org.ai (only `ai-primitives` umbrella re-export * tests). Use AI SDK 6's `Agent` / `ToolLoopAgent` with * `stopWhen: stepCountIs(N)` instead. Will be removed alongside * `AgenticLoop` in the Phase C semver bump. See `bd show aip-ibid`. */ export declare function createAgenticLoop(options: Partial<LoopOptions> & { tools: Tool[]; }): AgenticLoop; //# sourceMappingURL=tool-orchestration.d.ts.map