@smartspace/chat-ui 1.13.1-dev.c162627 → 1.13.1-dev.cbd3240
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/LICENSE +21 -0
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +40 -19
- package/dist/index.js +705 -134
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import MuiButton from '@mui/material/Button';
|
|
2
2
|
import IconButton from '@mui/material/IconButton';
|
|
3
|
-
import { Loader2, Check, X, Paperclip, ArrowBigUp, Minimize2, AlertTriangle, FileImage, FileVideo, FileAudio, FileArchive, FileCode, FileSpreadsheet, Presentation, FileText, ChevronUp,
|
|
4
|
-
import * as
|
|
3
|
+
import { Loader2, Check, X, Paperclip, ArrowBigUp, Minimize2, AlertTriangle, FileImage, FileVideo, FileAudio, FileArchive, FileCode, FileSpreadsheet, Presentation, FileText, ChevronUp, Download, Copy, Globe, ShieldAlert } from 'lucide-react';
|
|
4
|
+
import * as React9 from 'react';
|
|
5
5
|
import { createContext, forwardRef, useImperativeHandle, useRef, useState, useEffect, useMemo, useCallback, createElement, useContext } from 'react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
|
-
import { useQuery, queryOptions, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
7
|
+
import { useQuery, queryOptions, useQueryClient, useMutation, skipToken } from '@tanstack/react-query';
|
|
8
8
|
import { toast } from 'sonner';
|
|
9
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
|
-
import { Editor, rootCtx, defaultValueCtx, editorViewOptionsCtx, editorViewCtx, serializerCtx, SchemaReady, nodeViewCtx, markViewCtx, schemaCtx, prosePluginsCtx, nodesCtx } from '@milkdown/core';
|
|
10
|
+
import { Editor, rootCtx, defaultValueCtx, editorViewOptionsCtx, editorViewCtx, serializerCtx, parserCtx, SchemaReady, nodeViewCtx, markViewCtx, schemaCtx, prosePluginsCtx, nodesCtx } from '@milkdown/core';
|
|
11
11
|
import { history } from '@milkdown/kit/plugin/history';
|
|
12
12
|
import { clipboard } from '@milkdown/plugin-clipboard';
|
|
13
13
|
import { listenerCtx, listener } from '@milkdown/plugin-listener';
|
|
@@ -127,6 +127,7 @@ var filesKeys = {
|
|
|
127
127
|
var useFileMutations = (scope) => {
|
|
128
128
|
const { workspaceId, threadId } = scope;
|
|
129
129
|
const service = useChatService();
|
|
130
|
+
const queryClient = useQueryClient();
|
|
130
131
|
const [uploadedFiles, setUploadedFiles] = useState([]);
|
|
131
132
|
const [fileProgress, setFileProgress] = useState({});
|
|
132
133
|
const clearUploadState = useCallback(() => {
|
|
@@ -185,11 +186,19 @@ var useFileMutations = (scope) => {
|
|
|
185
186
|
status: uploadedFiles.some((f) => f.name === file.name) ? "done" : "uploading"
|
|
186
187
|
}));
|
|
187
188
|
const getFileBlobUrl = useCallback(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
189
|
+
(id) => queryClient.fetchQuery({
|
|
190
|
+
queryKey: filesKeys.downloadBlob(id),
|
|
191
|
+
queryFn: async () => {
|
|
192
|
+
const blob = await service.downloadFile(id, {
|
|
193
|
+
workspaceId,
|
|
194
|
+
threadId
|
|
195
|
+
});
|
|
196
|
+
return URL.createObjectURL(blob);
|
|
197
|
+
},
|
|
198
|
+
staleTime: Infinity,
|
|
199
|
+
gcTime: Infinity
|
|
200
|
+
}),
|
|
201
|
+
[queryClient, service, workspaceId, threadId]
|
|
193
202
|
);
|
|
194
203
|
return {
|
|
195
204
|
uploadFilesMutation,
|
|
@@ -415,6 +424,29 @@ var fileTag = $node("fileTag", () => ({
|
|
|
415
424
|
var MAX_IFRAME_HEIGHT = 5e3;
|
|
416
425
|
var HEIGHT_MESSAGE = "ss-html-preview-height";
|
|
417
426
|
var ERROR_MESSAGE = "ss-html-preview-error";
|
|
427
|
+
var SNAPSHOT_REQUEST = "ss-html-preview-snapshot";
|
|
428
|
+
var SNAPSHOT_RESULT = "ss-html-preview-snapshot-result";
|
|
429
|
+
var SS_MARKDOWN_CLIPBOARD_TYPE = "web text/markdown";
|
|
430
|
+
var MARKDOWN_MARKER_PREFIX = "<!--ss-md:";
|
|
431
|
+
var MARKDOWN_MARKER_SUFFIX = "-->";
|
|
432
|
+
var MARKDOWN_MARKER_RE = /<!--ss-md:([A-Za-z0-9+/=]+)-->/;
|
|
433
|
+
function encodeMarkdownMarker(markdown) {
|
|
434
|
+
try {
|
|
435
|
+
const b64 = btoa(unescape(encodeURIComponent(markdown)));
|
|
436
|
+
return `${MARKDOWN_MARKER_PREFIX}${b64}${MARKDOWN_MARKER_SUFFIX}`;
|
|
437
|
+
} catch {
|
|
438
|
+
return "";
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function extractMarkdownMarker(html4) {
|
|
442
|
+
const match = html4.match(MARKDOWN_MARKER_RE);
|
|
443
|
+
if (!match) return null;
|
|
444
|
+
try {
|
|
445
|
+
return decodeURIComponent(escape(atob(match[1])));
|
|
446
|
+
} catch {
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
418
450
|
var HEIGHT_REPORTER_SCRIPT = `
|
|
419
451
|
<script>(function(){
|
|
420
452
|
try {
|
|
@@ -439,6 +471,48 @@ var HEIGHT_REPORTER_SCRIPT = `
|
|
|
439
471
|
window.addEventListener('unhandledrejection', function(ev){
|
|
440
472
|
reportError(ev && ev.reason && ev.reason.message);
|
|
441
473
|
});
|
|
474
|
+
// Snapshot responder. The parent can't read this sandboxed (no
|
|
475
|
+
// allow-same-origin) document, so when it asks for a snapshot we rasterize
|
|
476
|
+
// our own <canvas> elements via toDataURL and post just the PNG strings
|
|
477
|
+
// back out \u2014 strings cross the sandbox boundary fine. Used by the message
|
|
478
|
+
// "smart copy" so client-side charts (Chart.js etc.) paste into Word as
|
|
479
|
+
// images instead of dead <canvas>/<script> source.
|
|
480
|
+
window.addEventListener('message', function(ev){
|
|
481
|
+
var d = ev && ev.data;
|
|
482
|
+
if (!d || d.type !== ${JSON.stringify(SNAPSHOT_REQUEST)}) return;
|
|
483
|
+
var images = [];
|
|
484
|
+
try {
|
|
485
|
+
var canvases = document.querySelectorAll('canvas');
|
|
486
|
+
for (var i = 0; i < canvases.length; i++) {
|
|
487
|
+
var c = canvases[i];
|
|
488
|
+
// Skip zero-area canvases (off-screen / not yet drawn).
|
|
489
|
+
if (!c.width || !c.height) continue;
|
|
490
|
+
try {
|
|
491
|
+
var rect = c.getBoundingClientRect();
|
|
492
|
+
images.push({
|
|
493
|
+
dataUrl: c.toDataURL('image/png'),
|
|
494
|
+
width: c.width,
|
|
495
|
+
height: c.height,
|
|
496
|
+
// On-screen CSS size, independent of devicePixelRatio scaling, so
|
|
497
|
+
// the pasted <img> renders at the chart's intended size rather than
|
|
498
|
+
// 2x on a retina display. Falls back to the pixel size.
|
|
499
|
+
cssWidth: Math.round(rect.width) || c.width,
|
|
500
|
+
cssHeight: Math.round(rect.height) || c.height
|
|
501
|
+
});
|
|
502
|
+
} catch (e) {
|
|
503
|
+
// Tainted canvas (cross-origin image drawn without CORS) \u2014 skip it;
|
|
504
|
+
// the host falls back to inlining the static HTML source.
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
} catch (e) {}
|
|
508
|
+
try {
|
|
509
|
+
parent.postMessage({
|
|
510
|
+
type: ${JSON.stringify(SNAPSHOT_RESULT)},
|
|
511
|
+
id: d.id,
|
|
512
|
+
images: images
|
|
513
|
+
}, '*');
|
|
514
|
+
} catch (e) {}
|
|
515
|
+
});
|
|
442
516
|
var lastSent = -1;
|
|
443
517
|
function send(){
|
|
444
518
|
try {
|
|
@@ -524,6 +598,38 @@ async function copyText(text6) {
|
|
|
524
598
|
return false;
|
|
525
599
|
}
|
|
526
600
|
}
|
|
601
|
+
var snapshotSeq = 0;
|
|
602
|
+
function snapshotIframe(iframe, timeoutMs = 1500) {
|
|
603
|
+
return new Promise((resolve) => {
|
|
604
|
+
const win = iframe.contentWindow;
|
|
605
|
+
if (!win || typeof window === "undefined") {
|
|
606
|
+
resolve([]);
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
const id = `snap-${++snapshotSeq}`;
|
|
610
|
+
let settled = false;
|
|
611
|
+
const finish = (images) => {
|
|
612
|
+
if (settled) return;
|
|
613
|
+
settled = true;
|
|
614
|
+
window.removeEventListener("message", onMessage);
|
|
615
|
+
clearTimeout(timer);
|
|
616
|
+
resolve(images);
|
|
617
|
+
};
|
|
618
|
+
const onMessage = (event) => {
|
|
619
|
+
if (event.source !== win) return;
|
|
620
|
+
const data = event.data;
|
|
621
|
+
if (!data || data.type !== SNAPSHOT_RESULT || data.id !== id) return;
|
|
622
|
+
finish(Array.isArray(data.images) ? data.images : []);
|
|
623
|
+
};
|
|
624
|
+
const timer = setTimeout(() => finish([]), timeoutMs);
|
|
625
|
+
window.addEventListener("message", onMessage);
|
|
626
|
+
try {
|
|
627
|
+
win.postMessage({ type: SNAPSHOT_REQUEST, id }, "*");
|
|
628
|
+
} catch {
|
|
629
|
+
finish([]);
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
}
|
|
527
633
|
|
|
528
634
|
// src/shared/markdown/extensions/htmlPreview.ts
|
|
529
635
|
var PREVIEW_LANGUAGES = /* @__PURE__ */ new Set(["html"]);
|
|
@@ -747,7 +853,7 @@ var mention = $node("mention", () => ({
|
|
|
747
853
|
match: (node2) => node2.type.name === "mention",
|
|
748
854
|
runner: (state, node2) => {
|
|
749
855
|
const { id, label } = node2.attrs;
|
|
750
|
-
state.addNode("
|
|
856
|
+
state.addNode("text", void 0, label || `@${id}`);
|
|
751
857
|
}
|
|
752
858
|
}
|
|
753
859
|
}));
|
|
@@ -871,7 +977,7 @@ var ssImageView = $view(ssImageNode, (ctx) => (node2) => {
|
|
|
871
977
|
removeBtn.type = "button";
|
|
872
978
|
removeBtn.className = "ss-attach__remove";
|
|
873
979
|
removeBtn.setAttribute("aria-label", "Remove image");
|
|
874
|
-
removeBtn.
|
|
980
|
+
removeBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>';
|
|
875
981
|
removeBtn.addEventListener("mousedown", (e) => {
|
|
876
982
|
e.preventDefault();
|
|
877
983
|
e.stopPropagation();
|
|
@@ -890,16 +996,19 @@ var ssImageView = $view(ssImageNode, (ctx) => (node2) => {
|
|
|
890
996
|
}
|
|
891
997
|
});
|
|
892
998
|
img.style.background = "rgba(0,0,0,0.04)";
|
|
999
|
+
img.style.visibility = "hidden";
|
|
893
1000
|
let hasSetRealSrc = false;
|
|
894
1001
|
img.addEventListener("load", () => {
|
|
895
1002
|
if (!hasSetRealSrc) return;
|
|
896
1003
|
spinner.remove();
|
|
897
1004
|
img.style.background = "";
|
|
1005
|
+
img.style.visibility = "";
|
|
898
1006
|
});
|
|
899
1007
|
img.addEventListener("error", () => {
|
|
900
1008
|
if (!hasSetRealSrc) return;
|
|
901
1009
|
spinner.remove();
|
|
902
1010
|
img.style.background = "rgba(255,0,0,0.06)";
|
|
1011
|
+
img.style.visibility = "";
|
|
903
1012
|
});
|
|
904
1013
|
try {
|
|
905
1014
|
const anyWin = window;
|
|
@@ -970,6 +1079,7 @@ function EditorInner({
|
|
|
970
1079
|
const [_isDragging, setIsDragging] = useState(false);
|
|
971
1080
|
const viewRef = useRef(null);
|
|
972
1081
|
const serializerRef = useRef(null);
|
|
1082
|
+
const parserRef = useRef(null);
|
|
973
1083
|
function guessImageExt(mime) {
|
|
974
1084
|
const t = (mime || "").toLowerCase();
|
|
975
1085
|
if (t === "image/jpeg") return "jpg";
|
|
@@ -1088,6 +1198,10 @@ function EditorInner({
|
|
|
1088
1198
|
serializerRef.current = anyCtx.get(serializerCtx);
|
|
1089
1199
|
} catch {
|
|
1090
1200
|
}
|
|
1201
|
+
try {
|
|
1202
|
+
parserRef.current = anyCtx.get(parserCtx);
|
|
1203
|
+
} catch {
|
|
1204
|
+
}
|
|
1091
1205
|
const handle2 = () => {
|
|
1092
1206
|
try {
|
|
1093
1207
|
if (enableMentions) updateMentionFromView();
|
|
@@ -1177,6 +1291,19 @@ function EditorInner({
|
|
|
1177
1291
|
const tr = view.state.tr.replaceWith(from, to, node2);
|
|
1178
1292
|
view.dispatch(tr.scrollIntoView());
|
|
1179
1293
|
}
|
|
1294
|
+
function insertMarkdownAtSelection(view, markdown) {
|
|
1295
|
+
const parser = parserRef.current;
|
|
1296
|
+
if (!parser) return false;
|
|
1297
|
+
try {
|
|
1298
|
+
const doc = parser(markdown);
|
|
1299
|
+
if (!doc) return false;
|
|
1300
|
+
const slice = new Slice(doc.content, 0, 0);
|
|
1301
|
+
view.dispatch(view.state.tr.replaceSelection(slice).scrollIntoView());
|
|
1302
|
+
return true;
|
|
1303
|
+
} catch {
|
|
1304
|
+
return false;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1180
1307
|
async function insertUploadedFilesIntoEditor(files) {
|
|
1181
1308
|
const view = viewRef.current;
|
|
1182
1309
|
if (!isEditable || !view) return false;
|
|
@@ -1449,6 +1576,17 @@ function EditorInner({
|
|
|
1449
1576
|
},
|
|
1450
1577
|
onPasteCapture: (e) => {
|
|
1451
1578
|
try {
|
|
1579
|
+
const view = viewRef.current;
|
|
1580
|
+
if (isEditable && view) {
|
|
1581
|
+
const ssMarkdown = extractMarkdownMarker(
|
|
1582
|
+
e.clipboardData?.getData("text/html") ?? ""
|
|
1583
|
+
) ?? e.clipboardData?.getData(SS_MARKDOWN_CLIPBOARD_TYPE);
|
|
1584
|
+
if (ssMarkdown && insertMarkdownAtSelection(view, ssMarkdown)) {
|
|
1585
|
+
e.preventDefault();
|
|
1586
|
+
e.stopPropagation();
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1452
1590
|
const items = e.clipboardData?.items;
|
|
1453
1591
|
if (!items) return;
|
|
1454
1592
|
const imageFiles = [];
|
|
@@ -1675,7 +1813,7 @@ var buttonVariants = cva(
|
|
|
1675
1813
|
}
|
|
1676
1814
|
}
|
|
1677
1815
|
);
|
|
1678
|
-
var Button =
|
|
1816
|
+
var Button = React9.forwardRef(
|
|
1679
1817
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
1680
1818
|
const Comp = asChild ? Slot : "button";
|
|
1681
1819
|
return /* @__PURE__ */ jsx(
|
|
@@ -2890,6 +3028,128 @@ var modelIdRendererTester = rankWith(
|
|
|
2890
3028
|
}
|
|
2891
3029
|
);
|
|
2892
3030
|
var ModelIdRendererControl = withJsonFormsControlProps(ModelIdRenderer);
|
|
3031
|
+
var NumberRenderer = ({
|
|
3032
|
+
data,
|
|
3033
|
+
handleChange,
|
|
3034
|
+
path: path2,
|
|
3035
|
+
label,
|
|
3036
|
+
description,
|
|
3037
|
+
errors,
|
|
3038
|
+
schema,
|
|
3039
|
+
uischema,
|
|
3040
|
+
visible,
|
|
3041
|
+
enabled,
|
|
3042
|
+
required
|
|
3043
|
+
}) => {
|
|
3044
|
+
const isInteger = schema?.type === "integer";
|
|
3045
|
+
const handleInputChange = useCallback(
|
|
3046
|
+
(event) => {
|
|
3047
|
+
const raw2 = event.target.value;
|
|
3048
|
+
if (raw2 === "") {
|
|
3049
|
+
handleChange(path2, void 0);
|
|
3050
|
+
return;
|
|
3051
|
+
}
|
|
3052
|
+
const parsed = isInteger ? parseInt(raw2, 10) : parseFloat(raw2);
|
|
3053
|
+
if (Number.isNaN(parsed)) {
|
|
3054
|
+
handleChange(path2, void 0);
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
3057
|
+
handleChange(path2, parsed);
|
|
3058
|
+
},
|
|
3059
|
+
[handleChange, path2, isInteger]
|
|
3060
|
+
);
|
|
3061
|
+
if (!visible) return null;
|
|
3062
|
+
const readOnly = uischema?.access === "Read";
|
|
3063
|
+
const isDisabled = !enabled || readOnly;
|
|
3064
|
+
const hasError = !!errors && errors.length > 0;
|
|
3065
|
+
const fieldSchema = schema;
|
|
3066
|
+
const min = fieldSchema?.minimum;
|
|
3067
|
+
const max = fieldSchema?.maximum;
|
|
3068
|
+
const step = isInteger ? 1 : fieldSchema?.multipleOf ?? "any";
|
|
3069
|
+
return /* @__PURE__ */ jsxs(
|
|
3070
|
+
"div",
|
|
3071
|
+
{
|
|
3072
|
+
className: "ss-jsonforms-field ss-jsonforms-number",
|
|
3073
|
+
style: {
|
|
3074
|
+
display: "inline-flex",
|
|
3075
|
+
flexDirection: "row",
|
|
3076
|
+
alignItems: "center",
|
|
3077
|
+
gap: 8,
|
|
3078
|
+
minHeight: "40px"
|
|
3079
|
+
},
|
|
3080
|
+
children: [
|
|
3081
|
+
label && /* @__PURE__ */ jsxs(
|
|
3082
|
+
"label",
|
|
3083
|
+
{
|
|
3084
|
+
htmlFor: `number-${path2}`,
|
|
3085
|
+
style: {
|
|
3086
|
+
color: hasError ? "#ef4444" : "#475569",
|
|
3087
|
+
fontSize: "0.875rem",
|
|
3088
|
+
fontWeight: 500,
|
|
3089
|
+
whiteSpace: "nowrap",
|
|
3090
|
+
lineHeight: "24px"
|
|
3091
|
+
},
|
|
3092
|
+
children: [
|
|
3093
|
+
label,
|
|
3094
|
+
required && /* @__PURE__ */ jsx("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
|
|
3095
|
+
]
|
|
3096
|
+
}
|
|
3097
|
+
),
|
|
3098
|
+
/* @__PURE__ */ jsx(
|
|
3099
|
+
"input",
|
|
3100
|
+
{
|
|
3101
|
+
id: `number-${path2}`,
|
|
3102
|
+
type: "number",
|
|
3103
|
+
value: data ?? "",
|
|
3104
|
+
onChange: handleInputChange,
|
|
3105
|
+
disabled: isDisabled,
|
|
3106
|
+
min,
|
|
3107
|
+
max,
|
|
3108
|
+
step,
|
|
3109
|
+
style: {
|
|
3110
|
+
width: "80px",
|
|
3111
|
+
height: "24px",
|
|
3112
|
+
padding: "0 0.5rem",
|
|
3113
|
+
border: hasError ? "2px solid #ef4444" : "1px solid #d1d5db",
|
|
3114
|
+
borderRadius: "6px",
|
|
3115
|
+
fontSize: "0.875rem",
|
|
3116
|
+
lineHeight: "24px",
|
|
3117
|
+
fontFamily: "inherit",
|
|
3118
|
+
backgroundColor: isDisabled ? "#f9fafb" : "#ffffff",
|
|
3119
|
+
color: isDisabled ? "#9ca3af" : "#111827",
|
|
3120
|
+
outline: "none",
|
|
3121
|
+
boxSizing: "border-box"
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
),
|
|
3125
|
+
hasError && /* @__PURE__ */ jsx(
|
|
3126
|
+
"div",
|
|
3127
|
+
{
|
|
3128
|
+
style: {
|
|
3129
|
+
color: "#ef4444",
|
|
3130
|
+
fontSize: "0.75rem"
|
|
3131
|
+
},
|
|
3132
|
+
children: errors
|
|
3133
|
+
}
|
|
3134
|
+
)
|
|
3135
|
+
]
|
|
3136
|
+
}
|
|
3137
|
+
);
|
|
3138
|
+
};
|
|
3139
|
+
var numberRendererTester = rankWith(
|
|
3140
|
+
40,
|
|
3141
|
+
(uischema, schema) => {
|
|
3142
|
+
if (uischema.type !== "Control") return false;
|
|
3143
|
+
const propertyPath = uischema.scope.replace(
|
|
3144
|
+
"#/properties/",
|
|
3145
|
+
""
|
|
3146
|
+
);
|
|
3147
|
+
const fieldSchema = schema?.properties?.[propertyPath];
|
|
3148
|
+
if (!fieldSchema) return false;
|
|
3149
|
+
return fieldSchema.type === "integer" || fieldSchema.type === "number";
|
|
3150
|
+
}
|
|
3151
|
+
);
|
|
3152
|
+
var NumberRendererControl = withJsonFormsControlProps(NumberRenderer);
|
|
2893
3153
|
var TextareaRenderer = ({
|
|
2894
3154
|
data,
|
|
2895
3155
|
handleChange,
|
|
@@ -3059,6 +3319,7 @@ var renderers = [
|
|
|
3059
3319
|
{ tester: modelIdRendererTester, renderer: ModelIdRendererControl },
|
|
3060
3320
|
{ tester: booleanRendererTester, renderer: BooleanRendererControl },
|
|
3061
3321
|
{ tester: dropdownRendererTester, renderer: DropdownRendererControl },
|
|
3322
|
+
{ tester: numberRendererTester, renderer: NumberRendererControl },
|
|
3062
3323
|
{ tester: textareaRendererTester, renderer: TextareaRendererControl },
|
|
3063
3324
|
...vanillaRenderers,
|
|
3064
3325
|
{ tester: jsonEditorTester, renderer: JsonEditorRendererControl }
|
|
@@ -3112,26 +3373,26 @@ function useChatVariablesFormVm({
|
|
|
3112
3373
|
const { mutate: updateVariableMutation } = useUpdateFlowRunVariable();
|
|
3113
3374
|
const querySettled = !isLoading && (threadVars !== void 0 || isError);
|
|
3114
3375
|
const shouldUseDefaults = isError || threadVars && Object.keys(threadVars).length === 0;
|
|
3115
|
-
const built =
|
|
3376
|
+
const built = React9.useMemo(() => {
|
|
3116
3377
|
return buildSimpleSchemaAndUi(
|
|
3117
3378
|
workspace.variables,
|
|
3118
3379
|
threadVars,
|
|
3119
3380
|
shouldUseDefaults ?? false
|
|
3120
3381
|
);
|
|
3121
3382
|
}, [workspace.variables, threadVars, shouldUseDefaults]);
|
|
3122
|
-
const [data, setData] =
|
|
3123
|
-
|
|
3383
|
+
const [data, setData] = React9.useState(null);
|
|
3384
|
+
React9.useEffect(() => {
|
|
3124
3385
|
if (querySettled) {
|
|
3125
3386
|
setData(built.initialData);
|
|
3126
3387
|
setVariables(built.initialData);
|
|
3127
3388
|
}
|
|
3128
3389
|
}, [querySettled, built.initialData, setVariables]);
|
|
3129
|
-
const ajv =
|
|
3130
|
-
const prevRef =
|
|
3131
|
-
|
|
3390
|
+
const ajv = React9.useMemo(() => createAjv({ useDefaults: false }), []);
|
|
3391
|
+
const prevRef = React9.useRef(null);
|
|
3392
|
+
React9.useEffect(() => {
|
|
3132
3393
|
prevRef.current = data;
|
|
3133
3394
|
}, [data]);
|
|
3134
|
-
const onChange =
|
|
3395
|
+
const onChange = React9.useCallback(
|
|
3135
3396
|
({ data: next2 }) => {
|
|
3136
3397
|
if (prevRef.current && !isDraftThreadId(threadId)) {
|
|
3137
3398
|
const keys2 = Object.keys(workspace.variables || {});
|
|
@@ -3152,7 +3413,7 @@ function useChatVariablesFormVm({
|
|
|
3152
3413
|
},
|
|
3153
3414
|
[workspace.variables, setVariables, updateVariableMutation, threadId]
|
|
3154
3415
|
);
|
|
3155
|
-
const config =
|
|
3416
|
+
const config = React9.useMemo(
|
|
3156
3417
|
() => ({
|
|
3157
3418
|
restrict: true,
|
|
3158
3419
|
trim: false,
|
|
@@ -3221,7 +3482,20 @@ var threadsKeys = {
|
|
|
3221
3482
|
};
|
|
3222
3483
|
|
|
3223
3484
|
// src/domains/threads/cache.ts
|
|
3485
|
+
function isStaleSummary(incoming, existing) {
|
|
3486
|
+
if (!existing) return false;
|
|
3487
|
+
if (typeof existing.summaryEmittedAt !== "number") return false;
|
|
3488
|
+
if (typeof incoming.summaryEmittedAt !== "number") return false;
|
|
3489
|
+
if (incoming.summaryEmittedAt >= existing.summaryEmittedAt) return false;
|
|
3490
|
+
return existing.isFlowRunning === false && incoming.isFlowRunning === true;
|
|
3491
|
+
}
|
|
3224
3492
|
function applyThreadToCache(qc, thread) {
|
|
3493
|
+
const existingDetail = qc.getQueryData(
|
|
3494
|
+
threadsKeys.detail(thread.workSpaceId, thread.id)
|
|
3495
|
+
);
|
|
3496
|
+
if (isStaleSummary(thread, existingDetail)) {
|
|
3497
|
+
return false;
|
|
3498
|
+
}
|
|
3225
3499
|
qc.setQueryData(
|
|
3226
3500
|
threadsKeys.detail(thread.workSpaceId, thread.id),
|
|
3227
3501
|
(old) => ({ ...old ?? thread, ...thread })
|
|
@@ -3242,6 +3516,7 @@ function applyThreadToCache(qc, thread) {
|
|
|
3242
3516
|
if (!page?.data) return page;
|
|
3243
3517
|
const idx2 = page.data.findIndex((t) => t.id === thread.id);
|
|
3244
3518
|
if (idx2 === -1) return page;
|
|
3519
|
+
if (isStaleSummary(thread, page.data[idx2])) return page;
|
|
3245
3520
|
changed = true;
|
|
3246
3521
|
foundInList = true;
|
|
3247
3522
|
const nextData2 = page.data.slice();
|
|
@@ -3254,6 +3529,7 @@ function applyThreadToCache(qc, thread) {
|
|
|
3254
3529
|
if (!list2.data) return old;
|
|
3255
3530
|
const idx = list2.data.findIndex((t) => t.id === thread.id);
|
|
3256
3531
|
if (idx === -1) return old;
|
|
3532
|
+
if (isStaleSummary(thread, list2.data[idx])) return old;
|
|
3257
3533
|
foundInList = true;
|
|
3258
3534
|
const nextData = list2.data.slice();
|
|
3259
3535
|
nextData[idx] = { ...nextData[idx], ...thread };
|
|
@@ -3323,36 +3599,40 @@ var {
|
|
|
3323
3599
|
messageThreadsGetMessageThreadWorkspacesWorkspaceIdMessagethreadsIdResponse: threadResponseSchema
|
|
3324
3600
|
} = ChatZod;
|
|
3325
3601
|
function mapThreadDtoToModel(dto) {
|
|
3602
|
+
const lastUpdatedAt = utcDate(dto.lastUpdatedAt);
|
|
3326
3603
|
return {
|
|
3327
3604
|
id: dto.id,
|
|
3328
3605
|
createdAt: utcDate(dto.createdAt),
|
|
3329
3606
|
createdBy: dto.createdBy ?? "",
|
|
3330
3607
|
createdByUserId: dto.createdByUserId,
|
|
3331
3608
|
isFlowRunning: dto.isFlowRunning,
|
|
3332
|
-
lastUpdatedAt
|
|
3609
|
+
lastUpdatedAt,
|
|
3333
3610
|
lastUpdatedByUserId: dto.lastUpdatedByUserId,
|
|
3334
3611
|
name: dto.name ?? "",
|
|
3335
3612
|
totalMessages: dto.totalMessages,
|
|
3336
3613
|
pinned: dto.favorited,
|
|
3337
|
-
workSpaceId: dto.workSpaceId
|
|
3614
|
+
workSpaceId: dto.workSpaceId,
|
|
3615
|
+
summaryEmittedAt: lastUpdatedAt.getTime()
|
|
3338
3616
|
};
|
|
3339
3617
|
}
|
|
3340
3618
|
function mapThreadsResponseDtoToModel(dto) {
|
|
3341
3619
|
return { data: dto.data.map(mapThreadDtoToModel), total: dto.total };
|
|
3342
3620
|
}
|
|
3343
3621
|
function mapSignalRThreadSummaryToModel(summary) {
|
|
3622
|
+
const lastUpdatedAt = utcDate(summary.lastUpdatedAt);
|
|
3344
3623
|
return {
|
|
3345
3624
|
id: summary.id,
|
|
3346
3625
|
createdAt: utcDate(summary.createdAt),
|
|
3347
3626
|
createdBy: summary.createdBy ?? "",
|
|
3348
3627
|
createdByUserId: summary.createdByUserId,
|
|
3349
3628
|
isFlowRunning: summary.isFlowRunning,
|
|
3350
|
-
lastUpdatedAt
|
|
3629
|
+
lastUpdatedAt,
|
|
3351
3630
|
lastUpdatedByUserId: summary.lastUpdatedByUserId,
|
|
3352
3631
|
name: summary.name ?? "",
|
|
3353
3632
|
totalMessages: summary.totalMessages,
|
|
3354
3633
|
pinned: summary.favorited,
|
|
3355
|
-
workSpaceId: summary.workSpaceId
|
|
3634
|
+
workSpaceId: summary.workSpaceId,
|
|
3635
|
+
summaryEmittedAt: lastUpdatedAt.getTime()
|
|
3356
3636
|
};
|
|
3357
3637
|
}
|
|
3358
3638
|
var threadDetailOptions = ({
|
|
@@ -3406,11 +3686,12 @@ var useThread = ({
|
|
|
3406
3686
|
});
|
|
3407
3687
|
};
|
|
3408
3688
|
var useThreadIsRunning = (workspaceId, threadId) => {
|
|
3409
|
-
const
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3689
|
+
const queryClient = useQueryClient();
|
|
3690
|
+
const { data: detailThread } = useQuery({
|
|
3691
|
+
queryKey: threadsKeys.detail(workspaceId ?? "", threadId ?? ""),
|
|
3692
|
+
queryFn: skipToken
|
|
3413
3693
|
});
|
|
3694
|
+
const listThread = workspaceId && threadId ? getThreadPlaceholderFromListCache(queryClient, workspaceId, threadId) : void 0;
|
|
3414
3695
|
const { data: optimistic } = useQuery({
|
|
3415
3696
|
queryKey: threadsKeys.optimisticRunning(threadId ?? ""),
|
|
3416
3697
|
queryFn: () => false,
|
|
@@ -3418,9 +3699,15 @@ var useThreadIsRunning = (workspaceId, threadId) => {
|
|
|
3418
3699
|
staleTime: Infinity,
|
|
3419
3700
|
enabled: !!threadId
|
|
3420
3701
|
});
|
|
3421
|
-
return !!optimistic || !!
|
|
3702
|
+
return !!optimistic || !!(detailThread ?? listThread)?.isFlowRunning;
|
|
3422
3703
|
};
|
|
3423
3704
|
|
|
3705
|
+
// src/shared/utils/randomUUID.ts
|
|
3706
|
+
function randomUUID() {
|
|
3707
|
+
const cryptoObj = globalThis?.crypto;
|
|
3708
|
+
return typeof cryptoObj?.randomUUID === "function" ? cryptoObj.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
3709
|
+
}
|
|
3710
|
+
|
|
3424
3711
|
// src/domains/messages/enums.ts
|
|
3425
3712
|
var MessageValueType = /* @__PURE__ */ ((MessageValueType2) => {
|
|
3426
3713
|
MessageValueType2["OUTPUT"] = "Output";
|
|
@@ -3444,6 +3731,15 @@ var messagesMutationsKeys = {
|
|
|
3444
3731
|
};
|
|
3445
3732
|
|
|
3446
3733
|
// src/domains/messages/mutations.ts
|
|
3734
|
+
function reconcileWithMessage(old, incoming, onDuplicate = "keep-existing") {
|
|
3735
|
+
const stable = old.filter((m) => !m.optimistic);
|
|
3736
|
+
const idx = stable.findIndex((m) => m.id === incoming.id);
|
|
3737
|
+
if (idx === -1) return [...stable, incoming];
|
|
3738
|
+
if (onDuplicate === "keep-existing") return stable;
|
|
3739
|
+
const copy = stable.slice();
|
|
3740
|
+
copy[idx] = incoming;
|
|
3741
|
+
return copy;
|
|
3742
|
+
}
|
|
3447
3743
|
function useSendMessage() {
|
|
3448
3744
|
const qc = useQueryClient();
|
|
3449
3745
|
const { userId, displayName: userName } = useChatIdentity();
|
|
@@ -3459,10 +3755,10 @@ function useSendMessage() {
|
|
|
3459
3755
|
if (!threadId) throw new Error("Thread ID is required");
|
|
3460
3756
|
if (!workspaceId) throw new Error("Workspace ID is required");
|
|
3461
3757
|
const optimistic = {
|
|
3462
|
-
id: `temp-${
|
|
3758
|
+
id: `temp-${randomUUID()}`,
|
|
3463
3759
|
values: [
|
|
3464
3760
|
{
|
|
3465
|
-
id: `temp-${
|
|
3761
|
+
id: `temp-${randomUUID()}-prompt`,
|
|
3466
3762
|
type: "Input" /* INPUT */,
|
|
3467
3763
|
name: "prompt",
|
|
3468
3764
|
value: contentList,
|
|
@@ -3473,7 +3769,7 @@ function useSendMessage() {
|
|
|
3473
3769
|
},
|
|
3474
3770
|
...files?.length ? [
|
|
3475
3771
|
{
|
|
3476
|
-
id: `temp-${
|
|
3772
|
+
id: `temp-${randomUUID()}-files`,
|
|
3477
3773
|
type: "Input" /* INPUT */,
|
|
3478
3774
|
name: "files",
|
|
3479
3775
|
value: files,
|
|
@@ -3485,7 +3781,7 @@ function useSendMessage() {
|
|
|
3485
3781
|
] : [],
|
|
3486
3782
|
...variables && Object.keys(variables).length ? [
|
|
3487
3783
|
{
|
|
3488
|
-
id: `temp-${
|
|
3784
|
+
id: `temp-${randomUUID()}-vars`,
|
|
3489
3785
|
type: "Input" /* INPUT */,
|
|
3490
3786
|
name: "variables",
|
|
3491
3787
|
value: variables,
|
|
@@ -3527,7 +3823,10 @@ function useSendMessage() {
|
|
|
3527
3823
|
toast.error("There was an error posting your message");
|
|
3528
3824
|
throw err;
|
|
3529
3825
|
}
|
|
3530
|
-
qc.setQueryData(
|
|
3826
|
+
qc.setQueryData(
|
|
3827
|
+
messagesKeys.list(threadId),
|
|
3828
|
+
(old = []) => reconcileWithMessage(old, realMessage)
|
|
3829
|
+
);
|
|
3531
3830
|
qc.setQueryData(
|
|
3532
3831
|
threadsKeys.detail(workspaceId, threadId),
|
|
3533
3832
|
(old) => old ? { ...old, isFlowRunning: true } : old
|
|
@@ -3551,8 +3850,9 @@ function useAddInputToMessage() {
|
|
|
3551
3850
|
const { userId, displayName: userName } = useChatIdentity();
|
|
3552
3851
|
const service = useChatService();
|
|
3553
3852
|
const addInputToMessageMutation = useMutation({
|
|
3554
|
-
|
|
3555
|
-
|
|
3853
|
+
onMutate: async ({ threadId, messageId, name, value, channels }) => {
|
|
3854
|
+
await qc.cancelQueries({ queryKey: messagesKeys.list(threadId) });
|
|
3855
|
+
const previousMessages = qc.getQueryData(messagesKeys.list(threadId)) ?? [];
|
|
3556
3856
|
qc.setQueryData(
|
|
3557
3857
|
messagesKeys.list(threadId),
|
|
3558
3858
|
(old = []) => old.map(
|
|
@@ -3561,7 +3861,7 @@ function useAddInputToMessage() {
|
|
|
3561
3861
|
values: [
|
|
3562
3862
|
...m.values ?? [],
|
|
3563
3863
|
{
|
|
3564
|
-
id: `temp-${
|
|
3864
|
+
id: `temp-${randomUUID()}-add`,
|
|
3565
3865
|
type: "Input" /* INPUT */,
|
|
3566
3866
|
name,
|
|
3567
3867
|
value,
|
|
@@ -3574,7 +3874,10 @@ function useAddInputToMessage() {
|
|
|
3574
3874
|
} : m
|
|
3575
3875
|
)
|
|
3576
3876
|
);
|
|
3577
|
-
|
|
3877
|
+
return { previousMessages };
|
|
3878
|
+
},
|
|
3879
|
+
mutationFn: async ({ threadId, messageId, name, value, channels }) => {
|
|
3880
|
+
if (!threadId) throw new Error("Thread ID is required");
|
|
3578
3881
|
return await service.addInputToMessage({
|
|
3579
3882
|
messageId,
|
|
3580
3883
|
name,
|
|
@@ -3583,20 +3886,18 @@ function useAddInputToMessage() {
|
|
|
3583
3886
|
});
|
|
3584
3887
|
},
|
|
3585
3888
|
onSuccess: (message, { threadId }) => {
|
|
3586
|
-
qc.setQueryData(messagesKeys.list(threadId), (old = []) => {
|
|
3587
|
-
const stable = old.filter((x) => !x.optimistic);
|
|
3588
|
-
const idx = stable.findIndex((x) => x.id === message.id);
|
|
3589
|
-
if (idx === -1) return [...stable, message];
|
|
3590
|
-
const copy = stable.slice();
|
|
3591
|
-
copy[idx] = message;
|
|
3592
|
-
return copy;
|
|
3593
|
-
});
|
|
3594
|
-
},
|
|
3595
|
-
onError: (_e, { threadId }) => {
|
|
3596
3889
|
qc.setQueryData(
|
|
3597
3890
|
messagesKeys.list(threadId),
|
|
3598
|
-
(old = []) => old
|
|
3891
|
+
(old = []) => reconcileWithMessage(old, message, "replace")
|
|
3599
3892
|
);
|
|
3893
|
+
},
|
|
3894
|
+
onError: (_e, { threadId }, context) => {
|
|
3895
|
+
if (context) {
|
|
3896
|
+
qc.setQueryData(
|
|
3897
|
+
messagesKeys.list(threadId),
|
|
3898
|
+
context.previousMessages
|
|
3899
|
+
);
|
|
3900
|
+
}
|
|
3600
3901
|
toast.error("There was an error posting your form input");
|
|
3601
3902
|
},
|
|
3602
3903
|
retry: false
|
|
@@ -18545,17 +18846,29 @@ function CodeBlock({ language, source }) {
|
|
|
18545
18846
|
/* @__PURE__ */ jsx("pre", { ...language ? { "data-language": language } : {}, children: /* @__PURE__ */ jsx("code", { className: codeClass, children: source }) })
|
|
18546
18847
|
] });
|
|
18547
18848
|
}
|
|
18849
|
+
var STREAM_SETTLE_MS = 250;
|
|
18548
18850
|
function HtmlPreview({ source }) {
|
|
18549
18851
|
const [showingPreview, setShowingPreview] = useState(true);
|
|
18550
18852
|
const [copyLabel, setCopyLabel] = useState(
|
|
18551
18853
|
"Copy"
|
|
18552
18854
|
);
|
|
18553
18855
|
const [iframeHeight, setIframeHeight] = useState(null);
|
|
18856
|
+
const [settledSource, setSettledSource] = useState(source);
|
|
18857
|
+
const [measured, setMeasured] = useState(false);
|
|
18858
|
+
const loading = showingPreview && (source !== settledSource || !measured);
|
|
18554
18859
|
const iframeRef = useRef(null);
|
|
18555
18860
|
const rafIdRef = useRef(null);
|
|
18556
18861
|
const pendingHeightRef = useRef(null);
|
|
18557
18862
|
const copyResetTimerRef = useRef(null);
|
|
18558
|
-
const srcdoc = injectHeightReporter(
|
|
18863
|
+
const srcdoc = injectHeightReporter(settledSource);
|
|
18864
|
+
useEffect(() => {
|
|
18865
|
+
if (source === settledSource) return;
|
|
18866
|
+
const id = setTimeout(() => setSettledSource(source), STREAM_SETTLE_MS);
|
|
18867
|
+
return () => clearTimeout(id);
|
|
18868
|
+
}, [source, settledSource]);
|
|
18869
|
+
useEffect(() => {
|
|
18870
|
+
setMeasured(false);
|
|
18871
|
+
}, [settledSource]);
|
|
18559
18872
|
useEffect(() => {
|
|
18560
18873
|
ensureGlobalListener();
|
|
18561
18874
|
}, []);
|
|
@@ -18570,6 +18883,7 @@ function HtmlPreview({ source }) {
|
|
|
18570
18883
|
pendingHeightRef.current = null;
|
|
18571
18884
|
if (next2 <= 0) return;
|
|
18572
18885
|
setIframeHeight(next2);
|
|
18886
|
+
setMeasured(true);
|
|
18573
18887
|
};
|
|
18574
18888
|
const scheduleHeight = (height) => {
|
|
18575
18889
|
pendingHeightRef.current = height;
|
|
@@ -18661,19 +18975,35 @@ function HtmlPreview({ source }) {
|
|
|
18661
18975
|
)
|
|
18662
18976
|
] })
|
|
18663
18977
|
] }),
|
|
18664
|
-
/* @__PURE__ */
|
|
18665
|
-
"
|
|
18978
|
+
/* @__PURE__ */ jsxs(
|
|
18979
|
+
"div",
|
|
18666
18980
|
{
|
|
18667
|
-
|
|
18668
|
-
className: "ss-code-block__iframe",
|
|
18669
|
-
sandbox: "allow-scripts",
|
|
18670
|
-
loading: "lazy",
|
|
18671
|
-
title: "HTML preview",
|
|
18672
|
-
srcDoc: srcdoc,
|
|
18981
|
+
className: "ss-code-block__preview",
|
|
18673
18982
|
style: {
|
|
18674
18983
|
display: showingPreview ? "block" : "none",
|
|
18675
|
-
...
|
|
18676
|
-
}
|
|
18984
|
+
...loading ? { minHeight: 180 } : {}
|
|
18985
|
+
},
|
|
18986
|
+
children: [
|
|
18987
|
+
loading && /* @__PURE__ */ jsxs("div", { className: "ss-code-block__loading", children: [
|
|
18988
|
+
/* @__PURE__ */ jsx("div", { className: "ss-code-block__spinner" }),
|
|
18989
|
+
/* @__PURE__ */ jsx("span", { children: "Rendering preview\u2026" })
|
|
18990
|
+
] }),
|
|
18991
|
+
/* @__PURE__ */ jsx(
|
|
18992
|
+
"iframe",
|
|
18993
|
+
{
|
|
18994
|
+
ref: iframeRef,
|
|
18995
|
+
className: "ss-code-block__iframe",
|
|
18996
|
+
sandbox: "allow-scripts",
|
|
18997
|
+
loading: "lazy",
|
|
18998
|
+
title: "HTML preview",
|
|
18999
|
+
srcDoc: srcdoc,
|
|
19000
|
+
style: {
|
|
19001
|
+
opacity: loading ? 0 : 1,
|
|
19002
|
+
...loading ? { position: "absolute", inset: 0, height: "100%" } : iframeHeight != null ? { height: `${iframeHeight}px` } : {}
|
|
19003
|
+
}
|
|
19004
|
+
}
|
|
19005
|
+
)
|
|
19006
|
+
]
|
|
18677
19007
|
}
|
|
18678
19008
|
),
|
|
18679
19009
|
/* @__PURE__ */ jsx(
|
|
@@ -18760,7 +19090,8 @@ function SsImage(props) {
|
|
|
18760
19090
|
alt: alt ?? "",
|
|
18761
19091
|
title,
|
|
18762
19092
|
width: finalWidth,
|
|
18763
|
-
height: finalHeight
|
|
19093
|
+
height: finalHeight,
|
|
19094
|
+
style: !resolvedSrc && !errored ? { visibility: "hidden" } : void 0
|
|
18764
19095
|
}
|
|
18765
19096
|
)
|
|
18766
19097
|
]
|
|
@@ -19036,7 +19367,7 @@ function getAvatarColour(name) {
|
|
|
19036
19367
|
const textColor = brightness > 128 ? "#000000" : "#FFFFFF";
|
|
19037
19368
|
return { backgroundColor, textColor };
|
|
19038
19369
|
}
|
|
19039
|
-
var Avatar =
|
|
19370
|
+
var Avatar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
19040
19371
|
"div",
|
|
19041
19372
|
{
|
|
19042
19373
|
ref,
|
|
@@ -19048,7 +19379,7 @@ var Avatar = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
19048
19379
|
}
|
|
19049
19380
|
));
|
|
19050
19381
|
Avatar.displayName = "Avatar";
|
|
19051
|
-
var AvatarImage =
|
|
19382
|
+
var AvatarImage = React9.forwardRef(({ className, alt, src, children: children2, ...props }, _ref) => /* @__PURE__ */ jsx(
|
|
19052
19383
|
MuiAvatar,
|
|
19053
19384
|
{
|
|
19054
19385
|
className: cn("aspect-square h-full w-full", className),
|
|
@@ -19059,7 +19390,7 @@ var AvatarImage = React8.forwardRef(({ className, alt, src, children: children2,
|
|
|
19059
19390
|
}
|
|
19060
19391
|
));
|
|
19061
19392
|
AvatarImage.displayName = "AvatarImage";
|
|
19062
|
-
var AvatarFallback =
|
|
19393
|
+
var AvatarFallback = React9.forwardRef(
|
|
19063
19394
|
({ className, colored = true, ...props }, ref) => {
|
|
19064
19395
|
const childText = String(props.children ?? "");
|
|
19065
19396
|
const colours = colored ? getAvatarColour(childText) : void 0;
|
|
@@ -19111,23 +19442,115 @@ function getUserPhotoUrl(userId) {
|
|
|
19111
19442
|
if (!base2) return void 0;
|
|
19112
19443
|
return `${base2}/users/${userId}/photo`;
|
|
19113
19444
|
}
|
|
19445
|
+
|
|
19446
|
+
// src/messages/smartCopy.ts
|
|
19447
|
+
async function copyMessageRich(container, markdown) {
|
|
19448
|
+
try {
|
|
19449
|
+
const canRichWrite = typeof ClipboardItem !== "undefined" && !!navigator.clipboard?.write;
|
|
19450
|
+
if (!canRichWrite) return copyText(markdown);
|
|
19451
|
+
const { html: html4, images } = await buildHtmlPayload(container);
|
|
19452
|
+
const htmlWithMarker = `${html4}${encodeMarkdownMarker(markdown)}`;
|
|
19453
|
+
const parts = {
|
|
19454
|
+
"text/html": new Blob([htmlWithMarker], { type: "text/html" }),
|
|
19455
|
+
"text/plain": new Blob([markdown], { type: "text/plain" })
|
|
19456
|
+
};
|
|
19457
|
+
if (images.length === 1) {
|
|
19458
|
+
const pngBlob = await dataUrlToBlob(images[0].dataUrl);
|
|
19459
|
+
if (pngBlob) parts["image/png"] = pngBlob;
|
|
19460
|
+
}
|
|
19461
|
+
const withCustom = {
|
|
19462
|
+
...parts,
|
|
19463
|
+
[SS_MARKDOWN_CLIPBOARD_TYPE]: new Blob([markdown], {
|
|
19464
|
+
type: SS_MARKDOWN_CLIPBOARD_TYPE
|
|
19465
|
+
})
|
|
19466
|
+
};
|
|
19467
|
+
if (await tryWrite(withCustom)) return true;
|
|
19468
|
+
if (await tryWrite(parts)) return true;
|
|
19469
|
+
return copyText(markdown);
|
|
19470
|
+
} catch {
|
|
19471
|
+
return copyText(markdown);
|
|
19472
|
+
}
|
|
19473
|
+
}
|
|
19474
|
+
async function tryWrite(parts) {
|
|
19475
|
+
try {
|
|
19476
|
+
await navigator.clipboard.write([new ClipboardItem(parts)]);
|
|
19477
|
+
return true;
|
|
19478
|
+
} catch {
|
|
19479
|
+
return false;
|
|
19480
|
+
}
|
|
19481
|
+
}
|
|
19482
|
+
async function buildHtmlPayload(container) {
|
|
19483
|
+
const liveBlocks = Array.from(
|
|
19484
|
+
container.querySelectorAll(".ss-code-block--previewable")
|
|
19485
|
+
);
|
|
19486
|
+
const snapshots = await Promise.all(
|
|
19487
|
+
liveBlocks.map((block) => {
|
|
19488
|
+
const iframe = block.querySelector("iframe");
|
|
19489
|
+
return iframe ? snapshotIframe(iframe) : Promise.resolve([]);
|
|
19490
|
+
})
|
|
19491
|
+
);
|
|
19492
|
+
const clone = container.cloneNode(true);
|
|
19493
|
+
const cloneBlocks = Array.from(
|
|
19494
|
+
clone.querySelectorAll(".ss-code-block--previewable")
|
|
19495
|
+
);
|
|
19496
|
+
const allImages = [];
|
|
19497
|
+
cloneBlocks.forEach((block, i) => {
|
|
19498
|
+
const images = snapshots[i] ?? [];
|
|
19499
|
+
if (images.length > 0) {
|
|
19500
|
+
allImages.push(...images);
|
|
19501
|
+
const frag = block.ownerDocument.createElement("div");
|
|
19502
|
+
for (const img of images) {
|
|
19503
|
+
const el = block.ownerDocument.createElement("img");
|
|
19504
|
+
el.src = img.dataUrl;
|
|
19505
|
+
el.setAttribute("width", String(img.cssWidth));
|
|
19506
|
+
el.setAttribute("height", String(img.cssHeight));
|
|
19507
|
+
el.style.maxWidth = "100%";
|
|
19508
|
+
frag.appendChild(el);
|
|
19509
|
+
}
|
|
19510
|
+
block.replaceWith(frag);
|
|
19511
|
+
} else {
|
|
19512
|
+
const source = block.querySelector("code")?.textContent ?? "";
|
|
19513
|
+
const div = block.ownerDocument.createElement("div");
|
|
19514
|
+
div.innerHTML = stripScripts(source);
|
|
19515
|
+
block.replaceWith(div);
|
|
19516
|
+
}
|
|
19517
|
+
});
|
|
19518
|
+
clone.querySelectorAll(
|
|
19519
|
+
"iframe, button, .ss-code-block__header, .ss-code-block__copy, .ss-code-block__toggle"
|
|
19520
|
+
).forEach((el) => el.remove());
|
|
19521
|
+
const html4 = `<meta charset="utf-8">${clone.innerHTML}`;
|
|
19522
|
+
return { html: html4, images: allImages };
|
|
19523
|
+
}
|
|
19524
|
+
function stripScripts(html4) {
|
|
19525
|
+
return html4.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
19526
|
+
}
|
|
19527
|
+
async function dataUrlToBlob(dataUrl) {
|
|
19528
|
+
try {
|
|
19529
|
+
const res = await fetch(dataUrl);
|
|
19530
|
+
return await res.blob();
|
|
19531
|
+
} catch {
|
|
19532
|
+
return null;
|
|
19533
|
+
}
|
|
19534
|
+
}
|
|
19114
19535
|
var RESET_DELAY = 1e3;
|
|
19115
19536
|
function ChatMessageCopyButton({
|
|
19116
|
-
content
|
|
19537
|
+
content,
|
|
19538
|
+
contentRef
|
|
19117
19539
|
}) {
|
|
19118
19540
|
const [state, setState] = useState("idle" /* IDLE */);
|
|
19119
19541
|
const handleCopy = async () => {
|
|
19120
19542
|
if (!content) return;
|
|
19121
19543
|
const textToCopy = content.filter((item) => !!item.text).map((item) => item.text).join("\n");
|
|
19122
19544
|
if (!textToCopy) return;
|
|
19123
|
-
|
|
19124
|
-
|
|
19545
|
+
const container = contentRef?.current;
|
|
19546
|
+
const ok3 = container ? await copyMessageRich(container, textToCopy) : await copyText(textToCopy);
|
|
19547
|
+
if (ok3) {
|
|
19125
19548
|
setState("success" /* SUCCESS */);
|
|
19126
19549
|
setTimeout(() => {
|
|
19127
19550
|
setState("idle" /* IDLE */);
|
|
19128
19551
|
}, RESET_DELAY);
|
|
19129
|
-
}
|
|
19130
|
-
console.error("Failed to copy
|
|
19552
|
+
} else {
|
|
19553
|
+
console.error("Failed to copy message content");
|
|
19131
19554
|
}
|
|
19132
19555
|
};
|
|
19133
19556
|
const getIcon = () => {
|
|
@@ -19279,17 +19702,12 @@ function getSafeUrl(url) {
|
|
|
19279
19702
|
return null;
|
|
19280
19703
|
}
|
|
19281
19704
|
}
|
|
19282
|
-
function
|
|
19283
|
-
|
|
19284
|
-
|
|
19285
|
-
|
|
19286
|
-
|
|
19287
|
-
return parsed.hostname + (parsed.pathname !== "/" ? parsed.pathname : "");
|
|
19288
|
-
} catch {
|
|
19289
|
-
return source.url;
|
|
19290
|
-
}
|
|
19705
|
+
function getHost(url) {
|
|
19706
|
+
try {
|
|
19707
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
19708
|
+
} catch {
|
|
19709
|
+
return url;
|
|
19291
19710
|
}
|
|
19292
|
-
return `Source ${source.index}`;
|
|
19293
19711
|
}
|
|
19294
19712
|
function isFileSource(s2) {
|
|
19295
19713
|
return s2.sourceType === "File" /* File */ && !!s2.file;
|
|
@@ -19297,15 +19715,82 @@ function isFileSource(s2) {
|
|
|
19297
19715
|
function isLinkSource(s2) {
|
|
19298
19716
|
return (s2.sourceType === "URL" /* URL */ || s2.sourceType === "WebExternal" /* WebExternal */) && !!s2.url;
|
|
19299
19717
|
}
|
|
19718
|
+
function UnverifiedBadge({
|
|
19719
|
+
attribution,
|
|
19720
|
+
compact = false
|
|
19721
|
+
}) {
|
|
19722
|
+
if (attribution !== "unsupported" /* Unsupported */) return null;
|
|
19723
|
+
return /* @__PURE__ */ jsxs(
|
|
19724
|
+
"span",
|
|
19725
|
+
{
|
|
19726
|
+
title: "This citation couldn't be verified against the source text \u2014 double-check it.",
|
|
19727
|
+
className: cn(
|
|
19728
|
+
"inline-flex items-center gap-0.5 rounded text-[10px] font-medium text-amber-600 dark:text-amber-400 flex-shrink-0",
|
|
19729
|
+
!compact && "px-1 py-px bg-amber-500/10"
|
|
19730
|
+
),
|
|
19731
|
+
children: [
|
|
19732
|
+
/* @__PURE__ */ jsx(ShieldAlert, { className: "h-3 w-3" }),
|
|
19733
|
+
!compact && "Unverified"
|
|
19734
|
+
]
|
|
19735
|
+
}
|
|
19736
|
+
);
|
|
19737
|
+
}
|
|
19738
|
+
function IndexChip({ index }) {
|
|
19739
|
+
return /* @__PURE__ */ jsx("span", { className: "flex h-4 min-w-[16px] flex-shrink-0 items-center justify-center rounded-full bg-muted px-1 text-[10px] font-medium tabular-nums text-muted-foreground", children: index });
|
|
19740
|
+
}
|
|
19741
|
+
function SourceFavicon({ host }) {
|
|
19742
|
+
const [failed, setFailed] = useState(false);
|
|
19743
|
+
if (failed) {
|
|
19744
|
+
return /* @__PURE__ */ jsx(Globe, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" });
|
|
19745
|
+
}
|
|
19746
|
+
return /* @__PURE__ */ jsx(
|
|
19747
|
+
"img",
|
|
19748
|
+
{
|
|
19749
|
+
src: `https://www.google.com/s2/favicons?domain=${encodeURIComponent(
|
|
19750
|
+
host
|
|
19751
|
+
)}&sz=64`,
|
|
19752
|
+
alt: "",
|
|
19753
|
+
width: 16,
|
|
19754
|
+
height: 16,
|
|
19755
|
+
loading: "lazy",
|
|
19756
|
+
onError: () => setFailed(true),
|
|
19757
|
+
className: "h-4 w-4 flex-shrink-0 rounded-sm"
|
|
19758
|
+
}
|
|
19759
|
+
);
|
|
19760
|
+
}
|
|
19761
|
+
function CitedQuote({ text: text6 }) {
|
|
19762
|
+
if (!text6) return null;
|
|
19763
|
+
return /* @__PURE__ */ jsxs("p", { className: "m-0 text-xs leading-snug text-muted-foreground", children: [
|
|
19764
|
+
"\u201C",
|
|
19765
|
+
text6,
|
|
19766
|
+
"\u201D"
|
|
19767
|
+
] });
|
|
19768
|
+
}
|
|
19769
|
+
function SectionLabel({ children: children2 }) {
|
|
19770
|
+
return /* @__PURE__ */ jsx("p", { className: "m-0 px-0.5 pb-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: children2 });
|
|
19771
|
+
}
|
|
19772
|
+
var pillClasses = "inline-flex max-w-full items-center gap-1.5 rounded-md border border-border/60 bg-background px-2 py-1 text-xs font-medium text-foreground transition-colors hover:border-border hover:bg-muted/40";
|
|
19773
|
+
var expandedCardClasses = "w-full rounded-lg border border-border/60 bg-background p-2.5 flex flex-col gap-1.5";
|
|
19300
19774
|
function ChatMessageSources({
|
|
19301
19775
|
sources
|
|
19302
19776
|
}) {
|
|
19303
19777
|
const { workspaceId, threadId } = useChatContext();
|
|
19304
19778
|
const { downloadFileMutation } = useFileMutations({ workspaceId, threadId });
|
|
19305
19779
|
const [isExpanded, setIsExpanded] = useState(true);
|
|
19780
|
+
const [openIndexes, setOpenIndexes] = useState(
|
|
19781
|
+
/* @__PURE__ */ new Set()
|
|
19782
|
+
);
|
|
19783
|
+
const toggleOpen = (index) => setOpenIndexes((prev) => {
|
|
19784
|
+
const next2 = new Set(prev);
|
|
19785
|
+
if (next2.has(index)) next2.delete(index);
|
|
19786
|
+
else next2.add(index);
|
|
19787
|
+
return next2;
|
|
19788
|
+
});
|
|
19306
19789
|
const displaySources = (sources ?? []).filter(
|
|
19307
19790
|
(s2) => isFileSource(s2) || isLinkSource(s2)
|
|
19308
19791
|
);
|
|
19792
|
+
const urlSources = displaySources.filter((s2) => !isFileSource(s2));
|
|
19793
|
+
const fileSources = displaySources.filter(isFileSource);
|
|
19309
19794
|
if (displaySources.length === 0) return null;
|
|
19310
19795
|
return /* @__PURE__ */ jsxs("div", { className: "mt-4 rounded-lg border border-border bg-muted/30 overflow-hidden", children: [
|
|
19311
19796
|
/* @__PURE__ */ jsxs(
|
|
@@ -19331,72 +19816,148 @@ function ChatMessageSources({
|
|
|
19331
19816
|
]
|
|
19332
19817
|
}
|
|
19333
19818
|
),
|
|
19334
|
-
isExpanded && /* @__PURE__ */
|
|
19335
|
-
"
|
|
19336
|
-
|
|
19337
|
-
className: "
|
|
19338
|
-
|
|
19339
|
-
|
|
19340
|
-
|
|
19341
|
-
if (isFileSource(source)) {
|
|
19342
|
-
const Icon = getFileIcon3(source.file.name);
|
|
19819
|
+
isExpanded && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 p-2.5", children: [
|
|
19820
|
+
urlSources.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
19821
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "URLs" }),
|
|
19822
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: urlSources.map((source) => {
|
|
19823
|
+
const host = getHost(source.url ?? "");
|
|
19824
|
+
const safeHref = source.url ? getSafeUrl(source.url) : null;
|
|
19825
|
+
if (!openIndexes.has(source.index)) {
|
|
19343
19826
|
return /* @__PURE__ */ jsxs(
|
|
19344
|
-
"
|
|
19827
|
+
"button",
|
|
19345
19828
|
{
|
|
19346
|
-
|
|
19347
|
-
|
|
19829
|
+
type: "button",
|
|
19830
|
+
"aria-expanded": false,
|
|
19831
|
+
title: source.url ?? host,
|
|
19832
|
+
onClick: () => toggleOpen(source.index),
|
|
19833
|
+
className: pillClasses,
|
|
19348
19834
|
children: [
|
|
19349
|
-
/* @__PURE__ */
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19835
|
+
/* @__PURE__ */ jsx(SourceFavicon, { host }),
|
|
19836
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: host }),
|
|
19837
|
+
/* @__PURE__ */ jsx(
|
|
19838
|
+
UnverifiedBadge,
|
|
19839
|
+
{
|
|
19840
|
+
attribution: source.attribution,
|
|
19841
|
+
compact: true
|
|
19842
|
+
}
|
|
19843
|
+
),
|
|
19844
|
+
/* @__PURE__ */ jsx(IndexChip, { index: source.index })
|
|
19845
|
+
]
|
|
19846
|
+
},
|
|
19847
|
+
`url-${source.index}`
|
|
19848
|
+
);
|
|
19849
|
+
}
|
|
19850
|
+
return /* @__PURE__ */ jsxs(
|
|
19851
|
+
"div",
|
|
19852
|
+
{
|
|
19853
|
+
className: expandedCardClasses,
|
|
19854
|
+
children: [
|
|
19855
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2", children: [
|
|
19856
|
+
/* @__PURE__ */ jsx(SourceFavicon, { host }),
|
|
19857
|
+
safeHref ? /* @__PURE__ */ jsx(
|
|
19858
|
+
"a",
|
|
19859
|
+
{
|
|
19860
|
+
href: safeHref,
|
|
19861
|
+
target: "_blank",
|
|
19862
|
+
rel: "noreferrer",
|
|
19863
|
+
className: "min-w-0 truncate text-sm font-medium text-foreground no-underline hover:underline underline-offset-2",
|
|
19864
|
+
children: host
|
|
19865
|
+
}
|
|
19866
|
+
) : /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-sm font-medium text-foreground", children: host }),
|
|
19867
|
+
/* @__PURE__ */ jsx(UnverifiedBadge, { attribution: source.attribution }),
|
|
19868
|
+
/* @__PURE__ */ jsx(IndexChip, { index: source.index }),
|
|
19354
19869
|
/* @__PURE__ */ jsx(
|
|
19355
19870
|
"button",
|
|
19356
19871
|
{
|
|
19357
19872
|
type: "button",
|
|
19358
|
-
|
|
19359
|
-
|
|
19360
|
-
|
|
19361
|
-
|
|
19362
|
-
children:
|
|
19873
|
+
"aria-expanded": true,
|
|
19874
|
+
"aria-label": "Collapse source",
|
|
19875
|
+
onClick: () => toggleOpen(source.index),
|
|
19876
|
+
className: "ml-auto rounded p-0.5 text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground",
|
|
19877
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-3.5 w-3.5" })
|
|
19363
19878
|
}
|
|
19364
19879
|
)
|
|
19880
|
+
] }),
|
|
19881
|
+
source.url && /* @__PURE__ */ jsx("p", { className: "m-0 truncate text-xs text-muted-foreground/80", children: source.url }),
|
|
19882
|
+
/* @__PURE__ */ jsx(CitedQuote, { text: source.citedText })
|
|
19883
|
+
]
|
|
19884
|
+
},
|
|
19885
|
+
`url-${source.index}`
|
|
19886
|
+
);
|
|
19887
|
+
}) })
|
|
19888
|
+
] }),
|
|
19889
|
+
fileSources.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
19890
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Files" }),
|
|
19891
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: fileSources.map((source) => {
|
|
19892
|
+
const Icon = getFileIcon3(source.file.name);
|
|
19893
|
+
if (!openIndexes.has(source.index)) {
|
|
19894
|
+
return /* @__PURE__ */ jsxs(
|
|
19895
|
+
"button",
|
|
19896
|
+
{
|
|
19897
|
+
type: "button",
|
|
19898
|
+
"aria-expanded": false,
|
|
19899
|
+
title: source.file.name,
|
|
19900
|
+
onClick: () => toggleOpen(source.index),
|
|
19901
|
+
className: pillClasses,
|
|
19902
|
+
children: [
|
|
19903
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" }),
|
|
19904
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: source.file.name }),
|
|
19905
|
+
/* @__PURE__ */ jsx(
|
|
19906
|
+
UnverifiedBadge,
|
|
19907
|
+
{
|
|
19908
|
+
attribution: source.attribution,
|
|
19909
|
+
compact: true
|
|
19910
|
+
}
|
|
19911
|
+
),
|
|
19912
|
+
/* @__PURE__ */ jsx(IndexChip, { index: source.index })
|
|
19365
19913
|
]
|
|
19366
19914
|
},
|
|
19367
19915
|
`${source.file.id}-${source.index}`
|
|
19368
19916
|
);
|
|
19369
19917
|
}
|
|
19370
|
-
const safeHref = source.url ? getSafeUrl(source.url) : null;
|
|
19371
19918
|
return /* @__PURE__ */ jsxs(
|
|
19372
|
-
"
|
|
19919
|
+
"div",
|
|
19373
19920
|
{
|
|
19374
|
-
className:
|
|
19375
|
-
style: { paddingLeft: 0, marginLeft: 0 },
|
|
19921
|
+
className: expandedCardClasses,
|
|
19376
19922
|
children: [
|
|
19377
|
-
/* @__PURE__ */ jsxs("
|
|
19378
|
-
|
|
19379
|
-
" : "
|
|
19923
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2", children: [
|
|
19924
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" }),
|
|
19925
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-sm font-medium text-foreground", children: source.file.name }),
|
|
19926
|
+
/* @__PURE__ */ jsx(UnverifiedBadge, { attribution: source.attribution }),
|
|
19927
|
+
/* @__PURE__ */ jsx(IndexChip, { index: source.index }),
|
|
19928
|
+
/* @__PURE__ */ jsx(
|
|
19929
|
+
"button",
|
|
19930
|
+
{
|
|
19931
|
+
type: "button",
|
|
19932
|
+
"aria-expanded": true,
|
|
19933
|
+
"aria-label": "Collapse source",
|
|
19934
|
+
onClick: () => toggleOpen(source.index),
|
|
19935
|
+
className: "ml-auto rounded p-0.5 text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground",
|
|
19936
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-3.5 w-3.5" })
|
|
19937
|
+
}
|
|
19938
|
+
)
|
|
19380
19939
|
] }),
|
|
19381
|
-
/* @__PURE__ */ jsx(
|
|
19382
|
-
|
|
19383
|
-
"
|
|
19940
|
+
/* @__PURE__ */ jsx(CitedQuote, { text: source.citedText }),
|
|
19941
|
+
/* @__PURE__ */ jsxs(
|
|
19942
|
+
"button",
|
|
19384
19943
|
{
|
|
19385
|
-
|
|
19386
|
-
|
|
19387
|
-
|
|
19388
|
-
|
|
19389
|
-
|
|
19390
|
-
|
|
19944
|
+
type: "button",
|
|
19945
|
+
onClick: () => downloadFileMutation.mutate(source.file),
|
|
19946
|
+
disabled: downloadFileMutation.isPending,
|
|
19947
|
+
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",
|
|
19948
|
+
children: [
|
|
19949
|
+
/* @__PURE__ */ jsx(Download, { className: "h-3 w-3" }),
|
|
19950
|
+
"Download"
|
|
19951
|
+
]
|
|
19391
19952
|
}
|
|
19392
|
-
)
|
|
19953
|
+
)
|
|
19393
19954
|
]
|
|
19394
19955
|
},
|
|
19395
|
-
|
|
19956
|
+
`${source.file.id}-${source.index}`
|
|
19396
19957
|
);
|
|
19397
|
-
})
|
|
19398
|
-
}
|
|
19399
|
-
|
|
19958
|
+
}) })
|
|
19959
|
+
] })
|
|
19960
|
+
] })
|
|
19400
19961
|
] });
|
|
19401
19962
|
}
|
|
19402
19963
|
var MessageBubble = (props) => {
|
|
@@ -19415,6 +19976,7 @@ var MessageBubble = (props) => {
|
|
|
19415
19976
|
} = props;
|
|
19416
19977
|
const [responseFormData, setResponseFormData] = useState(userInput);
|
|
19417
19978
|
const [responseFormValid, setResponseFormValid] = useState(false);
|
|
19979
|
+
const contentRef = useRef(null);
|
|
19418
19980
|
const isBotResponse = type === "Output" /* OUTPUT */;
|
|
19419
19981
|
const showForm = userOutput;
|
|
19420
19982
|
useEffect(() => {
|
|
@@ -19452,12 +20014,12 @@ var MessageBubble = (props) => {
|
|
|
19452
20014
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: createdAt ? parseDateTime(createdAt, "Do MMMM YYYY, h:mm a") : "" })
|
|
19453
20015
|
] })
|
|
19454
20016
|
] }),
|
|
19455
|
-
/* @__PURE__ */ jsx(ChatMessageCopyButton, { content })
|
|
20017
|
+
/* @__PURE__ */ jsx(ChatMessageCopyButton, { content, contentRef })
|
|
19456
20018
|
]
|
|
19457
20019
|
}
|
|
19458
20020
|
),
|
|
19459
20021
|
/* @__PURE__ */ jsxs("div", { className: cn(isBotResponse ? "p-4" : "px-4 py-2"), children: [
|
|
19460
|
-
contentIsList && content?.map(
|
|
20022
|
+
/* @__PURE__ */ jsx("div", { ref: contentRef, children: contentIsList && content?.map(
|
|
19461
20023
|
(item, i) => item.text ? /* @__PURE__ */ jsx(
|
|
19462
20024
|
"div",
|
|
19463
20025
|
{
|
|
@@ -19466,7 +20028,7 @@ var MessageBubble = (props) => {
|
|
|
19466
20028
|
},
|
|
19467
20029
|
`content-${i}`
|
|
19468
20030
|
) : item.image ? /* @__PURE__ */ jsx("div", { className: "mb-3 last:mb-0", children: /* @__PURE__ */ jsx(ChatMessageImage, { image: item.image }) }, `image-${i}`) : null
|
|
19469
|
-
),
|
|
20031
|
+
) }),
|
|
19470
20032
|
files.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ss-chat-message__attachments mt-4 space-y-2", children: [
|
|
19471
20033
|
/* @__PURE__ */ jsx("h4", { className: "text-xs font-semibold text-muted-foreground mb-1", children: "Attachments" }),
|
|
19472
20034
|
files.map((file, idx) => {
|
|
@@ -19649,7 +20211,8 @@ var MessageItem = ({
|
|
|
19649
20211
|
groupType = v.type;
|
|
19650
20212
|
const name = v.name.toLowerCase();
|
|
19651
20213
|
switch (name) {
|
|
19652
|
-
case "variables":
|
|
20214
|
+
case "variables":
|
|
20215
|
+
case "userinfo": {
|
|
19653
20216
|
continue;
|
|
19654
20217
|
}
|
|
19655
20218
|
case "status": {
|
|
@@ -19790,6 +20353,10 @@ function MessageList({
|
|
|
19790
20353
|
const messagesEndRef = useRef(null);
|
|
19791
20354
|
const prevMessageCountRef = useRef(0);
|
|
19792
20355
|
const hasInitialScrollRef = useRef(false);
|
|
20356
|
+
const everHadMessagesRef = useRef({
|
|
20357
|
+
threadId: "",
|
|
20358
|
+
had: false
|
|
20359
|
+
});
|
|
19793
20360
|
const isMobile = useIsMobile();
|
|
19794
20361
|
const { data: activeWorkspace } = useWorkspace(workspaceId);
|
|
19795
20362
|
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
@@ -19861,8 +20428,15 @@ function MessageList({
|
|
|
19861
20428
|
ro.observe(content);
|
|
19862
20429
|
return () => ro.disconnect();
|
|
19863
20430
|
}, [isAtBottom, scrollToBottom]);
|
|
20431
|
+
const safeMessages = messages ?? [];
|
|
20432
|
+
if (everHadMessagesRef.current.threadId !== threadId) {
|
|
20433
|
+
everHadMessagesRef.current = { threadId, had: safeMessages.length > 0 };
|
|
20434
|
+
} else if (safeMessages.length > 0) {
|
|
20435
|
+
everHadMessagesRef.current.had = true;
|
|
20436
|
+
}
|
|
20437
|
+
const hadMessagesBefore = everHadMessagesRef.current.had;
|
|
19864
20438
|
const isLoading = isChoosingThread || (threadPending || threadFetching) && !thread || (messagesPending || messagesFetching) && messages === void 0;
|
|
19865
|
-
if (isLoading) {
|
|
20439
|
+
if (isLoading && !hadMessagesBefore) {
|
|
19866
20440
|
return /* @__PURE__ */ jsx(
|
|
19867
20441
|
"div",
|
|
19868
20442
|
{
|
|
@@ -19878,7 +20452,7 @@ function MessageList({
|
|
|
19878
20452
|
}
|
|
19879
20453
|
);
|
|
19880
20454
|
}
|
|
19881
|
-
if (threadError || messagesError) {
|
|
20455
|
+
if ((threadError || messagesError) && !hadMessagesBefore) {
|
|
19882
20456
|
return /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center p-6", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-md space-y-3", children: [
|
|
19883
20457
|
threadError && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-destructive", children: [
|
|
19884
20458
|
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4" }),
|
|
@@ -19890,8 +20464,7 @@ function MessageList({
|
|
|
19890
20464
|
] })
|
|
19891
20465
|
] }) });
|
|
19892
20466
|
}
|
|
19893
|
-
|
|
19894
|
-
if (safeMessages.length === 0) {
|
|
20467
|
+
if (safeMessages.length === 0 && !hadMessagesBefore) {
|
|
19895
20468
|
return /* @__PURE__ */ jsxs("div", { className: "flex overflow-auto flex-shrink-10 flex-col p-8 text-center", children: [
|
|
19896
20469
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-medium mb-2", children: activeWorkspace?.name ?? "No messages yet" }),
|
|
19897
20470
|
activeWorkspace?.firstPrompt && /* @__PURE__ */ jsx("div", { className: "max-w-3xl mx-auto p-4", children: /* @__PURE__ */ jsx(MessageMarkdown, { value: activeWorkspace.firstPrompt }) })
|
|
@@ -20109,6 +20682,7 @@ var computeAvatar = (name, fallback) => {
|
|
|
20109
20682
|
function mapMentionUserDtoToModel(dto) {
|
|
20110
20683
|
return {
|
|
20111
20684
|
id: dto.id,
|
|
20685
|
+
userId: dto.userId,
|
|
20112
20686
|
displayName: dto.displayName ?? "",
|
|
20113
20687
|
initials: getInitials(dto.displayName ?? "")
|
|
20114
20688
|
};
|
|
@@ -20143,9 +20717,6 @@ function mapWorkspaceDtoToModel(dto) {
|
|
|
20143
20717
|
firstPrompt: dto.firstPrompt ?? "",
|
|
20144
20718
|
outputSchema: dto.outputSchema ?? void 0,
|
|
20145
20719
|
inputs: dto.inputs ?? void 0,
|
|
20146
|
-
isPromptAndResponseLoggingEnabled: truthy(
|
|
20147
|
-
dto.isPromptAndResponseLoggingEnabled
|
|
20148
|
-
),
|
|
20149
20720
|
variables,
|
|
20150
20721
|
sandBoxThreadId: dto.sandBoxThreadId ?? void 0,
|
|
20151
20722
|
supportsFiles: truthy(dto.supportsFiles),
|
|
@@ -20154,6 +20725,6 @@ function mapWorkspaceDtoToModel(dto) {
|
|
|
20154
20725
|
}
|
|
20155
20726
|
var mapWorkspacesDtoToModels = (arr) => arr.map(mapWorkspaceDtoToModel);
|
|
20156
20727
|
|
|
20157
|
-
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, getModelIcon, getThreadPlaceholderFromListCache, getUserPhotoUrl, invalidateWorkspaceThreadLists, isDraftThreadId, mapFileInfoDtoToModel, mapMentionUserDtoToModel, mapMessageDtoToModel, mapMessageErrorDtoToModel, mapMessageValueDtoToModel, mapMessagesDtoToModels, mapSignalRThreadSummaryToModel, mapThreadDtoToModel, mapThreadsResponseDtoToModel, mapWorkspaceDtoToModel, mapWorkspacesDtoToModels, markDraftThreadId, messagesKeys, messagesListOptions, messagesMutationsKeys, modelsKeys, parseDateTime, parseDateTimeHuman, setThreadOptimisticRunning, setThreadRunningInLists, taggableUsersOptions, threadDetailOptions, threadsKeys, unmarkDraftThreadId, useAddInputToMessage, useChatContext, useChatIdentity, useChatService, useDownloadFileBlobQuery, useFileMutations, useFlowRunVariables, useMessages, useModels, useSendMessage, useTaggableWorkspaceUsers, useThread, useThreadIsRunning, useUpdateFlowRunVariable, useWorkspace, utcDate, workspaceDetailOptions, workspaceKeys };
|
|
20728
|
+
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, getModelIcon, getThreadPlaceholderFromListCache, getUserPhotoUrl, invalidateWorkspaceThreadLists, isDraftThreadId, mapFileInfoDtoToModel, mapMentionUserDtoToModel, mapMessageDtoToModel, mapMessageErrorDtoToModel, mapMessageValueDtoToModel, mapMessagesDtoToModels, mapSignalRThreadSummaryToModel, mapThreadDtoToModel, mapThreadsResponseDtoToModel, mapWorkspaceDtoToModel, mapWorkspacesDtoToModels, markDraftThreadId, messagesKeys, messagesListOptions, messagesMutationsKeys, modelsKeys, parseDateTime, parseDateTimeHuman, randomUUID, setThreadOptimisticRunning, setThreadRunningInLists, taggableUsersOptions, threadDetailOptions, threadsKeys, unmarkDraftThreadId, useAddInputToMessage, useChatContext, useChatIdentity, useChatService, useDownloadFileBlobQuery, useFileMutations, useFlowRunVariables, useMessages, useModels, useSendMessage, useTaggableWorkspaceUsers, useThread, useThreadIsRunning, useUpdateFlowRunVariable, useWorkspace, utcDate, workspaceDetailOptions, workspaceKeys };
|
|
20158
20729
|
//# sourceMappingURL=index.js.map
|
|
20159
20730
|
//# sourceMappingURL=index.js.map
|