@cognizant-ai-lab/ui-common 1.7.0 → 1.9.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.
Files changed (98) hide show
  1. package/README.md +3 -3
  2. package/dist/Theme/Palettes.d.ts +0 -9
  3. package/dist/Theme/Palettes.js +0 -18
  4. package/dist/components/AgentChat/ChatCommon/ChatCommon.d.ts +13 -4
  5. package/dist/components/AgentChat/ChatCommon/ChatCommon.js +131 -38
  6. package/dist/components/AgentChat/ChatCommon/ChatHistory.d.ts +7 -0
  7. package/dist/components/AgentChat/ChatCommon/ChatHistory.js +1 -1
  8. package/dist/components/AgentChat/ChatCommon/Const.d.ts +1 -0
  9. package/dist/components/AgentChat/ChatCommon/Const.js +2 -0
  10. package/dist/components/AgentChat/ChatCommon/ControlButtons.d.ts +5 -3
  11. package/dist/components/AgentChat/ChatCommon/ControlButtons.js +13 -4
  12. package/dist/components/AgentChat/ChatCommon/ConversationTurn.d.ts +5 -5
  13. package/dist/components/AgentChat/ChatCommon/ConversationTurn.js +1 -0
  14. package/dist/components/AgentChat/ChatCommon/FormattedMarkdown.js +3 -0
  15. package/dist/components/AgentChat/ChatCommon/SendButton.js +7 -6
  16. package/dist/components/AgentChat/ChatCommon/SyntaxHighlighterThemes.js +1 -1
  17. package/dist/components/AgentChat/ChatCommon/Thinking.d.ts +1 -0
  18. package/dist/components/AgentChat/ChatCommon/Thinking.js +10 -7
  19. package/dist/components/AgentChat/Common/LlmChatButton.d.ts +0 -2
  20. package/dist/components/AgentChat/Common/LlmChatButton.js +6 -9
  21. package/dist/components/AgentChat/Common/Utils.d.ts +4 -0
  22. package/dist/components/AgentChat/Common/Utils.js +5 -1
  23. package/dist/components/AgentChat/VoiceChat/MicrophoneButton.js +12 -10
  24. package/dist/components/Common/Breadcrumbs.js +1 -1
  25. package/dist/components/Common/Navbar.js +24 -22
  26. package/dist/components/Common/StatusLight.d.ts +9 -0
  27. package/dist/components/Common/StatusLight.js +21 -0
  28. package/dist/components/Common/notification.d.ts +4 -4
  29. package/dist/components/ErrorPage/ErrorBoundary.js +1 -1
  30. package/dist/components/ErrorPage/ErrorPage.d.ts +3 -3
  31. package/dist/components/ErrorPage/ErrorPage.js +4 -3
  32. package/dist/components/Logo/Common.d.ts +4 -0
  33. package/dist/components/Logo/Common.js +8 -0
  34. package/dist/components/Logo/CustomerLogo.d.ts +23 -0
  35. package/dist/components/Logo/CustomerLogo.js +41 -0
  36. package/dist/components/MultiAgentAccelerator/AgentConversations.js +0 -1
  37. package/dist/components/MultiAgentAccelerator/{AgentFlow.d.ts → AgentFlow/AgentFlow.d.ts} +15 -5
  38. package/dist/components/MultiAgentAccelerator/{AgentFlow.js → AgentFlow/AgentFlow.js} +125 -84
  39. package/dist/components/MultiAgentAccelerator/{AgentNode.d.ts → AgentFlow/AgentNode.d.ts} +1 -1
  40. package/dist/components/MultiAgentAccelerator/{AgentNode.js → AgentFlow/AgentNode.js} +26 -30
  41. package/dist/components/MultiAgentAccelerator/AgentFlow/GraphLayouts.d.ts +43 -0
  42. package/dist/components/MultiAgentAccelerator/{GraphLayouts.js → AgentFlow/GraphLayouts.js} +10 -41
  43. package/dist/components/MultiAgentAccelerator/AgentFlow/GraphStructure.d.ts +21 -0
  44. package/dist/components/MultiAgentAccelerator/AgentFlow/GraphStructure.js +27 -0
  45. package/dist/components/MultiAgentAccelerator/AgentFlow/PlasmaEdge.d.ts +7 -0
  46. package/dist/components/MultiAgentAccelerator/{PlasmaEdge.js → AgentFlow/PlasmaEdge.js} +13 -8
  47. package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +3 -9
  48. package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +137 -103
  49. package/dist/components/MultiAgentAccelerator/Schema/SlyData.d.ts +17 -0
  50. package/dist/components/MultiAgentAccelerator/Schema/SlyData.js +23 -0
  51. package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.d.ts +0 -5
  52. package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.js +38 -28
  53. package/dist/components/MultiAgentAccelerator/Sidebar/ImportNetworkModal.d.ts +67 -0
  54. package/dist/components/MultiAgentAccelerator/Sidebar/ImportNetworkModal.js +585 -0
  55. package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.d.ts +5 -4
  56. package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.js +77 -168
  57. package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.d.ts +31 -13
  58. package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.js +177 -100
  59. package/dist/components/MultiAgentAccelerator/TemporaryNetworks.d.ts +22 -0
  60. package/dist/components/MultiAgentAccelerator/TemporaryNetworks.js +74 -3
  61. package/dist/components/MultiAgentAccelerator/{ThoughtBubbleEdge.d.ts → ThoughtBubbles/ThoughtBubbleEdge.d.ts} +1 -1
  62. package/dist/components/MultiAgentAccelerator/{ThoughtBubbleOverlay.js → ThoughtBubbles/ThoughtBubbleOverlay.js} +1 -1
  63. package/dist/components/MultiAgentAccelerator/Tour/MainTourSteps.js +15 -8
  64. package/dist/components/MultiAgentAccelerator/const.d.ts +3 -0
  65. package/dist/components/MultiAgentAccelerator/const.js +6 -0
  66. package/dist/components/Settings/ApiKeyInput.js +7 -8
  67. package/dist/components/Settings/InfoTip.d.ts +8 -0
  68. package/dist/components/Settings/InfoTip.js +14 -0
  69. package/dist/components/Settings/SettingsDialog.js +373 -183
  70. package/dist/components/Settings/SettingsRow.d.ts +18 -0
  71. package/dist/components/Settings/SettingsRow.js +35 -0
  72. package/dist/controller/agent/Agent.d.ts +16 -25
  73. package/dist/controller/agent/Agent.js +24 -54
  74. package/dist/controller/agent/IconSuggestions.d.ts +35 -0
  75. package/dist/controller/agent/IconSuggestions.js +85 -0
  76. package/dist/index.d.ts +1 -3
  77. package/dist/index.js +1 -3
  78. package/dist/state/IconSuggestions.d.ts +27 -0
  79. package/dist/state/IconSuggestions.js +50 -0
  80. package/dist/state/Settings.d.ts +97 -6
  81. package/dist/state/Settings.js +110 -8
  82. package/dist/tsconfig.build.tsbuildinfo +1 -1
  83. package/dist/utils/BrowserNavigation.js +2 -0
  84. package/dist/utils/File.d.ts +4 -1
  85. package/dist/utils/File.js +4 -9
  86. package/dist/utils/text.js +3 -7
  87. package/dist/utils/title.js +1 -1
  88. package/package.json +9 -6
  89. package/dist/components/Common/CustomerLogo.d.ts +0 -17
  90. package/dist/components/Common/CustomerLogo.js +0 -47
  91. package/dist/components/Common/MUIAccordion.d.ts +0 -17
  92. package/dist/components/Common/MUIAccordion.js +0 -66
  93. package/dist/components/MultiAgentAccelerator/GraphLayouts.d.ts +0 -36
  94. package/dist/components/MultiAgentAccelerator/PlasmaEdge.d.ts +0 -3
  95. package/dist/utils/useLocalStorage.d.ts +0 -1
  96. package/dist/utils/useLocalStorage.js +0 -55
  97. /package/dist/components/MultiAgentAccelerator/{ThoughtBubbleEdge.js → ThoughtBubbles/ThoughtBubbleEdge.js} +0 -0
  98. /package/dist/components/MultiAgentAccelerator/{ThoughtBubbleOverlay.d.ts → ThoughtBubbles/ThoughtBubbleOverlay.d.ts} +0 -0
