import { FunctionCall, FunctionCallOutput } from '../llm/chat_context.js';
import type { Future } from '../utils.js';
import type { AgentActivity } from './agent_activity.js';
import type { AgentSession } from './agent_session.js';
import { type SpeechHandle } from './speech_handle.js';
export type UnknownUserData = unknown;
export type PromptTemplate<Args> = string | ((args: Args) => string);
export interface UpdatePromptArgs {
    functionName: string;
    callId: string;
    message: string;
}
export interface RunContextUpdateOptions {
    template?: PromptTemplate<UpdatePromptArgs>;
}
export type FillerSource = string | ((step: number) => SpeechHandle | string | null | undefined);
export interface RunContextFillerOptions {
    /**
     * Continuous-idle dwell, in milliseconds, before filler speech fires.
     * Defaults to 0, which fires as soon as the session is next idle.
     */
    delay?: number;
    /**
     * Cooldown, in milliseconds, before waiting for another idle dwell.
     * When omitted, filler speech fires at most once.
     */
    interval?: number;
    /** Maximum number of filler speeches to create. */
    maxSteps?: number;
    /** Optional external cancellation signal for the filler scheduler. */
    signal?: AbortSignal;
}
export interface AttachedToolExecutor<UserData = UnknownUserData> {
    toolOptions: {
        updateTemplate: PromptTemplate<UpdatePromptArgs>;
    };
    enqueueReply(ctx: RunContext<UserData>, items: [FunctionCall, FunctionCallOutput]): Promise<void>;
    replyTask?: Promise<void>;
}
export declare class RunContext<UserData = UnknownUserData> {
    readonly session: AgentSession<UserData>;
    readonly speechHandle: SpeechHandle;
    readonly functionCall: FunctionCall;
    private readonly initialStepIdx;
    private _executor?;
    private _firstUpdateFuture?;
    private _updates;
    private _fillerSchedulers;
    constructor(session: AgentSession<UserData>, speechHandle: SpeechHandle, functionCall: FunctionCall);
    get userData(): UserData;
    /**
     * Waits for the speech playout corresponding to this function call step.
     *
     * Unlike {@link SpeechHandle.waitForPlayout}, which waits for the full
     * assistant turn to complete (including all function tools),
     * this method only waits for the assistant's spoken response prior to running
     * this tool to finish playing.
     */
    waitForPlayout(): Promise<void>;
    get updates(): readonly [FunctionCall, FunctionCallOutput][];
    disallowInterruptions(): void;
    /**
     * Report progress from a long-running tool — and, on the first call, turn the tool
     * **non-blocking** so the conversation continues while `execute()` keeps running.
     *
     * Behavior depends on whether this is the first `update()` for the call:
     *
     * - **First call:** resolves the pending tool result with `message` and marks the
     *   function call non-blocking (`functionCall.extra.__livekit_agents_tool_non_blocking = true`).
     *   The framework treats `message` as the tool's immediate output to the LLM and returns
     *   control to the session, so the agent can speak/listen while the tool continues in the
     *   background. Whatever `execute()` ultimately returns is delivered later as a deferred reply.
     * - **Subsequent calls:** each `message` is enqueued via the owning executor and delivered as a
     *   fresh assistant turn, gated on the session being idle (so updates never talk over the user).
     *   The arrival cadence is therefore conversational, not immediate.
     *
     * Message rendering:
     * - A **string** is rendered through a template — {@link RunContextUpdateOptions.template} if
     *   provided, otherwise the executor's configured `updateTemplate` — with `{functionName}`,
     *   `{callId}`, and `{message}` substituted. The default template tells the model the task is
     *   still running and not to fabricate results.
     * - A **non-string** value is used as-is (no templating), letting a tool emit structured output.
     *
     * Every update is also recorded in {@link RunContext.updates} (with a `_update_N` call-id suffix
     * for the 2nd and later updates) so the full progress trail is preserved in chat history.
     *
     * No-op for delivery when the tool isn't attached to an async-capable executor (e.g. a plain
     * blocking tool): the update is still recorded but nothing is sent.
     *
     * @param message - Progress text (templated) or a structured value (sent verbatim).
     * @param options - Per-call overrides; see {@link RunContextUpdateOptions}.
     */
    update(message: unknown, options?: RunContextUpdateOptions): Promise<void>;
    foreground<T>(fn: (activity: AgentActivity) => Promise<T> | T): Promise<T>;
    /**
     * Speak filler audio while a long-running tool step is in progress.
     *
     * The scheduler waits until the session is continuously idle for
     * {@link RunContextFillerOptions.delay} milliseconds, then speaks `source`
     * through {@link AgentSession.say}. When `interval` is set, it waits that
     * many milliseconds before starting another idle dwell; otherwise it fires at
     * most once. Agent speech, user speech, and {@link RunContext.update} reset
     * any pending dwell so filler does not race real conversation turns.
     *
     * @example
     * ```ts
     * await ctx.filler('Still searching, hang on.', { delay: 5000 }, async () => {
     *   return await slowLookup();
     * });
     * ```
     */
    filler<T>(source: FillerSource, fn: () => Promise<T> | T): Promise<T>;
    filler<T>(source: FillerSource, options: RunContextFillerOptions, fn: () => Promise<T> | T): Promise<T>;
    _attachExecutor(executor: AttachedToolExecutor<UserData>, firstUpdateFuture: Future<unknown>): void;
    _detachExecutor(): void;
    _drainPendingReply(): Promise<void>;
    _makeUpdatePair(message: unknown, callIdSuffix?: string): [FunctionCall, FunctionCallOutput];
    _recordUpdatePair(pair: [FunctionCall, FunctionCallOutput]): void;
}
//# sourceMappingURL=run_context.d.ts.map