diff --git a/modules/ROOT/examples/live-demos/revisionhistory/index.js b/modules/ROOT/examples/live-demos/revisionhistory/index.js index 9b7e1d1e37..9eaf5ce976 100644 --- a/modules/ROOT/examples/live-demos/revisionhistory/index.js +++ b/modules/ROOT/examples/live-demos/revisionhistory/index.js @@ -11,6 +11,7 @@ const revisions = [ name: 'James Wilson', avatar: 'https://sneak-preview.tiny.cloud/demouserdirectory/images/employee_james-wilson_128_52f19412.jpg', }, + metadata: { source: 'ai' }, content: `

TinyMCE Logo

Welcome to the TinyMCE editor demo!

@@ -150,6 +151,7 @@ tinymce.init({ revisionhistory_fetch, revisionhistory_fetch_revision, revisionhistory_display_author: true, + revisionhistory_ai_attribution: true, user_id: 'kai-nakamura', fetch_users: (userIds) => Promise.all(userIds .map((userId) => diff --git a/modules/ROOT/pages/8.7.0-release-notes.adoc b/modules/ROOT/pages/8.7.0-release-notes.adoc index 9114443f73..e43fa52cee 100644 --- a/modules/ROOT/pages/8.7.0-release-notes.adoc +++ b/modules/ROOT/pages/8.7.0-release-notes.adoc @@ -39,6 +39,23 @@ The following premium plugin updates were released alongside {productname} {rele // For information on the **** plugin, see: xref:.adoc[]. +=== Revision History + +The {productname} {release-version} release includes an accompanying release of the **Revision History** premium plugin. + +**Revision History** includes the following additions. + +==== Revisions can be attributed to AI and display an AI badge +// #TINY-14305 +// #TINY-14306 +// #TINY-14480 + +Revisions now support an optional `+metadata+` property. Setting its `+source+` field to `+'ai'+` marks a revision as AI-assisted, allowing integrators to track content produced by the xref:tinymceai.adoc[{productname} AI] plugin. When the new xref:revisionhistory.adoc#revisionhistory_ai_attribution[`+revisionhistory_ai_attribution+`] option is enabled, an AI badge is rendered on the cards of AI-assisted revisions. + +For details on attributing revisions to AI, see xref:revisionhistory.adoc#attributing-ai-assisted-revisions[Attributing AI-assisted revisions]. + +For information on the **Revision History** plugin, see: xref:revisionhistory.adoc[Revision History]. + === Suggested Edits The {productname} {release-version} release includes an accompanying release of the **Suggested Edits** premium plugin. diff --git a/modules/ROOT/pages/revisionhistory.adoc b/modules/ROOT/pages/revisionhistory.adoc index 2aaa4390f7..a95900379d 100644 --- a/modules/ROOT/pages/revisionhistory.adoc +++ b/modules/ROOT/pages/revisionhistory.adoc @@ -87,6 +87,7 @@ The revision is an `+Object+` that contains the following fields: | `+createdAt+` | `+string+` | required | A UTC datetime string in ISO-8061 format. | `+content+` | `+string+` | optional | HTML string of the revision content. Empty string is considered as valid content. | `+author+` | xref:#author[Author] `+Object+` | optional | The author of the revision. +| `+metadata+` | xref:#metadata[Metadata] `+Object+` | optional | Additional information about the revision, such as whether it was AI-assisted. |=== === Author @@ -101,6 +102,72 @@ The author is an `+Object+` that represents the author or creator of a revision. | `+avatar+` | `+string+` | optional | The URL of the author's avatar image. If not provided or invalid, the {pluginname} will use a generated avatar using the author's initials. |=== +=== Metadata + +The metadata is an `+Object+` that holds additional information about a revision. It contains the following fields: + +[cols="1,1,1,3",options="header"] +|=== +| Field | Type | Required? | Description +| `+source+` | `+string+` | optional | The origin of the revision's content. A value of `+'ai'+` marks the revision as AI-assisted and, when xref:revisionhistory_ai_attribution[`+revisionhistory_ai_attribution+`] is enabled, displays an AI badge on the revision card. +|=== + +== Attributing AI-assisted revisions + +A revision is identified as AI-assisted through the `+source+` field of its xref:#metadata[`+metadata+`] object. When `+metadata.source+` is `+'ai'+` and the xref:revisionhistory_ai_attribution[`+revisionhistory_ai_attribution+`] option is enabled, an AI badge appears on that revision card. + +The {pluginname} plugin does not set this marker automatically. The xref:tinymceai.adoc[{productname} AI] plugin sets `+ai+` to `+true+` on the `+SetContent+` event for any content it inserts. Detecting that signal and recording it as `+metadata.source+` when saving a revision is the responsibility of the application. There are three steps to keep attribution accurate: + +. **Detect**: Listen for the `+SetContent+` event and record when its `+ai+` property is `+true+`. +. **Save**: When saving a revision, set `+metadata.source+` to `+'ai'+` if AI contributed since the last save. +. **Restore**: When a revision is restored, carry its marker forward so later revisions remain correctly attributed. + +[NOTE] +The AI badge appears only on `+saved+` revisions. The `+draft+` and `+initial+` revisions are generated from the editor's current content and do not carry `+metadata+`, so they never display the badge, even when that content was AI-assisted. See xref:#understanding-revision-types[Understanding revision types]. + +=== Saving an AI-assisted revision + +The application is responsible for saving revisions and returns them through the xref:revisionhistory_fetch[`+revisionhistory_fetch+`] option. The following example tracks AI involvement from the `+SetContent+` event and attaches the `+metadata+` marker when saving a snapshot: + +[source,js] +---- +let aiAssisted = false; + +// The TinyMCE AI plugin sets `ai: true` on the SetContent event for content it inserts. +editor.on('SetContent', (e) => { + if (e.ai) { + aiAssisted = true; + } +}); + +// Call this when saving a snapshot of the current content as a revision. +const saveRevision = () => { + const revision = { + revisionId: createRevisionId(), // Replace with your ID generation + createdAt: new Date().toISOString(), + content: editor.getContent(), + // Mark the revision as AI-assisted if AI contributed since the last save. + ...(aiAssisted ? { metadata: { source: 'ai' } } : {}) + }; + + saveToStorage(revision); // Replace with your storage call + aiAssisted = false; // Reset state of AI assistance for new content +}; +---- + +=== Restoring an AI-assisted revision + +Restoring a revision sets its content back into the editor and fires the `+VersionRestored+` event. The restored content is not flagged as AI-assisted, so look up the restored revision and carry its marker forward to the next save: + +[source,js] +---- +editor.on('VersionRestored', (e) => { + const restored = getFromStorage(e.revisionId); // Replace with your storage lookup + // Preserve attribution so the next saved revision reflects the restored content. + aiAssisted = restored?.metadata?.source === 'ai'; +}); +---- + == Options @@ -120,6 +187,8 @@ include::partial$configuration/revisionhistory_author.adoc[leveloffset=+1] include::partial$configuration/revisionhistory_display_author.adoc[leveloffset=+1] +include::partial$configuration/revisionhistory_ai_attribution.adoc[leveloffset=+1] + include::partial$configuration/revisionhistory_css_url.adoc[leveloffset=+1] include::partial$configuration/revisionhistory_diff_classes.adoc[leveloffset=+1] diff --git a/modules/ROOT/partials/configuration/revisionhistory_ai_attribution.adoc b/modules/ROOT/partials/configuration/revisionhistory_ai_attribution.adoc new file mode 100644 index 0000000000..5b567fadf1 --- /dev/null +++ b/modules/ROOT/partials/configuration/revisionhistory_ai_attribution.adoc @@ -0,0 +1,23 @@ +[[revisionhistory_ai_attribution]] +== `revisionhistory_ai_attribution` + +This option controls the display of the AI badge on revision cards. When set to `+true+`, an AI badge appears on each revision whose xref:revisionhistory.adoc#metadata[`+metadata+`] has `+source+` set to `+'ai'+`. For details on attributing revisions to AI, see xref:revisionhistory.adoc#attributing-ai-assisted-revisions[Attributing AI-assisted revisions]. + +*Type:* `+Boolean+` + +*Default value:* `+false+` + +*Possible values:* `+true+`, `+false+` + +=== Example: using `revisionhistory_ai_attribution` + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // Change this value according to your HTML + plugins: 'revisionhistory', + toolbar: 'revisionhistory', + revisionhistory_fetch: () => Promise.resolve([]), + revisionhistory_ai_attribution: true +}); +----