@assistant-ui/react 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. package/dist/index.js +174 -171
  2. package/dist/index.mjs +176 -172
  3. 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
- return false;
89
- if (props.empty === false && thread.messages.length === 0)
90
- return false;
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
- return false;
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("Editing is only supported for user messages");
348
- const text = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
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("Editing is only supported for user messages");
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
- message,
383
- parentId,
384
- branches,
385
- isLast,
386
- isCopied,
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
- return false;
430
- if (props.user && message.role !== "user")
431
- return false;
432
- if (props.assistant && message.role !== "assistant")
433
- return false;
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
- return "normal" /* Normal */;
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 isEditing = useComposer((s) => s.isEditing);
897
- if (isEditing)
898
- return null;
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
- if (message.content[0]?.type !== "text")
902
- throw new Error("Copying is only supported for text-only messages");
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 { message, parentId } = useMessage.getState();
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: async () => {
965
+ append: () => {
991
966
  throw new Error("Not implemented");
992
967
  },
993
- cancelRun: () => {
968
+ startRun: () => {
994
969
  throw new Error("Not implemented");
995
970
  },
996
- startRun: async () => {
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
- // TODO previousId is confusing
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
- if ((item.prev?.current.id ?? null) !== parentId) {
1048
- this.deleteMessage(message.id);
1049
- } else {
1050
- item.current = message;
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("Unexpected: Parent message not found");
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("Unexpected: Message not found");
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("Unexpected: Child message not found");
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("Unexpected: Message not found");
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("Unexpected: Branch not found");
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("Unexpected: Branch not found");
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("Unsupported role");
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: [{ type: "text", text: message.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
- return [];
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("Unexpected: Message not found");
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 getBranches = (0, import_react22.useCallback)(
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 switchToBranch = (0, import_react22.useCallback)(
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("Reload not supported by Vercel AI SDK's useAssistant");
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 cancelRun = (0, import_react22.useCallback)(() => {
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
- getBranches,
1310
- switchToBranch,
1286
+ getBranches2,
1287
+ switchToBranch2,
1311
1288
  append,
1312
1289
  startRun,
1313
- cancelRun
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
- "Unexpected: Message editing is not supported, no edit callback was provided to VercelRSCAssistantProvider."
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
- "Unexpected: Message reloading is not supported, no reload callback was provided to VercelRSCAssistantProvider."
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
- messages,
1397
- append,
1398
- startRun
1399
- });
1400
- }, [context, messages, append, startRun]);
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: