@assistant-ui/react 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.d.mts CHANGED
@@ -1,8 +1,7 @@
1
1
  import * as react from 'react';
2
- import { FC, PropsWithChildren } from 'react';
2
+ import { FC, PropsWithChildren, ReactNode, ComponentType } from 'react';
3
3
  import { TextareaAutosizeProps } from 'react-textarea-autosize';
4
- import { Message } from 'ai';
5
- import { UseChatHelpers } from 'ai/react';
4
+ import { UseChatHelpers, UseAssistantHelpers } from 'ai/react';
6
5
  import { UseBoundStore, StoreApi } from 'zustand';
7
6
 
8
7
  declare const ThreadRoot: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
@@ -84,9 +83,60 @@ 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 ThreadMessageTextPart = {
105
+ type: "text";
106
+ text: string;
107
+ };
108
+ type ThreadMessageImagePart = {
109
+ type: "image";
110
+ image: string;
111
+ };
112
+ type ThreadMessageUIPart = {
113
+ type: "ui";
114
+ display: ReactNode;
115
+ };
116
+ type ThreadMessageToolCallPart = {
117
+ type: "tool-call";
118
+ name: string;
119
+ args: object;
120
+ result?: object;
121
+ };
122
+ type ThreadUserMessageContent = ThreadMessageTextPart | ThreadMessageImagePart | ThreadMessageUIPart;
123
+ type ThreadAssistantMessageContent = ThreadMessageTextPart | ThreadMessageImagePart | ThreadMessageUIPart | ThreadMessageToolCallPart;
124
+ type ThreadUserMessage = {
125
+ id: string;
126
+ role: "user";
127
+ content: ThreadUserMessageContent[];
128
+ };
129
+ type ThreadAssistantMessage = {
130
+ id: string;
131
+ role: "assistant";
132
+ content: ThreadAssistantMessageContent[];
133
+ };
134
+ type ThreadMessage = ThreadUserMessage | ThreadAssistantMessage;
135
+ type CreateThreadMessage = Omit<ThreadUserMessage, "id">;
136
+
87
137
  type MessageProviderProps = {
88
138
  children?: React.ReactNode;
89
- message: Message;
139
+ message: ThreadMessage;
90
140
  };
91
141
  declare const MessageProvider: FC<MessageProviderProps>;
92
142
 
@@ -108,7 +158,28 @@ type MessageIfProps = RequireAtLeastOne<MessageIfFilters> & {
108
158
  };
109
159
  declare const MessageIf: FC<MessageIfProps>;
110
160
 
111
- declare const MessageContent: FC;
161
+ type MessageContentProps = {
162
+ components?: {
163
+ Text?: ComponentType<{
164
+ part: ThreadMessageTextPart;
165
+ }>;
166
+ Image?: ComponentType<{
167
+ part: ThreadMessageImagePart;
168
+ }>;
169
+ UI?: ComponentType<{
170
+ part: ThreadMessageUIPart;
171
+ }>;
172
+ tools?: {
173
+ by_name?: Record<string, ComponentType<{
174
+ part: ThreadMessageToolCallPart;
175
+ }>>;
176
+ Fallback?: ComponentType<{
177
+ part: ThreadMessageToolCallPart;
178
+ }>;
179
+ };
180
+ };
181
+ };
182
+ declare const MessageContent: FC<MessageContentProps>;
112
183
 
