import type { Logger } from "../../../client.js";
import type { RequestOptions } from "../../../internal/request-options.js";
import type { BetaMessage, BetaMessageParam, BetaStopReason, MessageCreateParamsBase } from "../../../resources/beta/messages/messages.js";
import type { UnsupportedRequestBehavior, BetaMessageThreadFields, BetaMessageThreadCreateParams, BetaMessageThreadRequestOptions, BetaMessageThreadSendParams, BetaMessageThreadInput } from "../../threads/params.js";
/** The `create()` arguments of one turn, except `stream`. */
type CreateArguments = {
    params: MessageCreateParamsBase;
    options: RequestOptions;
};
/**
 * One message of the history: the reply it records if the thread received it from the server rather than from the
 * caller, and whether that reply's stream ended before `message_stop`.
 */
type Entry = {
    param: BetaMessageParam;
    reply: null;
} | {
    param: BetaMessageParam;
    reply: BetaMessage;
    partial: boolean;
};
/**
 * A turn in flight: the request fields it sends, the messages its call staged, the create-only fields its call gave,
 * and the history edits to apply once it ends.
 */
declare class Turn {
    readonly fields: BetaMessageThreadFields;
    readonly ownMessages: readonly Entry[];
    ownCreateOnly: CreateOnlyFields;
    deferredMessages: Array<BetaMessageParam | BetaMessage>;
    replacementHistory: BetaMessageParam[] | null;
    readonly createOnly: CreateOnlyJSON;
    constructor(fields: BetaMessageThreadFields, ownMessages: readonly Entry[], ownCreateOnly: CreateOnlyFields);
}
export type { Turn };
/**
 * A thread's local view of the conversation: the full history, which part of it the server holds and which
 * reply the next turn continues from, the request fields for the next turn, and the turn in flight, if any.
 *
 * Sends nothing itself: it assembles each turn's `create()` arguments and records what the reply changes.
 */
export declare class ThreadState {
    #private;
    options: BetaMessageThreadRequestOptions;
    readonly unsupportedRequestBehavior: UnsupportedRequestBehavior;
    constructor({ params, options, threading, logger, }: {
        params: BetaMessageThreadCreateParams;
        options: BetaMessageThreadRequestOptions;
        threading: boolean;
        logger: Logger;
    });
    /** Whether turns send a `thread` field at all. */
    get threading(): boolean;
    /** The `id` of the stored reply the next turn continues from, or `null` when it starts a new thread. */
    get previousMessageId(): string | null;
    /**
     * Every message the server holds plus those staged for the next turn, with any edits deferred by a turn in flight
     * already applied.
     */
    get messages(): BetaMessageParam[];
    /**
     * The thread as the params of one call for the whole conversation: its request fields and full history. A new
     * object on each access. While a turn that creates the thread is in flight, it shows that turn's create-only fields.
     */
    get params(): BetaMessageThreadFields & {
        messages: BetaMessageParam[];
    };
    /** Stage messages for the next turn, skipping the reply just recorded and deferring while a turn is in flight. */
    push(messages: Iterable<BetaMessageParam | BetaMessage>): void;
    /** Apply the given request fields and request options to all later turns. */
    update(fields?: BetaMessageThreadSendParams, options?: BetaMessageThreadRequestOptions): void;
    /**
     * A copy with the same history and options that continues from no stored reply and has no turn in flight. Its request
     * fields are the same too, unless `fields` takes their place.
     */
    fork(fields?: BetaMessageThreadFields): ThreadState;
    /** Replace the request fields with those of `params`, so a field it leaves out is gone, then `setMessages()`. */
    setParams({ messages, ...fields }: BetaMessageThreadFields & {
        messages: BetaMessageParam[];
    }): void;
    /**
     * Take the history from `messages`: additions to the current history are staged, and any other list replaces it
     * and starts a new thread.
     */
    setMessages(messages: BetaMessageParam[]): void;
    /** Whether the next turn has something to send: staged messages, or an unfinished reply to resume. */
    get hasTurnToSend(): boolean;
    /** Stage `messages` and start the turn that sends them with the overrides `fields`, in flight until `endTurn()`. */
    startTurn(messages: Iterable<BetaMessageParam | BetaMessage>, fields: BetaMessageThreadSendParams): Turn;
    /**
     * Mark `turn` finished, take back the messages its call staged if no reply to them started, and apply the history
     * edits deferred during it.
     */
    endTurn(turn: Turn): void;
    /**
     * Whether the turn should be sent again because `error` is a thread rejection this state has now adjusted for. With
     * `'continue_unthreaded'` a replay that finds the new thread lost as well stops threading, because the server may be
     * unable to store the conversation.
     */
    recoversFrom(error: unknown): boolean;
    /** Drop the `thread` field from this turn and every later one. */
    stopThreading(): void;
    /**
     * Record a turn whose stream ended after `message_start` and before `message_stop`. The next turn starts a new
     * thread because the server holds either the whole reply or none of it. `completedBlocks` is how many content
     * blocks received `content_block_stop`.
     */
    recordPartialReply(snapshot: BetaMessage, completedBlocks: number): void;
    /**
     * Record `message` as the reply of `turn`, for the next turn to continue from. The server does not store a reply
     * that a fallback model wrote, so the turn after one starts a new thread.
     */
    recordReply(turn: Turn, message: BetaMessage): void;
    /**
     * The `create()` arguments of `turn` except `stream`: request fields, betas, the `thread` field with the delta or
     * full history, and request options.
     */
    buildCreateArguments(turn: Turn, options: BetaMessageThreadRequestOptions, { stream }: {
        stream: boolean;
    }): CreateArguments;
    /** Throws if the thread refuses a turn with the overrides `fields`, as that turn would before it is sent. */
    checkNextTurn(fields: BetaMessageThreadSendParams): void;
}
declare const UNFINISHED_STOP_REASONS: readonly ["pause_turn", "compaction"];
export type UnfinishedStopReason = (typeof UNFINISHED_STOP_REASONS)[number];
export declare function isUnfinishedStopReason(stopReason: BetaStopReason | null | undefined): stopReason is UnfinishedStopReason;
/** Request fields the server takes from the thread on a `continue` and rejects if the request repeats them. */
declare const CREATE_ONLY_FIELDS: readonly ["system", "tools"];
type CreateOnlyFields = Pick<BetaMessageThreadFields, (typeof CREATE_ONLY_FIELDS)[number]>;
type CreateOnlyJSON = Record<keyof CreateOnlyFields, string | undefined>;
/** Throws if `fields` has a `thread`. The field types leave it out, which an untyped caller or a cast gets past. */
export declare function rejectThreadField(fields: object): void;
/** `object` without the keys whose value is `undefined`, so a spread of it leaves those keys as they were. */
export declare function definedEntries<T extends object>(object: T): T;
/** Whether every field of the two messages is equal. A reply given as it was received counts as its param. */
export declare function sameMessage(a: BetaMessageParam | BetaMessage, b: BetaMessageParam | BetaMessage): boolean;
export declare function toMessageList(input: BetaMessageThreadInput | undefined): ReadonlyArray<BetaMessageParam | BetaMessage>;
//# sourceMappingURL=ThreadState.d.ts.map