From 83ea51d8e142f58ec341c166be6deafbee0a3418 Mon Sep 17 00:00:00 2001 From: Karl Kemister-Sheppard Date: Tue, 6 Oct 2026 13:53:06 +1000 Subject: [PATCH 1/2] TINYDOC-3651: Correct and update the TinyMCE AI documentation for existing features. --- modules/ROOT/pages/events.adoc | 6 + modules/ROOT/pages/keyboard-shortcuts.adoc | 6 +- modules/ROOT/pages/tinymceai-actions.adoc | 39 +++---- .../ROOT/pages/tinymceai-api-overview.adoc | 78 ++++++++++++- .../ROOT/pages/tinymceai-api-quick-start.adoc | 8 +- modules/ROOT/pages/tinymceai-chat.adoc | 81 +++++++++---- .../pages/tinymceai-integration-options.adoc | 5 +- .../ROOT/pages/tinymceai-introduction.adoc | 4 +- .../tinymceai-jwt-authentication-intro.adoc | 37 ++++-- modules/ROOT/pages/tinymceai-limits.adoc | 17 ++- modules/ROOT/pages/tinymceai-models.adoc | 73 +++++++----- .../pages/tinymceai-on-premises-database.adoc | 25 ++-- .../tinymceai-on-premises-frameworks.adoc | 8 +- ...tinymceai-on-premises-getting-started.adoc | 20 ++-- .../ROOT/pages/tinymceai-on-premises-jwt.adoc | 15 ++- .../ROOT/pages/tinymceai-on-premises-mcp.adoc | 14 ++- .../tinymceai-on-premises-production.adoc | 25 ++-- .../tinymceai-on-premises-providers.adoc | 10 +- .../tinymceai-on-premises-reference.adoc | 46 +++++--- ...tinymceai-on-premises-troubleshooting.adoc | 110 ++++++++++++++++-- modules/ROOT/pages/tinymceai-on-premises.adoc | 10 +- modules/ROOT/pages/tinymceai-permissions.adoc | 82 +++++++++---- modules/ROOT/pages/tinymceai-review.adoc | 39 ++++--- modules/ROOT/pages/tinymceai-streaming.adoc | 30 ++--- ...ymceai-with-jwt-authentication-nodejs.adoc | 2 +- ...tinymceai-with-jwt-authentication-php.adoc | 2 +- modules/ROOT/pages/tinymceai.adoc | 36 ++++++ .../tinymceai/nodejs/configuration-steps.adoc | 2 +- .../nodejs/initial-project-setup.adoc | 2 +- .../nodejs/intro-and-prerequisites.adoc | 2 +- .../tinymceai/php/configuration-steps.adoc | 2 +- .../php/intro-and-prerequisites.adoc | 2 +- .../partials/commands/tinymceai-cmds.adoc | 6 +- .../configuration/tinymceai_options.adoc | 73 +++++++++--- .../partials/events/tinymceai-events.adoc | 13 +++ 35 files changed, 671 insertions(+), 259 deletions(-) create mode 100644 modules/ROOT/partials/events/tinymceai-events.adoc diff --git a/modules/ROOT/pages/events.adoc b/modules/ROOT/pages/events.adoc index 17d7ea945b..b8bc7a18d6 100644 --- a/modules/ROOT/pages/events.adoc +++ b/modules/ROOT/pages/events.adoc @@ -277,6 +277,7 @@ The following plugins provide events. * xref:spell-checker-events[Spell Checker events] * xref:revisionhistory-events[Revision History events] * xref:autocorrect-events[Spelling Autocorrect events] +* xref:tinymceai-events[{productname} AI events] * xref:visual-blocks-events[Visual Blocks events] * xref:visual-characters-events[Visual Characters events] * xref:word-count-events[Word Count events] @@ -423,6 +424,11 @@ include::partial$events/tinymcespellchecker-events.adoc[] include::partial$events/autocorrect-events.adoc[] +[[tinymceai-events]] +=== {productname} AI events + +include::partial$events/tinymceai-events.adoc[] + [[visual-blocks-events]] === Visual Blocks events diff --git a/modules/ROOT/pages/keyboard-shortcuts.adoc b/modules/ROOT/pages/keyboard-shortcuts.adoc index c54cbc6fda..b075d304c6 100644 --- a/modules/ROOT/pages/keyboard-shortcuts.adoc +++ b/modules/ROOT/pages/keyboard-shortcuts.adoc @@ -53,9 +53,9 @@ This is a list of the keyboard shortcuts provided by premium plugins. Each short [cols=",,,",options="header"] |=== |Action |Windows or Linux |macOS |Plugin -|Open the AI Chat sidebar and move focus to it |Ctrl+J |⌘+J |xref:tinymceai.adoc[tinymceai] -|Open the AI Review sidebar and move focus to it |Ctrl+Alt+S |Ctrl+Alt+S |xref:tinymceai.adoc[tinymceai] -|Move focus to the AI Chat sidebar header or the AI preview toolbar |Ctrl+F9 |Ctrl+F9 |xref:tinymceai.adoc[tinymceai] +|Open the AI Chat sidebar and move focus to the prompt input, or close it when focus is in the sidebar |Ctrl+J |⌘+J |xref:tinymceai.adoc[tinymceai] +|Open the AI Review sidebar and move focus to it, or close it when focus is in the sidebar |Ctrl+Alt+S |Ctrl+Alt+S |xref:tinymceai.adoc[tinymceai] +|Move focus to the AI Chat sidebar header, or from the AI preview toolbar to the toolbar of the selected suggestion |Ctrl+F9 |Ctrl+F9 |xref:tinymceai.adoc[tinymceai] |Open the AI dialog |Ctrl+J |⌘+J |xref:ai.adoc[ai] |Copy formatting |Ctrl+Alt+C |⌘+⌥+C |xref:formatpainter.adoc[formatpainter] |Apply formatting |Ctrl+Alt+V |⌘+⌥+V |xref:formatpainter.adoc[formatpainter] diff --git a/modules/ROOT/pages/tinymceai-actions.adoc b/modules/ROOT/pages/tinymceai-actions.adoc index bad22cd5aa..c0ffcf100c 100644 --- a/modules/ROOT/pages/tinymceai-actions.adoc +++ b/modules/ROOT/pages/tinymceai-actions.adoc @@ -31,7 +31,7 @@ Quick Actions fit transforming a selection or section (for example grammar fixes Both Quick Actions and Review can propose edits that apply only after acceptance or rejection. The main differences are scope and where the work happens in the editor: -* *Quick Actions*: Operate on a selection or section (including the full document when the scope includes it). The Quick Actions menu runs one-off operations such as Chat with a pre-filled prompt, preview transformations, translation, and custom actions. +* *Quick Actions*: Operate on a selection or section. When nothing is selected, a preview Quick Action (including a custom action of type `+action+`) runs on the whole document. When table cells are selected, the action runs on the selected cells. The Quick Actions menu runs one-off operations such as Chat with a pre-filled prompt, preview transformations, translation, and custom actions. * *Review*: Always analyzes the entire document in read-only Review mode. Suggestions appear in the Review sidebar and in the document. See xref:tinymceai-review.adoc[Review] for details. [[integration]] @@ -124,7 +124,7 @@ The following table lists built-in Quick Actions. [cols="1,3,2,3,1,1",options="header"] |=== -|Editor |Menu or control ID |System `actionName` |Description |Editor UI |API +|Editor |Menu or control ID |System `actionName` or quick-action prompt id |Description |Editor UI |API |**Explain** |`ai-chat-explain` |`explain` |Opens Chat with the selected text and a pre-filled prompt. Uses the Conversations API, not the system actions path. |✓ |— @@ -132,15 +132,15 @@ The following table lists built-in Quick Actions. |**Highlight key points** |`ai-chat-highlight-key-points` |`highlight-key-points` |Opens Chat with a key-points prompt. Uses the Conversations API, not the system actions path. |✓ |— -|**Improve Writing** |`ai-quickactions-improve-writing` |`improve-writing` |Enhance clarity, word choice, and sentence structure. |✓ |✓ +|**Improve writing** |`ai-quickactions-improve-writing` |`improve-writing` |Enhance clarity, word choice, and sentence structure. |✓ |✓ -|**Continue Writing** |`ai-quickactions-continue-writing` |`continue` |Complete unfinished sentences, paragraphs, or entire documents. |✓ |✓ +|**Continue writing** |`ai-quickactions-continue-writing` |`continue` |Complete unfinished sentences, paragraphs, or entire documents. |✓ |✓ -|**Fix Grammar** |`ai-quickactions-check-grammar` |`fix-grammar` |Correct grammar, spelling, and punctuation errors. |✓ |✓ +|**Fix grammar & spelling** |`ai-quickactions-check-grammar` |`fix-grammar` |Correct grammar, spelling, and punctuation errors. |✓ |✓ |**Change length** |`ai-quickactions-change-length` |`make-shorter`, `make-longer` |Shorten or lengthen the selection. Each option is its own system action. |✓ |✓ -|**Adjust Tone** +|**Change tone** a| `ai-quickactions-change-tone` + `ai-quickactions-tone-casual` + @@ -157,27 +157,16 @@ a| |Change writing style; each menu option maps to its own system action. |✓ |✓ |**Translate** -a| -`ai-quickactions-translate` + -`ai-quickactions-translate-english` + -`ai-quickactions-translate-spanish` + -`ai-quickactions-translate-russian` + -`ai-quickactions-translate-swedish` + -`ai-quickactions-translate-german` + -`ai-quickactions-translate-japanese` + -`ai-quickactions-translate-portuguese` + -`ai-quickactions-translate-korean` + -`ai-quickactions-translate-italian` + -`ai-quickactions-translate-chinese` -a| -`translate` -|Convert content between languages. Request body uses `args: { language: string }` with values such as `english`, `spanish`, `russian`, `swedish`, `german`, `japanese`, `portuguese`, `korean`, `italian`, or `chinese`. Configure the editor submenu with `tinymceai_languages`. |✓ |✓ +|`ai-quickactions-translate` +|`translate` +|Translate the selection into a language chosen from the **Translate** submenu. The submenu lists the languages set in xref:tinymceai.adoc#tinymceai_languages[`+tinymceai_languages+`]. Individual languages do not have menu item or toolbar button identifiers. |✓ |✓ |=== [NOTE] ==== * A checkmark in the **Editor UI** column means the action can appear when included in `tinymceai_quickactions_menu` (and related sub-menu options such as `tinymceai_quickactions_chat_prompts`). * A checkmark in the **API** column means the action is invoked through the system Actions API path `+/v1/actions/system/{actionName}/calls+`. An em dash means the command is Chat-based and uses the Conversations API instead. +* The `+ai-quickactions-custom+` identifier (labeled **Other**) lists the custom actions set in xref:tinymceai.adoc#tinymceai_quickactions_custom[`+tinymceai_quickactions_custom+`]. See xref:tinymceai-actions.adoc#custom-actions[Custom Actions]. ==== For system action endpoints, schemas, and streaming details, see the https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API] reference. @@ -272,6 +261,8 @@ Actions use streaming output with Server-Sent Events for real-time feedback as r Built-in Quick Actions—including identifiers, descriptions, and whether each command uses the system Actions API or Chat (Conversations API)—are summarized in xref:tinymceai-actions.adoc#quick-actions-reference-table[Default Actions]. +To run a system action, use https://tinymceai.api.tiny.cloud/docs#tag/Actions/operation/callSystemAction[Call a system action] with an `+actionName+` from the rows that have a checkmark in the **API** column of the table above. System actions use built-in prompts, so the request needs no prompt or model. For the token scopes that each system action needs, see xref:tinymceai-permissions.adoc#actions-permissions[Actions permissions]. + For endpoint details, request and response schemas, authentication, and streaming behavior for system `actionName` calls, see https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API]. [[actions-custom-actions-api]] @@ -279,14 +270,14 @@ For endpoint details, request and response schemas, authentication, and streamin In addition to system actions, custom actions can be created for specific use cases through the API. Custom actions allow specialized content transformations using custom prompts to control AI behavior. -Unlike system actions that use default identifiers, custom actions use a unified endpoint where the transformation behavior is defined through a prompt parameter. See https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API] for the custom actions endpoint and implementation details. +Unlike system actions that use default identifiers, custom actions use a unified endpoint, https://tinymceai.api.tiny.cloud/docs#tag/Actions/operation/callCustomAction[Call a custom action], where the transformation behavior is defined through a prompt parameter. See https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API] for the custom actions endpoint and implementation details. -Custom actions require the `ai:actions:custom` permission in the JWT token. +Custom actions require the `ai:actions:custom` permission in the JWT token. See xref:tinymceai-permissions.adoc#actions-permissions[Actions permissions]. [[actions-streaming]] === Streaming Responses -Actions use Server-Sent Events (SSE) for real-time streaming results. See the xref:tinymceai-streaming.adoc[Streaming Responses guide] for detailed implementation information. +Actions use Server-Sent Events (SSE) for real-time streaming results. See the xref:tinymceai-streaming.adoc[Streaming Responses guide] for detailed implementation information. For the events and their payloads, see https://tinymceai.api.tiny.cloud/docs#tag/Actions/operation/callSystemAction[Call a system action] and https://tinymceai.api.tiny.cloud/docs#tag/Actions/operation/callCustomAction[Call a custom action] in the API reference. [[actions-api-reference]] === API Reference diff --git a/modules/ROOT/pages/tinymceai-api-overview.adoc b/modules/ROOT/pages/tinymceai-api-overview.adoc index aafd646e0c..a187b9c760 100644 --- a/modules/ROOT/pages/tinymceai-api-overview.adoc +++ b/modules/ROOT/pages/tinymceai-api-overview.adoc @@ -1,8 +1,10 @@ = TinyMCE AI API Overview :navtitle: API overview +:pluginname: TinyMCE AI +:plugincode: tinymceai :description: Overview of TinyMCE AI service features and capabilities :description_short: API Overview -:keywords: AI, API, AI service, overview, tinymceai +:keywords: AI, API, AI service, overview, tinymceai, pagination, error codes, versioning The TinyMCE AI REST API enables AI integration within your application using the same infrastructure as the TinyMCE AI plugin, but without being tied to the editor. Integrate with multiple AI agents via one API, accessing all functionality from the Chat, Review, and Quick Actions features, with your own custom UI and workflows. @@ -12,12 +14,12 @@ The TinyMCE AI REST API enables AI integration within your application using the ==== [[getting-started]] -== Getting Started +== Getting started -New to TinyMCE AI? Start with the xref:tinymceai-api-quick-start.adoc[Quick Start] guide to set up the environment, generate access credentials, and make the first API call. +New to {pluginname}? Start with the xref:tinymceai-api-quick-start.adoc[Quick Start] guide to set up the environment, generate access credentials, and make the first API call. [[tinymce-ai-features]] -== TinyMCE AI features +== {pluginname} features * xref:tinymceai-chat.adoc[**Chat**]: Interactive AI chats with history and persistent context. * xref:tinymceai-review.adoc[**Review**]: Content analysis and proofreading, optimized for larger content. @@ -33,8 +35,74 @@ The following pages cover the AI service architecture and configuration. * xref:tinymceai-permissions.adoc[**Permissions**]: How to control user access to features. * xref:tinymceai-limits.adoc[**Limits**]: Rate limits, context size limits, and file restrictions. +[[versioning]] +== Versioning + +The version of each endpoint is part of its path, for example `+/v1/conversations+`. The {pluginname} plugin calls the `+/v1+` endpoints, and requests the model list with compatibility version `+1+`. The compatibility version is separate from the endpoint version. See xref:tinymceai-models.adoc#model-compatibility-versions[Model compatibility versions]. + +[[pagination]] +== Pagination + +List endpoints use cursor pagination. These include the conversation list, and the documents, files, and web resources of a conversation. The API reference documents the pagination parameters on each list operation, for example https://tinymceai.api.tiny.cloud/docs#tag/Conversations/operation/getConversations[Fetch multiple conversations]. + +[[error-responses]] +== Error responses + +Errors returned by the AI service use a JSON body with these fields: + +[cols="1,3",options="header"] +|=== +|Field |Description + +|`+statusCode+` +|The HTTP status code. + +|`+code+` +|A machine-readable error code, for example `+missing-permissions+`. + +|`+message+` +|A short description of the error. + +|`+traceId+` +|A unique identifier for the request. Include it when contacting {supportname}. + +|`+data+` +|Optional. An object with details specific to the error. + +|`+explanation+` +|Optional. More detail about why the error occurred. + +|`+action+` +|Optional. A suggested next step. +|=== + +For example, a token without the permission a request needs returns: + +[source,json] +---- +{ + "statusCode": 403, + "code": "missing-permissions", + "message": "The user is missing permissions", + "traceId": "8f3c1c2e-5b7a-4d0e-9a61-2f4c8e0b7d13", + "data": { + "missingPermissions": ["ai:conversations:write"] + } +} +---- + +[[error-codes]] +=== Error codes + +The API reference lists every code in its https://tinymceai.api.tiny.cloud/docs#section/Overview/Error-codes[Error codes] section. For token errors, see xref:tinymceai-jwt-authentication-intro.adoc#troubleshooting[JWT troubleshooting]. For a `+missing-permissions+` response, see xref:tinymceai-permissions.adoc[Permissions]. + +[[rate-limit-errors]] +=== Rate limit errors + +For `+429+` responses with the code `+rate-limits-exceeded+`, see xref:tinymceai-limits.adoc#handling-rate-limit-errors[Handling rate limit errors]. + [[resources-and-support]] -== Resources and Support +== Resources and support * **API Documentation**: link:https://tinymceai.api.tiny.cloud/docs[Complete API reference for TinyMCE AI]. * **Customer Support**: link:https://www.tiny.cloud/contact/[Contact us] to get help from the support team or speak with sales. diff --git a/modules/ROOT/pages/tinymceai-api-quick-start.adoc b/modules/ROOT/pages/tinymceai-api-quick-start.adoc index bbdd2779a5..04f4347feb 100644 --- a/modules/ROOT/pages/tinymceai-api-quick-start.adoc +++ b/modules/ROOT/pages/tinymceai-api-quick-start.adoc @@ -15,7 +15,7 @@ Sign up for the link:{accountsignup}[{productname} Premium Features 14-day free The {productname} Premium Features free trial allows for testing SaaS services. For on-premises solutions, link:{contactpage}[contact us]. ==== -== Getting Started +== Getting started Every request to the {pluginname} APIs must include a JWT signed with a keypair from the Customer Portal. Signing must run on the application server so private keys are never exposed to the browser. The editor supplies each token by calling xref:tinymceai.adoc#tinymceai_token_provider[+tinymceai_token_provider+], which is typically implemented as a `fetch` to a backend URL that returns a signed JWT for the signed-in user. @@ -64,7 +64,7 @@ Once the keypair is created, use it to sign JWTs in the token endpoint. For step * xref:tinymceai-with-jwt-authentication-php.adoc[JWT authentication (PHP)]: Complete PHP implementation guide [[api-integration]] -== API Integration +== API integration All features are accessible through the API at `https://tinymceai.api.tiny.cloud` with xref:tinymceai-jwt-authentication-intro.adoc[JWT authentication]. @@ -80,7 +80,7 @@ For feature documentation and API access information, see: link:https://tinymceai.api.tiny.cloud/docs[Complete API Documentation]: Full API reference with interactive examples for all endpoints. [[next-steps]] -== Next Steps +== Next steps After setting up the JWT endpoint, continue with: @@ -91,4 +91,4 @@ After setting up the JWT endpoint, continue with: * xref:tinymceai-chat.adoc#conversations-api[Chat API]: Start with interactive AI discussions. * xref:tinymceai-review.adoc#reviews-api[Review API]: Add content improvement features. * xref:tinymceai-actions.adoc#actions-api[Quick Actions API]: Implement content transformation. -* xref:tinymceai-api-overview.adoc[API Overview]: Optional high-level map of Chat, Review, Quick Actions, and related resources. +* xref:tinymceai-api-overview.adoc[API overview]: Optional high-level map of Chat, Review, Quick Actions, and related resources. diff --git a/modules/ROOT/pages/tinymceai-chat.adoc b/modules/ROOT/pages/tinymceai-chat.adoc index e110299faa..bc4394d248 100644 --- a/modules/ROOT/pages/tinymceai-chat.adoc +++ b/modules/ROOT/pages/tinymceai-chat.adoc @@ -27,7 +27,7 @@ The <> above shows the Chat sidebar open beside the docum [[working-with-the-document]] === Working with the document -{pluginname} operates directly within the context of the document. Users can ask questions about specific sections, request a full-document proofreading, and more. +{pluginname} operates directly within the context of the document. Users can ask questions about specific sections, request a full-document proofreading, and more. Each new conversation includes the current editor content and, while content is selected, the selection. See xref:tinymceai-chat.adoc#current-document-and-selection[Current document and selection]. By enabling image:icons-premium/web-search.svg[Web search icon,24px] xref:tinymceai-chat.adoc#web-search[Web search] or image:icons-premium/reasoning.svg[Reasoning icon,24px] xref:tinymceai-chat.adoc#reasoning[Reasoning], the chat capabilities can be extended, allowing the chat to look up information online and tackle complex tasks step by step. @@ -41,6 +41,15 @@ Users can chat with the AI and use it to introduce changes to the document. Ask The chat feature accelerates the creative process. Begin with a blank document and ask the AI for ideas. Build content step by step by chatting and applying changes. Then review or have the AI rewrite the final draft for best results, all in one place. +[[chat-controls]] +=== Chat controls + +The Chat sidebar provides the following controls: + +* **New chat**, in the sidebar header, starts a new conversation. The xref:tinymceai-chat.adoc#chat-history[Chat history] keeps the previous conversation. +* The image:icons/restore-draft.svg[Chat history icon,24px] history button, in the sidebar header, opens the list of past conversations. +* The image:icons/plus.svg[Add context source icon,24px] **Add context source** button, the image:icons-premium/web-search.svg[Web search icon,24px] **Web search** toggle, the image:icons-premium/reasoning.svg[Reasoning icon,24px] **Reasoning** toggle, and the model selector are below the prompt input. The model selector appears only when xref:tinymceai.adoc#tinymceai_allow_model_selection[`+tinymceai_allow_model_selection+`] is `+true+`. See xref:tinymceai-chat.adoc#available-models[Available models]. + [[integration]] == Integration @@ -55,15 +64,17 @@ Users can select the desired AI model for their conversation from a dropdown at image::tinymceai/tinymce-ai-chat-model-selector-dropdown-open.png[{pluginname} Chat available models dropdown,width=80%] -The model can be changed at any time using the same dropdown. Messages sent after a change use the newly selected model. +Each entry in the dropdown shows the model name, a short description, and whether the model supports web search and reasoning, for example **Web search: Yes • Reasoning: No**. The xref:tinymceai-chat.adoc#web-search[web search] and xref:tinymceai-chat.adoc#reasoning[reasoning] toggles are disabled when the token does not allow the capability for the selected model. See xref:tinymceai-models.adoc#model-capabilities[Model capabilities]. + +Users can change the model with the same dropdown. Messages sent after a change use the newly selected model. [[model-selection-configuration]] === Configuration Model selection for AI chat can be configured using these options: -* `tinymceai_default_model`: Sets the default model for new chat sessions. The value is a **model configuration id** (for example `+agent-1+`, `+gpt-5.4+`, or `+claude-4-5-haiku+`) that must be among the models allowed by the JWT and subscription. The xref:tinymceai-models.adoc#supported-models-table[Supported Models] table lists the documented names and ids. For the list the service returns for a given environment, use `GET /v1/models/\{version}` or the in-editor model selector when xref:tinymceai.adoc#tinymceai_allow_model_selection[+tinymceai_allow_model_selection+] is enabled; see xref:tinymceai-models.adoc#checking-compatibility[Checking compatibility]. -* `tinymceai_allow_model_selection`: When `true`, users can pick from models the service exposes in the UI; when `false`, the default model is used without a selector (defaults to `true`). +* xref:tinymceai.adoc#tinymceai_default_model[`+tinymceai_default_model+`]: Sets the default model for new chat sessions. The value is a **model configuration id** (for example `+agent-1+`, `+gpt-5.4+`, or `+claude-4-5-haiku+`) that must be among the models allowed by the JWT and subscription. The xref:tinymceai-models.adoc#supported-models-table[Supported Models] table lists the documented names and ids. For the list the service returns for a given environment, use `GET /v1/models/\{version}` or the in-editor model selector when xref:tinymceai.adoc#tinymceai_allow_model_selection[+tinymceai_allow_model_selection+] is enabled; see xref:tinymceai-models.adoc#checking-compatibility[Checking compatibility]. +* xref:tinymceai.adoc#tinymceai_allow_model_selection[`+tinymceai_allow_model_selection+`]: When `true`, users can pick from models the service exposes in the UI; when `false`, the default model is used without a selector (defaults to `true`). [source,js] ---- @@ -85,14 +96,14 @@ tinymce.init({ Web search in Chat allows the AI to access and retrieve real-time information from the internet. Instead of relying only on pre-trained knowledge, the model can search the web to find up-to-date facts, verify details, and provide more accurate, current answers. -Some models use web search automatically, while others may require manual activation. Whether the "Enable web search" button image:icons-premium/web-search.svg[Web search icon,24px] below the prompt input needs to be toggled depends on the model and sometimes even how the prompt is worded. For models that support web search, use the toggle button to enable it. +Some models use web search automatically, while others may require manual activation. Whether the **Web search** toggle image:icons-premium/web-search.svg[Web search icon,24px] below the prompt input needs to be toggled depends on the model and sometimes even how the prompt is worded. For models that support web search, use the toggle button to enable it. [[reasoning]] === Reasoning Reasoning in Chat models turns on the ability to think through problems, draw logical conclusions, and make sense of complex information. It enables the model to analyze context, connect ideas, and produce well-structured, coherent answers beyond simple pattern matching. -Some models use reasoning automatically, while others may require manual activation. Whether the "Enable reasoning" button image:icons-premium/reasoning.svg[Reasoning icon,24px] below the prompt input needs to be toggled depends on the model and sometimes even how the prompt is worded. For models that support reasoning, use the toggle button to enable it. +Some models use reasoning automatically, while others may require manual activation. Whether the **Reasoning** toggle image:icons-premium/reasoning.svg[Reasoning icon,24px] below the prompt input needs to be toggled depends on the model and sometimes even how the prompt is worded. For models that support reasoning, use the toggle button to enable it. [[welcome-chat-actions]] == Customizing the welcome message @@ -138,11 +149,23 @@ tinymce.init({ [[adding-context-to-conversations]] == Adding context to conversations -The AI chat can work with the document and beyond. Use the "Add context" image:icons/plus.svg[Add context icon,24px] button below the prompt input to add URLs, files, and external resources to the conversation. +The AI chat can work with the document and beyond. Use the **Add context source** image:icons/plus.svg[Add context source icon,24px] button below the prompt input to add URLs, files, and external resources to the conversation. The menu offers **Current document**, **File**, **Link**, and any custom source lists. + +[[current-document-and-selection]] +=== Current document and selection + +Each new conversation includes the current editor content as a **Current document** item above the prompt input. + +While content is selected in the editor, a **Selection** item appears next to the **Current document** item. The **Selection** item appears only while the current document is attached, and cannot be removed on its own. + +To start a conversation without the document, remove the **Current document** item before sending the first message. The **Current document** entry in the **Add context source** menu adds it back. After the AI has replied to a message that included the document, the document cannot be removed from that conversation. To start without the document again, select **New chat**. -Uploaded files can include PDF, DOCX, common image formats, Markdown, HTML, and plain text. Per-file size limits, attachment counts, and similar caps depend on the selected model; see xref:tinymceai-models.adoc#file-processing-limits[File processing limits]. +[[files-urls-and-external-resources]] +=== Files, URLs, and external resources -image::tinymceai/tinymce-ai-chat-add-context-source-menu.png[{pluginname} Chat add context user interface,width=80%] +Uploaded files can be PDF, DOCX, PNG, JPEG, Markdown, HTML, and plain text files. Per-file size limits, attachment counts, and similar caps depend on the selected model; see xref:tinymceai-models.adoc#file-processing-limits[File processing limits]. + +image::tinymceai/tinymce-ai-chat-add-context-source-menu.png[{pluginname} Chat Add context source menu,width=80%] Ask the AI about specific resources, for instance, _"Describe the attached image"_ or _"Summarize the key points from the attached Word document"_. The AI will analyze those resources and provide information that can be easily used in the document. @@ -195,7 +218,7 @@ tinymce.init({ When asking the AI for changes to the document, for instance, _"Bold key facts in the document"_, the AI proposes a series of changes. The changes are displayed directly in the document content, making it easy to see what will be modified. -When the AI response in the chat panel includes modification history, that block appears in a collapsible section. **Expand** shows the full history when the default preview is truncated. +When the AI response in the chat panel includes modification history, that block appears in a collapsible section. Select **View details** to show the full history when the default preview is truncated, and **Hide details** to collapse it again. [[previewing-changes]] === Previewing changes @@ -209,24 +232,23 @@ Click the checkmark image:icons/checkmark.svg[Accept suggestion icon,24px] in th image::tinymceai/tinymce-ai-chat-diff-mode-apply-single-suggestion-overlay.png[{pluginname} Chat apply changes,width=80%] -Click **Apply remaining** in the review bar at the bottom of the editor to apply all remaining suggestions at once. The button shows the number of remaining suggestions, for example, "Apply remaining (11)". +Click **Apply all** in the review bar at the bottom of the editor to apply every pending suggestion at once. After a suggestion has been applied or skipped, the button is labeled **Apply remaining** and shows the number of pending suggestions, for example, "Apply remaining (11)". image::tinymceai/tinymce-ai-chat-diff-mode-apply-remaining-suggestions.png[{pluginname} Chat apply all changes,width=80%] [[rejecting-suggestions]] === Rejecting suggestions -Click the image:icons/close.svg[Reject suggestion icon,24px] in the suggestion overlay to reject the current suggestion. Click **Skip remaining** in the review bar at the bottom of the editor to skip all remaining suggestions. +Click the image:icons/close.svg[Reject suggestion icon,24px] in the suggestion overlay to reject the current suggestion. Click **Skip all** in the review bar at the bottom of the editor to skip every pending suggestion. After a suggestion has been applied or skipped, the button is labeled **Skip remaining**. image::tinymceai/tinymce-ai-chat-diff-mode-reject-suggestion-overlay.png[{pluginname} Chat reject button,width=80%] - [[chat-history]] == Chat history -All past conversations appear in the Chat history. Click the image:icons/restore-draft.svg[Chat history icon,24px] button in the chat header to open the list. Click a conversation to reopen it, or use the menu on each entry to pin, rename, or delete it. Click **Go to AI Chat** to return from the history view to the active conversation. +All past conversations appear in the Chat history. Click the image:icons/restore-draft.svg[Chat history icon,24px] button in the chat header to open the list. Click a conversation to reopen it, or use the menu on each entry to pin, rename, or delete it. Click **AI Chat** to return from the history view to the active conversation. -Conversations are grouped by date to help navigate the history. Conversations can be filtered by name using the search field at the top of the user interface. +The list shows pinned conversations under **Pinned**, and the other conversations under **History**. image::tinymceai/tinymce-ai-chat-history-sidebar-conversation-list.png[AI Chat history,width=80%] @@ -250,7 +272,7 @@ For endpoint listings and request or response schemas, start with xref:tinymceai [[conversations-key-features]] === Key Features -The API supports uploading PDFs, Word docs, and images for the AI to read and understand. Ask questions about specific sections and get intelligent answers. The AI extracts text while preserving structure from PDFs, maintains formatting context from Word documents, parses web content from HTML files, and processes images with OCR and object recognition. +The API supports uploading PDFs, Word docs, and images for the AI to read and understand. Ask questions about specific sections and get intelligent answers. The AI extracts text while preserving structure from PDFs, maintains formatting context from Word documents, parses web content from HTML files, and describes the content of images. Each conversation builds on previous messages, so the AI keeps track of the entire discussion and any files that have been shared. Documents, images, web links, and text can be mixed in one conversation, and the AI connects information across all formats. @@ -264,18 +286,35 @@ Each conversation builds on previous messages, so the AI keeps track of the enti The AI remembers everything that has been shared and builds on it throughout the conversation. +[[conversations-api-flow]] +=== Sending a message through the API + +Sending a message through the API takes three requests. The token needs the conversation permissions for each request. See xref:tinymceai-permissions.adoc#conversation-permissions[Conversation permissions]. + +. https://tinymceai.api.tiny.cloud/docs#tag/Conversations/operation/createConversation[Create the conversation]. +. Attach content: an https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Documents/operation/createDocument[HTML document], a https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Files/operation/uploadFile[file], or a https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Web-Resources/operation/downloadWebResources[web page]. File size limits are listed in xref:tinymceai-limits.adoc#file-limits[File limits]. +. https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages/operation/createMessage[Send the message]. The service streams the reply with Server-Sent Events (SSE). See xref:tinymceai-chat.adoc#conversations-streaming[Streaming responses]. + [[conversations-api-capabilities]] -=== API Capabilities +=== API capabilities + +The `+capabilities+` object of a https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages/operation/createMessage[message request] enables web search (`+webSearch+`) and reasoning (`+reasoning+`) for that message. See xref:tinymceai-models.adoc#model-capabilities[Model capabilities] and xref:tinymceai-models.adoc#reasoning[Reasoning]. + +Web search is separate from the https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Web-Resources[Conversation Web Resources] endpoints, which attach the content of one known URL to the conversation. + +[[conversations-api-stored]] +=== Working with stored conversations -When using the Conversations API directly, advanced capabilities can be configured: +The Chat history in the sidebar shows the conversations and messages that the AI service stores. The following operations read and manage the same data: -* **Web Search**: Enable real-time web search to access current information during conversations. Configure using the `webSearch` capability in API requests. See https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Web-Resources[Conversation Web Resources API] for endpoint details. -* **Reasoning**: Enable step-by-step reasoning to see the AI's problem-solving process. Configure using the `reasoning` capability in API requests. See https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages[Conversation Messages API] for endpoint details. +* https://tinymceai.api.tiny.cloud/docs#tag/Conversations/operation/getConversations[List conversations]. +* https://tinymceai.api.tiny.cloud/docs#tag/Conversations/operation/getConversation[Get a conversation], https://tinymceai.api.tiny.cloud/docs#tag/Conversations/operation/updateConversation[update a conversation] (for example, to rename or pin it), or https://tinymceai.api.tiny.cloud/docs#tag/Conversations/operation/deleteConversation[delete a conversation]. +* https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages/operation/getMessages[List the messages in a conversation]. [[conversations-streaming]] === Streaming Responses -Conversations use Server-Sent Events (SSE) for real-time streaming responses. See the xref:tinymceai-streaming.adoc[Streaming Responses guide] for detailed implementation information and code examples. +Conversations use Server-Sent Events (SSE) for real-time streaming responses. See the xref:tinymceai-streaming.adoc[Streaming Responses guide] for detailed implementation information and code examples. For the events and their payloads, see https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages/operation/createMessage[Send a message] in the API reference. [[conversations-api-reference]] === API Reference diff --git a/modules/ROOT/pages/tinymceai-integration-options.adoc b/modules/ROOT/pages/tinymceai-integration-options.adoc index 476ba38783..c7d0d6b3ee 100644 --- a/modules/ROOT/pages/tinymceai-integration-options.adoc +++ b/modules/ROOT/pages/tinymceai-integration-options.adoc @@ -24,9 +24,10 @@ Use the AI service API to build custom integrations and workflows. Suitable for | [.lead] -**On-Premises Deployment** +xref:tinymceai-on-premises.adoc[**On-Premises Deployment**] include::partial$misc/tinymceai-on-premises-early-access-note.adoc[] a| -|=== \ No newline at end of file +|=== + diff --git a/modules/ROOT/pages/tinymceai-introduction.adoc b/modules/ROOT/pages/tinymceai-introduction.adoc index 5c3a99ccbd..ff9cadc5f0 100644 --- a/modules/ROOT/pages/tinymceai-introduction.adoc +++ b/modules/ROOT/pages/tinymceai-introduction.adoc @@ -22,7 +22,7 @@ liveDemo::tinymceai[] {pluginname} is an AI-powered writing assistant platform with two core components: * **xref:tinymceai.adoc[{pluginname} plugin]**: Integrates the AI directly into {productname}, providing instant text rewriting, summarization, correction, and contextual chat help based on organizational style guides. It includes automated review tools and enterprise-ready functionality that integrates with existing systems without requiring custom infrastructure. The plugin is available for both {cloudname} and self-hosted {productname}; from {productname} 8.7.0, it can be installed from the `+tinymce-premium+` NPM package or as an addon `.zip`. -* **xref:tinymceai-api-overview.adoc[TinyMCE AI API]**: A state-of-the-art back-end AI engine that incorporates multiple models and delivers high-quality content. Any functionality available in the plugin is also available in the API, plus more, and the API can be used anywhere in your application -- not just in {productname}. *The hosted AI service is currently available in Cloud setup only.* +* **xref:tinymceai-api-overview.adoc[TinyMCE AI API]**: A state-of-the-art back-end AI engine that incorporates multiple models and delivers high-quality content. Any functionality available in the plugin is also available in the API, plus more, and the API can be used anywhere in your application -- not just in {productname}. *The hosted AI service is currently available in Cloud setup only.* The API is also available from the self-hosted xref:tinymceai-on-premises.adoc[on-premises service]. These components enable teams to implement a full suite of AI writing tools quickly, delivering efficient content workflows that maintain brand consistency and integrate smoothly with document management systems. In addition, the plugin and API use the same authorisation mechanisms and share conversation history, enabling ease of integration with your application's broader content authoring workflow -- not just within {productname}. @@ -58,7 +58,7 @@ Developers can control access to AI features, models, and capabilities based on [[regional-data-storage]] === Regional Data Storage -All data stored by Tiny for {pluginname} is handled in the US region. +All data stored by Tiny for {pluginname} is handled in the US region. Data sent to LLM providers for processing is currently handled in the US region. {productname} does not offer separate LLM processing regions to choose from. diff --git a/modules/ROOT/pages/tinymceai-jwt-authentication-intro.adoc b/modules/ROOT/pages/tinymceai-jwt-authentication-intro.adoc index 2b5b4aff34..5023e5e335 100644 --- a/modules/ROOT/pages/tinymceai-jwt-authentication-intro.adoc +++ b/modules/ROOT/pages/tinymceai-jwt-authentication-intro.adoc @@ -36,7 +36,7 @@ tinymce.init({ selector: "textarea", plugins: "tinymceai", toolbar: "tinymceai-chat tinymceai-review tinymceai-quickactions", - sidebar_show: 'aichat', + sidebar_show: 'tinymceai-chat', tinymceai_token_provider: async () => { await fetch(`https://demo.api.tiny.cloud/1/no-api-key/auth/random`, { method: "POST", credentials: "include" }); return await fetch(`https://demo.api.tiny.cloud/1/no-api-key/jwt/tinymceai`, { credentials: "include" }) @@ -60,7 +60,7 @@ tinymce.init({ selector: "textarea", plugins: "tinymceai", toolbar: "tinymceai-chat tinymceai-review tinymceai-quickactions", - sidebar_show: 'aichat', + sidebar_show: 'tinymceai-chat', tinymceai_token_provider: async () => { // Wait for the session request so the JWT endpoint receives the session cookie. await isLoggedIn; @@ -148,11 +148,21 @@ The JWT payload is a JSON object containing claims that identify the user, speci The following properties **must** be included in the payload: * `aud`: The API key that has entitlements to use {pluginname}. -* `sub`: The user ID. This should be a unique identifier for the user making the request. This identifier is used to lock down conversation history, AI-generated content, and other user-specific data to individual users, ensuring privacy and data isolation. +* `sub`: The user ID. This should be a unique identifier for the user making the request. This identifier is used to lock down conversation history, AI-generated content, and other user-specific data to individual users, ensuring privacy and data isolation. The user ID must not exceed 96 characters. * `iat`: "Issued at". Ensure `iat` is present and contains a correct time stated in seconds. Some JWT implementations do not include it by default. Sometimes the system time may also be invalid, causing issues. * `exp`: Token expiration time. Identifies the expiration time after which the JWT will not be accepted. {pluginname} only accepts tokens no older than 24 hours. This field can be used to shorten the token validity time. * `auth`: The `auth.ai.permissions` array inside is required. This defines which AI features the user can access. See xref:#permissions[Permissions] below for details. +Every token returned during one editor session must carry the same `+sub+` and `+aud+` values as the first token. To switch to a different user or API key, reload the editor. See xref:#changed-claims-error[Changed `+sub+` or `+aud+` claims]. + +Each token must also meet these requirements, or the editor shows an error and the request is not sent: + +* It contains `+sub+`, `+aud+`, `+iat+`, `+exp+`, and the `+auth.ai.permissions+` array. Otherwise, the error is `+Invalid JWT token payload+`. +* It is no more than two minutes past its `+exp+` time. +* Its `+iat+` and `+exp+` times are no more than 24 hours in the past. + +A token that fails either time check produces the error `+JWT token has expired+`. + The properties that are optional: * `user`: User information. Providing `name` and `email` is recommended for better user experience and debugging. @@ -160,7 +170,7 @@ The properties that are optional: [[example-token-payload]] ==== Example Token Payload -The example below presents a complete token payload with access to all AI features: +The example below presents a complete token payload: [source,json] ---- @@ -226,7 +236,7 @@ The token for {pluginname} is requested by the {pluginname} plugin. The easiest The token endpoint will be requested: * At editor initialization -* Periodically to refresh the token (typically every hour) +* On the next request to the AI service once the current token is within 60 seconds of its `+exp+` time [[simple-token-request]] === Simple Usage @@ -248,13 +258,13 @@ tinymce.init({ [TIP] ==== -The editor will not be ready to use until the first token is obtained from the token endpoint. If an error occurs during the initial request, the editor will not start correctly. +The first token is requested while the editor loads. If the token request fails, the editor still starts, an error notification appears, and {pluginname} requests fail until the token endpoint returns a valid token. ==== [[token-responses]] == Responses from the Token Endpoint -The token provider must return an object with a `+token+` property: `+{ token: string }+`. The endpoint may respond in either format: +The token provider must return a Promise that resolves to an object with a `+token+` property: `+{ token: string }+`. The plugin reports an error if the function does not return a Promise, or if the resolved value has no `+token+` string. The endpoint may respond in either format: * **JSON response**: Endpoint returns `+{ "token": "eyJ..." }+`. Use `+response.json()+` and return `+{ token: data.token }+`. * **Plain text response**: Endpoint returns the raw JWT string. Use `+response.text()+` and return `+{ token }+`. @@ -305,8 +315,10 @@ If an error message indicates an invalid token: * Verify that the token is signed with one of the xref:#supported-algorithms[supported algorithms] * Check that the public key in the {accountpage} matches the private key used to sign the token * Validate the token structure using the link:https://jwt.io/[jwt.io debugger] +* Check that the token has every required claim and has not expired, as described in xref:#payload-properties[Payload properties] * Ensure the `iat` (issued at) timestamp is correct and not in the future * Verify that system time is accurate (time drift can cause token validation issues) +* If the error code is `+jwt-too-long+`, reduce the size of the claims [[insufficient-permissions-error]] === Insufficient permissions @@ -317,6 +329,17 @@ If an error indicates insufficient permissions: * Check that the permissions match the AI features being accessed * Review the xref:tinymceai-permissions.adoc[Permissions] guide for the correct permission format * Ensure permissions are specified correctly (for example, `ai:conversations:read`, `ai:conversations:write`) +* Add the scopes listed in the `+data.missingPermissions+` array of the `+403+` `+missing-permissions+` response + +[[changed-claims-error]] +=== Changed `+sub+` or `+aud+` claims + +If the plugin reports that the JWT token claims (`+sub+` or `+aud+`) have changed since the last token was issued, the token provider returned a token for a different user or API key during the same editor session. Return tokens with the same `+sub+` and `+aud+` for the whole session, or reload the editor after the user changes. + +[[error-codes]] +=== Error codes + +For the error response shape, see xref:tinymceai-api-overview.adoc#error-responses[Error responses]. For the full list of error codes, see the link:https://tinymceai.api.tiny.cloud/docs#section/Overview/Error-codes[API reference]. The token-related fixes are in xref:#invalid-token-error[Invalid token] and xref:#insufficient-permissions-error[Insufficient permissions]. [[related-features]] == Related Features diff --git a/modules/ROOT/pages/tinymceai-limits.adoc b/modules/ROOT/pages/tinymceai-limits.adoc index 09542b974b..90ede2f663 100644 --- a/modules/ROOT/pages/tinymceai-limits.adoc +++ b/modules/ROOT/pages/tinymceai-limits.adoc @@ -17,6 +17,11 @@ Rate limits control the frequency of requests to prevent abuse and ensure servic NOTE: Specific rate limit values are subject to change and may vary based on the subscription tier. For current rate limit details for the environment, link:{contactpage}[contact {supportname}]. +[[handling-rate-limit-errors]] +=== Handling rate limit errors + +A request over a rate limit fails with HTTP status `+429 Too Many Requests+` and the error code `+rate-limits-exceeded+`. The `+data.limits+` array in the error body names each limit that the request exceeded, for example `+[{ "name": "messages-per-minute" }]+`, and the `+action+` field reads `+Try again later.+` For the other fields of the error body, see xref:tinymceai-api-overview.adoc#error-responses[Error responses]. The API reference lists this response for https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages/operation/createMessage[sending conversation messages] and for https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Web-Resources/operation/downloadWebResources[adding web resources to a conversation]. + [[context-limits]] == Context Limits @@ -25,7 +30,9 @@ Context limits control how much content can be attached to conversations to ensu [[file-limits]] === File Limits -Supported attachment types include PDF, DOCX, PNG, JPEG, Markdown, HTML, and plain text. Exact per-file, per-conversation, and PDF page limits depend on the model in use. Read the `limits` object for that model from `GET /v1/models/\{version}` (see xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model] and xref:tinymceai-models.adoc#model-information[Model Information]). For schema details, see the https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] OpenAPI documentation. +Supported attachment types include PDF, DOCX, PNG, JPEG, Markdown, HTML, and plain text. The API accepts files of up to 25 MB in a single upload to a conversation. Exact per-file, per-conversation, and PDF page limits also depend on the model in use. Read the `+limits+` object for that model from `GET /v1/models/\{version}` (see xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model] and xref:tinymceai-models.adoc#model-information[Model Information]). For schema details, see the https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] OpenAPI documentation. + +The file picker in the {pluginname} plugin offers only the supported attachment types. The service enforces the file size and page count limits. [[context-optimization-tips]] === Context Optimization Tips @@ -35,9 +42,11 @@ Compress images and split large documents into smaller sections. Use text format [[model-specific-limits]] == Model-Specific Limits -Different AI models have varying capabilities and limitations that affect context processing. Each model exposes numeric caps and capability flags in the `GET /v1/models/\{version}` response: find the object in `items` whose `id` matches the model in use, then read `limits` (for example context length and file size ceilings, often in bytes) and `capabilities`. See xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model]. +Different AI models have varying capabilities and limitations that affect context processing. Each model exposes numeric caps and capability flags in the `GET /v1/models/\{version}` response: find the object in `+items+` whose `+id+` matches the model in use, then read `+limits+` (for example context length and file size ceilings, often in bytes) and `+capabilities+`. See xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model]. + +Models also have response timeouts, file processing timeouts, web resource timeouts, and streaming response limits. -Models also have response timeouts, file processing timeouts, web resource timeouts, and streaming response limits. All models include content moderation for inappropriate content, safety checks, and moderation response time limits. +For content moderation, see xref:tinymceai-models.adoc#content-moderation[Content moderation]. [[next-steps]] == Next Steps @@ -45,4 +54,4 @@ Models also have response timeouts, file processing timeouts, web resource timeo * xref:tinymceai-models.adoc#model-information[Model Information] documents the `GET /v1/models/\{version}` request; each item in the response includes `limits` and capabilities for that model. * xref:tinymceai-permissions.adoc[Set up Permissions] to control user access. * xref:tinymceai-chat.adoc[Explore Chat] for context management. -* https://tinymceai.api.tiny.cloud/docs[API Documentation]: Complete API reference for TinyMCE AI. +* https://tinymceai.api.tiny.cloud/docs[API documentation]: Complete API reference for {pluginname}. diff --git a/modules/ROOT/pages/tinymceai-models.adoc b/modules/ROOT/pages/tinymceai-models.adoc index 4e831e8f9f..0db049e27d 100644 --- a/modules/ROOT/pages/tinymceai-models.adoc +++ b/modules/ROOT/pages/tinymceai-models.adoc @@ -13,25 +13,28 @@ The `agent-1` model automatically selects the best AI model for requests based on speed, quality, and cost. It is the recommended choice for most use cases as it optimizes performance and cost automatically. +* For the token scope that the Agent model needs, see xref:tinymceai-permissions.adoc#model-permissions[Model permissions]. +* The model selector in the {pluginname} plugin shows the Agent model as *Auto*. + [[available-models]] == Available Models -{pluginname} supports multiple AI models from different providers. Each model has unique capabilities, performance characteristics, and cost profiles. By default, the automatically selected model (`agent-1`) will be used for optimal cost and performance. +{pluginname} supports multiple AI models from different providers. Each model has unique capabilities, performance characteristics, and cost profiles. For the model used when no model is selected, see xref:tinymceai.adoc#tinymceai_default_model[`+tinymceai_default_model+`]. The model selector lists every model that the models endpoint returns, including models that the token does not allow. [[supported-models-table]] === Supported Models -The following is a detailed list of available models with their capabilities: +[[supported-models]]The following is a detailed list of available models with their capabilities: [cols="1,2,1,1,2"] |=== |Model |Description |xref:tinymceai-chat.adoc#web-search[Web Search] |xref:tinymceai-chat.adoc#reasoning[Reasoning] |Configuration id -|**Auto (default)** +|**Agent** (shown as *Auto* in the plugin) |Automatically selects best model for speed, quality, and cost. |Yes |Yes -|`'auto'` (also `'agent-1'`, learn more about xref:tinymceai-models.adoc#model-compatibility-versions[compatibility versions]) +|`+'agent-1'+` (learn more about xref:tinymceai-models.adoc#model-compatibility-versions[compatibility versions]) |**GPT-5.6 Sol** |OpenAI's frontier model for complex professional work and advanced reasoning @@ -211,6 +214,8 @@ The agent model (`agent-1`) automatically selects the best underlying model base * **Required capabilities**: Web search and reasoning require compatible models * **Cost optimization**: Balances quality with cost efficiency +When no model can process the request, the service returns a `+502 Bad Gateway+` error with the code `+no-available-models+`. Retry the request after a few minutes. + [[model-configuration]] === Model Configuration @@ -244,13 +249,15 @@ tinymce.init({ [[model-compatibility-versions]] == Model Compatibility Versions -Models are organized by compatibility versions to ensure API stability. When new models are introduced or existing models are updated, they may be added to a new compatibility version. +Models are organized by compatibility versions to ensure API stability. When new models are introduced or existing models are updated, they may be added to a new compatibility version. Request paths include the version, as in `+GET /v1/models/1+`. [[how-it-works]] === How It Works Compatibility versions allow {pluginname} to introduce new models and capabilities without breaking existing integrations. Each version maintains a stable set of models and capabilities. +The {pluginname} plugin requests the models for version `+1+`. + [[checking-compatibility]] === Checking Compatibility @@ -267,13 +274,13 @@ Follow these steps to read limits and capabilities for the model the integration * *Align base URL and credentials* ** Call the same HTTP base URL the editor uses for {pluginname} requests. If the base URL and JWT do not belong to the same environment, the response is an authorization error rather than model metadata. * *List models for the compatibility version* -** Request `GET /v1/models/\{version}` with the compatibility version the integration targets (often `1`). Use the https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] OpenAPI definition to confirm `\{version}` when unsure. +** Request `+GET /v1/models/1+`, the compatibility version that the {pluginname} plugin uses. To read a single model, request `+GET /v1/models/1/{id}+`. * *Pick the matching `items[]` entry* ** In the JSON `items` array, select the object whose `id` matches the model in configuration (`tinymceai_default_model`) or in API bodies (`model`). * *Read `limits` and `capabilities`* -** Inspect `limits` for numeric caps (sizes are usually in bytes). Inspect `capabilities` for `webSearch` and `reasoning`, using `enabled` and `allowed`. Compare with the example response under xref:tinymceai-models.adoc#model-information[Model Information]. +** Inspect `+limits+` for numeric caps (sizes are in bytes). Inspect `capabilities` for `webSearch` and `reasoning`, using `enabled` and `allowed`. Compare with the example response under xref:tinymceai-models.adoc#model-information[Model Information]. * *Interpret availability flags* -** Treat `allowed: false` as “model not available for this token or subscription.” The `recommended` field guides default selection in the UI; it does not alter `limits`. +** Treat `+allowed: false+` as "the token does not include a scope for this model." The `+recommended+` field indicates whether the service recommends the model; it does not alter `+limits+`. [TIP] ==== @@ -283,7 +290,12 @@ Ready-to-run `fetch` (browser console) and `curl` examples appear under xref:tin [[model-capabilities]] == Model Capabilities -Different models support different capabilities (such as web search and reasoning). Check the model information through the API endpoint or the plugin model selection UI to see which capabilities are available for each model. +Web search and reasoning are optional capabilities, and not every model supports both. In the models response, the `+capabilities+` object of each model has an entry for `+webSearch+` and for `+reasoning+`: + +* `+enabled+`: Whether the model supports the capability. +* `+allowed+`: Whether the token permits the capability, based on its scopes. This field is present only when `+enabled+` is `+true+`. + +The {pluginname} plugin offers web search and reasoning in Chat only when the selected model reports the capability as allowed. For the token scopes, see xref:tinymceai-permissions.adoc#conversation-permissions[Conversation permissions], or xref:tinymceai-on-premises-jwt.adoc#permissions-reference[JWT permissions for the on-premises AI service] for the on-premises AI service. [[web-search]] === Web Search @@ -293,7 +305,7 @@ Enable real-time web search to access current information during conversations. [[reasoning]] === Reasoning -Enable step-by-step reasoning to see the AI's problem-solving process. Some models have reasoning always enabled and cannot be turned off. +The API does not return the reasoning text. The stream sends `+reasoning+` events with no text while the model is reasoning. Some models have reasoning always enabled and cannot be turned off. **Always-on reasoning models:** @@ -302,48 +314,53 @@ Enable step-by-step reasoning to see the AI's problem-solving process. Some mode To determine if a model has always-on reasoning, check the API response when listing models or refer to the model capabilities in the plugin UI. Models with mandatory reasoning will indicate this in their capability structure. -NOTE: Model names such as `gpt-5`, `claude-4-sonnet`, and similar are examples. Actual available models depend on the service compatibility version. Use the `/v1/models` API endpoint or check the plugin model selection dropdown to see current available models for the environment. +NOTE: Model names such as `+gpt-5+`, `+claude-4-sonnet+`, and similar are examples. Actual available models depend on the service compatibility version. Use the `+GET /v1/models/1+` API endpoint or check the plugin model selection dropdown to see current available models for the environment. [[web-scraping]] === Web Scraping -Web scraping extracts and processes content from web pages so the AI can analyze and summarize it. When users add web resources as context in xref:tinymceai-chat.adoc#adding-context-to-conversations[Chat], the service fetches and parses the page content for the AI to use. Web scraping supports standard web pages and is subject to xref:tinymceai-limits.adoc#rate-limits[rate limits] for web resource requests. +Web scraping extracts and processes content from web pages so the AI can analyze and summarize it. When users add web resources as context in xref:tinymceai-chat.adoc#adding-context-to-conversations[Chat], the service fetches and parses the page content for the AI to use. For the token scope, see xref:tinymceai-permissions.adoc#context-permissions[Conversation attachment permissions]. Web scraping supports standard web pages and is subject to xref:tinymceai-limits.adoc#rate-limits[rate limits] for web resource requests. [[model-limitations]] == Model Limitations -Per-model caps (context length, attachment sizes, PDF page totals, and similar) are returned in the `limits` object for each entry in `GET /v1/models/\{version}`. Those values are **the limits the service applies at runtime** and can differ by model (for example stricter `maxImageSize` than `maxFileSize` for some providers). See xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model] for how to match the integration’s model id to the correct `items[]` entry. +Per-model caps (context length, attachment sizes, PDF page totals, and similar) are returned in the `+limits+` object for each entry in `GET /v1/models/\{version}`. Those values are **the limits the service applies at runtime** and can differ by model. See xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model] for how to match the integration’s model id to the correct `+items[]+` entry. The sections below cover moderation, descriptions, and deprecation. Attachment limits are documented only under xref:tinymceai-models.adoc#file-processing-limits[File processing limits], using the live models API so values stay aligned with the service. [[file-processing-limits]] === File Processing Limits -{pluginname} supports common attachment types in Chat conversations, including PDF, DOCX, images, Markdown, HTML, and plain text. Per-file and per-conversation ceilings—including maximum sizes, attachment counts, and PDF page totals—are returned per model in the `limits` object from `GET /v1/models/\{version}`. Those numbers are **the current limits the service applies**; they can change with the service and vary by model, so read the `limits` object from that response at runtime for each model the integration uses. Field names, units, and schema updates are defined in the https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] OpenAPI documentation. +{pluginname} supports common attachment types in Chat conversations, including PDF, DOCX, images, Markdown, HTML, and plain text. Per-file and per-conversation ceilings—including maximum sizes, attachment counts, and PDF page totals—are returned per model in the `limits` object from `GET /v1/models/\{version}`. Those numbers are **the current limits the service applies**; they can change with the service and vary by model, so read the `+limits+` object from that response at runtime for each model the integration uses. Field names, units, and schema updates are defined in the https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] OpenAPI documentation. -For the request flow and how to match a configured model id to the correct `items[]` entry, see xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model]. Typical `limits` keys include `maxFileSize`, `maxImageSize`, `maxFiles`, `maxTotalFileSize`, and `maxTotalPdfFilePages`. +For the request flow and how to match a configured model id to the correct `items[]` entry, see xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model]. The https://tinymceai.api.tiny.cloud/docs#tag/Models/operation/getAiModels[Models API reference] defines each `+limits+` key. [[content-moderation]] === Content Moderation -All models include moderation for inappropriate content, harmful instructions, personal information, copyrighted material, misinformation, sensitive topics, and security threats. Requests containing content that triggers moderation may be rejected with an error response. Moderation is applied automatically and cannot be disabled. +All models include moderation for inappropriate content, harmful instructions, personal information, copyrighted material, misinformation, sensitive topics, and security threats. When moderation flags the content, the request fails with HTTP status `+422 Unprocessable Content+` and the error code `+unsafe-content-detected+`. The `+data.flaggedCategories+` array in the error body lists the categories that were flagged. For the error body, see xref:tinymceai-api-overview.adoc#error-responses[Error responses]. For the operations that can return this error, see the https://tinymceai.api.tiny.cloud/docs[API reference]. Moderation is applied automatically and cannot be disabled. [[model-descriptions]] === Model Descriptions -Model descriptions returned by the API are provided in English and may be updated over time to reflect model improvements or capability changes. For applications that require translated model descriptions, see xref:tinymceai-models.adoc#translation-and-localization[Translation and Localization] below. +Model descriptions returned by the API are provided in English by default and may be updated over time to reflect model improvements or capability changes. For applications that require translated model descriptions, see xref:tinymceai-models.adoc#translation-and-localization[Translation and Localization] below. [[translation-and-localization]] === Translation and Localization -NOTE: Back-end translation handling for model descriptions is planned in a future release. Until then, use the approach described below. +The models endpoints accept an optional `+languageCode+` query parameter, for example `+GET /v1/models/1?languageCode=de+`, and then return translated model descriptions. For the supported language codes, see the https://tinymceai.api.tiny.cloud/docs#tag/Models/operation/getAiModels[Models API] reference. + +In the {pluginname} plugin, model descriptions follow the primary language subtag of the editor language, for example `+fr+` for `+fr-FR+`, `+pt+` for `+pt-BR+`, and `+zh+` for `+zh-TW+`. Descriptions are in English when no editor language is set. -If the application requires translated model descriptions (the text returned by the API for each model), maintain a translation map in the code keyed by `model.id`, with fallback to the English description from the API for unknown models. This allows new models to work immediately while translations are added at a custom pace. +For a language that the endpoint does not support, maintain a translation map in the application code keyed by `+model.id+`, with fallback to the description from the API for unknown models. This allows new models to work immediately while translations are added at a custom pace. [[model-deprecation]] === Model Deprecation -Models scheduled for removal will include a `removal` field with an ISO 8601 date (for example, `"removal": "2025-11-17T00:00:00.000Z"`). When a model is removed, API requests will fail with error code `MODEL_NOT_FOUND` and the models endpoint will stop returning that particular model. +Each model in the models response can include two dates: + +* `+addition+`: The date the model becomes available. Before this date, requests cannot use the model. +* `+removal+`: The date the model is removed, as an ISO 8601 date (for example, `+"removal": "2025-11-17"+`). After this date, API requests that name the model fail with the error code `+model-not-found+`, and the models endpoint stops returning that model. [[api-examples]] == API Examples @@ -390,12 +407,14 @@ Authorization: Bearer } ---- +See xref:#model-capabilities[Model capabilities] for the model support and token scopes that each capability needs. + [[model-information]] === Model Information Get all available models for compatibility version `1`. -Replace `` with a JWT from xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. Use the same TinyMCE AI API base URL the integration uses for requests. For {cloudname} production deployments, that URL is `https://tinymceai.api.tiny.cloud`. A JWT is valid only for the API host and credentials it was issued for. +Replace `` with a JWT from xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. Use the same {pluginname} API base URL the integration uses for requests. For {cloudname} production deployments, that URL is `https://tinymceai.api.tiny.cloud`. A JWT is valid only for the API host and credentials it was issued for. To try the request from a **browser DevTools console** (JavaScript), substitute a real token string for `''` and use the same base URL as in the application. The `fetch` and `curl` examples below use `https://tinymceai.api.tiny.cloud`. @@ -441,7 +460,6 @@ Response (shape illustrated; field names and numeric limits follow the live serv "maxContextLength": 256000, "maxFiles": 100, "maxFileSize": 25000000, - "maxImageSize": 5000000, "maxTotalFileSize": 30000000, "maxTotalPdfFilePages": 100 }, @@ -460,11 +478,12 @@ Response (shape illustrated; field names and numeric limits follow the live serv } ---- -* **`id`**: Model identifier for `tinymceai_default_model` and API `model` fields. -* **`allowed`**: Whether the model can be used with the current token or subscription. -* **`recommended`**: Service hint for default or highlighted models in UIs. -* **`limits`**: Per-model numeric caps (sizes are typically bytes; `maxContextLength` is the context budget for that model in the service). -* **`capabilities`**: Whether `webSearch` and `reasoning` are available (`allowed`) and on by default (`enabled`) for that model. +* **`id`**: Model identifier for xref:tinymceai.adoc#tinymceai_default_model[`+tinymceai_default_model+`] and API `+model+` fields. +* **`allowed`**: Whether the token's scopes allow the model. +* **`recommended`**: Whether the service recommends the model. +* **`limits`**: Per-model numeric caps. Sizes are in bytes, and `+maxContextLength+` is a number of characters. The https://tinymceai.api.tiny.cloud/docs#tag/Models/operation/getAiModels[Models API reference] defines each key. +* **`capabilities`**: For `+webSearch+` and `+reasoning+`, whether the model supports the capability (`+enabled+`) and whether the token permits it (`+allowed+`). +* **`+addition+`** and **`+removal+`** (optional): The dates the model becomes available and is removed. See xref:#model-deprecation[Model deprecation]. After xref:tinymceai-models.adoc#verifying-model-limits-for-integration[locating the entry for the configured `id`], use these fields to validate integrations (for example before uploading large attachments or enabling reasoning in API calls). diff --git a/modules/ROOT/pages/tinymceai-on-premises-database.adoc b/modules/ROOT/pages/tinymceai-on-premises-database.adoc index 5b01e47d71..81de99c258 100644 --- a/modules/ROOT/pages/tinymceai-on-premises-database.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises-database.adoc @@ -54,7 +54,7 @@ NOTE: This section applies to PostgreSQL deployments only. MySQL deployments can The AI service expects a schema named `cs-on-premises` (with hyphens). If that schema does not exist, the container crashes on first boot with: .... -error: schema "cs-on-premises" does not exist +[FATAL] PostgreSQL Error: schema "cs-on-premises" does not exist .... Apply one of the following fixes *before* starting the AI service for the first time. @@ -89,13 +89,15 @@ TIP: Pin specific major versions for all data layer images (`mysql:8.0`, `postgr [[mysql-version-pinning]] === MySQL -WARNING: Do *not* use `mysql:8`. That tag now floats to the latest MySQL, which removes the `default-authentication-plugin=mysql_native_password` startup flag the AI service relies on. The container crashloops with: +WARNING: Do *not* use `mysql:8`. That tag now resolves to MySQL 8.4, which removes the `default-authentication-plugin` server option. A MySQL container started with `--default-authentication-plugin=mysql_native_password`, as some older compose files and manifests do, fails at startup and restarts repeatedly with: .... [ERROR] [MY-000067] [Server] unknown variable 'default-authentication-plugin=mysql_native_password'. [ERROR] [MY-010119] [Server] Aborting .... +The AI service connects with the MySQL 8.0 default authentication plugin, so that option is not needed; the examples on this page do not set it. + Pin to `mysql:8.0` in every manifest: `docker run`, Docker Compose, Kubernetes, Helm, ECS. Running newer MySQL versions with workarounds (removing the flag and switching to `caching_sha2_password`) is not a supported configuration. @@ -130,9 +132,9 @@ GRANT ALL PRIVILEGES ON ai_service.* TO 'ai_service'@'%'; [NOTE] -- -Some versions of the AI service image report false-positive "Not enough permissions to access database" errors even with `ALL PRIVILEGES`. If this occurs, grant the privileges globally rather than per-database, or use the MySQL `root` user for development. +Grant the privileges on the AI service database itself (`ON ai_service.*`), as in the statements above. The startup check does not accept privileges granted globally (`ON *.*`) or inherited through a role: the service stops with `Not enough permissions to access database. Missing privileges: ...` even when the user holds every listed privilege. -On Cloud SQL MySQL, grant privileges to the service user **directly** — not via a role (e.g. `cloudsqlsuperuser`). The startup grant check runs `SHOW GRANTS FOR user` and does not resolve role-inherited grants. +On Cloud SQL MySQL, the default user holds its privileges through the `cloudsqlsuperuser` role. Run the database-scoped `GRANT` statement for the service user before the first start. -- === PostgreSQL @@ -170,7 +172,7 @@ GRANT ALL ON SCHEMA "cs-on-premises" TO ai_service; == Database setup -The sections below provide ready-to-use configuration for each database engine. Use the Docker Compose files for local evaluation; for production, provision managed database services (Amazon RDS, Azure Database, Cloud SQL) and pass the connection details as environment variables (see <<_connecting_the_ai_service>>). +The sections below provide ready-to-use configuration for each database engine. Use the Docker Compose files for local evaluation; for production, provision managed database services (Amazon RDS, Azure Database, Cloud SQL) and pass the connection details as environment variables (see <>). === Docker Compose (recommended for evaluation) @@ -733,21 +735,14 @@ Expected: `PONG`. === AI service migration -After starting the AI service, confirm it has connected and run migrations: +After starting the AI service, check the log for start-up errors: [source,bash] ---- -docker logs ai-service 2>&1 | grep -i 'migrat\|schema\|database' +docker logs ai-service 2>&1 | grep -i 'fatal\|error\|listening' ---- -Expected output (paraphrased): - -.... -Connecting to database (driver=postgres host=...) -Running migrations on schema "cs-on-premises" -Migrations complete: 32 tables ready -Server is listening on port 8000. -.... +A successful start logs `Server is listening on port 8000.` The start-up log does not report the database driver, the schema, or the migration count, so list the tables to confirm the migrations ran (see below). On a new database, the migrations create 32 tables. If `schema "cs-on-premises" does not exist` appears, return to <>. If `unknown variable 'default-authentication-plugin'` appears, return to <>. diff --git a/modules/ROOT/pages/tinymceai-on-premises-frameworks.adoc b/modules/ROOT/pages/tinymceai-on-premises-frameworks.adoc index 119a5a0a9c..0c2b572b63 100644 --- a/modules/ROOT/pages/tinymceai-on-premises-frameworks.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises-frameworks.adoc @@ -45,7 +45,7 @@ The plugin calls the token provider on initialization and again before the cache |Include one or more of `tinymceai-chat`, `tinymceai-review`, `tinymceai-quickactions`. |`tinymceai_service_url` -|The origin of the AI service (no trailing slash, no path), for example `\https://ai.yourcompany.com`. +|The base URL of the AI service, for example `\https://ai.yourcompany.com`, or `\https://www.yourcompany.com/ai` when a reverse proxy serves the AI service under a path. See xref:tinymceai.adoc#tinymceai_service_url[`+tinymceai_service_url+`]. |`tinymceai_token_provider` |A function returning `Promise<{ token: string }>`. See <> below. @@ -121,7 +121,7 @@ tinymceai_token_provider: () => { |The plugin calls the provider on initialization and again when the cached token nears expiry (60-second safety margin). Do not cache the JWT inside the provider. |Error handling -|If the function rejects or the endpoint returns a non-OK response, the plugin surfaces an error in the editor UI. +|If the function rejects or the endpoint returns a non-OK response, the plugin surfaces an error in the editor UI. A provider that does not return a `Promise` fails with `JWT token provider did not return a promise`. A `Promise` that resolves to anything other than an object with a string `token` fails with `Invalid JWT token provider result`. |Token lifetime |Tokens should be short-lived (5-15 minutes recommended). See xref:tinymceai-on-premises-jwt.adoc[JWT authentication] for signing key, payload structure, and lifetime guidance. @@ -278,7 +278,7 @@ Set the `ALLOWED_ORIGINS` environment variable on the AI service container to a |`*` is accepted but not recommended for production. It allows any origin to call the AI service endpoints. |Preflight (OPTIONS) -|The service handles `OPTIONS` preflight requests internally and responds with the appropriate `Access-Control-Allow-Methods` and `Access-Control-Allow-Headers`. No reverse proxy configuration is required for OPTIONS. +|The service handles `OPTIONS` preflight requests internally and responds with the appropriate `Access-Control-Allow-Methods` and `Access-Control-Allow-Headers`. No reverse proxy configuration is required for OPTIONS. The plugin sends the `Authorization`, `Content-Type`, and `x-editor-version` request headers, so the preflight response must allow all three. |Credentials |The service responds with `Access-Control-Allow-Credentials: true` when the requesting origin matches an entry in `ALLOWED_ORIGINS`. @@ -291,7 +291,7 @@ Set the `ALLOWED_ORIGINS` environment variable on the AI service container to a curl -i -X OPTIONS https://ai.yourcompany.com/v1/conversations \ -H 'Origin: https://app.yourcompany.com' \ -H 'Access-Control-Request-Method: POST' \ - -H 'Access-Control-Request-Headers: authorization,content-type' + -H 'Access-Control-Request-Headers: authorization,content-type,x-editor-version' ---- The response should include `Access-Control-Allow-Origin: \https://app.yourcompany.com`. If it shows `*` or no CORS header, update `ALLOWED_ORIGINS` on the AI service container and restart. diff --git a/modules/ROOT/pages/tinymceai-on-premises-getting-started.adoc b/modules/ROOT/pages/tinymceai-on-premises-getting-started.adoc index 94ef14afb1..af243dcd0d 100644 --- a/modules/ROOT/pages/tinymceai-on-premises-getting-started.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises-getting-started.adoc @@ -108,7 +108,7 @@ volumes: mysql_data: ---- -TIP: Pin `mysql:8.0`, not `mysql:8`. The `:8` tag resolves to the latest MySQL minor version, which may use authentication plugins or SQL modes incompatible with the AI service schema migrations. See xref:tinymceai-on-premises-database.adoc#mysql-version-pinning[MySQL version pinning] for details. +TIP: Pin `mysql:8.0`, not `mysql:8`. The `:8` tag resolves to MySQL 8.4, which rejects a server option that some older compose files pass. See xref:tinymceai-on-premises-database.adoc#mysql-version-pinning[MySQL version pinning] for details. PostgreSQL is equally supported. See xref:tinymceai-on-premises-database.adoc[Database, Redis, and storage] for an equivalent compose file. Review the xref:tinymceai-on-premises-database.adoc#postgresql-schema-prerequisite[PostgreSQL schema prerequisite] before switching. @@ -216,9 +216,9 @@ TIP: If the container already exists from a previous attempt, remove it first wi TIP: The network name returned by `docker network ls` already includes the `_default` suffix (e.g., `tinymceai-onpremise_default`). Use the full name as-is in `--network`. For multiple LLM providers, extend the `PROVIDERS` JSON: `{"openai":{...},"anthropic":{...}}`. -NOTE: The launch command above starts the AI service with basic conversation support. To enable *web search* in conversations, add `WEBSEARCH_ENABLED='true'` and `WEBSEARCH_ENDPOINT` (pointing to a search backend) to the `docker run` command. See xref:tinymceai-on-premises-mcp.adoc#web-scraping-and-search[Web scraping and web search] for the full configuration, endpoint contracts, and a SerpAPI example. +NOTE: The launch command above starts the AI service with basic conversation support. To enable *web search* in conversations, add `WEBSEARCH_ENABLED='true'` and `WEBSEARCH_ENDPOINT` (pointing to a search backend) to the `docker run` command. See xref:tinymceai-on-premises-mcp.adoc#web-search[Web search] for the full configuration, endpoint contract, and a SerpAPI example. -For Podman, replace `docker run` with `podman run` and use a Podman pod instead of a compose network. See xref:tinymceai-on-premises-production.adoc[Production deployment] for Podman-specific guidance. See xref:tinymceai-on-premises-production.adoc#_podman_deployment[Podman deployment] for a full example. +For Podman, replace `docker run` with `podman run` and use a Podman pod instead of a compose network. See xref:tinymceai-on-premises-production.adoc[Production deployment] for Podman-specific guidance. See xref:tinymceai-on-premises-production.adoc#podman-deployment[Podman deployment] for a full example. For native databases (the database runs on the host or in a managed service rather than in Docker), drop the `--network` flag and set `DATABASE_HOST=host.docker.internal` (Docker Desktop and Podman 4{plus}). On native Linux Docker, additionally pass `--add-host=host.docker.internal:host-gateway`. @@ -239,14 +239,11 @@ Expected response: .Successful boot log (`docker logs ai-service`) [source,text] ---- -Connecting to database (driver=mysql host=mysql) -Running migrations... -Migrations complete: 32 tables ready -Connecting to Redis (host=redis:6379) -Redis connected Server is listening on port 8000. ---- +The start-up log does not report which database, Redis, or storage configuration the service loaded, so confirm those with the checks in <>. + [WARNING] -- If the container exits immediately, run `docker logs ai-service`. The most common causes are documented in the xref:tinymceai-on-premises-troubleshooting.adoc[Troubleshooting] guide. The top three are: malformed `AI_LICENSE_KEY` (line breaks from word wrap), missing PostgreSQL schema, and JSON syntax error in `PROVIDERS`. @@ -494,14 +491,11 @@ data: {"textDelta":"there, "} event: text-delta data: {"textDelta":"friend!"} - -event: done -data: {} ---- -A stream of `text-delta` events followed by `done` confirms the entire pipeline is working: container health, database connectivity, Redis connectivity, JWT signing and verification, permissions, environment registration, LLM provider authentication, and SSE streaming. +A `message-metadata` event followed by `text-delta` events, with no `error` event, confirms the entire pipeline is working: container health, database connectivity, Redis connectivity, JWT signing and verification, permissions, environment registration, LLM provider authentication, and SSE streaming. -If the stream emits `event: error`, inspect the `data` payload. Provider errors (invalid API key, IAM denial, model unavailable) ride inside the Server-Sent Events (SSE) response. The HTTP status stays 200. See the xref:tinymceai-on-premises-troubleshooting.adoc[LLM provider errors] section in the Troubleshooting guide for details. +If the stream emits `event: error`, inspect the `data` payload. Provider errors (invalid API key, IAM denial, model unavailable) ride inside the Server-Sent Events (SSE) response. The HTTP status stays 200. When a provider entry in `PROVIDERS` has no credentials that the service can use, the request fails before the stream starts, with HTTP status 500 and a `NoValidApiKeysFoundError` cause in the container log. See the xref:tinymceai-on-premises-troubleshooting.adoc#llm-provider-errors[LLM provider errors] section in the Troubleshooting guide for details. == Updating configuration diff --git a/modules/ROOT/pages/tinymceai-on-premises-jwt.adoc b/modules/ROOT/pages/tinymceai-on-premises-jwt.adoc index 19c1a5123d..912e46be06 100644 --- a/modules/ROOT/pages/tinymceai-on-premises-jwt.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises-jwt.adoc @@ -75,6 +75,8 @@ Every token MUST contain the following claims. |`auth.ai.permissions` |`string[]` |Array of feature permission strings. See the permissions reference below. Wildcards (`+*+`) are accepted only in the documented positions; the bare string `"*"` is rejected. |=== +The {pluginname} plugin also checks the claims of each token before it sends the token to the AI service. See xref:tinymceai-jwt-authentication-intro.adoc#payload-properties[Payload properties]. + == Optional claims [cols=",,",options="header",] @@ -100,6 +102,7 @@ This is the canonical permission list for the AI service. |`ai:conversations:*` |All conversation operations: create, list, send message, delete, and web search |`ai:conversations:create` |Create new conversations |`ai:conversations:read` |List and read existing conversations +|`+ai:conversations:write+` |Create conversations and send messages |`ai:conversations:delete` |Delete conversations |`ai:conversations:webSearch` |Enable the web search toggle in conversations. Without this permission, `GET /v1/models/1` reports `capabilities.webSearch.allowed: false` even when `WEBSEARCH_ENABLED=true` and `capabilities.webSearch: true` is set on the model. |`ai:models:agent` |Access the built-in agent model (model ID `agent-1`) @@ -123,6 +126,8 @@ ai:models:vertex:gemini-2.5-pro ai:models:azure:my-gpt5-deployment .... +`` is the key of the provider in `PROVIDERS`, not its `name`. The `+provider+` field of each model in `GET /v1/models/1` shows the display `name`, so do not build permission strings from that field. + For Azure, `` is the *deployment name* configured in the Azure portal, not the underlying OpenAI model name. For Bedrock models with an inference profile prefix (`us.`, `eu.`, `apac.`) and embedded version colons (`v1:0`), include them verbatim; the parser handles them. @@ -770,7 +775,7 @@ tinymce.init({ IMPORTANT: Do not cache the JWT in application code. The plugin calls the provider on initialization and again as the token nears expiry; it manages refresh internally. -The provider must return a Promise that resolves to `pass:c[{ token: '' }]`. Returning the raw string fails silently. If the provider rejects or returns a non-OK response, the plugin surfaces an error in the editor UI. +The provider must return a Promise that resolves to `pass:c[{ token: '' }]`. Any other return value fails with an error; see xref:tinymceai-on-premises-frameworks.adoc#token-provider[`tinymceai_token_provider`] for the error messages. If the provider rejects or returns a non-OK response, the plugin surfaces an error in the editor UI. TIP: Set `credentials: 'include'` on the fetch when the token endpoint relies on session cookies. Without it, the browser does not send cookies on cross-origin requests. When the token endpoint is on the same origin as the editor, `credentials: 'include'` is harmless but unnecessary. @@ -870,14 +875,14 @@ When debugging, start here. Most "auth failures" reflect wrong claim values rath |`invalid-jwt-signature` |API Secret mismatch |Verify `AI_API_SECRET` matches the value displayed at access-key creation. If lost, create a new access key and rotate. |`invalid-jwt-signature` (after copying cloud guide) |Token signed with RS256 |Switch to HS256 with the API Secret. See top-of-page warning. |`invalid-jwt-payload` |`aud` does not match a real Environment ID |Confirm the Environment ID from the Management Panel matches `aud` exactly. -|`invalid-jwt-payload` (env "exists") |Environment created through raw management API rather than the Management Panel UI |Recreate through the panel. See the Environment creation section below. +|`invalid-jwt-payload` (env "exists") |Environment created through the management API without the `ai-assistant` service attached |Recreate through the panel. See xref:tinymceai-on-premises-getting-started.adoc#create-an-environment-and-access-key[Create an environment and access key]. |`invalid-jwt` (not `jwt-expired`) |Token is past `exp` by more than 60 seconds |Request a new token. The server allows 60-second clock-skew leeway; anything beyond is rejected with `invalid-jwt`. -|`Environment not found` |Environment is in `environments__environment` / `security__environment` but not in `ai_assistant_environments` |Recreate through Management Panel UI. +|`Environment not found` |Environment is in `environments__environment` / `security__environment` but not in `ai_assistant_environments`, because no `ai-assistant` service is attached to it. |Recreate through Management Panel UI. |`allowed: false` on every endpoint |Wrong shape for `auth.ai.permissions` |Must be ``string[]``. Not a single string. Not `useAllFeatures`. Not `ai:admin`. |`allowed: false` on specific endpoints only |Missing the specific permission |Decode token, check the `auth.ai.permissions` array against the table above. |Token silently rejected, no decoded error |RS256 signature |Re-sign with HS256. |`aud` claim type mismatch |`aud` issued as array instead of string |Some JWT libraries default to array `aud`. Force string. -|Editor shows "Failed to authenticate" |Token endpoint returned non-JSON, returned `token` as nested object, or Cross-Origin Resource Sharing (CORS) blocked the request |Open browser devtools → Network → inspect the response from `/api/ai-token`. +|Editor shows an error, and the browser console logs `TinyMCE AI Error:` with the cause, for example `Invalid JWT token provider result` or `Invalid JWT token payload` |Token endpoint returned non-JSON, returned `token` as a nested object, returned a token without the required claims, or Cross-Origin Resource Sharing (CORS) blocked the request |Open browser devtools → Network → inspect the response from `/api/ai-token`. |=== === Sanity-check a token manually @@ -889,7 +894,7 @@ TOKEN=$(curl -s -X POST http://localhost:3000/api/ai-token | jq -r .token) curl -i https://ai.example.com/v1/conversations \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ - -d '{}' + -d '{"id":"token-check-1"}' ---- A `201 Created` confirms the full chain works: secret, claims, permissions, environment registration. diff --git a/modules/ROOT/pages/tinymceai-on-premises-mcp.adoc b/modules/ROOT/pages/tinymceai-on-premises-mcp.adoc index eb6780a122..ce3a5dd8a3 100644 --- a/modules/ROOT/pages/tinymceai-on-premises-mcp.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises-mcp.adoc @@ -8,7 +8,7 @@ The AI service extends model capabilities through two integration points: the https://modelcontextprotocol.io/[Model Context Protocol] (MCP) for tool calling, and pluggable web endpoints for page fetching and search. Both features operate within AI conversations only. Web search and scraping allow the AI to reference live internet content during conversations, and for most deployments, enabling at least web search improves response quality. -These features are configured entirely through environment variables on the AI service container. No additional infrastructure is required beyond a search endpoint. +These features are configured entirely through environment variables on the AI service container. No additional infrastructure is required beyond a search endpoint and a scrape endpoint. [.text-center] image::tinymceai-on-premises/mcp-web-integrations-architecture.svg[MCP and web integrations architecture: TinyMCE editor connects to AI Service through SSE conversations. AI Service connects to LLM provider for inference and to MCP servers and web search and scrape endpoints for tool calling and live web content.,width=100%] @@ -391,7 +391,7 @@ The {productname} editor sends the web search activation flag when the user togg } ---- -The value *must* be an empty object (`{}`). This is the documented API contract (see https://ckeditor.com/docs/cs/latest/guides/ckeditor-ai/models.html#capability-configuration[CKEditor AI Models: Capability Configuration]). The service rejects other shapes: +The value *must* be an empty object (`{}`). This is the documented API contract (see xref:tinymceai-models.adoc#capability-configuration[Capability configuration]). The service rejects other shapes: * `"webSearch": true` : rejected (schema expects an object, not a boolean). * `"webSearch": {"enabled": true}` : rejected (unrecognized key). @@ -399,6 +399,7 @@ The value *must* be an empty object (`{}`). This is the documented API contract Without this field, the environment variables, JWT permission, and MODELS configuration are insufficient. The model never receives the web search tool. +[[web-search-contract]] === Endpoint contract [cols="1,2",options="header"] @@ -487,10 +488,11 @@ Content-Type: application/json { "url": "https://example.com/page-to-fetch" } ---- -The {productname} editor sends this request when a user pastes or references a URL in conversation. Custom integrations must call this endpoint explicitly to trigger a page fetch. +The {productname} editor sends this request when a user adds a link as a source in the Chat sidebar (the *Add context source* button, then *Link*), or selects an integrator-provided source that resolves to a URL (see xref:tinymceai.adoc#tinymceai_chat_fetch_sources[`+tinymceai_chat_fetch_sources+`]). A URL typed into the chat message itself does not trigger a fetch. Custom integrations must call this endpoint explicitly to trigger a page fetch. -The response is stored against the conversation. The `type` field in the scrape response must be `text/html` or `text/markdown`. Other MIME types (for example, `application/pdf`) are rejected with a `422 web-resource-download-error`. +The response is stored against the conversation. The `type` field in the scrape response must be `text/html` or `text/markdown`, and `data` must not be empty. Other MIME types (for example, `application/pdf`) and an empty `data` field are rejected with a `422 web-resource-download-error`. +[[web-scraping-contract]] === Endpoint contract [cols="1,2",options="header"] @@ -545,10 +547,12 @@ Custom streaming UI integrations can use the following Server-Sent Events (SSE) |=== |Event name |Description |`mcp-tool-result` |Emitted when an MCP tool call completes. Contains the tool result. There is no pre-call event; clients receive no signal until the tool call finishes. -|`web-search` |Emitted when a web search returns results (or fails without emitting an error event; see <>). +|`web-search` |Sent when a web search runs. The payload is an empty object, and the event is also sent when the search back end fails (see <>). |`source` |Emitted with source citations from the model response. |=== +For every event and its payload, see the https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages/operation/createMessage[API reference]. + [[mcp-kubernetes]] diff --git a/modules/ROOT/pages/tinymceai-on-premises-production.adoc b/modules/ROOT/pages/tinymceai-on-premises-production.adoc index 8ea9208d57..a5fa985e77 100644 --- a/modules/ROOT/pages/tinymceai-on-premises-production.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises-production.adoc @@ -33,6 +33,15 @@ The AI service is stateless, persists all state to MySQL/PostgreSQL and Redis, a The AI service does not terminate Transport Layer Security (TLS). Place a reverse proxy in front. +[[proxy-requirements]] +=== Proxy requirements + +The reverse proxy or load balancer must meet these requirements: + +* *Keep long responses open.* Set the read timeout and the idle timeout to at least 300 seconds, as in the examples below. The {pluginname} plugin sets no request timeout of its own. +* *Do not buffer response bodies.* The service streams responses as Server-Sent Events (SSE). +* *Do not rewrite the `Content-Type` response header.* The {pluginname} plugin reads responses to `POST`, `PATCH`, and `DELETE` requests only when `Content-Type` is exactly `application/json`, and reads streamed responses only when it is exactly `text/event-stream`. A proxy that changes the header, for example by adding a `charset` parameter, stops the editor from reading those responses. + === Nginx example [source,nginx] @@ -99,7 +108,7 @@ When deploying for the first time or upgrading to a new version, start a single == Podman deployment -NOTE: This example uses `STORAGE_DRIVER='database'` for simplicity. For production workloads, use S3 or Azure Blob storage. See xref:tinymceai-on-premises-database.adoc#_file_storage[File storage] for options. +NOTE: This example uses `STORAGE_DRIVER='database'` for simplicity. For production workloads, use S3 or Azure Blob storage. See xref:tinymceai-on-premises-database.adoc#file-storage[File storage] for options. The AI service works with Podman as an alternative to Docker. In Podman, containers within a pod share a network namespace, so use `127.0.0.1` instead of container names for hostnames. @@ -301,7 +310,7 @@ Any multi-replica deployment should include the following Kubernetes primitives * *`podAntiAffinity`*: distributes replicas across nodes to avoid single-node failures. * *`topologySpreadConstraints`*: spreads replicas across availability zones for zone-level resilience. -The canonical Deployment example above does not include these — they are site-specific. Without them, the scheduler may bin-pack all replicas onto a single node in a single availability zone. +The canonical Deployment example above does not include these — they are site-specific. Without them, the scheduler may bin-pack all replicas onto a single node in a single availability zone. Soft rules can have the same result: on a cluster with spare capacity, `preferredDuringSchedulingIgnoredDuringExecution` anti-affinity and `whenUnsatisfiable: ScheduleAnyway` still let the scheduler place every replica on one node. To force a spread across zones, set `whenUnsatisfiable: DoNotSchedule` on the zone topology spread constraint. With two nodes, a node drain or a rolling restart can still drop a few requests, so plan for at least three nodes. === Step 4: Service @@ -329,7 +338,7 @@ After the first pod reaches Ready status, create an environment and access key t . Create an environment and note the Environment ID. . Create an access key and copy the API Secret immediately (shown only once). -These values are required by the token endpoint. See xref:tinymceai-on-premises-getting-started.adoc#_create_an_environment_and_access_key[Getting started — Create an environment and access key] for details. +These values are required by the token endpoint. See xref:tinymceai-on-premises-getting-started.adoc#create-an-environment-and-access-key[Getting started — Create an environment and access key] for details. [IMPORTANT] -- @@ -466,13 +475,15 @@ The AI service does not use platform-native credential chains. AWS IRSA, EC2 ins |Registry pull credentials |Secrets Manager {plus} ECR pull-through cache, or a private repository mirroring `registry.containers.tiny.cloud` |=== +NOTE: On Amazon EKS Auto Mode, pods use the cluster's primary security group (the Amazon EKS-managed cluster security group), not the node security group. Allow inbound database and Redis traffic from the cluster primary security group. With the wrong security group, the AI service pods stay unready and write no log output. + === Azure (AKS) Deploy on Azure Kubernetes Service with Azure Database for PostgreSQL Flexible Server, Azure Cache for Redis, and Azure Blob Storage. Service-shape considerations: * `STORAGE_DRIVER=azure` is the recommended storage backend on Azure. -* PostgreSQL Flexible Server defaults to enforcing TLS — see the xref:tinymceai-on-premises-database.adoc#_postgresql[known TLS error surface]. -* The AI service does not use Workload Identity or managed identity for LLM credentials — inline Azure OpenAI credentials in `PROVIDERS` (see xref:tinymceai-on-premises-providers.adoc#_azure_openai[Azure OpenAI]). +* PostgreSQL Flexible Server defaults to enforcing TLS — see the xref:tinymceai-on-premises-database.adoc#managed-database-tls[known TLS error surface]. +* The AI service does not use Workload Identity or managed identity for LLM credentials — inline Azure OpenAI credentials in `PROVIDERS` (see xref:tinymceai-on-premises-providers.adoc#azure-openai[Azure OpenAI]). For AKS cluster setup, node pools, and networking, refer to the https://learn.microsoft.com/en-us/azure/aks/[Azure Kubernetes Service documentation]. @@ -481,8 +492,8 @@ For AKS cluster setup, node pools, and networking, refer to the https://learn.mi Deploy on Google Kubernetes Engine (Standard mode — not Autopilot) with Cloud SQL for PostgreSQL, Memorystore for Redis, and GCS for file storage. Service-shape considerations: * No native GCS driver exists. Use GCS via S3-interop (`STORAGE_DRIVER=s3` with HMAC credentials). The bucket must have `uniform_bucket_level_access` disabled (the SDK sends `x-amz-acl` headers). -* The AI service does not use GKE Workload Identity or Application Default Credentials — inline Vertex SA credentials in `PROVIDERS` (see xref:tinymceai-on-premises-providers.adoc#_google_vertex_ai[Google Vertex AI]). -* Cloud SQL for PostgreSQL defaults to enforcing TLS — see the xref:tinymceai-on-premises-database.adoc#_postgresql[known TLS error surface]. +* The AI service does not use GKE Workload Identity or Application Default Credentials — inline Vertex SA credentials in `PROVIDERS` (see xref:tinymceai-on-premises-providers.adoc#google-vertex-ai[Google Vertex AI]). +* Cloud SQL for PostgreSQL defaults to enforcing TLS — see the xref:tinymceai-on-premises-database.adoc#managed-database-tls[known TLS error surface]. For GKE cluster creation and node pool configuration, refer to the https://cloud.google.com/kubernetes-engine/docs[Google Kubernetes Engine documentation]. diff --git a/modules/ROOT/pages/tinymceai-on-premises-providers.adoc b/modules/ROOT/pages/tinymceai-on-premises-providers.adoc index 2506ca7ca0..c0d6153cac 100644 --- a/modules/ROOT/pages/tinymceai-on-premises-providers.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises-providers.adoc @@ -60,6 +60,8 @@ The *key* (not the `type`) is what gets referenced from: } ---- +`GET /v1/models/1` reports the provider `name`, not the provider key, in the `provider` field of each model. + === How the pieces fit together [.text-center] @@ -421,6 +423,8 @@ IMPORTANT: The AI service does *not* use the AWS SDK default credential chain. ` The `sessionToken` field is optional but required for STS-issued short-lived credentials. Plan a rotation procedure when using temporary credentials. +Instead of `+credentials+`, a Bedrock provider can set `+apiKeys+` to a Bedrock API key issued in the AWS console. + NOTE: Bedrock console-issued API keys have a separate billing entitlement check that can return `INVALID_PAYMENT_INSTRUMENT` on accounts where the IAM-credential path works fine. Prefer the `credentials` block (IAM user with `accessKeyId` / `secretAccessKey`) for production. *Prerequisites checklist:* @@ -906,7 +910,7 @@ A `MODELS` array routes individual models to specific providers using the `provi This wires conversations to OpenAI, reviews to Bedrock-hosted Claude, and quick actions to a local Ollama model. The {productname} editor will pick the appropriate provider for each feature based on which models declare which `features`. -A `MODELS` entry with a `provider` value that does not exist in `PROVIDERS` is silently skipped; that model will not appear in `/v1/models/1`. When a model is missing from the model selector in the rich text editor, check the spelling of its `provider` field against the keys in `PROVIDERS` (case-sensitive). See xref:tinymceai-on-premises-troubleshooting.adoc[Troubleshooting] for additional debugging steps. +A `MODELS` entry with a `provider` value that does not exist in `PROVIDERS` stops the service at startup with `[FATAL] Following models have invalid provider:` followed by the affected model IDs. Check the spelling of each `provider` field against the keys in `PROVIDERS` (case-sensitive). See xref:tinymceai-on-premises-troubleshooting.adoc[Troubleshooting] for additional debugging steps. @@ -976,7 +980,7 @@ actions.fix-grammar actions.improve-writing ---- -The three umbrella values `conversations`, `reviews`, and `actions` enable the entire family. Use a specific sub-feature only when restricting a model to a subset; for example, a low-cost model that handles only `actions.fix-grammar`. +The three umbrella values `conversations`, `reviews`, and `actions` enable every sub-feature of that feature. Use a specific sub-feature only when restricting a model to a subset; for example, a low-cost model that handles only `actions.fix-grammar`. A model with no `features` entry, or with only sub-features the editor does not request, will be hidden from the picker. @@ -1012,7 +1016,7 @@ The same procedure works for `anthropic`, `google`, `azure`, and `openai-compati [cols=",,",options="header",] |=== |Symptom |Most likely cause |Section -|Editor shows "model unavailable" / `agent-1 allowed:false` |`MODELS` not set or every entry skipped |<> +|Editor shows "model unavailable" / `agent-1 allowed:false` |`MODELS` not set |<> |`GET /v1/models/v1` returns 500 |Wrong compatibility version |<> |Bedrock returns `NoValidApiKeysFoundError` |Relying on the AWS default credential chain |Bedrock |Bedrock returns `AccessDeniedException` |Model access not enabled in console |Bedrock prerequisites diff --git a/modules/ROOT/pages/tinymceai-on-premises-reference.adoc b/modules/ROOT/pages/tinymceai-on-premises-reference.adoc index a9eeb9bb12..81dbdfea82 100644 --- a/modules/ROOT/pages/tinymceai-on-premises-reference.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises-reference.adoc @@ -12,7 +12,7 @@ Alphabetized. Required-ness is marked relative to a minimum working deployment. [cols=",,,",options="header",] |=== |Variable |Required |Default |Description -|`ALLOWED_ORIGINS` |Recommended |- |Comma-separated list of CORS-allowed editor origins. Required for cross-origin editor deployments. See xref:tinymceai-on-premises-frameworks.adoc#_cross_origin_requests_to_the_ai_service[Cross-origin requests] for format, wildcards, and verification. +|`ALLOWED_ORIGINS` |Recommended |- |Comma-separated list of CORS-allowed editor origins. Required for cross-origin editor deployments. See xref:tinymceai-on-premises-frameworks.adoc#cross-origin-requests-to-the-ai-service[Cross-origin requests] for format, wildcards, and verification. |`DATABASE_DATABASE` |Yes |- |Database name (`ai_service` is the convention). |`DATABASE_DRIVER` |Yes |- |`mysql` or `postgres`. |`DATABASE_HOST` |Yes |- |Database hostname or IP. @@ -60,12 +60,12 @@ Alphabetized. Required-ness is marked relative to a minimum working deployment. |`STORAGE_LOCATION` |If using filesystem |- |Mount point for filesystem storage. Must be writable by the container user. |`STORAGE_REGION` |If using S3 |- |S3 region. |`STORAGE_SECRET_ACCESS_KEY` |If using S3 |- |S3 secret access key. -|`WEBRESOURCES_ENABLED` |No |`false` |Enable web scraping endpoint forwarding. See xref:tinymceai-on-premises-mcp.adoc#web-scraping-and-search[Web scraping and web search]. +|`WEBRESOURCES_ENABLED` |No |`false` |Enable web scraping endpoint forwarding. See xref:tinymceai-on-premises-mcp.adoc#web-scraping[Web scraping]. |`WEBRESOURCES_ENDPOINT` |If web resources enabled |- |Scraper URL. |`WEBRESOURCES_REQUEST_TIMEOUT` |No |- |Scraper request timeout in ms. -|`WEBSEARCH_ENABLED` |No |`false` |Enable web search forwarding. See xref:tinymceai-on-premises-mcp.adoc#web-scraping-and-search[Web scraping and web search]. +|`WEBSEARCH_ENABLED` |No |`false` |Enable web search forwarding. See xref:tinymceai-on-premises-mcp.adoc#web-search[Web search]. |`WEBSEARCH_ENDPOINT` |If web search enabled |- |Search URL. -|`WEBSEARCH_HEADERS` |No |- |Colon-CSV format (`Header-Name: value, Another: value`). Extra headers sent to the search endpoint. Do not use JSON — see xref:tinymceai-on-premises-mcp.adoc#web-scraping-and-search[Web scraping and web search]. +|`WEBSEARCH_HEADERS` |No |- |Colon-CSV format (`Header-Name: value, Another: value`). Extra headers sent to the search endpoint. Do not use JSON — see xref:tinymceai-on-premises-mcp.adoc#web-search[Web search]. |`WEBSEARCH_REQUEST_TIMEOUT` |No |- |Search request timeout in ms. |=== @@ -107,7 +107,8 @@ For PostgreSQL, change `DATABASE_DRIVER` to `'postgres'` and add `-e DATABASE_SC |=== |Method |Path |Auth |Description |GET |`/health` |None |Liveness probe. Returns `{"serviceName":"on-premises-http","uptime":}`. Not metric-logged. -|GET |`/docs/` |None |ReDoc-rendered API documentation. +|GET |`/docs/` |None |Redirects (HTTP 301) to `/v1/api/docs`. +|GET |`/v1/api/docs` |None |ReDoc-rendered API documentation. |GET |`/v1/api/doc.json` |None |OpenAPI 3 JSON spec. |GET |`/panel/` |Management secret (login form) |Management Panel UI. Sign in with `ENVIRONMENTS_MANAGEMENT_SECRET_KEY` through the browser login form. |GET |`/v1/models/1` |JWT |List available models for the current token. The compatibility version literal `1` is the only accepted value; `v1`, `v2`, `latest` all return 500. @@ -116,34 +117,42 @@ For PostgreSQL, change `DATABASE_DRIVER` to `'postgres'` and add `-e DATABASE_SC |GET |`/v1/conversations/\{id}` |JWT |Read one conversation. |POST |`/v1/conversations/\{id}/messages` |JWT |Send a message. Returns Server-Sent Events (SSE) stream. |POST |`/v1/conversations/\{id}/web-resources` |JWT |Fetch a web page through the configured scrape endpoint. Body: `{"url":"https://..."}`. Returns 201 on success, 422 on scrape failure. Requires `WEBRESOURCES_ENABLED='true'`. See xref:tinymceai-on-premises-mcp.adoc#web-scraping[Web scraping]. +|GET |`/v1/conversations/\{id}/web-resources` |JWT |List the web resources fetched for a conversation. +|DELETE |`/v1/conversations/\{id}/web-resources/\{webResourceId}` |JWT |Remove a web resource from a conversation. +|POST |`/v1/conversations/\{id}/files` |JWT |Upload a file to a conversation as `+multipart/form-data+`. +|DELETE |`/v1/conversations/\{id}/files/\{fileId}` |JWT |Remove a file from a conversation. +|POST |`/v1/conversations/\{id}/documents` |JWT |Add a document to a conversation. +|GET |`/v1/conversations/\{id}/documents/\{documentId}` |JWT |Read one conversation document. |DELETE |`/v1/conversations/\{id}` |JWT |Delete a conversation. -|POST |`/v1/actions/\{actionId}` |JWT |Run a quick action. Body shape: `{"content":[{"type":"text","content":"..."}]}` (no `modelId`). -|POST |`/v1/reviews/\{reviewId}` |JWT |Run a review. +|POST |`/v1/actions/system/\{actionName}/calls` |JWT |Run a built-in quick action, for example `+fix-grammar+`. Body shape: `{"content":[{"type":"text","content":"..."}]}` with exactly one `+text+` part (no `modelId`). Returns an SSE stream. +|POST |`/v1/reviews/system/\{reviewName}/calls` |JWT |Run a built-in review, for example `+correctness+`. Returns an SSE stream. For the content format, see the https://tinymceai.api.tiny.cloud/docs#tag/Reviews/operation/callSystemReview[API reference]. +|POST |`/v1/actions/custom/calls` |JWT |Run a custom action with a prompt and a model. Returns an SSE stream. +|POST |`/v1/reviews/custom/calls` |JWT |Run a custom review with a prompt and a model. Returns an SSE stream. |GET |`/v1/mcp/oauth/status` |JWT |Connection status for all OAuth-enabled MCP servers. See xref:tinymceai-on-premises-mcp.adoc#mcp-oauth-endpoints[OAuth REST endpoints]. |POST |`/v1/mcp/oauth/\{serverName}/initialize` |JWT |Start the OAuth authorization flow. |POST |`/v1/mcp/oauth/\{serverName}/complete` |JWT |Complete the OAuth flow with the authorization code. |DELETE |`/v1/mcp/oauth/\{serverName}` |JWT |Revoke the OAuth connection for the calling user. |=== -NOTE: The OAuth endpoints are available only when at least one MCP server has an `oauth` block configured. The interactive API documentation at `/docs/` may not include these endpoints; they are documented in the xref:tinymceai-on-premises-mcp.adoc#mcp-oauth[MCP OAuth section]. +NOTE: The OAuth endpoints are available only when at least one MCP server has an `oauth` block configured. The interactive API documentation at `/v1/api/docs` may not include these endpoints; they are documented in the xref:tinymceai-on-premises-mcp.adoc#mcp-oauth[MCP OAuth section]. NOTE: Environment management (create, read, update, delete) is handled through the Management Panel UI at `/panel/`. == Server-Sent Events reference -The message endpoint returns `Content-Type: text/event-stream`. Events use named types: +The message endpoint returns `Content-Type: text/event-stream`. Events use named types. The following table lists the main events. For every event and its payload, see the https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages/operation/createMessage[API reference]. [cols=",,",options="header",] |=== |Event |Payload shape |Meaning |`message-metadata` |`{"messageId":"..."}` |Sent once at the start of each message. |`text-delta` |`{"textDelta":"..."}` |Incremental text fragment. The editor concatenates these. -|`tool-call` |`{"toolName":"...","arguments":{...}}` |Emitted when the model invokes an MCP tool. -|`tool-result` |`{"toolName":"...","result":{...}}` |Emitted when an MCP tool returns. +|`+mcp-tool-result+` |`+{"toolName":"...","result":"...","success":true}+` |Emitted when an MCP tool call completes. `+result+` is a string. |`error` |`{"message":"...","cause":{...}}` |Provider error. HTTP status remains 200; the error is in-stream. -|`done` |`{}` |Sent once at the end of the stream. |=== +There is no end-of-stream event. The stream ends when the service closes the response. + Healthy stream example: [source,text] @@ -156,9 +165,6 @@ data: {"textDelta":"Hello "} event: text-delta data: {"textDelta":"there!"} - -event: done -data: {} ---- Error stream example: @@ -177,12 +183,16 @@ Browser client parsing notes: * Each event is two lines: `event: ` and `data: `, separated from the next event by a blank line. * `data` is always valid JSON. * Unknown `event` types carry informational payloads and can be ignored for forward compatibility. -* `text-delta` is the only event that contributes to the visible response body. +* `text-delta` carries the visible reply text, and `+modification-delta+` carries the text of a proposed document modification. + +The action and review endpoints also return SSE streams, with their own events. See the API reference for https://tinymceai.api.tiny.cloud/docs#tag/Actions/operation/callSystemAction[actions] and https://tinymceai.api.tiny.cloud/docs#tag/Reviews/operation/callSystemReview[reviews]. == Error code reference Error codes returned in HTTP 4xx responses and inside SSE `event: error` payloads. +Every error response carries a `+traceId+`. See xref:tinymceai-on-premises-troubleshooting.adoc#tracing-a-failed-request[Tracing a failed request]. + [cols=",,,",options="header",] |=== |Code |Origin |Likely cause |Fix @@ -192,10 +202,10 @@ Error codes returned in HTTP 4xx responses and inside SSE `event: error` payload |`Environment not found` |AI runtime |Same as `invalid-jwt-payload` second sub-cause |Recreate env through Panel UI |`missing-permissions` |Permission checker |`auth.ai.permissions` array does not cover the requested action |Add the missing permission string |`invalid-request-data` |Input validator |Field validation failed (most commonly the 100,000 char prompt cap) |Fix the request body. See error message -|`environment-not-found` |AI runtime |Same as `Environment not found` |Recreate through Panel UI +|`environment-not-found` |AI runtime |Same as `Environment not found`. The editor displays this error as `Invalid API key provided in JWT token (aud) claim`. |Recreate through Panel UI |`conversation in use` |Conversation runtime |Stream-abort left stale state |Start a new conversation |`conversation does not exist` |Conversation runtime |Follow-up to `conversation in use` |Start a new conversation -|`NoValidApiKeysFoundError` |Bedrock / Vertex adapter |Inline credentials missing |Inline `credentials` in `PROVIDERS` +|`NoValidApiKeysFoundError` (HTTP 500) |Bedrock / Vertex adapter |Inline credentials missing |Inline `credentials` in `PROVIDERS` |`AccessDeniedException` |Bedrock |Missing model access or IAM permissions |Enable Bedrock model access; attach the IAM policy from xref:tinymceai-on-premises-providers.adoc[LLM providers] |`INVALID_PAYMENT_INSTRUMENT` |Bedrock |Anthropic on Bedrock without Marketplace subscription |Subscribe through AWS Marketplace |`ValidationException` |Bedrock |Wrong model ID format (regional instead of cross-region) |Use the inference profile ID for Claude 4.x diff --git a/modules/ROOT/pages/tinymceai-on-premises-troubleshooting.adoc b/modules/ROOT/pages/tinymceai-on-premises-troubleshooting.adoc index 3ad08eddbd..cc6cd61fe4 100644 --- a/modules/ROOT/pages/tinymceai-on-premises-troubleshooting.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises-troubleshooting.adoc @@ -18,6 +18,7 @@ Work through this list to identify the symptom area: . *Is the editor side broken?* Missing toolbar, token 401, or hanging stream? See <>. . *Slow, timing out, or failing under load?* See <>. . *Scaling, upgrades, or deployment questions?* See xref:tinymceai-on-premises-production.adoc[Production deployment]. +. *Need the meaning of a service log message?* See <>. If none of the above match, see <> and then escalate to link:{supporturl}/[{supportname}]. @@ -39,22 +40,42 @@ Run `docker logs ai-service` first. All entries below assume the log output is a |`STORAGE_LOCATION` points to a path the container user cannot write |Switch to `STORAGE_DRIVER=database`, or mount a writable volume and point `STORAGE_LOCATION` at it (for example `/tmp/ai-storage`). -|`Not enough permissions to access database.` -|MySQL user lacks required privileges -|Grant the privileges listed in the error. See xref:tinymceai-on-premises-database.adoc[Database, Redis, and storage] for the GRANT statement. +|`Not enough permissions to access database. Missing privileges: ...` +|The MySQL user lacks the listed privileges on the AI service database. Privileges granted globally (`+ON *.*+`) or through a role, such as `cloudsqlsuperuser` on Cloud SQL, do not satisfy the start-up check. +|Grant the privileges on the AI service database itself (`+ON ai_service.*+`). See xref:tinymceai-on-premises-database.adoc#database-user-privileges[Database user privileges] for the `GRANT` statement. |`schema "cs-on-premises" does not exist` |Postgres schema not pre-created |Run `CREATE SCHEMA "cs-on-premises";` (double quotes required), or set `DATABASE_SCHEMA=public`. See xref:tinymceai-on-premises-database.adoc[Database, Redis, and storage]. +|`PostgreSQL Error: No permissions to connect to the database` although the user and grants are correct +|The managed PostgreSQL server requires TLS (`rds.force_ssl=1` on Amazon RDS, `require_secure_transport=ON` on Azure Database for PostgreSQL Flexible Server), and the AI service connected without it. The server-side log shows `no pg_hba.conf entry ... no encryption`. +|See xref:tinymceai-on-premises-database.adoc#managed-database-tls[Managed database TLS]. + +|`duplicate key value violates unique constraint "pg_class_relname_nsp_index"` on first start +|Several replicas started at the same time against a new database and ran the schema migrations concurrently. +|The replica restarts and recovers on its own. To avoid the error, start one replica, wait until it is healthy, then scale up. See xref:tinymceai-on-premises-production.adoc#upgrade-process[Upgrade process]. + |`[MY-000067] unknown variable 'default-authentication-plugin'` |`mysql:8` tag now points to the latest MySQL, which removed that variable |Pin `mysql:8.0` in the compose file and run `docker compose up -d --force-recreate mysql`. +|`Following models have invalid provider: ` +|A `MODELS` entry names a `provider` key that does not exist in `PROVIDERS`. The service stops at startup. +|Correct the `provider` value, or add the missing key to `PROVIDERS`. Keys are case-sensitive. + +|`[FATAL] ... is not a constructor` with minified identifiers +|A `PROVIDERS` entry has the wrong shape, for example a Vertex AI entry without the `type` and `name` fields and with `client_email` and `private_key` instead of `clientEmail` and `privateKey`. +|Start from the provider example on the xref:tinymceai-on-premises-providers.adoc[LLM providers] page and add fields one at a time. + |Container exits with no useful log |Missing required env var, or malformed JSON in `PROVIDERS` / `MODELS` |Run `docker inspect ai-service {vbar} jq '.[0].Config.Env'` and compare against the xref:tinymceai-on-premises-reference.adoc[environment variable reference]. Validate JSON with `echo "$PROVIDERS" {vbar} jq .` +|Pods stay unready on Amazon EKS Auto Mode, restart after failed liveness probes, and `kubectl logs` shows no output for the current or the previous container +|The database and Redis security groups allow inbound traffic from the node security group, but EKS Auto Mode attaches the cluster primary security group to the pods. +|Allow inbound database and Redis traffic from the cluster primary security group. See xref:tinymceai-on-premises-production.adoc#infrastructure-recommendations[Infrastructure recommendations]. + |`/health` times out despite successful boot |Port mapping missing |Add `-p 8000:8000` to `docker run`, or `ports: ["8000:8000"]` in compose. Confirm with `docker port ai-service`. @@ -86,7 +107,7 @@ These assume the container is running and `/health` returns OK. |Token is past its `exp` claim |Issue tokens with a reasonable lifetime (for example `exp = now {plus} 3600`) and refresh before expiry. Synchronize clocks with Network Time Protocol (NTP). -|`Environment not found` +|`Environment not found` (shown in the editor as `Invalid API key provided in JWT token (aud) claim`) |Environment was not created through the Management Panel UI |Delete and recreate the environment through `/panel/`. Update `AI_ENV_ID` in `.env`. @@ -125,7 +146,7 @@ Common mistakes: `"permissions": "ai:admin"` (string shorthand), `"permissions": [[llm-provider-errors]] == Large language model (LLM) provider errors -These appear as `event: error` inside the SSE stream. The HTTP response is still 200. +Most of these appear as `event: error` inside the SSE stream, and the HTTP response is still 200. `NoValidApiKeysFoundError` is the exception: the message request fails with HTTP 500, and the cause appears in the container log. === Cloud providers (OpenAI, Anthropic, Google) @@ -140,8 +161,8 @@ These appear as `event: error` inside the SSE stream. The HTTP response is still [cols="2,3",options="header"] |=== |Error |Fix -|`NoValidApiKeysFoundError` |Inline `accessKeyId` and `secretAccessKey` inside `credentials` in `PROVIDERS`. The AWS SDK default credential chain is not used. See xref:tinymceai-on-premises-providers.adoc[LLM providers]. -|`AccessDeniedException` |Enable model access in *Bedrock console -> Model access*. Attach an IAM policy with `bedrock:InvokeModel`, `bedrock:Converse`, and `bedrock:ConverseStream`. +|`NoValidApiKeysFoundError` |Inline `accessKeyId` and `secretAccessKey` inside `credentials` in `PROVIDERS`, or set `apiKeys`. The AWS SDK default credential chain is not used. See xref:tinymceai-on-premises-providers.adoc[LLM providers]. +|`AccessDeniedException` |Enable model access in *Bedrock console -> Model access*. Attach an IAM policy with `bedrock:InvokeModel`, `bedrock:InvokeModelWithResponseStream`, `bedrock:Converse`, and `bedrock:ConverseStream`. |`INVALID_PAYMENT_INSTRUMENT` |Complete the AWS Marketplace subscription for Anthropic in *Bedrock console -> Model access -> Anthropic*. |`ValidationException` (model invocation not supported) |Use the region-prefixed inference profile ID (for example `us.anthropic.claude-sonnet-4-...`). See xref:tinymceai-on-premises-providers.adoc[LLM providers]. |=== @@ -151,7 +172,7 @@ These appear as `event: error` inside the SSE stream. The HTTP response is still [cols="2,3",options="header"] |=== |Error |Fix -|`NoValidApiKeysFoundError` |Inline `clientEmail` and `privateKey` inside `credentials` in `PROVIDERS`. Google Application Default Credentials (ADC) is not used. See xref:tinymceai-on-premises-providers.adoc[LLM providers]. +|`NoValidApiKeysFoundError` |Inline `clientEmail` and `privateKey` inside `credentials` in `PROVIDERS`, or set `apiKeys` to an account-bound API key. Google Application Default Credentials (ADC) is not used. See xref:tinymceai-on-premises-providers.adoc[LLM providers]. |Auth errors with a valid service account |`private_key` newlines were mangled during copy-paste. Build `PROVIDERS` with a script (`json.dumps()` on the SA JSON file) rather than hand-editing. |`SERVICE_DISABLED` |Run `gcloud services enable aiplatform.googleapis.com --project=`. |Blocked by GCP org policy |Check `iam.disableServiceAccountCreation`, `iam.disableServiceAccountKeyCreation`, and account-bound API key policies. Exempt the AI service project from all three. @@ -221,6 +242,79 @@ Confirm `/health` is OK and a direct `curl` to `/v1/conversations` works before |=== +[[log-reference]] +== Log reference + +Read the AI service log with `docker logs ai-service`, or with `kubectl logs` on Kubernetes. To collect the log from several instances in one place, see xref:tinymceai-on-premises-production.adoc#distributed-logging[Distributed logging]. + +[[log-format]] +=== Log format + +Error and fatal entries are JSON objects, one per line: + +[cols="1,3",options="header"] +|=== +|Field |Content + +|`level` +|The severity, as a number: `50` for errors, and `60` for fatal errors, which stop the AI service. + +|`time` +|The time of the entry, in ISO 8601 format, in UTC. + +|`msg` +|The message. Error and fatal messages start with `[ERROR]` or `[FATAL]`. + +|`data` +|Optional. Details of the entry, such as the error `name` and `message`. + +|`stack` +|Optional. The stack trace of an error. +|=== + +For example, a PostgreSQL deployment without the required schema stops with this entry: + +[source,json] +---- +{"level":60,"time":"2026-05-05T11:19:07.634Z","msg":"[FATAL] PostgreSQL Error: schema \"cs-on-premises\" does not exist","data":{"name":"PostgreSQL Error","message":"PostgreSQL Error: schema \"cs-on-premises\" does not exist"}} +---- + +To show only error and fatal entries, filter the log with `jq`. The `fromjson?` filter skips any line that is not JSON: + +[source,bash] +---- +docker logs ai-service 2>&1 | jq -R -c 'fromjson? | select(.level >= 50)' +---- + +[[notable-log-messages]] +=== Notable log messages + +Start-up failures are logged with the prefix `[FATAL]` and stop the AI service. For those messages and their fixes, see <>. For MCP and web search messages, see xref:tinymceai-on-premises-mcp.adoc#web-search-troubleshooting[MCP troubleshooting]. + +[cols="2,3,3",options="header"] +|=== +|Message |Meaning |Action + +|`Server is listening on port 8000.` +|The AI service started and accepts requests. +|No action. + +|`[ERROR] The user did not create a message. Reason: No valid API keys found for provider ''` +|The message request failed with HTTP `500`. The `data.name` field is `NoValidApiKeysFoundError`. +|Add inline credentials for the provider. See <>. + +|`[ERROR] The user did not upload a file. Reason: Invalid argument.` +|The file upload failed with HTTP `500`. With Google Cloud Storage through the S3-compatible API, a bucket with uniform bucket-level access enabled causes this error. +|Turn off uniform bucket-level access on the bucket. See xref:tinymceai-on-premises-production.adoc#gcp-gke[GCP (GKE)]. +|=== + +[[tracing-a-failed-request]] +=== Tracing a failed request + +Every error response from the AI service carries a `traceId` that identifies the request. For the error response shape, see xref:tinymceai-api-overview.adoc#error-responses[Error responses]. + +The {pluginname} plugin prints each error in the browser console as a `TinyMCE AI Error:` entry, followed by the status code, a `Trace ID:` line, and the error code. + [[diagnostic-recipes]] == Diagnostic recipes diff --git a/modules/ROOT/pages/tinymceai-on-premises.adoc b/modules/ROOT/pages/tinymceai-on-premises.adoc index fee0cca932..91987c99f3 100644 --- a/modules/ROOT/pages/tinymceai-on-premises.adoc +++ b/modules/ROOT/pages/tinymceai-on-premises.adoc @@ -5,7 +5,7 @@ :keywords: AI, on-premises, self-hosted, deployment, overview, architecture, prerequisites, container, LLM :pluginname: TinyMCE AI -The {pluginname} on-premises service is a self-hosted back end that powers AI writing assistance. It can be used with the {productname} rich text editor, particularly the xref:tinymceai.adoc[TinyMCE AI plugin], or as a standalone service. It runs entirely within the host infrastructure. Document content, conversation history, file attachments, and user data stay within the host network and are not stored by Tiny. Data sent to a configured LLM provider is subject to that provider's data handling policies. +The {pluginname} on-premises service is a self-hosted back end that powers AI writing assistance. It can be used with the {productname} rich text editor, particularly the xref:tinymceai.adoc[{pluginname} plugin], or as a standalone service. It runs entirely within the host infrastructure. Document content, conversation history, file attachments, and user data stay within the host network and are not stored by Tiny. Data sent to a configured LLM provider is subject to that provider's data handling policies. The service ships as a single Open Container Initiative (OCI) container image (`registry.containers.tiny.cloud/ai-service-tiny`). It exposes a REST API, a Management Panel, Server-Sent Events streaming, and an OpenAPI spec. @@ -14,7 +14,7 @@ The service ships as a single Open Container Initiative (OCI) container image (` The infrastructure consists of three layers: * The *browser* runs the {productname} editor with the `tinymceai` plugin. -* The *application layer* runs the token endpoint (which signs JWTs), the AI service container, and a load balancer or reverse proxy. It may consist of one or more AI service instances behind the load balancer (round-robin recommended). Each instance runs the same stateless container image. +* The *application layer* runs the token endpoint (which signs JWTs), the AI service container, and a load balancer or reverse proxy. It may consist of one or more AI service instances behind the load balancer (round-robin recommended). Each instance runs the same stateless container image and listens on port `8000`. * The *data layer* consists of a SQL database, a Redis instance, and file storage: ** *SQL database*: stores persistent data such as configurations and conversations. ** *Redis*: caching and coordination (SSE delivery, rate limits, pub/sub). Enables the AI service to remain stateless. @@ -35,7 +35,7 @@ Data flow for a single AI request: When used with {productname} `tinymceai`, the plugin handles steps 1, 2, and 5 automatically through the `tinymceai_token_provider` callback. -NOTE: The browser connects directly to the AI service — requests do not pass through the application back end. The AI service must be network-reachable from the end-user browser, which means it must have a public URL (or be accessible through a VPN/internal network when deployed on an intranet). Configure xref:tinymceai-on-premises-frameworks.adoc#_cross_origin_requests_to_the_ai_service[CORS] and xref:tinymceai-on-premises-production.adoc#_tls_https[TLS] on the AI service accordingly. +NOTE: The browser connects directly to the AI service — requests do not pass through the application back end. The AI service must be network-reachable from the end-user browser, which means it must have a public URL (or be accessible through a VPN/internal network when deployed on an intranet). Configure xref:tinymceai-on-premises-frameworks.adoc#cross-origin-requests-to-the-ai-service[CORS] and xref:tinymceai-on-premises-production.adoc#tls-https[TLS] on the AI service accordingly. The shared secret (API Secret) exists only in the application back end (token endpoint) and the AI service container. The browser and the editor never see it — they only handle signed tokens. @@ -85,7 +85,7 @@ The shared secret (API Secret) exists only in the application back end (token en |The service is stateless; add replicas behind a load balancer without shared local state. |OpenAPI specification -|Published at `/v1/api/doc.json` with interactive documentation at `/docs/`. Auto-generate clients in any language. +|Published at `/v1/api/doc.json` with interactive documentation at `/v1/api/docs` (`/docs/` redirects there). Auto-generate clients in any language. |=== == Credentials @@ -128,7 +128,7 @@ NOTE: The service license key (`LICENSE_KEY`) and the {productname} editor licen |At least one provider. Multiple providers can coexist. |License key and registry credentials -|Provided by a Tiny account representative. +|Provided by a {companyname} account representative. |Token endpoint |A back end that signs HS256 JWTs. diff --git a/modules/ROOT/pages/tinymceai-permissions.adoc b/modules/ROOT/pages/tinymceai-permissions.adoc index 89c3c58bd6..c54d8cb144 100644 --- a/modules/ROOT/pages/tinymceai-permissions.adoc +++ b/modules/ROOT/pages/tinymceai-permissions.adoc @@ -11,7 +11,7 @@ For information about JWT authentication setup and required claims, see xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. [[quick-reference]] -== Quick Reference +== Quick reference [cols="2,3"] |=== @@ -37,7 +37,7 @@ For information about JWT authentication setup and required claims, see xref:tin |=== [[use-cases]] -== Use Cases +== Use cases * **Role-based access**: Different user roles have different AI capabilities * **Cost control**: Limit access to expensive models or features @@ -45,12 +45,12 @@ For information about JWT authentication setup and required claims, see xref:tin * **Security**: Restrict access to sensitive AI operations [[permission-format]] -== Permission Format +== Permission format -Permissions follow a hierarchical format: `ai:::` +Permissions are an array of strings in the `+auth.ai.permissions+` claim of the JWT. Each string has the form `+ai::+`, where `++` is one of `+models+`, `+conversations+`, `+actions+`, `+reviews+`, or `+admin+`. The `++` can contain the `+*+` wildcard. The service ignores any string that does not match this format. [[admin-permissions]] -== Admin Permissions +== Admin permissions [cols="2,3"] |=== @@ -61,7 +61,7 @@ Permissions follow a hierarchical format: `ai::::::::::::::::::::::::::: Parsing this format correctly (including chunk boundaries, multi-line `+data:+` fields, and comments) is easy to get wrong in hand-written loops. For production code, use a maintained SSE parser such as the https://www.npmjs.com/package/eventsource-parser[`eventsource-parser`] package. [[basic-implementation]] -== Basic Implementation +== Basic implementation -After obtaining a streaming `+Response+` from `+fetch+`, pass the byte stream through an SSE parser. The following example uses https://www.npmjs.com/package/eventsource-parser[`eventsource-parser`] to turn raw chunks into parsed events; application code then inspects each event payload (for example JSON with an `+event+` field and `+data+` for {pluginname} services): +After obtaining a streaming `+Response+` from `+fetch+`, pass the byte stream through an SSE parser. The following example uses https://www.npmjs.com/package/eventsource-parser[`eventsource-parser`] to turn raw chunks into parsed events. For each event, `+event.event+` is the event name from the `+event:+` line, and `+event.data+` is the JSON payload from the `+data:+` lines: [source,javascript] ---- @@ -63,20 +63,20 @@ const response = await fetch('/v1/your-endpoint', { const parser = createParser({ onEvent: (event) => { - // event.event is the SSE event name (if present) + // event.event is the SSE event name // event.data is the reassembled data string for this event - const data = JSON.parse(event.data); + const payload = JSON.parse(event.data); - switch (data.event) { + switch (event.event) { case 'error': - console.error('Error:', data.data.message); + console.error('Error:', payload.message); break; default: // Handle all other events — event names vary by API; see // https://tinymceai.api.tiny.cloud/docs for each operation's schema. // Examples: Conversations (text-delta, source, reasoning, modification-delta), // Reviews (review-delta, review-metadata), Actions (modification-delta, action-metadata) - console.log('Event:', data.event, data.data); + console.log('Event:', event.event, payload); } } }); @@ -92,30 +92,30 @@ while (true) { ---- [[error-handling]] -== Error Handling +== Error handling Always handle errors gracefully: [source,javascript] ---- -if (data.event === 'error') { - const error = data.data; - console.error('Streaming error:', error.message); +if (event.event === 'error') { + const payload = JSON.parse(event.data); + console.error('Streaming error:', payload.message); } ---- [[progress-tracking]] -== Progress Tracking +== Progress tracking Use metadata events to show progress. Event names and fields for review streaming are defined in the https://tinymceai.api.tiny.cloud/docs#tag/Reviews[Reviews API] operations that return SSE responses, not in the Review plugin overview. [[api-reference]] -== API Reference +== API reference The https://tinymceai.api.tiny.cloud/docs[interactive API documentation] describes streaming endpoints, event shapes, and errors for each feature area. [[next-steps]] -== Next Steps +== Next steps * xref:tinymceai-chat.adoc[Chat], xref:tinymceai-review.adoc[Review], and xref:tinymceai-actions.adoc[Quick Actions] for product behavior and editor integration. * xref:tinymceai-models.adoc[AI Models] for model configuration and limits. diff --git a/modules/ROOT/pages/tinymceai-with-jwt-authentication-nodejs.adoc b/modules/ROOT/pages/tinymceai-with-jwt-authentication-nodejs.adoc index 5f1ed39c1b..fee21bafb8 100644 --- a/modules/ROOT/pages/tinymceai-with-jwt-authentication-nodejs.adoc +++ b/modules/ROOT/pages/tinymceai-with-jwt-authentication-nodejs.adoc @@ -42,7 +42,7 @@ The `aud` is a case-sensitive string that must match a valid API key that has th `+sub+` _(required)_:: *Type:* `+String+` + -The `sub` claim identifies the user. This should be a unique identifier for the user making the request. +The `sub` claim identifies the user. This should be a unique identifier for the user making the request. See xref:tinymceai-jwt-authentication-intro.adoc#payload-properties[Payload properties] for the length limit and the session requirements. `+iat+` _(required)_:: *Type:* `+Number+` diff --git a/modules/ROOT/pages/tinymceai-with-jwt-authentication-php.adoc b/modules/ROOT/pages/tinymceai-with-jwt-authentication-php.adoc index c79f6a694a..be71fe7e35 100644 --- a/modules/ROOT/pages/tinymceai-with-jwt-authentication-php.adoc +++ b/modules/ROOT/pages/tinymceai-with-jwt-authentication-php.adoc @@ -42,7 +42,7 @@ The `aud` is a case-sensitive string that must match a valid API key that has th `+sub+` _(required)_:: *Type:* `+String+` + -The `sub` claim identifies the user. This should be a unique identifier for the user making the request. +The `sub` claim identifies the user. This should be a unique identifier for the user making the request. See xref:tinymceai-jwt-authentication-intro.adoc#payload-properties[Payload properties] for the length limit and the session requirements. `+iat+` _(required)_:: *Type:* `+Number+` diff --git a/modules/ROOT/pages/tinymceai.adoc b/modules/ROOT/pages/tinymceai.adoc index 8aca2f5dd8..1f9872ac0b 100644 --- a/modules/ROOT/pages/tinymceai.adoc +++ b/modules/ROOT/pages/tinymceai.adoc @@ -162,3 +162,39 @@ The {pluginname} plugin provides the following {productname} commands. include::partial$commands/{plugincode}-cmds.adoc[] +[[events]] +== Events + +The {pluginname} plugin provides the following events. + +include::partial$events/{plugincode}-events.adoc[] + +[[detecting-ai-changes]] +=== Detecting content written by the plugin + +When the {pluginname} plugin writes AI changes to the editor, it sets the `+ai+` property to `+true+` on the core `+BeforeSetContent+` and `+SetContent+` events. Event handlers can check this property to tell AI changes apart from other content changes. + +Other premium plugins use this property: + +* xref:suggestededits.adoc[Suggested Edits] records the edits as AI-assisted and shows an AI badge on their cards. See xref:suggestededits.adoc#suggestededits_ai_attribution[`+suggestededits_ai_attribution+`]. +* xref:revisionhistory.adoc[Revision History] can attribute revisions to AI when the application saves them from these events. + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to the HTML + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + }, + setup: (editor) => { + editor.on('SetContent', (e) => { + if (e.ai === true) { + console.log('The AI changes are now part of the editor content.'); + } + }); + } +}); +---- + diff --git a/modules/ROOT/partials/auth/tinymceai/nodejs/configuration-steps.adoc b/modules/ROOT/partials/auth/tinymceai/nodejs/configuration-steps.adoc index 89580518d4..4d0fbace44 100644 --- a/modules/ROOT/partials/auth/tinymceai/nodejs/configuration-steps.adoc +++ b/modules/ROOT/partials/auth/tinymceai/nodejs/configuration-steps.adoc @@ -8,7 +8,7 @@ === Add Private Key * Replace the private key placeholder in `jwt.js` with the actual private key -* Make sure it's in `PKCS8` format +* Make sure it is in `+PKCS8+` format * Keep this key secure and never share it publicly === Configure AI Permissions diff --git a/modules/ROOT/partials/auth/tinymceai/nodejs/initial-project-setup.adoc b/modules/ROOT/partials/auth/tinymceai/nodejs/initial-project-setup.adoc index 51213d134e..1c7a636c27 100644 --- a/modules/ROOT/partials/auth/tinymceai/nodejs/initial-project-setup.adoc +++ b/modules/ROOT/partials/auth/tinymceai/nodejs/initial-project-setup.adoc @@ -1,6 +1,6 @@ == Quick Start Guide -If a Node.js project is not already set up, follow the steps below to create a basic environment for integrating TinyMCE AI with JWT authentication. If a project is already configured, skip this section and proceed to the xref:tinymceai-with-jwt-authentication-nodejs.adoc#jwt-configuration-requirements[JWT Configuration Requirements] section. +If a Node.js project is not already set up, follow the steps below to create a basic environment for integrating {pluginname} with JWT authentication. If a project is already configured, skip this section and proceed to the xref:tinymceai-with-jwt-authentication-nodejs.adoc#jwt-configuration-requirements[JWT Configuration Requirements] section. === Project Setup diff --git a/modules/ROOT/partials/auth/tinymceai/nodejs/intro-and-prerequisites.adoc b/modules/ROOT/partials/auth/tinymceai/nodejs/intro-and-prerequisites.adoc index 61af3cafc1..265d3f2fad 100644 --- a/modules/ROOT/partials/auth/tinymceai/nodejs/intro-and-prerequisites.adoc +++ b/modules/ROOT/partials/auth/tinymceai/nodejs/intro-and-prerequisites.adoc @@ -22,7 +22,7 @@ This guide is designed for developers new to JWT authentication and {productname Before starting, ensure you have: * Node.js installed on the computer (to check, run `node -v` in the terminal) -* A {productname} API key with TinyMCE AI enabled (get one from link:https://www.tiny.cloud/signup[TinyMCE's website]) +* A {productname} API key with {pluginname} enabled (get one from link:https://www.tiny.cloud/signup[the {companyname} website]) * Basic familiarity with the command line [IMPORTANT] diff --git a/modules/ROOT/partials/auth/tinymceai/php/configuration-steps.adoc b/modules/ROOT/partials/auth/tinymceai/php/configuration-steps.adoc index ea07404a7b..aa145704fd 100644 --- a/modules/ROOT/partials/auth/tinymceai/php/configuration-steps.adoc +++ b/modules/ROOT/partials/auth/tinymceai/php/configuration-steps.adoc @@ -8,7 +8,7 @@ === Add Private Key * Replace the private key placeholder in `jwt.php` with the actual private key -* Make sure it's in `PKCS8` format +* Make sure it is in `+PKCS8+` format * Keep this key secure and never share it publicly === Configure AI Permissions diff --git a/modules/ROOT/partials/auth/tinymceai/php/intro-and-prerequisites.adoc b/modules/ROOT/partials/auth/tinymceai/php/intro-and-prerequisites.adoc index 8b2d27940c..0c425152e4 100644 --- a/modules/ROOT/partials/auth/tinymceai/php/intro-and-prerequisites.adoc +++ b/modules/ROOT/partials/auth/tinymceai/php/intro-and-prerequisites.adoc @@ -24,7 +24,7 @@ Before starting, ensure you have: * PHP installed on the computer (to check, run `php -v` in the terminal) * OpenSSL installed on the computer (to check, run `openssl version` in the terminal) * Composer installed on the computer (to check, run `composer -v` in the terminal) -* A {productname} API key with TinyMCE AI enabled (get one from link:https://www.tiny.cloud/signup[TinyMCE's website]) +* A {productname} API key with {pluginname} enabled (get one from link:https://www.tiny.cloud/signup[the {companyname} website]) * Basic familiarity with the command line [IMPORTANT] diff --git a/modules/ROOT/partials/commands/tinymceai-cmds.adoc b/modules/ROOT/partials/commands/tinymceai-cmds.adoc index 333d7401e2..fb7d0e08c4 100644 --- a/modules/ROOT/partials/commands/tinymceai-cmds.adoc +++ b/modules/ROOT/partials/commands/tinymceai-cmds.adoc @@ -32,7 +32,7 @@ The xref:tinymceai.adoc[`tinymceai`] plugin registers the following editor comma |`+TinyMCEAIQuickActionImproveWriting+` | |Runs the **Improve writing** quick action. |`+TinyMCEAIQuickActionContinueWriting+` | |Runs the **Continue writing** quick action. -|`+TinyMCEAIQuickActionCheckGrammar+` | |Runs the **Fix grammar** quick action. +|`+TinyMCEAIQuickActionCheckGrammar+` | |Runs the **Fix grammar & spelling** quick action. |`+TinyMCEAIQuickActionMakeShorter+` | |Runs **Make shorter**. |`+TinyMCEAIQuickActionMakeLonger+` | |Runs **Make longer**. |`+TinyMCEAIQuickActionToneCasual+` | |Runs **More casual** tone. @@ -99,7 +99,7 @@ tinymce.activeEditor.execCommand('TinyMCEAIReviewToneProfessional'); The `+TinyMCEAIReviewCustom+` command accepts three forms of third argument. -A `+String+` runs a review from that prompt on the default model, titled **Custom review**: +A `+String+` runs a review from that prompt on the model selected in the Review sidebar, titled **Custom review**: [source,js] ---- @@ -109,7 +109,7 @@ tinymce.activeEditor.execCommand('TinyMCEAIReviewCustom', false, 'Check for pass An object with a `+prompt+` property runs a review from a custom prompt: * `+prompt+` (`+String+`): The prompt sent to the model. This property is required. -* `+model+` (optional `+String+`): The model that runs the review. When omitted, the review runs on the model set by xref:tinymceai.adoc#tinymceai_default_model[`+tinymceai_default_model+`]. For the available model identifiers, see xref:tinymceai-models.adoc[AI Models]. +* `+model+` (optional `+String+`): The model that runs the review. When omitted, the review runs on the model selected in the Review sidebar, which is initially the default model set by xref:tinymceai.adoc#tinymceai_default_model[`+tinymceai_default_model+`]. For the available model identifiers, see xref:tinymceai-models.adoc[AI Models]. * `+name+` (optional `+String+`): The title shown above the review. When omitted, the title is **Custom review**. [source,js] diff --git a/modules/ROOT/partials/configuration/tinymceai_options.adoc b/modules/ROOT/partials/configuration/tinymceai_options.adoc index 73902da544..bd62935183 100644 --- a/modules/ROOT/partials/configuration/tinymceai_options.adoc +++ b/modules/ROOT/partials/configuration/tinymceai_options.adoc @@ -41,7 +41,7 @@ A function that returns a Promise resolving to an object with a `+token+` proper *Type:* `+Function+` (`+() => Promise<{ token: string }>+`) -*Default value:* `+undefined+` +*Default value:* A function that rejects with the error `+No token provider configured+`, so every request to the AI service fails until this option is set. The JWT payload must include these required claims: @@ -89,6 +89,38 @@ tinymce.init({ }); ---- +[[tinymceai_service_url]] +=== `+tinymceai_service_url+` + +The base URL of the AI service that the {pluginname} plugin sends its requests to. For the {cloudname} AI service, the value is `+https://tinymceai.api.tiny.cloud+`. For a xref:tinymceai-on-premises.adoc[self-hosted AI service], the value is the base URL of that service. Set the base URL only: API paths such as `+/v1/conversations+` are appended to it. A trailing slash is optional. + +Every {pluginname} request, including Chat, Quick Actions, Review, chat history, sources, and model list requests, goes to this URL, so the JSON Web Token (JWT) returned by xref:tinymceai.adoc#tinymceai_token_provider[`+tinymceai_token_provider+`] must be valid for the service at that address. If no service URL is available, requests fail with the error `+No service URL provided in "tinymceai_service_url" option+`. + +*Type:* `+String+` + +*Default value:* None. The {pluginname} plugin does not set a default service URL. + +When the option is not set, a self-hosted editor that uses a trial (ONLINE+) license key with `+online_license_services_opt_in: true+` uses the {cloudname} AI service URL, `+https://tinymceai.api.tiny.cloud+`. A value set in the editor configuration takes precedence. See xref:self-hosted-trial.adoc[Self-hosted trial]. + +Set the option when a self-hosted editor with a standard license key connects to the {cloudname} AI service. + +.Example: connecting to the {cloudname} AI service +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to the HTML + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_service_url: 'https://tinymceai.api.tiny.cloud', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +For the complete setup with a self-hosted AI service, see xref:tinymceai-on-premises-frameworks.adoc[{productname} integration for the on-premises AI service]. + [[tinymceai_sidebar_type]] === `+tinymceai_sidebar_type+` @@ -123,7 +155,9 @@ Changing this property dynamically (after the editor has been initialized) is no [[tinymceai_default_model]] === `+tinymceai_default_model+` -The default AI model to use when no model is explicitly selected by the user. If undefined, the AI service will select the best model for speed, quality, and cost. +The default AI model to use when no model is explicitly selected by the user. The value is a model ID returned by the AI service, for example `+agent-1+`. For the available IDs, see xref:tinymceai-models.adoc[AI Models]. + +If the option is not set, or the ID is not among the models that the AI service returns, the default is the first model that the service returns. An ID that is not found also logs the warning `+Default model provided not found+` in the browser console. *Type:* `+String+` @@ -299,11 +333,13 @@ tinymce.init({ [[tinymceai_chat_welcome_message]] === `+tinymceai_chat_welcome_message+` -Customizes the welcome message displayed in the Chat sidebar when starting a new conversation. +Customizes the welcome message displayed in the Chat sidebar when starting a new conversation. Set the option to an empty string (`+''+`) to show no welcome message. + +The value can contain Markdown or HTML formatting. Only these formatting elements are kept: paragraphs, headings, bold, italic and underlined text, links, ordered and unordered lists, line breaks, images, preformatted text and code, block quotes, tables, and horizontal rules. Other elements and attributes, scripts, styles, and event handler attributes are removed. *Type:* `+String+` -*Default value:* A default message introducing the AI assistant and its capabilities. +*Default value:* A default message that introduces the writing assistant and its capabilities. .Example [source,js] @@ -371,7 +407,7 @@ tinymce.init({ [[tinymceai_tool_data_callback]] === `+tinymceai_tool_data_callback+` -Customizes the status message shown in the Chat sidebar while the AI model calls a Model Context Protocol (MCP) tool. The function runs when the MCP server sends an `+mcp-tool-result+` or `+mcp-tool-notification+` event during a streaming response. The function returns a string to display as the status message, or returns `+undefined+` to fall back to the default status message. +Customizes the status message shown in the Chat sidebar while the AI model calls a Model Context Protocol (MCP) tool. The function runs when the MCP server sends an `+mcp-tool-result+` or `+mcp-tool-notification+` event during a streaming response. The function returns a string to display as the status message, or returns `+undefined+` to fall back to the default status message. Any value other than a string also falls back to the default status message. *Type:* `+Function+` (`+(event: MCPToolEvent) => string | undefined+`) @@ -390,7 +426,7 @@ The function receives a single `+event+` argument, which is one of the following ** `+level+` (`+String+`): The severity of the notification. One of `+'error'+`, `+'info'+`, `+'debug'+`, `+'notice'+`, `+'warning'+`, `+'critical'+`, `+'alert'+`, or `+'emergency'+`. ** `+data+`: The data included with the notification. -A common use is to map each tool name to a human-readable message. For example, the callback can display `+Searching the knowledge base...+` while a `+search-knowledge-base+` tool runs. +A common use is to map each tool name to a human-readable message. Tool names in these events start with the MCP server name, so match on the end of the name. For example, after a `+search-knowledge-base+` tool returns, the callback can display `+Knowledge base searched. Writing the reply...+`. .Example [source,js] @@ -400,12 +436,19 @@ tinymce.init({ plugins: 'tinymceai', toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', tinymceai_tool_data_callback: (event) => { - // Map tool names to human-readable status messages - const statusMessages = { - 'search-knowledge-base': 'Searching the knowledge base...' - }; + // Tool names arrive prefixed with the MCP server name, so match the end of the name if (event.type === 'mcp-tool-result') { - return statusMessages[event.toolName] || `Running ${event.toolName}...`; + // The tool has already returned when this event arrives + if (event.toolName.endsWith('search-knowledge-base')) { + return event.success + ? 'Knowledge base searched. Writing the reply...' + : 'The knowledge base search failed. Writing the reply...'; + } + return `Finished ${event.toolName}. Writing the reply...`; + } + if (event.type === 'mcp-tool-notification' && event.level === 'info') { + // A progress message from a tool that is still running + return `${event.toolName} is working...`; } // Use the default status message for other events return undefined; @@ -425,7 +468,7 @@ These options configure the Quick Actions menu, which provides one-click AI tran [[tinymceai_quickactions_menu]] === `+tinymceai_quickactions_menu+` -Array of control IDs that define the order of items in the Quick Actions menu. The default value includes all default items, including `+ai-quickactions-custom+` which adds a submenu of custom actions defined by `+tinymceai_quickactions_custom+`. +Array of control IDs that define the order of items in the Quick Actions menu. The default value includes all default items, including `+ai-quickactions-custom+`, which adds the **Other** submenu of custom actions defined by xref:tinymceai.adoc#tinymceai_quickactions_custom[`+tinymceai_quickactions_custom+`]. *Type:* `+Array+` of `+String+` @@ -575,13 +618,13 @@ tinymce.init({ [[tinymceai_quickactions_custom]] === `+tinymceai_quickactions_custom+` -Array of custom actions rendered in the Custom submenu within the AI Quick Actions menu. Each item can be type `+action+` (quick action with immediate preview) or type `+chat+` (opens in chat). +Array of custom actions rendered in the **Other** submenu within the AI Quick Actions menu. Each item can be type `+action+` (quick action with immediate preview) or type `+chat+` (opens in chat). * `+title+`: Text shown in the menu and chat history * `+prompt+`: The prompt sent to the AI * `+type+`: `+'action'+` or `+'chat'+` * `+model+`: Required for `+action+` type only -* `+id+` (optional): Stable identifier for the custom action. When set, the same string can be listed in xref:tinymceai.adoc#tinymceai_quickactions_menu[`tinymceai_quickactions_menu`] so the action appears as its own top-level menu item instead of only inside the Custom submenu. The identifier can also be used in the xref:menus-configuration-options.adoc#menu[`+menu+`] option or any other menu configuration that accepts menu item identifiers. +* `+id+` (optional): Stable identifier for the custom action. When set, the same string can be listed in xref:tinymceai.adoc#tinymceai_quickactions_menu[`+tinymceai_quickactions_menu+`] so the action appears as its own top-level menu item instead of only inside the **Other** submenu. The identifier can also be used in the xref:menus-configuration-options.adoc#menu[`+menu+`] option or any other menu configuration that accepts menu item identifiers. *Type:* `+Array+` of `+Object+` @@ -589,6 +632,8 @@ Array of custom actions rendered in the Custom submenu within the AI Quick Actio *Default value:* `+[]+` +The `+ai-quickactions-custom+` identifier, labeled **Other**, lists the custom actions. It is available as a menu item and a toolbar button only when the array contains at least one action. When the array is empty, it does not appear in the Quick Actions menu or in a toolbar that lists it. + .Example [source,js] ---- diff --git a/modules/ROOT/partials/events/tinymceai-events.adoc b/modules/ROOT/partials/events/tinymceai-events.adoc new file mode 100644 index 0000000000..73e23962d7 --- /dev/null +++ b/modules/ROOT/partials/events/tinymceai-events.adoc @@ -0,0 +1,13 @@ +The following events are provided by the xref:tinymceai.adoc[{productname} AI plugin]. + +[cols="1,1,2",options="header"] +|=== +|Name |Data |Description +|TinyMCEAIQuickActionResponse |N/A |Fired when the AI service finishes responding to a Quick Action, including the *Explain*, *Summarize*, and *Highlight key points* chat commands, custom actions of type `+chat+`, and the `+TinyMCEAIChatPrompt+` command. Not fired when the request is canceled or fails. +|TinyMCEAINewConversationInitialResponse |N/A |Fired when the AI service finishes its first reply to a prompt entered in a new Chat conversation. When a new conversation starts from a chat command or the `+TinyMCEAIChatPrompt+` command, `+TinyMCEAIQuickActionResponse+` fires instead. Not fired when the request is canceled or fails. +|TinyMCEAIReviewResponse |N/A |Fired when a review run in the Review sidebar ends, including when the review is stopped or fails. +|TinyMCEAIPreviewApplyChanges |N/A |Fired when the last pending suggestion in an AI preview is applied or skipped, and at least one suggestion was applied. The event fires before the editor content is updated. +|TinyMCEAIPreviewDiscardChanges |N/A |Fired when the last pending suggestion in an AI preview is skipped, and every suggestion was skipped. The event fires before the editor content is updated. +|=== + +None of these events carries data. To act on the editor content after the AI changes are written to it, listen for the `+SetContent+` event and check that its `+ai+` property is `+true+`. See xref:tinymceai.adoc#detecting-ai-changes[Detecting content written by the plugin]. From 3076b4ffee657aee7362a3c3b41b664f248e9e97 Mon Sep 17 00:00:00 2001 From: Karl Kemister-Sheppard Date: Tue, 6 Oct 2026 15:59:16 +1000 Subject: [PATCH 2/2] TINYDOC-3651: Remove the internal TinyMCE AI plugin events from the documentation. --- modules/ROOT/pages/events.adoc | 6 ------ modules/ROOT/pages/tinymceai.adoc | 9 +-------- modules/ROOT/partials/events/tinymceai-events.adoc | 13 ------------- 3 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 modules/ROOT/partials/events/tinymceai-events.adoc diff --git a/modules/ROOT/pages/events.adoc b/modules/ROOT/pages/events.adoc index b8bc7a18d6..17d7ea945b 100644 --- a/modules/ROOT/pages/events.adoc +++ b/modules/ROOT/pages/events.adoc @@ -277,7 +277,6 @@ The following plugins provide events. * xref:spell-checker-events[Spell Checker events] * xref:revisionhistory-events[Revision History events] * xref:autocorrect-events[Spelling Autocorrect events] -* xref:tinymceai-events[{productname} AI events] * xref:visual-blocks-events[Visual Blocks events] * xref:visual-characters-events[Visual Characters events] * xref:word-count-events[Word Count events] @@ -424,11 +423,6 @@ include::partial$events/tinymcespellchecker-events.adoc[] include::partial$events/autocorrect-events.adoc[] -[[tinymceai-events]] -=== {productname} AI events - -include::partial$events/tinymceai-events.adoc[] - [[visual-blocks-events]] === Visual Blocks events diff --git a/modules/ROOT/pages/tinymceai.adoc b/modules/ROOT/pages/tinymceai.adoc index 1f9872ac0b..b803b75b46 100644 --- a/modules/ROOT/pages/tinymceai.adoc +++ b/modules/ROOT/pages/tinymceai.adoc @@ -162,15 +162,8 @@ The {pluginname} plugin provides the following {productname} commands. include::partial$commands/{plugincode}-cmds.adoc[] -[[events]] -== Events - -The {pluginname} plugin provides the following events. - -include::partial$events/{plugincode}-events.adoc[] - [[detecting-ai-changes]] -=== Detecting content written by the plugin +== Detecting content written by the plugin When the {pluginname} plugin writes AI changes to the editor, it sets the `+ai+` property to `+true+` on the core `+BeforeSetContent+` and `+SetContent+` events. Event handlers can check this property to tell AI changes apart from other content changes. diff --git a/modules/ROOT/partials/events/tinymceai-events.adoc b/modules/ROOT/partials/events/tinymceai-events.adoc deleted file mode 100644 index 73e23962d7..0000000000 --- a/modules/ROOT/partials/events/tinymceai-events.adoc +++ /dev/null @@ -1,13 +0,0 @@ -The following events are provided by the xref:tinymceai.adoc[{productname} AI plugin]. - -[cols="1,1,2",options="header"] -|=== -|Name |Data |Description -|TinyMCEAIQuickActionResponse |N/A |Fired when the AI service finishes responding to a Quick Action, including the *Explain*, *Summarize*, and *Highlight key points* chat commands, custom actions of type `+chat+`, and the `+TinyMCEAIChatPrompt+` command. Not fired when the request is canceled or fails. -|TinyMCEAINewConversationInitialResponse |N/A |Fired when the AI service finishes its first reply to a prompt entered in a new Chat conversation. When a new conversation starts from a chat command or the `+TinyMCEAIChatPrompt+` command, `+TinyMCEAIQuickActionResponse+` fires instead. Not fired when the request is canceled or fails. -|TinyMCEAIReviewResponse |N/A |Fired when a review run in the Review sidebar ends, including when the review is stopped or fails. -|TinyMCEAIPreviewApplyChanges |N/A |Fired when the last pending suggestion in an AI preview is applied or skipped, and at least one suggestion was applied. The event fires before the editor content is updated. -|TinyMCEAIPreviewDiscardChanges |N/A |Fired when the last pending suggestion in an AI preview is skipped, and every suggestion was skipped. The event fires before the editor content is updated. -|=== - -None of these events carries data. To act on the editor content after the AI changes are written to it, listen for the `+SetContent+` event and check that its `+ai+` property is `+true+`. See xref:tinymceai.adoc#detecting-ai-changes[Detecting content written by the plugin].