探索 Tiptap V3 的最新功能

AI 建议扩展 API 参考

扩展选项

/**
 * AI 建议扩展的配置选项。
 */
export interface AiSuggestionOptions {
  /** 校对时要应用的规则
   * @default []
   */
  rules: AiSuggestionRule[]
  /** 在完成任何校对之前显示的初始建议
   * @default []
   */
  initialSuggestions: Suggestion[]
  /** 在完成任何校对之前应用的初始拒绝项
   * @default []
   */
  initialRejections: AiSuggestionRejection[]
  /** 自定义编辑器中建议装饰的方法
   * @default `getDefaultDecorations()`
   * @param args - 自定义建议装饰的选项。
   * @return 返回一个 `Decoration` 对象数组。
   */
  getCustomSuggestionDecoration: (args: GetCustomSuggestionDecorationOptions) => Decoration[]
  /** 内容变化后等待重新加载建议的时间,单位毫秒。
   * @default 800
   */
  debounceTimeout: number
  /** 编辑器初始化时是否加载建议
   * @default true
   */
  loadOnStart: boolean
  /** 编辑器内容变化时是否重新加载建议
   * @default true
   */
  reloadOnUpdate: boolean
  /** 加载建议时发生错误的回调函数
   * @param error - 加载建议时发生的错误。
   * @default console.error
   */
  onLoadSuggestionsError: (error: unknown) => void
  /**
   * 用于校对内容并生成建议的 AI 模型。
   * @default "gpt-4o-mini"
   */
  modelName: AiSuggestionModelName
  /**
   * 从外部来源加载建议的函数,基于当前编辑器内容和规则。允许你用自己的 AI 模型分析
   * 内容并返回建议。
   *
   * @param options - 解析建议的选项。
   * @return 应用的建议列表。
   */
  resolver: (options: AiSuggestionCustomResolverOptions) => Promise<Suggestion[]>
  /**
   * Tiptap AI 应用的 ID。
   */
  appId: string
  /**
   * Tiptap AI 令牌。
   */
  token: string
  /**
   * Tiptap AI API 的基础 URL。
   */
  baseUrl: string
  /**
   * 可选的上下文,用于向 AI 模型提供额外信息以生成建议。
   */
  context: string | null
  /**
   * 是否将编辑器内容分块并缓存每块的建议。这样扩展在重新加载内容时可以重复使用缓存的建议,
   * 对于处理大型文档,有助于提升性能并降低成本。
   *
   * @default true
   */
  enableCache: boolean
  /**
   * 将文档拆分成块的大小,以编辑器内容的顶层子节点数量计。
   *
   * @default 2
   */
  chunkSize: number
  /**
   * 一个将编辑器 HTML 内容分块的函数。
   * 默认根据配置的块大小将 HTML 拆分成更小部分,返回 HTML 块数组。你可以通过提供自己的函数覆盖此行为。
   *
   * @param options - 拆分 HTML 的选项。
   * @returns 返回一个块数组
   * @default `defaultChunkHtmlFunction`
   */
  chunkHtmlFunction: (options: ChunkHtmlOptions) => HtmlChunk[]
}

扩展命令

declare module '@tiptap/core' {
  interface Commands<ReturnType> {
    aiSuggestion: {
      /**
       * 立即加载 AI 建议。
       */
      loadAiSuggestions: () => ReturnType
      /**
       * 在扩展选项中定义的防抖超时后加载 AI 建议。
       */
      loadAiSuggestionsDebounced: () => ReturnType
      /**
       * 设置显示的 AI 建议。
       *
       * @param suggestions 要显示的建议。
       */
      setAiSuggestions: (suggestions: Suggestion[]) => ReturnType
      /**
       * 设置一个建议为选中状态。选中的建议在编辑器中会有不同样式。
       * */
      selectAiSuggestion: (suggestionId: string) => ReturnType
      /**
       * 应用一个建议到编辑器,修改内容。
       *
       * @param options 建议的 id 及选中替换选项。
       * 如果未提供替换选项,默认使用第一个选项。
       * 也可自定义替换内容的格式。
       */
      applyAiSuggestion: (options: ApplyAiSuggestionOptions) => ReturnType
      /**
       * 标记一个建议为已拒绝,从建议列表中移除。
       *
       * @param suggestionId 被拒绝建议的 id
       */
      rejectAiSuggestion: (suggestionId: string) => ReturnType

      /**
       * 设置多个被拒绝的建议。该命令对于撤销拒绝或清空所有拒绝项很有用。
       *
       * @param rejections 要设置的拒绝项。
       */
      setAiSuggestionRejections: (rejections: AiSuggestionRejection[]) => ReturnType

      /**
       * 应用所有未被拒绝的 AI 建议。
       * 对每个建议应用第一个替换选项。
       */
      applyAllAiSuggestions: (options?: ApplyAllAiSuggestionOptions) => ReturnType
      /**
       * 设置 AI 建议规则。允许你更新用于校对的规则,而无需重新加载编辑器。
       *
       * 该命令不会重新加载建议。要使用新规则重新加载建议,请调用 `loadAiSuggestions` 命令,例如:
       *
       * ```js
       * editor.chain().setAiSuggestionRules(newRules).loadAiSuggestions().run()
       * ```
       */
      setAiSuggestionRules: (rules?: AiSuggestionRule[]) => ReturnType

      /**
       * 设置 AI 建议上下文。该上下文用于向 AI 模型提供额外信息以生成建议。
       *
       * 该命令不会重新加载建议。要使用新上下文重新加载建议,请调用 `loadAiSuggestions` 命令,例如:
       *
       * ```js
       * editor.chain().setAiSuggestionContext(newContext).loadAiSuggestions().run()
       * ```
       *
       * @param context 可选上下文,用于向 AI 模型提供额外信息
       */
      setAiSuggestionContext: (context: string | null) => ReturnType
    }
  }
}

