import { z } from 'zod';
import type { AgentHandoffItem, ChatItem, ChatRole } from '../../llm/chat_context.js';
import type { LLM } from '../../llm/llm.js';
import type { Task } from '../../utils.js';
import type { Agent } from '../agent.js';
import type { AgentSession } from '../agent_session.js';
import { type SpeechHandle } from '../speech_handle.js';
import { type AgentHandoffAssertOptions, type AgentHandoffEvent, type ChatMessageEvent, type EventType, type FunctionCallAssertOptions, type FunctionCallEvent, type FunctionCallOutputAssertOptions, type FunctionCallOutputEvent, type MessageAssertOptions, type RunEvent } from './types.js';
/** @internal */
export type AgentConstructor = new (...args: any[]) => Agent;
type OutputSchema<T> = z.ZodType<T>;
/**
 * Structured-output behavior for `AgentSession.run`.
 *
 * Pass `outputOptions: null` to `run()` to disable the retry behavior
 * entirely (equivalent to `{ maxRetries: 0 }`); omitting the option uses the
 * defaults below.
 */
export type RunOutputOptions = {
    /** Re-prompts when a run ends without its output type. Defaults to 2. */
    maxRetries?: number;
    /** Override the built-in retry prompt. */
    retryInstructions?: string;
};
/**
 * Result of a test run containing recorded events and assertion utilities.
 *
 * @example
 * ```typescript
 * const result = await session.run({ userInput: 'Hello' });
 * result.expect.nextEvent().isMessage({ role: 'assistant' });
 * result.expect.noMoreEvents();
 * ```
 */
export declare class RunResult<T = unknown> {
    private _events;
    private doneFut;
    private userInput?;
    private outputType?;
    private outputRetries;
    private outputRetryInstructions;
    private outputRetryError?;
    private session?;
    private finalOutputValue?;
    private hasFinalOutput;
    private handles;
    private lastSpeechHandle?;
    private runAssert?;
    private doneCallbacks;
    private readonly itemAddedCallback;
    constructor(options?: {
        userInput?: string;
        outputType?: OutputSchema<T>;
        outputOptions?: RunOutputOptions | null;
        session?: AgentSession;
    });
    /**
     * List of all recorded events generated during the run.
     */
    get events(): RunEvent[];
    /**
     * Provides an assertion helper for verifying the run events.
     */
    get expect(): RunAssert;
    /**
     * Returns the final output of the run after completion.
     */
    get finalOutput(): T;
    /**
     * Indicates whether the run has finished processing all events.
     */
    done(): boolean;
    /**
     * Wait for the RunResult to complete. Returns `this` for method chaining.
     *
     * @example
     * ```ts
     * const result = session.run({ userInput: 'Hi!' });
     * await result.wait();  // waits for completion
     * result.expect.nextEvent().isMessage({ role: 'assistant' });
     * ```
     */
    wait(): Promise<this>;
    /**
     * @internal
     * Records an agent handoff event.
     */
    _agentHandoff(params: {
        item: AgentHandoffItem;
        oldAgent?: Agent;
        newAgent: Agent;
    }): void;
    /**
     * @internal
     * Called when a chat item is added during the run.
     */
    _itemAdded(item: ChatItem): void;
    /**
     * @internal
     * Watch a speech handle or task for completion.
     */
    _watchHandle(handle: SpeechHandle | Task<void>): void;
    /**
     * @internal
     * Unwatch a handle.
     */
    _unwatchHandle(handle: SpeechHandle | Task<void>): boolean;
    /** @internal */
    _watchedHandleCount(): number;
    /** @internal – Reject the run with an error (e.g. when deferred generateReply fails). */
    _reject(error: Error): void;
    /** @internal */
    _markDoneIfNeeded(handle?: SpeechHandle | Task<void> | null): void;
    private _markDone;
    private _maybeRetryOutput;
    /**
     * Find the correct insertion index to maintain chronological order.
     */
    private _findInsertionIndex;
}
/**
 * Assertion helper for verifying run events in sequence.
 */
