@assistant-ui/react 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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
  },