/** * @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/aiconfig * @publicApi */ import { type AIAssistantConfig } from "./aiassistant/aiassistant.js"; import { type AIChatConfig } from "./aichat/aichat.js"; import { type AISuggestionActionName } from "./aichat/ui/feed/aichatfeedsuggestionitemactionsview.js"; import { type AIQuickActionsConfig } from "./aiquickactions/aiquickactions.js"; import { type AITranslateConfig } from "./aitranslate/aitranslate.js"; import { type AIModelsConfig } from "./aicore/model/aimodels.js"; import { type AIReviewModeConfig } from "./aireviewmode/aireviewmode.js"; import { type AIDefaultContext } from "./aicore/model/aidefaultcontext.js"; /** * The configuration for all AI-related functionalities. * * Provides configuration properties for both AI features and AI adapters (which connect to the external AI services), * * ```ts * ClassicEditor * .create( { * ai: { * // ... * } * } ) * .then( ... ) * .catch( ... ); * ``` * * See {@link module:core/editor/editorconfig~EditorConfig all editor configuration options}. */ export interface AIConfig { /** * The URL of the AI service endpoint. * * This endpoint is used by AI features: AI Chat, AI Quick Actions, and AI Review Mode. * It does not affect the AI Assistant feature, which uses its own adapter configuration. * * **NOTE:** By default, the plugin uses the default AI service endpoint delivered by CKEditor Cloud Services. * * @default 'https://ai.cke-cs.com/v1' */ serviceUrl?: string; /** * A list of context references that are automatically attached to AI features. * Each entry references an administrator-managed context, which is a reusable * collection of prompts and files defined through the AI service and identified by its `id`. * * **Note:** The headless gateway APIs * ({@link module:ai/aireviewmode/aireviewgateway~AIReviewGateway}, * {@link module:ai/aitranslate/aitranslategateway~AITranslateGateway}, and * {@link module:ai/aidocumentprocessing/aidocumentprocessinggateway~AIDocumentProcessingGateway}) are * config-independent by design and do **not** apply this option. Pass their context references explicitly through * the `contexts` run option instead. * * Each entry is a context reference optionally narrowed down to specific features via `features`. When * `features` is omitted, the entry is attached to **every** AI feature: * * ```ts * ClassicEditor * .create( { * // ... Other configuration options ... * ai: { * defaultContext: [ * // Attached to every AI feature. * { id: 'style-guide' }, * * // Attached only to the `translate.*` quick actions and to every review command. * { * id: 'glossary', * features: { * quickActions: /^translate\./, * review: true * } * } * ] * } * } ) * .then( ... ) * .catch( ... ); * ``` * * Read more in {@link module:ai/aicore/model/aidefaultcontext~AIDefaultContext}. */ defaultContext?: AIDefaultContext; /** * Extra HTTP headers that the AI service should attach when it fetches document images that live behind * authentication (for example a private CDN or a token-protected asset server) during image analysis. * * The value is a list of entries, each pairing a `domain` with the `headers` to attach. A header set is attached when * the image URL starts with the entry's `domain`. * * Because the match is a plain string prefix, always scope each `domain` to a full origin ending with a slash, for * example `https://assets.example.com/`, so it cannot match a look-alike host such as `https://assets.example.com.incorrect.example/`. * * It is applied only to the AI Chat message flow and the document processing flow, as these are the only cases where * the AI service works with images embedded in the document. * * ```ts * ClassicEditor.create( { * ai: { * extraHttpHeaders: [ * { domain: 'https://assets.example.com/', headers: { authorization: 'Bearer ' } } * ] * } * } ); * ``` * * Because authorization tokens expire and rotate, the value can also be a function. It is called for every request, * so it can return fresh headers each time: * * ```ts * ClassicEditor.create( { * ai: { * extraHttpHeaders: () => ( [ * { domain: 'https://assets.example.com/', headers: { authorization: `Bearer ${ getFreshToken() }` } } * ] ) * } * } ); * ``` */ extraHttpHeaders?: AIExtraHttpHeaders | (() => AIExtraHttpHeaders); /** * The configuration of the {@link module:ai/aiassistant/aiassistant~AIAssistant AI Assistant feature}. * * Read more in {@link module:ai/aiassistant/aiassistant~AIAssistantConfig}. */ assistant?: AIAssistantConfig; /** * The configuration of the AI user interface provided by the {@link module:ai/aitabs/aitabs~AITabs} plugin. */ container?: AIContainerConfig; /** * The configuration of the {@link module:ai/aichat/aichat~AIChat AI Chat feature}. * * Read more in {@link module:ai/aichat/aichat~AIChatConfig}. */ chat?: AIChatConfig; /** * The configuration of the AI Quick Actions feature. * * Read more in {@link module:ai/aiquickactions/aiquickactions~AIQuickActionsConfig}. */ quickActions?: AIQuickActionsConfig; /** * The configuration of the AI Review feature. * * Read more in {@link module:ai/aireviewmode/aireviewmode~AIReviewModeConfig}. */ review?: AIReviewModeConfig; /** * The configuration of the {@link module:ai/aitranslate/aitranslate~AITranslate AI Translate feature}. */ translate?: AITranslateConfig; /** * The configuration for AI models used across all AI features (Chat and Review). * * ```ts * ClassicEditor.create( { * ai: { * models: { * defaultModelId: 'gpt-5.4', * displayedModels: [ 'gpt', 'claude' ], * showModelSelector: true * } * } * } ) * .then( ... ) * .catch( ... ); * ``` */ models?: AIModelsConfig; /** * Defines what actions are available for the user when interacting with AI responses in AI Chat and AI Quick Actions features. * * Users can perform following two actions: * * * `'applySuggestion'` - applies the presented change directly into the editor content. * * `'insertSuggestion'` - applies the presented change as a suggestion, which can be later on accepted or rejected. * * This setting impacts: * * * The action buttons located below an AI reply in the chat feed. * * The buttons located in the header of each change preview in the chat feed. * * The buttons located in the balloon which shows the change preview. * * Through this configuration option, you can change how users use the AI replies. For example, if you want to force users to always * insert AI-proposed changes as suggestions, omit `'applySuggestion'` action. * * Please note other factors that impact the availability of these actions: * * * Buttons related to `'applySuggestion'` action are hidden if {@link module:track-changes/trackchanges~TrackChanges track changes} * feature is turned on. * * Buttons related to `'insertSuggestion'` action are hidden if {@link module:track-changes/trackchanges~TrackChanges track changes} * feature is not loaded in the editor. * * Please note, that due to these factors, it is possible to accidentally configure the editor in a way, that no UI elements are * presented to the user. * * @default [ 'applySuggestion', 'insertSuggestion' ] */ availableReplyActions?: Array; } export type AIContainerType = "sidebar" | "overlay" | "custom"; export type AIContainerSide = "left" | "right"; export interface AIContainerBase { type: AIContainerType; /** * This option is used to show or hide the resize button in the AI user interface. * * Defaults to `true`. */ showResizeButton?: boolean; /** * Whether the AI interface should be visible when the editor is created. */ visibleByDefault?: boolean; /** * When `true`, clicking the active tab button collapses the panel and toggles the * `ck-ai-tabs_collapsed` CSS class on the AI tabs DOM element. Clicking the tab again expands * it back. When `false`, clicking the active tab button is a no-op. * * Defaults to `false`. */ collapsible?: boolean; } /** * The configuration of the AI user interface container in the sidebar mode. Provide an existing DOM * element to use as the container the AI user interface will automatically render into that element. * * Additionally, the {@link module:ai/aitabs/aitabs~AITabs tab buttons} can be positioned on the preferred * side of the container. * * ```ts * ClassicEditor * .create( { * attachTo: document.querySelector( '#editor' ), * // ... Other configuration options ... * ai: { * container: { * type: 'sidebar', * * // Existing DOM element to use as the container for the AI user interface. * element: document.querySelector( '#ai-sidebar-container' ), * * // (Optional) The preferred side of the element to position the tab buttons. * side: 'right' * }, * } * } ) * .then( ... ) * .catch( ... ); * ``` */ export interface AIContainerSidebar extends AIContainerBase { type: "sidebar"; element: HTMLElement; side?: AIContainerSide; } /** * The configuration of the AI user interface container in the overlay mode. In this mode, the AI user * interface is displayed on top of the web page on a preferred side. This mode is best suited * for integrations with limited space. * * ```ts * ClassicEditor * .create( { * attachTo: document.querySelector( '#editor' ), * // ... Other configuration options ... * ai: { * container: { * type: 'overlay', * side: 'right' * }, * } * } ) * .then( ... ) * .catch( ... ); * ``` */ export interface AIContainerOverlay extends AIContainerBase { type: "overlay"; side?: AIContainerSide; } /** * The configuration of the AI user interface container in the custom mode. * * In this mode, integrator is responsible for rendering the AI user interface in the web page. * * * Use {@link module:ai/aitabs/aitabs~AITabs#view} to access the view of the AI user interface, * * Use {@link module:ai/aitabs/tabs/aitabsview~AITabsView#getTabIds} to read available IDs of individual tabs in the AI user interface, * * Use {@link module:ai/aitabs/tabs/aitabsview~AITabsView#getTab} to access individual tab views in the AI user interface, * * Use {@link module:ai/aitabs/tabs/aitabsview~AITabsView#addTab} to add a new tab to the AI user interface, * * Use {@link module:ai/aitabs/tabs/aitabsview~AITabsView#activateTab} to switch between tabs from the code. * * For example, to integrate the AI user interface with custom containers on the web page, use the following code: * * ```ts * const tabsPlugin = editor.plugins.get( 'AITabs' ); * * for ( const id of tabsPlugin.view.getTabIds() ) { * const tab = tabsPlugin.view.getTab( id ); * * // Display tab button and panel in a custom container. * myButtonsContainer.appendChild( tab.button.element ); * myPanelContainer.appendChild( tab.panel.element ); * } * ``` */ export interface AIContainerCustom extends AIContainerBase { type: "custom"; } /** * The configuration of the AI user interface provided by the {@link module:ai/aitabs/aitabs~AITabs} plugin. * * The AI user interface can operate in three different modes: * * * {@link module:ai/aiconfig~AIContainerSidebar} - the AI user interface is displayed in a specific DOM element, * * {@link module:ai/aiconfig~AIContainerOverlay} - the AI user interface is displayed on top of the web page, * * {@link module:ai/aiconfig~AIContainerCustom} - the AI user interface is displayed in a custom way. */ export type AIContainerConfig = AIContainerSidebar | AIContainerOverlay | AIContainerCustom; /** * If fetching some resources (for example images) used during AI image analysis requires passing an additional * authorization factor in the form of additional HTTP headers: * * ``` * extraHttpHeaders: [ * { domain: 'https://ckeditor.com/', headers: { authorization: 'Bearer xxx' } }, * { domain: 'https://example.com/', headers: { authorization: 'Bearer xxx' } } * ] * ``` * * See {@link module:ai/aiconfig~AIConfig#extraHttpHeaders}. */ export type AIExtraHttpHeaders = Array<{ /** * The origin the headers apply to. Matched as a plain string prefix against the image URL, so it should be a full * origin ending with a slash, for example `https://assets.example.com/`. */ domain: string; /** * The HTTP headers to attach for the matching `domain`. */ headers: { [header: string]: string; }; }>;