@smartspace/chat-ui 1.14.0-main.ff8a2ab → 1.14.2-main.19dc263
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +81 -3
- package/dist/index.js +379 -45
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ 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 = [];
|
|
@@ -3576,6 +3702,12 @@ var useThreadIsRunning = (workspaceId, threadId) => {
|
|
|
3576
3702
|
return !!optimistic || !!(detailThread ?? listThread)?.isFlowRunning;
|
|
3577
3703
|
};
|
|
3578
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
|
+
|
|
3579
3711
|
// src/domains/messages/enums.ts
|
|
3580
3712
|
var MessageValueType = /* @__PURE__ */ ((MessageValueType2) => {
|
|
3581
3713
|
MessageValueType2["OUTPUT"] = "Output";
|
|
@@ -3623,10 +3755,10 @@ function useSendMessage() {
|
|
|
3623
3755
|
if (!threadId) throw new Error("Thread ID is required");
|
|
3624
3756
|
if (!workspaceId) throw new Error("Workspace ID is required");
|
|
3625
3757
|
const optimistic = {
|
|
3626
|
-
id: `temp-${
|
|
3758
|
+
id: `temp-${randomUUID()}`,
|
|
3627
3759
|
values: [
|
|
3628
3760
|
{
|
|
3629
|
-
id: `temp-${
|
|
3761
|
+
id: `temp-${randomUUID()}-prompt`,
|
|
3630
3762
|
type: "Input" /* INPUT */,
|
|
3631
3763
|
name: "prompt",
|
|
3632
3764
|
value: contentList,
|
|
@@ -3637,7 +3769,7 @@ function useSendMessage() {
|
|
|
3637
3769
|
},
|
|
3638
3770
|
...files?.length ? [
|
|
3639
3771
|
{
|
|
3640
|
-
id: `temp-${
|
|
3772
|
+
id: `temp-${randomUUID()}-files`,
|
|
3641
3773
|
type: "Input" /* INPUT */,
|
|
3642
3774
|
name: "files",
|
|
3643
3775
|
value: files,
|
|
@@ -3649,7 +3781,7 @@ function useSendMessage() {
|
|
|
3649
3781
|
] : [],
|
|
3650
3782
|
...variables && Object.keys(variables).length ? [
|
|
3651
3783
|
{
|
|
3652
|
-
id: `temp-${
|
|
3784
|
+
id: `temp-${randomUUID()}-vars`,
|
|
3653
3785
|
type: "Input" /* INPUT */,
|
|
3654
3786
|
name: "variables",
|
|
3655
3787
|
value: variables,
|
|
@@ -3718,8 +3850,9 @@ function useAddInputToMessage() {
|
|
|
3718
3850
|
const { userId, displayName: userName } = useChatIdentity();
|
|
3719
3851
|
const service = useChatService();
|
|
3720
3852
|
const addInputToMessageMutation = useMutation({
|
|
3721
|
-
|
|
3722
|
-
|
|
3853
|
+
onMutate: async ({ threadId, messageId, name, value, channels }) => {
|
|
3854
|
+
await qc.cancelQueries({ queryKey: messagesKeys.list(threadId) });
|
|
3855
|
+
const previousMessages = qc.getQueryData(messagesKeys.list(threadId)) ?? [];
|
|
3723
3856
|
qc.setQueryData(
|
|
3724
3857
|
messagesKeys.list(threadId),
|
|
3725
3858
|
(old = []) => old.map(
|
|
@@ -3728,7 +3861,7 @@ function useAddInputToMessage() {
|
|
|
3728
3861
|
values: [
|
|
3729
3862
|
...m.values ?? [],
|
|
3730
3863
|
{
|
|
3731
|
-
id: `temp-${
|
|
3864
|
+
id: `temp-${randomUUID()}-add`,
|
|
3732
3865
|
type: "Input" /* INPUT */,
|
|
3733
3866
|
name,
|
|
3734
3867
|
value,
|
|
@@ -3741,7 +3874,10 @@ function useAddInputToMessage() {
|
|
|
3741
3874
|
} : m
|
|
3742
3875
|
)
|
|
3743
3876
|
);
|
|
3744
|
-
|
|
3877
|
+
return { previousMessages };
|
|
3878
|
+
},
|
|
3879
|
+
mutationFn: async ({ threadId, messageId, name, value, channels }) => {
|
|
3880
|
+
if (!threadId) throw new Error("Thread ID is required");
|
|
3745
3881
|
return await service.addInputToMessage({
|
|
3746
3882
|
messageId,
|
|
3747
3883
|
name,
|
|
@@ -3755,11 +3891,13 @@ function useAddInputToMessage() {
|
|
|
3755
3891
|
(old = []) => reconcileWithMessage(old, message, "replace")
|
|
3756
3892
|
);
|
|
3757
3893
|
},
|
|
3758
|
-
onError: (_e, { threadId }) => {
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3894
|
+
onError: (_e, { threadId }, context) => {
|
|
3895
|
+
if (context) {
|
|
3896
|
+
qc.setQueryData(
|
|
3897
|
+
messagesKeys.list(threadId),
|
|
3898
|
+
context.previousMessages
|
|
3899
|
+
);
|
|
3900
|
+
}
|
|
3763
3901
|
toast.error("There was an error posting your form input");
|
|
3764
3902
|
},
|
|
3765
3903
|
retry: false
|
|
@@ -18708,17 +18846,29 @@ function CodeBlock({ language, source }) {
|
|
|
18708
18846
|
/* @__PURE__ */ jsx("pre", { ...language ? { "data-language": language } : {}, children: /* @__PURE__ */ jsx("code", { className: codeClass, children: source }) })
|
|
18709
18847
|
] });
|
|
18710
18848
|
}
|
|
18849
|
+
var STREAM_SETTLE_MS = 250;
|
|
18711
18850
|
function HtmlPreview({ source }) {
|
|
18712
18851
|
const [showingPreview, setShowingPreview] = useState(true);
|
|
18713
18852
|
const [copyLabel, setCopyLabel] = useState(
|
|
18714
18853
|
"Copy"
|
|
18715
18854
|
);
|
|
18716
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);
|
|
18717
18859
|
const iframeRef = useRef(null);
|
|
18718
18860
|
const rafIdRef = useRef(null);
|
|
18719
18861
|
const pendingHeightRef = useRef(null);
|
|
18720
18862
|
const copyResetTimerRef = useRef(null);
|
|
18721
|
-
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]);
|
|
18722
18872
|
useEffect(() => {
|
|
18723
18873
|
ensureGlobalListener();
|
|
18724
18874
|
}, []);
|
|
@@ -18733,6 +18883,7 @@ function HtmlPreview({ source }) {
|
|
|
18733
18883
|
pendingHeightRef.current = null;
|
|
18734
18884
|
if (next2 <= 0) return;
|
|
18735
18885
|
setIframeHeight(next2);
|
|
18886
|
+
setMeasured(true);
|
|
18736
18887
|
};
|
|
18737
18888
|
const scheduleHeight = (height) => {
|
|
18738
18889
|
pendingHeightRef.current = height;
|
|
@@ -18824,19 +18975,35 @@ function HtmlPreview({ source }) {
|
|
|
18824
18975
|
)
|
|
18825
18976
|
] })
|
|
18826
18977
|
] }),
|
|
18827
|
-
/* @__PURE__ */
|
|
18828
|
-
"
|
|
18978
|
+
/* @__PURE__ */ jsxs(
|
|
18979
|
+
"div",
|
|
18829
18980
|
{
|
|
18830
|
-
|
|
18831
|
-
className: "ss-code-block__iframe",
|
|
18832
|
-
sandbox: "allow-scripts",
|
|
18833
|
-
loading: "lazy",
|
|
18834
|
-
title: "HTML preview",
|
|
18835
|
-
srcDoc: srcdoc,
|
|
18981
|
+
className: "ss-code-block__preview",
|
|
18836
18982
|
style: {
|
|
18837
18983
|
display: showingPreview ? "block" : "none",
|
|
18838
|
-
...
|
|
18839
|
-
}
|
|
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
|
+
]
|
|
18840
19007
|
}
|
|
18841
19008
|
),
|
|
18842
19009
|
/* @__PURE__ */ jsx(
|
|
@@ -19072,13 +19239,83 @@ function getBackgroundGradientClasses({
|
|
|
19072
19239
|
}
|
|
19073
19240
|
|
|
19074
19241
|
// src/domains/messages/errors.ts
|
|
19075
|
-
var
|
|
19076
|
-
|
|
19077
|
-
|
|
19078
|
-
|
|
19079
|
-
|
|
19080
|
-
|
|
19242
|
+
var GENERIC_ERROR_TEXT = "\u26A0\uFE0F **Error**\n\nAn unexpected error occurred. Please try again.";
|
|
19243
|
+
var ERROR_CODE_TEXT = {
|
|
19244
|
+
"llm.rate_limit": "\u26A0\uFE0F **The model is receiving too many requests**\n\nI'm being rate limited right now. Please wait a moment and try again.",
|
|
19245
|
+
"llm.timeout": "\u26A0\uFE0F **The model took too long to respond**\n\nPlease try again. If this keeps happening, try a shorter question.",
|
|
19246
|
+
"llm.transient_connection": "\u26A0\uFE0F **The connection to the model was interrupted**\n\nThis is usually temporary. Please try again.",
|
|
19247
|
+
"llm.server_error": "\u26A0\uFE0F **The model provider had a problem**\n\nPlease try again in a moment.",
|
|
19248
|
+
"llm.auth": "\u26A0\uFE0F **The model connection isn't authorised**\n\nAn administrator needs to check the model configuration.",
|
|
19249
|
+
"llm.not_found": "\u26A0\uFE0F **The model or deployment could not be found**\n\nAn administrator needs to check the model configuration.",
|
|
19250
|
+
"llm.invalid_request": "\u26A0\uFE0F **The request was rejected by the model provider**\n\nPlease try rephrasing your message.",
|
|
19251
|
+
"llm.context_window": "\u26A0\uFE0F **This conversation is too long for the model**\n\nPlease start a new thread, or ask a shorter question.",
|
|
19252
|
+
"llm.content_policy": "\u26A0\uFE0F **The response was blocked by a content filter**\n\nPlease rephrase your request.",
|
|
19253
|
+
"llm.schema_validation": "\u26A0\uFE0F **The model returned an invalid response**\n\nPlease try again.",
|
|
19254
|
+
"llm.unknown": GENERIC_ERROR_TEXT
|
|
19255
|
+
};
|
|
19256
|
+
var STATUS_CODE_TEXT = {
|
|
19257
|
+
408: ERROR_CODE_TEXT["llm.timeout"],
|
|
19258
|
+
429: ERROR_CODE_TEXT["llm.rate_limit"],
|
|
19259
|
+
401: ERROR_CODE_TEXT["llm.auth"],
|
|
19260
|
+
403: ERROR_CODE_TEXT["llm.auth"],
|
|
19261
|
+
404: ERROR_CODE_TEXT["llm.not_found"],
|
|
19262
|
+
500: ERROR_CODE_TEXT["llm.server_error"],
|
|
19263
|
+
502: ERROR_CODE_TEXT["llm.server_error"],
|
|
19264
|
+
503: ERROR_CODE_TEXT["llm.transient_connection"],
|
|
19265
|
+
504: ERROR_CODE_TEXT["llm.timeout"]
|
|
19266
|
+
};
|
|
19267
|
+
var getMessageErrorText = (error) => {
|
|
19268
|
+
if (typeof error === "number") {
|
|
19269
|
+
return STATUS_CODE_TEXT[error] ?? GENERIC_ERROR_TEXT;
|
|
19270
|
+
}
|
|
19271
|
+
if (error.errorCode && ERROR_CODE_TEXT[error.errorCode]) {
|
|
19272
|
+
return ERROR_CODE_TEXT[error.errorCode];
|
|
19273
|
+
}
|
|
19274
|
+
return STATUS_CODE_TEXT[error.code] ?? GENERIC_ERROR_TEXT;
|
|
19275
|
+
};
|
|
19276
|
+
|
|
19277
|
+
// src/domains/messages/statuses.ts
|
|
19278
|
+
var asRecord = (value) => {
|
|
19279
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
19280
|
+
return value;
|
|
19281
|
+
}
|
|
19282
|
+
if (typeof value === "string" && value.trimStart().startsWith("{")) {
|
|
19283
|
+
try {
|
|
19284
|
+
const parsed = JSON.parse(value);
|
|
19285
|
+
return asRecord(parsed);
|
|
19286
|
+
} catch {
|
|
19287
|
+
return null;
|
|
19288
|
+
}
|
|
19081
19289
|
}
|
|
19290
|
+
return null;
|
|
19291
|
+
};
|
|
19292
|
+
var asNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
19293
|
+
var parseRetryStatus = (value) => {
|
|
19294
|
+
const record = asRecord(value);
|
|
19295
|
+
if (!record || record["type"] !== "retry") return null;
|
|
19296
|
+
const attempt = asNumber(record["attempt"]);
|
|
19297
|
+
const maxAttempts = asNumber(record["maxAttempts"]) ?? asNumber(record["max_attempts"]);
|
|
19298
|
+
if (attempt === void 0 || maxAttempts === void 0) return null;
|
|
19299
|
+
const delaySeconds = asNumber(record["delaySeconds"]) ?? asNumber(record["delay_seconds"]);
|
|
19300
|
+
const rawErrorCode = record["errorCode"] ?? record["error_code"];
|
|
19301
|
+
return {
|
|
19302
|
+
type: "retry",
|
|
19303
|
+
attempt,
|
|
19304
|
+
maxAttempts,
|
|
19305
|
+
delaySeconds,
|
|
19306
|
+
errorCode: typeof rawErrorCode === "string" ? rawErrorCode : void 0
|
|
19307
|
+
};
|
|
19308
|
+
};
|
|
19309
|
+
var RETRY_REASON_TEXT = {
|
|
19310
|
+
"llm.rate_limit": "the model is busy",
|
|
19311
|
+
"llm.timeout": "the model took too long",
|
|
19312
|
+
"llm.transient_connection": "the connection dropped",
|
|
19313
|
+
"llm.server_error": "the model provider had a problem"
|
|
19314
|
+
};
|
|
19315
|
+
var getRetryStatusText = (status) => {
|
|
19316
|
+
const reason = status.errorCode ? RETRY_REASON_TEXT[status.errorCode] : void 0;
|
|
19317
|
+
const waiting = status.delaySeconds && status.delaySeconds >= 1 ? ` (waiting ~${Math.round(status.delaySeconds)}s)` : "";
|
|
19318
|
+
return `${reason ? `Hit a snag \u2014 ${reason}. ` : "Hit a snag. "}Retrying, attempt ${status.attempt + 1} of ${status.maxAttempts}${waiting}\u2026`;
|
|
19082
19319
|
};
|
|
19083
19320
|
|
|
19084
19321
|
// src/theme/public-config.ts
|
|
@@ -19275,23 +19512,115 @@ function getUserPhotoUrl(userId) {
|
|
|
19275
19512
|
if (!base2) return void 0;
|
|
19276
19513
|
return `${base2}/users/${userId}/photo`;
|
|
19277
19514
|
}
|
|
19515
|
+
|
|
19516
|
+
// src/messages/smartCopy.ts
|
|
19517
|
+
async function copyMessageRich(container, markdown) {
|
|
19518
|
+
try {
|
|
19519
|
+
const canRichWrite = typeof ClipboardItem !== "undefined" && !!navigator.clipboard?.write;
|
|
19520
|
+
if (!canRichWrite) return copyText(markdown);
|
|
19521
|
+
const { html: html4, images } = await buildHtmlPayload(container);
|
|
19522
|
+
const htmlWithMarker = `${html4}${encodeMarkdownMarker(markdown)}`;
|
|
19523
|
+
const parts = {
|
|
19524
|
+
"text/html": new Blob([htmlWithMarker], { type: "text/html" }),
|
|
19525
|
+
"text/plain": new Blob([markdown], { type: "text/plain" })
|
|
19526
|
+
};
|
|
19527
|
+
if (images.length === 1) {
|
|
19528
|
+
const pngBlob = await dataUrlToBlob(images[0].dataUrl);
|
|
19529
|
+
if (pngBlob) parts["image/png"] = pngBlob;
|
|
19530
|
+
}
|
|
19531
|
+
const withCustom = {
|
|
19532
|
+
...parts,
|
|
19533
|
+
[SS_MARKDOWN_CLIPBOARD_TYPE]: new Blob([markdown], {
|
|
19534
|
+
type: SS_MARKDOWN_CLIPBOARD_TYPE
|
|
19535
|
+
})
|
|
19536
|
+
};
|
|
19537
|
+
if (await tryWrite(withCustom)) return true;
|
|
19538
|
+
if (await tryWrite(parts)) return true;
|
|
19539
|
+
return copyText(markdown);
|
|
19540
|
+
} catch {
|
|
19541
|
+
return copyText(markdown);
|
|
19542
|
+
}
|
|
19543
|
+
}
|
|
19544
|
+
async function tryWrite(parts) {
|
|
19545
|
+
try {
|
|
19546
|
+
await navigator.clipboard.write([new ClipboardItem(parts)]);
|
|
19547
|
+
return true;
|
|
19548
|
+
} catch {
|
|
19549
|
+
return false;
|
|
19550
|
+
}
|
|
19551
|
+
}
|
|
19552
|
+
async function buildHtmlPayload(container) {
|
|
19553
|
+
const liveBlocks = Array.from(
|
|
19554
|
+
container.querySelectorAll(".ss-code-block--previewable")
|
|
19555
|
+
);
|
|
19556
|
+
const snapshots = await Promise.all(
|
|
19557
|
+
liveBlocks.map((block) => {
|
|
19558
|
+
const iframe = block.querySelector("iframe");
|
|
19559
|
+
return iframe ? snapshotIframe(iframe) : Promise.resolve([]);
|
|
19560
|
+
})
|
|
19561
|
+
);
|
|
19562
|
+
const clone = container.cloneNode(true);
|
|
19563
|
+
const cloneBlocks = Array.from(
|
|
19564
|
+
clone.querySelectorAll(".ss-code-block--previewable")
|
|
19565
|
+
);
|
|
19566
|
+
const allImages = [];
|
|
19567
|
+
cloneBlocks.forEach((block, i) => {
|
|
19568
|
+
const images = snapshots[i] ?? [];
|
|
19569
|
+
if (images.length > 0) {
|
|
19570
|
+
allImages.push(...images);
|
|
19571
|
+
const frag = block.ownerDocument.createElement("div");
|
|
19572
|
+
for (const img of images) {
|
|
19573
|
+
const el = block.ownerDocument.createElement("img");
|
|
19574
|
+
el.src = img.dataUrl;
|
|
19575
|
+
el.setAttribute("width", String(img.cssWidth));
|
|
19576
|
+
el.setAttribute("height", String(img.cssHeight));
|
|
19577
|
+
el.style.maxWidth = "100%";
|
|
19578
|
+
frag.appendChild(el);
|
|
19579
|
+
}
|
|
19580
|
+
block.replaceWith(frag);
|
|
19581
|
+
} else {
|
|
19582
|
+
const source = block.querySelector("code")?.textContent ?? "";
|
|
19583
|
+
const div = block.ownerDocument.createElement("div");
|
|
19584
|
+
div.innerHTML = stripScripts(source);
|
|
19585
|
+
block.replaceWith(div);
|
|
19586
|
+
}
|
|
19587
|
+
});
|
|
19588
|
+
clone.querySelectorAll(
|
|
19589
|
+
"iframe, button, .ss-code-block__header, .ss-code-block__copy, .ss-code-block__toggle"
|
|
19590
|
+
).forEach((el) => el.remove());
|
|
19591
|
+
const html4 = `<meta charset="utf-8">${clone.innerHTML}`;
|
|
19592
|
+
return { html: html4, images: allImages };
|
|
19593
|
+
}
|
|
19594
|
+
function stripScripts(html4) {
|
|
19595
|
+
return html4.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
19596
|
+
}
|
|
19597
|
+
async function dataUrlToBlob(dataUrl) {
|
|
19598
|
+
try {
|
|
19599
|
+
const res = await fetch(dataUrl);
|
|
19600
|
+
return await res.blob();
|
|
19601
|
+
} catch {
|
|
19602
|
+
return null;
|
|
19603
|
+
}
|
|
19604
|
+
}
|
|
19278
19605
|
var RESET_DELAY = 1e3;
|
|
19279
19606
|
function ChatMessageCopyButton({
|
|
19280
|
-
content
|
|
19607
|
+
content,
|
|
19608
|
+
contentRef
|
|
19281
19609
|
}) {
|
|
19282
19610
|
const [state, setState] = useState("idle" /* IDLE */);
|
|
19283
19611
|
const handleCopy = async () => {
|
|
19284
19612
|
if (!content) return;
|
|
19285
19613
|
const textToCopy = content.filter((item) => !!item.text).map((item) => item.text).join("\n");
|
|
19286
19614
|
if (!textToCopy) return;
|
|
19287
|
-
|
|
19288
|
-
|
|
19615
|
+
const container = contentRef?.current;
|
|
19616
|
+
const ok3 = container ? await copyMessageRich(container, textToCopy) : await copyText(textToCopy);
|
|
19617
|
+
if (ok3) {
|
|
19289
19618
|
setState("success" /* SUCCESS */);
|
|
19290
19619
|
setTimeout(() => {
|
|
19291
19620
|
setState("idle" /* IDLE */);
|
|
19292
19621
|
}, RESET_DELAY);
|
|
19293
|
-
}
|
|
19294
|
-
console.error("Failed to copy
|
|
19622
|
+
} else {
|
|
19623
|
+
console.error("Failed to copy message content");
|
|
19295
19624
|
}
|
|
19296
19625
|
};
|
|
19297
19626
|
const getIcon = () => {
|
|
@@ -19579,6 +19908,7 @@ var MessageBubble = (props) => {
|
|
|
19579
19908
|
} = props;
|
|
19580
19909
|
const [responseFormData, setResponseFormData] = useState(userInput);
|
|
19581
19910
|
const [responseFormValid, setResponseFormValid] = useState(false);
|
|
19911
|
+
const contentRef = useRef(null);
|
|
19582
19912
|
const isBotResponse = type === "Output" /* OUTPUT */;
|
|
19583
19913
|
const showForm = userOutput;
|
|
19584
19914
|
useEffect(() => {
|
|
@@ -19616,12 +19946,12 @@ var MessageBubble = (props) => {
|
|
|
19616
19946
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: createdAt ? parseDateTime(createdAt, "Do MMMM YYYY, h:mm a") : "" })
|
|
19617
19947
|
] })
|
|
19618
19948
|
] }),
|
|
19619
|
-
/* @__PURE__ */ jsx(ChatMessageCopyButton, { content })
|
|
19949
|
+
/* @__PURE__ */ jsx(ChatMessageCopyButton, { content, contentRef })
|
|
19620
19950
|
]
|
|
19621
19951
|
}
|
|
19622
19952
|
),
|
|
19623
19953
|
/* @__PURE__ */ jsxs("div", { className: cn(isBotResponse ? "p-4" : "px-4 py-2"), children: [
|
|
19624
|
-
contentIsList && content?.map(
|
|
19954
|
+
/* @__PURE__ */ jsx("div", { ref: contentRef, children: contentIsList && content?.map(
|
|
19625
19955
|
(item, i) => item.text ? /* @__PURE__ */ jsx(
|
|
19626
19956
|
"div",
|
|
19627
19957
|
{
|
|
@@ -19630,7 +19960,7 @@ var MessageBubble = (props) => {
|
|
|
19630
19960
|
},
|
|
19631
19961
|
`content-${i}`
|
|
19632
19962
|
) : item.image ? /* @__PURE__ */ jsx("div", { className: "mb-3 last:mb-0", children: /* @__PURE__ */ jsx(ChatMessageImage, { image: item.image }) }, `image-${i}`) : null
|
|
19633
|
-
),
|
|
19963
|
+
) }),
|
|
19634
19964
|
files.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ss-chat-message__attachments mt-4 space-y-2", children: [
|
|
19635
19965
|
/* @__PURE__ */ jsx("h4", { className: "text-xs font-semibold text-muted-foreground mb-1", children: "Attachments" }),
|
|
19636
19966
|
files.map((file, idx) => {
|
|
@@ -19819,10 +20149,11 @@ var MessageItem = ({
|
|
|
19819
20149
|
}
|
|
19820
20150
|
case "status": {
|
|
19821
20151
|
if (groupOpen) flush(v.type);
|
|
20152
|
+
const retryStatus = parseRetryStatus(v.value);
|
|
19822
20153
|
lastStatusNode = /* @__PURE__ */ jsx(
|
|
19823
20154
|
MessageStatus,
|
|
19824
20155
|
{
|
|
19825
|
-
text: String(v.value ?? "")
|
|
20156
|
+
text: retryStatus ? getRetryStatusText(retryStatus) : String(v.value ?? "")
|
|
19826
20157
|
},
|
|
19827
20158
|
`status-${message.id ?? "msg"}-${keyCounter++}`
|
|
19828
20159
|
);
|
|
@@ -19930,14 +20261,14 @@ var MessageItem = ({
|
|
|
19930
20261
|
createdBy: chatbotName,
|
|
19931
20262
|
createdAt: message.createdAt,
|
|
19932
20263
|
type: "Output" /* OUTPUT */,
|
|
19933
|
-
content: [{ text: getMessageErrorText(error
|
|
20264
|
+
content: [{ text: getMessageErrorText(error) }],
|
|
19934
20265
|
files: [],
|
|
19935
20266
|
sources: [],
|
|
19936
20267
|
chatbotName,
|
|
19937
20268
|
userOutput: null,
|
|
19938
20269
|
userInput: null
|
|
19939
20270
|
},
|
|
19940
|
-
`error-${message.id ?? "msg"}-${error.code}`
|
|
20271
|
+
`error-${message.id ?? "msg"}-${error.errorCode ?? error.code}`
|
|
19941
20272
|
)
|
|
19942
20273
|
);
|
|
19943
20274
|
}
|
|
@@ -20219,8 +20550,10 @@ function mapMessageValueDtoToModel(dto) {
|
|
|
20219
20550
|
};
|
|
20220
20551
|
}
|
|
20221
20552
|
function mapMessageErrorDtoToModel(dto) {
|
|
20553
|
+
const { error_code, ...rest } = dto;
|
|
20222
20554
|
return {
|
|
20223
|
-
...
|
|
20555
|
+
...rest,
|
|
20556
|
+
errorCode: dto.errorCode ?? error_code ?? void 0,
|
|
20224
20557
|
data: dto.data
|
|
20225
20558
|
};
|
|
20226
20559
|
}
|
|
@@ -20284,6 +20617,7 @@ var computeAvatar = (name, fallback) => {
|
|
|
20284
20617
|
function mapMentionUserDtoToModel(dto) {
|
|
20285
20618
|
return {
|
|
20286
20619
|
id: dto.id,
|
|
20620
|
+
userId: dto.userId,
|
|
20287
20621
|
displayName: dto.displayName ?? "",
|
|
20288
20622
|
initials: getInitials(dto.displayName ?? "")
|
|
20289
20623
|
};
|
|
@@ -20326,6 +20660,6 @@ function mapWorkspaceDtoToModel(dto) {
|
|
|
20326
20660
|
}
|
|
20327
20661
|
var mapWorkspacesDtoToModels = (arr) => arr.map(mapWorkspaceDtoToModel);
|
|
20328
20662
|
|
|
20329
|
-
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 };
|
|
20663
|
+
export { ChatProvider, ChatVariablesForm, DRAFT_THREAD_PREFIX, DateFromApi, MarkdownEditor, MessageComposer, MessageList, MessageListSkeleton, MessageMarkdown, MessageValueType, NEW_THREAD_ID, THREAD_LIST_PAGE_SIZE, applyDeltaToMessage, applyThreadToCache, createDraftThreadId, createThreadId, downloadFileBlobOptions, filesKeys, flowRunsKeys, getMessageErrorText, getModelIcon, getRetryStatusText, getThreadPlaceholderFromListCache, getUserPhotoUrl, invalidateWorkspaceThreadLists, isDraftThreadId, mapFileInfoDtoToModel, mapMentionUserDtoToModel, mapMessageDtoToModel, mapMessageErrorDtoToModel, mapMessageValueDtoToModel, mapMessagesDtoToModels, mapSignalRThreadSummaryToModel, mapThreadDtoToModel, mapThreadsResponseDtoToModel, mapWorkspaceDtoToModel, mapWorkspacesDtoToModels, markDraftThreadId, messagesKeys, messagesListOptions, messagesMutationsKeys, modelsKeys, parseDateTime, parseDateTimeHuman, parseRetryStatus, randomUUID, setThreadOptimisticRunning, setThreadRunningInLists, taggableUsersOptions, threadDetailOptions, threadsKeys, unmarkDraftThreadId, useAddInputToMessage, useChatContext, useChatIdentity, useChatService, useDownloadFileBlobQuery, useFileMutations, useFlowRunVariables, useMessages, useModels, useSendMessage, useTaggableWorkspaceUsers, useThread, useThreadIsRunning, useUpdateFlowRunVariable, useWorkspace, utcDate, workspaceDetailOptions, workspaceKeys };
|
|
20330
20664
|
//# sourceMappingURL=index.js.map
|
|
20331
20665
|
//# sourceMappingURL=index.js.map
|