@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.
- package/dist/LiveblocksExtension.js +3 -8
- package/dist/LiveblocksExtension.js.map +1 -1
- package/dist/LiveblocksExtension.mjs +3 -8
- package/dist/LiveblocksExtension.mjs.map +1 -1
- package/dist/ai/AiExtension.js +52 -39
- package/dist/ai/AiExtension.js.map +1 -1
- package/dist/ai/AiExtension.mjs +53 -40
- package/dist/ai/AiExtension.mjs.map +1 -1
- package/dist/ai/AiToolbar.js +21 -20
- package/dist/ai/AiToolbar.js.map +1 -1
- package/dist/ai/AiToolbar.mjs +23 -22
- package/dist/ai/AiToolbar.mjs.map +1 -1
- package/dist/comments/FloatingComposer.js +4 -1
- package/dist/comments/FloatingComposer.js.map +1 -1
- package/dist/comments/FloatingComposer.mjs +5 -2
- package/dist/comments/FloatingComposer.mjs.map +1 -1
- package/dist/index.d.mts +38 -20
- package/dist/index.d.ts +38 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils.js +34 -24
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +33 -23
- package/dist/utils.mjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +6 -6
- package/src/styles/index.css +5 -3
- package/styles.css +1 -1
- package/styles.css.map +1 -1
|
@@ -286,7 +286,7 @@ const useLiveblocksExtension = (opts) => {
|
|
|
286
286
|
);
|
|
287
287
|
}
|
|
288
288
|
if (options.ai) {
|
|
289
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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":";;;;;;;;;;;;;;;;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,kBAAkB,OAAO;AAAA,UAC7B,MAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA;AAAA,UACA,MAAA;AAAA,SAC8C,KAAA;AAC9C,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;AAED,UAAM,MAAA,cAAA,GAAiB,IAAK,CAAA,KAAA,CAAM,MAAM,CAAA,CAAA;AACxC,UAAA,MAAM,OACJ,OAAO,cAAA,CAAe,IAAS,KAAA,QAAA,GAAW,eAAe,IAAO,GAAA,EAAA,CAAA;AAClE,UACE,IAAA,OAAO,cAAe,CAAA,OAAA,KAAY,QAClC,IAAA,CAAC,QAAU,EAAA,SAAA,EAAW,OAAO,CAAA,CAAE,QAAS,CAAA,IAAI,CAC5C,EAAA;AACA,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAEA,UAAM,MAAA,IAAI,MAAM,6BAA6B,CAAA,CAAA;AAAA,SAC/C,CAAA;AACA,QAAW,UAAA,CAAA,IAAA;AAAA,UACTC,wBAAY,SAAU,CAAA;AAAA,YACpB,eAAA;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;;;;;"}
|
|
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":"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"}
|
|
@@ -284,7 +284,7 @@ const useLiveblocksExtension = (opts) => {
|
|
|
284
284
|
);
|
|
285
285
|
}
|
|
286
286
|
if (options.ai) {
|
|
287
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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":";;;;;;;;;;;;;;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,cAAc,cAAe,EAAA,CAAA;AAEnC,EAAM,MAAA,WAAA,GAAc,YAAY,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,GAAA,WAAA;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,OAAA,oBAAA,CAAqB,SAAW,EAAA,WAAA,EAAa,WAAW,CAAA,CAAA;AACjE,CAAA;AAEA,MAAM,WAAA,GAAc,KAAK,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,GAAI,SAAwB,IAAI,CAAA,CAAA;AACxD,EAAA,MAAM,OAAO,OAAQ,EAAA,CAAA;AAcrB,EAAA,MAAM,gBAAgB,gBAAiB,EAAA,CAAA;AACvC,EAAA,MAAM,SAAS,SAAU,EAAA,CAAA;AACzB,EAAM,MAAA,KAAA,GAAQ,0BAA0B,MAAM,CAAA,CAAA;AAC9C,EAAA,MAAM,SAAS,IAAK,CAAA,EAAA,CAAA;AACpB,EAAA,MAAM,cAAc,cAAe,EAAA,CAAA;AAGnC,EAAA,SAAA,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,EAAA,mBAAA;AAAA,IACE,cAAe,CAAA,MAAA;AAAA,IACf,OAAA,CAAQ,SAAS,eAAgB,CAAA,KAAA;AAAA,GACnC,CAAA;AAEA,EAAA,MAAM,oBAAoB,oBAAqB,EAAA,CAAA;AAC/C,EAAA,MAAM,oBAAoB,oBAAqB,EAAA,CAAA;AAE/C,EAAA,OAAO,UAAU,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,GAAA,WAAA;AAAA,UACtB,4BAAA;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,KAAA,4BAAA,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,IAAI,GAAI,EAAA,CAAA;AACpB,QAAO,MAAA,CAAA,GAAA,CAAI,IAAK,CAAA,EAAA,EAAI,GAAG,CAAA,CAAA;AACvB,QAAA,MAAA,CAAO,IAAI,IAAK,CAAA,EAAA,EAAI,IAAI,iBAAA,CAAkB,GAAG,CAAC,CAAA,CAAA;AAC9C,QAAa,YAAA,CAAA,GAAA;AAAA,UACX,IAAK,CAAA,EAAA;AAAA,UACL,IAAI,qBAAsB,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,KAAK,iBAAiB,CAAA,CAAA;AAAA,OACnC;AACA,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAW,UAAA,CAAA,IAAA;AAAA,UACT,iBAAiB,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,kBAAkB,OAAO;AAAA,UAC7B,MAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA;AAAA,UACA,MAAA;AAAA,SAC8C,KAAA;AAC9C,UAAA,MAAM,MAAS,GAAA,MAAM,IAAK,CAAA,SAAA,CAAA,CAAW,uBAAwB,CAAA;AAAA,YAC3D,MAAA;AAAA,YACA,OAAA;AAAA,YACA,QAAA;AAAA,YACA,MAAA;AAAA,WACD,CAAA,CAAA;AAED,UAAM,MAAA,cAAA,GAAiB,IAAK,CAAA,KAAA,CAAM,MAAM,CAAA,CAAA;AACxC,UAAA,MAAM,OACJ,OAAO,cAAA,CAAe,IAAS,KAAA,QAAA,GAAW,eAAe,IAAO,GAAA,EAAA,CAAA;AAClE,UACE,IAAA,OAAO,cAAe,CAAA,OAAA,KAAY,QAClC,IAAA,CAAC,QAAU,EAAA,SAAA,EAAW,OAAO,CAAA,CAAE,QAAS,CAAA,IAAI,CAC5C,EAAA;AACA,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAEA,UAAM,MAAA,IAAI,MAAM,6BAA6B,CAAA,CAAA;AAAA,SAC/C,CAAA;AACA,QAAW,UAAA,CAAA,IAAA;AAAA,UACT,YAAY,SAAU,CAAA;AAAA,YACpB,eAAA;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;;;;"}
|
|
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":";;;;;;;;;;;;;;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,cAAc,cAAe,EAAA,CAAA;AAEnC,EAAM,MAAA,WAAA,GAAc,YAAY,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,GAAA,WAAA;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,OAAA,oBAAA,CAAqB,SAAW,EAAA,WAAA,EAAa,WAAW,CAAA,CAAA;AACjE,CAAA;AAEA,MAAM,WAAA,GAAc,KAAK,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,GAAI,SAAwB,IAAI,CAAA,CAAA;AACxD,EAAA,MAAM,OAAO,OAAQ,EAAA,CAAA;AAcrB,EAAA,MAAM,gBAAgB,gBAAiB,EAAA,CAAA;AACvC,EAAA,MAAM,SAAS,SAAU,EAAA,CAAA;AACzB,EAAM,MAAA,KAAA,GAAQ,0BAA0B,MAAM,CAAA,CAAA;AAC9C,EAAA,MAAM,SAAS,IAAK,CAAA,EAAA,CAAA;AACpB,EAAA,MAAM,cAAc,cAAe,EAAA,CAAA;AAGnC,EAAA,SAAA,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,EAAA,mBAAA;AAAA,IACE,cAAe,CAAA,MAAA;AAAA,IACf,OAAA,CAAQ,SAAS,eAAgB,CAAA,KAAA;AAAA,GACnC,CAAA;AAEA,EAAA,MAAM,oBAAoB,oBAAqB,EAAA,CAAA;AAC/C,EAAA,MAAM,oBAAoB,oBAAqB,EAAA,CAAA;AAE/C,EAAA,OAAO,UAAU,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,GAAA,WAAA;AAAA,UACtB,4BAAA;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,KAAA,4BAAA,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,IAAI,GAAI,EAAA,CAAA;AACpB,QAAO,MAAA,CAAA,GAAA,CAAI,IAAK,CAAA,EAAA,EAAI,GAAG,CAAA,CAAA;AACvB,QAAA,MAAA,CAAO,IAAI,IAAK,CAAA,EAAA,EAAI,IAAI,iBAAA,CAAkB,GAAG,CAAC,CAAA,CAAA;AAC9C,QAAa,YAAA,CAAA,GAAA;AAAA,UACX,IAAK,CAAA,EAAA;AAAA,UACL,IAAI,qBAAsB,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,KAAK,iBAAiB,CAAA,CAAA;AAAA,OACnC;AACA,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAW,UAAA,CAAA,IAAA;AAAA,UACT,iBAAiB,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,CAAA,SAAA,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,UACT,YAAY,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;;;;"}
|
package/dist/ai/AiExtension.js
CHANGED
|
@@ -20,8 +20,18 @@ function getYjsBinding(editor) {
|
|
|
20
20
|
function getLiveblocksYjsProvider(editor) {
|
|
21
21
|
return editor.extensionStorage.liveblocksExtension?.provider;
|
|
22
22
|
}
|
|
23
|
-
function
|
|
24
|
-
return
|
|
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
|
-
|
|
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
|
-
$
|
|
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 (
|
|
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
|
|
112
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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:
|
|
220
|
-
prompt: currentState.prompt
|
|
221
|
-
|
|
222
|
-
type: currentState.
|
|
223
|
-
|
|
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((
|
|
239
|
+
).then((response) => {
|
|
234
240
|
if (abortController.signal.aborted) {
|
|
235
241
|
return;
|
|
236
242
|
}
|
|
237
243
|
this.editor.commands._handleAiToolbarThinkingSuccess({
|
|
238
|
-
type:
|
|
239
|
-
text:
|
|
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
|
-
|
|
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: (
|
|
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 (!
|
|
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
|
-
|
|
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
|
-
|
|
312
|
+
response
|
|
307
313
|
};
|
|
314
|
+
const [firstParagraph, ...otherParagraphs] = response.text.split("\n");
|
|
308
315
|
tr.insertText(
|
|
309
|
-
|
|
310
|
-
|
|
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.
|
|
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" &&
|
|
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.
|
|
381
|
+
exports.isContextualPromptDiffResponse = isContextualPromptDiffResponse;
|
|
369
382
|
//# sourceMappingURL=AiExtension.js.map
|