import { ChunkRecording, ChunkStrategy, ProcessorResult, ProcessorState, ToolCallState } from './types.js';
import { ContentPart, ModelMessage, StreamChunk, UIMessage } from '../../../types.js';
/**
 * Events emitted by the StreamProcessor
 */
export interface StreamProcessorEvents {
    onMessagesChange?: (messages: Array<UIMessage>) => void;
    onStreamStart?: () => void;
    onStreamEnd?: (message: UIMessage) => void;
    onError?: (error: Error) => void;
    onToolCall?: (args: {
        toolCallId: string;
        toolName: string;
        input: any;
    }) => void;
    onApprovalRequest?: (args: {
        toolCallId: string;
        toolName: string;
        input: any;
        approvalId: string;
    }) => void;
    onCustomEvent?: (eventType: string, data: unknown, context: {
        toolCallId?: string;
    }) => void;
    onTextUpdate?: (messageId: string, content: string) => void;
    onToolCallStateChange?: (messageId: string, toolCallId: string, state: ToolCallState, args: string) => void;
    onThinkingUpdate?: (messageId: string, content: string) => void;
}
/**
 * Options for StreamProcessor
 */
export interface StreamProcessorOptions {
    chunkStrategy?: ChunkStrategy;
    /** Event-driven handlers */
    events?: StreamProcessorEvents;
    jsonParser?: {
        parse: (jsonString: string) => any;
    };
    /** Enable recording for replay testing */
    recording?: boolean;
    /** Initial messages to populate the processor */
    initialMessages?: Array<UIMessage>;
}
/**
 * StreamProcessor - State machine for processing AI response streams
 *
 * Manages the full UIMessage[] conversation and emits events on changes.
 * Trusts the adapter contract: adapters emit clean AG-UI events in the
 * correct order.
 *
 * State tracking:
 * - Full message array
 * - Per-message stream state (text, tool calls, thinking)
 * - Multiple concurrent message streams
 * - Tool call completion via TOOL_CALL_END events
 *
 * @see docs/chat-architecture.md#streamprocessor-internal-state — State field reference
 * @see docs/chat-architecture.md#adapter-contract — What this class expects from adapters
 */
