@liveblocks/react-tiptap 3.19.4-test1 → 3.19.4

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.
Files changed (52) hide show
  1. package/dist/LiveblocksExtension.cjs +5 -51
  2. package/dist/LiveblocksExtension.cjs.map +1 -1
  3. package/dist/LiveblocksExtension.js +5 -51
  4. package/dist/LiveblocksExtension.js.map +1 -1
  5. package/dist/ai/AiExtension.cjs +1 -2
  6. package/dist/ai/AiExtension.cjs.map +1 -1
  7. package/dist/ai/AiExtension.js +1 -2
  8. package/dist/ai/AiExtension.js.map +1 -1
  9. package/dist/comments/CommentsExtension.cjs +1 -7
  10. package/dist/comments/CommentsExtension.cjs.map +1 -1
  11. package/dist/comments/CommentsExtension.js +1 -7
  12. package/dist/comments/CommentsExtension.js.map +1 -1
  13. package/dist/index.d.cts +0 -5
  14. package/dist/index.d.ts +0 -5
  15. package/dist/mentions/MentionExtension.cjs +1 -4
  16. package/dist/mentions/MentionExtension.cjs.map +1 -1
  17. package/dist/mentions/MentionExtension.js +1 -4
  18. package/dist/mentions/MentionExtension.js.map +1 -1
  19. package/dist/types.cjs.map +1 -1
  20. package/dist/types.js.map +1 -1
  21. package/dist/version.cjs +1 -1
  22. package/dist/version.cjs.map +1 -1
  23. package/dist/version.js +1 -1
  24. package/dist/version.js.map +1 -1
  25. package/package.json +6 -6
  26. package/src/styles/index.css +4 -12
  27. package/styles.css +1 -1
  28. package/styles.css.map +1 -1
  29. package/dist/collaboration-liveblocks/cursors.cjs +0 -267
  30. package/dist/collaboration-liveblocks/cursors.cjs.map +0 -1
  31. package/dist/collaboration-liveblocks/cursors.js +0 -264
  32. package/dist/collaboration-liveblocks/cursors.js.map +0 -1
  33. package/dist/collaboration-liveblocks/mapping.cjs +0 -218
  34. package/dist/collaboration-liveblocks/mapping.cjs.map +0 -1
  35. package/dist/collaboration-liveblocks/mapping.js +0 -207
  36. package/dist/collaboration-liveblocks/mapping.js.map +0 -1
  37. package/dist/collaboration-liveblocks/plugin.cjs +0 -250
  38. package/dist/collaboration-liveblocks/plugin.cjs.map +0 -1
  39. package/dist/collaboration-liveblocks/plugin.js +0 -247
  40. package/dist/collaboration-liveblocks/plugin.js.map +0 -1
  41. package/dist/collaboration-liveblocks/remote.cjs +0 -196
  42. package/dist/collaboration-liveblocks/remote.cjs.map +0 -1
  43. package/dist/collaboration-liveblocks/remote.js +0 -193
  44. package/dist/collaboration-liveblocks/remote.js.map +0 -1
  45. package/dist/collaboration-liveblocks/schema.cjs +0 -150
  46. package/dist/collaboration-liveblocks/schema.cjs.map +0 -1
  47. package/dist/collaboration-liveblocks/schema.js +0 -135
  48. package/dist/collaboration-liveblocks/schema.js.map +0 -1
  49. package/dist/collaboration-liveblocks/steps.cjs +0 -359
  50. package/dist/collaboration-liveblocks/steps.cjs.map +0 -1
  51. package/dist/collaboration-liveblocks/steps.js +0 -356
  52. package/dist/collaboration-liveblocks/steps.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AiExtension.cjs","sources":["../../src/ai/AiExtension.ts"],"sourcesContent":["import {\n autoRetry,\n type ContextualPromptResponse,\n HttpError,\n} from \"@liveblocks/core\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { CommandProps, Editor } from \"@tiptap/core\";\nimport { Extension } from \"@tiptap/core\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { Transaction } from \"@tiptap/pm/state\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport {\n ySyncPluginKey,\n yXmlFragmentToProseMirrorFragment,\n} from \"y-prosemirror\";\nimport type { Doc, Snapshot } from \"yjs\";\nimport {\n createDocFromSnapshot,\n emptySnapshot,\n equalSnapshots,\n snapshot as takeSnapshot,\n} from \"yjs\";\n\nimport {\n AI_TOOLBAR_SELECTION_PLUGIN,\n type AiExtensionOptions,\n type AiExtensionStorage,\n type AiToolbarState,\n type LiveblocksExtensionStorage,\n type ResolveContextualPromptResponse,\n type YSyncPluginState,\n} from \"../types\";\nimport { getContextualPromptContext } from \"../utils\";\n\nconst DEFAULT_AI_NAME = \"AI\";\nexport const DEFAULT_STATE: AiToolbarState = { phase: \"closed\" };\n\nconst RESOLVE_AI_PROMPT_RETRY_ATTEMPTS = 3;\nconst RESOLVE_AI_PROMPT_RETRY_DELAYS = [1000, 2000, 4000];\n\nfunction getYjsBinding(editor: Editor) {\n return (ySyncPluginKey.getState(editor.view.state) as YSyncPluginState)\n .binding;\n}\n\nfunction getLiveblocksYjsProvider(\n editor: Editor\n): LiveblocksYjsProvider | undefined {\n // Tiptap extension storage is exposed as untyped extension data here.\n const storage = editor.extensionStorage\n .liveblocksExtension as LiveblocksExtensionStorage | undefined;\n\n return storage?.mode === \"yjs\" ? storage.provider : undefined;\n}\n\nexport function isContextualPromptDiffResponse(\n response: ContextualPromptResponse\n): response is Extract<\n ContextualPromptResponse,\n { type: \"replace\" | \"insert\" }\n> {\n return response.type === \"replace\" || response.type === \"insert\";\n}\n\nfunction isResolveContextualPromptResponse(\n response: unknown\n): response is ResolveContextualPromptResponse {\n return (\n typeof response === \"object\" &&\n response !== null &&\n typeof (response as { text: unknown }).text === \"string\" &&\n typeof (response as { type: unknown }).type === \"string\" &&\n [\"insert\", \"replace\", \"other\"].includes((response as { type: string }).type)\n );\n}\n\nfunction createParagraph(editor: Editor, text: string) {\n const paragraph =\n editor.schema.nodes.paragraph ??\n Object.values(editor.schema.nodes).find((node) => node.isBlock);\n\n if (!paragraph) {\n throw new Error(\"Could not create a paragraph.\");\n }\n\n return paragraph.create(null, text ? editor.schema.text(text) : undefined);\n}\n\nfunction getRevertTransaction(\n tr: Transaction,\n editor: Editor,\n storage: AiExtensionStorage,\n doc?: Doc\n): Transaction | null {\n if (storage.snapshot) {\n const binding = getYjsBinding(editor);\n\n if (binding) {\n binding.mapping.clear();\n\n const docFromSnapshot = createDocFromSnapshot(\n binding.doc,\n storage.snapshot\n );\n const type = docFromSnapshot.getXmlFragment(\"default\"); // TODO: field\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n type,\n editor.state.schema\n );\n\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n if (doc) {\n doc.gc = true;\n }\n\n storage.snapshot = undefined;\n\n return tr;\n }\n }\n return null;\n}\n\nexport const AiExtension = Extension.create<\n AiExtensionOptions,\n AiExtensionStorage\n>({\n name: \"liveblocksAi\",\n addOptions() {\n return {\n doc: undefined,\n pud: undefined,\n\n // The actual default resolver is set in LiveblocksExtension via AiExtension.configure()\n resolveContextualPrompt: () =>\n Promise.reject(new Error(\"resolveContextualPrompt not configured\")),\n name: DEFAULT_AI_NAME,\n };\n },\n addStorage() {\n return {\n state: DEFAULT_STATE,\n name: this.options.name,\n };\n },\n addCommands() {\n return {\n askAi: (prompt) => () => {\n if (typeof prompt === \"string\") {\n this.editor.commands.$startAiToolbarThinking(prompt);\n } else {\n this.editor.commands.$openAiToolbarAsking();\n }\n\n return true;\n },\n\n closeAi: () => () => {\n this.editor.commands.$closeAiToolbar();\n\n return true;\n },\n\n $acceptAiToolbarResponse:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"reviewing\" phase, do nothing\n if (currentState.phase !== \"reviewing\") {\n return false;\n }\n\n // 2. Accept the response\n if (isContextualPromptDiffResponse(currentState.response)) {\n // 2.a. If the response is a diff, apply it definitely\n const binding = getYjsBinding(this.editor);\n if (!binding) {\n return false;\n }\n\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n binding.type,\n this.editor.state.schema\n );\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n this.editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n this.storage.snapshot = undefined;\n } else {\n // 2.b. If the response is not a diff, insert it below the selection\n\n const paragraphs = currentState.response.text\n .split(\"\\n\")\n .map((paragraph) => createParagraph(this.editor, paragraph));\n\n tr.insert(this.editor.state.selection.$to.end(), paragraphs);\n tr.setMeta(\"addToHistory\", true);\n view.dispatch(tr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 4. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $closeAiToolbar:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If already in \"closed\" phase, do nothing\n if (currentState.phase === \"closed\") {\n return false;\n }\n\n // 2. If in \"thinking\" phase, cancel the current AI request\n if (currentState.phase === \"thinking\") {\n currentState.abortController.abort();\n }\n\n // 3. If in \"thinking\" or \"reviewing\" phase, revert the editor if possible and unblock it\n if (\n currentState.phase === \"thinking\" ||\n currentState.phase === \"reviewing\"\n ) {\n // Get the revert transaction and dispatch it\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n view.dispatch(revertTr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n }\n\n // 4. Restore the initial selection\n this.editor.commands.setTextSelection(currentState.initialSelection);\n\n // 5. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 6. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $openAiToolbarAsking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"closed\" phase, do nothing\n if (currentState.phase !== \"closed\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n // 3. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n // Store the initial selection\n initialSelection: {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty\n customPrompt: \"\",\n };\n\n return true;\n },\n\n $startAiToolbarThinking:\n (prompt: string, withPreviousResponse?: boolean) =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If in \"thinking\" phase already, do nothing\n if (currentState.phase === \"thinking\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n const abortController = new AbortController();\n const provider = getLiveblocksYjsProvider(this.editor);\n\n // 3. If this is a retry or a refinement, revert the editor and restore the initial selection\n if (currentState.phase === \"reviewing\") {\n // 3.a. Revert the editor\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n // Important: in this scenario we do not unpause the provider\n view.dispatch(revertTr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3.b. Restore the initial selection\n this.editor.commands.setTextSelection(\n currentState.initialSelection\n );\n }\n\n // 4. Set to \"thinking\" phase\n this.storage.state = {\n phase: \"thinking\",\n // Store the initial selection if the toolbar is opened directly in the \"thinking\" phase\n initialSelection: currentState.initialSelection ?? {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty if the toolbar is opened directly in the \"thinking\" phase\n customPrompt: currentState.customPrompt ?? \"\",\n prompt,\n abortController,\n previousResponse: currentState.response,\n };\n\n // 5. Block the editor\n this.editor.setEditable(false);\n\n // 6. Start the AI request\n autoRetry(\n async () => {\n await provider?.pause();\n\n // 6.a. Resolve the AI prompt\n const response = (await this.options.resolveContextualPrompt({\n prompt,\n context: getContextualPromptContext(this.editor, 3_000),\n signal: abortController.signal,\n previous:\n withPreviousResponse && currentState.phase === \"reviewing\"\n ? {\n prompt: currentState.prompt,\n response: {\n type: currentState.response?.type,\n text: currentState.response?.text,\n },\n }\n : undefined,\n })) as unknown;\n\n // 6.b. Validate the response\n if (isResolveContextualPromptResponse(response)) {\n return response;\n } else {\n throw new Error(\"Failed to resolve AI prompt.\");\n }\n },\n RESOLVE_AI_PROMPT_RETRY_ATTEMPTS,\n RESOLVE_AI_PROMPT_RETRY_DELAYS,\n\n (error) => {\n // Don't retry on 4xx errors or if the request was aborted\n return (\n abortController.signal.aborted ||\n (error instanceof HttpError &&\n error.status >= 400 &&\n error.status < 500)\n );\n }\n )\n .then((response) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.a. If the AI request succeeds, set to \"reviewing\" phase with the response\n this.editor.commands._handleAiToolbarThinkingSuccess({\n type: response.type,\n text: response.text,\n });\n })\n .catch((error) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.b. If the AI request fails, set to \"asking\" phase with error\n this.editor.commands._handleAiToolbarThinkingError(error);\n });\n\n return true;\n },\n\n $cancelAiToolbarThinking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Cancel the current AI request\n currentState.abortController.abort();\n\n // 3. Unblock the editor\n this.editor.setEditable(true);\n\n // 4. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n };\n\n return true;\n },\n\n _showAiToolbarReviewingDiff: () => () => {\n // The diff is applied right before moving to the \"reviewing\" phase\n if (this.storage.state.phase !== \"reviewing\") {\n return false;\n }\n\n if (!this.options.doc || !this.storage.snapshot) {\n return false;\n }\n\n const previousSnapshot: Snapshot =\n this.storage.snapshot ?? emptySnapshot;\n const currentSnapshot = takeSnapshot(this.options.doc);\n\n if (equalSnapshots(previousSnapshot, currentSnapshot)) {\n return true;\n }\n\n getYjsBinding(this.editor)?.renderSnapshot(\n currentSnapshot,\n previousSnapshot\n );\n\n return true;\n },\n\n _handleAiToolbarThinkingSuccess:\n (response: ContextualPromptResponse) =>\n ({ view, tr }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. If this is not a diff, the response will just be in the toolbar, set to \"reviewing\" phase directly with the response\n if (!isContextualPromptDiffResponse(response)) {\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n return true;\n }\n\n if (!this.options.doc) {\n return false;\n }\n\n // 3. Otherwise, the response is a diff, apply it to the editor\n this.options.doc.gc = false;\n this.storage.snapshot = takeSnapshot(this.options.doc);\n\n // 4. Set to \"reviewing\" phase with the new range\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n // 5. Insert the response's text as inline first (and replace the selection if it's a replace) then as block if there are multiple paragraphs\n const [firstParagraph, ...otherParagraphs] =\n response.text.split(\"\\n\");\n\n tr.insertText(\n firstParagraph,\n response.type === \"insert\"\n ? this.editor.state.selection.to\n : this.editor.state.selection.from,\n this.editor.state.selection.to\n );\n\n if (otherParagraphs.length > 0) {\n const paragraphs = otherParagraphs.map((paragraph) =>\n createParagraph(this.editor, paragraph)\n );\n\n tr.insert(tr.selection.$to.pos, paragraphs);\n }\n\n view.dispatch(tr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n\n // 6. Show the diff\n this.editor.commands._showAiToolbarReviewingDiff();\n\n // We moved to the \"reviewing\" phase, so even if `_showAiToolbarReviewingDiff`\n // returns `false` somehow, we still want to return `true`\n return true;\n },\n\n _handleAiToolbarThinkingError: (error: unknown) => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Unblock the editor\n this.editor.setEditable(true);\n\n // 3. Log the error\n console.error(error);\n\n // 4. Set to \"asking\" phase with error\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n // Pass the error so it can be displayed\n error:\n error instanceof Error\n ? error\n : new Error(String(error), { cause: error }),\n };\n\n return true;\n },\n\n _updateAiToolbarCustomPrompt:\n (customPrompt: string | ((currentCustomPrompt: string) => string)) =>\n () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in a phase with a custom prompt, do nothing\n if (typeof currentState.customPrompt !== \"string\") {\n return false;\n }\n\n // 2. Update the custom prompt\n this.storage.state.customPrompt =\n typeof customPrompt === \"function\"\n ? customPrompt(currentState.customPrompt)\n : customPrompt;\n\n return true;\n },\n };\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: AI_TOOLBAR_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n // Don't show the AI toolbar selection if the toolbar is closed or when reviewing diff responses\n if (\n this.storage.state.phase === \"closed\" ||\n (this.storage.state.phase === \"reviewing\" &&\n isContextualPromptDiffResponse(this.storage.state.response))\n ) {\n return DecorationSet.create(doc, []);\n }\n\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n ];\n },\n});\n"],"names":["ySyncPluginKey","createDocFromSnapshot","yXmlFragmentToProseMirrorFragment","Slice","Fragment","Extension","autoRetry","getContextualPromptContext","HttpError","emptySnapshot","takeSnapshot","equalSnapshots","Plugin","AI_TOOLBAR_SELECTION_PLUGIN","DecorationSet","Decoration"],"mappings":"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"}