export declare class RunAssert {
    private _events;
    private _currentIndex;
    constructor(runResult: RunResult);
    /**
     * Access a specific event by index for assertions.
     * Supports negative indices (e.g., -1 for last event).
     *
     * @example
     * ```typescript
     * result.expect.at(0).isMessage({ role: 'user' });
     * result.expect.at(-1).isMessage({ role: 'assistant' });
     * ```
     */
    at(index: number): EventAssert;
    /**
     * Advance to the next event, optionally filtering by type.
     *
     * @example
     * ```typescript
     * result.expect.nextEvent().isMessage({ role: 'assistant' });
     * result.expect.nextEvent({ type: 'function_call' }).isFunctionCall({ name: 'foo' });
     * ```
     */
    nextEvent(options?: {
        type?: EventType;
    }): EventAssert;
    /**
     * Skip a specified number of upcoming events without assertions.
     *
     * @example
     * ```typescript
     * result.expect.skipNext(2);
     * ```
     */
    skipNext(count?: number): this;
    /**
     * Conditionally skip the next event if it matches the specified criteria.
     * Returns the event assertion if matched and skipped, or undefined if not matched.
     *
     * @example
     * ```typescript
     * // Skip optional assistant message before function call
     * result.expect.skipNextEventIf({ type: 'message', role: 'assistant' });
     * result.expect.nextEvent().isFunctionCall({ name: 'foo' });
     * ```
     */
    skipNextEventIf(options: {
        type: 'message';
        role?: ChatRole;
    } | {
        type: 'function_call';
        name?: string;
        args?: Record<string, unknown>;
    } | {
        type: 'function_call_output';
        output?: string;
        isError?: boolean;
    } | {
        type: 'agent_handoff';
        newAgentType?: AgentConstructor;
    }): MessageAssert | FunctionCallAssert | FunctionCallOutputAssert | AgentHandoffAssert | undefined;
    /**
     * Get an EventRangeAssert for a range of events.
     * Similar to Python's slice access: expect[0:3] or expect[:]
     *
     * @param start - Start index (inclusive), defaults to 0
     * @param end - End index (exclusive), defaults to events.length
     *
     * @example
     * ```typescript
     * // Search all events
     * result.expect.range().containsFunctionCall({ name: 'foo' });
     * // Search first 3 events
     * result.expect.range(0, 3).containsMessage({ role: 'assistant' });
     * ```
     */
    range(start?: number, end?: number): EventRangeAssert;
    /**
     * Assert that a function call matching criteria exists anywhere in the events.
     *
     * @example
     * ```typescript
     * result.expect.containsFunctionCall({ name: 'order_item' });
     * ```
     */
    containsFunctionCall(options?: FunctionCallAssertOptions): FunctionCallAssert;
    /**
     * Assert that a message matching criteria exists anywhere in the events.
     *
     * @example
     * ```typescript
     * result.expect.containsMessage({ role: 'assistant' });
     * ```
     */
    containsMessage(options?: MessageAssertOptions): MessageAssert;
    /**
     * Assert that a function call output matching criteria exists anywhere in the events.
     *
     * @example
     * ```typescript
     * result.expect.containsFunctionCallOutput({ isError: false });
     * ```
     */
    containsFunctionCallOutput(options?: FunctionCallOutputAssertOptions): FunctionCallOutputAssert;
    /**
     * Assert that an agent handoff matching criteria exists anywhere in the events.
     *
     * @example
     * ```typescript
     * result.expect.containsAgentHandoff({ newAgentType: MyAgent });
     * ```
     */
    containsAgentHandoff(options?: AgentHandoffAssertOptions): AgentHandoffAssert;
    /**
     * Assert that there are no further events.
     *
     * @example
     * ```typescript
     * result.expect.noMoreEvents();
     * ```
     */
    noMoreEvents(): void;
    private _currentEvent;
    /** @internal */
    _raiseWithDebugInfo(message: string, index?: number): never;
}
/**
 * Assertion wrapper for a single event.
 */
export declare class EventAssert {
    protected _event: RunEvent;
    protected _parent: RunAssert;
    protected _index: number;
    constructor(event: RunEvent, parent: RunAssert, index: number);
    /**
     * Get the underlying event.
     */
    event(): RunEvent;
    protected _raise(message: string): never;
    /**
     * Verify this event is a message with optional role matching.
     *
     * @example
     * ```typescript
     * result.expect.nextEvent().isMessage({ role: 'assistant' });
     * ```
     */
    isMessage(options?: MessageAssertOptions): MessageAssert;
    /**
     * Verify this event is a function call with optional name/args matching.
     *
     * @example
     * ```typescript
     * result.expect.nextEvent().isFunctionCall({ name: 'order_item', args: { id: 'big_mac' } });
     * ```
     */
    isFunctionCall(options?: FunctionCallAssertOptions): FunctionCallAssert;
    /**
     * Verify this event is a function call output with optional matching.
     *
     * @example
     * ```typescript
     * result.expect.nextEvent().isFunctionCallOutput({ isError: false });
     * ```
     */
    isFunctionCallOutput(options?: FunctionCallOutputAssertOptions): FunctionCallOutputAssert;
    /**
     * Verify this event is an agent handoff with optional type matching.
     *
     * @example
     * ```typescript
     * result.expect.nextEvent().isAgentHandoff({ newAgentType: MyAgent });
     * ```
     */
    isAgentHandoff(options?: AgentHandoffAssertOptions): AgentHandoffAssert;
}
/**
 * Assertion wrapper for a range of events.
 * Provides contains*() methods to search within the range.
 */