@@ -15,27 +15,23 @@ See the License for the specific language governing permissions and
15
15
  limitations under the License.
16
16
  */
17
17
  import AddBoxRounded from "@mui/icons-material/AddBoxRounded";
18
- import CheckCircleOutlinedIcon from "@mui/icons-material/CheckCircleOutlined";
19
- import ClearIcon from "@mui/icons-material/Clear";
20
- import HighlightOff from "@mui/icons-material/HighlightOff";
21
- import SettingsIcon from "@mui/icons-material/Settings";
18
+ import FileUploadOutlinedIcon from "@mui/icons-material/FileUploadOutlined";
22
19
  import Box from "@mui/material/Box";
23
20
  import Button from "@mui/material/Button";
24
- import IconButton from "@mui/material/IconButton";
25
- import InputAdornment from "@mui/material/InputAdornment";
26
- import Popover from "@mui/material/Popover";
27
- import { keyframes, styled, useTheme } from "@mui/material/styles";
28
- import TextField from "@mui/material/TextField";
29
- import Tooltip from "@mui/material/Tooltip";
21
+ import { keyframes, styled } from "@mui/material/styles";
22
+ import Tooltip, { tooltipClasses } from "@mui/material/Tooltip";
30
23
  import Typography from "@mui/material/Typography";
