synapse-react-client 4.0.29 → 4.0.31
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/SWC.index.d.ts +4 -0
- package/dist/SWC.index.d.ts.map +1 -1
- package/dist/SWC.index.js +2 -1
- package/dist/SWC.index.js.map +1 -1
- package/dist/assets/illustrations/curie_avatar.svg +52 -0
- package/dist/assets/illustrations/curie_avatar_head.js +91 -0
- package/dist/assets/illustrations/curie_avatar_head.js.map +1 -0
- package/dist/assets/illustrations/curie_avatar_head.svg +21 -0
- package/dist/assets/illustrations/discussions_illustration2.js +96 -0
- package/dist/assets/illustrations/discussions_illustration2.js.map +1 -0
- package/dist/assets/illustrations/discussions_illustration2.svg +17 -0
- package/dist/assets/illustrations/index.d.ts +3 -0
- package/dist/assets/illustrations/index.d.ts.map +1 -1
- package/dist/assets/illustrations/index.js +34 -32
- package/dist/assets/illustrations/index.js.map +1 -1
- package/dist/assets/mui_components/CurieAvatarHead.d.ts +5 -0
- package/dist/assets/mui_components/CurieAvatarHead.d.ts.map +1 -0
- package/dist/assets/mui_components/CurieAvatarHead.js +17 -0
- package/dist/assets/mui_components/CurieAvatarHead.js.map +1 -0
- package/dist/assets/themed_icons/Model.d.ts +3 -0
- package/dist/assets/themed_icons/Model.d.ts.map +1 -0
- package/dist/assets/themed_icons/Model.js +31 -0
- package/dist/assets/themed_icons/Model.js.map +1 -0
- package/dist/assets/themed_icons/index.d.ts +2 -1
- package/dist/assets/themed_icons/index.d.ts.map +1 -1
- package/dist/assets/themed_icons/index.js +19 -18
- package/dist/components/ChallengeDataDownload/ChallengeDataDownload.d.ts.map +1 -1
- package/dist/components/ChallengeDataDownload/ChallengeDataDownload.js +49 -39
- package/dist/components/ChallengeDataDownload/ChallengeDataDownload.js.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.js +46 -45
- package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
- package/dist/components/DataGrid/utils/DataGridUtils.js +1 -1
- package/dist/components/DataGrid/utils/DataGridUtils.js.map +1 -1
- package/dist/components/EntityFinder/EntityFinder.js +127 -127
- package/dist/components/EntityFinder/EntityFinder.js.map +1 -1
- package/dist/components/EntityFinder/details/view/DetailsView.js +53 -53
- package/dist/components/EntitySidebar/EntitySidebar.css +1 -1
- package/dist/components/EntitySidebar/EntitySidebar.module.js +11 -11
- package/dist/components/EntitySidebar/EntitySidebar.module.js.map +1 -1
- package/dist/components/EntitySidebar/EntitySidebar.module.scss +2 -2
- package/dist/components/EntityTreeTable/EntityTreeTable.d.ts +7 -0
- package/dist/components/EntityTreeTable/EntityTreeTable.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/EntityTreeTable.js +24 -20
- package/dist/components/EntityTreeTable/EntityTreeTable.js.map +1 -1
- package/dist/components/EntityTreeTable/components/CheckboxCell.d.ts +4 -0
- package/dist/components/EntityTreeTable/components/CheckboxCell.d.ts.map +1 -0
- package/dist/components/EntityTreeTable/components/CheckboxCell.js +43 -0
- package/dist/components/EntityTreeTable/components/CheckboxCell.js.map +1 -0
- package/dist/components/EntityTreeTable/components/EntityNameCell.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/components/EntityNameCell.js +10 -9
- package/dist/components/EntityTreeTable/components/EntityNameCell.js.map +1 -1
- package/dist/components/EntityTreeTable/components/EntityTreeTableContext.d.ts +6 -0
- package/dist/components/EntityTreeTable/components/EntityTreeTableContext.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/components/EntityTreeTableContext.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableColumns.d.ts +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableColumns.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableColumns.js +49 -39
- package/dist/components/EntityTreeTable/hooks/useTableColumns.js.map +1 -1
- package/dist/components/EntityUpload/EntityUpload.js +6 -6
- package/dist/components/Forum/DiscussionEmpty.css +1 -0
- package/dist/components/Forum/DiscussionEmpty.d.ts +6 -0
- package/dist/components/Forum/DiscussionEmpty.d.ts.map +1 -0
- package/dist/components/Forum/DiscussionEmpty.js +30 -0
- package/dist/components/Forum/DiscussionEmpty.js.map +1 -0
- package/dist/components/Forum/DiscussionEmpty.module.js +10 -0
- package/dist/components/Forum/DiscussionEmpty.module.js.map +1 -0
- package/dist/components/Forum/DiscussionEmpty.module.scss +37 -0
- package/dist/components/Icon/Icon.d.ts.map +1 -1
- package/dist/components/Icon/Icon.js +82 -80
- package/dist/components/Icon/Icon.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.d.ts.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js +39 -41
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js +27 -20
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js.map +1 -1
- package/dist/components/SynapseChat/AccessLevelMenu.d.ts.map +1 -1
- package/dist/components/SynapseChat/AccessLevelMenu.js +1 -0
- package/dist/components/SynapseChat/AccessLevelMenu.js.map +1 -1
- package/dist/components/SynapseChat/GridAgentChat.d.ts.map +1 -1
- package/dist/components/SynapseChat/GridAgentChat.js +34 -25
- package/dist/components/SynapseChat/GridAgentChat.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChat.d.ts +10 -12
- package/dist/components/SynapseChat/SynapseChat.d.ts.map +1 -1
- package/dist/components/SynapseChat/SynapseChat.js +106 -103
- package/dist/components/SynapseChat/SynapseChat.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.css +1 -0
- package/dist/components/SynapseChat/SynapseChatInteraction.d.ts +22 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.d.ts.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.js +123 -94
- package/dist/components/SynapseChat/SynapseChatInteraction.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.module.js +8 -0
- package/dist/components/SynapseChat/SynapseChatInteraction.module.js.map +1 -0
- package/dist/components/SynapseChat/SynapseChatInteraction.module.scss +25 -0
- package/dist/components/SynapseChat/SynapseChatMessage.d.ts +16 -1
- package/dist/components/SynapseChat/SynapseChatMessage.d.ts.map +1 -1
- package/dist/components/SynapseChat/SynapseChatMessage.js +25 -11
- package/dist/components/SynapseChat/SynapseChatMessage.js.map +1 -1
- package/dist/components/SynapseChat/components/AddFilesDialog/AddFilesDialog.d.ts +27 -0
- package/dist/components/SynapseChat/components/AddFilesDialog/AddFilesDialog.d.ts.map +1 -0
- package/dist/components/SynapseChat/components/AddFilesDialog/AddFilesDialog.js +79 -0
- package/dist/components/SynapseChat/components/AddFilesDialog/AddFilesDialog.js.map +1 -0
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.css +1 -0
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.d.ts +33 -0
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.d.ts.map +1 -0
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.js +77 -0
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.js.map +1 -0
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.module.js +8 -0
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.module.js.map +1 -0
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.module.scss +16 -0
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.css +1 -0
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.d.ts +23 -0
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.d.ts.map +1 -0
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.js +24 -0
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.js.map +1 -0
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.js +9 -0
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.js.map +1 -0
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.scss +19 -0
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.css +1 -0
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.d.ts +22 -0
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.d.ts.map +1 -0
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.js +80 -0
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.js.map +1 -0
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.module.js +9 -0
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.module.js.map +1 -0
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.module.scss +39 -0
- package/dist/components/SynapseChat/useChatState.d.ts +12 -4
- package/dist/components/SynapseChat/useChatState.d.ts.map +1 -1
- package/dist/components/SynapseChat/useChatState.js +38 -20
- package/dist/components/SynapseChat/useChatState.js.map +1 -1
- package/dist/components/SynapseChat/utils/constants.d.ts +8 -0
- package/dist/components/SynapseChat/utils/constants.d.ts.map +1 -0
- package/dist/components/SynapseChat/utils/constants.js +12 -0
- package/dist/components/SynapseChat/utils/constants.js.map +1 -0
- package/dist/components/SynapseChat/utils/types.d.ts +13 -0
- package/dist/components/SynapseChat/utils/types.d.ts.map +1 -0
- package/dist/components/SynapseChat/utils/types.js +0 -0
- package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js +101 -101
- package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js.map +1 -1
- package/dist/components/entity/page/action_menu/EntityActionMenu.d.ts +1 -0
- package/dist/components/entity/page/action_menu/EntityActionMenu.d.ts.map +1 -1
- package/dist/components/entity/page/action_menu/EntityActionMenu.js +8 -0
- package/dist/components/entity/page/action_menu/EntityActionMenu.js.map +1 -1
- package/dist/components/entity/page/breadcrumbs/EntityPageBreadcrumbs.js +1 -1
- package/dist/components/entity/page/breadcrumbs/EntityPageBreadcrumbs.js.map +1 -1
- package/dist/components/file/upload/BasicFileHandleUpload.d.ts +35 -4
- package/dist/components/file/upload/BasicFileHandleUpload.d.ts.map +1 -1
- package/dist/components/file/upload/BasicFileHandleUpload.js +22 -16
- package/dist/components/file/upload/BasicFileHandleUpload.js.map +1 -1
- package/dist/components/file/upload/MultiFileUploadProgress.js +6 -6
- package/dist/components/file/upload/UploadFilePanel.d.ts +32 -0
- package/dist/components/file/upload/UploadFilePanel.d.ts.map +1 -1
- package/dist/components/file/upload/UploadFilePanel.js +58 -42
- package/dist/components/file/upload/UploadFilePanel.js.map +1 -1
- package/dist/components/file/upload/validateFileSelection.d.ts +25 -0
- package/dist/components/file/upload/validateFileSelection.d.ts.map +1 -0
- package/dist/components/file/upload/validateFileSelection.js +18 -0
- package/dist/components/file/upload/validateFileSelection.js.map +1 -0
- package/dist/components/menu/DropdownMenu.d.ts +3 -0
- package/dist/components/menu/DropdownMenu.d.ts.map +1 -1
- package/dist/components/menu/DropdownMenu.js +108 -83
- package/dist/components/menu/DropdownMenu.js.map +1 -1
- package/dist/features/curator/dashboard/CuratorDashboard.d.ts.map +1 -1
- package/dist/features/curator/dashboard/CuratorDashboard.js +22 -23
- package/dist/features/curator/dashboard/CuratorDashboard.js.map +1 -1
- package/dist/features/curator/dashboard/components/CurationTaskCard.css +1 -1
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.js +13 -13
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.js.map +1 -1
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.scss +2 -1
- package/dist/features/curator/dashboard/components/CurationTaskCardLayout.d.ts.map +1 -1
- package/dist/features/curator/dashboard/components/CurationTaskCardLayout.js +35 -27
- package/dist/features/curator/dashboard/components/CurationTaskCardLayout.js.map +1 -1
- package/dist/features/curator/dashboard/components/FilteredByTaskIdsBanner.d.ts +10 -0
- package/dist/features/curator/dashboard/components/FilteredByTaskIdsBanner.d.ts.map +1 -0
- package/dist/features/curator/dashboard/components/FilteredByTaskIdsBanner.js +19 -0
- package/dist/features/curator/dashboard/components/FilteredByTaskIdsBanner.js.map +1 -0
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.js +50 -47
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.js.map +1 -1
- package/dist/mocks/chat/mockChat.d.ts +13 -1
- package/dist/mocks/chat/mockChat.d.ts.map +1 -1
- package/dist/mocks/chat/mockChat.js +34 -9
- package/dist/mocks/chat/mockChat.js.map +1 -1
- package/dist/mocks/msw/handlers/chatHandlers.d.ts +1 -1
- package/dist/mocks/msw/handlers/chatHandlers.d.ts.map +1 -1
- package/dist/mocks/msw/handlers/chatHandlers.js +21 -7
- package/dist/mocks/msw/handlers/chatHandlers.js.map +1 -1
- package/dist/synapse-client/SynapseClient.d.ts +2 -2
- package/dist/synapse-client/SynapseClient.d.ts.map +1 -1
- package/dist/synapse-client/SynapseClient.js.map +1 -1
- package/dist/synapse-queries/KeyFactory.d.ts +10 -1
- package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
- package/dist/synapse-queries/KeyFactory.js +29 -2
- package/dist/synapse-queries/KeyFactory.js.map +1 -1
- package/dist/synapse-queries/asynchronous/usePollAsynchronousJob.d.ts +2 -2
- package/dist/synapse-queries/asynchronous/usePollAsynchronousJob.d.ts.map +1 -1
- package/dist/synapse-queries/asynchronous/usePollAsynchronousJob.js +2 -1
- package/dist/synapse-queries/asynchronous/usePollAsynchronousJob.js.map +1 -1
- package/dist/synapse-queries/chat/useChat.d.ts +3 -2
- package/dist/synapse-queries/chat/useChat.d.ts.map +1 -1
- package/dist/synapse-queries/chat/useChat.js +7 -6
- package/dist/synapse-queries/chat/useChat.js.map +1 -1
- package/dist/synapse-queries/dataaccess/index.d.ts +1 -0
- package/dist/synapse-queries/dataaccess/index.d.ts.map +1 -1
- package/dist/synapse-queries/dataaccess/index.js +4 -3
- package/dist/synapse-queries/dataaccess/useEDuc.d.ts +44 -0
- package/dist/synapse-queries/dataaccess/useEDuc.d.ts.map +1 -0
- package/dist/synapse-queries/dataaccess/useEDuc.js +75 -0
- package/dist/synapse-queries/dataaccess/useEDuc.js.map +1 -0
- package/dist/synapse-queries/featureflags/useGetFeatureFlag.d.ts.map +1 -1
- package/dist/synapse-queries/featureflags/useGetFeatureFlag.js +1 -1
- package/dist/synapse-queries/featureflags/useGetFeatureFlag.js.map +1 -1
- package/dist/synapse-queries/file/useDirectUploadToS3.js +6 -6
- package/dist/synapse-queries/index.js +181 -172
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/SynapseConstants.d.ts +3 -0
- package/dist/utils/SynapseConstants.d.ts.map +1 -1
- package/dist/utils/SynapseConstants.js +122 -119
- package/dist/utils/SynapseConstants.js.map +1 -1
- package/dist/utils/featureflag/FeatureFlags.d.ts +3 -1
- package/dist/utils/featureflag/FeatureFlags.d.ts.map +1 -1
- package/dist/utils/featureflag/FeatureFlags.js +1 -1
- package/dist/utils/featureflag/FeatureFlags.js.map +1 -1
- package/dist/utils/hooks/useCurationTaskListFilters.d.ts +36 -0
- package/dist/utils/hooks/useCurationTaskListFilters.d.ts.map +1 -0
- package/dist/utils/hooks/useCurationTaskListFilters.js +42 -0
- package/dist/utils/hooks/useCurationTaskListFilters.js.map +1 -0
- package/dist/utils/hooks/useUploadFileEntity/useUploadFileEntities.js +5 -5
- package/dist/utils/hooks/useUploadFileEntity/useUploadFiles.js +14 -14
- package/package.json +4 -4
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
import { SynapseSpinner as e } from "../LoadingScreen/LoadingScreen.js";
|
|
2
2
|
import { Markdown as t } from "../Markdown/MarkdownSynapse.js";
|
|
3
|
-
import n from "./
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { ChatAttachmentStrip as n } from "./components/ChatAttachmentStrip/ChatAttachmentStrip.js";
|
|
4
|
+
import r from "./extractMessageFromTraceEvent.js";
|
|
5
|
+
import i from "./SynapseChatInteraction.module.js";
|
|
6
|
+
import { useEffect as a, useMemo as o, useRef as s, useState as c } from "react";
|
|
7
|
+
import { Alert as l, Box as u, Button as d, Chip as f, Collapse as p, ListItem as m, ListItemText as h, Stack as g, Tooltip as _, useTheme as v } from "@mui/material";
|
|
8
|
+
import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
9
|
+
import { KeyboardArrowDown as S, KeyboardArrowRight as C } from "@mui/icons-material";
|
|
8
10
|
//#region src/components/SynapseChat/SynapseChatInteraction.tsx
|
|
9
|
-
function
|
|
11
|
+
function w(e) {
|
|
10
12
|
return "reasoningText" in e ? e.reasoningText : "";
|
|
11
13
|
}
|
|
12
|
-
function
|
|
13
|
-
let
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}, [
|
|
17
|
-
|
|
14
|
+
function T({ userMessage: T, chatResponseText: E, chatErrorReason: D, chatResponseTrace: O, scrollIntoView: k = !1, onSendChat: A, agentAvatar: j, userAvatar: M, animateEntry: N = !1, isAwaitingResponse: P = !1, attachments: F, attachmentStatuses: I }) {
|
|
15
|
+
let L = v(), R = s(null), z = s(null), [B, V] = c(!1), H = !E && !D;
|
|
16
|
+
a(() => {
|
|
17
|
+
k && R.current?.scrollIntoView({ behavior: "smooth" });
|
|
18
|
+
}, [k]), a(() => {
|
|
19
|
+
k && !H && z.current?.scrollIntoView({
|
|
20
|
+
behavior: "smooth",
|
|
21
|
+
block: "end"
|
|
22
|
+
});
|
|
23
|
+
}, [k, H]);
|
|
24
|
+
let U = o(() => (O ?? []).flatMap((e) => r(e))?.filter((e) => !!e), [O]), W = U.length > 0, G = o(() => U.filter((e) => "reasoningText" in e).at(-1), [U]), K = G == null ? "Thinking..." : G.reasoningText, q = H ? K : `${B ? "Hide" : "Show"} Trace`, { textContent: J, guidePrompts: Y } = o(() => {
|
|
18
25
|
try {
|
|
19
|
-
let e = new DOMParser().parseFromString(
|
|
26
|
+
let e = new DOMParser().parseFromString(E ?? "", "text/html");
|
|
20
27
|
e.querySelectorAll("tool_name, actions").forEach((e) => e.remove());
|
|
21
28
|
let t = Array.from(e.querySelectorAll("guideprompt")).map((e) => e.textContent?.trim()).filter((e) => !!e);
|
|
22
29
|
e.querySelectorAll("guideprompt").forEach((e) => e.remove());
|
|
@@ -27,128 +34,150 @@ function w({ userMessage: w, chatResponseText: T, chatErrorReason: E, chatRespon
|
|
|
27
34
|
};
|
|
28
35
|
} catch (e) {
|
|
29
36
|
return console.error(e), {
|
|
30
|
-
textContent:
|
|
37
|
+
textContent: E ?? "",
|
|
31
38
|
guidePrompts: []
|
|
32
39
|
};
|
|
33
40
|
}
|
|
34
|
-
}, [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
}, [E]), X = o(() => (F ?? []).map((e) => {
|
|
42
|
+
let t = I?.find((t) => t.fileHandleId === e.fileHandleId);
|
|
43
|
+
return {
|
|
44
|
+
fileHandleId: e.fileHandleId,
|
|
45
|
+
label: e.fileName ?? e.fileHandleId,
|
|
46
|
+
contentType: e.contentType,
|
|
47
|
+
status: t?.status === "FAILED" ? "failed" : "default",
|
|
48
|
+
errorMessage: t?.failureMessage
|
|
49
|
+
};
|
|
50
|
+
}), [F, I]);
|
|
51
|
+
return /* @__PURE__ */ x(y, { children: [
|
|
52
|
+
/* @__PURE__ */ x(m, {
|
|
53
|
+
ref: R,
|
|
38
54
|
sx: {
|
|
39
55
|
alignSelf: "flex-end",
|
|
40
|
-
|
|
41
|
-
borderRadius: "24px",
|
|
42
|
-
maxWidth: "70%",
|
|
43
|
-
display: "block",
|
|
56
|
+
maxWidth: "82%",
|
|
44
57
|
mb: "5px",
|
|
45
|
-
p: "8px 12px",
|
|
46
58
|
wordWrap: "break-word",
|
|
47
|
-
width: "auto"
|
|
59
|
+
width: "auto",
|
|
60
|
+
display: "grid",
|
|
61
|
+
gridTemplateColumns: "auto auto",
|
|
62
|
+
columnGap: "16px",
|
|
63
|
+
alignItems: "start",
|
|
64
|
+
justifyItems: "end"
|
|
48
65
|
},
|
|
49
|
-
children: /* @__PURE__ */
|
|
66
|
+
children: [/* @__PURE__ */ b(u, {
|
|
67
|
+
className: N ? i.entryAnimation : void 0,
|
|
68
|
+
sx: {
|
|
69
|
+
p: "4px 14px",
|
|
70
|
+
backgroundColor: "#F3F6F7",
|
|
71
|
+
borderRadius: "8px"
|
|
72
|
+
},
|
|
73
|
+
children: /* @__PURE__ */ b(h, { primary: T })
|
|
74
|
+
}), /* @__PURE__ */ b(u, {
|
|
75
|
+
sx: { marginTop: "4px" },
|
|
76
|
+
children: M
|
|
77
|
+
})]
|
|
50
78
|
}),
|
|
51
|
-
/* @__PURE__ */
|
|
79
|
+
X.length > 0 && /* @__PURE__ */ b(m, {
|
|
80
|
+
sx: {
|
|
81
|
+
display: "block",
|
|
82
|
+
p: "0px",
|
|
83
|
+
mb: "5px"
|
|
84
|
+
},
|
|
85
|
+
children: /* @__PURE__ */ b(n, {
|
|
86
|
+
items: X,
|
|
87
|
+
wrap: !0
|
|
88
|
+
})
|
|
89
|
+
}),
|
|
90
|
+
/* @__PURE__ */ x(m, {
|
|
91
|
+
ref: z,
|
|
52
92
|
sx: {
|
|
53
93
|
display: "grid",
|
|
54
94
|
gridTemplateColumns: "50px auto",
|
|
55
|
-
columnGap: "
|
|
95
|
+
columnGap: "16px",
|
|
56
96
|
justifyItems: "center",
|
|
57
97
|
alignItems: "start",
|
|
58
|
-
p: "0px"
|
|
98
|
+
p: "0px",
|
|
99
|
+
padding: "10px"
|
|
59
100
|
},
|
|
60
|
-
children: [/* @__PURE__ */
|
|
61
|
-
sx: {
|
|
62
|
-
p: "3px",
|
|
63
|
-
mt: "10px",
|
|
64
|
-
height: "31px",
|
|
65
|
-
borderRadius: "50%",
|
|
66
|
-
borderStyle: "solid",
|
|
67
|
-
borderWidth: "1px",
|
|
68
|
-
borderColor: "grey.300"
|
|
69
|
-
},
|
|
70
|
-
children: /* @__PURE__ */ v(S, { sx: { color: "secondary.main" } })
|
|
71
|
-
}), /* @__PURE__ */ y(c, {
|
|
101
|
+
children: [j, /* @__PURE__ */ x(u, {
|
|
72
102
|
sx: {
|
|
73
103
|
borderRadius: "10px",
|
|
74
|
-
padding: "10px",
|
|
75
104
|
maxWidth: "100%",
|
|
76
105
|
overflow: "auto"
|
|
77
106
|
},
|
|
78
|
-
children: [
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
107
|
+
children: [/* @__PURE__ */ x(u, {
|
|
108
|
+
component: "aside",
|
|
109
|
+
sx: { ".markdown": {
|
|
110
|
+
fontStyle: "italic",
|
|
111
|
+
borderLeft: `4px solid ${L.palette.grey[300]}`,
|
|
112
|
+
marginLeft: "4px",
|
|
113
|
+
paddingLeft: "8px",
|
|
114
|
+
mt: 1,
|
|
115
|
+
mb: 2
|
|
116
|
+
} },
|
|
117
|
+
children: [/* @__PURE__ */ b(d, {
|
|
118
|
+
variant: "outlined",
|
|
119
|
+
size: "small",
|
|
120
|
+
startIcon: H ? /* @__PURE__ */ b(e, { size: 14 }) : b(B ? S : C, { sx: { width: "14px" } }),
|
|
121
|
+
disabled: !W,
|
|
122
|
+
onClick: () => {
|
|
123
|
+
V((e) => !e);
|
|
124
|
+
},
|
|
125
|
+
sx: {
|
|
126
|
+
height: "20px",
|
|
127
|
+
fontSize: "12px",
|
|
128
|
+
fontWeight: 600,
|
|
129
|
+
mb: 1,
|
|
130
|
+
border: "none !important",
|
|
131
|
+
color: "grey.700",
|
|
132
|
+
justifyContent: "flex-start",
|
|
133
|
+
whiteSpace: "nowrap",
|
|
134
|
+
maxWidth: "325px",
|
|
135
|
+
textTransform: "none",
|
|
136
|
+
pl: 0,
|
|
137
|
+
".MuiButton-startIcon": { mr: .5 }
|
|
138
|
+
},
|
|
139
|
+
children: /* @__PURE__ */ b(u, {
|
|
97
140
|
sx: {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
fontWeight: 600,
|
|
101
|
-
mb: 1,
|
|
102
|
-
border: "none !important",
|
|
103
|
-
color: "grey.700",
|
|
104
|
-
justifyContent: "flex-start",
|
|
105
|
-
whiteSpace: "nowrap",
|
|
106
|
-
maxWidth: "325px",
|
|
107
|
-
textTransform: "none",
|
|
108
|
-
pl: 0,
|
|
109
|
-
".MuiButton-startIcon": { mr: .5 }
|
|
141
|
+
overflow: "hidden",
|
|
142
|
+
textOverflow: "ellipsis"
|
|
110
143
|
},
|
|
111
|
-
children:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
children: /* @__PURE__ */ v(t, { markdown: F.map(C).filter((e) => e.trim().length > 0).join("<br/><br/>") })
|
|
121
|
-
})]
|
|
122
|
-
}),
|
|
123
|
-
B && /* @__PURE__ */ v(t, { markdown: B }),
|
|
124
|
-
k && V.length > 0 && /* @__PURE__ */ v(m, {
|
|
144
|
+
children: q
|
|
145
|
+
})
|
|
146
|
+
}), O && /* @__PURE__ */ b(p, {
|
|
147
|
+
in: B,
|
|
148
|
+
children: /* @__PURE__ */ b(t, { markdown: U.map(w).filter((e) => e.trim().length > 0).join("<br/><br/>") })
|
|
149
|
+
})]
|
|
150
|
+
}), (J || A && Y.length > 0) && /* @__PURE__ */ x(u, {
|
|
151
|
+
className: N ? i.entryAnimation : void 0,
|
|
152
|
+
children: [J && /* @__PURE__ */ b(t, { markdown: J }), A && Y.length > 0 && /* @__PURE__ */ b(g, {
|
|
125
153
|
direction: "row",
|
|
126
154
|
flexWrap: "wrap",
|
|
127
155
|
gap: 1,
|
|
128
156
|
mt: 1,
|
|
129
|
-
children:
|
|
157
|
+
children: Y.map((e) => /* @__PURE__ */ b(_, {
|
|
130
158
|
title: e,
|
|
131
|
-
children: /* @__PURE__ */
|
|
159
|
+
children: /* @__PURE__ */ b(f, {
|
|
132
160
|
label: e,
|
|
133
161
|
variant: "outlined",
|
|
134
162
|
color: "primary",
|
|
135
163
|
clickable: !0,
|
|
136
|
-
|
|
164
|
+
disabled: P,
|
|
165
|
+
onClick: () => A(e),
|
|
137
166
|
sx: { maxWidth: 200 }
|
|
138
167
|
})
|
|
139
168
|
}, e))
|
|
140
|
-
})
|
|
141
|
-
]
|
|
169
|
+
})]
|
|
170
|
+
})]
|
|
142
171
|
})]
|
|
143
172
|
}),
|
|
144
|
-
|
|
173
|
+
D && /* @__PURE__ */ b(l, {
|
|
145
174
|
severity: "error",
|
|
146
175
|
sx: { my: 2 },
|
|
147
|
-
children:
|
|
176
|
+
children: D
|
|
148
177
|
})
|
|
149
178
|
] });
|
|
150
179
|
}
|
|
151
180
|
//#endregion
|
|
152
|
-
export {
|
|
181
|
+
export { T as SynapseChatInteraction, T as default };
|
|
153
182
|
|
|
154
183
|
//# sourceMappingURL=SynapseChatInteraction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseChatInteraction.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"sourcesContent":["import { SynapseSpinner } from '@/components/LoadingScreen/LoadingScreen'\nimport extractMessageFromTraceEvent, {\n TraceMessage,\n} from '@/components/SynapseChat/extractMessageFromTraceEvent'\nimport {\n KeyboardArrowDown,\n KeyboardArrowRight,\n SmartToyTwoTone,\n} from '@mui/icons-material'\nimport {\n Alert,\n Box,\n Button,\n Chip,\n Collapse,\n ListItem,\n ListItemText,\n Stack,\n Tooltip,\n useTheme,\n} from '@mui/material'\nimport { Color } from '@mui/material/styles'\nimport { TraceEvent } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\n\nexport type SynapseChatInteractionProps = {\n userMessage: string\n chatResponseText?: string\n chatResponseTrace?: TraceEvent[]\n scrollIntoView?: boolean\n chatErrorReason?: string\n onSendChat?: (message: string) => void\n}\n\n// Show tool calls in the trace. Useful for development. We may want to show them to users in the future.\nconst SHOW_TOOL_USE = false\n\nfunction getMarkdownForTraceMessage(traceMessage: TraceMessage): string {\n if ('reasoningText' in traceMessage) {\n return traceMessage.reasoningText\n }\n if (SHOW_TOOL_USE && 'toolName' in traceMessage) {\n return `**Tool Used:** \\`${\n traceMessage.toolName\n }\\`\\n\\n**Tool Input:**\\n\\`\\`\\`json\\n${JSON.stringify(\n traceMessage.toolInput,\n null,\n 2,\n )}\\n\\`\\`\\`\\n`\n }\n return ''\n}\n\nexport function SynapseChatInteraction({\n userMessage,\n chatResponseText,\n chatErrorReason,\n chatResponseTrace,\n scrollIntoView = false,\n onSendChat,\n}: SynapseChatInteractionProps) {\n const theme = useTheme()\n const ref = useRef<HTMLLIElement | null>(null)\n const [showTrace, setShowTrace] = useState(false)\n\n useEffect(() => {\n // on mount, scroll into view if instructed\n if (scrollIntoView) {\n if (ref.current) {\n ref.current.scrollIntoView({ behavior: 'smooth' })\n }\n }\n }, [ref, scrollIntoView])\n\n const isLoading = !chatResponseText && !chatErrorReason\n\n const traceMessages = useMemo(\n () =>\n (chatResponseTrace ?? [])\n .flatMap(traceEvent => extractMessageFromTraceEvent(traceEvent))\n ?.filter(trace => !!trace),\n [chatResponseTrace],\n )\n\n const hasTraceInfo = traceMessages.length > 0\n\n const lastReasoningMessage = useMemo(\n () => traceMessages.filter(trace => 'reasoningText' in trace).at(-1),\n [traceMessages],\n )\n\n const traceButtonLoadingText =\n lastReasoningMessage == null\n ? 'Thinking...'\n : lastReasoningMessage.reasoningText\n\n const traceButtonText = isLoading\n ? traceButtonLoadingText\n : `${showTrace ? 'Hide' : 'Show'} Trace`\n\n const { textContent, guidePrompts } = useMemo(() => {\n try {\n const parser = new DOMParser()\n const doc = parser.parseFromString(chatResponseText ?? '', 'text/html')\n\n // Remove tool_name and actions elements (AI XML tags not for display)\n doc\n .querySelectorAll('tool_name, actions')\n .forEach(element => element.remove())\n\n // Extract guideprompts before removing them\n const extractedGuidePrompts = Array.from(\n doc.querySelectorAll('guideprompt'),\n )\n .map(el => el.textContent?.trim())\n .filter((t): t is string => !!t)\n\n // Remove guideprompt elements\n doc.querySelectorAll('guideprompt').forEach(element => element.remove())\n\n // Extract text from <chat> element if present, otherwise use full body text\n const chatElement = doc.querySelector('chat')\n return {\n textContent: chatElement\n ? (chatElement.textContent ?? '')\n : (doc.body.textContent ?? ''),\n guidePrompts: extractedGuidePrompts,\n }\n } catch (e) {\n console.error(e)\n return { textContent: chatResponseText ?? '', guidePrompts: [] }\n }\n }, [chatResponseText])\n\n return (\n <>\n <ListItem\n ref={ref}\n sx={{\n alignSelf: 'flex-end',\n backgroundColor: (theme.palette.secondary as unknown as Color)[100],\n borderRadius: '24px',\n maxWidth: '70%',\n display: 'block',\n mb: '5px',\n p: '8px 12px',\n wordWrap: 'break-word',\n width: 'auto',\n }}\n >\n <ListItemText primary={userMessage} />\n </ListItem>\n <ListItem\n sx={{\n display: 'grid',\n gridTemplateColumns: '50px auto',\n columnGap: '0px',\n justifyItems: 'center',\n alignItems: 'start',\n p: '0px',\n }}\n >\n <Box\n sx={{\n p: '3px',\n mt: '10px',\n height: '31px',\n borderRadius: '50%',\n borderStyle: 'solid',\n borderWidth: '1px',\n borderColor: 'grey.300',\n }}\n >\n <SmartToyTwoTone sx={{ color: 'secondary.main' }} />\n </Box>\n <Box\n sx={{\n borderRadius: '10px',\n padding: '10px',\n maxWidth: '100%',\n overflow: 'auto',\n }}\n >\n <Box\n component={'aside'}\n sx={{\n '.markdown': {\n fontStyle: 'italic',\n borderLeft: `4px solid ${theme.palette.grey[300]}`,\n marginLeft: '4px',\n paddingLeft: '8px',\n mt: 1,\n mb: 2,\n },\n }}\n >\n <Button\n variant={'outlined'}\n size={'small'}\n startIcon={\n isLoading ? (\n <SynapseSpinner size={14} />\n ) : showTrace ? (\n <KeyboardArrowDown sx={{ width: '14px' }} />\n ) : (\n <KeyboardArrowRight sx={{ width: '14px' }} />\n )\n }\n disabled={!hasTraceInfo}\n onClick={() => {\n setShowTrace(v => !v)\n }}\n sx={{\n height: '20px',\n fontSize: '12px',\n fontWeight: 600,\n mb: 1,\n border: 'none !important',\n color: 'grey.700',\n justifyContent: 'flex-start',\n whiteSpace: 'nowrap',\n maxWidth: '325px',\n textTransform: 'none',\n pl: 0,\n '.MuiButton-startIcon': { mr: 0.5 },\n }}\n >\n <Box sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>\n {traceButtonText}\n </Box>\n </Button>\n {chatResponseTrace && (\n <Collapse in={showTrace}>\n <MarkdownSynapse\n markdown={traceMessages\n .map(getMarkdownForTraceMessage)\n .filter(md => md.trim().length > 0)\n .join('<br/><br/>')}\n />\n </Collapse>\n )}\n </Box>\n {textContent && <MarkdownSynapse markdown={textContent} />}\n {onSendChat && guidePrompts.length > 0 && (\n <Stack direction=\"row\" flexWrap=\"wrap\" gap={1} mt={1}>\n {guidePrompts.map(prompt => (\n <Tooltip key={prompt} title={prompt}>\n <Chip\n label={prompt}\n variant=\"outlined\"\n color=\"primary\"\n clickable\n onClick={() => onSendChat(prompt)}\n sx={{ maxWidth: 200 }}\n />\n </Tooltip>\n ))}\n </Stack>\n )}\n </Box>\n </ListItem>\n {chatErrorReason && (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {chatErrorReason}\n </Alert>\n )}\n </>\n )\n}\n\nexport default SynapseChatInteraction\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SynapseChatInteraction.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"sourcesContent":["import { SynapseSpinner } from '@/components/LoadingScreen/LoadingScreen'\nimport extractMessageFromTraceEvent, {\n TraceMessage,\n} from '@/components/SynapseChat/extractMessageFromTraceEvent'\nimport { KeyboardArrowDown, KeyboardArrowRight } from '@mui/icons-material'\nimport {\n Alert,\n Box,\n Button,\n Chip,\n Collapse,\n ListItem,\n ListItemText,\n Stack,\n Tooltip,\n useTheme,\n} from '@mui/material'\nimport { TraceEvent } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\nimport styles from './SynapseChatInteraction.module.scss'\nimport {\n AttachmentStripItem,\n ChatAttachmentStrip,\n} from './components/ChatAttachmentStrip/ChatAttachmentStrip'\nimport { AgentChatAttachmentStatus } from '@sage-bionetworks/synapse-client'\n\n/**\n * A chat attachment to display on a sent/pending turn. Only `fileHandleId` is guaranteed --\n * `fileName`/`contentType` are omitted for a restored/polled turn, where only the fileHandleId\n * that was sent to the server is known (see SynapseChatMessage).\n */\nexport type SynapseChatInteractionAttachment = {\n fileHandleId: string\n fileName?: string\n contentType?: string\n}\n\nexport type SynapseChatInteractionProps = {\n userMessage: string\n chatResponseText?: string\n chatResponseTrace?: TraceEvent[]\n scrollIntoView?: boolean\n chatErrorReason?: string\n onSendChat?: (message: string) => void\n agentAvatar: React.ReactNode\n userAvatar: React.ReactNode\n /** Whether to play the fade/rise-in entry animation for this interaction on mount. */\n animateEntry?: boolean\n /** Whether a turn is currently in flight; gates the guide-prompt chips so they can't bypass the composer. */\n isAwaitingResponse?: boolean\n /** Attachments the user sent with this message, if any. */\n attachments?: SynapseChatInteractionAttachment[]\n /** Server-reported outcome of staging each attachment, if available (see AgentChatResponseWithAttachmentStatuses). */\n attachmentStatuses?: AgentChatAttachmentStatus[]\n}\n\n// Show tool calls in the trace. Useful for development. We may want to show them to users in the future.\nconst SHOW_TOOL_USE = false\n\nfunction getMarkdownForTraceMessage(traceMessage: TraceMessage): string {\n if ('reasoningText' in traceMessage) {\n return traceMessage.reasoningText\n }\n if (SHOW_TOOL_USE && 'toolName' in traceMessage) {\n return `**Tool Used:** \\`${\n traceMessage.toolName\n }\\`\\n\\n**Tool Input:**\\n\\`\\`\\`json\\n${JSON.stringify(\n traceMessage.toolInput,\n null,\n 2,\n )}\\n\\`\\`\\`\\n`\n }\n return ''\n}\n\nexport function SynapseChatInteraction({\n userMessage,\n chatResponseText,\n chatErrorReason,\n chatResponseTrace,\n scrollIntoView = false,\n onSendChat,\n agentAvatar,\n userAvatar,\n animateEntry = false,\n isAwaitingResponse = false,\n attachments,\n attachmentStatuses,\n}: SynapseChatInteractionProps) {\n const theme = useTheme()\n const userMessageRef = useRef<HTMLLIElement | null>(null)\n const responseRef = useRef<HTMLLIElement | null>(null)\n const [showTrace, setShowTrace] = useState(false)\n\n const isLoading = !chatResponseText && !chatErrorReason\n\n useEffect(() => {\n // on mount, scroll into view if instructed. This brings the \"Thinking...\" row to the top so\n // the answer's opening lines are usually visible as soon as it starts streaming in.\n if (scrollIntoView) {\n userMessageRef.current?.scrollIntoView({ behavior: 'smooth' })\n }\n }, [scrollIntoView])\n\n useEffect(() => {\n // once the response (or an error) arrives, scroll all the way to the bottom so the full\n // answer - which may be taller than the viewport - is brought into view.\n if (scrollIntoView && !isLoading) {\n responseRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n }\n }, [scrollIntoView, isLoading])\n\n const traceMessages = useMemo(\n () =>\n (chatResponseTrace ?? [])\n .flatMap(traceEvent => extractMessageFromTraceEvent(traceEvent))\n ?.filter(trace => !!trace),\n [chatResponseTrace],\n )\n\n const hasTraceInfo = traceMessages.length > 0\n\n const lastReasoningMessage = useMemo(\n () => traceMessages.filter(trace => 'reasoningText' in trace).at(-1),\n [traceMessages],\n )\n\n const traceButtonLoadingText =\n lastReasoningMessage == null\n ? 'Thinking...'\n : lastReasoningMessage.reasoningText\n\n const traceButtonText = isLoading\n ? traceButtonLoadingText\n : `${showTrace ? 'Hide' : 'Show'} Trace`\n\n const { textContent, guidePrompts } = useMemo(() => {\n try {\n const parser = new DOMParser()\n const doc = parser.parseFromString(chatResponseText ?? '', 'text/html')\n\n // Remove tool_name and actions elements (AI XML tags not for display)\n doc\n .querySelectorAll('tool_name, actions')\n .forEach(element => element.remove())\n\n // Extract guideprompts before removing them\n const extractedGuidePrompts = Array.from(\n doc.querySelectorAll('guideprompt'),\n )\n .map(el => el.textContent?.trim())\n .filter((t): t is string => !!t)\n\n // Remove guideprompt elements\n doc.querySelectorAll('guideprompt').forEach(element => element.remove())\n\n // Extract text from <chat> element if present, otherwise use full body text\n const chatElement = doc.querySelector('chat')\n return {\n textContent: chatElement\n ? (chatElement.textContent ?? '')\n : (doc.body.textContent ?? ''),\n guidePrompts: extractedGuidePrompts,\n }\n } catch (e) {\n console.error(e)\n return { textContent: chatResponseText ?? '', guidePrompts: [] }\n }\n }, [chatResponseText])\n\n const attachmentItems: AttachmentStripItem[] = useMemo(\n () =>\n (attachments ?? []).map(attachment => {\n const status = attachmentStatuses?.find(\n s => s.fileHandleId === attachment.fileHandleId,\n )\n return {\n fileHandleId: attachment.fileHandleId,\n label: attachment.fileName ?? attachment.fileHandleId,\n contentType: attachment.contentType,\n status: status?.status === 'FAILED' ? 'failed' : 'default',\n errorMessage: status?.failureMessage,\n }\n }),\n [attachments, attachmentStatuses],\n )\n\n return (\n <>\n <ListItem\n ref={userMessageRef}\n sx={{\n alignSelf: 'flex-end',\n maxWidth: '82%',\n mb: '5px',\n wordWrap: 'break-word',\n width: 'auto',\n display: 'grid',\n gridTemplateColumns: 'auto auto',\n columnGap: '16px',\n alignItems: 'start',\n justifyItems: 'end',\n }}\n >\n <Box\n className={animateEntry ? styles.entryAnimation : undefined}\n sx={{\n p: '4px 14px',\n backgroundColor: '#F3F6F7',\n borderRadius: '8px',\n }}\n >\n <ListItemText primary={userMessage} />\n </Box>\n <Box sx={{ marginTop: '4px' }}>{userAvatar}</Box>\n </ListItem>\n {attachmentItems.length > 0 && (\n <ListItem sx={{ display: 'block', p: '0px', mb: '5px' }}>\n <ChatAttachmentStrip items={attachmentItems} wrap />\n </ListItem>\n )}\n <ListItem\n ref={responseRef}\n sx={{\n display: 'grid',\n gridTemplateColumns: '50px auto',\n columnGap: '16px',\n justifyItems: 'center',\n alignItems: 'start',\n p: '0px',\n padding: '10px',\n }}\n >\n {agentAvatar}\n <Box\n sx={{\n borderRadius: '10px',\n maxWidth: '100%',\n overflow: 'auto',\n }}\n >\n <Box\n component={'aside'}\n sx={{\n '.markdown': {\n fontStyle: 'italic',\n borderLeft: `4px solid ${theme.palette.grey[300]}`,\n marginLeft: '4px',\n paddingLeft: '8px',\n mt: 1,\n mb: 2,\n },\n }}\n >\n <Button\n variant={'outlined'}\n size={'small'}\n startIcon={\n isLoading ? (\n <SynapseSpinner size={14} />\n ) : showTrace ? (\n <KeyboardArrowDown sx={{ width: '14px' }} />\n ) : (\n <KeyboardArrowRight sx={{ width: '14px' }} />\n )\n }\n disabled={!hasTraceInfo}\n onClick={() => {\n setShowTrace(v => !v)\n }}\n sx={{\n height: '20px',\n fontSize: '12px',\n fontWeight: 600,\n mb: 1,\n border: 'none !important',\n color: 'grey.700',\n justifyContent: 'flex-start',\n whiteSpace: 'nowrap',\n maxWidth: '325px',\n textTransform: 'none',\n pl: 0,\n '.MuiButton-startIcon': { mr: 0.5 },\n }}\n >\n <Box sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>\n {traceButtonText}\n </Box>\n </Button>\n {chatResponseTrace && (\n <Collapse in={showTrace}>\n <MarkdownSynapse\n markdown={traceMessages\n .map(getMarkdownForTraceMessage)\n .filter(md => md.trim().length > 0)\n .join('<br/><br/>')}\n />\n </Collapse>\n )}\n </Box>\n {(textContent || (onSendChat && guidePrompts.length > 0)) && (\n <Box className={animateEntry ? styles.entryAnimation : undefined}>\n {textContent && <MarkdownSynapse markdown={textContent} />}\n {onSendChat && guidePrompts.length > 0 && (\n <Stack direction=\"row\" flexWrap=\"wrap\" gap={1} mt={1}>\n {guidePrompts.map(prompt => (\n <Tooltip key={prompt} title={prompt}>\n <Chip\n label={prompt}\n variant=\"outlined\"\n color=\"primary\"\n clickable\n disabled={isAwaitingResponse}\n onClick={() => onSendChat(prompt)}\n sx={{ maxWidth: 200 }}\n />\n </Tooltip>\n ))}\n </Stack>\n )}\n </Box>\n )}\n </Box>\n </ListItem>\n {chatErrorReason && (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {chatErrorReason}\n </Alert>\n )}\n </>\n )\n}\n\nexport default SynapseChatInteraction\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SynapseChatInteraction.module.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatInteraction.module.scss"],"sourcesContent":["// Entry animation for a chat bubble/response block mounting.\n$entry-duration: 500ms;\n$entry-easing: cubic-bezier(0.2, 0, 0, 1);\n$entry-translate-y: 10px;\n\n@keyframes chatInteractionEntry {\n from {\n opacity: 0;\n transform: translateY($entry-translate-y);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.entryAnimation {\n animation: chatInteractionEntry $entry-duration $entry-easing;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .entryAnimation {\n animation: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Entry animation for a chat bubble/response block mounting.
|
|
2
|
+
$entry-duration: 500ms;
|
|
3
|
+
$entry-easing: cubic-bezier(0.2, 0, 0, 1);
|
|
4
|
+
$entry-translate-y: 10px;
|
|
5
|
+
|
|
6
|
+
@keyframes chatInteractionEntry {
|
|
7
|
+
from {
|
|
8
|
+
opacity: 0;
|
|
9
|
+
transform: translateY($entry-translate-y);
|
|
10
|
+
}
|
|
11
|
+
to {
|
|
12
|
+
opacity: 1;
|
|
13
|
+
transform: translateY(0);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.entryAnimation {
|
|
18
|
+
animation: chatInteractionEntry $entry-duration $entry-easing;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@media (prefers-reduced-motion: reduce) {
|
|
22
|
+
.entryAnimation {
|
|
23
|
+
animation: none;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,6 +1,21 @@
|
|
|
1
|
+
import { ChatAttachment } from './utils/types';
|
|
1
2
|
type SynapseChatMessageProps = {
|
|
2
|
-
|
|
3
|
+
agentAvatar: React.ReactNode;
|
|
4
|
+
userAvatar: React.ReactNode;
|
|
5
|
+
/** Known at send time; never re-derived from the polled job so the bubble never renders empty. */
|
|
6
|
+
userMessage: string;
|
|
7
|
+
/** Undefined until the async job has been registered for this interaction. */
|
|
8
|
+
chatJobId?: string;
|
|
3
9
|
onSendChat?: (message: string) => void;
|
|
10
|
+
scrollIntoView?: boolean;
|
|
11
|
+
animateEntry?: boolean;
|
|
12
|
+
isAwaitingResponse?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Attachments sent with this message. This information is not available in any API request/response
|
|
15
|
+
* until the job has finished processing, so this prop is used to optimistically render the attachment
|
|
16
|
+
* chips in the message bubble until the response arrives.
|
|
17
|
+
*/
|
|
18
|
+
pendingAttachments?: ChatAttachment[];
|
|
4
19
|
};
|
|
5
20
|
export default function SynapseChatMessage(props: SynapseChatMessageProps): import("react/jsx-runtime").JSX.Element;
|
|
6
21
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseChatMessage.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseChat/SynapseChatMessage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SynapseChatMessage.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseChat/SynapseChatMessage.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAsC9C,KAAK,uBAAuB,GAAG;IAC7B,WAAW,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,UAAU,EAAE,KAAK,CAAC,SAAS,CAAA;IAC3B,kGAAkG;IAClG,WAAW,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,cAAc,EAAE,CAAA;CACtC,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,2CA6DxE"}
|
|
@@ -7,26 +7,40 @@ import { jsx as o } from "react/jsx-runtime";
|
|
|
7
7
|
function s(t, n) {
|
|
8
8
|
let [o, s] = a([]), c = r((e) => {
|
|
9
9
|
s((t) => [...t, ...e]);
|
|
10
|
-
}, []), { data:
|
|
11
|
-
jobId: t,
|
|
12
|
-
newerThanTimestamp:
|
|
10
|
+
}, []), l = o.at(o.length - 1), { data: u } = e({
|
|
11
|
+
jobId: t ?? "",
|
|
12
|
+
newerThanTimestamp: l?.timestamp
|
|
13
13
|
}, {
|
|
14
14
|
enabled: n,
|
|
15
15
|
refetchInterval: 1e3,
|
|
16
16
|
refetchIntervalInBackground: !0
|
|
17
17
|
});
|
|
18
18
|
return i(() => {
|
|
19
|
-
|
|
20
|
-
}, [c,
|
|
19
|
+
u && u.page.length > 0 && (c(u.page), console.debug(u.page));
|
|
20
|
+
}, [c, u]), { traceEvents: o };
|
|
21
21
|
}
|
|
22
22
|
function c(e) {
|
|
23
|
-
let {
|
|
23
|
+
let { userMessage: r, chatJobId: i, onSendChat: a, agentAvatar: c, userAvatar: l, scrollIntoView: u, animateEntry: d, isAwaitingResponse: f, pendingAttachments: p } = e, { data: m } = n(i), h = m?.requestBody, g = m?.responseBody, _ = m?.errorMessage, { traceEvents: v } = s(i, !!i && (!m?.jobState || m.jobState == "PROCESSING")), y = h?.attachments?.map((e) => {
|
|
24
|
+
let t = e.fileHandleId, n = g?.attachmentStatuses?.find((e) => e.fileHandleId === t), r = p?.find((e) => e.fileHandleId === t);
|
|
25
|
+
return {
|
|
26
|
+
fileHandleId: t,
|
|
27
|
+
fileName: n?.fileName ?? r?.fileName,
|
|
28
|
+
contentType: n?.contentType ?? r?.contentType
|
|
29
|
+
};
|
|
30
|
+
}) ?? p;
|
|
24
31
|
return /* @__PURE__ */ o(t, {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
agentAvatar: c,
|
|
33
|
+
userAvatar: l,
|
|
34
|
+
userMessage: r,
|
|
35
|
+
chatResponseText: g?.responseText,
|
|
36
|
+
chatResponseTrace: v,
|
|
37
|
+
chatErrorReason: _,
|
|
38
|
+
onSendChat: a,
|
|
39
|
+
scrollIntoView: u,
|
|
40
|
+
animateEntry: d,
|
|
41
|
+
isAwaitingResponse: f,
|
|
42
|
+
attachments: y,
|
|
43
|
+
attachmentStatuses: g?.attachmentStatuses
|
|
30
44
|
});
|
|
31
45
|
}
|
|
32
46
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseChatMessage.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatMessage.tsx"],"sourcesContent":["import SynapseChatInteraction from '@/components/SynapseChat/SynapseChatInteraction'\nimport usePollAsynchronousJob from '@/synapse-queries/asynchronous/usePollAsynchronousJob'\nimport { useGetChatAgentTraceEvents } from '@/synapse-queries/chat/useChat'\nimport {\n AgentChatRequest,\n AgentChatResponse,\n
|
|
1
|
+
{"version":3,"file":"SynapseChatMessage.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatMessage.tsx"],"sourcesContent":["import SynapseChatInteraction from '@/components/SynapseChat/SynapseChatInteraction'\nimport usePollAsynchronousJob from '@/synapse-queries/asynchronous/usePollAsynchronousJob'\nimport { useGetChatAgentTraceEvents } from '@/synapse-queries/chat/useChat'\nimport {\n AgentChatRequest,\n AgentChatResponse,\n} from '@sage-bionetworks/synapse-client'\nimport { TraceEvent } from '@sage-bionetworks/synapse-types'\nimport { useCallback, useEffect, useState } from 'react'\nimport { ChatAttachment } from './utils/types'\n\nfunction useTraceEvent(chatJobId: string | undefined, enabled: boolean) {\n const [traceEvents, setTraceEvents] = useState<TraceEvent[]>([])\n\n const appendTraceEvents = useCallback((newEvents: TraceEvent[]) => {\n setTraceEvents(prev => {\n return [...prev, ...newEvents]\n })\n }, [])\n\n const latestTraceEvent = traceEvents.at(traceEvents.length - 1)\n const { data: newTraceEvents } = useGetChatAgentTraceEvents(\n {\n jobId: chatJobId ?? '',\n newerThanTimestamp: latestTraceEvent?.timestamp,\n },\n {\n enabled: enabled,\n refetchInterval: 1000, // Re-fetch every second if enabled\n refetchIntervalInBackground: true, // Continue polling even when the tab is not active\n },\n )\n useEffect(() => {\n if (newTraceEvents && newTraceEvents.page.length > 0) {\n appendTraceEvents(newTraceEvents.page)\n\n // send trace events to the console to ease agent debugging\n // if the trace events do not contain the latest event, add the events to the array\n console.debug(newTraceEvents.page)\n }\n }, [appendTraceEvents, newTraceEvents])\n\n return {\n traceEvents,\n }\n}\n\ntype SynapseChatMessageProps = {\n agentAvatar: React.ReactNode\n userAvatar: React.ReactNode\n /** Known at send time; never re-derived from the polled job so the bubble never renders empty. */\n userMessage: string\n /** Undefined until the async job has been registered for this interaction. */\n chatJobId?: string\n onSendChat?: (message: string) => void\n scrollIntoView?: boolean\n animateEntry?: boolean\n isAwaitingResponse?: boolean\n /**\n * Attachments sent with this message. This information is not available in any API request/response\n * until the job has finished processing, so this prop is used to optimistically render the attachment\n * chips in the message bubble until the response arrives.\n */\n pendingAttachments?: ChatAttachment[]\n}\n\nexport default function SynapseChatMessage(props: SynapseChatMessageProps) {\n const {\n userMessage,\n chatJobId,\n onSendChat,\n agentAvatar,\n userAvatar,\n scrollIntoView,\n animateEntry,\n isAwaitingResponse,\n pendingAttachments,\n } = props\n const { data: asyncJobStatus } = usePollAsynchronousJob(chatJobId)\n\n const chatRequest = asyncJobStatus?.requestBody as AgentChatRequest\n const chatResponse = asyncJobStatus?.responseBody as\n | AgentChatResponse\n | undefined\n const chatError = asyncJobStatus?.errorMessage\n\n // enabled if the job has been registered and has not finished processing\n const enableTrace =\n !!chatJobId &&\n (!asyncJobStatus?.jobState || asyncJobStatus.jobState == 'PROCESSING')\n const { traceEvents } = useTraceEvent(chatJobId, enableTrace)\n\n const attachments =\n chatRequest?.attachments?.map(attachment => {\n const fileHandleId = attachment.fileHandleId!\n const status = chatResponse?.attachmentStatuses?.find(\n s => s.fileHandleId === fileHandleId,\n )\n const pending = pendingAttachments?.find(\n a => a.fileHandleId === fileHandleId,\n )\n // Prefer the server-resolved metadata once the job's response arrives. Fall back to what\n // was optimistically sent (`pending`) so the chip doesn't lose its filename between the\n // job being registered and its response arriving.\n return {\n fileHandleId,\n fileName: status?.fileName ?? pending?.fileName,\n contentType: status?.contentType ?? pending?.contentType,\n }\n }) ?? pendingAttachments\n\n return (\n <SynapseChatInteraction\n agentAvatar={agentAvatar}\n userAvatar={userAvatar}\n userMessage={userMessage}\n chatResponseText={chatResponse?.responseText}\n chatResponseTrace={traceEvents}\n chatErrorReason={chatError}\n onSendChat={onSendChat}\n scrollIntoView={scrollIntoView}\n animateEntry={animateEntry}\n isAwaitingResponse={isAwaitingResponse}\n attachments={attachments}\n attachmentStatuses={chatResponse?.attachmentStatuses}\n />\n )\n}\n"],"mappings":";;;;;;AAWA,SAAS,EAAc,GAA+B,GAAkB;CACtE,IAAM,CAAC,GAAa,KAAkB,EAAuB,CAAC,CAAC,GAEzD,IAAoB,GAAa,MAA4B;EACjE,GAAe,MACN,CAAC,GAAG,GAAM,GAAG,CAAS,CAC9B;CACH,GAAG,CAAC,CAAC,GAEC,IAAmB,EAAY,GAAG,EAAY,SAAS,CAAC,GACxD,EAAE,MAAM,MAAmB,EAC/B;EACE,OAAO,KAAa;EACpB,oBAAoB,GAAkB;CACxC,GACA;EACW;EACT,iBAAiB;EACjB,6BAA6B;CAC/B,CACF;CAWA,OAVA,QAAgB;EACd,AAAI,KAAkB,EAAe,KAAK,SAAS,MACjD,EAAkB,EAAe,IAAI,GAIrC,QAAQ,MAAM,EAAe,IAAI;CAErC,GAAG,CAAC,GAAmB,CAAc,CAAC,GAE/B,EACL,eACF;AACF;AAqBA,SAAwB,EAAmB,GAAgC;CACzE,IAAM,EACJ,gBACA,cACA,eACA,gBACA,eACA,mBACA,iBACA,uBACA,0BACE,GACE,EAAE,MAAM,MAAmB,EAAuB,CAAS,GAE3D,IAAc,GAAgB,aAC9B,IAAe,GAAgB,cAG/B,IAAY,GAAgB,cAM5B,EAAE,mBAAgB,EAAc,GAFpC,CAAC,CAAC,MACD,CAAC,GAAgB,YAAY,EAAe,YAAY,aACC,GAEtD,IACJ,GAAa,aAAa,KAAI,MAAc;EAC1C,IAAM,IAAe,EAAW,cAC1B,IAAS,GAAc,oBAAoB,MAC/C,MAAK,EAAE,iBAAiB,CAC1B,GACM,IAAU,GAAoB,MAClC,MAAK,EAAE,iBAAiB,CAC1B;EAIA,OAAO;GACL;GACA,UAAU,GAAQ,YAAY,GAAS;GACvC,aAAa,GAAQ,eAAe,GAAS;EAC/C;CACF,CAAC,KAAK;CAER,OACE,kBAAC,GAAD;EACe;EACD;EACC;EACb,kBAAkB,GAAc;EAChC,mBAAmB;EACnB,iBAAiB;EACL;EACI;EACF;EACM;EACP;EACb,oBAAoB,GAAc;CACnC,CAAA;AAEL"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { UploaderState } from '@/utils/hooks/useUploadFileEntity/useUploadFiles';
|
|
2
|
+
import { ChatAttachment } from '../../utils/types';
|
|
3
|
+
export declare const ALLOWED_FILE_TYPES_LABEL: string;
|
|
4
|
+
export type AddFilesDialogProps = {
|
|
5
|
+
open: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Invoked when the dialog should close (Cancel, Done, backdrop click, or the close button).
|
|
8
|
+
* Attachments that finished uploading while the dialog was open remain attached -- both
|
|
9
|
+
* buttons close the dialog the same way; removing an attachment is done via its chip's own
|
|
10
|
+
* remove control in the strip, not through this dialog.
|
|
11
|
+
*/
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
/** The number of attachments already attached, used to enforce the max attachment count cumulatively. */
|
|
14
|
+
currentAttachmentCount: number;
|
|
15
|
+
/** Invoked once per file, in upload-completion order, as each upload finishes. */
|
|
16
|
+
onAttachmentUploaded: (attachment: ChatAttachment) => void;
|
|
17
|
+
/** Invoked whenever the uploader's state changes, so the caller can disable Send while uploading. */
|
|
18
|
+
onUploadStateChange?: (state: UploaderState) => void;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Modal for attaching local files to a Curie chat message. Files are uploaded immediately on
|
|
22
|
+
* selection (see BasicFileHandleUpload); this dialog is a thin wrapper that applies the chat
|
|
23
|
+
* attachment limits and surfaces validation errors inline.
|
|
24
|
+
*/
|
|
25
|
+
export declare function AddFilesDialog({ open, onClose, currentAttachmentCount, onAttachmentUploaded, onUploadStateChange, }: AddFilesDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export default AddFilesDialog;
|
|
27
|
+
//# sourceMappingURL=AddFilesDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddFilesDialog.d.ts","sourceRoot":"","sources":["../../../../../src/components/SynapseChat/components/AddFilesDialog/AddFilesDialog.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,kDAAkD,CAAA;AAUhF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAMlD,eAAO,MAAM,wBAAwB,QAEzB,CAAA;AAEZ,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,OAAO,CAAA;IACb;;;;;OAKG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,yGAAyG;IACzG,sBAAsB,EAAE,MAAM,CAAA;IAC9B,kFAAkF;IAClF,oBAAoB,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAA;IAC1D,qGAAqG;IACrG,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;CACrD,CAAA;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,OAAO,EACP,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,GACpB,EAAE,mBAAmB,2CA2DrB;AAED,eAAe,cAAc,CAAA"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { DialogBase as e } from "../../../DialogBase.js";
|
|
2
|
+
import { BasicFileHandleUpload as t } from "../../../file/upload/BasicFileHandleUpload.js";
|
|
3
|
+
import { getContentTypeLabel as n } from "../AttachmentChip/AttachmentChip.js";
|
|
4
|
+
import { APPROVED_ATTACHMENT_CONTENT_TYPES as r, MAX_ATTACHMENT_FILE_SIZE_BYTES as i } from "../../utils/constants.js";
|
|
5
|
+
import { useRef as a, useState as o } from "react";
|
|
6
|
+
import { Alert as s, Button as c, Typography as l } from "@mui/material";
|
|
7
|
+
import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/SynapseChat/components/AddFilesDialog/AddFilesDialog.tsx
|
|
9
|
+
var p = Math.round(i / (1024 * 1024)), m = r.map((e) => n(e).toLowerCase()).join(", ");
|
|
10
|
+
function h({ open: n, onClose: h, currentAttachmentCount: g, onAttachmentUploaded: _, onUploadStateChange: v }) {
|
|
11
|
+
let [y, b] = o(null);
|
|
12
|
+
return /* @__PURE__ */ d(e, {
|
|
13
|
+
open: n,
|
|
14
|
+
onCancel: h,
|
|
15
|
+
title: "Add files",
|
|
16
|
+
maxWidth: "sm",
|
|
17
|
+
content: /* @__PURE__ */ f(u, { children: [
|
|
18
|
+
/* @__PURE__ */ d(t, {
|
|
19
|
+
ref: a(null),
|
|
20
|
+
allowMultipleUpload: !0,
|
|
21
|
+
disableFolderUpload: !0,
|
|
22
|
+
disableDragAndDrop: !0,
|
|
23
|
+
acceptedContentTypes: r,
|
|
24
|
+
maxFileSizeBytes: i,
|
|
25
|
+
maxFiles: 20,
|
|
26
|
+
currentFileCount: g,
|
|
27
|
+
onValidationError: b,
|
|
28
|
+
onStateChange: v,
|
|
29
|
+
onFileUploadComplete: (e, t) => {
|
|
30
|
+
_({
|
|
31
|
+
fileHandleId: e,
|
|
32
|
+
fileName: t.name,
|
|
33
|
+
contentType: t.type,
|
|
34
|
+
sizeBytes: t.size
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}),
|
|
38
|
+
/* @__PURE__ */ d(l, {
|
|
39
|
+
sx: {
|
|
40
|
+
fontWeight: 700,
|
|
41
|
+
mt: 2
|
|
42
|
+
},
|
|
43
|
+
children: "Limitations"
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ f(l, {
|
|
46
|
+
component: "ul",
|
|
47
|
+
sx: {
|
|
48
|
+
pl: 3,
|
|
49
|
+
m: 0
|
|
50
|
+
},
|
|
51
|
+
children: [/* @__PURE__ */ f("li", { children: [
|
|
52
|
+
20,
|
|
53
|
+
" files maximum, up to",
|
|
54
|
+
" ",
|
|
55
|
+
p,
|
|
56
|
+
" MB per file"
|
|
57
|
+
] }), /* @__PURE__ */ f("li", { children: ["Allowed file types: ", m] })]
|
|
58
|
+
}),
|
|
59
|
+
y && /* @__PURE__ */ d(s, {
|
|
60
|
+
severity: "error",
|
|
61
|
+
sx: { mt: 2 },
|
|
62
|
+
children: y
|
|
63
|
+
})
|
|
64
|
+
] }),
|
|
65
|
+
actions: /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d(c, {
|
|
66
|
+
variant: "outlined",
|
|
67
|
+
onClick: h,
|
|
68
|
+
children: "Cancel"
|
|
69
|
+
}), /* @__PURE__ */ d(c, {
|
|
70
|
+
variant: "contained",
|
|
71
|
+
onClick: h,
|
|
72
|
+
children: "Done"
|
|
73
|
+
})] })
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { m as ALLOWED_FILE_TYPES_LABEL, h as AddFilesDialog, h as default };
|
|
78
|
+
|
|
79
|
+
//# sourceMappingURL=AddFilesDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddFilesDialog.js","names":[],"sources":["../../../../../src/components/SynapseChat/components/AddFilesDialog/AddFilesDialog.tsx"],"sourcesContent":["import {\n BasicFileHandleUpload,\n FileUploadHandle,\n} from '@/components/file/upload/BasicFileHandleUpload'\nimport { UploaderState } from '@/utils/hooks/useUploadFileEntity/useUploadFiles'\nimport { Alert, Button, Typography } from '@mui/material'\nimport { useRef, useState } from 'react'\nimport { DialogBase } from '@/components/DialogBase'\nimport { getContentTypeLabel } from '../AttachmentChip/AttachmentChip'\nimport {\n APPROVED_ATTACHMENT_CONTENT_TYPES,\n MAX_AGENT_CHAT_ATTACHMENTS,\n MAX_ATTACHMENT_FILE_SIZE_BYTES,\n} from '../../utils/constants'\nimport { ChatAttachment } from '../../utils/types'\n\nconst MAX_FILE_SIZE_MB = Math.round(\n MAX_ATTACHMENT_FILE_SIZE_BYTES / (1024 * 1024),\n)\n\nexport const ALLOWED_FILE_TYPES_LABEL = APPROVED_ATTACHMENT_CONTENT_TYPES.map(\n contentType => getContentTypeLabel(contentType).toLowerCase(),\n).join(', ')\n\nexport type AddFilesDialogProps = {\n open: boolean\n /**\n * Invoked when the dialog should close (Cancel, Done, backdrop click, or the close button).\n * Attachments that finished uploading while the dialog was open remain attached -- both\n * buttons close the dialog the same way; removing an attachment is done via its chip's own\n * remove control in the strip, not through this dialog.\n */\n onClose: () => void\n /** The number of attachments already attached, used to enforce the max attachment count cumulatively. */\n currentAttachmentCount: number\n /** Invoked once per file, in upload-completion order, as each upload finishes. */\n onAttachmentUploaded: (attachment: ChatAttachment) => void\n /** Invoked whenever the uploader's state changes, so the caller can disable Send while uploading. */\n onUploadStateChange?: (state: UploaderState) => void\n}\n\n/**\n * Modal for attaching local files to a Curie chat message. Files are uploaded immediately on\n * selection (see BasicFileHandleUpload); this dialog is a thin wrapper that applies the chat\n * attachment limits and surfaces validation errors inline.\n */\nexport function AddFilesDialog({\n open,\n onClose,\n currentAttachmentCount,\n onAttachmentUploaded,\n onUploadStateChange,\n}: AddFilesDialogProps) {\n const [validationError, setValidationError] = useState<string | null>(null)\n const uploadRef = useRef<FileUploadHandle | null>(null)\n\n return (\n <DialogBase\n open={open}\n onCancel={onClose}\n title=\"Add files\"\n maxWidth=\"sm\"\n content={\n <>\n <BasicFileHandleUpload\n ref={uploadRef}\n allowMultipleUpload={true}\n disableFolderUpload={true}\n disableDragAndDrop={true}\n acceptedContentTypes={APPROVED_ATTACHMENT_CONTENT_TYPES}\n maxFileSizeBytes={MAX_ATTACHMENT_FILE_SIZE_BYTES}\n maxFiles={MAX_AGENT_CHAT_ATTACHMENTS}\n currentFileCount={currentAttachmentCount}\n onValidationError={setValidationError}\n onStateChange={onUploadStateChange}\n onFileUploadComplete={(fileHandleId, file) => {\n onAttachmentUploaded({\n fileHandleId,\n fileName: file.name,\n contentType: file.type,\n sizeBytes: file.size,\n })\n }}\n />\n <Typography sx={{ fontWeight: 700, mt: 2 }}>Limitations</Typography>\n <Typography component=\"ul\" sx={{ pl: 3, m: 0 }}>\n <li>\n {MAX_AGENT_CHAT_ATTACHMENTS} files maximum, up to{' '}\n {MAX_FILE_SIZE_MB} MB per file\n </li>\n <li>Allowed file types: {ALLOWED_FILE_TYPES_LABEL}</li>\n </Typography>\n {validationError && (\n <Alert severity=\"error\" sx={{ mt: 2 }}>\n {validationError}\n </Alert>\n )}\n </>\n }\n actions={\n <>\n <Button variant=\"outlined\" onClick={onClose}>\n Cancel\n </Button>\n <Button variant=\"contained\" onClick={onClose}>\n Done\n </Button>\n </>\n }\n />\n )\n}\n\nexport default AddFilesDialog\n"],"mappings":";;;;;;;;AAgBA,IAAM,IAAmB,KAAK,MAC5B,KAAkC,OAAO,KAC3C,GAEa,IAA2B,EAAkC,KACxE,MAAe,EAAoB,CAAW,EAAE,YAAY,CAC9D,EAAE,KAAK,IAAI;AAwBX,SAAgB,EAAe,EAC7B,SACA,YACA,2BACA,yBACA,0BACsB;CACtB,IAAM,CAAC,GAAiB,KAAsB,EAAwB,IAAI;CAG1E,OACE,kBAAC,GAAD;EACQ;EACN,UAAU;EACV,OAAM;EACN,UAAS;EACT,SACE,kBAAA,GAAA,EAAA,UAAA;GACE,kBAAC,GAAD;IACE,KAXQ,EAAgC,IAWnC;IACL,qBAAqB;IACrB,qBAAqB;IACrB,oBAAoB;IACpB,sBAAsB;IACtB,kBAAkB;IAClB,UAAA;IACA,kBAAkB;IAClB,mBAAmB;IACnB,eAAe;IACf,uBAAuB,GAAc,MAAS;KAC5C,EAAqB;MACnB;MACA,UAAU,EAAK;MACf,aAAa,EAAK;MAClB,WAAW,EAAK;KAClB,CAAC;IACH;GACD,CAAA;GACD,kBAAC,GAAD;IAAY,IAAI;KAAE,YAAY;KAAK,IAAI;IAAE;cAAG;GAAuB,CAAA;GACnE,kBAAC,GAAD;IAAY,WAAU;IAAK,IAAI;KAAE,IAAI;KAAG,GAAG;IAAE;cAA7C,CACE,kBAAC,MAAD,EAAA,UAAA;;KAC8B;KAAsB;KACjD;KAAiB;IAChB,EAAA,CAAA,GACJ,kBAAC,MAAD,EAAA,UAAA,CAAI,wBAAqB,CAA6B,EAAA,CAAA,CAC5C;;GACX,KACC,kBAAC,GAAD;IAAO,UAAS;IAAQ,IAAI,EAAE,IAAI,EAAE;cACjC;GACI,CAAA;EAET,EAAA,CAAA;EAEJ,SACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GAAQ,SAAQ;GAAW,SAAS;aAAS;EAErC,CAAA,GACR,kBAAC,GAAD;GAAQ,SAAQ;GAAY,SAAS;aAAS;EAEtC,CAAA,CACR,EAAA,CAAA;CAEL,CAAA;AAEL"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
._chip_1uzei_1{position:relative}._removeBadge_1uzei_5.MuiButtonBase-root{opacity:0;transition:opacity .1s;position:absolute;top:-6px;left:-6px}._chip_1uzei_1:hover ._removeBadge_1uzei_5,._chip_1uzei_1:focus-within ._removeBadge_1uzei_5{opacity:1}
|