@assistant-ui/react 0.0.19 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  ActionBarPrimitive: () => actionBar_exports,
34
+ AssistantRuntimeProvider: () => AssistantRuntimeProvider,
34
35
  BranchPickerPrimitive: () => branchPicker_exports,
35
36
  ComposerPrimitive: () => composer_exports,
36
37
  ContentPartPrimitive: () => contentPart_exports,
@@ -38,20 +39,175 @@ __export(src_exports, {
38
39
  ThreadPrimitive: () => thread_exports,
39
40
  VercelAIAssistantProvider: () => VercelAIAssistantProvider,
40
41
  VercelRSCAssistantProvider: () => VercelRSCAssistantProvider,
41
- unstable_AssistantProvider: () => AssistantProvider,
42
+ getVercelAIMessage: () => getVercelAIMessage,
43
+ getVercelRSCMessage: () => getVercelRSCMessage,
42
44
  unstable_VercelModelAdapter: () => VercelModelAdapter,
43
- unstable_getVercelMessage: () => getVercelMessage,
44
- unstable_getVercelRSCMessage: () => getVercelRSCMessage,
45
+ unstable_useComposerContext: () => useComposerContext,
46
+ unstable_useContentPartContext: () => useContentPartContext,
45
47
  unstable_useLocalRuntime: () => useLocalRuntime,
46
48
  unstable_useMessageContext: () => useMessageContext,
49
+ unstable_useThreadContext: () => useThreadContext,
47
50
  useBeginMessageEdit: () => useBeginMessageEdit,
48
51
  useCopyMessage: () => useCopyMessage,
49
52
  useGoToNextBranch: () => useGoToNextBranch,
50
53
  useGoToPreviousBranch: () => useGoToPreviousBranch,
51
- useReloadMessage: () => useReloadMessage
54
+ useReloadMessage: () => useReloadMessage,
55
+ useVercelRSCRuntime: () => useVercelRSCRuntime,
56
+ useVercelUseAssistantRuntime: () => useVercelUseAssistantRuntime,
57
+ useVercelUseChatRuntime: () => useVercelUseChatRuntime
52
58
  });
53
59
  module.exports = __toCommonJS(src_exports);
54
60
 
