import type { ComponentProps, SendEventForHits } from '../../types'; import type { SearchParameters } from 'algoliasearch-helper'; export type ChatStatus = 'ready' | 'submitted' | 'streaming' | 'error'; export type ChatRole = 'data' | 'user' | 'assistant' | 'system'; /** * Provider metadata type for UI message parts. */ export type ProviderMetadata = Record>; /** * A record of data types for data parts in UI messages. */ export type UIDataTypes = Record; /** * Tool input/output type definition. */ export type UITool = { input: unknown; output: unknown | undefined; }; /** * A record of UI tools. */ export type UITools = Record; /** * Helper type to get values of an object. */ type ValueOf = T[keyof T]; /** * Deep partial type. */ type DeepPartial = T extends object ? { [P in keyof T]?: DeepPartial; } : T; /** * A text part of a message. */ export type TextUIPart = { type: 'text'; text: string; state?: 'streaming' | 'done'; providerMetadata?: ProviderMetadata; }; /** * A reasoning part of a message. */ export type ReasoningUIPart = { type: 'reasoning'; text: string; state?: 'streaming' | 'done'; providerMetadata?: ProviderMetadata; }; /** * A source URL part of a message. */ export type SourceUrlUIPart = { type: 'source-url'; sourceId: string; url: string; title?: string; providerMetadata?: ProviderMetadata; }; /** * A document source part of a message. */ export type SourceDocumentUIPart = { type: 'source-document'; sourceId: string; mediaType: string; title: string; filename?: string; providerMetadata?: ProviderMetadata; }; /** * A file part of a message. */ export type FileUIPart = { type: 'file'; mediaType: string; filename?: string; url: string; providerMetadata?: ProviderMetadata; }; /** * A step boundary part of a message. */ export type StepStartUIPart = { type: 'step-start'; }; /** * A data part of a message. */ export type DataUIPart = ValueOf<{ [NAME in keyof TDataTypes & string]: { type: `data-${NAME}`; id?: string; data: TDataTypes[NAME]; }; }>; /** * A tool invocation part of a message. */ export type ToolUIPart = ValueOf<{ [NAME in keyof TTools & string]: { type: `tool-${NAME}`; toolCallId: string; } & ({ state: 'input-streaming'; input: DeepPartial | undefined; providerExecuted?: boolean; output?: never; errorText?: never; } | { state: 'input-available'; input: TTools[NAME]['input']; providerExecuted?: boolean; output?: never; errorText?: never; callProviderMetadata?: ProviderMetadata; } | { state: 'output-available'; input: TTools[NAME]['input']; output: TTools[NAME]['output']; errorText?: never; providerExecuted?: boolean; callProviderMetadata?: ProviderMetadata; preliminary?: boolean; } | { state: 'output-error'; input: TTools[NAME]['input'] | undefined; rawInput?: unknown; output?: never; errorText: string; providerExecuted?: boolean; callProviderMetadata?: ProviderMetadata; }); }>; /** * A dynamic tool invocation part of a message. */ export type DynamicToolUIPart = { type: 'dynamic-tool'; toolName: string; toolCallId: string; } & ({ state: 'input-streaming'; input: unknown | undefined; output?: never; errorText?: never; } | { state: 'input-available'; input: unknown; output?: never; errorText?: never; callProviderMetadata?: ProviderMetadata; } | { state: 'output-available'; input: unknown; output: unknown; errorText?: never; callProviderMetadata?: ProviderMetadata; preliminary?: boolean; } | { state: 'output-error'; input: unknown; output?: never; errorText: string; callProviderMetadata?: ProviderMetadata; }); /** * All possible message part types. */ export type UIMessagePart = TextUIPart | ReasoningUIPart | ToolUIPart | DynamicToolUIPart | SourceUrlUIPart | SourceDocumentUIPart | FileUIPart | DataUIPart | StepStartUIPart; /** * AI SDK UI Messages. They are used in the client and to communicate between the frontend and the API routes. */ export interface UIMessage { /** A unique identifier for the message. */ id: string; /** The role of the message. */ role: 'system' | 'user' | 'assistant'; /** The metadata of the message. */ metadata?: TMetadata; /** The parts of the message. Use this for rendering the message in the UI. */ parts: Array>; } export type ChatMessageBase = UIMessage; export type ChatToolMessage = Extract; export type ChatToolType = ChatToolMessage['type']; /** * Infer metadata type from UIMessage. */ export type InferUIMessageMetadata = T extends UIMessage ? TMetadata : unknown; /** * Infer data types from UIMessage. */ export type InferUIMessageData = T extends UIMessage ? TDataTypes : UIDataTypes; /** * Infer tools from UIMessage. */ export type InferUIMessageTools = T extends UIMessage ? TTools : UITools; /** * Chat state interface. */ export interface ChatState { status: ChatStatus; error: Error | undefined; messages: TUIMessage[]; pushMessage: (message: TUIMessage) => void; popMessage: () => void; replaceMessage: (index: number, message: TUIMessage) => void; snapshot: (thing: T) => T; } /** * ID generator function type. */ export type IdGenerator = () => string; /** * Callback function to be called when an error is encountered. */ export type ChatOnErrorCallback = (error: Error) => void; /** * Infer tool call type from UIMessage. */ export type InferUIMessageToolCall = ValueOf<{ [NAME in keyof InferUIMessageTools]: { toolName: NAME & string; toolCallId: string; input: InferUIMessageTools[NAME] extends { input: infer INPUT; } ? INPUT : never; dynamic?: false; }; }> | { toolName: string; toolCallId: string; input: unknown; dynamic: true; }; /** * Optional callback function that is invoked when a tool call is received. */ export type ChatOnToolCallCallback = (options: { toolCall: InferUIMessageToolCall; }) => void | PromiseLike; /** * Function that is called when the assistant response has finished streaming. */ export type ChatOnFinishCallback = (options: { message: TUIMessage; messages: TUIMessage[]; isAbort: boolean; isDisconnect: boolean; isError: boolean; }) => void; /** * Optional callback function that is called when a data part is received. */ export type ChatOnDataCallback = (dataPart: DataUIPart>) => void; /** * Transport interface for sending and receiving chat messages. */ export interface ChatTransport { sendMessages: (options: { chatId: string; messages: TUIMessage[]; abortSignal: AbortSignal; requestMetadata?: unknown; trigger: 'submit-message' | 'regenerate-message'; messageId?: string; }) => Promise>; reconnectToStream: (options: { chatId: string; }) => Promise | null>; } /** * Chat initialization options. */ export interface ChatInit { /** A unique identifier for the chat. If not provided, a random one will be generated. */ id?: string; messages?: TUIMessage[]; /** A way to provide a function for generating message and chat IDs. */ generateId?: IdGenerator; transport?: ChatTransport; /** Callback function to be called when an error is encountered. */ onError?: ChatOnErrorCallback; /** Optional callback function that is invoked when a tool call is received. */ onToolCall?: ChatOnToolCallCallback; /** Function that is called when the assistant response has finished streaming. */ onFinish?: ChatOnFinishCallback; /** Optional callback function that is called when a data part is received. */ onData?: ChatOnDataCallback; /** * When provided, this function will be called when the stream is finished or a tool call is added * to determine if the current messages should be resubmitted. */ sendAutomaticallyWhen?: (options: { messages: TUIMessage[]; }) => boolean | PromiseLike; } /** * Abstract base class for chat implementations. */ export interface AbstractChat { readonly id: string; readonly generateId: IdGenerator; status: ChatStatus; error: Error | undefined; messages: TUIMessage[]; lastMessage: TUIMessage | undefined; sendMessage: (message?: (Omit & { id?: TUIMessage['id']; role?: TUIMessage['role']; text?: never; files?: never; messageId?: string; }) | { text: string; files?: FileList | FileUIPart[]; metadata?: InferUIMessageMetadata; parts?: never; messageId?: string; } | { files: FileList | FileUIPart[]; metadata?: InferUIMessageMetadata; parts?: never; messageId?: string; }, options?: { headers?: Record | Headers; body?: object; }) => Promise; regenerate: (options?: { messageId?: string; } & { headers?: Record | Headers; body?: object; }) => Promise; resumeStream: (options?: { headers?: Record | Headers; body?: object; }) => Promise; clearError: () => void; addToolResult: >(params: { tool: TTool; toolCallId: string; output: InferUIMessageTools[TTool]['output']; }) => Promise; stop: () => Promise; } export type AddToolResult = AbstractChat['addToolResult']; export type AddToolResultWithOutput = (params: Pick[0], 'output'>) => ReturnType; export type SearchToolInput = { query: string; number_of_results?: number; facet_filters?: string[][]; }; export type ApplyFiltersParams = { query?: string; facetFilters?: string[][]; }; export type ChatLayoutOwnProps = { open: boolean; maximized: boolean; headerComponent: JSX.Element; messagesComponent: JSX.Element; promptComponent: JSX.Element; toggleButtonComponent: JSX.Element; classNames?: { root?: string | string[]; container?: string | string[]; }; isClearing?: boolean; clearMessages?: () => void; onClearTransitionEnd?: () => void; suggestions?: string[]; tools: ClientSideTools; } & Pick, 'messages'> & Partial, 'status'>> & Pick, 'sendMessage' | 'regenerate' | 'stop' | 'error'> & ComponentProps<'div'>; export type ClientSideToolComponentProps = { message: ChatToolMessage; indexUiState: object; setIndexUiState: (state: object) => void; onClose: () => void; addToolResult: AddToolResultWithOutput; applyFilters: (params: ApplyFiltersParams) => SearchParameters; sendEvent: SendEventForHits; }; export type ClientSideToolComponent = (props: ClientSideToolComponentProps) => JSX.Element; export type ClientSideTool = { layoutComponent?: ClientSideToolComponent; addToolResult: AddToolResult; sendEvent?: SendEventForHits; onToolCall?: (params: Parameters['onToolCall']>>[0]['toolCall'] & { addToolResult: AddToolResultWithOutput; }) => void; applyFilters: (params: ApplyFiltersParams) => SearchParameters; }; export type ClientSideTools = Record; export type UserClientSideTool = Omit; export type UserClientSideTools = Record; export type ChatEmptyProps = { /** * Function to send a message to the chat */ sendMessage?: ChatLayoutOwnProps['sendMessage']; /** * Current chat status */ status?: ChatStatus; /** * Callback to close the chat */ onClose?: () => void; /** * Function to set the prompt input value */ setInput?: (input: string) => void; }; export {};