@smartspace/chat-ui 1.14.4-pr.453.d6dd83a → 1.14.6-main.1a6776c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import MuiButton from '@mui/material/Button';
2
- import IconButton2 from '@mui/material/IconButton';
3
- import { Loader2, ChevronDown, Check, Cpu, SlidersHorizontal, X, Globe, Zap, Square, Mic, Paperclip, Send, Minimize2, AlertTriangle, FileImage, FileVideo, FileAudio, FileArchive, FileCode, FileSpreadsheet, Presentation, FileText, ChevronUp, ExternalLink, Download, ShieldAlert, Copy } from 'lucide-react';
2
+ import IconButton from '@mui/material/IconButton';
3
+ import { Loader2, ChevronDown, Check, Cpu, SlidersHorizontal, X, Globe, Zap, Paperclip, Mic, Square, Send, Minimize2, AlertTriangle, FileImage, FileVideo, FileAudio, FileArchive, FileCode, FileSpreadsheet, Presentation, FileText, ChevronUp, ExternalLink, Download, ShieldAlert, Copy } from 'lucide-react';
4
4
  import * as React9 from 'react';
5
5
  import React9__default, { createContext, forwardRef, useImperativeHandle, useRef, useState, useEffect, useMemo, useCallback, useContext, useSyncExternalStore } from 'react';
6
6
  import { createPortal } from 'react-dom';
@@ -17,7 +17,7 @@ import { codeBlockSchema, commonmark } from '@milkdown/preset-commonmark';
17
17
  import { Slice, NodeType } from '@milkdown/prose/model';
18
18
  import { MilkdownProvider, useEditor, Milkdown } from '@milkdown/react';
19
19
  import { PluginKey, Plugin } from '@milkdown/prose/state';
20
- import { DecorationSet, Decoration } from '@milkdown/prose/view';
20
+ import { Decoration, DecorationSet } from '@milkdown/prose/view';
21
21
  import 'crypto';
22
22
  import '@milkdown/prose';
23
23
  import '@milkdown/prose/inputrules';
@@ -842,37 +842,6 @@ function useMessages(threadId) {
842
842
  });
843
843
  }
844
844
 
845
- // src/domains/speech/queryKeys.ts
846
- var speechKeys = {
847
- all: ["speech"],
848
- config: () => [...speechKeys.all, "config"]
849
- };
850
-
851
- // src/domains/speech/queries.ts
852
- var unavailable = { enabled: false, defaultLocale: "en-US" };
853
- var isNotFound = (error) => error?.type === "NotFound" || error?.response?.status === 404;
854
- function useSpeechConfig() {
855
- const service = useChatService();
856
- const supported = !!service.getSpeechConfig && !!service.getSpeechToken;
857
- return useQuery({
858
- ...queryOptions({
859
- queryKey: speechKeys.config(),
860
- queryFn: async () => {
861
- try {
862
- return await service.getSpeechConfig?.() ?? unavailable;
863
- } catch (error) {
864
- if (isNotFound(error)) return unavailable;
865
- throw error;
866
- }
867
- },
868
- staleTime: Infinity,
869
- retry: (failureCount) => failureCount < 2,
870
- retryDelay: 1e3
871
- }),
872
- enabled: supported
873
- });
874
- }
875
-
876
845
  // ../../node_modules/.pnpm/@milkdown+exception@7.20.0/node_modules/@milkdown/exception/lib/index.js
877
846
  var ErrorCode = /* @__PURE__ */ (function(ErrorCode2) {
878
847
  ErrorCode2["docTypeError"] = "docTypeError";
@@ -1006,75 +975,6 @@ var autolink = $prose(() => {
1006
975
  }
1007
976
  });
1008
977
  });