export interface ApplyAiSuggestionOptions {
  /**
   * 要应用的建议标识符。如果找不到建议,则方法不会执行任何操作。
   */
  suggestionId: string
  /**
   * 要应用的替换选项标识符。如果为 `undefined`,
   * 方法默认使用第一个替换选项。
   */
  replacementOptionId?: string
  /**
   * 决定建议如何被应用
   * 如果是 `rich-text`,建议将格式化为 HTML。
   * 如果是 `plain-text`,建议将格式化为纯文本。
   * @default "plain-text"
   */
  format?: 'rich-text' | 'plain-text'
}

export interface ApplyAllAiSuggestionOptions {
  /**
   * 决定建议如何被应用
   * 如果是 `rich-text`,建议将格式化为 HTML。
   * 如果是 `plain-text`,建议将格式化为纯文本。
   * @default "plain-text"
   */
  format?: 'rich-text' | 'plain-text'
}

扩展存储

/**
 * AI 建议扩展的内部存储。
 */
export interface AiSuggestionStorage {
  /** 扩展使用的 ProseMirror 插件的键 */
  pluginKey: PluginKey<AiSuggestionProsemirrorPluginState>
  /** 校对时要应用的规则 */
  rules: AiSuggestionRule[]
  /** 获取当前建议的函数 */
  getSuggestions: () => Suggestion[]
  /** 获取被拒绝建议的函数 */
  getRejections: () => AiSuggestionRejection[]
  /** 获取当前所选建议的函数 */
  getSelectedSuggestion: () => Suggestion | null
  /** 是否正在加载建议 */
  isLoading: boolean
  /** 是否至少加载过一次建议 */
  firstLoad: boolean
  /** 上次加载尝试时出现的错误(如果有) */
  error: unknown | null
  /** 用于加载建议的防抖函数 */
  debouncedFunction: DebouncedFunction<() => void>
  /** 用于中止加载建议的控制器 */
  abortController: AbortController
  /**
   * 可选上下文,用于向 AI 模型提供额外信息以生成建议。
   */
  context: string | null
  /**
   * 用于存储文档每块建议的缓存。
   */
  cache: AiSuggestionCache
}

/**
 * 在编辑器中为建议创建装饰的参数。
 */
export interface GetCustomSuggestionDecorationOptions {
  /** 正在装饰的建议 */
  suggestion: Suggestion
  /** 此建议是否被选中 */
  isSelected: boolean
  /** 获取扩展提供的默认装饰样式的函数 */
  getDefaultDecorations: () => Decoration[]
}

扩展类型

规则

/**
 * 校对中要应用的一条规则。
 */
export interface AiSuggestionRule {
  /**
   * 规则的唯一标识符。
   */
  id: string
  /**
   * 规则标题。不会用于校对,仅用于展示。
   */
  title: string
  /**
   * 规则提示。会发送给 AI 模型用于校对。
   */
  prompt: string
  /**
   * 规则颜色。用于标记必须替换内容的下划线颜色。
   */
  color: string
  /**
   * 规则背景色。在选中建议时用于突出显示内容。
   */
  backgroundColor: string
  /**
   * 规则的额外元数据,可用于存储附加信息(例如其来源或类别)。
   * 扩展内部不使用,但可帮助开发者自定义规则在 UI 中的展示。
   */
  metadata?: any
}

校对建议

import { Range } from '@tiptap/core'
import { Slice } from '@tiptap/pm/model'

import { AiSuggestionRule } from './ai-suggestion-rule'

/**
 * 建议的一个替换选项,包含待添加的文本和被替换的片段。
 */
export interface AiSuggestionReplacementOption {
  id: string
  /**
   * 替换格式为 `plain-text` 时添加的文本。
   */
  addText: string
  /**
   * 替换格式为 `rich-text` 时,添加的内容片段。
   */
  addSlice: Slice
}

/**
 * AI 建议扩展给出的建议。包含应被替换的范围、
 * 要删除的文本、替换选项以及需应用的规则。
 *
 * 一个建议可以有多个替换选项,用户可以从中选择一个应用。
 */
export interface Suggestion {
  /**
   * 建议的唯一标识符。
   */
  id: string
  /**
   * 编辑器中应被替换内容的范围。
   */
  deleteRange: Range
  /**
   * 要从编辑器删除的纯文本内容。
   */
  deleteText: string
  /**
   * 要从编辑器删除的内容,Prosemirror 片段格式。
   */
  deleteSlice: Slice
  /**
   * 建议的多个替换选项,用户可以从中选一个应用。
   */
  replacementOptions: AiSuggestionReplacementOption[]
  /**
   * 该建议所遵循的校对规则。
   */
  rule: AiSuggestionRule
  /**
   * 建议是否被用户拒绝。
   */
  isRejected: boolean
  /**
   * 建议的额外元数据,可用于存储附加信息(如来源或类别)。
   * 扩展内部不使用,但可帮助开发者自定义建议在 UI 中的展示。
   */
  metadata?: any
}

被拒绝的建议

import { AiSuggestionRule } from './ai-suggestion-rule'

/**
 * 表示一条被拒绝的建议。这些会存储在 AI 建议扩展的存储中,
 * 以避免该建议再次被生成。
 */
export interface AiSuggestionRejection {
  /**
   * 被拒绝建议的规则。
   */
  rule: AiSuggestionRule
  /**
   * 被拒绝建议中即将被删除的文本。
   */
  deleteText: string
}