@smartspace/chat-ui 1.13.1-dev.c162627 → 1.13.1-dev.dc3bd10

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.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 React8 from 'react';
4
+ import * as React9 from 'react';
5
5
  import { createContext, forwardRef, useImperativeHandle, useRef, useState, useEffect, useMemo, useCallback, createElement, useContext } from 'react';
6
6
  import { createPortal } from 'react-dom';
7
- import { useQuery, queryOptions, useQueryClient, useMutation } from '@tanstack/react-query';
7
+ import { useQuery, queryOptions, useQueryClient, useMutation, skipToken } from '@tanstack/react-query';
8
8
  import { toast } from 'sonner';
9
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
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
- async (id) => {
189
- const blob = await service.downloadFile(id, { workspaceId, threadId });
190
- return URL.createObjectURL(blob);
191
- },
192
- [service, workspaceId, threadId]
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.textContent = "\xD7";
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 = React8.forwardRef(
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 = React8.useMemo(() => {
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] = React8.useState(null);
3123
- React8.useEffect(() => {
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 = React8.useMemo(() => createAjv({ useDefaults: false }), []);
3130
- const prevRef = React8.useRef(null);
3131
- React8.useEffect(() => {
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 = React8.useCallback(
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 = React8.useMemo(
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 };
@@ -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: utcDate(dto.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: utcDate(summary.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 { data: thread } = useThread({
3410
- workspaceId: workspaceId ?? "",
3411
- threadId: threadId ?? "",
3412
- enabled: !!workspaceId && !!threadId
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 || !!thread?.isFlowRunning;
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();
@@ -3527,7 +3691,10 @@ function useSendMessage() {
3527
3691
  toast.error("There was an error posting your message");
3528
3692
  throw err;
3529
3693
  }
3530
- qc.setQueryData(messagesKeys.list(threadId), [realMessage]);
3694
+ qc.setQueryData(
3695
+ messagesKeys.list(threadId),
3696
+ (old = []) => reconcileWithMessage(old, realMessage)
3697
+ );
3531
3698
  qc.setQueryData(
3532
3699
  threadsKeys.detail(workspaceId, threadId),
3533
3700
  (old) => old ? { ...old, isFlowRunning: true } : old
@@ -3583,14 +3750,10 @@ function useAddInputToMessage() {
3583
3750
  });
3584
3751
  },
3585
3752
  onSuccess: (message, { threadId }) => {
3586
- qc.setQueryData(messagesKeys.list(threadId), (old = []) => {
3587
- const stable = old.filter((x) => !x.optimistic);
3588
- const idx = stable.findIndex((x) => x.id === message.id);
3589
- if (idx === -1) return [...stable, message];
3590
- const copy = stable.slice();
3591
- copy[idx] = message;
3592
- return copy;
3593
- });
3753
+ qc.setQueryData(
3754
+ messagesKeys.list(threadId),
3755
+ (old = []) => reconcileWithMessage(old, message, "replace")
3756
+ );
3594
3757
  },
3595
3758
  onError: (_e, { threadId }) => {
3596
3759
  qc.setQueryData(
@@ -18760,7 +18923,8 @@ function SsImage(props) {
18760
18923
  alt: alt ?? "",
18761
18924
  title,
18762
18925
  width: finalWidth,
18763
- height: finalHeight
18926
+ height: finalHeight,
18927
+ style: !resolvedSrc && !errored ? { visibility: "hidden" } : void 0
18764
18928
  }
18765
18929
  )
18766
18930
  ]
@@ -19036,7 +19200,7 @@ function getAvatarColour(name) {
19036
19200
  const textColor = brightness > 128 ? "#000000" : "#FFFFFF";
19037
19201
  return { backgroundColor, textColor };
19038
19202
  }
19039
- var Avatar = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
19203
+ var Avatar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
19040
19204
  "div",
19041
19205
  {
19042
19206
  ref,
@@ -19048,7 +19212,7 @@ var Avatar = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
19048
19212
  }
19049
19213
  ));
19050
19214
  Avatar.displayName = "Avatar";
19051
- var AvatarImage = React8.forwardRef(({ className, alt, src, children: children2, ...props }, _ref) => /* @__PURE__ */ jsx(
19215
+ var AvatarImage = React9.forwardRef(({ className, alt, src, children: children2, ...props }, _ref) => /* @__PURE__ */ jsx(
19052
19216
  MuiAvatar,
19053
19217
  {
19054
19218
  className: cn("aspect-square h-full w-full", className),
@@ -19059,7 +19223,7 @@ var AvatarImage = React8.forwardRef(({ className, alt, src, children: children2,
19059
19223
  }
19060
19224
  ));
19061
19225
  AvatarImage.displayName = "AvatarImage";
19062
- var AvatarFallback = React8.forwardRef(
19226
+ var AvatarFallback = React9.forwardRef(
19063
19227
  ({ className, colored = true, ...props }, ref) => {
19064
19228
  const childText = String(props.children ?? "");
19065
19229
  const colours = colored ? getAvatarColour(childText) : void 0;
@@ -19649,7 +19813,8 @@ var MessageItem = ({
19649
19813
  groupType = v.type;
19650
19814
  const name = v.name.toLowerCase();
19651
19815
  switch (name) {
19652
- case "variables": {
19816
+ case "variables":
19817
+ case "userinfo": {
19653
19818
  continue;
19654
19819
  }
19655
19820
  case "status": {
@@ -19790,6 +19955,10 @@ function MessageList({
19790
19955
  const messagesEndRef = useRef(null);
19791
19956
  const prevMessageCountRef = useRef(0);
19792
19957
  const hasInitialScrollRef = useRef(false);
19958
+ const everHadMessagesRef = useRef({
19959
+ threadId: "",
19960
+ had: false
19961
+ });
19793
19962
  const isMobile = useIsMobile();
19794
19963
  const { data: activeWorkspace } = useWorkspace(workspaceId);
19795
19964
  const [isAtBottom, setIsAtBottom] = useState(true);
@@ -19861,8 +20030,15 @@ function MessageList({
19861
20030
  ro.observe(content);
19862
20031
  return () => ro.disconnect();
19863
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;
19864
20040
  const isLoading = isChoosingThread || (threadPending || threadFetching) && !thread || (messagesPending || messagesFetching) && messages === void 0;
19865
- if (isLoading) {
20041
+ if (isLoading && !hadMessagesBefore) {
19866
20042
  return /* @__PURE__ */ jsx(
19867
20043
  "div",
19868
20044
  {
@@ -19878,7 +20054,7 @@ function MessageList({
19878
20054
  }
19879
20055
  );
19880
20056
  }
19881
- if (threadError || messagesError) {
20057
+ if ((threadError || messagesError) && !hadMessagesBefore) {
19882
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: [
19883
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: [
19884
20060
  /* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4" }),
@@ -19890,8 +20066,7 @@ function MessageList({
19890
20066
  ] })
19891
20067
  ] }) });
19892
20068
  }
19893
- const safeMessages = messages ?? [];
19894
- if (safeMessages.length === 0) {
20069
+ if (safeMessages.length === 0 && !hadMessagesBefore) {
19895
20070
  return /* @__PURE__ */ jsxs("div", { className: "flex overflow-auto flex-shrink-10 flex-col p-8 text-center", children: [
19896
20071
  /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium mb-2", children: activeWorkspace?.name ?? "No messages yet" }),
19897
20072
  activeWorkspace?.firstPrompt && /* @__PURE__ */ jsx("div", { className: "max-w-3xl mx-auto p-4", children: /* @__PURE__ */ jsx(MessageMarkdown, { value: activeWorkspace.firstPrompt }) })