@assistant-ui/react 0.5.74 → 0.5.76

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.mjs CHANGED
@@ -605,20 +605,13 @@ var useActionBarReload = () => {
605
605
  // src/primitive-hooks/actionBar/useActionBarSpeak.tsx
606
606
  import { useCallback as useCallback6 } from "react";
607
607
  var useActionBarSpeak = () => {
608
- const messageStore = useMessageStore();
609
- const editComposerStore = useEditComposerStore();
610
608
  const messageRunime = useMessageRuntime();
611
- const messageUtilsStore = useMessageUtilsStore();
612
- const hasSpeakableContent = useCombinedStore(
613
- [messageStore, editComposerStore],
614
- (message, c) => {
615
- return !c.isEditing && (message.role !== "assistant" || message.status.type !== "running") && message.content.some((c2) => c2.type === "text" && c2.text.length > 0);
616
- }
617
- );
618
609
  const callback = useCallback6(async () => {
619
- const utt = messageRunime.speak();
620
- messageUtilsStore.getState().addUtterance(utt);
621
- }, [messageRunime, messageUtilsStore]);
610
+ messageRunime.speak();
611
+ }, [messageRunime]);
612
+ const hasSpeakableContent = useMessage((m) => {
613
+ return (m.role !== "assistant" || m.status.type !== "running") && m.content.some((c) => c.type === "text" && c.text.length > 0);
614
+ });
622
615
  if (!hasSpeakableContent) return null;
623
616
  return callback;
624
617
  };
@@ -626,11 +619,11 @@ var useActionBarSpeak = () => {
626
619
  // src/primitive-hooks/actionBar/useActionBarStopSpeaking.tsx
627
620
  import { useCallback as useCallback7 } from "react";
628
621
  var useActionBarStopSpeaking = () => {
629
- const messageUtilsStore = useMessageUtilsStore();
630
- const isSpeaking = useMessageUtils((u) => u.isSpeaking);
622
+ const messageRuntime = useMessageRuntime();
623
+ const isSpeaking = useMessage((u) => u.speech != null);
631
624
  const callback = useCallback7(async () => {
632
- messageUtilsStore.getState().stopSpeaking();
633
- }, [messageUtilsStore]);
625
+ messageRuntime.stopSpeaking();
626
+ }, [messageRuntime]);
634
627
  if (!isSpeaking) return null;
635
628
  return callback;
636
629
  };
@@ -639,13 +632,9 @@ var useActionBarStopSpeaking = () => {
639
632
  import { useCallback as useCallback8 } from "react";
640
633
  var useActionBarFeedbackPositive = () => {
641
634
  const messageRuntime = useMessageRuntime();
642
- const messageUtilsStore = useMessageUtilsStore();
643
635
  const callback = useCallback8(() => {
644
- messageRuntime.submitFeedback({
645
- type: "positive"
646
- });
647
- messageUtilsStore.getState().setSubmittedFeedback("positive");
648
- }, [messageUtilsStore, messageRuntime]);
636
+ messageRuntime.submitFeedback({ type: "positive" });
637
+ }, [messageRuntime]);
649
638
  return callback;
650
639
  };
651
640
 
@@ -653,13 +642,9 @@ var useActionBarFeedbackPositive = () => {
653
642
  import { useCallback as useCallback9 } from "react";
654
643
  var useActionBarFeedbackNegative = () => {
655
644
  const messageRuntime = useMessageRuntime();
656
- const messageUtilsStore = useMessageUtilsStore();
657
645
  const callback = useCallback9(() => {
658
- messageRuntime.submitFeedback({
659
- type: "negative"
660
- });
661
- messageUtilsStore.getState().setSubmittedFeedback("negative");
662
- }, [messageUtilsStore, messageRuntime]);
646
+ messageRuntime.submitFeedback({ type: "negative" });
647
+ }, [messageRuntime]);
663
648
  return callback;
664
649
  };
665
650
 
@@ -747,23 +732,21 @@ var useComposerSend = () => {
747
732
  import { useCallback as useCallback14 } from "react";
748
733
  var useComposerAddAttachment = () => {
749
734
  const disabled = useComposer((c) => !c.isEditing);
750
- const threadComposerStore = useThreadComposerStore();
751
- const threadRuntimeStore = useThreadComposerStore();
735
+ const composerRuntime = useComposerRuntime();
752
736
  const callback = useCallback14(() => {
753
- const { addAttachment } = threadComposerStore.getState();
754
- const { attachmentAccept } = threadRuntimeStore.getState();
755
737
  const input = document.createElement("input");
756
738
  input.type = "file";
739
+ const attachmentAccept = composerRuntime.getAttachmentAccept();
757
740
  if (attachmentAccept !== "*") {
758
741
  input.accept = attachmentAccept;
759
742
  }
760
743
  input.onchange = (e) => {
761
744
  const file = e.target.files?.[0];
762
745
  if (!file) return;
763
- addAttachment(file);
746
+ composerRuntime.addAttachment(file);
764
747
  };
765
748
  input.click();
766
- }, [threadComposerStore, threadRuntimeStore]);
749
+ }, [composerRuntime]);
767
750
  if (disabled) return null;
768
751
  return callback;
769
752
  };
