@ckeditor/ckeditor5-ai
Version:
AI features for CKEditor 5.
692 lines (690 loc) • 30.5 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/model/aichatcontext
* @publicApi
*/
import { type Editor } from '@ckeditor/ckeditor5-core';
import { type AIConnector, type AIUserMessage } from '../../aicore/aiconnector.js';
import { type AIContextItemType, type AIContextTextResourceType, type AIContextItem, type AIContextItemRequestData, type AIDocumentContextSlice, type AIToolContextItem } from '../../aicore/model/aicontext.js';
export declare const AI_CONTEXT_MODEL_EVENT_NAMES: readonly ["contextItemAdded", "contextItemRemoved", "contextItemLoadingEnded", "contextSent", "error", "addContextOptionsChanged", "sourceResourcesLoaded", "resourceStateChanged", "uploadProgressChanged"];
declare const AIChatContext_base: {
new (): import("@ckeditor/ckeditor5-utils").Observable;
prototype: import("@ckeditor/ckeditor5-utils").Observable;
};
/**
* Manages the context of the current conversation.
*
* @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 declare class AIChatContext extends /* #__PURE__ */ AIChatContext_base {
constructor({ connector, config, ownerId }: {
connector: AIConnector;
config?: AIChatContextConfig;
ownerId: string;
});
/**
* Initializes the 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.
*/
init(): void;
/**
* Returns the source (editor / root / content / documentId) that a `data-id` in an AI response belongs to.
*
* Relied on by the suggestion balloon flow when a single reply's change groups span multiple uploaded documents.
*
* @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.
*/
getSourceByDataId(dataId: string | undefined): (AIChatContextDocumentSource & {
documentId: string;
}) | undefined;
/**
* Returns an `AIDocumentContextSlice` describing the position and bounds of a single uploaded document inside the concatenated
* reply context, resolved via a `data-id` that appears in the uploaded documents. A convenience for AI response handling where
* the server returns `data-id` references rather than internal document ids.
*
* @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.
*/
getDocumentContextSliceByDataId(dataId: string | undefined): AIDocumentContextSlice | undefined;
/**
* Returns the pending context items that will be sent to the AI endpoint in the next interaction.
*
* @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.
* @returns Map of pending context items keyed by their uiId
*/
getPendingContextItems(): Map<string, AIContextItem>;
/**
* Populates context items from message data.
* This method converts user message content to context items and adds them to 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.
*/
populateFromMessage(content: AIUserMessage['content'][0]): Promise<AIContextItem>;
/**
* Creates a context item from conversation content.
*/
private _createContextItemFromContent;
/**
* Returns all context items that have been sent to the AI endpoint in the current conversation.
*
* @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.
* @returns Map of sent context items keyed by their uiId
*/
getSentContextItems(): Map<string, AIContextItem>;
/**
* Removes a context item from the pending context.
* Read-only items cannot be removed and the method returns early.
*
* @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 uiId The unique identifier of the context item to remove
*/
removeFromContext(uiId: string): void;
/**
* Clears all pending context items and adds the current document to the conversation context if it exists.
*
* @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.
*/
clearPendingContextItems(): void;
/**
* Adds context items to the conversation context and clears the pending context items.
*
* @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.
*/
addToConversationContext(contextItems: Map<string, AIContextItem>): void;
/**
* Checks if the current document is in the pending 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.
* @returns True if the current document is in pending context, false otherwise
*/
isCurrentDocumentInContext(): boolean;
/**
* @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.
*/
isSelectionInContext(): boolean;
/**
* Checks if the current document is in 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.
* @returns True if the current document is in conversation context, false otherwise
*/
isCurrentDocumentInConversation(): boolean;
/**
* Converts context items to request data format for API endpoint.
* This static method transforms the internal context item format to the format expected by the AI connector.
*
* @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 contextItems Map of context items to convert
* @returns Array of context items in API request format
*/
static mapContextItemsToRequestData(contextItems: Map<string, AIContextItem>): Array<AIContextItemRequestData>;
/**
* Adds files to the context by uploading them and creating context items.
* This method handles multiple files concurrently and tracks upload progress.
*
* @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 files Array of File objects to upload and add to context
* @param [attributes] Optional attributes object containing resourceId and label for tracking purposes and context chips
* @param [type] Context item type, defaults to 'file' to indicate that the file is being added as a file or text
* @returns Promise that resolves when all files are processed
*/
addFilesToContext(files: Array<File>, attributes?: {
resourceId: string;
label: string;
}, type?: 'file' | 'text'): Promise<void>;
/**
* Adds the current document to the pending context.
* If the document is already in context, this method returns early without changes.
*
* @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 label Display label for the current document
*/
addCurrentDocumentToContext(label: string): void;
/**
* Updates the current document in the pending context with new content and version.
* This method uploads the document content and updates the context item accordingly.
*
* @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 content The document content to upload, or undefined to skip
* @param version Version number of the document for change tracking
* @returns Promise that resolves when the document is updated
*/
updateCurrentDocument(content: string | undefined, version: number, sessionId: string | null, channelId: string, rootName: string, selections: Array<{
start: number;
end: number;
htmlFragment: string;
}>): Promise<void>;
/**
* @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.
*/
addSelectionToContext(selection: string): void;
/**
* @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.
*/
removeSelectionFromContext(): void;
/**
* Adds a URL to the context by uploading it and creating a context item.
* This method handles URL upload with proper error handling and progress tracking.
*
* @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 url The URL to upload and add to context
* @param [attributes] Optional attributes object containing resourceId and label for tracking purposes and context chips
* @returns Promise that resolves when the URL is processed
*/
addUrlToContext(url: string, attributes?: {
resourceId: string;
label: string;
}): Promise<void>;
/**
* Adds an AI tool context item to the pending context items.
*
* Note, that these context items are ignored by the CKEditor AI agent and should be handled by your backend AI tool.
*
* The object which is passed as a parameter can contain the following properties:
* ```ts
* {
* // Must be set to `'mcp-tool-context'`.
* type: 'mcp-tool-context',
*
* // The name of the MCP server.
* mcpServerName: string;
*
* // The data for the tool. Can be anything.
* data: Record<string, any>;
*
* // The label of the item used to display it in the chat UI.
* label: string;
*
* // Optional, 1-21 characters. Auto-generated if omitted.
* id?: string;
*
* // The name of the tool. Omit to send context to all tools on the server.
* toolName?: string;
* }
* ```
*
* @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.
*/
addToolItemToContext(contextItem: AIToolContextItem): void;
/**
* Loads resources for a given source provider with the specified query.
* This method calls the source's {@link module:ai/aichat/model/aichatcontext~AIContextProvider#getResources}
* callback and updates resource states.
*
* @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 sourceId The unique identifier of the source provider
* @param query Search query to filter resources
* @param uid Unique identifier for the request to prevent race conditions
* @returns Promise resolving to array of resources with context state
*/
loadSourceResources(sourceId: string, query: string, uid: string): Promise<Array<AIContextResourceState>>;
/**
* @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.
*/
addResourceToContext(source: AIContextProvider, resource: AIContextResource): Promise<void>;
}
/**
* A uploaded-document source stored on the chat context, keyed by the id returned by the `/documents/batch` endpoint.
*
* @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 type AIChatContextDocumentSource = {
editor: Editor;
rootName: string;
content: string;
version: number;
/**
* The document's stored `name` — the source root's identifier as reported when the document was uploaded.
*/
name?: string;
/**
* The document's stored `description`, taken from the source root's
* {@link module:core/editor/editorconfig~RootConfig root configuration}. The AI service uses descriptions to
* semantically distinguish roots when a user scopes a request to a specific area (e.g. "edit the title").
*/
description?: string;
};
export type AIChatContextItemAddedEvent = {
name: 'contextItemAdded';
args: [
{
contextItem: AIContextItem;
isLoading: boolean;
}
];
};
export type AIChatContextItemRemovedEvent = {
name: 'contextItemRemoved';
args: [
{
uiId: string;
type?: AIContextItemType;
}
];
};
export type AIChatContextSentEvent = {
name: 'contextSent';
args: [
{
contextItems: Array<AIContextItem>;
}
];
};
export type AIChatContextAddContextOptionsChangedEvent = {
name: 'addContextOptionsChanged';
args: [
{
options: AIAddContextOptionsState;
}
];
};
export type AIChatContextUploadProgressChangedEvent = {
name: 'uploadProgressChanged';
args: [
{
isUploadInProgress: boolean;
}
];
};
export type AIAddContextOptionsState = {
document: {
enabled: boolean;
isHidden: boolean;
};
urls: {
enabled: boolean;
};
files: {
enabled: boolean;
};
sources: Array<AIContextProviderState>;
customItems: Array<AIContextCustomItem>;
};
export type AIContextProviderState = AIContextProvider & {
resources: Array<AIContextResourceState>;
};
export type AIContextResourceState = AIContextResource & {
isInContext?: boolean;
};
/**
* The configuration of the AI Chat menu for adding resources to the prompt context.
*
* This menu allows users to attach additional resources (files, documents, URLs) to their AI chat prompts,
* providing the AI with more context for generating responses. The properties defined in this config are set
* in the `config.ai.chat.context` namespace.
*
* It also allows to change the minimal number of items in the context adding menu required to show the search input
* using `config.ai.chat.context.searchInputVisibleFrom` option.
*
* ```ts
* ClassicEditor
* .create( {
* ai: {
* chat: {
* context: {
* // Allow for adding the current document content to the conversation context.
* document: { enabled: true },
*
* // Allow for adding URLs (web pages, blogs, etc.) to the conversation context.
* urls: { enabled: false },
*
* // Allow for uploading files (PDF, Word, etc.) to the conversation context.
* files: { enabled: true },
*
* // Configuration of external resources (files, text, etc.) to the conversation context.
* sources: [
* {
* id: 'my-docs',
* label: 'My Documents',
* getResources: ( query ) => fetchMyDocuments( query ),
* getData: ( id ) => fetchDocumentContent( id )
* }
* ],
*
* // The minimum number of resources to show the search input.
* searchInputVisibleFrom: 5
* }
* }
* }
* } )
* .then( ... )
* .catch( ... );
* ```
*
* * The {@link module:ai/aichat/model/aichatcontext~AIChatContextConfig#document},
* {@link module:ai/aichat/model/aichatcontext~AIChatContextConfig#urls}, and
* {@link module:ai/aichat/model/aichatcontext~AIChatContextConfig#files} properties configure the **built-in** options in the context menu.
* Each option can be enabled or disabled using the `enabled` boolean property. See their respective documentation for more details.
*
* * The {@link module:ai/aichat/model/aichatcontext~AIChatContextConfig#sources} property introduces customizable menus to the
* conversation context user interface that display a list of **external** resources that can be attached to the AI prompt.
* The user can search resources and the minimal number of resources required to show the search input can be configured using
* the {@link module:ai/aichat/model/aichatcontext~AIChatContextConfig#searchInputVisibleFrom} option.
* See {@link module:ai/aichat/model/aichatcontext~AIContextProvider} and {@link module:ai/aichat/model/aichatcontext~AIContextResource}
* to learn more.
*/
export type AIChatContextConfig = {
/**
* When this option is enabled (default), adding the editor document to the context of the conversation becomes possible.
* This allows the AI to interact with the content of the entire document if the user asks for it
* (e.g. "Write an introduction to the document." or "Shorten headings to make them more concise.").
*
* **Note**: When set `true`, the document content will be automatically added to the context of the new conversation. The user
* can still remove it using the user interface before sending the message if needed.
*
* **Note**: When set to `false`, the {@link module:ai/aiquickactions/aiquickactions~AIQuickActions AI Quick Actions} that use AI Chat
* will be disabled and removed from the UI. The selection can’t be sent to AI Chat without sending the entire document.
*
* @default true
*/
document?: {
enabled: boolean;
};
/**
* When this option is enabled (default), adding URLs to the context of the conversation becomes possible.
* This allows the AI to interact with the content of the URLs (e.g. web pages, blog posts, etc.) if the user adds them to the context
* (e.g. "Write a very brief summary of the linked blog post.").
*
* @default true
*/
urls?: {
enabled: boolean;
};
/**
* When this option is enabled (default), adding files to the context of the conversation becomes possible.
* This allows the AI to interact with the content of the files (e.g. Word documents, PDF files, etc.) if the user adds them
* to the context (e.g. "Write a very brief summary of the attached Word document.").
*
* @default true
*/
files?: {
enabled: boolean;
};
/**
* The configuration of the custom options in the context menu.
*
* Each configured {@link module:ai/aichat/model/aichatcontext~AIContextProvider} represents a single menu option that, when clicked,
* displays a list of available resources that can be attached to the AI prompt.
*
* {@link module:ai/aichat/model/aichatcontext~AIContextProvider Learn more about the configuration of custom resources}.
*/
sources?: Array<AIContextProvider>;
/**
* When this option is enabled, the selection made in the editor will always be added to the context.
*
* By default, the selection is added to the context only after user explicitly requests it by clicking "Ask AI" button.
*
* **Note**: This setting will have no effect if the feature is configured to
* {@link module:ai/aichat/model/aichatcontext~AIChatContextConfig#document disallow setting document as the conversation context}.
*
* @default false
*/
alwaysAddSelection?: boolean;
/**
* The configuration of the custom items in the context menu.
*
* Each configured {@link module:ai/aichat/model/aichatcontext~AIContextCustomItem} represents a single menu option that, when clicked,
* will execute a custom callback (e.g. opening a file manager).
*
* {@link module:ai/aichat/model/aichatcontext~AIContextCustomItem Learn more about the configuration of custom items}.
*/
customItems?: Array<AIContextCustomItem>;
/**
* The minimum number of resources to show the search input.
*
* @default 7
*/
searchInputVisibleFrom?: number;
};
/**
* The configuration of a custom option in the AI Chat menu for adding external resources to the prompt context.
*
* A `AIContextProvider` represents a single menu option that, when clicked, displays a list of available
* resources that can be attached to the AI prompt. The {@link module:ai/aichat/model/aichatcontext~AIContextProvider#label} is displayed
* as the menu option text, and the optional {@link module:ai/aichat/model/aichatcontext~AIContextProvider#icon} can be used to provide
* a visual representation.
*
* The {@link module:ai/aichat/model/aichatcontext~AIContextProvider#getResources} callback is called when the user clicks on the menu
* option and should return an array of {@link module:ai/aichat/model/aichatcontext~AIContextResource available resources}.
* Resources returned by this callback are displayed as a list and each resource comes with an optional
* {@link module:ai/aichat/model/aichatcontext~AIContextResource#data} property that:
* * When present, it will be used as is.
* * When `undefined`, for instance, because the resource content is large and obtaining it along with the list is expensive,
* the data will be retrieved using the optional {@link module:ai/aichat/model/aichatcontext~AIContextProvider#getData} callback on
* demand the moment the user selects this particular resource.
*
* The optional {@link module:ai/aichat/model/aichatcontext~AIContextProvider#useDefaultFiltering} property controls whether the
* built-in search filtering should be applied to the resources returned by `getResources()`.
* * When set to `true`, the resources will be filtered based on the user's search query.
* * When set to `false`, all resources will be displayed regardless of the search query, allowing the provider to handle filtering
* internally within the `getResources()` callback.
*
* ```ts
* {
* // The unique identifier of the provider.
* id: 'knowledge-base',
*
* // The human-readable name of the provider.
* label: 'Knowledge Base',
*
* // (Optional) The SVG string of the provider's icon. If not provided, a generic icon will be used instead.
* icon: '<svg xmlns="http://www.w3.org/2000/svg">...</svg>',
*
* // Whether to use the built-in search filtering.
* useDefaultFiltering: false,
*
* // The async callback to retrieve the list of available resources. Usually involves fetching data from a database or an external API
* // but here we use a simple array of resources for demonstration purposes.
* getResources: async ( query ) => [
* // Texts in various formats
* {
* id: 'text1',
* type: 'text',
* label: 'Internal note in plain text format',
* data: {
* content: 'Lorem ipsum dolor sit amet...',
* type: 'text'
* }
* },
* {
* id: 'text2',
* type: 'text',
* label: 'Internal note in Markdown format',
* data: {
* content: '## Markdown note\n\n**Lorem ipsum** dolor sit amet...',
* type: 'markdown'
* }
* },
* {
* id: 'text3',
* type: 'text',
* label: 'Internal note in HTML format',
* data: {
* content: '<h2>HTML note</h2><p>Lorem ipsum dolor sit amet...</p>',
* type: 'html'
* }
* },
* {
* id: 'text4',
* type: 'text',
* label: 'Internal note (fetched on demand)',
* // Note: Since `data` property is not provided, the content will be retrieved using the `getData()` callback (see below).
* // This, for instance, prevents fetching large resources along with the list of resources.
* },
*
* // URLs to resources in different formats
* {
* id: 'url1',
* type: 'web-resource',
* label: 'Blog post in Markdown',
* data: 'https://example.com/blog-post.md'
* },
* {
* id: 'url2',
* type: 'web-resource',
* label: 'Company brochure in PDF',
* data: 'https://example.com/brochure.pdf'
* },
* {
* id: 'url3',
* type: 'web-resource',
* label: 'Company website in HTML',
* data: 'https://example.com/index.html'
* },
* {
* id: 'url4',
* type: 'web-resource',
* label: 'Terms of service in plain text',
* data: 'https://example.com/terms-of-service.txt'
* },
*
* // ...
* ],
*
* // (Optional) Callback to retrieve the content of resources without `data` property provided by `getResources()` callback.
* // When the user picks a specific resource, the content will be fetched on demand (from database or external API) by this callback.
* // This prevents fetching large resources along with the list of resources.
* getData: async ( id ) => fetchDocumentContent( id )
* }
* ```
*/
export type AIContextProvider = {
/**
* The unique identifier of the provider.
*/
id: string;
/**
* (Optional) The SVG string of the provider's icon. If not provided, a generic icon will be used instead.
*/
icon?: string;
/**
* The human-readable name of the provider.
*/
label: string;
/**
* Whether to use the built-in search filtering for resources returned by
* {@link module:ai/aichat/model/aichatcontext~AIContextProvider#getResources}.
*/
useDefaultFiltering?: boolean;
/**
* The callback to retrieve the list of available resources. Usually involves fetching data from a database or an external API.
*/
getResources: (query?: string) => Promise<Array<AIContextResource>>;
/**
* The optional callback to retrieve the content of {@link module:ai/aichat/model/aichatcontext~AIContextResource resources}
* without `data` property provided by {@link module:ai/aichat/model/aichatcontext~AIContextProvider#getResources} callback.
*
* It helps to prevent fetching large resources along with the list of resources.
*
* Usually involves fetching data from a database or an external API.
*/
getData?: (id: string) => Promise<string>;
};
/**
* An individual resource item within a {@link module:ai/aichat/model/aichatcontext~AIContextProvider}.
*
* Represents a single selectable item in the resources list displayed when a user clicks on a custom
* context menu option. The {@link module:ai/aichat/model/aichatcontext~AIContextResource#label} is displayed to the user as the
* resource name, and the {@link module:ai/aichat/model/aichatcontext~AIContextResource#type}
* indicates what kind of context item this represents (file, document, or URL).
*
* When selected, the resource will be attached to the AI prompt to provide additional context for
* generating responses. If the {@link module:ai/aichat/model/aichatcontext~AIContextResource#data} property is provided,
* it contains the content of the resource. If {@link module:ai/aichat/model/aichatcontext~AIContextResource#data} is `undefined`,
* the content will be retrieved using the {@link module:ai/aichat/model/aichatcontext~AIContextProvider#getData} callback from the parent
* {@link module:ai/aichat/model/aichatcontext~AIContextProvider} when the resource is selected by the user.
*
* ```ts
* {
* id: 'user-guide-intro',
* type: 'text',
* label: 'User Guide - Introduction',
* data: {
* content: '<p>Lorem ipsum dolor sit amet...</p>',
* type: 'html'
* }
* }
* ```
*/
export type AIContextResource = {
/**
* The unique identifier of the resource.
*/
id: string;
/**
* The type of the resource.
*/
type: AIContextItemType;
/**
* The human-readable name of the resource.
*/
label: string;
/**
* The content of the resource.
*
* **Note**: When `undefined`, for instance, because the resource content is large and obtaining it should be done on demand,
* the content will be retrieved using the optional {@link module:ai/aichat/model/aichatcontext~AIContextProvider#getData} callback
* from the parent {@link module:ai/aichat/model/aichatcontext~AIContextProvider} when the resource is selected by the user.
*
* **Note**: For the `'text'` {@link module:ai/aichat/model/aichatcontext~AIContextResource#type resource type}, `data` should be in the
* {@link module:ai/aichat/model/aichatcontext~AIContextTextResource} format.
*/
data?: string | File | AIContextTextResource;
};
/**
* A text resource that can be used as a context item. For instance:
*
* ```ts
* {
* content: '<h2>HTML note</h2><p>Lorem ipsum dolor sit amet...</p>',
* type: 'html'
* }
* ```
*/
export type AIContextTextResource = {
/**
* The content of the text resource.
*/
content: string;
/**
* The type of the text resource.
*/
type: AIContextTextResourceType;
};
/**
* A custom item in the context menu, e.g. a button opening external file manager.
*/
export type AIContextCustomItem = {
id: string;
label: string;
icon?: string;
callback: () => void;
};
export {};