31
24
  import { RichTreeView } from "@mui/x-tree-view/RichTreeView";
32
- import { useEffect, useState, } from "react";
25
+ import httpStatus from "http-status";
26
+ import { useEffect, useState } from "react";
33
27
  import { AgentNetworkTreeItem } from "./AgentNetworkTreeItem.js";
34
- import { buildTreeViewItems } from "./TreeBuilder.js";
28
+ import { buildTreeViewItems, findTreeItemById } from "./TreeBuilder.js";
35
29
  import { testConnection } from "../../../controller/agent/Agent.js";
36
- import { useEnvironmentStore } from "../../../state/Environment.js";
30
+ import { useSettingsStore } from "../../../state/Settings.js";
37
31
  import { getZIndex } from "../../../utils/zIndexLayers.js";
32
+ import { StatusLight } from "../../Common/StatusLight.js";
38
33
  import { AGENT_NETWORK_DESIGNER_ID, TEMPORARY_NETWORK_FOLDER } from "../const.js";
34
+ //#region Constants
39
35
  // Animation for the sparkle effect when a new temporary network is added.
40
36
  const sparkle = keyframes `
41
37
  0% {
@@ -71,13 +67,13 @@ const sparkle = keyframes `
71
67
  opacity: 0.25;
72
68
  }