61
+ // src/actions/useCopyMessage.tsx
62
+ var import_react4 = require("react");
63
+
64
+ // src/context/MessageContext.ts
65
+ var import_react = require("react");
66
+ var MessageContext = (0, import_react.createContext)(null);
67
+ var useMessageContext = () => {
68
+ const context = (0, import_react.useContext)(MessageContext);
69
+ if (!context)
70
+ throw new Error(
71
+ "This component can only be used inside a component passed to <ThreadPrimitive.Messages components={...} />."
72
+ );
73
+ return context;
74
+ };
75
+
76
+ // src/utils/combined/useCombinedStore.ts
77
+ var import_react3 = require("react");
78
+
79
+ // src/utils/combined/createCombinedStore.ts
80
+ var import_react2 = require("react");
81
+ var createCombinedStore = (stores) => {
82
+ const subscribe = (callback) => {
83
+ const unsubscribes = stores.map((store) => store.subscribe(callback));
84
+ return () => {
85
+ for (const unsub of unsubscribes) {
86
+ unsub();
87
+ }
88
+ };
89
+ };
90
+ return (selector) => {
91
+ const getSnapshot = () => selector(...stores.map((store) => store.getState()));
92
+ return (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
93
+ };
94
+ };
95
+
96
+ // src/utils/combined/useCombinedStore.ts
97
+ var useCombinedStore = (stores, selector) => {
98
+ const useCombined = (0, import_react3.useMemo)(() => createCombinedStore(stores), stores);
99
+ return useCombined(selector);
100
+ };
101
+
102
+ // src/utils/getMessageText.tsx
103
+ var getMessageText = (message) => {
104
+ const textParts = message.content.filter(
105
+ (part) => part.type === "text"
106
+ );
107
+ return textParts.map((part) => part.text).join("\n\n");
108
+ };
109
+
110
+ // src/actions/useCopyMessage.tsx
111
+ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
112
+ const { useMessage, useComposer } = useMessageContext();
113
+ const hasCopyableContent = useCombinedStore(
114
+ [useMessage, useComposer],
115
+ (m, c) => {
116
+ return c.isEditing || m.message.content.some((c2) => c2.type === "text");
117
+ }
118
+ );
119
+ const callback = (0, import_react4.useCallback)(() => {
120
+ const { isEditing, value: composerValue } = useComposer.getState();
121
+ const { message, setIsCopied } = useMessage.getState();
122
+ const valueToCopy = isEditing ? composerValue : getMessageText(message);
123
+ navigator.clipboard.writeText(valueToCopy);
124
+ setIsCopied(true);
125
+ setTimeout(() => setIsCopied(false), copiedDuration);
126
+ }, [useComposer, useMessage, copiedDuration]);
127
+ if (!hasCopyableContent) return null;
128
+ return callback;
129
+ };
130
+
131
+ // src/actions/useReloadMessage.tsx
132
+ var import_react6 = require("react");
133
+
134
+ // src/context/ThreadContext.ts
135
+ var import_react5 = require("react");
136
+ var ThreadContext = (0, import_react5.createContext)(null);
137
+ var useThreadContext = () => {
138
+ const context = (0, import_react5.useContext)(ThreadContext);
139
+ if (!context)
140
+ throw new Error("This component must be used within an AssistantProvider.");
141
+ return context;
142
+ };
143
+
144
+ // src/actions/useReloadMessage.tsx
145
+ var useReloadMessage = () => {
146
+ const { useThread, useViewport } = useThreadContext();
147
+ const { useMessage } = useMessageContext();
148
+ const disabled = useCombinedStore(
149
+ [useThread, useMessage],
150
+ (t, m) => t.isRunning || m.message.role !== "assistant"
151
+ );
152
+ const callback = (0, import_react6.useCallback)(() => {
153
+ const { parentId } = useMessage.getState();
154
+ useThread.getState().startRun(parentId);
155
+ useViewport.getState().scrollToBottom();
156
+ }, [useMessage, useThread, useViewport]);
157
+ if (disabled) return null;
158
+ return callback;
159
+ };
160
+
161
+ // src/actions/useBeginMessageEdit.tsx
162
+ var import_react7 = require("react");
163
+ var useBeginMessageEdit = () => {
164
+ const { useMessage, useComposer } = useMessageContext();
165
+ const disabled = useCombinedStore(
166
+ [useMessage, useComposer],
167
+ (m, c) => m.message.role !== "user" || c.isEditing
168
+ );
169
+ const callback = (0, import_react7.useCallback)(() => {
170
+ const { edit } = useComposer.getState();
171
+ edit();
172
+ }, [useComposer]);
173
+ if (disabled) return null;
174
+ return callback;
175
+ };
176
+
177
+ // src/actions/useGoToNextBranch.tsx
178
+ var import_react8 = require("react");
179
+ var useGoToNextBranch = () => {
180
+ const { useThread } = useThreadContext();
181
+ const { useMessage, useComposer } = useMessageContext();
182
+ const disabled = useCombinedStore(
183
+ [useMessage, useComposer],
184
+ (m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
185
+ );
186
+ const callback = (0, import_react8.useCallback)(() => {
187
+ const { message, branches } = useMessage.getState();
188
+ useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
189
+ }, [useMessage, useThread]);
190
+ if (disabled) return null;
191
+ return callback;
192
+ };
193
+
194
+ // src/actions/useGoToPreviousBranch.tsx
195
+ var import_react9 = require("react");
196
+ var useGoToPreviousBranch = () => {
197
+ const { useThread } = useThreadContext();
198
+ const { useMessage, useComposer } = useMessageContext();
199
+ const disabled = useCombinedStore(
200
+ [useMessage, useComposer],
201
+ (m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
202
+ );
203
+ const callback = (0, import_react9.useCallback)(() => {
204
+ const { message, branches } = useMessage.getState();
205
+ useThread.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
206
+ }, [useMessage, useThread]);
207
+ if (disabled) return null;
208
+ return callback;
209
+ };
210
+
55
211
  // src/primitives/thread/index.ts
56
212
  var thread_exports = {};
57
213
  __export(thread_exports, {
@@ -66,29 +222,17 @@ __export(thread_exports, {
66
222
 
67
223
  // src/primitives/thread/ThreadRoot.tsx
68
224
  var import_react_primitive = require("@radix-ui/react-primitive");
69
- var import_react = require("react");
225
+ var import_react10 = require("react");
70
226
  var import_jsx_runtime = require("react/jsx-runtime");
71
- var ThreadRoot = (0, import_react.forwardRef)(
227
+ var ThreadRoot = (0, import_react10.forwardRef)(
72
228
  (props, ref) => {
73
229
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { ...props, ref });
74
230
  }
75
231
  );
76
232
 
77
- // src/utils/context/AssistantContext.ts
78
- var import_react2 = require("react");
79
- var AssistantContext = (0, import_react2.createContext)(null);
80
- var useAssistantContext = () => {
81
- const context = (0, import_react2.useContext)(AssistantContext);
82
- if (!context)
83
- throw new Error(
84
- "This component must be used within a AssistantProvider."
85
- );
86
- return context;
87
- };
88
-
89
233
  // src/primitives/thread/ThreadIf.tsx
90
234
  var useThreadIf = (props) => {
91
- const { useThread } = useAssistantContext();
235
+ const { useThread } = useThreadContext();
92
236
  return useThread((thread) => {
93
237
  if (props.empty === true && thread.messages.length !== 0) return false;
94
238
  if (props.empty === false && thread.messages.length === 0) return false;
@@ -112,14 +256,14 @@ var ThreadEmpty = ({ children }) => {
112
256
  var import_primitive = require("@radix-ui/primitive");
113
257
  var import_react_compose_refs = require("@radix-ui/react-compose-refs");
114
258
  var import_react_primitive2 = require("@radix-ui/react-primitive");
115
- var import_react5 = require("react");
259
+ var import_react13 = require("react");
116
260
 
117
261
  // src/utils/hooks/useOnResizeContent.tsx
118
262
  var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
119
- var import_react3 = require("react");
263
+ var import_react11 = require("react");
120
264
  var useOnResizeContent = (ref, callback) => {
121
265
  const callbackRef = (0, import_react_use_callback_ref.useCallbackRef)(callback);
122
- (0, import_react3.useEffect)(() => {
266
+ (0, import_react11.useEffect)(() => {
123
267
  const el = ref.current;
124
268
  if (!el) return;
125
269
  const resizeObserver = new ResizeObserver(() => {
@@ -154,11 +298,11 @@ var useOnResizeContent = (ref, callback) => {
154
298
 
155
299
  // src/utils/hooks/useOnScrollToBottom.tsx
156
300
  var import_react_use_callback_ref2 = require("@radix-ui/react-use-callback-ref");
157
- var import_react4 = require("react");
301
+ var import_react12 = require("react");
158
302
  var useOnScrollToBottom = (callback) => {
159
303
  const callbackRef = (0, import_react_use_callback_ref2.useCallbackRef)(callback);
160
- const { useViewport } = useAssistantContext();
161
- (0, import_react4.useEffect)(() => {
304
+ const { useViewport } = useThreadContext();
305
+ (0, import_react12.useEffect)(() => {
162
306
  return useViewport.getState().onScrollToBottom(() => {
163
307
  callbackRef();
164
308
  });
@@ -167,14 +311,14 @@ var useOnScrollToBottom = (callback) => {
167
311
 
168
312
  // src/primitives/thread/ThreadViewport.tsx
169
313
  var import_jsx_runtime3 = require("react/jsx-runtime");
170
- var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
171
- const messagesEndRef = (0, import_react5.useRef)(null);
172
- const divRef = (0, import_react5.useRef)(null);
314
+ var ThreadViewport = (0, import_react13.forwardRef)(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
315
+ const messagesEndRef = (0, import_react13.useRef)(null);
316
+ const divRef = (0, import_react13.useRef)(null);
173
317
  const ref = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, divRef);
174
- const { useViewport } = useAssistantContext();
175
- const firstRenderRef = (0, import_react5.useRef)(true);
176
- const isScrollingToBottomRef = (0, import_react5.useRef)(false);
177
- const lastScrollTop = (0, import_react5.useRef)(0);
318
+ const { useViewport } = useThreadContext();
319
+ const firstRenderRef = (0, import_react13.useRef)(true);
320
+ const isScrollingToBottomRef = (0, import_react13.useRef)(false);
321
+ const lastScrollTop = (0, import_react13.useRef)(0);
178
322
  const scrollToBottom = () => {
179
323
  const div = messagesEndRef.current;
180
324
  if (!div || !autoScroll) return;
@@ -219,76 +363,23 @@ var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScrol
219
363
  );
220
364
  });
221
365
 
222
- // src/utils/context/useComposerContext.ts
223
- var import_react7 = require("react");
224
-
225
- // src/utils/context/useMessageContext.ts
226
- var import_react6 = require("react");
227
- var MessageContext = (0, import_react6.createContext)(null);
228
- var useMessageContext = () => {
229
- const context = (0, import_react6.useContext)(MessageContext);
230
- if (!context)
231
- throw new Error(
232
- "This component must be used within a MessagePrimitive.Provider."
233
- );
234
- return context;
235
- };
236
-
237
- // src/utils/context/useComposerContext.ts
238
- var useComposerContext = () => {
239
- const { useComposer: useAssisstantComposer } = useAssistantContext();
240
- const { useComposer: useMessageComposer } = (0, import_react7.useContext)(MessageContext) ?? {};
241
- return {
242
- useComposer: useMessageComposer ?? useAssisstantComposer,
243
- type: useMessageComposer ? "message" : "assistant"
244
- };
245
- };
246
-
247
- // src/primitives/composer/ComposerIf.tsx
248
- var useComposerIf = (props) => {
249
- const { useComposer } = useComposerContext();
250
- return useComposer((composer) => {
251
- if (props.editing === true && !composer.isEditing) return false;
252
- if (props.editing === false && composer.isEditing) return false;
253
- return true;
254
- });
255
- };
256
- var ComposerIf = ({ children, ...query }) => {
257
- const result = useComposerIf(query);
258
- return result ? children : null;
259
- };
260
-
261
- // src/primitives/message/index.ts
262
- var message_exports = {};
263
- __export(message_exports, {
264
- Content: () => MessageContent,
265
- If: () => MessageIf,
266
- InProgress: () => MessageInProgress,
267
- Provider: () => MessageProvider,
268
- Root: () => MessageRoot
269
- });
270
-
271
- // src/primitives/message/MessageProvider.tsx
272
- var import_react8 = require("react");
366
+ // src/context/providers/MessageProvider.tsx
367
+ var import_react14 = require("react");
273
368
  var import_zustand2 = require("zustand");
274
369
 
275
- // src/utils/context/getMessageText.tsx
276
- var getMessageText = (message) => {
277
- const textParts = message.content.filter(
278
- (part) => part.type === "text"
279
- );
280
- return textParts.map((part) => part.text).join("\n\n");
281
- };
282
-
283
- // src/utils/context/stores/ComposerStore.ts
370
+ // src/context/stores/MessageComposer.ts
284
371
  var import_zustand = require("zustand");
372
+
373
+ // src/context/stores/BaseComposer.ts
285
374
  var makeBaseComposer = (set) => ({
286
375
  value: "",
287
376
  setValue: (value) => {
288
377
  set({ value });
289
378
  }
290
379
  });
291
- var makeMessageComposerStore = ({
380
+
381
+ // src/context/stores/MessageComposer.ts
382
+ var makeEditComposerStore = ({
292
383
  onEdit,
293
384
  onSend
294
385
  }) => (0, import_zustand.create)()((set, get, store) => ({
@@ -309,35 +400,31 @@ var makeMessageComposerStore = ({
309
400
  return true;
310
401
  }
311
402
  }));
312
- var makeThreadComposerStore = (useThread) => (0, import_zustand.create)()((set, get, store) => {
313
- return {
314
- ...makeBaseComposer(set, get, store),
315
- isEditing: true,
316
- send: () => {
317
- const { value } = get();
318
- set({ value: "" });
319
- useThread.getState().append({
320
- parentId: useThread.getState().messages.at(-1)?.id ?? null,
321
- content: [{ type: "text", text: value }]
322
- });
323
- },
324
- cancel: () => {
325
- const thread = useThread.getState();
326
- if (!thread.isRunning) return false;
327
- useThread.getState().cancelRun();
328
- return true;
329
- }
330
- };
331
- });
332
403
 
333
- // src/primitives/message/MessageProvider.tsx
404
+ // src/context/providers/MessageProvider.tsx
334
405
  var import_jsx_runtime4 = require("react/jsx-runtime");
335
406
  var getIsLast = (thread, message) => {
336
407
  return thread.messages[thread.messages.length - 1]?.id === message.id;
337
408
  };
338
- var useMessageContext2 = () => {
339
- const { useThread } = useAssistantContext();
340
- const [context] = (0, import_react8.useState)(() => {
409
+ var syncMessage = (thread, useMessage, messageIndex) => {
410
+ const parentId = thread.messages[messageIndex - 1]?.id ?? null;
411
+ const message = thread.messages[messageIndex];
412
+ if (!message) return;
413
+ const isLast = getIsLast(thread, message);
414
+ const branches = thread.getBranches(message.id);
415
+ const currentState = useMessage.getState();
416
+ if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
417
+ return;
418
+ useMessage.setState({
419
+ message,
420
+ parentId,
421
+ branches,
422
+ isLast
423
+ });
424
+ };
425
+ var useMessageContext2 = (messageIndex) => {
426
+ const { useThread } = useThreadContext();
427
+ const [context] = (0, import_react14.useState)(() => {
341
428
  const useMessage = (0, import_zustand2.create)((set) => ({
342
429
  message: null,
343
430
  parentId: null,
@@ -356,7 +443,7 @@ var useMessageContext2 = () => {
356
443
  set({ isHovering: value });
357
444
  }
358
445
  }));
359
- const useComposer = makeMessageComposerStore({
446
+ const useComposer = makeEditComposerStore({
360
447
  onEdit: () => {
361
448
  const message = useMessage.getState().message;
362
449
  if (message.role !== "user")
@@ -381,56 +468,51 @@ var useMessageContext2 = () => {
381
468
  });
382
469
  }
383
470
  });
471
+ syncMessage(useThread.getState(), useMessage, messageIndex);
384
472
  return { useMessage, useComposer };
385
473
  });
474
+ (0, import_react14.useEffect)(() => {
475
+ return useThread.subscribe((thread) => {
476
+ syncMessage(thread, context.useMessage, messageIndex);
477
+ });
478
+ }, [context, useThread, messageIndex]);
386
479
  return context;
387
480
  };
388
481
  var MessageProvider = ({
389
- message,
390
- parentId,
482
+ messageIndex,
391
483
  children
392
484
  }) => {
393
- const { useThread } = useAssistantContext();
394
- const context = useMessageContext2();
395
- const isLast = useThread((thread) => getIsLast(thread, message));
396
- const branches = useThread((thread) => thread.getBranches(message.id));
397
- (0, import_react8.useMemo)(() => {
398
- context.useMessage.setState({
399
- message,
400
- parentId,
401
- branches,
402
- isLast
403
- });
404
- }, [context, message, parentId, branches, isLast]);
485
+ const context = useMessageContext2(messageIndex);
405
486
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageContext.Provider, { value: context, children });
406
487
  };
407
488
 
408
- // src/primitives/message/MessageRoot.tsx
409
- var import_primitive2 = require("@radix-ui/primitive");
410
- var import_react_primitive3 = require("@radix-ui/react-primitive");
411
- var import_react9 = require("react");
412
- var import_jsx_runtime5 = require("react/jsx-runtime");
413
- var MessageRoot = (0, import_react9.forwardRef)(
414
- ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
415
- const { useMessage } = useMessageContext();
416
- const setIsHovering = useMessage((s) => s.setIsHovering);
417
- const handleMouseEnter = () => {
418
- setIsHovering(true);
419
- };
420
- const handleMouseLeave = () => {
421
- setIsHovering(false);
422
- };
423
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
424
- import_react_primitive3.Primitive.div,
425
- {
426
- ...rest,
427
- ref,
428
- onMouseEnter: (0, import_primitive2.composeEventHandlers)(onMouseEnter, handleMouseEnter),
429
- onMouseLeave: (0, import_primitive2.composeEventHandlers)(onMouseLeave, handleMouseLeave)
430
- }
431
- );
432
- }
433
- );
489
+ // src/context/ComposerContext.ts
490
+ var import_react15 = require("react");
491
+ var useComposerContext = () => {
492
+ const { useComposer } = useThreadContext();
493
+ const { useComposer: useEditComposer } = (0, import_react15.useContext)(MessageContext) ?? {};
494
+ return (0, import_react15.useMemo)(
495
+ () => ({
496
+ useComposer: useEditComposer ?? useComposer,
497
+ type: useEditComposer ? "edit" : "new"
498
+ }),
499
+ [useEditComposer, useComposer]
500
+ );
501
+ };
502
+
503
+ // src/primitives/composer/ComposerIf.tsx
504
+ var useComposerIf = (props) => {
505
+ const { useComposer } = useComposerContext();
506
+ return useComposer((composer) => {
507
+ if (props.editing === true && !composer.isEditing) return false;
508
+ if (props.editing === false && composer.isEditing) return false;
509
+ return true;
510
+ });
511
+ };
512
+ var ComposerIf = ({ children, ...query }) => {
513
+ const result = useComposerIf(query);
514
+ return result ? children : null;
515
+ };
434
516
 
435
517
  // src/primitives/message/MessageIf.tsx
436
518
  var useMessageIf = (props) => {
@@ -450,160 +532,8 @@ var MessageIf = ({ children, ...query }) => {
450
532
  return result ? children : null;
451
533
  };
452
534
 
453
- // src/utils/context/combined/useCombinedStore.ts
454
- var import_react11 = require("react");
455
-
456
- // src/utils/context/combined/createCombinedStore.ts
457
- var import_react10 = require("react");
458
- var createCombinedStore = (stores) => {
459
- const subscribe = (callback) => {
460
- const unsubscribes = stores.map((store) => store.subscribe(callback));
461
- return () => {
462
- for (const unsub of unsubscribes) {
463
- unsub();
464
- }
465
- };
466
- };
467
- return (selector) => {
468
- const getSnapshot = () => selector(...stores.map((store) => store.getState()));
469
- return (0, import_react10.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
470
- };
471
- };
472
-
473
- // src/utils/context/combined/useCombinedStore.ts
474
- var useCombinedStore = (stores, selector) => {
475
- const useCombined = (0, import_react11.useMemo)(() => createCombinedStore(stores), stores);
476
- return useCombined(selector);
477
- };
478
-
479
- // src/utils/context/useContentPartContext.ts
480
- var import_react12 = require("react");
481
- var ContentPartContext = (0, import_react12.createContext)(null);
482
- var useContentPartContext = () => {
483
- const context = (0, import_react12.useContext)(ContentPartContext);
484
- if (!context)
485
- throw new Error(
486
- "This component must be used within a ContentPartPrimitive.Provider."
487
- );
488
- return context;
489
- };
490
-
491
- // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
492
- var ContentPartInProgressIndicator = () => {
493
- const { useMessage } = useMessageContext();
494
- const { useContentPart } = useContentPartContext();
495
- const indicator = useCombinedStore(
496
- [useMessage, useContentPart],
497
- (m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
498
- );
499
- return indicator;
500
- };
501
-
502
- // src/primitives/contentPart/ContentPartProvider.tsx
503
- var import_react13 = require("react");
504
- var import_zustand3 = require("zustand");
505
- var import_jsx_runtime6 = require("react/jsx-runtime");
506
- var useContentPartContext2 = () => {
507
- const [context] = (0, import_react13.useState)(() => {
508
- const useContentPart = (0, import_zustand3.create)(() => ({
509
- part: null,
510
- status: "done"
511
- }));
512
- return { useContentPart };
513
- });
514
- return context;
515
- };
516
- var ContentPartProvider = ({
517
- part,
518
- status,
519
- children
520
- }) => {
521
- const context = useContentPartContext2();
522
- (0, import_react13.useMemo)(() => {
523
- context.useContentPart.setState(
524
- {
525
- part,
526
- status
527
- },
528
- true
529
- );
530
- }, [context, part, status]);
531
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ContentPartContext.Provider, { value: context, children });
532
- };
533
-
534
- // src/primitives/message/MessageContent.tsx
535
- var import_jsx_runtime7 = require("react/jsx-runtime");
536
- var defaultComponents = {
537
- Text: ({ part }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
538
- part.text,
539
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ContentPartInProgressIndicator, {})
540
- ] }),
541
- Image: () => null,
542
- UI: ({ part }) => part.display,
543
- tools: {
544
- Fallback: () => null
545
- }
546
- };
547
- var MessageContent = ({
548
- components: {
549
- Text = defaultComponents.Text,
550
- Image = defaultComponents.Image,
551
- UI = defaultComponents.UI,
552
- tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
553
- } = {}
554
- }) => {
555
- const { useMessage } = useMessageContext();
556
- const message = useMessage((s) => s.message);
557
- const content = message.content;
558
- const status = message.role === "assistant" ? message.status : "done";
559
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: content.map((part, i) => {
560
- const key = i;
561
- const type = part.type;
562
- let component = null;
563
- switch (type) {
564
- case "text":
565
- component = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { part });
566
- break;
567
- case "image":
568
- component = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Image, { part });
569
- break;
570
- case "ui":
571
- component = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(UI, { part });
572
- break;
573
- case "tool-call": {
574
- const Tool = by_name[part.name] || Fallback;
575
- component = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Tool, { part });
576
- break;
577
- }
578
- default:
579
- throw new Error(`Unknown content part type: ${type}`);
580
- }
581
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
582
- ContentPartProvider,
583
- {
584
- part,
585
- status: i === content.length - 1 ? status : "done",
586
- children: component
587
- },
588
- key
589
- );
590
- }) });
591
- };
592
-
593
- // src/primitives/message/MessageInProgress.tsx
594
- var import_react_primitive4 = require("@radix-ui/react-primitive");
595
- var import_react14 = require("react");
596
- var import_jsx_runtime8 = require("react/jsx-runtime");
597
- var MessageInProgress = (0, import_react14.forwardRef)((props, ref) => {
598
- const { useMessage } = useMessageContext();
599
- (0, import_react14.useMemo)(() => {
600
- useMessage.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_primitive4.Primitive.div, { ...props, ref }));
601
- }, [useMessage, props, ref]);
602
- return null;
603
- });
604
-
605
535
  // src/primitives/thread/ThreadMessages.tsx
606
- var import_jsx_runtime9 = require("react/jsx-runtime");
536
+ var import_jsx_runtime5 = require("react/jsx-runtime");
607
537
  var getComponents = (components) => {
608
538
  return {
609
539
  EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
@@ -612,60 +542,58 @@ var getComponents = (components) => {
612
542
  };
613
543
  };
614
544
  var ThreadMessages = ({ components }) => {
615
- const { useThread } = useAssistantContext();
616
- const thread = useThread();
617
- const messages = thread.messages;
545
+ const { useThread } = useThreadContext();
546
+ const messagesLength = useThread((t) => t.messages.length);
618
547
  const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
619
- if (messages.length === 0) return null;
620
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: messages.map((message, idx) => {
621
- const parentId = messages[idx - 1]?.id ?? null;
622
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
548
+ if (messagesLength === 0) return null;
549
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: new Array(messagesLength).fill(null).map((_, idx) => {
550
+ const messageIndex = idx;
551
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
623
552
  MessageProvider,
624
553
  {
625
- message,
626
- parentId,
554
+ messageIndex,
627
555
  children: [
628
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(MessageIf, { user: true, children: [
629
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComposerIf, { editing: false, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(UserMessage, {}) }),
630
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComposerIf, { editing: true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EditComposer, {}) })
556
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(MessageIf, { user: true, children: [
557
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ComposerIf, { editing: false, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(UserMessage, {}) }),
558
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ComposerIf, { editing: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EditComposer, {}) })
631
559
  ] }),
632
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MessageIf, { assistant: true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AssistantMessage, {}) })
560
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MessageIf, { assistant: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AssistantMessage, {}) })
633
561
  ]
634
562
  },
635
- parentId ?? "__ROOT__"
563
+ messageIndex
636
564
  );
637
565
  }) });
638
566
  };
639
567
 
640
568
  // src/primitives/thread/ThreadScrollToBottom.tsx
641
- var import_primitive3 = require("@radix-ui/primitive");
642
- var import_react_primitive5 = require("@radix-ui/react-primitive");
643
- var import_react15 = require("react");
644
- var import_jsx_runtime10 = require("react/jsx-runtime");
645
- var ThreadScrollToBottom = (0, import_react15.forwardRef)(({ onClick, ...rest }, ref) => {
646
- const { useViewport } = useAssistantContext();
569
+ var import_primitive2 = require("@radix-ui/primitive");
570
+ var import_react_primitive3 = require("@radix-ui/react-primitive");
571
+ var import_react16 = require("react");
572
+ var import_jsx_runtime6 = require("react/jsx-runtime");
573
+ var ThreadScrollToBottom = (0, import_react16.forwardRef)(({ onClick, ...rest }, ref) => {
574
+ const { useViewport } = useThreadContext();
647
575
  const isAtBottom = useViewport((s) => s.isAtBottom);
648
576
  const handleScrollToBottom = () => {
649
577
  useViewport.getState().scrollToBottom();
650
578
  };
651
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
652
- import_react_primitive5.Primitive.button,
579
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
580
+ import_react_primitive3.Primitive.button,
653
581
  {
654
582
  ...rest,
655
583
  disabled: isAtBottom,
656
584
  ref,
657
- onClick: (0, import_primitive3.composeEventHandlers)(onClick, handleScrollToBottom)
585
+ onClick: (0, import_primitive2.composeEventHandlers)(onClick, handleScrollToBottom)
658
586
  }
659
587
  );
660
588
  });
661
589
 
662
590
  // src/primitives/thread/ThreadSuggestion.tsx
663
- var import_primitive4 = require("@radix-ui/primitive");
664
- var import_react_primitive6 = require("@radix-ui/react-primitive");
665
- var import_react16 = require("react");
666
- var import_jsx_runtime11 = require("react/jsx-runtime");
667
- var ThreadSuggestion = (0, import_react16.forwardRef)(({ onClick, prompt, method, autoSend: send, ...rest }, ref) => {
668
- const { useThread, useComposer } = useAssistantContext();
591
+ var import_primitive3 = require("@radix-ui/primitive");
592
+ var import_react_primitive4 = require("@radix-ui/react-primitive");
593
+ var import_react17 = require("react");
594
+ var import_jsx_runtime7 = require("react/jsx-runtime");
595
+ var ThreadSuggestion = (0, import_react17.forwardRef)(({ onClick, prompt, method, autoSend: send, ...rest }, ref) => {
596
+ const { useThread, useComposer } = useThreadContext();
669
597
  const isDisabled = useThread((t) => t.isRunning);
670
598
  const handleApplySuggestion = () => {
671
599
  const thread = useThread.getState();
@@ -675,13 +603,13 @@ var ThreadSuggestion = (0, import_react16.forwardRef)(({ onClick, prompt, method
675
603
  composer.send();
676
604
  }
677
605
  };
678
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
679
- import_react_primitive6.Primitive.button,
606
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
607
+ import_react_primitive4.Primitive.button,
680
608
  {
681
609
  ...rest,
682
610
  disabled: isDisabled,
683
611
  ref,
684
- onClick: (0, import_primitive4.composeEventHandlers)(onClick, handleApplySuggestion)
612
+ onClick: (0, import_primitive3.composeEventHandlers)(onClick, handleApplySuggestion)
685
613
  }
686
614
  );
687
615
  });
@@ -697,16 +625,16 @@ __export(composer_exports, {
697
625
  });
698
626
 
699
627
  // src/primitives/composer/ComposerRoot.tsx
700
- var import_primitive5 = require("@radix-ui/primitive");
628
+ var import_primitive4 = require("@radix-ui/primitive");
701
629
  var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
702
- var import_react_primitive7 = require("@radix-ui/react-primitive");
703
- var import_react17 = require("react");
704
- var import_jsx_runtime12 = require("react/jsx-runtime");
705
- var ComposerRoot = (0, import_react17.forwardRef)(
630
+ var import_react_primitive5 = require("@radix-ui/react-primitive");
631
+ var import_react18 = require("react");
632
+ var import_jsx_runtime8 = require("react/jsx-runtime");
633
+ var ComposerRoot = (0, import_react18.forwardRef)(
706
634
  ({ onSubmit, ...rest }, forwardedRef) => {
707
- const { useViewport } = useAssistantContext();
635
+ const { useViewport } = useThreadContext();
708
636
  const { useComposer } = useComposerContext();
709
- const formRef = (0, import_react17.useRef)(null);
637
+ const formRef = (0, import_react18.useRef)(null);
710
638
  const ref = (0, import_react_compose_refs2.useComposedRefs)(forwardedRef, formRef);
711
639
  const handleSubmit = (e) => {
712
640
  const composerState = useComposer.getState();
@@ -715,27 +643,27 @@ var ComposerRoot = (0, import_react17.forwardRef)(
715
643
  composerState.send();
716
644
  useViewport.getState().scrollToBottom();
717
645
  };
718
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
719
- import_react_primitive7.Primitive.form,
646
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
647
+ import_react_primitive5.Primitive.form,
720
648
  {
721
649
  ...rest,
722
650
  ref,
723
- onSubmit: (0, import_primitive5.composeEventHandlers)(onSubmit, handleSubmit)
651
+ onSubmit: (0, import_primitive4.composeEventHandlers)(onSubmit, handleSubmit)
724
652
  }
725
653
  );
726
654
  }
727
655
  );
728
656
 
729
657
  // src/primitives/composer/ComposerInput.tsx
730
- var import_primitive6 = require("@radix-ui/primitive");
658
+ var import_primitive5 = require("@radix-ui/primitive");
731
659
  var import_react_compose_refs3 = require("@radix-ui/react-compose-refs");
732
660
  var import_react_slot = require("@radix-ui/react-slot");
733
- var import_react18 = require("react");
661
+ var import_react19 = require("react");
734
662
  var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
735
- var import_jsx_runtime13 = require("react/jsx-runtime");
736
- var ComposerInput = (0, import_react18.forwardRef)(
663
+ var import_jsx_runtime9 = require("react/jsx-runtime");
664
+ var ComposerInput = (0, import_react19.forwardRef)(
737
665
  ({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
738
- const { useThread, useViewport } = useAssistantContext();
666
+ const { useThread, useViewport } = useThreadContext();
739
667
  const { useComposer, type } = useComposerContext();
740
668
  const value = useComposer((c) => {
741
669
  if (!c.isEditing) return "";
@@ -758,10 +686,10 @@ var ComposerInput = (0, import_react18.forwardRef)(
758
686
  }
759
687
  }
760
688
  };
761
- const textareaRef = (0, import_react18.useRef)(null);
689
+ const textareaRef = (0, import_react19.useRef)(null);
762
690
  const ref = (0, import_react_compose_refs3.useComposedRefs)(forwardedRef, textareaRef);
763
691
  const autoFocusEnabled = autoFocus && !disabled;
764
- const focus = (0, import_react18.useCallback)(() => {
692
+ const focus = (0, import_react19.useCallback)(() => {
765
693
  const textarea = textareaRef.current;
766
694
  if (!textarea || !autoFocusEnabled) return;
767
695
  textarea.focus();
@@ -770,40 +698,40 @@ var ComposerInput = (0, import_react18.forwardRef)(
770
698
  textareaRef.current.value.length
771
699
  );
772
700
  }, [autoFocusEnabled]);
773
- (0, import_react18.useEffect)(() => focus(), [focus]);
701
+ (0, import_react19.useEffect)(() => focus(), [focus]);
774
702
  useOnScrollToBottom(() => {
775
- if (type === "assistant") {
703
+ if (type === "new") {
776
704
  focus();
777
705
  }
778
706
  });
779
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
707
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
780
708
  Component,
781
709
  {
782
710
  value,
783
711
  ...rest,
784
712
  ref,
785
713
  disabled,
786
- onChange: (0, import_primitive6.composeEventHandlers)(onChange, (e) => {
714
+ onChange: (0, import_primitive5.composeEventHandlers)(onChange, (e) => {
787
715
  const composerState = useComposer.getState();
788
716
  if (!composerState.isEditing) return;
789
717
  return composerState.setValue(e.target.value);
790
718
  }),
791
- onKeyDown: (0, import_primitive6.composeEventHandlers)(onKeyDown, handleKeyPress)
719
+ onKeyDown: (0, import_primitive5.composeEventHandlers)(onKeyDown, handleKeyPress)
792
720
  }
793
721
  );
794
722
  }
795
723
  );
796
724
 
797
725
  // src/primitives/composer/ComposerSend.tsx
798
- var import_react_primitive8 = require("@radix-ui/react-primitive");
799
- var import_react19 = require("react");
800
- var import_jsx_runtime14 = require("react/jsx-runtime");
801
- var ComposerSend = (0, import_react19.forwardRef)(
726
+ var import_react_primitive6 = require("@radix-ui/react-primitive");
727
+ var import_react20 = require("react");
728
+ var import_jsx_runtime10 = require("react/jsx-runtime");
729
+ var ComposerSend = (0, import_react20.forwardRef)(
802
730
  ({ disabled, ...rest }, ref) => {
803
731
  const { useComposer } = useComposerContext();
804
732
  const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
805
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
806
- import_react_primitive8.Primitive.button,
733
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
734
+ import_react_primitive6.Primitive.button,
807
735
  {
808
736
  type: "submit",
809
737
  ...rest,
@@ -815,26 +743,187 @@ var ComposerSend = (0, import_react19.forwardRef)(
815
743
  );
816
744
 
817
745
  // src/primitives/composer/ComposerCancel.tsx
818
- var import_primitive7 = require("@radix-ui/primitive");
819
- var import_react_primitive9 = require("@radix-ui/react-primitive");
820
- var import_react20 = require("react");
821
- var import_jsx_runtime15 = require("react/jsx-runtime");
822
- var ComposerCancel = (0, import_react20.forwardRef)(({ onClick, ...rest }, ref) => {
746
+ var import_primitive6 = require("@radix-ui/primitive");
747
+ var import_react_primitive7 = require("@radix-ui/react-primitive");
748
+ var import_react21 = require("react");
749
+ var import_jsx_runtime11 = require("react/jsx-runtime");
750
+ var ComposerCancel = (0, import_react21.forwardRef)(({ onClick, ...rest }, ref) => {
823
751
  const { useComposer } = useComposerContext();
824
752
  const handleCancel = () => {
825
753
  useComposer.getState().cancel();
826
754
  };
827
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
828
- import_react_primitive9.Primitive.button,
755
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
756
+ import_react_primitive7.Primitive.button,
829
757
  {
830
758
  type: "button",
831
759
  ...rest,
832
760
  ref,
833
- onClick: (0, import_primitive7.composeEventHandlers)(onClick, handleCancel)
761
+ onClick: (0, import_primitive6.composeEventHandlers)(onClick, handleCancel)
834
762
  }
835
763
  );
836
764
  });
837
765
 
766
+ // src/primitives/message/index.ts
767
+ var message_exports = {};
768
+ __export(message_exports, {
769
+ Content: () => MessageContent,
770
+ If: () => MessageIf,
771
+ InProgress: () => MessageInProgress,
772
+ Root: () => MessageRoot
773
+ });
774
+
775
+ // src/primitives/message/MessageRoot.tsx
776
+ var import_primitive7 = require("@radix-ui/primitive");
777
+ var import_react_primitive8 = require("@radix-ui/react-primitive");
778
+ var import_react22 = require("react");
779
+ var import_jsx_runtime12 = require("react/jsx-runtime");
780
+ var MessageRoot = (0, import_react22.forwardRef)(
781
+ ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
782
+ const { useMessage } = useMessageContext();
783
+ const setIsHovering = useMessage((s) => s.setIsHovering);
784
+ const handleMouseEnter = () => {
785
+ setIsHovering(true);
786
+ };
787
+ const handleMouseLeave = () => {
788
+ setIsHovering(false);
789
+ };
790
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
791
+ import_react_primitive8.Primitive.div,
792
+ {
793
+ ...rest,
794
+ ref,
795
+ onMouseEnter: (0, import_primitive7.composeEventHandlers)(onMouseEnter, handleMouseEnter),
796
+ onMouseLeave: (0, import_primitive7.composeEventHandlers)(onMouseLeave, handleMouseLeave)
797
+ }
798
+ );
799
+ }
800
+ );
801
+
802
+ // src/context/providers/ContentPartProvider.tsx
803
+ var import_react24 = require("react");
804
+ var import_zustand3 = require("zustand");
805
+
806
+ // src/context/ContentPartContext.ts
807
+ var import_react23 = require("react");
808
+ var ContentPartContext = (0, import_react23.createContext)(
809
+ null
810
+ );
811
+ var useContentPartContext = () => {
812
+ const context = (0, import_react23.useContext)(ContentPartContext);
813
+ if (!context)
814
+ throw new Error(
815
+ "This component can only be used inside a component passed to <MessagePrimitive.Content components={...} >."
816
+ );
817
+ return context;
818
+ };
819
+
820
+ // src/context/providers/ContentPartProvider.tsx
821
+ var import_jsx_runtime13 = require("react/jsx-runtime");
822
+ var syncContentPart = ({ message }, useContentPart, partIndex) => {
823
+ const part = message.content[partIndex];
824
+ if (!part) return;
825
+ const messageStatus = message.role === "assistant" ? message.status : "done";
826
+ const status = partIndex === message.content.length - 1 ? messageStatus : "done";
827
+ useContentPart.setState({ part, status });
828
+ };
829
+ var useContentPartContext2 = (partIndex) => {
830
+ const { useMessage } = useMessageContext();
831
+ const [context] = (0, import_react24.useState)(() => {
832
+ const useContentPart = (0, import_zustand3.create)(() => ({
833
+ part: { type: "text", text: "" },
834
+ status: "done"
835
+ }));
836
+ syncContentPart(useMessage.getState(), useContentPart, partIndex);
837
+ return { useContentPart };
838
+ });
839
+ (0, import_react24.useEffect)(() => {
840
+ return useMessage.subscribe((message) => {
841
+ syncContentPart(message, context.useContentPart, partIndex);
842
+ });
843
+ }, [context, useMessage, partIndex]);
844
+ return context;
845
+ };
846
+ var ContentPartProvider = ({
847
+ partIndex,
848
+ children
849
+ }) => {
850
+ const context = useContentPartContext2(partIndex);
851
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ContentPartContext.Provider, { value: context, children });
852
+ };
853
+
854
+ // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
855
+ var ContentPartInProgressIndicator = () => {
856
+ const { useMessage } = useMessageContext();
857
+ const { useContentPart } = useContentPartContext();
858
+ const indicator = useCombinedStore(
859
+ [useMessage, useContentPart],
860
+ (m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
861
+ );
862
+ return indicator;
863
+ };
864
+
865
+ // src/primitives/message/MessageContent.tsx
866
+ var import_jsx_runtime14 = require("react/jsx-runtime");
867
+ var defaultComponents = {
868
+ Text: ({ part }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
869
+ part.text,
870
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ContentPartInProgressIndicator, {})
871
+ ] }),
872
+ Image: () => null,
873
+ UI: ({ part }) => part.display,
874
+ tools: {
875
+ Fallback: () => null
876
+ }
877
+ };
878
+ var MessageContent = ({
879
+ components: {
880
+ Text = defaultComponents.Text,
881
+ Image = defaultComponents.Image,
882
+ UI = defaultComponents.UI,
883
+ tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
884
+ } = {}
885
+ }) => {
886
+ const { useMessage } = useMessageContext();
887
+ const message = useMessage((s) => s.message);
888
+ const content = message.content;
889
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: content.map((part, i) => {
890
+ const partIndex = i;
891
+ const type = part.type;
892
+ let component = null;
893
+ switch (type) {
894
+ case "text":
895
+ component = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { part });
896
+ break;
897
+ case "image":
898
+ component = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Image, { part });
899
+ break;
900
+ case "ui":
901
+ component = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(UI, { part });
902
+ break;
903
+ case "tool-call": {
904
+ const Tool = by_name[part.name] || Fallback;
905
+ component = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Tool, { part });
906
+ break;
907
+ }
908
+ default:
909
+ throw new Error(`Unknown content part type: ${type}`);
910
+ }
911
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ContentPartProvider, { partIndex, children: component }, partIndex);
912
+ }) });
913
+ };
914
+
915
+ // src/primitives/message/MessageInProgress.tsx
916
+ var import_react_primitive9 = require("@radix-ui/react-primitive");
917
+ var import_react25 = require("react");
918
+ var import_jsx_runtime15 = require("react/jsx-runtime");
919
+ var MessageInProgress = (0, import_react25.forwardRef)((props, ref) => {
920
+ const { useMessage } = useMessageContext();
921
+ (0, import_react25.useMemo)(() => {
922
+ useMessage.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_primitive9.Primitive.span, { ...props, ref }));
923
+ }, [useMessage, props, ref]);
924
+ return null;
925
+ });
926
+
838
927
  // src/primitives/branchPicker/index.ts
839
928
  var branchPicker_exports = {};
840
929
  __export(branchPicker_exports, {
@@ -845,30 +934,13 @@ __export(branchPicker_exports, {
845
934
  Root: () => BranchPickerRoot
846
935
  });
847
936
 
848
- // src/actions/useGoToNextBranch.tsx
849
- var import_react21 = require("react");
850
- var useGoToNextBranch = () => {
851
- const { useThread } = useAssistantContext();
852
- const { useMessage, useComposer } = useMessageContext();
853
- const disabled = useCombinedStore(
854
- [useMessage, useComposer],
855
- (m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
856
- );
857
- const callback = (0, import_react21.useCallback)(() => {
858
- const { message, branches } = useMessage.getState();
859
- useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
860
- }, [useMessage, useThread]);
861
- if (disabled) return null;
862
- return callback;
863
- };
864
-
865
937
  // src/utils/createActionButton.tsx
866
938
  var import_primitive8 = require("@radix-ui/primitive");
867
939
  var import_react_primitive10 = require("@radix-ui/react-primitive");
868
- var import_react22 = require("react");
940
+ var import_react26 = require("react");
869
941
  var import_jsx_runtime16 = require("react/jsx-runtime");
870
942
  var createActionButton = (useActionButton) => {
871
- return (0, import_react22.forwardRef)(
943
+ return (0, import_react26.forwardRef)(
872
944
  (props, forwardedRef) => {
873
945
  const onClick = useActionButton(props);
874
946
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
@@ -888,23 +960,6 @@ var createActionButton = (useActionButton) => {
888
960
  // src/primitives/branchPicker/BranchPickerNext.tsx
889
961
  var BranchPickerNext = createActionButton(useGoToNextBranch);
890
962
 
891
- // src/actions/useGoToPreviousBranch.tsx
892
- var import_react23 = require("react");
893
- var useGoToPreviousBranch = () => {
894
- const { useThread } = useAssistantContext();
895
- const { useMessage, useComposer } = useMessageContext();
896
- const disabled = useCombinedStore(
897
- [useMessage, useComposer],
898
- (m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
899
- );
900
- const callback = (0, import_react23.useCallback)(() => {
901
- const { message, branches } = useMessage.getState();
902
- useThread.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
903
- }, [useMessage, useThread]);
904
- if (disabled) return null;
905
- return callback;
906
- };
907
-
908
963
  // src/primitives/branchPicker/BranchPickerPrevious.tsx
909
964
  var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
910
965
 
@@ -926,9 +981,9 @@ var BranchPickerNumber = () => {
926
981
 
927
982
  // src/primitives/branchPicker/BranchPickerRoot.tsx
928
983
  var import_react_primitive11 = require("@radix-ui/react-primitive");
929
- var import_react24 = require("react");
984
+ var import_react27 = require("react");
930
985
  var import_jsx_runtime19 = require("react/jsx-runtime");
931
- var BranchPickerRoot = (0, import_react24.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
986
+ var BranchPickerRoot = (0, import_react27.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
932
987
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_primitive11.Primitive.div, { ...rest, ref }) });
933
988
  });
934
989
 
@@ -943,10 +998,10 @@ __export(actionBar_exports, {
943
998
 
944
999
  // src/primitives/actionBar/ActionBarRoot.tsx
945
1000
  var import_react_primitive12 = require("@radix-ui/react-primitive");
946
- var import_react25 = require("react");
1001
+ var import_react28 = require("react");
947
1002
  var import_jsx_runtime20 = require("react/jsx-runtime");
948
- var ActionBarRoot = (0, import_react25.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
949
- const { useThread } = useAssistantContext();
1003
+ var ActionBarRoot = (0, import_react28.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
1004
+ const { useThread } = useThreadContext();
950
1005
  const { useMessage } = useMessageContext();
951
1006
  const hideAndfloatStatus = useCombinedStore(
952
1007
  [useThread, useMessage],
@@ -971,142 +1026,166 @@ var ActionBarRoot = (0, import_react25.forwardRef)(({ hideWhenRunning, autohide,
971
1026
  );
972
1027
  });
973
1028
 
974
- // src/actions/useCopyMessage.tsx
975
- var import_react26 = require("react");
976
- var useCopyMessage = ({ copiedDuration = 3e3 }) => {
977
- const { useMessage, useComposer } = useMessageContext();
978
- const hasCopyableContent = useCombinedStore(
979
- [useMessage, useComposer],
980
- (m, c) => {
981
- return c.isEditing || m.message.content.some((c2) => c2.type === "text");
982
- }
983
- );
984
- const callback = (0, import_react26.useCallback)(() => {
985
- const { isEditing, value: composerValue } = useComposer.getState();
986
- const { message, setIsCopied } = useMessage.getState();
987
- const valueToCopy = isEditing ? composerValue : getMessageText(message);
988
- navigator.clipboard.writeText(valueToCopy);
989
- setIsCopied(true);
990
- setTimeout(() => setIsCopied(false), copiedDuration);
991
- }, [useComposer, useMessage, copiedDuration]);
992
- if (!hasCopyableContent) return null;
993
- return callback;
994
- };
995
-
996
1029
  // src/primitives/actionBar/ActionBarCopy.tsx
997
1030
  var ActionBarCopy = createActionButton(useCopyMessage);
998
1031
 
999
- // src/actions/useReloadMessage.tsx
1000
- var import_react27 = require("react");
1001
- var useReloadMessage = () => {
1002
- const { useThread, useViewport } = useAssistantContext();
1003
- const { useMessage } = useMessageContext();
1004
- const disabled = useCombinedStore(
1005
- [useThread, useMessage],
1006
- (t, m) => t.isRunning || m.message.role !== "assistant"
1007
- );
1008
- const callback = (0, import_react27.useCallback)(() => {
1009
- const { parentId } = useMessage.getState();
1010
- useThread.getState().startRun(parentId);
1011
- useViewport.getState().scrollToBottom();
1012
- }, [useMessage, useThread, useViewport]);
1013
- if (disabled) return null;
1014
- return callback;
1015
- };
1016
-
1017
1032
  // src/primitives/actionBar/ActionBarReload.tsx
1018
1033
  var ActionBarReload = createActionButton(useReloadMessage);
1019
1034
 
1020
- // src/actions/useBeginMessageEdit.tsx
1021
- var import_react28 = require("react");
1022
- var useBeginMessageEdit = () => {
1023
- const { useMessage, useComposer } = useMessageContext();
1024
- const disabled = useCombinedStore(
1025
- [useMessage, useComposer],
1026
- (m, c) => m.message.role !== "user" || c.isEditing
1027
- );
1028
- const callback = (0, import_react28.useCallback)(() => {
1029
- const { edit } = useComposer.getState();
1030
- edit();
1031
- }, [useComposer]);
1032
- if (disabled) return null;
1033
- return callback;
1034
- };
1035
-
1036
1035
  // src/primitives/actionBar/ActionBarEdit.tsx
1037
1036
  var ActionBarEdit = createActionButton(useBeginMessageEdit);
1038
1037
 
1039
1038
  // src/primitives/contentPart/index.ts
1040
1039
  var contentPart_exports = {};
1041
1040
  __export(contentPart_exports, {
1042
- InProgressIndicator: () => ContentPartInProgressIndicator,
1043
- Provider: () => ContentPartProvider
1041
+ InProgressIndicator: () => ContentPartInProgressIndicator
1044
1042
  });
1045
1043
 
1046
- // src/adapters/vercel/VercelAIAssistantProvider.tsx
1047
- var import_react31 = require("react");
1044
+ // src/runtime/vercel-ai/rsc/useVercelRSCRuntime.tsx
1045
+ var import_react30 = require("react");
1046
+
1047
+ // src/runtime/vercel-ai/rsc/VercelRSCRuntime.tsx
1048
+ var import_zustand4 = require("zustand");
1048
1049
 
1049
- // src/adapters/vercel/useDummyAIAssistantContext.tsx
1050
+ // src/runtime/vercel-ai/rsc/useVercelRSCSync.tsx
1050
1051
  var import_react29 = require("react");
1051
- var import_zustand5 = require("zustand");
1052
1052
 
1053
- // src/utils/context/stores/ViewportStore.tsx
1054
- var import_zustand4 = require("zustand");
1055
- var makeViewportStore = () => {
1056
- const scrollToBottomListeners = /* @__PURE__ */ new Set();
1057
- return (0, import_zustand4.create)(() => ({
1058
- isAtBottom: true,
1059
- scrollToBottom: () => {
1060
- for (const listener of scrollToBottomListeners) {
1061
- listener();
1062
- }
1063
- },
1064
- onScrollToBottom: (callback) => {
1065
- scrollToBottomListeners.add(callback);
1066
- return () => {
1067
- scrollToBottomListeners.delete(callback);
1068
- };
1069
- }
1070
- }));
1053
+ // src/runtime/vercel-ai/utils/ThreadMessageConverter.ts
1054
+ var ThreadMessageConverter = class {
1055
+ cache = /* @__PURE__ */ new WeakMap();
1056
+ convertMessages(converter, messages) {
1057
+ return messages.map((m) => {
1058
+ const cached = this.cache.get(m);
1059
+ const newMessage = converter(m, cached);
1060
+ this.cache.set(m, newMessage);
1061
+ return newMessage;
1062
+ });
1063
+ }
1071
1064
  };
1072
1065
 
1073
- // src/adapters/vercel/useDummyAIAssistantContext.tsx
1074
- var makeDummyThreadStore = () => {
1075
- return (0, import_zustand5.create)(() => ({
1076
- messages: [],
1077
- isRunning: false,
1078
- getBranches: () => {
1079
- return [];
1080
- },
1081
- switchToBranch: () => {
1082
- throw new Error("Not implemented");
1083
- },
1084
- append: () => {
1085
- throw new Error("Not implemented");
1086
- },
1087
- startRun: () => {
1088
- throw new Error("Not implemented");
1089
- },
1090
- cancelRun: () => {
1091
- throw new Error("Not implemented");
1066
+ // src/runtime/vercel-ai/rsc/getVercelRSCMessage.tsx
1067
+ var symbolInnerRSCMessage = Symbol("innerVercelRSCMessage");
1068
+ var getVercelRSCMessage = (message) => {
1069
+ return message[symbolInnerRSCMessage];
1070
+ };
1071
+
1072
+ // src/runtime/vercel-ai/rsc/useVercelRSCSync.tsx
1073
+ var vercelToThreadMessage = (converter, rawMessage) => {
1074
+ const message = converter(rawMessage);
1075
+ return {
1076
+ id: message.id,
1077
+ role: message.role,
1078
+ content: [{ type: "ui", display: message.display }],
1079
+ createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
1080
+ ...{ status: "done" },
1081
+ [symbolInnerRSCMessage]: rawMessage
1082
+ };
1083
+ };
1084
+ var useVercelRSCSync = (adapter, updateData) => {
1085
+ const [converter, convertCallback] = (0, import_react29.useMemo)(() => {
1086
+ const rscConverter = adapter.convertMessage ?? ((m) => m);
1087
+ const convertCallback2 = (m, cache) => {
1088
+ if (cache) return cache;
1089
+ return vercelToThreadMessage(rscConverter, m);
1090
+ };
1091
+ return [new ThreadMessageConverter(), convertCallback2];
1092
+ }, [adapter.convertMessage]);
1093
+ (0, import_react29.useEffect)(() => {
1094
+ updateData(converter.convertMessages(convertCallback, adapter.messages));
1095
+ }, [updateData, converter, convertCallback, adapter.messages]);
1096
+ };
1097
+
1098
+ // src/runtime/vercel-ai/rsc/VercelRSCRuntime.tsx
1099
+ var EMPTY_BRANCHES = Object.freeze([]);
1100
+ var VercelRSCRuntime = class {
1101
+ constructor(adapter) {
1102
+ this.adapter = adapter;
1103
+ this.useAdapter = (0, import_zustand4.create)(() => ({
1104
+ adapter
1105
+ }));
1106
+ }
1107
+ useAdapter;
1108
+ _subscriptions = /* @__PURE__ */ new Set();
1109
+ isRunning = false;
1110
+ messages = [];
1111
+ withRunning = (callback) => {
1112
+ this.isRunning = true;
1113
+ return callback.finally(() => {
1114
+ this.isRunning = false;
1115
+ });
1116
+ };
1117
+ getBranches() {
1118
+ return EMPTY_BRANCHES;
1119
+ }
1120
+ switchToBranch() {
1121
+ throw new Error(
1122
+ "Branch switching is not supported by VercelRSCAssistantProvider."
1123
+ );
1124
+ }
1125
+ async append(message) {
1126
+ if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {
1127
+ if (!this.adapter.edit)
1128
+ throw new Error(
1129
+ "Message editing is not enabled, please provide an edit callback to VercelRSCAssistantProvider."
1130
+ );
1131
+ await this.withRunning(this.adapter.edit(message));
1132
+ } else {
1133
+ await this.withRunning(this.adapter.append(message));
1092
1134
  }
1093
- }));
1135
+ }
1136
+ async startRun(parentId) {
1137
+ if (!this.adapter.reload)
1138
+ throw new Error(
1139
+ "Message reloading is not enabled, please provide a reload callback to VercelRSCAssistantProvider."
1140
+ );
1141
+ await this.withRunning(this.adapter.reload(parentId));
1142
+ }
1143
+ cancelRun() {
1144
+ if (process.env["NODE_ENV"] === "development") {
1145
+ console.warn(
1146
+ "Run cancellation is not supported by VercelRSCAssistantProvider."
1147
+ );
1148
+ }
1149
+ }
1150
+ subscribe(callback) {
1151
+ this._subscriptions.add(callback);
1152
+ return () => this._subscriptions.delete(callback);
1153
+ }
1154
+ onAdapterUpdated() {
1155
+ if (this.useAdapter.getState().adapter !== this.adapter) {
1156
+ this.useAdapter.setState({ adapter: this.adapter });
1157
+ }
1158
+ }
1159
+ updateData = (messages) => {
1160
+ this.messages = messages;
1161
+ for (const callback of this._subscriptions) callback();
1162
+ };
1163
+ unstable_synchronizer = () => {
1164
+ const { adapter } = this.useAdapter();
1165
+ useVercelRSCSync(adapter, this.updateData);
1166
+ return null;
1167
+ };
1094
1168
  };
1095
- var useDummyAIAssistantContext = () => {
1096
- const [context] = (0, import_react29.useState)(() => {
1097
- const useThread = makeDummyThreadStore();
1098
- const useViewport = makeViewportStore();
1099
- const useComposer = makeThreadComposerStore(useThread);
1100
- return { useThread, useViewport, useComposer };
1169
+
1170
+ // src/runtime/vercel-ai/rsc/useVercelRSCRuntime.tsx
1171
+ var useVercelRSCRuntime = (adapter) => {
1172
+ const [runtime] = (0, import_react30.useState)(() => new VercelRSCRuntime(adapter));
1173
+ (0, import_react30.useInsertionEffect)(() => {
1174
+ runtime.adapter = adapter;
1101
1175
  });
1102
- return context;
1176
+ (0, import_react30.useEffect)(() => {
1177
+ runtime.onAdapterUpdated();
1178
+ });
1179
+ return runtime;
1103
1180
  };
1104
1181
 
1105
- // src/adapters/vercel/useVercelAIThreadState.tsx
1106
- var import_react_use_callback_ref3 = require("@radix-ui/react-use-callback-ref");
1107
- var import_react30 = require("react");
1182
+ // src/runtime/vercel-ai/ui/use-chat/useVercelUseChatRuntime.tsx
1183
+ var import_react33 = require("react");
1184
+
1185
+ // src/runtime/vercel-ai/ui/VercelAIRuntime.tsx
1186
+ var import_zustand5 = require("zustand");
1108
1187
 
1109
- // src/adapters/idUtils.tsx
1188
+ // src/runtime/utils/idUtils.tsx
1110
1189
  var import_non_secure = require("nanoid/non-secure");
1111
1190
  var generateId = (0, import_non_secure.customAlphabet)(
1112
1191
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
@@ -1115,7 +1194,7 @@ var generateId = (0, import_non_secure.customAlphabet)(
1115
1194
  var optimisticPrefix = "__optimistic__";
1116
1195
  var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
1117
1196
 
1118
- // src/adapters/MessageRepository.tsx
1197
+ // src/runtime/utils/MessageRepository.tsx
1119
1198
  var findHead = (message) => {
1120
1199
  if (message.next) return findHead(message.next);
1121
1200
  return message;
@@ -1184,10 +1263,10 @@ var MessageRepository = class {
1184
1263
  level: prev ? prev.level + 1 : 0
1185
1264
  };
1186
1265
  this.messages.set(message.id, newItem);
1266
+ this.performOp(prev, newItem, "link");
1187
1267
  if (this.head === prev) {
1188
1268
  this.head = newItem;
1189
1269
  }
1190
- this.performOp(prev, newItem, "link");
1191
1270
  }
1192
1271
  appendOptimisticMessage(parentId, message) {
1193
1272
  let optimisticId;
@@ -1204,14 +1283,14 @@ var MessageRepository = class {
1204
1283
  }
1205
1284
  deleteMessage(messageId, replacementId) {
1206
1285
  const message = this.messages.get(messageId);
1207
- const replacement = replacementId ? this.messages.get(replacementId) : null;
1208
1286
  if (!message)
1209
1287
  throw new Error(
1210
1288
  "MessageRepository(deleteMessage): Optimistic message not found. This is likely an internal bug in assistant-ui."
1211
1289
  );
1290
+ const replacement = replacementId === void 0 ? message.prev : replacementId === null ? null : this.messages.get(replacementId);
1212
1291
  if (replacement === void 0)
1213
1292
  throw new Error(
1214
- "MessageRepository(deleteMessage): New message not found. This is likely an internal bug in assistant-ui."
1293
+ "MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui."
1215
1294
  );
1216
1295
  for (const child of message.children) {
1217
1296
  const childMessage = this.messages.get(child);
@@ -1221,11 +1300,11 @@ var MessageRepository = class {
1221
1300
  );
1222
1301
  this.performOp(replacement, childMessage, "relink");
1223
1302
  }
1303
+ this.performOp(null, message, "cut");
1224
1304
  this.messages.delete(messageId);
1225
1305
  if (this.head === message) {
1226
- this.head = replacement;
1306
+ this.head = replacement ? findHead(replacement) : null;
1227
1307
  }
1228
- this.performOp(null, message, "cut");
1229
1308
  }
1230
1309
  getBranches(messageId) {
1231
1310
  const message = this.messages.get(messageId);
@@ -1266,35 +1345,46 @@ var MessageRepository = class {
1266
1345
  }
1267
1346
  };
1268
1347
 
1269
- // src/adapters/ThreadMessageConverter.ts
1270
- var ThreadMessageConverter = class {
1271
- cache = /* @__PURE__ */ new WeakMap();
1272
- convertMessages(converter, messages) {
1273
- return messages.map((m) => {
1274
- const cached = this.cache.get(m);
1275
- const newMessage = converter(m, cached);
1276
- this.cache.set(m, newMessage);
1277
- return newMessage;
1278
- });
1279
- }
1348
+ // src/runtime/vercel-ai/ui/getVercelAIMessage.tsx
1349
+ var symbolInnerAIMessage = Symbol("innerVercelAIUIMessage");
1350
+ var getVercelAIMessage = (message) => {
1351
+ return message[symbolInnerAIMessage];
1280
1352
  };
1281
1353
 
1282
- // src/adapters/vercel/VercelThreadMessage.tsx
1283
- var symbolInnerMessage = Symbol("innerMessage");
1284
- var symbolInnerRSCMessage = Symbol("innerRSCMessage");
1285
- var getVercelMessage = (message) => {
1286
- return message[symbolInnerMessage];
1354
+ // src/runtime/vercel-ai/ui/utils/sliceMessagesUntil.tsx
1355
+ var sliceMessagesUntil = (messages, messageId) => {
1356
+ if (messageId == null) return [];
1357
+ const messageIdx = messages.findIndex((m) => m.id === messageId);
1358
+ if (messageIdx === -1)
1359
+ throw new Error(
1360
+ "useVercelAIThreadState: Message not found. This is liekly an internal bug in assistant-ui."
1361
+ );
1362
+ return messages.slice(0, messageIdx + 1);
1287
1363
  };
1288
- var getVercelRSCMessage = (message) => {
1289
- return message[symbolInnerRSCMessage];
1364
+
1365
+ // src/runtime/vercel-ai/ui/utils/useVercelAIComposerSync.tsx
1366
+ var import_react31 = require("react");
1367
+ var useVercelAIComposerSync = (vercel) => {
1368
+ const { useComposer } = useThreadContext();
1369
+ (0, import_react31.useEffect)(() => {
1370
+ useComposer.setState({
1371
+ value: vercel.input,
1372
+ setValue: vercel.setInput
1373
+ });
1374
+ }, [useComposer, vercel.input, vercel.setInput]);
1290
1375
  };
1291
1376
 
1292
- // src/adapters/vercel/useVercelAIThreadState.tsx
1293
- var vercelToThreadMessage = (message, status) => {
1377
+ // src/runtime/vercel-ai/ui/utils/useVercelAIThreadSync.tsx
1378
+ var import_react32 = require("react");
1379
+ var getIsRunning = (vercel) => {
1380
+ if ("isLoading" in vercel) return vercel.isLoading;
1381
+ return vercel.status === "in_progress";
1382
+ };
1383
+ var vercelToThreadMessage2 = (message, status) => {
1294
1384
  const common = {
1295
1385
  id: message.id,
1296
1386
  createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
1297
- [symbolInnerMessage]: message
1387
+ [symbolInnerAIMessage]: message
1298
1388
  };
1299
1389
  switch (message.role) {
1300
1390
  case "user":
@@ -1326,47 +1416,115 @@ var vercelToThreadMessage = (message, status) => {
1326
1416
  );
1327
1417
  }
1328
1418
  };
1329
- var sliceMessagesUntil = (messages, messageId) => {
1330
- if (messageId == null) return [];
1331
- const messageIdx = messages.findIndex((m) => m.id === messageId);
1332
- if (messageIdx === -1)
1333
- throw new Error(
1334
- "useVercelAIThreadState: Message not found. This is liekly an internal bug in assistant-ui."
1335
- );
1336
- return messages.slice(0, messageIdx + 1);
1337
- };
1338
- var hasUpcomingMessage = (isRunning, messages) => {
1339
- return isRunning && messages[messages.length - 1]?.role !== "assistant";
1340
- };
1341
- var getIsRunning = (vercel) => {
1342
- if ("isLoading" in vercel) return vercel.isLoading;
1343
- return vercel.status === "in_progress";
1344
- };
1345
- var useVercelAIThreadState = (vercel) => {
1346
- const [data] = (0, import_react30.useState)(() => new MessageRepository());
1419
+ var useVercelAIThreadSync = (vercel, updateData) => {
1347
1420
  const isRunning = getIsRunning(vercel);
1348
- const converter = (0, import_react30.useMemo)(() => new ThreadMessageConverter(), []);
1349
- const assistantOptimisticIdRef = (0, import_react30.useRef)(null);
1350
- const messages = (0, import_react30.useMemo)(() => {
1421
+ const converter = (0, import_react32.useMemo)(() => new ThreadMessageConverter(), []);
1422
+ (0, import_react32.useEffect)(() => {
1351
1423
  const lastMessageId = vercel.messages.at(-1)?.id;
1352
1424
  const convertCallback = (message, cache) => {
1353
1425
  const status = lastMessageId === message.id && isRunning ? "in_progress" : "done";
1354
1426
  if (cache && (cache.role === "user" || cache.status === status))
1355
1427
  return cache;
1356
- return vercelToThreadMessage(message, status);
1428
+ return vercelToThreadMessage2(message, status);
1357
1429
  };
1358
- const vm = converter.convertMessages(convertCallback, vercel.messages);
1430
+ const messages = converter.convertMessages(
1431
+ convertCallback,
1432
+ vercel.messages
1433
+ );
1434
+ updateData(isRunning, messages);
1435
+ }, [updateData, isRunning, vercel.messages, converter]);
1436
+ };
1437
+
1438
+ // src/runtime/vercel-ai/ui/VercelAIRuntime.tsx
1439
+ var hasUpcomingMessage = (isRunning, messages) => {
1440
+ return isRunning && messages[messages.length - 1]?.role !== "assistant";
1441
+ };
1442
+ var VercelAIRuntime = class {
1443
+ constructor(vercel) {
1444
+ this.vercel = vercel;
1445
+ this.useVercel = (0, import_zustand5.create)(() => ({
1446
+ vercel
1447
+ }));
1448
+ }
1449
+ _subscriptions = /* @__PURE__ */ new Set();
1450
+ repository = new MessageRepository();
1451
+ assistantOptimisticId = null;
1452
+ useVercel;
1453
+ messages = [];
1454
+ isRunning = false;
1455
+ getBranches(messageId) {
1456
+ return this.repository.getBranches(messageId);
1457
+ }
1458
+ switchToBranch(branchId) {
1459
+ this.repository.switchToBranch(branchId);
1460
+ this.updateVercelMessages(this.repository.getMessages());
1461
+ }
1462
+ async append(message) {
1463
+ if (message.content.length !== 1 || message.content[0]?.type !== "text")
1464
+ throw new Error("Only text content is supported by Vercel AI SDK.");
1465
+ const newMessages = sliceMessagesUntil(
1466
+ this.vercel.messages,
1467
+ message.parentId
1468
+ );
1469
+ this.vercel.setMessages(newMessages);
1470
+ await this.vercel.append({
1471
+ role: "user",
1472
+ content: message.content[0].text
1473
+ });
1474
+ }
1475
+ async startRun(parentId) {
1476
+ const reloadMaybe = "reload" in this.vercel ? this.vercel.reload : void 0;
1477
+ if (!reloadMaybe)
1478
+ throw new Error(
1479
+ "Reload is not supported by Vercel AI SDK's useAssistant."
1480
+ );
1481
+ const newMessages = sliceMessagesUntil(this.vercel.messages, parentId);
1482
+ this.vercel.setMessages(newMessages);
1483
+ await reloadMaybe();
1484
+ }
1485
+ cancelRun() {
1486
+ const previousMessage = this.vercel.messages.at(-1);
1487
+ this.vercel.stop();
1488
+ if (this.assistantOptimisticId) {
1489
+ this.repository.deleteMessage(this.assistantOptimisticId);
1490
+ this.assistantOptimisticId = null;
1491
+ }
1492
+ let messages = this.repository.getMessages();
1493
+ if (previousMessage?.role === "user" && previousMessage.id === messages.at(-1)?.id) {
1494
+ this.vercel.setInput(previousMessage.content);
1495
+ this.repository.deleteMessage(previousMessage.id);
1496
+ messages = this.repository.getMessages();
1497
+ }
1498
+ setTimeout(() => {
1499
+ this.updateVercelMessages(messages);
1500
+ }, 0);
1501
+ }
1502
+ subscribe(callback) {
1503
+ this._subscriptions.add(callback);
1504
+ return () => this._subscriptions.delete(callback);
1505
+ }
1506
+ updateVercelMessages = (messages) => {
1507
+ this.vercel.setMessages(
1508
+ messages.map(getVercelAIMessage).filter((m) => m != null)
1509
+ );
1510
+ };
1511
+ onVercelUpdated() {
1512
+ if (this.useVercel.getState().vercel !== this.vercel) {
1513
+ this.useVercel.setState({ vercel: this.vercel });
1514
+ }
1515
+ }
1516
+ updateData = (isRunning, vm) => {
1359
1517
  for (let i = 0; i < vm.length; i++) {
1360
1518
  const message = vm[i];
1361
1519
  const parent = vm[i - 1];
1362
- data.addOrUpdateMessage(parent?.id ?? null, message);
1520
+ this.repository.addOrUpdateMessage(parent?.id ?? null, message);
1363
1521
  }
1364
- if (assistantOptimisticIdRef.current) {
1365
- data.deleteMessage(assistantOptimisticIdRef.current, null);
1366
- assistantOptimisticIdRef.current = null;
1522
+ if (this.assistantOptimisticId) {
1523
+ this.repository.deleteMessage(this.assistantOptimisticId);
1524
+ this.assistantOptimisticId = null;
1367
1525
  }
1368
1526
  if (hasUpcomingMessage(isRunning, vm)) {
1369
- assistantOptimisticIdRef.current = data.appendOptimisticMessage(
1527
+ this.assistantOptimisticId = this.repository.appendOptimisticMessage(
1370
1528
  vm.at(-1)?.id ?? null,
1371
1529
  {
1372
1530
  role: "assistant",
@@ -1374,321 +1532,220 @@ var useVercelAIThreadState = (vercel) => {
1374
1532
  }
1375
1533
  );
1376
1534
  }
1377
- data.resetHead(assistantOptimisticIdRef.current ?? vm.at(-1)?.id ?? null);
1378
- return data.getMessages();
1379
- }, [converter, data, isRunning, vercel.messages]);
1380
- const getBranches2 = (0, import_react30.useCallback)(
1381
- (messageId) => {
1382
- return data.getBranches(messageId);
1383
- },
1384
- [data]
1385
- );
1386
- const switchToBranch2 = (0, import_react_use_callback_ref3.useCallbackRef)((messageId) => {
1387
- data.switchToBranch(messageId);
1388
- vercel.setMessages(
1389
- data.getMessages().map(getVercelMessage).filter((m) => m != null)
1535
+ this.repository.resetHead(
1536
+ this.assistantOptimisticId ?? vm.at(-1)?.id ?? null
1390
1537
  );
1538
+ this.messages = this.repository.getMessages();
1539
+ this.isRunning = isRunning;
1540
+ for (const callback of this._subscriptions) callback();
1541
+ };
1542
+ unstable_synchronizer = () => {
1543
+ const { vercel } = this.useVercel();
1544
+ useVercelAIThreadSync(vercel, this.updateData);
1545
+ useVercelAIComposerSync(vercel);
1546
+ return null;
1547
+ };
1548
+ };
1549
+
1550
+ // src/runtime/vercel-ai/ui/use-chat/useVercelUseChatRuntime.tsx
1551
+ var useVercelUseChatRuntime = (chatHelpers) => {
1552
+ const [runtime] = (0, import_react33.useState)(() => new VercelAIRuntime(chatHelpers));
1553
+ (0, import_react33.useInsertionEffect)(() => {
1554
+ runtime.vercel = chatHelpers;
1391
1555
  });
1392
- const startRun = (0, import_react_use_callback_ref3.useCallbackRef)(async (parentId) => {
1393
- const reloadMaybe = "reload" in vercel ? vercel.reload : void 0;
1394
- if (!reloadMaybe)
1395
- throw new Error(
1396
- "Reload is not supported by Vercel AI SDK's useAssistant."
1397
- );
1398
- const newMessages = sliceMessagesUntil(vercel.messages, parentId);
1399
- vercel.setMessages(newMessages);
1400
- await reloadMaybe();
1556
+ (0, import_react33.useEffect)(() => {
1557
+ runtime.onVercelUpdated();
1401
1558
  });
1402
- const append = (0, import_react_use_callback_ref3.useCallbackRef)(async (message) => {
1403
- if (message.content.length !== 1 || message.content[0]?.type !== "text")
1404
- throw new Error("Only text content is supported by Vercel AI SDK.");
1405
- const newMessages = sliceMessagesUntil(vercel.messages, message.parentId);
1406
- vercel.setMessages(newMessages);
1407
- await vercel.append({
1408
- role: "user",
1409
- content: message.content[0].text
1410
- });
1559
+ return runtime;
1560
+ };
1561
+
1562
+ // src/runtime/vercel-ai/ui/use-assistant/useVercelUseAssistantRuntime.tsx
1563
+ var import_react34 = require("react");
1564
+ var useVercelUseAssistantRuntime = (assistantHelpers) => {
1565
+ const [runtime] = (0, import_react34.useState)(() => new VercelAIRuntime(assistantHelpers));
1566
+ (0, import_react34.useInsertionEffect)(() => {
1567
+ runtime.vercel = assistantHelpers;
1411
1568
  });
1412
- const cancelRun2 = (0, import_react_use_callback_ref3.useCallbackRef)(() => {
1413
- const lastMessage = vercel.messages.at(-1);
1414
- vercel.stop();
1415
- if (lastMessage?.role === "user") {
1416
- vercel.setInput(lastMessage.content);
1417
- }
1569
+ (0, import_react34.useEffect)(() => {
1570
+ runtime.onVercelUpdated();
1418
1571
  });
1419
- return (0, import_react30.useMemo)(
1420
- () => ({
1421
- isRunning,
1422
- messages,
1423
- getBranches: getBranches2,
1424
- switchToBranch: switchToBranch2,
1425
- append,
1426
- startRun,
1427
- cancelRun: cancelRun2
1428
- }),
1429
- [
1430
- isRunning,
1431
- messages,
1432
- getBranches2,
1433
- switchToBranch2,
1434
- append,
1435
- startRun,
1436
- cancelRun2
1437
- ]
1438
- );
1572
+ return runtime;
1439
1573
  };
1440
1574
 
1441
- // src/adapters/vercel/VercelAIAssistantProvider.tsx
1442
- var import_jsx_runtime21 = require("react/jsx-runtime");
1443
- var VercelAIAssistantProvider = ({
1444
- children,
1445
- ...rest
1446
- }) => {
1447
- const context = useDummyAIAssistantContext();
1448
- const vercel = "chat" in rest ? rest.chat : rest.assistant;
1449
- const threadState = useVercelAIThreadState(vercel);
1450
- (0, import_react31.useMemo)(() => {
1451
- context.useThread.setState(threadState, true);
1452
- }, [context, threadState]);
1453
- (0, import_react31.useMemo)(() => {
1454
- context.useComposer.setState({
1455
- value: vercel.input,
1456
- setValue: vercel.setInput
1457
- });
1458
- }, [context, vercel.input, vercel.setInput]);
1459
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AssistantContext.Provider, { value: context, children });
1460
- };
1575
+ // src/context/providers/AssistantRuntimeProvider.tsx
1576
+ var import_react36 = require("react");
1461
1577
 
1462
- // src/adapters/vercel/VercelRSCAssistantProvider.tsx
1463
- var import_react32 = require("react");
1464
- var import_jsx_runtime22 = require("react/jsx-runtime");
1465
- var vercelToThreadMessage2 = (converter, rawMessage) => {
1466
- const message = converter(rawMessage);
1467
- return {
1468
- id: message.id,
1469
- role: message.role,
1470
- content: [{ type: "ui", display: message.display }],
1471
- createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
1472
- ...{ status: "done" },
1473
- [symbolInnerRSCMessage]: rawMessage
1474
- };
1475
- };
1476
- var EMPTY_BRANCHES = [];
1477
- var getBranches = () => {
1478
- return EMPTY_BRANCHES;
1479
- };
1480
- var switchToBranch = () => {
1481
- throw new Error(
1482
- "Branch switching is not supported by VercelRSCAssistantProvider."
1483
- );
1484
- };
1485
- var cancelRun = () => {
1486
- if (process.env["NODE_ENV"] === "development") {
1487
- console.warn(
1488
- "Run cancellation is not supported by VercelRSCAssistantProvider."
1489
- );
1490
- }
1491
- };
1492
- var VercelRSCAssistantProvider = ({
1493
- children,
1494
- convertMessage,
1495
- messages: vercelMessages,
1496
- append: appendCallback,
1497
- edit,
1498
- reload
1499
- }) => {
1500
- const context = useDummyAIAssistantContext();
1501
- const [isRunning, setIsRunning] = (0, import_react32.useState)(false);
1502
- const withRunning = (0, import_react32.useCallback)((callback) => {
1503
- setIsRunning(true);
1504
- return callback.finally(() => setIsRunning(false));
1505
- }, []);
1506
- const [converter, convertCallback] = (0, import_react32.useMemo)(() => {
1507
- const rscConverter = convertMessage ?? ((m) => m);
1508
- const convertCallback2 = (m, cache) => {
1509
- if (cache) return cache;
1510
- return vercelToThreadMessage2(rscConverter, m);
1511
- };
1512
- return [new ThreadMessageConverter(), convertCallback2];
1513
- }, [convertMessage]);
1514
- const messages = (0, import_react32.useMemo)(() => {
1515
- return converter.convertMessages(convertCallback, vercelMessages);
1516
- }, [converter, convertCallback, vercelMessages]);
1517
- const append = (0, import_react32.useCallback)(
1518
- async (message) => {
1519
- if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
1520
- if (!edit)
1521
- throw new Error(
1522
- "Message editing is not enabled, please provide an edit callback to VercelRSCAssistantProvider."
1523
- );
1524
- await withRunning(edit(message));
1525
- } else {
1526
- await withRunning(appendCallback(message));
1527
- }
1528
- },
1529
- [context, withRunning, appendCallback, edit]
1530
- );
1531
- const startRun = (0, import_react32.useCallback)(
1532
- async (parentId) => {
1533
- if (!reload)
1534
- throw new Error(
1535
- "Message reloading is not enabled, please provide a reload callback to VercelRSCAssistantProvider."
1536
- );
1537
- await withRunning(reload(parentId));
1538
- },
1539
- [withRunning, reload]
1540
- );
1541
- (0, import_react32.useMemo)(() => {
1542
- context.useThread.setState(
1543
- {
1544
- messages,
1545
- isRunning,
1546
- getBranches,
1547
- switchToBranch,
1548
- append,
1549
- startRun,
1550
- cancelRun
1551
- },
1552
- true
1553
- );
1554
- }, [context, messages, isRunning, append, startRun]);
1555
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(AssistantContext.Provider, { value: context, children });
1556
- };
1578
+ // src/context/providers/ThreadProvider.tsx
1579
+ var import_react35 = require("react");
1557
1580
 
1558
- // src/adapters/core/utils/useAssistantContext.tsx
1559
- var import_react33 = require("react");
1581
+ // src/context/stores/Composer.ts
1560
1582
  var import_zustand6 = require("zustand");
1561
-
1562
- // src/adapters/core/utils/AssistantMessageRepository.tsx
1563
- var AssistantMessageRepository = class {
1564
- constructor(flushCallback) {
1565
- this.flushCallback = flushCallback;
1566
- }
1567
- repository = new MessageRepository();
1568
- getBranches(messageId) {
1569
- return this.repository.getBranches(messageId);
1570
- }
1571
- withModifications(callback) {
1572
- const res = callback(this.repository);
1573
- this.flushCallback(this.repository.getMessages());
1574
- return res;
1575
- }
1576
- };
1577
-
1578
- // src/adapters/core/utils/useAssistantContext.tsx
1579
- var makeThreadStore = (runtimeRef) => {
1580
- const repository = new AssistantMessageRepository((messages) => {
1581
- useThread.setState({ messages });
1582
- });
1583
- const useThread = (0, import_zustand6.create)(() => ({
1584
- messages: [],
1585
- isRunning: false,
1586
- getBranches: (messageId) => repository.getBranches(messageId),
1587
- switchToBranch: (branchId) => {
1588
- repository.withModifications((repository2) => {
1589
- repository2.switchToBranch(branchId);
1590
- });
1591
- },
1592
- startRun: async (parentId) => {
1593
- const optimisticId = repository.withModifications((repository2) => {
1594
- const optimisticId2 = repository2.appendOptimisticMessage(parentId, {
1595
- role: "assistant",
1596
- content: [{ type: "text", text: "" }]
1597
- });
1598
- repository2.resetHead(optimisticId2);
1599
- return optimisticId2;
1600
- });
1601
- const { id } = await runtimeRef.current.startRun(parentId);
1602
- repository.withModifications((repository2) => {
1603
- repository2.deleteMessage(optimisticId, id);
1604
- });
1605
- },
1606
- append: async (message) => {
1607
- const [parentOptimisticId, optimisticId] = repository.withModifications(
1608
- (repository2) => {
1609
- const parentOptimisticId2 = repository2.appendOptimisticMessage(
1610
- message.parentId,
1611
- {
1612
- role: "user",
1613
- content: message.content
1614
- }
1615
- );
1616
- const optimisticId2 = repository2.appendOptimisticMessage(
1617
- parentOptimisticId2,
1618
- {
1619
- role: "assistant",
1620
- content: [{ type: "text", text: "" }]
1621
- }
1622
- );
1623
- repository2.resetHead(optimisticId2);
1624
- return [parentOptimisticId2, optimisticId2];
1625
- }
1626
- );
1627
- const { parentId, id } = await runtimeRef.current.append(message);
1628
- repository.withModifications((repository2) => {
1629
- repository2.deleteMessage(parentOptimisticId, parentId);
1630
- repository2.deleteMessage(optimisticId, id);
1583
+ var makeComposerStore = (useThread) => (0, import_zustand6.create)()((set, get, store) => {
1584
+ return {
1585
+ ...makeBaseComposer(set, get, store),
1586
+ isEditing: true,
1587
+ send: () => {
1588
+ const { setValue, value } = get();
1589
+ setValue("");
1590
+ useThread.getState().append({
1591
+ parentId: useThread.getState().messages.at(-1)?.id ?? null,
1592
+ content: [{ type: "text", text: value }]
1631
1593
  });
1632
1594
  },
1595
+ cancel: () => {
1596
+ const thread = useThread.getState();
1597
+ if (!thread.isRunning) return false;
1598
+ useThread.getState().cancelRun();
1599
+ return true;
1600
+ }
1601
+ };
1602
+ });
1603
+
1604
+ // src/context/stores/Thread.ts
1605
+ var import_zustand7 = require("zustand");
1606
+ var makeThreadStore = (runtimeRef) => {
1607
+ const useThread = (0, import_zustand7.create)(() => ({
1608
+ messages: runtimeRef.current.messages,
1609
+ isRunning: runtimeRef.current.isRunning,
1610
+ getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1611
+ switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1612
+ startRun: (parentId) => runtimeRef.current.startRun(parentId),
1613
+ append: (message) => runtimeRef.current.append(message),
1633
1614
  cancelRun: () => runtimeRef.current.cancelRun()
1634
1615
  }));
1635
- const onNewMessage = (parentId, message) => {
1636
- repository.withModifications((repository2) => {
1637
- repository2.addOrUpdateMessage(parentId, message);
1616
+ const onRuntimeUpdate = () => {
1617
+ useThread.setState({
1618
+ messages: runtimeRef.current.messages,
1619
+ isRunning: runtimeRef.current.isRunning
1638
1620
  });
1639
1621
  };
1640
- const onRunningChange = (isRunning) => {
1641
- useThread.setState({ isRunning });
1642
- };
1643
1622
  return {
1644
1623
  useThread,
1645
- onNewMessage,
1646
- onRunningChange
1624
+ onRuntimeUpdate
1647
1625
  };
1648
1626
  };
1649
- var useAssistantContext2 = (runtime) => {
1650
- const runtimeRef = (0, import_react33.useRef)(runtime);
1651
- (0, import_react33.useInsertionEffect)(() => {
1627
+
1628
+ // src/context/stores/ThreadViewport.tsx
1629
+ var import_zustand8 = require("zustand");
1630
+ var makeThreadViewportStore = () => {
1631
+ const scrollToBottomListeners = /* @__PURE__ */ new Set();
1632
+ return (0, import_zustand8.create)(() => ({
1633
+ isAtBottom: true,
1634
+ scrollToBottom: () => {
1635
+ for (const listener of scrollToBottomListeners) {
1636
+ listener();
1637
+ }
1638
+ },
1639
+ onScrollToBottom: (callback) => {
1640
+ scrollToBottomListeners.add(callback);
1641
+ return () => {
1642
+ scrollToBottomListeners.delete(callback);
1643
+ };
1644
+ }
1645
+ }));
1646
+ };
1647
+
1648
+ // src/context/providers/ThreadProvider.tsx
1649
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1650
+ var ThreadProvider = ({
1651
+ children,
1652
+ runtime
1653
+ }) => {
1654
+ const runtimeRef = (0, import_react35.useRef)(runtime);
1655
+ (0, import_react35.useInsertionEffect)(() => {
1652
1656
  runtimeRef.current = runtime;
1653
1657
  });
1654
- const [{ context, onNewMessage, onRunningChange }] = (0, import_react33.useState)(() => {
1655
- const { useThread, onNewMessage: onNewMessage2, onRunningChange: onRunningChange2 } = makeThreadStore(runtimeRef);
1656
- const useViewport = makeViewportStore();
1657
- const useComposer = makeThreadComposerStore(useThread);
1658
+ const [{ context, onRuntimeUpdate }] = (0, import_react35.useState)(() => {
1659
+ const { useThread, onRuntimeUpdate: onRuntimeUpdate2 } = makeThreadStore(runtimeRef);
1660
+ const useViewport = makeThreadViewportStore();
1661
+ const useComposer = makeComposerStore(useThread);
1658
1662
  return {
1659
- context: { useViewport, useThread, useComposer },
1660
- onNewMessage: onNewMessage2,
1661
- onRunningChange: onRunningChange2
1663
+ context: {
1664
+ useViewport,
1665
+ useThread,
1666
+ useComposer
1667
+ },
1668
+ onRuntimeUpdate: onRuntimeUpdate2
1662
1669
  };
1663
1670
  });
1664
- (0, import_react33.useEffect)(() => {
1665
- return runtime.subscribeToMessageUpdates(onNewMessage);
1666
- }, [runtime, onNewMessage]);
1667
- (0, import_react33.useEffect)(() => {
1668
- return runtime.subscribeToStatusUpdates(onRunningChange);
1669
- }, [runtime, onRunningChange]);
1670
- return context;
1671
+ (0, import_react35.useEffect)(() => {
1672
+ onRuntimeUpdate();
1673
+ return runtime.subscribe(onRuntimeUpdate);
1674
+ }, [onRuntimeUpdate, runtime]);
1675
+ const RuntimeSynchronizer = runtime.unstable_synchronizer;
1676
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(ThreadContext.Provider, { value: context, children: [
1677
+ RuntimeSynchronizer && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(RuntimeSynchronizer, {}),
1678
+ children
1679
+ ] });
1680
+ };
1681
+
1682
+ // src/context/providers/AssistantRuntimeProvider.tsx
1683
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1684
+ var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
1685
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ThreadProvider, { runtime, children });
1671
1686
  };
1687
+ var AssistantRuntimeProvider = (0, import_react36.memo)(AssistantRuntimeProviderImpl);
1672
1688
 
1673
- // src/adapters/core/AssistantProvider.tsx
1689
+ // src/runtime/vercel-deprecated/VercelAIAssistantProvider.tsx
1674
1690
  var import_jsx_runtime23 = require("react/jsx-runtime");
1675
- var AssistantProvider = ({ children, runtime }) => {
1676
- const context = useAssistantContext2(runtime);
1677
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AssistantContext.Provider, { value: context, children });
1691
+ var VercelUseChatRuntimeProvider = ({
1692
+ chat,
1693
+ children
1694
+ }) => {
1695
+ const runtime = useVercelUseChatRuntime(chat);
1696
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AssistantRuntimeProvider, { runtime, children });
1697
+ };
1698
+ var VercelUseAssistantRuntimeProvider = ({
1699
+ assistant,
1700
+ children
1701
+ }) => {
1702
+ const runtime = useVercelUseAssistantRuntime(assistant);
1703
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AssistantRuntimeProvider, { runtime, children });
1704
+ };
1705
+ var VercelAIAssistantProvider = ({
1706
+ children,
1707
+ ...rest
1708
+ }) => {
1709
+ if ("chat" in rest) {
1710
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(VercelUseChatRuntimeProvider, { chat: rest.chat, children });
1711
+ }
1712
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(VercelUseAssistantRuntimeProvider, { assistant: rest.assistant, children });
1678
1713
  };
1679
1714
 
1680
- // src/adapters/core/local/useLocalRuntime.tsx
1681
- var import_react34 = require("react");
1715
+ // src/runtime/vercel-deprecated/VercelRSCAssistantProvider.tsx
1716
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1717
+ var VercelRSCAssistantProvider = ({
1718
+ children,
1719
+ ...adapter
1720
+ }) => {
1721
+ const runtime = useVercelRSCRuntime(adapter);
1722
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AssistantRuntimeProvider, { runtime, children });
1723
+ };
1724
+
1725
+ // src/runtime/local/useLocalRuntime.tsx
1726
+ var import_react37 = require("react");
1682
1727
 
1683
- // src/adapters/core/local/LocalRuntime.tsx
1728
+ // src/runtime/local/LocalRuntime.tsx
1684
1729
  var LocalRuntime = class {
1685
1730
  constructor(adapter) {
1686
1731
  this.adapter = adapter;
1687
1732
  }
1688
- _messageUpdateCallbacks = /* @__PURE__ */ new Set();
1689
- _statusUpdateCallbacks = /* @__PURE__ */ new Set();
1733
+ _subscriptions = /* @__PURE__ */ new Set();
1690
1734
  abortController = null;
1691
1735
  repository = new MessageRepository();
1736
+ get messages() {
1737
+ return this.repository.getMessages();
1738
+ }
1739
+ get isRunning() {
1740
+ return this.abortController != null;
1741
+ }
1742
+ getBranches(messageId) {
1743
+ return this.repository.getBranches(messageId);
1744
+ }
1745
+ switchToBranch(branchId) {
1746
+ this.repository.switchToBranch(branchId);
1747
+ this.notifySubscribers();
1748
+ }
1692
1749
  async append(message) {
1693
1750
  const userMessageId = generateId();
1694
1751
  const userMessage = {
@@ -1697,9 +1754,8 @@ var LocalRuntime = class {
1697
1754
  content: message.content,
1698
1755
  createdAt: /* @__PURE__ */ new Date()
1699
1756
  };
1700
- this.addOrUpdateMessage(message.parentId, userMessage);
1701
- const { id } = await this.startRun(userMessageId);
1702
- return { parentId: userMessageId, id };
1757
+ this.repository.addOrUpdateMessage(message.parentId, userMessage);
1758
+ await this.startRun(userMessageId);
1703
1759
  }
1704
1760
  async startRun(parentId) {
1705
1761
  const id = generateId();
@@ -1712,63 +1768,56 @@ var LocalRuntime = class {
1712
1768
  content: [{ type: "text", text: "" }],
1713
1769
  createdAt: /* @__PURE__ */ new Date()
1714
1770
  };
1715
- this.addOrUpdateMessage(parentId, message);
1716
- void this.run(parentId, messages, message);
1717
- return { id };
1718
- }
1719
- addOrUpdateMessage(parentId, message) {
1720
- const clone = { ...message };
1721
- this.repository.addOrUpdateMessage(parentId, clone);
1722
- for (const callback of this._messageUpdateCallbacks)
1723
- callback(parentId, clone);
1724
- }
1725
- async run(parentId, messages, message) {
1726
- this.cancelRun();
1727
- for (const callback of this._statusUpdateCallbacks) callback(true);
1771
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1772
+ this.abortController?.abort();
1728
1773
  this.abortController = new AbortController();
1774
+ this.notifySubscribers();
1729
1775
  try {
1730
1776
  await this.adapter.run({
1731
1777
  messages,
1732
1778
  abortSignal: this.abortController.signal,
1733
1779
  onUpdate: ({ content }) => {
1734
1780
  message.content = content;
1735
- this.addOrUpdateMessage(parentId, message);
1781
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1782
+ this.notifySubscribers();
1736
1783
  }
1737
1784
  });
1738
1785
  message.status = "done";
1739
- this.addOrUpdateMessage(parentId, message);
1786
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1740
1787
  } catch (e) {
1741
1788
  message.status = "error";
1742
- this.addOrUpdateMessage(parentId, message);
1789
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1743
1790
  console.error(e);
1744
1791
  } finally {
1745
- this.cancelRun();
1792
+ this.abortController = null;
1793
+ this.notifySubscribers();
1746
1794
  }
1747
1795
  }
1748
1796
  cancelRun() {
1749
1797
  if (!this.abortController) return;
1750
1798
  this.abortController.abort();
1751
1799
  this.abortController = null;
1752
- for (const callback of this._statusUpdateCallbacks) callback(false);
1800
+ this.notifySubscribers();
1753
1801
  }
1754
- subscribeToMessageUpdates(callback) {
1755
- this._messageUpdateCallbacks.add(callback);
1756
- return () => this._messageUpdateCallbacks.delete(callback);
1802
+ notifySubscribers() {
1803
+ for (const callback of this._subscriptions) callback();
1757
1804
  }
1758
- subscribeToStatusUpdates(callback) {
1759
- this._statusUpdateCallbacks.add(callback);
1760
- return () => this._statusUpdateCallbacks.delete(callback);
1805
+ subscribe(callback) {
1806
+ this._subscriptions.add(callback);
1807
+ return () => this._subscriptions.delete(callback);
1761
1808
  }
1762
1809
  };
1763
1810
 
1764
- // src/adapters/core/local/useLocalRuntime.tsx
1811
+ // src/runtime/local/useLocalRuntime.tsx
1765
1812
  var useLocalRuntime = (adapter) => {
1766
- const [runtime] = (0, import_react34.useState)(() => new LocalRuntime(adapter));
1767
- runtime.adapter = adapter;
1813
+ const [runtime] = (0, import_react37.useState)(() => new LocalRuntime(adapter));
1814
+ (0, import_react37.useInsertionEffect)(() => {
1815
+ runtime.adapter = adapter;
1816
+ });
1768
1817
  return runtime;
1769
1818
  };
1770
1819
 
1771
- // src/adapters/core/local/vercel/VercelModelAdapter.tsx
1820
+ // src/runtime/local/vercel/VercelModelAdapter.tsx
1772
1821
  var import_ai = require("ai");
1773
1822
  var VercelModelAdapter = class {
1774
1823
  constructor(model) {
@@ -1812,6 +1861,7 @@ var VercelModelAdapter = class {
1812
1861
  // Annotate the CommonJS export names for ESM import in node:
1813
1862
  0 && (module.exports = {
1814
1863
  ActionBarPrimitive,
1864
+ AssistantRuntimeProvider,
1815
1865
  BranchPickerPrimitive,
1816
1866
  ComposerPrimitive,
1817
1867
  ContentPartPrimitive,
@@ -1819,15 +1869,20 @@ var VercelModelAdapter = class {
1819
1869
  ThreadPrimitive,
1820
1870
  VercelAIAssistantProvider,
1821
1871
  VercelRSCAssistantProvider,
1822
- unstable_AssistantProvider,
1872
+ getVercelAIMessage,
1873
+ getVercelRSCMessage,
1823
1874
  unstable_VercelModelAdapter,
1824
- unstable_getVercelMessage,
1825
- unstable_getVercelRSCMessage,
1875
+ unstable_useComposerContext,
1876
+ unstable_useContentPartContext,
1826
1877
  unstable_useLocalRuntime,
1827
1878
  unstable_useMessageContext,
1879
+ unstable_useThreadContext,
1828
1880
  useBeginMessageEdit,
1829
1881
  useCopyMessage,
1830
1882
  useGoToNextBranch,
1831
1883
  useGoToPreviousBranch,
1832
- useReloadMessage
1884
+ useReloadMessage,
1885
+ useVercelRSCRuntime,
1886
+ useVercelUseAssistantRuntime,
1887
+ useVercelUseChatRuntime
1833
1888
  });