UNPKG

@nlux/core

Version:

nlux is JavaScript and React library for building conversational AI interfaces, with support for OpenAI, Hugging Face, and more.

1,248 lines (1,210 loc) 75 kB
/** * A single item in the conversation. * This can be a message from the user, the assistant, or a system message. * * - `role: 'assistant'`: A message from the assistant (an AI response). * The message type is generic and should match the generic type `AiMsg` used across the component. * The `serverResponse` field is optional and can be used to store the full response received from the server. * * - `role: 'user'`: A message from the user. * This is typically a string representing the prompt typed by the user. * * - `role: 'system'`: A system message. * This message is not displayed in the UI, but it will be used to when sending the conversation history to the AI. */ type ChatItem$1<AiMsg = string> = { role: 'assistant'; message: AiMsg; serverResponse?: string | object | undefined; } | { role: 'user'; message: string; } | { role: 'system'; message: string; }; /** * Additional data sent to the adapter when a message is sent. */ type ChatAdapterExtras$1<AiMsg = string> = { /** * This attribute contains the properties used with the AiChat component. */ aiChatProps: AiChatPropsInEvents<AiMsg>; /** * This attribute contains the conversation history. * It's only included if the `conversationOptions.historyPayloadSize` is set to a positive number or 'all'. */ conversationHistory?: ChatItem$1<AiMsg>[]; /** * This attribute contains the unique identifier of the context instance. * It's only included if a context instance is used with the AiChat component. * This can be used to send the context ID to the API and get a response that is specific to the context instance. */ contextId?: string; /** * This contains the headers that implementers can use to send additional data such as authentication headers. */ headers?: Record<string, string>; }; /** * This type is used to indicate the mode in which the adapter should request data from the API. */ type DataTransferMode$1 = 'stream' | 'batch'; /** * The type for the function used to submit a message to the API in stream mode. * * @param {string} message * @param {StreamingAdapterObserver} observer * @param {ChatAdapterExtras} extras */ type StreamSend<AiMsg = string> = (message: string, observer: StreamingAdapterObserver$1<AiMsg>, extras: ChatAdapterExtras$1<AiMsg>) => void; /** * The type for the function used to submit a message to the API in batch mode. * It should return a promise that resolves to the response from the API. * * @param `string` message * @param `ChatAdapterExtras` extras * @returns Promise<string> */ type BatchSend<AiMsg = string> = (message: string, extras: ChatAdapterExtras$1<AiMsg>) => Promise<AiMsg>; /** * This interface exposes methods that should be implemented by any chat adapter to connect the AiChat component * to any API or AI backend. Chat adapters can be used to request data from the API in batch mode or stream mode. * * The difference between this and the `AssistAdapter` interface is that this adapter can only return a text response * to be displayed to the user. It cannot return a task to be executed by the client. If you are using the `AiChat` * component in co-pilot mode, you should use the `AssistAdapter` interface instead. */ interface ChatAdapter<AiMsg = string> { /** * This method should be implemented by any adapter that wants to request data from the API in batch mode. * It should return a promise that resolves to the response from the API. * Either this method or `streamText` (or both) should be implemented by any adapter. * * @param `string` message * @param `ChatAdapterExtras` extras * @returns Promise<string> */ batchText?: BatchSend<AiMsg>; /** * This method should be implemented by any adapter to be used with nlux. * Either this method or `batchText` (or both) should be implemented by any adapter. * * @param {string} message * @param {StreamingAdapterObserver} observer * @param {ChatAdapterExtras} extras */ streamText?: StreamSend<AiMsg>; } /** * This interface is used to capture the stream of data being generated by the API and send it to the AiChat * user interface as it's being generated. */ interface StreamingAdapterObserver$1<ChunkType = string> { /** * This method should be called by the adapter when it has completed sending data to the AiChat user interface. * This will result in the AiChat component removing the loading indicator and resetting the conversation * text input. */ complete(): void; /** * This method should be called by the adapter when it has an error to send to the AiChat user interface. * This will result in the AiChat component displaying an error message to the user, resetting the * conversation text input, removing the loading indicator, removing the message sent from the conversation. * * The error will be logged to the console, but it will not be displayed to the user. A generic error message * will be displayed to the user instead. * * @param {Error} error */ error(error: Error): void; /** * This method should be called by the adapter when it has new data to send to the AiChat user interface. * @param {ChunkType} chunk being sent as part of the stream. */ next(chunk: ChunkType): void; } /** * This type is used to indicate the mode in which the adapter should request data from the API. */ type DataTransferMode = 'stream' | 'batch'; /** * This interface is used to capture the stream of data being generated by the API and send it to the AiChat * user interface as it's being generated. */ interface StreamingAdapterObserver<ChunkType = string> { /** * This method should be called by the adapter when it has completed sending data to the AiChat user interface. * This will result in the AiChat component removing the loading indicator and resetting the conversation * text input. */ complete(): void; /** * This method should be called by the adapter when it has an error to send to the AiChat user interface. * This will result in the AiChat component displaying an error message to the user, resetting the * conversation text input, removing the loading indicator, removing the message sent from the conversation. * * The error will be logged to the console, but it will not be displayed to the user. A generic error message * will be displayed to the user instead. * * @param {Error} error */ error(error: Error): void; /** * This method should be called by the adapter when it has new data to send to the AiChat user interface. * @param {ChunkType} chunk being sent as part of the stream. */ next(chunk: ChunkType): void; } /** * This type represents the information that the AiChat needs to know about an adapter. * It is used to determine which adapters are available and what capabilities they have. */ type StandardAdapterInfo$1 = Readonly<{ id: string; capabilities: Readonly<{ chat: boolean; fileUpload: boolean; textToSpeech: boolean; speechToText: boolean; }>; }>; /** * This interface is used by standard adapters provided by nlux to communicate with the AiChat component. */ interface StandardChatAdapter$1<AiMsg = string> { batchText(message: string, extras: ChatAdapterExtras$1<AiMsg>): Promise<string | object | undefined>; get dataTransferMode(): DataTransferMode; get id(): string; get info(): StandardAdapterInfo$1; preProcessAiBatchedMessage(message: string | object | undefined, extras: ChatAdapterExtras$1<AiMsg>): AiMsg | undefined; preProcessAiStreamedChunk(chunk: string | object | undefined, extras: ChatAdapterExtras$1<AiMsg>): AiMsg | undefined; streamText(message: string, observer: StreamingAdapterObserver<string | object | undefined>, extras: ChatAdapterExtras$1<AiMsg>): void; } /** * The base interface for creating a new instance of a StandardChatAdapter. * Adapter builders can extend this interface to add additional methods for configuration. */ interface ChatAdapterBuilder<AiMsg> { create(): StandardChatAdapter$1<AiMsg>; } /** * This interface is used by standard adapters provided by nlux to communicate with the AiChat component. */ interface StandardChatAdapter<AiMsg = string> { batchText(message: string, extras: ChatAdapterExtras$1<AiMsg>): Promise<string | object | undefined>; get dataTransferMode(): DataTransferMode; get id(): string; get info(): StandardAdapterInfo$1; preProcessAiBatchedMessage(message: string | object | undefined, extras: ChatAdapterExtras$1<AiMsg>): AiMsg | undefined; preProcessAiStreamedChunk(chunk: string | object | undefined, extras: ChatAdapterExtras$1<AiMsg>): AiMsg | undefined; streamText(message: string, observer: StreamingAdapterObserver<string | object | undefined>, extras: ChatAdapterExtras$1<AiMsg>): void; } /** * A single item in the conversation. * This can be a message from the user, the assistant, or a system message. * * - `role: 'assistant'`: A message from the assistant (an AI response). * The message type is generic and should match the generic type `AiMsg` used across the component. * The `serverResponse` field is optional and can be used to store the full response received from the server. * * - `role: 'user'`: A message from the user. * This is typically a string representing the prompt typed by the user. * * - `role: 'system'`: A system message. * This message is not displayed in the UI, but it will be used to when sending the conversation history to the AI. */ type ChatItem<AiMsg = string> = { role: 'assistant'; message: AiMsg; serverResponse?: string | object | undefined; } | { role: 'user'; message: string; } | { role: 'system'; message: string; }; interface ComposerOptions { /** * Indicates whether the prompt input field should be focused when the prompt is shown. * @default false */ autoFocus?: boolean; /** * This will override the disabled state of the submit button when the composer is in 'typing' status. * It will not have any impact in the composer 'submitting-prompt' and 'waiting' statuses, as the submit button * is always disabled in these statuses. * * @default: Submit button is only enabled when the message is not empty. */ disableSubmitButton?: boolean; /** * Indicates whether the stop button should be hidden. * * @default false */ hideStopButton?: boolean; /** * The placeholder message to be displayed in the prompt input field when empty. */ placeholder?: string; /** * The shortcut to submit the prompt message. * * - `Enter`: The user can submit the prompt message by pressing the `Enter` key. In order to add a new line, the * user can press `Shift + Enter`. * - `CommandEnter`: When this is used, the user can submit the prompt message by pressing `Ctrl + Enter` on * Windows/Linux or `Cmd + Enter` on macOS. In order to add a new line, the user can press `Enter`. * * @default 'Enter' */ submitShortcut?: 'Enter' | 'CommandEnter'; } /** * This represents a single item displayed in the chat UI while the conversation has not started yet. * */ type ConversationStarter = { /** * The prompt to type in the composer input and submit to start the conversation. */ prompt: string; /** * An optional label to display inside the conversation starter option button. */ label?: string; /** * An optional icon to display inside the conversation starter option button. * This could either be a URL to an image or an HTML element. */ icon?: string | Readonly<HTMLElement>; }; type HistoryPayloadSize = number | 'max'; type ConversationLayout = 'bubbles' | 'list'; interface ConversationOptions { /** * Indicates whether the conversation should be scrolled to the bottom when a new message is added. * * @default true */ autoScroll?: boolean; /** * Suggested prompts to display in the UI to help the user start a conversation. * Conversation starters are only displayed when the conversation is empty, and no conversation history is present. */ conversationStarters?: ConversationStarter[]; /** * Indicates the number of messages from conversation history that should be sent to the backend with each message. * For custom adapters, the history will be available as part of `extras.conversationHistory` attribute. * For standard adapters, the history will be automatically handled by the adapter. * * By default, the entire conversation history is sent with each message. * Set to `0` to disable sending conversation history with each message. * Or set to a positive integer to send a specific number of messages. * * @default 'max' */ historyPayloadSize?: HistoryPayloadSize; /** * Indicates how items in the conversation should be displayed. * * - `list`: Chat items are displayed as a list with the AI responses underneath each user message. * - `bubbles`: Items are displayed as chat bubbles with the prompts on the right and the AI messages on the left. * * @default 'bubbles' */ layout?: ConversationLayout; /** * Indicates whether the welcome message should be displayed when no conversation history is provided. * The welcome message consists of: * - The assistant's name and avatar * - The assistant's tagline as configured in the `personaOptions` * * When no assistant persona is provided, the welcome message will be the NLUX logo. */ showWelcomeMessage?: boolean; } type DisplayOptions = { /** * The theme ID to use. * This should be the ID of a theme that has been loaded into the page. */ themeId?: string; /** * Color scheme for the component. * This can be 'light', 'dark', or 'auto'. * * If 'auto' is used, the component will automatically switch between 'light' and 'dark' based on the user's * operating system preferences (if it can be detected), otherwise it will default to 'light'. * * @default 'auto' */ colorScheme?: 'light' | 'dark' | 'auto'; /** * The width of the component. */ width?: number | string; /** * The height of the component. */ height?: number | string; }; /** * A type representing a function to use as HTML sanitizer. * This type can be passed to markdown parser, to be used to sanitize generated * HTML before appending it to the document. */ type SanitizerExtension = (html: string) => string; type Highlighter = (input: string, language: string) => string; type HighlighterColorMode = 'dark' | 'light'; type CreateHighlighterOptions = { language?: string; colorMode?: HighlighterColorMode; }; interface HighlighterExtension { createHighlighter(options?: CreateHighlighterOptions): Highlighter; highlightingClass(language?: string): string; } /** * Props for the custom function that renders a message sent by the server in batch mode. * @template AiMsg The type of the message received from the AI. Defaults to string for standard NLUX adapters. * * @property {string} uid The unique identifier of the message. * @property {'batch'} dataTransferMode The data transfer mode used by the adapter. * @property {'complete'} status The status of the message. * * @property {AiMsg} content The content of the message. The content is a single message. * @property {unknown} serverResponse The raw server response. The server response is a single object or string * representing the raw response received from the server. */ type ResponseRendererProps<AiMsg> = { uid: string; dataTransferMode: 'stream' | 'batch'; status: 'streaming' | 'complete'; content: [AiMsg]; serverResponse: unknown[]; }; type ResponseRenderer<AiMsg> = (props: ResponseRendererProps<AiMsg>) => HTMLElement | null; type PromptRendererProps = { uid: string; prompt: string; }; type PromptRenderer = (props: PromptRendererProps) => HTMLElement | null; type MessageOptions<AiMsg = string> = { /** * Highlighter extension for code blocks inside messages. */ syntaxHighlighter?: HighlighterExtension; /** * Custom function to sanitize the HTML content of the messages. This function is called before any HTML content * is rendered in the chat. * * @param {string} html * @returns {string} */ htmlSanitizer?: SanitizerExtension; /** * Indicates the target of the links in the markdown messages. * - 'blank': Open links in a new tab. * - 'self': Open links in the same tab. * * @default 'blank' */ markdownLinkTarget?: 'blank' | 'self'; /** * Indicates whether the copy button should be shown for code blocks. * * @default true */ showCodeBlockCopyButton?: boolean; /** * Indicates whether the streaming animation should be skipped. * * @default false */ skipStreamingAnimation?: boolean; /** * The interval in milliseconds at which new characters are added when a message is being generated and * streamed to the user. * * @default 10 */ streamingAnimationSpeed?: number; /** * In streaming data transfer mode, this represents the wait time in milliseconds after last chunk of data * is received before marking the streaming as complete. This can be used to prevent the streaming from being * marked as complete too early. * * If set to 'never', the streaming will never be automatically be marked as complete. It will be up to the * adapter to manually mark the streaming as complete by calling the `observer.complete()` method. * * @default 2000 */ waitTimeBeforeStreamCompletion?: number | 'never'; /** * Custom function to render the message received from the AI. */ responseRenderer?: ResponseRenderer<AiMsg>; /** * Custom function to render the message sent by the user. */ promptRenderer?: PromptRenderer; /** * Indicates whether the user should be able to edit the message after sending it. * Editing a message will replace the original message and will remove all subsequent messages in the conversation. * * @default false */ editableUserMessages?: boolean; }; interface AssistantPersona { avatar: string | Readonly<HTMLElement>; name: string; tagline?: string; } interface UserPersona { avatar: string | Readonly<HTMLElement>; name: string; } interface PersonaOptions { assistant?: AssistantPersona; user?: UserPersona; } declare const NLErrors: { 'data-transfer-mode-not-supported': string; 'no-data-transfer-mode-supported': string; 'connection-error': string; 'invalid-credentials': string; 'invalid-api-key': string; 'http-server-side-error': string; 'http-client-side-error': string; 'failed-to-load-content': string; 'failed-to-stream-content': string; 'failed-to-stream-server-component': string; 'failed-to-render-content': string; }; type NLErrorId = keyof typeof NLErrors; /** * These are the props that are used internally by the AiChat component. */ type AiChatInternalProps<AiMsg> = { adapter: ChatAdapter<AiMsg> | StandardChatAdapter<AiMsg>; className?: string; events?: EventsConfig<AiMsg>; initialConversation?: ChatItem<AiMsg>[]; displayOptions: DisplayOptions; personaOptions: PersonaOptions; composerOptions: ComposerOptions; conversationOptions: ConversationOptions; messageOptions: MessageOptions<AiMsg>; }; /** * These are the props that are exposed to the user of the AiChat component. */ type AiChatProps<AiMsg = string> = { adapter: ChatAdapter<AiMsg> | StandardChatAdapter<AiMsg>; className?: string; events?: EventsConfig<AiMsg>; initialConversation?: ChatItem<AiMsg>[]; composerOptions?: ComposerOptions; conversationOptions?: ConversationOptions; messageOptions?: MessageOptions<AiMsg>; personaOptions?: PersonaOptions; displayOptions?: DisplayOptions; }; /** * When sending props to event callbacks, we exclude the adapter and events properties. * This is because they are not serializable and because the events are already being called. */ type AiChatPropsInEvents<AiMsg = string> = Omit<AiChatProps<AiMsg>, 'adapter' | 'events'>; /** * This type represents the props that can be updated on the AiChat component, after it has been initialized. * It excludes the initialConversation property because it's only used during initialization and cannot be updated. */ type UpdatableAiChatProps<AiMsg> = Partial<Omit<AiChatProps<AiMsg>, 'initialConversation'>>; type MessageSentEventDetails = { uid: string; message: string; }; type MessageStreamStartedEventDetails = { uid: string; }; type ServerComponentStreamStartedEventDetails = { uid: string; }; type ServerComponentRenderedEventDetails = { uid: string; }; type MessageRenderedEventDetails<AiMsg = string> = { uid: string; message?: AiMsg; }; type MessageReceivedEventDetails<AiMsg = string> = { uid: string; message: AiMsg; }; type ErrorEventDetails = { errorId: NLErrorId; message: string; errorObject?: Error; }; type ReadyEventDetails<AiMsg = string> = { aiChatProps: AiChatPropsInEvents<AiMsg>; }; type PreDestroyEventDetails<AiMsg = string> = { aiChatProps: AiChatPropsInEvents<AiMsg>; conversationHistory: Readonly<ChatItem<AiMsg>[]>; }; /** * The callback for when an error event is emitted. * * @param errorDetails The details of the error event such as the error message and the error id. */ type ErrorCallback = (errorDetails: ErrorEventDetails) => void; /** * The callback for when a message is sent. * This is called when the chat component sends the message to the adapter. * * @param message The message that was sent. */ type MessageSentCallback = (event: MessageSentEventDetails) => void; /** * The callback for when a response starts streaming from the adapter. * This is called when the chat component receives the first part of the response from the adapter. * This does not mean that the message has been rendered yet. You should use the messageRendered event * if you want to know when the message has been rendered. * * @param event The event details such as the uid of the message. */ type MessageStreamStartedCallback = (event: MessageStreamStartedEventDetails) => void; /** * The callback for when a server component stream starts. * This is used with React Server Component adapters to trigger an event when the component is about * to get mounted. */ type ServerComponentStreamStartedCallback = (event: ServerComponentStreamStartedEventDetails) => void; /** * The callback for when a server component is loaded and successfully rendered on the screen. * * @param event The event details such as the uid of the message. */ type ServerComponentRenderedCallback = (event: ServerComponentRenderedEventDetails) => void; /** * The callback for when a message is received. * This is called when the chat component receives the full response from the adapter. * This does not mean that the message has been rendered yet. You should use the messageRendered * event if you want to know when the message has been rendered. * * @param event The event details such as the uid of the message and the message content. */ type MessageReceivedCallback<AiMsg = string> = (event: MessageReceivedEventDetails<AiMsg>) => void; /** * The callback for when a message is fully rendered on the screen. * This event is only relevant when the user is using the NLUX markdown renderer. * If the user is using a custom renderer and directly accessing the props.content property to render the message, * this event will not be relevant. * * @param event The event details such as the uid of the message. */ type MessageRenderedCallback<AiMsg = string> = (event: MessageRenderedEventDetails<AiMsg>) => void; /** * The callback for when the chat component is ready. * This is called when the chat component is fully initialized and ready to be used. * * @param readyDetails The details of the ready event such as the AiChatProps used to initialize the chat component. */ type ReadyCallback<AiMsg = string> = (readyDetails: ReadyEventDetails<AiMsg>) => void; /** * The callback for when the chat component is about to be destroyed. * This is called when the chat component is about to be destroyed and unmounted from the DOM. * * @param preDestroyDetails The details of the pre-destroy event such as the AiChatProps used to initialize the chat * component and the conversation history. */ type PreDestroyCallback<AiMsg = string> = (preDestroyDetails: PreDestroyEventDetails<AiMsg>) => void; type EventsMap<AiMsg> = { ready: ReadyCallback<AiMsg>; preDestroy: PreDestroyCallback<AiMsg>; messageSent: MessageSentCallback; messageStreamStarted: MessageStreamStartedCallback; messageReceived: MessageReceivedCallback<AiMsg>; messageRendered: MessageRenderedCallback<AiMsg>; serverComponentStreamStarted: ServerComponentStreamStartedCallback; serverComponentRendered: ServerComponentRenderedCallback; error: ErrorCallback; }; type EventName = keyof EventsMap<unknown>; type EventCallback<AiMsg = string> = EventsMap<AiMsg>[EventName]; type EventsConfig<AiMsg = string> = Partial<EventsMap<AiMsg>>; /** * The status of the AiChat component. * - `idle`: The component has not been mounted yet. * - `mounted`: The component is currently mounted and active. It can be visible or hidden. * - `unmounted`: The component has been unmounted and destroyed and cannot be used anymore. */ type AiChatStatus = 'idle' | 'mounted' | 'unmounted'; /** * The main interface representing AiChat component. * It provides methods to instantiate, mount, and unmount the component, and listen to its events. */ interface IAiChat<AiMsg> { /** * Hides the chat component. * This does not unmount the component. It will only hide the chat component from the view. */ hide(): void; /** * Mounts the chat component to the given root element. * * @param {HTMLElement} rootElement */ mount(rootElement: HTMLElement): void; /** * Adds an event listener to the chat component. * The callback will be called when the event is emitted, with the expected event details. * * @param {EventName} event The name of the event to listen to. * @param {EventsMap[EventName]} callback The callback to be called, that should match the event type. * @returns {IAiChat} */ on(event: EventName, callback: EventsMap<AiMsg>[EventName]): IAiChat<AiMsg>; /** * Removes all event listeners from the chat component for a specific event. * * @param {EventName} event */ removeAllEventListeners(event: EventName): void; /** * Removes the given event listener for the specified event. * * @param {EventName} event The name of the event to remove the listener from. * @param {EventsMap[EventName]} callback The callback to be removed. */ removeEventListener(event: EventName, callback: EventCallback<AiMsg>): void; /** * Shows the chat component. * This method expects the chat component to be mounted. */ show(): void; /** * Returns true if the chat component is mounted. */ get status(): AiChatStatus; /** * Unmounts the chat component. * This will remove the chat component from the view and clean up its resources. * After unmounting, the chat component cannot be mounted again as all its resources, options, event listeners, and * adapters will be removed. You should create a new chat component if you want to use it again. */ unmount(): void; /** * Updates the properties of the chat component. This method expects the chat component to be mounted. * The properties will be updated and the relevant parts of the chat component will be re-rendered. * * @param {UpdatableAiChatProps} props The properties to be updated. */ updateProps(props: UpdatableAiChatProps<AiMsg>): void; /** * Enabled providing an adapter to the chat component. * The adapter will be used to send and receive messages from the chat backend. * This method should be called before mounting the chat component, and it should be called only once. * * @param {adapter: ChatAdapter | StandardChatAdapter | ChatAdapterBuilder} adapter The builder for the chat * adapter. */ withAdapter(adapter: ChatAdapter<AiMsg> | StandardChatAdapter<AiMsg> | ChatAdapterBuilder<AiMsg>): IAiChat<AiMsg>; /** * Enables providing a class name to the chat component. * The class name will be added to the root element of the chat component. * This method should be called before mounting the chat component, and it should be called only once. * * @param {string} className The class name to be added to the chat component. */ withClassName(className: string): IAiChat<AiMsg>; /** * Enables providing composer options to the chat component. * This method can be called before mounting the chat component, and it can be called only once. * * @param {ComposerOptions} composerOptions The composer options to be used. */ withComposerOptions(composerOptions: ComposerOptions): IAiChat<AiMsg>; /** * The conversation options will be used to configure the conversation behavior and display. * This method can be called before mounting the chat component, and it can be called only once. * * @param {ConversationOptions} conversationOptions The conversation options to be used. */ withConversationOptions(conversationOptions: ConversationOptions): IAiChat<AiMsg>; /** * Enables providing display options to the chat component. The display options will be used to configure the * layout of the chat component. When no display options are provided, the default display options will be used. * This method can be called before mounting the chat component, and it can be called only once. * * @param {DisplayOptions} displayOptions The display options to be used. */ withDisplayOptions(displayOptions: DisplayOptions): IAiChat<AiMsg>; /** * Enables providing an initial conversation to the chat component. * The initial conversation will be used to populate the chat component with a conversation history. * This method can be called before mounting the chat component, and it can be called only once. * * @param {ChatItem[]} initialConversation * @returns {IAiChat} */ withInitialConversation(initialConversation: ChatItem<AiMsg>[]): IAiChat<AiMsg>; /** * Enables providing message options to the chat component. * The message options will be used to configure the behavior and the * display of the messages inside the chat component. * * @param {MessageOptions<AiMsg>} messageOptions * @returns {IAiChat<AiMsg>} */ withMessageOptions(messageOptions: MessageOptions<AiMsg>): IAiChat<AiMsg>; /** * Enables providing persona options to the chat component. The persona options will be used to configure * the assistant and user personas in the chat component. * This method can be called before mounting the chat component, and it can be called only once. * * @param {PersonaOptions} personaOptions The persona options to be used. */ withPersonaOptions(personaOptions: PersonaOptions): IAiChat<AiMsg>; } declare class AiChat<AiMsg = string> implements IAiChat<AiMsg> { protected theAdapter: ChatAdapter<AiMsg> | StandardChatAdapter<AiMsg> | null; protected theAdapterBuilder: ChatAdapterBuilder<AiMsg> | null; protected theAdapterType: 'builder' | 'instance' | null; protected theClassName: string | null; protected theComposerOptions: ComposerOptions | null; protected theConversationOptions: ConversationOptions | null; protected theDisplayOptions: DisplayOptions | null; protected theInitialConversation: ChatItem<AiMsg>[] | null; protected theMessageOptions: MessageOptions<AiMsg> | null; protected thePersonasOptions: PersonaOptions | null; private aiChatStatus; private controller; private unregisteredEventListeners; get status(): AiChatStatus; private get isIdle(); hide(): void; mount(rootElement: HTMLElement): void; on(event: EventName, callback: EventsMap<AiMsg>[EventName]): this; removeAllEventListeners(event: EventName): void; removeEventListener(event: EventName, callback: EventCallback<AiMsg>): void; show(): void; unmount(): void; updateProps(props: UpdatableAiChatProps<AiMsg>): void; withAdapter(adapter: ChatAdapter<AiMsg> | StandardChatAdapter<AiMsg> | ChatAdapterBuilder<AiMsg>): this; withClassName(className: string): this; withComposerOptions(composerOptions: ComposerOptions): this; withConversationOptions(conversationOptions: ConversationOptions): this; withDisplayOptions(displayOptions: DisplayOptions): this; withInitialConversation(initialConversation: ChatItem<AiMsg>[]): this; withMessageOptions(messageOptions: MessageOptions<AiMsg>): this; withPersonaOptions(personaOptions: PersonaOptions): this; private clearEventListeners; } interface IObserver<DataType> { complete?(): void; error?(error: Error): void; next(value: DataType): void; } declare class Observable<DataType> { private buffer; private errorReceived; private isCompleted; private readonly isReplayObservable; private subscribers; constructor({ replay }?: { replay?: boolean; }); complete(): void; error(error: Error): void; next(value: DataType): void; reset(): void; subscribe(observer: IObserver<DataType>): { unsubscribe: () => void; }; unsubscribe(observer: IObserver<DataType>): void; private sendBufferToObserver; } type OutputFormat = 'text' | 'audio' | 'markdown' | 'html' | 'image' | 'video' | 'file'; type InputFormat = 'text'; type AdapterEncodeFunction<OutboundPayload> = (input: string) => Promise<OutboundPayload>; type AdapterDecodeFunction<InboundPayload> = <AiMsg>(output: InboundPayload) => Promise<AiMsg | undefined>; /** * This type represents the information that the AiChat needs to know about an adapter. * It is used to determine which adapters are available and what capabilities they have. */ type StandardAdapterInfo = Readonly<{ id: string; capabilities: Readonly<{ chat: boolean; fileUpload: boolean; textToSpeech: boolean; speechToText: boolean; }>; }>; /** * Additional data sent to the adapter when a message is sent. */ type ChatAdapterExtras<AiMsg = string> = { /** * This attribute contains the properties used with the AiChat component. */ aiChatProps: AiChatPropsInEvents<AiMsg>; /** * This attribute contains the conversation history. * It's only included if the `conversationOptions.historyPayloadSize` is set to a positive number or 'all'. */ conversationHistory?: ChatItem$1<AiMsg>[]; /** * This attribute contains the unique identifier of the context instance. * It's only included if a context instance is used with the AiChat component. * This can be used to send the context ID to the API and get a response that is specific to the context instance. */ contextId?: string; /** * This contains the headers that implementers can use to send additional data such as authentication headers. */ headers?: Record<string, string>; }; /** * This type represents the result of an assist request. * * If the request was successful, the `success` property will be `true` and the `response` property will contain the * text response to be displayed to the user. In addition, when the `task` property is present, it will contain the * details of the task to be executed by the client. * * If the request was not successful, the `success` property will be `false` and the `error` property will contain the * error message to be displayed to the user. */ type AssistResult$1 = { success: true; response: string; task?: { id: string; parameters: string[]; }; } | { success: false; error: string; }; /** * This interface exposes methods that should be implemented by adapters used when the AiChat is in co-pilot mode. * The difference between this and the `ChatAdapter` interface is that this adapter can return a task to be executed * by the client in addition to the text response to be displayed. * * Assist adapters can only be used in batch mode, and the response cannot be streamed. */ interface AssistAdapter$1 { /** * This method should be implemented by any adapter that wants to request data from the API in batch mode. * It should return a promise that resolves to the response from the API. * Either this method or `streamText` (or both) should be implemented by any adapter. * * @param `string` message * @param `ChatAdapterExtras` extras * @returns Promise<string> */ assist?: (message: string, extras: ChatAdapterExtras$1<string>) => Promise<AssistResult$1>; } /** * This type represents the result of an assist request. * * If the request was successful, the `success` property will be `true` and the `response` property will contain the * text response to be displayed to the user. In addition, when the `task` property is present, it will contain the * details of the task to be executed by the client. * * If the request was not successful, the `success` property will be `false` and the `error` property will contain the * error message to be displayed to the user. */ type AssistResult = { success: true; response: string; task?: { id: string; parameters: string[]; }; } | { success: false; error: string; }; /** * This interface exposes methods that should be implemented by adapters used when the AiChat is in co-pilot mode. * The difference between this and the `ChatAdapter` interface is that this adapter can return a task to be executed * by the client in addition to the text response to be displayed. * * Assist adapters can only be used in batch mode, and the response cannot be streamed. */ interface AssistAdapter { /** * This method should be implemented by any adapter that wants to request data from the API in batch mode. * It should return a promise that resolves to the response from the API. * Either this method or `streamText` (or both) should be implemented by any adapter. * * @param `string` message * @param `ChatAdapterExtras` extras * @returns Promise<string> */ assist?: (message: string, extras: ChatAdapterExtras$1<string>) => Promise<AssistResult>; } /** * The base interface for creating a new instance of a StandardChatAdapter. * Adapter builders can extend this interface to add additional methods for configuration. */ interface AssistAdapterBuilder { /** * Create a new instance of an AssistAdapter. */ create(): AssistAdapter; } type StreamParser = (root: HTMLElement, syntaxHighlighter?: HighlighterExtension) => IObserver<string>; type StandardStreamParserOutput = { next(value: string): void; complete(): void; cancel(): void; error(error: Error): void; }; type StandardStreamParser = (root: HTMLElement, options?: { syntaxHighlighter?: HighlighterExtension; htmlSanitizer?: SanitizerExtension; markdownLinkTarget?: 'blank' | 'self'; showCodeBlockCopyButton?: boolean; skipStreamingAnimation?: boolean; streamingAnimationSpeed?: number; waitTimeBeforeStreamCompletion?: number | 'never'; onComplete?: () => void; }) => StandardStreamParserOutput; type ContextItemDataType$1 = number | string | boolean | null | ContextObject$1 | ContextItemDataType$1[]; type ContextObject$1 = { [key: string]: ContextItemDataType$1; }; type ContextItem$1 = { value: ContextItemDataType$1; description: string; }; type ContextItems$1 = Record<string, ContextItem$1>; type ContextTask$1 = { description: string; paramDescriptions: string[]; }; type ContextTasks$1 = Record<string, ContextTask$1>; type InitializeContextResult$1 = { success: true; contextId: string; } | { success: false; error: string; }; type DestroyContextResult$1 = { success: true; } | { success: false; error: string; }; type FlushContextResult$1 = { success: true; } | { success: false; error: string; }; type RunTaskResult$1 = { success: true; result?: unknown; } | { success: false; error: string; }; type ContextActionResult$1 = { success: true; } | { success: false; error: string; }; type SetContextResult$1 = { success: true; contextId: string; } | { success: false; error: string; }; type ContextItemDataType = number | string | boolean | null | ContextObject | ContextItemDataType[]; type ContextObject = { [key: string]: ContextItemDataType; }; type ContextItem = { value: ContextItemDataType; description: string; }; type ContextItems = Record<string, ContextItem>; type ContextTask = { description: string; paramDescriptions: string[]; }; type ContextTasks = Record<string, ContextTask>; /** * This represents a set of extra data that can be sent to the context adapter. * It can be used by implementations to send additional data such as authentication headers. */ type ContextAdapterExtras$1 = { /** * This contains the headers that implementers can use to send additional data such as authentication headers. */ headers?: Record<string, string>; }; /** * The context data adapter is responsible for synchronizing the context data between the frontend application * and the backend system. In order to build a context-aware chat experience and AI assistants, the context * adapter should be used. * * nlux does not set any restrictions on the context data structure or where and how the data should be stored, * but it expects the backend system responsible for generating the chat responses to be able to access the * context data as needed. * * The goal of the context this adapter is to facilitate providing the context data to the backend. * The following methods are expected to be implemented by the context data adapter: * * - Set context data: On initial load, the context data should be set to the initial state. * - Get context data: Data loaded from the backend. * - Update context data: Called when the context data is updated. * - Clear context data: When the app is closed or the user logs out, the context data should be cleared. */ interface ContextDataAdapter$1 { /** * Creates a new context and sets the initial context data when provided. * On success, the new context ID should be returned. * * @param {Object} initialData * @param {ContextAdapterExtras} extras * @returns {Promise<SetContextResult>} */ create: (initialItems?: ContextItems, extras?: ContextAdapterExtras$1) => Promise<SetContextResult$1>; /** * Deletes the context data and any registered tasks for the given context ID, and makes the context ID invalid. * This method should be used when the context is no longer needed. * * @param {string} contextId * @param {ContextAdapterExtras} extras * @returns {Promise<ContextActionResult>} */ discard: (contextId: string, extras?: ContextAdapterExtras$1) => Promise<ContextActionResult$1>; /** * Deletes the data for the given context ID and item IDs. * * @param {string} contextId The context ID. * @param {string[]} itemIds The item IDs to delete. * @param {ContextAdapterExtras} extras * @returns {Promise<ContextActionResult>} */ removeItems: (contextId: string, itemIds: string[], extras?: ContextAdapterExtras$1) => Promise<ContextActionResult$1>; /** * Resets the context data for the given context ID. * If no new context data is not provided, the context will be emptied. * If new context data is provided, it will replace the existing context data. * * @param {string} contextId * @param {ContextItems} newData * @param {ContextAdapterExtras} extras * @returns {Promise<ContextActionResult>} */ resetItems: (contextId: string, newData?: ContextItems, extras?: ContextAdapterExtras$1) => Promise<ContextActionResult$1>; /** * Updates data for the given context ID. * * * @param {string} contextId * @param {string} itemId * @param {Object} data * @param {ContextAdapterExtras} extras * @returns {Promise<ContextActionResult>} */ updateItems: (contextId: string, itemsToUpdate: Partial<ContextItems>, extras?: ContextAdapterExtras$1) => Promise<ContextActionResult$1>; } /** * The context tasks adapter is responsible for registering and unregistering tasks that can be triggered by * the AI assistant. The tasks are front-end specific but can be triggered by backend based on specific user * prompts in the AI chat. In order to build a context-aware chat experience that can also trigger front-end * tasks, the context tasks adapter should be used to let the backend know about the tasks that can be triggered. * * The following methods are expected to be implemented by the context tasks adapter: * * - Register task: When a new screen is loaded, or a specific state is reached, a new task can be registered. * - Unregister task: When the screen is closed or the state is no longer valid, the task should be unregistered. */ interface ContextTasksAdapter$1 { /** * Unregisters specific tasks from the given context ID, based on their task IDs. * * @param {string} contextId * @param {string} taskIds[] * @param {ContextAdapterExtras} extras * @returns {Promise<ContextActionResult>} */ removeTasks: (contextId: string, taskIds: string[], extras?: ContextAdapterExtras$1) => Promise<ContextActionResult$1>; /** * Resets the tasks for the given context ID. * If new tasks are provided, they will replace the existing tasks. * If no tasks are provided, all the tasks will be emptied. * * @param {string} contextId * @param {ContextAdapterExtras} extras * @returns {Promise<ContextActionResult>} */ resetTasks: (contextId: string, newTasks?: ContextTasks, extras?: ContextAdapterExtras$1) => Promise<ContextActionResult$1>; /** * Updates the tasks included in the `tasks` object, for the given context ID. * Tasks that are not included in the `tasks` object should be left unchanged. * If you want to remove a task, you should use the `removeTasks` method. * * @param {string} contextId * @param {Partial<ContextTasks>} tasks * @param {ContextAdapterExtras} extras * @returns {Promise<ContextActionResult>} */ updateTasks: (contextId: string, tasks: Partial<ContextTasks>, extras?: ContextAdapterExtras$1) => Promise<ContextActionResult$1>; } /** * The context adapter context-aware chat experience and AI assistants. * This type provides the methods for both context data and tasks that should be implemented by adapters * in order to synchronize data related to the context between the frontend and the backend. * * If your chat experience does not require the execution of tasks, you can use the ContextDataAdapter type instead. * But if you need the LLM to execute tasks, as well as access the context data, you should use the ContextAdapter type * to implement both the context data and tasks. */ interface ContextAdapter$1 extends ContextDataAdapter$1, ContextTasksAdapter$1 { } /** * This represents a set of extra data that can be sent to the context adapter. * It can be used by implementations to send additional data such as authentication headers. */ type ContextAdapterExtras = { /** * This contains the headers that implementers can use to send additional data such as authentication headers. */ headers?: Record<string, string>; }; /** * The context tasks adapter is responsible for registering and unregistering tasks that can be triggered by * the AI assistant. The tasks are front-end specific but can be triggered by backend based on specific user * prompts in the AI chat. In order to build a context-aware chat experience that can also trigger front-end * tasks, the context tasks adapter should be used to let the backend know about the tasks that can be triggered. * * The following methods are expected to be implemented by the context tasks adapter: * * - Register task: When a new screen is loaded, or a specific state is reached, a new task can be registered. * - Unregister task: When the screen is closed or the state is no longer valid, the task should be unregistered. */ interface ContextTasksAdapter { /** * Unregisters specific tasks from the given context ID, based on their task IDs. * * @param {string} contextId * @param {string} taskIds[] * @param {ContextAdapterExtras} extras * @returns {Promise<ContextActionResult>} */ removeTasks: (