1009
- var dictationGhostKey = new PluginKey("dictationGhost");
1010
- function buildDecorations2(state, text6) {
1011
- const doc = state.doc;
1012
- const from = state.selection.head;
1013
- const before = from > 0 ? doc.textBetween(from - 1, from, " ") : "";
1014
- const display = before !== "" && !/\s/.test(before) ? ` ${text6}` : text6;
1015
- const widget = Decoration.widget(
1016
- from,
1017
- () => {
1018
- const span = document.createElement("span");
1019
- span.className = "md-editor__dictation-ghost";
1020
- span.setAttribute("aria-hidden", "true");
1021
- span.appendChild(document.createTextNode(display));
1022
- const dots = document.createElement("span");
1023
- dots.className = "md-editor__dictation-dots";
1024
- for (let i = 0; i < 3; i += 1)
1025
- dots.appendChild(document.createElement("span"));
1026
- span.appendChild(dots);
1027
- return span;
1028
- },
1029
- {
1030
- // Render after the caret so typing still lands where the user expects.
1031
- side: 1,
1032
- // Keyed by content so ProseMirror reuses the node between renders instead
1033
- // of tearing it down on every interim result.
1034
- key: `dictation-ghost:${display}`
1035
- }
1036
- );
1037
- const decorations = [widget];
1038
- const $head = state.selection.$head;
1039
- if ($head.depth > 0) {
1040
- decorations.push(
1041
- Decoration.node($head.before(), $head.after(), {
1042
- class: "md-editor__has-dictation-ghost"
1043
- })
1044
- );
1045
- }
1046
- return DecorationSet.create(doc, decorations);
1047
- }
1048
- var dictationGhost = $prose(() => {
1049
- return new Plugin({
1050
- key: dictationGhostKey,
1051
- state: {
1052
- init: () => "",
1053
- apply(tr, previous2) {
1054
- const meta = tr.getMeta(dictationGhostKey);
1055
- if (meta) return meta.text;
1056
- if (tr.docChanged || tr.selectionSet) return "";
1057
- return previous2;
1058
- }
1059
- },
1060
- props: {
1061
- decorations(state) {
1062
- const text6 = dictationGhostKey.getState(state) ?? "";
1063
- if (!text6) return DecorationSet.empty;
1064
- return buildDecorations2(state, text6);
1065
- }
1066
- }
1067
- });
1068
- });
1069
- function setDictationGhost(view, text6) {
1070
- const current = dictationGhostKey.getState(view.state) ?? "";
1071
- if (current === text6) return;
1072
- const tr = view.state.tr.setMeta(dictationGhostKey, {
1073
- text: text6
1074
- });
1075
- tr.setMeta("addToHistory", false);
1076
- view.dispatch(tr);
1077
- }
1078
978
 
1079
979
  // src/shared/markdown/extensions/fileTag.ts
1080
980
  var fileTag = $node("fileTag", () => ({
@@ -1984,7 +1884,7 @@ function EditorInner({
1984
1884
  } catch {
1985
1885
  }
1986
1886
  });
1987
- }).use(commonmark).use(history).use(clipboard).use(listener).use(autolink).use(dictationGhost).use(fileTag).use(ssImageNode).use(ssImageView).use(htmlPreviewView).use(enableMentions ? mention : fileTag);
1887
+ }).use(commonmark).use(history).use(clipboard).use(listener).use(autolink).use(fileTag).use(ssImageNode).use(ssImageView).use(htmlPreviewView).use(enableMentions ? mention : fileTag);
1988
1888
  },
1989
1889
  [isEditable]
1990
1890
  );
@@ -2194,25 +2094,6 @@ function EditorInner({
2194
2094
  return value ?? "";
2195
2095
  }
2196
2096
  },
