UNPKG

@continue-reasoning/mini-agent

Version:

A platform-agnostic AI agent framework for building autonomous AI agents with tool execution capabilities

657 lines 20.3 kB
/** * @fileoverview Universal AI Agent Framework Interfaces * * This file defines platform-agnostic interfaces for AI agents that can work * with multiple LLM providers (Gemini, OpenAI, etc.). All interfaces are * designed to be implementation-independent and focus on core functionality. */ import { ILogger, LogLevel } from './logger'; import type { ContentPart, MessageItem, FunctionCallStr, LLMStart, LLMChunk, LLMChunkTextDelta, LLMChunkTextDone, LLMChunkThinking, LLMFunctionCallDone, LLMFunctionCallDelta, ChunkItem, LLMComplete, LLMResponse, ToolDeclaration, IChatConfig, IChat, ITokenUsage, ITokenTracker } from './chat/interfaces.js'; export { ContentPart, MessageItem, FunctionCallStr, LLMStart, LLMChunk, LLMChunkTextDelta, LLMChunkTextDone, LLMChunkThinking, LLMFunctionCallDone, LLMFunctionCallDelta, ChunkItem, LLMComplete, LLMResponse, ToolDeclaration, IChatConfig, IChat, ITokenUsage, ITokenTracker, }; /** * File diff information for tool results */ export interface FileDiff { /** File diff content */ fileDiff: string; /** File name */ fileName: string; } /** * Tool result display type - can be string or file diff */ export type ToolResultDisplay = string | FileDiff; /** * Tool execution result - compatible with core package ToolResult */ export interface ToolResult { /** * A short, one-line summary of the tool's action and result. * e.g., "Read 5 files", "Wrote 256 bytes to foo.txt" */ summary?: string; /** * Content meant to be included in LLM history. * This should represent the factual outcome of the tool execution. * Platform-agnostic version - can be string or ContentPart array */ llmContent: string | ContentPart[]; /** * Display content for user interface. * This provides a user-friendly summary or visualization of the result. */ returnDisplay: ToolResultDisplay; } /** * Tool confirmation payload for modifications */ export interface ToolConfirmationPayload { /** New content to override proposed content */ newContent: string; } /** * Tool confirmation outcome options */ export declare enum ToolConfirmationOutcome { ProceedOnce = "proceed_once", ProceedAlways = "proceed_always", ProceedAlwaysServer = "proceed_always_server", ProceedAlwaysTool = "proceed_always_tool", ModifyWithEditor = "modify_with_editor", Cancel = "cancel" } /** * Edit confirmation details */ export interface ToolEditConfirmationDetails { type: 'edit'; title: string; onConfirm: (outcome: ToolConfirmationOutcome, payload?: ToolConfirmationPayload) => Promise<void>; fileName: string; fileDiff: string; isModifying?: boolean; } /** * Execute confirmation details */ export interface ToolExecuteConfirmationDetails { type: 'exec'; title: string; onConfirm: (outcome: ToolConfirmationOutcome) => Promise<void>; command: string; rootCommand: string; } /** * MCP confirmation details */ export interface ToolMcpConfirmationDetails { type: 'mcp'; title: string; serverName: string; toolName: string; toolDisplayName: string; onConfirm: (outcome: ToolConfirmationOutcome) => Promise<void>; } /** * Info confirmation details */ export interface ToolInfoConfirmationDetails { type: 'info'; title: string; onConfirm: (outcome: ToolConfirmationOutcome) => Promise<void>; prompt: string; urls?: string[]; } /** * Tool call confirmation details - union type compatible with core package */ export type ToolCallConfirmationDetails = ToolEditConfirmationDetails | ToolExecuteConfirmationDetails | ToolMcpConfirmationDetails | ToolInfoConfirmationDetails; /** * Core tool interface with generic parameters and result types * This interface is designed to be compatible with core package tools * while remaining platform-agnostic */ export interface ITool<TParams = unknown, TResult extends ToolResult = ToolResult> { /** Tool name */ name: string; /** Tool description */ description: string; /** Tool schema */ schema: ToolDeclaration; /** Whether output is markdown */ isOutputMarkdown: boolean; /** Whether tool supports streaming output */ canUpdateOutput: boolean; /** * Validate tool parameters * Should be called from both shouldConfirmExecute and execute * shouldConfirmExecute should return false immediately if invalid * @param params Parameters to validate * @returns Error message if invalid, null if valid */ validateToolParams(params: TParams): string | null; /** * Get tool description for given parameters * @param params Tool parameters * @returns Description of what tool will do */ getDescription(params: TParams): string; /** * Check if tool requires confirmation before execution * @param params Tool parameters * @param abortSignal Abort signal * @returns Confirmation details or false */ shouldConfirmExecute(params: TParams, abortSignal: AbortSignal): Promise<ToolCallConfirmationDetails | false>; /** * Execute the tool * @param params Tool parameters * @param signal Abort signal * @param updateOutput Callback for streaming output * @returns Tool result */ execute(params: TParams, signal: AbortSignal, updateOutput?: (output: string) => void): Promise<TResult>; } /** * Chat message parameters */ export interface ChatMessage { /** Message content */ content: string | ContentPart[]; /** Additional configuration */ config?: Record<string, unknown>; } /** * Tool call request information */ export interface ToolCallRequest { /** Call ID */ callId: string; /** Tool name */ name: string; /** Tool arguments */ args: Record<string, unknown>; /** Whether initiated by client */ isClientInitiated: boolean; /** Prompt ID */ promptId: string; } /** * Tool call response information */ export interface ToolCallResponse { /** Call ID */ callId: string; /** Response content */ content: ContentPart[]; /** Display content */ display?: string; /** Error if any */ error?: string; } /** * Agent event types - based on IChat LLMResponse events + tool execution events * * DESIGN PRINCIPLE: Maximize reuse of IChat's LLMResponse event stream. * We only add agent-specific events for tool execution and user interactions. * * Base events from LLMResponse: * - response.start, response.chunk.*, response.complete, response.failed, response.incomplete * * Agent-specific events: * - user.message: User input events * - tool.call.execution.*: Tool execution lifecycle * - agent.*: Agent-level events (errors, cancellation) */ export declare enum AgentEventType { UserMessage = "user.message", UserCancelled = "user.cancelled", ResponseStart = "response.start", ResponseChunkTextDelta = "response.chunk.text.delta", ResponseChunkTextDone = "response.chunk.text.done", ResponseChunkThinkingDelta = "response.chunk.thinking.delta", ResponseChunkThinkingDone = "response.chunk.thinking.done", ResponseChunkFunctionCallDelta = "response.chunk.function_call.delta", ResponseChunkFunctionCallDone = "response.chunk.function_call.done", ResponseComplete = "response.complete", ResponseIncomplete = "response.incomplete", ResponseFailed = "response.failed", ToolExecutionStart = "tool.call.execution.start", ToolExecutionDone = "tool.call.execution.done", ToolConfirmation = "tool.confirmation", TurnComplete = "turn.complete", Error = "agent.error", ModelFallback = "agent.model_fallback" } /** * Base agent event */ export interface AgentEvent { /** Event type */ type: AgentEventType; /** Event data */ data?: unknown; /** Event timestamp */ timestamp: number; /** Event metadata */ metadata?: Record<string, unknown>; } /** * LLM Response Agent Event - directly wraps LLMResponse * * This event type allows us to forward LLMResponse events directly * as AgentEvents without data transformation. */ export interface LLMResponseAgentEvent extends AgentEvent { /** Session ID for this conversation */ sessionId: string; /** Turn number */ turn: number; } /** * Tool execution events - Agent-specific */ export interface ToolExecutionStartEvent extends AgentEvent { type: AgentEventType.ToolExecutionStart; data: { toolName: string; callId: string; args: Record<string, unknown>; sessionId: string; turn: number; }; } export interface ToolExecutionDoneEvent extends AgentEvent { type: AgentEventType.ToolExecutionDone; data: { toolName: string; callId: string; result?: unknown; error?: string; duration?: number; sessionId: string; turn: number; }; } /** * Utility function to create AgentEvent from LLMResponse * * This is the core function that maps LLMResponse events to AgentEvents, * maintaining the event stream consistency between IChat and IAgent layers. */ export declare function createAgentEventFromLLMResponse(llmResponse: LLMResponse, sessionId: string, turn: number): LLMResponseAgentEvent; /** * Tool call request information - compatible with core package */ export interface IToolCallRequestInfo { /** Unique call identifier (call_ prefix) */ callId: string; /** Function call identifier (fc_ prefix, used for OpenAI function responses) */ functionId?: string; /** Tool name */ name: string; /** Tool arguments */ args: Record<string, unknown>; /** Whether initiated by client */ isClientInitiated: boolean; /** Associated prompt ID */ promptId: string; } /** * Tool call response information - compatible with core package */ export interface IToolCallResponseInfo { /** Call identifier */ callId: string; /** Response parts in Gemini format */ responseParts: unknown; /** Display content for UI */ resultDisplay?: string | FileDiff; /** Error if execution failed */ error?: Error; } /** * Tool call execution states */ export declare enum ToolCallStatus { Validating = "validating", Scheduled = "scheduled", Executing = "executing", Success = "success", Error = "error", Cancelled = "cancelled", AwaitingApproval = "awaiting_approval" } /** * Base tool call interface */ export interface IBaseToolCall { /** Current status */ status: ToolCallStatus; /** Request information */ request: IToolCallRequestInfo; /** Start time */ startTime?: number; /** Confirmation outcome */ outcome?: ToolConfirmationOutcome; } /** * Validating tool call */ export interface IValidatingToolCall extends IBaseToolCall { status: ToolCallStatus.Validating; tool: ITool; } /** * Scheduled tool call */ export interface IScheduledToolCall extends IBaseToolCall { status: ToolCallStatus.Scheduled; tool: ITool; } /** * Executing tool call */ export interface IExecutingToolCall extends IBaseToolCall { status: ToolCallStatus.Executing; tool: ITool; liveOutput?: string; } /** * Successful tool call */ export interface ISuccessfulToolCall extends IBaseToolCall { status: ToolCallStatus.Success; tool: ITool; response: IToolCallResponseInfo; durationMs?: number; } /** * Errored tool call */ export interface IErroredToolCall extends IBaseToolCall { status: ToolCallStatus.Error; response: IToolCallResponseInfo; durationMs?: number; } /** * Cancelled tool call */ export interface ICancelledToolCall extends IBaseToolCall { status: ToolCallStatus.Cancelled; tool: ITool; response: IToolCallResponseInfo; durationMs?: number; } /** * Waiting for approval tool call */ export interface IWaitingToolCall extends IBaseToolCall { status: ToolCallStatus.AwaitingApproval; tool: ITool; confirmationDetails: ToolCallConfirmationDetails; } /** * Union type for all tool call states */ export type IToolCall = IValidatingToolCall | IScheduledToolCall | IExecutingToolCall | ISuccessfulToolCall | IErroredToolCall | ICancelledToolCall | IWaitingToolCall; /** * Completed tool call types */ export type ICompletedToolCall = ISuccessfulToolCall | IErroredToolCall | ICancelledToolCall; /** * Handler for tool call confirmation */ export type IConfirmHandler = (toolCall: IWaitingToolCall) => Promise<ToolConfirmationOutcome>; /** * Handler for output updates during tool execution */ export type IOutputUpdateHandler = (toolCallId: string, outputChunk: string) => void; /** * Handler called when all tool calls complete */ export type IAllToolCallsCompleteHandler = (completedToolCalls: ICompletedToolCall[]) => void; /** * Handler for tool call status updates */ export type IToolCallsUpdateHandler = (toolCalls: IToolCall[]) => void; /** * Tool scheduler configuration */ export interface IToolSchedulerConfig { tools?: ITool[]; /** Output update handler */ outputUpdateHandler?: IOutputUpdateHandler; /** Completion handler */ onAllToolCallsComplete?: IAllToolCallsCompleteHandler; /** Update handler */ onToolCallsUpdate?: IToolCallsUpdateHandler; /** Approval mode */ approvalMode?: 'default' | 'yolo' | 'always'; /** Editor preference getter */ getPreferredEditor?: () => string | undefined; /** Configuration object */ config?: unknown; } /** * Core tool scheduler interface - tool scheduler interface * * This interface defines core tool scheduling functionality including: * - Tool call scheduling and execution * - State tracking and management * - Confirmation and approval workflows * - Error handling and retry logic * * Implementation references the core package's CoreToolScheduler but uses our own type system */ /** * Tool execution lifecycle callbacks */ export type ToolExecutionStartCallback = (toolCall: IToolCallRequestInfo) => void; export type ToolExecutionDoneCallback = (request: IToolCallRequestInfo, response: IToolCallResponseInfo, duration?: number) => void; export interface IToolScheduler { /** * Schedule tool call(s) for execution * @param request Tool call request(s) * @param signal Abort signal * @param callbacks Optional callbacks for tool execution lifecycle */ schedule(request: IToolCallRequestInfo | IToolCallRequestInfo[], signal: AbortSignal, callbacks?: { onExecutionStart?: ToolExecutionStartCallback; onExecutionDone?: ToolExecutionDoneCallback; }): Promise<void>; /** * Handle confirmation response * @param callId Call identifier * @param outcome Confirmation outcome * @param payload Optional payload for modifications */ handleConfirmationResponse(callId: string, outcome: ToolConfirmationOutcome, payload?: ToolConfirmationPayload): Promise<void>; registerTool(tool: ITool): void; removeTool(toolName: string): boolean; getTool(name: string): ITool | undefined; getToolList(): ITool[]; /** * Get current tool calls * @returns Array of current tool calls */ getCurrentToolCalls(): IToolCall[]; /** * Check if scheduler is currently running * @returns True if running */ isRunning(): boolean; /** * Cancel all pending tool calls * @param reason Cancellation reason */ cancelAll(reason: string): void; } /** * Agent configuration */ export interface AllConfig { agentConfig: IAgentConfig; /** Tool scheduler configuration */ toolSchedulerConfig: Omit<IToolSchedulerConfig, 'tools'>; chatConfig: Omit<IChatConfig, 'toolDeclarations'>; } /** * Agent configuration */ export interface IAgentConfig { /** The AI model to use */ model: string; /** Working directory for file operations */ workingDirectory: string; /** API key for authentication */ apiKey?: string; /** Default session identifier */ sessionId?: string; /** Maximum number of history records to keep */ maxHistorySize?: number; /** Maximum number of tokens to include in history */ maxHistoryTokens?: number; /** Enable debug mode */ debugMode?: boolean; /** Logger instance for this agent */ logger?: ILogger; /** Log level for this agent */ logLevel?: LogLevel; } /** * Agent status */ export interface IAgentStatus { /** Whether agent is running */ isRunning: boolean; /** Current turn number */ currentTurn: number; /** History size */ historySize: number; /** Configuration */ config: IAgentConfig; /** Last update time */ lastUpdateTime: number; /** Current token usage */ tokenUsage: ITokenUsage; /** Model information */ modelInfo: { model: string; tokenLimit: number; }; } /** * Event handler type */ export type EventHandler = (event: AgentEvent) => void; /** * Core Agent interface */ export interface IAgent { /** * Process user input with streaming responses * @param userInput User input text * @param sessionId Session identifier * @param abortSignal Abort signal * @returns AsyncGenerator yielding agent events */ process(userInput: string, sessionId: string, abortSignal: AbortSignal): AsyncGenerator<AgentEvent>; /** * Process one turn of conversation * @param sessionId - Unique identifier for this conversation session * @param chatMessage - The chat message to process * @param abortSignal - Signal to abort the processing if needed * @returns AsyncGenerator that yields AgentEvent objects */ processOneTurn(sessionId: string, chatMessage: MessageItem, abortSignal: AbortSignal): AsyncGenerator<AgentEvent>; /** * Get the underlying chat instance * @returns Chat instance */ getChat(): IChat<any>; /** * Get list of tools * @returns List of tools */ getToolList(): ITool[]; getTool(toolName: string): ITool | undefined; registerTool(tool: ITool): void; removeTool(toolName: string): boolean; /** * Get the tool scheduler instance * @returns Tool scheduler instance */ getToolScheduler(): IToolScheduler; /** * Get current token usage * @returns Token usage information */ getTokenUsage(): ITokenUsage; /** * Clear conversation history */ clearHistory(): void; /** * Set system prompt * @param systemPrompt System prompt text */ setSystemPrompt(systemPrompt: string): void; /** * Get current system prompt * @returns Current system prompt */ getSystemPrompt(): string | undefined; /** * Get current status * @returns Agent status */ getStatus(): IAgentStatus; /** * Register event handler * @param id Handler ID * @param handler Event handler */ onEvent(id: string, handler: EventHandler): void; /** * Remove event handler * @param id Handler ID */ offEvent(id: string): void; } /** * Agent factory interface */ export interface IAgentFactory { /** * Create new agent instance * @param config Agent configuration * @returns Promise resolving to agent instance */ createAgent(config: IAgentConfig): Promise<IAgent>; /** * Create simple agent with minimal configuration * @param model Model name * @param workingDirectory Working directory * @param systemPrompt Optional system prompt * @returns Promise resolving to agent instance */ createSimpleAgent(model: string, workingDirectory: string, systemPrompt?: string): Promise<IAgent>; } /** * Partial agent configuration type */ export type PartialAgentConfig = Partial<IAgentConfig> & Pick<IAgentConfig, 'model' | 'workingDirectory'>; /** * Type guard for IAgent */ export declare function isAgent(obj: unknown): obj is IAgent; /** * Type guard for IChat */ export declare function isChat(obj: unknown): obj is IChat<any>; /** * Type guard for ITool */ export declare function isTool(obj: unknown): obj is ITool; //# sourceMappingURL=interfaces.d.ts.map