@platejs/ai 49.0.0

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.
@@ -0,0 +1,1215 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/react/index.ts
31
+ var react_exports = {};
32
+ __export(react_exports, {
33
+ AIChatPlugin: () => AIChatPlugin,
34
+ AIPlugin: () => AIPlugin,
35
+ CopilotPlugin: () => CopilotPlugin,
36
+ acceptAIChat: () => acceptAIChat,
37
+ acceptCopilot: () => acceptCopilot,
38
+ acceptCopilotNextWord: () => acceptCopilotNextWord,
39
+ callCompletionApi: () => callCompletionApi,
40
+ createFormattedBlocks: () => createFormattedBlocks,
41
+ getEditorPrompt: () => getEditorPrompt,
42
+ getLastAssistantMessage: () => getLastAssistantMessage,
43
+ getMarkdown: () => getMarkdown,
44
+ getNextWord: () => getNextWord,
45
+ insertBelowAIChat: () => insertBelowAIChat,
46
+ removeAnchorAIChat: () => removeAnchorAIChat,
47
+ renderCopilotBelowNodes: () => renderCopilotBelowNodes,
48
+ replaceSelectionAIChat: () => replaceSelectionAIChat,
49
+ resetAIChat: () => resetAIChat,
50
+ submitAIChat: () => submitAIChat,
51
+ triggerCopilotSuggestion: () => triggerCopilotSuggestion,
52
+ useAIChatEditor: () => useAIChatEditor,
53
+ useChatChunk: () => useChatChunk,
54
+ useEditorChat: () => useEditorChat,
55
+ useLastAssistantMessage: () => useLastAssistantMessage,
56
+ withAIChat: () => withAIChat,
57
+ withCopilot: () => withCopilot,
58
+ withoutAbort: () => withoutAbort
59
+ });
60
+ module.exports = __toCommonJS(react_exports);
61
+
62
+ // src/react/ai/AIPlugin.ts
63
+ var import_react = require("platejs/react");
64
+
65
+ // src/lib/BaseAIPlugin.ts
66
+ var import_platejs2 = require("platejs");
67
+
68
+ // src/lib/transforms/insertAINodes.ts
69
+ var insertAINodes = (editor, nodes, {
70
+ target
71
+ } = {}) => {
72
+ if (!target && !editor.selection?.focus.path) return;
73
+ const aiNodes = nodes.map((node) => ({
74
+ ...node,
75
+ ai: true
76
+ }));
77
+ editor.tf.withoutNormalizing(() => {
78
+ editor.tf.insertNodes(aiNodes, {
79
+ at: editor.api.end(target || editor.selection.focus.path),
80
+ select: true
81
+ });
82
+ editor.tf.collapse({ edge: "end" });
83
+ });
84
+ };
85
+
86
+ // src/lib/transforms/removeAIMarks.ts
87
+ var removeAIMarks = (editor, { at = [] } = {}) => {
88
+ editor.tf.unsetNodes("ai", {
89
+ at,
90
+ match: (n) => n.ai
91
+ });
92
+ };
93
+
94
+ // src/lib/transforms/removeAINodes.ts
95
+ var import_platejs = require("platejs");
96
+ var removeAINodes = (editor, { at = [] } = {}) => {
97
+ editor.tf.removeNodes({
98
+ at,
99
+ match: (n) => import_platejs.TextApi.isText(n) && !!n.ai
100
+ });
101
+ };
102
+
103
+ // src/lib/transforms/undoAI.ts
104
+ var undoAI = (editor) => {
105
+ if (editor.history.undos.at(-1)?.ai && editor.api.some({
106
+ at: [],
107
+ match: (n) => !!n.ai
108
+ })) {
109
+ editor.undo();
110
+ editor.history.redos.pop();
111
+ }
112
+ };
113
+
114
+ // src/lib/transforms/withAIBatch.ts
115
+ var withAIBatch = (editor, fn, {
116
+ split
117
+ } = {}) => {
118
+ if (split) {
119
+ editor.tf.withNewBatch(fn);
120
+ } else {
121
+ editor.tf.withMerging(fn);
122
+ }
123
+ const lastBatch = editor.history.undos?.at(-1);
124
+ if (lastBatch) {
125
+ lastBatch.ai = true;
126
+ }
127
+ };
128
+
129
+ // src/lib/BaseAIPlugin.ts
130
+ var BaseAIPlugin = (0, import_platejs2.createTSlatePlugin)({
131
+ key: import_platejs2.KEYS.ai,
132
+ node: { isDecoration: false, isLeaf: true }
133
+ }).extendTransforms(({ editor }) => ({
134
+ insertNodes: (0, import_platejs2.bindFirst)(insertAINodes, editor),
135
+ removeMarks: (0, import_platejs2.bindFirst)(removeAIMarks, editor),
136
+ removeNodes: (0, import_platejs2.bindFirst)(removeAINodes, editor),
137
+ undo: (0, import_platejs2.bindFirst)(undoAI, editor)
138
+ }));
139
+
140
+ // src/react/ai/AIPlugin.ts
141
+ var AIPlugin = (0, import_react.toPlatePlugin)(BaseAIPlugin);
142
+
143
+ // src/react/ai-chat/AIChatPlugin.ts
144
+ var import_react9 = require("@platejs/selection/react");
145
+ var import_platejs11 = require("platejs");
146
+ var import_react10 = require("platejs/react");
147
+
148
+ // src/react/ai-chat/transforms/acceptAIChat.ts
149
+ var import_platejs3 = require("platejs");
150
+ var import_react2 = require("platejs/react");
151
+ var acceptAIChat = (editor) => {
152
+ const { tf } = (0, import_react2.getEditorPlugin)(editor, AIPlugin);
153
+ const api = editor.getApi({ key: import_platejs3.KEYS.ai });
154
+ const lastAINodePath = api.aiChat.node({ at: [], reverse: true })[1];
155
+ withAIBatch(editor, () => {
156
+ tf.ai.removeMarks();
157
+ editor.getTransforms(AIChatPlugin).aiChat.removeAnchor();
158
+ });
159
+ api.aiChat.hide();
160
+ editor.tf.focus();
161
+ const focusPoint = editor.api.end(lastAINodePath);
162
+ editor.tf.setSelection({
163
+ anchor: focusPoint,
164
+ focus: focusPoint
165
+ });
166
+ };
167
+
168
+ // src/react/ai-chat/transforms/insertBelowAIChat.ts
169
+ var import_react4 = require("@platejs/selection/react");
170
+ var import_cloneDeep2 = __toESM(require("lodash/cloneDeep.js"));
171
+ var import_platejs5 = require("platejs");
172
+
173
+ // src/react/ai-chat/transforms/replaceSelectionAIChat.ts
174
+ var import_react3 = require("@platejs/selection/react");
175
+ var import_cloneDeep = __toESM(require("lodash/cloneDeep.js"));
176
+ var import_platejs4 = require("platejs");
177
+ var createFormattedBlocks = ({
178
+ blocks,
179
+ format,
180
+ sourceBlock
181
+ }) => {
182
+ if (format === "none") return (0, import_cloneDeep.default)(blocks);
183
+ const [sourceNode] = sourceBlock;
184
+ const firstTextEntry = import_platejs4.NodeApi.firstText(sourceNode);
185
+ if (!firstTextEntry) return null;
186
+ const blockProps = import_platejs4.NodeApi.extractProps(sourceNode);
187
+ const textProps = import_platejs4.NodeApi.extractProps(firstTextEntry[0]);
188
+ const applyTextFormatting = (node) => {
189
+ if (import_platejs4.TextApi.isText(node)) {
190
+ return { ...textProps, ...node };
191
+ }
192
+ if (node.children) {
193
+ return {
194
+ ...node,
195
+ children: node.children.map(applyTextFormatting)
196
+ };
197
+ }
198
+ return node;
199
+ };
200
+ return blocks.map((block, index) => {
201
+ if (format === "single" && index > 0) {
202
+ return block;
203
+ }
204
+ return applyTextFormatting({
205
+ ...block,
206
+ ...blockProps
207
+ });
208
+ });
209
+ };
210
+ var replaceSelectionAIChat = (editor, sourceEditor, { format = "single" } = {}) => {
211
+ if (!sourceEditor || sourceEditor.api.isEmpty()) return;
212
+ const isBlockSelecting = editor.getOption(
213
+ import_react3.BlockSelectionPlugin,
214
+ "isSelectingSome"
215
+ );
216
+ editor.getApi({ key: import_platejs4.KEYS.ai }).aiChat.hide();
217
+ if (!isBlockSelecting) {
218
+ const firstBlock = editor.api.node({
219
+ block: true,
220
+ mode: "lowest"
221
+ });
222
+ if (firstBlock && editor.api.isSelected(firstBlock[1], { contains: true }) && format !== "none") {
223
+ const formattedBlocks2 = createFormattedBlocks({
224
+ blocks: (0, import_cloneDeep.default)(sourceEditor.children),
225
+ format,
226
+ sourceBlock: firstBlock
227
+ });
228
+ if (!formattedBlocks2) return;
229
+ editor.tf.insertFragment(formattedBlocks2);
230
+ editor.tf.focus();
231
+ return;
232
+ }
233
+ editor.tf.insertFragment(sourceEditor.children);
234
+ editor.tf.focus();
235
+ return;
236
+ }
237
+ const blockSelectionApi = editor.getApi(import_react3.BlockSelectionPlugin).blockSelection;
238
+ const selectedBlocks = blockSelectionApi.getNodes();
239
+ if (selectedBlocks.length === 0) return;
240
+ if (format === "none" || format === "single" && selectedBlocks.length > 1) {
241
+ editor.tf.withoutNormalizing(() => {
242
+ (0, import_react3.removeBlockSelectionNodes)(editor);
243
+ editor.tf.withNewBatch(() => {
244
+ editor.getTransforms(import_react3.BlockSelectionPlugin).blockSelection.insertBlocksAndSelect(
245
+ (0, import_cloneDeep.default)(sourceEditor.children),
246
+ {
247
+ at: selectedBlocks[0][1]
248
+ }
249
+ );
250
+ });
251
+ });
252
+ editor.getApi(import_react3.BlockSelectionPlugin).blockSelection.focus();
253
+ return;
254
+ }
255
+ const [, firstBlockPath] = selectedBlocks[0];
256
+ const formattedBlocks = createFormattedBlocks({
257
+ blocks: (0, import_cloneDeep.default)(sourceEditor.children),
258
+ format,
259
+ sourceBlock: selectedBlocks[0]
260
+ });
261
+ if (!formattedBlocks) return;
262
+ editor.tf.withoutNormalizing(() => {
263
+ (0, import_react3.removeBlockSelectionNodes)(editor);
264
+ editor.tf.withNewBatch(() => {
265
+ editor.getTransforms(import_react3.BlockSelectionPlugin).blockSelection.insertBlocksAndSelect(formattedBlocks, {
266
+ at: firstBlockPath
267
+ });
268
+ });
269
+ });
270
+ editor.getApi(import_react3.BlockSelectionPlugin).blockSelection.focus();
271
+ };
272
+
273
+ // src/react/ai-chat/transforms/insertBelowAIChat.ts
274
+ var insertBelowAIChat = (editor, sourceEditor, { format = "single" } = {}) => {
275
+ if (!sourceEditor || sourceEditor.api.isEmpty()) return;
276
+ const isBlockSelecting = editor.getOption(
277
+ import_react4.BlockSelectionPlugin,
278
+ "isSelectingSome"
279
+ );
280
+ editor.getApi({ key: import_platejs5.KEYS.ai }).aiChat.hide();
281
+ const insertBlocksAndSelect = editor.getTransforms(import_react4.BlockSelectionPlugin).blockSelection.insertBlocksAndSelect;
282
+ if (isBlockSelecting) {
283
+ const selectedBlocks = editor.getApi(import_react4.BlockSelectionPlugin).blockSelection.getNodes();
284
+ const selectedIds = editor.getOptions(import_react4.BlockSelectionPlugin).selectedIds;
285
+ if (!selectedIds || selectedIds.size === 0) return;
286
+ const lastBlock = selectedBlocks.at(-1);
287
+ if (!lastBlock) return;
288
+ const nextPath = import_platejs5.PathApi.next(lastBlock[1]);
289
+ if (format === "none") {
290
+ insertBlocksAndSelect((0, import_cloneDeep2.default)(sourceEditor.children), {
291
+ at: nextPath
292
+ });
293
+ return;
294
+ }
295
+ const formattedBlocks = createFormattedBlocks({
296
+ blocks: (0, import_cloneDeep2.default)(sourceEditor.children),
297
+ format,
298
+ sourceBlock: lastBlock
299
+ });
300
+ if (!formattedBlocks) return;
301
+ insertBlocksAndSelect(formattedBlocks, {
302
+ at: nextPath
303
+ });
304
+ } else {
305
+ const [, end] = import_platejs5.RangeApi.edges(editor.selection);
306
+ const endPath = [end.path[0]];
307
+ const currentBlock = editor.api.node({
308
+ at: endPath,
309
+ block: true,
310
+ mode: "lowest"
311
+ });
312
+ if (!currentBlock) return;
313
+ if (format === "none") {
314
+ insertBlocksAndSelect((0, import_cloneDeep2.default)(sourceEditor.children), {
315
+ at: import_platejs5.PathApi.next(endPath)
316
+ });
317
+ return;
318
+ }
319
+ const formattedBlocks = createFormattedBlocks({
320
+ blocks: (0, import_cloneDeep2.default)(sourceEditor.children),
321
+ format,
322
+ sourceBlock: currentBlock
323
+ });
324
+ if (!formattedBlocks) return;
325
+ insertBlocksAndSelect(formattedBlocks, {
326
+ at: import_platejs5.PathApi.next(endPath)
327
+ });
328
+ }
329
+ };
330
+
331
+ // src/react/ai-chat/transforms/removeAnchorAIChat.ts
332
+ var import_platejs6 = require("platejs");
333
+ var removeAnchorAIChat = (editor, options) => {
334
+ editor.tf.withoutSaving(() => {
335
+ editor.tf.removeNodes({
336
+ at: [],
337
+ match: (n) => import_platejs6.ElementApi.isElement(n) && n.type === import_platejs6.KEYS.aiChat,
338
+ ...options
339
+ });
340
+ });
341
+ };
342
+
343
+ // src/react/ai-chat/utils/getEditorPrompt.ts
344
+ var import_selection = require("@platejs/selection");
345
+ var import_react6 = require("@platejs/selection/react");
346
+
347
+ // src/react/ai-chat/utils/getMarkdown.ts
348
+ var import_markdown = require("@platejs/markdown");
349
+ var import_react5 = require("@platejs/selection/react");
350
+ var import_platejs7 = require("platejs");
351
+ var getMarkdown = (editor, type) => {
352
+ if (type === "editor") {
353
+ return (0, import_markdown.serializeMd)(editor);
354
+ }
355
+ if (type === "block") {
356
+ const blocks = editor.getOption(import_react5.BlockSelectionPlugin, "isSelectingSome") ? editor.getApi(import_react5.BlockSelectionPlugin).blockSelection.getNodes() : editor.api.nodes({
357
+ mode: "highest",
358
+ match: (n) => editor.api.isBlock(n)
359
+ });
360
+ const nodes = Array.from(blocks, (entry) => entry[0]);
361
+ return (0, import_markdown.serializeMd)(editor, { value: nodes });
362
+ }
363
+ if (type === "selection") {
364
+ const fragment = editor.api.fragment();
365
+ if (fragment.length === 1) {
366
+ const modifiedFragment = [
367
+ {
368
+ children: fragment[0].children,
369
+ type: import_platejs7.KEYS.p
370
+ }
371
+ ];
372
+ return (0, import_markdown.serializeMd)(editor, { value: modifiedFragment });
373
+ }
374
+ return (0, import_markdown.serializeMd)(editor, { value: fragment });
375
+ }
376
+ return "";
377
+ };
378
+
379
+ // src/react/ai-chat/utils/getEditorPrompt.ts
380
+ var replacePlaceholders = (editor, text, {
381
+ prompt
382
+ }) => {
383
+ let result = text.replace("{prompt}", prompt || "");
384
+ const placeholders = {
385
+ "{block}": "block",
386
+ "{editor}": "editor",
387
+ "{selection}": "selection"
388
+ };
389
+ Object.entries(placeholders).forEach(([placeholder, type]) => {
390
+ if (result.includes(placeholder)) {
391
+ result = result.replace(placeholder, getMarkdown(editor, type));
392
+ }
393
+ });
394
+ return result;
395
+ };
396
+ var createPromptFromConfig = (config, params) => {
397
+ const { isBlockSelecting, isSelecting: isSelecting3 } = params;
398
+ if (isBlockSelecting && config.blockSelecting) {
399
+ return config.blockSelecting ?? config.default;
400
+ } else if (isSelecting3 && config.selecting) {
401
+ return config.selecting ?? config.default;
402
+ } else {
403
+ return config.default;
404
+ }
405
+ };
406
+ var getEditorPrompt = (editor, {
407
+ prompt = "",
408
+ promptTemplate = () => "{prompt}"
409
+ } = {}) => {
410
+ const params = {
411
+ editor,
412
+ isBlockSelecting: editor.getOption(import_react6.BlockSelectionPlugin, "isSelectingSome"),
413
+ isSelecting: (0, import_selection.isSelecting)(editor)
414
+ };
415
+ const template = promptTemplate(params);
416
+ if (!template) return;
417
+ let promptText = "";
418
+ if (typeof prompt === "function") {
419
+ promptText = prompt(params);
420
+ } else if (typeof prompt === "object") {
421
+ promptText = createPromptFromConfig(prompt, params);
422
+ } else {
423
+ promptText = prompt;
424
+ }
425
+ return replacePlaceholders(editor, template, {
426
+ prompt: promptText
427
+ });
428
+ };
429
+
430
+ // src/react/ai-chat/utils/resetAIChat.ts
431
+ var import_platejs8 = require("platejs");
432
+ var import_react7 = require("platejs/react");
433
+ var resetAIChat = (editor) => {
434
+ const { api, getOptions } = (0, import_react7.getEditorPlugin)(editor, {
435
+ key: import_platejs8.KEYS.aiChat
436
+ });
437
+ api.aiChat.stop();
438
+ const chat = getOptions().chat;
439
+ if (chat.messages && chat.messages.length > 0) {
440
+ chat.setMessages?.([]);
441
+ }
442
+ editor.getTransforms(AIPlugin).ai.undo();
443
+ };
444
+
445
+ // src/react/ai-chat/utils/submitAIChat.ts
446
+ var import_selection2 = require("@platejs/selection");
447
+ var import_platejs9 = require("platejs");
448
+ var import_react8 = require("platejs/react");
449
+ var submitAIChat = (editor, {
450
+ mode,
451
+ options,
452
+ prompt,
453
+ system
454
+ } = {}) => {
455
+ const { getOptions, setOption } = (0, import_react8.getEditorPlugin)(
456
+ editor,
457
+ {
458
+ key: import_platejs9.KEYS.aiChat
459
+ }
460
+ );
461
+ const { chat, promptTemplate, systemTemplate } = getOptions();
462
+ if (!prompt && chat.input?.length === 0) {
463
+ return;
464
+ }
465
+ if (!prompt) {
466
+ prompt = chat.input;
467
+ }
468
+ if (!mode) {
469
+ mode = (0, import_selection2.isSelecting)(editor) ? "chat" : "insert";
470
+ }
471
+ if (mode === "insert") {
472
+ editor.getTransforms(AIPlugin).ai.undo();
473
+ }
474
+ setOption("mode", mode);
475
+ chat.setInput?.("");
476
+ void chat.append?.(
477
+ {
478
+ content: getEditorPrompt(editor, {
479
+ prompt,
480
+ promptTemplate
481
+ }) ?? "",
482
+ role: "user"
483
+ },
484
+ {
485
+ body: {
486
+ system: getEditorPrompt(editor, {
487
+ prompt: system,
488
+ promptTemplate: systemTemplate
489
+ })
490
+ },
491
+ ...options
492
+ }
493
+ );
494
+ };
495
+
496
+ // src/react/ai-chat/withAIChat.ts
497
+ var import_platejs10 = require("platejs");
498
+ var withAIChat = ({
499
+ api,
500
+ editor,
501
+ getOptions,
502
+ tf: { insertText, normalizeNode, setSelection },
503
+ type
504
+ }) => {
505
+ const tf = editor.getTransforms(AIPlugin);
506
+ const matchesTrigger = (text) => {
507
+ const { trigger } = getOptions();
508
+ if (trigger instanceof RegExp) {
509
+ return trigger.test(text);
510
+ }
511
+ if (Array.isArray(trigger)) {
512
+ return trigger.includes(text);
513
+ }
514
+ return text === trigger;
515
+ };
516
+ return {
517
+ transforms: {
518
+ insertText(text, options) {
519
+ const { triggerPreviousCharPattern, triggerQuery } = getOptions();
520
+ const fn = () => {
521
+ if (!editor.selection || !matchesTrigger(text) || triggerQuery && !triggerQuery(editor)) {
522
+ return;
523
+ }
524
+ const previousChar = editor.api.string(
525
+ editor.api.range("before", editor.selection)
526
+ );
527
+ const matchesPreviousCharPattern = triggerPreviousCharPattern?.test(previousChar);
528
+ if (!matchesPreviousCharPattern) return;
529
+ const nodeEntry = editor.api.block({ highest: true });
530
+ if (!nodeEntry || !editor.api.isEmpty(nodeEntry[0])) return;
531
+ api.aiChat.show();
532
+ return true;
533
+ };
534
+ if (fn()) return;
535
+ return insertText(text, options);
536
+ },
537
+ normalizeNode(entry) {
538
+ const [node, path] = entry;
539
+ if (node[import_platejs10.KEYS.ai] && !getOptions().open) {
540
+ tf.ai.removeMarks({ at: path });
541
+ return;
542
+ }
543
+ if (import_platejs10.ElementApi.isElement(node) && node.type === type && !getOptions().open) {
544
+ editor.getTransforms(AIChatPlugin).aiChat.removeAnchor({ at: path });
545
+ return;
546
+ }
547
+ return normalizeNode(entry);
548
+ }
549
+ }
550
+ };
551
+ };
552
+
553
+ // src/react/ai-chat/AIChatPlugin.ts
554
+ var AIChatPlugin = (0, import_react10.createTPlatePlugin)({
555
+ key: import_platejs11.KEYS.aiChat,
556
+ dependencies: ["ai"],
557
+ node: {
558
+ isElement: true
559
+ },
560
+ options: {
561
+ _blockChunks: "",
562
+ _blockPath: null,
563
+ aiEditor: null,
564
+ chat: { messages: [] },
565
+ experimental_lastTextId: null,
566
+ mode: "chat",
567
+ open: false,
568
+ streaming: false,
569
+ trigger: " ",
570
+ triggerPreviousCharPattern: /^\s?$/,
571
+ promptTemplate: () => "{prompt}",
572
+ systemTemplate: () => {
573
+ }
574
+ }
575
+ }).overrideEditor(withAIChat).extendApi(({ editor, getOption, getOptions, setOption, type }) => {
576
+ return {
577
+ reset: (0, import_platejs11.bindFirst)(resetAIChat, editor),
578
+ submit: (0, import_platejs11.bindFirst)(submitAIChat, editor),
579
+ node: (options = {}) => {
580
+ const { anchor = false, streaming = false, ...rest } = options;
581
+ if (anchor) {
582
+ return editor.api.node({
583
+ at: [],
584
+ match: (n) => import_platejs11.ElementApi.isElement(n) && n.type === type,
585
+ ...rest
586
+ });
587
+ }
588
+ if (streaming) {
589
+ if (!getOption("streaming")) return;
590
+ const path = getOption("_blockPath");
591
+ if (!path) return;
592
+ return editor.api.node({
593
+ at: path,
594
+ mode: "lowest",
595
+ reverse: true,
596
+ match: (t) => !!t.ai,
597
+ ...rest
598
+ });
599
+ }
600
+ return editor.api.node({
601
+ match: (n) => n.ai,
602
+ ...rest
603
+ });
604
+ },
605
+ reload: () => {
606
+ const { chat, mode } = getOptions();
607
+ if (mode === "insert") {
608
+ editor.getTransforms(AIPlugin).ai.undo();
609
+ }
610
+ void chat.reload?.({
611
+ body: {
612
+ system: getEditorPrompt(editor, {
613
+ promptTemplate: getOptions().systemTemplate
614
+ })
615
+ }
616
+ });
617
+ },
618
+ stop: () => {
619
+ setOption("streaming", false);
620
+ getOptions().chat.stop?.();
621
+ }
622
+ };
623
+ }).extendApi(({ api, editor, getOptions, setOption, tf, type }) => ({
624
+ hide: () => {
625
+ api.aiChat.reset();
626
+ setOption("open", false);
627
+ if (editor.getOption(import_react9.BlockSelectionPlugin, "isSelectingSome")) {
628
+ } else {
629
+ editor.tf.focus();
630
+ }
631
+ const lastBatch = editor.history.undos.at(-1);
632
+ if (lastBatch?.ai) {
633
+ delete lastBatch.ai;
634
+ }
635
+ tf.aiChat.removeAnchor();
636
+ },
637
+ show: () => {
638
+ api.aiChat.reset();
639
+ getOptions().chat.setMessages?.([]);
640
+ setOption("open", true);
641
+ }
642
+ })).extendTransforms(({ editor }) => ({
643
+ accept: (0, import_platejs11.bindFirst)(acceptAIChat, editor),
644
+ insertBelow: (0, import_platejs11.bindFirst)(insertBelowAIChat, editor),
645
+ removeAnchor: (0, import_platejs11.bindFirst)(removeAnchorAIChat, editor),
646
+ replaceSelection: (0, import_platejs11.bindFirst)(replaceSelectionAIChat, editor)
647
+ }));
648
+
649
+ // src/react/ai-chat/hooks/useAIChatEditor.ts
650
+ var import_react11 = require("react");
651
+ var import_markdown2 = require("@platejs/markdown");
652
+ var import_react12 = require("platejs/react");
653
+ var useAIChatEditor = (editor, content, { parser } = {}) => {
654
+ const { setOption } = (0, import_react12.useEditorPlugin)(AIChatPlugin);
655
+ editor.children = (0, import_react11.useMemo)(
656
+ () => {
657
+ return editor.getApi(import_markdown2.MarkdownPlugin).markdown.deserialize(content, {
658
+ memoize: true,
659
+ parser
660
+ });
661
+ },
662
+ // eslint-disable-next-line react-hooks/exhaustive-deps
663
+ [content]
664
+ );
665
+ (0, import_react11.useEffect)(() => {
666
+ setOption("aiEditor", editor);
667
+ }, [editor, setOption]);
668
+ };
669
+
670
+ // src/react/ai-chat/hooks/useChatChunk.ts
671
+ var import_react14 = require("react");
672
+ var import_platejs12 = require("platejs");
673
+ var import_react15 = require("platejs/react");
674
+
675
+ // src/react/ai-chat/utils/getLastAssistantMessage.ts
676
+ var import_react13 = require("platejs/react");
677
+ function getLastAssistantMessage(editor) {
678
+ const messages = editor.getOptions(AIChatPlugin).chat.messages;
679
+ return messages?.findLast((message) => message.role === "assistant");
680
+ }
681
+ function useLastAssistantMessage() {
682
+ const chat = (0, import_react13.usePluginOption)(AIChatPlugin, "chat");
683
+ return chat.messages?.findLast((message) => message.role === "assistant");
684
+ }
685
+
686
+ // src/react/ai-chat/hooks/useChatChunk.ts
687
+ var useChatChunk = ({
688
+ onChunk,
689
+ onFinish
690
+ }) => {
691
+ const { isLoading } = (0, import_react15.usePluginOption)(
692
+ { key: import_platejs12.KEYS.aiChat },
693
+ "chat"
694
+ );
695
+ const content = useLastAssistantMessage()?.content;
696
+ const insertedTextRef = (0, import_react14.useRef)("");
697
+ const prevIsLoadingRef = (0, import_react14.useRef)(isLoading);
698
+ (0, import_react14.useEffect)(() => {
699
+ if (!isLoading) {
700
+ insertedTextRef.current = "";
701
+ }
702
+ if (prevIsLoadingRef.current && !isLoading) {
703
+ onFinish?.({ content: content ?? "" });
704
+ }
705
+ prevIsLoadingRef.current = isLoading;
706
+ }, [isLoading]);
707
+ (0, import_react14.useEffect)(() => {
708
+ if (!content) {
709
+ return;
710
+ }
711
+ const chunk = content.slice(insertedTextRef.current.length);
712
+ const nodes = [];
713
+ if (chunk) {
714
+ const isFirst = insertedTextRef.current === "";
715
+ nodes.push({ text: chunk });
716
+ onChunk({
717
+ chunk,
718
+ isFirst,
719
+ nodes,
720
+ text: content
721
+ });
722
+ }
723
+ insertedTextRef.current = content;
724
+ }, [content]);
725
+ };
726
+
727
+ // src/react/ai-chat/hooks/useEditorChat.ts
728
+ var import_react16 = require("react");
729
+ var import_react17 = require("@platejs/selection/react");
730
+ var import_react18 = require("platejs/react");
731
+ var useEditorChat = ({
732
+ chat,
733
+ onOpenBlockSelection,
734
+ onOpenChange,
735
+ onOpenCursor,
736
+ onOpenSelection
737
+ }) => {
738
+ const { editor, setOption } = (0, import_react18.useEditorPlugin)(AIChatPlugin);
739
+ const open = (0, import_react18.usePluginOption)(AIChatPlugin, "open");
740
+ (0, import_react16.useEffect)(() => {
741
+ setOption("chat", chat);
742
+ }, [chat.input, chat.messages, chat.isLoading, chat.data, chat.error]);
743
+ (0, import_react16.useEffect)(() => {
744
+ onOpenChange?.(open);
745
+ if (open) {
746
+ if (onOpenBlockSelection) {
747
+ const blockSelectionApi = editor.getApi(import_react17.BlockSelectionPlugin).blockSelection;
748
+ const isBlockSelecting = editor.getOption(
749
+ import_react17.BlockSelectionPlugin,
750
+ "isSelectingSome"
751
+ );
752
+ if (isBlockSelecting) {
753
+ onOpenBlockSelection(blockSelectionApi.getNodes());
754
+ return;
755
+ }
756
+ }
757
+ if (onOpenCursor && editor.api.isCollapsed()) {
758
+ onOpenCursor();
759
+ return;
760
+ }
761
+ if (onOpenSelection && editor.api.isExpanded()) {
762
+ onOpenSelection();
763
+ return;
764
+ }
765
+ }
766
+ }, [open]);
767
+ };
768
+
769
+ // src/react/copilot/CopilotPlugin.tsx
770
+ var import_markdown6 = require("@platejs/markdown");
771
+ var import_debounce = __toESM(require("lodash/debounce.js"));
772
+ var import_platejs18 = require("platejs");
773
+ var import_react23 = require("platejs/react");
774
+
775
+ // src/react/copilot/renderCopilotBelowNodes.tsx
776
+ var import_react19 = __toESM(require("react"));
777
+ var import_platejs13 = require("platejs");
778
+ var import_react20 = require("platejs/react");
779
+ var renderCopilotBelowNodes = ({
780
+ editor
781
+ }) => {
782
+ const copilot = (0, import_react20.getEditorPlugin)(editor, {
783
+ key: import_platejs13.KEYS.copilot
784
+ });
785
+ const { renderGhostText: GhostText } = copilot.getOptions();
786
+ if (!GhostText) return;
787
+ return ({ children }) => {
788
+ return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, children, /* @__PURE__ */ import_react19.default.createElement(GhostText, null));
789
+ };
790
+ };
791
+
792
+ // src/react/copilot/transforms/acceptCopilot.ts
793
+ var import_markdown3 = require("@platejs/markdown");
794
+ var import_platejs14 = require("platejs");
795
+ var acceptCopilot = (editor) => {
796
+ const { suggestionText } = editor.getOptions({
797
+ key: import_platejs14.KEYS.copilot
798
+ });
799
+ if (!suggestionText?.length) return false;
800
+ editor.tf.insertFragment((0, import_markdown3.deserializeInlineMd)(editor, suggestionText));
801
+ };
802
+
803
+ // src/react/copilot/transforms/acceptCopilotNextWord.ts
804
+ var import_markdown4 = require("@platejs/markdown");
805
+ var import_platejs16 = require("platejs");
806
+ var import_react22 = require("platejs/react");
807
+
808
+ // src/react/copilot/utils/callCompletionApi.ts
809
+ var getOriginalFetch = () => fetch;
810
+ async function callCompletionApi({
811
+ api = "/api/completion",
812
+ body,
813
+ credentials,
814
+ fetch: fetch2 = getOriginalFetch(),
815
+ headers,
816
+ prompt,
817
+ setAbortController = () => {
818
+ },
819
+ setCompletion = () => {
820
+ },
821
+ setError = () => {
822
+ },
823
+ setLoading = () => {
824
+ },
825
+ onError,
826
+ onFinish,
827
+ onResponse
828
+ }) {
829
+ try {
830
+ setLoading(true);
831
+ setError(null);
832
+ const abortController = new AbortController();
833
+ setAbortController(abortController);
834
+ setCompletion("");
835
+ const res = await fetch2(api, {
836
+ body: JSON.stringify({
837
+ prompt,
838
+ ...body
839
+ }),
840
+ credentials,
841
+ headers: {
842
+ "Content-Type": "application/json",
843
+ ...headers
844
+ },
845
+ method: "POST",
846
+ signal: abortController.signal
847
+ }).catch((error) => {
848
+ throw error;
849
+ });
850
+ if (onResponse) {
851
+ await onResponse(res);
852
+ }
853
+ if (!res.ok) {
854
+ throw new Error(
855
+ await res.text() || "Failed to fetch the chat response."
856
+ );
857
+ }
858
+ if (!res.body) {
859
+ throw new Error("The response body is empty.");
860
+ }
861
+ const { text } = await res.json();
862
+ if (!text) {
863
+ throw new Error("The response does not contain a text field.");
864
+ }
865
+ setCompletion(text);
866
+ if (onFinish) {
867
+ onFinish(prompt, text);
868
+ }
869
+ setAbortController(null);
870
+ return text;
871
+ } catch (error) {
872
+ if (error.name === "AbortError") {
873
+ setAbortController(null);
874
+ return null;
875
+ }
876
+ if (error instanceof Error && onError) {
877
+ onError(error);
878
+ }
879
+ setError(error);
880
+ } finally {
881
+ setLoading(false);
882
+ }
883
+ }
884
+
885
+ // src/react/copilot/utils/getNextWord.ts
886
+ var getNextWord = ({ text }) => {
887
+ if (!text) return { firstWord: "", remainingText: "" };
888
+ const nonSpaceMatch = /^\s*(\S)/.exec(text);
889
+ if (!nonSpaceMatch) return { firstWord: "", remainingText: "" };
890
+ const firstNonSpaceChar = nonSpaceMatch[1];
891
+ const isCJKChar = /[\u1100-\u11FF\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF]/.test(
892
+ firstNonSpaceChar
893
+ );
894
+ let firstWord, remainingText;
895
+ if (isCJKChar) {
896
+ const match = /^(\s*)([\u1100-\u11FF\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF])([\u3000-\u303F\uFF00-\uFFEF])?/.exec(
897
+ text
898
+ );
899
+ if (match) {
900
+ const [fullMatch, spaces = "", char = "", punctuation = ""] = match;
901
+ firstWord = spaces + char + punctuation;
902
+ remainingText = text.slice(firstWord.length);
903
+ } else {
904
+ firstWord = "";
905
+ remainingText = text;
906
+ }
907
+ } else {
908
+ const match = /^(\s*\S+?)(?=[\s\u1100-\u11FF\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF]|$)/.exec(
909
+ text
910
+ );
911
+ if (match) {
912
+ firstWord = match[0];
913
+ remainingText = text.slice(firstWord.length);
914
+ } else {
915
+ firstWord = text;
916
+ remainingText = "";
917
+ }
918
+ }
919
+ return { firstWord, remainingText };
920
+ };
921
+
922
+ // src/react/copilot/utils/triggerCopilotSuggestion.ts
923
+ var import_platejs15 = require("platejs");
924
+ var import_react21 = require("platejs/react");
925
+ var triggerCopilotSuggestion = async (editor) => {
926
+ const { api, getOptions, setOption } = (0, import_react21.getEditorPlugin)(
927
+ editor,
928
+ {
929
+ key: import_platejs15.KEYS.copilot
930
+ }
931
+ );
932
+ const { completeOptions, getPrompt, isLoading, triggerQuery } = getOptions();
933
+ if (isLoading || editor.getOptions({ key: import_platejs15.KEYS.aiChat }).chat?.isLoading) {
934
+ return false;
935
+ }
936
+ if (!triggerQuery({ editor })) return false;
937
+ const prompt = getPrompt({ editor });
938
+ if (prompt.length === 0) return false;
939
+ api.copilot.stop();
940
+ await callCompletionApi({
941
+ prompt,
942
+ onFinish: (_, completion) => {
943
+ api.copilot.setBlockSuggestion({ text: completion });
944
+ },
945
+ ...completeOptions,
946
+ setAbortController: (controller) => setOption("abortController", controller),
947
+ setCompletion: (completion) => setOption("completion", completion),
948
+ setError: (error) => setOption("error", error),
949
+ setLoading: (loading) => setOption("isLoading", loading),
950
+ onError: (error) => {
951
+ setOption("error", error);
952
+ completeOptions?.onError?.(error);
953
+ }
954
+ });
955
+ };
956
+
957
+ // src/react/copilot/utils/withoutAbort.ts
958
+ var withoutAbort = (editor, fn) => {
959
+ editor.setOption(CopilotPlugin, "shouldAbort", false);
960
+ fn();
961
+ editor.setOption(CopilotPlugin, "shouldAbort", true);
962
+ };
963
+
964
+ // src/react/copilot/transforms/acceptCopilotNextWord.ts
965
+ var acceptCopilotNextWord = (editor) => {
966
+ const { api, getOptions } = (0, import_react22.getEditorPlugin)(editor, {
967
+ key: import_platejs16.KEYS.copilot
968
+ });
969
+ const { getNextWord: getNextWord2, suggestionText } = getOptions();
970
+ if (!suggestionText?.length) {
971
+ return false;
972
+ }
973
+ const { firstWord, remainingText } = getNextWord2({ text: suggestionText });
974
+ api.copilot.setBlockSuggestion({
975
+ text: remainingText
976
+ });
977
+ withoutAbort(editor, () => {
978
+ editor.tf.insertFragment((0, import_markdown4.deserializeInlineMd)(editor, firstWord));
979
+ });
980
+ };
981
+
982
+ // src/react/copilot/withCopilot.ts
983
+ var import_markdown5 = require("@platejs/markdown");
984
+ var import_platejs17 = require("platejs");
985
+ var getPatchString = (editor, operations) => {
986
+ let string = "";
987
+ for (const operation of operations) {
988
+ if (operation.type === "insert_node") {
989
+ const node = operation.node;
990
+ const text = (0, import_markdown5.serializeInlineMd)(editor, { value: [node] });
991
+ string += text;
992
+ } else if (operation.type === "insert_text") {
993
+ string += operation.text;
994
+ }
995
+ }
996
+ return string;
997
+ };
998
+ var withCopilot = ({
999
+ api,
1000
+ editor,
1001
+ getOptions,
1002
+ setOption,
1003
+ tf: { apply, insertText, redo, setSelection, undo, writeHistory }
1004
+ }) => {
1005
+ let prevSelection = null;
1006
+ return {
1007
+ transforms: {
1008
+ apply(operation) {
1009
+ const { shouldAbort } = getOptions();
1010
+ if (shouldAbort) {
1011
+ api.copilot.reject();
1012
+ }
1013
+ apply(operation);
1014
+ },
1015
+ insertText(text, options) {
1016
+ const suggestionText = getOptions().suggestionText;
1017
+ if (suggestionText?.startsWith(text)) {
1018
+ withoutAbort(editor, () => {
1019
+ editor.tf.withoutMerging(() => {
1020
+ const newText = suggestionText?.slice(text.length);
1021
+ setOption("suggestionText", newText);
1022
+ insertText(text);
1023
+ });
1024
+ });
1025
+ return;
1026
+ }
1027
+ insertText(text, options);
1028
+ },
1029
+ redo() {
1030
+ if (!getOptions().suggestionText) return redo();
1031
+ const topRedo = editor.history.redos.at(-1);
1032
+ const prevSuggestion = getOptions().suggestionText;
1033
+ if (topRedo && topRedo.shouldAbort === false && prevSuggestion) {
1034
+ withoutAbort(editor, () => {
1035
+ const shouldRemoveText = getPatchString(editor, topRedo.operations);
1036
+ const newText = prevSuggestion.slice(shouldRemoveText.length);
1037
+ setOption("suggestionText", newText);
1038
+ redo();
1039
+ });
1040
+ return;
1041
+ }
1042
+ return redo();
1043
+ },
1044
+ setSelection(props) {
1045
+ setSelection(props);
1046
+ if (editor.selection && (!prevSelection || !import_platejs17.RangeApi.equals(prevSelection, editor.selection)) && getOptions().autoTriggerQuery({ editor }) && editor.api.isFocused()) {
1047
+ void api.copilot.triggerSuggestion();
1048
+ }
1049
+ prevSelection = editor.selection;
1050
+ },
1051
+ undo() {
1052
+ if (!getOptions().suggestionText) return undo();
1053
+ const lastUndos = editor.history.undos.at(-1);
1054
+ const oldText = getOptions().suggestionText;
1055
+ if (lastUndos && lastUndos.shouldAbort === false && oldText) {
1056
+ withoutAbort(editor, () => {
1057
+ const shouldInsertText = getPatchString(
1058
+ editor,
1059
+ lastUndos.operations
1060
+ );
1061
+ const newText = shouldInsertText + oldText;
1062
+ setOption("suggestionText", newText);
1063
+ undo();
1064
+ });
1065
+ return;
1066
+ }
1067
+ return undo();
1068
+ },
1069
+ writeHistory(stacks, batch) {
1070
+ if (!getOptions().isLoading) {
1071
+ batch.shouldAbort = getOptions().shouldAbort;
1072
+ }
1073
+ return writeHistory(stacks, batch);
1074
+ }
1075
+ }
1076
+ };
1077
+ };
1078
+
1079
+ // src/react/copilot/CopilotPlugin.tsx
1080
+ var CopilotPlugin = (0, import_react23.createTPlatePlugin)({
1081
+ key: import_platejs18.KEYS.copilot,
1082
+ handlers: {
1083
+ onBlur: ({ api }) => {
1084
+ api.copilot.reject();
1085
+ },
1086
+ onMouseDown: ({ api }) => {
1087
+ api.copilot.reject();
1088
+ }
1089
+ },
1090
+ options: {
1091
+ abortController: null,
1092
+ completeOptions: {},
1093
+ completion: "",
1094
+ debounceDelay: 0,
1095
+ error: null,
1096
+ getNextWord,
1097
+ isLoading: false,
1098
+ renderGhostText: null,
1099
+ shouldAbort: true,
1100
+ suggestionNodeId: null,
1101
+ suggestionText: null,
1102
+ autoTriggerQuery: ({ editor }) => {
1103
+ if (editor.getOptions({ key: import_platejs18.KEYS.copilot }).suggestionText) {
1104
+ return false;
1105
+ }
1106
+ const isEmpty = editor.api.isEmpty(editor.selection, { block: true });
1107
+ if (isEmpty) return false;
1108
+ const blockAbove = editor.api.block();
1109
+ if (!blockAbove) return false;
1110
+ const blockString = import_platejs18.NodeApi.string(blockAbove[0]);
1111
+ return blockString.at(-1) === " ";
1112
+ },
1113
+ getPrompt: ({ editor }) => {
1114
+ const contextEntry = editor.api.block({ highest: true });
1115
+ if (!contextEntry) return "";
1116
+ return (0, import_markdown6.serializeMd)(editor, {
1117
+ value: [contextEntry[0]]
1118
+ });
1119
+ },
1120
+ triggerQuery: ({ editor }) => {
1121
+ if (editor.api.isExpanded()) return false;
1122
+ const isEnd = editor.api.isAt({ end: true });
1123
+ if (!isEnd) return false;
1124
+ return true;
1125
+ }
1126
+ }
1127
+ }).overrideEditor(withCopilot).extendSelectors(({ getOptions }) => ({
1128
+ isSuggested: (id) => getOptions().suggestionNodeId === id
1129
+ })).extendTransforms(({ editor }) => ({
1130
+ accept: (0, import_platejs18.bindFirst)(acceptCopilot, editor),
1131
+ acceptNextWord: (0, import_platejs18.bindFirst)(acceptCopilotNextWord, editor)
1132
+ })).extendApi(
1133
+ ({ api, editor, getOptions, setOption, setOptions }) => {
1134
+ const debounceDelay = getOptions().debounceDelay;
1135
+ let triggerSuggestion = (0, import_platejs18.bindFirst)(triggerCopilotSuggestion, editor);
1136
+ if (debounceDelay) {
1137
+ triggerSuggestion = (0, import_debounce.default)(
1138
+ (0, import_platejs18.bindFirst)(triggerCopilotSuggestion, editor),
1139
+ debounceDelay
1140
+ );
1141
+ }
1142
+ return {
1143
+ triggerSuggestion,
1144
+ setBlockSuggestion: ({ id = getOptions().suggestionNodeId, text }) => {
1145
+ if (!id) {
1146
+ id = editor.api.block()[0].id;
1147
+ }
1148
+ setOptions({
1149
+ suggestionNodeId: id,
1150
+ suggestionText: text
1151
+ });
1152
+ },
1153
+ stop: () => {
1154
+ const { abortController } = getOptions();
1155
+ api.copilot.triggerSuggestion?.cancel();
1156
+ if (abortController) {
1157
+ abortController.abort();
1158
+ setOption("abortController", null);
1159
+ }
1160
+ }
1161
+ };
1162
+ }
1163
+ ).extendApi(({ api, getOptions, setOptions }) => ({
1164
+ reject: () => {
1165
+ if (!getOptions().suggestionText?.length) return false;
1166
+ api.copilot.stop();
1167
+ setOptions({
1168
+ completion: null,
1169
+ suggestionNodeId: null,
1170
+ suggestionText: null
1171
+ });
1172
+ }
1173
+ })).extend({
1174
+ render: {
1175
+ belowNodes: renderCopilotBelowNodes
1176
+ },
1177
+ shortcuts: {
1178
+ accept: {
1179
+ keys: "tab"
1180
+ },
1181
+ reject: {
1182
+ keys: "escape"
1183
+ }
1184
+ }
1185
+ });
1186
+ // Annotate the CommonJS export names for ESM import in node:
1187
+ 0 && (module.exports = {
1188
+ AIChatPlugin,
1189
+ AIPlugin,
1190
+ CopilotPlugin,
1191
+ acceptAIChat,
1192
+ acceptCopilot,
1193
+ acceptCopilotNextWord,
1194
+ callCompletionApi,
1195
+ createFormattedBlocks,
1196
+ getEditorPrompt,
1197
+ getLastAssistantMessage,
1198
+ getMarkdown,
1199
+ getNextWord,
1200
+ insertBelowAIChat,
1201
+ removeAnchorAIChat,
1202
+ renderCopilotBelowNodes,
1203
+ replaceSelectionAIChat,
1204
+ resetAIChat,
1205
+ submitAIChat,
1206
+ triggerCopilotSuggestion,
1207
+ useAIChatEditor,
1208
+ useChatChunk,
1209
+ useEditorChat,
1210
+ useLastAssistantMessage,
1211
+ withAIChat,
1212
+ withCopilot,
1213
+ withoutAbort
1214
+ });
1215
+ //# sourceMappingURL=index.js.map