73
69
  `;
74
- // #region: Styled Components
75
- const PrimaryButton = styled(Button)({
76
- marginLeft: "0.5rem",
77
- marginTop: "2px",
78
- });
79
70
  // Name for sparkle animation CSS class
80
71
  export const SPARKLE_HIGHLIGHT_CLASS = "sparkle-highlight";
72
+ const EMPTY_ARRAY = [];
73
+ // Interval for pinging the Neuro-san server to check if it's online, in milliseconds
74
+ const NEURO_SAN_PING_INTERVAL_MS = 30_000;
75
+ //#endregion: Constants
76
+ //#region: Styled Components
81
77
  // Styled component for Sidebar aside element, including styles for the sparkle highlight animation
82
78
  // when a new temporary network is added.
83
79
  const SidebarAside = styled("aside")({
@@ -111,98 +107,39 @@ const SidebarHeading = styled("h2")(({ theme }) => ({
111
107
  top: 0,
112
108
  zIndex: getZIndex(1, theme),
113
109
  }));
114
- // #endregion: Styled Components
115
- // #region: Types
116
- var CONNECTION_STATUS;
117
- (function (CONNECTION_STATUS) {
118
- CONNECTION_STATUS["IDLE"] = "idle";
119
- CONNECTION_STATUS["SUCCESS"] = "success";
120
- CONNECTION_STATUS["ERROR"] = "error";
121
- })(CONNECTION_STATUS || (CONNECTION_STATUS = {}));
122
- // #endregion: Types
123
- const EMPTY_ARRAY = [];
124
- export const Sidebar = ({ customURLCallback, customURLLocalStorage, id, isAwaitingLlm, networkIconSuggestions, networks, newlyAddedTemporaryNetworks, onDeleteNetwork, onEditNetwork, setSelectedNetwork, temporaryNetworks = EMPTY_ARRAY, }) => {
125
- // Get default URL from the environment store.
126
- const { backendNeuroSanApiUrl } = useEnvironmentStore();
127
- const [urlInput, setUrlInput] = useState(customURLLocalStorage || backendNeuroSanApiUrl);
128
- const [connectionStatus, setConnectionStatus] = useState(CONNECTION_STATUS.IDLE);
129
- const [testConnectionResult, setTestConnectionResult] = useState(null);
130
- const connectionStatusSuccess = connectionStatus === CONNECTION_STATUS.SUCCESS;
131
- const connectionStatusError = connectionStatus === CONNECTION_STATUS.ERROR;
132
- const isDefaultUrl = urlInput === backendNeuroSanApiUrl;
133
- const saveEnabled = urlInput && (connectionStatusSuccess || (isDefaultUrl && !connectionStatusError));
134
- const [settingsAnchorEl, setSettingsAnchorEl] = useState(null);
135
- const settingsPopoverOpen = Boolean(settingsAnchorEl);
110
+ // For showing server status which can be lengthy
111
+ const ServerStatusTooltip = styled(({ className, ...props }) => (_jsx(Tooltip, { describeChild: true, ...props, classes: { popper: className } })))({
112
+ [`& .${tooltipClasses.tooltip}`]: {
113
+ backgroundColor: "rgba(97, 97, 97, 1)",
114
+ maxWidth: 500,
115
+ opacity: 1,
116
+ },
117
+ });
118
+ //#endregion: Types
119
+ export const Sidebar = ({ id, isAwaitingLlm, isImporting, networkIconSuggestions, networks, neuroSanServerURL, newlyAddedTemporaryNetworks, onDeleteNetwork, onEditNetwork, onImportClick, setSelectedNetwork, temporaryNetworks = EMPTY_ARRAY, }) => {
136
120
  const [expandedItems, setExpandedItems] = useState([]);
137
121
  const [selectedItem, setSelectedItem] = useState(null);
138
- // Theming/Dark mode
139
- const darkMode = useTheme().palette.mode === "dark";
140
- const handleSettingsClick = (event) => {
141
- // On open of Settings popover, reset the connection status to idle
142
- setConnectionStatus(CONNECTION_STATUS.IDLE);
143
- setSettingsAnchorEl(event.currentTarget);
144
- };
145
- const handleSettingsClose = (cancel = false) => {
146
- setSettingsAnchorEl(null);
147
- // If the user cancels, reset the custom URL input to the local storage value, or the default URL
148
- if (cancel) {
149
- setUrlInput(customURLLocalStorage || backendNeuroSanApiUrl);
150
- }
151
- };
152
- const handleURLChange = (event) => {
153
- setUrlInput(event.target.value);
154
- // Reset connection check since URL input was changed
155
- setConnectionStatus(CONNECTION_STATUS.IDLE);
156
- };
157
- const handleDefaultSettings = () => {
158
- // Clear input but don't close the popover
159
- setUrlInput(backendNeuroSanApiUrl);
160
- // Reset connection check since URL input was cleared
161
- setConnectionStatus(CONNECTION_STATUS.IDLE);
162
- };
163
- const handleSaveSettings = () => {
164
- let tempUrl = urlInput;
165
- if (tempUrl.endsWith("/")) {
166
- tempUrl = tempUrl.slice(0, -1);
167
- }
168
- if (tempUrl && !tempUrl.startsWith("http://") && !tempUrl.startsWith("https://")) {
169
- tempUrl = `https://${tempUrl}`;
170
- }
171
- // Call setSelectedNetwork(null) otherwise it can cause issues when switching agent networks (i.e. for Save)
172
- setSelectedNetwork(null);
173
- handleSettingsClose();
174
- customURLCallback(tempUrl);
175
- };
176
- const handleSettingsSaveEnterKey = (event) => {
177
- if (event.key === "Enter" && saveEnabled) {
178
- handleSaveSettings();
179
- }
180
- };
181
- const handleTestConnection = async () => {
182
- const result = await testConnection(urlInput);
183
- setTestConnectionResult(result);
184
- if (result.success) {
185
- setConnectionStatus(CONNECTION_STATUS.SUCCESS);
186
- }
187
- else {
188
- setConnectionStatus(CONNECTION_STATUS.ERROR);
189
- }
190
- };
191
- const handleClearInput = () => {
192
- setUrlInput("");
193
- setConnectionStatus(CONNECTION_STATUS.IDLE);
194
- };
195
- // Fetch Neuro-san version on load and whenever the saved URL changes
122
+ // Display option for agent/network names
123
+ const useNativeNames = useSettingsStore((state) => state.settings.appearance.useNativeNames);
124
+ const [neuroSanServerStatus, setNeuroSanServerStatus] = useState(null);
196
125
  useEffect(() => {
197
- const fetchVersion = async () => {
198
- // We aren't really trying to test the connection here, just getting the version.
199
- const result = await testConnection(customURLLocalStorage || backendNeuroSanApiUrl);
200
- if (result.success) {
201
- setTestConnectionResult(result);
126
+ // Track whether the current request is still valid. If the component unmounts or the URL changes,
127
+ // we want to ignore any results from previous requests.
128
+ let isCurrentRequest = true;
129
+ const checkStatus = async () => {
130
+ const result = await testConnection(neuroSanServerURL);
131
+ if (!isCurrentRequest) {
132
+ return;
202
133
  }
134
+ setNeuroSanServerStatus(result);
203
135
  };
204
- void fetchVersion();
205
- }, [customURLLocalStorage, backendNeuroSanApiUrl]);
136
+ void checkStatus();
137
+ const intervalId = setInterval(checkStatus, NEURO_SAN_PING_INTERVAL_MS);
138
+ return () => {
139
+ isCurrentRequest = false;
140
+ clearInterval(intervalId);
141
+ };
142
+ }, [neuroSanServerURL]);
206
143
  // When the edit pencil is clicked, select the network first (if not already selected) so the network loads