2197
- insertText: (text6) => {
2198
- const view = viewRef.current;
2199
- if (!view || !isEditable || !text6) return;
2200
- try {
2201
- const { from } = view.state.selection;
2202
- const before = from > 0 ? view.state.doc.textBetween(from - 1, from, " ") : "";
2203
- const needsSpace = before !== "" && !/\s/.test(before);
2204
- insertTextAtSelection(view, (needsSpace ? " " : "") + text6);
2205
- } catch {
2206
- }
2207
- },
2208
- setDictationGhost: (text6) => {
2209
- const view = viewRef.current;
2210
- if (!view || !isEditable) return;
2211
- try {
2212
- setDictationGhost(view, text6);
2213
- } catch {
2214
- }
2215
- },
2216
2097
  clear: () => {
2217
2098
  const view = viewRef.current;
2218
2099
  if (!view) return;
@@ -2556,237 +2437,6 @@ var MarkdownEditor = forwardRef((props, ref) => {
2556
2437
  return /* @__PURE__ */ jsx(MilkdownProvider, { children: /* @__PURE__ */ jsx(EditorInner, { ...props, editorHandleRef: ref }) });
2557
2438
  });
2558
2439
  MarkdownEditor.displayName = "MarkdownEditor";
2559
- var TOKEN_EXPIRY_MARGIN_MS = 15e3;
2560
- var STALE_TOKEN_FLOOR_MS = 6e4;
2561
- function kickOff(fn) {
2562
- let promise;
2563
- try {
2564
- promise = Promise.resolve(fn());
2565
- } catch (e) {
2566
- promise = Promise.reject(e);
2567
- }
2568
- promise.catch(() => void 0);
2569
- return promise;
2570
- }
2571
- var isSupported = () => typeof window !== "undefined" && window.isSecureContext && !!navigator.mediaDevices?.getUserMedia;
2572
- function classifyTokenFailure(error) {
2573
- const code3 = error?.code;
2574
- if (code3 === "SP500") return "unavailable";
2575
- if (error?.type === "NotFound") {
2576
- return "unavailable";
2577
- }
2578
- return "unavailable-temporarily";
2579
- }
2580
- function useDictation({
2581
- region,
2582
- locale,
2583
- getToken,
2584
- onPhrase,
2585
- onInterim,
2586
- maxDurationMs = 18e4,
2587
- idleTimeoutMs = 2e4
2588
- }) {
2589
- const [state, setState] = useState("idle");
2590
- const [error, setError] = useState(null);
2591
- const sessionRef = useRef(null);
2592
- const generationRef = useRef(0);
2593
- const onPhraseRef = useRef(onPhrase);
2594
- const onInterimRef = useRef(onInterim);
2595
- useEffect(() => {
2596
- onPhraseRef.current = onPhrase;
2597
- onInterimRef.current = onInterim;
2598
- });
2599
- const clearInterim = useCallback(() => onInterimRef.current?.(""), []);
2600
- const supported = isSupported();
2601
- const available = supported && !!region && !!getToken;
2602
- useEffect(() => {
2603
- if (!available) return;
2604
- const nav = navigator;
2605
- if (nav.connection?.saveData) return;
2606
- const warm = () => void kickOff(() => import('microsoft-cognitiveservices-speech-sdk'));
2607
- if (typeof window.requestIdleCallback === "function") {
2608
- const id2 = window.requestIdleCallback(warm, { timeout: 2e3 });
2609
- return () => window.cancelIdleCallback(id2);
2610
- }
2611
- const id = window.setTimeout(warm, 1500);
2612
- return () => window.clearTimeout(id);
2613
- }, [available]);
2614
- const stop = useCallback(() => {
2615
- generationRef.current += 1;
2616
- const session = sessionRef.current;
2617
- sessionRef.current = null;
2618
- clearInterim();
2619
- setState("idle");
2620
- if (!session) return;
2621
- window.clearTimeout(session.timers.idle);
2622
- window.clearTimeout(session.timers.max);
2623
- session.stream.getTracks().forEach((t) => t.stop());
2624
- session.recognizer.stopContinuousRecognitionAsync(
2625
- () => session.recognizer.close(),
2626
- () => session.recognizer.close()
2627
- );
2628
- }, [clearInterim]);
2629
- const start = useCallback(async () => {
2630
- if (!available || sessionRef.current) return;
2631
- const generation = ++generationRef.current;
2632
- const superseded = () => generationRef.current !== generation;
2633
- setError(null);
2634
- setState("starting");
2635
- const streamPromise = kickOff(
2636
- () => navigator.mediaDevices.getUserMedia({
2637
- audio: {
2638
- echoCancellation: true,
2639
- noiseSuppression: true,
2640
- autoGainControl: true
2641
- }
2642
- })
2643
- );
2644
- const tokenPromise = kickOff(getToken);
2645
- const sdkPromise = kickOff(
2646
- () => import('microsoft-cognitiveservices-speech-sdk')
2647
- );
2648
- let stream;
2649
- try {
2650
- stream = await streamPromise;
2651
- } catch (e) {
2652
- if (superseded()) return;
2653
- const name = e?.name;
2654
- setError(
2655
- name === "NotAllowedError" || name === "SecurityError" ? "permission-denied" : name === "NotFoundError" || name === "OverconstrainedError" ? "no-microphone" : "unknown"
2656
- );
2657
- setState("idle");
2658
- return;
2659
- }
2660
- if (superseded()) {
2661
- stream.getTracks().forEach((t) => t.stop());
2662
- return;
2663
- }
2664
- let token;
2665
- try {
2666
- token = await tokenPromise;
2667
- if (Date.parse(token.expiresOn) - Date.now() < STALE_TOKEN_FLOOR_MS) {
2668
- token = await getToken();
2669
- }
2670
- } catch (e) {
2671
- stream.getTracks().forEach((t) => t.stop());
2672
- if (superseded()) return;
2673
- setError(classifyTokenFailure(e));
2674
- setState("idle");
2675
- return;
2676
- }
2677
- if (superseded()) {
2678
- stream.getTracks().forEach((t) => t.stop());
2679
- return;
2680
- }
2681
- let recognizer = null;
2682
- let published = null;
2683
- try {
2684
- const sdk = await sdkPromise;
2685
- if (superseded()) {
2686
- stream.getTracks().forEach((t) => t.stop());
2687
- return;
2688
- }
2689
- const speechConfig = sdk.SpeechConfig.fromAuthorizationToken(
2690
- token.token,
2691
- region
2692
- );
2693
- speechConfig.speechRecognitionLanguage = locale;
2694
- speechConfig.setProfanity(sdk.ProfanityOption.Raw);
2695
- speechConfig.setProperty(
2696
- sdk.PropertyId.Speech_SegmentationSilenceTimeoutMs,
2697
- "700"
2698
- );
2699
- recognizer = new sdk.SpeechRecognizer(
2700
- speechConfig,
2701
- sdk.AudioConfig.fromStreamInput(stream)
2702
- );
2703
- const untilExpiry = Date.parse(token.expiresOn) - Date.now() - TOKEN_EXPIRY_MARGIN_MS;
2704
- const sessionCapMs = Number.isFinite(untilExpiry) && untilExpiry > 0 ? Math.min(maxDurationMs, untilExpiry) : maxDurationMs;
2705
- const session = { recognizer, stream, timers: {} };
2706
- const armIdle = () => {
2707
- window.clearTimeout(session.timers.idle);
2708
- session.timers.idle = window.setTimeout(stop, idleTimeoutMs);
2709
- };
2710
- const isLive = () => sessionRef.current === session;
2711
- sessionRef.current = session;
2712
- published = session;
2713
- const goLive = () => {
2714
- if (!isLive()) return;
2715
- session.timers.max ??= window.setTimeout(stop, sessionCapMs);
2716
- armIdle();
2717
- setState("listening");
2718
- };
2719
- recognizer.sessionStarted = () => goLive();
2720
- recognizer.recognizing = (_sender, event) => {
2721
- if (!isLive()) return;
2722
- onInterimRef.current?.(event.result.text ?? "");
2723
- armIdle();
2724
- };
2725
- recognizer.recognized = (_sender, event) => {
2726
- if (!isLive()) return;
2727
- const text6 = event.result.text?.trim();
2728
- clearInterim();
2729
- if (event.result.reason === sdk.ResultReason.RecognizedSpeech && text6) {
2730
- onPhraseRef.current(text6);
2731
- }
2732
- armIdle();
2733
- };
2734
- recognizer.canceled = (_sender, event) => {
2735
- if (!isLive()) return;
2736
- if (event.reason === sdk.CancellationReason.Error) {
2737
- console.warn("[dictation] cancelled, errorCode:", event.errorCode);
2738
- setError(
2739
- event.errorCode === sdk.CancellationErrorCode.ConnectionFailure ? "network" : event.errorCode === sdk.CancellationErrorCode.AuthenticationFailure ? "unavailable-temporarily" : "unknown"
2740
- );
2741
- }
2742
- stop();
2743
- };
2744
- recognizer.sessionStopped = () => {
2745
- if (isLive()) stop();
2746
- };
2747
- try {
2748
- const connection = sdk.Connection.fromRecognizer(recognizer);
2749
- connection.connected = () => goLive();
2750
- connection.openConnection();
2751
- } catch {
2752
- }
2753
- await new Promise(
2754
- (resolve, reject) => session.recognizer.startContinuousRecognitionAsync(resolve, reject)
2755
- );
2756
- goLive();
2757
- } catch (e) {
2758
- stream.getTracks().forEach((t) => t.stop());
2759
- try {
2760
- recognizer?.close();
2761
- } catch {
2762
- }
2763
- if (published) {
2764
- window.clearTimeout(published.timers.idle);
2765
- window.clearTimeout(published.timers.max);
2766
- if (sessionRef.current === published) sessionRef.current = null;
2767
- }
2768
- if (superseded()) return;
2769
- console.warn("[dictation] failed to start:", e);
2770
- setError((prev) => prev ?? "unavailable-temporarily");
2771
- setState("idle");
2772
- }
2773
- }, [
2774
- available,
2775
- clearInterim,
2776
- getToken,
2777
- idleTimeoutMs,
2778
- locale,
2779
- maxDurationMs,
2780
- region,
2781
- stop
2782
- ]);
2783
- useEffect(() => stop, [stop]);
2784
- const toggle = useCallback(() => {
2785
- if (state === "idle") void start();
2786
- else stop();
2787
- }, [start, state, stop]);
2788
- return { supported, available, state, error, start, stop, toggle };
2789
- }
2790
2440
  function useFlowRunVariables(flowRunId) {
2791
2441
  const service = useChatService();
2792
2442
  return useQuery({
@@ -4092,56 +3742,6 @@ var ChatVariablesForm = forwardRef(({ workspace, threadId, setVariables }, ref)
4092
3742
  ) }) })
