@assistant-ui/react 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.mjs CHANGED
@@ -16,13 +16,14 @@ __export(thread_exports, {
16
16
  });
17
17
 
18
18
  // src/primitives/thread/ThreadRoot.tsx
19
- import { forwardRef } from "react";
20
19
  import {
21
20
  Primitive
22
21
  } from "@radix-ui/react-primitive";
22
+ import { forwardRef } from "react";
23
+ import { jsx } from "react/jsx-runtime";
23
24
  var ThreadRoot = forwardRef(
24
25
  (props, ref) => {
25
- return /* @__PURE__ */ React.createElement(Primitive.div, { ...props, ref });
26
+ return /* @__PURE__ */ jsx(Primitive.div, { ...props, ref });
26
27
  }
27
28
  );
28
29
 
@@ -59,8 +60,9 @@ var ThreadIf = ({ children, ...query }) => {
59
60
  };
60
61
 
61
62
  // src/primitives/thread/ThreadEmpty.tsx
63
+ import { jsx as jsx2 } from "react/jsx-runtime";
62
64
  var ThreadEmpty = ({ children }) => {
63
- return /* @__PURE__ */ React.createElement(ThreadIf, { empty: true }, children);
65
+ return /* @__PURE__ */ jsx2(ThreadIf, { empty: true, children });
64
66
  };
65
67
 
66
68
  // src/primitives/thread/ThreadViewport.tsx
@@ -124,6 +126,7 @@ var useOnScrollToBottom = (callback) => {
124
126
  };
125
127
 
126
128
  // src/primitives/thread/ThreadViewport.tsx
129
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
127
130
  var ThreadViewport = forwardRef2(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
128
131
  const messagesEndRef = useRef3(null);
129
132
  const divRef = useRef3(null);
@@ -160,156 +163,19 @@ var ThreadViewport = forwardRef2(({ autoScroll = true, onScroll, children, ...re
160
163
  }
161
164
  lastScrollTop.current = div.scrollTop;
162
165
  };
163
- return /* @__PURE__ */ React.createElement(
166
+ return /* @__PURE__ */ jsxs(
164
167
  Primitive2.div,
165
168
  {
166
169
  ...rest,
167
170
  onScroll: composeEventHandlers(onScroll, handleScroll),
168
- ref
169
- },
170
- children,
171
- /* @__PURE__ */ React.createElement("div", { ref: messagesEndRef })
172
- );
173
- });
174
-
175
- // src/adapters/vercel/useVercelAIBranches.tsx
176
- import { useCallback, useMemo, useRef as useRef4 } from "react";
177
-
178
- // src/utils/context/stores/AssistantTypes.ts
179
- var ROOT_PARENT_ID = "__ROOT_ID__";
180
-
181
- // src/adapters/vercel/useVercelAIBranches.tsx
182
- var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
183
- var updateBranchData = (data, messages) => {
184
- for (let i = 0; i < messages.length; i++) {
185
- const child = messages[i];
186
- const childId = child.id;
187
- const parentId = messages[i - 1]?.id ?? ROOT_PARENT_ID;
188
- data.parentMap.set(childId, parentId);
189
- const parentArray = data.branchMap.get(parentId);
190
- if (!parentArray) {
191
- data.branchMap.set(parentId, [childId]);
192
- } else if (!parentArray.includes(childId)) {
193
- parentArray.push(childId);
171
+ ref,
172
+ children: [
173
+ children,
174
+ /* @__PURE__ */ jsx3("div", { ref: messagesEndRef })
175
+ ]
194
176
  }
195
- data.snapshots.set(childId, messages);
196
- }
197
- };
198
- var getParentId = (data, messages, messageId) => {
199
- if (messageId === UPCOMING_MESSAGE_ID) {
200
- const parent = messages.at(-1);
201
- if (!parent)
202
- return ROOT_PARENT_ID;
203
- return parent.id;
204
- }
205
- const parentId = data.parentMap.get(messageId);
206
- if (!parentId)
207
- throw new Error("Unexpected: Message parent not found");
208
- return parentId;
209
- };
210
- var getBranchStateImpl = (data, messages, messageId) => {
211
- const parentId = getParentId(data, messages, messageId);
212
- const branches = data.branchMap.get(parentId) ?? [];
213
- const branchId = messageId === UPCOMING_MESSAGE_ID ? branches.length : branches.indexOf(messageId);
214
- if (branchId === -1)
215
- throw new Error("Unexpected: Message not found in parent children");
216
- const upcomingOffset = messageId === UPCOMING_MESSAGE_ID ? 1 : 0;
217
- return {
218
- branchId,
219
- branchCount: branches.length + upcomingOffset
220
- };
221
- };
222
- var switchToBranchImpl = (data, messages, messageId, branchId) => {
223
- const parentId = getParentId(data, messages, messageId);
224
- const branches = data.branchMap.get(parentId);
225
- if (!branches)
226
- throw new Error("Unexpected: Parent children not found");
227
- const newMessageId = branches[branchId];
228
- if (!newMessageId)
229
- throw new Error("Unexpected: Requested branch not found");
230
- if (branchId < 0 || branchId >= branches.length)
231
- throw new Error("Switch to branch called with a branch index out of range");
232
- if (newMessageId === messageId)
233
- return messages;
234
- const snapshot = data.snapshots.get(newMessageId);
235
- if (!snapshot)
236
- throw new Error("Unexpected: Branch snapshot not found");
237
- return snapshot;
238
- };
239
- var sliceMessagesUntil = (messages, messageId) => {
240
- if (messageId === ROOT_PARENT_ID)
241
- return [];
242
- if (messageId === UPCOMING_MESSAGE_ID)
243
- return messages;
244
- const messageIdx = messages.findIndex((m) => m.id === messageId);
245
- if (messageIdx === -1)
246
- throw new Error("Unexpected: Message not found");
247
- return messages.slice(0, messageIdx + 1);
248
- };
249
- var useVercelAIBranches = (chat, context) => {
250
- const data = useRef4({
251
- parentMap: /* @__PURE__ */ new Map(),
252
- branchMap: /* @__PURE__ */ new Map(),
253
- snapshots: /* @__PURE__ */ new Map()
254
- }).current;
255
- updateBranchData(data, chat.messages);
256
- const getBranchState = useCallback(
257
- (messageId) => {
258
- return getBranchStateImpl(data, chat.messages, messageId);
259
- },
260
- [data, chat.messages]
261
- );
262
- const switchToBranch = useCallback(
263
- (messageId, branchId) => {
264
- const newMessages = switchToBranchImpl(
265
- data,
266
- chat.messages,
267
- messageId,
268
- branchId
269
- );
270
- chat.setMessages(newMessages);
271
- },
272
- [data, chat.messages, chat.setMessages]
273
- );
274
- const reloadMaybe = "reload" in chat ? chat.reload : void 0;
275
- const startRun = useCallback(
276
- async (parentId) => {
277
- if (!reloadMaybe)
278
- throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
279
- const newMessages = sliceMessagesUntil(chat.messages, parentId);
280
- chat.setMessages(newMessages);
281
- context.useViewport.getState().scrollToBottom();
282
- await reloadMaybe();
283
- },
284
- [context, chat.messages, chat.setMessages, reloadMaybe]
285
- );
286
- const append = useCallback(
287
- async (message) => {
288
- const newMessages = sliceMessagesUntil(chat.messages, message.parentId);
289
- chat.setMessages(newMessages);
290
- if (message.content.length !== 1 || message.content[0]?.type !== "text")
291
- throw new Error("Only text content is currently supported");
292
- context.useViewport.getState().scrollToBottom();
293
- await chat.append({
294
- role: "user",
295
- content: message.content[0].text
296
- });
297
- },
298
- [context, chat.messages, chat.setMessages, chat.append]
299
177
  );
300
- return useMemo(
301
- () => ({
302
- getBranchState,
303
- switchToBranch,
304
- append,
305
- startRun
306
- }),
307
- [getBranchState, switchToBranch, append, startRun]
308
- );
309
- };
310
- var hasUpcomingMessage = (thread) => {
311
- return thread.isRunning && thread.messages[thread.messages.length - 1]?.role !== "assistant";
312
- };
178
+ });
313
179
 
