@assistant-ui/react 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.d.mts CHANGED
@@ -1,7 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { FC, PropsWithChildren } from 'react';
3
3
  import { TextareaAutosizeProps } from 'react-textarea-autosize';
4
- import { Message } from 'ai';
5
4
  import { UseChatHelpers } from 'ai/react';
6
5
  import { UseBoundStore, StoreApi } from 'zustand';
7
6
 
@@ -84,9 +83,49 @@ declare namespace index$3 {
84
83
  export { ComposerCancel as Cancel, ComposerIf as If, ComposerInput as Input, ComposerRoot as Root, ComposerSend as Send };
85
84
  }
86
85
 
86
+ type BranchState = {
87
+ branchId: number;
88
+ branchCount: number;
89
+ };
90
+
91
+ type ComposerState = {
92
+ isEditing: boolean;
93
+ canCancel: boolean;
94
+ edit: () => void;
95
+ send: () => void;
96
+ cancel: () => void;
97
+ value: string;
98
+ setValue: (value: string) => void;
99
+ };
100
+ type ComposerStore = {
101
+ useComposer: UseBoundStore<StoreApi<ComposerState>>;
102
+ };
103
+
104
+ type TextContent = {
105
+ type: "text";
106
+ text: string;
107
+ };
108
+ type ImageContent = {
109
+ type: "image";
110
+ image: string;
111
+ };
112
+ type ThreadUserMessageContent = TextContent | ImageContent;
113
+ type ThreadAssistantMessageContent = TextContent | ImageContent;
114
+ type ThreadUserMessage = {
115
+ id: string;
116
+ role: "user";
117
+ content: ThreadUserMessageContent[];
118
+ };
119
+ type ThreadAssistantMessage = {
120
+ id: string;
121
+ role: "assistant";
122
+ content: ThreadAssistantMessageContent[];
123
+ };
124
+ type ThreadMessage = ThreadUserMessage | ThreadAssistantMessage;
125
+
87
126
  type MessageProviderProps = {
88
127
  children?: React.ReactNode;
89
- message: Message;
128
+ message: ThreadMessage;
90
129
  };
91
130
  declare const MessageProvider: FC<MessageProviderProps>;
92
131
 
@@ -177,32 +216,14 @@ declare namespace index {
177
216
  export { ActionBarCopy as Copy, ActionBarEdit as Edit, ActionBarReload as Reload, ActionBarRoot as Root };
178
217
  }
179
218
 