1
+ {"version":3,"file":"AiExtension.cjs","sources":["../../src/ai/AiExtension.ts"],"sourcesContent":["import {\n autoRetry,\n type ContextualPromptResponse,\n HttpError,\n} from \"@liveblocks/core\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { CommandProps, Editor } from \"@tiptap/core\";\nimport { Extension } from \"@tiptap/core\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { Transaction } from \"@tiptap/pm/state\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport {\n ySyncPluginKey,\n yXmlFragmentToProseMirrorFragment,\n} from \"y-prosemirror\";\nimport type { Doc, Snapshot } from \"yjs\";\nimport {\n createDocFromSnapshot,\n emptySnapshot,\n equalSnapshots,\n snapshot as takeSnapshot,\n} from \"yjs\";\n\nimport {\n AI_TOOLBAR_SELECTION_PLUGIN,\n type AiExtensionOptions,\n type AiExtensionStorage,\n type AiToolbarState,\n type ResolveContextualPromptResponse,\n type YSyncPluginState,\n} from \"../types\";\nimport { getContextualPromptContext } from \"../utils\";\n\nconst DEFAULT_AI_NAME = \"AI\";\nexport const DEFAULT_STATE: AiToolbarState = { phase: \"closed\" };\n\nconst RESOLVE_AI_PROMPT_RETRY_ATTEMPTS = 3;\nconst RESOLVE_AI_PROMPT_RETRY_DELAYS = [1000, 2000, 4000];\n\nfunction getYjsBinding(editor: Editor) {\n return (ySyncPluginKey.getState(editor.view.state) as YSyncPluginState)\n .binding;\n}\n\nfunction getLiveblocksYjsProvider(\n editor: Editor\n): LiveblocksYjsProvider | undefined {\n // Eslint doesn't seem to like Tiptap's Type declaration strategy\n return editor.extensionStorage.liveblocksExtension?.provider;\n}\n\nexport function isContextualPromptDiffResponse(\n response: ContextualPromptResponse\n): response is Extract<\n ContextualPromptResponse,\n { type: \"replace\" | \"insert\" }\n> {\n return response.type === \"replace\" || response.type === \"insert\";\n}\n\nfunction isResolveContextualPromptResponse(\n response: unknown\n): response is ResolveContextualPromptResponse {\n return (\n typeof response === \"object\" &&\n response !== null &&\n typeof (response as { text: unknown }).text === \"string\" &&\n typeof (response as { type: unknown }).type === \"string\" &&\n [\"insert\", \"replace\", \"other\"].includes((response as { type: string }).type)\n );\n}\n\nfunction createParagraph(editor: Editor, text: string) {\n const paragraph =\n editor.schema.nodes.paragraph ??\n Object.values(editor.schema.nodes).find((node) => node.isBlock);\n\n if (!paragraph) {\n throw new Error(\"Could not create a paragraph.\");\n }\n\n return paragraph.create(null, text ? editor.schema.text(text) : undefined);\n}\n\nfunction getRevertTransaction(\n tr: Transaction,\n editor: Editor,\n storage: AiExtensionStorage,\n doc?: Doc\n): Transaction | null {\n if (storage.snapshot) {\n const binding = getYjsBinding(editor);\n\n if (binding) {\n binding.mapping.clear();\n\n const docFromSnapshot = createDocFromSnapshot(\n binding.doc,\n storage.snapshot\n );\n const type = docFromSnapshot.getXmlFragment(\"default\"); // TODO: field\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n type,\n editor.state.schema\n );\n\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n if (doc) {\n doc.gc = true;\n }\n\n storage.snapshot = undefined;\n\n return tr;\n }\n }\n return null;\n}\n\nexport const AiExtension = Extension.create<\n AiExtensionOptions,\n AiExtensionStorage\n>({\n name: \"liveblocksAi\",\n addOptions() {\n return {\n doc: undefined,\n pud: undefined,\n\n // The actual default resolver is set in LiveblocksExtension via AiExtension.configure()\n resolveContextualPrompt: () =>\n Promise.reject(new Error(\"resolveContextualPrompt not configured\")),\n name: DEFAULT_AI_NAME,\n };\n },\n addStorage() {\n return {\n state: DEFAULT_STATE,\n name: this.options.name,\n };\n },\n addCommands() {\n return {\n askAi: (prompt) => () => {\n if (typeof prompt === \"string\") {\n this.editor.commands.$startAiToolbarThinking(prompt);\n } else {\n this.editor.commands.$openAiToolbarAsking();\n }\n\n return true;\n },\n\n closeAi: () => () => {\n this.editor.commands.$closeAiToolbar();\n\n return true;\n },\n\n $acceptAiToolbarResponse:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"reviewing\" phase, do nothing\n if (currentState.phase !== \"reviewing\") {\n return false;\n }\n\n // 2. Accept the response\n if (isContextualPromptDiffResponse(currentState.response)) {\n // 2.a. If the response is a diff, apply it definitely\n const binding = getYjsBinding(this.editor);\n if (!binding) {\n return false;\n }\n\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n binding.type,\n this.editor.state.schema\n );\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n this.editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n this.storage.snapshot = undefined;\n } else {\n // 2.b. If the response is not a diff, insert it below the selection\n\n const paragraphs = currentState.response.text\n .split(\"\\n\")\n .map((paragraph) => createParagraph(this.editor, paragraph));\n\n tr.insert(this.editor.state.selection.$to.end(), paragraphs);\n tr.setMeta(\"addToHistory\", true);\n view.dispatch(tr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 4. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $closeAiToolbar:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If already in \"closed\" phase, do nothing\n if (currentState.phase === \"closed\") {\n return false;\n }\n\n // 2. If in \"thinking\" phase, cancel the current AI request\n if (currentState.phase === \"thinking\") {\n currentState.abortController.abort();\n }\n\n // 3. If in \"thinking\" or \"reviewing\" phase, revert the editor if possible and unblock it\n if (\n currentState.phase === \"thinking\" ||\n currentState.phase === \"reviewing\"\n ) {\n // Get the revert transaction and dispatch it\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n view.dispatch(revertTr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n }\n\n // 4. Restore the initial selection\n this.editor.commands.setTextSelection(currentState.initialSelection);\n\n // 5. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 6. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $openAiToolbarAsking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"closed\" phase, do nothing\n if (currentState.phase !== \"closed\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n // 3. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n // Store the initial selection\n initialSelection: {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty\n customPrompt: \"\",\n };\n\n return true;\n },\n\n $startAiToolbarThinking:\n (prompt: string, withPreviousResponse?: boolean) =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If in \"thinking\" phase already, do nothing\n if (currentState.phase === \"thinking\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n const abortController = new AbortController();\n const provider = getLiveblocksYjsProvider(this.editor);\n\n // 3. If this is a retry or a refinement, revert the editor and restore the initial selection\n if (currentState.phase === \"reviewing\") {\n // 3.a. Revert the editor\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n // Important: in this scenario we do not unpause the provider\n view.dispatch(revertTr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3.b. Restore the initial selection\n this.editor.commands.setTextSelection(\n currentState.initialSelection\n );\n }\n\n // 4. Set to \"thinking\" phase\n this.storage.state = {\n phase: \"thinking\",\n // Store the initial selection if the toolbar is opened directly in the \"thinking\" phase\n initialSelection: currentState.initialSelection ?? {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty if the toolbar is opened directly in the \"thinking\" phase\n customPrompt: currentState.customPrompt ?? \"\",\n prompt,\n abortController,\n previousResponse: currentState.response,\n };\n\n // 5. Block the editor\n this.editor.setEditable(false);\n\n // 6. Start the AI request\n autoRetry(\n async () => {\n await provider?.pause();\n\n // 6.a. Resolve the AI prompt\n const response = (await this.options.resolveContextualPrompt({\n prompt,\n context: getContextualPromptContext(this.editor, 3_000),\n signal: abortController.signal,\n previous:\n withPreviousResponse && currentState.phase === \"reviewing\"\n ? {\n prompt: currentState.prompt,\n response: {\n type: currentState.response?.type,\n text: currentState.response?.text,\n },\n }\n : undefined,\n })) as unknown;\n\n // 6.b. Validate the response\n if (isResolveContextualPromptResponse(response)) {\n return response;\n } else {\n throw new Error(\"Failed to resolve AI prompt.\");\n }\n },\n RESOLVE_AI_PROMPT_RETRY_ATTEMPTS,\n RESOLVE_AI_PROMPT_RETRY_DELAYS,\n\n (error) => {\n // Don't retry on 4xx errors or if the request was aborted\n return (\n abortController.signal.aborted ||\n (error instanceof HttpError &&\n error.status >= 400 &&\n error.status < 500)\n );\n }\n )\n .then((response) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.a. If the AI request succeeds, set to \"reviewing\" phase with the response\n this.editor.commands._handleAiToolbarThinkingSuccess({\n type: response.type,\n text: response.text,\n });\n })\n .catch((error) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.b. If the AI request fails, set to \"asking\" phase with error\n this.editor.commands._handleAiToolbarThinkingError(error);\n });\n\n return true;\n },\n\n $cancelAiToolbarThinking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Cancel the current AI request\n currentState.abortController.abort();\n\n // 3. Unblock the editor\n this.editor.setEditable(true);\n\n // 4. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n };\n\n return true;\n },\n\n _showAiToolbarReviewingDiff: () => () => {\n // The diff is applied right before moving to the \"reviewing\" phase\n if (this.storage.state.phase !== \"reviewing\") {\n return false;\n }\n\n if (!this.options.doc || !this.storage.snapshot) {\n return false;\n }\n\n const previousSnapshot: Snapshot =\n this.storage.snapshot ?? emptySnapshot;\n const currentSnapshot = takeSnapshot(this.options.doc);\n\n if (equalSnapshots(previousSnapshot, currentSnapshot)) {\n return true;\n }\n\n getYjsBinding(this.editor)?.renderSnapshot(\n currentSnapshot,\n previousSnapshot\n );\n\n return true;\n },\n\n _handleAiToolbarThinkingSuccess:\n (response: ContextualPromptResponse) =>\n ({ view, tr }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. If this is not a diff, the response will just be in the toolbar, set to \"reviewing\" phase directly with the response\n if (!isContextualPromptDiffResponse(response)) {\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n return true;\n }\n\n if (!this.options.doc) {\n return false;\n }\n\n // 3. Otherwise, the response is a diff, apply it to the editor\n this.options.doc.gc = false;\n this.storage.snapshot = takeSnapshot(this.options.doc);\n\n // 4. Set to \"reviewing\" phase with the new range\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n // 5. Insert the response's text as inline first (and replace the selection if it's a replace) then as block if there are multiple paragraphs\n const [firstParagraph, ...otherParagraphs] =\n response.text.split(\"\\n\");\n\n tr.insertText(\n firstParagraph,\n response.type === \"insert\"\n ? this.editor.state.selection.to\n : this.editor.state.selection.from,\n this.editor.state.selection.to\n );\n\n if (otherParagraphs.length > 0) {\n const paragraphs = otherParagraphs.map((paragraph) =>\n createParagraph(this.editor, paragraph)\n );\n\n tr.insert(tr.selection.$to.pos, paragraphs);\n }\n\n view.dispatch(tr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n\n // 6. Show the diff\n this.editor.commands._showAiToolbarReviewingDiff();\n\n // We moved to the \"reviewing\" phase, so even if `_showAiToolbarReviewingDiff`\n // returns `false` somehow, we still want to return `true`\n return true;\n },\n\n _handleAiToolbarThinkingError: (error: unknown) => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Unblock the editor\n this.editor.setEditable(true);\n\n // 3. Log the error\n console.error(error);\n\n // 4. Set to \"asking\" phase with error\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n // Pass the error so it can be displayed\n error:\n error instanceof Error\n ? error\n : new Error(String(error), { cause: error }),\n };\n\n return true;\n },\n\n _updateAiToolbarCustomPrompt:\n (customPrompt: string | ((currentCustomPrompt: string) => string)) =>\n () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in a phase with a custom prompt, do nothing\n if (typeof currentState.customPrompt !== \"string\") {\n return false;\n }\n\n // 2. Update the custom prompt\n this.storage.state.customPrompt =\n typeof customPrompt === \"function\"\n ? customPrompt(currentState.customPrompt)\n : customPrompt;\n\n return true;\n },\n };\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: AI_TOOLBAR_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n // Don't show the AI toolbar selection if the toolbar is closed or when reviewing diff responses\n if (\n this.storage.state.phase === \"closed\" ||\n (this.storage.state.phase === \"reviewing\" &&\n isContextualPromptDiffResponse(this.storage.state.response))\n ) {\n return DecorationSet.create(doc, []);\n }\n\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n ];\n },\n});\n"],"names":["ySyncPluginKey","createDocFromSnapshot","yXmlFragmentToProseMirrorFragment","Slice","Fragment","Extension","autoRetry","getContextualPromptContext","HttpError","emptySnapshot","takeSnapshot","equalSnapshots","Plugin","AI_TOOLBAR_SELECTION_PLUGIN","DecorationSet","Decoration"],"mappings":"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"}
@@ -16,8 +16,7 @@ function getYjsBinding(editor) {
16
16
  return ySyncPluginKey.getState(editor.view.state).binding;
17
17
  }
