@cognizant-ai-lab/ui-common 1.7.0 → 1.8.0
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/Theme/Palettes.d.ts +0 -9
- package/dist/Theme/Palettes.js +0 -18
- package/dist/components/AgentChat/ChatCommon/ChatCommon.d.ts +4 -1
- package/dist/components/AgentChat/ChatCommon/ChatCommon.js +74 -47
- package/dist/components/AgentChat/ChatCommon/Const.d.ts +1 -0
- package/dist/components/AgentChat/ChatCommon/Const.js +2 -0
- package/dist/components/AgentChat/ChatCommon/ControlButtons.d.ts +1 -1
- package/dist/components/AgentChat/ChatCommon/ControlButtons.js +7 -4
- package/dist/components/AgentChat/ChatCommon/FormattedMarkdown.js +3 -0
- package/dist/components/AgentChat/ChatCommon/SendButton.js +7 -6
- package/dist/components/AgentChat/ChatCommon/SyntaxHighlighterThemes.js +1 -1
- package/dist/components/AgentChat/ChatCommon/Thinking.d.ts +1 -0
- package/dist/components/AgentChat/ChatCommon/Thinking.js +10 -7
- package/dist/components/AgentChat/Common/LlmChatButton.d.ts +0 -2
- package/dist/components/AgentChat/Common/LlmChatButton.js +6 -9
- package/dist/components/AgentChat/VoiceChat/MicrophoneButton.js +12 -10
- package/dist/components/Common/Navbar.js +24 -22
- package/dist/components/Common/StatusLight.d.ts +9 -0
- package/dist/components/Common/StatusLight.js +21 -0
- package/dist/components/ErrorPage/ErrorBoundary.js +1 -1
- package/dist/components/ErrorPage/ErrorPage.d.ts +3 -3
- package/dist/components/ErrorPage/ErrorPage.js +4 -3
- package/dist/components/Logo/Common.d.ts +4 -0
- package/dist/components/Logo/Common.js +8 -0
- package/dist/components/Logo/CustomerLogo.d.ts +23 -0
- package/dist/components/Logo/CustomerLogo.js +41 -0
- package/dist/components/MultiAgentAccelerator/AgentConversations.js +0 -1
- package/dist/components/MultiAgentAccelerator/AgentFlow.js +85 -53
- package/dist/components/MultiAgentAccelerator/AgentNode.js +23 -27
- package/dist/components/MultiAgentAccelerator/GraphLayouts.d.ts +17 -10
- package/dist/components/MultiAgentAccelerator/GraphLayouts.js +4 -6
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +3 -9
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +28 -32
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.d.ts +0 -5
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.js +30 -25
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.d.ts +3 -4
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.js +84 -168
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.d.ts +30 -13
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.js +157 -100
- package/dist/components/MultiAgentAccelerator/Tour/MainTourSteps.js +10 -8
- package/dist/components/MultiAgentAccelerator/const.d.ts +2 -0
- package/dist/components/MultiAgentAccelerator/const.js +4 -0
- package/dist/components/Settings/ApiKeyInput.js +7 -8
- package/dist/components/Settings/InfoTip.d.ts +8 -0
- package/dist/components/Settings/InfoTip.js +14 -0
- package/dist/components/Settings/SettingsDialog.js +355 -181
- package/dist/components/Settings/SettingsRow.d.ts +18 -0
- package/dist/components/Settings/SettingsRow.js +35 -0
- package/dist/controller/agent/Agent.d.ts +3 -20
- package/dist/controller/agent/Agent.js +9 -43
- package/dist/controller/agent/IconSuggestions.d.ts +35 -0
- package/dist/controller/agent/IconSuggestions.js +85 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/state/IconSuggestions.d.ts +27 -0
- package/dist/state/IconSuggestions.js +50 -0
- package/dist/state/Settings.d.ts +17 -3
- package/dist/state/Settings.js +23 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/title.js +1 -1
- package/package.json +5 -1
- package/dist/components/Common/CustomerLogo.d.ts +0 -17
- package/dist/components/Common/CustomerLogo.js +0 -47
- package/dist/components/Common/MUIAccordion.d.ts +0 -17
- package/dist/components/Common/MUIAccordion.js +0 -66
- package/dist/utils/useLocalStorage.d.ts +0 -1
- package/dist/utils/useLocalStorage.js +0 -55
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
|
|
4
4
|
|
|
@@ -18,6 +18,7 @@ limitations under the License.
|
|
|
18
18
|
* Main navigation bar that appears at the top of each page
|
|
19
19
|
*/
|
|
20
20
|
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
|
21
|
+
import Business from "@mui/icons-material/Business";
|
|
21
22
|
import DarkModeIcon from "@mui/icons-material/DarkMode";
|
|
22
23
|
import SettingsIcon from "@mui/icons-material/Settings";
|
|
23
24
|
import Box from "@mui/material/Box";
|
|
@@ -28,14 +29,14 @@ import MenuItem from "@mui/material/MenuItem";
|
|
|
28
29
|
import { useColorScheme } from "@mui/material/styles";
|
|
29
30
|
import Tooltip from "@mui/material/Tooltip";
|
|
30
31
|
import Typography from "@mui/material/Typography";
|
|
31
|
-
import {
|
|
32
|
+
import { useState } from "react";
|
|
32
33
|
import { ConfirmationModal } from "./ConfirmationModal.js";
|
|
33
|
-
import { CustomerLogo, getCognizantLogoImage } from "./CustomerLogo.js";
|
|
34
|
-
import { LoadingSpinner } from "./LoadingSpinner.js";
|
|
35
34
|
import { authenticationEnabled, DEFAULT_USER_IMAGE, getContactUsConfirmationText, NEURO_SAN_UI_VERSION, } from "../../const.js";
|
|
36
35
|
import { useSettingsStore } from "../../state/Settings.js";
|
|
37
36
|
import { isDarkMode } from "../../Theme/Theme.js";
|
|
38
37
|
import { navigateToUrl } from "../../utils/BrowserNavigation.js";
|
|
38
|
+
import { getCognizantLogoImage } from "../Logo/Common.js";
|
|
39
|
+
import { CustomerLogo } from "../Logo/CustomerLogo.js";
|
|
39
40
|
import { SettingsDialog } from "../Settings/SettingsDialog.js";
|
|
40
41
|
const MENU_ITEM_TEXT_PROPS = {
|
|
41
42
|
color: "var(--bs-white)",
|
|
@@ -58,12 +59,6 @@ export const Navbar = ({ authenticationType, id, logo, logoServiceToken, onStart
|
|
|
58
59
|
// Dark mode
|
|
59
60
|
const { mode, setMode, systemMode } = useColorScheme();
|
|
60
61
|
const darkMode = isDarkMode(mode, systemMode);
|
|
61
|
-
// Gate to make sure we only attempt to render after Next.js has completed its rehydration
|
|
62
|
-
const [hydrated, setHydrated] = useState(false);
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
// Indicate that the component has been hydrated
|
|
65
|
-
setHydrated(true);
|
|
66
|
-
}, []);
|
|
67
62
|
// Help menu wiring
|
|
68
63
|
const [helpMenuAnchorEl, setHelpMenuAnchorEl] = useState(null);
|
|
69
64
|
const helpMenuOpen = Boolean(helpMenuAnchorEl);
|
|
@@ -88,18 +83,25 @@ export const Navbar = ({ authenticationType, id, logo, logoServiceToken, onStart
|
|
|
88
83
|
const customer = useSettingsStore((state) => state.settings.branding.customer);
|
|
89
84
|
const primary = useSettingsStore((state) => state.settings.branding.primary);
|
|
90
85
|
const hasCustomer = customer?.trim().length > 0;
|
|
91
|
-
|
|
86
|
+
// Logo settings
|
|
87
|
+
const iconSuggestion = useSettingsStore((state) => state.settings.branding.iconSuggestion);
|
|
88
|
+
const logoSource = useSettingsStore((state) => state.settings.branding.logoSource);
|
|
89
|
+
return (_jsxs(Grid, { id: "nav-bar-container", container: true, sx: {
|
|
92
90
|
alignItems: "center",
|
|
93
91
|
...MENU_ITEM_TEXT_PROPS,
|
|
94
92
|
padding: "0.5rem",
|
|
95
|
-
}, children: [settingsDialogOpen && (_jsx(SettingsDialog, { id: "settings-dialog", isOpen: settingsDialogOpen, logoServiceToken: logoServiceToken, onClose: () => setSettingsDialogOpen(false) })),
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
}, children: [settingsDialogOpen && (_jsx(SettingsDialog, { id: "settings-dialog", isOpen: settingsDialogOpen, logoServiceToken: logoServiceToken, onClose: () => setSettingsDialogOpen(false) })), _jsx(Box, { sx: {
|
|
94
|
+
alignItems: "center",
|
|
95
|
+
display: "flex",
|
|
96
|
+
gap: 2,
|
|
97
|
+
}, children: hasCustomer ? (_jsxs(_Fragment, { children: [_jsx(CustomerLogo, { customer: customer, fallbackIcon: Business, iconSuggestion: iconSuggestion, logoServiceToken: logoServiceToken, logoSource: logoSource }), _jsx(Typography, { "data-testid": "customer-branding", sx: {
|
|
98
|
+
fontSize: "20px",
|
|
99
|
+
fontWeight: "600",
|
|
100
|
+
paddingLeft: "0.15rem",
|
|
101
|
+
width: "200px",
|
|
102
|
+
display: "flex",
|
|
103
|
+
alignItems: "center",
|
|
104
|
+
}, children: customer })] })) : (getCognizantLogoImage()) }), _jsxs(Grid, { id: id, sx: { display: "flex", alignItems: "center" }, children: [hasCustomer ? getCognizantLogoImage() : null, _jsx(Typography, { id: "nav-bar-brand", sx: {
|
|
103
105
|
...MENU_ITEM_TEXT_PROPS,
|
|
104
106
|
marginLeft: "0.85rem",
|
|
105
107
|
fontSize: "16px",
|
|
@@ -125,13 +127,13 @@ export const Navbar = ({ authenticationType, id, logo, logoServiceToken, onStart
|
|
|
125
127
|
alignItems: "center",
|
|
126
128
|
}, onClick: (event) => {
|
|
127
129
|
setExploreMenuAnchorEl(event.currentTarget);
|
|
128
|
-
}, children: ["Explore", _jsx(ArrowDropDownIcon, { id: "nav-explore-dropdown-arrow", sx: { color: primary || "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "explore-menu", anchorEl: exploreMenuAnchorEl, open: exploreMenuOpen, onClose: handleCloseExploreMenu, children: [_jsx(MenuItem, { id: "explore-neuro-san-studio", component: "a", href: "https://github.com/cognizant-ai-lab/neuro-san-studio",
|
|
130
|
+
}, children: ["Explore", _jsx(ArrowDropDownIcon, { id: "nav-explore-dropdown-arrow", sx: { color: primary || "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "explore-menu", anchorEl: exploreMenuAnchorEl, open: exploreMenuOpen, onClose: handleCloseExploreMenu, children: [_jsx(MenuItem, { id: "explore-neuro-san-studio", component: "a", href: "https://github.com/cognizant-ai-lab/neuro-san-studio", rel: "noopener noreferrer", sx: { ...DISABLE_OUTLINE_PROPS }, target: "_blank", children: "Neuro-san studio (examples)" }, "explore-neuro-san-studio"), _jsx(MenuItem, { id: "explore-neuro-san", component: "a", href: "https://github.com/cognizant-ai-lab/neuro-san", rel: "noopener noreferrer", sx: { ...DISABLE_OUTLINE_PROPS }, target: "_blank", children: "Neuro-san (core)" }, "explore-neuro-san")] })] }), _jsxs(Grid, { id: "help-dropdown", sx: { cursor: "pointer", marginRight: "30px" }, children: [_jsxs(Typography, { id: "help-toggle", sx: {
|
|
129
131
|
...MENU_ITEM_TEXT_PROPS,
|
|
130
132
|
display: "flex",
|
|
131
133
|
alignItems: "center",
|
|
132
134
|
}, onClick: (event) => {
|
|
133
135
|
setHelpMenuAnchorEl(event.currentTarget);
|
|
134
|
-
}, children: ["Help", _jsx(ArrowDropDownIcon, { id: "nav-help-dropdown-arrow", sx: { color: primary || "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "help-menu", anchorEl: helpMenuAnchorEl, open: helpMenuOpen, onClose: handleCloseHelpMenu, children: [_jsx(MenuItem, { id: "user-guide", component: "a", href: "/
|
|
136
|
+
}, children: ["Help", _jsx(ArrowDropDownIcon, { id: "nav-help-dropdown-arrow", sx: { color: primary || "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "help-menu", anchorEl: helpMenuAnchorEl, open: helpMenuOpen, onClose: handleCloseHelpMenu, children: [_jsx(MenuItem, { id: "user-guide", component: "a", href: "/UserGuide", rel: "noopener noreferrer", sx: { ...DISABLE_OUTLINE_PROPS }, target: "_blank", children: "User guide" }, "user-guide"), _jsx(MenuItem, { id: "take-a-tour", onClick: () => {
|
|
135
137
|
handleCloseHelpMenu();
|
|
136
138
|
onStartTour?.();
|
|
137
139
|
}, sx: { ...DISABLE_OUTLINE_PROPS }, children: "Take a tour" }, "take-a-tour"), _jsx(MenuItem, { href: null, id: "contact-us-help", onClick: () => setEmailDialogOpen(true), children: "Contact Us" }, "contact-us-help")] })] }), emailDialogOpen ? (_jsx(ConfirmationModal, { id: "email-dialog", content: getContactUsConfirmationText(supportEmailAddress), handleCancel: () => {
|
|
@@ -163,5 +165,5 @@ export const Navbar = ({ authenticationType, id, logo, logoServiceToken, onStart
|
|
|
163
165
|
cursor: "pointer",
|
|
164
166
|
}, onClick: () => {
|
|
165
167
|
setSettingsDialogOpen(true);
|
|
166
|
-
} }) }))] }))
|
|
168
|
+
} }) }))] }));
|
|
167
169
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC, ReactElement } from "react";
|
|
2
|
+
type Status = "green" | "red" | "unknown";
|
|
3
|
+
interface StatusLightProps {
|
|
4
|
+
readonly id?: string;
|
|
5
|
+
readonly statusValue: Status;
|
|
6
|
+
readonly tooltip?: ReactElement;
|
|
7
|
+
}
|
|
8
|
+
export declare const StatusLight: FC<StatusLightProps>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import Box from "@mui/material/Box";
|
|
3
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
4
|
+
const statusToColor = (statusValue) => {
|
|
5
|
+
switch (statusValue) {
|
|
6
|
+
case "green":
|
|
7
|
+
return "success.main";
|
|
8
|
+
case "red":
|
|
9
|
+
return "error.main";
|
|
10
|
+
case "unknown":
|
|
11
|
+
default:
|
|
12
|
+
return "action.disabled";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export const StatusLight = ({ id, statusValue, tooltip }) => (_jsx(Tooltip, { title: tooltip, placement: "top", children: _jsx(Box, { id: id, "data-testid": id, "data-status": statusValue, sx: {
|
|
16
|
+
backgroundColor: statusToColor(statusValue),
|
|
17
|
+
borderRadius: "50%",
|
|
18
|
+
display: "inline-block",
|
|
19
|
+
minWidth: "0.75rem",
|
|
20
|
+
minHeight: "0.75rem",
|
|
21
|
+
} }) }));
|
|
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import { Component } from "react";
|
|
18
|
-
import ErrorPage from "./ErrorPage.js";
|
|
18
|
+
import { default as ErrorPage } from "./ErrorPage.js";
|
|
19
19
|
/**
|
|
20
20
|
* Implements a system-wide error handler for Next.js pages in our app.
|
|
21
21
|
* Taken from here: https://nextjs.org/docs/advanced-features/error-handling
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FC } from "react";
|
|
2
2
|
interface ErrorPageProps {
|
|
3
3
|
id: string;
|
|
4
4
|
errorText: string;
|
|
@@ -8,5 +8,5 @@ interface ErrorPageProps {
|
|
|
8
8
|
* @param id HTML id for the <code>div</code> for this page
|
|
9
9
|
* @param errorText Error text to be displayed
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
export
|
|
11
|
+
declare const ErrorPage: FC<ErrorPageProps>;
|
|
12
|
+
export default ErrorPage;
|
|
@@ -28,9 +28,9 @@ import { Navbar } from "../Common/Navbar.js";
|
|
|
28
28
|
* @param id HTML id for the <code>div</code> for this page
|
|
29
29
|
* @param errorText Error text to be displayed
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
const ErrorPage = ({ id, errorText }) => {
|
|
32
32
|
const { auth0ClientId, auth0Domain, supportEmailAddress, logoServiceToken } = useEnvironmentStore();
|
|
33
|
-
// Access
|
|
33
|
+
// Access Next.js router
|
|
34
34
|
const router = useRouter();
|
|
35
35
|
// Access user info store
|
|
36
36
|
const { currentUser, setCurrentUser, setPicture, oidcProvider } = useUserInfoStore();
|
|
@@ -44,4 +44,5 @@ export default function ErrorPage({ id, errorText }) {
|
|
|
44
44
|
await smartSignOut(currentUser, auth0Domain, auth0ClientId, oidcProvider);
|
|
45
45
|
};
|
|
46
46
|
return (_jsxs(_Fragment, { children: [_jsx(Navbar, { authenticationType: authenticationType, id: "nav-bar", logo: LOGO, logoServiceToken: logoServiceToken, pathname: router.pathname, query: router.query, signOut: handleSignOut, supportEmailAddress: supportEmailAddress, userInfo: userInfo }), _jsxs(Box, { id: id, sx: { marginLeft: "1rem" }, children: [_jsx(NeuroAIBreadcrumbs, {}), _jsx("h4", { id: "error-header", style: { color: "var(--bs-red)", marginTop: "1rem" }, children: "Oops, an internal error occurred on our end." }), _jsxs("div", { id: "error-div-1", children: [_jsxs(Box, { id: "no-need-to-worry", sx: { marginBottom: "1.5rem" }, children: [_jsx("b", { id: "bold-1", children: "There's no need to worry \u2013 you didn't do anything wrong." }), " This is a bug in our server and we'll fix it as soon as possible."] }), _jsx(Box, { id: "try-these-steps", sx: { marginBottom: "1.5rem" }, children: "To attempt to recover from the error, try these steps:" }), _jsx(Box, { id: "refresh-page", sx: { marginBottom: "1.5rem" }, children: _jsxs("ul", { id: "error-boundary-advice-list", className: "list-decimal list-inside", children: [_jsx("li", { id: "error-advice-refresh", children: "Refresh the page to see if the error goes away." }), _jsx("li", { id: "error-advice-reload", children: "Close and re-open your browser, then navigate back to the page where you encountered the error." })] }) }), "If none of that helps, please report the following error to the LEAF team:"] }), _jsx("div", { id: "error-text-div", style: { fontFamily: "monospace", marginTop: "1.5rem", marginBottom: "1.5rem" }, children: errorText }), "More information may be available in the browser console. Please include such information in your report if possible."] }), _jsx(Footer, { supportEmailAddress: supportEmailAddress, logoLinkUrl: "https://www.cognizant.com/", logoUrl: "/cognizant-logo-white.svg" })] }));
|
|
47
|
-
}
|
|
47
|
+
};
|
|
48
|
+
export default ErrorPage;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the Cognizant logo with a link to the corporate website.
|
|
4
|
+
*/
|
|
5
|
+
export const getCognizantLogoImage = () => (_jsx("a", { id: "splash-logo-link", href: "https://www.cognizant.com/us/en", style: {
|
|
6
|
+
display: "flex",
|
|
7
|
+
paddingLeft: "0.15rem",
|
|
8
|
+
}, target: "_blank", rel: "noopener noreferrer", children: _jsx("img", { id: "logo-img", width: "200", height: "45", src: "/cognizant-logo-white.svg", alt: "Cognizant Logo" }) }));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SvgIconProps } from "@mui/material/SvgIcon";
|
|
2
|
+
import { FC } from "react";
|
|
3
|
+
import { LogoSource } from "../../state/Settings.js";
|
|
4
|
+
interface CustomerLogoProps {
|
|
5
|
+
readonly customer: string;
|
|
6
|
+
readonly fallbackIcon?: FC<SvgIconProps>;
|
|
7
|
+
readonly iconSuggestion?: string;
|
|
8
|
+
readonly logoServiceToken?: string;
|
|
9
|
+
readonly logoSource: LogoSource;
|
|
10
|
+
}
|
|
11
|
+
export declare const LOGO_DEV_URL = "https://img.logo.dev/name";
|
|
12
|
+
/**
|
|
13
|
+
* Component to display the customer's logo based on the settings.
|
|
14
|
+
* @param customer - Name of the customer, used for fetching the logo from logo.dev when logoSource is "auto"
|
|
15
|
+
* @param fallbackIcon - Optional MUI icon to use as a fallback if other approaches fail
|
|
16
|
+
* @param iconSuggestion - Optional MUI icon name to use when logoSource is "generic"
|
|
17
|
+
* @param logoServiceToken - Optional token for fetching the logo from logo.dev
|
|
18
|
+
* @param logoSource - Source of the logo, determines how the logo is rendered ("none", "generic", or "auto")
|
|
19
|
+
* @returns JSX element representing the customer's logo, MUI icon, or Cognizant fallback, or null if no logo
|
|
20
|
+
* should be displayed or if the logo.dev token is missing/invalid.
|
|
21
|
+
*/
|
|
22
|
+
export declare const CustomerLogo: FC<CustomerLogoProps>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// Have to suppress this lint error to allow dynamic access of MUI icons
|
|
3
|
+
// eslint-disable-next-line no-restricted-imports
|
|
4
|
+
import * as MuiIcons from "@mui/icons-material";
|
|
5
|
+
//#endregion
|
|
6
|
+
export const LOGO_DEV_URL = "https://img.logo.dev/name";
|
|
7
|
+
/**
|
|
8
|
+
* Component to display the customer's logo based on the settings.
|
|
9
|
+
* @param customer - Name of the customer, used for fetching the logo from logo.dev when logoSource is "auto"
|
|
10
|
+
* @param fallbackIcon - Optional MUI icon to use as a fallback if other approaches fail
|
|
11
|
+
* @param iconSuggestion - Optional MUI icon name to use when logoSource is "generic"
|
|
12
|
+
* @param logoServiceToken - Optional token for fetching the logo from logo.dev
|
|
13
|
+
* @param logoSource - Source of the logo, determines how the logo is rendered ("none", "generic", or "auto")
|
|
14
|
+
* @returns JSX element representing the customer's logo, MUI icon, or Cognizant fallback, or null if no logo
|
|
15
|
+
* should be displayed or if the logo.dev token is missing/invalid.
|
|
16
|
+
*/
|
|
17
|
+
export const CustomerLogo = ({ customer, fallbackIcon: FallbackIcon, iconSuggestion, logoServiceToken, logoSource, }) => {
|
|
18
|
+
const hasCustomer = customer?.trim()?.length > 0;
|
|
19
|
+
const fallback = FallbackIcon ? _jsx(FallbackIcon, { sx: { fontSize: "2rem" } }) : null;
|
|
20
|
+
// "generic": check if suggested MUI icon is valid
|
|
21
|
+
switch (logoSource) {
|
|
22
|
+
case "generic": {
|
|
23
|
+
const MuiIcon = MuiIcons[iconSuggestion];
|
|
24
|
+
const LogoIcon = MuiIcon ?? FallbackIcon;
|
|
25
|
+
return LogoIcon ? _jsx(LogoIcon, { sx: { fontSize: "2rem" } }) : null;
|
|
26
|
+
}
|
|
27
|
+
case "auto": {
|
|
28
|
+
if (!hasCustomer || !logoServiceToken || logoServiceToken.trim().length === 0) {
|
|
29
|
+
return fallback;
|
|
30
|
+
}
|
|
31
|
+
// "auto": use logo.dev service
|
|
32
|
+
// eslint-disable-next-line max-len -- better to keep URL together
|
|
33
|
+
const logoUrl = `${LOGO_DEV_URL}/${encodeURIComponent(customer)}?token=${logoServiceToken}&theme=dark&format=png&size=75`;
|
|
34
|
+
return (_jsx("img", { src: logoUrl, alt: `${customer} Logo`, width: 40, height: 40, style: { borderRadius: "50%" } }));
|
|
35
|
+
}
|
|
36
|
+
case "none":
|
|
37
|
+
return null;
|
|
38
|
+
default:
|
|
39
|
+
return fallback;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
@@ -22,7 +22,6 @@ export const isFinalMessage = (chatMessage) => {
|
|
|
22
22
|
export const createConversation = (agents, text, type) => ({
|
|
23
23
|
// Could use crypto.randomUUID, but it's only available under HTTPS, and don't want to use a different
|
|
24
24
|
// solution for HTTP on localhost.
|
|
25
|
-
// eslint-disable-next-line newline-per-chained-call
|
|
26
25
|
id: `conv_${Date.now()}${Math.random().toString(36).slice(2, 10)}`,
|
|
27
26
|
agents: new Set(agents),
|
|
28
27
|
startedAt: new Date(),
|
|
@@ -45,8 +45,8 @@ import { ThoughtBubbleOverlay } from "./ThoughtBubbleOverlay.js";
|
|
|
45
45
|
import { sendChatQuery } from "../../controller/agent/Agent.js";
|
|
46
46
|
import { StreamingUnit } from "../../controller/llm/LlmChat.js";
|
|
47
47
|
import { useAgentChatHistoryStore } from "../../state/ChatHistory.js";
|
|
48
|
+
import { usePalette, useSettingsStore } from "../../state/Settings.js";
|
|
48
49
|
import { useTempNetworksStore } from "../../state/TemporaryNetworks.js";
|
|
49
|
-
import { usePalette } from "../../Theme/Palettes.js";
|
|
50
50
|
import { getZIndex } from "../../utils/zIndexLayers.js";
|
|
51
51
|
import { chatMessageFromChunk } from "../AgentChat/Common/Utils.js";
|
|
52
52
|
import { MUIAlert } from "../Common/MUIAlert.js";
|
|
@@ -55,7 +55,7 @@ import { NotificationType, sendNotification } from "../Common/notification.js";
|
|
|
55
55
|
// #region: Constants
|
|
56
56
|
// Timeout for thought bubbles is set to 10 seconds
|
|
57
57
|
const THOUGHT_BUBBLE_TIMEOUT_MS = 10_000;
|
|
58
|
-
// How long the dock'
|
|
58
|
+
// How long the dock's status banner stays visible before auto-dismissing. Error banners persist until dismissed.
|
|
59
59
|
// Exported for tests.
|
|
60
60
|
export const DOCK_BANNER_AUTO_DISMISS_MS = 5_000;
|
|
61
61
|
// #endregion: Constants
|
|
@@ -113,6 +113,8 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
113
113
|
}, []);
|
|
114
114
|
// Ref for isStreaming, read inside the cleanup interval.
|
|
115
115
|
const isStreamingRef = useRef(isStreaming);
|
|
116
|
+
// Display option for agent/network names
|
|
117
|
+
const useNativeNames = useSettingsStore((state) => state.settings.appearance.useNativeNames);
|
|
116
118
|
// Keep the ref current after every render.
|
|
117
119
|
useEffect(() => {
|
|
118
120
|
isStreamingRef.current = isStreaming;
|
|
@@ -166,7 +168,7 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
166
168
|
return edgesMap ?? prev;
|
|
167
169
|
});
|
|
168
170
|
}, [currentConversations, showThoughtBubbles, setThoughtBubbleEdges]);
|
|
169
|
-
//
|
|
171
|
+
// Clean up expired thought bubble edges — created once on mount, reads isStreaming via ref.
|
|
170
172
|
useEffect(() => {
|
|
171
173
|
const cleanupInterval = setInterval(() => {
|
|
172
174
|
if (!isStreamingRef.current)
|
|
@@ -187,9 +189,6 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
187
189
|
}, 1000);
|
|
188
190
|
return () => clearInterval(cleanupInterval);
|
|
189
191
|
}, [setThoughtBubbleEdges]); // mount/unmount only
|
|
190
|
-
// Shadow color for icon
|
|
191
|
-
const isDarkMode = theme.palette.mode === "dark";
|
|
192
|
-
const foregroundColor = isDarkMode ? theme.palette.common.white : theme.palette.common.black;
|
|
193
192
|
const isHeatmap = coloringOption === "heatmap";
|
|
194
193
|
const palette = usePalette();
|
|
195
194
|
// Merge agents from active thought bubbles with agentsInNetwork for layout
|
|
@@ -216,8 +215,28 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
216
215
|
// Create the flow layout depending on user preference
|
|
217
216
|
// Memoize layoutResult so it only recalculates when relevant data changes
|
|
218
217
|
const layoutResult = useMemo(() => layout === "linear"
|
|
219
|
-
? layoutLinear(
|
|
220
|
-
|
|
218
|
+
? layoutLinear({
|
|
219
|
+
agentCounts: isHeatmap ? agentCounts : undefined,
|
|
220
|
+
agentIconSuggestions,
|
|
221
|
+
agentsInNetwork: mergedAgentsInNetwork,
|
|
222
|
+
currentConversations,
|
|
223
|
+
isAgentNetworkDesignerMode,
|
|
224
|
+
isAwaitingLlm,
|
|
225
|
+
isTemporaryNetwork,
|
|
226
|
+
thoughtBubbleEdges,
|
|
227
|
+
useNativeNames,
|
|
228
|
+
})
|
|
229
|
+
: layoutRadial({
|
|
230
|
+
agentCounts: isHeatmap ? agentCounts : undefined,
|
|
231
|
+
agentIconSuggestions,
|
|
232
|
+
agentsInNetwork: mergedAgentsInNetwork,
|
|
233
|
+
currentConversations,
|
|
234
|
+
isAgentNetworkDesignerMode,
|
|
235
|
+
isAwaitingLlm,
|
|
236
|
+
isTemporaryNetwork,
|
|
237
|
+
thoughtBubbleEdges,
|
|
238
|
+
useNativeNames,
|
|
239
|
+
}), [
|
|
221
240
|
agentCounts,
|
|
222
241
|
agentIconSuggestions,
|
|
223
242
|
currentConversations,
|
|
@@ -228,6 +247,7 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
228
247
|
layout,
|
|
229
248
|
mergedAgentsInNetwork,
|
|
230
249
|
thoughtBubbleEdges,
|
|
250
|
+
useNativeNames,
|
|
231
251
|
]);
|
|
232
252
|
const [nodes, setNodes] = useState(layoutResult.nodes);
|
|
233
253
|
// Sync up the nodes with the layout result
|
|
@@ -237,7 +257,7 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
237
257
|
// Track which node the user clicked on so we can open the popup
|
|
238
258
|
const [selectedAgent, setSelectedAgent] = useState(null);
|
|
239
259
|
const [isPopupOpen, setIsPopupOpen] = useState(false);
|
|
240
|
-
// True while the agent-edit request is in-flight so we can disable the Save button.
|
|
260
|
+
// True, while the agent-edit request is in-flight so we can disable the Save button.
|
|
241
261
|
const [isSavingAgent, setIsSavingAgent] = useState(false);
|
|
242
262
|
// AbortController for the in-flight save request — stored in a ref so handlePopupClose can cancel it.
|
|
243
263
|
const saveAbortControllerRef = useRef(null);
|
|
@@ -247,7 +267,7 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
247
267
|
const dockAbortControllerRef = useRef(null);
|
|
248
268
|
// Stop-confirm overlay state: null = not shown, "confirming" = abort dialog open.
|
|
249
269
|
const [stopState, setStopState] = useState(null);
|
|
250
|
-
// Inline status banner shown above the dock header after an apply succeeds, is
|
|
270
|
+
// Inline status banner shown above the dock header after an "apply" succeeds, is canceled, or fails.
|
|
251
271
|
const [dockBanner, setDockBanner] = useState(null);
|
|
252
272
|
const bannerTimeoutRef = useRef(null);
|
|
253
273
|
// Clear the banner auto-dismiss timer on unmount.
|
|
@@ -333,7 +353,7 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
333
353
|
}
|
|
334
354
|
return true;
|
|
335
355
|
}
|
|
336
|
-
// Reservations came back but none matched the current network — surface this in the dock banner.
|
|
356
|
+
// Reservations came back, but none matched the current network — surface this in the dock banner.
|
|
337
357
|
showDockBanner({
|
|
338
358
|
severity: "error",
|
|
339
359
|
title: "Failed to apply network change.",
|
|
@@ -370,15 +390,17 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
370
390
|
}
|
|
371
391
|
catch (e) {
|
|
372
392
|
const isAbort = e instanceof DOMException && e.name === "AbortError";
|
|
373
|
-
if (
|
|
374
|
-
|
|
393
|
+
if (isAbort) {
|
|
394
|
+
if (hasTimedOut) {
|
|
395
|
+
showDockBanner({
|
|
396
|
+
severity: "error",
|
|
397
|
+
title: "Failed to apply network change.",
|
|
398
|
+
detail: "The request timed out. Please try again.",
|
|
399
|
+
});
|
|
400
|
+
}
|
|
375
401
|
}
|
|
376
|
-
else
|
|
377
|
-
showDockBanner({
|
|
378
|
-
severity: "error",
|
|
379
|
-
title: "Failed to apply network change.",
|
|
380
|
-
detail: "The request timed out. Please try again.",
|
|
381
|
-
});
|
|
402
|
+
else {
|
|
403
|
+
showDockBanner({ severity: "error", title: "Failed to apply network change.", detail: String(e) });
|
|
382
404
|
}
|
|
383
405
|
}
|
|
384
406
|
finally {
|
|
@@ -445,8 +467,8 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
445
467
|
}, [agentsInNetwork, fitView, layout]);
|
|
446
468
|
const onNodesChange = useCallback((changes) => {
|
|
447
469
|
setNodes((currentNodes) => applyNodeChanges(
|
|
448
|
-
// For now, we only allow dragging, no updates. In agent network designer mode, doesn't make
|
|
449
|
-
// to allow position changes since the user isn't actually manipulating a real network
|
|
470
|
+
// For now, we only allow dragging, no updates. In agent network designer mode, it doesn't make
|
|
471
|
+
// sense to allow position changes since the user isn't actually manipulating a real network
|
|
450
472
|
changes.filter((c) => c.type === "position" && !isAgentNetworkDesignerMode), currentNodes));
|
|
451
473
|
}, [isAgentNetworkDesignerMode]);
|
|
452
474
|
const transform = useStore((state) => state.transform);
|
|
@@ -479,53 +501,62 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
479
501
|
const getLegend = () => {
|
|
480
502
|
const length = isHeatmap ? palette.length : Math.min(maxDepth, palette.length);
|
|
481
503
|
return (_jsxs(Box, { id: `${id}-legend`, sx: {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
504
|
+
alignItems: "center",
|
|
505
|
+
backgroundColor: theme.palette.background.paper,
|
|
506
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
507
|
+
boxShadow: `0 2px 8px ${alpha(theme.palette.text.primary, 0.18)}`,
|
|
486
508
|
borderRadius: "5px",
|
|
487
|
-
boxShadow: `0 0 5px color-mix(in srgb, ${foregroundColor} 30%, transparent)`,
|
|
488
509
|
display: "flex",
|
|
489
|
-
|
|
510
|
+
padding: theme.spacing(0.5),
|
|
511
|
+
position: "absolute",
|
|
512
|
+
right: theme.spacing(2),
|
|
513
|
+
top: theme.spacing(4),
|
|
490
514
|
zIndex: getZIndex(2, theme),
|
|
491
|
-
}, children: [Array.from({ length }, (_, i) => (_jsx(Box, { id: `${id}-legend-depth-${i}`,
|
|
515
|
+
}, children: [Array.from({ length }, (_, i) => (_jsx(Box, { id: `${id}-legend-depth-${i}`, sx: {
|
|
492
516
|
alignItems: "center",
|
|
493
517
|
backgroundColor: palette[i],
|
|
494
518
|
borderRadius: "50%",
|
|
495
519
|
color: theme.palette.getContrastText(palette[i]),
|
|
496
520
|
display: "flex",
|
|
497
|
-
|
|
521
|
+
fontSize: "0.5rem",
|
|
498
522
|
justifyContent: "center",
|
|
499
|
-
marginLeft:
|
|
523
|
+
marginLeft: theme.spacing(0.75),
|
|
500
524
|
width: "15px",
|
|
501
|
-
}, children:
|
|
502
|
-
fontSize: "8px",
|
|
503
|
-
}, children: i }) }, i))), _jsxs(ToggleButtonGroup, { id: `${id}-coloring-toggle`, value: coloringOption, exclusive: true, onChange: (_, newValue) => {
|
|
525
|
+
}, children: i }, i))), _jsxs(ToggleButtonGroup, { id: `${id}-coloring-toggle`, value: coloringOption, exclusive: true, onChange: (_, newValue) => {
|
|
504
526
|
if (newValue !== null) {
|
|
505
527
|
setColoringOption(newValue);
|
|
506
528
|
}
|
|
507
|
-
}, sx: {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
529
|
+
}, size: "small", sx: {
|
|
530
|
+
marginLeft: theme.spacing(2),
|
|
531
|
+
"& .MuiToggleButton-root": {
|
|
532
|
+
backgroundColor: theme.palette.background.paper,
|
|
533
|
+
borderColor: theme.palette.divider,
|
|
534
|
+
color: theme.palette.text.primary,
|
|
535
|
+
minHeight: 22,
|
|
536
|
+
px: 1,
|
|
537
|
+
"&:hover": {
|
|
538
|
+
backgroundColor: theme.palette.action.hover,
|
|
539
|
+
},
|
|
540
|
+
"&.Mui-selected": {
|
|
541
|
+
backgroundColor: theme.palette.action.selected,
|
|
542
|
+
borderColor: theme.palette.text.primary,
|
|
543
|
+
},
|
|
544
|
+
"&.Mui-selected:hover": {
|
|
545
|
+
backgroundColor: theme.palette.action.selected,
|
|
546
|
+
borderColor: theme.palette.text.primary,
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
}, children: [_jsx(ToggleButton, { id: `${id}-depth-toggle`, value: "depth", sx: {
|
|
512
550
|
fontSize: "0.5rem",
|
|
513
551
|
height: "1rem",
|
|
514
|
-
}, children: _jsx(
|
|
515
|
-
fontSize: "10px",
|
|
516
|
-
}, children: "Depth" }) }), _jsx(ToggleButton, { id: `${id}-heatmap-toggle`, size: "small", value: "heatmap", sx: {
|
|
552
|
+
}, children: "Depth" }), _jsx(ToggleButton, { id: `${id}-heatmap-toggle`, value: "heatmap", sx: {
|
|
517
553
|
fontSize: "0.5rem",
|
|
518
554
|
height: "1rem",
|
|
519
|
-
}, children:
|
|
520
|
-
fontSize: "10px",
|
|
521
|
-
}, children: "Heatmap" }) })] })] }));
|
|
555
|
+
}, children: "Heatmap" })] })] }));
|
|
522
556
|
};
|
|
523
557
|
// Get the background color for the control buttons based on the layout and dark mode setting
|
|
524
558
|
const getControlButtonBackgroundColor = (isActive) => {
|
|
525
|
-
|
|
526
|
-
return undefined;
|
|
527
|
-
}
|
|
528
|
-
return isDarkMode ? theme.palette.grey[800] : theme.palette.grey[200];
|
|
559
|
+
return isActive ? theme.palette.action.selected : undefined;
|
|
529
560
|
};
|
|
530
561
|
// Only show radial guides if radial layout is selected, radial guides are enabled, and it's not just Frontman
|
|
531
562
|
const shouldShowRadialGuides = enableRadialGuides && layout === "radial" && maxDepth > 1;
|
|
@@ -604,9 +635,12 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
604
635
|
fill: theme.palette.text.primary,
|
|
605
636
|
},
|
|
606
637
|
}, children: [_jsxs(Box, { id: `${id}-react-flow-wrapper`, sx: { position: "relative", flex: 1, minHeight: 0 }, children: [networkDisplayName ? _jsx(Box, { sx: { marginBottom: "1rem" }, children: getTitle() }) : null, _jsx(ReactFlow, { id: `${id}-react-flow`, nodes: nodes, edges: edges, onNodesChange: onNodesChange, onNodeClick: handleNodeClick, fitView: true, nodeTypes: nodeTypes, edgeTypes: edgeTypes, connectionMode: ConnectionMode.Loose, children: !isAwaitingLlm && (_jsxs(_Fragment, { children: [agentsInNetwork?.length && !isAgentNetworkDesignerMode && !isEditMode ? getLegend() : null, _jsx(Background, { id: `${id}-background` }), !isAgentNetworkDesignerMode && !isEditMode && getControls(), shouldShowRadialGuides ? getRadialGuides() : null] })) }), _jsx(ThoughtBubbleOverlay, { nodes: nodes, edges: thoughtBubbleEdgesForOverlay, showThoughtBubbles: showThoughtBubbles, isStreaming: isStreaming, onBubbleHoverChange: handleBubbleHoverChange })] }), isEditMode && isTemporaryNetwork && !isAwaitingLlm && (_jsxs(Box, { sx: {
|
|
638
|
+
backdropFilter: "blur(8px)",
|
|
639
|
+
backgroundColor: alpha(theme.palette.background.paper, 0.2),
|
|
607
640
|
borderTop: `2px solid ${theme.palette.primary.main}`,
|
|
608
|
-
backgroundColor: theme.palette.background.paper,
|
|
609
641
|
flexShrink: 0,
|
|
642
|
+
position: "relative",
|
|
643
|
+
zIndex: getZIndex(2, theme),
|
|
610
644
|
}, children: [dockBanner && (_jsx(MUIAlert, { closeable: true, id: `${id}-dock-banner`, onClose: handleDismissBanner, severity: dockBanner.severity, sx: {
|
|
611
645
|
borderRadius: 0,
|
|
612
646
|
// Override MUIAlert's default 1rem bottom margin so the banner sits flush
|
|
@@ -617,10 +651,8 @@ export const AgentFlow = ({ agentCounts, agentIconSuggestions, agentsInNetwork,
|
|
|
617
651
|
// vertically with the header's close X below it.
|
|
618
652
|
paddingRight: 0.5,
|
|
619
653
|
alignItems: "center",
|
|
620
|
-
// Frost the banner like the dock header so the graph doesn't show through the
|
|
621
|
-
// app's translucent paper background; keep a tinted, mostly
|
|
622
|
-
backdropFilter: "blur(8px)",
|
|
623
|
-
backgroundColor: alpha(theme.palette[dockBanner.severity].main, isDarkMode ? 0.28 : 0.16),
|
|
654
|
+
// Frost the banner like the dock header, so the graph doesn't show through the
|
|
655
|
+
// app's translucent paper background; keep a tinted, mostly opaque severity wash.
|
|
624
656
|
"& .MuiAlert-action": {
|
|
625
657
|
alignItems: "center",
|
|
626
658
|
marginRight: 0,
|
|
@@ -29,8 +29,7 @@ import Typography from "@mui/material/Typography";
|
|
|
29
29
|
import { Handle, Position } from "@xyflow/react";
|
|
30
30
|
import { useState } from "react";
|
|
31
31
|
import { DisplayAs } from "./const.js";
|
|
32
|
-
import { useSettingsStore } from "../../state/Settings.js";
|
|
33
|
-
import { usePalette } from "../../Theme/Palettes.js";
|
|
32
|
+
import { usePalette, useSettingsStore } from "../../state/Settings.js";
|
|
34
33
|
import { isLightColor } from "../../Theme/Theme.js";
|
|
35
34
|
import { getZIndex } from "../../utils/zIndexLayers.js";
|
|
36
35
|
// A zero-width space character, used to give the browser a hint where to break long names
|
|
@@ -125,32 +124,28 @@ export const AgentNode = (props) => {
|
|
|
125
124
|
// Determine which icon to display based on the agent type whether it is Frontman or not
|
|
126
125
|
const getDisplayAsIcon = () => {
|
|
127
126
|
const id = `${agentId}-icon`;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
// Check for valid MUI icon suggestion from the LLM suggestion service
|
|
128
|
+
const SuggestedIcon = agentIconSuggestion ? MuiIcons[agentIconSuggestion] : undefined;
|
|
129
|
+
// If the LLM provided a valid icon suggestion, use it. Otherwise, fall back to default icons based on
|
|
130
|
+
// agent type.
|
|
131
|
+
if (SuggestedIcon) {
|
|
132
|
+
return (_jsx(SuggestedIcon, { id: id, sx: { fontSize: AGENT_ICON_SIZE } }));
|
|
131
133
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
_jsx(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
case DisplayAs.CODED_TOOL:
|
|
148
|
-
return (_jsx(HandymanIcon, { id: id, sx: { fontSize: AGENT_ICON_SIZE } }));
|
|
149
|
-
case DisplayAs.LLM_AGENT:
|
|
150
|
-
default:
|
|
151
|
-
return (_jsx(AutoAwesomeIcon, { id: id, sx: { fontSize: AGENT_ICON_SIZE } }));
|
|
152
|
-
}
|
|
153
|
-
}
|
|
134
|
+
if (isFrontman) {
|
|
135
|
+
return (
|
|
136
|
+
// Use special icon and larger size for Frontman
|
|
137
|
+
_jsx(PersonIcon, { id: id, sx: { fontSize: FRONTMAN_ICON_SIZE } }));
|
|
138
|
+
}
|
|
139
|
+
switch (displayAs) {
|
|
140
|
+
case DisplayAs.EXTERNAL_AGENT:
|
|
141
|
+
return (_jsx(TravelExploreIcon, { id: id, sx: { fontSize: AGENT_ICON_SIZE } }));
|
|
142
|
+
// This should be a supported type but we're not seeing it?
|
|
143
|
+
case DisplayAs.LANGCHAIN_TOOL:
|
|
144
|
+
case DisplayAs.CODED_TOOL:
|
|
145
|
+
return (_jsx(HandymanIcon, { id: id, sx: { fontSize: AGENT_ICON_SIZE } }));
|
|
146
|
+
case DisplayAs.LLM_AGENT:
|
|
147
|
+
default:
|
|
148
|
+
return (_jsx(AutoAwesomeIcon, { id: id, sx: { fontSize: AGENT_ICON_SIZE } }));
|
|
154
149
|
}
|
|
155
150
|
};
|
|
156
151
|
// Determine icon color based on settings. If auto color is enabled, use contrasting color for readability.
|
|
@@ -160,6 +155,7 @@ export const AgentNode = (props) => {
|
|
|
160
155
|
? theme.palette.common.black
|
|
161
156
|
: theme.palette.common.white;
|
|
162
157
|
const [isHovered, setIsHovered] = useState(false);
|
|
158
|
+
// Insert zero-width spaces into the agent name to give the browser hints where to wrap.
|
|
163
159
|
const wrappedAgentName = agentName
|
|
164
160
|
// Allow wrap after underscore
|
|
165
161
|
.replaceAll("_", `_${ZERO_WIDTH_SPACE}`)
|