180
- type VercelAIAssistantProviderProps = {
219
+ type VercelAIChatAssistantProviderProps = {
181
220
  chat: UseChatHelpers;
182
221
  children: React.ReactNode;
183
222
  };
184
- declare const VercelAIAssistantProvider: FC<VercelAIAssistantProviderProps>;
185
-
186
- type ComposerState = {
187
- isEditing: boolean;
188
- canCancel: boolean;
189
- edit: () => void;
190
- send: () => void;
191
- cancel: () => void;
192
- value: string;
193
- setValue: (value: string) => void;
194
- };
195
- type ComposerStore = {
196
- useComposer: UseBoundStore<StoreApi<ComposerState>>;
197
- };
198
-
199
- type BranchState = {
200
- branchId: number;
201
- branchCount: number;
202
- };
223
+ declare const VercelAIChatAssistantProvider: FC<VercelAIChatAssistantProviderProps>;
203
224
 
204
225
  type MessageState = {
205
- message: Message;
226
+ message: ThreadMessage;
206
227
  branchState: BranchState;
207
228
  isLast: boolean;
208
229
  isCopied: boolean;
@@ -227,4 +248,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
227
248
 
228
249
  declare const useGoToPreviousBranch: () => (() => void) | null;
229
250
 
230
- export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIAssistantProvider as VercelAIThreadProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
251
+ export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIChatAssistantProvider as VercelAIAssistantProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { FC, PropsWithChildren } from 'react';
3
3
  import { TextareaAutosizeProps } from 'react-textarea-autosize';
4
- import { Message } from 'ai';
5
4
  import { UseChatHelpers } from 'ai/react';
6
5
  import { UseBoundStore, StoreApi } from 'zustand';
7
6
 
@@ -84,9 +83,49 @@ declare namespace index$3 {
84
83
  export { ComposerCancel as Cancel, ComposerIf as If, ComposerInput as Input, ComposerRoot as Root, ComposerSend as Send };
85
84
  }
86
85
 
86
+ type BranchState = {
87
+ branchId: number;
88
+ branchCount: number;
89
+ };
90
+
91
+ type ComposerState = {
92
+ isEditing: boolean;
93
+ canCancel: boolean;
94
+ edit: () => void;
95
+ send: () => void;
96
+ cancel: () => void;
97
+ value: string;
98
+ setValue: (value: string) => void;
99
+ };
100
+ type ComposerStore = {
101
+ useComposer: UseBoundStore<StoreApi<ComposerState>>;
102
+ };
103
+
104
+ type TextContent = {
105
+ type: "text";
106
+ text: string;
107
+ };
108
+ type ImageContent = {
109
+ type: "image";
110
+ image: string;
111
+ };
112
+ type ThreadUserMessageContent = TextContent | ImageContent;
113
+ type ThreadAssistantMessageContent = TextContent | ImageContent;
114
+ type ThreadUserMessage = {
115
+ id: string;
116
+ role: "user";
117
+ content: ThreadUserMessageContent[];
118
+ };
119
+ type ThreadAssistantMessage = {
120
+ id: string;
121
+ role: "assistant";
122
+ content: ThreadAssistantMessageContent[];
123
+ };
124
+ type ThreadMessage = ThreadUserMessage | ThreadAssistantMessage;
125
+
87
126
  type MessageProviderProps = {
88
127
  children?: React.ReactNode;
89
- message: Message;
128
+ message: ThreadMessage;
90
129
  };
91
130
  declare const MessageProvider: FC<MessageProviderProps>;
92
131
 
@@ -177,32 +216,14 @@ declare namespace index {
177
216
  export { ActionBarCopy as Copy, ActionBarEdit as Edit, ActionBarReload as Reload, ActionBarRoot as Root };
178
217
  }
179
218
 
180
- type VercelAIAssistantProviderProps = {
219
+ type VercelAIChatAssistantProviderProps = {
181
220
  chat: UseChatHelpers;
182
221
  children: React.ReactNode;
183
222
  };
184
- declare const VercelAIAssistantProvider: FC<VercelAIAssistantProviderProps>;
185
-
186
- type ComposerState = {
187
- isEditing: boolean;
188
- canCancel: boolean;
189
- edit: () => void;
190
- send: () => void;
191
- cancel: () => void;
192
- value: string;
193
- setValue: (value: string) => void;
194
- };
195
- type ComposerStore = {
196
- useComposer: UseBoundStore<StoreApi<ComposerState>>;
197
- };
198
-
199
- type BranchState = {
200
- branchId: number;
201
- branchCount: number;
202
- };
223
+ declare const VercelAIChatAssistantProvider: FC<VercelAIChatAssistantProviderProps>;
203
224
 
204
225
  type MessageState = {
205
- message: Message;
226
+ message: ThreadMessage;
206
227
  branchState: BranchState;
207
228
  isLast: boolean;
208
229
  isCopied: boolean;
@@ -227,4 +248,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
227
248
 
228
249
  declare const useGoToPreviousBranch: () => (() => void) | null;
229
250
 
230
- export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIAssistantProvider as VercelAIThreadProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
251
+ export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIChatAssistantProvider as VercelAIAssistantProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
package/dist/index.js CHANGED
@@ -35,7 +35,7 @@ __export(src_exports, {
35
35
  ComposerPrimitive: () => composer_exports,
36
36
  MessagePrimitive: () => message_exports,
37
37
  ThreadPrimitive: () => thread_exports,
38
- VercelAIThreadProvider: () => VercelAIAssistantProvider,
38
+ VercelAIAssistantProvider: () => VercelAIChatAssistantProvider,
39
39
  unstable_useMessageContext: () => useMessageContext,
40
40
  useBeginMessageEdit: () => useBeginMessageEdit,
41
41
  useCopyMessage: () => useCopyMessage,
@@ -177,7 +177,7 @@ var ThreadViewport = (0, import_react4.forwardRef)(({ onScroll, children, ...res
177
177
  );
178
178
  });
179
179
 
180
- // src/utils/hooks/useBranches.tsx
180
+ // src/vercel/useVercelAIBranches.tsx
181
181
  var import_react5 = require("react");
182
182
  var ROOT_ID = "__ROOT_ID__";
183
183
  var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
@@ -245,7 +245,7 @@ var sliceMessagesUntil = (messages, message) => {
245
245
  throw new Error("Unexpected: Message not found");
246
246
  return messages.slice(0, messageIdx);
247
247
  };
248
- var useChatWithBranches = (chat) => {
248
+ var useVercelAIBranches = (chat) => {
249
249
  const data = (0, import_react5.useRef)({
250
250
  parentMap: /* @__PURE__ */ new Map(),
251
251
  branchMap: /* @__PURE__ */ new Map(),
@@ -282,7 +282,12 @@ var useChatWithBranches = (chat) => {
282
282
  async (message, newMessage) => {
283
283
  const newMessages = sliceMessagesUntil(chat.messages, message);
284
284
  chat.setMessages(newMessages);
285
- await chat.append(newMessage);
285
+ if (newMessage.content[0]?.type !== "text")
286
+ throw new Error("Only text content is currently supported");
287
+ await chat.append({
288
+ role: "user",
289
+ content: newMessage.content[0].text
290
+ });
286
291
  },
287
292
  [chat.messages, chat.setMessages, chat.append]
288
293
  );
@@ -373,18 +378,25 @@ var useMessageContext2 = () => {
373
378
  const useComposer = (0, import_zustand.create)((set, get) => ({
374
379
  isEditing: false,
375
380
  canCancel: true,
376
- edit: () => set({
377
- isEditing: true,
378
- value: useMessage.getState().message.content
379
- }),
381
+ edit: () => {
382
+ const message = useMessage.getState().message;
383
+ if (message.role !== "user")
384
+ throw new Error("Editing is only supported for user messages");
385
+ if (message.content[0]?.type !== "text")
386
+ throw new Error("Editing is only supported for text-only messages");
387
+ return set({
388
+ isEditing: true,
389
+ value: message.content[0].text
390
+ });
391
+ },
380
392
  cancel: () => set({ isEditing: false }),
381
393
  send: () => {
382
394
  const message = useMessage.getState().message;
395
+ if (message.role !== "user")
396
+ throw new Error("Editing is only supported for user messages");
383
397
  useBranchObserver.getState().editAt(message, {
384
- ...message,
385
- id: void 0,
386
- // remove id to create a new message
387
- content: get().value
398
+ role: "user",
399
+ content: [{ type: "text", text: get().value }]
388
400
  });
389
401
  set({ isEditing: false });
390
402
  },
@@ -486,7 +498,9 @@ var MessageIf = ({ children, ...query }) => {
486
498
  var MessageContent = () => {
487
499
  const { useMessage } = useMessageContext();
488
500
  const content = useMessage((s) => s.message.content);
489
- return /* @__PURE__ */ React.createElement(React.Fragment, null, content);
501
+ if (content[0]?.type !== "text")
502
+ throw new Error("Unsupported message content type");
503
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, content[0].text);
490
504
  };
491
505
 
492
506
  // src/primitives/thread/ThreadMessages.tsx
@@ -515,7 +529,7 @@ var ThreadMessages = ({ components }) => {
515
529
  message: {
516
530
  id: UPCOMING_MESSAGE_ID,
517
531
  role: "assistant",
518
- content: "..."
532
+ content: [{ type: "text", text: "..." }]
519
533
  }
520
534
  },
521
535
  /* @__PURE__ */ React.createElement(AssistantMessage, null)
@@ -810,11 +824,10 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
810
824
  if (isEditing)
811
825
  return null;
812
826
  return () => {
813
- const {
814
- message: { content },
815
- setIsCopied
816
- } = useMessage.getState();
817
- navigator.clipboard.writeText(content);
827
+ const { message, setIsCopied } = useMessage.getState();
828
+ if (message.content[0]?.type !== "text")
829
+ throw new Error("Copying is only supported for text-only messages");
830
+ navigator.clipboard.writeText(message.content[0].text);
818
831
  setIsCopied(true);
819
832
  setTimeout(() => setIsCopied(false), copiedDuration);
820
833
  };
@@ -832,7 +845,10 @@ var useReloadMessage = () => {
832
845
  if (isLoading || !isAssistant)
833
846
  return null;
834
847
  return () => {
835
- useBranchObserver.getState().reloadAt(useMessage.getState().message);
848
+ const message = useMessage.getState().message;
849
+ if (message.role !== "assistant")
850
+ throw new Error("Reloading is only supported on assistant messages");
851
+ useBranchObserver.getState().reloadAt(message);
836
852
  };
837
853
  };
838
854
 
@@ -862,8 +878,6 @@ var useAIAssistantContext = () => {
862
878
  const [context] = (0, import_react17.useState)(() => {
863
879
  const useThread = (0, import_zustand2.create)()(() => ({
864
880
  messages: [],
865
- setMessages: () => {
866
- },
867
881
  isLoading: false,
868
882
  reload: async () => {
869
883
  },
@@ -883,9 +897,8 @@ var useAIAssistantContext = () => {
883
897
  },
884
898
  send: () => {
885
899
  useThread.getState().append({
886
- content: useComposer.getState().value,
887
900
  role: "user",
888
- createdAt: /* @__PURE__ */ new Date()
901
+ content: [{ type: "text", text: useComposer.getState().value }]
889
902
  });
890
903
  useComposer.getState().setValue("");
891
904
  },
@@ -909,36 +922,65 @@ var useAIAssistantContext = () => {
909
922
  });
910
923
  return context;
911
924
  };
912
- var VercelAIAssistantProvider = ({
913
- chat,
914
- children
915
- }) => {
925
+ var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
926
+ var vercelToThreadMessage = (message) => {
927
+ if (message.role !== "user" && message.role !== "assistant")
928
+ throw new Error("Unsupported role");
929
+ return {
930
+ id: message.id,
931
+ role: message.role,
932
+ content: [{ type: "text", text: message.content }]
933
+ };
934
+ };
935
+ var vercelToCachedThreadMessages = (messages) => {
936
+ return messages.map((m) => {
937
+ const cached = ThreadMessageCache.get(m);
938
+ if (cached)
939
+ return cached;
940
+ const newMessage = vercelToThreadMessage(m);
941
+ ThreadMessageCache.set(m, newMessage);
942
+ return newMessage;
943
+ });
944
+ };
945
+ var VercelAIChatAssistantProvider = ({ chat, children }) => {
916
946
  const context = useAIAssistantContext();
947
+ const messages = (0, import_react17.useMemo)(() => {
948
+ return vercelToCachedThreadMessages(chat.messages);
949
+ }, [chat.messages]);
950
+ const reload = (0, import_react17.useCallback)(async () => {
951
+ await chat.reload();
952
+ }, [chat.reload]);
953
+ const append = (0, import_react17.useCallback)(
954
+ async (message) => {
955
+ if (message.content[0]?.type !== "text") {
956
+ throw new Error("Only text content is currently supported");
957
+ }
958
+ await chat.append({
959
+ role: message.role,
960
+ content: message.content[0].text
961
+ });
962
+ },
963
+ [chat.append]
964
+ );
965
+ const stop = (0, import_react17.useCallback)(() => {
966
+ const lastMessage = chat.messages.at(-1);
967
+ chat.stop();
968
+ if (lastMessage?.role === "user") {
969
+ chat.setInput(lastMessage.content);
970
+ }
971
+ }, [chat.messages, chat.stop, chat.setInput]);
917
972
  (0, import_react17.useMemo)(() => {
918
973
  context.useThread.setState(
919
974
  {
920
- messages: chat.messages,
921
- setMessages: (value) => {
922
- chat.setMessages(value);
923
- },
975
+ messages,
924
976
  isLoading: chat.isLoading,
925
- reload: async () => {
926
- await chat.reload();
927
- },
928
- append: async (message) => {
929
- await chat.append(message);
930
- },
931
- stop: () => {
932
- const lastMessage = chat.messages.at(-1);
933
- chat.stop();
934
- if (lastMessage?.role === "user") {
935
- chat.setInput(lastMessage.content);
936
- }
937
- }
977
+ reload,
978
+ append,
979
+ stop
938
980
  },
939
981
  true
940
982
  );
941
- }, [context, chat]);
983
+ }, [context, messages, reload, append, stop, chat.isLoading]);
942
984
  (0, import_react17.useMemo)(() => {
943
985
  context.useComposer.setState({
944
986
  canCancel: chat.isLoading,
@@ -946,17 +988,9 @@ var VercelAIAssistantProvider = ({
946
988
  setValue: chat.setInput
947
989
  });
948
990
  }, [context, chat.isLoading, chat.input, chat.setInput]);
949
- const branches = useChatWithBranches(chat);
991
+ const branches = useVercelAIBranches(chat);
950
992
  (0, import_react17.useMemo)(() => {
951
- context.useBranchObserver.setState(
952
- {
953
- getBranchState: (message) => branches.getBranchState(message),
954
- switchToBranch: (message, branchId) => branches.switchToBranch(message, branchId),
955
- editAt: async (message, newMessage) => branches.editAt(message, newMessage),
956
- reloadAt: async (message) => branches.reloadAt(message)
957
- },
958
- true
959
- );
993
+ context.useBranchObserver.setState(branches, true);
960
994
  }, [context, branches]);
961
995
  return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
962
996
  };
@@ -967,7 +1001,7 @@ var VercelAIAssistantProvider = ({
967
1001
  ComposerPrimitive,
968
1002
  MessagePrimitive,
969
1003
  ThreadPrimitive,
970
- VercelAIThreadProvider,
1004
+ VercelAIAssistantProvider,
971
1005
  unstable_useMessageContext,
972
1006
  useBeginMessageEdit,
973
1007
  useCopyMessage,
package/dist/index.mjs CHANGED
@@ -140,7 +140,7 @@ var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef)
140
140
  );
141
141
  });
142
142
 
143
- // src/utils/hooks/useBranches.tsx
143
+ // src/vercel/useVercelAIBranches.tsx
144
144
  import { useCallback, useMemo, useRef as useRef3 } from "react";
145
145
  var ROOT_ID = "__ROOT_ID__";
146
146
  var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
@@ -208,7 +208,7 @@ var sliceMessagesUntil = (messages, message) => {
208
208
  throw new Error("Unexpected: Message not found");
209
209
  return messages.slice(0, messageIdx);
210
210
  };
211
- var useChatWithBranches = (chat) => {
211
+ var useVercelAIBranches = (chat) => {
212
212
  const data = useRef3({
213
213
  parentMap: /* @__PURE__ */ new Map(),
214
214
  branchMap: /* @__PURE__ */ new Map(),
@@ -245,7 +245,12 @@ var useChatWithBranches = (chat) => {
245
245
  async (message, newMessage) => {
246
246
  const newMessages = sliceMessagesUntil(chat.messages, message);
247
247
  chat.setMessages(newMessages);
248
- await chat.append(newMessage);
248
+ if (newMessage.content[0]?.type !== "text")
249
+ throw new Error("Only text content is currently supported");
250
+ await chat.append({
251
+ role: "user",
252
+ content: newMessage.content[0].text
253
+ });
249
254
  },
250
255
  [chat.messages, chat.setMessages, chat.append]
251
256
  );
@@ -336,18 +341,25 @@ var useMessageContext2 = () => {
336
341
  const useComposer = create((set, get) => ({
337
342
  isEditing: false,
338
343
  canCancel: true,
339
- edit: () => set({
340
- isEditing: true,
341
- value: useMessage.getState().message.content
342
- }),
344
+ edit: () => {
345
+ const message = useMessage.getState().message;
346
+ if (message.role !== "user")
347
+ throw new Error("Editing is only supported for user messages");
348
+ if (message.content[0]?.type !== "text")
349
+ throw new Error("Editing is only supported for text-only messages");
350
+ return set({
351
+ isEditing: true,
352
+ value: message.content[0].text
353
+ });
354
+ },
343
355
  cancel: () => set({ isEditing: false }),
344
356
  send: () => {
345
357
  const message = useMessage.getState().message;
358
+ if (message.role !== "user")
359
+ throw new Error("Editing is only supported for user messages");
346
360
  useBranchObserver.getState().editAt(message, {
347
- ...message,
348
- id: void 0,
349
- // remove id to create a new message
350
- content: get().value
361
+ role: "user",
362
+ content: [{ type: "text", text: get().value }]
351
363
  });
352
364
  set({ isEditing: false });
353
365
  },
@@ -451,7 +463,9 @@ var MessageIf = ({ children, ...query }) => {
451
463
  var MessageContent = () => {
452
464
  const { useMessage } = useMessageContext();
453
465
  const content = useMessage((s) => s.message.content);
454
- return /* @__PURE__ */ React.createElement(React.Fragment, null, content);
466
+ if (content[0]?.type !== "text")
467
+ throw new Error("Unsupported message content type");
468
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, content[0].text);
455
469
  };
456
470
 
457
471
  // src/primitives/thread/ThreadMessages.tsx
@@ -480,7 +494,7 @@ var ThreadMessages = ({ components }) => {
480
494
  message: {
481
495
  id: UPCOMING_MESSAGE_ID,
482
496
  role: "assistant",
483
- content: "..."
497
+ content: [{ type: "text", text: "..." }]
484
498
  }
485
499
  },
486
500
  /* @__PURE__ */ React.createElement(AssistantMessage, null)
@@ -793,11 +807,10 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
793
807
  if (isEditing)
794
808
  return null;
795
809
  return () => {
796
- const {
797
- message: { content },
798
- setIsCopied
799
- } = useMessage.getState();
800
- navigator.clipboard.writeText(content);
810
+ const { message, setIsCopied } = useMessage.getState();
811
+ if (message.content[0]?.type !== "text")
812
+ throw new Error("Copying is only supported for text-only messages");
813
+ navigator.clipboard.writeText(message.content[0].text);
801
814
  setIsCopied(true);
802
815
  setTimeout(() => setIsCopied(false), copiedDuration);
803
816
  };
@@ -815,7 +828,10 @@ var useReloadMessage = () => {
815
828
  if (isLoading || !isAssistant)
816
829
  return null;
817
830
  return () => {
818
- useBranchObserver.getState().reloadAt(useMessage.getState().message);
831
+ const message = useMessage.getState().message;
832
+ if (message.role !== "assistant")
833
+ throw new Error("Reloading is only supported on assistant messages");
834
+ useBranchObserver.getState().reloadAt(message);
819
835
  };
820
836
  };
821
837
 
@@ -839,14 +855,12 @@ var useBeginMessageEdit = () => {
839
855
  var ActionBarEdit = createActionButton(useBeginMessageEdit);
840
856
 
841
857
  // src/vercel/VercelAIAssistantProvider.tsx
842
- import { useMemo as useMemo4, useState as useState3 } from "react";
858
+ import { useCallback as useCallback2, useMemo as useMemo4, useState as useState3 } from "react";
843
859
  import { create as create2 } from "zustand";
844
860
  var useAIAssistantContext = () => {
845
861
  const [context] = useState3(() => {
846
862
  const useThread = create2()(() => ({
847
863
  messages: [],
848
- setMessages: () => {
849
- },
850
864
  isLoading: false,
851
865
  reload: async () => {
852
866
  },
@@ -866,9 +880,8 @@ var useAIAssistantContext = () => {
866
880
  },
867
881
  send: () => {
868
882
  useThread.getState().append({
869
- content: useComposer.getState().value,
870
883
  role: "user",
871
- createdAt: /* @__PURE__ */ new Date()
884
+ content: [{ type: "text", text: useComposer.getState().value }]
872
885
  });
873
886
  useComposer.getState().setValue("");
874
887
  },
@@ -892,36 +905,65 @@ var useAIAssistantContext = () => {
892
905
  });
893
906
  return context;
894
907
  };
895
- var VercelAIAssistantProvider = ({
896
- chat,
897
- children
898
- }) => {
908
+ var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
909
+ var vercelToThreadMessage = (message) => {
910
+ if (message.role !== "user" && message.role !== "assistant")
911
+ throw new Error("Unsupported role");
912
+ return {
913
+ id: message.id,
914
+ role: message.role,
915
+ content: [{ type: "text", text: message.content }]
916
+ };
917
+ };
918
+ var vercelToCachedThreadMessages = (messages) => {
919
+ return messages.map((m) => {
920
+ const cached = ThreadMessageCache.get(m);
921
+ if (cached)
922
+ return cached;
923
+ const newMessage = vercelToThreadMessage(m);
924
+ ThreadMessageCache.set(m, newMessage);
925
+ return newMessage;
926
+ });
927
+ };
928
+ var VercelAIChatAssistantProvider = ({ chat, children }) => {
899
929
  const context = useAIAssistantContext();
930
+ const messages = useMemo4(() => {
931
+ return vercelToCachedThreadMessages(chat.messages);
932
+ }, [chat.messages]);
933
+ const reload = useCallback2(async () => {
934
+ await chat.reload();
935
+ }, [chat.reload]);
936
+ const append = useCallback2(
937
+ async (message) => {
938
+ if (message.content[0]?.type !== "text") {
939
+ throw new Error("Only text content is currently supported");
940
+ }
941
+ await chat.append({
942
+ role: message.role,
943
+ content: message.content[0].text
944
+ });
945
+ },
946
+ [chat.append]
947
+ );
948
+ const stop = useCallback2(() => {
949
+ const lastMessage = chat.messages.at(-1);
950
+ chat.stop();
951
+ if (lastMessage?.role === "user") {
952
+ chat.setInput(lastMessage.content);
953
+ }
954
+ }, [chat.messages, chat.stop, chat.setInput]);
900
955
  useMemo4(() => {
901
956
  context.useThread.setState(
902
957
  {
903
- messages: chat.messages,
904
- setMessages: (value) => {
905
- chat.setMessages(value);
906
- },
958
+ messages,
907
959
  isLoading: chat.isLoading,
908
- reload: async () => {
909
- await chat.reload();
910
- },
911
- append: async (message) => {
912
- await chat.append(message);
913
- },
914
- stop: () => {
915
- const lastMessage = chat.messages.at(-1);
916
- chat.stop();
917
- if (lastMessage?.role === "user") {
918
- chat.setInput(lastMessage.content);
919
- }
920
- }
960
+ reload,
961
+ append,
962
+ stop
921
963
  },
922
964
  true
923
965
  );
924
- }, [context, chat]);
966
+ }, [context, messages, reload, append, stop, chat.isLoading]);
925
967
  useMemo4(() => {
926
968
  context.useComposer.setState({
927
969
  canCancel: chat.isLoading,
@@ -929,17 +971,9 @@ var VercelAIAssistantProvider = ({
929
971
  setValue: chat.setInput
930
972
  });
931
973
  }, [context, chat.isLoading, chat.input, chat.setInput]);
932
- const branches = useChatWithBranches(chat);
974
+ const branches = useVercelAIBranches(chat);
933
975
  useMemo4(() => {
934
- context.useBranchObserver.setState(
935
- {
936
- getBranchState: (message) => branches.getBranchState(message),
937
- switchToBranch: (message, branchId) => branches.switchToBranch(message, branchId),
938
- editAt: async (message, newMessage) => branches.editAt(message, newMessage),
939
- reloadAt: async (message) => branches.reloadAt(message)
940
- },
941
- true
942
- );
976
+ context.useBranchObserver.setState(branches, true);
943
977
  }, [context, branches]);
944
978
  return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
945
979
  };
@@ -949,7 +983,7 @@ export {
949
983
  composer_exports as ComposerPrimitive,
950
984
  message_exports as MessagePrimitive,
951
985
  thread_exports as ThreadPrimitive,
952
- VercelAIAssistantProvider as VercelAIThreadProvider,
986
+ VercelAIChatAssistantProvider as VercelAIAssistantProvider,
953
987
  useMessageContext as unstable_useMessageContext,
954
988
  useBeginMessageEdit,
955
989
  useCopyMessage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": {