@assistant-ui/react 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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
  });