4093
3743
  ] });
4094
3744
  });
4095
- var dictationErrorMessages = {
4096
- "permission-denied": "Microphone access is blocked \u2014 allow it in your browser settings and try again",
4097
- "no-microphone": "No microphone was found",
4098
- network: "Could not reach the speech service \u2014 try again",
4099
- "unavailable-temporarily": "Dictation is starting up \u2014 try again in a moment",
4100
- unavailable: "Dictation is not available on this workspace",
4101
- unknown: "Dictation stopped unexpectedly \u2014 try again"
4102
- };
4103
- function DictationButton({
4104
- state,
4105
- error,
4106
- disabled,
4107
- onToggle,
4108
- size = "sm"
4109
- }) {
4110
- const listening = state === "listening";
4111
- const starting = state === "starting";
4112
- const label = listening ? "Stop dictation" : "Dictate a message";
4113
- const dims = size === "sm" ? "h-8 w-8" : "h-9 w-9";
4114
- const icon = size === "sm" ? "h-4 w-4" : "h-5 w-5";
4115
- return /* @__PURE__ */ jsxs(
4116
- IconButton2,
4117
- {
4118
- type: "button",
4119
- onClick: onToggle,
4120
- disabled,
4121
- "aria-pressed": listening,
4122
- "aria-label": label,
4123
- title: error ? dictationErrorMessages[error] : label,
4124
- className: `relative ${dims} rounded-full transition-colors ${listening ? "bg-destructive text-destructive-foreground hover:bg-destructive/90" : "text-muted-foreground hover:bg-secondary"}`,
4125
- children: [
4126
- starting && /* @__PURE__ */ jsx(
4127
- "span",
4128
- {
4129
- "aria-hidden": "true",
4130
- className: "absolute inset-0 animate-spin rounded-full border-2 border-transparent border-t-current opacity-70"
4131
- }
4132
- ),
4133
- listening && /* @__PURE__ */ jsx(
4134
- "span",
4135
- {
4136
- "aria-hidden": "true",
4137
- className: "absolute inset-0 animate-ping rounded-full bg-destructive/30"
4138
- }
4139
- ),
4140
- listening ? /* @__PURE__ */ jsx(Square, { className: `relative ${icon} fill-current` }) : /* @__PURE__ */ jsx(Mic, { className: `relative ${icon}` })
4141
- ]
4142
- }
4143
- );
4144
- }
4145
3745
 
