import type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';
import { ChatContext, type FunctionCall } from '../llm/chat_context.js';
import { LLM } from '../llm/llm.js';
import type { LLMMetrics } from '../metrics/base.js';
import type { STT } from '../stt/stt.js';
import { Task } from '../utils.js';
import { AgentSessionEventTypes, type ConversationItemAddedEvent } from './events.js';
/**
 * Keyterm biasing for STTs that accept a term list.
 *
 * Can be passed as a plain object:
 *
 * ```ts
 * new AgentSession({
 *   keytermsOptions: {
 *     keyterms: ['LiveKit', 'Acme Corp'],
 *     keytermDetection: { enabled: true, turnInterval: 1 },
 *   },
 * });
 * ```
 */
export interface KeytermsOptions {
    /** Static keyterms applied wherever the STT accepts a term list; never touched by detection. */
    keyterms?: string[];
    /** LLM-based keyterm extraction, for STTs that accept a term list. */
    keytermDetection?: KeytermDetectionOptions;
}
/**
 * Configuration for automatic keyterm detection.
 *
 * Lives under the `keytermDetection` key of {@link KeytermsOptions}. Absent or
 * `{ enabled: false }` keeps detection off.
 */
export interface KeytermDetectionOptions {
    /** Whether to run the background detector. Defaults to `false`. */
    enabled?: boolean;
    /**
     * LLM used for extraction. An `LLM` instance, or a model string (e.g.
     * `"google/gemini-3.5-flash"`) resolved via the inference gateway. Defaults to a
     * built-in detection model; the agent's own LLM is not used.
     */
    llm?: LLM | string;
    /** Run a pass once per N user turns. Defaults to `1`. */
    turnInterval?: number;
    /** Cap on the confirmed (applied) detected keyterms if provided. Defaults to `undefined`. */
    maxKeyterms?: number;
    /** Override the built-in extraction prompt. */
    instructions?: string;
    /**
     * Milliseconds a single detection pass may run before it is dropped (no keyterm change).
     * Defaults to `10_000`. Raise it if a slow detection `llm` needs longer.
     */
    timeout?: number;
}
/** A fully-defaulted keyterm-detection config. @internal */
export interface ResolvedKeytermDetectionOptions {
    enabled: boolean;
    llm?: LLM | string;
    turnInterval: number;
    maxKeyterms?: number;
    instructions?: string;
    timeout: number;
}
/** A fully-defaulted keyterms config. @internal */
export interface ResolvedKeytermsOptions {
    keyterms: string[];
    keytermDetection: ResolvedKeytermDetectionOptions;
}
/** A pending term not confirmed within this many passes is dropped. @internal */
export declare const PENDING_TTL = 3;
/** Return a fully-defaulted keyterm-detection config (`enabled` defaults to false). @internal */
export declare function resolveDetection(config?: KeytermDetectionOptions): ResolvedKeytermDetectionOptions;
/** Return a fully-defaulted keyterms config. @internal */
export declare function resolveKeytermsOptions(config?: KeytermsOptions): ResolvedKeytermsOptions;
/**
 * The minimal session surface the detector needs. `AgentSession` satisfies this
 * structurally; tests can supply a lightweight fake.
 *
 */
export interface KeytermDetectorSession {
    readonly history: ChatContext;
    on(event: AgentSessionEventTypes.ConversationItemAdded, listener: (ev: ConversationItemAddedEvent) => void): unknown;
    off(event: AgentSessionEventTypes.ConversationItemAdded, listener: (ev: ConversationItemAddedEvent) => void): unknown;
}
export type KeytermDetectorCallbacks = {
    ['metrics_collected']: (metrics: LLMMetrics) => void;
};
declare const KeytermDetector_base: new () => TypedEmitter<KeytermDetectorCallbacks>;
/**
 * Maintains the STT keyterm set and, when enabled, auto-detects keyterms during a call.
 *
 * Owned by the {@link AgentSession} so keyterm state survives agent handoffs. Each agent
 * activity binds it to that activity's STT via {@link KeytermDetector.start} and releases it via
 * {@link KeytermDetector.aclose}. When detection is on, an LLM extracts distinctive spellings from
 * the conversation; only confirmed terms are pushed to the STT, while pending terms are tracked
 * (and fed back to the detector) without biasing recognition.
 */
export declare class KeytermDetector extends KeytermDetector_base {
    #private;
    private detection;
    private maxKeyterms?;
    private turnInterval;
    private instructions;
    private detectionTimeout;
    private staticTerms;
    /** confirmed terms, oldest first (for eviction) @internal */
    _detectedTerms: string[];
    /** term -> pass it was added (for TTL) @internal */
    _pendingTerms: Map<string, number>;
    private tick;
    private stt?;
    private llm?;
    private session?;
    private turnCount;
    /** @internal */
    _detectTask?: Task<void>;
    constructor(opts?: {
        staticKeyterms?: string[];
        options?: KeytermDetectionOptions;
    });
    /** The effective list applied to the STT: static terms + confirmed detected terms. */
    get keyterms(): string[];
    get staticKeyterms(): string[];
    setStaticKeyterms(terms: string[]): void;
    swapStt(stt: STT | undefined): void;
    /** Bind this activity's STT (always) and start detection (if enabled). */
    start(session: KeytermDetectorSession, stt: STT): void;
    /** Stop detection for the current activity; keyterm state is kept. */
    aclose(): Promise<void>;
    private forwardMetrics;
    private onConversationItemAdded;
    private static snapshot;
    /** @internal exposed for tests */
    runOnce(chatCtx: ChatContext, abortSignal?: AbortSignal): Promise<void>;
}
/**
 * Run one extraction pass via a forced function call.
 *
 * Returns `[pending, confirm, remove]`.
 *
 * @internal exposed for tests
 */
export declare function detectKeyterms(llm: LLM, chatCtx: ChatContext, opts?: {
    instructions?: string;
    currentKeyterms?: [string, boolean][];
    timeout?: number;
    abortSignal?: AbortSignal;
}): Promise<[string[], string[], string[]]>;
/**
 * Render the detector's user message: recent transcript + current keyterms.
 *
 * Returns `undefined` when the transcript holds no user/assistant text yet.
 *
 * @internal exposed for tests
 */
export declare function formatInput(chatCtx: ChatContext, currentKeyterms: [string, boolean][]): string | undefined;
/**
 * Parse the `record_keyterms` tool call into `[pending, confirm, remove]`.
 *
 * @internal exposed for tests
 */
export declare function parseToolCall(toolCalls: FunctionCall[]): [string[], string[], string[]];
export {};
//# sourceMappingURL=keyterm_detection.d.ts.map