@smartspace/chat-ui 1.13.1-dev.29e6ec0 → 1.13.1-dev.8387ebd

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
@@ -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;
@@ -3310,7 +3322,7 @@ function utcDate(value) {
3310
3322
  }
3311
3323
  return new Date(value);
3312
3324
  }
3313
- z.preprocess((val) => {
3325
+ var DateFromApi = z.preprocess((val) => {
3314
3326
  if (typeof val === "string" && !hasTimezone(val)) {
3315
3327
  return val + "Z";
3316
3328
  }
@@ -3459,10 +3471,10 @@ function useSendMessage() {
3459
3471
  if (!threadId) throw new Error("Thread ID is required");
3460
3472
  if (!workspaceId) throw new Error("Workspace ID is required");
3461
3473
  const optimistic = {
3462
- id: `temp-${Date.now()}`,
3474
+ id: `temp-${crypto.randomUUID()}`,
3463
3475
  values: [
3464
3476
  {
3465
- id: `temp-${Date.now()}-prompt`,
3477
+ id: `temp-${crypto.randomUUID()}-prompt`,
3466
3478
  type: "Input" /* INPUT */,
3467
3479
  name: "prompt",
3468
3480
  value: contentList,
@@ -3473,7 +3485,7 @@ function useSendMessage() {
3473
3485
  },
3474
3486
  ...files?.length ? [
3475
3487
  {
3476
- id: `temp-${Date.now()}-files`,
3488
+ id: `temp-${crypto.randomUUID()}-files`,
3477
3489
  type: "Input" /* INPUT */,
3478
3490
  name: "files",
3479
3491
  value: files,
@@ -3485,7 +3497,7 @@ function useSendMessage() {
3485
3497
  ] : [],
3486
3498
  ...variables && Object.keys(variables).length ? [
3487
3499
  {
3488
- id: `temp-${Date.now()}-vars`,
3500
+ id: `temp-${crypto.randomUUID()}-vars`,
3489
3501
  type: "Input" /* INPUT */,
3490
3502
  name: "variables",
3491
3503
  value: variables,
@@ -3527,13 +3539,7 @@ function useSendMessage() {
3527
3539
  toast.error("There was an error posting your message");
3528
3540
  throw err;
3529
3541
  }
3530
- qc.setQueryData(messagesKeys.list(threadId), (old = []) => {
3531
- const withoutOptimistic = old.filter((m) => !m.optimistic);
3532
- const alreadyPresent = withoutOptimistic.some(
3533
- (m) => m.id === realMessage.id
3534
- );
3535
- return alreadyPresent ? withoutOptimistic : [...withoutOptimistic, realMessage];
3536
- });
3542
+ qc.setQueryData(messagesKeys.list(threadId), [realMessage]);
3537
3543
  qc.setQueryData(
3538
3544
  threadsKeys.detail(workspaceId, threadId),
3539
3545
  (old) => old ? { ...old, isFlowRunning: true } : old
@@ -3633,7 +3639,10 @@ var workspaceDetailOptions = ({
3633
3639
  });
3634
3640
  function useWorkspace(workspaceId) {
3635
3641
  const service = useChatService();
3636
- return useQuery(workspaceDetailOptions({ service, workspaceId }));
3642
+ return useQuery({
3643
+ ...workspaceDetailOptions({ service, workspaceId }),
3644
+ enabled: !!workspaceId
3645
+ });
3637
3646
  }
3638
3647
  var taggableUsersOptions = ({
3639
3648
  service,
@@ -3821,11 +3830,13 @@ function MessageComposer({
3821
3830
  workspaceId,
3822
3831
  threadId: isDraftThread ? void 0 : threadId
3823
3832
  });
3824
- if (typeof window !== "undefined") {
3825
- window.__ssDownloadFile = async (id) => {
3826
- return await getFileBlobUrl(id);
3833
+ useEffect(() => {
3834
+ if (typeof window === "undefined") return;
3835
+ window.__ssDownloadFile = (id) => getFileBlobUrl(id);
3836
+ return () => {
3837
+ if (window.__ssDownloadFile) delete window.__ssDownloadFile;
3827
3838
  };
3828
- }
3839
+ }, [getFileBlobUrl]);
3829
3840
  const onUploadFiles = async (files) => {
3830
3841
  const res = await uploadFilesMutation.mutateAsync(files);
3831
3842
  return res.map(({ id, name }) => ({ id, name }));
@@ -4233,43 +4244,14 @@ function MessageComposer({
4233
4244
  )
4234
4245
  ] });
4235
4246
  }
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
4247
  var messagesListOptions = (service, threadId, opts) => queryOptions({
4262
4248
  queryKey: threadId ? messagesKeys.list(threadId) : messagesKeys.lists(),
4263
4249
  // NOTE: queryKey intentionally does NOT include opts. This keeps cache updates from
4264
4250
  // message mutations (which write to messagesKeys.list(threadId)) working.
4265
4251
  // If opts changes (e.g. user clicks "Load full history"), we manually refetch.
4266
- queryFn: async (ctx) => {
4252
+ queryFn: async () => {
4267
4253
  if (!threadId) return [];
4268
- const fetched = (await service.fetchMessages(threadId, opts)).reverse();
4269
- const current = ctx.client.getQueryData(
4270
- messagesKeys.list(threadId)
4271
- );
4272
- return mergeFetchedWithOptimistics(current, fetched);
4254
+ return (await service.fetchMessages(threadId, opts)).reverse();
4273
4255
  },
4274
4256
  retry: false,
4275
4257
  refetchOnWindowFocus: false,
@@ -4277,15 +4259,13 @@ var messagesListOptions = (service, threadId, opts) => queryOptions({
4277
4259
  // Avoid re-fetching the entire thread on every small navigation.
4278
4260
  staleTime: 3e4
4279
4261
  });
4280
- function useMessages(threadId, opts) {
4262
+ function useMessages(threadId) {
4281
4263
  const service = useChatService();
4282
4264
  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
4265
  return useQuery({
4286
- ...messagesListOptions(service, threadId, listOpts),
4287
- enabled: !opts?.skipWhenNewThread && !!threadId && !isDraft,
4288
- initialData: skipFetch ? [] : void 0
4266
+ ...messagesListOptions(service, threadId),
4267
+ enabled: !!threadId && !isDraft,
4268
+ initialData: !threadId || isDraft ? [] : void 0
4289
4269
  });
4290
4270
  }
4291
4271
 
@@ -18792,7 +18772,8 @@ function SsImage(props) {
18792
18772
  alt: alt ?? "",
18793
18773
  title,
18794
18774
  width: finalWidth,
18795
- height: finalHeight
18775
+ height: finalHeight,
18776
+ style: !resolvedSrc && !errored ? { visibility: "hidden" } : void 0
18796
18777
  }
18797
18778
  )
18798
18779
  ]
@@ -19118,14 +19099,20 @@ dayjs.extend(relativeTime);
19118
19099
  dayjs.extend(advancedFormat);
19119
19100
  function parseDateTime(date, customFormat) {
19120
19101
  const d = dayjs.utc(date).local();
19121
- return d.format(customFormat);
19102
+ if (customFormat === "X") return Math.floor(d.valueOf() / 1e3).toString();
19103
+ if (customFormat === "x") return d.valueOf().toString();
19104
+ return d.format(customFormat ?? "YYYY-MM-DD HH:mm:ss");
19105
+ }
19106
+ function parseDateTimeHuman(date) {
19107
+ return dayjs.utc(date).local().fromNow();
19122
19108
  }
19123
19109
 
19124
19110
  // src/shared/utils/userPhoto.ts
19125
19111
  function getChatApiBaseUrl() {
19126
19112
  try {
19127
19113
  const w = window;
19128
- const cfg = w?.ssconfig?.Chat_Api_Uri ?? import.meta.env.VITE_CHAT_API_URI;
19114
+ const env2 = import.meta.env;
19115
+ const cfg = w?.ssconfig?.Chat_Api_Uri ?? env2?.VITE_CHAT_API_URI;
19129
19116
  return typeof cfg === "string" && cfg.trim() ? cfg.trim() : "";
19130
19117
  } catch {
19131
19118
  return "";
@@ -19619,7 +19606,19 @@ var MessageItem = ({
19619
19606
  const t = d.getTime();
19620
19607
  return Number.isFinite(t) ? t : 0;
19621
19608
  };
19622
- const values = (message.values ?? []).slice().sort((a, b) => safeTime(a.createdAt) - safeTime(b.createdAt));
19609
+ const sortedValues = (message.values ?? []).slice().sort((a, b) => safeTime(a.createdAt) - safeTime(b.createdAt));
19610
+ const slotByKey = /* @__PURE__ */ new Map();
19611
+ const values = [];
19612
+ for (const v of sortedValues) {
19613
+ const key = `${v.name}|${v.type}`;
19614
+ const existing = slotByKey.get(key);
19615
+ if (existing !== void 0) {
19616
+ values[existing] = v;
19617
+ } else {
19618
+ slotByKey.set(key, values.length);
19619
+ values.push(v);
19620
+ }
19621
+ }
19623
19622
  const bubbles = [];
19624
19623
  let groupContent = [];
19625
19624
  let groupSources = [];
@@ -20146,26 +20145,28 @@ function mapWorkspaceDtoToModel(dto) {
20146
20145
  id: dto.id ?? "",
20147
20146
  name: dto.name ?? "",
20148
20147
  tags: dto.tags ?? [],
20149
- showSources: dto.showSources ?? void 0,
20150
- dataSpaces: Array.isArray(dto.dataSpaces) ? dto.dataSpaces : void 0,
20148
+ showSources: truthy(dto.showSources),
20149
+ dataSpaces: Array.isArray(dto.dataSpaces) ? dto.dataSpaces : [],
20151
20150
  createdByUserId: dto.createdByUserId ?? void 0,
20152
20151
  createdAt: dto.createdAt != null ? utcDate(dto.createdAt) : void 0,
20153
20152
  modifiedByUserId: dto.modifiedByUserId ?? void 0,
20154
20153
  modifiedAt: dto.modifiedAt != null ? utcDate(dto.modifiedAt) : void 0,
20155
20154
  favorited: truthy(dto.favorited),
20156
- summary: dto.summary ?? void 0,
20157
- firstPrompt: dto.firstPrompt ?? void 0,
20155
+ summary: dto.summary ?? "",
20156
+ firstPrompt: dto.firstPrompt ?? "",
20158
20157
  outputSchema: dto.outputSchema ?? void 0,
20159
- isPromptAndResponseLoggingEnabled: dto.isPromptAndResponseLoggingEnabled ?? void 0,
20160
20158
  inputs: dto.inputs ?? void 0,
20159
+ isPromptAndResponseLoggingEnabled: truthy(
20160
+ dto.isPromptAndResponseLoggingEnabled
20161
+ ),
20161
20162
  variables,
20162
20163
  sandBoxThreadId: dto.sandBoxThreadId ?? void 0,
20163
- supportsFiles: dto.supportsFiles ?? void 0,
20164
+ supportsFiles: truthy(dto.supportsFiles),
20164
20165
  avatarName: computeAvatar(dto.name ?? "")
20165
20166
  };
20166
20167
  }
20167
20168
  var mapWorkspacesDtoToModels = (arr) => arr.map(mapWorkspaceDtoToModel);
20168
20169
 
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 };
20170
+ 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
20171
  //# sourceMappingURL=index.js.map
20171
20172
  //# sourceMappingURL=index.js.map