@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.js CHANGED
@@ -58,11 +58,12 @@ __export(thread_exports, {
58
58
  });
59
59
 
60
60
  // src/primitives/thread/ThreadRoot.tsx
61
- var import_react = require("react");
62
61
  var import_react_primitive = require("@radix-ui/react-primitive");
62
+ var import_react = require("react");
63
+ var import_jsx_runtime = require("react/jsx-runtime");
63
64
  var ThreadRoot = (0, import_react.forwardRef)(
64
65
  (props, ref) => {
65
- return /* @__PURE__ */ React.createElement(import_react_primitive.Primitive.div, { ...props, ref });
66
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { ...props, ref });
66
67
  }
67
68
  );
68
69
 
@@ -99,8 +100,9 @@ var ThreadIf = ({ children, ...query }) => {
99
100
  };
100
101
 
101
102
  // src/primitives/thread/ThreadEmpty.tsx
103
+ var import_jsx_runtime2 = require("react/jsx-runtime");
102
104
  var ThreadEmpty = ({ children }) => {
103
- return /* @__PURE__ */ React.createElement(ThreadIf, { empty: true }, children);
105
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThreadIf, { empty: true, children });
104
106
  };
105
107
 
106
108
  // src/primitives/thread/ThreadViewport.tsx
@@ -162,6 +164,7 @@ var useOnScrollToBottom = (callback) => {
162
164
  };
163
165
 
164
166
  // src/primitives/thread/ThreadViewport.tsx
167
+ var import_jsx_runtime3 = require("react/jsx-runtime");
165
168
  var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
166
169
  const messagesEndRef = (0, import_react5.useRef)(null);
167
170
  const divRef = (0, import_react5.useRef)(null);
@@ -198,165 +201,28 @@ var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScrol
198
201
  }
199
202
  lastScrollTop.current = div.scrollTop;
200
203
  };
201
- return /* @__PURE__ */ React.createElement(
204
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
202
205
  import_react_primitive2.Primitive.div,
203
206
  {
204
207
  ...rest,
205
208
  onScroll: (0, import_primitive.composeEventHandlers)(onScroll, handleScroll),
206
- ref
207
- },
208
- children,
209
- /* @__PURE__ */ React.createElement("div", { ref: messagesEndRef })
210
- );
211
- });
212
-
213
- // src/adapters/vercel/useVercelAIBranches.tsx
214
- var import_react6 = require("react");
215
-
216
- // src/utils/context/stores/AssistantTypes.ts
217
- var ROOT_PARENT_ID = "__ROOT_ID__";
218
-
219
- // src/adapters/vercel/useVercelAIBranches.tsx
220
- var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
221
- var updateBranchData = (data, messages) => {
222
- for (let i = 0; i < messages.length; i++) {
223
- const child = messages[i];
224
- const childId = child.id;
225
- const parentId = messages[i - 1]?.id ?? ROOT_PARENT_ID;
226
- data.parentMap.set(childId, parentId);
227
- const parentArray = data.branchMap.get(parentId);
228
- if (!parentArray) {
229
- data.branchMap.set(parentId, [childId]);
230
- } else if (!parentArray.includes(childId)) {
231
- parentArray.push(childId);
209
+ ref,
210
+ children: [
211
+ children,
212
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: messagesEndRef })
213
+ ]
232
214
  }
233
- data.snapshots.set(childId, messages);
234
- }
235
- };
236
- var getParentId = (data, messages, messageId) => {
237
- if (messageId === UPCOMING_MESSAGE_ID) {
238
- const parent = messages.at(-1);
239
- if (!parent)
240
- return ROOT_PARENT_ID;
241
- return parent.id;
242
- }
243
- const parentId = data.parentMap.get(messageId);
244
- if (!parentId)
245
- throw new Error("Unexpected: Message parent not found");
246
- return parentId;
247
- };
248
- var getBranchStateImpl = (data, messages, messageId) => {
249
- const parentId = getParentId(data, messages, messageId);
250
- const branches = data.branchMap.get(parentId) ?? [];
251
- const branchId = messageId === UPCOMING_MESSAGE_ID ? branches.length : branches.indexOf(messageId);
252
- if (branchId === -1)
253
- throw new Error("Unexpected: Message not found in parent children");
254
- const upcomingOffset = messageId === UPCOMING_MESSAGE_ID ? 1 : 0;
255
- return {
256
- branchId,
257
- branchCount: branches.length + upcomingOffset
258
- };
259
- };
260
- var switchToBranchImpl = (data, messages, messageId, branchId) => {
261
- const parentId = getParentId(data, messages, messageId);
262
- const branches = data.branchMap.get(parentId);
263
- if (!branches)
264
- throw new Error("Unexpected: Parent children not found");
265
- const newMessageId = branches[branchId];
266
- if (!newMessageId)
267
- throw new Error("Unexpected: Requested branch not found");
268
- if (branchId < 0 || branchId >= branches.length)
269
- throw new Error("Switch to branch called with a branch index out of range");
270
- if (newMessageId === messageId)
271
- return messages;
272
- const snapshot = data.snapshots.get(newMessageId);
273
- if (!snapshot)
274
- throw new Error("Unexpected: Branch snapshot not found");
275
- return snapshot;
276
- };
277
- var sliceMessagesUntil = (messages, messageId) => {
278
- if (messageId === ROOT_PARENT_ID)
279
- return [];
280
- if (messageId === UPCOMING_MESSAGE_ID)
281
- return messages;
282
- const messageIdx = messages.findIndex((m) => m.id === messageId);
283
- if (messageIdx === -1)
284
- throw new Error("Unexpected: Message not found");
285
- return messages.slice(0, messageIdx + 1);
286
- };
287
- var useVercelAIBranches = (chat, context) => {
288
- const data = (0, import_react6.useRef)({
289
- parentMap: /* @__PURE__ */ new Map(),
290
- branchMap: /* @__PURE__ */ new Map(),
291
- snapshots: /* @__PURE__ */ new Map()
292
- }).current;
293
- updateBranchData(data, chat.messages);
294
- const getBranchState = (0, import_react6.useCallback)(
295
- (messageId) => {
296
- return getBranchStateImpl(data, chat.messages, messageId);
297
- },
298
- [data, chat.messages]
299
215
  );
300
- const switchToBranch = (0, import_react6.useCallback)(
301
- (messageId, branchId) => {
302
- const newMessages = switchToBranchImpl(
303
- data,
304
- chat.messages,
305
- messageId,
306
- branchId
307
- );
308
- chat.setMessages(newMessages);
309
- },
310
- [data, chat.messages, chat.setMessages]
311
- );
312
- const reloadMaybe = "reload" in chat ? chat.reload : void 0;
313
- const startRun = (0, import_react6.useCallback)(
314
- async (parentId) => {
315
- if (!reloadMaybe)
316
- throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
317
- const newMessages = sliceMessagesUntil(chat.messages, parentId);
318
- chat.setMessages(newMessages);
319
- context.useViewport.getState().scrollToBottom();
320
- await reloadMaybe();
321
- },
322
- [context, chat.messages, chat.setMessages, reloadMaybe]
323
- );
324
- const append = (0, import_react6.useCallback)(
325
- async (message) => {
326
- const newMessages = sliceMessagesUntil(chat.messages, message.parentId);
327
- chat.setMessages(newMessages);
328
- if (message.content.length !== 1 || message.content[0]?.type !== "text")
329
- throw new Error("Only text content is currently supported");
330
- context.useViewport.getState().scrollToBottom();
331
- await chat.append({
332
- role: "user",
333
- content: message.content[0].text
334
- });
335
- },
336
- [context, chat.messages, chat.setMessages, chat.append]
337
- );
338
- return (0, import_react6.useMemo)(
339
- () => ({
340
- getBranchState,
341
- switchToBranch,
342
- append,
343
- startRun
344
- }),
345
- [getBranchState, switchToBranch, append, startRun]
346
- );
347
- };
348
- var hasUpcomingMessage = (thread) => {
349
- return thread.isRunning && thread.messages[thread.messages.length - 1]?.role !== "assistant";
350
- };
216
+ });
351
217
 
