@ckeditor/ckeditor5-ai
Version:
AI features for CKEditor 5.
276 lines (275 loc) • 12.6 kB
TypeScript
/**
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/**
* @module ai/aichat/aichatcontroller
* @publicApi
*/
import { ContextPlugin } from '@ckeditor/ckeditor5-core';
import { AIConnector } from '../aicore/aiconnector.js';
import { AIChatConversation, type AIChatInteractionCreatedEvent } from './model/aichatconversation.js';
import { type AIInteractionReplyCreatedEvent, type AIToolData } from '../aicore/model/aiinteraction.js';
import { type AIChatInteraction } from './model/aichatinteraction.js';
import { DocumentCompare } from '@ckeditor/ckeditor5-collaboration-core';
import { type AIChatFeedCustomElementView } from './ui/feed/aichatfeedcustomelementview.js';
/**
* Implements integration layer between AI Chat feature UI and logic.
*
* Provides an API to interact with AI Chat feature.
*
* @experimental **Experimental:** Some methods of this class are production-ready but experimental and may change
* in minor releases without the standard deprecation policy. Check the changelog for migration guidance.
*/
export declare class AIChatController extends ContextPlugin {
/**
* Active conversation (currently open and visible in UI).
*/
activeConversation?: AIChatConversation;
/**
* @inheritDoc
*/
static get requires(): readonly [typeof AIConnector, typeof DocumentCompare];
/**
* @inheritDoc
*/
static get pluginName(): "AIChatController";
/**
* @inheritDoc
*/
static get isOfficialPlugin(): true;
/**
* @inheritDoc
*/
static get isPremiumPlugin(): true;
/**
* @inheritDoc
*/
init(): void;
/**
* @inheritDoc
*/
afterInit(): Promise<void>;
/**
* @inheritDoc
*/
destroy(): Promise<void>;
/**
* Loads a conversation by its ID and sets it as the active conversation.
*/
loadConversation(conversationId: string): Promise<void>;
/**
* Registers a function that is called when data from a custom AI tool is received from the backend service.
*
* This data can only be received if you connect your own custom AI tool with the Cloud Services AI backend. By registering a callback
* function, you can implement custom handling for this data, such as displaying custom elements inside the AI chat component, or
* setting a custom loading message.
*
* When data is received, the callback is immediately called with two parameters:
*
* * `toolData` – data returned by the AI tool,
* * `api` – {@link module:ai/aichat/aichatcontroller~AIChatFeedAPI set of tools} which you can use to reflect the received AI tool data
* in the AI chat feed.
*
* The callback is called for data received from all tools that you have connected, and both for tool results and tool notifications.
* Check `toolData.toolName` and `toolData.type` to handle various tools and actions. You can register multiple callbacks to better
* organize your code.
*
* Please remember, that your tool is fully responsible for generating the contents of `toolData.data` and `toolData.attributes`.
*
* Example usage:
*
* 1. Register a callback that changes the loading message when tool "my-tool" returns a notification:
*
* ```ts
* aiChat.registerToolDataCallback( ( toolData, api ) => {
* if ( toolData.toolName === 'my-tool' && toolData.type === 'notification' ) {
* api.setLoadingMessage( toolData.data.message );
* }
* } );
* ```
*
* 2. Register a callback to create a custom text chat reply based on custom tool data:
*
* ```ts
* aiChat.registerToolDataCallback( ( toolData, api ) => {
* if ( toolData.type == 'result' ) {
* api.insertTextReply( toolData.toolName + ': ' + toolData.data.msg );
* }
* } );
* ```
*
* 3. Register a callback to insert a custom element into the chat feed based on custom tool data:
*
* ```ts
* aiChat.registerToolDataCallback( async ( toolData, api ) => {
* if ( toolData.type == 'result' && toolData.data.html ) {
* api.insertCustomElement( toolData.data.html )
* .then( ( customElementView ) => {
* // You can further manipulate the inserted custom element using `customElementView`.
* // For example, you can fetch some data asynchronously and put it into the element.
* // Use `customElementView.element` to reference the created DOM structure.
* // The `customElementView.element` is a wrapper element of a custom UI HTML provided.
* } );
* }
* } );
* ```
*
* @experimental **Experimental:** This is a production-ready API but may change in minor releases
* without the standard deprecation policy. Check the changelog for migration guidance.
* @param callback A callback function that is called when tool data is received.
*/
registerToolDataCallback(callback: AIToolEventCallback): void;
/**
* Adds the current document to the chat context.
*/
addCurrentDocumentToChatContext(): void;
/**
* Adds current document selection to the conversation context. If document is not added to the context, it is added as well.
*
* @experimental **Experimental:** This is a production-ready API but may change in minor releases
* without the standard deprecation policy. Check the changelog for migration guidance.
*/
addSelectionToChatContext(): Promise<void>;
/**
* Removes current document selection from the conversation context.
*
* @experimental **Experimental:** This is a production-ready API but may change in minor releases
* without the standard deprecation policy. Check the changelog for migration guidance.
*/
removeSelectionFromChatContext(): void;
/**
* Moves focus to the AI Chat prompt input field.
*
* @experimental **Experimental:** This is a production-ready API but may change in minor releases
* without the standard deprecation policy. Check the changelog for migration guidance.
*/
focusPromptInput(): void;
/**
* Creates a new, empty conversation.
*
* @param options Optional parameters for starting the conversation.
* @param options.modelId If provided, this model will be selected for the new conversation instead of the default one.
*/
startConversation(options?: {
modelId?: string;
}): Promise<void>;
/**
* Submits a user message to the currently active conversation.
*/
sendMessage(messageData: AIChatUserMessageData): Promise<void>;
/**
* Returns the ID under which conversations are grouped. All created conversations will have this `groupId` set. Conversation history
* will fetch conversations with such `groupId`.
*
* This is equal to the channelId passed in context/editor configuration.
*/
getGroupId(): string;
/**
* Starts an AI chat conversation safely, catching and logging any errors.
*
* @param options Options for starting the conversation.
* @param options.id Optional conversation ID. If provided, initializes an existing conversation.
* If not defined, starts a new conversation with a generated ID.
* @param options.modelId Optional model ID to use for the conversation. If not provided, the default model is used.
*/
protected _startConversationSafely(options?: {
id?: string;
modelId?: string;
}): Promise<void>;
}
/**
* Data for the message send by the user in the AI chat.
*/
export type AIChatUserMessageData = {
/**
* The query that the user provided for the message. Displayed in the chat feed as the user's message.
*/
message: string;
/**
* Additional parameters for the message. This data is stored together with the message and can influence how the message is processed
* or displayed.
*
* You can pass following properties to alter how the message behaves:
*
* * `displayedPrompt: string` - If set, will be displayed instead of the actual `message`. You can use it to display a shorter,
* or a friendlier user message. This is also respected in the conversation history. Original `message` will still be used to query
* the AI model.
*
* Besides supported properties, `attributes` can be used to save any additional metadata with the message, which can be used by your
* integration in any way. Data passed in `attributes` will be saved in the conversation history. If your integration connects external
* custom AI tools, `attributes` are passed to the tool calls and can be used by these tools.
*
* Additionally, other official features that interact with the AI chat feature may introduce their own attributes.
*/
attributes?: Record<string, unknown>;
};
/**
* Set of helpers dedicated to be used inside {@link module:ai/aichat/aichatcontroller~AIToolEventCallback callbacks} registered
* through {@link module:ai/aichat/aichatcontroller~AIChatController#registerToolDataCallback}.
*
* Using this tools you can manipulate AI chat feed (e.g. add custom replies) in response to the received custom AI tool data.
*
* @experimental **Experimental:** This is a production-ready API but may change in minor releases
* without the standard deprecation policy. Check the changelog for migration guidance.
*/
export interface AIChatFeedAPI {
/**
* Creates a new reply in the current interaction. The created reply becomes the current reply of the interaction.
*
* Passing an `id` is optional. When passed, it is added to the wrapping HTML element as `data-cke-ai-id` attribute,
* allowing to query it later with native DOM methods.
*
* This method allows adding custom text replies to the AI chat feed. You can pass plain text or Markdown-formatted text
* as the `content` parameter. Markdown is automatically converted to proper HTML formatting when rendered in the chat feed.
*
* Note, that the text reply is **not** immediately inserted into the UI when this method is called. Insertions are queued
* to ensure the reply is rendered after currently processed content.
*
* Note also, that the content of the reply is visually streamed in the chat feed (word by word),
* so it will appear gradually.
*/
insertTextReply: (content: string, id?: string) => ReturnType<AIChatInteraction['createReply']>;
/**
* Inserts a custom element into the AI chat feed. The element can be provided as a HTML string or as a `HTMLElement`.
*
* Passing an `id` is optional. When passed, it is added to the wrapping HTML element as `data-cke-ai-id` attribute,
* allowing to query it later with native DOM methods.
*
* Note, that the element is **not** immediately inserted into the UI when this method is called. Insertions are queued
* to ensure the element is rendered after currently processed content.
*
* Returns a promise which is resolved after the element is finally attached to the DOM. You can use this promise to further
* manage the displayed content, for example, fetch asynchronous data and display it inside the inserted element.
*/
insertCustomElement: (element: string | HTMLElement, id?: string) => Promise<AIChatFeedCustomElementView>;
/**
* Sets the currently displayed AI chat loading message.
*/
setLoadingMessage: (message: string) => void;
/**
* Clears the currently displayed AI chat loading message. No text will be shown.
*/
clearLoadingMessage: () => void;
}
/**
* A callback type for handling custom AI tools data.
*
* This callback receives two parameters:
*
* * `toolData` - data returned by the AI tool.
* * `api` - set of tools which you can use to reflect the received AI tool data in the AI chat feed.
*/
export type AIToolEventCallback = (toolData: AIToolData, api: AIChatFeedAPI) => void | Promise<void>;
/**
* An event emitted by `AIChatController` when an AI reply is created.
*
* @eventName ~AIChatController#replyCreated
*/
export type AIChatControllerAIReplyCreatedEvent = AIInteractionReplyCreatedEvent;
/**
* An event emitted by `AIChatController` when an AI chat interaction is created.
*
* @eventName ~AIChatController#interactionCreated
*/
export type AIChatControllerAIInteractionCreatedEvent = AIChatInteractionCreatedEvent;