@assistant-ui/react 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -33,18 +33,15 @@ __export(src_exports, {
33
33
  ActionBarPrimitive: () => actionBar_exports,
34
34
  BranchPickerPrimitive: () => branchPicker_exports,
35
35
  ComposerPrimitive: () => composer_exports,
36
- EditBarPrimitive: () => editBar_exports,
37
36
  MessagePrimitive: () => message_exports,
38
37
  ThreadPrimitive: () => thread_exports,
39
- VercelAIThreadProvider: () => VercelAIThreadProvider,
38
+ VercelAIAssistantProvider: () => VercelAIChatAssistantProvider,
40
39
  unstable_useMessageContext: () => useMessageContext,
41
40
  useBeginMessageEdit: () => useBeginMessageEdit,
42
- useCancelMessageEdit: () => useCancelMessageEdit,
43
41
  useCopyMessage: () => useCopyMessage,
44
42
  useGoToNextBranch: () => useGoToNextBranch,
45
43
  useGoToPreviousBranch: () => useGoToPreviousBranch,
46
- useReloadMessage: () => useReloadMessage,
47
- useSaveMessageEdit: () => useSaveMessageEdit
44
+ useReloadMessage: () => useReloadMessage
48
45
  });
49
46
  module.exports = __toCommonJS(src_exports);
50
47
 
@@ -67,87 +64,22 @@ var ThreadRoot = (0, import_react.forwardRef)(
67
64
  }
68
65
  );
69
66
 
70
- // src/utils/context/createStoreContext.tsx
67
+ // src/utils/context/AssistantContext.ts
71
68
  var import_react2 = require("react");