export declare class StreamProcessor {
    private chunkStrategy;
    private events;
    private jsonParser;
    private recordingEnabled;
    private messages;
    private messageStates;
    private activeMessageIds;
    private toolCallToMessage;
    private pendingManualMessageId;
    private activeRuns;
    private finishReason;
    private hasError;
    private isDone;
    private recording;
    private recordingStartTime;
    constructor(options?: StreamProcessorOptions);
    /**
     * Set the messages array (e.g., from persisted state)
     */
    setMessages(messages: Array<UIMessage>): void;
    /**
     * Add a user message to the conversation.
     * Supports both simple string content and multimodal content arrays.
     *
     * @param content - The message content (string or array of content parts)
     * @param id - Optional custom message ID (generated if not provided)
     * @returns The created UIMessage
     *
     * @example
     * ```ts
     * // Simple text message
     * processor.addUserMessage('Hello!')
     *
     * // Multimodal message with image
     * processor.addUserMessage([
     *   { type: 'text', content: 'What is in this image?' },
     *   { type: 'image', source: { type: 'url', value: 'https://example.com/photo.jpg' } }
     * ])
     *
     * // With custom ID
     * processor.addUserMessage('Hello!', 'custom-id-123')
     * ```
     */
    addUserMessage(content: string | Array<ContentPart>, id?: string): UIMessage;
    /**
     * Prepare for a new assistant message stream.
     * Does NOT create the message immediately -- the message is created lazily
     * when the first content-bearing chunk arrives via ensureAssistantMessage().
     * This prevents empty assistant messages from flickering in the UI when
     * auto-continuation produces no content.
     */
    prepareAssistantMessage(): void;
    /**
     * @deprecated Use prepareAssistantMessage() instead. This eagerly creates
     * an assistant message which can cause empty message flicker.
     */
    startAssistantMessage(messageId?: string): string;
    /**
     * Get the current assistant message ID (if one has been created).
     * Returns null if prepareAssistantMessage() was called but no content
     * has arrived yet.
     */
    getCurrentAssistantMessageId(): string | null;
    /**
     * Add a tool result (called by client after handling onToolCall)
     */
    addToolResult(toolCallId: string, output: any, error?: string): void;
    /**
     * Add an approval response (called by client after handling onApprovalRequest)
     */
    addToolApprovalResponse(approvalId: string, approved: boolean): void;
    /**
     * Get the conversation as ModelMessages (for sending to LLM)
     */
    toModelMessages(): Array<ModelMessage>;
    /**
     * Get current messages
     */
    getMessages(): Array<UIMessage>;
    /**
     * Check if all tool calls in the last assistant message are complete
     * Useful for auto-continue logic
     */
    areAllToolsComplete(): boolean;
    /**
     * Remove messages after a certain index (for reload/retry)
     */
    removeMessagesAfter(index: number): void;
    /**
     * Clear all messages
     */
    clearMessages(): void;
    /**
     * Process a stream and emit events through handlers
     */
    process(stream: AsyncIterable<any>): Promise<ProcessorResult>;
    /**
     * Process a single chunk from the stream.
     *
     * Central dispatch for all AG-UI events. Each event type maps to a specific
     * handler. Events not listed in the switch are intentionally ignored
     * (RUN_STARTED, STEP_STARTED, STATE_DELTA).
     *
     * @see docs/chat-architecture.md#adapter-contract — Expected event types and ordering
     */
    processChunk(chunk: StreamChunk): void;
    /**
     * Create a new MessageStreamState for a message
     */
    private createMessageState;
    /**
     * Get the MessageStreamState for a message
     */
    private getMessageState;
    /**
     * Get the most recent active assistant message ID.
     * Used as fallback for events that don't include a messageId.
     */
    private getActiveAssistantMessageId;
    /**
     * Ensure an active assistant message exists, creating one if needed.
     * Used for backward compat when events arrive without prior TEXT_MESSAGE_START.
     *
     * On reconnect/resume, a TEXT_MESSAGE_CONTENT may arrive for a message that
     * already exists in this.messages (e.g. from initialMessages or a prior
     * MESSAGES_SNAPSHOT) but whose transient state was cleared. In that case we
     * hydrate state from the existing message rather than creating a duplicate.
     */
    private ensureAssistantMessage;
    /**
     * Handle TEXT_MESSAGE_START event
     */
    private handleTextMessageStartEvent;
    /**
     * Handle TEXT_MESSAGE_END event
     */
    private handleTextMessageEndEvent;
    /**
     * Handle MESSAGES_SNAPSHOT event
     */
    private handleMessagesSnapshotEvent;
    /**
     * Handle TEXT_MESSAGE_CONTENT event.
     *
     * Accumulates delta into both currentSegmentText (for UI emission) and
     * totalTextContent (for ProcessorResult). Lazily creates the assistant
     * UIMessage on first content. Uses updateTextPart() which replaces the
     * last TextPart or creates a new one depending on part ordering.
     *
     * @see docs/chat-architecture.md#single-shot-text-response — Text accumulation step-by-step
     * @see docs/chat-architecture.md#uimessage-part-ordering-invariants — Replace vs. push logic
     */
    private handleTextMessageContentEvent;
    /**
     * Handle TOOL_CALL_START event.
     *
     * Creates a new InternalToolCallState entry in the toolCalls Map and appends
     * a ToolCallPart to the UIMessage. Duplicate toolCallId is a no-op.
     *
     * CRITICAL: This MUST be received before any TOOL_CALL_ARGS for the same
     * toolCallId. Args for unknown IDs are silently dropped.
     *
     * @see docs/chat-architecture.md#single-shot-tool-call-response — Tool call state transitions
     * @see docs/chat-architecture.md#parallel-tool-calls-single-shot — Parallel tracking by ID
     * @see docs/chat-architecture.md#adapter-contract — Ordering requirements
     */
    private handleToolCallStartEvent;
    /**
     * Handle TOOL_CALL_ARGS event.
     *
     * Appends the delta to the tool call's accumulated arguments string.
     * Transitions state from awaiting-input → input-streaming on first non-empty delta.
     * Attempts partial JSON parse on each update for UI preview.
     *
     * If toolCallId is not found in the Map (no preceding TOOL_CALL_START),
     * this event is silently dropped.
     *
     * @see docs/chat-architecture.md#single-shot-tool-call-response — Step-by-step tool call processing
     */
    private handleToolCallArgsEvent;
    /**
     * Handle TOOL_CALL_END event — authoritative signal that a tool call's input is finalized.
     *
     * This event has a DUAL ROLE:
     * - Without `result`: Signals arguments are done (from adapter). Transitions to input-complete.
     * - With `result`: Signals tool was executed and result is available (from TextEngine).
     *   Creates both output on the tool-call part AND a tool-result part.
     *
     * If `input` is provided, it overrides the accumulated string parse as the
     * canonical parsed arguments.
     *
     * @see docs/chat-architecture.md#tool-results-and-the-tool_call_end-dual-role — Full explanation
     * @see docs/chat-architecture.md#single-shot-tool-call-response — End-to-end flow
     */
    private handleToolCallEndEvent;
    /**
     * Handle RUN_STARTED event.
     *
     * Registers the run so that RUN_FINISHED can determine whether other
     * runs are still active before finalizing.
     */
    private handleRunStartedEvent;
    /**
     * Handle RUN_FINISHED event.
     *
     * Records the finishReason and removes the run from activeRuns.
     * Only finalizes when no more runs are active, so that concurrent
     * runs don't interfere with each other.
     *
     * @see docs/chat-architecture.md#single-shot-tool-call-response — finishReason semantics
     * @see docs/chat-architecture.md#adapter-contract — Why RUN_FINISHED is mandatory
     */
    private handleRunFinishedEvent;
    /**
     * Handle RUN_ERROR event
     */
    private handleRunErrorEvent;
    /**
     * Handle STEP_FINISHED event (for thinking/reasoning content).
     *
     * Accumulates delta into thinkingContent and updates a single ThinkingPart
     * in the UIMessage (replaced in-place, not appended).
     *
     * @see docs/chat-architecture.md#thinkingreasoning-content — Thinking flow
     */
    private handleStepFinishedEvent;
    /**
     * Handle CUSTOM event.
     *
     * Handles special custom events emitted by the TextEngine (not adapters):
     * - 'tool-input-available': Client tool needs execution. Fires onToolCall.
     * - 'approval-requested': Tool needs user approval. Updates tool-call part
     *   state and fires onApprovalRequest.
     *
     * @see docs/chat-architecture.md#client-tools-and-approval-flows — Full flow details
     */
    private handleCustomEvent;
    /**
     * Detect if an incoming content chunk represents a NEW text segment
     */
    private isNewTextSegment;
    /**
     * Complete all tool calls across all active messages — safety net for stream termination.
     *
     * Called by RUN_FINISHED and finalizeStream(). Force-transitions any tool call
     * not yet in input-complete state. Handles cases where TOOL_CALL_END was
     * missed (adapter bug, network error, aborted stream).
     *
     * @see docs/chat-architecture.md#single-shot-tool-call-response — Safety net behavior
     */
    private completeAllToolCalls;
    /**
     * Complete all tool calls for a specific message
     */
    private completeAllToolCallsForMessage;
    /**
     * Mark a tool call as complete and emit event
     */
    private completeToolCall;
    /**
     * Emit pending text update for a specific message.
     *
     * Calls updateTextPart() which has critical append-vs-replace logic:
     * - If last UIMessage part is TextPart → replaces its content (same segment).
     * - If last part is anything else → pushes new TextPart (new segment after tools).
     *
     * @see docs/chat-architecture.md#uimessage-part-ordering-invariants — Replace vs. push logic
     */
    private emitTextUpdateForMessage;
    /**
     * Emit messages change event
     */
    private emitMessagesChange;
    /**
     * Finalize the stream — complete all pending operations.
     *
     * Called when the async iterable ends (stream closed). Acts as the final
     * safety net: completes any remaining tool calls, flushes un-emitted text,
     * and fires onStreamEnd.
     *
     * @see docs/chat-architecture.md#single-shot-text-response — Finalization step
     */
    finalizeStream(): void;
    /**
     * Get completed tool calls in API format (aggregated across all messages)
     */
    private getCompletedToolCalls;
    /**
     * Get current result (aggregated across all messages)
     */
    private getResult;
    /**
     * Get current processor state (aggregated across all messages)
     */
    getState(): ProcessorState;
    /**
     * Start recording chunks
     */
    startRecording(): void;
    /**
     * Get the current recording
     */
    getRecording(): ChunkRecording | null;
    /**
     * Reset stream state (but keep messages)
     */
    private resetStreamState;
    /**
     * Full reset (including messages)
     */
    reset(): void;
    /**
     * Check if a message contains only whitespace text and no other meaningful parts
     * (no tool calls, tool results, thinking, etc.)
     */
    private isWhitespaceOnlyMessage;
    /**
     * Replay a recording through the processor
     */
    static replay(recording: ChunkRecording, options?: StreamProcessorOptions): Promise<ProcessorResult>;
}
/**
 * Create an async iterable from a recording
 */
export declare function createReplayStream(recording: ChunkRecording): AsyncIterable<StreamChunk>;
