@smartspace/chat-ui 1.13.1-dev.c6d0f32 → 1.13.1-dev.d2cc725
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 +33 -29
- package/dist/index.js +267 -107
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import MuiButton from '@mui/material/Button';
|
|
2
2
|
import IconButton from '@mui/material/IconButton';
|
|
3
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
|
|
4
|
+
import * as React9 from 'react';
|
|
5
5
|
import { createContext, forwardRef, useImperativeHandle, useRef, useState, useEffect, useMemo, useCallback, createElement, useContext } from 'react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
|
-
import { useQuery, queryOptions, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
7
|
+
import { useQuery, queryOptions, useQueryClient, useMutation, skipToken } from '@tanstack/react-query';
|
|
8
8
|
import { toast } from 'sonner';
|
|
9
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
10
|
import { Editor, rootCtx, defaultValueCtx, editorViewOptionsCtx, editorViewCtx, serializerCtx, SchemaReady, nodeViewCtx, markViewCtx, schemaCtx, prosePluginsCtx, nodesCtx } from '@milkdown/core';
|
|
@@ -127,6 +127,7 @@ var filesKeys = {
|
|
|
127
127
|
var useFileMutations = (scope) => {
|
|
128
128
|
const { workspaceId, threadId } = scope;
|
|
129
129
|
const service = useChatService();
|
|
130
|
+
const queryClient = useQueryClient();
|
|
130
131
|
const [uploadedFiles, setUploadedFiles] = useState([]);
|
|
131
132
|
const [fileProgress, setFileProgress] = useState({});
|
|
132
133
|
const clearUploadState = useCallback(() => {
|
|
@@ -185,11 +186,19 @@ var useFileMutations = (scope) => {
|
|
|
185
186
|
status: uploadedFiles.some((f) => f.name === file.name) ? "done" : "uploading"
|
|
186
187
|
}));
|
|
187
188
|
const getFileBlobUrl = useCallback(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
189
|
+
(id) => queryClient.fetchQuery({
|
|
190
|
+
queryKey: filesKeys.downloadBlob(id),
|
|
191
|
+
queryFn: async () => {
|
|
192
|
+
const blob = await service.downloadFile(id, {
|
|
193
|
+
workspaceId,
|
|
194
|
+
threadId
|
|
195
|
+
});
|
|
196
|
+
return URL.createObjectURL(blob);
|
|
197
|
+
},
|
|
198
|
+
staleTime: Infinity,
|
|
199
|
+
gcTime: Infinity
|
|
200
|
+
}),
|
|
201
|
+
[queryClient, service, workspaceId, threadId]
|
|
193
202
|
);
|
|
194
203
|
return {
|
|
195
204
|
uploadFilesMutation,
|
|
@@ -871,7 +880,7 @@ var ssImageView = $view(ssImageNode, (ctx) => (node2) => {
|
|
|
871
880
|
removeBtn.type = "button";
|
|
872
881
|
removeBtn.className = "ss-attach__remove";
|
|
873
882
|
removeBtn.setAttribute("aria-label", "Remove image");
|
|
874
|
-
removeBtn.
|
|
883
|
+
removeBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>';
|
|
875
884
|
removeBtn.addEventListener("mousedown", (e) => {
|
|
876
885
|
e.preventDefault();
|
|
877
886
|
e.stopPropagation();
|
|
@@ -890,16 +899,19 @@ var ssImageView = $view(ssImageNode, (ctx) => (node2) => {
|
|
|
890
899
|
}
|
|
891
900
|
});
|
|
892
901
|
img.style.background = "rgba(0,0,0,0.04)";
|
|
902
|
+
img.style.visibility = "hidden";
|
|
893
903
|
let hasSetRealSrc = false;
|
|
894
904
|
img.addEventListener("load", () => {
|
|
895
905
|
if (!hasSetRealSrc) return;
|
|
896
906
|
spinner.remove();
|
|
897
907
|
img.style.background = "";
|
|
908
|
+
img.style.visibility = "";
|
|
898
909
|
});
|
|
899
910
|
img.addEventListener("error", () => {
|
|
900
911
|
if (!hasSetRealSrc) return;
|
|
901
912
|
spinner.remove();
|
|
902
913
|
img.style.background = "rgba(255,0,0,0.06)";
|
|
914
|
+
img.style.visibility = "";
|
|
903
915
|
});
|
|
904
916
|
try {
|
|
905
917
|
const anyWin = window;
|
|
@@ -1675,7 +1687,7 @@ var buttonVariants = cva(
|
|
|
1675
1687
|
}
|
|
1676
1688
|
}
|
|
1677
1689
|
);
|
|
1678
|
-
var Button =
|
|
1690
|
+
var Button = React9.forwardRef(
|
|
1679
1691
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
1680
1692
|
const Comp = asChild ? Slot : "button";
|
|
1681
1693
|
return /* @__PURE__ */ jsx(
|
|
@@ -2890,6 +2902,128 @@ var modelIdRendererTester = rankWith(
|
|
|
2890
2902
|
}
|
|
2891
2903
|
);
|
|
2892
2904
|
var ModelIdRendererControl = withJsonFormsControlProps(ModelIdRenderer);
|
|
2905
|
+
var NumberRenderer = ({
|
|
2906
|
+
data,
|
|
2907
|
+
handleChange,
|
|
2908
|
+
path: path2,
|
|
2909
|
+
label,
|
|
2910
|
+
description,
|
|
2911
|
+
errors,
|
|
2912
|
+
schema,
|
|
2913
|
+
uischema,
|
|
2914
|
+
visible,
|
|
2915
|
+
enabled,
|
|
2916
|
+
required
|
|
2917
|
+
}) => {
|
|
2918
|
+
const isInteger = schema?.type === "integer";
|
|
2919
|
+
const handleInputChange = useCallback(
|
|
2920
|
+
(event) => {
|
|
2921
|
+
const raw2 = event.target.value;
|
|
2922
|
+
if (raw2 === "") {
|
|
2923
|
+
handleChange(path2, void 0);
|
|
2924
|
+
return;
|
|
2925
|
+
}
|
|
2926
|
+
const parsed = isInteger ? parseInt(raw2, 10) : parseFloat(raw2);
|
|
2927
|
+
if (Number.isNaN(parsed)) {
|
|
2928
|
+
handleChange(path2, void 0);
|
|
2929
|
+
return;
|
|
2930
|
+
}
|
|
2931
|
+
handleChange(path2, parsed);
|
|
2932
|
+
},
|
|
2933
|
+
[handleChange, path2, isInteger]
|
|
2934
|
+
);
|
|
2935
|
+
if (!visible) return null;
|
|
2936
|
+
const readOnly = uischema?.access === "Read";
|
|
2937
|
+
const isDisabled = !enabled || readOnly;
|
|
2938
|
+
const hasError = !!errors && errors.length > 0;
|
|
2939
|
+
const fieldSchema = schema;
|
|
2940
|
+
const min = fieldSchema?.minimum;
|
|
2941
|
+
const max = fieldSchema?.maximum;
|
|
2942
|
+
const step = isInteger ? 1 : fieldSchema?.multipleOf ?? "any";
|
|
2943
|
+
return /* @__PURE__ */ jsxs(
|
|
2944
|
+
"div",
|
|
2945
|
+
{
|
|
2946
|
+
className: "ss-jsonforms-field ss-jsonforms-number",
|
|
2947
|
+
style: {
|
|
2948
|
+
display: "inline-flex",
|
|
2949
|
+
flexDirection: "row",
|
|
2950
|
+
alignItems: "center",
|
|
2951
|
+
gap: 8,
|
|
2952
|
+
minHeight: "40px"
|
|
2953
|
+
},
|
|
2954
|
+
children: [
|
|
2955
|
+
label && /* @__PURE__ */ jsxs(
|
|
2956
|
+
"label",
|
|
2957
|
+
{
|
|
2958
|
+
htmlFor: `number-${path2}`,
|
|
2959
|
+
style: {
|
|
2960
|
+
color: hasError ? "#ef4444" : "#475569",
|
|
2961
|
+
fontSize: "0.875rem",
|
|
2962
|
+
fontWeight: 500,
|
|
2963
|
+
whiteSpace: "nowrap",
|
|
2964
|
+
lineHeight: "24px"
|
|
2965
|
+
},
|
|
2966
|
+
children: [
|
|
2967
|
+
label,
|
|
2968
|
+
required && /* @__PURE__ */ jsx("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
|
|
2969
|
+
]
|
|
2970
|
+
}
|
|
2971
|
+
),
|
|
2972
|
+
/* @__PURE__ */ jsx(
|
|
2973
|
+
"input",
|
|
2974
|
+
{
|
|
2975
|
+
id: `number-${path2}`,
|
|
2976
|
+
type: "number",
|
|
2977
|
+
value: data ?? "",
|
|
2978
|
+
onChange: handleInputChange,
|
|
2979
|
+
disabled: isDisabled,
|
|
2980
|
+
min,
|
|
2981
|
+
max,
|
|
2982
|
+
step,
|
|
2983
|
+
style: {
|
|
2984
|
+
width: "80px",
|
|
2985
|
+
height: "24px",
|
|
2986
|
+
padding: "0 0.5rem",
|
|
2987
|
+
border: hasError ? "2px solid #ef4444" : "1px solid #d1d5db",
|
|
2988
|
+
borderRadius: "6px",
|
|
2989
|
+
fontSize: "0.875rem",
|
|
2990
|
+
lineHeight: "24px",
|
|
2991
|
+
fontFamily: "inherit",
|
|
2992
|
+
backgroundColor: isDisabled ? "#f9fafb" : "#ffffff",
|
|
2993
|
+
color: isDisabled ? "#9ca3af" : "#111827",
|
|
2994
|
+
outline: "none",
|
|
2995
|
+
boxSizing: "border-box"
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
),
|
|
2999
|
+
hasError && /* @__PURE__ */ jsx(
|
|
3000
|
+
"div",
|
|
3001
|
+
{
|
|
3002
|
+
style: {
|
|
3003
|
+
color: "#ef4444",
|
|
3004
|
+
fontSize: "0.75rem"
|
|
3005
|
+
},
|
|
3006
|
+
children: errors
|
|
3007
|
+
}
|
|
3008
|
+
)
|
|
3009
|
+
]
|
|
3010
|
+
}
|
|
3011
|
+
);
|
|
3012
|
+
};
|
|
3013
|
+
var numberRendererTester = rankWith(
|
|
3014
|
+
40,
|
|
3015
|
+
(uischema, schema) => {
|
|
3016
|
+
if (uischema.type !== "Control") return false;
|
|
3017
|
+
const propertyPath = uischema.scope.replace(
|
|
3018
|
+
"#/properties/",
|
|
3019
|
+
""
|
|
3020
|
+
);
|
|
3021
|
+
const fieldSchema = schema?.properties?.[propertyPath];
|
|
3022
|
+
if (!fieldSchema) return false;
|
|
3023
|
+
return fieldSchema.type === "integer" || fieldSchema.type === "number";
|
|
3024
|
+
}
|
|
3025
|
+
);
|
|
3026
|
+
var NumberRendererControl = withJsonFormsControlProps(NumberRenderer);
|
|
2893
3027
|
var TextareaRenderer = ({
|
|
2894
3028
|
data,
|
|
2895
3029
|
handleChange,
|
|
@@ -3059,6 +3193,7 @@ var renderers = [
|
|
|
3059
3193
|
{ tester: modelIdRendererTester, renderer: ModelIdRendererControl },
|
|
3060
3194
|
{ tester: booleanRendererTester, renderer: BooleanRendererControl },
|
|
3061
3195
|
{ tester: dropdownRendererTester, renderer: DropdownRendererControl },
|
|
3196
|
+
{ tester: numberRendererTester, renderer: NumberRendererControl },
|
|
3062
3197
|
{ tester: textareaRendererTester, renderer: TextareaRendererControl },
|
|
3063
3198
|
...vanillaRenderers,
|
|
3064
3199
|
{ tester: jsonEditorTester, renderer: JsonEditorRendererControl }
|
|
@@ -3112,26 +3247,26 @@ function useChatVariablesFormVm({
|
|
|
3112
3247
|
const { mutate: updateVariableMutation } = useUpdateFlowRunVariable();
|
|
3113
3248
|
const querySettled = !isLoading && (threadVars !== void 0 || isError);
|
|
3114
3249
|
const shouldUseDefaults = isError || threadVars && Object.keys(threadVars).length === 0;
|
|
3115
|
-
const built =
|
|
3250
|
+
const built = React9.useMemo(() => {
|
|
3116
3251
|
return buildSimpleSchemaAndUi(
|
|
3117
3252
|
workspace.variables,
|
|
3118
3253
|
threadVars,
|
|
3119
3254
|
shouldUseDefaults ?? false
|
|
3120
3255
|
);
|
|
3121
3256
|
}, [workspace.variables, threadVars, shouldUseDefaults]);
|
|
3122
|
-
const [data, setData] =
|
|
3123
|
-
|
|
3257
|
+
const [data, setData] = React9.useState(null);
|
|
3258
|
+
React9.useEffect(() => {
|
|
3124
3259
|
if (querySettled) {
|
|
3125
3260
|
setData(built.initialData);
|
|
3126
3261
|
setVariables(built.initialData);
|
|
3127
3262
|
}
|
|
3128
3263
|
}, [querySettled, built.initialData, setVariables]);
|
|
3129
|
-
const ajv =
|
|
3130
|
-
const prevRef =
|
|
3131
|
-
|
|
3264
|
+
const ajv = React9.useMemo(() => createAjv({ useDefaults: false }), []);
|
|
3265
|
+
const prevRef = React9.useRef(null);
|
|
3266
|
+
React9.useEffect(() => {
|
|
3132
3267
|
prevRef.current = data;
|
|
3133
3268
|
}, [data]);
|
|
3134
|
-
const onChange =
|
|
3269
|
+
const onChange = React9.useCallback(
|
|
3135
3270
|
({ data: next2 }) => {
|
|
3136
3271
|
if (prevRef.current && !isDraftThreadId(threadId)) {
|
|
3137
3272
|
const keys2 = Object.keys(workspace.variables || {});
|
|
@@ -3152,7 +3287,7 @@ function useChatVariablesFormVm({
|
|
|
3152
3287
|
},
|
|
3153
3288
|
[workspace.variables, setVariables, updateVariableMutation, threadId]
|
|
3154
3289
|
);
|
|
3155
|
-
const config =
|
|
3290
|
+
const config = React9.useMemo(
|
|
3156
3291
|
() => ({
|
|
3157
3292
|
restrict: true,
|
|
3158
3293
|
trim: false,
|
|
@@ -3221,7 +3356,20 @@ var threadsKeys = {
|
|
|
3221
3356
|
};
|
|
3222
3357
|
|
|
3223
3358
|
// src/domains/threads/cache.ts
|
|
3359
|
+
function isStaleSummary(incoming, existing) {
|
|
3360
|
+
if (!existing) return false;
|
|
3361
|
+
if (typeof existing.summaryEmittedAt !== "number") return false;
|
|
3362
|
+
if (typeof incoming.summaryEmittedAt !== "number") return false;
|
|
3363
|
+
if (incoming.summaryEmittedAt >= existing.summaryEmittedAt) return false;
|
|
3364
|
+
return existing.isFlowRunning === false && incoming.isFlowRunning === true;
|
|
3365
|
+
}
|
|
3224
3366
|
function applyThreadToCache(qc, thread) {
|
|
3367
|
+
const existingDetail = qc.getQueryData(
|
|
3368
|
+
threadsKeys.detail(thread.workSpaceId, thread.id)
|
|
3369
|
+
);
|
|
3370
|
+
if (isStaleSummary(thread, existingDetail)) {
|
|
3371
|
+
return false;
|
|
3372
|
+
}
|
|
3225
3373
|
qc.setQueryData(
|
|
3226
3374
|
threadsKeys.detail(thread.workSpaceId, thread.id),
|
|
3227
3375
|
(old) => ({ ...old ?? thread, ...thread })
|
|
@@ -3242,6 +3390,7 @@ function applyThreadToCache(qc, thread) {
|
|
|
3242
3390
|
if (!page?.data) return page;
|
|
3243
3391
|
const idx2 = page.data.findIndex((t) => t.id === thread.id);
|
|
3244
3392
|
if (idx2 === -1) return page;
|
|
3393
|
+
if (isStaleSummary(thread, page.data[idx2])) return page;
|
|
3245
3394
|
changed = true;
|
|
3246
3395
|
foundInList = true;
|
|
3247
3396
|
const nextData2 = page.data.slice();
|
|
@@ -3254,6 +3403,7 @@ function applyThreadToCache(qc, thread) {
|
|
|
3254
3403
|
if (!list2.data) return old;
|
|
3255
3404
|
const idx = list2.data.findIndex((t) => t.id === thread.id);
|
|
3256
3405
|
if (idx === -1) return old;
|
|
3406
|
+
if (isStaleSummary(thread, list2.data[idx])) return old;
|
|
3257
3407
|
foundInList = true;
|
|
3258
3408
|
const nextData = list2.data.slice();
|
|
3259
3409
|
nextData[idx] = { ...nextData[idx], ...thread };
|
|
@@ -3310,7 +3460,7 @@ function utcDate(value) {
|
|
|
3310
3460
|
}
|
|
3311
3461
|
return new Date(value);
|
|
3312
3462
|
}
|
|
3313
|
-
z.preprocess((val) => {
|
|
3463
|
+
var DateFromApi = z.preprocess((val) => {
|
|
3314
3464
|
if (typeof val === "string" && !hasTimezone(val)) {
|
|
3315
3465
|
return val + "Z";
|
|
3316
3466
|
}
|
|
@@ -3323,36 +3473,40 @@ var {
|
|
|
3323
3473
|
messageThreadsGetMessageThreadWorkspacesWorkspaceIdMessagethreadsIdResponse: threadResponseSchema
|
|
3324
3474
|
} = ChatZod;
|
|
3325
3475
|
function mapThreadDtoToModel(dto) {
|
|
3476
|
+
const lastUpdatedAt = utcDate(dto.lastUpdatedAt);
|
|
3326
3477
|
return {
|
|
3327
3478
|
id: dto.id,
|
|
3328
3479
|
createdAt: utcDate(dto.createdAt),
|
|
3329
3480
|
createdBy: dto.createdBy ?? "",
|
|
3330
3481
|
createdByUserId: dto.createdByUserId,
|
|
3331
3482
|
isFlowRunning: dto.isFlowRunning,
|
|
3332
|
-
lastUpdatedAt
|
|
3483
|
+
lastUpdatedAt,
|
|
3333
3484
|
lastUpdatedByUserId: dto.lastUpdatedByUserId,
|
|
3334
3485
|
name: dto.name ?? "",
|
|
3335
3486
|
totalMessages: dto.totalMessages,
|
|
3336
3487
|
pinned: dto.favorited,
|
|
3337
|
-
workSpaceId: dto.workSpaceId
|
|
3488
|
+
workSpaceId: dto.workSpaceId,
|
|
3489
|
+
summaryEmittedAt: lastUpdatedAt.getTime()
|
|
3338
3490
|
};
|
|
3339
3491
|
}
|
|
3340
3492
|
function mapThreadsResponseDtoToModel(dto) {
|
|
3341
3493
|
return { data: dto.data.map(mapThreadDtoToModel), total: dto.total };
|
|
3342
3494
|
}
|
|
3343
3495
|
function mapSignalRThreadSummaryToModel(summary) {
|
|
3496
|
+
const lastUpdatedAt = utcDate(summary.lastUpdatedAt);
|
|
3344
3497
|
return {
|
|
3345
3498
|
id: summary.id,
|
|
3346
3499
|
createdAt: utcDate(summary.createdAt),
|
|
3347
3500
|
createdBy: summary.createdBy ?? "",
|
|
3348
3501
|
createdByUserId: summary.createdByUserId,
|
|
3349
3502
|
isFlowRunning: summary.isFlowRunning,
|
|
3350
|
-
lastUpdatedAt
|
|
3503
|
+
lastUpdatedAt,
|
|
3351
3504
|
lastUpdatedByUserId: summary.lastUpdatedByUserId,
|
|
3352
3505
|
name: summary.name ?? "",
|
|
3353
3506
|
totalMessages: summary.totalMessages,
|
|
3354
3507
|
pinned: summary.favorited,
|
|
3355
|
-
workSpaceId: summary.workSpaceId
|
|
3508
|
+
workSpaceId: summary.workSpaceId,
|
|
3509
|
+
summaryEmittedAt: lastUpdatedAt.getTime()
|
|
3356
3510
|
};
|
|
3357
3511
|
}
|
|
3358
3512
|
var threadDetailOptions = ({
|
|
@@ -3406,11 +3560,12 @@ var useThread = ({
|
|
|
3406
3560
|
});
|
|
3407
3561
|
};
|
|
3408
3562
|
var useThreadIsRunning = (workspaceId, threadId) => {
|
|
3409
|
-
const
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3563
|
+
const queryClient = useQueryClient();
|
|
3564
|
+
const { data: detailThread } = useQuery({
|
|
3565
|
+
queryKey: threadsKeys.detail(workspaceId ?? "", threadId ?? ""),
|
|
3566
|
+
queryFn: skipToken
|
|
3413
3567
|
});
|
|
3568
|
+
const listThread = workspaceId && threadId ? getThreadPlaceholderFromListCache(queryClient, workspaceId, threadId) : void 0;
|
|
3414
3569
|
const { data: optimistic } = useQuery({
|
|
3415
3570
|
queryKey: threadsKeys.optimisticRunning(threadId ?? ""),
|
|
3416
3571
|
queryFn: () => false,
|
|
@@ -3418,7 +3573,7 @@ var useThreadIsRunning = (workspaceId, threadId) => {
|
|
|
3418
3573
|
staleTime: Infinity,
|
|
3419
3574
|
enabled: !!threadId
|
|
3420
3575
|
});
|
|
3421
|
-
return !!optimistic || !!
|
|
3576
|
+
return !!optimistic || !!(detailThread ?? listThread)?.isFlowRunning;
|
|
3422
3577
|
};
|
|
3423
3578
|
|
|
3424
3579
|
// src/domains/messages/enums.ts
|
|
@@ -3444,6 +3599,15 @@ var messagesMutationsKeys = {
|
|
|
3444
3599
|
};
|
|
3445
3600
|
|
|
3446
3601
|
// src/domains/messages/mutations.ts
|
|
3602
|
+
function reconcileWithMessage(old, incoming, onDuplicate = "keep-existing") {
|
|
3603
|
+
const stable = old.filter((m) => !m.optimistic);
|
|
3604
|
+
const idx = stable.findIndex((m) => m.id === incoming.id);
|
|
3605
|
+
if (idx === -1) return [...stable, incoming];
|
|
3606
|
+
if (onDuplicate === "keep-existing") return stable;
|
|
3607
|
+
const copy = stable.slice();
|
|
3608
|
+
copy[idx] = incoming;
|
|
3609
|
+
return copy;
|
|
3610
|
+
}
|
|
3447
3611
|
function useSendMessage() {
|
|
3448
3612
|
const qc = useQueryClient();
|
|
3449
3613
|
const { userId, displayName: userName } = useChatIdentity();
|
|
@@ -3459,10 +3623,10 @@ function useSendMessage() {
|
|
|
3459
3623
|
if (!threadId) throw new Error("Thread ID is required");
|
|
3460
3624
|
if (!workspaceId) throw new Error("Workspace ID is required");
|
|
3461
3625
|
const optimistic = {
|
|
3462
|
-
id: `temp-${
|
|
3626
|
+
id: `temp-${crypto.randomUUID()}`,
|
|
3463
3627
|
values: [
|
|
3464
3628
|
{
|
|
3465
|
-
id: `temp-${
|
|
3629
|
+
id: `temp-${crypto.randomUUID()}-prompt`,
|
|
3466
3630
|
type: "Input" /* INPUT */,
|
|
3467
3631
|
name: "prompt",
|
|
3468
3632
|
value: contentList,
|
|
@@ -3473,7 +3637,7 @@ function useSendMessage() {
|
|
|
3473
3637
|
},
|
|
3474
3638
|
...files?.length ? [
|
|
3475
3639
|
{
|
|
3476
|
-
id: `temp-${
|
|
3640
|
+
id: `temp-${crypto.randomUUID()}-files`,
|
|
3477
3641
|
type: "Input" /* INPUT */,
|
|
3478
3642
|
name: "files",
|
|
3479
3643
|
value: files,
|
|
@@ -3485,7 +3649,7 @@ function useSendMessage() {
|
|
|
3485
3649
|
] : [],
|
|
3486
3650
|
...variables && Object.keys(variables).length ? [
|
|
3487
3651
|
{
|
|
3488
|
-
id: `temp-${
|
|
3652
|
+
id: `temp-${crypto.randomUUID()}-vars`,
|
|
3489
3653
|
type: "Input" /* INPUT */,
|
|
3490
3654
|
name: "variables",
|
|
3491
3655
|
value: variables,
|
|
@@ -3527,13 +3691,10 @@ function useSendMessage() {
|
|
|
3527
3691
|
toast.error("There was an error posting your message");
|
|
3528
3692
|
throw err;
|
|
3529
3693
|
}
|
|
3530
|
-
qc.setQueryData(
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
);
|
|
3535
|
-
return alreadyPresent ? withoutOptimistic : [...withoutOptimistic, realMessage];
|
|
3536
|
-
});
|
|
3694
|
+
qc.setQueryData(
|
|
3695
|
+
messagesKeys.list(threadId),
|
|
3696
|
+
(old = []) => reconcileWithMessage(old, realMessage)
|
|
3697
|
+
);
|
|
3537
3698
|
qc.setQueryData(
|
|
3538
3699
|
threadsKeys.detail(workspaceId, threadId),
|
|
3539
3700
|
(old) => old ? { ...old, isFlowRunning: true } : old
|
|
@@ -3589,14 +3750,10 @@ function useAddInputToMessage() {
|
|
|
3589
3750
|
});
|
|
3590
3751
|
},
|
|
3591
3752
|
onSuccess: (message, { threadId }) => {
|
|
3592
|
-
qc.setQueryData(
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
const copy = stable.slice();
|
|
3597
|
-
copy[idx] = message;
|
|
3598
|
-
return copy;
|
|
3599
|
-
});
|
|
3753
|
+
qc.setQueryData(
|
|
3754
|
+
messagesKeys.list(threadId),
|
|
3755
|
+
(old = []) => reconcileWithMessage(old, message, "replace")
|
|
3756
|
+
);
|
|
3600
3757
|
},
|
|
3601
3758
|
onError: (_e, { threadId }) => {
|
|
3602
3759
|
qc.setQueryData(
|
|
@@ -3633,7 +3790,10 @@ var workspaceDetailOptions = ({
|
|
|
3633
3790
|
});
|
|
3634
3791
|
function useWorkspace(workspaceId) {
|
|
3635
3792
|
const service = useChatService();
|
|
3636
|
-
return useQuery(
|
|
3793
|
+
return useQuery({
|
|
3794
|
+
...workspaceDetailOptions({ service, workspaceId }),
|
|
3795
|
+
enabled: !!workspaceId
|
|
3796
|
+
});
|
|
3637
3797
|
}
|
|
3638
3798
|
var taggableUsersOptions = ({
|
|
3639
3799
|
service,
|
|
@@ -3821,11 +3981,13 @@ function MessageComposer({
|
|
|
3821
3981
|
workspaceId,
|
|
3822
3982
|
threadId: isDraftThread ? void 0 : threadId
|
|
3823
3983
|
});
|
|
3824
|
-
|
|
3825
|
-
window
|
|
3826
|
-
|
|
3984
|
+
useEffect(() => {
|
|
3985
|
+
if (typeof window === "undefined") return;
|
|
3986
|
+
window.__ssDownloadFile = (id) => getFileBlobUrl(id);
|
|
3987
|
+
return () => {
|
|
3988
|
+
if (window.__ssDownloadFile) delete window.__ssDownloadFile;
|
|
3827
3989
|
};
|
|
3828
|
-
}
|
|
3990
|
+
}, [getFileBlobUrl]);
|
|
3829
3991
|
const onUploadFiles = async (files) => {
|
|
3830
3992
|
const res = await uploadFilesMutation.mutateAsync(files);
|
|
3831
3993
|
return res.map(({ id, name }) => ({ id, name }));
|
|
@@ -4233,43 +4395,14 @@ function MessageComposer({
|
|
|
4233
4395
|
)
|
|
4234
4396
|
] });
|
|
4235
4397
|
}
|
|
4236
|
-
function getPromptSignature(m) {
|
|
4237
|
-
const prompt = m.values?.find(
|
|
4238
|
-
(v) => v.type === "Input" /* INPUT */ && v.name === "prompt"
|
|
4239
|
-
);
|
|
4240
|
-
if (!prompt) return null;
|
|
4241
|
-
try {
|
|
4242
|
-
return JSON.stringify(prompt.value ?? null);
|
|
4243
|
-
} catch {
|
|
4244
|
-
return null;
|
|
4245
|
-
}
|
|
4246
|
-
}
|
|
4247
|
-
function mergeFetchedWithOptimistics(current, fetched) {
|
|
4248
|
-
if (!current?.length) return fetched;
|
|
4249
|
-
const optimistics = current.filter((m) => m.optimistic);
|
|
4250
|
-
if (!optimistics.length) return fetched;
|
|
4251
|
-
const fetchedPromptSigs = new Set(
|
|
4252
|
-
fetched.map((m) => getPromptSignature(m)).filter((s2) => typeof s2 === "string" && s2.length > 0)
|
|
4253
|
-
);
|
|
4254
|
-
const dedupedOptimistics = optimistics.filter((o) => {
|
|
4255
|
-
const sig = getPromptSignature(o);
|
|
4256
|
-
if (!sig) return true;
|
|
4257
|
-
return !fetchedPromptSigs.has(sig);
|
|
4258
|
-
});
|
|
4259
|
-
return [...fetched, ...dedupedOptimistics];
|
|
4260
|
-
}
|
|
4261
4398
|
var messagesListOptions = (service, threadId, opts) => queryOptions({
|
|
4262
4399
|
queryKey: threadId ? messagesKeys.list(threadId) : messagesKeys.lists(),
|
|
4263
4400
|
// NOTE: queryKey intentionally does NOT include opts. This keeps cache updates from
|
|
4264
4401
|
// message mutations (which write to messagesKeys.list(threadId)) working.
|
|
4265
4402
|
// If opts changes (e.g. user clicks "Load full history"), we manually refetch.
|
|
4266
|
-
queryFn: async (
|
|
4403
|
+
queryFn: async () => {
|
|
4267
4404
|
if (!threadId) return [];
|
|
4268
|
-
|
|
4269
|
-
const current = ctx.client.getQueryData(
|
|
4270
|
-
messagesKeys.list(threadId)
|
|
4271
|
-
);
|
|
4272
|
-
return mergeFetchedWithOptimistics(current, fetched);
|
|
4405
|
+
return (await service.fetchMessages(threadId, opts)).reverse();
|
|
4273
4406
|
},
|
|
4274
4407
|
retry: false,
|
|
4275
4408
|
refetchOnWindowFocus: false,
|
|
@@ -4277,15 +4410,13 @@ var messagesListOptions = (service, threadId, opts) => queryOptions({
|
|
|
4277
4410
|
// Avoid re-fetching the entire thread on every small navigation.
|
|
4278
4411
|
staleTime: 3e4
|
|
4279
4412
|
});
|
|
4280
|
-
function useMessages(threadId
|
|
4413
|
+
function useMessages(threadId) {
|
|
4281
4414
|
const service = useChatService();
|
|
4282
4415
|
const isDraft = isDraftThreadId(threadId);
|
|
4283
|
-
const skipFetch = opts?.skipWhenNewThread || !threadId || isDraft;
|
|
4284
|
-
const listOpts = opts?.take != null || opts?.skip != null ? { take: opts.take, skip: opts.skip } : void 0;
|
|
4285
4416
|
return useQuery({
|
|
4286
|
-
...messagesListOptions(service, threadId
|
|
4287
|
-
enabled:
|
|
4288
|
-
initialData:
|
|
4417
|
+
...messagesListOptions(service, threadId),
|
|
4418
|
+
enabled: !!threadId && !isDraft,
|
|
4419
|
+
initialData: !threadId || isDraft ? [] : void 0
|
|
4289
4420
|
});
|
|
4290
4421
|
}
|
|
4291
4422
|
|
|
@@ -18792,7 +18923,8 @@ function SsImage(props) {
|
|
|
18792
18923
|
alt: alt ?? "",
|
|
18793
18924
|
title,
|
|
18794
18925
|
width: finalWidth,
|
|
18795
|
-
height: finalHeight
|
|
18926
|
+
height: finalHeight,
|
|
18927
|
+
style: !resolvedSrc && !errored ? { visibility: "hidden" } : void 0
|
|
18796
18928
|
}
|
|
18797
18929
|
)
|
|
18798
18930
|
]
|
|
@@ -19068,7 +19200,7 @@ function getAvatarColour(name) {
|
|
|
19068
19200
|
const textColor = brightness > 128 ? "#000000" : "#FFFFFF";
|
|
19069
19201
|
return { backgroundColor, textColor };
|
|
19070
19202
|
}
|
|
19071
|
-
var Avatar =
|
|
19203
|
+
var Avatar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
19072
19204
|
"div",
|
|
19073
19205
|
{
|
|
19074
19206
|
ref,
|
|
@@ -19080,7 +19212,7 @@ var Avatar = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
19080
19212
|
}
|
|
19081
19213
|
));
|
|
19082
19214
|
Avatar.displayName = "Avatar";
|
|
19083
|
-
var AvatarImage =
|
|
19215
|
+
var AvatarImage = React9.forwardRef(({ className, alt, src, children: children2, ...props }, _ref) => /* @__PURE__ */ jsx(
|
|
19084
19216
|
MuiAvatar,
|
|
19085
19217
|
{
|
|
19086
19218
|
className: cn("aspect-square h-full w-full", className),
|
|
@@ -19091,7 +19223,7 @@ var AvatarImage = React8.forwardRef(({ className, alt, src, children: children2,
|
|
|
19091
19223
|
}
|
|
19092
19224
|
));
|
|
19093
19225
|
AvatarImage.displayName = "AvatarImage";
|
|
19094
|
-
var AvatarFallback =
|
|
19226
|
+
var AvatarFallback = React9.forwardRef(
|
|
19095
19227
|
({ className, colored = true, ...props }, ref) => {
|
|
19096
19228
|
const childText = String(props.children ?? "");
|
|
19097
19229
|
const colours = colored ? getAvatarColour(childText) : void 0;
|
|
@@ -19118,14 +19250,20 @@ dayjs.extend(relativeTime);
|
|
|
19118
19250
|
dayjs.extend(advancedFormat);
|
|
19119
19251
|
function parseDateTime(date, customFormat) {
|
|
19120
19252
|
const d = dayjs.utc(date).local();
|
|
19121
|
-
return d.
|
|
19253
|
+
if (customFormat === "X") return Math.floor(d.valueOf() / 1e3).toString();
|
|
19254
|
+
if (customFormat === "x") return d.valueOf().toString();
|
|
19255
|
+
return d.format(customFormat ?? "YYYY-MM-DD HH:mm:ss");
|
|
19256
|
+
}
|
|
19257
|
+
function parseDateTimeHuman(date) {
|
|
19258
|
+
return dayjs.utc(date).local().fromNow();
|
|
19122
19259
|
}
|
|
19123
19260
|
|
|
19124
19261
|
// src/shared/utils/userPhoto.ts
|
|
19125
19262
|
function getChatApiBaseUrl() {
|
|
19126
19263
|
try {
|
|
19127
19264
|
const w = window;
|
|
19128
|
-
const
|
|
19265
|
+
const env2 = import.meta.env;
|
|
19266
|
+
const cfg = w?.ssconfig?.Chat_Api_Uri ?? env2?.VITE_CHAT_API_URI;
|
|
19129
19267
|
return typeof cfg === "string" && cfg.trim() ? cfg.trim() : "";
|
|
19130
19268
|
} catch {
|
|
19131
19269
|
return "";
|
|
@@ -19619,7 +19757,19 @@ var MessageItem = ({
|
|
|
19619
19757
|
const t = d.getTime();
|
|
19620
19758
|
return Number.isFinite(t) ? t : 0;
|
|
19621
19759
|
};
|
|
19622
|
-
const
|
|
19760
|
+
const sortedValues = (message.values ?? []).slice().sort((a, b) => safeTime(a.createdAt) - safeTime(b.createdAt));
|
|
19761
|
+
const slotByKey = /* @__PURE__ */ new Map();
|
|
19762
|
+
const values = [];
|
|
19763
|
+
for (const v of sortedValues) {
|
|
19764
|
+
const key = `${v.name}|${v.type}`;
|
|
19765
|
+
const existing = slotByKey.get(key);
|
|
19766
|
+
if (existing !== void 0) {
|
|
19767
|
+
values[existing] = v;
|
|
19768
|
+
} else {
|
|
19769
|
+
slotByKey.set(key, values.length);
|
|
19770
|
+
values.push(v);
|
|
19771
|
+
}
|
|
19772
|
+
}
|
|
19623
19773
|
const bubbles = [];
|
|
19624
19774
|
let groupContent = [];
|
|
19625
19775
|
let groupSources = [];
|
|
@@ -19663,7 +19813,8 @@ var MessageItem = ({
|
|
|
19663
19813
|
groupType = v.type;
|
|
19664
19814
|
const name = v.name.toLowerCase();
|
|
19665
19815
|
switch (name) {
|
|
19666
|
-
case "variables":
|
|
19816
|
+
case "variables":
|
|
19817
|
+
case "userinfo": {
|
|
19667
19818
|
continue;
|
|
19668
19819
|
}
|
|
19669
19820
|
case "status": {
|
|
@@ -19804,6 +19955,10 @@ function MessageList({
|
|
|
19804
19955
|
const messagesEndRef = useRef(null);
|
|
19805
19956
|
const prevMessageCountRef = useRef(0);
|
|
19806
19957
|
const hasInitialScrollRef = useRef(false);
|
|
19958
|
+
const everHadMessagesRef = useRef({
|
|
19959
|
+
threadId: "",
|
|
19960
|
+
had: false
|
|
19961
|
+
});
|
|
19807
19962
|
const isMobile = useIsMobile();
|
|
19808
19963
|
const { data: activeWorkspace } = useWorkspace(workspaceId);
|
|
19809
19964
|
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
@@ -19875,8 +20030,15 @@ function MessageList({
|
|
|
19875
20030
|
ro.observe(content);
|
|
19876
20031
|
return () => ro.disconnect();
|
|
19877
20032
|
}, [isAtBottom, scrollToBottom]);
|
|
20033
|
+
const safeMessages = messages ?? [];
|
|
20034
|
+
if (everHadMessagesRef.current.threadId !== threadId) {
|
|
20035
|
+
everHadMessagesRef.current = { threadId, had: safeMessages.length > 0 };
|
|
20036
|
+
} else if (safeMessages.length > 0) {
|
|
20037
|
+
everHadMessagesRef.current.had = true;
|
|
20038
|
+
}
|
|
20039
|
+
const hadMessagesBefore = everHadMessagesRef.current.had;
|
|
19878
20040
|
const isLoading = isChoosingThread || (threadPending || threadFetching) && !thread || (messagesPending || messagesFetching) && messages === void 0;
|
|
19879
|
-
if (isLoading) {
|
|
20041
|
+
if (isLoading && !hadMessagesBefore) {
|
|
19880
20042
|
return /* @__PURE__ */ jsx(
|
|
19881
20043
|
"div",
|
|
19882
20044
|
{
|
|
@@ -19892,7 +20054,7 @@ function MessageList({
|
|
|
19892
20054
|
}
|
|
19893
20055
|
);
|
|
19894
20056
|
}
|
|
19895
|
-
if (threadError || messagesError) {
|
|
20057
|
+
if ((threadError || messagesError) && !hadMessagesBefore) {
|
|
19896
20058
|
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
20059
|
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
20060
|
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4" }),
|
|
@@ -19904,8 +20066,7 @@ function MessageList({
|
|
|
19904
20066
|
] })
|
|
19905
20067
|
] }) });
|
|
19906
20068
|
}
|
|
19907
|
-
|
|
19908
|
-
if (safeMessages.length === 0) {
|
|
20069
|
+
if (safeMessages.length === 0 && !hadMessagesBefore) {
|
|
19909
20070
|
return /* @__PURE__ */ jsxs("div", { className: "flex overflow-auto flex-shrink-10 flex-col p-8 text-center", children: [
|
|
19910
20071
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-medium mb-2", children: activeWorkspace?.name ?? "No messages yet" }),
|
|
19911
20072
|
activeWorkspace?.firstPrompt && /* @__PURE__ */ jsx("div", { className: "max-w-3xl mx-auto p-4", children: /* @__PURE__ */ jsx(MessageMarkdown, { value: activeWorkspace.firstPrompt }) })
|
|
@@ -20146,26 +20307,25 @@ function mapWorkspaceDtoToModel(dto) {
|
|
|
20146
20307
|
id: dto.id ?? "",
|
|
20147
20308
|
name: dto.name ?? "",
|
|
20148
20309
|
tags: dto.tags ?? [],
|
|
20149
|
-
showSources: dto.showSources
|
|
20150
|
-
dataSpaces: Array.isArray(dto.dataSpaces) ? dto.dataSpaces :
|
|
20310
|
+
showSources: truthy(dto.showSources),
|
|
20311
|
+
dataSpaces: Array.isArray(dto.dataSpaces) ? dto.dataSpaces : [],
|
|
20151
20312
|
createdByUserId: dto.createdByUserId ?? void 0,
|
|
20152
20313
|
createdAt: dto.createdAt != null ? utcDate(dto.createdAt) : void 0,
|
|
20153
20314
|
modifiedByUserId: dto.modifiedByUserId ?? void 0,
|
|
20154
20315
|
modifiedAt: dto.modifiedAt != null ? utcDate(dto.modifiedAt) : void 0,
|
|
20155
20316
|
favorited: truthy(dto.favorited),
|
|
20156
|
-
summary: dto.summary ??
|
|
20157
|
-
firstPrompt: dto.firstPrompt ??
|
|
20317
|
+
summary: dto.summary ?? "",
|
|
20318
|
+
firstPrompt: dto.firstPrompt ?? "",
|
|
20158
20319
|
outputSchema: dto.outputSchema ?? void 0,
|
|
20159
|
-
isPromptAndResponseLoggingEnabled: dto.isPromptAndResponseLoggingEnabled ?? void 0,
|
|
20160
20320
|
inputs: dto.inputs ?? void 0,
|
|
20161
20321
|
variables,
|
|
20162
20322
|
sandBoxThreadId: dto.sandBoxThreadId ?? void 0,
|
|
20163
|
-
supportsFiles: dto.supportsFiles
|
|
20323
|
+
supportsFiles: truthy(dto.supportsFiles),
|
|
20164
20324
|
avatarName: computeAvatar(dto.name ?? "")
|
|
20165
20325
|
};
|
|
20166
20326
|
}
|
|
20167
20327
|
var mapWorkspacesDtoToModels = (arr) => arr.map(mapWorkspaceDtoToModel);
|
|
20168
20328
|
|
|
20169
|
-
export { ChatProvider, ChatVariablesForm, DRAFT_THREAD_PREFIX, MarkdownEditor, MessageComposer, MessageList, MessageListSkeleton, MessageMarkdown, MessageValueType, NEW_THREAD_ID, THREAD_LIST_PAGE_SIZE, applyDeltaToMessage, applyThreadToCache, createDraftThreadId, createThreadId, downloadFileBlobOptions, filesKeys, flowRunsKeys, getModelIcon, getThreadPlaceholderFromListCache, invalidateWorkspaceThreadLists, isDraftThreadId, mapFileInfoDtoToModel, mapMentionUserDtoToModel, mapMessageDtoToModel, mapMessageErrorDtoToModel, mapMessageValueDtoToModel, mapMessagesDtoToModels, mapSignalRThreadSummaryToModel, mapThreadDtoToModel, mapThreadsResponseDtoToModel, mapWorkspaceDtoToModel, mapWorkspacesDtoToModels, markDraftThreadId, messagesKeys, messagesListOptions, messagesMutationsKeys, modelsKeys, setThreadOptimisticRunning, setThreadRunningInLists, taggableUsersOptions, threadDetailOptions, threadsKeys, unmarkDraftThreadId, useAddInputToMessage, useChatContext, useChatIdentity, useChatService, useDownloadFileBlobQuery, useFileMutations, useFlowRunVariables, useMessages, useModels, useSendMessage, useTaggableWorkspaceUsers, useThread, useThreadIsRunning, useUpdateFlowRunVariable, useWorkspace, workspaceDetailOptions, workspaceKeys };
|
|
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 };
|
|
20170
20330
|
//# sourceMappingURL=index.js.map
|
|
20171
20331
|
//# sourceMappingURL=index.js.map
|