import type { AudioFrame } from '@livekit/rtc-node';
import type { ReadableStream } from 'stream/web';
import type { Instructions } from '../llm/chat_context.js';
import { type ChatContext, FunctionCall, FunctionCallOutput } from '../llm/chat_context.js';
import { type ToolChoice, type ToolContext } from '../llm/tool_context.js';
import { type FlushSentinel } from '../types.js';
import { Future, Task } from '../utils.js';
import { type Agent, type ModelSettings } from './agent.js';
import type { AgentSession } from './agent_session.js';
import { AudioOutput, type LLMNode, type TTSNode, type TextOutput, type TimedString } from './io.js';
import type { SpeechHandle } from './speech_handle.js';
import { type TextTransform } from './transcription/text_transforms.js';
export declare const DEFAULT_TTS_READ_IDLE_TIMEOUT_MS = 10000;
export declare const DEFAULT_FORWARD_AUDIO_IDLE_TIMEOUT_MS = 10000;
/** @internal */
export declare class _LLMGenerationData {
    readonly textStream: ReadableStream<string | FlushSentinel>;
    readonly toolCallStream: ReadableStream<FunctionCall>;
    generatedText: string;
    generatedToolCalls: FunctionCall[];
    generatedExtra: Record<string, unknown>;
    id: string;
    ttft?: number;
    constructor(textStream: ReadableStream<string | FlushSentinel>, toolCallStream: ReadableStream<FunctionCall>);
}
/**
 * TTS generation data containing audio stream and optional timed transcripts.
 * @internal
 */
export interface _TTSGenerationData {
    /** Audio frame stream from TTS */
    audioStream: ReadableStream<AudioFrame>;
    /**
     * Future that resolves to a stream of timed transcripts, or null if TTS doesn't support it.
     */
    timedTextsFut: Future<ReadableStream<TimedString> | null, never>;
    /** Time to first byte (set when first audio frame is received) */
    ttfb?: number;
}
export declare class _ToolOutput {
    output: _JsOutput[];
    firstToolFut: Future;
    constructor();
}
export declare class _SanitizedOutput {
    toolCall: FunctionCall;
    toolCallOutput?: FunctionCallOutput;
    replyRequired: boolean;
    agentTask?: Agent;
    constructor(toolCall: FunctionCall, toolCallOutput: FunctionCallOutput | undefined, replyRequired: boolean, agentTask: Agent | undefined);
    static create(params: {
        toolCall: FunctionCall;
        toolCallOutput?: FunctionCallOutput;
        replyRequired?: boolean;
        agentTask?: Agent;
    }): _SanitizedOutput;
}
export declare class ToolExecutionOutput {
    readonly toolCall: FunctionCall;
    readonly toolCallOutput: FunctionCallOutput | undefined;
    readonly agentTask: Agent | undefined;
    readonly rawOutput: unknown;
    readonly rawException: Error | undefined;
    readonly replyRequired: boolean;
    constructor(toolCall: FunctionCall, toolCallOutput: FunctionCallOutput | undefined, agentTask: Agent | undefined, rawOutput: unknown, rawException: Error | undefined, replyRequired: boolean);
    static create(params: {
        toolCall: FunctionCall;
        toolCallOutput?: FunctionCallOutput;
        agentTask?: Agent;
        rawOutput: unknown;
        rawException?: Error;
        replyRequired?: boolean;
    }): ToolExecutionOutput;
}
export interface ToolOutput {
    output: ToolExecutionOutput[];
    firstToolStartedFuture: Future<void>;
}
export declare class _JsOutput {
    #private;
    toolCall: FunctionCall;
    output: unknown;
    exception?: Error;
    constructor(toolCall: FunctionCall, output: unknown, exception: Error | undefined);
    static create(params: {
        toolCall: FunctionCall;
        output?: unknown;
        exception?: Error;
    }): _JsOutput;
    sanitize(): _SanitizedOutput;
}
export declare function createToolOutput(params: {
    toolCall: FunctionCall;
    output?: unknown;
    exception?: Error;
}): ToolExecutionOutput;
export declare const INSTRUCTIONS_MESSAGE_ID = "lk.agent_task.instructions";
/**
 * Update the instruction message in the chat context or insert a new one if missing.
 *
 * This function looks for an existing instruction message in the chat context using the identifier
 * 'INSTRUCTIONS_MESSAGE_ID'.
 *
 * @param options - The options for updating the instructions.
 * @param options.chatCtx - The chat context to update.
 * @param options.instructions - The instructions to add.
 * @param options.addIfMissing - Whether to add the instructions if they are missing.
 */
export declare function updateInstructions(options: {
    chatCtx: ChatContext;
    instructions: string | Instructions;
    addIfMissing: boolean;
}): void;
/**
 * Apply the correct {@link Instructions} variant for the turn's input modality.
 *
 * Locates the instructions message (by {@link INSTRUCTIONS_MESSAGE_ID}) and,
 * if its content contains any {@link Instructions} entries, rebuilds the
 * message so each Instructions renders as the chosen variant. No-op when no
 * modality-aware instructions are present.
 */
export declare function applyInstructionsModality(chatCtx: ChatContext, options: {
    modality: 'audio' | 'text';
}): void;
export declare function performLLMInference(node: LLMNode, chatCtx: ChatContext, toolCtx: ToolContext, modelSettings: ModelSettings, controller: AbortController, model?: string, provider?: string): [Task<void>, _LLMGenerationData];
export declare function performTTSInference(node: TTSNode, text: ReadableStream<string | TimedString>, modelSettings: ModelSettings, controller: AbortController, model?: string, provider?: string, readIdleTimeout?: number, textTransforms?: readonly TextTransform[] | null): [Task<void>, _TTSGenerationData];
export interface _TextOut {
    text: string;
    firstTextFut: Future;
}
export declare function performTextForwarding(source: ReadableStream<string | TimedString>, controller: AbortController, textOutput: TextOutput | null): [Task<void>, _TextOut];
export interface _AudioOut {
    audio: Array<AudioFrame>;
    firstFrameFut: Future<number>;
    /**
     * Timestamp (ms, `Date.now()`) when the first audio frame was forwarded to the
     * `AudioOutput`. Set by `forwardAudio` as soon as the first TTS frame is
     * appended; remains `undefined` until then. Used together with the playback-started
     * timestamp from `firstFrameFut` to derive the assistant's `playbackLatency`
     * metric.
     */
    startedForwardingAt?: number;
}
export declare function performAudioForwarding(ttsStream: ReadableStream<AudioFrame>, audioOutput: AudioOutput, controller: AbortController, idleTimeout?: number): [Task<void>, _AudioOut];
export declare function performToolExecutions({ session, speechHandle, toolCtx, toolChoice, toolCallStream, onToolExecutionStarted, onToolExecutionCompleted, controller, }: {
    session: AgentSession;
    speechHandle: SpeechHandle;
    toolCtx: ToolContext;
    toolChoice?: ToolChoice;
    toolCallStream: ReadableStream<FunctionCall>;
    onToolExecutionStarted?: (toolCall: FunctionCall) => void;
    onToolExecutionCompleted?: (toolExecutionOutput: ToolExecutionOutput) => void;
    controller: AbortController;
}): [Task<void>, ToolOutput];
export declare function removeInstructions(chatCtx: ChatContext): void;
//# sourceMappingURL=generation.d.ts.map