@smartspace/chat-ui 1.14.4-dev.4755c72 → 1.14.4-dev.4d23cd2
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.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +155 -1
- package/dist/index.js +1390 -519
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import MuiButton from '@mui/material/Button';
|
|
2
|
-
import
|
|
3
|
-
import { Loader2,
|
|
4
|
-
import * as
|
|
5
|
-
import { createContext, forwardRef, useImperativeHandle, useRef, useState, useEffect, useMemo, useCallback, useContext, useSyncExternalStore } from 'react';
|
|
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, ChevronRight, ChevronUp, ExternalLink, Download, ShieldAlert, Copy } from 'lucide-react';
|
|
4
|
+
import * as React9 from 'react';
|
|
5
|
+
import React9__default, { createContext, forwardRef, useImperativeHandle, useRef, useState, useEffect, useMemo, useCallback, useContext, useSyncExternalStore, Fragment as Fragment$1 } from 'react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
|
-
import { useQuery, queryOptions, useQueryClient, useMutation
|
|
8
|
+
import { useQuery, queryOptions, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
9
9
|
import { toast } from 'sonner';
|
|
10
10
|
import { ChatZod } from '@smartspace/api-client';
|
|
11
11
|
import { z } from 'zod';
|
|
@@ -17,14 +17,13 @@ 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 {
|
|
20
|
+
import { DecorationSet, Decoration } from '@milkdown/prose/view';
|
|
21
21
|
import 'crypto';
|
|
22
22
|
import '@milkdown/prose';
|
|
23
23
|
import '@milkdown/prose/inputrules';
|
|
24
24
|
import { withJsonFormsControlProps, withJsonFormsLayoutProps, JsonForms, ResolvedJsonFormsDispatch } from '@jsonforms/react';
|
|
25
25
|
import { rankWith, uiTypeIs, createAjv } from '@jsonforms/core';
|
|
26
26
|
import { vanillaRenderers, vanillaCells } from '@jsonforms/vanilla-renderers';
|
|
27
|
-
import { FormControl, InputLabel, Select, MenuItem, useTheme, Box, Skeleton as Skeleton$1 } from '@mui/material';
|
|
28
27
|
import 'ace-builds/src-noconflict/ace';
|
|
29
28
|
import 'ace-builds/src-noconflict/ext-language_tools';
|
|
30
29
|
import 'ace-builds/src-noconflict/mode-json';
|
|
@@ -57,6 +56,7 @@ import relativeTime from 'dayjs/plugin/relativeTime';
|
|
|
57
56
|
import utc from 'dayjs/plugin/utc';
|
|
58
57
|
import { Slot } from '@radix-ui/react-slot';
|
|
59
58
|
import { cva } from 'class-variance-authority';
|
|
59
|
+
import { useTheme, Box, Skeleton as Skeleton$1 } from '@mui/material';
|
|
60
60
|
|
|
61
61
|
var __defProp = Object.defineProperty;
|
|
62
62
|
var __export = (target, all5) => {
|
|
@@ -365,6 +365,19 @@ var MessageValueType = /* @__PURE__ */ ((MessageValueType2) => {
|
|
|
365
365
|
MessageValueType2["INPUT"] = "Input";
|
|
366
366
|
return MessageValueType2;
|
|
367
367
|
})(MessageValueType || {});
|
|
368
|
+
var MessageResponseSourceType = /* @__PURE__ */ ((MessageResponseSourceType2) => {
|
|
369
|
+
MessageResponseSourceType2["BlobInternal"] = "BlobInternal";
|
|
370
|
+
MessageResponseSourceType2["WebExternal"] = "WebExternal";
|
|
371
|
+
MessageResponseSourceType2["File"] = "File";
|
|
372
|
+
MessageResponseSourceType2["URL"] = "URL";
|
|
373
|
+
return MessageResponseSourceType2;
|
|
374
|
+
})(MessageResponseSourceType || {});
|
|
375
|
+
var MessageAttribution = /* @__PURE__ */ ((MessageAttribution2) => {
|
|
376
|
+
MessageAttribution2["Supported"] = "supported";
|
|
377
|
+
MessageAttribution2["Partial"] = "partial";
|
|
378
|
+
MessageAttribution2["Unsupported"] = "unsupported";
|
|
379
|
+
return MessageAttribution2;
|
|
380
|
+
})(MessageAttribution || {});
|
|
368
381
|
|
|
369
382
|
// src/domains/threads/queryKeys.ts
|
|
370
383
|
var THREAD_LIST_PAGE_SIZE = 30;
|
|
@@ -587,9 +600,14 @@ var useThread = ({
|
|
|
587
600
|
};
|
|
588
601
|
var useThreadIsRunning = (workspaceId, threadId) => {
|
|
589
602
|
const queryClient = useQueryClient();
|
|
603
|
+
const service = useChatService();
|
|
590
604
|
const { data: detailThread } = useQuery({
|
|
591
|
-
|
|
592
|
-
|
|
605
|
+
...threadDetailOptions({
|
|
606
|
+
service,
|
|
607
|
+
workspaceId: workspaceId ?? "",
|
|
608
|
+
threadId: threadId ?? ""
|
|
609
|
+
}),
|
|
610
|
+
enabled: false
|
|
593
611
|
});
|
|
594
612
|
const listThread = workspaceId && threadId ? getThreadPlaceholderFromListCache(queryClient, workspaceId, threadId) : void 0;
|
|
595
613
|
const { data: optimistic } = useQuery({
|
|
@@ -824,6 +842,37 @@ function useMessages(threadId) {
|
|
|
824
842
|
});
|
|
825
843
|
}
|
|
826
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
|
+
|
|
827
876
|
// ../../node_modules/.pnpm/@milkdown+exception@7.20.0/node_modules/@milkdown/exception/lib/index.js
|
|
828
877
|
var ErrorCode = /* @__PURE__ */ (function(ErrorCode2) {
|
|
829
878
|
ErrorCode2["docTypeError"] = "docTypeError";
|
|
@@ -957,6 +1006,75 @@ var autolink = $prose(() => {
|
|
|
957
1006
|
}
|
|
958
1007
|
});
|
|
959
1008
|
});
|
|
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
|
+
}
|
|
960
1078
|
|
|
961
1079
|
// src/shared/markdown/extensions/fileTag.ts
|
|
962
1080
|
var fileTag = $node("fileTag", () => ({
|
|
@@ -1866,7 +1984,7 @@ function EditorInner({
|
|
|
1866
1984
|
} catch {
|
|
1867
1985
|
}
|
|
1868
1986
|
});
|
|
1869
|
-
}).use(commonmark).use(history).use(clipboard).use(listener).use(autolink).use(fileTag).use(ssImageNode).use(ssImageView).use(htmlPreviewView).use(enableMentions ? mention : fileTag);
|
|
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);
|
|
1870
1988
|
},
|
|
1871
1989
|
[isEditable]
|
|
1872
1990
|
);
|
|
@@ -2076,6 +2194,25 @@ function EditorInner({
|
|
|
2076
2194
|
return value ?? "";
|
|
2077
2195
|
}
|
|
2078
2196
|
},
|
|
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
|
+
},
|
|
2079
2216
|
clear: () => {
|
|
2080
2217
|
const view = viewRef.current;
|
|
2081
2218
|
if (!view) return;
|
|
@@ -2419,6 +2556,326 @@ var MarkdownEditor = forwardRef((props, ref) => {
|
|
|
2419
2556
|
return /* @__PURE__ */ jsx(MilkdownProvider, { children: /* @__PURE__ */ jsx(EditorInner, { ...props, editorHandleRef: ref }) });
|
|
2420
2557
|
});
|
|
2421
2558
|
MarkdownEditor.displayName = "MarkdownEditor";
|
|
2559
|
+
var TOKEN_EXPIRY_MARGIN_MS = 15e3;
|
|
2560
|
+
var noLevelMonitor = () => void 0;
|
|
2561
|
+
var SILENCE_HINT_MS = 6e3;
|
|
2562
|
+
var SILENCE_LEVEL = 3;
|
|
2563
|
+
function monitorInputLevel(stream, onSilent, onSound) {
|
|
2564
|
+
let context;
|
|
2565
|
+
let source;
|
|
2566
|
+
let analyser;
|
|
2567
|
+
try {
|
|
2568
|
+
context = new AudioContext();
|
|
2569
|
+
source = context.createMediaStreamSource(stream);
|
|
2570
|
+
analyser = context.createAnalyser();
|
|
2571
|
+
analyser.fftSize = 512;
|
|
2572
|
+
source.connect(analyser);
|
|
2573
|
+
} catch {
|
|
2574
|
+
return () => void 0;
|
|
2575
|
+
}
|
|
2576
|
+
if (context.state === "suspended")
|
|
2577
|
+
void context.resume().catch(() => void 0);
|
|
2578
|
+
const samples = new Uint8Array(analyser.fftSize);
|
|
2579
|
+
let lastSound = Date.now();
|
|
2580
|
+
let silent = false;
|
|
2581
|
+
let stopped = false;
|
|
2582
|
+
const poll = window.setInterval(() => {
|
|
2583
|
+
if (context.state !== "running") return;
|
|
2584
|
+
analyser.getByteTimeDomainData(samples);
|
|
2585
|
+
let peak = 0;
|
|
2586
|
+
for (const sample of samples) peak = Math.max(peak, Math.abs(sample - 128));
|
|
2587
|
+
if (peak > SILENCE_LEVEL) {
|
|
2588
|
+
lastSound = Date.now();
|
|
2589
|
+
if (silent) {
|
|
2590
|
+
silent = false;
|
|
2591
|
+
onSound();
|
|
2592
|
+
}
|
|
2593
|
+
} else if (!silent && Date.now() - lastSound > SILENCE_HINT_MS) {
|
|
2594
|
+
silent = true;
|
|
2595
|
+
onSilent();
|
|
2596
|
+
}
|
|
2597
|
+
}, 250);
|
|
2598
|
+
return () => {
|
|
2599
|
+
if (stopped) return;
|
|
2600
|
+
stopped = true;
|
|
2601
|
+
window.clearInterval(poll);
|
|
2602
|
+
try {
|
|
2603
|
+
source.disconnect();
|
|
2604
|
+
void context.close().catch(() => void 0);
|
|
2605
|
+
} catch {
|
|
2606
|
+
}
|
|
2607
|
+
};
|
|
2608
|
+
}
|
|
2609
|
+
var STALE_TOKEN_FLOOR_MS = 6e4;
|
|
2610
|
+
function kickOff(fn) {
|
|
2611
|
+
let promise;
|
|
2612
|
+
try {
|
|
2613
|
+
promise = Promise.resolve(fn());
|
|
2614
|
+
} catch (e) {
|
|
2615
|
+
promise = Promise.reject(e);
|
|
2616
|
+
}
|
|
2617
|
+
promise.catch(() => void 0);
|
|
2618
|
+
return promise;
|
|
2619
|
+
}
|
|
2620
|
+
var isSupported = () => typeof window !== "undefined" && window.isSecureContext && !!navigator.mediaDevices?.getUserMedia;
|
|
2621
|
+
function classifyTokenFailure(error) {
|
|
2622
|
+
const code3 = error?.code;
|
|
2623
|
+
if (code3 === "SP500") return "unavailable";
|
|
2624
|
+
if (error?.type === "NotFound") {
|
|
2625
|
+
return "unavailable";
|
|
2626
|
+
}
|
|
2627
|
+
return "unavailable-temporarily";
|
|
2628
|
+
}
|
|
2629
|
+
function useDictation({
|
|
2630
|
+
region,
|
|
2631
|
+
locale,
|
|
2632
|
+
getToken,
|
|
2633
|
+
onPhrase,
|
|
2634
|
+
onInterim,
|
|
2635
|
+
maxDurationMs = 18e4,
|
|
2636
|
+
idleTimeoutMs = 2e4
|
|
2637
|
+
}) {
|
|
2638
|
+
const [state, setState] = useState("idle");
|
|
2639
|
+
const [error, setError] = useState(null);
|
|
2640
|
+
const [deviceLabel, setDeviceLabel] = useState("");
|
|
2641
|
+
const [silent, setSilent] = useState(false);
|
|
2642
|
+
const sessionRef = useRef(null);
|
|
2643
|
+
const generationRef = useRef(0);
|
|
2644
|
+
const onPhraseRef = useRef(onPhrase);
|
|
2645
|
+
const onInterimRef = useRef(onInterim);
|
|
2646
|
+
useEffect(() => {
|
|
2647
|
+
onPhraseRef.current = onPhrase;
|
|
2648
|
+
onInterimRef.current = onInterim;
|
|
2649
|
+
});
|
|
2650
|
+
const clearInterim = useCallback(() => onInterimRef.current?.(""), []);
|
|
2651
|
+
const supported = isSupported();
|
|
2652
|
+
const available = supported && !!region && !!getToken;
|
|
2653
|
+
useEffect(() => {
|
|
2654
|
+
if (!available) return;
|
|
2655
|
+
const nav = navigator;
|
|
2656
|
+
if (nav.connection?.saveData) return;
|
|
2657
|
+
const warm = () => void kickOff(() => import('microsoft-cognitiveservices-speech-sdk'));
|
|
2658
|
+
if (typeof window.requestIdleCallback === "function") {
|
|
2659
|
+
const id2 = window.requestIdleCallback(warm, { timeout: 2e3 });
|
|
2660
|
+
return () => window.cancelIdleCallback(id2);
|
|
2661
|
+
}
|
|
2662
|
+
const id = window.setTimeout(warm, 1500);
|
|
2663
|
+
return () => window.clearTimeout(id);
|
|
2664
|
+
}, [available]);
|
|
2665
|
+
const stop = useCallback(() => {
|
|
2666
|
+
generationRef.current += 1;
|
|
2667
|
+
const session = sessionRef.current;
|
|
2668
|
+
sessionRef.current = null;
|
|
2669
|
+
clearInterim();
|
|
2670
|
+
setState("idle");
|
|
2671
|
+
setSilent(false);
|
|
2672
|
+
setDeviceLabel("");
|
|
2673
|
+
if (!session) return;
|
|
2674
|
+
window.clearTimeout(session.timers.idle);
|
|
2675
|
+
window.clearTimeout(session.timers.max);
|
|
2676
|
+
session.stopLevelMonitor();
|
|
2677
|
+
session.stream.getTracks().forEach((t) => t.stop());
|
|
2678
|
+
session.recognizer.stopContinuousRecognitionAsync(
|
|
2679
|
+
() => session.recognizer.close(),
|
|
2680
|
+
() => session.recognizer.close()
|
|
2681
|
+
);
|
|
2682
|
+
}, [clearInterim]);
|
|
2683
|
+
const start = useCallback(async () => {
|
|
2684
|
+
if (!available || sessionRef.current) return;
|
|
2685
|
+
const generation = ++generationRef.current;
|
|
2686
|
+
const superseded = () => generationRef.current !== generation;
|
|
2687
|
+
setError(null);
|
|
2688
|
+
setSilent(false);
|
|
2689
|
+
setState("starting");
|
|
2690
|
+
const streamPromise = kickOff(
|
|
2691
|
+
() => navigator.mediaDevices.getUserMedia({
|
|
2692
|
+
audio: {
|
|
2693
|
+
echoCancellation: true,
|
|
2694
|
+
noiseSuppression: true,
|
|
2695
|
+
autoGainControl: true
|
|
2696
|
+
}
|
|
2697
|
+
})
|
|
2698
|
+
);
|
|
2699
|
+
const tokenPromise = kickOff(getToken);
|
|
2700
|
+
const sdkPromise = kickOff(
|
|
2701
|
+
() => import('microsoft-cognitiveservices-speech-sdk')
|
|
2702
|
+
);
|
|
2703
|
+
let stream;
|
|
2704
|
+
try {
|
|
2705
|
+
stream = await streamPromise;
|
|
2706
|
+
} catch (e) {
|
|
2707
|
+
if (superseded()) return;
|
|
2708
|
+
const name = e?.name;
|
|
2709
|
+
setError(
|
|
2710
|
+
name === "NotAllowedError" || name === "SecurityError" ? "permission-denied" : name === "NotFoundError" || name === "OverconstrainedError" ? "no-microphone" : "unknown"
|
|
2711
|
+
);
|
|
2712
|
+
setState("idle");
|
|
2713
|
+
return;
|
|
2714
|
+
}
|
|
2715
|
+
if (superseded()) {
|
|
2716
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2717
|
+
return;
|
|
2718
|
+
}
|
|
2719
|
+
let token;
|
|
2720
|
+
try {
|
|
2721
|
+
token = await tokenPromise;
|
|
2722
|
+
if (Date.parse(token.expiresOn) - Date.now() < STALE_TOKEN_FLOOR_MS) {
|
|
2723
|
+
token = await getToken();
|
|
2724
|
+
}
|
|
2725
|
+
} catch (e) {
|
|
2726
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2727
|
+
if (superseded()) return;
|
|
2728
|
+
setError(classifyTokenFailure(e));
|
|
2729
|
+
setState("idle");
|
|
2730
|
+
return;
|
|
2731
|
+
}
|
|
2732
|
+
if (superseded()) {
|
|
2733
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2734
|
+
return;
|
|
2735
|
+
}
|
|
2736
|
+
let recognizer = null;
|
|
2737
|
+
let published = null;
|
|
2738
|
+
try {
|
|
2739
|
+
const sdk = await sdkPromise;
|
|
2740
|
+
if (superseded()) {
|
|
2741
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2742
|
+
return;
|
|
2743
|
+
}
|
|
2744
|
+
const speechConfig = sdk.SpeechConfig.fromAuthorizationToken(
|
|
2745
|
+
token.token,
|
|
2746
|
+
region
|
|
2747
|
+
);
|
|
2748
|
+
speechConfig.speechRecognitionLanguage = locale;
|
|
2749
|
+
speechConfig.setProfanity(sdk.ProfanityOption.Raw);
|
|
2750
|
+
speechConfig.setProperty(
|
|
2751
|
+
sdk.PropertyId.Speech_SegmentationSilenceTimeoutMs,
|
|
2752
|
+
"700"
|
|
2753
|
+
);
|
|
2754
|
+
recognizer = new sdk.SpeechRecognizer(
|
|
2755
|
+
speechConfig,
|
|
2756
|
+
sdk.AudioConfig.fromStreamInput(stream)
|
|
2757
|
+
);
|
|
2758
|
+
const untilExpiry = Date.parse(token.expiresOn) - Date.now() - TOKEN_EXPIRY_MARGIN_MS;
|
|
2759
|
+
const sessionCapMs = Number.isFinite(untilExpiry) && untilExpiry > 0 ? Math.min(maxDurationMs, untilExpiry) : maxDurationMs;
|
|
2760
|
+
const session = {
|
|
2761
|
+
recognizer,
|
|
2762
|
+
stream,
|
|
2763
|
+
timers: {},
|
|
2764
|
+
stopLevelMonitor: noLevelMonitor
|
|
2765
|
+
};
|
|
2766
|
+
const armIdle = () => {
|
|
2767
|
+
window.clearTimeout(session.timers.idle);
|
|
2768
|
+
session.timers.idle = window.setTimeout(stop, idleTimeoutMs);
|
|
2769
|
+
};
|
|
2770
|
+
const isLive = () => sessionRef.current === session;
|
|
2771
|
+
sessionRef.current = session;
|
|
2772
|
+
published = session;
|
|
2773
|
+
const goLive = () => {
|
|
2774
|
+
if (!isLive()) return;
|
|
2775
|
+
session.timers.max ??= window.setTimeout(stop, sessionCapMs);
|
|
2776
|
+
if (session.stopLevelMonitor === noLevelMonitor) {
|
|
2777
|
+
try {
|
|
2778
|
+
setDeviceLabel(stream.getAudioTracks()[0]?.label ?? "");
|
|
2779
|
+
session.stopLevelMonitor = monitorInputLevel(
|
|
2780
|
+
stream,
|
|
2781
|
+
() => {
|
|
2782
|
+
if (isLive()) setSilent(true);
|
|
2783
|
+
},
|
|
2784
|
+
() => {
|
|
2785
|
+
if (isLive()) setSilent(false);
|
|
2786
|
+
}
|
|
2787
|
+
);
|
|
2788
|
+
} catch {
|
|
2789
|
+
session.stopLevelMonitor = noLevelMonitor;
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
armIdle();
|
|
2793
|
+
setState("listening");
|
|
2794
|
+
};
|
|
2795
|
+
recognizer.sessionStarted = () => goLive();
|
|
2796
|
+
recognizer.recognizing = (_sender, event) => {
|
|
2797
|
+
if (!isLive()) return;
|
|
2798
|
+
onInterimRef.current?.(event.result.text ?? "");
|
|
2799
|
+
armIdle();
|
|
2800
|
+
};
|
|
2801
|
+
recognizer.recognized = (_sender, event) => {
|
|
2802
|
+
if (!isLive()) return;
|
|
2803
|
+
const text6 = event.result.text?.trim();
|
|
2804
|
+
clearInterim();
|
|
2805
|
+
if (event.result.reason === sdk.ResultReason.RecognizedSpeech && text6) {
|
|
2806
|
+
onPhraseRef.current(text6);
|
|
2807
|
+
}
|
|
2808
|
+
armIdle();
|
|
2809
|
+
};
|
|
2810
|
+
recognizer.canceled = (_sender, event) => {
|
|
2811
|
+
if (!isLive()) return;
|
|
2812
|
+
if (event.reason === sdk.CancellationReason.Error) {
|
|
2813
|
+
console.warn("[dictation] cancelled, errorCode:", event.errorCode);
|
|
2814
|
+
setError(
|
|
2815
|
+
event.errorCode === sdk.CancellationErrorCode.ConnectionFailure ? "network" : event.errorCode === sdk.CancellationErrorCode.AuthenticationFailure ? "unavailable-temporarily" : "unknown"
|
|
2816
|
+
);
|
|
2817
|
+
}
|
|
2818
|
+
stop();
|
|
2819
|
+
};
|
|
2820
|
+
recognizer.sessionStopped = () => {
|
|
2821
|
+
if (isLive()) stop();
|
|
2822
|
+
};
|
|
2823
|
+
try {
|
|
2824
|
+
const connection = sdk.Connection.fromRecognizer(recognizer);
|
|
2825
|
+
connection.connected = () => goLive();
|
|
2826
|
+
connection.openConnection();
|
|
2827
|
+
} catch {
|
|
2828
|
+
}
|
|
2829
|
+
await new Promise(
|
|
2830
|
+
(resolve, reject) => session.recognizer.startContinuousRecognitionAsync(resolve, reject)
|
|
2831
|
+
);
|
|
2832
|
+
goLive();
|
|
2833
|
+
} catch (e) {
|
|
2834
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2835
|
+
try {
|
|
2836
|
+
recognizer?.close();
|
|
2837
|
+
} catch {
|
|
2838
|
+
}
|
|
2839
|
+
if (published) {
|
|
2840
|
+
window.clearTimeout(published.timers.idle);
|
|
2841
|
+
window.clearTimeout(published.timers.max);
|
|
2842
|
+
published.stopLevelMonitor();
|
|
2843
|
+
if (sessionRef.current === published) sessionRef.current = null;
|
|
2844
|
+
}
|
|
2845
|
+
if (superseded()) return;
|
|
2846
|
+
console.warn("[dictation] failed to start:", e);
|
|
2847
|
+
setError((prev) => prev ?? "unavailable-temporarily");
|
|
2848
|
+
setState("idle");
|
|
2849
|
+
}
|
|
2850
|
+
}, [
|
|
2851
|
+
available,
|
|
2852
|
+
clearInterim,
|
|
2853
|
+
getToken,
|
|
2854
|
+
idleTimeoutMs,
|
|
2855
|
+
locale,
|
|
2856
|
+
maxDurationMs,
|
|
2857
|
+
region,
|
|
2858
|
+
stop
|
|
2859
|
+
]);
|
|
2860
|
+
useEffect(() => stop, [stop]);
|
|
2861
|
+
const toggle = useCallback(() => {
|
|
2862
|
+
if (state === "idle") void start();
|
|
2863
|
+
else stop();
|
|
2864
|
+
}, [start, state, stop]);
|
|
2865
|
+
return {
|
|
2866
|
+
supported,
|
|
2867
|
+
available,
|
|
2868
|
+
state,
|
|
2869
|
+
error,
|
|
2870
|
+
/** Name of the microphone in use, once a session is live. May be ''. */
|
|
2871
|
+
deviceLabel,
|
|
2872
|
+
/** Listening, but the microphone has produced no sound for a while. */
|
|
2873
|
+
silent,
|
|
2874
|
+
start,
|
|
2875
|
+
stop,
|
|
2876
|
+
toggle
|
|
2877
|
+
};
|
|
2878
|
+
}
|
|
2422
2879
|
function useFlowRunVariables(flowRunId) {
|
|
2423
2880
|
const service = useChatService();
|
|
2424
2881
|
return useQuery({
|
|
@@ -2430,6 +2887,31 @@ function useFlowRunVariables(flowRunId) {
|
|
|
2430
2887
|
enabled: !!flowRunId
|
|
2431
2888
|
});
|
|
2432
2889
|
}
|
|
2890
|
+
|
|
2891
|
+
// src/chat-variables/renders/fieldStyles.ts
|
|
2892
|
+
var scaleFor = (surface) => surface === "form" ? "comfortable" : "dense";
|
|
2893
|
+
var fieldLabelClass = (scale) => `block truncate font-medium text-muted-foreground ${scale === "dense" ? "mb-1 text-xs" : "mb-1.5 text-sm"}`;
|
|
2894
|
+
var CONTROL_BASE = "rounded-md border bg-background text-foreground transition-colors placeholder:text-muted-foreground ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-60";
|
|
2895
|
+
var borderClass = (hasError) => hasError ? "border-destructive" : "border-input";
|
|
2896
|
+
var fieldControlClass = (scale, hasError) => `w-full ${CONTROL_BASE} ${borderClass(hasError)} ${scale === "dense" ? "px-2.5 py-1.5 text-xs" : "px-3 py-2 text-sm"}`;
|
|
2897
|
+
var fieldTriggerClass = (scale, hasError) => `w-full ${CONTROL_BASE} ${borderClass(
|
|
2898
|
+
hasError
|
|
2899
|
+
)} flex items-center justify-between gap-2 text-left ${scale === "dense" ? "h-8 px-2.5 text-xs" : "h-10 px-3 text-sm"}`;
|
|
2900
|
+
var fieldNumberClass = (scale, hasError) => `${CONTROL_BASE} ${borderClass(hasError)} tabular-nums ${scale === "dense" ? "h-8 w-20 px-2 text-xs" : "h-10 w-24 px-2.5 text-sm"}`;
|
|
2901
|
+
var fieldHintClass = "mt-1 text-xs text-muted-foreground";
|
|
2902
|
+
var fieldErrorClass = "mt-1 text-xs text-destructive";
|
|
2903
|
+
var fieldRowClass = "flex items-center justify-between gap-3";
|
|
2904
|
+
var fieldRowLabelClass = (scale) => `min-w-0 flex-1 truncate font-medium text-muted-foreground ${scale === "dense" ? "text-xs" : "text-sm"}`;
|
|
2905
|
+
var pillClass = (opts) => `flex h-8 shrink-0 items-center gap-1.5 rounded-full border px-2.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${opts.active ? "border-primary/30 bg-primary/10 text-primary" : "border-border/70 bg-transparent text-muted-foreground hover:bg-secondary"} ${opts.hasError ? "border-destructive text-destructive" : ""} ${opts.disabled ? "cursor-not-allowed opacity-60" : ""}`;
|
|
2906
|
+
var pillLabelClass = "max-w-[9rem] truncate";
|
|
2907
|
+
var pillValueClass = "max-w-[9rem] truncate text-foreground";
|
|
2908
|
+
var switchTrackClass = (on, disabled) => `peer inline-flex h-6 w-11 shrink-0 items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background ${on ? "bg-primary" : "bg-input"} ${disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"}`;
|
|
2909
|
+
var switchThumbClass = (on) => `pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform ${on ? "translate-x-5" : "translate-x-0"}`;
|
|
2910
|
+
var POPOVER_WIDTH_PX = 288;
|
|
2911
|
+
var POPOVER_MAX_HEIGHT_PX = 288;
|
|
2912
|
+
var popoverClass = "flex flex-col overflow-hidden rounded-xl border border-border bg-popover shadow-lg";
|
|
2913
|
+
var popoverRowClass = "flex w-full items-center gap-2.5 px-3 py-2 text-left transition-colors hover:bg-secondary/60";
|
|
2914
|
+
var popoverHeadingClass = "text-[10px] font-semibold uppercase tracking-wide text-muted-foreground";
|
|
2433
2915
|
function iconFor(label) {
|
|
2434
2916
|
const name = (label ?? "").toLowerCase();
|
|
2435
2917
|
if (/search|web|browse|internet/.test(name)) return Globe;
|
|
@@ -2445,7 +2927,8 @@ var BooleanRenderer = ({
|
|
|
2445
2927
|
errors,
|
|
2446
2928
|
uischema,
|
|
2447
2929
|
visible,
|
|
2448
|
-
enabled
|
|
2930
|
+
enabled,
|
|
2931
|
+
config
|
|
2449
2932
|
}) => {
|
|
2450
2933
|
const onToggle = useCallback(() => {
|
|
2451
2934
|
handleChange(path2, !data);
|
|
@@ -2456,13 +2939,17 @@ var BooleanRenderer = ({
|
|
|
2456
2939
|
const hasError = !!errors && errors.length > 0;
|
|
2457
2940
|
const isChecked = Boolean(data);
|
|
2458
2941
|
const Icon = iconFor(label);
|
|
2942
|
+
const surface = (config ?? {}).surface ?? "form";
|
|
2943
|
+
const scale = scaleFor(surface);
|
|
2459
2944
|
const tooltip = [label, description, hasError ? errors : null].filter(Boolean).join(" \u2014 ");
|
|
2460
|
-
|
|
2945
|
+
const toggle = /* @__PURE__ */ jsx(
|
|
2461
2946
|
"button",
|
|
2462
2947
|
{
|
|
2463
2948
|
id: `toggle-${path2}`,
|
|
2464
2949
|
type: "button",
|
|
2465
|
-
"
|
|
2950
|
+
role: surface === "bar" ? void 0 : "switch",
|
|
2951
|
+
"aria-pressed": surface === "bar" ? isChecked : void 0,
|
|
2952
|
+
"aria-checked": surface === "bar" ? void 0 : isChecked,
|
|
2466
2953
|
"aria-label": label,
|
|
2467
2954
|
title: tooltip || void 0,
|
|
2468
2955
|
onClick: onToggle,
|
|
@@ -2472,16 +2959,28 @@ var BooleanRenderer = ({
|
|
|
2472
2959
|
e.currentTarget.blur();
|
|
2473
2960
|
}
|
|
2474
2961
|
},
|
|
2475
|
-
className:
|
|
2476
|
-
|
|
2962
|
+
className: surface === "bar" ? `boolean-switch ${pillClass({
|
|
2963
|
+
active: isChecked,
|
|
2964
|
+
hasError,
|
|
2965
|
+
disabled: isDisabled
|
|
2966
|
+
})}` : switchTrackClass(isChecked, isDisabled),
|
|
2967
|
+
children: surface === "bar" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2477
2968
|
/* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
2478
2969
|
label && // Desktop-first: the app and the package each ship a full Tailwind
|
|
2479
|
-
// build, so a base `hidden` can out-order `sm:inline`.
|
|
2480
|
-
// is the form that survives both cascades.
|
|
2481
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
2482
|
-
]
|
|
2970
|
+
// build, so a base `hidden` can out-order `sm:inline`.
|
|
2971
|
+
// `max-sm:hidden` is the form that survives both cascades.
|
|
2972
|
+
/* @__PURE__ */ jsx("span", { className: `inline ${pillLabelClass} max-sm:hidden`, children: label })
|
|
2973
|
+
] }) : /* @__PURE__ */ jsx("span", { className: switchThumbClass(isChecked) })
|
|
2483
2974
|
}
|
|
2484
2975
|
);
|
|
2976
|
+
if (surface === "bar") return toggle;
|
|
2977
|
+
return /* @__PURE__ */ jsxs("div", { className: "ss-jsonforms-field ss-jsonforms-boolean", children: [
|
|
2978
|
+
/* @__PURE__ */ jsxs("div", { className: fieldRowClass, children: [
|
|
2979
|
+
/* @__PURE__ */ jsx("label", { htmlFor: `toggle-${path2}`, className: fieldRowLabelClass(scale), children: label }),
|
|
2980
|
+
toggle
|
|
2981
|
+
] }),
|
|
2982
|
+
hasError && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: errors })
|
|
2983
|
+
] });
|
|
2485
2984
|
};
|
|
2486
2985
|
var booleanRendererTester = rankWith(40, (uischema, schema) => {
|
|
2487
2986
|
if (uischema.type !== "Control") return false;
|
|
@@ -2491,6 +2990,104 @@ var booleanRendererTester = rankWith(40, (uischema, schema) => {
|
|
|
2491
2990
|
return fieldSchema?.type === "boolean";
|
|
2492
2991
|
});
|
|
2493
2992
|
var BooleanRendererControl = withJsonFormsControlProps(BooleanRenderer);
|
|
2993
|
+
var GAP_PX = 8;
|
|
2994
|
+
var MIN_TRIGGER_WIDTH_PX = 224;
|
|
2995
|
+
var MIN_PANEL_HEIGHT_PX = 180;
|
|
2996
|
+
var NestedPopoverContext = React9__default.createContext(null);
|
|
2997
|
+
function useAnchoredPopover({
|
|
2998
|
+
trigger,
|
|
2999
|
+
popover,
|
|
3000
|
+
width,
|
|
3001
|
+
maxHeight,
|
|
3002
|
+
role,
|
|
3003
|
+
label
|
|
3004
|
+
}) {
|
|
3005
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
3006
|
+
const parentRegistry = useContext(NestedPopoverContext);
|
|
3007
|
+
const descendants = useRef(/* @__PURE__ */ new Set());
|
|
3008
|
+
const close = useCallback(() => setIsOpen(false), []);
|
|
3009
|
+
const toggle = useCallback(() => setIsOpen((open) => !open), []);
|
|
3010
|
+
const registry = useMemo(
|
|
3011
|
+
() => ({
|
|
3012
|
+
register: (el) => {
|
|
3013
|
+
descendants.current.add(el);
|
|
3014
|
+
parentRegistry?.register(el);
|
|
3015
|
+
},
|
|
3016
|
+
unregister: (el) => {
|
|
3017
|
+
descendants.current.delete(el);
|
|
3018
|
+
parentRegistry?.unregister(el);
|
|
3019
|
+
}
|
|
3020
|
+
}),
|
|
3021
|
+
[parentRegistry]
|
|
3022
|
+
);
|
|
3023
|
+
useEffect(() => {
|
|
3024
|
+
if (!isOpen || !parentRegistry) return;
|
|
3025
|
+
const el = popover.current;
|
|
3026
|
+
if (!el) return;
|
|
3027
|
+
parentRegistry.register(el);
|
|
3028
|
+
return () => parentRegistry.unregister(el);
|
|
3029
|
+
}, [isOpen, parentRegistry, popover]);
|
|
3030
|
+
useEffect(() => {
|
|
3031
|
+
if (!isOpen) return;
|
|
3032
|
+
const onPointerDown = (event) => {
|
|
3033
|
+
const target = event.target;
|
|
3034
|
+
if (trigger.current?.contains(target)) return;
|
|
3035
|
+
if (popover.current?.contains(target)) return;
|
|
3036
|
+
for (const el of descendants.current) {
|
|
3037
|
+
if (el.contains(target)) return;
|
|
3038
|
+
}
|
|
3039
|
+
close();
|
|
3040
|
+
};
|
|
3041
|
+
const onKeyDown = (event) => {
|
|
3042
|
+
if (event.key === "Escape") close();
|
|
3043
|
+
};
|
|
3044
|
+
document.addEventListener("mousedown", onPointerDown);
|
|
3045
|
+
document.addEventListener("keydown", onKeyDown);
|
|
3046
|
+
window.addEventListener("resize", close);
|
|
3047
|
+
return () => {
|
|
3048
|
+
document.removeEventListener("mousedown", onPointerDown);
|
|
3049
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
3050
|
+
window.removeEventListener("resize", close);
|
|
3051
|
+
};
|
|
3052
|
+
}, [isOpen, close, trigger, popover]);
|
|
3053
|
+
const renderPopover = (children2) => {
|
|
3054
|
+
if (!isOpen) return null;
|
|
3055
|
+
const anchor = trigger.current?.getBoundingClientRect();
|
|
3056
|
+
if (!anchor) return null;
|
|
3057
|
+
const panelWidth = width === "trigger" ? Math.max(anchor.width, MIN_TRIGGER_WIDTH_PX) : width;
|
|
3058
|
+
const spaceAbove = anchor.top - GAP_PX * 2;
|
|
3059
|
+
const spaceBelow = window.innerHeight - anchor.bottom - GAP_PX * 2;
|
|
3060
|
+
const openAbove = spaceAbove >= MIN_PANEL_HEIGHT_PX || spaceAbove >= spaceBelow;
|
|
3061
|
+
const panelMaxHeight = Math.max(
|
|
3062
|
+
0,
|
|
3063
|
+
Math.min(maxHeight, openAbove ? spaceAbove : spaceBelow)
|
|
3064
|
+
);
|
|
3065
|
+
return createPortal(
|
|
3066
|
+
/* @__PURE__ */ jsx(
|
|
3067
|
+
"div",
|
|
3068
|
+
{
|
|
3069
|
+
ref: popover,
|
|
3070
|
+
role,
|
|
3071
|
+
"aria-label": label,
|
|
3072
|
+
className: `fixed z-50 ${popoverClass}`,
|
|
3073
|
+
style: {
|
|
3074
|
+
width: panelWidth,
|
|
3075
|
+
maxWidth: `calc(100vw - ${GAP_PX * 4}px)`,
|
|
3076
|
+
left: Math.max(
|
|
3077
|
+
GAP_PX,
|
|
3078
|
+
Math.min(anchor.left, window.innerWidth - panelWidth - GAP_PX)
|
|
3079
|
+
),
|
|
3080
|
+
...openAbove ? { bottom: window.innerHeight - anchor.top + GAP_PX } : { top: anchor.bottom + GAP_PX },
|
|
3081
|
+
maxHeight: panelMaxHeight
|
|
3082
|
+
},
|
|
3083
|
+
children: /* @__PURE__ */ jsx(NestedPopoverContext.Provider, { value: registry, children: children2 })
|
|
3084
|
+
}
|
|
3085
|
+
),
|
|
3086
|
+
document.body
|
|
3087
|
+
);
|
|
3088
|
+
};
|
|
3089
|
+
return { isOpen, close, toggle, renderPopover };
|
|
3090
|
+
}
|
|
2494
3091
|
function hasConst(x) {
|
|
2495
3092
|
return !!x && typeof x === "object" && "const" in x;
|
|
2496
3093
|
}
|
|
@@ -2529,185 +3126,109 @@ var DropdownRenderer = ({
|
|
|
2529
3126
|
label,
|
|
2530
3127
|
description,
|
|
2531
3128
|
errors,
|
|
2532
|
-
|
|
3129
|
+
config,
|
|
3130
|
+
uischema,
|
|
3131
|
+
visible
|
|
2533
3132
|
}) => {
|
|
3133
|
+
const triggerRef = useRef(null);
|
|
3134
|
+
const listRef = useRef(null);
|
|
3135
|
+
const surface = (config ?? {}).surface ?? "form";
|
|
3136
|
+
const scale = scaleFor(surface);
|
|
3137
|
+
const { isOpen, close, toggle, renderPopover } = useAnchoredPopover({
|
|
3138
|
+
trigger: triggerRef,
|
|
3139
|
+
popover: listRef,
|
|
3140
|
+
// A select's list lines up with its own control.
|
|
3141
|
+
width: "trigger",
|
|
3142
|
+
maxHeight: POPOVER_MAX_HEIGHT_PX,
|
|
3143
|
+
role: "listbox",
|
|
3144
|
+
label: label || "Options"
|
|
3145
|
+
});
|
|
2534
3146
|
const options = toOptions(schema);
|
|
2535
|
-
const
|
|
2536
|
-
(
|
|
2537
|
-
handleChange(path2,
|
|
3147
|
+
const select = useCallback(
|
|
3148
|
+
(value) => {
|
|
3149
|
+
handleChange(path2, value);
|
|
3150
|
+
close();
|
|
2538
3151
|
},
|
|
2539
|
-
[handleChange, path2]
|
|
3152
|
+
[handleChange, path2, close]
|
|
2540
3153
|
);
|
|
2541
|
-
|
|
3154
|
+
if (!visible) return null;
|
|
2542
3155
|
const readOnly = uischema?.access === "Read";
|
|
2543
3156
|
const isDisabled = !enabled || readOnly;
|
|
2544
|
-
|
|
2545
|
-
|
|
3157
|
+
const hasError = !!errors;
|
|
3158
|
+
const selected = options.find((option) => option.const === data);
|
|
3159
|
+
const valueText = selected ? selected.title ?? String(selected.const) : data != null && data !== "" ? String(data) : "";
|
|
3160
|
+
const triggerId = `${path2}-trigger`;
|
|
3161
|
+
const isBar = surface === "bar";
|
|
3162
|
+
const placeholder = `Select ${(label || "value").toLowerCase()}\u2026`;
|
|
3163
|
+
const trigger = /* @__PURE__ */ jsxs(
|
|
3164
|
+
"button",
|
|
2546
3165
|
{
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
error: !!errors,
|
|
3166
|
+
id: triggerId,
|
|
3167
|
+
ref: triggerRef,
|
|
3168
|
+
type: "button",
|
|
2551
3169
|
disabled: isDisabled,
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
3170
|
+
onClick: toggle,
|
|
3171
|
+
"aria-haspopup": "listbox",
|
|
3172
|
+
"aria-expanded": isOpen,
|
|
3173
|
+
"aria-label": label,
|
|
3174
|
+
title: [label, valueText, hasError ? errors : null].filter(Boolean).join(" \u2014 ") || void 0,
|
|
3175
|
+
className: isBar ? `ss-jsonforms-select-trigger ${pillClass({
|
|
3176
|
+
active: isOpen,
|
|
3177
|
+
hasError,
|
|
3178
|
+
disabled: isDisabled
|
|
3179
|
+
})}` : `ss-jsonforms-select-trigger ${fieldTriggerClass(scale, hasError)}`,
|
|
2556
3180
|
children: [
|
|
3181
|
+
isBar && label && /* @__PURE__ */ jsx("span", { className: `inline ${pillLabelClass} max-sm:hidden`, children: label }),
|
|
2557
3182
|
/* @__PURE__ */ jsx(
|
|
2558
|
-
|
|
3183
|
+
"span",
|
|
2559
3184
|
{
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
color: "#6b7280",
|
|
2563
|
-
fontSize: "0.875rem",
|
|
2564
|
-
fontWeight: 500,
|
|
2565
|
-
"&.Mui-focused": {
|
|
2566
|
-
color: "#6366f1"
|
|
2567
|
-
},
|
|
2568
|
-
"&.Mui-error": {
|
|
2569
|
-
color: "#ef4444"
|
|
2570
|
-
}
|
|
2571
|
-
},
|
|
2572
|
-
children: label
|
|
3185
|
+
className: isBar ? pillValueClass : `min-w-0 flex-1 truncate ${valueText ? "" : "text-muted-foreground"}`,
|
|
3186
|
+
children: valueText || (isBar ? "\u2014" : placeholder)
|
|
2573
3187
|
}
|
|
2574
3188
|
),
|
|
2575
3189
|
/* @__PURE__ */ jsx(
|
|
2576
|
-
|
|
3190
|
+
ChevronDown,
|
|
2577
3191
|
{
|
|
2578
|
-
|
|
2579
|
-
value: displayValue,
|
|
2580
|
-
onChange: handleSelectionChange,
|
|
2581
|
-
label,
|
|
2582
|
-
sx: {
|
|
2583
|
-
"& .MuiOutlinedInput-root": {
|
|
2584
|
-
backgroundColor: "#fafafa",
|
|
2585
|
-
borderRadius: "8px",
|
|
2586
|
-
transition: "all 0.2s ease-in-out",
|
|
2587
|
-
height: "40px",
|
|
2588
|
-
// Same height as model dropdown
|
|
2589
|
-
"& fieldset": {
|
|
2590
|
-
borderColor: "#e5e7eb",
|
|
2591
|
-
borderWidth: "1px"
|
|
2592
|
-
},
|
|
2593
|
-
"&:hover": {
|
|
2594
|
-
backgroundColor: "#ffffff",
|
|
2595
|
-
"& fieldset": {
|
|
2596
|
-
borderColor: "#9ca3af"
|
|
2597
|
-
}
|
|
2598
|
-
},
|
|
2599
|
-
"&.Mui-focused": {
|
|
2600
|
-
backgroundColor: "#ffffff",
|
|
2601
|
-
"& fieldset": {
|
|
2602
|
-
borderColor: "#6366f1",
|
|
2603
|
-
borderWidth: "2px"
|
|
2604
|
-
}
|
|
2605
|
-
},
|
|
2606
|
-
"&.Mui-error": {
|
|
2607
|
-
"& fieldset": {
|
|
2608
|
-
borderColor: "#ef4444"
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2611
|
-
},
|
|
2612
|
-
"& .MuiSelect-select": {
|
|
2613
|
-
backgroundColor: "#fafafa",
|
|
2614
|
-
borderRadius: "8px",
|
|
2615
|
-
transition: "all 0.2s ease-in-out",
|
|
2616
|
-
height: "40px",
|
|
2617
|
-
display: "flex",
|
|
2618
|
-
alignItems: "center",
|
|
2619
|
-
paddingRight: "32px !important",
|
|
2620
|
-
"&:hover": {
|
|
2621
|
-
backgroundColor: "#ffffff"
|
|
2622
|
-
},
|
|
2623
|
-
"&.Mui-focused": {
|
|
2624
|
-
backgroundColor: "#ffffff"
|
|
2625
|
-
}
|
|
2626
|
-
},
|
|
2627
|
-
"& .MuiOutlinedInput-notchedOutline": {
|
|
2628
|
-
borderColor: "#e5e7eb",
|
|
2629
|
-
borderWidth: "1px",
|
|
2630
|
-
borderRadius: "8px"
|
|
2631
|
-
},
|
|
2632
|
-
"&:hover .MuiOutlinedInput-notchedOutline": {
|
|
2633
|
-
borderColor: "#9ca3af"
|
|
2634
|
-
},
|
|
2635
|
-
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
|
|
2636
|
-
borderColor: "#6366f1",
|
|
2637
|
-
borderWidth: "2px"
|
|
2638
|
-
},
|
|
2639
|
-
"&.Mui-error .MuiOutlinedInput-notchedOutline": {
|
|
2640
|
-
borderColor: "#ef4444"
|
|
2641
|
-
},
|
|
2642
|
-
"& .MuiSelect-icon": {
|
|
2643
|
-
color: "#9ca3af",
|
|
2644
|
-
"&:hover": {
|
|
2645
|
-
color: "#6b7280"
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2648
|
-
},
|
|
2649
|
-
MenuProps: {
|
|
2650
|
-
PaperProps: {
|
|
2651
|
-
sx: {
|
|
2652
|
-
borderRadius: "8px",
|
|
2653
|
-
boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
|
|
2654
|
-
border: "1px solid #e5e7eb",
|
|
2655
|
-
marginTop: "4px",
|
|
2656
|
-
maxHeight: "280px"
|
|
2657
|
-
}
|
|
2658
|
-
},
|
|
2659
|
-
MenuListProps: {
|
|
2660
|
-
sx: {
|
|
2661
|
-
padding: 0
|
|
2662
|
-
}
|
|
2663
|
-
}
|
|
2664
|
-
},
|
|
2665
|
-
children: options.map((option, index) => {
|
|
2666
|
-
const raw2 = option.const;
|
|
2667
|
-
const key = typeof raw2 === "string" || typeof raw2 === "number" ? String(raw2) : String(index);
|
|
2668
|
-
const value = typeof raw2 === "string" || typeof raw2 === "number" ? raw2 : String(raw2 ?? index);
|
|
2669
|
-
return /* @__PURE__ */ jsx(
|
|
2670
|
-
MenuItem,
|
|
2671
|
-
{
|
|
2672
|
-
value,
|
|
2673
|
-
sx: {
|
|
2674
|
-
padding: "12px 16px",
|
|
2675
|
-
fontSize: "0.875rem",
|
|
2676
|
-
borderBottom: "1px solid #f3f4f6",
|
|
2677
|
-
"&:last-child": {
|
|
2678
|
-
borderBottom: "none"
|
|
2679
|
-
},
|
|
2680
|
-
"&:hover": {
|
|
2681
|
-
backgroundColor: "#f8fafc"
|
|
2682
|
-
},
|
|
2683
|
-
"&.Mui-selected": {
|
|
2684
|
-
backgroundColor: "#eff6ff",
|
|
2685
|
-
"&:hover": {
|
|
2686
|
-
backgroundColor: "#dbeafe"
|
|
2687
|
-
}
|
|
2688
|
-
}
|
|
2689
|
-
},
|
|
2690
|
-
children: option.title ?? String(raw2)
|
|
2691
|
-
},
|
|
2692
|
-
key
|
|
2693
|
-
);
|
|
2694
|
-
})
|
|
2695
|
-
}
|
|
2696
|
-
),
|
|
2697
|
-
(description || errors) && /* @__PURE__ */ jsx(
|
|
2698
|
-
"div",
|
|
2699
|
-
{
|
|
2700
|
-
style: {
|
|
2701
|
-
fontSize: "0.75rem",
|
|
2702
|
-
marginTop: "4px",
|
|
2703
|
-
color: errors ? "#ef4444" : "#6b7280"
|
|
2704
|
-
},
|
|
2705
|
-
children: errors || description
|
|
3192
|
+
className: `shrink-0 opacity-50 ${isBar ? "h-3 w-3" : "h-4 w-4"}`
|
|
2706
3193
|
}
|
|
2707
3194
|
)
|
|
2708
3195
|
]
|
|
2709
3196
|
}
|
|
2710
3197
|
);
|
|
3198
|
+
return /* @__PURE__ */ jsxs("div", { className: "ss-jsonforms-field ss-jsonforms-select compact-field", children: [
|
|
3199
|
+
!isBar && label && /* @__PURE__ */ jsx("label", { htmlFor: triggerId, className: fieldLabelClass(scale), children: label }),
|
|
3200
|
+
trigger,
|
|
3201
|
+
!isBar && (errors || description) && /* @__PURE__ */ jsx("div", { className: errors ? fieldErrorClass : fieldHintClass, children: errors || description }),
|
|
3202
|
+
renderPopover(
|
|
3203
|
+
/* @__PURE__ */ jsxs("div", { className: "min-h-0 overflow-y-auto py-1", children: [
|
|
3204
|
+
options.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-muted-foreground", children: "No options available" }),
|
|
3205
|
+
options.map((option, index) => {
|
|
3206
|
+
const active = option.const === data;
|
|
3207
|
+
const text6 = option.title ?? String(option.const);
|
|
3208
|
+
return /* @__PURE__ */ jsxs(
|
|
3209
|
+
"button",
|
|
3210
|
+
{
|
|
3211
|
+
type: "button",
|
|
3212
|
+
role: "option",
|
|
3213
|
+
"aria-selected": active,
|
|
3214
|
+
onClick: () => select(option.const),
|
|
3215
|
+
className: popoverRowClass,
|
|
3216
|
+
children: [
|
|
3217
|
+
/* @__PURE__ */ jsx(
|
|
3218
|
+
Check,
|
|
3219
|
+
{
|
|
3220
|
+
className: `h-3.5 w-3.5 shrink-0 ${active ? "text-primary" : "opacity-0"}`
|
|
3221
|
+
}
|
|
3222
|
+
),
|
|
3223
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm text-foreground", children: text6 })
|
|
3224
|
+
]
|
|
3225
|
+
},
|
|
3226
|
+
typeof option.const === "string" || typeof option.const === "number" ? String(option.const) : `option-${index}`
|
|
3227
|
+
);
|
|
3228
|
+
})
|
|
3229
|
+
] })
|
|
3230
|
+
)
|
|
3231
|
+
] });
|
|
2711
3232
|
};
|
|
2712
3233
|
var dropdownRendererTester = rankWith(
|
|
2713
3234
|
90,
|
|
@@ -2725,8 +3246,8 @@ var dropdownRendererTester = rankWith(
|
|
|
2725
3246
|
return false;
|
|
2726
3247
|
}
|
|
2727
3248
|
const hasDropdownOptions = !!(fieldSchema.oneOf || fieldSchema.anyOf || fieldSchema.enum && Array.isArray(fieldSchema.enum));
|
|
2728
|
-
const
|
|
2729
|
-
return hasDropdownOptions && !
|
|
3249
|
+
const isModelSelector2 = typeof fieldSchema === "object" && fieldSchema && fieldSchema["x-model-selector"] === true || fieldSchema.title === "ModelId" || fieldSchema.format === "uuid";
|
|
3250
|
+
return hasDropdownOptions && !isModelSelector2;
|
|
2730
3251
|
}
|
|
2731
3252
|
);
|
|
2732
3253
|
var DropdownRendererControl = withJsonFormsControlProps(DropdownRenderer);
|
|
@@ -2761,7 +3282,8 @@ var JsonEditorRenderer = ({
|
|
|
2761
3282
|
uischema,
|
|
2762
3283
|
visible,
|
|
2763
3284
|
enabled,
|
|
2764
|
-
required
|
|
3285
|
+
required,
|
|
3286
|
+
config
|
|
2765
3287
|
}) => {
|
|
2766
3288
|
const [jsonValue, setJsonValue] = useState("");
|
|
2767
3289
|
const [displayedParseError, setDisplayedParseError] = useState(
|
|
@@ -2815,43 +3337,19 @@ var JsonEditorRenderer = ({
|
|
|
2815
3337
|
}
|
|
2816
3338
|
const readOnly = uischema?.access === "Read";
|
|
2817
3339
|
const isDisabled = !enabled || readOnly;
|
|
3340
|
+
const scale = scaleFor(
|
|
3341
|
+
(config ?? {}).surface ?? "form"
|
|
3342
|
+
);
|
|
2818
3343
|
return /* @__PURE__ */ jsxs("div", { style: { marginBottom: "1rem" }, children: [
|
|
2819
|
-
label && /* @__PURE__ */ jsxs(
|
|
2820
|
-
|
|
2821
|
-
{
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
color: "#475569",
|
|
2825
|
-
fontSize: "0.875rem",
|
|
2826
|
-
fontWeight: 500,
|
|
2827
|
-
marginBottom: "0.375rem"
|
|
2828
|
-
},
|
|
2829
|
-
children: [
|
|
2830
|
-
label,
|
|
2831
|
-
required && /* @__PURE__ */ jsx("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
|
|
2832
|
-
]
|
|
2833
|
-
}
|
|
2834
|
-
),
|
|
2835
|
-
description && /* @__PURE__ */ jsx(
|
|
2836
|
-
"div",
|
|
2837
|
-
{
|
|
2838
|
-
style: {
|
|
2839
|
-
color: "#6b7280",
|
|
2840
|
-
fontSize: "0.75rem",
|
|
2841
|
-
marginBottom: "0.5rem"
|
|
2842
|
-
},
|
|
2843
|
-
children: description
|
|
2844
|
-
}
|
|
2845
|
-
),
|
|
3344
|
+
label && /* @__PURE__ */ jsxs("label", { className: fieldLabelClass(scale), children: [
|
|
3345
|
+
label,
|
|
3346
|
+
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3347
|
+
] }),
|
|
3348
|
+
description && /* @__PURE__ */ jsx("div", { className: fieldHintClass, children: description }),
|
|
2846
3349
|
/* @__PURE__ */ jsx(
|
|
2847
3350
|
"div",
|
|
2848
3351
|
{
|
|
2849
|
-
|
|
2850
|
-
border: errors || displayedParseError ? "1px solid #ef4444" : "1px solid #d1d5db",
|
|
2851
|
-
borderRadius: "6px",
|
|
2852
|
-
overflow: "hidden",
|
|
2853
|
-
opacity: isDisabled ? 0.6 : 1
|
|
2854
|
-
},
|
|
3352
|
+
className: `overflow-hidden rounded-md border ${errors || displayedParseError ? "border-destructive" : "border-input"} ${isDisabled ? "opacity-60" : ""}`,
|
|
2855
3353
|
children: /* @__PURE__ */ jsx(
|
|
2856
3354
|
AceEditor,
|
|
2857
3355
|
{
|
|
@@ -2884,28 +3382,8 @@ var JsonEditorRenderer = ({
|
|
|
2884
3382
|
)
|
|
2885
3383
|
}
|
|
2886
3384
|
),
|
|
2887
|
-
displayedParseError && /* @__PURE__ */ jsx(
|
|
2888
|
-
|
|
2889
|
-
{
|
|
2890
|
-
style: {
|
|
2891
|
-
color: "#ef4444",
|
|
2892
|
-
fontSize: "0.75rem",
|
|
2893
|
-
marginTop: "0.25rem"
|
|
2894
|
-
},
|
|
2895
|
-
children: displayedParseError
|
|
2896
|
-
}
|
|
2897
|
-
),
|
|
2898
|
-
errors && /* @__PURE__ */ jsx(
|
|
2899
|
-
"div",
|
|
2900
|
-
{
|
|
2901
|
-
style: {
|
|
2902
|
-
color: "#ef4444",
|
|
2903
|
-
fontSize: "0.75rem",
|
|
2904
|
-
marginTop: "0.25rem"
|
|
2905
|
-
},
|
|
2906
|
-
children: errors
|
|
2907
|
-
}
|
|
2908
|
-
)
|
|
3385
|
+
displayedParseError && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: displayedParseError }),
|
|
3386
|
+
errors && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: errors })
|
|
2909
3387
|
] });
|
|
2910
3388
|
};
|
|
2911
3389
|
var jsonEditorTester = rankWith(
|
|
@@ -2996,14 +3474,31 @@ var ModelIdRenderer = ({
|
|
|
2996
3474
|
description,
|
|
2997
3475
|
errors,
|
|
2998
3476
|
uischema,
|
|
2999
|
-
visible
|
|
3477
|
+
visible,
|
|
3478
|
+
config
|
|
3000
3479
|
}) => {
|
|
3001
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
3002
3480
|
const [searchValue, setSearchValue] = useState("");
|
|
3003
3481
|
const [debouncedSearchValue, setDebouncedSearchValue] = useState("");
|
|
3004
|
-
const
|
|
3482
|
+
const triggerRef = useRef(null);
|
|
3005
3483
|
const menuRef = useRef(null);
|
|
3006
3484
|
const searchRef = useRef(null);
|
|
3485
|
+
const surface = (config ?? {}).surface ?? "bar";
|
|
3486
|
+
const scale = scaleFor(surface);
|
|
3487
|
+
const isBar = surface === "bar";
|
|
3488
|
+
const {
|
|
3489
|
+
isOpen,
|
|
3490
|
+
close: closeMenu,
|
|
3491
|
+
toggle,
|
|
3492
|
+
renderPopover
|
|
3493
|
+
} = useAnchoredPopover({
|
|
3494
|
+
trigger: triggerRef,
|
|
3495
|
+
popover: menuRef,
|
|
3496
|
+
// Wide enough for a provider glyph, a model name and its id underneath.
|
|
3497
|
+
width: POPOVER_WIDTH_PX,
|
|
3498
|
+
maxHeight: POPOVER_MAX_HEIGHT_PX,
|
|
3499
|
+
role: "listbox",
|
|
3500
|
+
label: "Models"
|
|
3501
|
+
});
|
|
3007
3502
|
const debounceTimerRef = useRef(
|
|
3008
3503
|
void 0
|
|
3009
3504
|
);
|
|
@@ -3042,35 +3537,13 @@ var ModelIdRenderer = ({
|
|
|
3042
3537
|
handleChange(path2, model.id);
|
|
3043
3538
|
setSearchValue("");
|
|
3044
3539
|
setDebouncedSearchValue("");
|
|
3045
|
-
|
|
3540
|
+
closeMenu();
|
|
3046
3541
|
},
|
|
3047
|
-
[handleChange, path2]
|
|
3542
|
+
[handleChange, path2, closeMenu]
|
|
3048
3543
|
);
|
|
3049
|
-
const close = useCallback(() => {
|
|
3050
|
-
setIsOpen(false);
|
|
3051
|
-
setSearchValue("");
|
|
3052
|
-
}, []);
|
|
3053
3544
|
useEffect(() => {
|
|
3054
|
-
if (!isOpen)
|
|
3055
|
-
|
|
3056
|
-
const target = event.target;
|
|
3057
|
-
if (containerRef.current && !containerRef.current.contains(target) && !(menuRef.current && menuRef.current.contains(target))) {
|
|
3058
|
-
close();
|
|
3059
|
-
}
|
|
3060
|
-
};
|
|
3061
|
-
const onKeyDown = (event) => {
|
|
3062
|
-
if (event.key === "Escape") close();
|
|
3063
|
-
};
|
|
3064
|
-
const onResize = () => close();
|
|
3065
|
-
document.addEventListener("mousedown", onPointerDown);
|
|
3066
|
-
document.addEventListener("keydown", onKeyDown);
|
|
3067
|
-
window.addEventListener("resize", onResize);
|
|
3068
|
-
return () => {
|
|
3069
|
-
document.removeEventListener("mousedown", onPointerDown);
|
|
3070
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
3071
|
-
window.removeEventListener("resize", onResize);
|
|
3072
|
-
};
|
|
3073
|
-
}, [isOpen, close]);
|
|
3545
|
+
if (!isOpen) setSearchValue("");
|
|
3546
|
+
}, [isOpen]);
|
|
3074
3547
|
useEffect(() => {
|
|
3075
3548
|
if (isOpen) searchRef.current?.focus();
|
|
3076
3549
|
}, [isOpen]);
|
|
@@ -3079,53 +3552,58 @@ var ModelIdRenderer = ({
|
|
|
3079
3552
|
const isDisabled = !enabled || readOnly;
|
|
3080
3553
|
const hasError = !!errors && errors.length > 0;
|
|
3081
3554
|
const selectedName = selectedModel ? selectedModel.displayName || selectedModel.name || "" : "";
|
|
3082
|
-
const triggerText = selectedName ||
|
|
3555
|
+
const triggerText = selectedName || "Select model";
|
|
3083
3556
|
const iconSrc = getModelIcon(selectedModel);
|
|
3084
3557
|
const tooltip = [selectedName || label, description, hasError ? errors : null].filter(Boolean).join(" \u2014 ");
|
|
3085
|
-
const
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3558
|
+
const triggerLabel = !label || label === "ModelId" ? "Model" : label;
|
|
3559
|
+
const trigger = /* @__PURE__ */ jsxs(
|
|
3560
|
+
"button",
|
|
3561
|
+
{
|
|
3562
|
+
ref: triggerRef,
|
|
3563
|
+
id: `${path2}-trigger`,
|
|
3564
|
+
type: "button",
|
|
3565
|
+
onClick: toggle,
|
|
3566
|
+
disabled: isDisabled,
|
|
3567
|
+
"aria-expanded": isOpen,
|
|
3568
|
+
"aria-haspopup": "listbox",
|
|
3569
|
+
"aria-label": triggerLabel,
|
|
3570
|
+
title: tooltip || void 0,
|
|
3571
|
+
className: isBar ? pillClass({ active: isOpen, hasError, disabled: isDisabled }) : fieldTriggerClass(scale, hasError),
|
|
3572
|
+
children: [
|
|
3573
|
+
iconSrc ? /* @__PURE__ */ jsx(
|
|
3574
|
+
"img",
|
|
3575
|
+
{
|
|
3576
|
+
src: iconSrc,
|
|
3577
|
+
alt: "",
|
|
3578
|
+
className: "h-3.5 w-3.5 shrink-0 object-contain"
|
|
3579
|
+
}
|
|
3580
|
+
) : /* @__PURE__ */ jsx(Cpu, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
3581
|
+
/* @__PURE__ */ jsx(
|
|
3582
|
+
"span",
|
|
3583
|
+
{
|
|
3584
|
+
className: isBar ? `inline ${pillValueClass} max-sm:hidden` : "min-w-0 flex-1 truncate",
|
|
3585
|
+
children: triggerText
|
|
3586
|
+
}
|
|
3587
|
+
),
|
|
3588
|
+
/* @__PURE__ */ jsx(
|
|
3589
|
+
ChevronDown,
|
|
3590
|
+
{
|
|
3591
|
+
className: `shrink-0 opacity-60 ${isBar ? "h-3 w-3" : "h-4 w-4"}`
|
|
3592
|
+
}
|
|
3593
|
+
)
|
|
3594
|
+
]
|
|
3595
|
+
}
|
|
3596
|
+
);
|
|
3597
|
+
return /* @__PURE__ */ jsxs(
|
|
3598
|
+
"div",
|
|
3599
|
+
{
|
|
3600
|
+
className: isBar ? "ss-jsonforms-field ss-jsonforms-model relative shrink-0" : "ss-jsonforms-field ss-jsonforms-model compact-field",
|
|
3601
|
+
children: [
|
|
3602
|
+
!isBar && /* @__PURE__ */ jsx("label", { htmlFor: `${path2}-trigger`, className: fieldLabelClass(scale), children: triggerLabel }),
|
|
3603
|
+
trigger,
|
|
3604
|
+
renderPopover(
|
|
3605
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3606
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0 border-b border-border p-2", children: /* @__PURE__ */ jsx(
|
|
3129
3607
|
"input",
|
|
3130
3608
|
{
|
|
3131
3609
|
ref: searchRef,
|
|
@@ -3137,7 +3615,7 @@ var ModelIdRenderer = ({
|
|
|
3137
3615
|
className: "h-8 w-full rounded-md border border-border bg-background px-2 text-xs text-foreground outline-none placeholder:text-muted-foreground focus:border-primary/40"
|
|
3138
3616
|
}
|
|
3139
3617
|
) }),
|
|
3140
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
3618
|
+
/* @__PURE__ */ jsxs("div", { className: "min-h-0 overflow-y-auto", children: [
|
|
3141
3619
|
isLoading && listModels.length === 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-primary" }) }),
|
|
3142
3620
|
!isLoading && listModels.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-muted-foreground", children: searchValue ? "No models found" : "No models available" }),
|
|
3143
3621
|
listModels.map((model) => {
|
|
@@ -3150,7 +3628,7 @@ var ModelIdRenderer = ({
|
|
|
3150
3628
|
role: "option",
|
|
3151
3629
|
"aria-selected": active,
|
|
3152
3630
|
onClick: () => handleSelect(model),
|
|
3153
|
-
className:
|
|
3631
|
+
className: popoverRowClass,
|
|
3154
3632
|
children: [
|
|
3155
3633
|
/* @__PURE__ */ jsx(
|
|
3156
3634
|
Check,
|
|
@@ -3176,12 +3654,11 @@ var ModelIdRenderer = ({
|
|
|
3176
3654
|
);
|
|
3177
3655
|
})
|
|
3178
3656
|
] })
|
|
3179
|
-
]
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
] });
|
|
3657
|
+
] })
|
|
3658
|
+
)
|
|
3659
|
+
]
|
|
3660
|
+
}
|
|
3661
|
+
);
|
|
3185
3662
|
};
|
|
3186
3663
|
var modelIdRendererTester = rankWith(
|
|
3187
3664
|
100,
|
|
@@ -3216,6 +3693,7 @@ var NumberRenderer = ({
|
|
|
3216
3693
|
uischema,
|
|
3217
3694
|
visible,
|
|
3218
3695
|
enabled,
|
|
3696
|
+
config,
|
|
3219
3697
|
required
|
|
3220
3698
|
}) => {
|
|
3221
3699
|
const isInteger = schema?.type === "integer";
|
|
@@ -3244,40 +3722,58 @@ var NumberRenderer = ({
|
|
|
3244
3722
|
const max = fieldSchema?.maximum;
|
|
3245
3723
|
const step = isInteger ? 1 : fieldSchema?.multipleOf ?? "any";
|
|
3246
3724
|
const tooltip = [label, description, hasError ? errors : null].filter(Boolean).join(" \u2014 ");
|
|
3247
|
-
|
|
3248
|
-
|
|
3725
|
+
const surface = (config ?? {}).surface ?? "form";
|
|
3726
|
+
const scale = scaleFor(surface);
|
|
3727
|
+
const input = /* @__PURE__ */ jsx(
|
|
3728
|
+
"input",
|
|
3249
3729
|
{
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
label,
|
|
3260
|
-
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3261
|
-
]
|
|
3262
|
-
}
|
|
3263
|
-
),
|
|
3264
|
-
/* @__PURE__ */ jsx(
|
|
3265
|
-
"input",
|
|
3266
|
-
{
|
|
3267
|
-
id: `number-${path2}`,
|
|
3268
|
-
type: "number",
|
|
3269
|
-
value: data ?? "",
|
|
3270
|
-
onChange: handleInputChange,
|
|
3271
|
-
disabled: isDisabled,
|
|
3272
|
-
min,
|
|
3273
|
-
max,
|
|
3274
|
-
step,
|
|
3275
|
-
className: "w-14 border-0 bg-transparent p-0 text-xs font-medium tabular-nums text-foreground outline-none disabled:cursor-not-allowed"
|
|
3276
|
-
}
|
|
3277
|
-
)
|
|
3278
|
-
]
|
|
3730
|
+
id: `number-${path2}`,
|
|
3731
|
+
type: "number",
|
|
3732
|
+
value: data ?? "",
|
|
3733
|
+
onChange: handleInputChange,
|
|
3734
|
+
disabled: isDisabled,
|
|
3735
|
+
min,
|
|
3736
|
+
max,
|
|
3737
|
+
step,
|
|
3738
|
+
className: surface === "bar" ? "w-14 border-0 bg-transparent p-0 text-xs font-medium tabular-nums text-foreground outline-none disabled:cursor-not-allowed" : fieldNumberClass(scale, hasError)
|
|
3279
3739
|
}
|
|
3280
3740
|
);
|
|
3741
|
+
if (surface === "bar") {
|
|
3742
|
+
return /* @__PURE__ */ jsxs(
|
|
3743
|
+
"div",
|
|
3744
|
+
{
|
|
3745
|
+
className: `ss-jsonforms-field ss-jsonforms-number ${pillClass({
|
|
3746
|
+
hasError,
|
|
3747
|
+
disabled: isDisabled
|
|
3748
|
+
})}`,
|
|
3749
|
+
title: tooltip || void 0,
|
|
3750
|
+
children: [
|
|
3751
|
+
label && /* @__PURE__ */ jsxs(
|
|
3752
|
+
"label",
|
|
3753
|
+
{
|
|
3754
|
+
htmlFor: `number-${path2}`,
|
|
3755
|
+
className: `${pillLabelClass} whitespace-nowrap ${hasError ? "text-destructive" : "text-muted-foreground"}`,
|
|
3756
|
+
children: [
|
|
3757
|
+
label,
|
|
3758
|
+
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3759
|
+
]
|
|
3760
|
+
}
|
|
3761
|
+
),
|
|
3762
|
+
input
|
|
3763
|
+
]
|
|
3764
|
+
}
|
|
3765
|
+
);
|
|
3766
|
+
}
|
|
3767
|
+
return /* @__PURE__ */ jsxs("div", { className: "ss-jsonforms-field ss-jsonforms-number", children: [
|
|
3768
|
+
/* @__PURE__ */ jsxs("div", { className: fieldRowClass, children: [
|
|
3769
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: `number-${path2}`, className: fieldRowLabelClass(scale), children: [
|
|
3770
|
+
label,
|
|
3771
|
+
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3772
|
+
] }),
|
|
3773
|
+
input
|
|
3774
|
+
] }),
|
|
3775
|
+
hasError && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: errors })
|
|
3776
|
+
] });
|
|
3281
3777
|
};
|
|
3282
3778
|
var numberRendererTester = rankWith(
|
|
3283
3779
|
40,
|
|
@@ -3293,6 +3789,14 @@ var numberRendererTester = rankWith(
|
|
|
3293
3789
|
}
|
|
3294
3790
|
);
|
|
3295
3791
|
var NumberRendererControl = withJsonFormsControlProps(NumberRenderer);
|
|
3792
|
+
var SCALE = {
|
|
3793
|
+
comfortable: { lineHeight: 20, padding: 8 },
|
|
3794
|
+
dense: { lineHeight: 16, padding: 6 }
|
|
3795
|
+
};
|
|
3796
|
+
var rowsToPx = (rows, scale) => rows * scale.lineHeight + scale.padding * 2 + 2;
|
|
3797
|
+
var MAX_VIEWPORT_SHARE = 0.5;
|
|
3798
|
+
var DEFAULT_MIN_ROWS = 3;
|
|
3799
|
+
var DEFAULT_MAX_ROWS = 9;
|
|
3296
3800
|
var TextareaRenderer = ({
|
|
3297
3801
|
data,
|
|
3298
3802
|
handleChange,
|
|
@@ -3304,28 +3808,49 @@ var TextareaRenderer = ({
|
|
|
3304
3808
|
uischema,
|
|
3305
3809
|
visible,
|
|
3306
3810
|
enabled,
|
|
3307
|
-
required
|
|
3811
|
+
required,
|
|
3812
|
+
config
|
|
3308
3813
|
}) => {
|
|
3309
3814
|
const textareaRef = useRef(null);
|
|
3815
|
+
const textareaOptions = schema["ui:textarea"] ?? {};
|
|
3816
|
+
const formConfig = config ?? {};
|
|
3817
|
+
const scaleName = scaleFor(formConfig.surface ?? "form");
|
|
3818
|
+
const scale = SCALE[scaleName];
|
|
3819
|
+
const minRows = textareaOptions.minRows ?? formConfig.minRows ?? DEFAULT_MIN_ROWS;
|
|
3820
|
+
const maxRows = Math.max(
|
|
3821
|
+
minRows,
|
|
3822
|
+
textareaOptions.maxRows ?? formConfig.maxRows ?? DEFAULT_MAX_ROWS
|
|
3823
|
+
);
|
|
3824
|
+
const minHeight = rowsToPx(minRows, scale);
|
|
3825
|
+
const maxHeight = rowsToPx(maxRows, scale);
|
|
3826
|
+
const [viewportCap, setViewportCap] = useState(
|
|
3827
|
+
() => typeof window === "undefined" ? Number.POSITIVE_INFINITY : Math.round(window.innerHeight * MAX_VIEWPORT_SHARE)
|
|
3828
|
+
);
|
|
3829
|
+
const ceiling = Math.max(minHeight, Math.min(maxHeight, viewportCap));
|
|
3310
3830
|
const autoResize = useCallback(() => {
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
}
|
|
3320
|
-
}, []);
|
|
3831
|
+
const el = textareaRef.current;
|
|
3832
|
+
if (!el) return;
|
|
3833
|
+
el.style.height = "auto";
|
|
3834
|
+
el.style.height = `${Math.min(
|
|
3835
|
+
Math.max(el.scrollHeight, minHeight),
|
|
3836
|
+
ceiling
|
|
3837
|
+
)}px`;
|
|
3838
|
+
}, [minHeight, ceiling]);
|
|
3321
3839
|
useEffect(() => {
|
|
3322
3840
|
autoResize();
|
|
3323
3841
|
}, [data, autoResize]);
|
|
3842
|
+
useEffect(() => {
|
|
3843
|
+
const onResize = () => {
|
|
3844
|
+
setViewportCap(Math.round(window.innerHeight * MAX_VIEWPORT_SHARE));
|
|
3845
|
+
autoResize();
|
|
3846
|
+
};
|
|
3847
|
+
window.addEventListener("resize", onResize);
|
|
3848
|
+
return () => window.removeEventListener("resize", onResize);
|
|
3849
|
+
}, [autoResize]);
|
|
3324
3850
|
const handleInputChange = useCallback(
|
|
3325
3851
|
(event) => {
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
setTimeout(autoResize, 0);
|
|
3852
|
+
handleChange(path2, event.target.value);
|
|
3853
|
+
autoResize();
|
|
3329
3854
|
},
|
|
3330
3855
|
[handleChange, path2, autoResize]
|
|
3331
3856
|
);
|
|
@@ -3335,89 +3860,34 @@ var TextareaRenderer = ({
|
|
|
3335
3860
|
const readOnly = uischema?.access === "Read";
|
|
3336
3861
|
const isDisabled = !enabled || readOnly;
|
|
3337
3862
|
const hasError = errors && errors.length > 0;
|
|
3338
|
-
const textareaOptions = schema["ui:textarea"] ?? {};
|
|
3339
3863
|
const placeholder = textareaOptions.placeholder || schema?.description || `Enter ${label?.toLowerCase() || "text"}...`;
|
|
3340
|
-
const minRows = textareaOptions.minRows || 3;
|
|
3341
3864
|
return /* @__PURE__ */ jsxs("div", { className: "ss-jsonforms-field ss-jsonforms-textarea", children: [
|
|
3342
|
-
label && /* @__PURE__ */ jsxs(
|
|
3343
|
-
|
|
3344
|
-
{
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
color: hasError ? "#ef4444" : "#475569",
|
|
3348
|
-
fontSize: "0.875rem",
|
|
3349
|
-
fontWeight: 500,
|
|
3350
|
-
marginBottom: "0.375rem"
|
|
3351
|
-
},
|
|
3352
|
-
children: [
|
|
3353
|
-
label,
|
|
3354
|
-
required && /* @__PURE__ */ jsx("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
|
|
3355
|
-
]
|
|
3356
|
-
}
|
|
3357
|
-
),
|
|
3358
|
-
description && /* @__PURE__ */ jsx(
|
|
3359
|
-
"div",
|
|
3360
|
-
{
|
|
3361
|
-
style: {
|
|
3362
|
-
color: "#6b7280",
|
|
3363
|
-
fontSize: "0.75rem",
|
|
3364
|
-
marginBottom: "0.5rem"
|
|
3365
|
-
},
|
|
3366
|
-
children: description
|
|
3367
|
-
}
|
|
3368
|
-
),
|
|
3865
|
+
label && /* @__PURE__ */ jsxs("label", { htmlFor: path2, className: fieldLabelClass(scaleName), children: [
|
|
3866
|
+
label,
|
|
3867
|
+
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3868
|
+
] }),
|
|
3869
|
+
description && /* @__PURE__ */ jsx("div", { className: fieldHintClass, children: description }),
|
|
3369
3870
|
/* @__PURE__ */ jsx(
|
|
3370
3871
|
"textarea",
|
|
3371
3872
|
{
|
|
3873
|
+
id: path2,
|
|
3372
3874
|
ref: textareaRef,
|
|
3373
3875
|
value: data || "",
|
|
3374
3876
|
onChange: handleInputChange,
|
|
3375
3877
|
placeholder,
|
|
3376
3878
|
disabled: isDisabled,
|
|
3377
3879
|
rows: minRows,
|
|
3880
|
+
className: `resize-y ${fieldControlClass(scaleName, !!hasError)}`,
|
|
3378
3881
|
style: {
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
padding: "0.75rem",
|
|
3384
|
-
border: hasError ? "2px solid #ef4444" : "1px solid #d1d5db",
|
|
3385
|
-
borderRadius: "6px",
|
|
3386
|
-
fontSize: "16px",
|
|
3387
|
-
lineHeight: "1.5",
|
|
3388
|
-
fontFamily: "inherit",
|
|
3389
|
-
backgroundColor: isDisabled ? "#f9fafb" : "#ffffff",
|
|
3390
|
-
color: isDisabled ? "#9ca3af" : "#111827",
|
|
3391
|
-
outline: "none",
|
|
3392
|
-
transition: "border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out",
|
|
3393
|
-
boxShadow: hasError ? "0 0 0 1px #ef4444" : "none",
|
|
3882
|
+
minHeight: `${minHeight}px`,
|
|
3883
|
+
maxHeight: `${ceiling}px`,
|
|
3884
|
+
// iOS zooms a focused control under 16px; the design's fields are
|
|
3885
|
+
// 14px, so opt out of the adjustment rather than the design.
|
|
3394
3886
|
WebkitTextSizeAdjust: "100%"
|
|
3395
|
-
},
|
|
3396
|
-
onFocus: (e) => {
|
|
3397
|
-
if (!hasError) {
|
|
3398
|
-
e.target.style.borderColor = "#6366f1";
|
|
3399
|
-
e.target.style.boxShadow = "0 0 0 1px #6366f1";
|
|
3400
|
-
}
|
|
3401
|
-
},
|
|
3402
|
-
onBlur: (e) => {
|
|
3403
|
-
if (!hasError) {
|
|
3404
|
-
e.target.style.borderColor = "#d1d5db";
|
|
3405
|
-
e.target.style.boxShadow = "none";
|
|
3406
|
-
}
|
|
3407
3887
|
}
|
|
3408
3888
|
}
|
|
3409
3889
|
),
|
|
3410
|
-
hasError && /* @__PURE__ */ jsx(
|
|
3411
|
-
"div",
|
|
3412
|
-
{
|
|
3413
|
-
style: {
|
|
3414
|
-
color: "#ef4444",
|
|
3415
|
-
fontSize: "0.75rem",
|
|
3416
|
-
marginTop: "0.25rem"
|
|
3417
|
-
},
|
|
3418
|
-
children: errors
|
|
3419
|
-
}
|
|
3420
|
-
)
|
|
3890
|
+
hasError && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: errors })
|
|
3421
3891
|
] });
|
|
3422
3892
|
};
|
|
3423
3893
|
var textareaRendererTester = rankWith(
|
|
@@ -3469,14 +3939,31 @@ var renderers = [
|
|
|
3469
3939
|
];
|
|
3470
3940
|
|
|
3471
3941
|
// src/chat-variables/VariablesForm.vm.ts
|
|
3942
|
+
var MAX_INLINE_VARIABLES = 3;
|
|
3943
|
+
var isModelSelector = (schema) => schema.title === "ModelId" || schema["x-model-selector"] === true;
|
|
3944
|
+
function rowLayout(controls) {
|
|
3945
|
+
const innerRow = {
|
|
3946
|
+
type: "HorizontalLayout",
|
|
3947
|
+
elements: controls,
|
|
3948
|
+
options: { gap: "12px", alignItems: "flex-start" }
|
|
3949
|
+
};
|
|
3950
|
+
const ui = {
|
|
3951
|
+
type: "VerticalLayout",
|
|
3952
|
+
elements: [innerRow]
|
|
3953
|
+
};
|
|
3954
|
+
return ui;
|
|
3955
|
+
}
|
|
3472
3956
|
function buildSimpleSchemaAndUi(vars, threadVars, useDefaults) {
|
|
3473
3957
|
const names = Object.keys(vars || {});
|
|
3474
3958
|
const properties2 = {};
|
|
3475
3959
|
const controls = [];
|
|
3960
|
+
const inlineOnly = [];
|
|
3476
3961
|
const initialData = {};
|
|
3962
|
+
const $defs = {};
|
|
3477
3963
|
for (const name of names) {
|
|
3478
3964
|
const cfg = vars?.[name] || {};
|
|
3479
|
-
const s2 = cfg.schema || {};
|
|
3965
|
+
const { $defs: varDefs, ...s2 } = cfg.schema || {};
|
|
3966
|
+
if (varDefs) Object.assign($defs, varDefs);
|
|
3480
3967
|
properties2[name] = s2;
|
|
3481
3968
|
const hasServerKey = threadVars !== void 0 && Object.prototype.hasOwnProperty.call(threadVars, name);
|
|
3482
3969
|
const val = hasServerKey ? threadVars?.[name] : useDefaults ? s2.default : void 0;
|
|
@@ -3490,18 +3977,24 @@ function buildSimpleSchemaAndUi(vars, threadVars, useDefaults) {
|
|
|
3490
3977
|
control.enabled = false;
|
|
3491
3978
|
}
|
|
3492
3979
|
controls.push(control);
|
|
3980
|
+
if (isModelSelector(properties2[name])) inlineOnly.push(control);
|
|
3493
3981
|
}
|
|
3494
3982
|
const schema = { type: "object", properties: properties2 };
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3983
|
+
if (Object.keys($defs).length > 0) schema.$defs = $defs;
|
|
3984
|
+
if (controls.length <= MAX_INLINE_VARIABLES) {
|
|
3985
|
+
return {
|
|
3986
|
+
schema,
|
|
3987
|
+
inlineControls: controls,
|
|
3988
|
+
overflowControls: [],
|
|
3989
|
+
initialData
|
|
3990
|
+
};
|
|
3991
|
+
}
|
|
3992
|
+
return {
|
|
3993
|
+
schema,
|
|
3994
|
+
inlineControls: inlineOnly,
|
|
3995
|
+
overflowControls: controls.filter((c) => !inlineOnly.includes(c)),
|
|
3996
|
+
initialData
|
|
3503
3997
|
};
|
|
3504
|
-
return { schema, uiSchema: ui, initialData };
|
|
3505
3998
|
}
|
|
3506
3999
|
function useChatVariablesFormVm({
|
|
3507
4000
|
workspace,
|
|
@@ -3516,26 +4009,26 @@ function useChatVariablesFormVm({
|
|
|
3516
4009
|
const { mutate: updateVariableMutation } = useUpdateFlowRunVariable();
|
|
3517
4010
|
const querySettled = !isLoading && (threadVars !== void 0 || isError);
|
|
3518
4011
|
const shouldUseDefaults = isError || threadVars && Object.keys(threadVars).length === 0;
|
|
3519
|
-
const built =
|
|
4012
|
+
const built = React9.useMemo(() => {
|
|
3520
4013
|
return buildSimpleSchemaAndUi(
|
|
3521
4014
|
workspace.variables,
|
|
3522
4015
|
threadVars,
|
|
3523
4016
|
shouldUseDefaults ?? false
|
|
3524
4017
|
);
|
|
3525
4018
|
}, [workspace.variables, threadVars, shouldUseDefaults]);
|
|
3526
|
-
const [data, setData] =
|
|
3527
|
-
|
|
4019
|
+
const [data, setData] = React9.useState(null);
|
|
4020
|
+
React9.useEffect(() => {
|
|
3528
4021
|
if (querySettled) {
|
|
3529
4022
|
setData(built.initialData);
|
|
3530
4023
|
setVariables(built.initialData);
|
|
3531
4024
|
}
|
|
3532
4025
|
}, [querySettled, built.initialData, setVariables]);
|
|
3533
|
-
const ajv =
|
|
3534
|
-
const prevRef =
|
|
3535
|
-
|
|
4026
|
+
const ajv = React9.useMemo(() => createAjv({ useDefaults: false }), []);
|
|
4027
|
+
const prevRef = React9.useRef(null);
|
|
4028
|
+
React9.useEffect(() => {
|
|
3536
4029
|
prevRef.current = data;
|
|
3537
4030
|
}, [data]);
|
|
3538
|
-
const onChange =
|
|
4031
|
+
const onChange = React9.useCallback(
|
|
3539
4032
|
({ data: next2 }) => {
|
|
3540
4033
|
if (prevRef.current && !isDraftThreadId(threadId)) {
|
|
3541
4034
|
const keys2 = Object.keys(workspace.variables || {});
|
|
@@ -3556,29 +4049,96 @@ function useChatVariablesFormVm({
|
|
|
3556
4049
|
},
|
|
3557
4050
|
[workspace.variables, setVariables, updateVariableMutation, threadId]
|
|
3558
4051
|
);
|
|
3559
|
-
const
|
|
4052
|
+
const barConfig = React9.useMemo(
|
|
3560
4053
|
() => ({
|
|
3561
4054
|
restrict: true,
|
|
3562
4055
|
trim: false,
|
|
3563
4056
|
showUnfocusedDescription: true,
|
|
3564
|
-
hideRequiredAsterisk: true
|
|
4057
|
+
hideRequiredAsterisk: true,
|
|
4058
|
+
surface: "bar",
|
|
4059
|
+
minRows: 1,
|
|
4060
|
+
maxRows: 6
|
|
3565
4061
|
}),
|
|
3566
4062
|
[]
|
|
3567
4063
|
);
|
|
4064
|
+
const panelConfig = React9.useMemo(
|
|
4065
|
+
() => ({ ...barConfig, surface: "panel" }),
|
|
4066
|
+
[barConfig]
|
|
4067
|
+
);
|
|
4068
|
+
const inlineUiSchema = React9.useMemo(
|
|
4069
|
+
() => built.inlineControls.length ? rowLayout(built.inlineControls) : null,
|
|
4070
|
+
[built.inlineControls]
|
|
4071
|
+
);
|
|
4072
|
+
const overflowUiSchema = React9.useMemo(
|
|
4073
|
+
() => built.overflowControls.length ? rowLayout(built.overflowControls) : null,
|
|
4074
|
+
[built.overflowControls]
|
|
4075
|
+
);
|
|
3568
4076
|
return {
|
|
3569
4077
|
schema: built.schema,
|
|
3570
|
-
|
|
4078
|
+
inlineUiSchema,
|
|
4079
|
+
overflowUiSchema,
|
|
4080
|
+
overflowCount: built.overflowControls.length,
|
|
3571
4081
|
data,
|
|
3572
4082
|
renderers,
|
|
3573
4083
|
cells,
|
|
3574
4084
|
ajv,
|
|
3575
4085
|
onChange,
|
|
3576
|
-
|
|
4086
|
+
barConfig,
|
|
4087
|
+
panelConfig,
|
|
3577
4088
|
isLoading,
|
|
3578
4089
|
isReady: querySettled,
|
|
3579
4090
|
isHydrated: data !== null
|
|
3580
4091
|
};
|
|
3581
4092
|
}
|
|
4093
|
+
function VariablesOverflowPanel({ count, children: children2 }) {
|
|
4094
|
+
const triggerRef = useRef(null);
|
|
4095
|
+
const panelRef = useRef(null);
|
|
4096
|
+
const { isOpen, close, toggle, renderPopover } = useAnchoredPopover({
|
|
4097
|
+
trigger: triggerRef,
|
|
4098
|
+
popover: panelRef,
|
|
4099
|
+
width: POPOVER_WIDTH_PX,
|
|
4100
|
+
maxHeight: POPOVER_MAX_HEIGHT_PX,
|
|
4101
|
+
role: "dialog",
|
|
4102
|
+
label: "Workspace variables"
|
|
4103
|
+
});
|
|
4104
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4105
|
+
/* @__PURE__ */ jsxs(
|
|
4106
|
+
"button",
|
|
4107
|
+
{
|
|
4108
|
+
ref: triggerRef,
|
|
4109
|
+
type: "button",
|
|
4110
|
+
onClick: toggle,
|
|
4111
|
+
"aria-expanded": isOpen,
|
|
4112
|
+
"aria-haspopup": "dialog",
|
|
4113
|
+
"aria-label": `Variables (${count})`,
|
|
4114
|
+
className: `flex h-8 shrink-0 items-center gap-1.5 rounded-full border px-2.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${isOpen ? "border-primary/30 bg-primary/10 text-primary" : "border-border/70 bg-transparent text-muted-foreground hover:bg-secondary"}`,
|
|
4115
|
+
children: [
|
|
4116
|
+
/* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
4117
|
+
/* @__PURE__ */ jsx("span", { className: "inline max-sm:hidden", children: "Variables" }),
|
|
4118
|
+
/* @__PURE__ */ jsx("span", { className: "rounded-full bg-secondary px-1.5 text-[10px] leading-4 tabular-nums", children: count })
|
|
4119
|
+
]
|
|
4120
|
+
}
|
|
4121
|
+
),
|
|
4122
|
+
renderPopover(
|
|
4123
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4124
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-between border-b border-border px-3 py-2", children: [
|
|
4125
|
+
/* @__PURE__ */ jsx("span", { className: popoverHeadingClass, children: "Variables" }),
|
|
4126
|
+
/* @__PURE__ */ jsx(
|
|
4127
|
+
"button",
|
|
4128
|
+
{
|
|
4129
|
+
type: "button",
|
|
4130
|
+
onClick: close,
|
|
4131
|
+
"aria-label": "Close variables",
|
|
4132
|
+
className: "inline-flex h-5 w-5 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground",
|
|
4133
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
4134
|
+
}
|
|
4135
|
+
)
|
|
4136
|
+
] }),
|
|
4137
|
+
/* @__PURE__ */ jsx("div", { className: "ss-variables-panel min-h-0 overflow-y-auto p-3", children: children2 })
|
|
4138
|
+
] })
|
|
4139
|
+
)
|
|
4140
|
+
] });
|
|
4141
|
+
}
|
|
3582
4142
|
var ChatVariablesForm = forwardRef(({ workspace, threadId, setVariables }, ref) => {
|
|
3583
4143
|
const vm = useChatVariablesFormVm({ workspace, threadId, setVariables });
|
|
3584
4144
|
useImperativeHandle(ref, () => ({
|
|
@@ -3594,20 +4154,85 @@ var ChatVariablesForm = forwardRef(({ workspace, threadId, setVariables }, ref)
|
|
|
3594
4154
|
if (!vm.isHydrated) {
|
|
3595
4155
|
return /* @__PURE__ */ jsx("div", { className: "flex justify-center items-center w-full h-8", children: /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-primary" }) });
|
|
3596
4156
|
}
|
|
3597
|
-
|
|
3598
|
-
|
|
4157
|
+
const formProps = {
|
|
4158
|
+
schema: vm.schema,
|
|
4159
|
+
data: vm.data,
|
|
4160
|
+
renderers: vm.renderers,
|
|
4161
|
+
cells: vm.cells,
|
|
4162
|
+
ajv: vm.ajv,
|
|
4163
|
+
onChange: vm.onChange
|
|
4164
|
+
};
|
|
4165
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex w-full min-w-0 items-center gap-1", children: [
|
|
4166
|
+
vm.inlineUiSchema && /* @__PURE__ */ jsx("div", { className: "min-w-0 jsonforms-compact", children: /* @__PURE__ */ jsx(
|
|
4167
|
+
JsonForms,
|
|
4168
|
+
{
|
|
4169
|
+
...formProps,
|
|
4170
|
+
uischema: vm.inlineUiSchema,
|
|
4171
|
+
config: vm.barConfig
|
|
4172
|
+
}
|
|
4173
|
+
) }),
|
|
4174
|
+
vm.overflowUiSchema && /* @__PURE__ */ jsx(VariablesOverflowPanel, { count: vm.overflowCount, children: /* @__PURE__ */ jsx("div", { className: "jsonforms-compact", children: /* @__PURE__ */ jsx(
|
|
4175
|
+
JsonForms,
|
|
4176
|
+
{
|
|
4177
|
+
...formProps,
|
|
4178
|
+
uischema: vm.overflowUiSchema,
|
|
4179
|
+
config: vm.panelConfig
|
|
4180
|
+
}
|
|
4181
|
+
) }) })
|
|
4182
|
+
] });
|
|
4183
|
+
});
|
|
4184
|
+
var dictationErrorMessages = {
|
|
4185
|
+
"permission-denied": "Microphone access is blocked \u2014 allow it in your browser settings and try again",
|
|
4186
|
+
"no-microphone": "No microphone was found",
|
|
4187
|
+
network: "Could not reach the speech service \u2014 try again",
|
|
4188
|
+
"unavailable-temporarily": "Dictation is starting up \u2014 try again in a moment",
|
|
4189
|
+
unavailable: "Dictation is not available on this workspace",
|
|
4190
|
+
unknown: "Dictation stopped unexpectedly \u2014 try again"
|
|
4191
|
+
};
|
|
4192
|
+
function DictationButton({
|
|
4193
|
+
state,
|
|
4194
|
+
error,
|
|
4195
|
+
disabled,
|
|
4196
|
+
onToggle,
|
|
4197
|
+
deviceLabel,
|
|
4198
|
+
size = "sm"
|
|
4199
|
+
}) {
|
|
4200
|
+
const listening = state === "listening";
|
|
4201
|
+
const starting = state === "starting";
|
|
4202
|
+
const label = listening ? "Stop dictation" : "Dictate a message";
|
|
4203
|
+
const hint = listening && deviceLabel ? `${label} \u2014 ${deviceLabel}` : label;
|
|
4204
|
+
const dims = size === "sm" ? "h-8 w-8" : "h-9 w-9";
|
|
4205
|
+
const icon = size === "sm" ? "h-4 w-4" : "h-5 w-5";
|
|
4206
|
+
return /* @__PURE__ */ jsxs(
|
|
4207
|
+
IconButton2,
|
|
3599
4208
|
{
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
4209
|
+
type: "button",
|
|
4210
|
+
onClick: onToggle,
|
|
4211
|
+
disabled,
|
|
4212
|
+
"aria-pressed": listening,
|
|
4213
|
+
"aria-label": label,
|
|
4214
|
+
title: error ? dictationErrorMessages[error] : hint,
|
|
4215
|
+
className: `relative ${dims} rounded-full transition-colors ${listening ? "bg-destructive text-destructive-foreground hover:bg-destructive/90" : "text-muted-foreground hover:bg-secondary"}`,
|
|
4216
|
+
children: [
|
|
4217
|
+
starting && /* @__PURE__ */ jsx(
|
|
4218
|
+
"span",
|
|
4219
|
+
{
|
|
4220
|
+
"aria-hidden": "true",
|
|
4221
|
+
className: "absolute inset-0 animate-spin rounded-full border-2 border-transparent border-t-current opacity-70"
|
|
4222
|
+
}
|
|
4223
|
+
),
|
|
4224
|
+
listening && /* @__PURE__ */ jsx(
|
|
4225
|
+
"span",
|
|
4226
|
+
{
|
|
4227
|
+
"aria-hidden": "true",
|
|
4228
|
+
className: "absolute inset-0 animate-ping rounded-full bg-destructive/30"
|
|
4229
|
+
}
|
|
4230
|
+
),
|
|
4231
|
+
listening ? /* @__PURE__ */ jsx(Square, { className: `relative ${icon} fill-current` }) : /* @__PURE__ */ jsx(Mic, { className: `relative ${icon}` })
|
|
4232
|
+
]
|
|
3608
4233
|
}
|
|
3609
|
-
)
|
|
3610
|
-
}
|
|
4234
|
+
);
|
|
4235
|
+
}
|
|
3611
4236
|
|
|
3612
4237
|
// src/domains/workspaces/queryKeys.ts
|
|
3613
4238
|
var workspaceKeys = {
|
|
@@ -3840,6 +4465,40 @@ function MessageComposer(_props = {}) {
|
|
|
3840
4465
|
cancelReset();
|
|
3841
4466
|
}
|
|
3842
4467
|
}, [isSending, cancelAccepted, cancelErrored, cancelReset]);
|
|
4468
|
+
const attachEditor = useCallback(
|
|
4469
|
+
(handle2) => {
|
|
4470
|
+
if (handle2) editorRef.current = handle2;
|
|
4471
|
+
},
|
|
4472
|
+
// Both flags matter: the portal mounts on `isMobile && isFullscreen`, and
|
|
4473
|
+
// nothing resets isFullscreen when the breakpoint flips, so crossing it
|
|
4474
|
+
// while fullscreen would unmount the portal editor without re-attaching the
|
|
4475
|
+
// inline one — leaving a destroyed handle and silently swallowing phrases.
|
|
4476
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4477
|
+
[isFullscreen, isMobile]
|
|
4478
|
+
);
|
|
4479
|
+
const { data: speechConfig, isFetching: speechConfigLoading } = useSpeechConfig();
|
|
4480
|
+
const getSpeechToken = useMemo(
|
|
4481
|
+
() => chatService.getSpeechToken?.bind(chatService),
|
|
4482
|
+
[chatService]
|
|
4483
|
+
);
|
|
4484
|
+
const dictation = useDictation({
|
|
4485
|
+
region: speechConfig?.enabled ? speechConfig.region : null,
|
|
4486
|
+
locale: speechConfig?.defaultLocale ?? "en-US",
|
|
4487
|
+
getToken: getSpeechToken,
|
|
4488
|
+
// Final phrases become real text; provisional ones render as greyed ghost
|
|
4489
|
+
// text at the caret and never enter the document.
|
|
4490
|
+
onPhrase: (text6) => editorRef.current?.insertText(`${text6} `),
|
|
4491
|
+
onInterim: (text6) => editorRef.current?.setDictationGhost(text6)
|
|
4492
|
+
});
|
|
4493
|
+
const { stop: stopDictation } = dictation;
|
|
4494
|
+
const dictationUnavailableReason = speechConfigLoading ? "Checking whether dictation is available" : dictation.supported ? "Dictation is not enabled for this workspace" : "Dictation is not available in this browser";
|
|
4495
|
+
const handleDictationToggle = () => {
|
|
4496
|
+
if (dictation.state === "idle") editorRef.current?.focus();
|
|
4497
|
+
dictation.toggle();
|
|
4498
|
+
};
|
|
4499
|
+
useEffect(() => {
|
|
4500
|
+
if (disabled) stopDictation();
|
|
4501
|
+
}, [disabled, stopDictation]);
|
|
3843
4502
|
useEffect(() => {
|
|
3844
4503
|
if (typeof window === "undefined") return;
|
|
3845
4504
|
window.__ssDownloadFile = (id) => getFileBlobUrl(id);
|
|
@@ -3959,6 +4618,7 @@ function MessageComposer(_props = {}) {
|
|
|
3959
4618
|
const latestText = editorRef.current?.getMarkdown() ?? newMessage;
|
|
3960
4619
|
const sent = handleSendMessage(latestText, uploadedAttachments);
|
|
3961
4620
|
if (!sent) return;
|
|
4621
|
+
stopDictation();
|
|
3962
4622
|
handleClearAttachments();
|
|
3963
4623
|
setEditorKey((k) => k + 1);
|
|
3964
4624
|
};
|
|
@@ -4065,7 +4725,7 @@ function MessageComposer(_props = {}) {
|
|
|
4065
4725
|
/* @__PURE__ */ jsx("div", { className: "max-h-[400px] w-full overflow-y-auto", children: /* @__PURE__ */ jsx(
|
|
4066
4726
|
MarkdownEditor,
|
|
4067
4727
|
{
|
|
4068
|
-
ref:
|
|
4728
|
+
ref: attachEditor,
|
|
4069
4729
|
value: newMessage,
|
|
4070
4730
|
onChange: (md) => setNewMessage(md),
|
|
4071
4731
|
onKeyDown: handleComposerKeyDown,
|
|
@@ -4078,14 +4738,22 @@ function MessageComposer(_props = {}) {
|
|
|
4078
4738
|
disabled,
|
|
4079
4739
|
placeholder: "What would you like to do?",
|
|
4080
4740
|
className: "md-editor--bare px-5 pb-3 pt-4 text-sm",
|
|
4081
|
-
minHeight:
|
|
4741
|
+
minHeight: 24
|
|
4082
4742
|
},
|
|
4083
4743
|
`composer-md-${editorKey}`
|
|
4084
4744
|
) }),
|
|
4745
|
+
/* @__PURE__ */ jsx("div", { role: "status", className: "sr-only", children: dictation.state === "listening" ? dictation.silent ? `Listening, but not hearing anything from ${dictation.deviceLabel || "your microphone"}` : "Listening" : dictation.state === "starting" ? "Starting dictation" : "" }),
|
|
4746
|
+
dictation.state === "listening" && dictation.silent && /* @__PURE__ */ jsxs("div", { className: "px-5 pb-1 text-xs text-muted-foreground", children: [
|
|
4747
|
+
"Not hearing anything from",
|
|
4748
|
+
" ",
|
|
4749
|
+
dictation.deviceLabel || "your microphone",
|
|
4750
|
+
"."
|
|
4751
|
+
] }),
|
|
4752
|
+
dictation.error && /* @__PURE__ */ jsx("div", { role: "alert", className: "px-5 pb-1 text-xs text-destructive", children: dictationErrorMessages[dictation.error] }),
|
|
4085
4753
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-3 pb-3", children: [
|
|
4086
4754
|
/* @__PURE__ */ jsxs("div", { className: "ss-composer__actions flex min-w-0 flex-1 items-center gap-1", children: [
|
|
4087
4755
|
supportsFiles && /* @__PURE__ */ jsx(
|
|
4088
|
-
|
|
4756
|
+
IconButton2,
|
|
4089
4757
|
{
|
|
4090
4758
|
type: "button",
|
|
4091
4759
|
onClick: handlePickFilesClick,
|
|
@@ -4106,19 +4774,39 @@ function MessageComposer(_props = {}) {
|
|
|
4106
4774
|
)
|
|
4107
4775
|
] }),
|
|
4108
4776
|
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
4109
|
-
/* @__PURE__ */ jsx(
|
|
4110
|
-
|
|
4777
|
+
dictation.available ? /* @__PURE__ */ jsx(
|
|
4778
|
+
DictationButton,
|
|
4111
4779
|
{
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
children: /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" })
|
|
4780
|
+
state: dictation.state,
|
|
4781
|
+
error: dictation.error,
|
|
4782
|
+
disabled,
|
|
4783
|
+
onToggle: handleDictationToggle,
|
|
4784
|
+
deviceLabel: dictation.deviceLabel
|
|
4118
4785
|
}
|
|
4786
|
+
) : (
|
|
4787
|
+
// A disabled button receives no pointer events, so its own
|
|
4788
|
+
// `title` never renders a tooltip. The wrapper is what the user
|
|
4789
|
+
// actually hovers.
|
|
4790
|
+
/* @__PURE__ */ jsx(
|
|
4791
|
+
"span",
|
|
4792
|
+
{
|
|
4793
|
+
title: dictationUnavailableReason,
|
|
4794
|
+
className: "inline-flex cursor-not-allowed",
|
|
4795
|
+
children: /* @__PURE__ */ jsx(
|
|
4796
|
+
IconButton2,
|
|
4797
|
+
{
|
|
4798
|
+
type: "button",
|
|
4799
|
+
disabled: true,
|
|
4800
|
+
"aria-label": `Dictate a message. ${dictationUnavailableReason}`,
|
|
4801
|
+
className: "h-8 w-8 rounded-full text-muted-foreground",
|
|
4802
|
+
children: /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" })
|
|
4803
|
+
}
|
|
4804
|
+
)
|
|
4805
|
+
}
|
|
4806
|
+
)
|
|
4119
4807
|
),
|
|
4120
4808
|
canStop ? /* @__PURE__ */ jsx(
|
|
4121
|
-
|
|
4809
|
+
IconButton2,
|
|
4122
4810
|
{
|
|
4123
4811
|
onClick: handleStopRun,
|
|
4124
4812
|
className: "chat-send h-8 w-8 rounded-full",
|
|
@@ -4132,7 +4820,7 @@ function MessageComposer(_props = {}) {
|
|
|
4132
4820
|
)
|
|
4133
4821
|
}
|
|
4134
4822
|
) : /* @__PURE__ */ jsx(
|
|
4135
|
-
|
|
4823
|
+
IconButton2,
|
|
4136
4824
|
{
|
|
4137
4825
|
onClick: handleSendMessageAndClear,
|
|
4138
4826
|
className: `chat-send h-8 w-8 rounded-full ${sendDisabled ? "cursor-not-allowed" : ""}`,
|
|
@@ -4161,7 +4849,7 @@ function MessageComposer(_props = {}) {
|
|
|
4161
4849
|
},
|
|
4162
4850
|
children: /* @__PURE__ */ jsxs("div", { className: "relative h-full w-full bg-background border shadow-lg", children: [
|
|
4163
4851
|
/* @__PURE__ */ jsx(
|
|
4164
|
-
|
|
4852
|
+
IconButton2,
|
|
4165
4853
|
{
|
|
4166
4854
|
type: "button",
|
|
4167
4855
|
size: "small",
|
|
@@ -4179,7 +4867,7 @@ function MessageComposer(_props = {}) {
|
|
|
4179
4867
|
/* @__PURE__ */ jsx("div", { className: "flex-1 p-4", children: /* @__PURE__ */ jsx(
|
|
4180
4868
|
MarkdownEditor,
|
|
4181
4869
|
{
|
|
4182
|
-
ref:
|
|
4870
|
+
ref: attachEditor,
|
|
4183
4871
|
value: newMessage,
|
|
4184
4872
|
onChange: (md) => setNewMessage(md),
|
|
4185
4873
|
onKeyDown: handleComposerKeyDown,
|
|
@@ -4194,10 +4882,18 @@ function MessageComposer(_props = {}) {
|
|
|
4194
4882
|
},
|
|
4195
4883
|
`composer-md-${editorKey}`
|
|
4196
4884
|
) }),
|
|
4885
|
+
dictation.error && /* @__PURE__ */ jsx(
|
|
4886
|
+
"div",
|
|
4887
|
+
{
|
|
4888
|
+
"aria-hidden": "true",
|
|
4889
|
+
className: "px-4 pb-1 text-xs text-destructive",
|
|
4890
|
+
children: dictationErrorMessages[dictation.error]
|
|
4891
|
+
}
|
|
4892
|
+
),
|
|
4197
4893
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-t bg-background", children: [
|
|
4198
4894
|
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
4199
4895
|
supportsFiles && /* @__PURE__ */ jsx(
|
|
4200
|
-
|
|
4896
|
+
IconButton2,
|
|
4201
4897
|
{
|
|
4202
4898
|
type: "button",
|
|
4203
4899
|
onClick: handlePickFilesClick,
|
|
@@ -4212,8 +4908,19 @@ function MessageComposer(_props = {}) {
|
|
|
4212
4908
|
)
|
|
4213
4909
|
}
|
|
4214
4910
|
),
|
|
4911
|
+
dictation.available && /* @__PURE__ */ jsx(
|
|
4912
|
+
DictationButton,
|
|
4913
|
+
{
|
|
4914
|
+
size: "md",
|
|
4915
|
+
state: dictation.state,
|
|
4916
|
+
error: dictation.error,
|
|
4917
|
+
disabled,
|
|
4918
|
+
onToggle: handleDictationToggle,
|
|
4919
|
+
deviceLabel: dictation.deviceLabel
|
|
4920
|
+
}
|
|
4921
|
+
),
|
|
4215
4922
|
canStop ? /* @__PURE__ */ jsx(
|
|
4216
|
-
|
|
4923
|
+
IconButton2,
|
|
4217
4924
|
{
|
|
4218
4925
|
onClick: handleStopRun,
|
|
4219
4926
|
className: "chat-send h-9 w-9 rounded-full",
|
|
@@ -4227,7 +4934,7 @@ function MessageComposer(_props = {}) {
|
|
|
4227
4934
|
)
|
|
4228
4935
|
}
|
|
4229
4936
|
) : /* @__PURE__ */ jsx(
|
|
4230
|
-
|
|
4937
|
+
IconButton2,
|
|
4231
4938
|
{
|
|
4232
4939
|
onClick: handleSendMessageAndClear,
|
|
4233
4940
|
className: `chat-send h-9 w-9 rounded-full ${sendDisabled ? "cursor-not-allowed" : ""}`,
|
|
@@ -18941,6 +19648,107 @@ var getMessageErrorText = (error) => {
|
|
|
18941
19648
|
}
|
|
18942
19649
|
return STATUS_CODE_TEXT[error.code] ?? GENERIC_ERROR_TEXT;
|
|
18943
19650
|
};
|
|
19651
|
+
function extractProviderErrorDetail(raw2) {
|
|
19652
|
+
const start = raw2.indexOf("{");
|
|
19653
|
+
if (start === -1) return null;
|
|
19654
|
+
let parsed;
|
|
19655
|
+
try {
|
|
19656
|
+
parsed = JSON.parse(raw2.slice(start));
|
|
19657
|
+
} catch {
|
|
19658
|
+
return null;
|
|
19659
|
+
}
|
|
19660
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
19661
|
+
const record = parsed;
|
|
19662
|
+
const inner = typeof record.error === "object" && record.error !== null ? record.error : record;
|
|
19663
|
+
if (typeof inner.message !== "string") return null;
|
|
19664
|
+
return {
|
|
19665
|
+
message: inner.message,
|
|
19666
|
+
param: typeof inner.param === "string" ? inner.param : void 0
|
|
19667
|
+
};
|
|
19668
|
+
}
|
|
19669
|
+
var getMessageErrorDetail = (error) => {
|
|
19670
|
+
if (typeof error === "number" || !error.message) {
|
|
19671
|
+
return null;
|
|
19672
|
+
}
|
|
19673
|
+
const detail = extractProviderErrorDetail(error.message);
|
|
19674
|
+
if (!detail) {
|
|
19675
|
+
return error.message;
|
|
19676
|
+
}
|
|
19677
|
+
return detail.param ? `${detail.message} (param: ${detail.param})` : detail.message;
|
|
19678
|
+
};
|
|
19679
|
+
var FileInfoSchema = z.object({
|
|
19680
|
+
id: z.string(),
|
|
19681
|
+
name: z.string()
|
|
19682
|
+
});
|
|
19683
|
+
z.object({
|
|
19684
|
+
workspaceId: z.string().optional(),
|
|
19685
|
+
threadId: z.string().optional()
|
|
19686
|
+
});
|
|
19687
|
+
|
|
19688
|
+
// src/domains/messages/schemas.ts
|
|
19689
|
+
var MessageResponseSourceSchema = z.object({
|
|
19690
|
+
index: z.number(),
|
|
19691
|
+
datasetItemId: z.string().optional(),
|
|
19692
|
+
containerItemId: z.string().nullish(),
|
|
19693
|
+
flowRunId: z.string().optional(),
|
|
19694
|
+
file: FileInfoSchema.nullish(),
|
|
19695
|
+
url: z.string().nullish(),
|
|
19696
|
+
sourceType: z.nativeEnum(MessageResponseSourceType),
|
|
19697
|
+
// WS3c citation grounding (additive; absent on older responses).
|
|
19698
|
+
uri: z.string().nullish(),
|
|
19699
|
+
citedText: z.string().nullish(),
|
|
19700
|
+
attribution: z.nativeEnum(MessageAttribution).nullish(),
|
|
19701
|
+
// Where the cited item lives at its source (SharePoint web link, HubSpot record page).
|
|
19702
|
+
// Distinct from `url` (the source *is* that URL): this rides File sources so the card
|
|
19703
|
+
// can offer "open at source" beside the download of our copy. Absent when unknown.
|
|
19704
|
+
webUrl: z.string().nullish()
|
|
19705
|
+
});
|
|
19706
|
+
var MessageResponseSchema = z.object({
|
|
19707
|
+
content: z.string(),
|
|
19708
|
+
messageId: z.string(),
|
|
19709
|
+
sources: z.array(MessageResponseSourceSchema).nullish(),
|
|
19710
|
+
isReplying: z.boolean().nullish().default(false),
|
|
19711
|
+
requestedJsonSchema: z.string().nullish()
|
|
19712
|
+
});
|
|
19713
|
+
var MessageErrorMessageSchema = z.object({
|
|
19714
|
+
code: z.number(),
|
|
19715
|
+
// Stable machine-readable category (e.g. "llm.rate_limit"). Accept both
|
|
19716
|
+
// spellings: app-api serialises camelCase, the ai-api origin field is
|
|
19717
|
+
// snake_case — the mapper coalesces them.
|
|
19718
|
+
errorCode: z.string().nullish(),
|
|
19719
|
+
error_code: z.string().nullish(),
|
|
19720
|
+
message: z.string().nullish(),
|
|
19721
|
+
data: z.string().nullish(),
|
|
19722
|
+
blockId: z.string().nullish()
|
|
19723
|
+
});
|
|
19724
|
+
var MessageSchema = z.object({
|
|
19725
|
+
id: z.string().nullish(),
|
|
19726
|
+
createdAt: DateFromApi,
|
|
19727
|
+
createdBy: z.string().nullish(),
|
|
19728
|
+
hasComments: z.boolean().default(false),
|
|
19729
|
+
createdByUserId: z.string().nullish(),
|
|
19730
|
+
messageThreadId: z.string().nullish(),
|
|
19731
|
+
errors: z.array(MessageErrorMessageSchema).nullish(),
|
|
19732
|
+
values: z.array(
|
|
19733
|
+
z.object({
|
|
19734
|
+
id: z.string(),
|
|
19735
|
+
name: z.string(),
|
|
19736
|
+
type: z.nativeEnum(MessageValueType),
|
|
19737
|
+
value: z.any(),
|
|
19738
|
+
// Can be string (for Output), array (for Input), or object (for Variables)
|
|
19739
|
+
channels: z.record(z.string(), z.number()),
|
|
19740
|
+
createdAt: DateFromApi,
|
|
19741
|
+
createdBy: z.string(),
|
|
19742
|
+
createdByUserId: z.string().nullish()
|
|
19743
|
+
})
|
|
19744
|
+
).nullish(),
|
|
19745
|
+
optimistic: z.boolean().optional().default(false)
|
|
19746
|
+
});
|
|
19747
|
+
z.object({
|
|
19748
|
+
text: z.string().nullish(),
|
|
19749
|
+
image: FileInfoSchema.nullish()
|
|
19750
|
+
});
|
|
19751
|
+
z.array(MessageSchema);
|
|
18944
19752
|
|
|
18945
19753
|
// src/domains/messages/statuses.ts
|
|
18946
19754
|
var asRecord = (value) => {
|
|
@@ -19084,7 +19892,7 @@ var buttonVariants = cva(
|
|
|
19084
19892
|
}
|
|
19085
19893
|
}
|
|
19086
19894
|
);
|
|
19087
|
-
var Button =
|
|
19895
|
+
var Button = React9.forwardRef(
|
|
19088
19896
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
19089
19897
|
const Comp = asChild ? Slot : "button";
|
|
19090
19898
|
return /* @__PURE__ */ jsx(
|
|
@@ -19547,6 +20355,7 @@ function ChatMessageSources({
|
|
|
19547
20355
|
/* @__PURE__ */ jsx(SectionLabel, { children: "Files" }),
|
|
19548
20356
|
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: fileSources.map((source) => {
|
|
19549
20357
|
const Icon = getFileIcon3(source.file.name);
|
|
20358
|
+
const sourceHref = source.webUrl ? getSafeUrl(source.webUrl) : null;
|
|
19550
20359
|
if (!openIndexes.has(source.index)) {
|
|
19551
20360
|
return /* @__PURE__ */ jsxs(
|
|
19552
20361
|
"button",
|
|
@@ -19595,19 +20404,36 @@ function ChatMessageSources({
|
|
|
19595
20404
|
)
|
|
19596
20405
|
] }),
|
|
19597
20406
|
/* @__PURE__ */ jsx(CitedQuote, { text: source.citedText }),
|
|
19598
|
-
/* @__PURE__ */ jsxs(
|
|
19599
|
-
|
|
19600
|
-
|
|
19601
|
-
|
|
19602
|
-
|
|
19603
|
-
|
|
19604
|
-
|
|
19605
|
-
|
|
19606
|
-
|
|
19607
|
-
|
|
19608
|
-
|
|
19609
|
-
|
|
19610
|
-
|
|
20407
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
20408
|
+
sourceHref && /* @__PURE__ */ jsxs(
|
|
20409
|
+
"a",
|
|
20410
|
+
{
|
|
20411
|
+
href: sourceHref,
|
|
20412
|
+
target: "_blank",
|
|
20413
|
+
rel: "noreferrer",
|
|
20414
|
+
title: source.webUrl ?? void 0,
|
|
20415
|
+
className: "inline-flex w-fit items-center gap-1 rounded-md border border-border/60 px-2 py-1 text-xs font-medium text-foreground no-underline transition-colors hover:bg-muted/40",
|
|
20416
|
+
children: [
|
|
20417
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3" }),
|
|
20418
|
+
"Open in ",
|
|
20419
|
+
getHost(sourceHref)
|
|
20420
|
+
]
|
|
20421
|
+
}
|
|
20422
|
+
),
|
|
20423
|
+
/* @__PURE__ */ jsxs(
|
|
20424
|
+
"button",
|
|
20425
|
+
{
|
|
20426
|
+
type: "button",
|
|
20427
|
+
onClick: () => downloadFileMutation.mutate(source.file),
|
|
20428
|
+
disabled: downloadFileMutation.isPending,
|
|
20429
|
+
className: "inline-flex w-fit items-center gap-1 rounded-md border border-border/60 px-2 py-1 text-xs font-medium text-foreground transition-colors hover:bg-muted/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
20430
|
+
children: [
|
|
20431
|
+
/* @__PURE__ */ jsx(Download, { className: "h-3 w-3" }),
|
|
20432
|
+
"Download"
|
|
20433
|
+
]
|
|
20434
|
+
}
|
|
20435
|
+
)
|
|
20436
|
+
] })
|
|
19611
20437
|
]
|
|
19612
20438
|
},
|
|
19613
20439
|
`${source.file.id}-${source.index}`
|
|
@@ -19617,6 +20443,7 @@ function ChatMessageSources({
|
|
|
19617
20443
|
] })
|
|
19618
20444
|
] });
|
|
19619
20445
|
}
|
|
20446
|
+
var USER_FORM_CONFIG = { surface: "form", minRows: 6, maxRows: 20 };
|
|
19620
20447
|
var REVEAL_ON_HOVER = "opacity-100 focus-visible:opacity-100 [@media(hover:hover)]:opacity-0 [@media(hover:hover)]:group-hover:opacity-100";
|
|
19621
20448
|
var MessageBubble = (props) => {
|
|
19622
20449
|
const {
|
|
@@ -19670,7 +20497,7 @@ var MessageBubble = (props) => {
|
|
|
19670
20497
|
);
|
|
19671
20498
|
})
|
|
19672
20499
|
] }),
|
|
19673
|
-
showForm && /* @__PURE__ */ jsxs("div", { className: "mt-4 border-t border-border pt-4", children: [
|
|
20500
|
+
showForm && /* @__PURE__ */ jsxs("div", { className: "ss-chat-message__user-form mt-4 border-t border-border pt-4", children: [
|
|
19674
20501
|
/* @__PURE__ */ jsx(
|
|
19675
20502
|
JsonForms,
|
|
19676
20503
|
{
|
|
@@ -19679,6 +20506,7 @@ var MessageBubble = (props) => {
|
|
|
19679
20506
|
renderers,
|
|
19680
20507
|
cells,
|
|
19681
20508
|
readonly: userInput !== void 0,
|
|
20509
|
+
config: USER_FORM_CONFIG,
|
|
19682
20510
|
onChange: ({ data, errors }) => {
|
|
19683
20511
|
setResponseFormData(data);
|
|
19684
20512
|
setResponseFormValid(!errors?.length);
|
|
@@ -19739,6 +20567,25 @@ var MessageBubble = (props) => {
|
|
|
19739
20567
|
/* @__PURE__ */ jsx("div", { className: "mt-1.5", children: metaRow })
|
|
19740
20568
|
] });
|
|
19741
20569
|
};
|
|
20570
|
+
function MessageErrorDetails({ detail }) {
|
|
20571
|
+
const [expanded, setExpanded] = useState(false);
|
|
20572
|
+
return /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
|
|
20573
|
+
/* @__PURE__ */ jsxs(
|
|
20574
|
+
"button",
|
|
20575
|
+
{
|
|
20576
|
+
type: "button",
|
|
20577
|
+
onClick: () => setExpanded((prev) => !prev),
|
|
20578
|
+
"aria-expanded": expanded,
|
|
20579
|
+
className: "m-0 inline-flex w-auto cursor-pointer appearance-none items-center gap-1 border-0 bg-transparent p-0 text-[11px] font-medium leading-none text-muted-foreground hover:text-foreground",
|
|
20580
|
+
children: [
|
|
20581
|
+
expanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3 shrink-0" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 shrink-0" }),
|
|
20582
|
+
expanded ? "Hide details" : "Show details"
|
|
20583
|
+
]
|
|
20584
|
+
}
|
|
20585
|
+
),
|
|
20586
|
+
expanded && /* @__PURE__ */ jsx("div", { className: "mt-1.5 whitespace-pre-wrap break-words rounded-md bg-secondary/60 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: detail })
|
|
20587
|
+
] });
|
|
20588
|
+
}
|
|
19742
20589
|
var ThinkingSection = ({ status }) => /* @__PURE__ */ jsxs(
|
|
19743
20590
|
"div",
|
|
19744
20591
|
{
|
|
@@ -19811,6 +20658,10 @@ function coerceSources(x) {
|
|
|
19811
20658
|
if (!Array.isArray(x)) return [];
|
|
19812
20659
|
return x.filter(isMessageResponseSource);
|
|
19813
20660
|
}
|
|
20661
|
+
var ENVELOPE_KEYS = Object.keys(MessageResponseSchema.shape);
|
|
20662
|
+
function isResponseEnvelope(keys2) {
|
|
20663
|
+
return keys2.length > 0 && keys2.every((key) => ENVELOPE_KEYS.includes(key));
|
|
20664
|
+
}
|
|
19814
20665
|
var MessageItem = ({
|
|
19815
20666
|
message,
|
|
19816
20667
|
isLive = false
|
|
@@ -19819,14 +20670,14 @@ var MessageItem = ({
|
|
|
19819
20670
|
const { data: workspace } = useWorkspace(workspaceId);
|
|
19820
20671
|
const chatbotName = getChatbotName(workspace?.name);
|
|
19821
20672
|
const { addInputToMessageMutation } = useAddInputToMessage();
|
|
19822
|
-
const onSubmitUserForm = (messageId) => (name, value) => {
|
|
20673
|
+
const onSubmitUserForm = (messageId, channels = {}) => (name, value) => {
|
|
19823
20674
|
if (!threadId || !messageId) return;
|
|
19824
20675
|
addInputToMessageMutation.mutate({
|
|
19825
20676
|
threadId,
|
|
19826
20677
|
messageId,
|
|
19827
20678
|
name,
|
|
19828
20679
|
value,
|
|
19829
|
-
channels
|
|
20680
|
+
channels
|
|
19830
20681
|
});
|
|
19831
20682
|
};
|
|
19832
20683
|
const safeTime = (d) => {
|
|
@@ -19918,9 +20769,16 @@ var MessageItem = ({
|
|
|
19918
20769
|
});
|
|
19919
20770
|
} else if (name === "response" && typeof v.value === "object" && v.value !== null && !Array.isArray(v.value)) {
|
|
19920
20771
|
const resp = v.value;
|
|
19921
|
-
const
|
|
19922
|
-
|
|
19923
|
-
|
|
20772
|
+
const keys2 = Object.keys(resp);
|
|
20773
|
+
const isEnvelope = isResponseEnvelope(keys2);
|
|
20774
|
+
if ("sources" in resp && (isEnvelope || "text" in resp || "image" in resp)) {
|
|
20775
|
+
groupSources = coerceSources(resp.sources);
|
|
20776
|
+
}
|
|
20777
|
+
if (isEnvelope) {
|
|
20778
|
+
pushContent(groupContent, resp.content);
|
|
20779
|
+
} else if (keys2.length > 0) {
|
|
20780
|
+
pushContent(groupContent, resp);
|
|
20781
|
+
}
|
|
19924
20782
|
} else {
|
|
19925
20783
|
pushContent(groupContent, v.value);
|
|
19926
20784
|
}
|
|
@@ -19950,7 +20808,7 @@ var MessageItem = ({
|
|
|
19950
20808
|
userOutput: v.value && typeof v.value === "object" ? v.value : null,
|
|
19951
20809
|
chatbotName,
|
|
19952
20810
|
userInput: userInput?.value,
|
|
19953
|
-
onSubmitUserForm: onSubmitUserForm(message.id ?? "")
|
|
20811
|
+
onSubmitUserForm: onSubmitUserForm(message.id ?? "", v.channels)
|
|
19954
20812
|
},
|
|
19955
20813
|
`user-${message.id ?? "msg"}-${keyCounter++}`
|
|
19956
20814
|
)
|
|
@@ -20015,22 +20873,26 @@ var MessageItem = ({
|
|
|
20015
20873
|
);
|
|
20016
20874
|
}
|
|
20017
20875
|
(message.errors ?? []).forEach((error, errorIndex) => {
|
|
20876
|
+
const key = `error-${message.id ?? "msg"}-${errorIndex}-${error.errorCode ?? error.code}`;
|
|
20877
|
+
const detail = getMessageErrorDetail(error);
|
|
20018
20878
|
bubbles.push(
|
|
20019
|
-
/* @__PURE__ */
|
|
20020
|
-
|
|
20021
|
-
|
|
20022
|
-
|
|
20023
|
-
|
|
20024
|
-
|
|
20025
|
-
|
|
20026
|
-
|
|
20027
|
-
|
|
20028
|
-
|
|
20029
|
-
|
|
20030
|
-
|
|
20031
|
-
|
|
20032
|
-
|
|
20033
|
-
|
|
20879
|
+
/* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
20880
|
+
/* @__PURE__ */ jsx(
|
|
20881
|
+
MessageBubble,
|
|
20882
|
+
{
|
|
20883
|
+
createdBy: chatbotName,
|
|
20884
|
+
createdAt: message.createdAt,
|
|
20885
|
+
type: "Output" /* OUTPUT */,
|
|
20886
|
+
content: [{ text: getMessageErrorText(error) }],
|
|
20887
|
+
files: [],
|
|
20888
|
+
sources: [],
|
|
20889
|
+
chatbotName,
|
|
20890
|
+
userOutput: null,
|
|
20891
|
+
userInput: null
|
|
20892
|
+
}
|
|
20893
|
+
),
|
|
20894
|
+
detail && /* @__PURE__ */ jsx(MessageErrorDetails, { detail })
|
|
20895
|
+
] }, key)
|
|
20034
20896
|
);
|
|
20035
20897
|
});
|
|
20036
20898
|
return bubbles;
|
|
@@ -20146,6 +21008,7 @@ function MessageList({
|
|
|
20146
21008
|
] }) });
|
|
20147
21009
|
}
|
|
20148
21010
|
if (safeMessages.length === 0 && !hadMessagesBefore) {
|
|
21011
|
+
const descriptionParagraphs = (activeWorkspace?.summary ?? "").split(/\n+/).map((paragraph2) => paragraph2.trim()).filter(Boolean);
|
|
20149
21012
|
return (
|
|
20150
21013
|
// A new thread opens the way the design does: the greeting and the
|
|
20151
21014
|
// composer travel together as one narrower block centred in the canvas.
|
|
@@ -20158,6 +21021,14 @@ function MessageList({
|
|
|
20158
21021
|
"data-ss-layer": "message-list",
|
|
20159
21022
|
children: /* @__PURE__ */ jsxs("div", { className: "mx-auto mb-6 w-full max-w-2xl px-4 text-center", children: [
|
|
20160
21023
|
/* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold text-foreground", children: "What\u2019s on the agenda today?" }),
|
|
21024
|
+
descriptionParagraphs.length > 0 && /* @__PURE__ */ jsx(
|
|
21025
|
+
"div",
|
|
21026
|
+
{
|
|
21027
|
+
className: "mx-auto mt-2 max-w-lg space-y-1.5 text-sm text-muted-foreground",
|
|
21028
|
+
"data-ss-layer": "workspace-description",
|
|
21029
|
+
children: descriptionParagraphs.map((paragraph2, index) => /* @__PURE__ */ jsx("p", { children: paragraph2 }, index))
|
|
21030
|
+
}
|
|
21031
|
+
),
|
|
20161
21032
|
activeWorkspace?.firstPrompt && /* @__PURE__ */ jsx("div", { className: "chat-prose mt-3 text-center", children: /* @__PURE__ */ jsx(MessageMarkdown, { value: activeWorkspace.firstPrompt }) })
|
|
20162
21033
|
] })
|
|
20163
21034
|
}
|
|
@@ -20188,7 +21059,7 @@ function MessageList({
|
|
|
20188
21059
|
{
|
|
20189
21060
|
ref: viewportRef,
|
|
20190
21061
|
"data-ss-layer": "scroll-viewport",
|
|
20191
|
-
className: "h-full w-full rounded-[inherit] overflow-y-auto",
|
|
21062
|
+
className: "h-full w-full rounded-[inherit] overflow-y-auto [&>div]:!block",
|
|
20192
21063
|
onScroll: () => {
|
|
20193
21064
|
if (!viewportRef.current) return;
|
|
20194
21065
|
const viewport = viewportRef.current;
|
|
@@ -20449,6 +21320,6 @@ function getUserPhotoUrl(userId) {
|
|
|
20449
21320
|
return `${base2}/users/${userId}/photo`;
|
|
20450
21321
|
}
|
|
20451
21322
|
|
|
20452
|
-
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 };
|
|
21323
|
+
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, getMessageErrorDetail, 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 };
|
|
20453
21324
|
//# sourceMappingURL=index.js.map
|
|
20454
21325
|
//# sourceMappingURL=index.js.map
|