import { Client, type ClientConfig } from "../client.js";
import type { Command, DisconnectMode, MultitaskStrategy, OnCompletionBehavior } from "../types.js";
import type { Message } from "../types.messages.js";
import type { Checkpoint, Config, Interrupt, Metadata, ThreadState } from "../schema.js";
import type { CustomStreamEvent, DebugStreamEvent, EventsStreamEvent, MetadataStreamEvent, StreamMode, UpdatesStreamEvent } from "../types.stream.js";
interface Node<StateType = any> {
    type: "node";
    value: ThreadState<StateType>;
    path: string[];
}
interface Fork<StateType = any> {
    type: "fork";
    items: Array<Sequence<StateType>>;
}
interface Sequence<StateType = any> {
    type: "sequence";
    items: Array<Node<StateType> | Fork<StateType>>;
}
export type MessageMetadata<StateType extends Record<string, unknown>> = {
    /**
     * The ID of the message used.
     */
    messageId: string;
    /**
     * The first thread state the message was seen in.
     */
    firstSeenState: ThreadState<StateType> | undefined;
    /**
     * The branch of the message.
     */
    branch: string | undefined;
    /**
     * The list of branches this message is part of.
     * This is useful for displaying branching controls.
     */
    branchOptions: string[] | undefined;
};
type BagTemplate = {
    ConfigurableType?: Record<string, unknown>;
    InterruptType?: unknown;
    CustomEventType?: unknown;
    UpdateType?: unknown;
};
type GetUpdateType<Bag extends BagTemplate, StateType extends Record<string, unknown>> = Bag extends {
    UpdateType: unknown;
} ? Bag["UpdateType"] : Partial<StateType>;
type GetConfigurableType<Bag extends BagTemplate> = Bag extends {
    ConfigurableType: Record<string, unknown>;
} ? Bag["ConfigurableType"] : Record<string, unknown>;
type GetInterruptType<Bag extends BagTemplate> = Bag extends {
    InterruptType: unknown;
} ? Bag["InterruptType"] : unknown;
type GetCustomEventType<Bag extends BagTemplate> = Bag extends {
    CustomEventType: unknown;
} ? Bag["CustomEventType"] : unknown;
interface RunCallbackMeta {
    run_id: string;
    thread_id: string;
}
export interface UseStreamOptions<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends BagTemplate = BagTemplate> {
    /**
     * The ID of the assistant to use.
     */
    assistantId: string;
    /**
     * Client used to send requests.
     */
    client?: Client;
    /**
     * The URL of the API to use.
     */
    apiUrl?: ClientConfig["apiUrl"];
    /**
     * The API key to use.
     */
    apiKey?: ClientConfig["apiKey"];
    /**
     * Custom call options, such as custom fetch implementation.
     */
    callerOptions?: ClientConfig["callerOptions"];
    /**
     * Default headers to send with requests.
     */
    defaultHeaders?: ClientConfig["defaultHeaders"];
    /**
     * Specify the key within the state that contains messages.
     * Defaults to "messages".
     *
     * @default "messages"
     */
    messagesKey?: string;
    /**
     * Callback that is called when an error occurs.
     */
    onError?: (error: unknown, run: RunCallbackMeta | undefined) => void;
    /**
     * Callback that is called when the stream is finished.
     */
    onFinish?: (state: ThreadState<StateType>, run: RunCallbackMeta | undefined) => void;
    /**
     * Callback that is called when a new stream is created.
     */
    onCreated?: (run: RunCallbackMeta) => void;
    /**
     * Callback that is called when an update event is received.
     */
    onUpdateEvent?: (data: UpdatesStreamEvent<GetUpdateType<Bag, StateType>>["data"]) => void;
    /**
     * Callback that is called when a custom event is received.
     */
    onCustomEvent?: (data: CustomStreamEvent<GetCustomEventType<Bag>>["data"], options: {
        mutate: (update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)) => void;
    }) => void;
    /**
     * Callback that is called when a metadata event is received.
     */
    onMetadataEvent?: (data: MetadataStreamEvent["data"]) => void;
    /**
     * Callback that is called when a LangChain event is received.
     * @see https://langchain-ai.github.io/langgraph/cloud/how-tos/stream_events/#stream-graph-in-events-mode for more details.
     */
    onLangChainEvent?: (data: EventsStreamEvent["data"]) => void;
    /**
     * Callback that is called when a debug event is received.
     * @internal This API is experimental and subject to change.
     */
    onDebugEvent?: (data: DebugStreamEvent["data"]) => void;
    /**
     * Callback that is called when the stream is stopped by the user.
     * Provides a mutate function to update the stream state immediately
     * without requiring a server roundtrip.
     *
     * @example
     * ```typescript
     * onStop: ({ mutate }) => {
     *   mutate((prev) => ({
     *     ...prev,
     *     ui: prev.ui?.map(component =>
     *       component.props.isLoading
     *         ? { ...component, props: { ...component.props, stopped: true, isLoading: false }}
     *         : component
     *     )
     *   }));
     * }
     * ```
     */
    onStop?: (options: {
        mutate: (update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)) => void;
    }) => void;
    /**
     * The ID of the thread to fetch history and current values from.
     */
    threadId?: string | null;
    /**
     * Callback that is called when the thread ID is updated (ie when a new thread is created).
     */
    onThreadId?: (threadId: string) => void;
    /** Will reconnect the stream on mount */
    reconnectOnMount?: boolean | (() => RunMetadataStorage);
    /**
     * Initial values to display immediately when loading a thread.
     * Useful for displaying cached thread data while official history loads.
     * These values will be replaced when official thread data is fetched.
     *
     * Note: UI components from initialValues will render immediately if they're
     * predefined in LoadExternalComponent's components prop, providing instant
     * cached UI display without server fetches.
     */
    initialValues?: StateType | null;
}
interface RunMetadataStorage {
    getItem(key: `lg:stream:${string}`): string | null;
    setItem(key: `lg:stream:${string}`, value: string): void;
    removeItem(key: `lg:stream:${string}`): void;
}
export interface UseStream<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends BagTemplate = BagTemplate> {
    /**
     * The current values of the thread.
     */
    values: StateType;
    /**
     * Last seen error from the thread or during streaming.
     */
    error: unknown;
    /**
     * Whether the stream is currently running.
     */
    isLoading: boolean;
    /**
     * Stops the stream.
     */
    stop: () => void;
    /**
     * Create and stream a run to the thread.
     */
    submit: (values: GetUpdateType<Bag, StateType> | null | undefined, options?: SubmitOptions<StateType, GetConfigurableType<Bag>>) => void;
    /**
     * The current branch of the thread.
     */
    branch: string;
    /**
     * Set the branch of the thread.
     */
    setBranch: (branch: string) => void;
    /**
     * Flattened history of thread states of a thread.
     */
    history: ThreadState<StateType>[];
    /**
     * Tree of all branches for the thread.
     * @experimental
     */
    experimental_branchTree: Sequence<StateType>;
    /**
     * Get the interrupt value for the stream if interrupted.
     */
    interrupt: Interrupt<GetInterruptType<Bag>> | undefined;
    /**
     * Messages inferred from the thread.
     * Will automatically update with incoming message chunks.
     */
    messages: Message[];
    /**
     * Get the metadata for a message, such as first thread state the message
     * was seen in and branch information.
     
     * @param message - The message to get the metadata for.
     * @param index - The index of the message in the thread.
     * @returns The metadata for the message.
     */
    getMessagesMetadata: (message: Message, index?: number) => MessageMetadata<StateType> | undefined;
    /**
     * LangGraph SDK client used to send request and receive responses.
     */
    client: Client;
    /**
     * The ID of the assistant to use.
     */
    assistantId: string;
    /**
     * Join an active stream.
     */
    joinStream: (runId: string, lastEventId?: string, options?: {
        streamMode?: StreamMode | StreamMode[];
    }) => Promise<void>;
}
type ConfigWithConfigurable<ConfigurableType extends Record<string, unknown>> = Config & {
    configurable?: ConfigurableType;
};
interface SubmitOptions<StateType extends Record<string, unknown> = Record<string, unknown>, ConfigurableType extends Record<string, unknown> = Record<string, unknown>> {
    config?: ConfigWithConfigurable<ConfigurableType>;
    checkpoint?: Omit<Checkpoint, "thread_id"> | null;
    command?: Command;
    interruptBefore?: "*" | string[];
    interruptAfter?: "*" | string[];
    metadata?: Metadata;
    multitaskStrategy?: MultitaskStrategy;
    onCompletion?: OnCompletionBehavior;
    onDisconnect?: DisconnectMode;
    feedbackKeys?: string[];
    streamMode?: Array<StreamMode>;
    optimisticValues?: Partial<StateType> | ((prev: StateType) => Partial<StateType>);
    /**
     * Whether or not to stream the nodes of any subgraphs called
     * by the assistant.
     * @default false
     */
    streamSubgraphs?: boolean;
    streamResumable?: boolean;
    /**
     * The ID to use when creating a new thread. When provided, this ID will be used
     * for thread creation when threadId is `null` or `undefined`.
     * This enables optimistic UI updates where you know the thread ID
     * before the thread is actually created.
     */
    threadId?: string;
}
export declare function useStream<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends {
    ConfigurableType?: Record<string, unknown>;
    InterruptType?: unknown;
    CustomEventType?: unknown;
    UpdateType?: unknown;
} = BagTemplate>(options: UseStreamOptions<StateType, Bag>): UseStream<StateType, Bag>;
export {};