72
- var import_with_selector = require("use-sync-external-store/with-selector");
73
-
74
- // src/utils/context/shallow.ts
75
- function shallow(objA, objB) {
76
- if (Object.is(objA, objB)) {
77
- return true;
78
- }
79
- if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
80
- return false;
81
- }
82
- const keysA = Object.keys(objA);
83
- if (keysA.length !== Object.keys(objB).length) {
84
- return false;
85
- }
86
- for (const keyA of keysA) {
87
- if (!Object.prototype.hasOwnProperty.call(objB, keyA) || !Object.is(objA[keyA], objB[keyA])) {
88
- return false;
89
- }
90
- }
91
- return true;
92
- }
93
-
94
- // src/utils/context/createStoreContext.tsx
95
- var createStoreContext = (providerName) => {
96
- const context = (0, import_react2.createContext)(null);
97
- const StoreProvider = ({ children, ...rest }) => {
98
- const unstableContext = rest;
99
- const [store] = (0, import_react2.useState)(() => {
100
- let state = unstableContext;
101
- const listeners = /* @__PURE__ */ new Set();
102
- return {
103
- subscribe: (cb) => {
104
- listeners.add(cb);
105
- return () => listeners.delete(cb);
106
- },
107
- emit: () => {
108
- for (const listener of listeners) {
109
- listener();
110
- }
111
- },
112
- snapshot: () => {
113
- return state;
114
- },
115
- setState: (value) => {
116
- state = value;
117
- store.emit();
118
- }
119
- };
120
- });
121
- (0, import_react2.useMemo)(
122
- () => store.setState(unstableContext),
123
- Object.values(unstableContext)
124
- );
125
- return /* @__PURE__ */ React.createElement(context.Provider, { value: store }, children);
126
- };
127
- const useStoreContext = (consumerName, selector) => {
128
- const store = (0, import_react2.useContext)(context);
129
- if (!store)
130
- throw new Error(
131
- `${consumerName} can only be used inside ${providerName}.`
132
- );
133
- return (0, import_with_selector.useSyncExternalStoreWithSelector)(
134
- store.subscribe,
135
- store.snapshot,
136
- store.snapshot,
137
- selector,
138
- shallow
69
+ var AssistantContext = (0, import_react2.createContext)(null);
70
+ var useAssistantContext = () => {
71
+ const context = (0, import_react2.useContext)(AssistantContext);
72
+ if (!context)
73
+ throw new Error(
74
+ "useAssistantContext must be used within a AssistantProvider"
139
75
  );
140
- };
141
- return [StoreProvider, useStoreContext];
76
+ return context;
142
77
  };
143
78
 
144
- // src/utils/context/ThreadContext.ts
145
- var [ThreadContextProvider, useThreadContext] = createStoreContext("Thread.Provider");
146
-
147
79
  // src/primitives/thread/ThreadIf.tsx
148
80
  var useThreadIf = (props) => {
149
- return useThreadContext("Thread.If", (s) => {
150
- const thread = s.chat;
81
+ const { useThread } = useAssistantContext();
82
+ return useThread((thread) => {
151
83
  if (props.empty === true && thread.messages.length !== 0)
152
84
  return false;
153
85
  if (props.empty === false && thread.messages.length === 0)
@@ -245,7 +177,7 @@ var ThreadViewport = (0, import_react4.forwardRef)(({ onScroll, children, ...res
245
177
  );
246
178
  });
247
179
 
248
- // src/utils/hooks/useBranches.tsx
180
+ // src/vercel/useVercelAIBranches.tsx
249
181
  var import_react5 = require("react");
250
182
  var ROOT_ID = "__ROOT_ID__";
251
183
  var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
@@ -313,7 +245,7 @@ var sliceMessagesUntil = (messages, message) => {
313
245
  throw new Error("Unexpected: Message not found");
314
246
  return messages.slice(0, messageIdx);
315
247
  };
316
- var useChatWithBranches = (chat) => {
248
+ var useVercelAIBranches = (chat) => {
317
249
  const data = (0, import_react5.useRef)({
318
250
  parentMap: /* @__PURE__ */ new Map(),
319
251
  branchMap: /* @__PURE__ */ new Map(),
@@ -350,85 +282,168 @@ var useChatWithBranches = (chat) => {
350
282
  async (message, newMessage) => {
351
283
  const newMessages = sliceMessagesUntil(chat.messages, message);
352
284
  chat.setMessages(newMessages);
353
- await chat.append(newMessage);
285
+ if (newMessage.content[0]?.type !== "text")
286
+ throw new Error("Only text content is currently supported");
287
+ await chat.append({
288
+ role: "user",
289
+ content: newMessage.content[0].text
290
+ });
354
291
  },
355
292
  [chat.messages, chat.setMessages, chat.append]
356
293
  );
357
294
  return (0, import_react5.useMemo)(
358
295
  () => ({
359
- ...chat,
360
296
  getBranchState,
361
297
  switchToBranch,
362
298
  editAt,
363
299
  reloadAt
364
300
  }),
365
- [chat, getBranchState, switchToBranch, editAt, reloadAt]
301
+ [getBranchState, switchToBranch, editAt, reloadAt]
366
302
  );
367
303
  };
368
304
  var hasUpcomingMessage = (thread) => {
369
305
  return thread.isLoading && thread.messages[thread.messages.length - 1]?.role !== "assistant";
370
306
  };
371
307
 
308
+ // src/utils/context/ComposerState.ts
309
+ var import_react7 = require("react");
310
+
311
+ // src/utils/context/MessageContext.ts
312
+ var import_react6 = require("react");
313
+ var MessageContext = (0, import_react6.createContext)(null);
314
+ var useMessageContext = () => {
315
+ const context = (0, import_react6.useContext)(MessageContext);
316
+ if (!context)
317
+ throw new Error("useMessageContext must be used within a MessageProvider");
318
+ return context;
319
+ };
320
+
321
+ // src/utils/context/ComposerState.ts
322
+ var useComposerContext = () => {
323
+ const { useComposer: useAssisstantComposer } = useAssistantContext();
324
+ const { useComposer: useMessageComposer } = (0, import_react7.useContext)(MessageContext) ?? {};
325
+ return { useComposer: useMessageComposer ?? useAssisstantComposer };
326
+ };
327
+
328
+ // src/primitives/composer/ComposerIf.tsx
329
+ var useComposerIf = (props) => {
330
+ const { useComposer } = useComposerContext();
331
+ return useComposer((composer) => {
332
+ if (props.editing === true && !composer.isEditing)
333
+ return false;
334
+ if (props.editing === false && composer.isEditing)
335
+ return false;
336
+ return true;
337
+ });
338
+ };
339
+ var ComposerIf = ({ children, ...query }) => {
340
+ const result = useComposerIf(query);
341
+ return result ? children : null;
342
+ };
343
+
372
344
  // src/primitives/message/index.ts
373
345
  var message_exports = {};
374
346
  __export(message_exports, {
375
347
  Content: () => MessageContent,
376
- EditableContent: () => MessageEditableContent,
377
348
  If: () => MessageIf,
378
349
  Provider: () => MessageProvider,
379
350
  Root: () => MessageRoot
380
351
  });
381
352
 
382
353
  // src/primitives/message/MessageProvider.tsx
383
- var import_react6 = require("react");
384
-
385
- // src/utils/context/MessageContext.ts
386
- var [MessageContextProvider, useMessageContext] = createStoreContext("Thread.Provider");
387
-
388
- // src/primitives/message/MessageProvider.tsx
354
+ var import_react8 = require("react");
355
+ var import_zustand = require("zustand");
356
+ var import_shallow = require("zustand/react/shallow");
357
+ var getIsLast = (thread, message) => {
358
+ const hasUpcoming = hasUpcomingMessage(thread);
359
+ return hasUpcoming ? message.id === UPCOMING_MESSAGE_ID : thread.messages[thread.messages.length - 1]?.id === message.id;
360
+ };
361
+ var useMessageContext2 = () => {
362
+ const { useBranchObserver } = useAssistantContext();
363
+ const [context] = (0, import_react8.useState)(() => {
364
+ const useMessage = (0, import_zustand.create)(() => ({
365
+ message: null,
366
+ isLast: false,
367
+ isCopied: false,
368
+ isHovering: false,
369
+ setIsCopied: () => {
370
+ },
371
+ setIsHovering: () => {
372
+ },
373
+ branchState: {
374
+ branchId: 0,
375
+ branchCount: 0
376
+ }
377
+ }));
378
+ const useComposer = (0, import_zustand.create)((set, get) => ({
379
+ isEditing: false,
380
+ canCancel: true,
381
+ edit: () => {
382
+ const message = useMessage.getState().message;
383
+ if (message.role !== "user")
384
+ throw new Error("Editing is only supported for user messages");
385
+ if (message.content[0]?.type !== "text")
386
+ throw new Error("Editing is only supported for text-only messages");
387
+ return set({
388
+ isEditing: true,
389
+ value: message.content[0].text
390
+ });
391
+ },
392
+ cancel: () => set({ isEditing: false }),
393
+ send: () => {
394
+ const message = useMessage.getState().message;
395
+ if (message.role !== "user")
396
+ throw new Error("Editing is only supported for user messages");
397
+ useBranchObserver.getState().editAt(message, {
398
+ role: "user",
399
+ content: [{ type: "text", text: get().value }]
400
+ });
401
+ set({ isEditing: false });
402
+ },
403
+ value: "",
404
+ setValue: (value) => set({ value })
405
+ }));
406
+ return { useMessage, useComposer };
407
+ });
408
+ return context;
409
+ };
389
410
  var MessageProvider = ({
390
411
  message,
391
412
  children
392
413
  }) => {
393
- const getBranchState = useThreadContext(
394
- "Message.Provider",
395
- (s) => s.chat.getBranchState
396
- );
397
- const [editState, setEditState] = (0, import_react6.useState)({
398
- isEditing: false
399
- });
400
- const [isCopied, setIsCopied] = (0, import_react6.useState)(false);
401
- const [isHovering, setIsHovering] = (0, import_react6.useState)(false);
402
- const branchState = (0, import_react6.useMemo)(
403
- () => getBranchState(message),
404
- [getBranchState, message]
405
- );
406
- return /* @__PURE__ */ React.createElement(
407
- MessageContextProvider,
408
- {
409
- message,
410
- editState,
411
- setEditState,
412
- branchState,
413
- isCopied,
414
- setIsCopied,
415
- isHovering,
416
- setIsHovering
417
- },
418
- children
414
+ const { useThread, useBranchObserver } = useAssistantContext();
415
+ const context = useMessageContext2();
416
+ const branchState = useBranchObserver(
417
+ (0, import_shallow.useShallow)((b) => b.getBranchState(message))
419
418
  );
419
+ const isLast = useThread((thread) => getIsLast(thread, message));
420
+ const [isCopied, setIsCopied] = (0, import_react8.useState)(false);
421
+ const [isHovering, setIsHovering] = (0, import_react8.useState)(false);
422
+ (0, import_react8.useMemo)(() => {
423
+ context.useMessage.setState(
424
+ {
425
+ message,
426
+ isLast,
427
+ isCopied,
428
+ isHovering,
429
+ setIsCopied,
430
+ setIsHovering,
431
+ branchState
432
+ },
433
+ true
434
+ );
435
+ }, [context, message, isLast, isCopied, isHovering, branchState]);
436
+ return /* @__PURE__ */ React.createElement(MessageContext.Provider, { value: context }, children);
420
437
  };
421
438
 
422
439
  // src/primitives/message/MessageRoot.tsx
423
- var import_react7 = require("react");
424
- var import_react_primitive3 = require("@radix-ui/react-primitive");
425
440
  var import_primitive2 = require("@radix-ui/primitive");
426
- var MessageRoot = (0, import_react7.forwardRef)(
441
+ var import_react_primitive3 = require("@radix-ui/react-primitive");
442
+ var import_react9 = require("react");
443
+ var MessageRoot = (0, import_react9.forwardRef)(
427
444
  ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
428
- const setIsHovering = useMessageContext(
429
- "Message.Root",
430
- (s) => s.setIsHovering
431
- );
445
+ const { useMessage } = useMessageContext();
446
+ const setIsHovering = useMessage((s) => s.setIsHovering);
432
447
  const handleMouseEnter = () => {
433
448
  setIsHovering(true);
434
449
  };
@@ -448,27 +463,23 @@ var MessageRoot = (0, import_react7.forwardRef)(
448
463
  );
449
464
 
450
465
  // src/primitives/message/MessageIf.tsx
451
- var isLast = (thread, message) => {
452
- const hasUpcoming = hasUpcomingMessage(thread);
453
- return hasUpcoming ? message.id === UPCOMING_MESSAGE_ID : thread.messages[thread.messages.length - 1]?.id === message.id;
454
- };
455
466
  var useMessageIf = (props) => {
456
- const thread = useThreadContext("Message.If", (s) => s.chat);
457
- return useMessageContext(
458
- "Message.If",
459
- ({ message, editState: { isEditing }, isCopied, isHovering }) => {
460
- const { branchCount } = thread.getBranchState(message);
467
+ const { useMessage } = useMessageContext();
468
+ return useMessage(
469
+ ({
470
+ message,
471
+ isLast,
472
+ isCopied,
473
+ isHovering,
474
+ branchState: { branchCount }
475
+ }) => {
461
476
  if (props.hasBranches === true && branchCount < 2)
462
477
  return false;
463
478
  if (props.user && message.role !== "user")
464
479
  return false;
465
480
  if (props.assistant && message.role !== "assistant")
466
481
  return false;
467
- if (props.editing === true && !isEditing)
468
- return false;
469
- if (props.editing === false && isEditing)
470
- return false;
471
- if (props.lastOrHover === true && !isHovering && !isLast(thread, message))
482
+ if (props.lastOrHover === true && !isHovering && !isLast)
472
483
  return false;
473
484
  if (props.copied === true && !isCopied)
474
485
  return false;
@@ -485,66 +496,40 @@ var MessageIf = ({ children, ...query }) => {
485
496
 
486
497
  // src/primitives/message/MessageContent.tsx
487
498
  var MessageContent = () => {
488
- const content = useMessageContext(
489
- "Message.Content",
490
- (s) => s.message.content
491
- );
492
- return /* @__PURE__ */ React.createElement(React.Fragment, null, content);
499
+ const { useMessage } = useMessageContext();
500
+ const content = useMessage((s) => s.message.content);
501
+ if (content[0]?.type !== "text")
502
+ throw new Error("Unsupported message content type");
503
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, content[0].text);
493
504
  };
494
505
 
495
- // src/primitives/message/MessageEditableContent.tsx
496
- var import_react8 = require("react");
497
- var import_primitive3 = require("@radix-ui/primitive");
498
- var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
499
- var MessageEditableContent = (0, import_react8.forwardRef)(({ onChange, value, ...rest }, forwardedRef) => {
500
- const [editState, setEditState] = useMessageContext(
501
- "Message.EditableContent",
502
- (s) => [s.editState, s.setEditState]
503
- );
504
- const handleChange = (e) => {
505
- setEditState({ isEditing: true, value: e.target.value });
506
- };
507
- if (!editState.isEditing)
508
- throw new Error(
509
- "Message.EditableContent may only be rendered when edit mode is enabled. Consider wrapping the component in <Message.If editing>."
510
- );
511
- return /* @__PURE__ */ React.createElement(
512
- import_react_textarea_autosize.default,
513
- {
514
- ...rest,
515
- ref: forwardedRef,
516
- onChange: (0, import_primitive3.composeEventHandlers)(onChange, handleChange),
517
- value: editState.value || value
518
- }
519
- );
520
- });
521
-
522
506
  // src/primitives/thread/ThreadMessages.tsx
523
507
  var getComponents = (components) => {
524
508
  return {
525
- EditingUserMessage: components.EditingUserMessage ?? components.UserMessage ?? components.Message,
509
+ EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
526
510
  UserMessage: components.UserMessage ?? components.Message,
527
511
  AssistantMessage: components.AssistantMessage ?? components.Message
528
512
  };
529
513
  };
530
514
  var ThreadMessages = ({ components }) => {
531
- const chat = useThreadContext("Thread.Messages", (s) => s.chat);
532
- const messages = chat.messages;
533
- const { UserMessage, EditingUserMessage, AssistantMessage } = getComponents(components);
515
+ const { useThread } = useAssistantContext();
516
+ const thread = useThread();
517
+ const messages = thread.messages;
518
+ const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
534
519
  if (messages.length === 0)
535
520
  return null;
536
521
  return /* @__PURE__ */ React.createElement(React.Fragment, null, messages.map((message, idx) => {
537
522
  return (
538
523
  // biome-ignore lint/suspicious/noArrayIndexKey: fixes a11y issues with branch navigation
539
- /* @__PURE__ */ React.createElement(MessageProvider, { key: idx, message }, /* @__PURE__ */ React.createElement(MessageIf, { user: true, editing: false }, /* @__PURE__ */ React.createElement(UserMessage, null)), /* @__PURE__ */ React.createElement(MessageIf, { user: true, editing: true }, /* @__PURE__ */ React.createElement(EditingUserMessage, null)), /* @__PURE__ */ React.createElement(MessageIf, { assistant: true }, /* @__PURE__ */ React.createElement(AssistantMessage, null)))
524
+ /* @__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)))
540
525
  );
541
- }), hasUpcomingMessage(chat) && /* @__PURE__ */ React.createElement(
526
+ }), hasUpcomingMessage(thread) && /* @__PURE__ */ React.createElement(
542
527
  MessageProvider,
543
528
  {
544
529
  message: {
545
530
  id: UPCOMING_MESSAGE_ID,
546
531
  role: "assistant",
547
- content: "..."
532
+ content: [{ type: "text", text: "..." }]
548
533
  }
549
534
  },
550
535
  /* @__PURE__ */ React.createElement(AssistantMessage, null)
@@ -554,20 +539,21 @@ var ThreadMessages = ({ components }) => {
554
539
  // src/primitives/composer/index.ts
555
540
  var composer_exports = {};
556
541
  __export(composer_exports, {
542
+ Cancel: () => ComposerCancel,
543
+ If: () => ComposerIf,
557
544
  Input: () => ComposerInput,
558
545
  Root: () => ComposerRoot,
559
- Send: () => ComposerSend,
560
- Stop: () => ComposerStop
546
+ Send: () => ComposerSend
561
547
  });
562
548
 
563
549
  // src/primitives/composer/ComposerRoot.tsx
564
- var import_react9 = require("react");
565
- var import_react_primitive4 = require("@radix-ui/react-primitive");
566
- var import_primitive4 = require("@radix-ui/primitive");
550
+ var import_primitive3 = require("@radix-ui/primitive");
567
551
  var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
568
- var ComposerContext = (0, import_react9.createContext)(null);
569
- var useComposerContext = () => {
570
- const context = (0, import_react9.useContext)(ComposerContext);
552
+ var import_react_primitive4 = require("@radix-ui/react-primitive");
553
+ var import_react10 = require("react");
554
+ var ComposerFormContext = (0, import_react10.createContext)(null);
555
+ var useComposerFormContext = () => {
556
+ const context = (0, import_react10.useContext)(ComposerFormContext);
571
557
  if (!context) {
572
558
  throw new Error(
573
559
  "Composer compound components cannot be rendered outside the Composer component"
@@ -575,15 +561,12 @@ var useComposerContext = () => {
575
561
  }
576
562
  return context;
577
563
  };
578
- var ComposerRoot = (0, import_react9.forwardRef)(
564
+ var ComposerRoot = (0, import_react10.forwardRef)(
579
565
  ({ onSubmit, ...rest }, forwardedRef) => {
580
- const handleSubmit = useThreadContext(
581
- "Composer.Root",
582
- (s) => s.chat.handleSubmit
583
- );
584
- const formRef = (0, import_react9.useRef)(null);
566
+ const { useComposer } = useComposerContext();
567
+ const formRef = (0, import_react10.useRef)(null);
585
568
  const ref = (0, import_react_compose_refs2.useComposedRefs)(forwardedRef, formRef);
586
- const composerContextValue = (0, import_react9.useMemo)(
569
+ const composerContextValue = (0, import_react10.useMemo)(
587
570
  () => ({
588
571
  submit: () => formRef.current?.dispatchEvent(
589
572
  new Event("submit", { cancelable: true, bubbles: true })
@@ -591,104 +574,111 @@ var ComposerRoot = (0, import_react9.forwardRef)(
591
574
  }),
592
575
  []
593
576
  );
594
- return /* @__PURE__ */ React.createElement(ComposerContext.Provider, { value: composerContextValue }, /* @__PURE__ */ React.createElement(
577
+ const handleSubmit = (e) => {
578
+ const composerState = useComposer.getState();
579
+ if (!composerState.isEditing)
580
+ return;
581
+ e.preventDefault();
582
+ composerState.send();
583
+ };
584
+ return /* @__PURE__ */ React.createElement(ComposerFormContext.Provider, { value: composerContextValue }, /* @__PURE__ */ React.createElement(
595
585
  import_react_primitive4.Primitive.form,
596
586
  {
597
587
  ...rest,
598
588
  ref,
599
- onSubmit: (0, import_primitive4.composeEventHandlers)(onSubmit, handleSubmit)
589
+ onSubmit: (0, import_primitive3.composeEventHandlers)(onSubmit, handleSubmit)
600
590
  }
601
591
  ));
602
592
  }
603
593
  );
604
594
 
605
595
  // src/primitives/composer/ComposerInput.tsx
606
- var import_react10 = require("react");
596
+ var import_primitive4 = require("@radix-ui/primitive");
607
597
  var import_react_slot = require("@radix-ui/react-slot");
608
- var import_primitive5 = require("@radix-ui/primitive");
609
- var import_react_textarea_autosize2 = __toESM(require("react-textarea-autosize"));
610
- var ComposerInput = (0, import_react10.forwardRef)(({ asChild, onChange, onKeyDown, ...rest }, forwardedRef) => {
611
- const chat = useThreadContext(
612
- "Composer.Input",
613
- ({ chat: { input, handleInputChange, isLoading } }) => ({
614
- input,
615
- handleInputChange,
616
- isLoading
617
- })
618
- );
619
- const Component = asChild ? import_react_slot.Slot : import_react_textarea_autosize2.default;
620
- const composer = useComposerContext();
598
+ var import_react11 = require("react");
599
+ var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
600
+ var ComposerInput = (0, import_react11.forwardRef)(({ asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
601
+ const { useThread } = useAssistantContext();
602
+ const isLoading = useThread((t) => t.isLoading);
603
+ const { useComposer } = useComposerContext();
604
+ const value = useComposer((c) => {
605
+ if (!c.isEditing)
606
+ return "";
607
+ return c.value;
608
+ });
609
+ const Component = asChild ? import_react_slot.Slot : import_react_textarea_autosize.default;
610
+ const composerForm = useComposerFormContext();
621
611
  const handleKeyPress = (e) => {
622
- if (chat.isLoading || rest.disabled)
612
+ if (disabled)
613
+ return;
614
+ if (e.key === "Escape") {
615
+ useComposer.getState().cancel();
616
+ }
617
+ if (isLoading)
623
618
  return;
624
619
  if (e.key === "Enter" && e.shiftKey === false) {
625
620
  e.preventDefault();
626
- composer.submit();
621
+ composerForm.submit();
627
622
  }
628
623
  };
629
624
  return /* @__PURE__ */ React.createElement(
630
625
  Component,
631
626
  {
632
- value: chat.input,
627
+ value,
633
628
  ...rest,
634
629
  ref: forwardedRef,
635
- onChange: (0, import_primitive5.composeEventHandlers)(onChange, chat.handleInputChange),
636
- onKeyDown: (0, import_primitive5.composeEventHandlers)(onKeyDown, handleKeyPress)
630
+ disabled,
631
+ onChange: (0, import_primitive4.composeEventHandlers)(onChange, (e) => {
632
+ const composerState = useComposer.getState();
633
+ if (!composerState.isEditing)
634
+ return;
635
+ return composerState.setValue(e.target.value);
636
+ }),
637
+ onKeyDown: (0, import_primitive4.composeEventHandlers)(onKeyDown, handleKeyPress)
637
638
  }
638
639
  );
639
640
  });
640
641
 
641
642
  // src/primitives/composer/ComposerSend.tsx
642
- var import_react11 = require("react");
643
643
  var import_react_primitive5 = require("@radix-ui/react-primitive");
644
- var ComposerSend = (0, import_react11.forwardRef)(
644
+ var import_react12 = require("react");
645
+ var ComposerSend = (0, import_react12.forwardRef)(
645
646
  ({ disabled, ...rest }, ref) => {
646
- const input = useThreadContext("Composer.Send", (s) => s.chat.input);
647
+ const { useComposer } = useComposerContext();
648
+ const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
647
649
  return /* @__PURE__ */ React.createElement(
648
650
  import_react_primitive5.Primitive.button,
649
651
  {
650
652
  type: "submit",
651
653
  ...rest,
652
654
  ref,
653
- disabled: disabled || input.length === 0
655
+ disabled: disabled || !hasValue
654
656
  }
655
657
  );
656
658
  }
657
659
  );
658
660
 
659
- // src/utils/createActionButton.tsx
660
- var import_react12 = require("react");
661
+ // src/primitives/composer/ComposerCancel.tsx
662
+ var import_primitive5 = require("@radix-ui/primitive");
661
663
  var import_react_primitive6 = require("@radix-ui/react-primitive");
662
- var import_primitive6 = require("@radix-ui/primitive");
663
- var createActionButton = (useActionButton) => {
664
- return (0, import_react12.forwardRef)(
665
- (props, forwardedRef) => {
666
- const onClick = useActionButton(props);
667
- return /* @__PURE__ */ React.createElement(
668
- import_react_primitive6.Primitive.button,
669
- {
670
- type: "button",
671
- disabled: !onClick,
672
- ...props,
673
- ref: forwardedRef,
674
- onClick: (0, import_primitive6.composeEventHandlers)(props.onClick, onClick ?? void 0)
675
- }
676
- );
664
+ var import_react13 = require("react");
665
+ var ComposerCancel = (0, import_react13.forwardRef)(({ disabled, onClick, ...rest }, ref) => {
666
+ const { useComposer } = useComposerContext();
667
+ const hasValue = useComposer((c) => c.canCancel);
668
+ const handleClose = () => {
669
+ useComposer.getState().cancel();
670
+ };
671
+ return /* @__PURE__ */ React.createElement(
672
+ import_react_primitive6.Primitive.button,
673
+ {
674
+ type: "button",
675
+ ...rest,
676
+ ref,
677
+ onClick: (0, import_primitive5.composeEventHandlers)(onClick, handleClose),
678
+ disabled: disabled || !hasValue
677
679
  }
678
680
  );
679
- };
680
-
681
- // src/primitives/composer/ComposerStop.tsx
682
- var useComposerStop = () => {
683
- const [isLoading, stop] = useThreadContext("Composer.Stop", (s) => [
684
- s.chat.isLoading,
685
- s.chat.stop
686
- ]);
687
- if (!isLoading)
688
- return null;
689
- return stop;
690
- };
691
- var ComposerStop = createActionButton(useComposerStop);
681
+ });
692
682
 
693
683
  // src/primitives/branchPicker/index.ts
694
684
  var branchPicker_exports = {};
@@ -702,52 +692,64 @@ __export(branchPicker_exports, {
702
692
 
703
693
  // src/actions/useGoToNextBranch.tsx
704
694
  var useGoToNextBranch = () => {
705
- const switchToBranch = useThreadContext(
706
- "BranchPicker.Next",
707
- (s) => s.chat.switchToBranch
695
+ const { useThread, useBranchObserver } = useAssistantContext();
696
+ const { useComposer, useMessage } = useMessageContext();
697
+ const isLoading = useThread((s) => s.isLoading);
698
+ const isEditing = useComposer((s) => s.isEditing);
699
+ const hasNext = useMessage(
700
+ ({ branchState: { branchId, branchCount } }) => branchId + 1 < branchCount
708
701
  );
709
- const context = useMessageContext("BranchPicker.Next", (s) => {
710
- const {
711
- message: message2,
712
- editState: { isEditing },
713
- branchState: { branchId: branchId2, branchCount }
714
- } = s;
715
- if (isEditing || branchCount <= 1 || branchId2 + 1 >= branchCount)
716
- return null;
717
- return { message: message2, branchId: branchId2 };
718
- });
719
- if (!context)
702
+ if (isLoading || isEditing || !hasNext)
720
703
  return null;
721
- const { message, branchId } = context;
722
704
  return () => {
723
- switchToBranch(message, branchId + 1);
705
+ const {
706
+ message,
707
+ branchState: { branchId }
708
+ } = useMessage.getState();
709
+ useBranchObserver.getState().switchToBranch(message, branchId + 1);
724
710
  };
725
711
  };
726
712
 
713
+ // src/utils/createActionButton.tsx
714
+ var import_react14 = require("react");
715
+ var import_react_primitive7 = require("@radix-ui/react-primitive");
716
+ var import_primitive6 = require("@radix-ui/primitive");
717
+ var createActionButton = (useActionButton) => {
718
+ return (0, import_react14.forwardRef)(
719
+ (props, forwardedRef) => {
720
+ const onClick = useActionButton(props);
721
+ return /* @__PURE__ */ React.createElement(
722
+ import_react_primitive7.Primitive.button,
723
+ {
724
+ type: "button",
725
+ disabled: !onClick,
726
+ ...props,
727
+ ref: forwardedRef,
728
+ onClick: (0, import_primitive6.composeEventHandlers)(props.onClick, onClick ?? void 0)
729
+ }
730
+ );
731
+ }
732
+ );
733
+ };
734
+
727
735
  // src/primitives/branchPicker/BranchPickerNext.tsx
728
736
  var BranchPickerNext = createActionButton(useGoToNextBranch);
729
737
 
730
738
  // src/actions/useGoToPreviousBranch.tsx
731
739
  var useGoToPreviousBranch = () => {
732
- const switchToBranch = useThreadContext(
733
- "BranchPicker.Previous",
734
- (s) => s.chat.switchToBranch
735
- );
736
- const context = useMessageContext("BranchPicker.Previous", (s) => {
737
- const {
738
- message: message2,
739
- editState: { isEditing },
740
- branchState: { branchId: branchId2, branchCount }
741
- } = s;
742
- if (isEditing || branchCount <= 1 || branchId2 <= 0)
743
- return null;
744
- return { message: message2, branchId: branchId2 };
745
- });
746
- if (!context)
740
+ const { useThread, useBranchObserver } = useAssistantContext();
741
+ const { useComposer, useMessage } = useMessageContext();
742
+ const isLoading = useThread((s) => s.isLoading);
743
+ const isEditing = useComposer((s) => s.isEditing);
744
+ const hasNext = useMessage(({ branchState: { branchId } }) => branchId > 0);
745
+ if (isLoading || isEditing || !hasNext)
747
746
  return null;
748
- const { message, branchId } = context;
749
747
  return () => {
750
- switchToBranch(message, branchId - 1);
748
+ const {
749
+ message,
750
+ branchState: { branchId }
751
+ } = useMessage.getState();
752
+ useBranchObserver.getState().switchToBranch(message, branchId - 1);
751
753
  };
752
754
  };
753
755
 
@@ -756,27 +758,23 @@ var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
756
758
 
757
759
  // src/primitives/branchPicker/BranchPickerCount.tsx
758
760
  var BranchPickerCount = () => {
759
- const branchCount = useMessageContext(
760
- "BranchPicker.Count",
761
- (s) => s.branchState.branchCount
762
- );
761
+ const { useMessage } = useMessageContext();
762
+ const branchCount = useMessage((s) => s.branchState.branchCount);
763
763
  return /* @__PURE__ */ React.createElement(React.Fragment, null, branchCount);
764
764
  };
765
765
 
766
766
  // src/primitives/branchPicker/BranchPickerNumber.tsx
767
767
  var BranchPickerNumber = () => {
768
- const branchId = useMessageContext(
769
- "BranchPicker.Number",
770
- (s) => s.branchState.branchId
771
- );
768
+ const { useMessage } = useMessageContext();
769
+ const branchId = useMessage((s) => s.branchState.branchId);
772
770
  return /* @__PURE__ */ React.createElement(React.Fragment, null, branchId + 1);
773
771
  };
774
772
 
775
773
  // src/primitives/branchPicker/BranchPickerRoot.tsx
776
- var import_react_primitive7 = require("@radix-ui/react-primitive");
777
- var import_react13 = require("react");
778
- var BranchPickerRoot = (0, import_react13.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
779
- return /* @__PURE__ */ React.createElement(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0 }, /* @__PURE__ */ React.createElement(import_react_primitive7.Primitive.div, { ...rest, ref }));
774
+ var import_react_primitive8 = require("@radix-ui/react-primitive");
775
+ var import_react15 = require("react");
776
+ var BranchPickerRoot = (0, import_react15.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
777
+ return /* @__PURE__ */ React.createElement(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0 }, /* @__PURE__ */ React.createElement(import_react_primitive8.Primitive.div, { ...rest, ref }));
780
778
  });
781
779
 
782
780
  // src/primitives/actionBar/index.ts
@@ -789,29 +787,47 @@ __export(actionBar_exports, {
789
787
  });
790
788
 
791
789
  // src/primitives/actionBar/ActionBarRoot.tsx
792
- var import_react_primitive8 = require("@radix-ui/react-primitive");
793
- var import_react14 = require("react");
794
- var ActionBarRoot = (0, import_react14.forwardRef)(({ hideWhenBusy, hideWhenNotLastOrHover, ...rest }, ref) => {
795
- return /* @__PURE__ */ React.createElement(ThreadIf, { busy: hideWhenBusy ? false : void 0 }, /* @__PURE__ */ React.createElement(MessageIf, { lastOrHover: hideWhenNotLastOrHover ? true : void 0 }, /* @__PURE__ */ React.createElement(import_react_primitive8.Primitive.div, { ...rest, ref })));
790
+ var import_react_primitive9 = require("@radix-ui/react-primitive");
791
+ var import_react16 = require("react");
792
+ var ActionBarRoot = (0, import_react16.forwardRef)(({ hideWhenBusy, autohide, autohideFloat, ...rest }, ref) => {
793
+ const { useThread } = useAssistantContext();
794
+ const { useMessage } = useMessageContext();
795
+ const hideAndfloatStatus = useMessage((m) => {
796
+ const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
797
+ if (!autohideEnabled)
798
+ return "normal" /* Normal */;
799
+ if (!m.isHovering)
800
+ return "hidden" /* Hidden */;
801
+ if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branchState.branchCount <= 1)
802
+ return "floating" /* Floating */;
803
+ return "normal" /* Normal */;
804
+ });
805
+ const busy = useThread((t) => t.isLoading);
806
+ if (hideWhenBusy && busy)
807
+ return null;
808
+ if (hideAndfloatStatus === "hidden" /* Hidden */)
809
+ return null;
810
+ return /* @__PURE__ */ React.createElement(
811
+ import_react_primitive9.Primitive.div,
812
+ {
813
+ "data-floating": hideAndfloatStatus === "floating" /* Floating */,
814
+ ...rest,
815
+ ref
816
+ }
817
+ );
796
818
  });
797
819
 
798
820
  // src/actions/useCopyMessage.tsx
799
821
  var useCopyMessage = ({ copiedDuration = 3e3 }) => {
800
- const context = useMessageContext("ActionBar.Copy", (s) => {
801
- const {
802
- editState: { isEditing },
803
- message: { content: content2 },
804
- setIsCopied: setIsCopied2
805
- } = s;
806
- if (isEditing)
807
- return null;
808
- return { content: content2, setIsCopied: setIsCopied2 };
809
- });
810
- if (!context)
822
+ const { useMessage, useComposer } = useMessageContext();
823
+ const isEditing = useComposer((s) => s.isEditing);
824
+ if (isEditing)
811
825
  return null;
812
- const { content, setIsCopied } = context;
813
826
  return () => {
814
- navigator.clipboard.writeText(content);
827
+ const { message, setIsCopied } = useMessage.getState();
828
+ if (message.content[0]?.type !== "text")
829
+ throw new Error("Copying is only supported for text-only messages");
830
+ navigator.clipboard.writeText(message.content[0].text);
815
831
  setIsCopied(true);
816
832
  setTimeout(() => setIsCopied(false), copiedDuration);
817
833
  };
@@ -822,19 +838,18 @@ var ActionBarCopy = createActionButton(useCopyMessage);
822
838
 
823
839
  // src/actions/useReloadMessage.tsx
824
840
  var useReloadMessage = () => {
825
- const [isLoading, reloadAt] = useThreadContext("ActionBar.Reload", (s) => [
826
- s.chat.isLoading,
827
- s.chat.reloadAt
828
- ]);
829
- const message = useMessageContext("ActionBar.Reload", (s) => {
830
- const message2 = s.message;
831
- if (message2.role !== "assistant" || isLoading)
832
- return null;
833
- return message2;
834
- });
835
- if (!message)
841
+ const { useThread, useBranchObserver } = useAssistantContext();
842
+ const { useMessage } = useMessageContext();
843
+ const isLoading = useThread((s) => s.isLoading);
844
+ const isAssistant = useMessage((s) => s.message.role === "assistant");
845
+ if (isLoading || !isAssistant)
836
846
  return null;
837
- return () => reloadAt(message);
847
+ return () => {
848
+ const message = useMessage.getState().message;
849
+ if (message.role !== "assistant")
850
+ throw new Error("Reloading is only supported on assistant messages");
851
+ useBranchObserver.getState().reloadAt(message);
852
+ };
838
853
  };
839
854
 
840
855
  // src/primitives/actionBar/ActionBarReload.tsx
@@ -842,115 +857,155 @@ var ActionBarReload = createActionButton(useReloadMessage);
842
857
 
843
858
  // src/actions/useBeginMessageEdit.tsx
844
859
  var useBeginMessageEdit = () => {
845
- const context = useMessageContext("ActionBar.Edit", (s) => {
846
- const {
847
- message: { content: content2 },
848
- editState: { isEditing },
849
- setEditState: setEditState2
850
- } = s;
851
- if (isEditing)
852
- return null;
853
- return { content: content2, setEditState: setEditState2 };
854
- });
855
- if (!context)
860
+ const { useMessage, useComposer } = useMessageContext();
861
+ const isUser = useMessage((s) => s.message.role === "user");
862
+ const isEditing = useComposer((s) => s.isEditing);
863
+ if (!isUser || isEditing)
856
864
  return null;
857
- const { content, setEditState } = context;
858
865
  return () => {
859
- setEditState({ isEditing: true, value: content });
866
+ const { edit } = useComposer.getState();
867
+ edit();
860
868
  };
861
869
  };
862
870
 
863
871
  // src/primitives/actionBar/ActionBarEdit.tsx
864
872
  var ActionBarEdit = createActionButton(useBeginMessageEdit);
865
873
 
866
- // src/primitives/editBar/index.ts
867
- var editBar_exports = {};
868
- __export(editBar_exports, {
869
- Cancel: () => EditBarCancel,
870
- Root: () => EditBarRoot,
871
- Save: () => EditBarSave
872
- });
873
-
874
- // src/primitives/editBar/EditBarRoot.tsx
875
- var import_react_primitive9 = require("@radix-ui/react-primitive");
876
- var import_react15 = require("react");
877
- var EditBarRoot = (0, import_react15.forwardRef)(
878
- ({ ...rest }, ref) => {
879
- return /* @__PURE__ */ React.createElement(import_react_primitive9.Primitive.div, { ...rest, ref });
880
- }
881
- );
882
-
883
- // src/actions/useSaveMessageEdit.tsx
884
- var useSaveMessageEdit = () => {
885
- const chat = useThreadContext("EditBar.Save", (s) => s.chat);
886
- const context = useMessageContext("EditBar.Save", (s) => {
887
- const { message: message2, editState, setEditState: setEditState2 } = s;
888
- if (!editState.isEditing)
889
- return null;
890
- return { message: message2, content: editState.value, setEditState: setEditState2 };
874
+ // src/vercel/VercelAIAssistantProvider.tsx
875
+ var import_react17 = require("react");
876
+ var import_zustand2 = require("zustand");
877
+ var useAIAssistantContext = () => {
878
+ const [context] = (0, import_react17.useState)(() => {
879
+ const useThread = (0, import_zustand2.create)()(() => ({
880
+ messages: [],
881
+ isLoading: false,
882
+ reload: async () => {
883
+ },
884
+ append: async () => {
885
+ },
886
+ stop: () => {
887
+ }
888
+ }));
889
+ const useComposer = (0, import_zustand2.create)()(() => ({
890
+ isEditing: true,
891
+ canCancel: false,
892
+ value: "",
893
+ setValue: () => {
894
+ },
895
+ edit: () => {
896
+ throw new Error("Not implemented");
897
+ },
898
+ send: () => {
899
+ useThread.getState().append({
900
+ role: "user",
901
+ content: [{ type: "text", text: useComposer.getState().value }]
902
+ });
903
+ useComposer.getState().setValue("");
904
+ },
905
+ cancel: () => {
906
+ useThread.getState().stop();
907
+ }
908
+ }));
909
+ const useBranchObserver = (0, import_zustand2.create)()(() => ({
910
+ getBranchState: () => ({
911
+ branchId: 0,
912
+ branchCount: 0
913
+ }),
914
+ switchToBranch: () => {
915
+ },
916
+ editAt: async () => {
917
+ },
918
+ reloadAt: async () => {
919
+ }
920
+ }));
921
+ return { useThread, useComposer, useBranchObserver };
891
922
  });
892
- if (!context)
893
- return null;
894
- const { message, content, setEditState } = context;
895
- return () => {
896
- chat.editAt(message, {
897
- ...message,
898
- id: void 0,
899
- // remove id to create a new message
900
- content
901
- });
902
- setEditState({ isEditing: false });
923
+ return context;
924
+ };
925
+ var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
926
+ var vercelToThreadMessage = (message) => {
927
+ if (message.role !== "user" && message.role !== "assistant")
928
+ throw new Error("Unsupported role");
929
+ return {
930
+ id: message.id,
931
+ role: message.role,
932
+ content: [{ type: "text", text: message.content }]
903
933
  };
904
934
  };
905
-
906
- // src/primitives/editBar/EditBarSave.tsx
907
- var EditBarSave = createActionButton(useSaveMessageEdit);
908
-
909
- // src/actions/useCancelMessageEdit.tsx
910
- var useCancelMessageEdit = () => {
911
- const context = useMessageContext("EditBar.Cancel", (s) => {
912
- const {
913
- editState: { isEditing },
914
- setEditState: setEditState2
915
- } = s;
916
- if (!isEditing)
917
- return null;
918
- return { setEditState: setEditState2 };
935
+ var vercelToCachedThreadMessages = (messages) => {
936
+ return messages.map((m) => {
937
+ const cached = ThreadMessageCache.get(m);
938
+ if (cached)
939
+ return cached;
940
+ const newMessage = vercelToThreadMessage(m);
941
+ ThreadMessageCache.set(m, newMessage);
942
+ return newMessage;
919
943
  });
920
- if (!context)
921
- return null;
922
- const { setEditState } = context;
923
- return () => {
924
- setEditState({ isEditing: false });
925
- };
926
944
  };
927
-
928
- // src/primitives/editBar/EditBarCancel.tsx
929
- var EditBarCancel = createActionButton(useCancelMessageEdit);
930
-
931
- // src/vercel/VercelAIThreadProvider.tsx
932
- var VercelAIThreadProvider = ({
933
- chat,
934
- children
935
- }) => {
936
- const branches = useChatWithBranches(chat);
937
- return /* @__PURE__ */ React.createElement(ThreadContextProvider, { chat: branches }, children);
945
+ var VercelAIChatAssistantProvider = ({ chat, children }) => {
946
+ const context = useAIAssistantContext();
947
+ const messages = (0, import_react17.useMemo)(() => {
948
+ return vercelToCachedThreadMessages(chat.messages);
949
+ }, [chat.messages]);
950
+ const reload = (0, import_react17.useCallback)(async () => {
951
+ await chat.reload();
952
+ }, [chat.reload]);
953
+ const append = (0, import_react17.useCallback)(
954
+ async (message) => {
955
+ if (message.content[0]?.type !== "text") {
956
+ throw new Error("Only text content is currently supported");
957
+ }
958
+ await chat.append({
959
+ role: message.role,
960
+ content: message.content[0].text
961
+ });
962
+ },
963
+ [chat.append]
964
+ );
965
+ const stop = (0, import_react17.useCallback)(() => {
966
+ const lastMessage = chat.messages.at(-1);
967
+ chat.stop();
968
+ if (lastMessage?.role === "user") {
969
+ chat.setInput(lastMessage.content);
970
+ }
971
+ }, [chat.messages, chat.stop, chat.setInput]);
972
+ (0, import_react17.useMemo)(() => {
973
+ context.useThread.setState(
974
+ {
975
+ messages,
976
+ isLoading: chat.isLoading,
977
+ reload,
978
+ append,
979
+ stop
980
+ },
981
+ true
982
+ );
983
+ }, [context, messages, reload, append, stop, chat.isLoading]);
984
+ (0, import_react17.useMemo)(() => {
985
+ context.useComposer.setState({
986
+ canCancel: chat.isLoading,
987
+ value: chat.input,
988
+ setValue: chat.setInput
989
+ });
990
+ }, [context, chat.isLoading, chat.input, chat.setInput]);
991
+ const branches = useVercelAIBranches(chat);
992
+ (0, import_react17.useMemo)(() => {
993
+ context.useBranchObserver.setState(branches, true);
994
+ }, [context, branches]);
995
+ return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
938
996
  };
939
997
  // Annotate the CommonJS export names for ESM import in node:
940
998
  0 && (module.exports = {
941
999
  ActionBarPrimitive,
942
1000
  BranchPickerPrimitive,
943
1001
  ComposerPrimitive,
944
- EditBarPrimitive,
945
1002
  MessagePrimitive,
946
1003
  ThreadPrimitive,
947
- VercelAIThreadProvider,
1004
+ VercelAIAssistantProvider,
948
1005
  unstable_useMessageContext,
949
1006
  useBeginMessageEdit,
950
- useCancelMessageEdit,
951
1007
  useCopyMessage,
952
1008
  useGoToNextBranch,
953
1009
  useGoToPreviousBranch,
954
- useReloadMessage,
955
- useSaveMessageEdit
1010
+ useReloadMessage
956
1011
  });