@smartspace/chat-ui 1.14.2-main.fb46d29 → 1.14.4-main.0af780f
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.d.ts +22 -5
- package/dist/index.js +419 -189
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
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,
|
|
3
|
+
import { Loader2, Check, X, Paperclip, Square, ArrowBigUp, Minimize2, AlertTriangle, FileImage, FileVideo, FileAudio, FileArchive, FileCode, FileSpreadsheet, Presentation, FileText, ChevronUp, Download, Copy, Globe, ShieldAlert } from 'lucide-react';
|
|
4
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 { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
8
|
import { useQuery, queryOptions, useQueryClient, useMutation, skipToken } from '@tanstack/react-query';
|
|
8
9
|
import { toast } from 'sonner';
|
|
9
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
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';
|
|
@@ -221,6 +221,131 @@ var saveFile = (blob, fileName) => {
|
|
|
221
221
|
a.click();
|
|
222
222
|
};
|
|
223
223
|
|
|
224
|
+
// src/shared/utils/threadId.ts
|
|
225
|
+
var NEW_THREAD_ID = "__new__";
|
|
226
|
+
function createThreadId() {
|
|
227
|
+
const cryptoObj = globalThis?.crypto;
|
|
228
|
+
return typeof cryptoObj?.randomUUID === "function" ? cryptoObj.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
229
|
+
}
|
|
230
|
+
var DRAFT_THREAD_PREFIX = "draft-";
|
|
231
|
+
var DRAFT_THREAD_STORAGE_KEY = "ss:draftThreadIds";
|
|
232
|
+
var draftThreadIds = /* @__PURE__ */ new Set();
|
|
233
|
+
var hydratedFromStorage = false;
|
|
234
|
+
function isBrowserStorageAvailable() {
|
|
235
|
+
try {
|
|
236
|
+
return typeof window !== "undefined" && !!window.sessionStorage;
|
|
237
|
+
} catch {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function hydrateFromStorageOnce() {
|
|
242
|
+
if (hydratedFromStorage) return;
|
|
243
|
+
hydratedFromStorage = true;
|
|
244
|
+
if (!isBrowserStorageAvailable()) return;
|
|
245
|
+
try {
|
|
246
|
+
const raw2 = window.sessionStorage.getItem(DRAFT_THREAD_STORAGE_KEY);
|
|
247
|
+
if (!raw2) return;
|
|
248
|
+
const parsed = JSON.parse(raw2);
|
|
249
|
+
if (!Array.isArray(parsed)) return;
|
|
250
|
+
for (const id of parsed) {
|
|
251
|
+
if (typeof id === "string" && id) draftThreadIds.add(id);
|
|
252
|
+
}
|
|
253
|
+
} catch {
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function persistToStorage() {
|
|
257
|
+
if (!isBrowserStorageAvailable()) return;
|
|
258
|
+
try {
|
|
259
|
+
window.sessionStorage.setItem(
|
|
260
|
+
DRAFT_THREAD_STORAGE_KEY,
|
|
261
|
+
JSON.stringify(Array.from(draftThreadIds))
|
|
262
|
+
);
|
|
263
|
+
} catch {
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function markDraftThreadId(threadId) {
|
|
267
|
+
if (!threadId) return;
|
|
268
|
+
hydrateFromStorageOnce();
|
|
269
|
+
draftThreadIds.add(threadId);
|
|
270
|
+
persistToStorage();
|
|
271
|
+
}
|
|
272
|
+
function unmarkDraftThreadId(threadId) {
|
|
273
|
+
if (!threadId) return;
|
|
274
|
+
hydrateFromStorageOnce();
|
|
275
|
+
draftThreadIds.delete(threadId);
|
|
276
|
+
persistToStorage();
|
|
277
|
+
}
|
|
278
|
+
function isDraftThreadId(threadId) {
|
|
279
|
+
if (!threadId) return false;
|
|
280
|
+
if (threadId.startsWith(DRAFT_THREAD_PREFIX)) return true;
|
|
281
|
+
hydrateFromStorageOnce();
|
|
282
|
+
return draftThreadIds.has(threadId);
|
|
283
|
+
}
|
|
284
|
+
function createDraftThreadId() {
|
|
285
|
+
const cryptoObj = globalThis?.crypto;
|
|
286
|
+
return typeof cryptoObj?.randomUUID === "function" ? cryptoObj.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/domains/flowruns/queryKeys.ts
|
|
290
|
+
var flowRunsKeys = {
|
|
291
|
+
all: ["flowruns"],
|
|
292
|
+
variables: (flowRunId) => [...flowRunsKeys.all, "variables", { flowRunId }],
|
|
293
|
+
mutations: () => [...flowRunsKeys.all, "mutations"],
|
|
294
|
+
updateVariable: (flowRunId, variableName) => [
|
|
295
|
+
...flowRunsKeys.mutations(),
|
|
296
|
+
"updateVariable",
|
|
297
|
+
{ flowRunId, variableName }
|
|
298
|
+
],
|
|
299
|
+
cancel: () => [...flowRunsKeys.mutations(), "cancel"]
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// src/domains/flowruns/mutations.ts
|
|
303
|
+
function useCancelFlowRun() {
|
|
304
|
+
const service = useChatService();
|
|
305
|
+
return useMutation({
|
|
306
|
+
mutationKey: flowRunsKeys.cancel(),
|
|
307
|
+
mutationFn: async (flowRunId) => {
|
|
308
|
+
if (isDraftThreadId(flowRunId)) return;
|
|
309
|
+
await service.cancelFlowRun?.(flowRunId);
|
|
310
|
+
},
|
|
311
|
+
onError: (error) => {
|
|
312
|
+
console.error("Failed to cancel flow run:", error);
|
|
313
|
+
toast.error("Failed to stop the run");
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
function useUpdateFlowRunVariable() {
|
|
318
|
+
const qc = useQueryClient();
|
|
319
|
+
const service = useChatService();
|
|
320
|
+
return useMutation({
|
|
321
|
+
mutationKey: flowRunsKeys.updateVariable("", ""),
|
|
322
|
+
mutationFn: async ({
|
|
323
|
+
flowRunId,
|
|
324
|
+
variableName,
|
|
325
|
+
value
|
|
326
|
+
}) => {
|
|
327
|
+
if (isDraftThreadId(flowRunId)) return;
|
|
328
|
+
await service.updateFlowRunVariable({
|
|
329
|
+
flowRunId,
|
|
330
|
+
name: variableName,
|
|
331
|
+
value
|
|
332
|
+
});
|
|
333
|
+
},
|
|
334
|
+
onSuccess: (_data, variables) => {
|
|
335
|
+
if (variables?.flowRunId) {
|
|
336
|
+
qc.invalidateQueries({
|
|
337
|
+
queryKey: flowRunsKeys.variables(variables.flowRunId)
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
onError: (error) => {
|
|
342
|
+
console.error("Failed to update variable:", error);
|
|
343
|
+
toast.error("Failed to update variable");
|
|
344
|
+
throw error;
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
224
349
|
// ../../node_modules/.pnpm/@milkdown+exception@7.20.0/node_modules/@milkdown/exception/lib/index.js
|
|
225
350
|
var ErrorCode = /* @__PURE__ */ (function(ErrorCode2) {
|
|
226
351
|
ErrorCode2["docTypeError"] = "docTypeError";
|
|
@@ -1827,116 +1952,6 @@ var Button = React9.forwardRef(
|
|
|
1827
1952
|
}
|
|
1828
1953
|
);
|
|
1829
1954
|
Button.displayName = "Button";
|
|
1830
|
-
|
|
1831
|
-
// src/shared/utils/threadId.ts
|
|
1832
|
-
var NEW_THREAD_ID = "__new__";
|
|
1833
|
-
function createThreadId() {
|
|
1834
|
-
const cryptoObj = globalThis?.crypto;
|
|
1835
|
-
return typeof cryptoObj?.randomUUID === "function" ? cryptoObj.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
1836
|
-
}
|
|
1837
|
-
var DRAFT_THREAD_PREFIX = "draft-";
|
|
1838
|
-
var DRAFT_THREAD_STORAGE_KEY = "ss:draftThreadIds";
|
|
1839
|
-
var draftThreadIds = /* @__PURE__ */ new Set();
|
|
1840
|
-
var hydratedFromStorage = false;
|
|
1841
|
-
function isBrowserStorageAvailable() {
|
|
1842
|
-
try {
|
|
1843
|
-
return typeof window !== "undefined" && !!window.sessionStorage;
|
|
1844
|
-
} catch {
|
|
1845
|
-
return false;
|
|
1846
|
-
}
|
|
1847
|
-
}
|
|
1848
|
-
function hydrateFromStorageOnce() {
|
|
1849
|
-
if (hydratedFromStorage) return;
|
|
1850
|
-
hydratedFromStorage = true;
|
|
1851
|
-
if (!isBrowserStorageAvailable()) return;
|
|
1852
|
-
try {
|
|
1853
|
-
const raw2 = window.sessionStorage.getItem(DRAFT_THREAD_STORAGE_KEY);
|
|
1854
|
-
if (!raw2) return;
|
|
1855
|
-
const parsed = JSON.parse(raw2);
|
|
1856
|
-
if (!Array.isArray(parsed)) return;
|
|
1857
|
-
for (const id of parsed) {
|
|
1858
|
-
if (typeof id === "string" && id) draftThreadIds.add(id);
|
|
1859
|
-
}
|
|
1860
|
-
} catch {
|
|
1861
|
-
}
|
|
1862
|
-
}
|
|
1863
|
-
function persistToStorage() {
|
|
1864
|
-
if (!isBrowserStorageAvailable()) return;
|
|
1865
|
-
try {
|
|
1866
|
-
window.sessionStorage.setItem(
|
|
1867
|
-
DRAFT_THREAD_STORAGE_KEY,
|
|
1868
|
-
JSON.stringify(Array.from(draftThreadIds))
|
|
1869
|
-
);
|
|
1870
|
-
} catch {
|
|
1871
|
-
}
|
|
1872
|
-
}
|
|
1873
|
-
function markDraftThreadId(threadId) {
|
|
1874
|
-
if (!threadId) return;
|
|
1875
|
-
hydrateFromStorageOnce();
|
|
1876
|
-
draftThreadIds.add(threadId);
|
|
1877
|
-
persistToStorage();
|
|
1878
|
-
}
|
|
1879
|
-
function unmarkDraftThreadId(threadId) {
|
|
1880
|
-
if (!threadId) return;
|
|
1881
|
-
hydrateFromStorageOnce();
|
|
1882
|
-
draftThreadIds.delete(threadId);
|
|
1883
|
-
persistToStorage();
|
|
1884
|
-
}
|
|
1885
|
-
function isDraftThreadId(threadId) {
|
|
1886
|
-
if (!threadId) return false;
|
|
1887
|
-
if (threadId.startsWith(DRAFT_THREAD_PREFIX)) return true;
|
|
1888
|
-
hydrateFromStorageOnce();
|
|
1889
|
-
return draftThreadIds.has(threadId);
|
|
1890
|
-
}
|
|
1891
|
-
function createDraftThreadId() {
|
|
1892
|
-
const cryptoObj = globalThis?.crypto;
|
|
1893
|
-
return typeof cryptoObj?.randomUUID === "function" ? cryptoObj.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
1894
|
-
}
|
|
1895
|
-
|
|
1896
|
-
// src/domains/flowruns/queryKeys.ts
|
|
1897
|
-
var flowRunsKeys = {
|
|
1898
|
-
all: ["flowruns"],
|
|
1899
|
-
variables: (flowRunId) => [...flowRunsKeys.all, "variables", { flowRunId }],
|
|
1900
|
-
mutations: () => [...flowRunsKeys.all, "mutations"],
|
|
1901
|
-
updateVariable: (flowRunId, variableName) => [
|
|
1902
|
-
...flowRunsKeys.mutations(),
|
|
1903
|
-
"updateVariable",
|
|
1904
|
-
{ flowRunId, variableName }
|
|
1905
|
-
]
|
|
1906
|
-
};
|
|
1907
|
-
|
|
1908
|
-
// src/domains/flowruns/mutations.ts
|
|
1909
|
-
function useUpdateFlowRunVariable() {
|
|
1910
|
-
const qc = useQueryClient();
|
|
1911
|
-
const service = useChatService();
|
|
1912
|
-
return useMutation({
|
|
1913
|
-
mutationKey: flowRunsKeys.updateVariable("", ""),
|
|
1914
|
-
mutationFn: async ({
|
|
1915
|
-
flowRunId,
|
|
1916
|
-
variableName,
|
|
1917
|
-
value
|
|
1918
|
-
}) => {
|
|
1919
|
-
if (isDraftThreadId(flowRunId)) return;
|
|
1920
|
-
await service.updateFlowRunVariable({
|
|
1921
|
-
flowRunId,
|
|
1922
|
-
name: variableName,
|
|
1923
|
-
value
|
|
1924
|
-
});
|
|
1925
|
-
},
|
|
1926
|
-
onSuccess: (_data, variables) => {
|
|
1927
|
-
if (variables?.flowRunId) {
|
|
1928
|
-
qc.invalidateQueries({
|
|
1929
|
-
queryKey: flowRunsKeys.variables(variables.flowRunId)
|
|
1930
|
-
});
|
|
1931
|
-
}
|
|
1932
|
-
},
|
|
1933
|
-
onError: (error) => {
|
|
1934
|
-
console.error("Failed to update variable:", error);
|
|
1935
|
-
toast.error("Failed to update variable");
|
|
1936
|
-
throw error;
|
|
1937
|
-
}
|
|
1938
|
-
});
|
|
1939
|
-
}
|
|
1940
1955
|
function useFlowRunVariables(flowRunId) {
|
|
1941
1956
|
const service = useChatService();
|
|
1942
1957
|
return useQuery({
|
|
@@ -4119,6 +4134,25 @@ function MessageComposer({
|
|
|
4119
4134
|
workspaceId,
|
|
4120
4135
|
threadId: isDraftThread ? void 0 : threadId
|
|
4121
4136
|
});
|
|
4137
|
+
const chatService = useChatService();
|
|
4138
|
+
const {
|
|
4139
|
+
mutate: cancelMutate,
|
|
4140
|
+
isPending: cancelPending,
|
|
4141
|
+
isSuccess: cancelAccepted,
|
|
4142
|
+
isError: cancelErrored,
|
|
4143
|
+
reset: cancelReset
|
|
4144
|
+
} = useCancelFlowRun();
|
|
4145
|
+
const canStop = isSending && !!chatService.cancelFlowRun;
|
|
4146
|
+
const stopping = cancelPending || cancelAccepted;
|
|
4147
|
+
const handleStopRun = () => {
|
|
4148
|
+
if (stopping) return;
|
|
4149
|
+
cancelMutate(threadId);
|
|
4150
|
+
};
|
|
4151
|
+
useEffect(() => {
|
|
4152
|
+
if (!isSending && (cancelAccepted || cancelErrored)) {
|
|
4153
|
+
cancelReset();
|
|
4154
|
+
}
|
|
4155
|
+
}, [isSending, cancelAccepted, cancelErrored, cancelReset]);
|
|
4122
4156
|
useEffect(() => {
|
|
4123
4157
|
if (typeof window === "undefined") return;
|
|
4124
4158
|
window.__ssDownloadFile = (id) => getFileBlobUrl(id);
|
|
@@ -4391,7 +4425,21 @@ function MessageComposer({
|
|
|
4391
4425
|
)
|
|
4392
4426
|
}
|
|
4393
4427
|
),
|
|
4394
|
-
/* @__PURE__ */ jsx(
|
|
4428
|
+
canStop ? /* @__PURE__ */ jsx(
|
|
4429
|
+
IconButton,
|
|
4430
|
+
{
|
|
4431
|
+
onClick: handleStopRun,
|
|
4432
|
+
className: "h-10 w-10 rounded-full self-end",
|
|
4433
|
+
disabled: stopping,
|
|
4434
|
+
"aria-label": stopping ? "Stopping" : "Stop",
|
|
4435
|
+
children: /* @__PURE__ */ jsx(
|
|
4436
|
+
Square,
|
|
4437
|
+
{
|
|
4438
|
+
className: `h-4 w-4 fill-current ${stopping ? "animate-pulse" : ""}`
|
|
4439
|
+
}
|
|
4440
|
+
)
|
|
4441
|
+
}
|
|
4442
|
+
) : /* @__PURE__ */ jsx(
|
|
4395
4443
|
IconButton,
|
|
4396
4444
|
{
|
|
4397
4445
|
onClick: handleSendMessageAndClear,
|
|
@@ -4485,7 +4533,21 @@ function MessageComposer({
|
|
|
4485
4533
|
)
|
|
4486
4534
|
}
|
|
4487
4535
|
),
|
|
4488
|
-
/* @__PURE__ */ jsx(
|
|
4536
|
+
canStop ? /* @__PURE__ */ jsx(
|
|
4537
|
+
IconButton,
|
|
4538
|
+
{
|
|
4539
|
+
onClick: handleStopRun,
|
|
4540
|
+
className: "h-10 w-10 rounded-full",
|
|
4541
|
+
disabled: stopping,
|
|
4542
|
+
"aria-label": stopping ? "Stopping" : "Stop",
|
|
4543
|
+
children: /* @__PURE__ */ jsx(
|
|
4544
|
+
Square,
|
|
4545
|
+
{
|
|
4546
|
+
className: `h-4 w-4 fill-current ${stopping ? "animate-pulse" : ""}`
|
|
4547
|
+
}
|
|
4548
|
+
)
|
|
4549
|
+
}
|
|
4550
|
+
) : /* @__PURE__ */ jsx(
|
|
4489
4551
|
IconButton,
|
|
4490
4552
|
{
|
|
4491
4553
|
onClick: handleSendMessageAndClear,
|
|
@@ -4514,7 +4576,24 @@ function MessageComposer({
|
|
|
4514
4576
|
children: /* @__PURE__ */ jsx(Paperclip, { className: "h-5 w-5", strokeWidth: 2 })
|
|
4515
4577
|
}
|
|
4516
4578
|
) }),
|
|
4517
|
-
/* @__PURE__ */ jsx(
|
|
4579
|
+
canStop ? /* @__PURE__ */ jsx(
|
|
4580
|
+
Button,
|
|
4581
|
+
{
|
|
4582
|
+
onClick: handleStopRun,
|
|
4583
|
+
className: `text-xs h-7 px-4 py-1 ${stopping ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
4584
|
+
disabled: stopping,
|
|
4585
|
+
"aria-label": stopping ? "Stopping" : "Stop",
|
|
4586
|
+
children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
4587
|
+
/* @__PURE__ */ jsx(
|
|
4588
|
+
Square,
|
|
4589
|
+
{
|
|
4590
|
+
className: `h-3 w-3 fill-current ${stopping ? "animate-pulse" : ""}`
|
|
4591
|
+
}
|
|
4592
|
+
),
|
|
4593
|
+
stopping ? "Stopping\u2026" : "Stop"
|
|
4594
|
+
] })
|
|
4595
|
+
}
|
|
4596
|
+
) : /* @__PURE__ */ jsx(
|
|
4518
4597
|
Button,
|
|
4519
4598
|
{
|
|
4520
4599
|
onClick: handleSendMessageAndClear,
|
|
@@ -19773,17 +19852,12 @@ function getSafeUrl(url) {
|
|
|
19773
19852
|
return null;
|
|
19774
19853
|
}
|
|
19775
19854
|
}
|
|
19776
|
-
function
|
|
19777
|
-
|
|
19778
|
-
|
|
19779
|
-
|
|
19780
|
-
|
|
19781
|
-
return parsed.hostname + (parsed.pathname !== "/" ? parsed.pathname : "");
|
|
19782
|
-
} catch {
|
|
19783
|
-
return source.url;
|
|
19784
|
-
}
|
|
19855
|
+
function getHost(url) {
|
|
19856
|
+
try {
|
|
19857
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
19858
|
+
} catch {
|
|
19859
|
+
return url;
|
|
19785
19860
|
}
|
|
19786
|
-
return `Source ${source.index}`;
|
|
19787
19861
|
}
|
|
19788
19862
|
function isFileSource(s2) {
|
|
19789
19863
|
return s2.sourceType === "File" /* File */ && !!s2.file;
|
|
@@ -19791,15 +19865,82 @@ function isFileSource(s2) {
|
|
|
19791
19865
|
function isLinkSource(s2) {
|
|
19792
19866
|
return (s2.sourceType === "URL" /* URL */ || s2.sourceType === "WebExternal" /* WebExternal */) && !!s2.url;
|
|
19793
19867
|
}
|
|
19868
|
+
function UnverifiedBadge({
|
|
19869
|
+
attribution,
|
|
19870
|
+
compact = false
|
|
19871
|
+
}) {
|
|
19872
|
+
if (attribution !== "unsupported" /* Unsupported */) return null;
|
|
19873
|
+
return /* @__PURE__ */ jsxs(
|
|
19874
|
+
"span",
|
|
19875
|
+
{
|
|
19876
|
+
title: "This citation couldn't be verified against the source text \u2014 double-check it.",
|
|
19877
|
+
className: cn(
|
|
19878
|
+
"inline-flex items-center gap-0.5 rounded text-[10px] font-medium text-amber-600 dark:text-amber-400 flex-shrink-0",
|
|
19879
|
+
!compact && "px-1 py-px bg-amber-500/10"
|
|
19880
|
+
),
|
|
19881
|
+
children: [
|
|
19882
|
+
/* @__PURE__ */ jsx(ShieldAlert, { className: "h-3 w-3" }),
|
|
19883
|
+
!compact && "Unverified"
|
|
19884
|
+
]
|
|
19885
|
+
}
|
|
19886
|
+
);
|
|
19887
|
+
}
|
|
19888
|
+
function IndexChip({ index }) {
|
|
19889
|
+
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 });
|
|
19890
|
+
}
|
|
19891
|
+
function SourceFavicon({ host }) {
|
|
19892
|
+
const [failed, setFailed] = useState(false);
|
|
19893
|
+
if (failed) {
|
|
19894
|
+
return /* @__PURE__ */ jsx(Globe, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" });
|
|
19895
|
+
}
|
|
19896
|
+
return /* @__PURE__ */ jsx(
|
|
19897
|
+
"img",
|
|
19898
|
+
{
|
|
19899
|
+
src: `https://www.google.com/s2/favicons?domain=${encodeURIComponent(
|
|
19900
|
+
host
|
|
19901
|
+
)}&sz=64`,
|
|
19902
|
+
alt: "",
|
|
19903
|
+
width: 16,
|
|
19904
|
+
height: 16,
|
|
19905
|
+
loading: "lazy",
|
|
19906
|
+
onError: () => setFailed(true),
|
|
19907
|
+
className: "h-4 w-4 flex-shrink-0 rounded-sm"
|
|
19908
|
+
}
|
|
19909
|
+
);
|
|
19910
|
+
}
|
|
19911
|
+
function CitedQuote({ text: text6 }) {
|
|
19912
|
+
if (!text6) return null;
|
|
19913
|
+
return /* @__PURE__ */ jsxs("p", { className: "m-0 text-xs leading-snug text-muted-foreground", children: [
|
|
19914
|
+
"\u201C",
|
|
19915
|
+
text6,
|
|
19916
|
+
"\u201D"
|
|
19917
|
+
] });
|
|
19918
|
+
}
|
|
19919
|
+
function SectionLabel({ children: children2 }) {
|
|
19920
|
+
return /* @__PURE__ */ jsx("p", { className: "m-0 px-0.5 pb-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: children2 });
|
|
19921
|
+
}
|
|
19922
|
+
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";
|
|
19923
|
+
var expandedCardClasses = "w-full rounded-lg border border-border/60 bg-background p-2.5 flex flex-col gap-1.5";
|
|
19794
19924
|
function ChatMessageSources({
|
|
19795
19925
|
sources
|
|
19796
19926
|
}) {
|
|
19797
19927
|
const { workspaceId, threadId } = useChatContext();
|
|
19798
19928
|
const { downloadFileMutation } = useFileMutations({ workspaceId, threadId });
|
|
19799
19929
|
const [isExpanded, setIsExpanded] = useState(true);
|
|
19930
|
+
const [openIndexes, setOpenIndexes] = useState(
|
|
19931
|
+
/* @__PURE__ */ new Set()
|
|
19932
|
+
);
|
|
19933
|
+
const toggleOpen = (index) => setOpenIndexes((prev) => {
|
|
19934
|
+
const next2 = new Set(prev);
|
|
19935
|
+
if (next2.has(index)) next2.delete(index);
|
|
19936
|
+
else next2.add(index);
|
|
19937
|
+
return next2;
|
|
19938
|
+
});
|
|
19800
19939
|
const displaySources = (sources ?? []).filter(
|
|
19801
19940
|
(s2) => isFileSource(s2) || isLinkSource(s2)
|
|
19802
19941
|
);
|
|
19942
|
+
const urlSources = displaySources.filter((s2) => !isFileSource(s2));
|
|
19943
|
+
const fileSources = displaySources.filter(isFileSource);
|
|
19803
19944
|
if (displaySources.length === 0) return null;
|
|
19804
19945
|
return /* @__PURE__ */ jsxs("div", { className: "mt-4 rounded-lg border border-border bg-muted/30 overflow-hidden", children: [
|
|
19805
19946
|
/* @__PURE__ */ jsxs(
|
|
@@ -19825,72 +19966,148 @@ function ChatMessageSources({
|
|
|
19825
19966
|
]
|
|
19826
19967
|
}
|
|
19827
19968
|
),
|
|
19828
|
-
isExpanded && /* @__PURE__ */
|
|
19829
|
-
"
|
|
19830
|
-
|
|
19831
|
-
className: "
|
|
19832
|
-
|
|
19833
|
-
|
|
19834
|
-
|
|
19835
|
-
if (isFileSource(source)) {
|
|
19836
|
-
const Icon = getFileIcon3(source.file.name);
|
|
19969
|
+
isExpanded && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 p-2.5", children: [
|
|
19970
|
+
urlSources.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
19971
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "URLs" }),
|
|
19972
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: urlSources.map((source) => {
|
|
19973
|
+
const host = getHost(source.url ?? "");
|
|
19974
|
+
const safeHref = source.url ? getSafeUrl(source.url) : null;
|
|
19975
|
+
if (!openIndexes.has(source.index)) {
|
|
19837
19976
|
return /* @__PURE__ */ jsxs(
|
|
19838
|
-
"
|
|
19977
|
+
"button",
|
|
19839
19978
|
{
|
|
19840
|
-
|
|
19841
|
-
|
|
19979
|
+
type: "button",
|
|
19980
|
+
"aria-expanded": false,
|
|
19981
|
+
title: source.url ?? host,
|
|
19982
|
+
onClick: () => toggleOpen(source.index),
|
|
19983
|
+
className: pillClasses,
|
|
19842
19984
|
children: [
|
|
19843
|
-
/* @__PURE__ */
|
|
19844
|
-
|
|
19845
|
-
|
|
19846
|
-
|
|
19847
|
-
|
|
19985
|
+
/* @__PURE__ */ jsx(SourceFavicon, { host }),
|
|
19986
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: host }),
|
|
19987
|
+
/* @__PURE__ */ jsx(
|
|
19988
|
+
UnverifiedBadge,
|
|
19989
|
+
{
|
|
19990
|
+
attribution: source.attribution,
|
|
19991
|
+
compact: true
|
|
19992
|
+
}
|
|
19993
|
+
),
|
|
19994
|
+
/* @__PURE__ */ jsx(IndexChip, { index: source.index })
|
|
19995
|
+
]
|
|
19996
|
+
},
|
|
19997
|
+
`url-${source.index}`
|
|
19998
|
+
);
|
|
19999
|
+
}
|
|
20000
|
+
return /* @__PURE__ */ jsxs(
|
|
20001
|
+
"div",
|
|
20002
|
+
{
|
|
20003
|
+
className: expandedCardClasses,
|
|
20004
|
+
children: [
|
|
20005
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2", children: [
|
|
20006
|
+
/* @__PURE__ */ jsx(SourceFavicon, { host }),
|
|
20007
|
+
safeHref ? /* @__PURE__ */ jsx(
|
|
20008
|
+
"a",
|
|
20009
|
+
{
|
|
20010
|
+
href: safeHref,
|
|
20011
|
+
target: "_blank",
|
|
20012
|
+
rel: "noreferrer",
|
|
20013
|
+
className: "min-w-0 truncate text-sm font-medium text-foreground no-underline hover:underline underline-offset-2",
|
|
20014
|
+
children: host
|
|
20015
|
+
}
|
|
20016
|
+
) : /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-sm font-medium text-foreground", children: host }),
|
|
20017
|
+
/* @__PURE__ */ jsx(UnverifiedBadge, { attribution: source.attribution }),
|
|
20018
|
+
/* @__PURE__ */ jsx(IndexChip, { index: source.index }),
|
|
19848
20019
|
/* @__PURE__ */ jsx(
|
|
19849
20020
|
"button",
|
|
19850
20021
|
{
|
|
19851
20022
|
type: "button",
|
|
19852
|
-
|
|
19853
|
-
|
|
19854
|
-
|
|
19855
|
-
|
|
19856
|
-
children:
|
|
20023
|
+
"aria-expanded": true,
|
|
20024
|
+
"aria-label": "Collapse source",
|
|
20025
|
+
onClick: () => toggleOpen(source.index),
|
|
20026
|
+
className: "ml-auto rounded p-0.5 text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground",
|
|
20027
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-3.5 w-3.5" })
|
|
19857
20028
|
}
|
|
19858
20029
|
)
|
|
20030
|
+
] }),
|
|
20031
|
+
source.url && /* @__PURE__ */ jsx("p", { className: "m-0 truncate text-xs text-muted-foreground/80", children: source.url }),
|
|
20032
|
+
/* @__PURE__ */ jsx(CitedQuote, { text: source.citedText })
|
|
20033
|
+
]
|
|
20034
|
+
},
|
|
20035
|
+
`url-${source.index}`
|
|
20036
|
+
);
|
|
20037
|
+
}) })
|
|
20038
|
+
] }),
|
|
20039
|
+
fileSources.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
20040
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Files" }),
|
|
20041
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: fileSources.map((source) => {
|
|
20042
|
+
const Icon = getFileIcon3(source.file.name);
|
|
20043
|
+
if (!openIndexes.has(source.index)) {
|
|
20044
|
+
return /* @__PURE__ */ jsxs(
|
|
20045
|
+
"button",
|
|
20046
|
+
{
|
|
20047
|
+
type: "button",
|
|
20048
|
+
"aria-expanded": false,
|
|
20049
|
+
title: source.file.name,
|
|
20050
|
+
onClick: () => toggleOpen(source.index),
|
|
20051
|
+
className: pillClasses,
|
|
20052
|
+
children: [
|
|
20053
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" }),
|
|
20054
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: source.file.name }),
|
|
20055
|
+
/* @__PURE__ */ jsx(
|
|
20056
|
+
UnverifiedBadge,
|
|
20057
|
+
{
|
|
20058
|
+
attribution: source.attribution,
|
|
20059
|
+
compact: true
|
|
20060
|
+
}
|
|
20061
|
+
),
|
|
20062
|
+
/* @__PURE__ */ jsx(IndexChip, { index: source.index })
|
|
19859
20063
|
]
|
|
19860
20064
|
},
|
|
19861
20065
|
`${source.file.id}-${source.index}`
|
|
19862
20066
|
);
|
|
19863
20067
|
}
|
|
19864
|
-
const safeHref = source.url ? getSafeUrl(source.url) : null;
|
|
19865
20068
|
return /* @__PURE__ */ jsxs(
|
|
19866
|
-
"
|
|
20069
|
+
"div",
|
|
19867
20070
|
{
|
|
19868
|
-
className:
|
|
19869
|
-
style: { paddingLeft: 0, marginLeft: 0 },
|
|
20071
|
+
className: expandedCardClasses,
|
|
19870
20072
|
children: [
|
|
19871
|
-
/* @__PURE__ */ jsxs("
|
|
19872
|
-
|
|
19873
|
-
" : "
|
|
20073
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2", children: [
|
|
20074
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" }),
|
|
20075
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-sm font-medium text-foreground", children: source.file.name }),
|
|
20076
|
+
/* @__PURE__ */ jsx(UnverifiedBadge, { attribution: source.attribution }),
|
|
20077
|
+
/* @__PURE__ */ jsx(IndexChip, { index: source.index }),
|
|
20078
|
+
/* @__PURE__ */ jsx(
|
|
20079
|
+
"button",
|
|
20080
|
+
{
|
|
20081
|
+
type: "button",
|
|
20082
|
+
"aria-expanded": true,
|
|
20083
|
+
"aria-label": "Collapse source",
|
|
20084
|
+
onClick: () => toggleOpen(source.index),
|
|
20085
|
+
className: "ml-auto rounded p-0.5 text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground",
|
|
20086
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-3.5 w-3.5" })
|
|
20087
|
+
}
|
|
20088
|
+
)
|
|
19874
20089
|
] }),
|
|
19875
|
-
/* @__PURE__ */ jsx(
|
|
19876
|
-
|
|
19877
|
-
"
|
|
20090
|
+
/* @__PURE__ */ jsx(CitedQuote, { text: source.citedText }),
|
|
20091
|
+
/* @__PURE__ */ jsxs(
|
|
20092
|
+
"button",
|
|
19878
20093
|
{
|
|
19879
|
-
|
|
19880
|
-
|
|
19881
|
-
|
|
19882
|
-
|
|
19883
|
-
|
|
19884
|
-
|
|
20094
|
+
type: "button",
|
|
20095
|
+
onClick: () => downloadFileMutation.mutate(source.file),
|
|
20096
|
+
disabled: downloadFileMutation.isPending,
|
|
20097
|
+
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",
|
|
20098
|
+
children: [
|
|
20099
|
+
/* @__PURE__ */ jsx(Download, { className: "h-3 w-3" }),
|
|
20100
|
+
"Download"
|
|
20101
|
+
]
|
|
19885
20102
|
}
|
|
19886
|
-
)
|
|
20103
|
+
)
|
|
19887
20104
|
]
|
|
19888
20105
|
},
|
|
19889
|
-
|
|
20106
|
+
`${source.file.id}-${source.index}`
|
|
19890
20107
|
);
|
|
19891
|
-
})
|
|
19892
|
-
}
|
|
19893
|
-
|
|
20108
|
+
}) })
|
|
20109
|
+
] })
|
|
20110
|
+
] })
|
|
19894
20111
|
] });
|
|
19895
20112
|
}
|
|
19896
20113
|
var MessageBubble = (props) => {
|
|
@@ -20037,7 +20254,14 @@ function pushContent(items, value) {
|
|
|
20037
20254
|
return;
|
|
20038
20255
|
}
|
|
20039
20256
|
if (Array.isArray(value)) {
|
|
20040
|
-
|
|
20257
|
+
const looksLikeContent = value.every(
|
|
20258
|
+
(it) => it != null && typeof it === "object" && ("text" in it || "image" in it)
|
|
20259
|
+
);
|
|
20260
|
+
if (looksLikeContent) {
|
|
20261
|
+
items.push(...value);
|
|
20262
|
+
} else {
|
|
20263
|
+
items.push({ text: "```json\n" + JSON.stringify(value, null, 2) + "\n```" });
|
|
20264
|
+
}
|
|
20041
20265
|
return;
|
|
20042
20266
|
}
|
|
20043
20267
|
if (typeof value === "object") {
|
|
@@ -20112,25 +20336,28 @@ var MessageItem = ({
|
|
|
20112
20336
|
let groupOpen = false;
|
|
20113
20337
|
let keyCounter = 0;
|
|
20114
20338
|
let lastStatusNode = null;
|
|
20339
|
+
const groupHasAnything = () => groupContent.length > 0 || groupFiles.length > 0 || groupSources.length > 0;
|
|
20115
20340
|
const flush = (nextType) => {
|
|
20116
|
-
|
|
20117
|
-
|
|
20118
|
-
|
|
20119
|
-
|
|
20120
|
-
|
|
20121
|
-
|
|
20122
|
-
|
|
20123
|
-
|
|
20124
|
-
|
|
20125
|
-
|
|
20126
|
-
|
|
20127
|
-
|
|
20128
|
-
|
|
20129
|
-
|
|
20130
|
-
|
|
20131
|
-
|
|
20132
|
-
|
|
20133
|
-
|
|
20341
|
+
if (groupHasAnything()) {
|
|
20342
|
+
bubbles.push(
|
|
20343
|
+
/* @__PURE__ */ jsx(
|
|
20344
|
+
MessageBubble,
|
|
20345
|
+
{
|
|
20346
|
+
createdBy: lastCreatedBy,
|
|
20347
|
+
createdByUserId: lastCreatedByUserId,
|
|
20348
|
+
createdAt: lastCreatedAt,
|
|
20349
|
+
type: groupType,
|
|
20350
|
+
content: groupContent,
|
|
20351
|
+
files: groupFiles,
|
|
20352
|
+
sources: groupSources,
|
|
20353
|
+
chatbotName,
|
|
20354
|
+
userOutput: null,
|
|
20355
|
+
userInput: null
|
|
20356
|
+
},
|
|
20357
|
+
`bubble-${message.id ?? "msg"}-${keyCounter++}`
|
|
20358
|
+
)
|
|
20359
|
+
);
|
|
20360
|
+
}
|
|
20134
20361
|
groupContent = [];
|
|
20135
20362
|
groupFiles = [];
|
|
20136
20363
|
groupSources = [];
|
|
@@ -20163,6 +20390,9 @@ var MessageItem = ({
|
|
|
20163
20390
|
case "prompt":
|
|
20164
20391
|
case "response":
|
|
20165
20392
|
case "content": {
|
|
20393
|
+
if (v.value === "") {
|
|
20394
|
+
continue;
|
|
20395
|
+
}
|
|
20166
20396
|
lastStatusNode = null;
|
|
20167
20397
|
if (groupContent.length > 0) flush(v.type);
|
|
20168
20398
|
if (v.value == null) {
|
|
@@ -20217,7 +20447,7 @@ var MessageItem = ({
|
|
|
20217
20447
|
}
|
|
20218
20448
|
case "sources": {
|
|
20219
20449
|
groupSources = coerceSources(v.value);
|
|
20220
|
-
groupOpen = true;
|
|
20450
|
+
if (groupSources.length > 0) groupOpen = true;
|
|
20221
20451
|
break;
|
|
20222
20452
|
}
|
|
20223
20453
|
default: {
|
|
@@ -20231,7 +20461,7 @@ var MessageItem = ({
|
|
|
20231
20461
|
lastCreatedBy = v.createdBy;
|
|
20232
20462
|
lastCreatedByUserId = v.createdByUserId;
|
|
20233
20463
|
}
|
|
20234
|
-
if (groupOpen) {
|
|
20464
|
+
if (groupOpen && groupHasAnything()) {
|
|
20235
20465
|
bubbles.push(
|
|
20236
20466
|
/* @__PURE__ */ jsx(
|
|
20237
20467
|
MessageBubble,
|