export declare class EventRangeAssert {
    private _events;
    private _parent;
    private _range;
    constructor(events: RunEvent[], parent: RunAssert, range: {
        start: number;
        end: number;
    });
    /**
     * Assert that a function call matching criteria exists in this event range.
     *
     * @example
     * ```typescript
     * result.expect.range(0, 3).containsFunctionCall({ name: 'foo' });
     * ```
     */
    containsFunctionCall(options?: FunctionCallAssertOptions): FunctionCallAssert;
    /**
     * Assert that a message matching criteria exists in this event range.
     *
     * @example
     * ```typescript
     * result.expect.range(0, 2).containsMessage({ role: 'assistant' });
     * ```
     */
    containsMessage(options?: MessageAssertOptions): MessageAssert;
    /**
     * Assert that a function call output matching criteria exists in this event range.
     *
     * @example
     * ```typescript
     * result.expect.range(1, 4).containsFunctionCallOutput({ isError: true });
     * ```
     */
    containsFunctionCallOutput(options?: FunctionCallOutputAssertOptions): FunctionCallOutputAssert;
    /**
     * Assert that an agent handoff matching criteria exists in this event range.
     *
     * @example
     * ```typescript
     * result.expect.range(0, 3).containsAgentHandoff({ newAgentType: MyAgent });
     * ```
     */
    containsAgentHandoff(options?: AgentHandoffAssertOptions): AgentHandoffAssert;
}
/**
 * Assertion wrapper for message events.
 */
export declare class MessageAssert extends EventAssert {
    protected _event: ChatMessageEvent;
    constructor(event: ChatMessageEvent, parent: RunAssert, index: number);
    event(): ChatMessageEvent;
    /**
     * Evaluate whether the message fulfills the given intent using an LLM.
     *
     * @param llm - LLM instance for judgment
     * @param options - Options containing the intent description
     * @returns Self for chaining further assertions
     *
     * @example
     * ```typescript
     * await result.expect
     *   .nextEvent()
     *   .isMessage({ role: 'assistant' })
     *   .judge(llm, { intent: 'should ask for the drink size' });
     * ```
     */
    judge(llm: LLM, options: {
        intent: string;
    }): Promise<MessageAssert>;
}
/**
 * Assertion wrapper for function call events.
 */
export declare class FunctionCallAssert extends EventAssert {
    protected _event: FunctionCallEvent;
    constructor(event: FunctionCallEvent, parent: RunAssert, index: number);
    event(): FunctionCallEvent;
}
/**
 * Assertion wrapper for function call output events.
 */
export declare class FunctionCallOutputAssert extends EventAssert {
    protected _event: FunctionCallOutputEvent;
    constructor(event: FunctionCallOutputEvent, parent: RunAssert, index: number);
    event(): FunctionCallOutputEvent;
}
/**
 * Assertion wrapper for agent handoff events.
 */
export declare class AgentHandoffAssert extends EventAssert {
    protected _event: AgentHandoffEvent;
    constructor(event: AgentHandoffEvent, parent: RunAssert, index: number);
    event(): AgentHandoffEvent;
}
/**
 * Custom assertion error for test failures.
 */
export declare class AssertionError extends Error {
    constructor(message: string);
}
/**
 * A mock tool function. Can be sync or async. Receives the parsed tool arguments
 * and tool options (matching the regular `execute` signature), but the mock is free
 * to ignore them. Whatever the function returns becomes the tool output. Throwing
 * produces a tool error event, just like a real tool execute.
 */
export type MockToolFn = (...args: any[]) => any;
/** Map from agent constructor to a record of mocked tools by name. */
export type MockToolsMap = Map<AgentConstructor, Record<string, MockToolFn>>;
/** @internal */
export declare let activeMockTools: MockToolsMap | undefined;
/** @internal */
export declare function getMockTool(agent: Agent, toolName: string): MockToolFn | undefined;
/**
 * Temporarily assign a set of mock tool callables to a specific Agent type. Returns
 * a {@link Disposable} for use with a `using` declaration. While the binding is in
 * scope, tool calls for the matching agent type and tool name are routed to the
 * supplied mock instead of the real `execute` implementation, and are restored when
 * the enclosing block exits.
 *
 * Mirrors the Python `mock_tools` context manager, adapted to JS via the explicit
 * resource management `using` syntax (Python uses `with`).
 *
 * @param agent - The Agent constructor whose tools should be mocked.
 * @param mocks - A record mapping tool name to a mock implementation.
 *
 * @example
 * ```typescript
 * {
 *   using _mock = withMockTools(DriveThruAgent, {
 *     orderRegularItem: () => new Error('test failure'),
 *     getWeather: () => 'sunny',
 *   });
 *
 *   const result = await session.run({ userInput: 'Order a burger' });
 *   result.expect.containsFunctionCall({ name: 'orderRegularItem' });
 * }
 * ```
 */
export declare function withMockTools(agent: AgentConstructor, mocks: Record<string, MockToolFn>): Disposable;
export {};
//# sourceMappingURL=run_result.d.ts.map