4146
3746
  // src/domains/workspaces/queryKeys.ts
4147
3747
  var workspaceKeys = {
@@ -4374,39 +3974,6 @@ function MessageComposer(_props = {}) {
4374
3974
  cancelReset();
4375
3975
  }
4376
3976
  }, [isSending, cancelAccepted, cancelErrored, cancelReset]);
4377
- const attachEditor = useCallback(
4378
- (handle2) => {
4379
- if (handle2) editorRef.current = handle2;
4380
- },
4381
- // Both flags matter: the portal mounts on `isMobile && isFullscreen`, and
4382
- // nothing resets isFullscreen when the breakpoint flips, so crossing it
4383
- // while fullscreen would unmount the portal editor without re-attaching the
4384
- // inline one — leaving a destroyed handle and silently swallowing phrases.
4385
- // eslint-disable-next-line react-hooks/exhaustive-deps
4386
- [isFullscreen, isMobile]
4387
- );
4388
- const { data: speechConfig } = useSpeechConfig();
4389
- const getSpeechToken = useMemo(
4390
- () => chatService.getSpeechToken?.bind(chatService),
4391
- [chatService]
4392
- );
4393
- const dictation = useDictation({
4394
- region: speechConfig?.enabled ? speechConfig.region : null,
4395
- locale: speechConfig?.defaultLocale ?? "en-US",
4396
- getToken: getSpeechToken,
4397
- // Final phrases become real text; provisional ones render as greyed ghost
4398
- // text at the caret and never enter the document.
4399
- onPhrase: (text6) => editorRef.current?.insertText(`${text6} `),
4400
- onInterim: (text6) => editorRef.current?.setDictationGhost(text6)
4401
- });
4402
- const { stop: stopDictation } = dictation;
4403
- const handleDictationToggle = () => {
4404
- if (dictation.state === "idle") editorRef.current?.focus();
4405
- dictation.toggle();
4406
- };
4407
- useEffect(() => {
4408
- if (disabled) stopDictation();
4409
- }, [disabled, stopDictation]);
4410
3977
  useEffect(() => {
4411
3978
  if (typeof window === "undefined") return;
4412
3979
  window.__ssDownloadFile = (id) => getFileBlobUrl(id);
@@ -4526,7 +4093,6 @@ function MessageComposer(_props = {}) {
4526
4093
  const latestText = editorRef.current?.getMarkdown() ?? newMessage;
4527
4094
  const sent = handleSendMessage(latestText, uploadedAttachments);
4528
4095
  if (!sent) return;
4529
- stopDictation();
4530
4096
  handleClearAttachments();
4531
4097
  setEditorKey((k) => k + 1);
4532
4098
  };
@@ -4633,7 +4199,7 @@ function MessageComposer(_props = {}) {
4633
4199
  /* @__PURE__ */ jsx("div", { className: "max-h-[400px] w-full overflow-y-auto", children: /* @__PURE__ */ jsx(
4634
4200
  MarkdownEditor,
4635
4201
  {
4636
- ref: attachEditor,
4202
+ ref: editorRef,
4637
4203
  value: newMessage,
4638
4204
  onChange: (md) => setNewMessage(md),
4639
4205
  onKeyDown: handleComposerKeyDown,
@@ -4650,12 +4216,10 @@ function MessageComposer(_props = {}) {
4650
4216
  },
4651
4217
  `composer-md-${editorKey}`
4652
4218
  ) }),
4653
- /* @__PURE__ */ jsx("div", { role: "status", className: "sr-only", children: dictation.state === "listening" ? "Listening" : dictation.state === "starting" ? "Starting dictation" : "" }),
4654
- dictation.error && /* @__PURE__ */ jsx("div", { role: "alert", className: "px-5 pb-1 text-xs text-destructive", children: dictationErrorMessages[dictation.error] }),
4655
4219
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-3 pb-3", children: [
4656
4220
  /* @__PURE__ */ jsxs("div", { className: "ss-composer__actions flex min-w-0 flex-1 items-center gap-1", children: [
4657
4221
  supportsFiles && /* @__PURE__ */ jsx(
4658
- IconButton2,
4222
+ IconButton,
4659
4223
  {
4660
4224
  type: "button",
4661
4225
  onClick: handlePickFilesClick,
@@ -4676,27 +4240,19 @@ function MessageComposer(_props = {}) {
4676
4240
  )
4677
4241
  ] }),
4678
4242
  /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [
4679
- dictation.available ? /* @__PURE__ */ jsx(
4680
- DictationButton,
4681
- {
4682
- state: dictation.state,
4683
- error: dictation.error,
4684
- disabled,
4685
- onToggle: handleDictationToggle
4686
- }
4687
- ) : /* @__PURE__ */ jsx(
4688
- IconButton2,
4243
+ /* @__PURE__ */ jsx(
4244
+ IconButton,
4689
4245
  {
4690
4246
  type: "button",
4691
4247
  disabled: true,
4692
4248
  "aria-label": "Dictate a message",
4693
- title: "Dictation is not available",
4249
+ title: "Dictation is not available yet",
4694
4250
  className: "h-8 w-8 cursor-not-allowed rounded-full text-muted-foreground",
4695
4251
  children: /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" })
4696
4252
  }
4697
4253
  ),
4698
4254
  canStop ? /* @__PURE__ */ jsx(
4699
- IconButton2,
4255
+ IconButton,
4700
4256
  {
4701
4257
  onClick: handleStopRun,
4702
4258
  className: "chat-send h-8 w-8 rounded-full",
@@ -4710,7 +4266,7 @@ function MessageComposer(_props = {}) {
4710
4266
  )
4711
4267
  }
4712
4268
  ) : /* @__PURE__ */ jsx(
4713
- IconButton2,
4269
+ IconButton,
4714
4270
  {
4715
4271
  onClick: handleSendMessageAndClear,
4716
4272
  className: `chat-send h-8 w-8 rounded-full ${sendDisabled ? "cursor-not-allowed" : ""}`,
@@ -4739,7 +4295,7 @@ function MessageComposer(_props = {}) {
4739
4295
  },
4740
4296
  children: /* @__PURE__ */ jsxs("div", { className: "relative h-full w-full bg-background border shadow-lg", children: [
4741
4297
  /* @__PURE__ */ jsx(
4742
- IconButton2,
4298
+ IconButton,
4743
4299
  {
4744
4300
  type: "button",
4745
4301
  size: "small",
@@ -4757,7 +4313,7 @@ function MessageComposer(_props = {}) {
4757
4313
  /* @__PURE__ */ jsx("div", { className: "flex-1 p-4", children: /* @__PURE__ */ jsx(
4758
4314
  MarkdownEditor,
4759
4315
  {
4760
- ref: attachEditor,
4316
+ ref: editorRef,
4761
4317
  value: newMessage,
4762
4318
  onChange: (md) => setNewMessage(md),
4763
4319
  onKeyDown: handleComposerKeyDown,
@@ -4772,18 +4328,10 @@ function MessageComposer(_props = {}) {
4772
4328
  },
4773
4329
  `composer-md-${editorKey}`
4774
4330
  ) }),
4775
- dictation.error && /* @__PURE__ */ jsx(
4776
- "div",
4777
- {
4778
- "aria-hidden": "true",
4779
- className: "px-4 pb-1 text-xs text-destructive",
4780
- children: dictationErrorMessages[dictation.error]
4781
- }
4782
- ),
4783
4331
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-t bg-background", children: [
4784
4332
  /* @__PURE__ */ jsx("div", { className: "flex-1" }),
4785
4333
  supportsFiles && /* @__PURE__ */ jsx(
4786
- IconButton2,
4334
+ IconButton,
4787
4335
  {
4788
4336
  type: "button",
4789
4337
  onClick: handlePickFilesClick,
@@ -4798,18 +4346,8 @@ function MessageComposer(_props = {}) {
4798
4346
  )
4799
4347
  }
4800
4348
  ),
4801
- dictation.available && /* @__PURE__ */ jsx(
4802
- DictationButton,
4803
- {
4804
- size: "md",
4805
- state: dictation.state,
4806
- error: dictation.error,
4807
- disabled,
4808
- onToggle: handleDictationToggle
4809
- }
4810
- ),
4811
4349
  canStop ? /* @__PURE__ */ jsx(
4812
- IconButton2,
4350
+ IconButton,
4813
4351
  {
4814
4352
  onClick: handleStopRun,
4815
4353
  className: "chat-send h-9 w-9 rounded-full",
@@ -4823,7 +4361,7 @@ function MessageComposer(_props = {}) {
4823
4361
  )
4824
4362
  }
4825
4363
  ) : /* @__PURE__ */ jsx(
4826
- IconButton2,
4364
+ IconButton,
4827
4365
  {
4828
4366
  onClick: handleSendMessageAndClear,
4829
4367
  className: `chat-send h-9 w-9 rounded-full ${sendDisabled ? "cursor-not-allowed" : ""}`,
@@ -21158,6 +20696,6 @@ function getUserPhotoUrl(userId) {
21158
20696
  return `${base2}/users/${userId}/photo`;
21159
20697
  }
21160
20698
 
21161
- export { ChatProvider, ChatVariablesForm, DRAFT_THREAD_PREFIX, DateFromApi, DictationButton, MarkdownEditor, MessageComposer, MessageList, MessageListSkeleton, MessageMarkdown, MessageValueType, NEW_THREAD_ID, THREAD_LIST_PAGE_SIZE, applyDeltaToMessage, applyThreadToCache, createDraftThreadId, createThreadId, downloadFileBlobOptions, filesKeys, flowRunsKeys, getMessageErrorText, getModelIcon, getRetryStatusText, getThreadPlaceholderFromListCache, getUserPhotoUrl, invalidateWorkspaceThreadLists, isDraftThreadId, mapFileInfoDtoToModel, mapMentionUserDtoToModel, mapMessageDtoToModel, mapMessageErrorDtoToModel, mapMessageValueDtoToModel, mapMessagesDtoToModels, mapSignalRThreadSummaryToModel, mapThreadDtoToModel, mapThreadsResponseDtoToModel, mapWorkspaceDtoToModel, mapWorkspacesDtoToModels, markDraftThreadId, messagesKeys, messagesListOptions, messagesMutationsKeys, modelsKeys, parseDateTime, parseDateTimeHuman, parseRetryStatus, randomUUID, setThreadOptimisticRunning, setThreadRunningInLists, speechKeys, taggableUsersOptions, threadDetailOptions, threadsKeys, unmarkDraftThreadId, useAddInputToMessage, useChatContext, useChatIdentity, useChatService, useDictation, useDownloadFileBlobQuery, useFileMutations, useFlowRunVariables, useIsDraftThreadId, useMessages, useModels, useSendMessage, useSpeechConfig, useTaggableWorkspaceUsers, useThread, useThreadIsRunning, useUpdateFlowRunVariable, useWorkspace, utcDate, workspaceDetailOptions, workspaceKeys };
20699
+ export { ChatProvider, ChatVariablesForm, DRAFT_THREAD_PREFIX, DateFromApi, MarkdownEditor, MessageComposer, MessageList, MessageListSkeleton, MessageMarkdown, MessageValueType, NEW_THREAD_ID, THREAD_LIST_PAGE_SIZE, applyDeltaToMessage, applyThreadToCache, createDraftThreadId, createThreadId, downloadFileBlobOptions, filesKeys, flowRunsKeys, getMessageErrorText, getModelIcon, getRetryStatusText, getThreadPlaceholderFromListCache, getUserPhotoUrl, invalidateWorkspaceThreadLists, isDraftThreadId, mapFileInfoDtoToModel, mapMentionUserDtoToModel, mapMessageDtoToModel, mapMessageErrorDtoToModel, mapMessageValueDtoToModel, mapMessagesDtoToModels, mapSignalRThreadSummaryToModel, mapThreadDtoToModel, mapThreadsResponseDtoToModel, mapWorkspaceDtoToModel, mapWorkspacesDtoToModels, markDraftThreadId, messagesKeys, messagesListOptions, messagesMutationsKeys, modelsKeys, parseDateTime, parseDateTimeHuman, parseRetryStatus, randomUUID, setThreadOptimisticRunning, setThreadRunningInLists, taggableUsersOptions, threadDetailOptions, threadsKeys, unmarkDraftThreadId, useAddInputToMessage, useChatContext, useChatIdentity, useChatService, useDownloadFileBlobQuery, useFileMutations, useFlowRunVariables, useIsDraftThreadId, useMessages, useModels, useSendMessage, useTaggableWorkspaceUsers, useThread, useThreadIsRunning, useUpdateFlowRunVariable, useWorkspace, utcDate, workspaceDetailOptions, workspaceKeys };
21162
20700
  //# sourceMappingURL=index.js.map
21163
20701
  //# sourceMappingURL=index.js.map