/**
 * MockProvider — deterministic LLMProvider for tests + examples.
 *
 * Pattern: Adapter (GoF, Design Patterns ch. 4).
 * Role:    Ports-and-Adapters outer ring (Cockburn, 2005) — implements the
 *          LLMProvider port without calling out to a real LLM service.
 * Emits:   N/A (adapters don't emit; recorders observe them).
 *
 * Two modes, same provider:
 *   • DEFAULT (no latency options)  — instant `complete()`, no streaming.
 *     Use in unit tests; behavior unchanged from earlier revisions.
 *   • REALISTIC (`thinkingMs` set)  — randomised "thinking" latency before
 *     the response, plus a `stream()` implementation that emits the
 *     content word-by-word with `chunkDelayMs` between chunks. Lets
 *     consumers SEE the run unfold (pauses, streaming tokens, tool
 *     dispatch) instead of having every step finish in microseconds.
 *
 * Realistic mode is the right default for the playground / Lens demos:
 * a real OpenAI / Anthropic call takes 3–8 s, so the UX you build for
 * that timing is what matters. Use `MockProvider.realistic()` for the
 * common 3–8 s thinking + 30–80 ms per word streaming preset.
 */
import type { LLMChunk, LLMProvider, LLMRequest, LLMResponse, WireRole } from '../../provider-contract/types.js';
/** Either a fixed value (in ms) or a random `[min, max]` range (inclusive). */
export type LatencyMs = number | readonly [number, number];
/**
 * One scripted reply consumed in order from `MockProviderOptions.replies`.
 * String → plain text content; Partial<LLMResponse> → can include
 * `toolCalls`, `usage`, `stopReason` for tool-using ReAct loops.
 */
