Now Available: Notion-like editor templateNotion-style editor for Tiptap Cloud

Manage and review AI responses

Available in Start plan

The AI extension stores the current state in its extension storage under editor.storage.ai. It keeps track of the current state of the AI response, as well as any past responses.

keytypedefinition
state'loading' | 'error' | 'idle'While the AI is generating a response, the state is set to loading. After the response is generated, the state is set to idle. When there is an error, the state is set to error
responsestring | undefinedThe most recent message generated by the AI. When idle, if this is a string, it is the previous generated message, if undefined, no message has been generated. When loading, this will be a string of the HTML or text the AI has generated so far (if streaming the response). When error, this is undefined
errorError | undefinedThe error generated, only ever set in the error state
generatedWith{ action: TextAction; options: TextOptions; range: undefined | Range; } | undefinedThe options that describe what the last generated response was generated with range is only ever set if inserting the content into the editor
pastResponsesstring[]Stores previously generated responses (on success), most recent first. Cleared when the response is accepted/rejected.
initialContentSlice | nullThe content of the editor before the AI response was inserted. Used to undo the AI response with the aiReject command.

Accessing AI storage

You can use the extension storage to access the current state of the AI generation.

const aiStorage = editor.storage.ai

if (aiStorage.response.state === 'error') {
  // The error that occurred
  aiStorage.response.error
}

if (aiStorage.response.state === 'loading') {
  // The response of the AI model as it is being generated
  aiStorage.response
}

if (aiStorage.response.state === 'idle') {
  if (aiStorage.response) {
    // The successful response
    aiStorage.response
  } else {
    // No response has been requested yet
  }
}

Review AI-generated content

The AI extension provides commands to review the AI-generated content after it has been inserted into the editor.

aiAccept

Marks the AI response as accepted. This will clear the pastResponses array and set the initialContent to null.

editor.commands.aiAccept()

aiReject

Resets the editor content to the previous value.

editor.commands.aiReject()

Resetting to the initial value after multiple AI requests

If you call multiple AI commands in a row, the initialContent property will be set to the content of the immediately previous command. So when you call aiReject, the editor content will be reset to the state before the previous AI command was executed. To reset the editor content to the state before all AI commands were executed, you can call commands with the regenerate option set to true. For example: editor.commands.aiSummarize({ regenerate: true }).

aiRegenerate

Retries the AI response with the same parameters as the previous request.

editor.commands.aiRegenerate()

Preview AI responses before inserting them

Want to preview AI responses before they are inserted into the editor? You can use insert: false on any AI TextOption. The result will be stored in the extension storage but not inserted into the editor's content.

editor.commands.aiTextPrompt({
  text: 'Re-write this text to make it more formal',
  stream: true,
  insert: false,
  format: 'rich-text',
})

From there, you can use the aiAccept, aiReject, and aiRegenerate commands

aiAccept

This command is meant to be ran when the user has accepted the AI response, it will insert the response into the editor by default and it’s behavior changes depending on the provided options.

keytypedefinition
insertAtnumber | { from: number, to: number }When a number, accept the response and insert it into the start of the editor. When { from: number, to: number }, accept the response and replace the content from position from to position to with the AI response
appendbooleanIf true, instead of replacing the current selection, append to it

The default behavior with no provided options is to accept the response and insert it into the editor, replacing the current selection

// Accept the response and insert it into the editor
editor.commands.aiAccept()

// Accept the response and insert it into the editor at the start
editor.commands.aiAccept({ insertAt: 0 })

// Accept the response and insert it into the editor at the end
editor.commands.aiAccept({ insertAt: editor.state.doc.content.size })

// Accept the response and append it to the current selection
editor.commands.aiAccept({ append: true })

aiRegenerate

This command is meant to be ran when the user wants the to retry the AI response, it will use all the same options as the previous AI text operation and add to the editor.storage.ai.pastResponses array

keytypedefinition
insertbooleanWhether to insert the regenerated response into the editor
insertAtnumber | { from: number, to: number }If not specified,the regenerated response will be inserted where the previous response was. When a number, regenerate the response and insert it into the start of the editor. When { from: number, to: number }, regenerate the response and replace the content from position from to position to with the AI response

The default behavior with no provided options is to, regenerate the response and insert it into the editor, replacing the current selection

// Regenerate the response and insert it into the editor
editor.commands.aiRegenerate()

// Regenerate the response and insert it into the editor at the start
editor.commands.aiRegenerate({ insertAt: 0 })

// Regenerate the response and insert it into the editor at the end
editor.commands.aiRegenerate({ insertAt: editor.state.doc.content.size })

// Regenerate the response and append it to the current selection
editor.commands.aiRegenerate({ append: true })

aiReject

This command is meant to be ran when the user has rejected the AI response, it will reset the extension’s state to the initial idle state and clear all editor.storage.ai.pastResponses

keytypedefinition
type'reset' | 'pause'Whether to reset the AI to the idle state. Or just pause the current response. Default is 'reset'
editor.commands.aiReject()

// Will not clear out editor.storage.ai, useful for keeping current response in the editor storage
editor.commands.aiReject({ type: 'pause' })

Advanced example (preview AI responses)

One use case of the extension storage is to render a preview of the AI generated content. The tryParseToTiptapHTML function leverages your editor's schema to generate a HTML preview of the AI response.

// Display the response as HTML
import { tryParseToTiptapHTML } from '@tiptap-pro/extension-ai'

// try to parse the current message as HTML, and null if it could not be parsed
tryParseToTiptapHTML(editor.storage.ai.response, editor)

// try to parse a previous response as HTML, and null if it could not be parsed
tryParseToTiptapHTML(editor.storage.ai.pastResponses[0], editor)

// For example in React
function PreviewComponent({ editor }) {
  const htmlResponse = tryParseToTiptapHTML(editor.storage.ai.response, editor)
  /* This is safe since we've parsed the content with prose-mirror first */
  return <div dangerouslySetInnerHTML={{ __html: htmlResponse }}></div>
}

See our demo below for a full example.