import type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';
import type { LLMMetrics } from '../metrics/base.js';
import { type APIConnectOptions } from '../types.js';
import { AsyncIterableQueue } from '../utils.js';
import { type ChatContext, type ChatRole, type FunctionCall } from './chat_context.js';
import { type ToolChoice, type ToolContext, type ToolContextLike } from './tool_context.js';
export interface ChoiceDelta {
    role: ChatRole;
    content?: string;
    toolCalls?: FunctionCall[];
    extra?: Record<string, unknown>;
}
export interface CompletionUsage {
    completionTokens: number;
    promptTokens: number;
    promptCachedTokens: number;
    totalTokens: number;
    /** The service tier used for processing (e.g. 'default', 'priority', 'flex'). */
    serviceTier?: string;
}
export interface ChatChunk {
    id: string;
    delta?: ChoiceDelta;
    usage?: CompletionUsage;
}
export interface CollectedResponse {
    text: string;
    toolCalls: FunctionCall[];
    usage?: CompletionUsage;
    /**
     * Provider-specific extra data accumulated across chunks
     * (e.g., xAI encrypted reasoning, Google thought signatures).
     */
    extra: Record<string, unknown>;
}
export interface LLMError {
    type: 'llm_error';
    timestamp: number;
    label: string;
    error: Error;
    recoverable: boolean;
}
export type LLMCallbacks = {
    ['metrics_collected']: (metrics: LLMMetrics) => void;
    ['error']: (error: LLMError) => void;
};
declare const LLM_base: new () => TypedEmitter<LLMCallbacks>;
export declare abstract class LLM extends LLM_base {
    constructor();
    abstract label(): string;
    /**
     * Get the model name/identifier for this LLM instance.
     *
     * @returns The model name if available, "unknown" otherwise.
     *
     * @remarks
     * Plugins should override this property to provide their model information.
     */
    get model(): string;
    /**
     * Get the provider name for this LLM instance.
     *
     * @returns The provider name if available, "unknown" otherwise.
     *
     * @remarks
     * Plugins should override this property to provide their provider information.
     */
    get provider(): string;
    /**
     * Returns a {@link LLMStream} that can be used to push text and receive LLM responses.
     */
    abstract chat({ chatCtx, toolCtx, connOptions, parallelToolCalls, toolChoice, extraKwargs, }: {
        chatCtx: ChatContext;
        /**
         * Tools to advertise to the LLM. Accepts either a `ToolContext` instance or a raw
         * `(FunctionTool | ProviderTool)[]` array — the array form is normalized into a
         * `ToolContext` internally so callers don't have to construct one themselves.
         */
        toolCtx?: ToolContextLike;
        connOptions?: APIConnectOptions;
        parallelToolCalls?: boolean;
        toolChoice?: ToolChoice;
        extraKwargs?: Record<string, unknown>;
    }): LLMStream;
    /**
     * Pre-warm connection to the LLM service
     */
    prewarm(): void;
    aclose(): Promise<void>;
}
export declare abstract class LLMStream implements AsyncIterableIterator<ChatChunk> {
    #private;
    protected output: AsyncIterableQueue<ChatChunk>;
    protected queue: AsyncIterableQueue<ChatChunk>;
    protected closed: boolean;
    protected abortController: AbortController;
    protected _connOptions: APIConnectOptions;
    protected logger: import("pino").Logger;
    constructor(llm: LLM, { chatCtx, toolCtx, connOptions, }: {
        chatCtx: ChatContext;
        toolCtx?: ToolContextLike;
        connOptions: APIConnectOptions;
    });
    private _mainTaskImpl;
    private mainTask;
    private emitError;
    protected monitorMetrics(): Promise<void>;
    protected abstract run(): Promise<void>;
    /** The function context of this stream. */
    get toolCtx(): ToolContext | undefined;
    /** The initial chat context of this stream. */
    get chatCtx(): ChatContext;
    /** The connection options for this stream. */
    get connOptions(): APIConnectOptions;
    next(): Promise<IteratorResult<ChatChunk>>;
    close(): void;
    /**
     * Collect the entire stream into a single response.
     *
     * @example
     * ```ts
     * const response = await myLlm.chat({ chatCtx, toolCtx }).collect();
     *
     * for (const tc of response.toolCalls) {
     *   // execute the tool call...
     * }
     * ```
     */
    collect(): Promise<CollectedResponse>;
    [Symbol.asyncIterator](): LLMStream;
}
export {};
//# sourceMappingURL=llm.d.ts.map