314
180
  // src/utils/context/useComposerContext.ts
315
181
  import { useContext as useContext3 } from "react";
@@ -360,7 +226,7 @@ __export(message_exports, {
360
226
  });
361
227
 
362
228
  // src/primitives/message/MessageProvider.tsx
363
- import { useMemo as useMemo2, useState } from "react";
229
+ import { useMemo, useState } from "react";
364
230
  import { create as create2 } from "zustand";
365
231
 
366
232
  // src/utils/context/stores/ComposerStore.ts
@@ -378,7 +244,6 @@ var makeMessageComposerStore = ({
378
244
  onSend
379
245
  }) => create()((set, get, store) => ({
380
246
  ...makeBaseComposer(set, get, store),
381
- canCancel: true,
382
247
  isEditing: false,
383
248
  edit: () => {
384
249
  const value = onEdit();
@@ -387,39 +252,48 @@ var makeMessageComposerStore = ({
387
252
  send: () => {
388
253
  const value = get().value;
389
254
  set({ isEditing: false });
390
- return onSend(value);
255
+ onSend(value);
391
256
  },
392
257
  cancel: () => {
258
+ if (!get().isEditing)
259
+ return false;
393
260
  set({ isEditing: false });
261
+ return true;
394
262
  }
395
263
  }));
396
- var makeThreadComposerStore = ({
397
- onSend,
398
- onCancel
399
- }) => create()((set, get, store) => ({
400
- ...makeBaseComposer(set, get, store),
401
- isEditing: true,
402
- canCancel: false,
403
- send: () => {
404
- const value = get().value;
405
- set({ value: "", canCancel: true });
406
- onSend(value).then(() => {
407
- set({ canCancel: false });
408
- });
409
- },
410
- cancel: onCancel
411
- }));
264
+ var makeThreadComposerStore = (useThread) => create()((set, get, store) => {
265
+ return {
266
+ ...makeBaseComposer(set, get, store),
267
+ isEditing: true,
268
+ send: () => {
269
+ const { value } = get();
270
+ set({ value: "" });
271
+ useThread.getState().append({
272
+ parentId: useThread.getState().messages.at(-1)?.id ?? null,
273
+ content: [{ type: "text", text: value }]
274
+ });
275
+ },
276
+ cancel: () => {
277
+ const thread = useThread.getState();
278
+ if (!thread.isRunning)
279
+ return false;
280
+ useThread.getState().cancelRun();
281
+ return true;
282
+ }
283
+ };
284
+ });
412
285
 
413
286
  // src/primitives/message/MessageProvider.tsx
287
+ import { jsx as jsx4 } from "react/jsx-runtime";
414
288
  var getIsLast = (thread, message) => {
415
- const hasUpcoming = hasUpcomingMessage(thread);
416
- return hasUpcoming ? message.id === UPCOMING_MESSAGE_ID : thread.messages[thread.messages.length - 1]?.id === message.id;
289
+ return thread.messages[thread.messages.length - 1]?.id === message.id;
417
290
  };
418
291
  var useMessageContext2 = () => {
292
+ const { useThread } = useAssistantContext();
419
293
  const [context] = useState(() => {
420
- const { useThread } = useAssistantContext();
421
294
  const useMessage = create2(() => ({
422
295
  message: null,
296
+ branches: [],
423
297
  isLast: false,
424
298
  isCopied: false,
425
299
  isHovering: false,
@@ -439,7 +313,7 @@ var useMessageContext2 = () => {
439
313
  },
440
314
  onSend: (text) => {
441
315
  const message = useMessage.getState().message;
442
- return useThread.getState().append({
316
+ useThread.getState().append({
443
317
  parentId: message.parentId,
444
318
  content: [{ type: "text", text }]
445
319
  });
@@ -456,12 +330,14 @@ var MessageProvider = ({
456
330
  const { useThread } = useAssistantContext();
457
331
  const context = useMessageContext2();
458
332
  const isLast = useThread((thread) => getIsLast(thread, message));
333
+ const branches = useThread((thread) => thread.getBranches(message.id));
459
334
  const [isCopied, setIsCopied] = useState(false);
460
335
  const [isHovering, setIsHovering] = useState(false);
461
- useMemo2(() => {
336
+ useMemo(() => {
462
337
  context.useMessage.setState(
463
338
  {
464
339
  message,
340
+ branches,
465
341
  isLast,
466
342
  isCopied,
467
343
  isHovering,
@@ -470,8 +346,8 @@ var MessageProvider = ({
470
346
  },
471
347
  true
472
348
  );
473
- }, [context, message, isLast, isCopied, isHovering]);
474
- return /* @__PURE__ */ React.createElement(MessageContext.Provider, { value: context }, children);
349
+ }, [context, message, branches, isLast, isCopied, isHovering]);
350
+ return /* @__PURE__ */ jsx4(MessageContext.Provider, { value: context, children });
475
351
  };
476
352
 
477
353
  // src/primitives/message/MessageRoot.tsx
@@ -480,6 +356,7 @@ import {
480
356
  Primitive as Primitive3
481
357
  } from "@radix-ui/react-primitive";
482
358
  import { forwardRef as forwardRef3 } from "react";
359
+ import { jsx as jsx5 } from "react/jsx-runtime";
483
360
  var MessageRoot = forwardRef3(
484
361
  ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
485
362
  const { useMessage } = useMessageContext();
@@ -490,7 +367,7 @@ var MessageRoot = forwardRef3(
490
367
  const handleMouseLeave = () => {
491
368
  setIsHovering(false);
492
369
  };
493
- return /* @__PURE__ */ React.createElement(
370
+ return /* @__PURE__ */ jsx5(
494
371
  Primitive3.div,
495
372
  {
496
373
  ...rest,
@@ -505,8 +382,8 @@ var MessageRoot = forwardRef3(
505
382
  // src/primitives/message/MessageIf.tsx
506
383
  var useMessageIf = (props) => {
507
384
  const { useMessage } = useMessageContext();
508
- return useMessage(({ message, isLast, isCopied, isHovering }) => {
509
- if (props.hasBranches === true && message.branchCount < 2)
385
+ return useMessage(({ message, branches, isLast, isCopied, isHovering }) => {
386
+ if (props.hasBranches === true && branches.length < 2)
510
387
  return false;
511
388
  if (props.user && message.role !== "user")
512
389
  return false;
@@ -527,8 +404,9 @@ var MessageIf = ({ children, ...query }) => {
527
404
  };
528
405
 
529
406
  // src/primitives/message/MessageContent.tsx
407
+ import { Fragment, jsx as jsx6 } from "react/jsx-runtime";
530
408
  var defaultComponents = {
531
- Text: ({ part }) => /* @__PURE__ */ React.createElement(React.Fragment, null, part.text),
409
+ Text: ({ part }) => /* @__PURE__ */ jsx6(Fragment, { children: part.text }),
532
410
  Image: () => null,
533
411
  UI: ({ part }) => part.display,
534
412
  tools: {
@@ -545,26 +423,27 @@ var MessageContent = ({
545
423
  }) => {
546
424
  const { useMessage } = useMessageContext();
547
425
  const content = useMessage((s) => s.message.content);
548
- return /* @__PURE__ */ React.createElement(React.Fragment, null, content.map((part, i) => {
426
+ return /* @__PURE__ */ jsx6(Fragment, { children: content.map((part, i) => {
549
427
  const key = i;
550
428
  switch (part.type) {
551
429
  case "text":
552
- return /* @__PURE__ */ React.createElement(Text, { key, part });
430
+ return /* @__PURE__ */ jsx6(Text, { part }, key);
553
431
  case "image":
554
- return /* @__PURE__ */ React.createElement(Image, { key, part });
432
+ return /* @__PURE__ */ jsx6(Image, { part }, key);
555
433
  case "ui":
556
- return /* @__PURE__ */ React.createElement(UI, { key, part });
434
+ return /* @__PURE__ */ jsx6(UI, { part }, key);
557
435
  case "tool-call": {
558
436
  const Tool = by_name[part.name] || Fallback;
559
- return /* @__PURE__ */ React.createElement(Tool, { key, part });
437
+ return /* @__PURE__ */ jsx6(Tool, { part }, key);
560
438
  }
561
439
  default:
562
440
  return null;
563
441
  }
564
- }));
442
+ }) });
565
443
  };
566
444
 
567
445
  // src/primitives/thread/ThreadMessages.tsx
446
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
568
447
  var getComponents = (components) => {
569
448
  return {
570
449
  EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
@@ -579,27 +458,18 @@ var ThreadMessages = ({ components }) => {
579
458
  const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
580
459
  if (messages.length === 0)
581
460
  return null;
582
- return /* @__PURE__ */ React.createElement(React.Fragment, null, messages.map((message, idx) => {
461
+ return /* @__PURE__ */ jsx7(Fragment2, { children: messages.map((message, idx) => {
583
462
  return (
584
463
  // biome-ignore lint/suspicious/noArrayIndexKey: fixes a11y issues with branch navigation
585
- /* @__PURE__ */ React.createElement(MessageProvider, { key: idx, message }, /* @__PURE__ */ React.createElement(MessageIf, { user: true }, /* @__PURE__ */ React.createElement(ComposerIf, { editing: false }, /* @__PURE__ */ React.createElement(UserMessage, null)), /* @__PURE__ */ React.createElement(ComposerIf, { editing: true }, /* @__PURE__ */ React.createElement(EditComposer, null))), /* @__PURE__ */ React.createElement(MessageIf, { assistant: true }, /* @__PURE__ */ React.createElement(AssistantMessage, null)))
464
+ /* @__PURE__ */ jsxs2(MessageProvider, { message, children: [
465
+ /* @__PURE__ */ jsxs2(MessageIf, { user: true, children: [
466
+ /* @__PURE__ */ jsx7(ComposerIf, { editing: false, children: /* @__PURE__ */ jsx7(UserMessage, {}) }),
467
+ /* @__PURE__ */ jsx7(ComposerIf, { editing: true, children: /* @__PURE__ */ jsx7(EditComposer, {}) })
468
+ ] }),
469
+ /* @__PURE__ */ jsx7(MessageIf, { assistant: true, children: /* @__PURE__ */ jsx7(AssistantMessage, {}) })
470
+ ] }, idx)
586
471
  );
587
- }), hasUpcomingMessage(thread) && /* @__PURE__ */ React.createElement(
588
- MessageProvider,
589
- {
590
- message: {
591
- id: UPCOMING_MESSAGE_ID,
592
- role: "assistant",
593
- content: [{ type: "text", text: "..." }],
594
- parentId: messages.at(-1)?.id ?? ROOT_PARENT_ID,
595
- // TODO fix these (move upcoming message to AssistantContext)
596
- branchId: 0,
597
- branchCount: 1,
598
- createdAt: /* @__PURE__ */ new Date()
599
- }
600
- },
601
- /* @__PURE__ */ React.createElement(AssistantMessage, null)
602
- ));
472
+ }) });
603
473
  };
604
474
 
605
475
  // src/primitives/thread/ThreadScrollToBottom.tsx
@@ -608,13 +478,14 @@ import {
608
478
  Primitive as Primitive4
609
479
  } from "@radix-ui/react-primitive";
610
480
  import { forwardRef as forwardRef4 } from "react";
481
+ import { jsx as jsx8 } from "react/jsx-runtime";
611
482
  var ThreadScrollToBottom = forwardRef4(({ onClick, ...rest }, ref) => {
612
483
  const { useViewport } = useAssistantContext();
613
484
  const isAtBottom = useViewport((s) => s.isAtBottom);
614
485
  const handleScrollToBottom = () => {
615
486
  useViewport.getState().scrollToBottom();
616
487
  };
617
- return /* @__PURE__ */ React.createElement(
488
+ return /* @__PURE__ */ jsx8(
618
489
  Primitive4.button,
619
490
  {
620
491
  ...rest,
@@ -641,11 +512,13 @@ import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-ref
641
512
  import {
642
513
  Primitive as Primitive5
643
514
  } from "@radix-ui/react-primitive";
644
- import { forwardRef as forwardRef5, useRef as useRef5 } from "react";
515
+ import { forwardRef as forwardRef5, useRef as useRef4 } from "react";
516
+ import { jsx as jsx9 } from "react/jsx-runtime";
645
517
  var ComposerRoot = forwardRef5(
646
518
  ({ onSubmit, ...rest }, forwardedRef) => {
519
+ const { useViewport } = useAssistantContext();
647
520
  const { useComposer } = useComposerContext();
648
- const formRef = useRef5(null);
521
+ const formRef = useRef4(null);
649
522
  const ref = useComposedRefs2(forwardedRef, formRef);
650
523
  const handleSubmit = (e) => {
651
524
  const composerState = useComposer.getState();
@@ -653,8 +526,9 @@ var ComposerRoot = forwardRef5(
653
526
  return;
654
527
  e.preventDefault();
655
528
  composerState.send();
529
+ useViewport.getState().scrollToBottom();
656
530
  };
657
- return /* @__PURE__ */ React.createElement(
531
+ return /* @__PURE__ */ jsx9(
658
532
  Primitive5.form,
659
533
  {
660
534
  ...rest,
@@ -671,14 +545,15 @@ import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-ref
671
545
  import { Slot } from "@radix-ui/react-slot";
672
546
  import {
673
547
  forwardRef as forwardRef6,
674
- useCallback as useCallback2,
548
+ useCallback,
675
549
  useEffect as useEffect2,
676
- useRef as useRef6
550
+ useRef as useRef5
677
551
  } from "react";
678
552
  import TextareaAutosize from "react-textarea-autosize";
553
+ import { jsx as jsx10 } from "react/jsx-runtime";
679
554
  var ComposerInput = forwardRef6(
680
555
  ({ autoFocus, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
681
- const { useThread } = useAssistantContext();
556
+ const { useThread, useViewport } = useAssistantContext();
682
557
  const { useComposer, type } = useComposerContext();
683
558
  const value = useComposer((c) => {
684
559
  if (!c.isEditing)
@@ -690,22 +565,23 @@ var ComposerInput = forwardRef6(
690
565
  if (disabled)
691
566
  return;
692
567
  const composer = useComposer.getState();
693
- if (e.key === "Escape" && composer.canCancel) {
694
- e.preventDefault();
695
- useComposer.getState().cancel();
696
- }
697
- if (e.key === "Enter" && e.shiftKey === false) {
568
+ if (e.key === "Escape") {
569
+ if (useComposer.getState().cancel()) {
570
+ e.preventDefault();
571
+ }
572
+ } else if (e.key === "Enter" && e.shiftKey === false) {
698
573
  const isRunning = useThread.getState().isRunning;
699
574
  if (!isRunning) {
700
575
  e.preventDefault();
701
576
  composer.send();
577
+ useViewport.getState().scrollToBottom();
702
578
  }
703
579
  }
704
580
  };
705
- const textareaRef = useRef6(null);
581
+ const textareaRef = useRef5(null);
706
582
  const ref = useComposedRefs3(forwardedRef, textareaRef);
707
583
  const autoFocusEnabled = autoFocus !== false && !disabled;
708
- const focus = useCallback2(() => {
584
+ const focus = useCallback(() => {
709
585
  const textarea = textareaRef.current;
710
586
  if (!textarea || !autoFocusEnabled)
711
587
  return;
@@ -721,7 +597,7 @@ var ComposerInput = forwardRef6(
721
597
  focus();
722
598
  }
723
599
  });
724
- return /* @__PURE__ */ React.createElement(
600
+ return /* @__PURE__ */ jsx10(
725
601
  Component,
726
602
  {
727
603
  value,
@@ -745,11 +621,12 @@ import {
745
621
  Primitive as Primitive6
746
622
  } from "@radix-ui/react-primitive";
747
623
  import { forwardRef as forwardRef7 } from "react";
624
+ import { jsx as jsx11 } from "react/jsx-runtime";
748
625
  var ComposerSend = forwardRef7(
749
626
  ({ disabled, ...rest }, ref) => {
750
627
  const { useComposer } = useComposerContext();
751
628
  const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
752
- return /* @__PURE__ */ React.createElement(
629
+ return /* @__PURE__ */ jsx11(
753
630
  Primitive6.button,
754
631
  {
755
632
  type: "submit",
@@ -767,20 +644,19 @@ import {
767
644
  Primitive as Primitive7
768
645
  } from "@radix-ui/react-primitive";
769
646
  import { forwardRef as forwardRef8 } from "react";
770
- var ComposerCancel = forwardRef8(({ disabled, onClick, ...rest }, ref) => {
647
+ import { jsx as jsx12 } from "react/jsx-runtime";
648
+ var ComposerCancel = forwardRef8(({ onClick, ...rest }, ref) => {
771
649
  const { useComposer } = useComposerContext();
772
- const hasValue = useComposer((c) => c.canCancel);
773
- const handleClose = () => {
650
+ const handleCancel = () => {
774
651
  useComposer.getState().cancel();
775
652
  };
776
- return /* @__PURE__ */ React.createElement(
653
+ return /* @__PURE__ */ jsx12(
777
654
  Primitive7.button,
778
655
  {
779
656
  type: "button",
780
657
  ...rest,
781
658
  ref,
782
- onClick: composeEventHandlers6(onClick, handleClose),
783
- disabled: disabled || !hasValue
659
+ onClick: composeEventHandlers6(onClick, handleCancel)
784
660
  }
785
661
  );
786
662
  });
@@ -796,7 +672,7 @@ __export(branchPicker_exports, {
796
672
  });
797
673
 
798
674
  // src/utils/context/combined/useCombinedStore.ts
799
- import { useMemo as useMemo3 } from "react";
675
+ import { useMemo as useMemo2 } from "react";
800
676
 
801
677
  // src/utils/context/combined/createCombinedStore.ts
802
678
  import { useSyncExternalStore } from "react";
@@ -817,37 +693,38 @@ var createCombinedStore = (stores) => {
817
693
 
818
694
  // src/utils/context/combined/useCombinedStore.ts
819
695
  var useCombinedStore = (stores, selector) => {
820
- const useCombined = useMemo3(() => createCombinedStore(stores), stores);
696
+ const useCombined = useMemo2(() => createCombinedStore(stores), stores);
821
697
  return useCombined(selector);
822
698
  };
823
699
 
824
700
  // src/actions/useGoToNextBranch.tsx
825
701
  var useGoToNextBranch = () => {
826
702
  const { useThread } = useAssistantContext();
827
- const { useComposer, useMessage } = useMessageContext();
703
+ const { useMessage, useComposer } = useMessageContext();
828
704
  const disabled = useCombinedStore(
829
- [useThread, useComposer, useMessage],
830
- (t, c, m) => t.isRunning || c.isEditing || m.message.branchId + 1 >= m.message.branchCount
705
+ [useMessage, useComposer],
706
+ (m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
831
707
  );
832
708
  if (disabled)
833
709
  return null;
834
710
  return () => {
835
- const { message } = useMessage.getState();
836
- useThread.getState().switchToBranch(message.id, message.branchId + 1);
711
+ const { message, branches } = useMessage.getState();
712
+ useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
837
713
  };
838
714
  };
839
715
 
840
716
  // src/utils/createActionButton.tsx
841
- import { forwardRef as forwardRef9 } from "react";
717
+ import { composeEventHandlers as composeEventHandlers7 } from "@radix-ui/primitive";
842
718
  import {
843
719
  Primitive as Primitive8
844
720
  } from "@radix-ui/react-primitive";
845
- import { composeEventHandlers as composeEventHandlers7 } from "@radix-ui/primitive";
721
+ import { forwardRef as forwardRef9 } from "react";
722
+ import { jsx as jsx13 } from "react/jsx-runtime";
846
723
  var createActionButton = (useActionButton) => {
847
724
  return forwardRef9(
848
725
  (props, forwardedRef) => {
849
726
  const onClick = useActionButton(props);
850
- return /* @__PURE__ */ React.createElement(
727
+ return /* @__PURE__ */ jsx13(
851
728
  Primitive8.button,
852
729
  {
853
730
  type: "button",
@@ -867,16 +744,19 @@ var BranchPickerNext = createActionButton(useGoToNextBranch);
867
744
  // src/actions/useGoToPreviousBranch.tsx
868
745
  var useGoToPreviousBranch = () => {
869
746
  const { useThread } = useAssistantContext();
870
- const { useComposer, useMessage } = useMessageContext();
747
+ const { useMessage, useComposer } = useMessageContext();
871
748
  const disabled = useCombinedStore(
872
- [useThread, useComposer, useMessage],
873
- (t, c, m) => t.isRunning || c.isEditing || m.message.branchId <= 0
749
+ [useMessage, useComposer],
750
+ (m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
874
751
  );
875
752
  if (disabled)
876
753
  return null;
877
754
  return () => {
878
- const { message } = useMessage.getState();
879
- useThread.getState().switchToBranch(message.id, message.branchId - 1);
755
+ const { message, branches } = useMessage.getState();
756
+ useThread.getState().switchToBranch(
757
+ branches[branches.indexOf(message.id) - 1]
758
+ // TODO probably there's a more elegant way to do this
759
+ );
880
760
  };
881
761
  };
882
762
 
@@ -884,17 +764,19 @@ var useGoToPreviousBranch = () => {
884
764
  var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
885
765
 
886
766
  // src/primitives/branchPicker/BranchPickerCount.tsx
767
+ import { Fragment as Fragment3, jsx as jsx14 } from "react/jsx-runtime";
887
768
  var BranchPickerCount = () => {
888
769
  const { useMessage } = useMessageContext();
889
- const branchCount = useMessage((s) => s.message.branchCount);
890
- return /* @__PURE__ */ React.createElement(React.Fragment, null, branchCount);
770
+ const branchCount = useMessage((s) => s.branches.length);
771
+ return /* @__PURE__ */ jsx14(Fragment3, { children: branchCount });
891
772
  };
892
773
 
893
774
  // src/primitives/branchPicker/BranchPickerNumber.tsx
775
+ import { Fragment as Fragment4, jsx as jsx15 } from "react/jsx-runtime";
894
776
  var BranchPickerNumber = () => {
895
777
  const { useMessage } = useMessageContext();
896
- const branchId = useMessage((s) => s.message.branchId);
897
- return /* @__PURE__ */ React.createElement(React.Fragment, null, branchId + 1);
778
+ const branchIdx = useMessage((s) => s.branches.indexOf(s.message.id));
779
+ return /* @__PURE__ */ jsx15(Fragment4, { children: branchIdx + 1 });
898
780
  };
899
781
 
900
782
  // src/primitives/branchPicker/BranchPickerRoot.tsx
@@ -902,8 +784,9 @@ import {
902
784
  Primitive as Primitive9
903
785
  } from "@radix-ui/react-primitive";
904
786
  import { forwardRef as forwardRef10 } from "react";
787
+ import { jsx as jsx16 } from "react/jsx-runtime";
905
788
  var BranchPickerRoot = forwardRef10(({ hideWhenSingleBranch, ...rest }, ref) => {
906
- return /* @__PURE__ */ React.createElement(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0 }, /* @__PURE__ */ React.createElement(Primitive9.div, { ...rest, ref }));
789
+ return /* @__PURE__ */ jsx16(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ jsx16(Primitive9.div, { ...rest, ref }) });
907
790
  });
908
791
 
909
792
  // src/primitives/actionBar/index.ts
@@ -920,6 +803,7 @@ import {
920
803
  Primitive as Primitive10
921
804
  } from "@radix-ui/react-primitive";
922
805
  import { forwardRef as forwardRef11 } from "react";
806
+ import { jsx as jsx17 } from "react/jsx-runtime";
923
807
  var ActionBarRoot = forwardRef11(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
924
808
  const { useThread } = useAssistantContext();
925
809
  const { useMessage } = useMessageContext();
@@ -933,14 +817,14 @@ var ActionBarRoot = forwardRef11(({ hideWhenRunning, autohide, autohideFloat, ..
933
817
  return "normal" /* Normal */;
934
818
  if (!m.isHovering)
935
819
  return "hidden" /* Hidden */;
936
- if (autohideFloat === "always" || autohideFloat === "single-branch" && m.message.branchCount <= 1)
820
+ if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
937
821
  return "floating" /* Floating */;
938
822
  return "normal" /* Normal */;
939
823
  }
940
824
  );
941
825
  if (hideAndfloatStatus === "hidden" /* Hidden */)
942
826
  return null;
943
- return /* @__PURE__ */ React.createElement(
827
+ return /* @__PURE__ */ jsx17(
944
828
  Primitive10.div,
945
829
  {
946
830
  "data-floating": hideAndfloatStatus === "floating" /* Floating */,
@@ -971,7 +855,7 @@ var ActionBarCopy = createActionButton(useCopyMessage);
971
855
 
972
856
  // src/actions/useReloadMessage.tsx
973
857
  var useReloadMessage = () => {
974
- const { useThread } = useAssistantContext();
858
+ const { useThread, useViewport } = useAssistantContext();
975
859
  const { useMessage } = useMessageContext();
976
860
  const disabled = useCombinedStore(
977
861
  [useThread, useMessage],
@@ -984,6 +868,7 @@ var useReloadMessage = () => {
984
868
  if (message.role !== "assistant")
985
869
  throw new Error("Reloading is only supported on assistant messages");
986
870
  useThread.getState().startRun(message.parentId);
871
+ useViewport.getState().scrollToBottom();
987
872
  };
988
873
  };
989
874
 
@@ -1036,45 +921,285 @@ var makeViewportStore = () => {
1036
921
  };
1037
922
 
1038
923
  // src/adapters/vercel/useDummyAIAssistantContext.tsx
924
+ var makeDummyThreadStore = () => {
925
+ return create4(() => ({
926
+ messages: [],
927
+ isRunning: false,
928
+ getBranches: () => {
929
+ return [];
930
+ },
931
+ switchToBranch: () => {
932
+ throw new Error("Not implemented");
933
+ },
934
+ append: async () => {
935
+ throw new Error("Not implemented");
936
+ },
937
+ cancelRun: () => {
938
+ throw new Error("Not implemented");
939
+ },
940
+ startRun: async () => {
941
+ throw new Error("Not implemented");
942
+ }
943
+ }));
944
+ };
1039
945
  var useDummyAIAssistantContext = () => {
1040
946
  const [context] = useState2(() => {
1041
- const useThread = create4()(() => ({
1042
- id: "",
1043
- messages: [],
1044
- isRunning: false,
1045
- append: async () => {
1046
- throw new Error("Not implemented");
1047
- },
1048
- cancelRun: () => {
1049
- throw new Error("Not implemented");
1050
- },
1051
- switchToBranch: () => {
1052
- throw new Error("Not implemented");
1053
- },
1054
- startRun: async () => {
1055
- throw new Error("Not implemented");
1056
- }
1057
- }));
947
+ const useThread = makeDummyThreadStore();
1058
948
  const useViewport = makeViewportStore();
1059
- const useComposer = makeThreadComposerStore({
1060
- onSend: async (text) => {
1061
- await useThread.getState().append({
1062
- parentId: useThread.getState().messages.at(-1)?.id ?? ROOT_PARENT_ID,
1063
- content: [{ type: "text", text }]
1064
- });
1065
- },
1066
- onCancel: () => {
1067
- useThread.getState().cancelRun();
1068
- }
1069
- });
949
+ const useComposer = makeThreadComposerStore(useThread);
1070
950
  return { useThread, useViewport, useComposer };
1071
951
  });
1072
952
  return context;
1073
953
  };
1074
954
 
955
+ // src/adapters/vercel/useVercelAIBranches.tsx
956
+ import { useCallback as useCallback2, useMemo as useMemo3, useRef as useRef6, useState as useState3 } from "react";
957
+
958
+ // ../../node_modules/nanoid/non-secure/index.js
959
+ var customAlphabet = (alphabet, defaultSize = 21) => {
960
+ return (size = defaultSize) => {
961
+ let id = "";
962
+ let i = size;
963
+ while (i--) {
964
+ id += alphabet[Math.random() * alphabet.length | 0];
965
+ }
966
+ return id;
967
+ };
968
+ };
969
+
970
+ // src/adapters/MessageRepository.tsx
971
+ var generateId = customAlphabet(
972
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
973
+ 7
974
+ );
975
+ var optimisticPrefix = "__optimistic__";
976
+ var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
977
+ var isOptimisticId = (id) => id.startsWith(optimisticPrefix);
978
+ var findHead = (message) => {
979
+ if (message.next)
980
+ return findHead(message.next);
981
+ return message;
982
+ };
983
+ var MessageRepository = class {
984
+ messages = /* @__PURE__ */ new Map();
985
+ // message_id -> item
986
+ head = null;
987
+ rootChildren = [];
988
+ getMessages() {
989
+ const messages = new Array(this.head?.level ?? 0);
990
+ for (let current = this.head; current; current = current.prev) {
991
+ messages[current.level] = current.current;
992
+ }
993
+ return messages;
994
+ }
995
+ addOrUpdateMessage(message) {
996
+ const item = this.messages.get(message.id);
997
+ if (item) {
998
+ if (item.current.parentId !== message.parentId) {
999
+ this.deleteMessage(message.id);
1000
+ } else {
1001
+ item.current = message;
1002
+ return;
1003
+ }
1004
+ }
1005
+ const prev = message.parentId ? this.messages.get(message.parentId) : null;
1006
+ if (prev === void 0)
1007
+ throw new Error("Unexpected: Parent message not found");
1008
+ const newItem = {
1009
+ prev,
1010
+ current: message,
1011
+ next: null,
1012
+ children: [],
1013
+ level: prev ? prev.level + 1 : 0
1014
+ };
1015
+ this.messages.set(message.id, newItem);
1016
+ if (prev) {
1017
+ prev.children = [...prev.children, message.id];
1018
+ prev.next = newItem;
1019
+ } else {
1020
+ this.rootChildren = [...this.rootChildren, message.id];
1021
+ }
1022
+ if (this.head === prev) {
1023
+ this.head = newItem;
1024
+ }
1025
+ }
1026
+ deleteMessage(messageId) {
1027
+ const message = this.messages.get(messageId);
1028
+ if (!message)
1029
+ throw new Error("Unexpected: Message not found");
1030
+ if (message.children.length > 0) {
1031
+ for (const child of message.children) {
1032
+ this.deleteMessage(child);
1033
+ }
1034
+ }
1035
+ this.messages.delete(messageId);
1036
+ if (message.prev) {
1037
+ message.prev.children = message.prev.children.filter(
1038
+ (m) => m !== messageId
1039
+ );
1040
+ if (message.prev.next === message) {
1041
+ const childId = message.prev.children.at(-1);
1042
+ const child = childId ? this.messages.get(childId) : null;
1043
+ if (child === void 0)
1044
+ throw new Error("Unexpected: Child message not found");
1045
+ message.prev.next = child;
1046
+ }
1047
+ } else {
1048
+ this.rootChildren = this.rootChildren.filter((m) => m !== messageId);
1049
+ }
1050
+ if (this.head === message) {
1051
+ this.head = message.prev ? findHead(message.prev) : null;
1052
+ }
1053
+ }
1054
+ getOptimisticId = () => {
1055
+ let optimisticId;
1056
+ do {
1057
+ optimisticId = generateOptimisticId();
1058
+ } while (this.messages.has(optimisticId));
1059
+ return optimisticId;
1060
+ };
1061
+ commitOptimisticRun(parentId) {
1062
+ const optimisticId = this.getOptimisticId();
1063
+ this.addOrUpdateMessage({
1064
+ id: optimisticId,
1065
+ role: "assistant",
1066
+ content: [
1067
+ {
1068
+ type: "text",
1069
+ text: ""
1070
+ }
1071
+ ],
1072
+ parentId,
1073
+ createdAt: /* @__PURE__ */ new Date()
1074
+ });
1075
+ return optimisticId;
1076
+ }
1077
+ getBranches(messageId) {
1078
+ const message = this.messages.get(messageId);
1079
+ if (!message)
1080
+ throw new Error("Unexpected: Message not found");
1081
+ if (message.prev) {
1082
+ return message.prev.children;
1083
+ }
1084
+ return this.rootChildren;
1085
+ }
1086
+ switchToBranch(messageId) {
1087
+ const message = this.messages.get(messageId);
1088
+ if (!message)
1089
+ throw new Error("Unexpected: Branch not found");
1090
+ if (message.prev) {
1091
+ message.prev.next = message;
1092
+ }
1093
+ this.head = findHead(message);
1094
+ }
1095
+ resetHead(messageId) {
1096
+ if (messageId) {
1097
+ const message = this.messages.get(messageId);
1098
+ if (!message)
1099
+ throw new Error("Unexpected: Branch not found");
1100
+ this.head = message;
1101
+ for (let current = message; current; current = current.prev) {
1102
+ if (current.prev) {
1103
+ current.prev.next = current;
1104
+ }
1105
+ }
1106
+ } else {
1107
+ this.head = null;
1108
+ }
1109
+ }
1110
+ };
1111
+
1112
+ // src/adapters/vercel/useVercelAIBranches.tsx
1113
+ var sliceMessagesUntil = (messages, messageId) => {
1114
+ if (messageId == null)
1115
+ return [];
1116
+ if (isOptimisticId(messageId))
1117
+ return messages;
1118
+ const messageIdx = messages.findIndex((m) => m.id === messageId);
1119
+ if (messageIdx === -1)
1120
+ throw new Error("Unexpected: Message not found");
1121
+ return messages.slice(0, messageIdx + 1);
1122
+ };
1123
+ var hasUpcomingMessage = (isRunning, messages) => {
1124
+ return isRunning && messages[messages.length - 1]?.role !== "assistant";
1125
+ };
1126
+ var useVercelAIBranches = (chat, messages) => {
1127
+ const [data] = useState3(() => new MessageRepository());
1128
+ const isRunning = "isLoading" in chat ? chat.isLoading : chat.status === "in_progress";
1129
+ const assistantOptimisticIdRef = useRef6(null);
1130
+ const messagesEx = useMemo3(() => {
1131
+ for (const message of messages) {
1132
+ data.addOrUpdateMessage(message);
1133
+ }
1134
+ if (assistantOptimisticIdRef.current) {
1135
+ data.deleteMessage(assistantOptimisticIdRef.current);
1136
+ assistantOptimisticIdRef.current = null;
1137
+ }
1138
+ if (hasUpcomingMessage(isRunning, messages)) {
1139
+ assistantOptimisticIdRef.current = data.commitOptimisticRun(
1140
+ messages.at(-1)?.id ?? null
1141
+ );
1142
+ }
1143
+ data.resetHead(
1144
+ assistantOptimisticIdRef.current ?? messages.at(-1)?.id ?? null
1145
+ );
1146
+ return data.getMessages();
1147
+ }, [data, isRunning, messages]);
1148
+ const getBranches = useCallback2(
1149
+ (messageId) => {
1150
+ return data.getBranches(messageId);
1151
+ },
1152
+ [data]
1153
+ );
1154
+ const switchToBranch = useCallback2(
1155
+ (messageId) => {
1156
+ data.switchToBranch(messageId);
1157
+ chat.setMessages(
1158
+ data.getMessages().filter((m) => !isOptimisticId(m.id)).map((m) => m.innerMessage)
1159
+ );
1160
+ },
1161
+ [data, chat.setMessages]
1162
+ );
1163
+ const reloadMaybe = "reload" in chat ? chat.reload : void 0;
1164
+ const startRun = useCallback2(
1165
+ async (parentId) => {
1166
+ if (!reloadMaybe)
1167
+ throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
1168
+ const newMessages = sliceMessagesUntil(chat.messages, parentId);
1169
+ chat.setMessages(newMessages);
1170
+ await reloadMaybe();
1171
+ },
1172
+ [chat.messages, chat.setMessages, reloadMaybe]
1173
+ );
1174
+ const append = useCallback2(
1175
+ async (message) => {
1176
+ if (message.content.length !== 1 || message.content[0]?.type !== "text")
1177
+ throw new Error("Only text content is supported by Vercel AI SDK");
1178
+ const newMessages = sliceMessagesUntil(chat.messages, message.parentId);
1179
+ chat.setMessages(newMessages);
1180
+ await chat.append({
1181
+ role: "user",
1182
+ content: message.content[0].text
1183
+ });
1184
+ },
1185
+ [chat.messages, chat.setMessages, chat.append]
1186
+ );
1187
+ return useMemo3(
1188
+ () => ({
1189
+ messages: messagesEx,
1190
+ getBranches,
1191
+ switchToBranch,
1192
+ append,
1193
+ startRun
1194
+ }),
1195
+ [messagesEx, getBranches, switchToBranch, append, startRun]
1196
+ );
1197
+ };
1198
+
1075
1199
  // src/adapters/vercel/VercelAIAssistantProvider.tsx
1200
+ import { jsx as jsx18 } from "react/jsx-runtime";
1076
1201
  var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
1077
- var vercelToThreadMessage = (message, parentId, branchId, branchCount) => {
1202
+ var vercelToThreadMessage = (message, parentId) => {
1078
1203
  if (message.role !== "user" && message.role !== "assistant")
1079
1204
  throw new Error("Unsupported role");
1080
1205
  return {
@@ -1082,24 +1207,17 @@ var vercelToThreadMessage = (message, parentId, branchId, branchCount) => {
1082
1207
  id: message.id,
1083
1208
  role: message.role,
1084
1209
  content: [{ type: "text", text: message.content }],
1085
- branchId,
1086
- branchCount,
1087
- createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
1210
+ createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
1211
+ innerMessage: message
1088
1212
  };
1089
1213
  };
1090
- var vercelToCachedThreadMessages = (messages, getBranchState) => {
1214
+ var vercelToCachedThreadMessages = (messages) => {
1091
1215
  return messages.map((m, idx) => {
1092
1216
  const cached = ThreadMessageCache.get(m);
1093
- const parentId = messages[idx - 1]?.id ?? ROOT_PARENT_ID;
1094
- const { branchId, branchCount } = getBranchState(m.id);
1095
- if (cached && cached.parentId === parentId && cached.branchId === branchId && cached.branchCount === branchCount)
1217
+ const parentId = messages[idx - 1]?.id ?? null;
1218
+ if (cached && cached.parentId === parentId)
1096
1219
  return cached;
1097
- const newMessage = vercelToThreadMessage(
1098
- m,
1099
- parentId,
1100
- branchId,
1101
- branchCount
1102
- );
1220
+ const newMessage = vercelToThreadMessage(m, parentId);
1103
1221
  ThreadMessageCache.set(m, newMessage);
1104
1222
  return newMessage;
1105
1223
  });
@@ -1110,13 +1228,10 @@ var VercelAIAssistantProvider = ({
1110
1228
  }) => {
1111
1229
  const context = useDummyAIAssistantContext();
1112
1230
  const vercel = "chat" in rest ? rest.chat : rest.assistant;
1113
- const branches = useVercelAIBranches(vercel, context);
1114
1231
  const messages = useMemo4(() => {
1115
- return vercelToCachedThreadMessages(
1116
- vercel.messages,
1117
- branches.getBranchState
1118
- );
1119
- }, [vercel.messages, branches.getBranchState]);
1232
+ return vercelToCachedThreadMessages(vercel.messages);
1233
+ }, [vercel.messages]);
1234
+ const branches = useVercelAIBranches(vercel, messages);
1120
1235
  const cancelRun = useCallback3(() => {
1121
1236
  const lastMessage = vercel.messages.at(-1);
1122
1237
  vercel.stop();
@@ -1126,23 +1241,26 @@ var VercelAIAssistantProvider = ({
1126
1241
  }, [vercel.messages, vercel.stop, vercel.setInput]);
1127
1242
  const isRunning = "isLoading" in vercel ? vercel.isLoading : vercel.status === "in_progress";
1128
1243
  useMemo4(() => {
1129
- context.useThread.setState({
1130
- messages,
1131
- isRunning,
1132
- cancelRun,
1133
- switchToBranch: branches.switchToBranch,
1134
- append: branches.append,
1135
- startRun: branches.startRun
1136
- });
1137
- }, [context, messages, isRunning, cancelRun, branches]);
1244
+ context.useThread.setState(
1245
+ {
1246
+ messages: branches.messages,
1247
+ isRunning,
1248
+ getBranches: branches.getBranches,
1249
+ switchToBranch: branches.switchToBranch,
1250
+ append: branches.append,
1251
+ startRun: branches.startRun,
1252
+ cancelRun
1253
+ },
1254
+ true
1255
+ );
1256
+ }, [context, isRunning, cancelRun, branches]);
1138
1257
  useMemo4(() => {
1139
1258
  context.useComposer.setState({
1140
- canCancel: isRunning,
1141
1259
  value: vercel.input,
1142
1260
  setValue: vercel.setInput
1143
1261
  });
1144
- }, [context, isRunning, vercel.input, vercel.setInput]);
1145
- return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
1262
+ }, [context, vercel.input, vercel.setInput]);
1263
+ return /* @__PURE__ */ jsx18(AssistantContext.Provider, { value: context, children });
1146
1264
  };
1147
1265
 
1148
1266
  // src/adapters/vercel/VercelRSCAssistantProvider.tsx
@@ -1150,6 +1268,7 @@ import {
1150
1268
  useCallback as useCallback4,
1151
1269
  useMemo as useMemo5
1152
1270
  } from "react";
1271
+ import { jsx as jsx19 } from "react/jsx-runtime";
1153
1272
  var ThreadMessageCache2 = /* @__PURE__ */ new WeakMap();
1154
1273
  var vercelToThreadMessage2 = (parentId, message) => {
1155
1274
  if (message.role !== "user" && message.role !== "assistant")
@@ -1159,15 +1278,13 @@ var vercelToThreadMessage2 = (parentId, message) => {
1159
1278
  id: message.id,
1160
1279
  role: message.role,
1161
1280
  content: [{ type: "ui", display: message.display }],
1162
- createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
1163
- branchId: 0,
1164
- branchCount: 1
1281
+ createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
1165
1282
  };
1166
1283
  };
1167
1284
  var vercelToCachedThreadMessages2 = (messages) => {
1168
1285
  return messages.map((m, idx) => {
1169
1286
  const cached = ThreadMessageCache2.get(m);
1170
- const parentId = messages[idx - 1]?.id ?? ROOT_PARENT_ID;
1287
+ const parentId = messages[idx - 1]?.id ?? null;
1171
1288
  if (cached && cached.parentId === parentId)
1172
1289
  return cached;
1173
1290
  const newMessage = vercelToThreadMessage2(parentId, m);
@@ -1186,12 +1303,11 @@ var VercelRSCAssistantProvider = ({
1186
1303
  }, [vercelMessages]);
1187
1304
  const append = useCallback4(
1188
1305
  async (message) => {
1189
- if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? ROOT_PARENT_ID))
1306
+ if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null))
1190
1307
  throw new Error("Unexpected: Message editing is not supported");
1191
1308
  if (message.content[0]?.type !== "text") {
1192
1309
  throw new Error("Only text content is currently supported");
1193
1310
  }
1194
- context.useViewport.getState().scrollToBottom();
1195
1311
  await vercelAppend(message);
1196
1312
  },
1197
1313
  [context, vercelAppend]
@@ -1202,7 +1318,7 @@ var VercelRSCAssistantProvider = ({
1202
1318
  append
1203
1319
  });
1204
1320
  }, [context, messages, append]);
1205
- return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
1321
+ return /* @__PURE__ */ jsx19(AssistantContext.Provider, { value: context, children });
1206
1322
  };
1207
1323
  export {
1208
1324
  actionBar_exports as ActionBarPrimitive,