@liveblocks/react-tiptap 3.9.2-tiptap3 → 3.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LiveblocksExtension.cjs +3 -4
- package/dist/LiveblocksExtension.cjs.map +1 -1
- package/dist/LiveblocksExtension.js +3 -4
- package/dist/LiveblocksExtension.js.map +1 -1
- package/dist/ai/AiExtension.cjs.map +1 -1
- package/dist/ai/AiExtension.js.map +1 -1
- package/dist/ai/AiToolbar.cjs.map +1 -1
- package/dist/ai/AiToolbar.js.map +1 -1
- package/dist/comments/AnchoredThreads.cjs +1 -1
- package/dist/comments/AnchoredThreads.cjs.map +1 -1
- package/dist/comments/AnchoredThreads.js +1 -1
- package/dist/comments/AnchoredThreads.js.map +1 -1
- package/dist/comments/CommentsExtension.cjs +3 -0
- package/dist/comments/CommentsExtension.cjs.map +1 -1
- package/dist/comments/CommentsExtension.js +3 -0
- package/dist/comments/CommentsExtension.js.map +1 -1
- package/dist/comments/FloatingComposer.cjs +3 -7
- package/dist/comments/FloatingComposer.cjs.map +1 -1
- package/dist/comments/FloatingComposer.js +3 -7
- package/dist/comments/FloatingComposer.js.map +1 -1
- package/dist/index.d.cts +4 -135
- package/dist/index.d.ts +4 -135
- package/dist/mentions/GroupMentionNode.cjs.map +1 -1
- package/dist/mentions/GroupMentionNode.js.map +1 -1
- package/dist/mentions/Mention.cjs +46 -37
- package/dist/mentions/Mention.cjs.map +1 -1
- package/dist/mentions/Mention.js +45 -36
- package/dist/mentions/Mention.js.map +1 -1
- package/dist/mentions/MentionNode.cjs.map +1 -1
- package/dist/mentions/MentionNode.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/version-history/HistoryVersionPreview.cjs +0 -1
- package/dist/version-history/HistoryVersionPreview.cjs.map +1 -1
- package/dist/version-history/HistoryVersionPreview.js +0 -1
- package/dist/version-history/HistoryVersionPreview.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +14 -12
- package/src/styles/index.css +2 -3
- package/styles.css +1 -1
- package/styles.css.map +1 -1
|
@@ -7,7 +7,7 @@ var _private$1 = require('@liveblocks/react-ui/_private');
|
|
|
7
7
|
var yjs = require('@liveblocks/yjs');
|
|
8
8
|
var core = require('@tiptap/core');
|
|
9
9
|
var Collaboration = require('@tiptap/extension-collaboration');
|
|
10
|
-
var CollaborationCursor = require('@tiptap/extension-collaboration-
|
|
10
|
+
var CollaborationCursor = require('@tiptap/extension-collaboration-cursor');
|
|
11
11
|
var react = require('react');
|
|
12
12
|
var AiExtension = require('./ai/AiExtension.cjs');
|
|
13
13
|
var CommentsExtension = require('./comments/CommentsExtension.cjs');
|
|
@@ -41,9 +41,9 @@ const LiveblocksCollab = Collaboration.extend({
|
|
|
41
41
|
"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension."
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
|
-
if (this.editor.extensionManager.extensions.find((e) => e.name === "
|
|
44
|
+
if (this.editor.extensionManager.extensions.find((e) => e.name === "history")) {
|
|
45
45
|
console.warn(
|
|
46
|
-
"[Liveblocks] The
|
|
46
|
+
"[Liveblocks] The history extension is enabled, Liveblocks extension provides its own. Please remove or disable the History plugin to prevent unwanted conflicts."
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -293,7 +293,6 @@ const useLiveblocksExtension = (opts) => {
|
|
|
293
293
|
document: this.storage.doc,
|
|
294
294
|
field: options.field
|
|
295
295
|
}),
|
|
296
|
-
// I don't really think this is needed...
|
|
297
296
|
CollaborationCursor.configure({
|
|
298
297
|
provider: this.storage.provider
|
|
299
298
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveblocksExtension.cjs","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n IUserInfo,\n JsonObject,\n User,\n} from \"@liveblocks/core\";\nimport { kInternal, TextEditorType } from \"@liveblocks/core\";\nimport { useClient, useRoom } from \"@liveblocks/react\";\nimport {\n getUmbrellaStoreForClient,\n useCreateTextMention,\n useDeleteTextMention,\n useReportTextEditor,\n useYjsProvider,\n} from \"@liveblocks/react/_private\";\nimport { useInitial } from \"@liveblocks/react-ui/_private\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport { getYjsProviderForRoom } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType, Mark } from \"@tiptap/core\";\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor, {\n type CollaborationCaretOptions,\n} from \"@tiptap/extension-collaboration-caret\";\nimport type { Mark as PMMark } from \"@tiptap/pm/model\";\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport {\n areSetsEqual,\n CommentsExtension,\n FILTERED_THREADS_PLUGIN_KEY,\n} from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveContextualPromptArgs,\n ResolveContextualPromptResponse,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: false,\n enablePermanentUserData: false,\n};\n\nconst LiveblocksCollab = Collaboration.extend({\n // Override the onCreate method to warn users about potential misconfigurations\n onCreate() {\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"doc\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap document extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n !this.editor.extensionManager.extensions.find(\n (e) => e.name === \"paragraph\"\n )\n ) {\n console.warn(\n \"[Liveblocks] The tiptap paragraph extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"text\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n this.editor.extensionManager.extensions.find((e) => e.name === \"undoRedo\")\n ) {\n console.warn(\n \"[Liveblocks] The undoRedo extension is enabled, Liveblocks extension provides its own. Please remove or disable the undoRedo extension to prevent conflicts.\"\n );\n }\n },\n});\n\n/**\n * Returns whether the editor has loaded the initial text contents from the\n * server and is ready to be used.\n *\n */\nexport function useIsEditorReady(): boolean {\n const yjsProvider = useYjsProvider();\n\n const getSnapshot = useCallback(() => {\n const status = yjsProvider?.getStatus();\n return status === \"synchronizing\" || status === \"synchronized\";\n }, [yjsProvider]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n if (yjsProvider === undefined) return () => {};\n yjsProvider.on(\"status\", callback);\n return () => {\n yjsProvider.off(\"status\", callback);\n };\n },\n [yjsProvider]\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nconst YChangeMark = Mark.create({\n name: \"ychange\",\n inclusive: false,\n parseHTML() {\n return [{ tag: \"ychange\" }];\n },\n addAttributes() {\n return {\n user: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_user\") ?? null,\n renderHTML: (attributes: { user: string | null }) => {\n if (!attributes.user) {\n return {};\n }\n return { \"data-ychange-user\": attributes.user };\n },\n },\n type: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_type\") ?? null,\n renderHTML: (attributes: { type: string | null }) => {\n if (!attributes.type) {\n return {};\n }\n return {\n \"data-ychange-type\": attributes.type,\n \"data-liveblocks\": \"\",\n class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`,\n };\n },\n },\n color: {\n default: null,\n parseHTML: (element) => {\n return element.getAttribute(\"ychange_color\") ?? null;\n },\n renderHTML: () => {\n // attributes: { color: { light: string; dark: string } | null }\n return {}; // we don't need this color attribute for now\n },\n },\n };\n },\n renderHTML({ HTMLAttributes }) {\n return [\"ychange\", HTMLAttributes, 0];\n },\n});\n\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const textEditorType = useInitial<TextEditorType>(\n options.textEditorType ?? TextEditorType.TipTap\n );\n const editor = useRef<Editor | null>(null);\n const room = useRoom();\n\n // TODO: we don't need these things if comments isn't turned on...\n // TODO: we don't have a reference to the editor here, need to figure this out\n // useErrorListener((error) => {\n // // If thread creation fails, we remove the thread id from the associated nodes and unwrap the nodes if they are no longer associated with any threads\n // if (\n // error.context.type === \"CREATE_THREAD_ERROR\" &&\n // error.context.roomId === room.id\n // ) {\n // handleThreadDelete(error.context.threadId);\n // }\n // });\n\n const isEditorReady = useIsEditorReady();\n const client = useClient();\n const store = getUmbrellaStoreForClient(client);\n const roomId = room.id;\n const yjsProvider = useYjsProvider();\n\n // If the user provided initialContent, wait for ready and then set it\n useEffect(() => {\n if (\n !isEditorReady ||\n !yjsProvider ||\n !options.initialContent ||\n !editor.current\n )\n return;\n\n // As noted in the tiptap documentation, you may not set initial content with collaboration.\n // The docs provide the following workaround:\n const ydoc = (yjsProvider as LiveblocksYjsProvider).getYDoc();\n const hasContentSet = ydoc.getMap(\"liveblocks_config\").get(\"hasContentSet\");\n if (!hasContentSet) {\n ydoc.getMap(\"liveblocks_config\").set(\"hasContentSet\", true);\n editor.current.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent]);\n\n useReportTextEditor(textEditorType, options.field ?? DEFAULT_OPTIONS.field);\n\n const prevThreadsRef = useRef<Set<string> | undefined>(undefined);\n\n useEffect(() => {\n if (!isEditorReady) return;\n\n if (!editor.current) return;\n\n const newThreads = options.threads_experimental\n ? new Set(options.threads_experimental.map((t) => t.id))\n : undefined;\n\n const hasFilteredThreadsChanged = !areSetsEqual(\n prevThreadsRef.current,\n newThreads\n );\n\n if (hasFilteredThreadsChanged) {\n prevThreadsRef.current = newThreads;\n }\n\n if (hasFilteredThreadsChanged) {\n editor.current.view.dispatch(\n editor.current.state.tr.setMeta(FILTERED_THREADS_PLUGIN_KEY, {\n filteredThreads: options.threads_experimental\n ? new Set(options.threads_experimental.map((t) => t.id))\n : undefined,\n })\n );\n }\n }, [isEditorReady, options.threads_experimental]);\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n // Tiptap has options default as any, in tiptap2, we could use never, but now we must use any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Extension.create<any, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n editor.current = this.editor;\n if (this.editor.options.content) {\n console.warn(\n \"[Liveblocks] Initial content must be set in the useLiveblocksExtension hook option. Remove content from your editor options.\"\n );\n }\n if (\n options.mentions &&\n this.editor.extensionManager.extensions.find(\n (e) => e.name.toLowerCase() === \"mention\"\n )\n ) {\n console.warn(\n \"[Liveblocks] Liveblocks own mention plugin is enabled, using another mention plugin may cause a conflict.\"\n );\n }\n const self = room.getSelf();\n const updateUser = ({\n info,\n id: userId,\n }: User<JsonObject, BaseUserMeta>) => {\n if (!info) {\n return;\n }\n const { user: storedUser } =\n this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n if (this.storage.permanentUserData) {\n const pud = this.storage.permanentUserData.clients.get(\n this.storage.doc.clientID\n );\n // Only update if there is no entry or if the entry is different\n if (!pud || pud !== userId) {\n this.storage.permanentUserData.setUserMapping(\n this.storage.doc,\n this.storage.doc.clientID,\n userId ?? \"Unknown\" // TODO: change this to the user's ID so we can map it to the user's name\n );\n }\n }\n if (\n info.name !== storedUser?.name ||\n info.color !== storedUser?.color\n ) {\n this.editor.commands.updateUser({\n name: info.name,\n color: info.color,\n });\n }\n };\n // if we already have user info, we update the user\n if (self?.info) {\n updateUser(self);\n }\n // we also listen in case the user info changes\n this.storage.unsubs.push(room.events.self.subscribe(updateUser));\n if (options.comments) {\n const commentMarkType = getMarkType(\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n this.editor.schema\n );\n this.storage.unsubs.push(\n // Subscribe to threads so we can update comment marks if they become resolved/deleted\n store.outputs.threads.subscribe(() => {\n const threadMap = new Map(\n store.outputs.threads\n .get()\n .findMany(roomId, { resolved: false }, \"asc\", undefined)\n .map((thread) => [thread.id, true])\n );\n function isComment(mark: PMMark): mark is PMMark & {\n attrs: { orphan: boolean; threadId: string };\n } {\n return mark.type.name === LIVEBLOCKS_COMMENT_MARK_TYPE;\n }\n // when threads change, find marks and update them if needed\n this.editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (isComment(mark)) {\n const markThreadId = mark.attrs.threadId;\n const isOrphan = !threadMap.has(markThreadId);\n if (isOrphan !== mark.attrs.orphan) {\n const { tr } = this.editor.state;\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n this.editor.state.doc.content.size - 1\n );\n tr.removeMark(trimmedFrom, trimmedTo, mark);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n commentMarkType.create({\n ...mark.attrs,\n orphan: isOrphan,\n })\n );\n this.editor.view.dispatch(tr);\n }\n }\n });\n });\n })\n );\n }\n },\n onDestroy() {\n this.storage.unsubs.forEach((unsub) => unsub());\n },\n addGlobalAttributes() {\n return [\n {\n types: [\"paragraph\", \"heading\"],\n attributes: {\n ychange: { default: null },\n },\n },\n ];\n },\n addStorage() {\n const provider = getYjsProviderForRoom(room, {\n enablePermanentUserData:\n !!options.ai || options.enablePermanentUserData,\n offlineSupport_experimental: options.offlineSupport_experimental,\n });\n return {\n doc: provider.getYDoc(),\n provider,\n permanentUserData: provider.permanentUserData,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n YChangeMark,\n\n LiveblocksCollab.configure({\n ySyncOptions: {\n permanentUserData: this.storage.permanentUserData,\n },\n document: this.storage.doc,\n field: options.field,\n }), // I don't really think this is needed...\n CollaborationCursor.configure({\n provider: this.storage.provider,\n }) as Extension<CollaborationCaretOptions>,\n ];\n\n if (options.comments) {\n extensions.push(CommentsExtension);\n }\n if (options.mentions) {\n extensions.push(\n MentionExtension.configure({\n onCreateMention: (mention) => {\n createTextMention(mention.notificationId, mention);\n },\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveContextualPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveContextualPromptArgs): Promise<ResolveContextualPromptResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n // This response is validated afterwards by AiExtension itself\n return JSON.parse(result) as ResolveContextualPromptResponse;\n };\n\n extensions.push(\n AiExtension.configure({\n resolveContextualPrompt,\n ...(typeof options.ai === \"boolean\" ? {} : options.ai),\n doc: this.storage.doc,\n pud: this.storage.permanentUserData,\n })\n );\n }\n\n return extensions;\n },\n });\n};\n"],"names":["useYjsProvider","useCallback","useSyncExternalStore","Mark","useInitial","TextEditorType","useRef","useRoom","useClient","getUmbrellaStoreForClient","useEffect","useReportTextEditor","areSetsEqual","FILTERED_THREADS_PLUGIN_KEY","useCreateTextMention","useDeleteTextMention","Extension","getMarkType","LIVEBLOCKS_COMMENT_MARK_TYPE","getYjsProviderForRoom","CommentsExtension","MentionExtension","kInternal","AiExtension"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LiveblocksExtension.cjs","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n IUserInfo,\n JsonObject,\n User,\n} from \"@liveblocks/core\";\nimport { kInternal, TextEditorType } from \"@liveblocks/core\";\nimport { useClient, useRoom } from \"@liveblocks/react\";\nimport {\n getUmbrellaStoreForClient,\n useCreateTextMention,\n useDeleteTextMention,\n useReportTextEditor,\n useYjsProvider,\n} from \"@liveblocks/react/_private\";\nimport { useInitial } from \"@liveblocks/react-ui/_private\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport { getYjsProviderForRoom } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType, Mark } from \"@tiptap/core\";\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor from \"@tiptap/extension-collaboration-cursor\";\nimport type { Mark as PMMark } from \"@tiptap/pm/model\";\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport {\n areSetsEqual,\n CommentsExtension,\n FILTERED_THREADS_PLUGIN_KEY,\n} from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveContextualPromptArgs,\n ResolveContextualPromptResponse,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: false,\n enablePermanentUserData: false,\n};\n\nconst LiveblocksCollab = Collaboration.extend({\n // Override the onCreate method to warn users about potential misconfigurations\n onCreate() {\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"doc\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap document extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n !this.editor.extensionManager.extensions.find(\n (e) => e.name === \"paragraph\"\n )\n ) {\n console.warn(\n \"[Liveblocks] The tiptap paragraph extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"text\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n this.editor.extensionManager.extensions.find((e) => e.name === \"history\")\n ) {\n console.warn(\n \"[Liveblocks] The history extension is enabled, Liveblocks extension provides its own. Please remove or disable the History plugin to prevent unwanted conflicts.\"\n );\n }\n },\n});\n\n/**\n * Returns whether the editor has loaded the initial text contents from the\n * server and is ready to be used.\n *\n */\nexport function useIsEditorReady(): boolean {\n const yjsProvider = useYjsProvider();\n\n const getSnapshot = useCallback(() => {\n const status = yjsProvider?.getStatus();\n return status === \"synchronizing\" || status === \"synchronized\";\n }, [yjsProvider]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n if (yjsProvider === undefined) return () => {};\n yjsProvider.on(\"status\", callback);\n return () => {\n yjsProvider.off(\"status\", callback);\n };\n },\n [yjsProvider]\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nconst YChangeMark = Mark.create({\n name: \"ychange\",\n inclusive: false,\n parseHTML() {\n return [{ tag: \"ychange\" }];\n },\n addAttributes() {\n return {\n user: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_user\") ?? null,\n renderHTML: (attributes: { user: string | null }) => {\n if (!attributes.user) {\n return {};\n }\n return { \"data-ychange-user\": attributes.user };\n },\n },\n type: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_type\") ?? null,\n renderHTML: (attributes: { type: string | null }) => {\n if (!attributes.type) {\n return {};\n }\n return {\n \"data-ychange-type\": attributes.type,\n \"data-liveblocks\": \"\",\n class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`,\n };\n },\n },\n color: {\n default: null,\n parseHTML: (element) => {\n return element.getAttribute(\"ychange_color\") ?? null;\n },\n renderHTML: () => {\n // attributes: { color: { light: string; dark: string } | null }\n return {}; // we don't need this color attribute for now\n },\n },\n };\n },\n renderHTML({ HTMLAttributes }) {\n return [\"ychange\", HTMLAttributes, 0];\n },\n});\n\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const textEditorType = useInitial<TextEditorType>(\n options.textEditorType ?? TextEditorType.TipTap\n );\n const editor = useRef<Editor | null>(null);\n const room = useRoom();\n\n // TODO: we don't need these things if comments isn't turned on...\n // TODO: we don't have a reference to the editor here, need to figure this out\n // useErrorListener((error) => {\n // // If thread creation fails, we remove the thread id from the associated nodes and unwrap the nodes if they are no longer associated with any threads\n // if (\n // error.context.type === \"CREATE_THREAD_ERROR\" &&\n // error.context.roomId === room.id\n // ) {\n // handleThreadDelete(error.context.threadId);\n // }\n // });\n\n const isEditorReady = useIsEditorReady();\n const client = useClient();\n const store = getUmbrellaStoreForClient(client);\n const roomId = room.id;\n const yjsProvider = useYjsProvider();\n\n // If the user provided initialContent, wait for ready and then set it\n useEffect(() => {\n if (\n !isEditorReady ||\n !yjsProvider ||\n !options.initialContent ||\n !editor.current\n )\n return;\n\n // As noted in the tiptap documentation, you may not set initial content with collaboration.\n // The docs provide the following workaround:\n const ydoc = (yjsProvider as LiveblocksYjsProvider).getYDoc();\n const hasContentSet = ydoc.getMap(\"liveblocks_config\").get(\"hasContentSet\");\n if (!hasContentSet) {\n ydoc.getMap(\"liveblocks_config\").set(\"hasContentSet\", true);\n editor.current.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent]);\n\n useReportTextEditor(textEditorType, options.field ?? DEFAULT_OPTIONS.field);\n\n const prevThreadsRef = useRef<Set<string> | undefined>(undefined);\n\n useEffect(() => {\n if (!isEditorReady) return;\n\n if (!editor.current) return;\n\n const newThreads = options.threads_experimental\n ? new Set(options.threads_experimental.map((t) => t.id))\n : undefined;\n\n const hasFilteredThreadsChanged = !areSetsEqual(\n prevThreadsRef.current,\n newThreads\n );\n\n if (hasFilteredThreadsChanged) {\n prevThreadsRef.current = newThreads;\n }\n\n if (hasFilteredThreadsChanged) {\n editor.current.view.dispatch(\n editor.current.state.tr.setMeta(FILTERED_THREADS_PLUGIN_KEY, {\n filteredThreads: options.threads_experimental\n ? new Set(options.threads_experimental.map((t) => t.id))\n : undefined,\n })\n );\n }\n }, [isEditorReady, options.threads_experimental]);\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n editor.current = this.editor;\n if (this.editor.options.content) {\n console.warn(\n \"[Liveblocks] Initial content must be set in the useLiveblocksExtension hook option. Remove content from your editor options.\"\n );\n }\n if (\n options.mentions &&\n this.editor.extensionManager.extensions.find(\n (e) => e.name.toLowerCase() === \"mention\"\n )\n ) {\n console.warn(\n \"[Liveblocks] Liveblocks own mention plugin is enabled, using another mention plugin may cause a conflict.\"\n );\n }\n const self = room.getSelf();\n const updateUser = ({\n info,\n id: userId,\n }: User<JsonObject, BaseUserMeta>) => {\n if (!info) {\n return;\n }\n const { user: storedUser } =\n this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n if (this.storage.permanentUserData) {\n const pud = this.storage.permanentUserData.clients.get(\n this.storage.doc.clientID\n );\n // Only update if there is no entry or if the entry is different\n if (!pud || pud !== userId) {\n this.storage.permanentUserData.setUserMapping(\n this.storage.doc,\n this.storage.doc.clientID,\n userId ?? \"Unknown\" // TODO: change this to the user's ID so we can map it to the user's name\n );\n }\n }\n if (\n info.name !== storedUser?.name ||\n info.color !== storedUser?.color\n ) {\n this.editor.commands.updateUser({\n name: info.name,\n color: info.color,\n });\n }\n };\n // if we already have user info, we update the user\n if (self?.info) {\n updateUser(self);\n }\n // we also listen in case the user info changes\n this.storage.unsubs.push(room.events.self.subscribe(updateUser));\n if (options.comments) {\n const commentMarkType = getMarkType(\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n this.editor.schema\n );\n this.storage.unsubs.push(\n // Subscribe to threads so we can update comment marks if they become resolved/deleted\n store.outputs.threads.subscribe(() => {\n const threadMap = new Map(\n store.outputs.threads\n .get()\n .findMany(roomId, { resolved: false }, \"asc\", undefined)\n .map((thread) => [thread.id, true])\n );\n function isComment(mark: PMMark): mark is PMMark & {\n attrs: { orphan: boolean; threadId: string };\n } {\n return mark.type.name === LIVEBLOCKS_COMMENT_MARK_TYPE;\n }\n // when threads change, find marks and update them if needed\n this.editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (isComment(mark)) {\n const markThreadId = mark.attrs.threadId;\n const isOrphan = !threadMap.has(markThreadId);\n if (isOrphan !== mark.attrs.orphan) {\n const { tr } = this.editor.state;\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n this.editor.state.doc.content.size - 1\n );\n tr.removeMark(trimmedFrom, trimmedTo, mark);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n commentMarkType.create({\n ...mark.attrs,\n orphan: isOrphan,\n })\n );\n this.editor.view.dispatch(tr);\n }\n }\n });\n });\n })\n );\n }\n },\n onDestroy() {\n this.storage.unsubs.forEach((unsub) => unsub());\n },\n addGlobalAttributes() {\n return [\n {\n types: [\"paragraph\", \"heading\"],\n attributes: {\n ychange: { default: null },\n },\n },\n ];\n },\n addStorage() {\n const provider = getYjsProviderForRoom(room, {\n enablePermanentUserData:\n !!options.ai || options.enablePermanentUserData,\n offlineSupport_experimental: options.offlineSupport_experimental,\n });\n return {\n doc: provider.getYDoc(),\n provider,\n permanentUserData: provider.permanentUserData,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n YChangeMark,\n LiveblocksCollab.configure({\n ySyncOptions: {\n permanentUserData: this.storage.permanentUserData,\n },\n document: this.storage.doc,\n field: options.field,\n }),\n CollaborationCursor.configure({\n provider: this.storage.provider,\n }),\n ];\n\n if (options.comments) {\n extensions.push(CommentsExtension);\n }\n if (options.mentions) {\n extensions.push(\n MentionExtension.configure({\n onCreateMention: (mention) => {\n createTextMention(mention.notificationId, mention);\n },\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveContextualPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveContextualPromptArgs): Promise<ResolveContextualPromptResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n // This response is validated afterwards by AiExtension itself\n return JSON.parse(result) as ResolveContextualPromptResponse;\n };\n\n extensions.push(\n AiExtension.configure({\n resolveContextualPrompt,\n ...(typeof options.ai === \"boolean\" ? {} : options.ai),\n doc: this.storage.doc,\n pud: this.storage.permanentUserData,\n })\n );\n }\n\n return extensions;\n },\n });\n};\n"],"names":["useYjsProvider","useCallback","useSyncExternalStore","Mark","useInitial","TextEditorType","useRef","useRoom","useClient","getUmbrellaStoreForClient","useEffect","useReportTextEditor","areSetsEqual","FILTERED_THREADS_PLUGIN_KEY","useCreateTextMention","useDeleteTextMention","Extension","getMarkType","LIVEBLOCKS_COMMENT_MARK_TYPE","getYjsProviderForRoom","CommentsExtension","MentionExtension","kInternal","AiExtension"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { useInitial } from '@liveblocks/react-ui/_private';
|
|
|
5
5
|
import { getYjsProviderForRoom } from '@liveblocks/yjs';
|
|
6
6
|
import { Mark, Extension, getMarkType } from '@tiptap/core';
|
|
7
7
|
import Collaboration from '@tiptap/extension-collaboration';
|
|
8
|
-
import CollaborationCursor from '@tiptap/extension-collaboration-
|
|
8
|
+
import CollaborationCursor from '@tiptap/extension-collaboration-cursor';
|
|
9
9
|
import { useCallback, useSyncExternalStore, useRef, useEffect } from 'react';
|
|
10
10
|
import { AiExtension } from './ai/AiExtension.js';
|
|
11
11
|
import { areSetsEqual, FILTERED_THREADS_PLUGIN_KEY, CommentsExtension } from './comments/CommentsExtension.js';
|
|
@@ -39,9 +39,9 @@ const LiveblocksCollab = Collaboration.extend({
|
|
|
39
39
|
"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension."
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
|
-
if (this.editor.extensionManager.extensions.find((e) => e.name === "
|
|
42
|
+
if (this.editor.extensionManager.extensions.find((e) => e.name === "history")) {
|
|
43
43
|
console.warn(
|
|
44
|
-
"[Liveblocks] The
|
|
44
|
+
"[Liveblocks] The history extension is enabled, Liveblocks extension provides its own. Please remove or disable the History plugin to prevent unwanted conflicts."
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -291,7 +291,6 @@ const useLiveblocksExtension = (opts) => {
|
|
|
291
291
|
document: this.storage.doc,
|
|
292
292
|
field: options.field
|
|
293
293
|
}),
|
|
294
|
-
// I don't really think this is needed...
|
|
295
294
|
CollaborationCursor.configure({
|
|
296
295
|
provider: this.storage.provider
|
|
297
296
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveblocksExtension.js","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n IUserInfo,\n JsonObject,\n User,\n} from \"@liveblocks/core\";\nimport { kInternal, TextEditorType } from \"@liveblocks/core\";\nimport { useClient, useRoom } from \"@liveblocks/react\";\nimport {\n getUmbrellaStoreForClient,\n useCreateTextMention,\n useDeleteTextMention,\n useReportTextEditor,\n useYjsProvider,\n} from \"@liveblocks/react/_private\";\nimport { useInitial } from \"@liveblocks/react-ui/_private\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport { getYjsProviderForRoom } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType, Mark } from \"@tiptap/core\";\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor, {\n type CollaborationCaretOptions,\n} from \"@tiptap/extension-collaboration-caret\";\nimport type { Mark as PMMark } from \"@tiptap/pm/model\";\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport {\n areSetsEqual,\n CommentsExtension,\n FILTERED_THREADS_PLUGIN_KEY,\n} from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveContextualPromptArgs,\n ResolveContextualPromptResponse,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: false,\n enablePermanentUserData: false,\n};\n\nconst LiveblocksCollab = Collaboration.extend({\n // Override the onCreate method to warn users about potential misconfigurations\n onCreate() {\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"doc\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap document extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n !this.editor.extensionManager.extensions.find(\n (e) => e.name === \"paragraph\"\n )\n ) {\n console.warn(\n \"[Liveblocks] The tiptap paragraph extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"text\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n this.editor.extensionManager.extensions.find((e) => e.name === \"undoRedo\")\n ) {\n console.warn(\n \"[Liveblocks] The undoRedo extension is enabled, Liveblocks extension provides its own. Please remove or disable the undoRedo extension to prevent conflicts.\"\n );\n }\n },\n});\n\n/**\n * Returns whether the editor has loaded the initial text contents from the\n * server and is ready to be used.\n *\n */\nexport function useIsEditorReady(): boolean {\n const yjsProvider = useYjsProvider();\n\n const getSnapshot = useCallback(() => {\n const status = yjsProvider?.getStatus();\n return status === \"synchronizing\" || status === \"synchronized\";\n }, [yjsProvider]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n if (yjsProvider === undefined) return () => {};\n yjsProvider.on(\"status\", callback);\n return () => {\n yjsProvider.off(\"status\", callback);\n };\n },\n [yjsProvider]\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nconst YChangeMark = Mark.create({\n name: \"ychange\",\n inclusive: false,\n parseHTML() {\n return [{ tag: \"ychange\" }];\n },\n addAttributes() {\n return {\n user: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_user\") ?? null,\n renderHTML: (attributes: { user: string | null }) => {\n if (!attributes.user) {\n return {};\n }\n return { \"data-ychange-user\": attributes.user };\n },\n },\n type: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_type\") ?? null,\n renderHTML: (attributes: { type: string | null }) => {\n if (!attributes.type) {\n return {};\n }\n return {\n \"data-ychange-type\": attributes.type,\n \"data-liveblocks\": \"\",\n class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`,\n };\n },\n },\n color: {\n default: null,\n parseHTML: (element) => {\n return element.getAttribute(\"ychange_color\") ?? null;\n },\n renderHTML: () => {\n // attributes: { color: { light: string; dark: string } | null }\n return {}; // we don't need this color attribute for now\n },\n },\n };\n },\n renderHTML({ HTMLAttributes }) {\n return [\"ychange\", HTMLAttributes, 0];\n },\n});\n\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const textEditorType = useInitial<TextEditorType>(\n options.textEditorType ?? TextEditorType.TipTap\n );\n const editor = useRef<Editor | null>(null);\n const room = useRoom();\n\n // TODO: we don't need these things if comments isn't turned on...\n // TODO: we don't have a reference to the editor here, need to figure this out\n // useErrorListener((error) => {\n // // If thread creation fails, we remove the thread id from the associated nodes and unwrap the nodes if they are no longer associated with any threads\n // if (\n // error.context.type === \"CREATE_THREAD_ERROR\" &&\n // error.context.roomId === room.id\n // ) {\n // handleThreadDelete(error.context.threadId);\n // }\n // });\n\n const isEditorReady = useIsEditorReady();\n const client = useClient();\n const store = getUmbrellaStoreForClient(client);\n const roomId = room.id;\n const yjsProvider = useYjsProvider();\n\n // If the user provided initialContent, wait for ready and then set it\n useEffect(() => {\n if (\n !isEditorReady ||\n !yjsProvider ||\n !options.initialContent ||\n !editor.current\n )\n return;\n\n // As noted in the tiptap documentation, you may not set initial content with collaboration.\n // The docs provide the following workaround:\n const ydoc = (yjsProvider as LiveblocksYjsProvider).getYDoc();\n const hasContentSet = ydoc.getMap(\"liveblocks_config\").get(\"hasContentSet\");\n if (!hasContentSet) {\n ydoc.getMap(\"liveblocks_config\").set(\"hasContentSet\", true);\n editor.current.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent]);\n\n useReportTextEditor(textEditorType, options.field ?? DEFAULT_OPTIONS.field);\n\n const prevThreadsRef = useRef<Set<string> | undefined>(undefined);\n\n useEffect(() => {\n if (!isEditorReady) return;\n\n if (!editor.current) return;\n\n const newThreads = options.threads_experimental\n ? new Set(options.threads_experimental.map((t) => t.id))\n : undefined;\n\n const hasFilteredThreadsChanged = !areSetsEqual(\n prevThreadsRef.current,\n newThreads\n );\n\n if (hasFilteredThreadsChanged) {\n prevThreadsRef.current = newThreads;\n }\n\n if (hasFilteredThreadsChanged) {\n editor.current.view.dispatch(\n editor.current.state.tr.setMeta(FILTERED_THREADS_PLUGIN_KEY, {\n filteredThreads: options.threads_experimental\n ? new Set(options.threads_experimental.map((t) => t.id))\n : undefined,\n })\n );\n }\n }, [isEditorReady, options.threads_experimental]);\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n // Tiptap has options default as any, in tiptap2, we could use never, but now we must use any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Extension.create<any, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n editor.current = this.editor;\n if (this.editor.options.content) {\n console.warn(\n \"[Liveblocks] Initial content must be set in the useLiveblocksExtension hook option. Remove content from your editor options.\"\n );\n }\n if (\n options.mentions &&\n this.editor.extensionManager.extensions.find(\n (e) => e.name.toLowerCase() === \"mention\"\n )\n ) {\n console.warn(\n \"[Liveblocks] Liveblocks own mention plugin is enabled, using another mention plugin may cause a conflict.\"\n );\n }\n const self = room.getSelf();\n const updateUser = ({\n info,\n id: userId,\n }: User<JsonObject, BaseUserMeta>) => {\n if (!info) {\n return;\n }\n const { user: storedUser } =\n this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n if (this.storage.permanentUserData) {\n const pud = this.storage.permanentUserData.clients.get(\n this.storage.doc.clientID\n );\n // Only update if there is no entry or if the entry is different\n if (!pud || pud !== userId) {\n this.storage.permanentUserData.setUserMapping(\n this.storage.doc,\n this.storage.doc.clientID,\n userId ?? \"Unknown\" // TODO: change this to the user's ID so we can map it to the user's name\n );\n }\n }\n if (\n info.name !== storedUser?.name ||\n info.color !== storedUser?.color\n ) {\n this.editor.commands.updateUser({\n name: info.name,\n color: info.color,\n });\n }\n };\n // if we already have user info, we update the user\n if (self?.info) {\n updateUser(self);\n }\n // we also listen in case the user info changes\n this.storage.unsubs.push(room.events.self.subscribe(updateUser));\n if (options.comments) {\n const commentMarkType = getMarkType(\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n this.editor.schema\n );\n this.storage.unsubs.push(\n // Subscribe to threads so we can update comment marks if they become resolved/deleted\n store.outputs.threads.subscribe(() => {\n const threadMap = new Map(\n store.outputs.threads\n .get()\n .findMany(roomId, { resolved: false }, \"asc\", undefined)\n .map((thread) => [thread.id, true])\n );\n function isComment(mark: PMMark): mark is PMMark & {\n attrs: { orphan: boolean; threadId: string };\n } {\n return mark.type.name === LIVEBLOCKS_COMMENT_MARK_TYPE;\n }\n // when threads change, find marks and update them if needed\n this.editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (isComment(mark)) {\n const markThreadId = mark.attrs.threadId;\n const isOrphan = !threadMap.has(markThreadId);\n if (isOrphan !== mark.attrs.orphan) {\n const { tr } = this.editor.state;\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n this.editor.state.doc.content.size - 1\n );\n tr.removeMark(trimmedFrom, trimmedTo, mark);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n commentMarkType.create({\n ...mark.attrs,\n orphan: isOrphan,\n })\n );\n this.editor.view.dispatch(tr);\n }\n }\n });\n });\n })\n );\n }\n },\n onDestroy() {\n this.storage.unsubs.forEach((unsub) => unsub());\n },\n addGlobalAttributes() {\n return [\n {\n types: [\"paragraph\", \"heading\"],\n attributes: {\n ychange: { default: null },\n },\n },\n ];\n },\n addStorage() {\n const provider = getYjsProviderForRoom(room, {\n enablePermanentUserData:\n !!options.ai || options.enablePermanentUserData,\n offlineSupport_experimental: options.offlineSupport_experimental,\n });\n return {\n doc: provider.getYDoc(),\n provider,\n permanentUserData: provider.permanentUserData,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n YChangeMark,\n\n LiveblocksCollab.configure({\n ySyncOptions: {\n permanentUserData: this.storage.permanentUserData,\n },\n document: this.storage.doc,\n field: options.field,\n }), // I don't really think this is needed...\n CollaborationCursor.configure({\n provider: this.storage.provider,\n }) as Extension<CollaborationCaretOptions>,\n ];\n\n if (options.comments) {\n extensions.push(CommentsExtension);\n }\n if (options.mentions) {\n extensions.push(\n MentionExtension.configure({\n onCreateMention: (mention) => {\n createTextMention(mention.notificationId, mention);\n },\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveContextualPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveContextualPromptArgs): Promise<ResolveContextualPromptResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n // This response is validated afterwards by AiExtension itself\n return JSON.parse(result) as ResolveContextualPromptResponse;\n };\n\n extensions.push(\n AiExtension.configure({\n resolveContextualPrompt,\n ...(typeof options.ai === \"boolean\" ? {} : options.ai),\n doc: this.storage.doc,\n pud: this.storage.permanentUserData,\n })\n );\n }\n\n return extensions;\n },\n });\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LiveblocksExtension.js","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n IUserInfo,\n JsonObject,\n User,\n} from \"@liveblocks/core\";\nimport { kInternal, TextEditorType } from \"@liveblocks/core\";\nimport { useClient, useRoom } from \"@liveblocks/react\";\nimport {\n getUmbrellaStoreForClient,\n useCreateTextMention,\n useDeleteTextMention,\n useReportTextEditor,\n useYjsProvider,\n} from \"@liveblocks/react/_private\";\nimport { useInitial } from \"@liveblocks/react-ui/_private\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport { getYjsProviderForRoom } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType, Mark } from \"@tiptap/core\";\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor from \"@tiptap/extension-collaboration-cursor\";\nimport type { Mark as PMMark } from \"@tiptap/pm/model\";\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport {\n areSetsEqual,\n CommentsExtension,\n FILTERED_THREADS_PLUGIN_KEY,\n} from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveContextualPromptArgs,\n ResolveContextualPromptResponse,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: false,\n enablePermanentUserData: false,\n};\n\nconst LiveblocksCollab = Collaboration.extend({\n // Override the onCreate method to warn users about potential misconfigurations\n onCreate() {\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"doc\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap document extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n !this.editor.extensionManager.extensions.find(\n (e) => e.name === \"paragraph\"\n )\n ) {\n console.warn(\n \"[Liveblocks] The tiptap paragraph extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"text\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n this.editor.extensionManager.extensions.find((e) => e.name === \"history\")\n ) {\n console.warn(\n \"[Liveblocks] The history extension is enabled, Liveblocks extension provides its own. Please remove or disable the History plugin to prevent unwanted conflicts.\"\n );\n }\n },\n});\n\n/**\n * Returns whether the editor has loaded the initial text contents from the\n * server and is ready to be used.\n *\n */\nexport function useIsEditorReady(): boolean {\n const yjsProvider = useYjsProvider();\n\n const getSnapshot = useCallback(() => {\n const status = yjsProvider?.getStatus();\n return status === \"synchronizing\" || status === \"synchronized\";\n }, [yjsProvider]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n if (yjsProvider === undefined) return () => {};\n yjsProvider.on(\"status\", callback);\n return () => {\n yjsProvider.off(\"status\", callback);\n };\n },\n [yjsProvider]\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nconst YChangeMark = Mark.create({\n name: \"ychange\",\n inclusive: false,\n parseHTML() {\n return [{ tag: \"ychange\" }];\n },\n addAttributes() {\n return {\n user: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_user\") ?? null,\n renderHTML: (attributes: { user: string | null }) => {\n if (!attributes.user) {\n return {};\n }\n return { \"data-ychange-user\": attributes.user };\n },\n },\n type: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_type\") ?? null,\n renderHTML: (attributes: { type: string | null }) => {\n if (!attributes.type) {\n return {};\n }\n return {\n \"data-ychange-type\": attributes.type,\n \"data-liveblocks\": \"\",\n class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`,\n };\n },\n },\n color: {\n default: null,\n parseHTML: (element) => {\n return element.getAttribute(\"ychange_color\") ?? null;\n },\n renderHTML: () => {\n // attributes: { color: { light: string; dark: string } | null }\n return {}; // we don't need this color attribute for now\n },\n },\n };\n },\n renderHTML({ HTMLAttributes }) {\n return [\"ychange\", HTMLAttributes, 0];\n },\n});\n\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const textEditorType = useInitial<TextEditorType>(\n options.textEditorType ?? TextEditorType.TipTap\n );\n const editor = useRef<Editor | null>(null);\n const room = useRoom();\n\n // TODO: we don't need these things if comments isn't turned on...\n // TODO: we don't have a reference to the editor here, need to figure this out\n // useErrorListener((error) => {\n // // If thread creation fails, we remove the thread id from the associated nodes and unwrap the nodes if they are no longer associated with any threads\n // if (\n // error.context.type === \"CREATE_THREAD_ERROR\" &&\n // error.context.roomId === room.id\n // ) {\n // handleThreadDelete(error.context.threadId);\n // }\n // });\n\n const isEditorReady = useIsEditorReady();\n const client = useClient();\n const store = getUmbrellaStoreForClient(client);\n const roomId = room.id;\n const yjsProvider = useYjsProvider();\n\n // If the user provided initialContent, wait for ready and then set it\n useEffect(() => {\n if (\n !isEditorReady ||\n !yjsProvider ||\n !options.initialContent ||\n !editor.current\n )\n return;\n\n // As noted in the tiptap documentation, you may not set initial content with collaboration.\n // The docs provide the following workaround:\n const ydoc = (yjsProvider as LiveblocksYjsProvider).getYDoc();\n const hasContentSet = ydoc.getMap(\"liveblocks_config\").get(\"hasContentSet\");\n if (!hasContentSet) {\n ydoc.getMap(\"liveblocks_config\").set(\"hasContentSet\", true);\n editor.current.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent]);\n\n useReportTextEditor(textEditorType, options.field ?? DEFAULT_OPTIONS.field);\n\n const prevThreadsRef = useRef<Set<string> | undefined>(undefined);\n\n useEffect(() => {\n if (!isEditorReady) return;\n\n if (!editor.current) return;\n\n const newThreads = options.threads_experimental\n ? new Set(options.threads_experimental.map((t) => t.id))\n : undefined;\n\n const hasFilteredThreadsChanged = !areSetsEqual(\n prevThreadsRef.current,\n newThreads\n );\n\n if (hasFilteredThreadsChanged) {\n prevThreadsRef.current = newThreads;\n }\n\n if (hasFilteredThreadsChanged) {\n editor.current.view.dispatch(\n editor.current.state.tr.setMeta(FILTERED_THREADS_PLUGIN_KEY, {\n filteredThreads: options.threads_experimental\n ? new Set(options.threads_experimental.map((t) => t.id))\n : undefined,\n })\n );\n }\n }, [isEditorReady, options.threads_experimental]);\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n editor.current = this.editor;\n if (this.editor.options.content) {\n console.warn(\n \"[Liveblocks] Initial content must be set in the useLiveblocksExtension hook option. Remove content from your editor options.\"\n );\n }\n if (\n options.mentions &&\n this.editor.extensionManager.extensions.find(\n (e) => e.name.toLowerCase() === \"mention\"\n )\n ) {\n console.warn(\n \"[Liveblocks] Liveblocks own mention plugin is enabled, using another mention plugin may cause a conflict.\"\n );\n }\n const self = room.getSelf();\n const updateUser = ({\n info,\n id: userId,\n }: User<JsonObject, BaseUserMeta>) => {\n if (!info) {\n return;\n }\n const { user: storedUser } =\n this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n if (this.storage.permanentUserData) {\n const pud = this.storage.permanentUserData.clients.get(\n this.storage.doc.clientID\n );\n // Only update if there is no entry or if the entry is different\n if (!pud || pud !== userId) {\n this.storage.permanentUserData.setUserMapping(\n this.storage.doc,\n this.storage.doc.clientID,\n userId ?? \"Unknown\" // TODO: change this to the user's ID so we can map it to the user's name\n );\n }\n }\n if (\n info.name !== storedUser?.name ||\n info.color !== storedUser?.color\n ) {\n this.editor.commands.updateUser({\n name: info.name,\n color: info.color,\n });\n }\n };\n // if we already have user info, we update the user\n if (self?.info) {\n updateUser(self);\n }\n // we also listen in case the user info changes\n this.storage.unsubs.push(room.events.self.subscribe(updateUser));\n if (options.comments) {\n const commentMarkType = getMarkType(\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n this.editor.schema\n );\n this.storage.unsubs.push(\n // Subscribe to threads so we can update comment marks if they become resolved/deleted\n store.outputs.threads.subscribe(() => {\n const threadMap = new Map(\n store.outputs.threads\n .get()\n .findMany(roomId, { resolved: false }, \"asc\", undefined)\n .map((thread) => [thread.id, true])\n );\n function isComment(mark: PMMark): mark is PMMark & {\n attrs: { orphan: boolean; threadId: string };\n } {\n return mark.type.name === LIVEBLOCKS_COMMENT_MARK_TYPE;\n }\n // when threads change, find marks and update them if needed\n this.editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (isComment(mark)) {\n const markThreadId = mark.attrs.threadId;\n const isOrphan = !threadMap.has(markThreadId);\n if (isOrphan !== mark.attrs.orphan) {\n const { tr } = this.editor.state;\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n this.editor.state.doc.content.size - 1\n );\n tr.removeMark(trimmedFrom, trimmedTo, mark);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n commentMarkType.create({\n ...mark.attrs,\n orphan: isOrphan,\n })\n );\n this.editor.view.dispatch(tr);\n }\n }\n });\n });\n })\n );\n }\n },\n onDestroy() {\n this.storage.unsubs.forEach((unsub) => unsub());\n },\n addGlobalAttributes() {\n return [\n {\n types: [\"paragraph\", \"heading\"],\n attributes: {\n ychange: { default: null },\n },\n },\n ];\n },\n addStorage() {\n const provider = getYjsProviderForRoom(room, {\n enablePermanentUserData:\n !!options.ai || options.enablePermanentUserData,\n offlineSupport_experimental: options.offlineSupport_experimental,\n });\n return {\n doc: provider.getYDoc(),\n provider,\n permanentUserData: provider.permanentUserData,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n YChangeMark,\n LiveblocksCollab.configure({\n ySyncOptions: {\n permanentUserData: this.storage.permanentUserData,\n },\n document: this.storage.doc,\n field: options.field,\n }),\n CollaborationCursor.configure({\n provider: this.storage.provider,\n }),\n ];\n\n if (options.comments) {\n extensions.push(CommentsExtension);\n }\n if (options.mentions) {\n extensions.push(\n MentionExtension.configure({\n onCreateMention: (mention) => {\n createTextMention(mention.notificationId, mention);\n },\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveContextualPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveContextualPromptArgs): Promise<ResolveContextualPromptResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n // This response is validated afterwards by AiExtension itself\n return JSON.parse(result) as ResolveContextualPromptResponse;\n };\n\n extensions.push(\n AiExtension.configure({\n resolveContextualPrompt,\n ...(typeof options.ai === \"boolean\" ? {} : options.ai),\n doc: this.storage.doc,\n pud: this.storage.permanentUserData,\n })\n );\n }\n\n return extensions;\n },\n });\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiExtension.cjs","sources":["../../src/ai/AiExtension.ts"],"sourcesContent":["import {\n autoRetry,\n type ContextualPromptResponse,\n HttpError,\n} from \"@liveblocks/core\";\nimport type { CommandProps, Editor } from \"@tiptap/core\";\nimport { Extension } from \"@tiptap/core\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { Transaction } from \"@tiptap/pm/state\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport {\n ySyncPluginKey,\n yXmlFragmentToProseMirrorFragment,\n} from \"y-prosemirror\";\nimport type { Doc, Snapshot } from \"yjs\";\nimport {\n createDocFromSnapshot,\n emptySnapshot,\n equalSnapshots,\n snapshot as takeSnapshot,\n} from \"yjs\";\n\nimport {\n AI_TOOLBAR_SELECTION_PLUGIN,\n type AiCommands,\n type AiExtensionOptions,\n type AiExtensionStorage,\n type AiToolbarState,\n type ResolveContextualPromptResponse,\n type YSyncPluginState,\n} from \"../types\";\nimport { getContextualPromptContext } from \"../utils\";\n\nconst DEFAULT_AI_NAME = \"AI\";\nexport const DEFAULT_STATE: AiToolbarState = { phase: \"closed\" };\n\nconst RESOLVE_AI_PROMPT_RETRY_ATTEMPTS = 3;\nconst RESOLVE_AI_PROMPT_RETRY_DELAYS = [1000, 2000, 4000];\n\nfunction getYjsBinding(editor: Editor) {\n return (ySyncPluginKey.getState(editor.view.state) as YSyncPluginState)\n .binding;\n}\n\nfunction getLiveblocksYjsProvider(editor: Editor) {\n return editor.extensionStorage.liveblocksExtension?.provider;\n}\n\nexport function isContextualPromptDiffResponse(\n response: ContextualPromptResponse\n): response is Extract<\n ContextualPromptResponse,\n { type: \"replace\" | \"insert\" }\n> {\n return response.type === \"replace\" || response.type === \"insert\";\n}\n\nfunction isResolveContextualPromptResponse(\n response: unknown\n): response is ResolveContextualPromptResponse {\n return (\n typeof response === \"object\" &&\n response !== null &&\n typeof (response as { text: unknown }).text === \"string\" &&\n typeof (response as { type: unknown }).type === \"string\" &&\n [\"insert\", \"replace\", \"other\"].includes((response as { type: string }).type)\n );\n}\n\nfunction createParagraph(editor: Editor, text: string) {\n const paragraph =\n editor.schema.nodes.paragraph ??\n Object.values(editor.schema.nodes).find((node) => node.isBlock);\n\n if (!paragraph) {\n throw new Error(\"Could not create a paragraph.\");\n }\n\n return paragraph.create(null, text ? editor.schema.text(text) : undefined);\n}\n\nfunction getRevertTransaction(\n tr: Transaction,\n editor: Editor,\n storage: AiExtensionStorage,\n doc?: Doc\n): Transaction | null {\n if (storage.snapshot) {\n const binding = getYjsBinding(editor);\n\n if (binding) {\n binding.mapping.clear();\n\n const docFromSnapshot = createDocFromSnapshot(\n binding.doc,\n storage.snapshot\n );\n const type = docFromSnapshot.getXmlFragment(\"default\"); // TODO: field\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n type,\n editor.state.schema\n );\n\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n if (doc) {\n doc.gc = true;\n }\n\n storage.snapshot = undefined;\n\n return tr;\n }\n }\n return null;\n}\n\nexport const AiExtension = Extension.create<\n AiExtensionOptions,\n AiExtensionStorage\n>({\n name: \"liveblocksAi\",\n addOptions() {\n return {\n doc: undefined,\n pud: undefined,\n\n // The actual default resolver is set in LiveblocksExtension via AiExtension.configure()\n resolveContextualPrompt: () => Promise.reject(),\n name: DEFAULT_AI_NAME,\n };\n },\n addStorage() {\n return {\n state: DEFAULT_STATE,\n name: this.options.name,\n };\n },\n addCommands() {\n return {\n askAi: (prompt) => () => {\n if (typeof prompt === \"string\") {\n (\n this.editor.commands as unknown as AiCommands\n ).$startAiToolbarThinking(prompt);\n } else {\n (\n this.editor.commands as unknown as AiCommands\n ).$openAiToolbarAsking();\n }\n\n return true;\n },\n\n closeAi: () => () => {\n (this.editor.commands as unknown as AiCommands).$closeAiToolbar();\n\n return true;\n },\n\n $acceptAiToolbarResponse:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"reviewing\" phase, do nothing\n if (currentState.phase !== \"reviewing\") {\n return false;\n }\n\n // 2. Accept the response\n if (isContextualPromptDiffResponse(currentState.response)) {\n // 2.a. If the response is a diff, apply it definitely\n const binding = getYjsBinding(this.editor);\n if (!binding) {\n return false;\n }\n\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n binding.type,\n this.editor.state.schema\n );\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n this.editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n this.storage.snapshot = undefined;\n } else {\n // 2.b. If the response is not a diff, insert it below the selection\n\n const paragraphs = currentState.response.text\n .split(\"\\n\")\n .map((paragraph) => createParagraph(this.editor, paragraph));\n\n tr.insert(this.editor.state.selection.$to.end(), paragraphs);\n tr.setMeta(\"addToHistory\", true);\n view.dispatch(tr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 4. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $closeAiToolbar:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If already in \"closed\" phase, do nothing\n if (currentState.phase === \"closed\") {\n return false;\n }\n\n // 2. If in \"thinking\" phase, cancel the current AI request\n if (currentState.phase === \"thinking\") {\n currentState.abortController.abort();\n }\n\n // 3. If in \"thinking\" or \"reviewing\" phase, revert the editor if possible and unblock it\n if (\n currentState.phase === \"thinking\" ||\n currentState.phase === \"reviewing\"\n ) {\n // Get the revert transaction and dispatch it\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n view.dispatch(revertTr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n }\n\n // 4. Restore the initial selection\n this.editor.commands.setTextSelection(currentState.initialSelection);\n\n // 5. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 6. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $openAiToolbarAsking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"closed\" phase, do nothing\n if (currentState.phase !== \"closed\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n // 3. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n // Store the initial selection\n initialSelection: {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty\n customPrompt: \"\",\n };\n\n return true;\n },\n\n $startAiToolbarThinking:\n (prompt: string, withPreviousResponse?: boolean) =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If in \"thinking\" phase already, do nothing\n if (currentState.phase === \"thinking\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n const abortController = new AbortController();\n const provider = getLiveblocksYjsProvider(this.editor);\n\n // 3. If this is a retry or a refinement, revert the editor and restore the initial selection\n if (currentState.phase === \"reviewing\") {\n // 3.a. Revert the editor\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n // Important: in this scenario we do not unpause the provider\n view.dispatch(revertTr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3.b. Restore the initial selection\n this.editor.commands.setTextSelection(\n currentState.initialSelection\n );\n }\n\n // 4. Set to \"thinking\" phase\n this.storage.state = {\n phase: \"thinking\",\n // Store the initial selection if the toolbar is opened directly in the \"thinking\" phase\n initialSelection: currentState.initialSelection ?? {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty if the toolbar is opened directly in the \"thinking\" phase\n customPrompt: currentState.customPrompt ?? \"\",\n prompt,\n abortController,\n previousResponse: currentState.response,\n };\n\n // 5. Block the editor\n this.editor.setEditable(false);\n\n // 6. Start the AI request\n autoRetry(\n async () => {\n await provider?.pause();\n\n // 6.a. Resolve the AI prompt\n const response = (await this.options.resolveContextualPrompt({\n prompt,\n context: getContextualPromptContext(this.editor, 3_000),\n signal: abortController.signal,\n previous:\n withPreviousResponse && currentState.phase === \"reviewing\"\n ? {\n prompt: currentState.prompt,\n response: {\n type: currentState.response?.type,\n text: currentState.response?.text,\n },\n }\n : undefined,\n })) as unknown;\n\n // 6.b. Validate the response\n if (isResolveContextualPromptResponse(response)) {\n return response;\n } else {\n throw new Error(\"Failed to resolve AI prompt.\");\n }\n },\n RESOLVE_AI_PROMPT_RETRY_ATTEMPTS,\n RESOLVE_AI_PROMPT_RETRY_DELAYS,\n\n (error) => {\n // Don't retry on 4xx errors or if the request was aborted\n return (\n abortController.signal.aborted ||\n (error instanceof HttpError &&\n error.status >= 400 &&\n error.status < 500)\n );\n }\n )\n .then((response) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.a. If the AI request succeeds, set to \"reviewing\" phase with the response\n (\n this.editor.commands as unknown as AiCommands\n )._handleAiToolbarThinkingSuccess({\n type: response.type,\n text: response.text,\n });\n })\n .catch((error) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.b. If the AI request fails, set to \"asking\" phase with error\n (\n this.editor.commands as unknown as AiCommands\n )._handleAiToolbarThinkingError(error);\n });\n\n return true;\n },\n\n $cancelAiToolbarThinking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Cancel the current AI request\n currentState.abortController.abort();\n\n // 3. Unblock the editor\n this.editor.setEditable(true);\n\n // 4. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n };\n\n return true;\n },\n\n _showAiToolbarReviewingDiff: () => () => {\n // The diff is applied right before moving to the \"reviewing\" phase\n if (this.storage.state.phase !== \"reviewing\") {\n return false;\n }\n\n if (!this.options.doc || !this.storage.snapshot) {\n return false;\n }\n\n const previousSnapshot: Snapshot =\n this.storage.snapshot ?? emptySnapshot;\n const currentSnapshot = takeSnapshot(this.options.doc);\n\n if (equalSnapshots(previousSnapshot, currentSnapshot)) {\n return true;\n }\n\n getYjsBinding(this.editor)?.renderSnapshot(\n currentSnapshot,\n previousSnapshot\n );\n\n return true;\n },\n\n _handleAiToolbarThinkingSuccess:\n (response: ContextualPromptResponse) =>\n ({ view, tr }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. If this is not a diff, the response will just be in the toolbar, set to \"reviewing\" phase directly with the response\n if (!isContextualPromptDiffResponse(response)) {\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n return true;\n }\n\n if (!this.options.doc) {\n return false;\n }\n\n // 3. Otherwise, the response is a diff, apply it to the editor\n this.options.doc.gc = false;\n this.storage.snapshot = takeSnapshot(this.options.doc);\n\n // 4. Set to \"reviewing\" phase with the new range\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n // 5. Insert the response's text as inline first (and replace the selection if it's a replace) then as block if there are multiple paragraphs\n const [firstParagraph, ...otherParagraphs] =\n response.text.split(\"\\n\");\n\n tr.insertText(\n firstParagraph,\n response.type === \"insert\"\n ? this.editor.state.selection.to\n : this.editor.state.selection.from,\n this.editor.state.selection.to\n );\n\n if (otherParagraphs.length > 0) {\n const paragraphs = otherParagraphs.map((paragraph) =>\n createParagraph(this.editor, paragraph)\n );\n\n tr.insert(tr.selection.$to.pos, paragraphs);\n }\n\n view.dispatch(tr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n\n // 6. Show the diff\n (\n this.editor.commands as unknown as AiCommands\n )._showAiToolbarReviewingDiff();\n\n // We moved to the \"reviewing\" phase, so even if `_showAiToolbarReviewingDiff`\n // returns `false` somehow, we still want to return `true`\n return true;\n },\n\n _handleAiToolbarThinkingError: (error: unknown) => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Unblock the editor\n this.editor.setEditable(true);\n\n // 3. Log the error\n console.error(error);\n\n // 4. Set to \"asking\" phase with error\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n // Pass the error so it can be displayed\n error:\n error instanceof Error\n ? error\n : new Error(String(error), { cause: error }),\n };\n\n return true;\n },\n\n _updateAiToolbarCustomPrompt:\n (customPrompt: string | ((currentCustomPrompt: string) => string)) =>\n () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in a phase with a custom prompt, do nothing\n if (typeof currentState.customPrompt !== \"string\") {\n return false;\n }\n\n // 2. Update the custom prompt\n this.storage.state.customPrompt =\n typeof customPrompt === \"function\"\n ? customPrompt(currentState.customPrompt)\n : customPrompt;\n\n return true;\n },\n };\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: AI_TOOLBAR_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n // Don't show the AI toolbar selection if the toolbar is closed or when reviewing diff responses\n if (\n this.storage.state.phase === \"closed\" ||\n (this.storage.state.phase === \"reviewing\" &&\n isContextualPromptDiffResponse(this.storage.state.response))\n ) {\n return DecorationSet.create(doc, []);\n }\n\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n ];\n },\n});\n"],"names":["ySyncPluginKey","createDocFromSnapshot","yXmlFragmentToProseMirrorFragment","Slice","Fragment","Extension","autoRetry","getContextualPromptContext","HttpError","emptySnapshot","takeSnapshot","equalSnapshots","Plugin","AI_TOOLBAR_SELECTION_PLUGIN","DecorationSet","Decoration"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AiExtension.cjs","sources":["../../src/ai/AiExtension.ts"],"sourcesContent":["import {\n autoRetry,\n type ContextualPromptResponse,\n HttpError,\n} from \"@liveblocks/core\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { CommandProps, Editor } from \"@tiptap/core\";\nimport { Extension } from \"@tiptap/core\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { Transaction } from \"@tiptap/pm/state\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport {\n ySyncPluginKey,\n yXmlFragmentToProseMirrorFragment,\n} from \"y-prosemirror\";\nimport type { Doc, Snapshot } from \"yjs\";\nimport {\n createDocFromSnapshot,\n emptySnapshot,\n equalSnapshots,\n snapshot as takeSnapshot,\n} from \"yjs\";\n\nimport {\n AI_TOOLBAR_SELECTION_PLUGIN,\n type AiCommands,\n type AiExtensionOptions,\n type AiExtensionStorage,\n type AiToolbarState,\n type LiveblocksExtensionStorage,\n type ResolveContextualPromptResponse,\n type YSyncPluginState,\n} from \"../types\";\nimport { getContextualPromptContext } from \"../utils\";\n\nconst DEFAULT_AI_NAME = \"AI\";\nexport const DEFAULT_STATE: AiToolbarState = { phase: \"closed\" };\n\nconst RESOLVE_AI_PROMPT_RETRY_ATTEMPTS = 3;\nconst RESOLVE_AI_PROMPT_RETRY_DELAYS = [1000, 2000, 4000];\n\nfunction getYjsBinding(editor: Editor) {\n return (ySyncPluginKey.getState(editor.view.state) as YSyncPluginState)\n .binding;\n}\n\nfunction getLiveblocksYjsProvider(editor: Editor) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n return (\n editor.extensionStorage.liveblocksExtension as\n | LiveblocksExtensionStorage\n | undefined\n )?.provider as LiveblocksYjsProvider | undefined;\n}\n\nexport function isContextualPromptDiffResponse(\n response: ContextualPromptResponse\n): response is Extract<\n ContextualPromptResponse,\n { type: \"replace\" | \"insert\" }\n> {\n return response.type === \"replace\" || response.type === \"insert\";\n}\n\nfunction isResolveContextualPromptResponse(\n response: unknown\n): response is ResolveContextualPromptResponse {\n return (\n typeof response === \"object\" &&\n response !== null &&\n typeof (response as { text: unknown }).text === \"string\" &&\n typeof (response as { type: unknown }).type === \"string\" &&\n [\"insert\", \"replace\", \"other\"].includes((response as { type: string }).type)\n );\n}\n\nfunction createParagraph(editor: Editor, text: string) {\n const paragraph =\n editor.schema.nodes.paragraph ??\n Object.values(editor.schema.nodes).find((node) => node.isBlock);\n\n if (!paragraph) {\n throw new Error(\"Could not create a paragraph.\");\n }\n\n return paragraph.create(null, text ? editor.schema.text(text) : undefined);\n}\n\nfunction getRevertTransaction(\n tr: Transaction,\n editor: Editor,\n storage: AiExtensionStorage,\n doc?: Doc\n): Transaction | null {\n if (storage.snapshot) {\n const binding = getYjsBinding(editor);\n\n if (binding) {\n binding.mapping.clear();\n\n const docFromSnapshot = createDocFromSnapshot(\n binding.doc,\n storage.snapshot\n );\n const type = docFromSnapshot.getXmlFragment(\"default\"); // TODO: field\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n type,\n editor.state.schema\n );\n\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n if (doc) {\n doc.gc = true;\n }\n\n storage.snapshot = undefined;\n\n return tr;\n }\n }\n return null;\n}\n\nexport const AiExtension = Extension.create<\n AiExtensionOptions,\n AiExtensionStorage\n>({\n name: \"liveblocksAi\",\n addOptions() {\n return {\n doc: undefined,\n pud: undefined,\n\n // The actual default resolver is set in LiveblocksExtension via AiExtension.configure()\n resolveContextualPrompt: () => Promise.reject(),\n name: DEFAULT_AI_NAME,\n };\n },\n addStorage() {\n return {\n state: DEFAULT_STATE,\n name: this.options.name,\n };\n },\n addCommands() {\n return {\n askAi: (prompt) => () => {\n if (typeof prompt === \"string\") {\n (\n this.editor.commands as unknown as AiCommands\n ).$startAiToolbarThinking(prompt);\n } else {\n (\n this.editor.commands as unknown as AiCommands\n ).$openAiToolbarAsking();\n }\n\n return true;\n },\n\n closeAi: () => () => {\n (this.editor.commands as unknown as AiCommands).$closeAiToolbar();\n\n return true;\n },\n\n $acceptAiToolbarResponse:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"reviewing\" phase, do nothing\n if (currentState.phase !== \"reviewing\") {\n return false;\n }\n\n // 2. Accept the response\n if (isContextualPromptDiffResponse(currentState.response)) {\n // 2.a. If the response is a diff, apply it definitely\n const binding = getYjsBinding(this.editor);\n if (!binding) {\n return false;\n }\n\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n binding.type,\n this.editor.state.schema\n );\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n this.editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n this.storage.snapshot = undefined;\n } else {\n // 2.b. If the response is not a diff, insert it below the selection\n\n const paragraphs = currentState.response.text\n .split(\"\\n\")\n .map((paragraph) => createParagraph(this.editor, paragraph));\n\n tr.insert(this.editor.state.selection.$to.end(), paragraphs);\n tr.setMeta(\"addToHistory\", true);\n view.dispatch(tr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 4. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $closeAiToolbar:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If already in \"closed\" phase, do nothing\n if (currentState.phase === \"closed\") {\n return false;\n }\n\n // 2. If in \"thinking\" phase, cancel the current AI request\n if (currentState.phase === \"thinking\") {\n currentState.abortController.abort();\n }\n\n // 3. If in \"thinking\" or \"reviewing\" phase, revert the editor if possible and unblock it\n if (\n currentState.phase === \"thinking\" ||\n currentState.phase === \"reviewing\"\n ) {\n // Get the revert transaction and dispatch it\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n view.dispatch(revertTr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n }\n\n // 4. Restore the initial selection\n this.editor.commands.setTextSelection(currentState.initialSelection);\n\n // 5. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 6. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $openAiToolbarAsking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"closed\" phase, do nothing\n if (currentState.phase !== \"closed\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n // 3. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n // Store the initial selection\n initialSelection: {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty\n customPrompt: \"\",\n };\n\n return true;\n },\n\n $startAiToolbarThinking:\n (prompt: string, withPreviousResponse?: boolean) =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If in \"thinking\" phase already, do nothing\n if (currentState.phase === \"thinking\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n const abortController = new AbortController();\n const provider = getLiveblocksYjsProvider(this.editor);\n\n // 3. If this is a retry or a refinement, revert the editor and restore the initial selection\n if (currentState.phase === \"reviewing\") {\n // 3.a. Revert the editor\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n // Important: in this scenario we do not unpause the provider\n view.dispatch(revertTr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3.b. Restore the initial selection\n this.editor.commands.setTextSelection(\n currentState.initialSelection\n );\n }\n\n // 4. Set to \"thinking\" phase\n this.storage.state = {\n phase: \"thinking\",\n // Store the initial selection if the toolbar is opened directly in the \"thinking\" phase\n initialSelection: currentState.initialSelection ?? {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty if the toolbar is opened directly in the \"thinking\" phase\n customPrompt: currentState.customPrompt ?? \"\",\n prompt,\n abortController,\n previousResponse: currentState.response,\n };\n\n // 5. Block the editor\n this.editor.setEditable(false);\n\n // 6. Start the AI request\n autoRetry(\n async () => {\n await provider?.pause();\n\n // 6.a. Resolve the AI prompt\n const response = (await this.options.resolveContextualPrompt({\n prompt,\n context: getContextualPromptContext(this.editor, 3_000),\n signal: abortController.signal,\n previous:\n withPreviousResponse && currentState.phase === \"reviewing\"\n ? {\n prompt: currentState.prompt,\n response: {\n type: currentState.response?.type,\n text: currentState.response?.text,\n },\n }\n : undefined,\n })) as unknown;\n\n // 6.b. Validate the response\n if (isResolveContextualPromptResponse(response)) {\n return response;\n } else {\n throw new Error(\"Failed to resolve AI prompt.\");\n }\n },\n RESOLVE_AI_PROMPT_RETRY_ATTEMPTS,\n RESOLVE_AI_PROMPT_RETRY_DELAYS,\n\n (error) => {\n // Don't retry on 4xx errors or if the request was aborted\n return (\n abortController.signal.aborted ||\n (error instanceof HttpError &&\n error.status >= 400 &&\n error.status < 500)\n );\n }\n )\n .then((response) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.a. If the AI request succeeds, set to \"reviewing\" phase with the response\n (\n this.editor.commands as unknown as AiCommands\n )._handleAiToolbarThinkingSuccess({\n type: response.type,\n text: response.text,\n });\n })\n .catch((error) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.b. If the AI request fails, set to \"asking\" phase with error\n (\n this.editor.commands as unknown as AiCommands\n )._handleAiToolbarThinkingError(error);\n });\n\n return true;\n },\n\n $cancelAiToolbarThinking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Cancel the current AI request\n currentState.abortController.abort();\n\n // 3. Unblock the editor\n this.editor.setEditable(true);\n\n // 4. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n };\n\n return true;\n },\n\n _showAiToolbarReviewingDiff: () => () => {\n // The diff is applied right before moving to the \"reviewing\" phase\n if (this.storage.state.phase !== \"reviewing\") {\n return false;\n }\n\n if (!this.options.doc || !this.storage.snapshot) {\n return false;\n }\n\n const previousSnapshot: Snapshot =\n this.storage.snapshot ?? emptySnapshot;\n const currentSnapshot = takeSnapshot(this.options.doc);\n\n if (equalSnapshots(previousSnapshot, currentSnapshot)) {\n return true;\n }\n\n getYjsBinding(this.editor)?.renderSnapshot(\n currentSnapshot,\n previousSnapshot\n );\n\n return true;\n },\n\n _handleAiToolbarThinkingSuccess:\n (response: ContextualPromptResponse) =>\n ({ view, tr }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. If this is not a diff, the response will just be in the toolbar, set to \"reviewing\" phase directly with the response\n if (!isContextualPromptDiffResponse(response)) {\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n return true;\n }\n\n if (!this.options.doc) {\n return false;\n }\n\n // 3. Otherwise, the response is a diff, apply it to the editor\n this.options.doc.gc = false;\n this.storage.snapshot = takeSnapshot(this.options.doc);\n\n // 4. Set to \"reviewing\" phase with the new range\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n // 5. Insert the response's text as inline first (and replace the selection if it's a replace) then as block if there are multiple paragraphs\n const [firstParagraph, ...otherParagraphs] =\n response.text.split(\"\\n\");\n\n tr.insertText(\n firstParagraph,\n response.type === \"insert\"\n ? this.editor.state.selection.to\n : this.editor.state.selection.from,\n this.editor.state.selection.to\n );\n\n if (otherParagraphs.length > 0) {\n const paragraphs = otherParagraphs.map((paragraph) =>\n createParagraph(this.editor, paragraph)\n );\n\n tr.insert(tr.selection.$to.pos, paragraphs);\n }\n\n view.dispatch(tr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n\n // 6. Show the diff\n (\n this.editor.commands as unknown as AiCommands\n )._showAiToolbarReviewingDiff();\n\n // We moved to the \"reviewing\" phase, so even if `_showAiToolbarReviewingDiff`\n // returns `false` somehow, we still want to return `true`\n return true;\n },\n\n _handleAiToolbarThinkingError: (error: unknown) => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Unblock the editor\n this.editor.setEditable(true);\n\n // 3. Log the error\n console.error(error);\n\n // 4. Set to \"asking\" phase with error\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n // Pass the error so it can be displayed\n error:\n error instanceof Error\n ? error\n : new Error(String(error), { cause: error }),\n };\n\n return true;\n },\n\n _updateAiToolbarCustomPrompt:\n (customPrompt: string | ((currentCustomPrompt: string) => string)) =>\n () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in a phase with a custom prompt, do nothing\n if (typeof currentState.customPrompt !== \"string\") {\n return false;\n }\n\n // 2. Update the custom prompt\n this.storage.state.customPrompt =\n typeof customPrompt === \"function\"\n ? customPrompt(currentState.customPrompt)\n : customPrompt;\n\n return true;\n },\n };\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: AI_TOOLBAR_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n // Don't show the AI toolbar selection if the toolbar is closed or when reviewing diff responses\n if (\n this.storage.state.phase === \"closed\" ||\n (this.storage.state.phase === \"reviewing\" &&\n isContextualPromptDiffResponse(this.storage.state.response))\n ) {\n return DecorationSet.create(doc, []);\n }\n\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n ];\n },\n});\n"],"names":["ySyncPluginKey","createDocFromSnapshot","yXmlFragmentToProseMirrorFragment","Slice","Fragment","Extension","autoRetry","getContextualPromptContext","HttpError","emptySnapshot","takeSnapshot","equalSnapshots","Plugin","AI_TOOLBAR_SELECTION_PLUGIN","DecorationSet","Decoration"],"mappings":"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"}
|