207
144
  // before entering edit mode — the user shouldn't have to click the network and then click the pencil separately.
208
145
  const handleEditNetworkWithSelect = (network) => {
@@ -212,26 +149,21 @@ export const Sidebar = ({ customURLCallback, customURLLocalStorage, id, isAwaiti
212
149
  }
213
150
  onEditNetwork?.(network);
214
151
  };
215
- const { treeViewItems, nodeIndex } = buildTreeViewItems(networks, temporaryNetworks);
216
- const temporaryNetworkExpirationTimes = temporaryNetworks.reduce((acc, tempNetwork) => {
217
- acc[tempNetwork.agentInfo.agent_name] = new Date(tempNetwork.reservation.expiration_time_in_seconds * 1000);
218
- return acc;
219
- }, {});
220
- const temporaryNetworkHoconStrings = temporaryNetworks.reduce((acc, tempNetwork) => {
221
- acc[tempNetwork.agentInfo.agent_name] = tempNetwork.networkHocon;
222
- return acc;
223
- }, {});
152
+ const treeViewItems = buildTreeViewItems(useNativeNames, networks, temporaryNetworks, networkIconSuggestions);
224
153
  const handleSelectedItemsChange = (_event, itemId) => {
225
154
  if (!itemId) {
226
155
  return;
227
156
  }
228
- // Only select leaf nodes (items in nodeIndex) as networks
229
- const isLeafNode = nodeIndex.has(itemId);
230
- if (!isLeafNode) {
157
+ const treeItem = findTreeItemById(treeViewItems, itemId);
158
+ if (!treeItem) {
159
+ return;
160
+ }
161
+ // Only allow selecting child nodes (i.e., actual networks), not parent nodes (folders).
162
+ if (!treeItem.isNetwork) {
231
163
  return;
232
164
  }
233
165
  // Don't allow selecting expired temporary networks
234
- const expirationTime = temporaryNetworkExpirationTimes[itemId];
166
+ const expirationTime = treeItem?.temporaryNetworkExpirationTime;
235
167
  if (expirationTime && expirationTime < new Date()) {
236
168
  return;
237
169
  }
@@ -251,7 +183,7 @@ export const Sidebar = ({ customURLCallback, customURLLocalStorage, id, isAwaiti
251
183
  in MUI RichTreeView including the imperative API (https://mui.com/x/react-tree-view/rich-tree-view/selection/#imperative-api)
252
184
  but couldn't get it to work so resorting to this for now.
253
185
  */
254
- const temporaryNetworkNode = document.querySelector(`[data-itemid="${firstItem}"]`);
186
+ const temporaryNetworkNode = document.querySelector(`[data-itemid="${CSS.escape(firstItem)}"]`);
255
187
  if (temporaryNetworkNode) {
256
188
  temporaryNetworkNode.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
257
189
  temporaryNetworkNode.classList.add(SPARKLE_HIGHLIGHT_CLASS);
@@ -266,53 +198,30 @@ export const Sidebar = ({ customURLCallback, customURLLocalStorage, id, isAwaiti
266
198
  clearTimeout(removeHighlightTimeout);
267
199
  };
268
200
  }, [newlyAddedTemporaryNetworks]);
269
- return (_jsxs(_Fragment, { children: [_jsxs(SidebarAside, { id: `${id}-sidebar`, children: [_jsxs(SidebarHeading, { id: `${id}-heading`, children: ["Agent Networks", _jsxs(Box, { sx: { display: "flex" }, children: [_jsx(Button, { "aria-label": "Add New Network", disabled: isAwaitingLlm, id: "add-network-btn", onClick: () => {
270
- setSelectedItem(AGENT_NETWORK_DESIGNER_ID);
271
- setSelectedNetwork(AGENT_NETWORK_DESIGNER_ID);
272
- }, sx: { display: "inline-block", minWidth: "40px" }, children: _jsx(Tooltip, { title: "Create your own agent network", placement: "top", children: _jsx(AddBoxRounded, { id: "add-network-icon", sx: { color: isAwaitingLlm ? "rgba(0, 0, 0, 0.12)" : "var(--bs-secondary)" } }) }) }), _jsx(Button, { "aria-label": "Agent Network Settings", disabled: isAwaitingLlm, id: "agent-network-settings-btn", onClick: handleSettingsClick, sx: { display: "inline-block", minWidth: "40px" }, children: _jsx(Tooltip, { id: "agent-network-settings-tooltip", placement: "top", title: `${customURLLocalStorage || backendNeuroSanApiUrl}\nversion: ${testConnectionResult?.version || "unknown"}`, children: _jsx(SettingsIcon, { id: "agent-network-settings-icon", sx: {
273
- color: isAwaitingLlm ? "rgba(0, 0, 0, 0.12)" : "var(--bs-secondary)",
274
- } }) }) })] })] }), _jsx(RichTreeView, { items: treeViewItems, expandedItems: expandedItems, onExpandedItemsChange: (_event, itemIds) => setExpandedItems(itemIds), multiSelect: false, onSelectedItemsChange: handleSelectedItemsChange, selectedItems: selectedItem, disableSelection: isAwaitingLlm, slots: {
275
- item: AgentNetworkTreeItem,
276
- },
277
- // Pass custom props to tree items via slotProps.
278
- // Reference: https://github.com/mui/mui-x/issues/13351
279
- slotProps: {
280
- item: {
281
- networkIconSuggestions,
282
- nodeIndex,
283
- onDeleteNetwork,
284
- onEditNetwork: handleEditNetworkWithSelect,
285
- temporaryNetworkExpirationTimes,
286
- temporaryNetworkHoconStrings,
287
- },
288
- } }, Object.keys(networkIconSuggestions || {}).length)] }), _jsxs(Popover, { id: "agent-network-settings-popover", open: settingsPopoverOpen, anchorEl: settingsAnchorEl, onClose: () => handleSettingsClose(true), anchorOrigin: {
289
- vertical: "bottom",
290
- horizontal: "left",
291
- }, slotProps: {
292
- paper: {
293
- sx: {
294
- paddingTop: "0.75rem",
295
- paddingLeft: "0.5rem",
296
- paddingRight: "0.5rem",
297
- paddingBottom: "0.2rem",
298
- },
299
- },
300
- }, children: [_jsx(TextField, { autoComplete: "off", label: "Agent server address", id: "agent-network-settings-url", onChange: handleURLChange, onKeyUp: handleSettingsSaveEnterKey, placeholder: "https://my_server_address:port", size: "small", sx: { marginBottom: "0.5rem", minWidth: "400px" }, type: "url", variant: "outlined", value: urlInput, slotProps: {
301
- input: {
302
- endAdornment: urlInput && urlInput !== backendNeuroSanApiUrl ? (_jsx(InputAdornment, { id: "clear-input-adornment", position: "end", children: _jsx(IconButton, { id: "clear-input-icon-button", edge: "end", onClick: handleClearInput, size: "small", "aria-label": "Clear input", children: _jsx(ClearIcon, { fontSize: "small", id: "clear-input-icon" }) }) })) : undefined,
303
- },
304
- } }), _jsx(PrimaryButton, { disabled: !urlInput, id: "agent-network-settings-test-btn", onClick: handleTestConnection, variant: "contained", children: "Test" }), _jsx(PrimaryButton, { disabled: !saveEnabled, id: "agent-network-settings-save-btn", onClick: handleSaveSettings, variant: "contained", children: "Save" }), _jsx(PrimaryButton, { id: "agent-network-settings-cancel-btn", onClick: () => handleSettingsClose(true), variant: "contained", children: "Cancel" }), _jsx(Button, { id: "agent-network-settings-default-btn", onClick: handleDefaultSettings, sx: {
305
- marginLeft: "0.35rem",
306
- marginTop: "2px",
307
- color: darkMode ? "var(--bs-dark-mode-link)" : undefined,
308
- }, variant: "text", children: "Default" }), (connectionStatusSuccess || connectionStatusError) && (_jsxs(Box, { id: "connection-status-box", sx: {
309
- display: "flex",
310
- alignItems: "center",
311
- marginLeft: "0.25rem",
312
- marginBottom: "0.5rem",
313
- }, children: [connectionStatusSuccess && (_jsxs(_Fragment, { children: [_jsx(CheckCircleOutlinedIcon, { id: "connection-status-success-icon", sx: { color: "var(--bs-green)", fontSize: "1.2rem", marginRight: "0.25rem" } }), _jsx(Typography, { id: "connection-status-success-msg", variant: "body2", sx: {
314
- color: "var(--bs-green)",
315
- }, children: "Connected successfully" })] })), connectionStatusError && (_jsxs(_Fragment, { children: [_jsx(HighlightOff, { id: "connection-status-error-icon", sx: { color: "var(--bs-red)", fontSize: "1.2rem", marginRight: "0.25rem" } }), _jsx(Typography, { id: "connection-status-failed-msg", variant: "body2", sx: {
316
- color: "var(--bs-red)",
317
- }, children: `Connection failed: "${testConnectionResult?.status || "unknown error"}"` })] }))] }))] })] }));
201
+ const toStatusColor = () => {
202
+ switch (neuroSanServerStatus?.success) {
203
+ case true:
204
+ return "green";
205
+ case false:
206
+ return "red";
207
+ case undefined:
208
+ default:
209
+ return "unknown";
210
+ }
211
+ };
212
+ const mapStatus = (statusText) => (statusText === "ok" ? "online" : (statusText ?? "unknown"));
213
+ const getStatusLight = () => (_jsx(ServerStatusTooltip, { slotProps: {
214
+ popper: {
215
+ "aria-label": "Neuro-san server status",
216
+ },
217
+ }, title: _jsxs(Box, { sx: { display: "flex", flexDirection: "column", gap: 0.5 }, children: [_jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "Status:" }), " ", mapStatus(neuroSanServerStatus?.statusText)] }), _jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "URL:" }), " ", neuroSanServerURL || "unknown"] }), _jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "Service:" }), " ", neuroSanServerStatus?.healthCheckResponse?.service || "unknown"] }), _jsx(Typography, { sx: { fontWeight: "bold" }, variant: "body2", children: "Versions:" }), _jsxs(Box, { sx: { ml: 1 }, children: [_jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "Neuro SAN:" }), " ", neuroSanServerStatus?.healthCheckResponse?.versions?.["neuro-san"] ?? "unknown"] }), _jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "Neuro SAN Studio:" }), " ", neuroSanServerStatus?.healthCheckResponse?.versions?.["neuro-san-studio"] ?? "unknown"] })] }), !neuroSanServerStatus?.success && neuroSanServerStatus?.httpStatus && (_jsx(_Fragment, { children: _jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "HTTP status:" }), " ", `${neuroSanServerStatus.httpStatus} (${httpStatus[neuroSanServerStatus.httpStatus] ?? "Unknown status"})`] }) }))] }), placement: "right", children: _jsx("span", { children: _jsx(StatusLight, { id: `${id}-agent-network-status-light`, statusValue: toStatusColor() }) }) }));
218
+ const getAddNetworkButton = () => (_jsxs(Box, { sx: { display: "flex" }, children: [_jsx(Button, { "aria-label": "Add New Network", disabled: isAwaitingLlm, id: "add-network-btn", onClick: () => {
219
+ setSelectedItem(AGENT_NETWORK_DESIGNER_ID);
220
+ setSelectedNetwork(AGENT_NETWORK_DESIGNER_ID);
221
+ }, sx: { display: "inline-block", minWidth: "40px" }, children: _jsx(Tooltip, { title: "Create your own agent network", placement: "top", children: _jsx(AddBoxRounded, { id: "add-network-icon", sx: { color: "var(--bs-secondary)" } }) }) }), _jsx(Button, { "aria-label": "Import Network Definition", disabled: isAwaitingLlm || isImporting, id: "import-network-btn", onClick: onImportClick, sx: { display: "inline-block", minWidth: "40px" }, children: _jsx(Tooltip, { title: "Import a network definition file", placement: "top", children: _jsx(FileUploadOutlinedIcon, { id: "import-network-icon", sx: { color: isAwaitingLlm || isImporting ? "rgba(0, 0, 0, 0.12)" : "var(--bs-secondary)" } }) }) })] }));
222
+ const getSidebarHeading = () => (_jsxs(SidebarHeading, { id: `${id}-heading`, children: [_jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: (theme) => theme.spacing(1.5) }, children: [getStatusLight(), "Agent Networks"] }), getAddNetworkButton()] }));
223
+ const getSidebarNetworksTree = () => (_jsx(RichTreeView, { disableSelection: isAwaitingLlm, expandedItems: expandedItems, items: treeViewItems, multiSelect: false, onExpandedItemsChange: (_event, itemIds) => setExpandedItems(itemIds), onSelectedItemsChange: handleSelectedItemsChange, selectedItems: selectedItem, slotProps: {
224
+ item: { onDeleteNetwork, onEditNetwork: handleEditNetworkWithSelect },
225
+ }, slots: { item: AgentNetworkTreeItem } }));
226
+ return (_jsxs(SidebarAside, { id: `${id}-sidebar`, children: [getSidebarHeading(), getSidebarNetworksTree()] }));
318
227
  };
