@assistant-ui/react 0.0.14 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +174 -171
- package/dist/index.mjs +176 -172
- package/package.json +3 -3
package/dist/index.js
CHANGED
@@ -75,7 +75,7 @@ var useAssistantContext = () => {
|
|
75
75
|
const context = (0, import_react2.useContext)(AssistantContext);
|
76
76
|
if (!context)
|
77
77
|
throw new Error(
|
78
|
-
"This component must be used within a AssistantProvider"
|
78
|
+
"This component must be used within a AssistantProvider."
|
79
79
|
);
|
80
80
|
return context;
|
81
81
|
};
|
@@ -84,14 +84,10 @@ var useAssistantContext = () => {
|
|
84
84
|
var useThreadIf = (props) => {
|
85
85
|
const { useThread } = useAssistantContext();
|
86
86
|
return useThread((thread) => {
|
87
|
-
if (props.empty === true && thread.messages.length !== 0)
|
88
|
-
|
89
|
-
if (props.
|
90
|
-
|
91
|
-
if (props.running === true && !thread.isRunning)
|
92
|
-
return false;
|
93
|
-
if (props.running === false && thread.isRunning)
|
94
|
-
return false;
|
87
|
+
if (props.empty === true && thread.messages.length !== 0) return false;
|
88
|
+
if (props.empty === false && thread.messages.length === 0) return false;
|
89
|
+
if (props.running === true && !thread.isRunning) return false;
|
90
|
+
if (props.running === false && thread.isRunning) return false;
|
95
91
|
return true;
|
96
92
|
});
|
97
93
|
};
|
@@ -119,8 +115,7 @@ var useOnResizeContent = (ref, callback) => {
|
|
119
115
|
callbackRef.current = callback;
|
120
116
|
(0, import_react3.useLayoutEffect)(() => {
|
121
117
|
const el = ref.current;
|
122
|
-
if (!el)
|
123
|
-
return;
|
118
|
+
if (!el) return;
|
124
119
|
const resizeObserver = new ResizeObserver(() => {
|
125
120
|
callbackRef.current();
|
126
121
|
});
|
@@ -175,16 +170,14 @@ var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScrol
|
|
175
170
|
const lastScrollTop = (0, import_react5.useRef)(0);
|
176
171
|
const scrollToBottom = () => {
|
177
172
|
const div = messagesEndRef.current;
|
178
|
-
if (!div || !autoScroll)
|
179
|
-
return;
|
173
|
+
if (!div || !autoScroll) return;
|
180
174
|
const behavior = firstRenderRef.current ? "instant" : "auto";
|
181
175
|
firstRenderRef.current = false;
|
182
176
|
useViewport.setState({ isAtBottom: true });
|
183
177
|
div.scrollIntoView({ behavior });
|
184
178
|
};
|
185
179
|
useOnResizeContent(divRef, () => {
|
186
|
-
if (!useViewport.getState().isAtBottom)
|
187
|
-
return;
|
180
|
+
if (!useViewport.getState().isAtBottom) return;
|
188
181
|
scrollToBottom();
|
189
182
|
});
|
190
183
|
useOnScrollToBottom(() => {
|
@@ -192,8 +185,7 @@ var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScrol
|
|
192
185
|
});
|
193
186
|
const handleScroll = () => {
|
194
187
|
const div = divRef.current;
|
195
|
-
if (!div)
|
196
|
-
return;
|
188
|
+
if (!div) return;
|
197
189
|
const isAtBottom = useViewport.getState().isAtBottom;
|
198
190
|
const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
|
199
191
|
if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
|
@@ -225,7 +217,7 @@ var MessageContext = (0, import_react6.createContext)(null);
|
|
225
217
|
var useMessageContext = () => {
|
226
218
|
const context = (0, import_react6.useContext)(MessageContext);
|
227
219
|
if (!context)
|
228
|
-
throw new Error("This component must be used within a MessageProvider");
|
220
|
+
throw new Error("This component must be used within a MessageProvider.");
|
229
221
|
return context;
|
230
222
|
};
|
231
223
|
|
@@ -243,10 +235,8 @@ var useComposerContext = () => {
|
|
243
235
|
var useComposerIf = (props) => {
|
244
236
|
const { useComposer } = useComposerContext();
|
245
237
|
return useComposer((composer) => {
|
246
|
-
if (props.editing === true && !composer.isEditing)
|
247
|
-
|
248
|
-
if (props.editing === false && composer.isEditing)
|
249
|
-
return false;
|
238
|
+
if (props.editing === true && !composer.isEditing) return false;
|
239
|
+
if (props.editing === false && composer.isEditing) return false;
|
250
240
|
return true;
|
251
241
|
});
|
252
242
|
};
|
@@ -268,6 +258,14 @@ __export(message_exports, {
|
|
268
258
|
var import_react8 = require("react");
|
269
259
|
var import_zustand2 = require("zustand");
|
270
260
|
|
261
|
+
// src/utils/context/getMessageText.tsx
|
262
|
+
var getMessageText = (message) => {
|
263
|
+
const textParts = message.content.filter(
|
264
|
+
(part) => part.type === "text"
|
265
|
+
);
|
266
|
+
return textParts.map((part) => part.text).join("\n\n");
|
267
|
+
};
|
268
|
+
|
271
269
|
// src/utils/context/stores/ComposerStore.ts
|
272
270
|
var import_zustand = require("zustand");
|
273
271
|
var makeBaseComposer = (set) => ({
|
@@ -292,8 +290,7 @@ var makeMessageComposerStore = ({
|
|
292
290
|
onSend(value);
|
293
291
|
},
|
294
292
|
cancel: () => {
|
295
|
-
if (!get().isEditing)
|
296
|
-
return false;
|
293
|
+
if (!get().isEditing) return false;
|
297
294
|
set({ isEditing: false });
|
298
295
|
return true;
|
299
296
|
}
|
@@ -312,8 +309,7 @@ var makeThreadComposerStore = (useThread) => (0, import_zustand.create)()((set,
|
|
312
309
|
},
|
313
310
|
cancel: () => {
|
314
311
|
const thread = useThread.getState();
|
315
|
-
if (!thread.isRunning)
|
316
|
-
return false;
|
312
|
+
if (!thread.isRunning) return false;
|
317
313
|
useThread.getState().cancelRun();
|
318
314
|
return true;
|
319
315
|
}
|
@@ -328,30 +324,36 @@ var getIsLast = (thread, message) => {
|
|
328
324
|
var useMessageContext2 = () => {
|
329
325
|
const { useThread } = useAssistantContext();
|
330
326
|
const [context] = (0, import_react8.useState)(() => {
|
331
|
-
const useMessage = (0, import_zustand2.create)(() => ({
|
327
|
+
const useMessage = (0, import_zustand2.create)((set) => ({
|
332
328
|
message: null,
|
333
329
|
parentId: null,
|
334
330
|
branches: [],
|
335
331
|
isLast: false,
|
336
332
|
isCopied: false,
|
337
333
|
isHovering: false,
|
338
|
-
setIsCopied: () => {
|
334
|
+
setIsCopied: (value) => {
|
335
|
+
set({ isCopied: value });
|
339
336
|
},
|
340
|
-
setIsHovering: () => {
|
337
|
+
setIsHovering: (value) => {
|
338
|
+
set({ isHovering: value });
|
341
339
|
}
|
342
340
|
}));
|
343
341
|
const useComposer = makeMessageComposerStore({
|
344
342
|
onEdit: () => {
|
345
343
|
const message = useMessage.getState().message;
|
346
344
|
if (message.role !== "user")
|
347
|
-
throw new Error(
|
348
|
-
|
345
|
+
throw new Error(
|
346
|
+
"Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
|
347
|
+
);
|
348
|
+
const text = getMessageText(message);
|
349
349
|
return text;
|
350
350
|
},
|
351
351
|
onSend: (text) => {
|
352
352
|
const { message, parentId } = useMessage.getState();
|
353
353
|
if (message.role !== "user")
|
354
|
-
throw new Error(
|
354
|
+
throw new Error(
|
355
|
+
"Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
|
356
|
+
);
|
355
357
|
const nonTextParts = message.content.filter(
|
356
358
|
(part) => part.type !== "text" && part.type !== "ui"
|
357
359
|
);
|
@@ -374,23 +376,14 @@ var MessageProvider = ({
|
|
374
376
|
const context = useMessageContext2();
|
375
377
|
const isLast = useThread((thread) => getIsLast(thread, message));
|
376
378
|
const branches = useThread((thread) => thread.getBranches(message.id));
|
377
|
-
const [isCopied, setIsCopied] = (0, import_react8.useState)(false);
|
378
|
-
const [isHovering, setIsHovering] = (0, import_react8.useState)(false);
|
379
379
|
(0, import_react8.useMemo)(() => {
|
380
|
-
context.useMessage.setState(
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
isHovering,
|
388
|
-
setIsCopied,
|
389
|
-
setIsHovering
|
390
|
-
},
|
391
|
-
true
|
392
|
-
);
|
393
|
-
}, [context, message, parentId, branches, isLast, isCopied, isHovering]);
|
380
|
+
context.useMessage.setState({
|
381
|
+
message,
|
382
|
+
parentId,
|
383
|
+
branches,
|
384
|
+
isLast
|
385
|
+
});
|
386
|
+
}, [context, message, parentId, branches, isLast]);
|
394
387
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageContext.Provider, { value: context, children });
|
395
388
|
};
|
396
389
|
|
@@ -425,18 +418,12 @@ var MessageRoot = (0, import_react9.forwardRef)(
|
|
425
418
|
var useMessageIf = (props) => {
|
426
419
|
const { useMessage } = useMessageContext();
|
427
420
|
return useMessage(({ message, branches, isLast, isCopied, isHovering }) => {
|
428
|
-
if (props.hasBranches === true && branches.length < 2)
|
429
|
-
|
430
|
-
if (props.
|
431
|
-
|
432
|
-
if (props.
|
433
|
-
|
434
|
-
if (props.lastOrHover === true && !isHovering && !isLast)
|
435
|
-
return false;
|
436
|
-
if (props.copied === true && !isCopied)
|
437
|
-
return false;
|
438
|
-
if (props.copied === false && isCopied)
|
439
|
-
return false;
|
421
|
+
if (props.hasBranches === true && branches.length < 2) return false;
|
422
|
+
if (props.user && message.role !== "user") return false;
|
423
|
+
if (props.assistant && message.role !== "assistant") return false;
|
424
|
+
if (props.lastOrHover === true && !isHovering && !isLast) return false;
|
425
|
+
if (props.copied === true && !isCopied) return false;
|
426
|
+
if (props.copied === false && isCopied) return false;
|
440
427
|
return true;
|
441
428
|
});
|
442
429
|
};
|
@@ -498,8 +485,7 @@ var ThreadMessages = ({ components }) => {
|
|
498
485
|
const thread = useThread();
|
499
486
|
const messages = thread.messages;
|
500
487
|
const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
|
501
|
-
if (messages.length === 0)
|
502
|
-
return null;
|
488
|
+
if (messages.length === 0) return null;
|
503
489
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: messages.map((message, idx) => {
|
504
490
|
const parentId = messages[idx - 1]?.id ?? null;
|
505
491
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
@@ -593,8 +579,7 @@ var ComposerRoot = (0, import_react12.forwardRef)(
|
|
593
579
|
const ref = (0, import_react_compose_refs2.useComposedRefs)(forwardedRef, formRef);
|
594
580
|
const handleSubmit = (e) => {
|
595
581
|
const composerState = useComposer.getState();
|
596
|
-
if (!composerState.isEditing)
|
597
|
-
return;
|
582
|
+
if (!composerState.isEditing) return;
|
598
583
|
e.preventDefault();
|
599
584
|
composerState.send();
|
600
585
|
useViewport.getState().scrollToBottom();
|
@@ -622,14 +607,12 @@ var ComposerInput = (0, import_react13.forwardRef)(
|
|
622
607
|
const { useThread, useViewport } = useAssistantContext();
|
623
608
|
const { useComposer, type } = useComposerContext();
|
624
609
|
const value = useComposer((c) => {
|
625
|
-
if (!c.isEditing)
|
626
|
-
return "";
|
610
|
+
if (!c.isEditing) return "";
|
627
611
|
return c.value;
|
628
612
|
});
|
629
613
|
const Component = asChild ? import_react_slot.Slot : import_react_textarea_autosize.default;
|
630
614
|
const handleKeyPress = (e) => {
|
631
|
-
if (disabled)
|
632
|
-
return;
|
615
|
+
if (disabled) return;
|
633
616
|
const composer = useComposer.getState();
|
634
617
|
if (e.key === "Escape") {
|
635
618
|
if (useComposer.getState().cancel()) {
|
@@ -649,8 +632,7 @@ var ComposerInput = (0, import_react13.forwardRef)(
|
|
649
632
|
const autoFocusEnabled = autoFocus && !disabled;
|
650
633
|
const focus = (0, import_react13.useCallback)(() => {
|
651
634
|
const textarea = textareaRef.current;
|
652
|
-
if (!textarea || !autoFocusEnabled)
|
653
|
-
return;
|
635
|
+
if (!textarea || !autoFocusEnabled) return;
|
654
636
|
textarea.focus();
|
655
637
|
textarea.setSelectionRange(
|
656
638
|
textareaRef.current.value.length,
|
@@ -672,8 +654,7 @@ var ComposerInput = (0, import_react13.forwardRef)(
|
|
672
654
|
disabled,
|
673
655
|
onChange: (0, import_primitive6.composeEventHandlers)(onChange, (e) => {
|
674
656
|
const composerState = useComposer.getState();
|
675
|
-
if (!composerState.isEditing)
|
676
|
-
return;
|
657
|
+
if (!composerState.isEditing) return;
|
677
658
|
return composerState.setValue(e.target.value);
|
678
659
|
}),
|
679
660
|
onKeyDown: (0, import_primitive6.composeEventHandlers)(onKeyDown, handleKeyPress)
|
@@ -767,8 +748,7 @@ var useGoToNextBranch = () => {
|
|
767
748
|
[useMessage, useComposer],
|
768
749
|
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
|
769
750
|
);
|
770
|
-
if (disabled)
|
771
|
-
return null;
|
751
|
+
if (disabled) return null;
|
772
752
|
return () => {
|
773
753
|
const { message, branches } = useMessage.getState();
|
774
754
|
useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
|
@@ -809,8 +789,7 @@ var useGoToPreviousBranch = () => {
|
|
809
789
|
[useMessage, useComposer],
|
810
790
|
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
|
811
791
|
);
|
812
|
-
if (disabled)
|
813
|
-
return null;
|
792
|
+
if (disabled) return null;
|
814
793
|
return () => {
|
815
794
|
const { message, branches } = useMessage.getState();
|
816
795
|
useThread.getState().switchToBranch(
|
@@ -866,20 +845,16 @@ var ActionBarRoot = (0, import_react20.forwardRef)(({ hideWhenRunning, autohide,
|
|
866
845
|
const hideAndfloatStatus = useCombinedStore(
|
867
846
|
[useThread, useMessage],
|
868
847
|
(t, m) => {
|
869
|
-
if (hideWhenRunning && t.isRunning)
|
870
|
-
return "hidden" /* Hidden */;
|
848
|
+
if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
|
871
849
|
const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
|
872
|
-
if (!autohideEnabled)
|
873
|
-
|
874
|
-
if (!m.isHovering)
|
875
|
-
return "hidden" /* Hidden */;
|
850
|
+
if (!autohideEnabled) return "normal" /* Normal */;
|
851
|
+
if (!m.isHovering) return "hidden" /* Hidden */;
|
876
852
|
if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
|
877
853
|
return "floating" /* Floating */;
|
878
854
|
return "normal" /* Normal */;
|
879
855
|
}
|
880
856
|
);
|
881
|
-
if (hideAndfloatStatus === "hidden" /* Hidden */)
|
882
|
-
return null;
|
857
|
+
if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
|
883
858
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
884
859
|
import_react_primitive11.Primitive.div,
|
885
860
|
{
|
@@ -893,14 +868,18 @@ var ActionBarRoot = (0, import_react20.forwardRef)(({ hideWhenRunning, autohide,
|
|
893
868
|
// src/actions/useCopyMessage.tsx
|
894
869
|
var useCopyMessage = ({ copiedDuration = 3e3 }) => {
|
895
870
|
const { useMessage, useComposer } = useMessageContext();
|
896
|
-
const
|
897
|
-
|
898
|
-
|
871
|
+
const hasCopyableContent = useCombinedStore(
|
872
|
+
[useMessage, useComposer],
|
873
|
+
(m, c) => {
|
874
|
+
return c.isEditing || m.message.content.some((c2) => c2.type === "text");
|
875
|
+
}
|
876
|
+
);
|
877
|
+
if (!hasCopyableContent) return null;
|
899
878
|
return () => {
|
879
|
+
const { isEditing, value: composerValue } = useComposer.getState();
|
900
880
|
const { message, setIsCopied } = useMessage.getState();
|
901
|
-
|
902
|
-
|
903
|
-
navigator.clipboard.writeText(message.content[0].text);
|
881
|
+
const valueToCopy = isEditing ? composerValue : getMessageText(message);
|
882
|
+
navigator.clipboard.writeText(valueToCopy);
|
904
883
|
setIsCopied(true);
|
905
884
|
setTimeout(() => setIsCopied(false), copiedDuration);
|
906
885
|
};
|
@@ -917,12 +896,9 @@ var useReloadMessage = () => {
|
|
917
896
|
[useThread, useMessage],
|
918
897
|
(t, m) => t.isRunning || m.message.role !== "assistant"
|
919
898
|
);
|
920
|
-
if (disabled)
|
921
|
-
return null;
|
899
|
+
if (disabled) return null;
|
922
900
|
return () => {
|
923
|
-
const {
|
924
|
-
if (message.role !== "assistant")
|
925
|
-
throw new Error("Reloading is only supported on assistant messages");
|
901
|
+
const { parentId } = useMessage.getState();
|
926
902
|
useThread.getState().startRun(parentId);
|
927
903
|
useViewport.getState().scrollToBottom();
|
928
904
|
};
|
@@ -938,8 +914,7 @@ var useBeginMessageEdit = () => {
|
|
938
914
|
[useMessage, useComposer],
|
939
915
|
(m, c) => m.message.role !== "user" || c.isEditing
|
940
916
|
);
|
941
|
-
if (disabled)
|
942
|
-
return null;
|
917
|
+
if (disabled) return null;
|
943
918
|
return () => {
|
944
919
|
const { edit } = useComposer.getState();
|
945
920
|
edit();
|
@@ -987,13 +962,13 @@ var makeDummyThreadStore = () => {
|
|
987
962
|
switchToBranch: () => {
|
988
963
|
throw new Error("Not implemented");
|
989
964
|
},
|
990
|
-
append:
|
965
|
+
append: () => {
|
991
966
|
throw new Error("Not implemented");
|
992
967
|
},
|
993
|
-
|
968
|
+
startRun: () => {
|
994
969
|
throw new Error("Not implemented");
|
995
970
|
},
|
996
|
-
|
971
|
+
cancelRun: () => {
|
997
972
|
throw new Error("Not implemented");
|
998
973
|
}
|
999
974
|
}));
|
@@ -1021,8 +996,7 @@ var optimisticPrefix = "__optimistic__";
|
|
1021
996
|
var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
1022
997
|
var isOptimisticId = (id) => id.startsWith(optimisticPrefix);
|
1023
998
|
var findHead = (message) => {
|
1024
|
-
if (message.next)
|
1025
|
-
return findHead(message.next);
|
999
|
+
if (message.next) return findHead(message.next);
|
1026
1000
|
return message;
|
1027
1001
|
};
|
1028
1002
|
var MessageRepository = class {
|
@@ -1037,28 +1011,21 @@ var MessageRepository = class {
|
|
1037
1011
|
}
|
1038
1012
|
return messages;
|
1039
1013
|
}
|
1040
|
-
|
1041
|
-
// TODO previousId does not fix children
|
1042
|
-
// TODO cut / link operations
|
1043
|
-
addOrUpdateMessage(parentId, message, previousId = message.id) {
|
1014
|
+
addOrUpdateMessage(parentId, message) {
|
1044
1015
|
const item = this.messages.get(message.id);
|
1045
1016
|
if (item) {
|
1046
|
-
if (item.prev?.current.id !== parentId) {
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
if (previousId !== message.id) {
|
1052
|
-
this.messages.delete(previousId);
|
1053
|
-
this.messages.set(message.id, item);
|
1054
|
-
}
|
1055
|
-
return;
|
1056
|
-
}
|
1017
|
+
if ((item.prev?.current.id ?? null) !== parentId) {
|
1018
|
+
this.deleteMessage(message.id);
|
1019
|
+
} else {
|
1020
|
+
item.current = message;
|
1021
|
+
return;
|
1057
1022
|
}
|
1058
1023
|
}
|
1059
1024
|
const prev = parentId ? this.messages.get(parentId) : null;
|
1060
1025
|
if (prev === void 0)
|
1061
|
-
throw new Error(
|
1026
|
+
throw new Error(
|
1027
|
+
"MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui."
|
1028
|
+
);
|
1062
1029
|
const newItem = {
|
1063
1030
|
prev,
|
1064
1031
|
current: message,
|
@@ -1080,7 +1047,9 @@ var MessageRepository = class {
|
|
1080
1047
|
deleteMessage(messageId) {
|
1081
1048
|
const message = this.messages.get(messageId);
|
1082
1049
|
if (!message)
|
1083
|
-
throw new Error(
|
1050
|
+
throw new Error(
|
1051
|
+
"MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui."
|
1052
|
+
);
|
1084
1053
|
if (message.children.length > 0) {
|
1085
1054
|
for (const child of message.children) {
|
1086
1055
|
this.deleteMessage(child);
|
@@ -1095,7 +1064,9 @@ var MessageRepository = class {
|
|
1095
1064
|
const childId = message.prev.children.at(-1);
|
1096
1065
|
const child = childId ? this.messages.get(childId) : null;
|
1097
1066
|
if (child === void 0)
|
1098
|
-
throw new Error(
|
1067
|
+
throw new Error(
|
1068
|
+
"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui."
|
1069
|
+
);
|
1099
1070
|
message.prev.next = child;
|
1100
1071
|
}
|
1101
1072
|
} else {
|
@@ -1112,17 +1083,6 @@ var MessageRepository = class {
|
|
1112
1083
|
} while (this.messages.has(optimisticId));
|
1113
1084
|
return optimisticId;
|
1114
1085
|
}
|
1115
|
-
commitOptimisticAppend(message) {
|
1116
|
-
const optimisticIdUser = this.getOptimisticId();
|
1117
|
-
this.addOrUpdateMessage(message.parentId, {
|
1118
|
-
id: optimisticIdUser,
|
1119
|
-
role: "user",
|
1120
|
-
content: message.content,
|
1121
|
-
createdAt: /* @__PURE__ */ new Date()
|
1122
|
-
});
|
1123
|
-
const optimisticIdAssistant = this.commitOptimisticRun(optimisticIdUser);
|
1124
|
-
return [optimisticIdUser, optimisticIdAssistant];
|
1125
|
-
}
|
1126
1086
|
commitOptimisticRun(parentId) {
|
1127
1087
|
const optimisticId = this.getOptimisticId();
|
1128
1088
|
this.addOrUpdateMessage(parentId, {
|
@@ -1141,7 +1101,9 @@ var MessageRepository = class {
|
|
1141
1101
|
getBranches(messageId) {
|
1142
1102
|
const message = this.messages.get(messageId);
|
1143
1103
|
if (!message)
|
1144
|
-
throw new Error(
|
1104
|
+
throw new Error(
|
1105
|
+
"MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui."
|
1106
|
+
);
|
1145
1107
|
if (message.prev) {
|
1146
1108
|
return message.prev.children;
|
1147
1109
|
}
|
@@ -1150,7 +1112,9 @@ var MessageRepository = class {
|
|
1150
1112
|
switchToBranch(messageId) {
|
1151
1113
|
const message = this.messages.get(messageId);
|
1152
1114
|
if (!message)
|
1153
|
-
throw new Error(
|
1115
|
+
throw new Error(
|
1116
|
+
"MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui."
|
1117
|
+
);
|
1154
1118
|
if (message.prev) {
|
1155
1119
|
message.prev.next = message;
|
1156
1120
|
}
|
@@ -1160,7 +1124,9 @@ var MessageRepository = class {
|
|
1160
1124
|
if (messageId) {
|
1161
1125
|
const message = this.messages.get(messageId);
|
1162
1126
|
if (!message)
|
1163
|
-
throw new Error(
|
1127
|
+
throw new Error(
|
1128
|
+
"MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui."
|
1129
|
+
);
|
1164
1130
|
this.head = message;
|
1165
1131
|
for (let current = message; current; current = current.prev) {
|
1166
1132
|
if (current.prev) {
|
@@ -1182,8 +1148,7 @@ var ThreadMessageConverter = class {
|
|
1182
1148
|
convertMessages(messages) {
|
1183
1149
|
return messages.map((m) => {
|
1184
1150
|
const cached = this.cache.get(m);
|
1185
|
-
if (cached)
|
1186
|
-
return cached;
|
1151
|
+
if (cached) return cached;
|
1187
1152
|
const newMessage = this.converter(m);
|
1188
1153
|
this.cache.set(m, newMessage);
|
1189
1154
|
return newMessage;
|
@@ -1194,32 +1159,42 @@ var ThreadMessageConverter = class {
|
|
1194
1159
|
// src/adapters/vercel/useVercelAIThreadState.tsx
|
1195
1160
|
var vercelToThreadMessage = (message) => {
|
1196
1161
|
if (message.role !== "user" && message.role !== "assistant")
|
1197
|
-
throw new Error(
|
1162
|
+
throw new Error(
|
1163
|
+
`You have a message with an unsupported role. The role ${message.role} is not supported.`
|
1164
|
+
);
|
1198
1165
|
return {
|
1199
1166
|
id: message.id,
|
1200
1167
|
role: message.role,
|
1201
|
-
content: [
|
1168
|
+
content: [
|
1169
|
+
...message.content ? [{ type: "text", text: message.content }] : [],
|
1170
|
+
...message.toolInvocations?.map((t) => ({
|
1171
|
+
type: "tool-call",
|
1172
|
+
name: t.toolName,
|
1173
|
+
args: t.args,
|
1174
|
+
result: "result" in t ? t.result : void 0
|
1175
|
+
})) ?? []
|
1176
|
+
],
|
1177
|
+
// ignore type mismatch for now
|
1202
1178
|
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1203
1179
|
innerMessage: message
|
1204
1180
|
};
|
1205
1181
|
};
|
1206
1182
|
var converter = new ThreadMessageConverter(vercelToThreadMessage);
|
1207
1183
|
var sliceMessagesUntil = (messages, messageId) => {
|
1208
|
-
if (messageId == null)
|
1209
|
-
|
1210
|
-
if (isOptimisticId(messageId))
|
1211
|
-
return messages;
|
1184
|
+
if (messageId == null) return [];
|
1185
|
+
if (isOptimisticId(messageId)) return messages;
|
1212
1186
|
const messageIdx = messages.findIndex((m) => m.id === messageId);
|
1213
1187
|
if (messageIdx === -1)
|
1214
|
-
throw new Error(
|
1188
|
+
throw new Error(
|
1189
|
+
"useVercelAIThreadState: Message not found. This is liekly an internal bug in assistant-ui."
|
1190
|
+
);
|
1215
1191
|
return messages.slice(0, messageIdx + 1);
|
1216
1192
|
};
|
1217
1193
|
var hasUpcomingMessage = (isRunning, messages) => {
|
1218
1194
|
return isRunning && messages[messages.length - 1]?.role !== "assistant";
|
1219
1195
|
};
|
1220
1196
|
var getIsRunning = (vercel) => {
|
1221
|
-
if ("isLoading" in vercel)
|
1222
|
-
return vercel.isLoading;
|
1197
|
+
if ("isLoading" in vercel) return vercel.isLoading;
|
1223
1198
|
return vercel.status === "in_progress";
|
1224
1199
|
};
|
1225
1200
|
var useVercelAIThreadState = (vercel) => {
|
@@ -1247,13 +1222,13 @@ var useVercelAIThreadState = (vercel) => {
|
|
1247
1222
|
data.resetHead(assistantOptimisticIdRef.current ?? vm.at(-1)?.id ?? null);
|
1248
1223
|
return data.getMessages();
|
1249
1224
|
}, [data, isRunning, vercel.messages]);
|
1250
|
-
const
|
1225
|
+
const getBranches2 = (0, import_react22.useCallback)(
|
1251
1226
|
(messageId) => {
|
1252
1227
|
return data.getBranches(messageId);
|
1253
1228
|
},
|
1254
1229
|
[data]
|
1255
1230
|
);
|
1256
|
-
const
|
1231
|
+
const switchToBranch2 = (0, import_react22.useCallback)(
|
1257
1232
|
(messageId) => {
|
1258
1233
|
data.switchToBranch(messageId);
|
1259
1234
|
vercelRef.current.setMessages(
|
@@ -1265,7 +1240,9 @@ var useVercelAIThreadState = (vercel) => {
|
|
1265
1240
|
const startRun = (0, import_react22.useCallback)(async (parentId) => {
|
1266
1241
|
const reloadMaybe = "reload" in vercelRef.current ? vercelRef.current.reload : void 0;
|
1267
1242
|
if (!reloadMaybe)
|
1268
|
-
throw new Error(
|
1243
|
+
throw new Error(
|
1244
|
+
"Reload is not supported by Vercel AI SDK's useAssistant."
|
1245
|
+
);
|
1269
1246
|
const newMessages = sliceMessagesUntil(
|
1270
1247
|
vercelRef.current.messages,
|
1271
1248
|
parentId
|
@@ -1275,7 +1252,7 @@ var useVercelAIThreadState = (vercel) => {
|
|
1275
1252
|
}, []);
|
1276
1253
|
const append = (0, import_react22.useCallback)(async (message) => {
|
1277
1254
|
if (message.content.length !== 1 || message.content[0]?.type !== "text")
|
1278
|
-
throw new Error("Only text content is supported by Vercel AI SDK");
|
1255
|
+
throw new Error("Only text content is supported by Vercel AI SDK.");
|
1279
1256
|
const newMessages = sliceMessagesUntil(
|
1280
1257
|
vercelRef.current.messages,
|
1281
1258
|
message.parentId
|
@@ -1286,7 +1263,7 @@ var useVercelAIThreadState = (vercel) => {
|
|
1286
1263
|
content: message.content[0].text
|
1287
1264
|
});
|
1288
1265
|
}, []);
|
1289
|
-
const
|
1266
|
+
const cancelRun2 = (0, import_react22.useCallback)(() => {
|
1290
1267
|
const lastMessage = vercelRef.current.messages.at(-1);
|
1291
1268
|
vercelRef.current.stop();
|
1292
1269
|
if (lastMessage?.role === "user") {
|
@@ -1297,20 +1274,20 @@ var useVercelAIThreadState = (vercel) => {
|
|
1297
1274
|
() => ({
|
1298
1275
|
isRunning,
|
1299
1276
|
messages,
|
1300
|
-
getBranches,
|
1301
|
-
switchToBranch,
|
1277
|
+
getBranches: getBranches2,
|
1278
|
+
switchToBranch: switchToBranch2,
|
1302
1279
|
append,
|
1303
1280
|
startRun,
|
1304
|
-
cancelRun
|
1281
|
+
cancelRun: cancelRun2
|
1305
1282
|
}),
|
1306
1283
|
[
|
1307
1284
|
isRunning,
|
1308
1285
|
messages,
|
1309
|
-
|
1310
|
-
|
1286
|
+
getBranches2,
|
1287
|
+
switchToBranch2,
|
1311
1288
|
append,
|
1312
1289
|
startRun,
|
1313
|
-
|
1290
|
+
cancelRun2
|
1314
1291
|
]
|
1315
1292
|
);
|
1316
1293
|
};
|
@@ -1340,8 +1317,6 @@ var VercelAIAssistantProvider = ({
|
|
1340
1317
|
var import_react24 = require("react");
|
1341
1318
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
1342
1319
|
var vercelToThreadMessage2 = (message) => {
|
1343
|
-
if (message.role !== "user" && message.role !== "assistant")
|
1344
|
-
throw new Error("Unsupported role");
|
1345
1320
|
return {
|
1346
1321
|
id: message.id,
|
1347
1322
|
role: message.role,
|
@@ -1349,6 +1324,22 @@ var vercelToThreadMessage2 = (message) => {
|
|
1349
1324
|
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1350
1325
|
};
|
1351
1326
|
};
|
1327
|
+
var EMPTY_BRANCHES = [];
|
1328
|
+
var getBranches = () => {
|
1329
|
+
return EMPTY_BRANCHES;
|
1330
|
+
};
|
1331
|
+
var switchToBranch = () => {
|
1332
|
+
throw new Error(
|
1333
|
+
"Branch switching is not supported by VercelRSCAssistantProvider."
|
1334
|
+
);
|
1335
|
+
};
|
1336
|
+
var cancelRun = () => {
|
1337
|
+
if (process.env["NODE_ENV"] === "development") {
|
1338
|
+
console.warn(
|
1339
|
+
"Run cancellation is not supported by VercelRSCAssistantProvider."
|
1340
|
+
);
|
1341
|
+
}
|
1342
|
+
};
|
1352
1343
|
var VercelRSCAssistantProvider = ({
|
1353
1344
|
children,
|
1354
1345
|
convertMessage,
|
@@ -1358,6 +1349,11 @@ var VercelRSCAssistantProvider = ({
|
|
1358
1349
|
reload
|
1359
1350
|
}) => {
|
1360
1351
|
const context = useDummyAIAssistantContext();
|
1352
|
+
const [isRunning, setIsRunning] = (0, import_react24.useState)(false);
|
1353
|
+
const withRunning = (0, import_react24.useCallback)((callback) => {
|
1354
|
+
setIsRunning(true);
|
1355
|
+
return callback.finally(() => setIsRunning(false));
|
1356
|
+
}, []);
|
1361
1357
|
const converter2 = (0, import_react24.useMemo)(() => {
|
1362
1358
|
const rscConverter = convertMessage ?? ((m) => m);
|
1363
1359
|
return new ThreadMessageConverter((m) => {
|
@@ -1372,32 +1368,39 @@ var VercelRSCAssistantProvider = ({
|
|
1372
1368
|
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
|
1373
1369
|
if (!edit)
|
1374
1370
|
throw new Error(
|
1375
|
-
"
|
1371
|
+
"Message editing is not enabled, please provide an edit callback to VercelRSCAssistantProvider."
|
1376
1372
|
);
|
1377
|
-
await edit(message);
|
1373
|
+
await withRunning(edit(message));
|
1378
1374
|
} else {
|
1379
|
-
await appendCallback(message);
|
1375
|
+
await withRunning(appendCallback(message));
|
1380
1376
|
}
|
1381
1377
|
},
|
1382
|
-
[context, appendCallback, edit]
|
1378
|
+
[context, withRunning, appendCallback, edit]
|
1383
1379
|
);
|
1384
1380
|
const startRun = (0, import_react24.useCallback)(
|
1385
1381
|
async (parentId) => {
|
1386
1382
|
if (!reload)
|
1387
1383
|
throw new Error(
|
1388
|
-
"
|
1384
|
+
"Message reloading is not enabled, please provide a reload callback to VercelRSCAssistantProvider."
|
1389
1385
|
);
|
1390
|
-
await reload(parentId);
|
1386
|
+
await withRunning(reload(parentId));
|
1391
1387
|
},
|
1392
|
-
[reload]
|
1388
|
+
[withRunning, reload]
|
1393
1389
|
);
|
1394
1390
|
(0, import_react24.useMemo)(() => {
|
1395
|
-
context.useThread.setState(
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1391
|
+
context.useThread.setState(
|
1392
|
+
{
|
1393
|
+
messages,
|
1394
|
+
isRunning,
|
1395
|
+
getBranches,
|
1396
|
+
switchToBranch,
|
1397
|
+
append,
|
1398
|
+
startRun,
|
1399
|
+
cancelRun
|
1400
|
+
},
|
1401
|
+
true
|
1402
|
+
);
|
1403
|
+
}, [context, messages, isRunning, append, startRun]);
|
1401
1404
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AssistantContext.Provider, { value: context, children });
|
1402
1405
|
};
|
1403
1406
|
// Annotate the CommonJS export names for ESM import in node:
|