@liveblocks/react-tiptap 2.16.1-ai3 → 2.16.1-ai5

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.
@@ -286,7 +286,7 @@ const useLiveblocksExtension = (opts) => {
286
286
  );
287
287
  }
288
288
  if (options.ai) {
289
- const resolveAiPrompt = async ({
289
+ const resolveContextualPrompt = async ({
290
290
  prompt,
291
291
  context,
292
292
  previous,
@@ -298,16 +298,11 @@ const useLiveblocksExtension = (opts) => {
298
298
  previous,
299
299
  signal
300
300
  });
301
- const parsedResponse = JSON.parse(result);
302
- const type = typeof parsedResponse.type === "string" ? parsedResponse.type : "";
303
- if (typeof parsedResponse.content === "string" && ["insert", "replace", "other"].includes(type)) {
304
- return parsedResponse;
305
- }
306
- throw new Error("Failed to resolve AI prompt");
301
+ return JSON.parse(result);
307
302
  };
308
303
  extensions.push(
309
304
  AiExtension.AiExtension.configure({
310
- resolveAiPrompt,
305
+ resolveContextualPrompt,
311
306
  ...typeof options.ai === "boolean" ? {} : options.ai,
312
307
  doc: this.storage.doc,
313
308
  pud: this.storage.permanentUserData
@@ -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 { LiveblocksYjsProvider } 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, useState, useSyncExternalStore } from \"react\";\nimport { Doc, PermanentUserData } from \"yjs\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport { CommentsExtension } from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n AiResponse,\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveAiPromptArgs,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<any, any, any, any, any>\n>();\n\nconst docMap = new Map<string, Doc>();\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst pudMap = new Map<string, PermanentUserData>();\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: 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 [editor, setEditor] = useState<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 (!isEditorReady || !yjsProvider || !options.initialContent || !editor)\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.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent, editor]);\n\n useReportTextEditor(\n TextEditorType.TipTap,\n options.field ?? DEFAULT_OPTIONS.field\n );\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n setEditor(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 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 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\")\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, commentMarkType);\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 if (!providersMap.has(room.id)) {\n const doc = new Doc();\n docMap.set(room.id, doc);\n pudMap.set(room.id, new PermanentUserData(doc));\n providersMap.set(\n room.id,\n new LiveblocksYjsProvider(room, doc, {\n offlineSupport_experimental: options.offlineSupport_experimental,\n })\n );\n }\n return {\n doc: docMap.get(room.id)!,\n provider: providersMap.get(room.id)!,\n permanentUserData: pudMap.get(room.id)!,\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: createTextMention,\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveAiPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveAiPromptArgs): Promise<AiResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n const parsedResponse = JSON.parse(result) as JsonObject;\n const type =\n typeof parsedResponse.type === \"string\" ? parsedResponse.type : \"\";\n if (\n typeof parsedResponse.content === \"string\" &&\n [\"insert\", \"replace\", \"other\"].includes(type)\n ) {\n return parsedResponse as AiResponse;\n }\n\n throw new Error(\"Failed to resolve AI prompt\");\n };\n extensions.push(\n AiExtension.configure({\n resolveAiPrompt,\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","useState","useRoom","useClient","getUmbrellaStoreForClient","useEffect","useReportTextEditor","TextEditorType","useCreateTextMention","useDeleteTextMention","Extension","getMarkType","LIVEBLOCKS_COMMENT_MARK_TYPE","Doc","PermanentUserData","LiveblocksYjsProvider","CommentsExtension","MentionExtension","kInternal","AiExtension"],"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 { LiveblocksYjsProvider } 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, useState, useSyncExternalStore } from \"react\";\nimport { Doc, PermanentUserData } from \"yjs\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport { CommentsExtension } 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\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<any, any, any, any, any>\n>();\n\nconst docMap = new Map<string, Doc>();\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst pudMap = new Map<string, PermanentUserData>();\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: 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 [editor, setEditor] = useState<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 (!isEditorReady || !yjsProvider || !options.initialContent || !editor)\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.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent, editor]);\n\n useReportTextEditor(\n TextEditorType.TipTap,\n options.field ?? DEFAULT_OPTIONS.field\n );\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n setEditor(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 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 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\")\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, commentMarkType);\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 if (!providersMap.has(room.id)) {\n const doc = new Doc();\n docMap.set(room.id, doc);\n pudMap.set(room.id, new PermanentUserData(doc));\n providersMap.set(\n room.id,\n new LiveblocksYjsProvider(room, doc, {\n offlineSupport_experimental: options.offlineSupport_experimental,\n })\n );\n }\n return {\n doc: docMap.get(room.id)!,\n provider: providersMap.get(room.id)!,\n permanentUserData: pudMap.get(room.id)!,\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: createTextMention,\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","useState","useRoom","useClient","getUmbrellaStoreForClient","useEffect","useReportTextEditor","TextEditorType","useCreateTextMention","useDeleteTextMention","Extension","getMarkType","LIVEBLOCKS_COMMENT_MARK_TYPE","Doc","PermanentUserData","LiveblocksYjsProvider","CommentsExtension","MentionExtension","kInternal","AiExtension"],"mappings":";;;;;;;;;;;;;;;;AAmCA,MAAM,YAAA,uBAAmB,GAGvB,EAAA,CAAA;AAEF,MAAM,MAAA,uBAAa,GAAiB,EAAA,CAAA;AAIpC,MAAM,MAAA,uBAAa,GAA+B,EAAA,CAAA;AAElD,MAAM,eAAqE,GAAA;AAAA,EACzE,KAAO,EAAA,SAAA;AAAA,EACP,QAAU,EAAA,IAAA;AAAA,EACV,QAAU,EAAA,IAAA;AAAA,EACV,2BAA6B,EAAA,KAAA;AAC/B,CAAA,CAAA;AAEA,MAAM,gBAAA,GAAmB,cAAc,MAAO,CAAA;AAAA,EAE5C,QAAW,GAAA;AACT,IACE,IAAA,CAAC,IAAK,CAAA,MAAA,CAAO,gBAAiB,CAAA,UAAA,CAAW,IAAK,CAAA,CAAC,CAAM,KAAA,CAAA,CAAE,IAAS,KAAA,KAAK,CACrE,EAAA;AACA,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,wIAAA;AAAA,OACF,CAAA;AAAA,KACF;AACA,IAAA,IACE,CAAC,IAAA,CAAK,MAAO,CAAA,gBAAA,CAAiB,UAAW,CAAA,IAAA;AAAA,MACvC,CAAC,CAAM,KAAA,CAAA,CAAE,IAAS,KAAA,WAAA;AAAA,KAEpB,EAAA;AACA,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,yIAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IACE,IAAA,CAAC,IAAK,CAAA,MAAA,CAAO,gBAAiB,CAAA,UAAA,CAAW,IAAK,CAAA,CAAC,CAAM,KAAA,CAAA,CAAE,IAAS,KAAA,MAAM,CACtE,EAAA;AACA,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,oIAAA;AAAA,OACF,CAAA;AAAA,KACF;AACA,IACE,IAAA,IAAA,CAAK,MAAO,CAAA,gBAAA,CAAiB,UAAW,CAAA,IAAA,CAAK,CAAC,CAAM,KAAA,CAAA,CAAE,IAAS,KAAA,SAAS,CACxE,EAAA;AACA,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,kKAAA;AAAA,OACF,CAAA;AAAA,KACF;AAAA,GACF;AACF,CAAC,CAAA,CAAA;AAOM,SAAS,gBAA4B,GAAA;AAC1C,EAAA,MAAM,cAAcA,uBAAe,EAAA,CAAA;AAEnC,EAAM,MAAA,WAAA,GAAcC,kBAAY,MAAM;AACpC,IAAM,MAAA,MAAA,GAAS,aAAa,SAAU,EAAA,CAAA;AACtC,IAAO,OAAA,MAAA,KAAW,mBAAmB,MAAW,KAAA,cAAA,CAAA;AAAA,GAClD,EAAG,CAAC,WAAW,CAAC,CAAA,CAAA;AAEhB,EAAA,MAAM,SAAY,GAAAA,iBAAA;AAAA,IAChB,CAAC,QAAyB,KAAA;AACxB,MAAA,IAAI,WAAgB,KAAA,KAAA,CAAA;AAAW,QAAA,OAAO,MAAM;AAAA,SAAC,CAAA;AAC7C,MAAY,WAAA,CAAA,EAAA,CAAG,UAAU,QAAQ,CAAA,CAAA;AACjC,MAAA,OAAO,MAAM;AACX,QAAY,WAAA,CAAA,GAAA,CAAI,UAAU,QAAQ,CAAA,CAAA;AAAA,OACpC,CAAA;AAAA,KACF;AAAA,IACA,CAAC,WAAW,CAAA;AAAA,GACd,CAAA;AAEA,EAAO,OAAAC,0BAAA,CAAqB,SAAW,EAAA,WAAA,EAAa,WAAW,CAAA,CAAA;AACjE,CAAA;AAEA,MAAM,WAAA,GAAcC,UAAK,MAAO,CAAA;AAAA,EAC9B,IAAM,EAAA,SAAA;AAAA,EACN,SAAW,EAAA,KAAA;AAAA,EACX,SAAY,GAAA;AACV,IAAA,OAAO,CAAC,EAAE,GAAK,EAAA,SAAA,EAAW,CAAA,CAAA;AAAA,GAC5B;AAAA,EACA,aAAgB,GAAA;AACd,IAAO,OAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,OAAS,EAAA,IAAA;AAAA,QACT,WAAW,CAAC,OAAA,KAAY,OAAQ,CAAA,YAAA,CAAa,cAAc,CAAK,IAAA,IAAA;AAAA,QAChE,UAAA,EAAY,CAAC,UAAwC,KAAA;AACnD,UAAI,IAAA,CAAC,WAAW,IAAM,EAAA;AACpB,YAAA,OAAO,EAAC,CAAA;AAAA,WACV;AACA,UAAO,OAAA,EAAE,mBAAqB,EAAA,UAAA,CAAW,IAAK,EAAA,CAAA;AAAA,SAChD;AAAA,OACF;AAAA,MACA,IAAM,EAAA;AAAA,QACJ,OAAS,EAAA,IAAA;AAAA,QACT,WAAW,CAAC,OAAA,KAAY,OAAQ,CAAA,YAAA,CAAa,cAAc,CAAK,IAAA,IAAA;AAAA,QAChE,UAAA,EAAY,CAAC,UAAwC,KAAA;AACnD,UAAI,IAAA,CAAC,WAAW,IAAM,EAAA;AACpB,YAAA,OAAO,EAAC,CAAA;AAAA,WACV;AACA,UAAO,OAAA;AAAA,YACL,qBAAqB,UAAW,CAAA,IAAA;AAAA,YAChC,iBAAmB,EAAA,EAAA;AAAA,YACnB,KAAA,EAAO,6CAA6C,UAAW,CAAA,IAAA,CAAA,CAAA;AAAA,WACjE,CAAA;AAAA,SACF;AAAA,OACF;AAAA,MACA,KAAO,EAAA;AAAA,QACL,OAAS,EAAA,IAAA;AAAA,QACT,SAAA,EAAW,CAAC,OAAY,KAAA;AACtB,UAAO,OAAA,OAAA,CAAQ,YAAa,CAAA,eAAe,CAAK,IAAA,IAAA,CAAA;AAAA,SAClD;AAAA,QACA,YAAY,MAAM;AAEhB,UAAA,OAAO,EAAC,CAAA;AAAA,SACV;AAAA,OACF;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EACA,UAAA,CAAW,EAAE,cAAA,EAAkB,EAAA;AAC7B,IAAO,OAAA,CAAC,SAAW,EAAA,cAAA,EAAgB,CAAC,CAAA,CAAA;AAAA,GACtC;AACF,CAAC,CAAA,CAAA;AAEY,MAAA,sBAAA,GAAyB,CACpC,IACc,KAAA;AACd,EAAA,MAAM,OAAU,GAAA;AAAA,IACd,GAAG,eAAA;AAAA,IACH,GAAG,IAAA;AAAA,GACL,CAAA;AACA,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIC,eAAwB,IAAI,CAAA,CAAA;AACxD,EAAA,MAAM,OAAOC,eAAQ,EAAA,CAAA;AAcrB,EAAA,MAAM,gBAAgB,gBAAiB,EAAA,CAAA;AACvC,EAAA,MAAM,SAASC,iBAAU,EAAA,CAAA;AACzB,EAAM,MAAA,KAAA,GAAQC,mCAA0B,MAAM,CAAA,CAAA;AAC9C,EAAA,MAAM,SAAS,IAAK,CAAA,EAAA,CAAA;AACpB,EAAA,MAAM,cAAcP,uBAAe,EAAA,CAAA;AAGnC,EAAAQ,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,aAAiB,IAAA,CAAC,eAAe,CAAC,OAAA,CAAQ,kBAAkB,CAAC,MAAA;AAChE,MAAA,OAAA;AAIF,IAAM,MAAA,IAAA,GAAQ,YAAsC,OAAQ,EAAA,CAAA;AAC5D,IAAA,MAAM,gBAAgB,IAAK,CAAA,MAAA,CAAO,mBAAmB,CAAA,CAAE,IAAI,eAAe,CAAA,CAAA;AAC1E,IAAA,IAAI,CAAC,aAAe,EAAA;AAClB,MAAA,IAAA,CAAK,MAAO,CAAA,mBAAmB,CAAE,CAAA,GAAA,CAAI,iBAAiB,IAAI,CAAA,CAAA;AAC1D,MAAO,MAAA,CAAA,QAAA,CAAS,UAAW,CAAA,OAAA,CAAQ,cAAc,CAAA,CAAA;AAAA,KACnD;AAAA,KACC,CAAC,aAAA,EAAe,aAAa,OAAQ,CAAA,cAAA,EAAgB,MAAM,CAAC,CAAA,CAAA;AAE/D,EAAAC,4BAAA;AAAA,IACEC,qBAAe,CAAA,MAAA;AAAA,IACf,OAAA,CAAQ,SAAS,eAAgB,CAAA,KAAA;AAAA,GACnC,CAAA;AAEA,EAAA,MAAM,oBAAoBC,6BAAqB,EAAA,CAAA;AAC/C,EAAA,MAAM,oBAAoBC,6BAAqB,EAAA,CAAA;AAE/C,EAAA,OAAOC,eAAU,MAA0C,CAAA;AAAA,IACzD,IAAM,EAAA,qBAAA;AAAA,IAEN,QAAW,GAAA;AACT,MAAA,SAAA,CAAU,KAAK,MAAM,CAAA,CAAA;AACrB,MAAI,IAAA,IAAA,CAAK,MAAO,CAAA,OAAA,CAAQ,OAAS,EAAA;AAC/B,QAAQ,OAAA,CAAA,IAAA;AAAA,UACN,8HAAA;AAAA,SACF,CAAA;AAAA,OACF;AACA,MAAA,IACE,OAAQ,CAAA,QAAA,IACR,IAAK,CAAA,MAAA,CAAO,iBAAiB,UAAW,CAAA,IAAA;AAAA,QACtC,CAAC,CAAA,KAAM,CAAE,CAAA,IAAA,CAAK,aAAkB,KAAA,SAAA;AAAA,OAElC,EAAA;AACA,QAAQ,OAAA,CAAA,IAAA;AAAA,UACN,2GAAA;AAAA,SACF,CAAA;AAAA,OACF;AACA,MAAM,MAAA,IAAA,GAAO,KAAK,OAAQ,EAAA,CAAA;AAC1B,MAAA,MAAM,aAAa,CAAC;AAAA,QAClB,IAAA;AAAA,QACA,EAAI,EAAA,MAAA;AAAA,OACgC,KAAA;AACpC,QAAA,IAAI,CAAC,IAAM,EAAA;AACT,UAAA,OAAA;AAAA,SACF;AACA,QAAM,MAAA,EAAE,MAAM,UAAW,EAAA,GACvB,KAAK,OAAQ,CAAA,QAAA,CAAS,UAAU,aAAc,EAAA,CAAA;AAGhD,QAAA,IAAA,CAAK,QAAQ,iBAAmB,EAAA,cAAA;AAAA,UAC9B,KAAK,OAAQ,CAAA,GAAA;AAAA,UACb,IAAA,CAAK,QAAQ,GAAI,CAAA,QAAA;AAAA,UACjB,MAAU,IAAA,SAAA;AAAA,SACZ,CAAA;AACA,QAAA,IACE,KAAK,IAAS,KAAA,UAAA,EAAY,QAC1B,IAAK,CAAA,KAAA,KAAU,YAAY,KAC3B,EAAA;AACA,UAAK,IAAA,CAAA,MAAA,CAAO,SAAS,UAAW,CAAA;AAAA,YAC9B,MAAM,IAAK,CAAA,IAAA;AAAA,YACX,OAAO,IAAK,CAAA,KAAA;AAAA,WACb,CAAA,CAAA;AAAA,SACH;AAAA,OACF,CAAA;AAEA,MAAA,IAAI,MAAM,IAAM,EAAA;AACd,QAAA,UAAA,CAAW,IAAI,CAAA,CAAA;AAAA,OACjB;AAEA,MAAK,IAAA,CAAA,OAAA,CAAQ,OAAO,IAAK,CAAA,IAAA,CAAK,OAAO,IAAK,CAAA,SAAA,CAAU,UAAU,CAAC,CAAA,CAAA;AAC/D,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAA,MAAM,eAAkB,GAAAC,gBAAA;AAAA,UACtBC,kCAAA;AAAA,UACA,KAAK,MAAO,CAAA,MAAA;AAAA,SACd,CAAA;AACA,QAAA,IAAA,CAAK,QAAQ,MAAO,CAAA,IAAA;AAAA,UAElB,KAAM,CAAA,OAAA,CAAQ,OAAQ,CAAA,SAAA,CAAU,MAAM;AACpC,YAAA,MAAM,YAAY,IAAI,GAAA;AAAA,cACpB,KAAA,CAAM,QAAQ,OACX,CAAA,GAAA,GACA,QAAS,CAAA,MAAA,EAAQ,EAAE,QAAU,EAAA,KAAA,IAAS,KAAK,CAAA,CAC3C,IAAI,CAAC,MAAA,KAAW,CAAC,MAAO,CAAA,EAAA,EAAI,IAAI,CAAC,CAAA;AAAA,aACtC,CAAA;AACA,YAAA,SAAS,UAAU,IAEjB,EAAA;AACA,cAAO,OAAA,IAAA,CAAK,KAAK,IAAS,KAAAA,kCAAA,CAAA;AAAA,aAC5B;AAEA,YAAA,IAAA,CAAK,OAAO,KAAM,CAAA,GAAA,CAAI,WAAY,CAAA,CAAC,MAAM,GAAQ,KAAA;AAC/C,cAAK,IAAA,CAAA,KAAA,CAAM,OAAQ,CAAA,CAAC,IAAS,KAAA;AAC3B,gBAAI,IAAA,SAAA,CAAU,IAAI,CAAG,EAAA;AACnB,kBAAM,MAAA,YAAA,GAAe,KAAK,KAAM,CAAA,QAAA,CAAA;AAChC,kBAAA,MAAM,QAAW,GAAA,CAAC,SAAU,CAAA,GAAA,CAAI,YAAY,CAAA,CAAA;AAC5C,kBAAI,IAAA,QAAA,KAAa,IAAK,CAAA,KAAA,CAAM,MAAQ,EAAA;AAClC,oBAAA,MAAM,EAAE,EAAA,EAAO,GAAA,IAAA,CAAK,MAAO,CAAA,KAAA,CAAA;AAC3B,oBAAA,MAAM,WAAc,GAAA,IAAA,CAAK,GAAI,CAAA,GAAA,EAAK,CAAC,CAAA,CAAA;AACnC,oBAAA,MAAM,YAAY,IAAK,CAAA,GAAA;AAAA,sBACrB,MAAM,IAAK,CAAA,QAAA;AAAA,sBACX,IAAK,CAAA,MAAA,CAAO,KAAM,CAAA,GAAA,CAAI,QAAQ,IAAO,GAAA,CAAA;AAAA,qBACvC,CAAA;AACA,oBAAG,EAAA,CAAA,UAAA,CAAW,WAAa,EAAA,SAAA,EAAW,eAAe,CAAA,CAAA;AACrD,oBAAG,EAAA,CAAA,OAAA;AAAA,sBACD,WAAA;AAAA,sBACA,SAAA;AAAA,sBACA,gBAAgB,MAAO,CAAA;AAAA,wBACrB,GAAG,IAAK,CAAA,KAAA;AAAA,wBACR,MAAQ,EAAA,QAAA;AAAA,uBACT,CAAA;AAAA,qBACH,CAAA;AACA,oBAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,QAAA,CAAS,EAAE,CAAA,CAAA;AAAA,mBAC9B;AAAA,iBACF;AAAA,eACD,CAAA,CAAA;AAAA,aACF,CAAA,CAAA;AAAA,WACF,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AAAA,KACF;AAAA,IACA,SAAY,GAAA;AACV,MAAA,IAAA,CAAK,QAAQ,MAAO,CAAA,OAAA,CAAQ,CAAC,KAAA,KAAU,OAAO,CAAA,CAAA;AAAA,KAChD;AAAA,IACA,mBAAsB,GAAA;AACpB,MAAO,OAAA;AAAA,QACL;AAAA,UACE,KAAA,EAAO,CAAC,WAAA,EAAa,SAAS,CAAA;AAAA,UAC9B,UAAY,EAAA;AAAA,YACV,OAAA,EAAS,EAAE,OAAA,EAAS,IAAK,EAAA;AAAA,WAC3B;AAAA,SACF;AAAA,OACF,CAAA;AAAA,KACF;AAAA,IACA,UAAa,GAAA;AACX,MAAA,IAAI,CAAC,YAAA,CAAa,GAAI,CAAA,IAAA,CAAK,EAAE,CAAG,EAAA;AAC9B,QAAM,MAAA,GAAA,GAAM,IAAIC,OAAI,EAAA,CAAA;AACpB,QAAO,MAAA,CAAA,GAAA,CAAI,IAAK,CAAA,EAAA,EAAI,GAAG,CAAA,CAAA;AACvB,QAAA,MAAA,CAAO,IAAI,IAAK,CAAA,EAAA,EAAI,IAAIC,qBAAA,CAAkB,GAAG,CAAC,CAAA,CAAA;AAC9C,QAAa,YAAA,CAAA,GAAA;AAAA,UACX,IAAK,CAAA,EAAA;AAAA,UACL,IAAIC,2BAAsB,CAAA,IAAA,EAAM,GAAK,EAAA;AAAA,YACnC,6BAA6B,OAAQ,CAAA,2BAAA;AAAA,WACtC,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AACA,MAAO,OAAA;AAAA,QACL,GAAK,EAAA,MAAA,CAAO,GAAI,CAAA,IAAA,CAAK,EAAE,CAAA;AAAA,QACvB,QAAU,EAAA,YAAA,CAAa,GAAI,CAAA,IAAA,CAAK,EAAE,CAAA;AAAA,QAClC,iBAAmB,EAAA,MAAA,CAAO,GAAI,CAAA,IAAA,CAAK,EAAE,CAAA;AAAA,QACrC,QAAQ,EAAC;AAAA,OACX,CAAA;AAAA,KACF;AAAA,IACA,aAAgB,GAAA;AACd,MAAA,MAAM,UAA6B,GAAA;AAAA,QACjC,WAAA;AAAA,QACA,iBAAiB,SAAU,CAAA;AAAA,UACzB,YAAc,EAAA;AAAA,YACZ,iBAAA,EAAmB,KAAK,OAAQ,CAAA,iBAAA;AAAA,WAClC;AAAA,UACA,QAAA,EAAU,KAAK,OAAQ,CAAA,GAAA;AAAA,UACvB,OAAO,OAAQ,CAAA,KAAA;AAAA,SAChB,CAAA;AAAA,QACD,oBAAoB,SAAU,CAAA;AAAA,UAC5B,QAAA,EAAU,KAAK,OAAQ,CAAA,QAAA;AAAA,SACxB,CAAA;AAAA,OACH,CAAA;AAEA,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAA,UAAA,CAAW,KAAKC,mCAAiB,CAAA,CAAA;AAAA,OACnC;AACA,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAW,UAAA,CAAA,IAAA;AAAA,UACTC,kCAAiB,SAAU,CAAA;AAAA,YACzB,eAAiB,EAAA,iBAAA;AAAA,YACjB,eAAiB,EAAA,iBAAA;AAAA,WAClB,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AACA,MAAA,IAAI,QAAQ,EAAI,EAAA;AACd,QAAA,MAAM,0BAA0B,OAAO;AAAA,UACrC,MAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA;AAAA,UACA,MAAA;AAAA,SAC2E,KAAA;AAC3E,UAAA,MAAM,MAAS,GAAA,MAAM,IAAK,CAAAC,gBAAA,CAAA,CAAW,uBAAwB,CAAA;AAAA,YAC3D,MAAA;AAAA,YACA,OAAA;AAAA,YACA,QAAA;AAAA,YACA,MAAA;AAAA,WACD,CAAA,CAAA;AAGD,UAAO,OAAA,IAAA,CAAK,MAAM,MAAM,CAAA,CAAA;AAAA,SAC1B,CAAA;AAEA,QAAW,UAAA,CAAA,IAAA;AAAA,UACTC,wBAAY,SAAU,CAAA;AAAA,YACpB,uBAAA;AAAA,YACA,GAAI,OAAO,OAAA,CAAQ,OAAO,SAAY,GAAA,KAAK,OAAQ,CAAA,EAAA;AAAA,YACnD,GAAA,EAAK,KAAK,OAAQ,CAAA,GAAA;AAAA,YAClB,GAAA,EAAK,KAAK,OAAQ,CAAA,iBAAA;AAAA,WACnB,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AAEA,MAAO,OAAA,UAAA,CAAA;AAAA,KACT;AAAA,GACD,CAAA,CAAA;AACH;;;;;"}
@@ -284,7 +284,7 @@ const useLiveblocksExtension = (opts) => {
284
284
  );
285
285
  }
286
286
  if (options.ai) {
287
- const resolveAiPrompt = async ({
287
+ const resolveContextualPrompt = async ({
288
288
  prompt,
289
289
  context,
290
290
  previous,
@@ -296,16 +296,11 @@ const useLiveblocksExtension = (opts) => {
296
296
  previous,
297
297
  signal
298
298
  });
299
- const parsedResponse = JSON.parse(result);
300
- const type = typeof parsedResponse.type === "string" ? parsedResponse.type : "";
301
- if (typeof parsedResponse.content === "string" && ["insert", "replace", "other"].includes(type)) {
302
- return parsedResponse;
303
- }
304
- throw new Error("Failed to resolve AI prompt");
299
+ return JSON.parse(result);
305
300
  };
306
301
  extensions.push(
307
302
  AiExtension.configure({
308
- resolveAiPrompt,
303
+ resolveContextualPrompt,
309
304
  ...typeof options.ai === "boolean" ? {} : options.ai,
310
305
  doc: this.storage.doc,
311
306
  pud: this.storage.permanentUserData
@@ -1 +1 @@
1
- {"version":3,"file":"LiveblocksExtension.mjs","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 { LiveblocksYjsProvider } 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, useState, useSyncExternalStore } from \"react\";\nimport { Doc, PermanentUserData } from \"yjs\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport { CommentsExtension } from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n AiResponse,\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveAiPromptArgs,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<any, any, any, any, any>\n>();\n\nconst docMap = new Map<string, Doc>();\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst pudMap = new Map<string, PermanentUserData>();\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: 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 [editor, setEditor] = useState<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 (!isEditorReady || !yjsProvider || !options.initialContent || !editor)\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.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent, editor]);\n\n useReportTextEditor(\n TextEditorType.TipTap,\n options.field ?? DEFAULT_OPTIONS.field\n );\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n setEditor(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 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 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\")\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, commentMarkType);\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 if (!providersMap.has(room.id)) {\n const doc = new Doc();\n docMap.set(room.id, doc);\n pudMap.set(room.id, new PermanentUserData(doc));\n providersMap.set(\n room.id,\n new LiveblocksYjsProvider(room, doc, {\n offlineSupport_experimental: options.offlineSupport_experimental,\n })\n );\n }\n return {\n doc: docMap.get(room.id)!,\n provider: providersMap.get(room.id)!,\n permanentUserData: pudMap.get(room.id)!,\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: createTextMention,\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveAiPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveAiPromptArgs): Promise<AiResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n const parsedResponse = JSON.parse(result) as JsonObject;\n const type =\n typeof parsedResponse.type === \"string\" ? parsedResponse.type : \"\";\n if (\n typeof parsedResponse.content === \"string\" &&\n [\"insert\", \"replace\", \"other\"].includes(type)\n ) {\n return parsedResponse as AiResponse;\n }\n\n throw new Error(\"Failed to resolve AI prompt\");\n };\n extensions.push(\n AiExtension.configure({\n resolveAiPrompt,\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.mjs","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 { LiveblocksYjsProvider } 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, useState, useSyncExternalStore } from \"react\";\nimport { Doc, PermanentUserData } from \"yjs\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport { CommentsExtension } 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\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<any, any, any, any, any>\n>();\n\nconst docMap = new Map<string, Doc>();\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst pudMap = new Map<string, PermanentUserData>();\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: 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 [editor, setEditor] = useState<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 (!isEditorReady || !yjsProvider || !options.initialContent || !editor)\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.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent, editor]);\n\n useReportTextEditor(\n TextEditorType.TipTap,\n options.field ?? DEFAULT_OPTIONS.field\n );\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n setEditor(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 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 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\")\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, commentMarkType);\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 if (!providersMap.has(room.id)) {\n const doc = new Doc();\n docMap.set(room.id, doc);\n pudMap.set(room.id, new PermanentUserData(doc));\n providersMap.set(\n room.id,\n new LiveblocksYjsProvider(room, doc, {\n offlineSupport_experimental: options.offlineSupport_experimental,\n })\n );\n }\n return {\n doc: docMap.get(room.id)!,\n provider: providersMap.get(room.id)!,\n permanentUserData: pudMap.get(room.id)!,\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: createTextMention,\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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"}
@@ -20,8 +20,18 @@ function getYjsBinding(editor) {
20
20
  function getLiveblocksYjsProvider(editor) {
21
21
  return editor.extensionStorage.liveblocksExtension?.provider;
22
22
  }
23
- function isAiToolbarDiffOutput(output) {
24
- return output.type === "replace" || output.type === "insert";
23
+ function isContextualPromptDiffResponse(response) {
24
+ return response.type === "replace" || response.type === "insert";
25
+ }
26
+ function isResolveContextualPromptResponse(response) {
27
+ return typeof response === "object" && response !== null && typeof response.text === "string" && typeof response.type === "string" && ["insert", "replace", "other"].includes(response.type);
28
+ }
29
+ function createParagraph(editor, text) {
30
+ const paragraph = editor.schema.nodes.paragraph ?? Object.values(editor.schema.nodes).find((node) => node.isBlock);
31
+ if (!paragraph) {
32
+ throw new Error("Could not create a paragraph.");
33
+ }
34
+ return paragraph.create(null, text ? editor.schema.text(text) : void 0);
25
35
  }
26
36
  function getRevertTransaction(tr, editor, storage, doc) {
27
37
  if (storage.snapshot) {
@@ -62,7 +72,7 @@ const AiExtension = core.Extension.create({
62
72
  return {
63
73
  doc: void 0,
64
74
  pud: void 0,
65
- resolveAiPrompt: () => Promise.reject(),
75
+ resolveContextualPrompt: () => Promise.reject(),
66
76
  name: DEFAULT_AI_NAME
67
77
  };
68
78
  },
@@ -82,12 +92,12 @@ const AiExtension = core.Extension.create({
82
92
  }
83
93
  return true;
84
94
  },
85
- $acceptAiToolbarOutput: () => ({ tr, view }) => {
95
+ $acceptAiToolbarResponse: () => ({ tr, view }) => {
86
96
  const currentState = this.storage.state;
87
97
  if (currentState.phase !== "reviewing") {
88
98
  return false;
89
99
  }
90
- if (isAiToolbarDiffOutput(currentState.output)) {
100
+ if (isContextualPromptDiffResponse(currentState.response)) {
91
101
  const binding = getYjsBinding(this.editor);
92
102
  if (!binding) {
93
103
  return false;
@@ -108,17 +118,9 @@ const AiExtension = core.Extension.create({
108
118
  });
109
119
  this.storage.snapshot = void 0;
110
120
  } else {
111
- const block = this.editor.schema.nodes.paragraph || Object.values(this.editor.schema.nodes).find(
112
- (node) => node.isBlock
113
- );
114
- if (!block) {
115
- throw new Error("Could not insert a new paragraph.");
116
- }
117
- const paragraph = block.create(
118
- {},
119
- this.editor.schema.text(currentState.output.text)
120
- );
121
- tr.insert(this.editor.state.selection.$to.end() + 1, paragraph);
121
+ const paragraphs = currentState.response.text.split("\n").map((paragraph) => createParagraph(this.editor, paragraph));
122
+ tr.insert(this.editor.state.selection.$to.end(), paragraphs);
123
+ tr.setMeta("addToHistory", true);
122
124
  view.dispatch(tr);
123
125
  tr.setMeta("preventDispatch", true);
124
126
  }
@@ -171,7 +173,7 @@ const AiExtension = core.Extension.create({
171
173
  };
172
174
  return true;
173
175
  },
174
- $startAiToolbarThinking: (prompt, withPreviousOutput = false) => ({ tr, view }) => {
176
+ $startAiToolbarThinking: (prompt, withPreviousResponse) => ({ tr, view }) => {
175
177
  const currentState = this.storage.state;
176
178
  if (currentState.phase === "thinking") {
177
179
  return false;
@@ -205,38 +207,42 @@ const AiExtension = core.Extension.create({
205
207
  customPrompt: currentState.customPrompt ?? "",
206
208
  prompt,
207
209
  abortController,
208
- previousOutput: currentState.output
210
+ previousResponse: currentState.response
209
211
  };
210
212
  this.editor.setEditable(false);
211
213
  core$1.autoRetry(
212
214
  async () => {
213
215
  await provider?.pause();
214
- const context = utils.getDocumentText(this.editor, 3e3);
215
- return this.options.resolveAiPrompt({
216
+ const response = await this.options.resolveContextualPrompt({
216
217
  prompt,
217
- context,
218
+ context: utils.getContextualPromptContext(this.editor, 3e3),
218
219
  signal: abortController.signal,
219
- previous: withPreviousOutput ? {
220
- prompt: currentState.prompt ?? "",
221
- output: {
222
- type: currentState.output?.type ?? "",
223
- content: currentState.output?.text ?? ""
220
+ previous: withPreviousResponse && currentState.phase === "reviewing" ? {
221
+ prompt: currentState.prompt,
222
+ response: {
223
+ type: currentState.response?.type,
224
+ text: currentState.response?.text
224
225
  }
225
226
  } : void 0
226
227
  });
228
+ if (isResolveContextualPromptResponse(response)) {
229
+ return response;
230
+ } else {
231
+ throw new Error("Failed to resolve AI prompt.");
232
+ }
227
233
  },
228
234
  RESOLVE_AI_PROMPT_RETRY_ATTEMPTS,
229
235
  RESOLVE_AI_PROMPT_RETRY_DELAYS,
230
236
  (error) => {
231
237
  return abortController.signal.aborted || error instanceof core$1.HttpError && error.status >= 400 && error.status < 500;
232
238
  }
233
- ).then((output) => {
239
+ ).then((response) => {
234
240
  if (abortController.signal.aborted) {
235
241
  return;
236
242
  }
237
243
  this.editor.commands._handleAiToolbarThinkingSuccess({
238
- type: output.type,
239
- text: output.content
244
+ type: response.type,
245
+ text: response.text
240
246
  });
241
247
  }).catch((error) => {
242
248
  if (abortController.signal.aborted) {
@@ -260,7 +266,7 @@ const AiExtension = core.Extension.create({
260
266
  };
261
267
  return true;
262
268
  },
263
- _showAiToolbarOutputDiff: () => () => {
269
+ _showAiToolbarReviewingDiff: () => () => {
264
270
  if (this.storage.state.phase !== "reviewing") {
265
271
  return false;
266
272
  }
@@ -278,18 +284,18 @@ const AiExtension = core.Extension.create({
278
284
  );
279
285
  return true;
280
286
  },
281
- _handleAiToolbarThinkingSuccess: (output) => ({ view, tr }) => {
287
+ _handleAiToolbarThinkingSuccess: (response) => ({ view, tr }) => {
282
288
  const currentState = this.storage.state;
283
289
  if (currentState.phase !== "thinking") {
284
290
  return false;
285
291
  }
286
- if (!isAiToolbarDiffOutput(output)) {
292
+ if (!isContextualPromptDiffResponse(response)) {
287
293
  this.storage.state = {
288
294
  phase: "reviewing",
289
295
  initialSelection: currentState.initialSelection,
290
296
  customPrompt: "",
291
297
  prompt: currentState.prompt,
292
- output
298
+ response
293
299
  };
294
300
  return true;
295
301
  }
@@ -303,16 +309,23 @@ const AiExtension = core.Extension.create({
303
309
  initialSelection: currentState.initialSelection,
304
310
  customPrompt: "",
305
311
  prompt: currentState.prompt,
306
- output
312
+ response
307
313
  };
314
+ const [firstParagraph, ...otherParagraphs] = response.text.split("\n");
308
315
  tr.insertText(
309
- output.text,
310
- output.type === "insert" ? this.editor.state.selection.to : this.editor.state.selection.from,
316
+ firstParagraph,
317
+ response.type === "insert" ? this.editor.state.selection.to : this.editor.state.selection.from,
311
318
  this.editor.state.selection.to
312
319
  );
320
+ if (otherParagraphs.length > 0) {
321
+ const paragraphs = otherParagraphs.map(
322
+ (paragraph) => createParagraph(this.editor, paragraph)
323
+ );
324
+ tr.insert(tr.selection.$to.pos, paragraphs);
325
+ }
313
326
  view.dispatch(tr);
314
327
  tr.setMeta("preventDispatch", true);
315
- this.editor.commands._showAiToolbarOutputDiff();
328
+ this.editor.commands._showAiToolbarReviewingDiff();
316
329
  return true;
317
330
  },
318
331
  _handleAiToolbarThinkingError: (error) => () => {
@@ -346,7 +359,7 @@ const AiExtension = core.Extension.create({
346
359
  key: types.AI_TOOLBAR_SELECTION_PLUGIN,
347
360
  props: {
348
361
  decorations: ({ doc, selection }) => {
349
- if (this.storage.state.phase === "closed" || this.storage.state.phase === "reviewing" && isAiToolbarDiffOutput(this.storage.state.output)) {
362
+ if (this.storage.state.phase === "closed" || this.storage.state.phase === "reviewing" && isContextualPromptDiffResponse(this.storage.state.response)) {
350
363
  return view.DecorationSet.create(doc, []);
351
364
  }
352
365
  const { from, to } = selection;
@@ -365,5 +378,5 @@ const AiExtension = core.Extension.create({
365
378
 
366
379
  exports.AiExtension = AiExtension;
367
380
  exports.DEFAULT_STATE = DEFAULT_STATE;
368
- exports.isAiToolbarDiffOutput = isAiToolbarDiffOutput;
381
+ exports.isContextualPromptDiffResponse = isContextualPromptDiffResponse;
369
382
  //# sourceMappingURL=AiExtension.js.map