@@ -810,7 +793,15 @@ var useMessageIf = (props) => {
810
793
  const messageUtilsStore = useMessageUtilsStore();
811
794
  return useCombinedStore(
812
795
  [messageStore, messageUtilsStore],
813
- ({ role, attachments, branchCount, isLast }, { isCopied, isHovering, isSpeaking, submittedFeedback }) => {
796
+ ({
797
+ role,
798
+ attachments,
799
+ content,
800
+ branchCount,
801
+ isLast,
802
+ speech,
803
+ submittedFeedback
804
+ }, { isCopied, isHovering }) => {
814
805
  if (props.hasBranches === true && branchCount < 2) return false;
815
806
  if (props.user && role !== "user") return false;
816
807
  if (props.assistant && role !== "assistant") return false;
@@ -818,13 +809,15 @@ var useMessageIf = (props) => {
818
809
  if (props.lastOrHover === true && !isHovering && !isLast) return false;
819
810
  if (props.copied === true && !isCopied) return false;
820
811
  if (props.copied === false && isCopied) return false;
821
- if (props.speaking === true && !isSpeaking) return false;
822
- if (props.speaking === false && isSpeaking) return false;
812
+ if (props.speaking === true && speech == null) return false;
813
+ if (props.speaking === false && speech != null) return false;
823
814
  if (props.hasAttachments === true && (role !== "user" || !attachments.length))
824
815
  return false;
825
816
  if (props.hasAttachments === false && role === "user" && !!attachments.length)
826
817
  return false;
827
- if (props.submittedFeedback !== void 0 && submittedFeedback !== props.submittedFeedback)
818
+ if (props.hasContent === true && content.length === 0) return false;
819
+ if (props.hasContent === false && content.length > 0) return false;
820
+ if (props.submittedFeedback !== void 0 && (submittedFeedback?.type ?? null) !== props.submittedFeedback)
828
821
  return false;
829
822
  return true;
830
823
  }
@@ -920,7 +913,7 @@ var useActionBarFloatStatus = ({
920
913
  const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
921
914
  if (!autohideEnabled) return "normal" /* Normal */;
922
915
  if (!mu.isHovering) return "hidden" /* Hidden */;
923
- if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
916
+ if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branchCount <= 1)
924
917
  return "floating" /* Floating */;
925
918
  return "normal" /* Normal */;
926
919
  }
@@ -1058,8 +1051,8 @@ import { composeEventHandlers as composeEventHandlers4 } from "@radix-ui/primiti
1058
1051
  import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
1059
1052
  import { jsx as jsx8 } from "react/jsx-runtime";
1060
1053
  var ActionBarPrimitiveFeedbackPositive = forwardRef5(({ onClick, disabled, ...props }, forwardedRef) => {
1061
- const isSubmitted = useMessageUtils(
1062
- (u) => u.submittedFeedback === "positive"
1054
+ const isSubmitted = useMessage(
1055
+ (u) => u.submittedFeedback?.type === "positive"
1063
1056
  );
1064
1057
  const callback = useActionBarFeedbackPositive();
1065
1058
  return /* @__PURE__ */ jsx8(
@@ -1084,8 +1077,8 @@ import { composeEventHandlers as composeEventHandlers5 } from "@radix-ui/primiti
1084
1077
  import { Primitive as Primitive6 } from "@radix-ui/react-primitive";
1085
1078
  import { jsx as jsx9 } from "react/jsx-runtime";
1086
1079
  var ActionBarPrimitiveFeedbackNegative = forwardRef6(({ onClick, disabled, ...props }, forwardedRef) => {
1087
- const isSubmitted = useMessageUtils(
1088
- (u) => u.submittedFeedback === "negative"
1080
+ const isSubmitted = useMessage(
1081
+ (u) => u.submittedFeedback?.type === "negative"
1089
1082
  );
1090
1083
  const callback = useActionBarFeedbackNegative();
1091
1084
  return /* @__PURE__ */ jsx9(
@@ -1309,9 +1302,9 @@ var { useAttachment: useMessageAttachment } = createContextStoreHook(
1309
1302
  // src/primitives/attachment/AttachmentThumb.tsx
1310
1303
  import { Primitive as Primitive8 } from "@radix-ui/react-primitive";
1311
1304
  import { jsxs } from "react/jsx-runtime";
1312
- var AttachmentPrimitiveThumb = forwardRef11(() => {
1305
+ var AttachmentPrimitiveThumb = forwardRef11((props, ref) => {
1313
1306
  const ext = useAttachment((a) => a.name.split(".").pop());
1314
- return /* @__PURE__ */ jsxs(Primitive8.div, { children: [
1307
+ return /* @__PURE__ */ jsxs(Primitive8.div, { ...props, ref, children: [
1315
1308
  ".",
1316
1309
  ext
1317
1310
  ] });
@@ -1348,7 +1341,7 @@ __export(branchPicker_exports, {
1348
1341
  Count: () => BranchPickerPrimitiveCount,
1349
1342
  Next: () => BranchPickerPrimitiveNext,
1350
1343
  Number: () => BranchPickerPrimitiveNumber,
1351
- Previous: () => BranchPickerPrevious,
1344
+ Previous: () => BranchPickerPrimitivePrevious,
1352
1345
  Root: () => BranchPickerPrimitiveRoot
1353
1346
  });
1354
1347
 
@@ -1359,7 +1352,7 @@ var BranchPickerPrimitiveNext = createActionButton(
1359
1352
  );
1360
1353
 
1361
1354
  // src/primitives/branchPicker/BranchPickerPrevious.tsx
1362
- var BranchPickerPrevious = createActionButton(
1355
+ var BranchPickerPrimitivePrevious = createActionButton(
1363
1356
  "BranchPickerPrimitive.Previous",
1364
1357
  useBranchPickerPrevious
1365
1358
  );
@@ -1852,7 +1845,6 @@ var getThreadComposerState = (runtime, focus, onFocus) => {
1852
1845
  isEmpty: runtime?.isEmpty ?? true,
1853
1846
  text: runtime?.text ?? "",
1854
1847
  attachments: runtime?.attachments ?? EMPTY_ARRAY,
1855
- attachmentAccept: runtime?.attachmentAccept ?? "*",
1856
1848
  value: runtime?.text ?? "",
1857
1849
  setValue: runtime?.setText.bind(runtime) ?? METHOD_NOT_SUPPORTED,
1858
1850
  setText: runtime?.setText.bind(runtime) ?? METHOD_NOT_SUPPORTED,
@@ -1874,7 +1866,6 @@ var getEditComposerState = (runtime, beginEdit) => {
1874
1866
  isEmpty: runtime?.isEmpty ?? true,
1875
1867
  text: runtime?.text ?? "",
1876
1868
  attachments: runtime?.attachments ?? EMPTY_ARRAY,
1877
- attachmentAccept: runtime?.attachmentAccept ?? "*",
1878
1869
  value: runtime?.text ?? "",
1879
1870
  setValue: runtime?.setText.bind(runtime) ?? METHOD_NOT_SUPPORTED,
1880
1871
  setText: runtime?.setText.bind(runtime) ?? METHOD_NOT_SUPPORTED,
@@ -1911,12 +1902,6 @@ var ComposerRuntimeImpl = class {
1911
1902
  get text() {
1912
1903
  return this.getState().text;
1913
1904
  }
1914
- /**
1915
- * @deprecated Use `getState().attachmentAccept` instead. This will be removed in 0.6.0.
1916
- */
1917
- get attachmentAccept() {
1918
- return this.getState().attachmentAccept;
1919
- }
1920
1905
  /**
1921
1906
  * @deprecated Use `getState().attachments` instead. This will be removed in 0.6.0.
1922
1907
  */
@@ -1971,6 +1956,11 @@ var ComposerRuntimeImpl = class {
1971
1956
  subscribe(callback) {
1972
1957
  return this._core.subscribe(callback);
1973
1958
  }
1959
+ getAttachmentAccept() {
1960
+ const core = this._core.getState();
1961
+ if (!core) throw new Error("Composer is not available");
1962
+ return core.getAttachmentAccept();
1963
+ }
1974
1964
  };
1975
1965
  var ThreadComposerRuntimeImpl = class extends ComposerRuntimeImpl {
1976
1966
  get type() {
@@ -2173,6 +2163,16 @@ var MessageRuntimeImpl = class {
2173
2163
  if (!state) throw new Error("Message is not available");
2174
2164
  return this._threadBinding.getState().speak(state.id);
2175
2165
  }
2166
+ stopSpeaking() {
2167
+ const state = this._core.getState();
2168
+ if (!state) throw new Error("Message is not available");
2169
+ const thread = this._threadBinding.getState();
2170
+ if (thread.speech?.messageId === state.id) {
2171
+ this._threadBinding.getState().stopSpeaking();
2172
+ } else {
2173
+ throw new Error("Message is not being spoken");
2174
+ }
2175
+ }
2176
2176
  submitFeedback({ type }) {
2177
2177
  const state = this._core.getState();
2178
2178
  if (!state) throw new Error("Message is not available");
@@ -2817,7 +2817,6 @@ import { create as create10 } from "zustand";
2817
2817
  // src/context/stores/MessageUtils.ts
2818
2818
  import { create as create9 } from "zustand";
2819
2819
  var makeMessageUtilsStore = () => create9((set) => {
2820
- let utterance = null;
2821
2820
  return {
2822
2821
  isCopied: false,
2823
2822
  setIsCopied: (value) => {
@@ -2826,21 +2825,6 @@ var makeMessageUtilsStore = () => create9((set) => {
2826
2825
  isHovering: false,
2827
2826
  setIsHovering: (value) => {
2828
2827
  set({ isHovering: value });
2829
- },
2830
- isSpeaking: false,
2831
- stopSpeaking: () => {
2832
- utterance?.cancel();
2833
- },
2834
- addUtterance: (utt) => {
2835
- utterance = utt;
2836
- set({ isSpeaking: true });
2837
- utt.onEnd(() => {
2838
- set({ isSpeaking: false });
2839
- });
2840
- },
2841
- submittedFeedback: null,
2842
- setSubmittedFeedback: (feedback) => {
2843
- set({ submittedFeedback: feedback });
2844
2828
  }
2845
2829
  };
2846
2830
  });
@@ -3037,7 +3021,9 @@ __export(internal_exports, {
3037
3021
  var isAttachmentComplete = (a) => a.status.type === "complete";
3038
3022
  var BaseComposerRuntimeCore = class {
3039
3023
  isEditing = true;
3040
- attachmentAccept = "*";
3024
+ getAttachmentAccept() {
3025
+ return this.getAttachmentAdapter()?.accept ?? "*";
3026
+ }
3041
3027
  _attachments = [];
3042
3028
  set attachments(value) {
3043
3029
  this._attachments = value;
@@ -3063,10 +3049,11 @@ var BaseComposerRuntimeCore = class {
3063
3049
  this.notifySubscribers();
3064
3050
  }
3065
3051
  async send() {
3066
- const attachments = this._attachmentAdapter ? await Promise.all(
3052
+ const adapter = this.getAttachmentAdapter();
3053
+ const attachments = adapter && this.attachments.length > 0 ? await Promise.all(
3067
3054
  this.attachments.map(async (a) => {
3068
3055
  if (isAttachmentComplete(a)) return a;
3069
- const result = await this._attachmentAdapter.send(a);
3056
+ const result = await adapter.send(a);
3070
3057
  if (result.status?.type !== "complete") {
3071
3058
  result.status = { type: "complete" };
3072
3059
  }
@@ -3081,19 +3068,10 @@ var BaseComposerRuntimeCore = class {
3081
3068
  this.reset();
3082
3069
  this.handleSend(message);
3083
3070
  }
3084
- _attachmentAdapter;
3085
- setAttachmentAdapter(adapter) {
3086
- this._attachmentAdapter = adapter;
3087
- const accept = adapter?.accept ?? "*";
3088
- if (this.attachmentAccept !== accept) {
3089
- this.attachmentAccept = accept;
3090
- this.notifySubscribers();
3091
- }
3092
- }
3093
3071
  async addAttachment(file) {
3094
- if (!this._attachmentAdapter)
3095
- throw new Error("Attachments are not supported");
3096
- const attachment = await this._attachmentAdapter.add({ file });
3072
+ const adapter = this.getAttachmentAdapter();
3073
+ if (!adapter) throw new Error("Attachments are not supported");
3074
+ const attachment = await adapter.add({ file });
3097
3075
  if (attachment.status === void 0) {
3098
3076
  attachment.status = { type: "requires-action", reason: "composer-send" };
3099
3077
  }
@@ -3101,12 +3079,12 @@ var BaseComposerRuntimeCore = class {
3101
3079
  this.notifySubscribers();
3102
3080
  }
3103
3081
  async removeAttachment(attachmentId) {
3104
- if (!this._attachmentAdapter)
3105
- throw new Error("Attachments are not supported");
3082
+ const adapter = this.getAttachmentAdapter();
3083
+ if (!adapter) throw new Error("Attachments are not supported");
3106
3084
  const index = this._attachments.findIndex((a) => a.id === attachmentId);
3107
3085
  if (index === -1) throw new Error("Attachment not found");
3108
3086
  const attachment = this._attachments[index];
3109
- await this._attachmentAdapter.remove(attachment);
3087
+ await adapter.remove(attachment);
3110
3088
  this._attachments = this._attachments.toSpliced(index, 1);
3111
3089
  this.notifySubscribers();
3112
3090
  }
@@ -3134,6 +3112,9 @@ var DefaultThreadComposerRuntimeCore = class extends BaseComposerRuntimeCore {
3134
3112
  get attachments() {
3135
3113
  return super.attachments;
3136
3114
  }
3115
+ getAttachmentAdapter() {
3116
+ return this.runtime.adapters?.attachments;
3117
+ }
3137
3118
  connect() {
3138
3119
  return this.runtime.subscribe(() => {
3139
3120
  if (this.canCancel !== this.runtime.capabilities.cancel) {
@@ -3512,36 +3493,6 @@ var TooltipIconButton = forwardRef23(({ children, tooltip, side = "bottom", ...r
3512
3493
  });
3513
3494
  TooltipIconButton.displayName = "TooltipIconButton";
3514
3495
 
3515
- // src/api/AssistantRuntime.ts
3516
- var AssistantRuntimeImpl = class {
3517
- constructor(_core, CustomThreadRuntime) {
3518
- this._core = _core;
3519
- this.thread = new CustomThreadRuntime(
3520
- new NestedSubscriptionSubject({
3521
- getState: () => this._core.thread,
3522
- subscribe: (callback) => this._core.subscribe(callback)
3523
- })
3524
- );
3525
- }
3526
- thread;
3527
- switchToNewThread() {
3528
- return this._core.switchToNewThread();
3529
- }
3530
- switchToThread(threadId) {
3531
- return this._core.switchToThread(threadId);
3532
- }
3533
- registerModelConfigProvider(provider) {
3534
- return this._core.registerModelConfigProvider(provider);
3535
- }
3536
- // TODO events for thread switching
3537
- /**
3538
- * @deprecated Thread is now static and never gets updated. This will be removed in 0.6.0.
3539
- */
3540
- subscribe(callback) {
3541
- return this._core.subscribe(callback);
3542
- }
3543
- };
3544
-
3545
3496
  // src/api/ThreadRuntime.ts
3546
3497
  var toAppendMessage = (messages2, message) => {
3547
3498
  if (typeof message === "string") {
@@ -3571,7 +3522,8 @@ var getThreadState = (runtime) => {
3571
3522
  isRunning: lastMessage?.role !== "assistant" ? false : lastMessage.status.type === "running",
3572
3523
  messages: runtime.messages,
3573
3524
  suggestions: runtime.suggestions,
3574
- extras: runtime.extras
3525
+ extras: runtime.extras,
3526
+ speech: runtime.speech
3575
3527
  });
3576
3528
  };
3577
3529
  var ThreadRuntimeImpl = class {
@@ -3618,6 +3570,12 @@ var ThreadRuntimeImpl = class {
3618
3570
  get messages() {
3619
3571
  return this._threadBinding.getState().messages;
3620
3572
  }
3573
+ /**
3574
+ * @deprecated Use `getState().speechState` instead. This will be removed in 0.6.0.
3575
+ */
3576
+ get speech() {
3577
+ return this._threadBinding.getState().speech;
3578
+ }
3621
3579
  unstable_getCore() {
3622
3580
  return this._threadBinding.getState();
3623
3581
  }
@@ -3678,15 +3636,21 @@ var ThreadRuntimeImpl = class {
3678
3636
  switchToBranch(branchId) {
3679
3637
  return this._threadBinding.getState().switchToBranch(branchId);
3680
3638
  }
3681
- // /**
3682
- // * @deprecated Use `getMesssageById(id).speak()` instead. This will be removed in 0.6.0.
3683
- // */
3639
+ /**
3640
+ * @deprecated Use `getMesssageById(id).speak()` instead. This will be removed in 0.6.0.
3641
+ */
3684
3642
  speak(messageId) {
3685
3643
  return this._threadBinding.getState().speak(messageId);
3686
3644
  }
3687
- // /**
3688
- // * @deprecated Use `getMesssageById(id).submitFeedback({ type })` instead. This will be removed in 0.6.0.
3689
- // */
3645
+ stopSpeaking() {
3646
+ return this._threadBinding.getState().stopSpeaking();
3647
+ }
3648
+ getSubmittedFeedback(messageId) {
3649
+ return this._threadBinding.getState().getSubmittedFeedback(messageId);
3650
+ }
3651
+ /**
3652
+ * @deprecated Use `getMesssageById(id).submitFeedback({ type })` instead. This will be removed in 0.6.0.
3653
+ */
3690
3654
  submitFeedback(options) {
3691
3655
  return this._threadBinding.getState().submitFeedback(options);
3692
3656
  }
@@ -3713,10 +3677,12 @@ var ThreadRuntimeImpl = class {
3713
3677
  return new MessageRuntimeImpl(
3714
3678
  new ShallowMemoizeSubject({
3715
3679
  getState: () => {
3716
- const messages2 = this.getState().messages;
3680
+ const { messages: messages2, speech: speechState } = this.getState();
3717
3681
  const message = messages2[idx];
3718
3682
  if (!message) return SKIP_UPDATE;
3719
- const branches = this._threadBinding.getState().getBranches(message.id);
3683
+ const thread = this._threadBinding.getState();
3684
+ const branches = thread.getBranches(message.id);
3685
+ const submittedFeedback = thread.getSubmittedFeedback(message.id);
3720
3686
  return {
3721
3687
  ...message,
3722
3688
  message,
@@ -3724,7 +3690,9 @@ var ThreadRuntimeImpl = class {
3724
3690
  parentId: messages2[idx - 1]?.id ?? null,
3725
3691
  branches,
3726
3692
  branchNumber: branches.indexOf(message.id) + 1,
3727
- branchCount: branches.length
3693
+ branchCount: branches.length,
3694
+ speech: speechState?.messageId === message.id ? speechState : void 0,
3695
+ submittedFeedback
3728
3696
  };
3729
3697
  },
3730
3698
  subscribe: (callback) => this._threadBinding.subscribe(callback)
@@ -3734,6 +3702,47 @@ var ThreadRuntimeImpl = class {
3734
3702
  }
3735
3703
  };
3736
3704
 
3705
+ // src/api/AssistantRuntime.ts
3706
+ var AssistantRuntimeImpl = class _AssistantRuntimeImpl {
3707
+ constructor(_core, _thread) {
3708
+ this._core = _core;
3709
+ this._thread = _thread;
3710
+ }
3711
+ get thread() {
3712
+ return this._thread;
3713
+ }
3714
+ switchToNewThread() {
3715
+ return this._core.switchToNewThread();
3716
+ }
3717
+ switchToThread(threadId) {
3718
+ return this._core.switchToThread(threadId);
3719
+ }
3720
+ registerModelConfigProvider(provider) {
3721
+ return this._core.registerModelConfigProvider(provider);
3722
+ }
3723
+ // TODO events for thread switching
3724
+ /**
3725
+ * @deprecated Thread is now static and never gets updated. This will be removed in 0.6.0.
3726
+ */
3727
+ subscribe(callback) {
3728
+ return this._core.subscribe(callback);
3729
+ }
3730
+ static createThreadRuntime(_core, CustomThreadRuntime = ThreadRuntimeImpl) {
3731
+ return new CustomThreadRuntime(
3732
+ new NestedSubscriptionSubject({
3733
+ getState: () => _core.thread,
3734
+ subscribe: (callback) => _core.subscribe(callback)
3735
+ })
3736
+ );
3737
+ }
3738
+ static create(_core, CustomThreadRuntime = ThreadRuntimeImpl) {
3739
+ return new _AssistantRuntimeImpl(
3740
+ _core,
3741
+ _AssistantRuntimeImpl.createThreadRuntime(_core, CustomThreadRuntime)
3742
+ );
3743
+ }
3744
+ };
3745
+
3737
3746
  // src/runtimes/edge/converters/fromLanguageModelMessages.ts
3738
3747
  var fromLanguageModelMessages = (lm, { mergeSteps }) => {
3739
3748
  const messages2 = [];
@@ -4096,10 +4105,14 @@ var DefaultEditComposerRuntimeCore = class extends BaseComposerRuntimeCore {
4096
4105
  this._nonTextParts = message.content.filter(
4097
4106
  (part) => part.type !== "text" && part.type !== "ui"
4098
4107
  );
4108
+ this.attachments = message.attachments ?? [];
4099
4109
  }
4100
4110
  get canCancel() {
4101
4111
  return true;
4102
4112
  }
4113
+ getAttachmentAdapter() {
4114
+ return this.runtime.adapters?.attachments;
4115
+ }
4103
4116
  _nonTextParts;
4104
4117
  _previousText;
4105
4118
  _parentId;
@@ -4121,10 +4134,107 @@ var DefaultEditComposerRuntimeCore = class extends BaseComposerRuntimeCore {
4121
4134
  }
4122
4135
  };
4123
4136
 
4137
+ // src/runtimes/core/BaseThreadRuntimeCore.tsx
4138
+ var BaseThreadRuntimeCore = class {
4139
+ constructor(configProvider) {
4140
+ this.configProvider = configProvider;
4141
+ }
4142
+ _subscriptions = /* @__PURE__ */ new Set();
4143
+ repository = new MessageRepository();
4144
+ get messages() {
4145
+ return this.repository.getMessages();
4146
+ }
4147
+ composer = new DefaultThreadComposerRuntimeCore(this);
4148
+ getModelConfig() {
4149
+ return this.configProvider.getModelConfig();
4150
+ }
4151
+ _editComposers = /* @__PURE__ */ new Map();
4152
+ getEditComposer(messageId) {
4153
+ return this._editComposers.get(messageId);
4154
+ }
4155
+ beginEdit(messageId) {
4156
+ if (this._editComposers.has(messageId))
4157
+ throw new Error("Edit already in progress");
4158
+ this._editComposers.set(
4159
+ messageId,
4160
+ new DefaultEditComposerRuntimeCore(
4161
+ this,
4162
+ () => this._editComposers.delete(messageId),
4163
+ this.repository.getMessage(messageId)
4164
+ )
4165
+ );
4166
+ this.notifySubscribers();
4167
+ }
4168
+ getBranches(messageId) {
4169
+ return this.repository.getBranches(messageId);
4170
+ }
4171
+ switchToBranch(branchId) {
4172
+ this.repository.switchToBranch(branchId);
4173
+ this.notifySubscribers();
4174
+ }
4175
+ notifySubscribers() {
4176
+ for (const callback of this._subscriptions) callback();
4177
+ }
4178
+ subscribe(callback) {
4179
+ this._subscriptions.add(callback);
4180
+ return () => this._subscriptions.delete(callback);
4181
+ }
4182
+ _submittedFeedback = {};
4183
+ getSubmittedFeedback(messageId) {
4184
+ return this._submittedFeedback[messageId];
4185
+ }
4186
+ submitFeedback({ messageId, type }) {
4187
+ const adapter = this.adapters?.feedback;
4188
+ if (!adapter) throw new Error("Feedback adapter not configured");
4189
+ const { message } = this.repository.getMessage(messageId);
4190
+ adapter.submit({ message, type });
4191
+ this._submittedFeedback[messageId] = { type };
4192
+ this.notifySubscribers();
4193
+ }
4194
+ _stopSpeaking;
4195
+ speech;
4196
+ speak(messageId) {
4197
+ const adapter = this.adapters?.speech;
4198
+ if (!adapter) throw new Error("Speech adapter not configured");
4199
+ const { message } = this.repository.getMessage(messageId);
4200
+ this._stopSpeaking?.();
4201
+ const utterance = adapter.speak(message);
4202
+ const unsub = utterance.subscribe(() => {
4203
+ if (utterance.status.type === "ended") {
4204
+ this._stopSpeaking = void 0;
4205
+ this.speech = void 0;
4206
+ } else {
4207
+ this.speech = { messageId, status: utterance.status };
4208
+ }
4209
+ this.notifySubscribers();
4210
+ });
4211
+ this.speech = { messageId, status: utterance.status };
4212
+ this.notifySubscribers();
4213
+ this._stopSpeaking = () => {
4214
+ utterance.cancel();
4215
+ unsub();
4216
+ this.speech = void 0;
4217
+ this._stopSpeaking = void 0;
4218
+ };
4219
+ }
4220
+ stopSpeaking() {
4221
+ if (!this._stopSpeaking) throw new Error("No message is being spoken");
4222
+ this._stopSpeaking();
4223
+ this.notifySubscribers();
4224
+ }
4225
+ export() {
4226
+ return this.repository.export();
4227
+ }
4228
+ import(data) {
4229
+ this.repository.import(data);
4230
+ this.notifySubscribers();
4231
+ }
4232
+ };
4233
+
4124
4234
  // src/runtimes/local/LocalThreadRuntimeCore.tsx
4125
- var LocalThreadRuntimeCore = class {
4235
+ var LocalThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4126
4236
  constructor(configProvider, adapter, { initialMessages, ...options }) {
4127
- this.configProvider = configProvider;
4237
+ super(configProvider);
4128
4238
  this.adapter = adapter;
4129
4239
  this.threadId = generateId();
4130
4240
  this.options = options;
@@ -4137,28 +4247,22 @@ var LocalThreadRuntimeCore = class {
4137
4247
  }
4138
4248
  }
4139
4249
  }
4140
- _subscriptions = /* @__PURE__ */ new Set();
4141
- abortController = null;
4142
- repository = new MessageRepository();
4143
4250
  capabilities = {
4144
4251
  switchToBranch: true,
4145
4252
  edit: true,
4146
4253
  reload: true,
4147
4254
  cancel: true,
4148
4255
  unstable_copy: true,
4149
- speak: false,
4256
+ speech: false,
4150
4257
  attachments: false,
4151
4258
  feedback: false
4152
4259
  };
4260
+ abortController = null;
4153
4261
  threadId;
4154
4262
  isDisabled = false;
4155
4263
  suggestions = [];
4156
- get messages() {
4157
- return this.repository.getMessages();
4158
- }
4159
- composer = new DefaultThreadComposerRuntimeCore(this);
4160
- getModelConfig() {
4161
- return this.configProvider.getModelConfig();
4264
+ get adapters() {
4265
+ return this.options.adapters;
4162
4266
  }
4163
4267
  _options;
4164
4268
  get options() {
@@ -4171,11 +4275,10 @@ var LocalThreadRuntimeCore = class {
4171
4275
  this._options = options;
4172
4276
  let hasUpdates = false;
4173
4277
  const canSpeak = options.adapters?.speech !== void 0;
4174
- if (this.capabilities.speak !== canSpeak) {
4175
- this.capabilities.speak = canSpeak;
4278
+ if (this.capabilities.speech !== canSpeak) {
4279
+ this.capabilities.speech = canSpeak;
4176
4280
  hasUpdates = true;
4177
4281
  }
4178
- this.composer.setAttachmentAdapter(options.adapters?.attachments);
4179
4282
  const canAttach = options.adapters?.attachments !== void 0;
4180
4283
  if (this.capabilities.attachments !== canAttach) {
4181
4284
  this.capabilities.attachments = canAttach;
@@ -4188,30 +4291,6 @@ var LocalThreadRuntimeCore = class {
4188
4291
  }
4189
4292
  if (hasUpdates) this.notifySubscribers();
4190
4293
  }
4191
- _editComposers = /* @__PURE__ */ new Map();
4192
- getEditComposer(messageId) {
4193
- return this._editComposers.get(messageId);
4194
- }
4195
- beginEdit(messageId) {
4196
- if (this._editComposers.has(messageId))
4197
- throw new Error("Edit already in progress");
4198
- this._editComposers.set(
4199
- messageId,
4200
- new DefaultEditComposerRuntimeCore(
4201
- this,
4202
- () => this._editComposers.delete(messageId),
4203
- this.repository.getMessage(messageId)
4204
- )
4205
- );
4206
- this.notifySubscribers();
4207
- }
4208
- getBranches(messageId) {
4209
- return this.repository.getBranches(messageId);
4210
- }
4211
- switchToBranch(branchId) {
4212
- this.repository.switchToBranch(branchId);
4213
- this.notifySubscribers();
4214
- }
4215
4294
  async append(message) {
4216
4295
  const newMessage = fromCoreMessage(message, {
4217
4296
  attachments: message.attachments
@@ -4288,7 +4367,7 @@ var LocalThreadRuntimeCore = class {
4288
4367
  const promiseOrGenerator = this.adapter.run({
4289
4368
  messages: messages2,
4290
4369
  abortSignal: this.abortController.signal,
4291
- config: this.configProvider.getModelConfig(),
4370
+ config: this.getModelConfig(),
4292
4371
  onUpdate: updateMessage
4293
4372
  });
4294
4373
  if (Symbol.asyncIterator in promiseOrGenerator) {
@@ -4320,17 +4399,9 @@ var LocalThreadRuntimeCore = class {
4320
4399
  return message;
4321
4400
  }
4322
4401
  cancelRun() {
4323
- if (!this.abortController) return;
4324
- this.abortController.abort();
4402
+ this.abortController?.abort();
4325
4403
  this.abortController = null;
4326
4404
  }
4327
- notifySubscribers() {
4328
- for (const callback of this._subscriptions) callback();
4329
- }
4330
- subscribe(callback) {
4331
- this._subscriptions.add(callback);
4332
- return () => this._subscriptions.delete(callback);
4333
- }
4334
4405
  addToolResult({
4335
4406
  messageId,
4336
4407
  toolCallId,
@@ -4364,38 +4435,6 @@ var LocalThreadRuntimeCore = class {
4364
4435
  this.performRoundtrip(parentId, message);
4365
4436
  }
4366
4437
  }
4367
- // TODO lift utterance state to thread runtime
4368
- _utterance;
4369
- speak(messageId) {
4370
- const adapter = this.options.adapters?.speech;
4371
- if (!adapter) throw new Error("Speech adapter not configured");
4372
- const { message } = this.repository.getMessage(messageId);
4373
- if (this._utterance) {
4374
- this._utterance.cancel();
4375
- this._utterance = void 0;
4376
- }
4377
- const utterance = adapter.speak(message);
4378
- utterance.onEnd(() => {
4379
- if (this._utterance === utterance) {
4380
- this._utterance = void 0;
4381
- }
4382
- });
4383
- this._utterance = utterance;
4384
- return this._utterance;
4385
- }
4386
- submitFeedback({ messageId, type }) {
4387
- const adapter = this.options.adapters?.feedback;
4388
- if (!adapter) throw new Error("Feedback adapter not configured");
4389
- const { message } = this.repository.getMessage(messageId);
4390
- adapter.submit({ message, type });
4391
- }
4392
- export() {
4393
- return this.repository.export();
4394
- }
4395
- import(data) {
4396
- this.repository.import(data);
4397
- this.notifySubscribers();
4398
- }
4399
4438
  };
4400
4439
 
4401
4440
  // src/runtimes/local/LocalRuntimeCore.tsx
@@ -4439,14 +4478,20 @@ var LocalRuntimeCore = class extends BaseAssistantRuntimeCore {
4439
4478
  };
4440
4479
 
4441
4480
  // src/runtimes/local/useLocalRuntime.tsx
4442
- var LocalRuntime = class extends AssistantRuntimeImpl {
4443
- constructor(core) {
4444
- super(core, ThreadRuntimeImpl);
4481
+ var LocalRuntimeImpl = class _LocalRuntimeImpl extends AssistantRuntimeImpl {
4482
+ constructor(core, thread) {
4483
+ super(core, thread);
4445
4484
  this.core = core;
4446
4485
  }
4447
4486
  reset(options) {
4448
4487
  this.core.reset(options);
4449
4488
  }
4489
+ static create(_core) {
4490
+ return new _LocalRuntimeImpl(
4491
+ _core,
4492
+ AssistantRuntimeImpl.createThreadRuntime(_core, ThreadRuntimeImpl)
4493
+ );
4494
+ }
4450
4495
  };
4451
4496
  var useLocalRuntime = (adapter, options = {}) => {
4452
4497
  const [runtime] = useState11(() => new LocalRuntimeCore(adapter, options));
@@ -4454,7 +4499,7 @@ var useLocalRuntime = (adapter, options = {}) => {
4454
4499
  runtime.thread.adapter = adapter;
4455
4500
  runtime.thread.options = options;
4456
4501
  });
4457
- return useMemo11(() => new LocalRuntime(runtime), [runtime]);
4502
+ return useMemo11(() => LocalRuntimeImpl.create(runtime), [runtime]);
4458
4503
  };
4459
4504
 
4460
4505
  // src/runtimes/external-store/useExternalStoreRuntime.tsx
@@ -4567,13 +4612,7 @@ var EMPTY_ARRAY2 = Object.freeze([]);
4567
4612
  var hasUpcomingMessage = (isRunning, messages2) => {
4568
4613
  return isRunning && messages2[messages2.length - 1]?.role !== "assistant";
4569
4614
  };
4570
- var ExternalStoreThreadRuntimeCore = class {
4571
- constructor(configProvider, store) {
4572
- this.configProvider = configProvider;
4573
- this.store = store;
4574
- }
4575
- _subscriptions = /* @__PURE__ */ new Set();
4576
- repository = new MessageRepository();
4615
+ var ExternalStoreThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4577
4616
  assistantOptimisticId = null;
4578
4617
  _capabilities = {
4579
4618
  switchToBranch: false,
@@ -4581,7 +4620,7 @@ var ExternalStoreThreadRuntimeCore = class {
4581
4620
  reload: false,
4582
4621
  cancel: false,
4583
4622
  unstable_copy: false,
4584
- speak: false,
4623
+ speech: false,
4585
4624
  attachments: false,
4586
4625
  feedback: false
4587
4626
  };
@@ -4589,29 +4628,26 @@ var ExternalStoreThreadRuntimeCore = class {
4589
4628
  return this._capabilities;
4590
4629
  }
4591
4630
  threadId;
4592
- messages;
4631
+ _messages;
4593
4632
  isDisabled;
4633
+ get messages() {
4634
+ return this._messages;
4635
+ }
4636
+ get adapters() {
4637
+ return this._store.adapters;
4638
+ }
4594
4639
  suggestions = [];
4595
4640
  extras = void 0;
4596
4641
  _converter = new ThreadMessageConverter();
4597
4642
  _store;
4598
- composer = new DefaultThreadComposerRuntimeCore(this);
4599
- _editComposers = /* @__PURE__ */ new Map();
4600
- getEditComposer(messageId) {
4601
- return this._editComposers.get(messageId);
4602
- }
4603
4643
  beginEdit(messageId) {
4604
- if (this._editComposers.has(messageId))
4605
- throw new Error("Edit already in progress");
4606
- this._editComposers.set(
4607
- messageId,
4608
- new DefaultEditComposerRuntimeCore(
4609
- this,
4610
- () => this._editComposers.delete(messageId),
4611
- this.repository.getMessage(messageId)
4612
- )
4613
- );
4614
- this.notifySubscribers();
4644
+ if (!this.store.onEdit)
4645
+ throw new Error("Runtime does not support editing.");
4646
+ super.beginEdit(messageId);
4647
+ }
4648
+ constructor(configProvider, store) {
4649
+ super(configProvider);
4650
+ this.store = store;
4615
4651
  }
4616
4652
  get store() {
4617
4653
  return this._store;
@@ -4630,13 +4666,12 @@ var ExternalStoreThreadRuntimeCore = class {
4630
4666
  edit: this._store.onEdit !== void 0,
4631
4667
  reload: this._store.onReload !== void 0,
4632
4668
  cancel: this._store.onCancel !== void 0,
4633
- speak: this._store.onSpeak !== void 0,
4669
+ speech: this._store.adapters?.speech !== void 0,
4634
4670
  unstable_copy: this._store.unstable_capabilities?.copy !== false,
4635
4671
  // default true
4636
4672
  attachments: !!this.store.adapters?.attachments,
4637
4673
  feedback: !!this.store.adapters?.feedback
4638
4674
  };
4639
- this.composer.setAttachmentAdapter(this._store.adapters?.attachments);
4640
4675
  if (oldStore) {
4641
4676
  if (oldStore.convertMessage !== store.convertMessage) {
4642
4677
  this._converter = new ThreadMessageConverter();
@@ -4680,18 +4715,9 @@ var ExternalStoreThreadRuntimeCore = class {
4680
4715
  this.repository.resetHead(
4681
4716
  this.assistantOptimisticId ?? messages2.at(-1)?.id ?? null
4682
4717
  );
4683
- this.messages = this.repository.getMessages();
4718
+ this._messages = this.repository.getMessages();
4684
4719
  this.notifySubscribers();
4685
4720
  }
4686
- getModelConfig() {
4687
- return this.configProvider.getModelConfig();
4688
- }
4689
- notifySubscribers() {
4690
- for (const callback of this._subscriptions) callback();
4691
- }
4692
- getBranches(messageId) {
4693
- return this.repository.getBranches(messageId);
4694
- }
4695
4721
  switchToBranch(branchId) {
4696
4722
  if (!this._store.setMessages)
4697
4723
  throw new Error("Runtime does not support switching branches.");
@@ -4740,33 +4766,11 @@ var ExternalStoreThreadRuntimeCore = class {
4740
4766
  throw new Error("Runtime does not support tool results.");
4741
4767
  this._store.onAddToolResult(options);
4742
4768
  }
4743
- speak(messageId) {
4744
- if (!this._store.onSpeak)
4745
- throw new Error("Runtime does not support speaking.");
4746
- const { message } = this.repository.getMessage(messageId);
4747
- return this._store.onSpeak(message);
4748
- }
4749
- submitFeedback({ messageId, type }) {
4750
- const adapter = this._store.adapters?.feedback;
4751
- if (!adapter) throw new Error("Feedback adapter not configured");
4752
- const { message } = this.repository.getMessage(messageId);
4753
- adapter.submit({ message, type });
4754
- }
4755
- subscribe(callback) {
4756
- this._subscriptions.add(callback);
4757
- return () => this._subscriptions.delete(callback);
4758
- }
4759
4769
  updateMessages = (messages2) => {
4760
4770
  this._store.setMessages?.(
4761
4771
  messages2.flatMap(getExternalStoreMessage).filter((m) => m != null)
4762
4772
  );
4763
4773
  };
4764
- import(repository) {
4765
- this.repository.import(repository);
4766
- }
4767
- export() {
4768
- return this.repository.export();
4769
- }
4770
4774
  };
4771
4775
 
4772
4776
  // src/runtimes/external-store/ExternalStoreRuntimeCore.tsx
@@ -4821,7 +4825,7 @@ var useExternalStoreRuntime = (store) => {
4821
4825
  runtime.thread.store = store;
4822
4826
  });
4823
4827
  return useMemo12(
4824
- () => new AssistantRuntimeImpl(runtime, ThreadRuntimeImpl),
4828
+ () => AssistantRuntimeImpl.create(runtime, ThreadRuntimeImpl),
4825
4829
  [runtime]
4826
4830
  );
4827
4831
  };
@@ -5011,11 +5015,11 @@ var WebSpeechSynthesisAdapter = class {
5011
5015
  speak(message) {
5012
5016
  const text = getThreadMessageText(message);
5013
5017
  const utterance = new SpeechSynthesisUtterance(text);
5014
- const endHandlers = /* @__PURE__ */ new Set();
5018
+ const subscribers = /* @__PURE__ */ new Set();
5015
5019
  const handleEnd = (reason, error) => {
5016
5020
  if (res.status.type === "ended") return;
5017
5021
  res.status = { type: "ended", reason, error };
5018
- endHandlers.forEach((handler) => handler());
5022
+ subscribers.forEach((handler) => handler());
5019
5023
  };
5020
5024
  utterance.addEventListener("end", () => handleEnd("finished"));
5021
5025
  utterance.addEventListener("error", (e) => handleEnd("error", e.error));
@@ -5026,7 +5030,7 @@ var WebSpeechSynthesisAdapter = class {
5026
5030
  window.speechSynthesis.cancel();
5027
5031
  handleEnd("cancelled");
5028
5032
  },
5029
- onEnd: (callback) => {
5033
+ subscribe: (callback) => {
5030
5034
  if (res.status.type === "ended") {
5031
5035
  let cancelled = false;
5032
5036
  queueMicrotask(() => {
@@ -5036,9 +5040,9 @@ var WebSpeechSynthesisAdapter = class {
5036
5040
  cancelled = true;
5037
5041
  };
5038
5042
  } else {
5039
- endHandlers.add(callback);
5043
+ subscribers.add(callback);
5040
5044
  return () => {
5041
- endHandlers.delete(callback);
5045
+ subscribers.delete(callback);
5042
5046
  };
5043
5047
  }
5044
5048
  }
@@ -5241,8 +5245,8 @@ var useAllowCopy = (ensureCapability = false) => {
5241
5245
  };
5242
5246
  var useAllowSpeak = (ensureCapability = false) => {
5243
5247
  const { assistantMessage: { allowSpeak = true } = {} } = useThreadConfig();
5244
- const speakSupported = useThread((t) => t.capabilities.speak);
5245
- return allowSpeak && (!ensureCapability || speakSupported);
5248
+ const speechSupported = useThread((t) => t.capabilities.speech);
5249
+ return allowSpeak && (!ensureCapability || speechSupported);
5246
5250
  };
5247
5251
  var useAllowReload = (ensureCapability = false) => {
5248
5252
  const { assistantMessage: { allowReload = true } = {} } = useThreadConfig();
@@ -5288,13 +5292,13 @@ var AssistantActionBarRoot = withDefaults(actionBar_exports.Root, {
5288
5292
  className: "aui-assistant-action-bar-root"
5289
5293
  });
5290
5294
  AssistantActionBarRoot.displayName = "AssistantActionBarRoot";
5291
- var AssistantActionBarCopy = forwardRef24((props, ref) => {
5295
+ var AssistantActionBarCopy = forwardRef24(({ copiedDuration, ...props }, ref) => {
5292
5296
  const {
5293
5297
  strings: {
5294
5298
  assistantMessage: { copy: { tooltip = "Copy" } = {} } = {}
5295
5299
  } = {}
5296
5300
  } = useThreadConfig();
5297
- return /* @__PURE__ */ jsx39(actionBar_exports.Copy, { asChild: true, children: /* @__PURE__ */ jsx39(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsxs4(Fragment5, { children: [
5301
+ return /* @__PURE__ */ jsx39(actionBar_exports.Copy, { copiedDuration, asChild: true, children: /* @__PURE__ */ jsx39(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsxs4(Fragment5, { children: [
5298
5302
  /* @__PURE__ */ jsx39(message_exports.If, { copied: true, children: /* @__PURE__ */ jsx39(CheckIcon, {}) }),
5299
5303
  /* @__PURE__ */ jsx39(message_exports.If, { copied: false, children: /* @__PURE__ */ jsx39(CopyIcon, {}) })
5300
5304
  ] }) }) });
@@ -5409,7 +5413,7 @@ var BranchPicker = () => {
5409
5413
  const allowBranchPicker = useAllowBranchPicker(true);
5410
5414
  if (!allowBranchPicker) return null;
5411
5415
  return /* @__PURE__ */ jsxs5(BranchPickerRoot, { hideWhenSingleBranch: true, children: [
5412
- /* @__PURE__ */ jsx40(BranchPickerPrevious2, {}),
5416
+ /* @__PURE__ */ jsx40(BranchPickerPrevious, {}),
5413
5417
  /* @__PURE__ */ jsx40(BranchPickerState, {}),
5414
5418
  /* @__PURE__ */ jsx40(BranchPickerNext, {})
5415
5419
  ] });
@@ -5419,7 +5423,7 @@ var BranchPickerRoot = withDefaults(branchPicker_exports.Root, {
5419
5423
  className: "aui-branch-picker-root"
5420
5424
  });
5421
5425
  BranchPickerRoot.displayName = "BranchPickerRoot";
5422
- var BranchPickerPrevious2 = forwardRef25((props, ref) => {
5426
+ var BranchPickerPrevious = forwardRef25((props, ref) => {
5423
5427
  const {
5424
5428
  strings: {
5425
5429
  branchPicker: { previous: { tooltip = "Previous" } = {} } = {}
@@ -5428,7 +5432,7 @@ var BranchPickerPrevious2 = forwardRef25((props, ref) => {
5428
5432
  const allowBranchPicker = useAllowBranchPicker();
5429
5433
  return /* @__PURE__ */ jsx40(branchPicker_exports.Previous, { disabled: !allowBranchPicker, asChild: true, children: /* @__PURE__ */ jsx40(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx40(ChevronLeftIcon, {}) }) });
5430
5434
  });
5431
- BranchPickerPrevious2.displayName = "BranchPickerPrevious";
5435
+ BranchPickerPrevious.displayName = "BranchPickerPrevious";
5432
5436
  var BranchPickerStateWrapper = withDefaults("span", {
5433
5437
  className: "aui-branch-picker-state"
5434
5438
  });
@@ -5450,7 +5454,7 @@ var BranchPickerNext = forwardRef25((props, ref) => {
5450
5454
  BranchPickerNext.displayName = "BranchPickerNext";
5451
5455
  var exports2 = {
5452
5456
  Root: BranchPickerRoot,
5453
- Previous: BranchPickerPrevious2,
5457
+ Previous: BranchPickerPrevious,
5454
5458
  Next: BranchPickerNext
5455
5459
  };
5456
5460
  var branch_picker_default = Object.assign(BranchPicker, exports2);
@@ -5591,12 +5595,30 @@ import { forwardRef as forwardRef27 } from "react";
5591
5595
  import { CircleXIcon } from "lucide-react";
5592
5596
  import { jsx as jsx45, jsxs as jsxs8 } from "react/jsx-runtime";
5593
5597
  var ComposerAttachmentRoot = withDefaults(attachment_exports.Root, {
5594
- className: "aui-composer-attachment-root"
5598
+ className: "aui-attachment-root"
5595
5599
  });
5596
5600
  ComposerAttachmentRoot.displayName = "ComposerAttachmentRoot";
5597
5601
  var ComposerAttachment2 = () => {
5602
+ const typeLabel = useAttachment((a) => {
5603
+ const type = a.type;
5604
+ switch (type) {
5605
+ case "image":
5606
+ return "Image";
5607
+ case "document":
5608
+ return "Document";
5609
+ case "file":
5610
+ return "File";
5611
+ default:
5612
+ const _exhaustiveCheck = type;
5613
+ throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
5614
+ }
5615
+ });
5598
5616
  return /* @__PURE__ */ jsxs8(ComposerAttachmentRoot, { children: [
5599
- /* @__PURE__ */ jsx45(attachment_exports.unstable_Thumb, {}),
5617
+ /* @__PURE__ */ jsx45(attachment_exports.unstable_Thumb, { className: "aui-attachment-thumb" }),
5618
+ /* @__PURE__ */ jsxs8("div", { className: "aui-attachment-text", children: [
5619
+ /* @__PURE__ */ jsx45("p", { className: "aui-attachment-name", children: /* @__PURE__ */ jsx45(attachment_exports.Name, {}) }),
5620
+ /* @__PURE__ */ jsx45("p", { className: "aui-attachment-type", children: typeLabel })
5621
+ ] }),
5600
5622
  /* @__PURE__ */ jsx45(ComposerAttachmentRemove, {})
5601
5623
  ] });
5602
5624
  };
@@ -5720,23 +5742,27 @@ var ComposerSendButton = withDefaults(TooltipIconButton, {
5720
5742
  variant: "default",
5721
5743
  className: "aui-composer-send"
5722
5744
  });
5723
- var ComposerSend = forwardRef28((props, ref) => {
5724
- const {
5725
- strings: { composer: { send: { tooltip = "Send" } = {} } = {} } = {}
5726
- } = useThreadConfig();
5727
- return /* @__PURE__ */ jsx46(composer_exports.Send, { asChild: true, children: /* @__PURE__ */ jsx46(ComposerSendButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx46(SendHorizontalIcon, {}) }) });
5728
- });
5745
+ var ComposerSend = forwardRef28(
5746
+ (props, ref) => {
5747
+ const {
5748
+ strings: { composer: { send: { tooltip = "Send" } = {} } = {} } = {}
5749
+ } = useThreadConfig();
5750
+ return /* @__PURE__ */ jsx46(composer_exports.Send, { asChild: true, children: /* @__PURE__ */ jsx46(ComposerSendButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx46(SendHorizontalIcon, {}) }) });
5751
+ }
5752
+ );
5729
5753
  ComposerSend.displayName = "ComposerSend";
5730
5754
  var ComposerCancelButton = withDefaults(TooltipIconButton, {
5731
5755
  variant: "default",
5732
5756
  className: "aui-composer-cancel"
5733
5757
  });
5734
- var ComposerCancel = forwardRef28((props, ref) => {
5735
- const {
5736
- strings: { composer: { cancel: { tooltip = "Cancel" } = {} } = {} } = {}
5737
- } = useThreadConfig();
5738
- return /* @__PURE__ */ jsx46(composer_exports.Cancel, { asChild: true, children: /* @__PURE__ */ jsx46(ComposerCancelButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx46(CircleStopIcon, {}) }) });
5739
- });
5758
+ var ComposerCancel = forwardRef28(
5759
+ (props, ref) => {
5760
+ const {
5761
+ strings: { composer: { cancel: { tooltip = "Cancel" } = {} } = {} } = {}
5762
+ } = useThreadConfig();
5763
+ return /* @__PURE__ */ jsx46(composer_exports.Cancel, { asChild: true, children: /* @__PURE__ */ jsx46(ComposerCancelButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx46(CircleStopIcon, {}) }) });
5764
+ }
5765
+ );
5740
5766
  ComposerCancel.displayName = "ComposerCancel";
5741
5767
  var exports6 = {
5742
5768
  Root: ComposerRoot,
@@ -5768,11 +5794,9 @@ var ThreadWelcomeRootStyled = withDefaults("div", {
5768
5794
  var ThreadWelcomeCenter = withDefaults("div", {
5769
5795
  className: "aui-thread-welcome-center"
5770
5796
  });
5771
- var ThreadWelcomeRoot = forwardRef29(
5772
- (props, ref) => {
5773
- return /* @__PURE__ */ jsx47(thread_exports.Empty, { children: /* @__PURE__ */ jsx47(ThreadWelcomeRootStyled, { ...props, ref }) });
5774
- }
5775
- );
5797
+ var ThreadWelcomeRoot = forwardRef29((props, ref) => {
5798
+ return /* @__PURE__ */ jsx47(thread_exports.Empty, { children: /* @__PURE__ */ jsx47(ThreadWelcomeRootStyled, { ...props, ref }) });
5799
+ });
5776
5800
  ThreadWelcomeRoot.displayName = "ThreadWelcomeRoot";
5777
5801
  var ThreadWelcomeAvatar = () => {
5778
5802
  const { assistantAvatar: avatar = { fallback: "A" } } = useThreadConfig();
@@ -5854,13 +5878,33 @@ var exports8 = {
5854
5878
  var user_action_bar_default = Object.assign(UserActionBar, exports8);
5855
5879
 
5856
5880
  // src/ui/user-message-attachment.tsx
5857
- import { jsx as jsx49 } from "react/jsx-runtime";
5881
+ import { jsx as jsx49, jsxs as jsxs11 } from "react/jsx-runtime";
5858
5882
  var UserMessageAttachmentRoot = withDefaults(attachment_exports.Root, {
5859
- className: "aui-user-message-attachment-root"
5883
+ className: "aui-attachment-root"
5860
5884
  });
5861
5885
  UserMessageAttachmentRoot.displayName = "UserMessageAttachmentRoot";
5862
5886
  var UserMessageAttachment = () => {
5863
- return /* @__PURE__ */ jsx49(UserMessageAttachmentRoot, { children: /* @__PURE__ */ jsx49(attachment_exports.unstable_Thumb, {}) });
5887
+ const typeLabel = useAttachment((a) => {
5888
+ const type = a.type;
5889
+ switch (type) {
5890
+ case "image":
5891
+ return "Image";
5892
+ case "document":
5893
+ return "Document";
5894
+ case "file":
5895
+ return "File";
5896
+ default:
5897
+ const _exhaustiveCheck = type;
5898
+ throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
5899
+ }
5900
+ });
5901
+ return /* @__PURE__ */ jsxs11(UserMessageAttachmentRoot, { children: [
5902
+ /* @__PURE__ */ jsx49(attachment_exports.unstable_Thumb, { className: "aui-attachment-thumb" }),
5903
+ /* @__PURE__ */ jsxs11("div", { className: "aui-attachment-text", children: [
5904
+ /* @__PURE__ */ jsx49("p", { className: "aui-attachment-name", children: /* @__PURE__ */ jsx49(attachment_exports.Name, {}) }),
5905
+ /* @__PURE__ */ jsx49("p", { className: "aui-attachment-type", children: typeLabel })
5906
+ ] })
5907
+ ] });
5864
5908
  };
5865
5909
  UserMessageAttachment.displayName = "UserMessageAttachment";
5866
5910
  var exports9 = {
@@ -5872,12 +5916,14 @@ var user_message_attachment_default = Object.assign(
5872
5916
  );
5873
5917
 
5874
5918
  // src/ui/user-message.tsx
5875
- import { jsx as jsx50, jsxs as jsxs11 } from "react/jsx-runtime";
5919
+ import { jsx as jsx50, jsxs as jsxs12 } from "react/jsx-runtime";
5876
5920
  var UserMessage = () => {
5877
- return /* @__PURE__ */ jsxs11(UserMessageRoot, { children: [
5921
+ return /* @__PURE__ */ jsxs12(UserMessageRoot, { children: [
5878
5922
  /* @__PURE__ */ jsx50(UserMessageAttachments, {}),
5879
- /* @__PURE__ */ jsx50(user_action_bar_default, {}),
5880
- /* @__PURE__ */ jsx50(UserMessageContent, {}),
5923
+ /* @__PURE__ */ jsxs12(message_exports.If, { hasContent: true, children: [
5924
+ /* @__PURE__ */ jsx50(user_action_bar_default, {}),
5925
+ /* @__PURE__ */ jsx50(UserMessageContent, {})
5926
+ ] }),
5881
5927
  /* @__PURE__ */ jsx50(branch_picker_default, {})
5882
5928
  ] });
5883
5929
  };
@@ -5889,19 +5935,17 @@ UserMessageRoot.displayName = "UserMessageRoot";
5889
5935
  var UserMessageContentWrapper = withDefaults("div", {
5890
5936
  className: "aui-user-message-content"
5891
5937
  });
5892
- var UserMessageContent = forwardRef31(
5893
- ({ components, ...props }, ref) => {
5894
- return /* @__PURE__ */ jsx50(UserMessageContentWrapper, { ...props, ref, children: /* @__PURE__ */ jsx50(
5895
- message_exports.Content,
5896
- {
5897
- components: {
5898
- ...components,
5899
- Text: components?.Text ?? content_part_default.Text
5900
- }
5938
+ var UserMessageContent = forwardRef31(({ components, ...props }, ref) => {
5939
+ return /* @__PURE__ */ jsx50(UserMessageContentWrapper, { ...props, ref, children: /* @__PURE__ */ jsx50(
5940
+ message_exports.Content,
5941
+ {
5942
+ components: {
5943
+ ...components,
5944
+ Text: components?.Text ?? content_part_default.Text
5901
5945
  }
5902
- ) });
5903
- }
5904
- );
5946
+ }
5947
+ ) });
5948
+ });
5905
5949
  UserMessageContent.displayName = "UserMessageContent";
5906
5950
  var UserMessageAttachmentsContainer = withDefaults("div", {
5907
5951
  className: "aui-user-message-attachments"
@@ -5928,11 +5972,11 @@ var user_message_default = Object.assign(UserMessage, exports10);
5928
5972
 
5929
5973
  // src/ui/edit-composer.tsx
5930
5974
  import { forwardRef as forwardRef32 } from "react";
5931
- import { jsx as jsx51, jsxs as jsxs12 } from "react/jsx-runtime";
5975
+ import { jsx as jsx51, jsxs as jsxs13 } from "react/jsx-runtime";
5932
5976
  var EditComposer = () => {
5933
- return /* @__PURE__ */ jsxs12(EditComposerRoot, { children: [
5977
+ return /* @__PURE__ */ jsxs13(EditComposerRoot, { children: [
5934
5978
  /* @__PURE__ */ jsx51(EditComposerInput, {}),
5935
- /* @__PURE__ */ jsxs12(EditComposerFooter, { children: [
5979
+ /* @__PURE__ */ jsxs13(EditComposerFooter, { children: [
5936
5980
  /* @__PURE__ */ jsx51(EditComposerCancel, {}),
5937
5981
  /* @__PURE__ */ jsx51(EditComposerSend, {})
5938
5982
  ] })
@@ -5951,25 +5995,19 @@ var EditComposerFooter = withDefaults("div", {
5951
5995
  className: "aui-edit-composer-footer"
5952
5996
  });
5953
5997
  EditComposerFooter.displayName = "EditComposerFooter";
5954
- var EditComposerCancel = forwardRef32(
5955
- (props, ref) => {
5956
- const {
5957
- strings: {
5958
- editComposer: { cancel: { label = "Cancel" } = {} } = {}
5959
- } = {}
5960
- } = useThreadConfig();
5961
- return /* @__PURE__ */ jsx51(composer_exports.Cancel, { asChild: true, children: /* @__PURE__ */ jsx51(Button, { variant: "ghost", ...props, ref, children: props.children ?? label }) });
5962
- }
5963
- );
5998
+ var EditComposerCancel = forwardRef32((props, ref) => {
5999
+ const {
6000
+ strings: { editComposer: { cancel: { label = "Cancel" } = {} } = {} } = {}
6001
+ } = useThreadConfig();
6002
+ return /* @__PURE__ */ jsx51(composer_exports.Cancel, { asChild: true, children: /* @__PURE__ */ jsx51(Button, { variant: "ghost", ...props, ref, children: props.children ?? label }) });
6003
+ });
5964
6004
  EditComposerCancel.displayName = "EditComposerCancel";
5965
- var EditComposerSend = forwardRef32(
5966
- (props, ref) => {
5967
- const {
5968
- strings: { editComposer: { send: { label = "Send" } = {} } = {} } = {}
5969
- } = useThreadConfig();
5970
- return /* @__PURE__ */ jsx51(composer_exports.Send, { asChild: true, children: /* @__PURE__ */ jsx51(Button, { ...props, ref, children: props.children ?? label }) });
5971
- }
5972
- );
6005
+ var EditComposerSend = forwardRef32((props, ref) => {
6006
+ const {
6007
+ strings: { editComposer: { send: { label = "Send" } = {} } = {} } = {}
6008
+ } = useThreadConfig();
6009
+ return /* @__PURE__ */ jsx51(composer_exports.Send, { asChild: true, children: /* @__PURE__ */ jsx51(Button, { ...props, ref, children: props.children ?? label }) });
6010
+ });
5973
6011
  EditComposerSend.displayName = "EditComposerSend";
5974
6012
  var exports11 = {
5975
6013
  Root: EditComposerRoot,
@@ -5981,7 +6019,7 @@ var exports11 = {
5981
6019
  var edit_composer_default = Object.assign(EditComposer, exports11);
5982
6020
 
5983
6021
  // src/ui/thread.tsx
5984
- import { Fragment as Fragment7, jsx as jsx52, jsxs as jsxs13 } from "react/jsx-runtime";
6022
+ import { Fragment as Fragment7, jsx as jsx52, jsxs as jsxs14 } from "react/jsx-runtime";
5985
6023
  var Thread = (config) => {
5986
6024
  const {
5987
6025
  components: {
@@ -5989,11 +6027,11 @@ var Thread = (config) => {
5989
6027
  ThreadWelcome: ThreadWelcomeComponent = thread_welcome_default
5990
6028
  } = {}
5991
6029
  } = config;
5992
- return /* @__PURE__ */ jsx52(ThreadRoot, { config, children: /* @__PURE__ */ jsxs13(ThreadViewport, { children: [
6030
+ return /* @__PURE__ */ jsx52(ThreadRoot, { config, children: /* @__PURE__ */ jsxs14(ThreadViewport, { children: [
5993
6031
  /* @__PURE__ */ jsx52(ThreadWelcomeComponent, {}),
5994
6032
  /* @__PURE__ */ jsx52(ThreadMessages, {}),
5995
6033
  /* @__PURE__ */ jsx52(ThreadFollowupSuggestions, {}),
5996
- /* @__PURE__ */ jsxs13(ThreadViewportFooter, { children: [
6034
+ /* @__PURE__ */ jsxs14(ThreadViewportFooter, { children: [
5997
6035
  /* @__PURE__ */ jsx52(ThreadScrollToBottom, {}),
5998
6036
  /* @__PURE__ */ jsx52(ComposerComponent, {})
5999
6037
  ] })
@@ -6018,7 +6056,7 @@ var ThreadViewportFooter = withDefaults("div", {
6018
6056
  ThreadViewportFooter.displayName = "ThreadViewportFooter";
6019
6057
  var SystemMessage = () => null;
6020
6058
  var ThreadMessages = ({ components, unstable_flexGrowDiv: flexGrowDiv = true, ...rest }) => {
6021
- return /* @__PURE__ */ jsxs13(Fragment7, { children: [
6059
+ return /* @__PURE__ */ jsxs14(Fragment7, { children: [
6022
6060
  /* @__PURE__ */ jsx52(
6023
6061
  thread_exports.Messages,
6024
6062
  {
@@ -6073,15 +6111,18 @@ var exports12 = {
6073
6111
  var thread_default = Object.assign(Thread, exports12);
6074
6112
 
6075
6113
  // src/ui/assistant-modal.tsx
6076
- import { Fragment as Fragment8, jsx as jsx53, jsxs as jsxs14 } from "react/jsx-runtime";
6114
+ import { Fragment as Fragment8, jsx as jsx53, jsxs as jsxs15 } from "react/jsx-runtime";
6077
6115
  var AssistantModal = (config) => {
6078
- return /* @__PURE__ */ jsxs14(AssistantModalRoot, { config, children: [
6116
+ return /* @__PURE__ */ jsxs15(AssistantModalRoot, { config, children: [
6079
6117
  /* @__PURE__ */ jsx53(AssistantModalTrigger, {}),
6080
6118
  /* @__PURE__ */ jsx53(AssistantModalContent, { children: /* @__PURE__ */ jsx53(thread_default, {}) })
6081
6119
  ] });
6082
6120
  };
6083
6121
  AssistantModal.displayName = "AssistantModal";
6084
- var AssistantModalRoot = ({ config, ...props }) => {
6122
+ var AssistantModalRoot = ({
6123
+ config,
6124
+ ...props
6125
+ }) => {
6085
6126
  return /* @__PURE__ */ jsx53(ThreadConfigProvider, { config, children: /* @__PURE__ */ jsx53(assistantModal_exports.Root, { ...props }) });
6086
6127
  };
6087
6128
  AssistantModalRoot.displayName = "AssistantModalRoot";
@@ -6119,7 +6160,7 @@ var AssistantModalButton = forwardRef34(({ "data-state": state, ...rest }, ref)
6119
6160
  "data-state": state,
6120
6161
  ...rest,
6121
6162
  ref,
6122
- children: rest.children ?? /* @__PURE__ */ jsxs14(Fragment8, { children: [
6163
+ children: rest.children ?? /* @__PURE__ */ jsxs15(Fragment8, { children: [
6123
6164
  /* @__PURE__ */ jsx53(
6124
6165
  BotIcon,
6125
6166
  {