@@ -1,20 +1,38 @@
1
1
  import { TreeViewDefaultItemModelProperties } from "@mui/x-tree-view/models";
2
2
  import { AgentInfo } from "../../../generated/neuro-san/NeuroSanClient.js";
3
3
  import { TemporaryNetwork } from "../../../state/TemporaryNetworks.js";
4
- export type NodeIndex = Map<string, {
5
- agentInfo: AgentInfo;
6
- displayName: string;
7
- }>;
4
+ import { AgentNetworkDefinitionEntry } from "../const.js";
5
+ /**
6
+ * Represents either a category (folder) or a network (leaf) in the tree view.
7
+ * Note that we omit the `children` property from the parent as we want to use read-only semantics
8
+ */
9
+ export interface AgentNetworkTreeItemModel extends Omit<TreeViewDefaultItemModelProperties, "children"> {
10
+ readonly children?: readonly AgentNetworkTreeItemModel[];
11
+ readonly displayName: string;
12
+ readonly iconSuggestion?: string;
13
+ readonly isNetwork: boolean;
14
+ readonly tags?: readonly string[];
15
+ readonly temporaryNetworkExpirationTime?: Date;
16
+ readonly temporaryNetworkDefinition?: readonly AgentNetworkDefinitionEntry[];
17
+ }
18
+ /**
19
+ * Recursively searches for a tree item with the specified ID within the given list of tree items.
20
+ * @param items - The list of tree items to search through
21
+ * @param itemId - The ID of the tree item to find
22
+ * @returns The tree item with the matching ID, or undefined if not found
23
+ *
24
+ * @note Short-circuiting is used to avoid unnecessary searches once a match is found (compared to e.g., `flatMap()`)
25
+ */
26
+ export declare const findTreeItemById: (items: readonly AgentNetworkTreeItemModel[], itemId: string) => AgentNetworkTreeItemModel | undefined;
8
27
  /**
9
28
  * Build a tree view structure from a flat list of networks.
10
29
  * The list of networks comes from a call to the Neuro-san /list API
11
- * The tree structure is used by the RichTreeView component to display the networks
12
- * @param networks - Array of networks from the Neuro-san /list API
13
- * @param temporaryNetworks - Array of temporary networks (e.g. ones recently created by the user)
14
- * @returns Array of {@linkcode TreeViewDefaultItemModelProperties} objects representing the tree structure and an
15
- * index for rapid access
30
+ * The tree structure is used by the RichTreeView component to display the networks.
31
+ *
32
+ * @param useNativeNames - Whether to use the raw agent names from the API or to clean them up for display.
33
+ * @param regularNetworks - Array of networks from the Neuro-san /list API
34
+ * @param temporaryNetworks - Array of temporary networks (e.g., ones recently created by the user)
35
+ * @param iconSuggestions
36
+ * @returns Array of {@linkcode AgentNetworkTreeItemModel} objects representing the tree structure
16
37
  */
17
- export declare const buildTreeViewItems: (networks: readonly AgentInfo[], temporaryNetworks: readonly TemporaryNetwork[]) => {
18
- treeViewItems: TreeViewDefaultItemModelProperties[];
19
- nodeIndex: NodeIndex;
20
- };
38
+ export declare const buildTreeViewItems: (useNativeNames: boolean, regularNetworks?: readonly AgentInfo[], temporaryNetworks?: readonly TemporaryNetwork[], iconSuggestions?: Record<string, string>) => AgentNetworkTreeItemModel[];