18
18
  function getLiveblocksYjsProvider(editor) {
19
- const storage = editor.extensionStorage.liveblocksExtension;
20
- return storage?.mode === "yjs" ? storage.provider : void 0;
19
+ return editor.extensionStorage.liveblocksExtension?.provider;
21
20
  }
22
21
  function isContextualPromptDiffResponse(response) {
23
22
  return response.type === "replace" || response.type === "insert";
@@ -1 +1 @@
1
- {"version":3,"file":"AiExtension.js","sources":["../../src/ai/AiExtension.ts"],"sourcesContent":["import {\n autoRetry,\n type ContextualPromptResponse,\n HttpError,\n} from \"@liveblocks/core\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { CommandProps, Editor } from \"@tiptap/core\";\nimport { Extension } from \"@tiptap/core\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { Transaction } from \"@tiptap/pm/state\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport {\n ySyncPluginKey,\n yXmlFragmentToProseMirrorFragment,\n} from \"y-prosemirror\";\nimport type { Doc, Snapshot } from \"yjs\";\nimport {\n createDocFromSnapshot,\n emptySnapshot,\n equalSnapshots,\n snapshot as takeSnapshot,\n} from \"yjs\";\n\nimport {\n AI_TOOLBAR_SELECTION_PLUGIN,\n type AiExtensionOptions,\n type AiExtensionStorage,\n type AiToolbarState,\n type LiveblocksExtensionStorage,\n type ResolveContextualPromptResponse,\n type YSyncPluginState,\n} from \"../types\";\nimport { getContextualPromptContext } from \"../utils\";\n\nconst DEFAULT_AI_NAME = \"AI\";\nexport const DEFAULT_STATE: AiToolbarState = { phase: \"closed\" };\n\nconst RESOLVE_AI_PROMPT_RETRY_ATTEMPTS = 3;\nconst RESOLVE_AI_PROMPT_RETRY_DELAYS = [1000, 2000, 4000];\n\nfunction getYjsBinding(editor: Editor) {\n return (ySyncPluginKey.getState(editor.view.state) as YSyncPluginState)\n .binding;\n}\n\nfunction getLiveblocksYjsProvider(\n editor: Editor\n): LiveblocksYjsProvider | undefined {\n // Tiptap extension storage is exposed as untyped extension data here.\n const storage = editor.extensionStorage\n .liveblocksExtension as LiveblocksExtensionStorage | undefined;\n\n return storage?.mode === \"yjs\" ? storage.provider : undefined;\n}\n\nexport function isContextualPromptDiffResponse(\n response: ContextualPromptResponse\n): response is Extract<\n ContextualPromptResponse,\n { type: \"replace\" | \"insert\" }\n> {\n return response.type === \"replace\" || response.type === \"insert\";\n}\n\nfunction isResolveContextualPromptResponse(\n response: unknown\n): response is ResolveContextualPromptResponse {\n return (\n typeof response === \"object\" &&\n response !== null &&\n typeof (response as { text: unknown }).text === \"string\" &&\n typeof (response as { type: unknown }).type === \"string\" &&\n [\"insert\", \"replace\", \"other\"].includes((response as { type: string }).type)\n );\n}\n\nfunction createParagraph(editor: Editor, text: string) {\n const paragraph =\n editor.schema.nodes.paragraph ??\n Object.values(editor.schema.nodes).find((node) => node.isBlock);\n\n if (!paragraph) {\n throw new Error(\"Could not create a paragraph.\");\n }\n\n return paragraph.create(null, text ? editor.schema.text(text) : undefined);\n}\n\nfunction getRevertTransaction(\n tr: Transaction,\n editor: Editor,\n storage: AiExtensionStorage,\n doc?: Doc\n): Transaction | null {\n if (storage.snapshot) {\n const binding = getYjsBinding(editor);\n\n if (binding) {\n binding.mapping.clear();\n\n const docFromSnapshot = createDocFromSnapshot(\n binding.doc,\n storage.snapshot\n );\n const type = docFromSnapshot.getXmlFragment(\"default\"); // TODO: field\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n type,\n editor.state.schema\n );\n\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n if (doc) {\n doc.gc = true;\n }\n\n storage.snapshot = undefined;\n\n return tr;\n }\n }\n return null;\n}\n\nexport const AiExtension = Extension.create<\n AiExtensionOptions,\n AiExtensionStorage\n>({\n name: \"liveblocksAi\",\n addOptions() {\n return {\n doc: undefined,\n pud: undefined,\n\n // The actual default resolver is set in LiveblocksExtension via AiExtension.configure()\n resolveContextualPrompt: () =>\n Promise.reject(new Error(\"resolveContextualPrompt not configured\")),\n name: DEFAULT_AI_NAME,\n };\n },\n addStorage() {\n return {\n state: DEFAULT_STATE,\n name: this.options.name,\n };\n },\n addCommands() {\n return {\n askAi: (prompt) => () => {\n if (typeof prompt === \"string\") {\n this.editor.commands.$startAiToolbarThinking(prompt);\n } else {\n this.editor.commands.$openAiToolbarAsking();\n }\n\n return true;\n },\n\n closeAi: () => () => {\n this.editor.commands.$closeAiToolbar();\n\n return true;\n },\n\n $acceptAiToolbarResponse:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"reviewing\" phase, do nothing\n if (currentState.phase !== \"reviewing\") {\n return false;\n }\n\n // 2. Accept the response\n if (isContextualPromptDiffResponse(currentState.response)) {\n // 2.a. If the response is a diff, apply it definitely\n const binding = getYjsBinding(this.editor);\n if (!binding) {\n return false;\n }\n\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n binding.type,\n this.editor.state.schema\n );\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n this.editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n this.storage.snapshot = undefined;\n } else {\n // 2.b. If the response is not a diff, insert it below the selection\n\n const paragraphs = currentState.response.text\n .split(\"\\n\")\n .map((paragraph) => createParagraph(this.editor, paragraph));\n\n tr.insert(this.editor.state.selection.$to.end(), paragraphs);\n tr.setMeta(\"addToHistory\", true);\n view.dispatch(tr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 4. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $closeAiToolbar:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If already in \"closed\" phase, do nothing\n if (currentState.phase === \"closed\") {\n return false;\n }\n\n // 2. If in \"thinking\" phase, cancel the current AI request\n if (currentState.phase === \"thinking\") {\n currentState.abortController.abort();\n }\n\n // 3. If in \"thinking\" or \"reviewing\" phase, revert the editor if possible and unblock it\n if (\n currentState.phase === \"thinking\" ||\n currentState.phase === \"reviewing\"\n ) {\n // Get the revert transaction and dispatch it\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n view.dispatch(revertTr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n }\n\n // 4. Restore the initial selection\n this.editor.commands.setTextSelection(currentState.initialSelection);\n\n // 5. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 6. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $openAiToolbarAsking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"closed\" phase, do nothing\n if (currentState.phase !== \"closed\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n // 3. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n // Store the initial selection\n initialSelection: {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty\n customPrompt: \"\",\n };\n\n return true;\n },\n\n $startAiToolbarThinking:\n (prompt: string, withPreviousResponse?: boolean) =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If in \"thinking\" phase already, do nothing\n if (currentState.phase === \"thinking\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n const abortController = new AbortController();\n const provider = getLiveblocksYjsProvider(this.editor);\n\n // 3. If this is a retry or a refinement, revert the editor and restore the initial selection\n if (currentState.phase === \"reviewing\") {\n // 3.a. Revert the editor\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n // Important: in this scenario we do not unpause the provider\n view.dispatch(revertTr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3.b. Restore the initial selection\n this.editor.commands.setTextSelection(\n currentState.initialSelection\n );\n }\n\n // 4. Set to \"thinking\" phase\n this.storage.state = {\n phase: \"thinking\",\n // Store the initial selection if the toolbar is opened directly in the \"thinking\" phase\n initialSelection: currentState.initialSelection ?? {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty if the toolbar is opened directly in the \"thinking\" phase\n customPrompt: currentState.customPrompt ?? \"\",\n prompt,\n abortController,\n previousResponse: currentState.response,\n };\n\n // 5. Block the editor\n this.editor.setEditable(false);\n\n // 6. Start the AI request\n autoRetry(\n async () => {\n await provider?.pause();\n\n // 6.a. Resolve the AI prompt\n const response = (await this.options.resolveContextualPrompt({\n prompt,\n context: getContextualPromptContext(this.editor, 3_000),\n signal: abortController.signal,\n previous:\n withPreviousResponse && currentState.phase === \"reviewing\"\n ? {\n prompt: currentState.prompt,\n response: {\n type: currentState.response?.type,\n text: currentState.response?.text,\n },\n }\n : undefined,\n })) as unknown;\n\n // 6.b. Validate the response\n if (isResolveContextualPromptResponse(response)) {\n return response;\n } else {\n throw new Error(\"Failed to resolve AI prompt.\");\n }\n },\n RESOLVE_AI_PROMPT_RETRY_ATTEMPTS,\n RESOLVE_AI_PROMPT_RETRY_DELAYS,\n\n (error) => {\n // Don't retry on 4xx errors or if the request was aborted\n return (\n abortController.signal.aborted ||\n (error instanceof HttpError &&\n error.status >= 400 &&\n error.status < 500)\n );\n }\n )\n .then((response) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.a. If the AI request succeeds, set to \"reviewing\" phase with the response\n this.editor.commands._handleAiToolbarThinkingSuccess({\n type: response.type,\n text: response.text,\n });\n })\n .catch((error) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.b. If the AI request fails, set to \"asking\" phase with error\n this.editor.commands._handleAiToolbarThinkingError(error);\n });\n\n return true;\n },\n\n $cancelAiToolbarThinking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Cancel the current AI request\n currentState.abortController.abort();\n\n // 3. Unblock the editor\n this.editor.setEditable(true);\n\n // 4. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n };\n\n return true;\n },\n\n _showAiToolbarReviewingDiff: () => () => {\n // The diff is applied right before moving to the \"reviewing\" phase\n if (this.storage.state.phase !== \"reviewing\") {\n return false;\n }\n\n if (!this.options.doc || !this.storage.snapshot) {\n return false;\n }\n\n const previousSnapshot: Snapshot =\n this.storage.snapshot ?? emptySnapshot;\n const currentSnapshot = takeSnapshot(this.options.doc);\n\n if (equalSnapshots(previousSnapshot, currentSnapshot)) {\n return true;\n }\n\n getYjsBinding(this.editor)?.renderSnapshot(\n currentSnapshot,\n previousSnapshot\n );\n\n return true;\n },\n\n _handleAiToolbarThinkingSuccess:\n (response: ContextualPromptResponse) =>\n ({ view, tr }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. If this is not a diff, the response will just be in the toolbar, set to \"reviewing\" phase directly with the response\n if (!isContextualPromptDiffResponse(response)) {\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n return true;\n }\n\n if (!this.options.doc) {\n return false;\n }\n\n // 3. Otherwise, the response is a diff, apply it to the editor\n this.options.doc.gc = false;\n this.storage.snapshot = takeSnapshot(this.options.doc);\n\n // 4. Set to \"reviewing\" phase with the new range\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n // 5. Insert the response's text as inline first (and replace the selection if it's a replace) then as block if there are multiple paragraphs\n const [firstParagraph, ...otherParagraphs] =\n response.text.split(\"\\n\");\n\n tr.insertText(\n firstParagraph,\n response.type === \"insert\"\n ? this.editor.state.selection.to\n : this.editor.state.selection.from,\n this.editor.state.selection.to\n );\n\n if (otherParagraphs.length > 0) {\n const paragraphs = otherParagraphs.map((paragraph) =>\n createParagraph(this.editor, paragraph)\n );\n\n tr.insert(tr.selection.$to.pos, paragraphs);\n }\n\n view.dispatch(tr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n\n // 6. Show the diff\n this.editor.commands._showAiToolbarReviewingDiff();\n\n // We moved to the \"reviewing\" phase, so even if `_showAiToolbarReviewingDiff`\n // returns `false` somehow, we still want to return `true`\n return true;\n },\n\n _handleAiToolbarThinkingError: (error: unknown) => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Unblock the editor\n this.editor.setEditable(true);\n\n // 3. Log the error\n console.error(error);\n\n // 4. Set to \"asking\" phase with error\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n // Pass the error so it can be displayed\n error:\n error instanceof Error\n ? error\n : new Error(String(error), { cause: error }),\n };\n\n return true;\n },\n\n _updateAiToolbarCustomPrompt:\n (customPrompt: string | ((currentCustomPrompt: string) => string)) =>\n () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in a phase with a custom prompt, do nothing\n if (typeof currentState.customPrompt !== \"string\") {\n return false;\n }\n\n // 2. Update the custom prompt\n this.storage.state.customPrompt =\n typeof customPrompt === \"function\"\n ? customPrompt(currentState.customPrompt)\n : customPrompt;\n\n return true;\n },\n };\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: AI_TOOLBAR_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n // Don't show the AI toolbar selection if the toolbar is closed or when reviewing diff responses\n if (\n this.storage.state.phase === \"closed\" ||\n (this.storage.state.phase === \"reviewing\" &&\n isContextualPromptDiffResponse(this.storage.state.response))\n ) {\n return DecorationSet.create(doc, []);\n }\n\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n ];\n },\n});\n"],"names":["takeSnapshot"],"mappings":"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"}
1
+ {"version":3,"file":"AiExtension.js","sources":["../../src/ai/AiExtension.ts"],"sourcesContent":["import {\n autoRetry,\n type ContextualPromptResponse,\n HttpError,\n} from \"@liveblocks/core\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { CommandProps, Editor } from \"@tiptap/core\";\nimport { Extension } from \"@tiptap/core\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { Transaction } from \"@tiptap/pm/state\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport {\n ySyncPluginKey,\n yXmlFragmentToProseMirrorFragment,\n} from \"y-prosemirror\";\nimport type { Doc, Snapshot } from \"yjs\";\nimport {\n createDocFromSnapshot,\n emptySnapshot,\n equalSnapshots,\n snapshot as takeSnapshot,\n} from \"yjs\";\n\nimport {\n AI_TOOLBAR_SELECTION_PLUGIN,\n type AiExtensionOptions,\n type AiExtensionStorage,\n type AiToolbarState,\n type ResolveContextualPromptResponse,\n type YSyncPluginState,\n} from \"../types\";\nimport { getContextualPromptContext } from \"../utils\";\n\nconst DEFAULT_AI_NAME = \"AI\";\nexport const DEFAULT_STATE: AiToolbarState = { phase: \"closed\" };\n\nconst RESOLVE_AI_PROMPT_RETRY_ATTEMPTS = 3;\nconst RESOLVE_AI_PROMPT_RETRY_DELAYS = [1000, 2000, 4000];\n\nfunction getYjsBinding(editor: Editor) {\n return (ySyncPluginKey.getState(editor.view.state) as YSyncPluginState)\n .binding;\n}\n\nfunction getLiveblocksYjsProvider(\n editor: Editor\n): LiveblocksYjsProvider | undefined {\n // Eslint doesn't seem to like Tiptap's Type declaration strategy\n return editor.extensionStorage.liveblocksExtension?.provider;\n}\n\nexport function isContextualPromptDiffResponse(\n response: ContextualPromptResponse\n): response is Extract<\n ContextualPromptResponse,\n { type: \"replace\" | \"insert\" }\n> {\n return response.type === \"replace\" || response.type === \"insert\";\n}\n\nfunction isResolveContextualPromptResponse(\n response: unknown\n): response is ResolveContextualPromptResponse {\n return (\n typeof response === \"object\" &&\n response !== null &&\n typeof (response as { text: unknown }).text === \"string\" &&\n typeof (response as { type: unknown }).type === \"string\" &&\n [\"insert\", \"replace\", \"other\"].includes((response as { type: string }).type)\n );\n}\n\nfunction createParagraph(editor: Editor, text: string) {\n const paragraph =\n editor.schema.nodes.paragraph ??\n Object.values(editor.schema.nodes).find((node) => node.isBlock);\n\n if (!paragraph) {\n throw new Error(\"Could not create a paragraph.\");\n }\n\n return paragraph.create(null, text ? editor.schema.text(text) : undefined);\n}\n\nfunction getRevertTransaction(\n tr: Transaction,\n editor: Editor,\n storage: AiExtensionStorage,\n doc?: Doc\n): Transaction | null {\n if (storage.snapshot) {\n const binding = getYjsBinding(editor);\n\n if (binding) {\n binding.mapping.clear();\n\n const docFromSnapshot = createDocFromSnapshot(\n binding.doc,\n storage.snapshot\n );\n const type = docFromSnapshot.getXmlFragment(\"default\"); // TODO: field\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n type,\n editor.state.schema\n );\n\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n if (doc) {\n doc.gc = true;\n }\n\n storage.snapshot = undefined;\n\n return tr;\n }\n }\n return null;\n}\n\nexport const AiExtension = Extension.create<\n AiExtensionOptions,\n AiExtensionStorage\n>({\n name: \"liveblocksAi\",\n addOptions() {\n return {\n doc: undefined,\n pud: undefined,\n\n // The actual default resolver is set in LiveblocksExtension via AiExtension.configure()\n resolveContextualPrompt: () =>\n Promise.reject(new Error(\"resolveContextualPrompt not configured\")),\n name: DEFAULT_AI_NAME,\n };\n },\n addStorage() {\n return {\n state: DEFAULT_STATE,\n name: this.options.name,\n };\n },\n addCommands() {\n return {\n askAi: (prompt) => () => {\n if (typeof prompt === \"string\") {\n this.editor.commands.$startAiToolbarThinking(prompt);\n } else {\n this.editor.commands.$openAiToolbarAsking();\n }\n\n return true;\n },\n\n closeAi: () => () => {\n this.editor.commands.$closeAiToolbar();\n\n return true;\n },\n\n $acceptAiToolbarResponse:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"reviewing\" phase, do nothing\n if (currentState.phase !== \"reviewing\") {\n return false;\n }\n\n // 2. Accept the response\n if (isContextualPromptDiffResponse(currentState.response)) {\n // 2.a. If the response is a diff, apply it definitely\n const binding = getYjsBinding(this.editor);\n if (!binding) {\n return false;\n }\n\n const fragmentContent = yXmlFragmentToProseMirrorFragment(\n binding.type,\n this.editor.state.schema\n );\n tr.setMeta(\"addToHistory\", false);\n tr.replace(\n 0,\n this.editor.state.doc.content.size,\n new Slice(Fragment.from(fragmentContent), 0, 0)\n );\n tr.setMeta(ySyncPluginKey, {\n snapshot: null,\n prevSnapshot: null,\n });\n\n this.storage.snapshot = undefined;\n } else {\n // 2.b. If the response is not a diff, insert it below the selection\n\n const paragraphs = currentState.response.text\n .split(\"\\n\")\n .map((paragraph) => createParagraph(this.editor, paragraph));\n\n tr.insert(this.editor.state.selection.$to.end(), paragraphs);\n tr.setMeta(\"addToHistory\", true);\n view.dispatch(tr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 4. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $closeAiToolbar:\n () =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If already in \"closed\" phase, do nothing\n if (currentState.phase === \"closed\") {\n return false;\n }\n\n // 2. If in \"thinking\" phase, cancel the current AI request\n if (currentState.phase === \"thinking\") {\n currentState.abortController.abort();\n }\n\n // 3. If in \"thinking\" or \"reviewing\" phase, revert the editor if possible and unblock it\n if (\n currentState.phase === \"thinking\" ||\n currentState.phase === \"reviewing\"\n ) {\n // Get the revert transaction and dispatch it\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n view.dispatch(revertTr);\n // Prevent TipTap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n }\n\n // 4. Restore the initial selection\n this.editor.commands.setTextSelection(currentState.initialSelection);\n\n // 5. Unblock the editor\n getLiveblocksYjsProvider(this.editor)?.unpause();\n this.editor.setEditable(true);\n\n // 6. Set to \"closed\" phase\n this.storage.state = { phase: \"closed\" };\n\n return true;\n },\n\n $openAiToolbarAsking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"closed\" phase, do nothing\n if (currentState.phase !== \"closed\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n // 3. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n // Store the initial selection\n initialSelection: {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty\n customPrompt: \"\",\n };\n\n return true;\n },\n\n $startAiToolbarThinking:\n (prompt: string, withPreviousResponse?: boolean) =>\n ({ tr, view }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If in \"thinking\" phase already, do nothing\n if (currentState.phase === \"thinking\") {\n return false;\n }\n\n // 2. Blur the editor if needed\n if (this.editor.isFocused) {\n this.editor.commands.blur();\n }\n\n const abortController = new AbortController();\n const provider = getLiveblocksYjsProvider(this.editor);\n\n // 3. If this is a retry or a refinement, revert the editor and restore the initial selection\n if (currentState.phase === \"reviewing\") {\n // 3.a. Revert the editor\n const revertTr = getRevertTransaction(\n tr,\n this.editor,\n this.storage,\n this.options.doc\n );\n if (revertTr) {\n // Important: in this scenario we do not unpause the provider\n view.dispatch(revertTr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n }\n\n // 3.b. Restore the initial selection\n this.editor.commands.setTextSelection(\n currentState.initialSelection\n );\n }\n\n // 4. Set to \"thinking\" phase\n this.storage.state = {\n phase: \"thinking\",\n // Store the initial selection if the toolbar is opened directly in the \"thinking\" phase\n initialSelection: currentState.initialSelection ?? {\n from: this.editor.state.selection.from,\n to: this.editor.state.selection.to,\n },\n // Initialize the custom prompt as empty if the toolbar is opened directly in the \"thinking\" phase\n customPrompt: currentState.customPrompt ?? \"\",\n prompt,\n abortController,\n previousResponse: currentState.response,\n };\n\n // 5. Block the editor\n this.editor.setEditable(false);\n\n // 6. Start the AI request\n autoRetry(\n async () => {\n await provider?.pause();\n\n // 6.a. Resolve the AI prompt\n const response = (await this.options.resolveContextualPrompt({\n prompt,\n context: getContextualPromptContext(this.editor, 3_000),\n signal: abortController.signal,\n previous:\n withPreviousResponse && currentState.phase === \"reviewing\"\n ? {\n prompt: currentState.prompt,\n response: {\n type: currentState.response?.type,\n text: currentState.response?.text,\n },\n }\n : undefined,\n })) as unknown;\n\n // 6.b. Validate the response\n if (isResolveContextualPromptResponse(response)) {\n return response;\n } else {\n throw new Error(\"Failed to resolve AI prompt.\");\n }\n },\n RESOLVE_AI_PROMPT_RETRY_ATTEMPTS,\n RESOLVE_AI_PROMPT_RETRY_DELAYS,\n\n (error) => {\n // Don't retry on 4xx errors or if the request was aborted\n return (\n abortController.signal.aborted ||\n (error instanceof HttpError &&\n error.status >= 400 &&\n error.status < 500)\n );\n }\n )\n .then((response) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.a. If the AI request succeeds, set to \"reviewing\" phase with the response\n this.editor.commands._handleAiToolbarThinkingSuccess({\n type: response.type,\n text: response.text,\n });\n })\n .catch((error) => {\n if (abortController.signal.aborted) {\n return;\n }\n\n // 6.b. If the AI request fails, set to \"asking\" phase with error\n this.editor.commands._handleAiToolbarThinkingError(error);\n });\n\n return true;\n },\n\n $cancelAiToolbarThinking: () => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Cancel the current AI request\n currentState.abortController.abort();\n\n // 3. Unblock the editor\n this.editor.setEditable(true);\n\n // 4. Set to \"asking\" phase\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n };\n\n return true;\n },\n\n _showAiToolbarReviewingDiff: () => () => {\n // The diff is applied right before moving to the \"reviewing\" phase\n if (this.storage.state.phase !== \"reviewing\") {\n return false;\n }\n\n if (!this.options.doc || !this.storage.snapshot) {\n return false;\n }\n\n const previousSnapshot: Snapshot =\n this.storage.snapshot ?? emptySnapshot;\n const currentSnapshot = takeSnapshot(this.options.doc);\n\n if (equalSnapshots(previousSnapshot, currentSnapshot)) {\n return true;\n }\n\n getYjsBinding(this.editor)?.renderSnapshot(\n currentSnapshot,\n previousSnapshot\n );\n\n return true;\n },\n\n _handleAiToolbarThinkingSuccess:\n (response: ContextualPromptResponse) =>\n ({ view, tr }: CommandProps) => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. If this is not a diff, the response will just be in the toolbar, set to \"reviewing\" phase directly with the response\n if (!isContextualPromptDiffResponse(response)) {\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n return true;\n }\n\n if (!this.options.doc) {\n return false;\n }\n\n // 3. Otherwise, the response is a diff, apply it to the editor\n this.options.doc.gc = false;\n this.storage.snapshot = takeSnapshot(this.options.doc);\n\n // 4. Set to \"reviewing\" phase with the new range\n this.storage.state = {\n phase: \"reviewing\",\n initialSelection: currentState.initialSelection,\n customPrompt: \"\",\n prompt: currentState.prompt,\n response,\n };\n\n // 5. Insert the response's text as inline first (and replace the selection if it's a replace) then as block if there are multiple paragraphs\n const [firstParagraph, ...otherParagraphs] =\n response.text.split(\"\\n\");\n\n tr.insertText(\n firstParagraph,\n response.type === \"insert\"\n ? this.editor.state.selection.to\n : this.editor.state.selection.from,\n this.editor.state.selection.to\n );\n\n if (otherParagraphs.length > 0) {\n const paragraphs = otherParagraphs.map((paragraph) =>\n createParagraph(this.editor, paragraph)\n );\n\n tr.insert(tr.selection.$to.pos, paragraphs);\n }\n\n view.dispatch(tr);\n // Prevent Tiptap from dispatching this transaction, because we already did (this is a hack)\n tr.setMeta(\"preventDispatch\", true);\n\n // 6. Show the diff\n this.editor.commands._showAiToolbarReviewingDiff();\n\n // We moved to the \"reviewing\" phase, so even if `_showAiToolbarReviewingDiff`\n // returns `false` somehow, we still want to return `true`\n return true;\n },\n\n _handleAiToolbarThinkingError: (error: unknown) => () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in \"thinking\" phase, do nothing\n if (currentState.phase !== \"thinking\") {\n return false;\n }\n\n // 2. Unblock the editor\n this.editor.setEditable(true);\n\n // 3. Log the error\n console.error(error);\n\n // 4. Set to \"asking\" phase with error\n this.storage.state = {\n phase: \"asking\",\n initialSelection: currentState.initialSelection,\n // If the custom prompt is different than the prompt, reset it\n customPrompt:\n currentState.prompt === currentState.customPrompt\n ? currentState.customPrompt\n : \"\",\n // Pass the error so it can be displayed\n error:\n error instanceof Error\n ? error\n : new Error(String(error), { cause: error }),\n };\n\n return true;\n },\n\n _updateAiToolbarCustomPrompt:\n (customPrompt: string | ((currentCustomPrompt: string) => string)) =>\n () => {\n const currentState = this.storage.state;\n\n // 1. If NOT in a phase with a custom prompt, do nothing\n if (typeof currentState.customPrompt !== \"string\") {\n return false;\n }\n\n // 2. Update the custom prompt\n this.storage.state.customPrompt =\n typeof customPrompt === \"function\"\n ? customPrompt(currentState.customPrompt)\n : customPrompt;\n\n return true;\n },\n };\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: AI_TOOLBAR_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n // Don't show the AI toolbar selection if the toolbar is closed or when reviewing diff responses\n if (\n this.storage.state.phase === \"closed\" ||\n (this.storage.state.phase === \"reviewing\" &&\n isContextualPromptDiffResponse(this.storage.state.response))\n ) {\n return DecorationSet.create(doc, []);\n }\n\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n ];\n },\n});\n"],"names":["takeSnapshot"],"mappings":"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"}
@@ -6,7 +6,6 @@ var model = require('@tiptap/pm/model');
6
6
  var state = require('@tiptap/pm/state');
7
7
  var view = require('@tiptap/pm/view');
8
8
  var yProsemirror = require('y-prosemirror');
9
- var plugin = require('../collaboration-liveblocks/plugin.cjs');
10
9
  var types = require('../types.cjs');
11
10
  var utils = require('../utils.cjs');
12
11
 
@@ -259,12 +258,7 @@ const CommentsExtension = core.Extension.create({
259
258
  };
260
259
  },
261
260
  onSelectionUpdate({ transaction }) {
262
- const yjsMeta = transaction.getMeta(yProsemirror.ySyncPluginKey);
263
- const liveblocksMeta = transaction.getMeta(
264
- plugin.LIVEBLOCKS_COLLABORATION_PLUGIN_KEY
265
- );
266
- const isRemoteCollaborationUpdate = yjsMeta || liveblocksMeta;
267
- if (this.storage.pendingComment && !isRemoteCollaborationUpdate) {
261
+ if (this.storage.pendingComment && !transaction.getMeta(yProsemirror.ySyncPluginKey)) {
268
262
  this.storage.pendingComment = false;
269
263
  }
270
264
  if (this.storage.pendingComment) return;
@@ -1 +1 @@
1
- {"version":3,"file":"CommentsExtension.cjs","sources":["../../src/comments/CommentsExtension.ts"],"sourcesContent":["import { shallow } from \"@liveblocks/core\";\nimport { type Editor, Extension, Mark, mergeAttributes } from \"@tiptap/core\";\nimport type {\n Mark as ProseMirrorMark,\n MarkType,\n Node,\n ResolvedPos,\n} from \"@tiptap/pm/model\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { EditorState, Transaction } from \"@tiptap/pm/state\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport { ySyncPluginKey } from \"y-prosemirror\";\n\nimport { LIVEBLOCKS_COLLABORATION_PLUGIN_KEY } from \"../collaboration-liveblocks/plugin\";\nimport type { CommentsExtensionStorage, ThreadPluginState } from \"../types\";\nimport {\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n ThreadPluginActions,\n THREADS_ACTIVE_SELECTION_PLUGIN,\n THREADS_PLUGIN_KEY,\n} from \"../types\";\nimport { areSetsEqual } from \"../utils\";\n\ntype ThreadPluginAction = {\n name: ThreadPluginActions;\n data: string[];\n};\n\nexport const FILTERED_THREADS_PLUGIN_KEY = new PluginKey<{\n filteredThreads?: Set<string>;\n}>();\n\nfunction getFilteredThreads(state: EditorState): Set<string> | undefined {\n return FILTERED_THREADS_PLUGIN_KEY.getState(state)?.filteredThreads;\n}\n\nfunction getVisibleThreadIdsFromMarks(\n marks: readonly ProseMirrorMark[],\n markType: MarkType,\n filteredThreads: Set<string> | undefined\n): string[] {\n const ids = new Set<string>();\n for (const mark of marks) {\n if (mark.type !== markType || mark.attrs.orphan) continue;\n const threadId = mark.attrs.threadId as string | undefined;\n if (!threadId) continue;\n if (filteredThreads && !filteredThreads.has(threadId)) continue;\n ids.add(threadId);\n }\n return [...ids];\n}\n\nfunction getVisibleThreadIdsAtPos(\n state: EditorState,\n $pos: ResolvedPos,\n markType: MarkType\n): string[] {\n return getVisibleThreadIdsFromMarks(\n $pos.marks(),\n markType,\n getFilteredThreads(state)\n );\n}\n\nfunction dispatchSetActiveThreadIds(view: EditorView, ids: string[]): void {\n view.dispatch(\n view.state.tr.setMeta(THREADS_PLUGIN_KEY, {\n name: ThreadPluginActions.SET_ACTIVE_THREAD_IDS,\n data: ids,\n } satisfies ThreadPluginAction)\n );\n}\n\nconst Comment = Mark.create({\n name: LIVEBLOCKS_COMMENT_MARK_TYPE,\n excludes: \"\",\n inclusive: false,\n keepOnSplit: true,\n parseHTML: () => {\n return [\n {\n tag: \"span\",\n getAttrs: (node) =>\n node.getAttribute(\"data-lb-thread-id\") !== null && null,\n },\n ];\n },\n addAttributes() {\n // Return an object with attribute configuration\n return {\n orphan: {\n parseHTML: (element) => !!element.getAttribute(\"data-orphan\"),\n renderHTML: (attributes) => {\n return (attributes as { orphan: boolean }).orphan\n ? {\n \"data-orphan\": \"true\",\n }\n : {};\n },\n default: false,\n },\n threadId: {\n parseHTML: (element) => element.getAttribute(\"data-lb-thread-id\"),\n renderHTML: (attributes) => {\n return {\n \"data-lb-thread-id\": (attributes as { threadId: string }).threadId,\n };\n },\n default: \"\",\n },\n };\n },\n\n renderHTML({ HTMLAttributes }: { HTMLAttributes: Record<string, any> }) {\n const filteredThreads = this.editor\n ? FILTERED_THREADS_PLUGIN_KEY.getState(this.editor.state)?.filteredThreads\n : undefined;\n const threadId = (HTMLAttributes as { [\"data-lb-thread-id\"]: string })[\n \"data-lb-thread-id\"\n ];\n if (filteredThreads && !filteredThreads.has(threadId)) {\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"lb-root lb-tiptap-thread-mark\",\n \"data-hidden\": \"\",\n }),\n ];\n }\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"lb-root lb-tiptap-thread-mark\",\n }),\n ];\n },\n\n /**\n * This plugin tracks the (first) position of each thread mark in the doc and creates a decoration for the selected thread\n */\n addProseMirrorPlugins() {\n const updateState = (\n doc: Node,\n activeThreadIds: string[],\n { scroll }: { scroll: boolean }\n ): ThreadPluginState => {\n const threadPositions = new Map<string, { from: number; to: number }>();\n const decorations: Decoration[] = [];\n const activeSet = new Set(activeThreadIds);\n\n doc.descendants((node, pos) => {\n for (const mark of node.marks) {\n if (mark.type !== this.type) continue;\n\n const threadId = (mark.attrs as { threadId?: string }).threadId;\n if (!threadId) continue;\n\n const from = pos;\n const to = from + node.nodeSize;\n\n // FloatingThreads component uses \"to\" as the position, so we always store the largest \"to\" found.\n // AnchoredThreads component uses \"from\" as the position, so we always store the smallest \"from\" found.\n const current = threadPositions.get(threadId) ?? {\n from: Infinity,\n to: 0,\n };\n threadPositions.set(threadId, {\n from: Math.min(from, current.from),\n to: Math.max(to, current.to),\n });\n\n if (activeSet.has(threadId)) {\n decorations.push(\n Decoration.inline(from, to, {\n class: \"lb-root lb-tiptap-thread-mark-selected\",\n })\n );\n }\n }\n });\n\n // Only scroll when the active selection explicitly changes.\n if (scroll && activeThreadIds.length > 0) {\n const [scrollTargetId] = activeThreadIds;\n const element = this.editor.view.dom.querySelector(\n `.lb-tiptap-thread-mark[data-lb-thread-id=\"${scrollTargetId}\"]`\n );\n element?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }\n\n return {\n decorations: DecorationSet.create(doc, decorations),\n activeThreadIds,\n threadPositions,\n };\n };\n\n // Recursively walks a Fragment and removes only this extension's comment mark from every node it finds.\n const stripCommentMarks = (slice: Slice): Slice => {\n const stripFragment = (fragment: Fragment): Fragment => {\n let changed = false;\n const nodes: Node[] = [];\n\n fragment.forEach((node) => {\n // Filter out this extension's comment mark from the node's marks so that it is not copied to the clipboard\n const nextMarks = node.marks.filter(\n (mark) => mark.type !== this.type\n );\n const marksChanged = nextMarks.length !== node.marks.length;\n\n // Recursively strip comment marks from child content (e.g. inline content inside paragraphs, list items)\n const nextContent =\n node.content.childCount > 0\n ? stripFragment(node.content)\n : node.content;\n const contentChanged = nextContent !== node.content;\n\n if (marksChanged || contentChanged) {\n changed = true;\n nodes.push(\n node.isText\n ? node.mark(nextMarks)\n : node.type.create(node.attrs, nextContent, nextMarks)\n );\n } else {\n nodes.push(node);\n }\n });\n\n return changed ? Fragment.fromArray(nodes) : fragment;\n };\n\n const content = stripFragment(slice.content);\n return content === slice.content\n ? slice\n : new Slice(content, slice.openStart, slice.openEnd);\n };\n\n return [\n new Plugin({\n key: new PluginKey(\"lb-comment-clipboard\"),\n props: {\n transformCopied: (slice) => stripCommentMarks(slice),\n transformPasted: (slice) => stripCommentMarks(slice),\n },\n }),\n new Plugin({\n key: THREADS_PLUGIN_KEY,\n state: {\n init(): ThreadPluginState {\n return {\n threadPositions: new Map(),\n activeThreadIds: [],\n decorations: DecorationSet.empty,\n };\n },\n apply(tr, state) {\n const action = tr.getMeta(THREADS_PLUGIN_KEY) as\n | ThreadPluginAction\n | undefined;\n\n if (!tr.docChanged && !action) {\n return state;\n }\n\n if (!action) {\n return updateState(tr.doc, state.activeThreadIds, {\n scroll: false,\n });\n }\n\n if (action.name === ThreadPluginActions.SET_ACTIVE_THREAD_IDS) {\n const idsChanged = !shallow(action.data, state.activeThreadIds);\n if (!tr.docChanged && !idsChanged) {\n return state;\n }\n return updateState(tr.doc, action.data, { scroll: idsChanged });\n }\n\n return state;\n },\n },\n props: {\n decorations: (state) => {\n return (\n THREADS_PLUGIN_KEY.getState(state)?.decorations ??\n DecorationSet.empty\n );\n },\n handleClick: (view, pos, event) => {\n if (event.button !== 0) return;\n\n const $pos = view.state.doc.resolve(pos);\n const ids = getVisibleThreadIdsAtPos(view.state, $pos, this.type);\n dispatchSetActiveThreadIds(view, ids);\n },\n },\n }),\n ];\n },\n});\n\nexport const CommentsExtension = Extension.create<\n { filteredThreads?: Set<string> },\n CommentsExtensionStorage\n>({\n name: \"liveblocksComments\",\n priority: 95,\n addExtensions() {\n return [Comment];\n },\n\n addStorage() {\n return {\n pendingComment: false,\n };\n },\n\n addCommands() {\n return {\n addPendingComment: () => () => {\n if (this.editor.state.selection.empty) {\n return false;\n }\n // Unselect any open threads.\n dispatchSetActiveThreadIds(this.editor.view, []);\n this.storage.pendingComment = true;\n return true;\n },\n closePendingComment: () => () => {\n this.storage.pendingComment = false;\n return true;\n },\n selectThread: (id: string | null) => () => {\n // If the target thread is filtered out, clear the active selection\n // instead of selecting an invisible thread.\n const filtered = getFilteredThreads(this.editor.state);\n const nextIds =\n id === null || (filtered && !filtered.has(id)) ? [] : [id];\n\n dispatchSetActiveThreadIds(this.editor.view, nextIds);\n return true;\n },\n addComment:\n (id: string) =>\n ({ commands }) => {\n if (\n !this.storage.pendingComment ||\n this.editor.state.selection.empty\n ) {\n return false;\n }\n commands.setMark(LIVEBLOCKS_COMMENT_MARK_TYPE, { threadId: id });\n this.storage.pendingComment = false;\n return true;\n },\n };\n },\n onSelectionUpdate(\n this: { storage: CommentsExtensionStorage; editor: Editor },\n { transaction }: { transaction: Transaction }\n ) {\n const yjsMeta: unknown = transaction.getMeta(ySyncPluginKey);\n const liveblocksMeta: unknown = transaction.getMeta(\n LIVEBLOCKS_COLLABORATION_PLUGIN_KEY\n );\n const isRemoteCollaborationUpdate = yjsMeta || liveblocksMeta;\n\n // Close any pending composer when the user moves the selection locally\n // (but ignore remote collaboration-driven selection changes).\n if (this.storage.pendingComment && !isRemoteCollaborationUpdate) {\n this.storage.pendingComment = false;\n }\n\n if (this.storage.pendingComment) return;\n\n const { state } = this.editor;\n const markType = state.schema.marks[LIVEBLOCKS_COMMENT_MARK_TYPE];\n if (!markType) return;\n\n const ids = getVisibleThreadIdsAtPos(\n state,\n state.selection.$from,\n markType\n );\n const current = THREADS_PLUGIN_KEY.getState(state)?.activeThreadIds ?? [];\n if (shallow(ids, current)) return;\n\n dispatchSetActiveThreadIds(this.editor.view, ids);\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: THREADS_ACTIVE_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n if (!this.storage.pendingComment) {\n return DecorationSet.create(doc, []);\n }\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n new Plugin({\n key: FILTERED_THREADS_PLUGIN_KEY,\n state: {\n init: () => ({\n filteredThreads: this.options.filteredThreads,\n }),\n apply(tr, value) {\n const meta = tr.getMeta(FILTERED_THREADS_PLUGIN_KEY) as\n | { filteredThreads?: Set<string> }\n | undefined;\n if (meta?.filteredThreads) {\n return { filteredThreads: meta.filteredThreads };\n }\n return value;\n },\n },\n view: (view) => {\n const syncDom = () => {\n const filteredThreads = FILTERED_THREADS_PLUGIN_KEY.getState(\n view.state\n )?.filteredThreads;\n\n // Toggle attribute for all comment-mark spans\n const els = view.dom.querySelectorAll<HTMLElement>(\n \"span.lb-tiptap-thread-mark[data-lb-thread-id]\"\n );\n els.forEach((el) => {\n const id = el.getAttribute(\"data-lb-thread-id\");\n if (!id) return;\n if (!filteredThreads || filteredThreads.has(id)) {\n el.removeAttribute(\"data-hidden\");\n } else {\n el.setAttribute(\"data-hidden\", \"\");\n }\n });\n };\n\n queueMicrotask(syncDom);\n\n return {\n update: (view, prevState) => {\n const curr = FILTERED_THREADS_PLUGIN_KEY.getState(\n view.state\n )?.filteredThreads;\n const prev =\n FILTERED_THREADS_PLUGIN_KEY.getState(\n prevState\n )?.filteredThreads;\n\n if (\n !areSetsEqual(prev, curr) ||\n view.state.doc !== prevState.doc\n ) {\n syncDom();\n\n const active =\n THREADS_PLUGIN_KEY.getState(view.state)?.activeThreadIds ??\n [];\n\n if (active.length && curr) {\n const next = active.filter((id) => curr.has(id));\n if (next.length !== active.length) {\n dispatchSetActiveThreadIds(view, next);\n }\n }\n }\n },\n };\n },\n }),\n ];\n },\n});\n"],"names":["PluginKey","THREADS_PLUGIN_KEY","ThreadPluginActions","Mark","LIVEBLOCKS_COMMENT_MARK_TYPE","mergeAttributes","Decoration","DecorationSet","Fragment","Slice","Plugin","shallow","Extension","ySyncPluginKey","LIVEBLOCKS_COLLABORATION_PLUGIN_KEY","THREADS_ACTIVE_SELECTION_PLUGIN","view","areSetsEqual"],"mappings":"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"}
1
+ {"version":3,"file":"CommentsExtension.cjs","sources":["../../src/comments/CommentsExtension.ts"],"sourcesContent":["import { shallow } from \"@liveblocks/core\";\nimport { type Editor, Extension, Mark, mergeAttributes } from \"@tiptap/core\";\nimport type {\n Mark as ProseMirrorMark,\n MarkType,\n Node,\n ResolvedPos,\n} from \"@tiptap/pm/model\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { EditorState, Transaction } from \"@tiptap/pm/state\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport { ySyncPluginKey } from \"y-prosemirror\";\n\nimport type { CommentsExtensionStorage, ThreadPluginState } from \"../types\";\nimport {\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n ThreadPluginActions,\n THREADS_ACTIVE_SELECTION_PLUGIN,\n THREADS_PLUGIN_KEY,\n} from \"../types\";\nimport { areSetsEqual } from \"../utils\";\n\ntype ThreadPluginAction = {\n name: ThreadPluginActions;\n data: string[];\n};\n\nexport const FILTERED_THREADS_PLUGIN_KEY = new PluginKey<{\n filteredThreads?: Set<string>;\n}>();\n\nfunction getFilteredThreads(state: EditorState): Set<string> | undefined {\n return FILTERED_THREADS_PLUGIN_KEY.getState(state)?.filteredThreads;\n}\n\nfunction getVisibleThreadIdsFromMarks(\n marks: readonly ProseMirrorMark[],\n markType: MarkType,\n filteredThreads: Set<string> | undefined\n): string[] {\n const ids = new Set<string>();\n for (const mark of marks) {\n if (mark.type !== markType || mark.attrs.orphan) continue;\n const threadId = mark.attrs.threadId as string | undefined;\n if (!threadId) continue;\n if (filteredThreads && !filteredThreads.has(threadId)) continue;\n ids.add(threadId);\n }\n return [...ids];\n}\n\nfunction getVisibleThreadIdsAtPos(\n state: EditorState,\n $pos: ResolvedPos,\n markType: MarkType\n): string[] {\n return getVisibleThreadIdsFromMarks(\n $pos.marks(),\n markType,\n getFilteredThreads(state)\n );\n}\n\nfunction dispatchSetActiveThreadIds(view: EditorView, ids: string[]): void {\n view.dispatch(\n view.state.tr.setMeta(THREADS_PLUGIN_KEY, {\n name: ThreadPluginActions.SET_ACTIVE_THREAD_IDS,\n data: ids,\n } satisfies ThreadPluginAction)\n );\n}\n\nconst Comment = Mark.create({\n name: LIVEBLOCKS_COMMENT_MARK_TYPE,\n excludes: \"\",\n inclusive: false,\n keepOnSplit: true,\n parseHTML: () => {\n return [\n {\n tag: \"span\",\n getAttrs: (node) =>\n node.getAttribute(\"data-lb-thread-id\") !== null && null,\n },\n ];\n },\n addAttributes() {\n // Return an object with attribute configuration\n return {\n orphan: {\n parseHTML: (element) => !!element.getAttribute(\"data-orphan\"),\n renderHTML: (attributes) => {\n return (attributes as { orphan: boolean }).orphan\n ? {\n \"data-orphan\": \"true\",\n }\n : {};\n },\n default: false,\n },\n threadId: {\n parseHTML: (element) => element.getAttribute(\"data-lb-thread-id\"),\n renderHTML: (attributes) => {\n return {\n \"data-lb-thread-id\": (attributes as { threadId: string }).threadId,\n };\n },\n default: \"\",\n },\n };\n },\n\n renderHTML({ HTMLAttributes }: { HTMLAttributes: Record<string, any> }) {\n const filteredThreads = this.editor\n ? FILTERED_THREADS_PLUGIN_KEY.getState(this.editor.state)?.filteredThreads\n : undefined;\n const threadId = (HTMLAttributes as { [\"data-lb-thread-id\"]: string })[\n \"data-lb-thread-id\"\n ];\n if (filteredThreads && !filteredThreads.has(threadId)) {\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"lb-root lb-tiptap-thread-mark\",\n \"data-hidden\": \"\",\n }),\n ];\n }\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"lb-root lb-tiptap-thread-mark\",\n }),\n ];\n },\n\n /**\n * This plugin tracks the (first) position of each thread mark in the doc and creates a decoration for the selected thread\n */\n addProseMirrorPlugins() {\n const updateState = (\n doc: Node,\n activeThreadIds: string[],\n { scroll }: { scroll: boolean }\n ): ThreadPluginState => {\n const threadPositions = new Map<string, { from: number; to: number }>();\n const decorations: Decoration[] = [];\n const activeSet = new Set(activeThreadIds);\n\n doc.descendants((node, pos) => {\n for (const mark of node.marks) {\n if (mark.type !== this.type) continue;\n\n const threadId = (mark.attrs as { threadId?: string }).threadId;\n if (!threadId) continue;\n\n const from = pos;\n const to = from + node.nodeSize;\n\n // FloatingThreads component uses \"to\" as the position, so we always store the largest \"to\" found.\n // AnchoredThreads component uses \"from\" as the position, so we always store the smallest \"from\" found.\n const current = threadPositions.get(threadId) ?? {\n from: Infinity,\n to: 0,\n };\n threadPositions.set(threadId, {\n from: Math.min(from, current.from),\n to: Math.max(to, current.to),\n });\n\n if (activeSet.has(threadId)) {\n decorations.push(\n Decoration.inline(from, to, {\n class: \"lb-root lb-tiptap-thread-mark-selected\",\n })\n );\n }\n }\n });\n\n // Only scroll when the active selection explicitly changes.\n if (scroll && activeThreadIds.length > 0) {\n const [scrollTargetId] = activeThreadIds;\n const element = this.editor.view.dom.querySelector(\n `.lb-tiptap-thread-mark[data-lb-thread-id=\"${scrollTargetId}\"]`\n );\n element?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }\n\n return {\n decorations: DecorationSet.create(doc, decorations),\n activeThreadIds,\n threadPositions,\n };\n };\n\n // Recursively walks a Fragment and removes only this extension's comment mark from every node it finds.\n const stripCommentMarks = (slice: Slice): Slice => {\n const stripFragment = (fragment: Fragment): Fragment => {\n let changed = false;\n const nodes: Node[] = [];\n\n fragment.forEach((node) => {\n // Filter out this extension's comment mark from the node's marks so that it is not copied to the clipboard\n const nextMarks = node.marks.filter(\n (mark) => mark.type !== this.type\n );\n const marksChanged = nextMarks.length !== node.marks.length;\n\n // Recursively strip comment marks from child content (e.g. inline content inside paragraphs, list items)\n const nextContent =\n node.content.childCount > 0\n ? stripFragment(node.content)\n : node.content;\n const contentChanged = nextContent !== node.content;\n\n if (marksChanged || contentChanged) {\n changed = true;\n nodes.push(\n node.isText\n ? node.mark(nextMarks)\n : node.type.create(node.attrs, nextContent, nextMarks)\n );\n } else {\n nodes.push(node);\n }\n });\n\n return changed ? Fragment.fromArray(nodes) : fragment;\n };\n\n const content = stripFragment(slice.content);\n return content === slice.content\n ? slice\n : new Slice(content, slice.openStart, slice.openEnd);\n };\n\n return [\n new Plugin({\n key: new PluginKey(\"lb-comment-clipboard\"),\n props: {\n transformCopied: (slice) => stripCommentMarks(slice),\n transformPasted: (slice) => stripCommentMarks(slice),\n },\n }),\n new Plugin({\n key: THREADS_PLUGIN_KEY,\n state: {\n init(): ThreadPluginState {\n return {\n threadPositions: new Map(),\n activeThreadIds: [],\n decorations: DecorationSet.empty,\n };\n },\n apply(tr, state) {\n const action = tr.getMeta(THREADS_PLUGIN_KEY) as\n | ThreadPluginAction\n | undefined;\n\n if (!tr.docChanged && !action) {\n return state;\n }\n\n if (!action) {\n return updateState(tr.doc, state.activeThreadIds, {\n scroll: false,\n });\n }\n\n if (action.name === ThreadPluginActions.SET_ACTIVE_THREAD_IDS) {\n const idsChanged = !shallow(action.data, state.activeThreadIds);\n if (!tr.docChanged && !idsChanged) {\n return state;\n }\n return updateState(tr.doc, action.data, { scroll: idsChanged });\n }\n\n return state;\n },\n },\n props: {\n decorations: (state) => {\n return (\n THREADS_PLUGIN_KEY.getState(state)?.decorations ??\n DecorationSet.empty\n );\n },\n handleClick: (view, pos, event) => {\n if (event.button !== 0) return;\n\n const $pos = view.state.doc.resolve(pos);\n const ids = getVisibleThreadIdsAtPos(view.state, $pos, this.type);\n dispatchSetActiveThreadIds(view, ids);\n },\n },\n }),\n ];\n },\n});\n\nexport const CommentsExtension = Extension.create<\n { filteredThreads?: Set<string> },\n CommentsExtensionStorage\n>({\n name: \"liveblocksComments\",\n priority: 95,\n addExtensions() {\n return [Comment];\n },\n\n addStorage() {\n return {\n pendingComment: false,\n };\n },\n\n addCommands() {\n return {\n addPendingComment: () => () => {\n if (this.editor.state.selection.empty) {\n return false;\n }\n // Unselect any open threads.\n dispatchSetActiveThreadIds(this.editor.view, []);\n this.storage.pendingComment = true;\n return true;\n },\n closePendingComment: () => () => {\n this.storage.pendingComment = false;\n return true;\n },\n selectThread: (id: string | null) => () => {\n // If the target thread is filtered out, clear the active selection\n // instead of selecting an invisible thread.\n const filtered = getFilteredThreads(this.editor.state);\n const nextIds =\n id === null || (filtered && !filtered.has(id)) ? [] : [id];\n\n dispatchSetActiveThreadIds(this.editor.view, nextIds);\n return true;\n },\n addComment:\n (id: string) =>\n ({ commands }) => {\n if (\n !this.storage.pendingComment ||\n this.editor.state.selection.empty\n ) {\n return false;\n }\n commands.setMark(LIVEBLOCKS_COMMENT_MARK_TYPE, { threadId: id });\n this.storage.pendingComment = false;\n return true;\n },\n };\n },\n onSelectionUpdate(\n this: { storage: CommentsExtensionStorage; editor: Editor },\n { transaction }: { transaction: Transaction }\n ) {\n // Close any pending composer when the user moves the selection locally\n // (but ignore remote Yjs-driven selection changes).\n if (this.storage.pendingComment && !transaction.getMeta(ySyncPluginKey)) {\n this.storage.pendingComment = false;\n }\n\n if (this.storage.pendingComment) return;\n\n const { state } = this.editor;\n const markType = state.schema.marks[LIVEBLOCKS_COMMENT_MARK_TYPE];\n if (!markType) return;\n\n const ids = getVisibleThreadIdsAtPos(\n state,\n state.selection.$from,\n markType\n );\n const current = THREADS_PLUGIN_KEY.getState(state)?.activeThreadIds ?? [];\n if (shallow(ids, current)) return;\n\n dispatchSetActiveThreadIds(this.editor.view, ids);\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: THREADS_ACTIVE_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n if (!this.storage.pendingComment) {\n return DecorationSet.create(doc, []);\n }\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n new Plugin({\n key: FILTERED_THREADS_PLUGIN_KEY,\n state: {\n init: () => ({\n filteredThreads: this.options.filteredThreads,\n }),\n apply(tr, value) {\n const meta = tr.getMeta(FILTERED_THREADS_PLUGIN_KEY) as\n | { filteredThreads?: Set<string> }\n | undefined;\n if (meta?.filteredThreads) {\n return { filteredThreads: meta.filteredThreads };\n }\n return value;\n },\n },\n view: (view) => {\n const syncDom = () => {\n const filteredThreads = FILTERED_THREADS_PLUGIN_KEY.getState(\n view.state\n )?.filteredThreads;\n\n // Toggle attribute for all comment-mark spans\n const els = view.dom.querySelectorAll<HTMLElement>(\n \"span.lb-tiptap-thread-mark[data-lb-thread-id]\"\n );\n els.forEach((el) => {\n const id = el.getAttribute(\"data-lb-thread-id\");\n if (!id) return;\n if (!filteredThreads || filteredThreads.has(id)) {\n el.removeAttribute(\"data-hidden\");\n } else {\n el.setAttribute(\"data-hidden\", \"\");\n }\n });\n };\n\n queueMicrotask(syncDom);\n\n return {\n update: (view, prevState) => {\n const curr = FILTERED_THREADS_PLUGIN_KEY.getState(\n view.state\n )?.filteredThreads;\n const prev =\n FILTERED_THREADS_PLUGIN_KEY.getState(\n prevState\n )?.filteredThreads;\n\n if (\n !areSetsEqual(prev, curr) ||\n view.state.doc !== prevState.doc\n ) {\n syncDom();\n\n const active =\n THREADS_PLUGIN_KEY.getState(view.state)?.activeThreadIds ??\n [];\n\n if (active.length && curr) {\n const next = active.filter((id) => curr.has(id));\n if (next.length !== active.length) {\n dispatchSetActiveThreadIds(view, next);\n }\n }\n }\n },\n };\n },\n }),\n ];\n },\n});\n"],"names":["PluginKey","THREADS_PLUGIN_KEY","ThreadPluginActions","Mark","LIVEBLOCKS_COMMENT_MARK_TYPE","mergeAttributes","Decoration","DecorationSet","Fragment","Slice","Plugin","shallow","Extension","ySyncPluginKey","THREADS_ACTIVE_SELECTION_PLUGIN","view","areSetsEqual"],"mappings":"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"}
@@ -4,7 +4,6 @@ import { Fragment, Slice } from '@tiptap/pm/model';
4
4
  import { PluginKey, Plugin } from '@tiptap/pm/state';
5
5
  import { Decoration, DecorationSet } from '@tiptap/pm/view';
6
6
  import { ySyncPluginKey } from 'y-prosemirror';
7
- import { LIVEBLOCKS_COLLABORATION_PLUGIN_KEY } from '../collaboration-liveblocks/plugin.js';
8
7
  import { THREADS_PLUGIN_KEY, ThreadPluginActions, LIVEBLOCKS_COMMENT_MARK_TYPE, THREADS_ACTIVE_SELECTION_PLUGIN } from '../types.js';
9
8
  import { areSetsEqual } from '../utils.js';
10
9
 
@@ -257,12 +256,7 @@ const CommentsExtension = Extension.create({
257
256
  };
258
257
  },
259
258
  onSelectionUpdate({ transaction }) {
260
- const yjsMeta = transaction.getMeta(ySyncPluginKey);
261
- const liveblocksMeta = transaction.getMeta(
262
- LIVEBLOCKS_COLLABORATION_PLUGIN_KEY
263
- );
264
- const isRemoteCollaborationUpdate = yjsMeta || liveblocksMeta;
265
- if (this.storage.pendingComment && !isRemoteCollaborationUpdate) {
259
+ if (this.storage.pendingComment && !transaction.getMeta(ySyncPluginKey)) {
266
260
  this.storage.pendingComment = false;
267
261
  }
268
262
  if (this.storage.pendingComment) return;