export type MockReply = string | Partial<LLMResponse>;
export interface MockProviderOptions {
    readonly name?: string;
    /** Fixed response content. Overrides `respond` when set. */
    readonly reply?: string;
    /**
     * Scripted replies for multi-turn / tool-using agents. Each entry
     * is consumed in order — iteration 1 reads `replies[0]`, iteration
     * 2 reads `replies[1]`, and so on. Use Partial<LLMResponse> to
     * inject `toolCalls`:
     *
     * ```ts
     * mock({
     *   replies: [
     *     { toolCalls: [{ id: '1', name: 'lookup', args: { id: 42 } }] },
     *     { content: 'Found it: refunds take 3 business days.' },
     *   ],
     * });
     * ```
     *
     * **Exhaustion semantics:** if the agent calls the LLM more times
     * than there are replies, `complete()` / `stream()` throw a clear
     * error. This makes mock-script bugs loud, not silent. Tune the
     * agent's `maxIterations` to bound the call count.
     *
     * Takes precedence over `reply` and `respond` when set.
     */
    readonly replies?: readonly MockReply[];
    /**
     * Build the response from the request. Returns either a plain
     * string (renders as content with no tool calls) or a partial
     * `LLMResponse` so consumers can simulate tool calls + multi-turn
     * loops without needing a separate `scripted()` helper.
     *
     * Default: echoes the last message a PERSON wrote (`isSaidByPerson`) —
     * never a line this library served in the user role, such as the time
     * layer's late line, which is the LAST user-role message of every request
     * under `.time()`.
     */
    readonly respond?: (req: LLMRequest) => string | Partial<LLMResponse>;
    /**
     * Simulated wall-clock delay per request (ms).
     * Pass a single number for a fixed delay or a `[min, max]` tuple for
     * a uniformly random delay (e.g. `[3000, 8000]` for "real LLM"
     * thinking time). Default 0 (instant).
     *
     * Aliased via `delayMs` for backward compatibility.
     */
    readonly thinkingMs?: LatencyMs;
    /** Alias for `thinkingMs`. Kept for back-compat with prior revisions. */
    readonly delayMs?: LatencyMs;
    /**
     * For `stream()`: delay between successive chunks (ms). Pass a
     * single number for a fixed delay or a `[min, max]` tuple for a
     * uniformly random delay per chunk (e.g. `[30, 80]` for typing-like
     * cadence). Default 30ms.
     *
     * Has no effect on `complete()`.
     */
    readonly chunkDelayMs?: LatencyMs;
    /** Fixed stop reason to return. Default 'stop'. */
    readonly stopReason?: string;
    /** Override usage counts returned. Default: chars/4 heuristic. */
    readonly usage?: Readonly<{
        input?: number;
        output?: number;
        cacheRead?: number;
        cacheWrite?: number;
    }>;
}
export declare class MockProvider implements LLMProvider {
    readonly name: string;
    readonly carriesInMessages: readonly WireRole[];
    /**
     * The mock carries a forced tool choice, so `strategy: 'tool-forced'` is
     * testable end-to-end with no key and no network: script a reply whose
     * `toolCalls` names the synthetic tool and the whole loop — forced request,
     * tool-shaped answer, validation, retry — runs deterministically. A mock
     * that refused the strategy would make the one path that most needs a
     * cheap rehearsal the one path you could only rehearse in production.
     */
    readonly carriesForcedToolChoice = true;
    /**
     * The mock "carries" a structured-output format for the same reason it
     * carries a forced choice: the scripted reply IS the constrained answer, so
     * `strategy: 'native'` can be rehearsed offline. Its manifest states the
     * format whenever the request carried one.
     */
    readonly carriesNativeOutputSchema = true;
    /** Every mock model is a known synthetic transport, never an opaque endpoint. */
    readonly supportsAutoNativeOutputSchema: () => boolean;
    /** Normalizes the scripted `rawThinking` a reply carries. */
    readonly thinkingHandler: import("../../thinking/types.js").ThinkingHandler;
    private readonly reply?;
    private readonly replies?;
    private repliesCursor;
    private readonly respond;
    private readonly thinkingMs;
    private readonly chunkDelayMs;
    private readonly stopReason;
    private readonly usageOverride;
    constructor(options?: MockProviderOptions);
    /**
     * Reset the scripted-replies cursor. Useful when reusing one
     * `MockProvider` instance across multiple test scenarios — each
     * scenario can `provider.resetReplies()` to start from `replies[0]`
     * again. No-op when `replies` was not supplied.
     */
    resetReplies(): void;
    /**
     * Convenience factory for the playground / Lens demo defaults: a
     * real-feel mock with 3–8 s of "thinking" before the response and
     * 30–80 ms per streamed word. Lets users observe pause/resume,
     * streaming, and tool dispatch happening live without hitting a
     * paid API.
     */
    static realistic(options?: MockProviderOptions): MockProvider;
    complete(req: LLMRequest): Promise<LLMResponse>;
    /**
     * Streaming mode — emits the response content word-by-word so
     * consumers (Lens commentary, chat UIs) can render tokens as they
     * arrive. Tool calls land all at once on the final chunk because
     * that is how real providers (OpenAI, Anthropic) deliver them too.
     */
    stream(req: LLMRequest): AsyncIterable<LLMChunk>;
    private buildResponse;
    /**
     * Resolve the next reply source for one `complete()` / `stream()` call.
     * Priority: `replies` (scripted, throws on exhaustion) → `reply` (single
     * fixed string) → `respond` (callback default). Replies are consumed
     * in order; the cursor is per-instance, not per-request.
     */
    private consumeNextReply;
}
/**
 * Lowercase factory for `MockProvider` — matches the v1 `mock()` import
 * shape so docs and quick-starts stay copy-pasteable. Equivalent to
 * `new MockProvider(options)`.
 *
 * @example
 *   import { Agent, defineTool } from 'agentfootprint'
import { mock } from 'agentfootprint/providers';
 *
 *   const agent = Agent.create({ provider: mock({ reply: 'hello' }) })
 *     .tool(defineTool({ name: 'echo', ... }))
 *     .build();
 */
export declare function mock(options?: MockProviderOptions): MockProvider;