113
184
  declare namespace index$2 {
114
185
  export { MessageContent as Content, MessageIf as If, MessageProvider as Provider, MessageRoot as Root };
@@ -177,32 +248,26 @@ declare namespace index {
177
248
  export { ActionBarCopy as Copy, ActionBarEdit as Edit, ActionBarReload as Reload, ActionBarRoot as Root };
178
249
  }
179
250
 
180
- type VercelAIAssistantProviderProps = {
251
+ type VercelAIAssistantProviderProps$1 = PropsWithChildren<{
181
252
  chat: UseChatHelpers;
182
- children: React.ReactNode;
183
- };
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;
253
+ } | {
254
+ assistant: UseAssistantHelpers;
255
+ }>;
256
+ declare const VercelAIAssistantProvider: FC<VercelAIAssistantProviderProps$1>;
257
+
258
+ type RSCMessage = {
259
+ id: string;
260
+ role: "user" | "assistant";
261
+ display: ReactNode;
202
262
  };
263
+ type VercelAIAssistantProviderProps = PropsWithChildren<{
264
+ messages: RSCMessage[];
265
+ append: (message: CreateThreadMessage) => Promise<void>;
266
+ }>;
267
+ declare const VercelRSCAssistantProvider: FC<VercelAIAssistantProviderProps>;
203
268
 
204
269
  type MessageState = {
205
- message: Message;
270
+ message: ThreadMessage;
206
271
  branchState: BranchState;
207
272
  isLast: boolean;
208
273
  isCopied: boolean;
@@ -227,4 +292,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
227
292
 
228
293
  declare const useGoToPreviousBranch: () => (() => void) | null;
229
294
 
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 };
295
+ export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIAssistantProvider, VercelRSCAssistantProvider as unstable_VercelRSCAssistantProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import * as react from 'react';
2
- import { FC, PropsWithChildren } from 'react';
2
+ import { FC, PropsWithChildren, ReactNode, ComponentType } from 'react';
3
3
  import { TextareaAutosizeProps } from 'react-textarea-autosize';
4
- import { Message } from 'ai';
5
- import { UseChatHelpers } from 'ai/react';
4
+ import { UseChatHelpers, UseAssistantHelpers } from 'ai/react';
6
5
  import { UseBoundStore, StoreApi } from 'zustand';
7
6
 
8
7
  declare const ThreadRoot: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
@@ -84,9 +83,60 @@ 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 ThreadMessageTextPart = {
105
+ type: "text";
106
+ text: string;
107
+ };
108
+ type ThreadMessageImagePart = {
109
+ type: "image";
110
+ image: string;
111
+ };
112
+ type ThreadMessageUIPart = {
113
+ type: "ui";
114
+ display: ReactNode;
115
+ };
116
+ type ThreadMessageToolCallPart = {
117
+ type: "tool-call";
118
+ name: string;
119
+ args: object;
120
+ result?: object;
121
+ };
122
+ type ThreadUserMessageContent = ThreadMessageTextPart | ThreadMessageImagePart | ThreadMessageUIPart;
123
+ type ThreadAssistantMessageContent = ThreadMessageTextPart | ThreadMessageImagePart | ThreadMessageUIPart | ThreadMessageToolCallPart;
124
+ type ThreadUserMessage = {
125
+ id: string;
126
+ role: "user";
127
+ content: ThreadUserMessageContent[];
128
+ };
129
+ type ThreadAssistantMessage = {
130
+ id: string;
131
+ role: "assistant";
132
+ content: ThreadAssistantMessageContent[];
133
+ };
134
+ type ThreadMessage = ThreadUserMessage | ThreadAssistantMessage;
135
+ type CreateThreadMessage = Omit<ThreadUserMessage, "id">;
136
+
87
137
  type MessageProviderProps = {
88
138
  children?: React.ReactNode;
89
- message: Message;
139
+ message: ThreadMessage;
90
140
  };
91
141
  declare const MessageProvider: FC<MessageProviderProps>;
92
142
 
@@ -108,7 +158,28 @@ type MessageIfProps = RequireAtLeastOne<MessageIfFilters> & {
108
158
  };
109
159
  declare const MessageIf: FC<MessageIfProps>;
110
160
 
111
- declare const MessageContent: FC;
161
+ type MessageContentProps = {
162
+ components?: {
163
+ Text?: ComponentType<{
164
+ part: ThreadMessageTextPart;
165
+ }>;
166
+ Image?: ComponentType<{
167
+ part: ThreadMessageImagePart;
168
+ }>;
169
+ UI?: ComponentType<{
170
+ part: ThreadMessageUIPart;
171
+ }>;
172
+ tools?: {
173
+ by_name?: Record<string, ComponentType<{
174
+ part: ThreadMessageToolCallPart;
175
+ }>>;
176
+ Fallback?: ComponentType<{
177
+ part: ThreadMessageToolCallPart;
178
+ }>;
179
+ };
180
+ };
181
+ };
182
+ declare const MessageContent: FC<MessageContentProps>;
112
183
 
113
184
  declare namespace index$2 {
114
185
  export { MessageContent as Content, MessageIf as If, MessageProvider as Provider, MessageRoot as Root };
@@ -177,32 +248,26 @@ declare namespace index {
177
248
  export { ActionBarCopy as Copy, ActionBarEdit as Edit, ActionBarReload as Reload, ActionBarRoot as Root };
178
249
  }
179
250
 
180
- type VercelAIAssistantProviderProps = {
251
+ type VercelAIAssistantProviderProps$1 = PropsWithChildren<{
181
252
  chat: UseChatHelpers;
182
- children: React.ReactNode;
183
- };
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;
253
+ } | {
254
+ assistant: UseAssistantHelpers;
255
+ }>;
256
+ declare const VercelAIAssistantProvider: FC<VercelAIAssistantProviderProps$1>;
257
+
258
+ type RSCMessage = {
259
+ id: string;
260
+ role: "user" | "assistant";
261
+ display: ReactNode;
202
262
  };
263
+ type VercelAIAssistantProviderProps = PropsWithChildren<{
264
+ messages: RSCMessage[];
265
+ append: (message: CreateThreadMessage) => Promise<void>;
266
+ }>;
267
+ declare const VercelRSCAssistantProvider: FC<VercelAIAssistantProviderProps>;
203
268
 
204
269
  type MessageState = {
205
- message: Message;
270
+ message: ThreadMessage;
206
271
  branchState: BranchState;
207
272
  isLast: boolean;
208
273
  isCopied: boolean;
@@ -227,4 +292,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
227
292
 
228
293
  declare const useGoToPreviousBranch: () => (() => void) | null;
229
294
 
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 };
295
+ export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIAssistantProvider, VercelRSCAssistantProvider as unstable_VercelRSCAssistantProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
package/dist/index.js CHANGED
@@ -35,7 +35,8 @@ __export(src_exports, {
35
35
  ComposerPrimitive: () => composer_exports,
36
36
  MessagePrimitive: () => message_exports,
37
37
  ThreadPrimitive: () => thread_exports,
38
- VercelAIThreadProvider: () => VercelAIAssistantProvider,
38
+ VercelAIAssistantProvider: () => VercelAIAssistantProvider,
39
+ unstable_VercelRSCAssistantProvider: () => VercelRSCAssistantProvider,
39
40
  unstable_useMessageContext: () => useMessageContext,
40
41
  useBeginMessageEdit: () => useBeginMessageEdit,
41
42
  useCopyMessage: () => useCopyMessage,
@@ -102,10 +103,10 @@ var ThreadEmpty = ({ children }) => {
102
103
  };
103
104
 
104
105
  // src/primitives/thread/ThreadViewport.tsx
105
- var import_react4 = require("react");
106
- var import_react_primitive2 = require("@radix-ui/react-primitive");
107
- var import_react_compose_refs = require("@radix-ui/react-compose-refs");
108
106
  var import_primitive = require("@radix-ui/primitive");
107
+ var import_react_compose_refs = require("@radix-ui/react-compose-refs");
108
+ var import_react_primitive2 = require("@radix-ui/react-primitive");
109
+ var import_react4 = require("react");
109
110
 
110
111
  // src/utils/hooks/useOnResizeContent.tsx
111
112
  var import_react3 = require("react");
@@ -138,10 +139,8 @@ var useOnResizeContent = (ref, callback) => {
138
139
  mutationObserver.observe(el, { childList: true });
139
140
  for (const child of el.children) {
140
141
  resizeObserver.observe(child);
141
- console.log("observing child", child);
142
142
  }
143
143
  return () => {
144
- console.log("disconnecting");
145
144
  resizeObserver.disconnect();
146
145
  mutationObserver.disconnect();
147
146
  };
@@ -165,7 +164,6 @@ var ThreadViewport = (0, import_react4.forwardRef)(({ onScroll, children, ...res
165
164
  return;
166
165
  setIsAtBottom(div.scrollHeight - div.scrollTop <= div.clientHeight + 50);
167
166
  };
168
- console.log(isAtBottom);
169
167
  return /* @__PURE__ */ React.createElement(
170
168
  import_react_primitive2.Primitive.div,
171
169
  {
@@ -177,7 +175,7 @@ var ThreadViewport = (0, import_react4.forwardRef)(({ onScroll, children, ...res
177
175
  );
178
176
  });
179
177
 
180
- // src/utils/hooks/useBranches.tsx
178
+ // src/vercel/useVercelAIBranches.tsx
181
179
  var import_react5 = require("react");
182
180
  var ROOT_ID = "__ROOT_ID__";
183
181
  var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
@@ -245,7 +243,7 @@ var sliceMessagesUntil = (messages, message) => {
245
243
  throw new Error("Unexpected: Message not found");
246
244
  return messages.slice(0, messageIdx);
247
245
  };
248
- var useChatWithBranches = (chat) => {
246
+ var useVercelAIBranches = (chat) => {
249
247
  const data = (0, import_react5.useRef)({
250
248
  parentMap: /* @__PURE__ */ new Map(),
251
249
  branchMap: /* @__PURE__ */ new Map(),
@@ -270,19 +268,27 @@ var useChatWithBranches = (chat) => {
270
268
  },
271
269
  [data, chat.messages, chat.setMessages]
272
270
  );
271
+ const reloadMaybe = "reload" in chat ? chat.reload : void 0;
273
272
  const reloadAt = (0, import_react5.useCallback)(
274
273
  async (message) => {
274
+ if (!reloadMaybe)
275
+ throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
275
276
  const newMessages = sliceMessagesUntil(chat.messages, message);
276
277
  chat.setMessages(newMessages);
277
- await chat.reload();
278
+ await reloadMaybe();
278
279
  },
279
- [chat.messages, chat.setMessages, chat.reload]
280
+ [chat.messages, chat.setMessages, reloadMaybe]
280
281
  );
281
282
  const editAt = (0, import_react5.useCallback)(
282
283
  async (message, newMessage) => {
283
284
  const newMessages = sliceMessagesUntil(chat.messages, message);
284
285
  chat.setMessages(newMessages);
285
- await chat.append(newMessage);
286
+ if (newMessage.content[0]?.type !== "text")
287
+ throw new Error("Only text content is currently supported");
288
+ await chat.append({
289
+ role: "user",
290
+ content: newMessage.content[0].text
291
+ });
286
292
  },
287
293
  [chat.messages, chat.setMessages, chat.append]
288
294
  );
@@ -373,18 +379,25 @@ var useMessageContext2 = () => {
373
379
  const useComposer = (0, import_zustand.create)((set, get) => ({
374
380
  isEditing: false,
375
381
  canCancel: true,
376
- edit: () => set({
377
- isEditing: true,
378
- value: useMessage.getState().message.content
379
- }),
382
+ edit: () => {
383
+ const message = useMessage.getState().message;
384
+ if (message.role !== "user")
385
+ throw new Error("Editing is only supported for user messages");
386
+ if (message.content[0]?.type !== "text")
387
+ throw new Error("Editing is only supported for text-only messages");
388
+ return set({
389
+ isEditing: true,
390
+ value: message.content[0].text
391
+ });
392
+ },
380
393
  cancel: () => set({ isEditing: false }),
381
394
  send: () => {
382
395
  const message = useMessage.getState().message;
396
+ if (message.role !== "user")
397
+ throw new Error("Editing is only supported for user messages");
383
398
  useBranchObserver.getState().editAt(message, {
384
- ...message,
385
- id: void 0,
386
- // remove id to create a new message
387
- content: get().value
399
+ role: "user",
400
+ content: [{ type: "text", text: get().value }]
388
401
  });
389
402
  set({ isEditing: false });
390
403
  },
@@ -483,10 +496,41 @@ var MessageIf = ({ children, ...query }) => {
483
496
  };
484
497
 
485
498
  // src/primitives/message/MessageContent.tsx
486
- var MessageContent = () => {
499
+ var defaultComponents = {
500
+ Text: ({ part }) => /* @__PURE__ */ React.createElement(React.Fragment, null, part.text),
501
+ Image: () => null,
502
+ UI: ({ part }) => part.display,
503
+ tools: {
504
+ Fallback: () => null
505
+ }
506
+ };
507
+ var MessageContent = ({
508
+ components: {
509
+ Text = defaultComponents.Text,
510
+ Image = defaultComponents.Image,
511
+ UI = defaultComponents.UI,
512
+ tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
513
+ } = {}
514
+ }) => {
487
515
  const { useMessage } = useMessageContext();
488
516
  const content = useMessage((s) => s.message.content);
489
- return /* @__PURE__ */ React.createElement(React.Fragment, null, content);
517
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, content.map((part, i) => {
518
+ const key = i;
519
+ switch (part.type) {
520
+ case "text":
521
+ return /* @__PURE__ */ React.createElement(Text, { key, part });
522
+ case "image":
523
+ return /* @__PURE__ */ React.createElement(Image, { key, part });
524
+ case "ui":
525
+ return /* @__PURE__ */ React.createElement(UI, { key, part });
526
+ case "tool-call": {
527
+ const Tool = by_name[part.name] || Fallback;
528
+ return /* @__PURE__ */ React.createElement(Tool, { key, part });
529
+ }
530
+ default:
531
+ return null;
532
+ }
533
+ }));
490
534
  };
491
535
 
492
536
  // src/primitives/thread/ThreadMessages.tsx
@@ -515,7 +559,7 @@ var ThreadMessages = ({ components }) => {
515
559
  message: {
516
560
  id: UPCOMING_MESSAGE_ID,
517
561
  role: "assistant",
518
- content: "..."
562
+ content: [{ type: "text", text: "..." }]
519
563
  }
520
564
  },
521
565
  /* @__PURE__ */ React.createElement(AssistantMessage, null)
@@ -810,11 +854,10 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
810
854
  if (isEditing)
811
855
  return null;
812
856
  return () => {
813
- const {
814
- message: { content },
815
- setIsCopied
816
- } = useMessage.getState();
817
- navigator.clipboard.writeText(content);
857
+ const { message, setIsCopied } = useMessage.getState();
858
+ if (message.content[0]?.type !== "text")
859
+ throw new Error("Copying is only supported for text-only messages");
860
+ navigator.clipboard.writeText(message.content[0].text);
818
861
  setIsCopied(true);
819
862
  setTimeout(() => setIsCopied(false), copiedDuration);
820
863
  };
@@ -832,7 +875,10 @@ var useReloadMessage = () => {
832
875
  if (isLoading || !isAssistant)
833
876
  return null;
834
877
  return () => {
835
- useBranchObserver.getState().reloadAt(useMessage.getState().message);
878
+ const message = useMessage.getState().message;
879
+ if (message.role !== "assistant")
880
+ throw new Error("Reloading is only supported on assistant messages");
881
+ useBranchObserver.getState().reloadAt(message);
836
882
  };
837
883
  };
838
884
 
@@ -856,36 +902,40 @@ var useBeginMessageEdit = () => {
856
902
  var ActionBarEdit = createActionButton(useBeginMessageEdit);
857
903
 
858
904
  // src/vercel/VercelAIAssistantProvider.tsx
905
+ var import_react18 = require("react");
906
+
907
+ // src/vercel/useDummyAIAssistantContext.tsx
859
908
  var import_react17 = require("react");
860
909
  var import_zustand2 = require("zustand");
861
- var useAIAssistantContext = () => {
910
+ var useDummyAIAssistantContext = () => {
862
911
  const [context] = (0, import_react17.useState)(() => {
863
912
  const useThread = (0, import_zustand2.create)()(() => ({
864
913
  messages: [],
865
- setMessages: () => {
866
- },
867
914
  isLoading: false,
868
915
  reload: async () => {
916
+ throw new Error("Not implemented");
869
917
  },
870
918
  append: async () => {
919
+ throw new Error("Not implemented");
871
920
  },
872
921
  stop: () => {
922
+ throw new Error("Not implemented");
873
923
  }
874
924
  }));
875
925
  const useComposer = (0, import_zustand2.create)()(() => ({
876
926
  isEditing: true,
877
927
  canCancel: false,
878
928
  value: "",
879
- setValue: () => {
929
+ setValue: (value) => {
930
+ useComposer.setState({ value });
880
931
  },
881
932
  edit: () => {
882
933
  throw new Error("Not implemented");
883
934
  },
884
935
  send: () => {
885
936
  useThread.getState().append({
886
- content: useComposer.getState().value,
887
937
  role: "user",
888
- createdAt: /* @__PURE__ */ new Date()
938
+ content: [{ type: "text", text: useComposer.getState().value }]
889
939
  });
890
940
  useComposer.getState().setValue("");
891
941
  },
@@ -896,70 +946,156 @@ var useAIAssistantContext = () => {
896
946
  const useBranchObserver = (0, import_zustand2.create)()(() => ({
897
947
  getBranchState: () => ({
898
948
  branchId: 0,
899
- branchCount: 0
949
+ branchCount: 1
900
950
  }),
901
951
  switchToBranch: () => {
952
+ throw new Error("Not implemented");
902
953
  },
903
954
  editAt: async () => {
955
+ throw new Error("Not implemented");
904
956
  },
905
957
  reloadAt: async () => {
958
+ throw new Error("Not implemented");
906
959
  }
907
960
  }));
908
961
  return { useThread, useComposer, useBranchObserver };
909
962
  });
910
963
  return context;
911
964
  };
965
+
966
+ // src/vercel/VercelAIAssistantProvider.tsx
967
+ var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
968
+ var vercelToThreadMessage = (message) => {
969
+ if (message.role !== "user" && message.role !== "assistant")
970
+ throw new Error("Unsupported role");
971
+ return {
972
+ id: message.id,
973
+ role: message.role,
974
+ content: [{ type: "text", text: message.content }]
975
+ };
976
+ };
977
+ var vercelToCachedThreadMessages = (messages) => {
978
+ return messages.map((m) => {
979
+ const cached = ThreadMessageCache.get(m);
980
+ if (cached)
981
+ return cached;
982
+ const newMessage = vercelToThreadMessage(m);
983
+ ThreadMessageCache.set(m, newMessage);
984
+ return newMessage;
985
+ });
986
+ };
912
987
  var VercelAIAssistantProvider = ({
913
- chat,
914
- children
988
+ children,
989
+ ...rest
915
990
  }) => {
916
- const context = useAIAssistantContext();
917
- (0, import_react17.useMemo)(() => {
991
+ const context = useDummyAIAssistantContext();
992
+ const vercel = "chat" in rest ? rest.chat : rest.assistant;
993
+ const messages = (0, import_react18.useMemo)(() => {
994
+ return vercelToCachedThreadMessages(vercel.messages);
995
+ }, [vercel.messages]);
996
+ const maybeReload = "reload" in vercel ? vercel.reload : null;
997
+ const reload = (0, import_react18.useCallback)(async () => {
998
+ if (!maybeReload)
999
+ throw new Error("Reload not supported");
1000
+ await maybeReload();
1001
+ }, [maybeReload]);
1002
+ const append = (0, import_react18.useCallback)(
1003
+ async (message) => {
1004
+ if (message.content[0]?.type !== "text") {
1005
+ throw new Error("Only text content is currently supported");
1006
+ }
1007
+ await vercel.append({
1008
+ role: message.role,
1009
+ content: message.content[0].text
1010
+ });
1011
+ },
1012
+ [vercel.append]
1013
+ );
1014
+ const stop = (0, import_react18.useCallback)(() => {
1015
+ const lastMessage = vercel.messages.at(-1);
1016
+ vercel.stop();
1017
+ if (lastMessage?.role === "user") {
1018
+ vercel.setInput(lastMessage.content);
1019
+ }
1020
+ }, [vercel.messages, vercel.stop, vercel.setInput]);
1021
+ const isLoading = "isLoading" in vercel ? vercel.isLoading : vercel.status === "in_progress";
1022
+ (0, import_react18.useMemo)(() => {
918
1023
  context.useThread.setState(
919
1024
  {
920
- messages: chat.messages,
921
- setMessages: (value) => {
922
- chat.setMessages(value);
923
- },
924
- 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
- }
1025
+ messages,
1026
+ isLoading,
1027
+ reload,
1028
+ append,
1029
+ stop
938
1030
  },
939
1031
  true
940
1032
  );
941
- }, [context, chat]);
942
- (0, import_react17.useMemo)(() => {
1033
+ }, [context, messages, reload, append, stop, isLoading]);
1034
+ (0, import_react18.useMemo)(() => {
943
1035
  context.useComposer.setState({
944
- canCancel: chat.isLoading,
945
- value: chat.input,
946
- setValue: chat.setInput
1036
+ canCancel: isLoading,
1037
+ value: vercel.input,
1038
+ setValue: vercel.setInput
947
1039
  });
948
- }, [context, chat.isLoading, chat.input, chat.setInput]);
949
- const branches = useChatWithBranches(chat);
950
- (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
- );
1040
+ }, [context, isLoading, vercel.input, vercel.setInput]);
1041
+ const branches = useVercelAIBranches(vercel);
1042
+ (0, import_react18.useMemo)(() => {
1043
+ context.useBranchObserver.setState(branches, true);
960
1044
  }, [context, branches]);
961
1045
  return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
962
1046
  };
1047
+
1048
+ // src/vercel/VercelRSCAssistantProvider.tsx
1049
+ var import_react19 = require("react");
1050
+ var ThreadMessageCache2 = /* @__PURE__ */ new WeakMap();
1051
+ var vercelToThreadMessage2 = (message) => {
1052
+ if (message.role !== "user" && message.role !== "assistant")
1053
+ throw new Error("Unsupported role");
1054
+ return {
1055
+ id: message.id,
1056
+ role: message.role,
1057
+ content: [{ type: "ui", display: message.display }]
1058
+ };
1059
+ };
1060
+ var vercelToCachedThreadMessages2 = (messages) => {
1061
+ return messages.map((m) => {
1062
+ const cached = ThreadMessageCache2.get(m);
1063
+ if (cached)
1064
+ return cached;
1065
+ const newMessage = vercelToThreadMessage2(m);
1066
+ ThreadMessageCache2.set(m, newMessage);
1067
+ return newMessage;
1068
+ });
1069
+ };
1070
+ var VercelRSCAssistantProvider = ({
1071
+ children,
1072
+ messages: vercelMessages,
1073
+ append: vercelAppend
1074
+ }) => {
1075
+ const context = useDummyAIAssistantContext();
1076
+ const messages = (0, import_react19.useMemo)(() => {
1077
+ return vercelToCachedThreadMessages2(vercelMessages);
1078
+ }, [vercelMessages]);
1079
+ const append = (0, import_react19.useCallback)(
1080
+ async (message) => {
1081
+ if (message.content[0]?.type !== "text") {
1082
+ throw new Error("Only text content is currently supported");
1083
+ }
1084
+ await vercelAppend({
1085
+ role: message.role,
1086
+ content: [{ type: "text", text: message.content[0].text }]
1087
+ });
1088
+ },
1089
+ [vercelAppend]
1090
+ );
1091
+ (0, import_react19.useMemo)(() => {
1092
+ context.useThread.setState({
1093
+ messages,
1094
+ append
1095
+ });
1096
+ }, [context, messages, append]);
1097
+ return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
1098
+ };
963
1099
  // Annotate the CommonJS export names for ESM import in node:
964
1100
  0 && (module.exports = {
965
1101
  ActionBarPrimitive,
@@ -967,7 +1103,8 @@ var VercelAIAssistantProvider = ({
967
1103
  ComposerPrimitive,
968
1104
  MessagePrimitive,
969
1105
  ThreadPrimitive,
970
- VercelAIThreadProvider,
1106
+ VercelAIAssistantProvider,
1107
+ unstable_VercelRSCAssistantProvider,
971
1108
  unstable_useMessageContext,
972
1109
  useBeginMessageEdit,
973
1110
  useCopyMessage,
package/dist/index.mjs CHANGED
@@ -63,12 +63,12 @@ var ThreadEmpty = ({ children }) => {
63
63
  };
64
64
 
65
65
  // src/primitives/thread/ThreadViewport.tsx
66
- import { forwardRef as forwardRef2, useRef as useRef2, useState } from "react";
66
+ import { composeEventHandlers } from "@radix-ui/primitive";
67
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
67
68
  import {
68
69
  Primitive as Primitive2
69
70
  } from "@radix-ui/react-primitive";
70
- import { useComposedRefs } from "@radix-ui/react-compose-refs";
71
- import { composeEventHandlers } from "@radix-ui/primitive";
71
+ import { forwardRef as forwardRef2, useRef as useRef2, useState } from "react";
72
72
 
73
73
  // src/utils/hooks/useOnResizeContent.tsx
74
74
  import { useLayoutEffect, useRef } from "react";
@@ -101,10 +101,8 @@ var useOnResizeContent = (ref, callback) => {
101
101
  mutationObserver.observe(el, { childList: true });
102
102
  for (const child of el.children) {
103
103
  resizeObserver.observe(child);
104
- console.log("observing child", child);
105
104
  }
106
105
  return () => {
107
- console.log("disconnecting");
108
106
  resizeObserver.disconnect();
109
107
  mutationObserver.disconnect();
110
108
  };
@@ -128,7 +126,6 @@ var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef)
128
126
  return;
129
127
  setIsAtBottom(div.scrollHeight - div.scrollTop <= div.clientHeight + 50);
130
128
  };
131
- console.log(isAtBottom);
132
129
  return /* @__PURE__ */ React.createElement(
133
130
  Primitive2.div,
134
131
  {
@@ -140,7 +137,7 @@ var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef)
140
137
  );
141
138
  });
142
139
 
143
- // src/utils/hooks/useBranches.tsx
140
+ // src/vercel/useVercelAIBranches.tsx
144
141
  import { useCallback, useMemo, useRef as useRef3 } from "react";
145
142
  var ROOT_ID = "__ROOT_ID__";
146
143
  var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
@@ -208,7 +205,7 @@ var sliceMessagesUntil = (messages, message) => {
208
205
  throw new Error("Unexpected: Message not found");
209
206
  return messages.slice(0, messageIdx);
210
207
  };
211
- var useChatWithBranches = (chat) => {
208
+ var useVercelAIBranches = (chat) => {
212
209
  const data = useRef3({
213
210
  parentMap: /* @__PURE__ */ new Map(),
214
211
  branchMap: /* @__PURE__ */ new Map(),
@@ -233,19 +230,27 @@ var useChatWithBranches = (chat) => {
233
230
  },
234
231
  [data, chat.messages, chat.setMessages]
235
232
  );
233
+ const reloadMaybe = "reload" in chat ? chat.reload : void 0;
236
234
  const reloadAt = useCallback(
237
235
  async (message) => {
236
+ if (!reloadMaybe)
237
+ throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
238
238
  const newMessages = sliceMessagesUntil(chat.messages, message);
239
239
  chat.setMessages(newMessages);
240
- await chat.reload();
240
+ await reloadMaybe();
241
241
  },
242
- [chat.messages, chat.setMessages, chat.reload]
242
+ [chat.messages, chat.setMessages, reloadMaybe]
243
243
  );
244
244
  const editAt = useCallback(
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
  },
@@ -448,10 +460,41 @@ var MessageIf = ({ children, ...query }) => {
448
460
  };
449
461
 
450
462
  // src/primitives/message/MessageContent.tsx
451
- var MessageContent = () => {
463
+ var defaultComponents = {
464
+ Text: ({ part }) => /* @__PURE__ */ React.createElement(React.Fragment, null, part.text),
465
+ Image: () => null,
466
+ UI: ({ part }) => part.display,
467
+ tools: {
468
+ Fallback: () => null
469
+ }
470
+ };
471
+ var MessageContent = ({
472
+ components: {
473
+ Text = defaultComponents.Text,
474
+ Image = defaultComponents.Image,
475
+ UI = defaultComponents.UI,
476
+ tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
477
+ } = {}
478
+ }) => {
452
479
  const { useMessage } = useMessageContext();
453
480
  const content = useMessage((s) => s.message.content);
454
- return /* @__PURE__ */ React.createElement(React.Fragment, null, content);
481
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, content.map((part, i) => {
482
+ const key = i;
483
+ switch (part.type) {
484
+ case "text":
485
+ return /* @__PURE__ */ React.createElement(Text, { key, part });
486
+ case "image":
487
+ return /* @__PURE__ */ React.createElement(Image, { key, part });
488
+ case "ui":
489
+ return /* @__PURE__ */ React.createElement(UI, { key, part });
490
+ case "tool-call": {
491
+ const Tool = by_name[part.name] || Fallback;
492
+ return /* @__PURE__ */ React.createElement(Tool, { key, part });
493
+ }
494
+ default:
495
+ return null;
496
+ }
497
+ }));
455
498
  };
456
499
 
457
500
  // src/primitives/thread/ThreadMessages.tsx
@@ -480,7 +523,7 @@ var ThreadMessages = ({ components }) => {
480
523
  message: {
481
524
  id: UPCOMING_MESSAGE_ID,
482
525
  role: "assistant",
483
- content: "..."
526
+ content: [{ type: "text", text: "..." }]
484
527
  }
485
528
  },
486
529
  /* @__PURE__ */ React.createElement(AssistantMessage, null)
@@ -793,11 +836,10 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
793
836
  if (isEditing)
794
837
  return null;
795
838
  return () => {
796
- const {
797
- message: { content },
798
- setIsCopied
799
- } = useMessage.getState();
800
- navigator.clipboard.writeText(content);
839
+ const { message, setIsCopied } = useMessage.getState();
840
+ if (message.content[0]?.type !== "text")
841
+ throw new Error("Copying is only supported for text-only messages");
842
+ navigator.clipboard.writeText(message.content[0].text);
801
843
  setIsCopied(true);
802
844
  setTimeout(() => setIsCopied(false), copiedDuration);
803
845
  };
@@ -815,7 +857,10 @@ var useReloadMessage = () => {
815
857
  if (isLoading || !isAssistant)
816
858
  return null;
817
859
  return () => {
818
- useBranchObserver.getState().reloadAt(useMessage.getState().message);
860
+ const message = useMessage.getState().message;
861
+ if (message.role !== "assistant")
862
+ throw new Error("Reloading is only supported on assistant messages");
863
+ useBranchObserver.getState().reloadAt(message);
819
864
  };
820
865
  };
821
866
 
@@ -839,36 +884,40 @@ var useBeginMessageEdit = () => {
839
884
  var ActionBarEdit = createActionButton(useBeginMessageEdit);
840
885
 
841
886
  // src/vercel/VercelAIAssistantProvider.tsx
842
- import { useMemo as useMemo4, useState as useState3 } from "react";
887
+ import { useCallback as useCallback2, useMemo as useMemo4 } from "react";
888
+
889
+ // src/vercel/useDummyAIAssistantContext.tsx
890
+ import { useState as useState3 } from "react";
843
891
  import { create as create2 } from "zustand";
844
- var useAIAssistantContext = () => {
892
+ var useDummyAIAssistantContext = () => {
845
893
  const [context] = useState3(() => {
846
894
  const useThread = create2()(() => ({
847
895
  messages: [],
848
- setMessages: () => {
849
- },
850
896
  isLoading: false,
851
897
  reload: async () => {
898
+ throw new Error("Not implemented");
852
899
  },
853
900
  append: async () => {
901
+ throw new Error("Not implemented");
854
902
  },
855
903
  stop: () => {
904
+ throw new Error("Not implemented");
856
905
  }
857
906
  }));
858
907
  const useComposer = create2()(() => ({
859
908
  isEditing: true,
860
909
  canCancel: false,
861
910
  value: "",
862
- setValue: () => {
911
+ setValue: (value) => {
912
+ useComposer.setState({ value });
863
913
  },
864
914
  edit: () => {
865
915
  throw new Error("Not implemented");
866
916
  },
867
917
  send: () => {
868
918
  useThread.getState().append({
869
- content: useComposer.getState().value,
870
919
  role: "user",
871
- createdAt: /* @__PURE__ */ new Date()
920
+ content: [{ type: "text", text: useComposer.getState().value }]
872
921
  });
873
922
  useComposer.getState().setValue("");
874
923
  },
@@ -879,77 +928,167 @@ var useAIAssistantContext = () => {
879
928
  const useBranchObserver = create2()(() => ({
880
929
  getBranchState: () => ({
881
930
  branchId: 0,
882
- branchCount: 0
931
+ branchCount: 1
883
932
  }),
884
933
  switchToBranch: () => {
934
+ throw new Error("Not implemented");
885
935
  },
886
936
  editAt: async () => {
937
+ throw new Error("Not implemented");
887
938
  },
888
939
  reloadAt: async () => {
940
+ throw new Error("Not implemented");
889
941
  }
890
942
  }));
891
943
  return { useThread, useComposer, useBranchObserver };
892
944
  });
893
945
  return context;
894
946
  };
947
+
948
+ // src/vercel/VercelAIAssistantProvider.tsx
949
+ var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
950
+ var vercelToThreadMessage = (message) => {
951
+ if (message.role !== "user" && message.role !== "assistant")
952
+ throw new Error("Unsupported role");
953
+ return {
954
+ id: message.id,
955
+ role: message.role,
956
+ content: [{ type: "text", text: message.content }]
957
+ };
958
+ };
959
+ var vercelToCachedThreadMessages = (messages) => {
960
+ return messages.map((m) => {
961
+ const cached = ThreadMessageCache.get(m);
962
+ if (cached)
963
+ return cached;
964
+ const newMessage = vercelToThreadMessage(m);
965
+ ThreadMessageCache.set(m, newMessage);
966
+ return newMessage;
967
+ });
968
+ };
895
969
  var VercelAIAssistantProvider = ({
896
- chat,
897
- children
970
+ children,
971
+ ...rest
898
972
  }) => {
899
- const context = useAIAssistantContext();
973
+ const context = useDummyAIAssistantContext();
974
+ const vercel = "chat" in rest ? rest.chat : rest.assistant;
975
+ const messages = useMemo4(() => {
976
+ return vercelToCachedThreadMessages(vercel.messages);
977
+ }, [vercel.messages]);
978
+ const maybeReload = "reload" in vercel ? vercel.reload : null;
979
+ const reload = useCallback2(async () => {
980
+ if (!maybeReload)
981
+ throw new Error("Reload not supported");
982
+ await maybeReload();
983
+ }, [maybeReload]);
984
+ const append = useCallback2(
985
+ async (message) => {
986
+ if (message.content[0]?.type !== "text") {
987
+ throw new Error("Only text content is currently supported");
988
+ }
989
+ await vercel.append({
990
+ role: message.role,
991
+ content: message.content[0].text
992
+ });
993
+ },
994
+ [vercel.append]
995
+ );
996
+ const stop = useCallback2(() => {
997
+ const lastMessage = vercel.messages.at(-1);
998
+ vercel.stop();
999
+ if (lastMessage?.role === "user") {
1000
+ vercel.setInput(lastMessage.content);
1001
+ }
1002
+ }, [vercel.messages, vercel.stop, vercel.setInput]);
1003
+ const isLoading = "isLoading" in vercel ? vercel.isLoading : vercel.status === "in_progress";
900
1004
  useMemo4(() => {
901
1005
  context.useThread.setState(
902
1006
  {
903
- messages: chat.messages,
904
- setMessages: (value) => {
905
- chat.setMessages(value);
906
- },
907
- 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
- }
1007
+ messages,
1008
+ isLoading,
1009
+ reload,
1010
+ append,
1011
+ stop
921
1012
  },
922
1013
  true
923
1014
  );
924
- }, [context, chat]);
1015
+ }, [context, messages, reload, append, stop, isLoading]);
925
1016
  useMemo4(() => {
926
1017
  context.useComposer.setState({
927
- canCancel: chat.isLoading,
928
- value: chat.input,
929
- setValue: chat.setInput
1018
+ canCancel: isLoading,
1019
+ value: vercel.input,
1020
+ setValue: vercel.setInput
930
1021
  });
931
- }, [context, chat.isLoading, chat.input, chat.setInput]);
932
- const branches = useChatWithBranches(chat);
1022
+ }, [context, isLoading, vercel.input, vercel.setInput]);
1023
+ const branches = useVercelAIBranches(vercel);
933
1024
  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
- );
1025
+ context.useBranchObserver.setState(branches, true);
943
1026
  }, [context, branches]);
944
1027
  return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
945
1028
  };
1029
+
1030
+ // src/vercel/VercelRSCAssistantProvider.tsx
1031
+ import {
1032
+ useCallback as useCallback3,
1033
+ useMemo as useMemo5
1034
+ } from "react";
1035
+ var ThreadMessageCache2 = /* @__PURE__ */ new WeakMap();
1036
+ var vercelToThreadMessage2 = (message) => {
1037
+ if (message.role !== "user" && message.role !== "assistant")
1038
+ throw new Error("Unsupported role");
1039
+ return {
1040
+ id: message.id,
1041
+ role: message.role,
1042
+ content: [{ type: "ui", display: message.display }]
1043
+ };
1044
+ };
1045
+ var vercelToCachedThreadMessages2 = (messages) => {
1046
+ return messages.map((m) => {
1047
+ const cached = ThreadMessageCache2.get(m);
1048
+ if (cached)
1049
+ return cached;
1050
+ const newMessage = vercelToThreadMessage2(m);
1051
+ ThreadMessageCache2.set(m, newMessage);
1052
+ return newMessage;
1053
+ });
1054
+ };
1055
+ var VercelRSCAssistantProvider = ({
1056
+ children,
1057
+ messages: vercelMessages,
1058
+ append: vercelAppend
1059
+ }) => {
1060
+ const context = useDummyAIAssistantContext();
1061
+ const messages = useMemo5(() => {
1062
+ return vercelToCachedThreadMessages2(vercelMessages);
1063
+ }, [vercelMessages]);
1064
+ const append = useCallback3(
1065
+ async (message) => {
1066
+ if (message.content[0]?.type !== "text") {
1067
+ throw new Error("Only text content is currently supported");
1068
+ }
1069
+ await vercelAppend({
1070
+ role: message.role,
1071
+ content: [{ type: "text", text: message.content[0].text }]
1072
+ });
1073
+ },
1074
+ [vercelAppend]
1075
+ );
1076
+ useMemo5(() => {
1077
+ context.useThread.setState({
1078
+ messages,
1079
+ append
1080
+ });
1081
+ }, [context, messages, append]);
1082
+ return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
1083
+ };
946
1084
  export {
947
1085
  actionBar_exports as ActionBarPrimitive,
948
1086
  branchPicker_exports as BranchPickerPrimitive,
949
1087
  composer_exports as ComposerPrimitive,
950
1088
  message_exports as MessagePrimitive,
951
1089
  thread_exports as ThreadPrimitive,
952
- VercelAIAssistantProvider as VercelAIThreadProvider,
1090
+ VercelAIAssistantProvider,
1091
+ VercelRSCAssistantProvider as unstable_VercelRSCAssistantProvider,
953
1092
  useMessageContext as unstable_useMessageContext,
954
1093
  useBeginMessageEdit,
955
1094
  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.7",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": {
@@ -28,7 +28,7 @@
28
28
  "@radix-ui/react-compose-refs": "^1.0.1",
29
29
  "@radix-ui/react-primitive": "^1.0.3",
30
30
  "@radix-ui/react-slot": "^1.0.2",
31
- "ai": "^3.1.10",
31
+ "ai": "^3.1.12",
32
32
  "react-textarea-autosize": "^8.5.3",
33
33
  "zustand": "^4.5.2"
34
34
  },