@smartspace/chat-ui 1.13.1-dev.aa44752 → 1.13.1-dev.abffa36
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 +27 -19
- package/dist/index.js +512 -72
- 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, ExternalLink, Copy, Download } from 'lucide-react';
|
|
4
|
-
import * as
|
|
3
|
+
import { Loader2, Check, X, Paperclip, ArrowBigUp, Minimize2, AlertTriangle, FileImage, FileVideo, FileAudio, FileArchive, FileCode, FileSpreadsheet, Presentation, FileText, ChevronUp, ExternalLink, Copy, Download, 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
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';
|
|
@@ -424,6 +424,29 @@ var fileTag = $node("fileTag", () => ({
|
|
|
424
424
|
var MAX_IFRAME_HEIGHT = 5e3;
|
|
425
425
|
var HEIGHT_MESSAGE = "ss-html-preview-height";
|
|
426
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
|
+
}
|
|
427
450
|
var HEIGHT_REPORTER_SCRIPT = `
|
|
428
451
|
<script>(function(){
|
|
429
452
|
try {
|
|
@@ -448,6 +471,48 @@ var HEIGHT_REPORTER_SCRIPT = `
|
|
|
448
471
|
window.addEventListener('unhandledrejection', function(ev){
|
|
449
472
|
reportError(ev && ev.reason && ev.reason.message);
|
|
450
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
|
+
});
|
|
451
516
|
var lastSent = -1;
|
|
452
517
|
function send(){
|
|
453
518
|
try {
|
|
@@ -533,6 +598,38 @@ async function copyText(text6) {
|
|
|
533
598
|
return false;
|
|
534
599
|
}
|
|
535
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
|
+
}
|
|
536
633
|
|
|
537
634
|
// src/shared/markdown/extensions/htmlPreview.ts
|
|
538
635
|
var PREVIEW_LANGUAGES = /* @__PURE__ */ new Set(["html"]);
|
|
@@ -756,7 +853,7 @@ var mention = $node("mention", () => ({
|
|
|
756
853
|
match: (node2) => node2.type.name === "mention",
|
|
757
854
|
runner: (state, node2) => {
|
|
758
855
|
const { id, label } = node2.attrs;
|
|
759
|
-
state.addNode("
|
|
856
|
+
state.addNode("text", void 0, label || `@${id}`);
|
|
760
857
|
}
|
|
761
858
|
}
|
|
762
859
|
}));
|
|
@@ -982,6 +1079,7 @@ function EditorInner({
|
|
|
982
1079
|
const [_isDragging, setIsDragging] = useState(false);
|
|
983
1080
|
const viewRef = useRef(null);
|
|
984
1081
|
const serializerRef = useRef(null);
|
|
1082
|
+
const parserRef = useRef(null);
|
|
985
1083
|
function guessImageExt(mime) {
|
|
986
1084
|
const t = (mime || "").toLowerCase();
|
|
987
1085
|
if (t === "image/jpeg") return "jpg";
|
|
@@ -1100,6 +1198,10 @@ function EditorInner({
|
|
|
1100
1198
|
serializerRef.current = anyCtx.get(serializerCtx);
|
|
1101
1199
|
} catch {
|
|
1102
1200
|
}
|
|
1201
|
+
try {
|
|
1202
|
+
parserRef.current = anyCtx.get(parserCtx);
|
|
1203
|
+
} catch {
|
|
1204
|
+
}
|
|
1103
1205
|
const handle2 = () => {
|
|
1104
1206
|
try {
|
|
1105
1207
|
if (enableMentions) updateMentionFromView();
|
|
@@ -1189,6 +1291,19 @@ function EditorInner({
|
|
|
1189
1291
|
const tr = view.state.tr.replaceWith(from, to, node2);
|
|
1190
1292
|
view.dispatch(tr.scrollIntoView());
|
|
1191
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
|
+
}
|
|
1192
1307
|
async function insertUploadedFilesIntoEditor(files) {
|
|
1193
1308
|
const view = viewRef.current;
|
|
1194
1309
|
if (!isEditable || !view) return false;
|
|
@@ -1461,6 +1576,17 @@ function EditorInner({
|
|
|
1461
1576
|
},
|
|
1462
1577
|
onPasteCapture: (e) => {
|
|
1463
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
|
+
}
|
|
1464
1590
|
const items = e.clipboardData?.items;
|
|
1465
1591
|
if (!items) return;
|
|
1466
1592
|
const imageFiles = [];
|
|
@@ -1687,7 +1813,7 @@ var buttonVariants = cva(
|
|
|
1687
1813
|
}
|
|
1688
1814
|
}
|
|
1689
1815
|
);
|
|
1690
|
-
var Button =
|
|
1816
|
+
var Button = React9.forwardRef(
|
|
1691
1817
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
1692
1818
|
const Comp = asChild ? Slot : "button";
|
|
1693
1819
|
return /* @__PURE__ */ jsx(
|
|
@@ -2902,6 +3028,128 @@ var modelIdRendererTester = rankWith(
|
|
|
2902
3028
|
}
|
|
2903
3029
|
);
|
|
2904
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);
|
|
2905
3153
|
var TextareaRenderer = ({
|
|
2906
3154
|
data,
|
|
2907
3155
|
handleChange,
|
|
@@ -3071,6 +3319,7 @@ var renderers = [
|
|
|
3071
3319
|
{ tester: modelIdRendererTester, renderer: ModelIdRendererControl },
|
|
3072
3320
|
{ tester: booleanRendererTester, renderer: BooleanRendererControl },
|
|
3073
3321
|
{ tester: dropdownRendererTester, renderer: DropdownRendererControl },
|
|
3322
|
+
{ tester: numberRendererTester, renderer: NumberRendererControl },
|
|
3074
3323
|
{ tester: textareaRendererTester, renderer: TextareaRendererControl },
|
|
3075
3324
|
...vanillaRenderers,
|
|
3076
3325
|
{ tester: jsonEditorTester, renderer: JsonEditorRendererControl }
|
|
@@ -3124,26 +3373,26 @@ function useChatVariablesFormVm({
|
|
|
3124
3373
|
const { mutate: updateVariableMutation } = useUpdateFlowRunVariable();
|
|
3125
3374
|
const querySettled = !isLoading && (threadVars !== void 0 || isError);
|
|
3126
3375
|
const shouldUseDefaults = isError || threadVars && Object.keys(threadVars).length === 0;
|
|
3127
|
-
const built =
|
|
3376
|
+
const built = React9.useMemo(() => {
|
|
3128
3377
|
return buildSimpleSchemaAndUi(
|
|
3129
3378
|
workspace.variables,
|
|
3130
3379
|
threadVars,
|
|
3131
3380
|
shouldUseDefaults ?? false
|
|
3132
3381
|
);
|
|
3133
3382
|
}, [workspace.variables, threadVars, shouldUseDefaults]);
|
|
3134
|
-
const [data, setData] =
|
|
3135
|
-
|
|
3383
|
+
const [data, setData] = React9.useState(null);
|
|
3384
|
+
React9.useEffect(() => {
|
|
3136
3385
|
if (querySettled) {
|
|
3137
3386
|
setData(built.initialData);
|
|
3138
3387
|
setVariables(built.initialData);
|
|
3139
3388
|
}
|
|
3140
3389
|
}, [querySettled, built.initialData, setVariables]);
|
|
3141
|
-
const ajv =
|
|
3142
|
-
const prevRef =
|
|
3143
|
-
|
|
3390
|
+
const ajv = React9.useMemo(() => createAjv({ useDefaults: false }), []);
|
|
3391
|
+
const prevRef = React9.useRef(null);
|
|
3392
|
+
React9.useEffect(() => {
|
|
3144
3393
|
prevRef.current = data;
|
|
3145
3394
|
}, [data]);
|
|
3146
|
-
const onChange =
|
|
3395
|
+
const onChange = React9.useCallback(
|
|
3147
3396
|
({ data: next2 }) => {
|
|
3148
3397
|
if (prevRef.current && !isDraftThreadId(threadId)) {
|
|
3149
3398
|
const keys2 = Object.keys(workspace.variables || {});
|
|
@@ -3164,7 +3413,7 @@ function useChatVariablesFormVm({
|
|
|
3164
3413
|
},
|
|
3165
3414
|
[workspace.variables, setVariables, updateVariableMutation, threadId]
|
|
3166
3415
|
);
|
|
3167
|
-
const config =
|
|
3416
|
+
const config = React9.useMemo(
|
|
3168
3417
|
() => ({
|
|
3169
3418
|
restrict: true,
|
|
3170
3419
|
trim: false,
|
|
@@ -3233,7 +3482,20 @@ var threadsKeys = {
|
|
|
3233
3482
|
};
|
|
3234
3483
|
|
|
3235
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
|
+
}
|
|
3236
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
|
+
}
|
|
3237
3499
|
qc.setQueryData(
|
|
3238
3500
|
threadsKeys.detail(thread.workSpaceId, thread.id),
|
|
3239
3501
|
(old) => ({ ...old ?? thread, ...thread })
|
|
@@ -3254,6 +3516,7 @@ function applyThreadToCache(qc, thread) {
|
|
|
3254
3516
|
if (!page?.data) return page;
|
|
3255
3517
|
const idx2 = page.data.findIndex((t) => t.id === thread.id);
|
|
3256
3518
|
if (idx2 === -1) return page;
|
|
3519
|
+
if (isStaleSummary(thread, page.data[idx2])) return page;
|
|
3257
3520
|
changed = true;
|
|
3258
3521
|
foundInList = true;
|
|
3259
3522
|
const nextData2 = page.data.slice();
|
|
@@ -3266,6 +3529,7 @@ function applyThreadToCache(qc, thread) {
|
|
|
3266
3529
|
if (!list2.data) return old;
|
|
3267
3530
|
const idx = list2.data.findIndex((t) => t.id === thread.id);
|
|
3268
3531
|
if (idx === -1) return old;
|
|
3532
|
+
if (isStaleSummary(thread, list2.data[idx])) return old;
|
|
3269
3533
|
foundInList = true;
|
|
3270
3534
|
const nextData = list2.data.slice();
|
|
3271
3535
|
nextData[idx] = { ...nextData[idx], ...thread };
|
|
@@ -3335,36 +3599,40 @@ var {
|
|
|
3335
3599
|
messageThreadsGetMessageThreadWorkspacesWorkspaceIdMessagethreadsIdResponse: threadResponseSchema
|
|
3336
3600
|
} = ChatZod;
|
|
3337
3601
|
function mapThreadDtoToModel(dto) {
|
|
3602
|
+
const lastUpdatedAt = utcDate(dto.lastUpdatedAt);
|
|
3338
3603
|
return {
|
|
3339
3604
|
id: dto.id,
|
|
3340
3605
|
createdAt: utcDate(dto.createdAt),
|
|
3341
3606
|
createdBy: dto.createdBy ?? "",
|
|
3342
3607
|
createdByUserId: dto.createdByUserId,
|
|
3343
3608
|
isFlowRunning: dto.isFlowRunning,
|
|
3344
|
-
lastUpdatedAt
|
|
3609
|
+
lastUpdatedAt,
|
|
3345
3610
|
lastUpdatedByUserId: dto.lastUpdatedByUserId,
|
|
3346
3611
|
name: dto.name ?? "",
|
|
3347
3612
|
totalMessages: dto.totalMessages,
|
|
3348
3613
|
pinned: dto.favorited,
|
|
3349
|
-
workSpaceId: dto.workSpaceId
|
|
3614
|
+
workSpaceId: dto.workSpaceId,
|
|
3615
|
+
summaryEmittedAt: lastUpdatedAt.getTime()
|
|
3350
3616
|
};
|
|
3351
3617
|
}
|
|
3352
3618
|
function mapThreadsResponseDtoToModel(dto) {
|
|
3353
3619
|
return { data: dto.data.map(mapThreadDtoToModel), total: dto.total };
|
|
3354
3620
|
}
|
|
3355
3621
|
function mapSignalRThreadSummaryToModel(summary) {
|
|
3622
|
+
const lastUpdatedAt = utcDate(summary.lastUpdatedAt);
|
|
3356
3623
|
return {
|
|
3357
3624
|
id: summary.id,
|
|
3358
3625
|
createdAt: utcDate(summary.createdAt),
|
|
3359
3626
|
createdBy: summary.createdBy ?? "",
|
|
3360
3627
|
createdByUserId: summary.createdByUserId,
|
|
3361
3628
|
isFlowRunning: summary.isFlowRunning,
|
|
3362
|
-
lastUpdatedAt
|
|
3629
|
+
lastUpdatedAt,
|
|
3363
3630
|
lastUpdatedByUserId: summary.lastUpdatedByUserId,
|
|
3364
3631
|
name: summary.name ?? "",
|
|
3365
3632
|
totalMessages: summary.totalMessages,
|
|
3366
3633
|
pinned: summary.favorited,
|
|
3367
|
-
workSpaceId: summary.workSpaceId
|
|
3634
|
+
workSpaceId: summary.workSpaceId,
|
|
3635
|
+
summaryEmittedAt: lastUpdatedAt.getTime()
|
|
3368
3636
|
};
|
|
3369
3637
|
}
|
|
3370
3638
|
var threadDetailOptions = ({
|
|
@@ -3434,6 +3702,12 @@ var useThreadIsRunning = (workspaceId, threadId) => {
|
|
|
3434
3702
|
return !!optimistic || !!(detailThread ?? listThread)?.isFlowRunning;
|
|
3435
3703
|
};
|
|
3436
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
|
+
|
|
3437
3711
|
// src/domains/messages/enums.ts
|
|
3438
3712
|
var MessageValueType = /* @__PURE__ */ ((MessageValueType2) => {
|
|
3439
3713
|
MessageValueType2["OUTPUT"] = "Output";
|
|
@@ -3457,6 +3731,15 @@ var messagesMutationsKeys = {
|
|
|
3457
3731
|
};
|
|
3458
3732
|
|
|
3459
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
|
+
}
|
|
3460
3743
|
function useSendMessage() {
|
|
3461
3744
|
const qc = useQueryClient();
|
|
3462
3745
|
const { userId, displayName: userName } = useChatIdentity();
|
|
@@ -3472,10 +3755,10 @@ function useSendMessage() {
|
|
|
3472
3755
|
if (!threadId) throw new Error("Thread ID is required");
|
|
3473
3756
|
if (!workspaceId) throw new Error("Workspace ID is required");
|
|
3474
3757
|
const optimistic = {
|
|
3475
|
-
id: `temp-${
|
|
3758
|
+
id: `temp-${randomUUID()}`,
|
|
3476
3759
|
values: [
|
|
3477
3760
|
{
|
|
3478
|
-
id: `temp-${
|
|
3761
|
+
id: `temp-${randomUUID()}-prompt`,
|
|
3479
3762
|
type: "Input" /* INPUT */,
|
|
3480
3763
|
name: "prompt",
|
|
3481
3764
|
value: contentList,
|
|
@@ -3486,7 +3769,7 @@ function useSendMessage() {
|
|
|
3486
3769
|
},
|
|
3487
3770
|
...files?.length ? [
|
|
3488
3771
|
{
|
|
3489
|
-
id: `temp-${
|
|
3772
|
+
id: `temp-${randomUUID()}-files`,
|
|
3490
3773
|
type: "Input" /* INPUT */,
|
|
3491
3774
|
name: "files",
|
|
3492
3775
|
value: files,
|
|
@@ -3498,7 +3781,7 @@ function useSendMessage() {
|
|
|
3498
3781
|
] : [],
|
|
3499
3782
|
...variables && Object.keys(variables).length ? [
|
|
3500
3783
|
{
|
|
3501
|
-
id: `temp-${
|
|
3784
|
+
id: `temp-${randomUUID()}-vars`,
|
|
3502
3785
|
type: "Input" /* INPUT */,
|
|
3503
3786
|
name: "variables",
|
|
3504
3787
|
value: variables,
|
|
@@ -3540,7 +3823,10 @@ function useSendMessage() {
|
|
|
3540
3823
|
toast.error("There was an error posting your message");
|
|
3541
3824
|
throw err;
|
|
3542
3825
|
}
|
|
3543
|
-
qc.setQueryData(
|
|
3826
|
+
qc.setQueryData(
|
|
3827
|
+
messagesKeys.list(threadId),
|
|
3828
|
+
(old = []) => reconcileWithMessage(old, realMessage)
|
|
3829
|
+
);
|
|
3544
3830
|
qc.setQueryData(
|
|
3545
3831
|
threadsKeys.detail(workspaceId, threadId),
|
|
3546
3832
|
(old) => old ? { ...old, isFlowRunning: true } : old
|
|
@@ -3564,8 +3850,9 @@ function useAddInputToMessage() {
|
|
|
3564
3850
|
const { userId, displayName: userName } = useChatIdentity();
|
|
3565
3851
|
const service = useChatService();
|
|
3566
3852
|
const addInputToMessageMutation = useMutation({
|
|
3567
|
-
|
|
3568
|
-
|
|
3853
|
+
onMutate: async ({ threadId, messageId, name, value, channels }) => {
|
|
3854
|
+
await qc.cancelQueries({ queryKey: messagesKeys.list(threadId) });
|
|
3855
|
+
const previousMessages = qc.getQueryData(messagesKeys.list(threadId)) ?? [];
|
|
3569
3856
|
qc.setQueryData(
|
|
3570
3857
|
messagesKeys.list(threadId),
|
|
3571
3858
|
(old = []) => old.map(
|
|
@@ -3574,7 +3861,7 @@ function useAddInputToMessage() {
|
|
|
3574
3861
|
values: [
|
|
3575
3862
|
...m.values ?? [],
|
|
3576
3863
|
{
|
|
3577
|
-
id: `temp-${
|
|
3864
|
+
id: `temp-${randomUUID()}-add`,
|
|
3578
3865
|
type: "Input" /* INPUT */,
|
|
3579
3866
|
name,
|
|
3580
3867
|
value,
|
|
@@ -3587,7 +3874,10 @@ function useAddInputToMessage() {
|
|
|
3587
3874
|
} : m
|
|
3588
3875
|
)
|
|
3589
3876
|
);
|
|
3590
|
-
|
|
3877
|
+
return { previousMessages };
|
|
3878
|
+
},
|
|
3879
|
+
mutationFn: async ({ threadId, messageId, name, value, channels }) => {
|
|
3880
|
+
if (!threadId) throw new Error("Thread ID is required");
|
|
3591
3881
|
return await service.addInputToMessage({
|
|
3592
3882
|
messageId,
|
|
3593
3883
|
name,
|
|
@@ -3596,20 +3886,18 @@ function useAddInputToMessage() {
|
|
|
3596
3886
|
});
|
|
3597
3887
|
},
|
|
3598
3888
|
onSuccess: (message, { threadId }) => {
|
|
3599
|
-
qc.setQueryData(messagesKeys.list(threadId), (old = []) => {
|
|
3600
|
-
const stable = old.filter((x) => !x.optimistic);
|
|
3601
|
-
const idx = stable.findIndex((x) => x.id === message.id);
|
|
3602
|
-
if (idx === -1) return [...stable, message];
|
|
3603
|
-
const copy = stable.slice();
|
|
3604
|
-
copy[idx] = message;
|
|
3605
|
-
return copy;
|
|
3606
|
-
});
|
|
3607
|
-
},
|
|
3608
|
-
onError: (_e, { threadId }) => {
|
|
3609
3889
|
qc.setQueryData(
|
|
3610
3890
|
messagesKeys.list(threadId),
|
|
3611
|
-
(old = []) => old
|
|
3891
|
+
(old = []) => reconcileWithMessage(old, message, "replace")
|
|
3612
3892
|
);
|
|
3893
|
+
},
|
|
3894
|
+
onError: (_e, { threadId }, context) => {
|
|
3895
|
+
if (context) {
|
|
3896
|
+
qc.setQueryData(
|
|
3897
|
+
messagesKeys.list(threadId),
|
|
3898
|
+
context.previousMessages
|
|
3899
|
+
);
|
|
3900
|
+
}
|
|
3613
3901
|
toast.error("There was an error posting your form input");
|
|
3614
3902
|
},
|
|
3615
3903
|
retry: false
|
|
@@ -18558,17 +18846,29 @@ function CodeBlock({ language, source }) {
|
|
|
18558
18846
|
/* @__PURE__ */ jsx("pre", { ...language ? { "data-language": language } : {}, children: /* @__PURE__ */ jsx("code", { className: codeClass, children: source }) })
|
|
18559
18847
|
] });
|
|
18560
18848
|
}
|
|
18849
|
+
var STREAM_SETTLE_MS = 250;
|
|
18561
18850
|
function HtmlPreview({ source }) {
|
|
18562
18851
|
const [showingPreview, setShowingPreview] = useState(true);
|
|
18563
18852
|
const [copyLabel, setCopyLabel] = useState(
|
|
18564
18853
|
"Copy"
|
|
18565
18854
|
);
|
|
18566
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);
|
|
18567
18859
|
const iframeRef = useRef(null);
|
|
18568
18860
|
const rafIdRef = useRef(null);
|
|
18569
18861
|
const pendingHeightRef = useRef(null);
|
|
18570
18862
|
const copyResetTimerRef = useRef(null);
|
|
18571
|
-
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]);
|
|
18572
18872
|
useEffect(() => {
|
|
18573
18873
|
ensureGlobalListener();
|
|
18574
18874
|
}, []);
|
|
@@ -18583,6 +18883,7 @@ function HtmlPreview({ source }) {
|
|
|
18583
18883
|
pendingHeightRef.current = null;
|
|
18584
18884
|
if (next2 <= 0) return;
|
|
18585
18885
|
setIframeHeight(next2);
|
|
18886
|
+
setMeasured(true);
|
|
18586
18887
|
};
|
|
18587
18888
|
const scheduleHeight = (height) => {
|
|
18588
18889
|
pendingHeightRef.current = height;
|
|
@@ -18674,19 +18975,35 @@ function HtmlPreview({ source }) {
|
|
|
18674
18975
|
)
|
|
18675
18976
|
] })
|
|
18676
18977
|
] }),
|
|
18677
|
-
/* @__PURE__ */
|
|
18678
|
-
"
|
|
18978
|
+
/* @__PURE__ */ jsxs(
|
|
18979
|
+
"div",
|
|
18679
18980
|
{
|
|
18680
|
-
|
|
18681
|
-
className: "ss-code-block__iframe",
|
|
18682
|
-
sandbox: "allow-scripts",
|
|
18683
|
-
loading: "lazy",
|
|
18684
|
-
title: "HTML preview",
|
|
18685
|
-
srcDoc: srcdoc,
|
|
18981
|
+
className: "ss-code-block__preview",
|
|
18686
18982
|
style: {
|
|
18687
18983
|
display: showingPreview ? "block" : "none",
|
|
18688
|
-
...
|
|
18689
|
-
}
|
|
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
|
+
]
|
|
18690
19007
|
}
|
|
18691
19008
|
),
|
|
18692
19009
|
/* @__PURE__ */ jsx(
|
|
@@ -19050,7 +19367,7 @@ function getAvatarColour(name) {
|
|
|
19050
19367
|
const textColor = brightness > 128 ? "#000000" : "#FFFFFF";
|
|
19051
19368
|
return { backgroundColor, textColor };
|
|
19052
19369
|
}
|
|
19053
|
-
var Avatar =
|
|
19370
|
+
var Avatar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
19054
19371
|
"div",
|
|
19055
19372
|
{
|
|
19056
19373
|
ref,
|
|
@@ -19062,7 +19379,7 @@ var Avatar = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
19062
19379
|
}
|
|
19063
19380
|
));
|
|
19064
19381
|
Avatar.displayName = "Avatar";
|
|
19065
|
-
var AvatarImage =
|
|
19382
|
+
var AvatarImage = React9.forwardRef(({ className, alt, src, children: children2, ...props }, _ref) => /* @__PURE__ */ jsx(
|
|
19066
19383
|
MuiAvatar,
|
|
19067
19384
|
{
|
|
19068
19385
|
className: cn("aspect-square h-full w-full", className),
|
|
@@ -19073,7 +19390,7 @@ var AvatarImage = React8.forwardRef(({ className, alt, src, children: children2,
|
|
|
19073
19390
|
}
|
|
19074
19391
|
));
|
|
19075
19392
|
AvatarImage.displayName = "AvatarImage";
|
|
19076
|
-
var AvatarFallback =
|
|
19393
|
+
var AvatarFallback = React9.forwardRef(
|
|
19077
19394
|
({ className, colored = true, ...props }, ref) => {
|
|
19078
19395
|
const childText = String(props.children ?? "");
|
|
19079
19396
|
const colours = colored ? getAvatarColour(childText) : void 0;
|
|
@@ -19125,23 +19442,115 @@ function getUserPhotoUrl(userId) {
|
|
|
19125
19442
|
if (!base2) return void 0;
|
|
19126
19443
|
return `${base2}/users/${userId}/photo`;
|
|
19127
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
|
+
}
|
|
19128
19535
|
var RESET_DELAY = 1e3;
|
|
19129
19536
|
function ChatMessageCopyButton({
|
|
19130
|
-
content
|
|
19537
|
+
content,
|
|
19538
|
+
contentRef
|
|
19131
19539
|
}) {
|
|
19132
19540
|
const [state, setState] = useState("idle" /* IDLE */);
|
|
19133
19541
|
const handleCopy = async () => {
|
|
19134
19542
|
if (!content) return;
|
|
19135
19543
|
const textToCopy = content.filter((item) => !!item.text).map((item) => item.text).join("\n");
|
|
19136
19544
|
if (!textToCopy) return;
|
|
19137
|
-
|
|
19138
|
-
|
|
19545
|
+
const container = contentRef?.current;
|
|
19546
|
+
const ok3 = container ? await copyMessageRich(container, textToCopy) : await copyText(textToCopy);
|
|
19547
|
+
if (ok3) {
|
|
19139
19548
|
setState("success" /* SUCCESS */);
|
|
19140
19549
|
setTimeout(() => {
|
|
19141
19550
|
setState("idle" /* IDLE */);
|
|
19142
19551
|
}, RESET_DELAY);
|
|
19143
|
-
}
|
|
19144
|
-
console.error("Failed to copy
|
|
19552
|
+
} else {
|
|
19553
|
+
console.error("Failed to copy message content");
|
|
19145
19554
|
}
|
|
19146
19555
|
};
|
|
19147
19556
|
const getIcon = () => {
|
|
@@ -19311,6 +19720,25 @@ function isFileSource(s2) {
|
|
|
19311
19720
|
function isLinkSource(s2) {
|
|
19312
19721
|
return (s2.sourceType === "URL" /* URL */ || s2.sourceType === "WebExternal" /* WebExternal */) && !!s2.url;
|
|
19313
19722
|
}
|
|
19723
|
+
function UnverifiedBadge({
|
|
19724
|
+
attribution
|
|
19725
|
+
}) {
|
|
19726
|
+
if (attribution !== "unsupported" /* Unsupported */) return null;
|
|
19727
|
+
return /* @__PURE__ */ jsxs(
|
|
19728
|
+
"span",
|
|
19729
|
+
{
|
|
19730
|
+
title: "This citation couldn't be verified against the source text \u2014 double-check it.",
|
|
19731
|
+
className: "inline-flex items-center gap-0.5 rounded px-1 py-px text-[10px] font-medium text-amber-600 dark:text-amber-400 bg-amber-500/10 flex-shrink-0",
|
|
19732
|
+
children: [
|
|
19733
|
+
/* @__PURE__ */ jsx(ShieldAlert, { className: "h-3 w-3" }),
|
|
19734
|
+
"Unverified"
|
|
19735
|
+
]
|
|
19736
|
+
}
|
|
19737
|
+
);
|
|
19738
|
+
}
|
|
19739
|
+
function nameTitle(source, displayName) {
|
|
19740
|
+
return source.citedText ? `${displayName} \u2014 \u201C${source.citedText}\u201D` : displayName;
|
|
19741
|
+
}
|
|
19314
19742
|
function ChatMessageSources({
|
|
19315
19743
|
sources
|
|
19316
19744
|
}) {
|
|
@@ -19369,13 +19797,14 @@ function ChatMessageSources({
|
|
|
19369
19797
|
"button",
|
|
19370
19798
|
{
|
|
19371
19799
|
type: "button",
|
|
19372
|
-
title: displayName,
|
|
19800
|
+
title: nameTitle(source, displayName),
|
|
19373
19801
|
onClick: () => downloadFileMutation.mutate(source.file),
|
|
19374
19802
|
className: "text-foreground hover:bg-muted/50 rounded px-1 py-0.5 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
|
|
19375
19803
|
disabled: downloadFileMutation.isPending,
|
|
19376
19804
|
children: displayName
|
|
19377
19805
|
}
|
|
19378
|
-
)
|
|
19806
|
+
),
|
|
19807
|
+
/* @__PURE__ */ jsx(UnverifiedBadge, { attribution: source.attribution })
|
|
19379
19808
|
]
|
|
19380
19809
|
},
|
|
19381
19810
|
`${source.file.id}-${source.index}`
|
|
@@ -19396,14 +19825,15 @@ function ChatMessageSources({
|
|
|
19396
19825
|
safeHref ? /* @__PURE__ */ jsx(
|
|
19397
19826
|
"a",
|
|
19398
19827
|
{
|
|
19399
|
-
title: source.url ?? displayName,
|
|
19828
|
+
title: nameTitle(source, source.url ?? displayName),
|
|
19400
19829
|
href: safeHref,
|
|
19401
19830
|
target: "_blank",
|
|
19402
19831
|
rel: "noreferrer",
|
|
19403
19832
|
className: "text-foreground hover:bg-muted/50 rounded px-1 py-0.5 underline underline-offset-2",
|
|
19404
19833
|
children: displayName
|
|
19405
19834
|
}
|
|
19406
|
-
) : /* @__PURE__ */ jsx("span", { className: "text-foreground rounded px-1 py-0.5", children: displayName })
|
|
19835
|
+
) : /* @__PURE__ */ jsx("span", { className: "text-foreground rounded px-1 py-0.5", children: displayName }),
|
|
19836
|
+
/* @__PURE__ */ jsx(UnverifiedBadge, { attribution: source.attribution })
|
|
19407
19837
|
]
|
|
19408
19838
|
},
|
|
19409
19839
|
`url-${source.index}`
|
|
@@ -19429,6 +19859,7 @@ var MessageBubble = (props) => {
|
|
|
19429
19859
|
} = props;
|
|
19430
19860
|
const [responseFormData, setResponseFormData] = useState(userInput);
|
|
19431
19861
|
const [responseFormValid, setResponseFormValid] = useState(false);
|
|
19862
|
+
const contentRef = useRef(null);
|
|
19432
19863
|
const isBotResponse = type === "Output" /* OUTPUT */;
|
|
19433
19864
|
const showForm = userOutput;
|
|
19434
19865
|
useEffect(() => {
|
|
@@ -19466,12 +19897,12 @@ var MessageBubble = (props) => {
|
|
|
19466
19897
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: createdAt ? parseDateTime(createdAt, "Do MMMM YYYY, h:mm a") : "" })
|
|
19467
19898
|
] })
|
|
19468
19899
|
] }),
|
|
19469
|
-
/* @__PURE__ */ jsx(ChatMessageCopyButton, { content })
|
|
19900
|
+
/* @__PURE__ */ jsx(ChatMessageCopyButton, { content, contentRef })
|
|
19470
19901
|
]
|
|
19471
19902
|
}
|
|
19472
19903
|
),
|
|
19473
19904
|
/* @__PURE__ */ jsxs("div", { className: cn(isBotResponse ? "p-4" : "px-4 py-2"), children: [
|
|
19474
|
-
contentIsList && content?.map(
|
|
19905
|
+
/* @__PURE__ */ jsx("div", { ref: contentRef, children: contentIsList && content?.map(
|
|
19475
19906
|
(item, i) => item.text ? /* @__PURE__ */ jsx(
|
|
19476
19907
|
"div",
|
|
19477
19908
|
{
|
|
@@ -19480,7 +19911,7 @@ var MessageBubble = (props) => {
|
|
|
19480
19911
|
},
|
|
19481
19912
|
`content-${i}`
|
|
19482
19913
|
) : item.image ? /* @__PURE__ */ jsx("div", { className: "mb-3 last:mb-0", children: /* @__PURE__ */ jsx(ChatMessageImage, { image: item.image }) }, `image-${i}`) : null
|
|
19483
|
-
),
|
|
19914
|
+
) }),
|
|
19484
19915
|
files.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ss-chat-message__attachments mt-4 space-y-2", children: [
|
|
19485
19916
|
/* @__PURE__ */ jsx("h4", { className: "text-xs font-semibold text-muted-foreground mb-1", children: "Attachments" }),
|
|
19486
19917
|
files.map((file, idx) => {
|
|
@@ -19663,7 +20094,8 @@ var MessageItem = ({
|
|
|
19663
20094
|
groupType = v.type;
|
|
19664
20095
|
const name = v.name.toLowerCase();
|
|
19665
20096
|
switch (name) {
|
|
19666
|
-
case "variables":
|
|
20097
|
+
case "variables":
|
|
20098
|
+
case "userinfo": {
|
|
19667
20099
|
continue;
|
|
19668
20100
|
}
|
|
19669
20101
|
case "status": {
|
|
@@ -19804,6 +20236,10 @@ function MessageList({
|
|
|
19804
20236
|
const messagesEndRef = useRef(null);
|
|
19805
20237
|
const prevMessageCountRef = useRef(0);
|
|
19806
20238
|
const hasInitialScrollRef = useRef(false);
|
|
20239
|
+
const everHadMessagesRef = useRef({
|
|
20240
|
+
threadId: "",
|
|
20241
|
+
had: false
|
|
20242
|
+
});
|
|
19807
20243
|
const isMobile = useIsMobile();
|
|
19808
20244
|
const { data: activeWorkspace } = useWorkspace(workspaceId);
|
|
19809
20245
|
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
@@ -19875,8 +20311,15 @@ function MessageList({
|
|
|
19875
20311
|
ro.observe(content);
|
|
19876
20312
|
return () => ro.disconnect();
|
|
19877
20313
|
}, [isAtBottom, scrollToBottom]);
|
|
20314
|
+
const safeMessages = messages ?? [];
|
|
20315
|
+
if (everHadMessagesRef.current.threadId !== threadId) {
|
|
20316
|
+
everHadMessagesRef.current = { threadId, had: safeMessages.length > 0 };
|
|
20317
|
+
} else if (safeMessages.length > 0) {
|
|
20318
|
+
everHadMessagesRef.current.had = true;
|
|
20319
|
+
}
|
|
20320
|
+
const hadMessagesBefore = everHadMessagesRef.current.had;
|
|
19878
20321
|
const isLoading = isChoosingThread || (threadPending || threadFetching) && !thread || (messagesPending || messagesFetching) && messages === void 0;
|
|
19879
|
-
if (isLoading) {
|
|
20322
|
+
if (isLoading && !hadMessagesBefore) {
|
|
19880
20323
|
return /* @__PURE__ */ jsx(
|
|
19881
20324
|
"div",
|
|
19882
20325
|
{
|
|
@@ -19892,7 +20335,7 @@ function MessageList({
|
|
|
19892
20335
|
}
|
|
19893
20336
|
);
|
|
19894
20337
|
}
|
|
19895
|
-
if (threadError || messagesError) {
|
|
20338
|
+
if ((threadError || messagesError) && !hadMessagesBefore) {
|
|
19896
20339
|
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: [
|
|
19897
20340
|
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: [
|
|
19898
20341
|
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4" }),
|
|
@@ -19904,8 +20347,7 @@ function MessageList({
|
|
|
19904
20347
|
] })
|
|
19905
20348
|
] }) });
|
|
19906
20349
|
}
|
|
19907
|
-
|
|
19908
|
-
if (safeMessages.length === 0) {
|
|
20350
|
+
if (safeMessages.length === 0 && !hadMessagesBefore) {
|
|
19909
20351
|
return /* @__PURE__ */ jsxs("div", { className: "flex overflow-auto flex-shrink-10 flex-col p-8 text-center", children: [
|
|
19910
20352
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-medium mb-2", children: activeWorkspace?.name ?? "No messages yet" }),
|
|
19911
20353
|
activeWorkspace?.firstPrompt && /* @__PURE__ */ jsx("div", { className: "max-w-3xl mx-auto p-4", children: /* @__PURE__ */ jsx(MessageMarkdown, { value: activeWorkspace.firstPrompt }) })
|
|
@@ -20123,6 +20565,7 @@ var computeAvatar = (name, fallback) => {
|
|
|
20123
20565
|
function mapMentionUserDtoToModel(dto) {
|
|
20124
20566
|
return {
|
|
20125
20567
|
id: dto.id,
|
|
20568
|
+
userId: dto.userId,
|
|
20126
20569
|
displayName: dto.displayName ?? "",
|
|
20127
20570
|
initials: getInitials(dto.displayName ?? "")
|
|
20128
20571
|
};
|
|
@@ -20157,9 +20600,6 @@ function mapWorkspaceDtoToModel(dto) {
|
|
|
20157
20600
|
firstPrompt: dto.firstPrompt ?? "",
|
|
20158
20601
|
outputSchema: dto.outputSchema ?? void 0,
|
|
20159
20602
|
inputs: dto.inputs ?? void 0,
|
|
20160
|
-
isPromptAndResponseLoggingEnabled: truthy(
|
|
20161
|
-
dto.isPromptAndResponseLoggingEnabled
|
|
20162
|
-
),
|
|
20163
20603
|
variables,
|
|
20164
20604
|
sandBoxThreadId: dto.sandBoxThreadId ?? void 0,
|
|
20165
20605
|
supportsFiles: truthy(dto.supportsFiles),
|
|
@@ -20168,6 +20608,6 @@ function mapWorkspaceDtoToModel(dto) {
|
|
|
20168
20608
|
}
|
|
20169
20609
|
var mapWorkspacesDtoToModels = (arr) => arr.map(mapWorkspaceDtoToModel);
|
|
20170
20610
|
|
|
20171
|
-
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 };
|
|
20611
|
+
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 };
|
|
20172
20612
|
//# sourceMappingURL=index.js.map
|
|
20173
20613
|
//# sourceMappingURL=index.js.map
|