352
218
  // src/utils/context/useComposerContext.ts
353
- var import_react8 = require("react");
219
+ var import_react7 = require("react");
354
220
 
355
221
  // src/utils/context/useMessageContext.ts
356
- var import_react7 = require("react");
357
- var MessageContext = (0, import_react7.createContext)(null);
222
+ var import_react6 = require("react");
223
+ var MessageContext = (0, import_react6.createContext)(null);
358
224
  var useMessageContext = () => {
359
- const context = (0, import_react7.useContext)(MessageContext);
225
+ const context = (0, import_react6.useContext)(MessageContext);
360
226
  if (!context)
361
227
  throw new Error("useMessageContext must be used within a MessageProvider");
362
228
  return context;
@@ -365,7 +231,7 @@ var useMessageContext = () => {
365
231
  // src/utils/context/useComposerContext.ts
366
232
  var useComposerContext = () => {
367
233
  const { useComposer: useAssisstantComposer } = useAssistantContext();
368
- const { useComposer: useMessageComposer } = (0, import_react8.useContext)(MessageContext) ?? {};
234
+ const { useComposer: useMessageComposer } = (0, import_react7.useContext)(MessageContext) ?? {};
369
235
  return {
370
236
  useComposer: useMessageComposer ?? useAssisstantComposer,
371
237
  type: useMessageComposer ? "message" : "assistant"
@@ -398,7 +264,7 @@ __export(message_exports, {
398
264
  });
399
265
 
400
266
  // src/primitives/message/MessageProvider.tsx
401
- var import_react9 = require("react");
267
+ var import_react8 = require("react");
402
268
  var import_zustand2 = require("zustand");
403
269
 
404
270
  // src/utils/context/stores/ComposerStore.ts
@@ -414,7 +280,6 @@ var makeMessageComposerStore = ({
414
280
  onSend
415
281
  }) => (0, import_zustand.create)()((set, get, store) => ({
416
282
  ...makeBaseComposer(set, get, store),
417
- canCancel: true,
418
283
  isEditing: false,
419
284
  edit: () => {
420
285
  const value = onEdit();
@@ -423,39 +288,48 @@ var makeMessageComposerStore = ({
423
288
  send: () => {
424
289
  const value = get().value;
425
290
  set({ isEditing: false });
426
- return onSend(value);
291
+ onSend(value);
427
292
  },
428
293
  cancel: () => {
294
+ if (!get().isEditing)
295
+ return false;
429
296
  set({ isEditing: false });
297
+ return true;
430
298
  }
431
299
  }));
432
- var makeThreadComposerStore = ({
433
- onSend,
434
- onCancel
435
- }) => (0, import_zustand.create)()((set, get, store) => ({
436
- ...makeBaseComposer(set, get, store),
437
- isEditing: true,
438
- canCancel: false,
439
- send: () => {
440
- const value = get().value;
441
- set({ value: "", canCancel: true });
442
- onSend(value).then(() => {
443
- set({ canCancel: false });
444
- });
445
- },
446
- cancel: onCancel
447
- }));
300
+ var makeThreadComposerStore = (useThread) => (0, import_zustand.create)()((set, get, store) => {
301
+ return {
302
+ ...makeBaseComposer(set, get, store),
303
+ isEditing: true,
304
+ send: () => {
305
+ const { value } = get();
306
+ set({ value: "" });
307
+ useThread.getState().append({
308
+ parentId: useThread.getState().messages.at(-1)?.id ?? null,
309
+ content: [{ type: "text", text: value }]
310
+ });
311
+ },
312
+ cancel: () => {
313
+ const thread = useThread.getState();
314
+ if (!thread.isRunning)
315
+ return false;
316
+ useThread.getState().cancelRun();
317
+ return true;
318
+ }
319
+ };
320
+ });
448
321
 
449
322
  // src/primitives/message/MessageProvider.tsx
323
+ var import_jsx_runtime4 = require("react/jsx-runtime");
450
324
  var getIsLast = (thread, message) => {
451
- const hasUpcoming = hasUpcomingMessage(thread);
452
- return hasUpcoming ? message.id === UPCOMING_MESSAGE_ID : thread.messages[thread.messages.length - 1]?.id === message.id;
325
+ return thread.messages[thread.messages.length - 1]?.id === message.id;
453
326
  };
454
327
  var useMessageContext2 = () => {
455
- const [context] = (0, import_react9.useState)(() => {
456
- const { useThread } = useAssistantContext();
328
+ const { useThread } = useAssistantContext();
329
+ const [context] = (0, import_react8.useState)(() => {
457
330
  const useMessage = (0, import_zustand2.create)(() => ({
458
331
  message: null,
332
+ branches: [],
459
333
  isLast: false,
460
334
  isCopied: false,
461
335
  isHovering: false,
@@ -475,7 +349,7 @@ var useMessageContext2 = () => {
475
349
  },
476
350
  onSend: (text) => {
477
351
  const message = useMessage.getState().message;
478
- return useThread.getState().append({
352
+ useThread.getState().append({
479
353
  parentId: message.parentId,
480
354
  content: [{ type: "text", text }]
481
355
  });
@@ -492,12 +366,14 @@ var MessageProvider = ({
492
366
  const { useThread } = useAssistantContext();
493
367
  const context = useMessageContext2();
494
368
  const isLast = useThread((thread) => getIsLast(thread, message));
495
- const [isCopied, setIsCopied] = (0, import_react9.useState)(false);
496
- const [isHovering, setIsHovering] = (0, import_react9.useState)(false);
497
- (0, import_react9.useMemo)(() => {
369
+ const branches = useThread((thread) => thread.getBranches(message.id));
370
+ const [isCopied, setIsCopied] = (0, import_react8.useState)(false);
371
+ const [isHovering, setIsHovering] = (0, import_react8.useState)(false);
372
+ (0, import_react8.useMemo)(() => {
498
373
  context.useMessage.setState(
499
374
  {
500
375
  message,
376
+ branches,
501
377
  isLast,
502
378
  isCopied,
503
379
  isHovering,
@@ -506,15 +382,16 @@ var MessageProvider = ({
506
382
  },
507
383
  true
508
384
  );
509
- }, [context, message, isLast, isCopied, isHovering]);
510
- return /* @__PURE__ */ React.createElement(MessageContext.Provider, { value: context }, children);
385
+ }, [context, message, branches, isLast, isCopied, isHovering]);
386
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageContext.Provider, { value: context, children });
511
387
  };
512
388
 
513
389
  // src/primitives/message/MessageRoot.tsx
514
390
  var import_primitive2 = require("@radix-ui/primitive");
515
391
  var import_react_primitive3 = require("@radix-ui/react-primitive");
516
- var import_react10 = require("react");
517
- var MessageRoot = (0, import_react10.forwardRef)(
392
+ var import_react9 = require("react");
393
+ var import_jsx_runtime5 = require("react/jsx-runtime");
394
+ var MessageRoot = (0, import_react9.forwardRef)(
518
395
  ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
519
396
  const { useMessage } = useMessageContext();
520
397
  const setIsHovering = useMessage((s) => s.setIsHovering);
@@ -524,7 +401,7 @@ var MessageRoot = (0, import_react10.forwardRef)(
524
401
  const handleMouseLeave = () => {
525
402
  setIsHovering(false);
526
403
  };
527
- return /* @__PURE__ */ React.createElement(
404
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
528
405
  import_react_primitive3.Primitive.div,
529
406
  {
530
407
  ...rest,
@@ -539,8 +416,8 @@ var MessageRoot = (0, import_react10.forwardRef)(
539
416
  // src/primitives/message/MessageIf.tsx
540
417
  var useMessageIf = (props) => {
541
418
  const { useMessage } = useMessageContext();
542
- return useMessage(({ message, isLast, isCopied, isHovering }) => {
543
- if (props.hasBranches === true && message.branchCount < 2)
419
+ return useMessage(({ message, branches, isLast, isCopied, isHovering }) => {
420
+ if (props.hasBranches === true && branches.length < 2)
544
421
  return false;
545
422
  if (props.user && message.role !== "user")
546
423
  return false;
@@ -561,8 +438,9 @@ var MessageIf = ({ children, ...query }) => {
561
438
  };
562
439
 
563
440
  // src/primitives/message/MessageContent.tsx
441
+ var import_jsx_runtime6 = require("react/jsx-runtime");
564
442
  var defaultComponents = {
565
- Text: ({ part }) => /* @__PURE__ */ React.createElement(React.Fragment, null, part.text),
443
+ Text: ({ part }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: part.text }),
566
444
  Image: () => null,
567
445
  UI: ({ part }) => part.display,
568
446
  tools: {
@@ -579,26 +457,27 @@ var MessageContent = ({
579
457
  }) => {
580
458
  const { useMessage } = useMessageContext();
581
459
  const content = useMessage((s) => s.message.content);
582
- return /* @__PURE__ */ React.createElement(React.Fragment, null, content.map((part, i) => {
460
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: content.map((part, i) => {
583
461
  const key = i;
584
462
  switch (part.type) {
585
463
  case "text":
586
- return /* @__PURE__ */ React.createElement(Text, { key, part });
464
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { part }, key);
587
465
  case "image":
588
- return /* @__PURE__ */ React.createElement(Image, { key, part });
466
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Image, { part }, key);
589
467
  case "ui":
590
- return /* @__PURE__ */ React.createElement(UI, { key, part });
468
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(UI, { part }, key);
591
469
  case "tool-call": {
592
470
  const Tool = by_name[part.name] || Fallback;
593
- return /* @__PURE__ */ React.createElement(Tool, { key, part });
471
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Tool, { part }, key);
594
472
  }
595
473
  default:
596
474
  return null;
597
475
  }
598
- }));
476
+ }) });
599
477
  };
600
478
 
601
479
  // src/primitives/thread/ThreadMessages.tsx
480
+ var import_jsx_runtime7 = require("react/jsx-runtime");
602
481
  var getComponents = (components) => {
603
482
  return {
604
483
  EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
@@ -613,40 +492,32 @@ var ThreadMessages = ({ components }) => {
613
492
  const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
614
493
  if (messages.length === 0)
615
494
  return null;
616
- return /* @__PURE__ */ React.createElement(React.Fragment, null, messages.map((message, idx) => {
495
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: messages.map((message, idx) => {
617
496
  return (
618
497
  // biome-ignore lint/suspicious/noArrayIndexKey: fixes a11y issues with branch navigation
619
- /* @__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)))
498
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(MessageProvider, { message, children: [
499
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(MessageIf, { user: true, children: [
500
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ComposerIf, { editing: false, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(UserMessage, {}) }),
501
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ComposerIf, { editing: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(EditComposer, {}) })
502
+ ] }),
503
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessageIf, { assistant: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AssistantMessage, {}) })
504
+ ] }, idx)
620
505
  );
621
- }), hasUpcomingMessage(thread) && /* @__PURE__ */ React.createElement(
622
- MessageProvider,
623
- {
624
- message: {
625
- id: UPCOMING_MESSAGE_ID,
626
- role: "assistant",
627
- content: [{ type: "text", text: "..." }],
628
- parentId: messages.at(-1)?.id ?? ROOT_PARENT_ID,
629
- // TODO fix these (move upcoming message to AssistantContext)
630
- branchId: 0,
631
- branchCount: 1,
632
- createdAt: /* @__PURE__ */ new Date()
633
- }
634
- },
635
- /* @__PURE__ */ React.createElement(AssistantMessage, null)
636
- ));
506
+ }) });
637
507
  };
638
508
 
639
509
  // src/primitives/thread/ThreadScrollToBottom.tsx
640
510
  var import_primitive3 = require("@radix-ui/primitive");
641
511
  var import_react_primitive4 = require("@radix-ui/react-primitive");
642
- var import_react11 = require("react");
643
- var ThreadScrollToBottom = (0, import_react11.forwardRef)(({ onClick, ...rest }, ref) => {
512
+ var import_react10 = require("react");
513
+ var import_jsx_runtime8 = require("react/jsx-runtime");
514
+ var ThreadScrollToBottom = (0, import_react10.forwardRef)(({ onClick, ...rest }, ref) => {
644
515
  const { useViewport } = useAssistantContext();
645
516
  const isAtBottom = useViewport((s) => s.isAtBottom);
646
517
  const handleScrollToBottom = () => {
647
518
  useViewport.getState().scrollToBottom();
648
519
  };
649
- return /* @__PURE__ */ React.createElement(
520
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
650
521
  import_react_primitive4.Primitive.button,
651
522
  {
652
523
  ...rest,
@@ -671,11 +542,13 @@ __export(composer_exports, {
671
542
  var import_primitive4 = require("@radix-ui/primitive");
672
543
  var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
673
544
  var import_react_primitive5 = require("@radix-ui/react-primitive");
674
- var import_react12 = require("react");
675
- var ComposerRoot = (0, import_react12.forwardRef)(
545
+ var import_react11 = require("react");
546
+ var import_jsx_runtime9 = require("react/jsx-runtime");
547
+ var ComposerRoot = (0, import_react11.forwardRef)(
676
548
  ({ onSubmit, ...rest }, forwardedRef) => {
549
+ const { useViewport } = useAssistantContext();
677
550
  const { useComposer } = useComposerContext();
678
- const formRef = (0, import_react12.useRef)(null);
551
+ const formRef = (0, import_react11.useRef)(null);
679
552
  const ref = (0, import_react_compose_refs2.useComposedRefs)(forwardedRef, formRef);
680
553
  const handleSubmit = (e) => {
681
554
  const composerState = useComposer.getState();
@@ -683,8 +556,9 @@ var ComposerRoot = (0, import_react12.forwardRef)(
683
556
  return;
684
557
  e.preventDefault();
685
558
  composerState.send();
559
+ useViewport.getState().scrollToBottom();
686
560
  };
687
- return /* @__PURE__ */ React.createElement(
561
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
688
562
  import_react_primitive5.Primitive.form,
689
563
  {
690
564
  ...rest,
@@ -699,11 +573,12 @@ var ComposerRoot = (0, import_react12.forwardRef)(
699
573
  var import_primitive5 = require("@radix-ui/primitive");
700
574
  var import_react_compose_refs3 = require("@radix-ui/react-compose-refs");
701
575
  var import_react_slot = require("@radix-ui/react-slot");
702
- var import_react13 = require("react");
576
+ var import_react12 = require("react");
703
577
  var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
704
- var ComposerInput = (0, import_react13.forwardRef)(
578
+ var import_jsx_runtime10 = require("react/jsx-runtime");
579
+ var ComposerInput = (0, import_react12.forwardRef)(
705
580
  ({ autoFocus, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
706
- const { useThread } = useAssistantContext();
581
+ const { useThread, useViewport } = useAssistantContext();
707
582
  const { useComposer, type } = useComposerContext();
708
583
  const value = useComposer((c) => {
709
584
  if (!c.isEditing)
@@ -715,22 +590,23 @@ var ComposerInput = (0, import_react13.forwardRef)(
715
590
  if (disabled)
716
591
  return;
717
592
  const composer = useComposer.getState();
718
- if (e.key === "Escape" && composer.canCancel) {
719
- e.preventDefault();
720
- useComposer.getState().cancel();
721
- }
722
- if (e.key === "Enter" && e.shiftKey === false) {
593
+ if (e.key === "Escape") {
594
+ if (useComposer.getState().cancel()) {
595
+ e.preventDefault();
596
+ }
597
+ } else if (e.key === "Enter" && e.shiftKey === false) {
723
598
  const isRunning = useThread.getState().isRunning;
724
599
  if (!isRunning) {
725
600
  e.preventDefault();
726
601
  composer.send();
602
+ useViewport.getState().scrollToBottom();
727
603
  }
728
604
  }
729
605
  };
730
- const textareaRef = (0, import_react13.useRef)(null);
606
+ const textareaRef = (0, import_react12.useRef)(null);
731
607
  const ref = (0, import_react_compose_refs3.useComposedRefs)(forwardedRef, textareaRef);
732
608
  const autoFocusEnabled = autoFocus !== false && !disabled;
733
- const focus = (0, import_react13.useCallback)(() => {
609
+ const focus = (0, import_react12.useCallback)(() => {
734
610
  const textarea = textareaRef.current;
735
611
  if (!textarea || !autoFocusEnabled)
736
612
  return;
@@ -740,13 +616,13 @@ var ComposerInput = (0, import_react13.forwardRef)(
740
616
  textareaRef.current.value.length
741
617
  );
742
618
  }, [autoFocusEnabled]);
743
- (0, import_react13.useEffect)(() => focus(), [focus]);
619
+ (0, import_react12.useEffect)(() => focus(), [focus]);
744
620
  useOnScrollToBottom(() => {
745
621
  if (type === "assistant") {
746
622
  focus();
747
623
  }
748
624
  });
749
- return /* @__PURE__ */ React.createElement(
625
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
750
626
  Component,
751
627
  {
752
628
  value,
@@ -767,12 +643,13 @@ var ComposerInput = (0, import_react13.forwardRef)(
767
643
 
768
644
  // src/primitives/composer/ComposerSend.tsx
769
645
  var import_react_primitive6 = require("@radix-ui/react-primitive");
770
- var import_react14 = require("react");
771
- var ComposerSend = (0, import_react14.forwardRef)(
646
+ var import_react13 = require("react");
647
+ var import_jsx_runtime11 = require("react/jsx-runtime");
648
+ var ComposerSend = (0, import_react13.forwardRef)(
772
649
  ({ disabled, ...rest }, ref) => {
773
650
  const { useComposer } = useComposerContext();
774
651
  const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
775
- return /* @__PURE__ */ React.createElement(
652
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
776
653
  import_react_primitive6.Primitive.button,
777
654
  {
778
655
  type: "submit",
@@ -787,21 +664,20 @@ var ComposerSend = (0, import_react14.forwardRef)(
787
664
  // src/primitives/composer/ComposerCancel.tsx
788
665
  var import_primitive6 = require("@radix-ui/primitive");
789
666
  var import_react_primitive7 = require("@radix-ui/react-primitive");
790
- var import_react15 = require("react");
791
- var ComposerCancel = (0, import_react15.forwardRef)(({ disabled, onClick, ...rest }, ref) => {
667
+ var import_react14 = require("react");
668
+ var import_jsx_runtime12 = require("react/jsx-runtime");
669
+ var ComposerCancel = (0, import_react14.forwardRef)(({ onClick, ...rest }, ref) => {
792
670
  const { useComposer } = useComposerContext();
793
- const hasValue = useComposer((c) => c.canCancel);
794
- const handleClose = () => {
671
+ const handleCancel = () => {
795
672
  useComposer.getState().cancel();
796
673
  };
797
- return /* @__PURE__ */ React.createElement(
674
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
798
675
  import_react_primitive7.Primitive.button,
799
676
  {
800
677
  type: "button",
801
678
  ...rest,
802
679
  ref,
803
- onClick: (0, import_primitive6.composeEventHandlers)(onClick, handleClose),
804
- disabled: disabled || !hasValue
680
+ onClick: (0, import_primitive6.composeEventHandlers)(onClick, handleCancel)
805
681
  }
806
682
  );
807
683
  });
@@ -817,10 +693,10 @@ __export(branchPicker_exports, {
817
693
  });
818
694
 
819
695
  // src/utils/context/combined/useCombinedStore.ts
820
- var import_react17 = require("react");
696
+ var import_react16 = require("react");
821
697
 
822
698
  // src/utils/context/combined/createCombinedStore.ts
823
- var import_react16 = require("react");
699
+ var import_react15 = require("react");
824
700
  var createCombinedStore = (stores) => {
825
701
  const subscribe = (callback) => {
826
702
  const unsubscribes = stores.map((store) => store.subscribe(callback));
@@ -832,41 +708,42 @@ var createCombinedStore = (stores) => {
832
708
  };
833
709
  return (selector) => {
834
710
  const getSnapshot = () => selector(...stores.map((store) => store.getState()));
835
- return (0, import_react16.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
711
+ return (0, import_react15.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
836
712
  };
837
713
  };
838
714
 
839
715
  // src/utils/context/combined/useCombinedStore.ts
840
716
  var useCombinedStore = (stores, selector) => {
841
- const useCombined = (0, import_react17.useMemo)(() => createCombinedStore(stores), stores);
717
+ const useCombined = (0, import_react16.useMemo)(() => createCombinedStore(stores), stores);
842
718
  return useCombined(selector);
843
719
  };
844
720
 
845
721
  // src/actions/useGoToNextBranch.tsx
846
722
  var useGoToNextBranch = () => {
847
723
  const { useThread } = useAssistantContext();
848
- const { useComposer, useMessage } = useMessageContext();
724
+ const { useMessage, useComposer } = useMessageContext();
849
725
  const disabled = useCombinedStore(
850
- [useThread, useComposer, useMessage],
851
- (t, c, m) => t.isRunning || c.isEditing || m.message.branchId + 1 >= m.message.branchCount
726
+ [useMessage, useComposer],
727
+ (m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
852
728
  );
853
729
  if (disabled)
854
730
  return null;
855
731
  return () => {
856
- const { message } = useMessage.getState();
857
- useThread.getState().switchToBranch(message.id, message.branchId + 1);
732
+ const { message, branches } = useMessage.getState();
733
+ useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
858
734
  };
859
735
  };
860
736
 
861
737
  // src/utils/createActionButton.tsx
862
- var import_react18 = require("react");
863
- var import_react_primitive8 = require("@radix-ui/react-primitive");
864
738
  var import_primitive7 = require("@radix-ui/primitive");
739
+ var import_react_primitive8 = require("@radix-ui/react-primitive");
740
+ var import_react17 = require("react");
741
+ var import_jsx_runtime13 = require("react/jsx-runtime");
865
742
  var createActionButton = (useActionButton) => {
866
- return (0, import_react18.forwardRef)(
743
+ return (0, import_react17.forwardRef)(
867
744
  (props, forwardedRef) => {
868
745
  const onClick = useActionButton(props);
869
- return /* @__PURE__ */ React.createElement(
746
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
870
747
  import_react_primitive8.Primitive.button,
871
748
  {
872
749
  type: "button",
@@ -886,16 +763,19 @@ var BranchPickerNext = createActionButton(useGoToNextBranch);
886
763
  // src/actions/useGoToPreviousBranch.tsx
887
764
  var useGoToPreviousBranch = () => {
888
765
  const { useThread } = useAssistantContext();
889
- const { useComposer, useMessage } = useMessageContext();
766
+ const { useMessage, useComposer } = useMessageContext();
890
767
  const disabled = useCombinedStore(
891
- [useThread, useComposer, useMessage],
892
- (t, c, m) => t.isRunning || c.isEditing || m.message.branchId <= 0
768
+ [useMessage, useComposer],
769
+ (m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
893
770
  );
894
771
  if (disabled)
895
772
  return null;
896
773
  return () => {
897
- const { message } = useMessage.getState();
898
- useThread.getState().switchToBranch(message.id, message.branchId - 1);
774
+ const { message, branches } = useMessage.getState();
775
+ useThread.getState().switchToBranch(
776
+ branches[branches.indexOf(message.id) - 1]
777
+ // TODO probably there's a more elegant way to do this
778
+ );
899
779
  };
900
780
  };
901
781
 
@@ -903,24 +783,27 @@ var useGoToPreviousBranch = () => {
903
783
  var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
904
784
 
905
785
  // src/primitives/branchPicker/BranchPickerCount.tsx
786
+ var import_jsx_runtime14 = require("react/jsx-runtime");
906
787
  var BranchPickerCount = () => {
907
788
  const { useMessage } = useMessageContext();
908
- const branchCount = useMessage((s) => s.message.branchCount);
909
- return /* @__PURE__ */ React.createElement(React.Fragment, null, branchCount);
789
+ const branchCount = useMessage((s) => s.branches.length);
790
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: branchCount });
910
791
  };
911
792
 
912
793
  // src/primitives/branchPicker/BranchPickerNumber.tsx
794
+ var import_jsx_runtime15 = require("react/jsx-runtime");
913
795
  var BranchPickerNumber = () => {
914
796
  const { useMessage } = useMessageContext();
915
- const branchId = useMessage((s) => s.message.branchId);
916
- return /* @__PURE__ */ React.createElement(React.Fragment, null, branchId + 1);
797
+ const branchIdx = useMessage((s) => s.branches.indexOf(s.message.id));
798
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: branchIdx + 1 });
917
799
  };
918
800
 
919
801
  // src/primitives/branchPicker/BranchPickerRoot.tsx
920
802
  var import_react_primitive9 = require("@radix-ui/react-primitive");
921
- var import_react19 = require("react");
922
- var BranchPickerRoot = (0, import_react19.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
923
- return /* @__PURE__ */ React.createElement(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0 }, /* @__PURE__ */ React.createElement(import_react_primitive9.Primitive.div, { ...rest, ref }));
803
+ var import_react18 = require("react");
804
+ var import_jsx_runtime16 = require("react/jsx-runtime");
805
+ var BranchPickerRoot = (0, import_react18.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
806
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_primitive9.Primitive.div, { ...rest, ref }) });
924
807
  });
925
808
 
926
809
  // src/primitives/actionBar/index.ts
@@ -934,8 +817,9 @@ __export(actionBar_exports, {
934
817
 
935
818
  // src/primitives/actionBar/ActionBarRoot.tsx
936
819
  var import_react_primitive10 = require("@radix-ui/react-primitive");
937
- var import_react20 = require("react");
938
- var ActionBarRoot = (0, import_react20.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
820
+ var import_react19 = require("react");
821
+ var import_jsx_runtime17 = require("react/jsx-runtime");
822
+ var ActionBarRoot = (0, import_react19.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
939
823
  const { useThread } = useAssistantContext();
940
824
  const { useMessage } = useMessageContext();
941
825
  const hideAndfloatStatus = useCombinedStore(
@@ -948,14 +832,14 @@ var ActionBarRoot = (0, import_react20.forwardRef)(({ hideWhenRunning, autohide,
948
832
  return "normal" /* Normal */;
949
833
  if (!m.isHovering)
950
834
  return "hidden" /* Hidden */;
951
- if (autohideFloat === "always" || autohideFloat === "single-branch" && m.message.branchCount <= 1)
835
+ if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
952
836
  return "floating" /* Floating */;
953
837
  return "normal" /* Normal */;
954
838
  }
955
839
  );
956
840
  if (hideAndfloatStatus === "hidden" /* Hidden */)
957
841
  return null;
958
- return /* @__PURE__ */ React.createElement(
842
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
959
843
  import_react_primitive10.Primitive.div,
960
844
  {
961
845
  "data-floating": hideAndfloatStatus === "floating" /* Floating */,
@@ -986,7 +870,7 @@ var ActionBarCopy = createActionButton(useCopyMessage);
986
870
 
987
871
  // src/actions/useReloadMessage.tsx
988
872
  var useReloadMessage = () => {
989
- const { useThread } = useAssistantContext();
873
+ const { useThread, useViewport } = useAssistantContext();
990
874
  const { useMessage } = useMessageContext();
991
875
  const disabled = useCombinedStore(
992
876
  [useThread, useMessage],
@@ -999,6 +883,7 @@ var useReloadMessage = () => {
999
883
  if (message.role !== "assistant")
1000
884
  throw new Error("Reloading is only supported on assistant messages");
1001
885
  useThread.getState().startRun(message.parentId);
886
+ useViewport.getState().scrollToBottom();
1002
887
  };
1003
888
  };
1004
889
 
@@ -1027,7 +912,7 @@ var ActionBarEdit = createActionButton(useBeginMessageEdit);
1027
912
  var import_react22 = require("react");
1028
913
 
1029
914
  // src/adapters/vercel/useDummyAIAssistantContext.tsx
1030
- var import_react21 = require("react");
915
+ var import_react20 = require("react");
1031
916
  var import_zustand4 = require("zustand");
1032
917
 
1033
918
  // src/utils/context/stores/ViewportStore.tsx
@@ -1051,45 +936,285 @@ var makeViewportStore = () => {
1051
936
  };
1052
937
 
1053
938
  // src/adapters/vercel/useDummyAIAssistantContext.tsx
939
+ var makeDummyThreadStore = () => {
940
+ return (0, import_zustand4.create)(() => ({
941
+ messages: [],
942
+ isRunning: false,
943
+ getBranches: () => {
944
+ return [];
945
+ },
946
+ switchToBranch: () => {
947
+ throw new Error("Not implemented");
948
+ },
949
+ append: async () => {
950
+ throw new Error("Not implemented");
951
+ },
952
+ cancelRun: () => {
953
+ throw new Error("Not implemented");
954
+ },
955
+ startRun: async () => {
956
+ throw new Error("Not implemented");
957
+ }
958
+ }));
959
+ };
1054
960
  var useDummyAIAssistantContext = () => {
1055
- const [context] = (0, import_react21.useState)(() => {
1056
- const useThread = (0, import_zustand4.create)()(() => ({
1057
- id: "",
1058
- messages: [],
1059
- isRunning: false,
1060
- append: async () => {
1061
- throw new Error("Not implemented");
1062
- },
1063
- cancelRun: () => {
1064
- throw new Error("Not implemented");
1065
- },
1066
- switchToBranch: () => {
1067
- throw new Error("Not implemented");
1068
- },
1069
- startRun: async () => {
1070
- throw new Error("Not implemented");
1071
- }
1072
- }));
961
+ const [context] = (0, import_react20.useState)(() => {
962
+ const useThread = makeDummyThreadStore();
1073
963
  const useViewport = makeViewportStore();
1074
- const useComposer = makeThreadComposerStore({
1075
- onSend: async (text) => {
1076
- await useThread.getState().append({
1077
- parentId: useThread.getState().messages.at(-1)?.id ?? ROOT_PARENT_ID,
1078
- content: [{ type: "text", text }]
1079
- });
1080
- },
1081
- onCancel: () => {
1082
- useThread.getState().cancelRun();
1083
- }
1084
- });
964
+ const useComposer = makeThreadComposerStore(useThread);
1085
965
  return { useThread, useViewport, useComposer };
1086
966
  });
1087
967
  return context;
1088
968
  };
1089
969
 
970
+ // src/adapters/vercel/useVercelAIBranches.tsx
971
+ var import_react21 = require("react");
972
+
973
+ // ../../node_modules/nanoid/non-secure/index.js
974
+ var customAlphabet = (alphabet, defaultSize = 21) => {
975
+ return (size = defaultSize) => {
976
+ let id = "";
977
+ let i = size;
978
+ while (i--) {
979
+ id += alphabet[Math.random() * alphabet.length | 0];
980
+ }
981
+ return id;
982
+ };
983
+ };
984
+
985
+ // src/adapters/MessageRepository.tsx
986
+ var generateId = customAlphabet(
987
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
988
+ 7
989
+ );
990
+ var optimisticPrefix = "__optimistic__";
991
+ var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
992
+ var isOptimisticId = (id) => id.startsWith(optimisticPrefix);
993
+ var findHead = (message) => {
994
+ if (message.next)
995
+ return findHead(message.next);
996
+ return message;
997
+ };
998
+ var MessageRepository = class {
999
+ messages = /* @__PURE__ */ new Map();
1000
+ // message_id -> item
1001
+ head = null;
1002
+ rootChildren = [];
1003
+ getMessages() {
1004
+ const messages = new Array(this.head?.level ?? 0);
1005
+ for (let current = this.head; current; current = current.prev) {
1006
+ messages[current.level] = current.current;
1007
+ }
1008
+ return messages;
1009
+ }
1010
+ addOrUpdateMessage(message) {
1011
+ const item = this.messages.get(message.id);
1012
+ if (item) {
1013
+ if (item.current.parentId !== message.parentId) {
1014
+ this.deleteMessage(message.id);
1015
+ } else {
1016
+ item.current = message;
1017
+ return;
1018
+ }
1019
+ }
1020
+ const prev = message.parentId ? this.messages.get(message.parentId) : null;
1021
+ if (prev === void 0)
1022
+ throw new Error("Unexpected: Parent message not found");
1023
+ const newItem = {
1024
+ prev,
1025
+ current: message,
1026
+ next: null,
1027
+ children: [],
1028
+ level: prev ? prev.level + 1 : 0
1029
+ };
1030
+ this.messages.set(message.id, newItem);
1031
+ if (prev) {
1032
+ prev.children = [...prev.children, message.id];
1033
+ prev.next = newItem;
1034
+ } else {
1035
+ this.rootChildren = [...this.rootChildren, message.id];
1036
+ }
1037
+ if (this.head === prev) {
1038
+ this.head = newItem;
1039
+ }
1040
+ }
1041
+ deleteMessage(messageId) {
1042
+ const message = this.messages.get(messageId);
1043
+ if (!message)
1044
+ throw new Error("Unexpected: Message not found");
1045
+ if (message.children.length > 0) {
1046
+ for (const child of message.children) {
1047
+ this.deleteMessage(child);
1048
+ }
1049
+ }
1050
+ this.messages.delete(messageId);
1051
+ if (message.prev) {
1052
+ message.prev.children = message.prev.children.filter(
1053
+ (m) => m !== messageId
1054
+ );
1055
+ if (message.prev.next === message) {
1056
+ const childId = message.prev.children.at(-1);
1057
+ const child = childId ? this.messages.get(childId) : null;
1058
+ if (child === void 0)
1059
+ throw new Error("Unexpected: Child message not found");
1060
+ message.prev.next = child;
1061
+ }
1062
+ } else {
1063
+ this.rootChildren = this.rootChildren.filter((m) => m !== messageId);
1064
+ }
1065
+ if (this.head === message) {
1066
+ this.head = message.prev ? findHead(message.prev) : null;
1067
+ }
1068
+ }
1069
+ getOptimisticId = () => {
1070
+ let optimisticId;
1071
+ do {
1072
+ optimisticId = generateOptimisticId();
1073
+ } while (this.messages.has(optimisticId));
1074
+ return optimisticId;
1075
+ };
1076
+ commitOptimisticRun(parentId) {
1077
+ const optimisticId = this.getOptimisticId();
1078
+ this.addOrUpdateMessage({
1079
+ id: optimisticId,
1080
+ role: "assistant",
1081
+ content: [
1082
+ {
1083
+ type: "text",
1084
+ text: ""
1085
+ }
1086
+ ],
1087
+ parentId,
1088
+ createdAt: /* @__PURE__ */ new Date()
1089
+ });
1090
+ return optimisticId;
1091
+ }
1092
+ getBranches(messageId) {
1093
+ const message = this.messages.get(messageId);
1094
+ if (!message)
1095
+ throw new Error("Unexpected: Message not found");
1096
+ if (message.prev) {
1097
+ return message.prev.children;
1098
+ }
1099
+ return this.rootChildren;
1100
+ }
1101
+ switchToBranch(messageId) {
1102
+ const message = this.messages.get(messageId);
1103
+ if (!message)
1104
+ throw new Error("Unexpected: Branch not found");
1105
+ if (message.prev) {
1106
+ message.prev.next = message;
1107
+ }
1108
+ this.head = findHead(message);
1109
+ }
1110
+ resetHead(messageId) {
1111
+ if (messageId) {
1112
+ const message = this.messages.get(messageId);
1113
+ if (!message)
1114
+ throw new Error("Unexpected: Branch not found");
1115
+ this.head = message;
1116
+ for (let current = message; current; current = current.prev) {
1117
+ if (current.prev) {
1118
+ current.prev.next = current;
1119
+ }
1120
+ }
1121
+ } else {
1122
+ this.head = null;
1123
+ }
1124
+ }
1125
+ };
1126
+
1127
+ // src/adapters/vercel/useVercelAIBranches.tsx
1128
+ var sliceMessagesUntil = (messages, messageId) => {
1129
+ if (messageId == null)
1130
+ return [];
1131
+ if (isOptimisticId(messageId))
1132
+ return messages;
1133
+ const messageIdx = messages.findIndex((m) => m.id === messageId);
1134
+ if (messageIdx === -1)
1135
+ throw new Error("Unexpected: Message not found");
1136
+ return messages.slice(0, messageIdx + 1);
1137
+ };
1138
+ var hasUpcomingMessage = (isRunning, messages) => {
1139
+ return isRunning && messages[messages.length - 1]?.role !== "assistant";
1140
+ };
1141
+ var useVercelAIBranches = (chat, messages) => {
1142
+ const [data] = (0, import_react21.useState)(() => new MessageRepository());
1143
+ const isRunning = "isLoading" in chat ? chat.isLoading : chat.status === "in_progress";
1144
+ const assistantOptimisticIdRef = (0, import_react21.useRef)(null);
1145
+ const messagesEx = (0, import_react21.useMemo)(() => {
1146
+ for (const message of messages) {
1147
+ data.addOrUpdateMessage(message);
1148
+ }
1149
+ if (assistantOptimisticIdRef.current) {
1150
+ data.deleteMessage(assistantOptimisticIdRef.current);
1151
+ assistantOptimisticIdRef.current = null;
1152
+ }
1153
+ if (hasUpcomingMessage(isRunning, messages)) {
1154
+ assistantOptimisticIdRef.current = data.commitOptimisticRun(
1155
+ messages.at(-1)?.id ?? null
1156
+ );
1157
+ }
1158
+ data.resetHead(
1159
+ assistantOptimisticIdRef.current ?? messages.at(-1)?.id ?? null
1160
+ );
1161
+ return data.getMessages();
1162
+ }, [data, isRunning, messages]);
1163
+ const getBranches = (0, import_react21.useCallback)(
1164
+ (messageId) => {
1165
+ return data.getBranches(messageId);
1166
+ },
1167
+ [data]
1168
+ );
1169
+ const switchToBranch = (0, import_react21.useCallback)(
1170
+ (messageId) => {
1171
+ data.switchToBranch(messageId);
1172
+ chat.setMessages(
1173
+ data.getMessages().filter((m) => !isOptimisticId(m.id)).map((m) => m.innerMessage)
1174
+ );
1175
+ },
1176
+ [data, chat.setMessages]
1177
+ );
1178
+ const reloadMaybe = "reload" in chat ? chat.reload : void 0;
1179
+ const startRun = (0, import_react21.useCallback)(
1180
+ async (parentId) => {
1181
+ if (!reloadMaybe)
1182
+ throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
1183
+ const newMessages = sliceMessagesUntil(chat.messages, parentId);
1184
+ chat.setMessages(newMessages);
1185
+ await reloadMaybe();
1186
+ },
1187
+ [chat.messages, chat.setMessages, reloadMaybe]
1188
+ );
1189
+ const append = (0, import_react21.useCallback)(
1190
+ async (message) => {
1191
+ if (message.content.length !== 1 || message.content[0]?.type !== "text")
1192
+ throw new Error("Only text content is supported by Vercel AI SDK");
1193
+ const newMessages = sliceMessagesUntil(chat.messages, message.parentId);
1194
+ chat.setMessages(newMessages);
1195
+ await chat.append({
1196
+ role: "user",
1197
+ content: message.content[0].text
1198
+ });
1199
+ },
1200
+ [chat.messages, chat.setMessages, chat.append]
1201
+ );
1202
+ return (0, import_react21.useMemo)(
1203
+ () => ({
1204
+ messages: messagesEx,
1205
+ getBranches,
1206
+ switchToBranch,
1207
+ append,
1208
+ startRun
1209
+ }),
1210
+ [messagesEx, getBranches, switchToBranch, append, startRun]
1211
+ );
1212
+ };
1213
+
1090
1214
  // src/adapters/vercel/VercelAIAssistantProvider.tsx
1215
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1091
1216
  var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
1092
- var vercelToThreadMessage = (message, parentId, branchId, branchCount) => {
1217
+ var vercelToThreadMessage = (message, parentId) => {
1093
1218
  if (message.role !== "user" && message.role !== "assistant")
1094
1219
  throw new Error("Unsupported role");
1095
1220
  return {
@@ -1097,24 +1222,17 @@ var vercelToThreadMessage = (message, parentId, branchId, branchCount) => {
1097
1222
  id: message.id,
1098
1223
  role: message.role,
1099
1224
  content: [{ type: "text", text: message.content }],
1100
- branchId,
1101
- branchCount,
1102
- createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
1225
+ createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
1226
+ innerMessage: message
1103
1227
  };
1104
1228
  };
1105
- var vercelToCachedThreadMessages = (messages, getBranchState) => {
1229
+ var vercelToCachedThreadMessages = (messages) => {
1106
1230
  return messages.map((m, idx) => {
1107
1231
  const cached = ThreadMessageCache.get(m);
1108
- const parentId = messages[idx - 1]?.id ?? ROOT_PARENT_ID;
1109
- const { branchId, branchCount } = getBranchState(m.id);
1110
- if (cached && cached.parentId === parentId && cached.branchId === branchId && cached.branchCount === branchCount)
1232
+ const parentId = messages[idx - 1]?.id ?? null;
1233
+ if (cached && cached.parentId === parentId)
1111
1234
  return cached;
1112
- const newMessage = vercelToThreadMessage(
1113
- m,
1114
- parentId,
1115
- branchId,
1116
- branchCount
1117
- );
1235
+ const newMessage = vercelToThreadMessage(m, parentId);
1118
1236
  ThreadMessageCache.set(m, newMessage);
1119
1237
  return newMessage;
1120
1238
  });
@@ -1125,13 +1243,10 @@ var VercelAIAssistantProvider = ({
1125
1243
  }) => {
1126
1244
  const context = useDummyAIAssistantContext();
1127
1245
  const vercel = "chat" in rest ? rest.chat : rest.assistant;
1128
- const branches = useVercelAIBranches(vercel, context);
1129
1246
  const messages = (0, import_react22.useMemo)(() => {
1130
- return vercelToCachedThreadMessages(
1131
- vercel.messages,
1132
- branches.getBranchState
1133
- );
1134
- }, [vercel.messages, branches.getBranchState]);
1247
+ return vercelToCachedThreadMessages(vercel.messages);
1248
+ }, [vercel.messages]);
1249
+ const branches = useVercelAIBranches(vercel, messages);
1135
1250
  const cancelRun = (0, import_react22.useCallback)(() => {
1136
1251
  const lastMessage = vercel.messages.at(-1);
1137
1252
  vercel.stop();
@@ -1141,27 +1256,31 @@ var VercelAIAssistantProvider = ({
1141
1256
  }, [vercel.messages, vercel.stop, vercel.setInput]);
1142
1257
  const isRunning = "isLoading" in vercel ? vercel.isLoading : vercel.status === "in_progress";
1143
1258
  (0, import_react22.useMemo)(() => {
1144
- context.useThread.setState({
1145
- messages,
1146
- isRunning,
1147
- cancelRun,
1148
- switchToBranch: branches.switchToBranch,
1149
- append: branches.append,
1150
- startRun: branches.startRun
1151
- });
1152
- }, [context, messages, isRunning, cancelRun, branches]);
1259
+ context.useThread.setState(
1260
+ {
1261
+ messages: branches.messages,
1262
+ isRunning,
1263
+ getBranches: branches.getBranches,
1264
+ switchToBranch: branches.switchToBranch,
1265
+ append: branches.append,
1266
+ startRun: branches.startRun,
1267
+ cancelRun
1268
+ },
1269
+ true
1270
+ );
1271
+ }, [context, isRunning, cancelRun, branches]);
1153
1272
  (0, import_react22.useMemo)(() => {
1154
1273
  context.useComposer.setState({
1155
- canCancel: isRunning,
1156
1274
  value: vercel.input,
1157
1275
  setValue: vercel.setInput
1158
1276
  });
1159
- }, [context, isRunning, vercel.input, vercel.setInput]);
1160
- return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
1277
+ }, [context, vercel.input, vercel.setInput]);
1278
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AssistantContext.Provider, { value: context, children });
1161
1279
  };
1162
1280
 
1163
1281
  // src/adapters/vercel/VercelRSCAssistantProvider.tsx
1164
1282
  var import_react23 = require("react");
1283
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1165
1284
  var ThreadMessageCache2 = /* @__PURE__ */ new WeakMap();
1166
1285
  var vercelToThreadMessage2 = (parentId, message) => {
1167
1286
  if (message.role !== "user" && message.role !== "assistant")
@@ -1171,15 +1290,13 @@ var vercelToThreadMessage2 = (parentId, message) => {
1171
1290
  id: message.id,
1172
1291
  role: message.role,
1173
1292
  content: [{ type: "ui", display: message.display }],
1174
- createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
1175
- branchId: 0,
1176
- branchCount: 1
1293
+ createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
1177
1294
  };
1178
1295
  };
1179
1296
  var vercelToCachedThreadMessages2 = (messages) => {
1180
1297
  return messages.map((m, idx) => {
1181
1298
  const cached = ThreadMessageCache2.get(m);
1182
- const parentId = messages[idx - 1]?.id ?? ROOT_PARENT_ID;
1299
+ const parentId = messages[idx - 1]?.id ?? null;
1183
1300
  if (cached && cached.parentId === parentId)
1184
1301
  return cached;
1185
1302
  const newMessage = vercelToThreadMessage2(parentId, m);
@@ -1198,12 +1315,11 @@ var VercelRSCAssistantProvider = ({
1198
1315
  }, [vercelMessages]);
1199
1316
  const append = (0, import_react23.useCallback)(
1200
1317
  async (message) => {
1201
- if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? ROOT_PARENT_ID))
1318
+ if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null))
1202
1319
  throw new Error("Unexpected: Message editing is not supported");
1203
1320
  if (message.content[0]?.type !== "text") {
1204
1321
  throw new Error("Only text content is currently supported");
1205
1322
  }
1206
- context.useViewport.getState().scrollToBottom();
1207
1323
  await vercelAppend(message);
1208
1324
  },
1209
1325
  [context, vercelAppend]
@@ -1214,7 +1330,7 @@ var VercelRSCAssistantProvider = ({
1214
1330
  append
1215
1331
  });
1216
1332
  }, [context, messages, append]);
1217
- return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
1333
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(AssistantContext.Provider, { value: context, children });
1218
1334
  };
1219
1335
  // Annotate the CommonJS export names for ESM import in node:
1220
1336
  0 && (module.exports = {