@cognizant-ai-lab/ui-common 1.3.3 → 1.4.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/README.md +287 -0
- package/dist/Theme/Palettes.d.ts +18 -0
- package/dist/Theme/Palettes.js +94 -0
- package/dist/Theme/Theme.d.ts +22 -0
- package/dist/Theme/Theme.js +58 -0
- package/dist/components/AgentChat/ChatCommon.d.ts +4 -2
- package/dist/components/AgentChat/ChatCommon.js +141 -105
- package/dist/components/AgentChat/ControlButtons.js +3 -1
- package/dist/components/AgentChat/FormattedMarkdown.d.ts +4 -4
- package/dist/components/AgentChat/FormattedMarkdown.js +5 -7
- package/dist/components/AgentChat/LlmChatButton.d.ts +2 -6
- package/dist/components/AgentChat/LlmChatButton.js +3 -3
- package/dist/components/AgentChat/UserQueryDisplay.js +2 -4
- package/dist/components/AgentChat/Utils.d.ts +2 -1
- package/dist/components/AgentChat/Utils.js +4 -1
- package/dist/components/AgentChat/VoiceChat/MicrophoneButton.d.ts +2 -2
- package/dist/components/AgentChat/VoiceChat/VoiceChat.d.ts +3 -3
- package/dist/components/AgentChat/VoiceChat/VoiceChat.js +5 -5
- package/dist/components/ChatBot/ChatBot.js +2 -2
- package/dist/components/Common/Breadcrumbs.js +1 -1
- package/dist/components/Common/{confirmationModal.js → ConfirmationModal.js} +2 -5
- package/dist/components/Common/CustomerLogo.d.ts +17 -0
- package/dist/components/Common/CustomerLogo.js +49 -0
- package/dist/components/Common/Footer.d.ts +18 -0
- package/dist/components/Common/Footer.js +59 -0
- package/dist/components/Common/LlmChatOptionsButton.d.ts +1 -4
- package/dist/components/Common/LlmChatOptionsButton.js +4 -4
- package/dist/components/Common/LoadingSpinner.js +1 -1
- package/dist/components/Common/MUIAccordion.d.ts +2 -2
- package/dist/components/Common/MUIAccordion.js +2 -12
- package/dist/components/Common/MUIAlert.d.ts +2 -1
- package/dist/components/Common/MUIAlert.js +4 -1
- package/dist/components/Common/MUIDialog.d.ts +1 -1
- package/dist/components/Common/MUIDialog.js +1 -1
- package/dist/components/Common/Navbar.d.ts +3 -1
- package/dist/components/Common/Navbar.js +60 -35
- package/dist/components/Common/PageLoader.js +3 -4
- package/dist/components/Common/Snackbar.d.ts +4 -1
- package/dist/components/Common/Snackbar.js +11 -19
- package/dist/components/Common/notification.d.ts +3 -3
- package/dist/components/Common/notification.js +6 -6
- package/dist/components/ErrorPage/ErrorBoundary.d.ts +2 -2
- package/dist/components/ErrorPage/ErrorBoundary.js +1 -1
- package/dist/components/ErrorPage/ErrorPage.js +6 -5
- package/dist/components/MultiAgentAccelerator/AgentConversations.d.ts +17 -0
- package/dist/components/MultiAgentAccelerator/AgentConversations.js +77 -0
- package/dist/components/MultiAgentAccelerator/AgentCounts.d.ts +12 -0
- package/dist/components/MultiAgentAccelerator/AgentCounts.js +21 -0
- package/dist/components/MultiAgentAccelerator/AgentFlow.d.ts +6 -4
- package/dist/components/MultiAgentAccelerator/AgentFlow.js +106 -185
- package/dist/components/MultiAgentAccelerator/AgentNode.d.ts +7 -5
- package/dist/components/MultiAgentAccelerator/AgentNode.js +93 -50
- package/dist/components/MultiAgentAccelerator/GraphLayouts.d.ts +20 -17
- package/dist/components/MultiAgentAccelerator/GraphLayouts.js +16 -14
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +2 -3
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +214 -55
- package/dist/components/MultiAgentAccelerator/PlasmaEdge.d.ts +1 -1
- package/dist/components/MultiAgentAccelerator/PlasmaEdge.js +14 -12
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.d.ts +15 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.js +104 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.d.ts +17 -0
- package/dist/components/MultiAgentAccelerator/{Sidebar.js → Sidebar/Sidebar.js} +146 -59
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.d.ts +19 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.js +113 -0
- package/dist/components/MultiAgentAccelerator/TemporaryNetworks.d.ts +26 -0
- package/dist/components/MultiAgentAccelerator/TemporaryNetworks.js +20 -0
- package/dist/components/MultiAgentAccelerator/ThoughtBubbleEdge.d.ts +10 -8
- package/dist/components/MultiAgentAccelerator/ThoughtBubbleEdge.js +1 -1
- package/dist/components/MultiAgentAccelerator/ThoughtBubbleOverlay.d.ts +3 -2
- package/dist/components/MultiAgentAccelerator/ThoughtBubbleOverlay.js +10 -13
- package/dist/components/MultiAgentAccelerator/const.d.ts +1 -3
- package/dist/components/MultiAgentAccelerator/const.js +4 -18
- package/dist/components/Settings/FadingCheckmark.d.ts +14 -0
- package/dist/components/Settings/FadingCheckmark.js +43 -0
- package/dist/components/Settings/SettingsDialog.d.ts +9 -0
- package/dist/components/Settings/SettingsDialog.js +265 -0
- package/dist/const.d.ts +1 -2
- package/dist/const.js +2 -3
- package/dist/controller/Types/AgentIconSuggestions.d.ts +4 -0
- package/dist/controller/Types/AgentIconSuggestions.js +1 -0
- package/dist/controller/Types/Branding.d.ts +12 -0
- package/dist/controller/Types/Branding.js +1 -0
- package/dist/controller/Types/NetworkIconSuggestions.d.ts +4 -0
- package/dist/controller/Types/NetworkIconSuggestions.js +1 -0
- package/dist/controller/agent/Agent.d.ts +32 -12
- package/dist/controller/agent/Agent.js +71 -19
- package/dist/controller/llm/LlmChat.d.ts +1 -1
- package/dist/controller/llm/LlmChat.js +2 -2
- package/dist/index.d.ts +10 -5
- package/dist/index.js +10 -5
- package/dist/state/{environment.d.ts → Environment.d.ts} +2 -0
- package/dist/state/{environment.js → Environment.js} +2 -0
- package/dist/state/Settings.d.ts +62 -0
- package/dist/state/Settings.js +62 -0
- package/dist/state/TemporaryNetworks.d.ts +32 -0
- package/dist/state/TemporaryNetworks.js +26 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/Authentication.d.ts +2 -2
- package/dist/utils/Authentication.js +6 -6
- package/dist/utils/text.d.ts +2 -2
- package/dist/utils/text.js +3 -5
- package/dist/utils/title.d.ts +1 -1
- package/dist/utils/title.js +2 -2
- package/dist/utils/useLocalStorage.d.ts +1 -1
- package/dist/utils/useLocalStorage.js +3 -3
- package/dist/utils/zIndexLayers.d.ts +1 -1
- package/dist/utils/zIndexLayers.js +3 -15
- package/package.json +23 -21
- package/dist/components/MultiAgentAccelerator/Sidebar.d.ts +0 -12
- package/dist/utils/Theme.d.ts +0 -7
- package/dist/utils/Theme.js +0 -7
- package/dist/utils/agentConversations.d.ts +0 -24
- package/dist/utils/agentConversations.js +0 -113
- /package/dist/components/Common/{confirmationModal.d.ts → ConfirmationModal.d.ts} +0 -0
|
@@ -14,37 +14,70 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
14
14
|
See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
|
16
16
|
*/
|
|
17
|
-
import
|
|
17
|
+
import StopCircle from "@mui/icons-material/StopCircle";
|
|
18
18
|
import Box from "@mui/material/Box";
|
|
19
|
+
import Collapse from "@mui/material/Collapse";
|
|
19
20
|
import Grid from "@mui/material/Grid";
|
|
20
21
|
import Slide from "@mui/material/Slide";
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
22
|
+
import { ReactFlowProvider } from "@xyflow/react";
|
|
23
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
24
|
+
import { extractConversations } from "./AgentConversations.js";
|
|
25
|
+
import { getUpdatedAgentCounts } from "./AgentCounts.js";
|
|
23
26
|
import { AgentFlow } from "./AgentFlow.js";
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
+
import { TEMPORARY_NETWORK_FOLDER } from "./const.js";
|
|
28
|
+
import { Sidebar } from "./Sidebar/Sidebar.js";
|
|
29
|
+
import { extractReservations } from "./TemporaryNetworks.js";
|
|
30
|
+
import { getAgentIconSuggestions, getAgentNetworks, getConnectivity, getNetworkIconSuggestions, } from "../../controller/agent/Agent.js";
|
|
31
|
+
import { useSettingsStore } from "../../state/Settings.js";
|
|
32
|
+
import { useTempNetworksStore } from "../../state/TemporaryNetworks.js";
|
|
27
33
|
import { useLocalStorage } from "../../utils/useLocalStorage.js";
|
|
28
34
|
import { ChatCommon } from "../AgentChat/ChatCommon.js";
|
|
29
35
|
import { SmallLlmChatButton } from "../AgentChat/LlmChatButton.js";
|
|
30
|
-
import { cleanUpAgentName } from "../AgentChat/Utils.js";
|
|
36
|
+
import { chatMessageFromChunk, cleanUpAgentName, removeTrailingUuid } from "../AgentChat/Utils.js";
|
|
37
|
+
import { ConfirmationModal } from "../Common/ConfirmationModal.js";
|
|
38
|
+
import { MUIAlert } from "../Common/MUIAlert.js";
|
|
31
39
|
import { closeNotification, NotificationType, sendNotification } from "../Common/notification.js";
|
|
40
|
+
// Display expired temporary networks for this amount of time after they expire so users can see what happened
|
|
41
|
+
const GRACE_PERIOD_MS = 5 * 60 * 1000; // 5 minutes
|
|
42
|
+
// Animation time for the left and right panels to slide in or out when launching the animation
|
|
43
|
+
const GROW_ANIMATION_TIME_MS = 800;
|
|
44
|
+
/**
|
|
45
|
+
* Helper function to convert agent reservations received from the backend into temporary networks that can be displayed
|
|
46
|
+
* in the tree.
|
|
47
|
+
* @param agentReservations List of "agent reservations" (temporary networks) received from the backend
|
|
48
|
+
* @returns List of TemporaryNetwork objects that can be displayed in the UI
|
|
49
|
+
*/
|
|
50
|
+
const convertReservationsToNetworks = (agentReservations) => {
|
|
51
|
+
return agentReservations.map((reservation) => ({
|
|
52
|
+
reservation,
|
|
53
|
+
agentInfo: {
|
|
54
|
+
agent_name: `${TEMPORARY_NETWORK_FOLDER}/${reservation.reservation_id}`,
|
|
55
|
+
origin: reservation.reservation_id,
|
|
56
|
+
status: "active",
|
|
57
|
+
},
|
|
58
|
+
}));
|
|
59
|
+
};
|
|
32
60
|
/**
|
|
33
61
|
* Main Multi-Agent Accelerator component that contains the sidebar, agent flow, and chat components.
|
|
34
62
|
* @param backendNeuroSanApiUrl Initial URL of the backend Neuro-San API. User can change this in the UI.
|
|
35
63
|
* @param darkMode Whether dark mode is enabled.
|
|
36
64
|
* @param userInfo Information about the current user, including userName and userImage.
|
|
37
65
|
*/
|
|
38
|
-
export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl,
|
|
39
|
-
|
|
40
|
-
const GROW_ANIMATION_TIME_MS = 800;
|
|
66
|
+
export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
67
|
+
const enableZenMode = useSettingsStore((state) => state.settings.behavior.enableZenMode);
|
|
41
68
|
// Stores whether are currently awaiting LLM response (for knowing when to show spinners)
|
|
42
69
|
const [isAwaitingLlm, setIsAwaitingLlm] = useState(false);
|
|
43
70
|
// Track streaming state - controls thought bubble cleanup timer, and enables "zen mode" (hides outer panels after
|
|
44
71
|
// animation)
|
|
45
72
|
const [isStreaming, setIsStreaming] = useState(false);
|
|
46
73
|
const [networks, setNetworks] = useState([]);
|
|
74
|
+
// List of known temporary networks (agent reservations) received from the backend
|
|
75
|
+
const temporaryNetworks = useTempNetworksStore((state) => state.tempNetworks);
|
|
76
|
+
// Track newly added temp networks so we can highlight them
|
|
77
|
+
const [newlyAddedTemporaryNetworks, setNewlyAddedTemporaryNetworks] = useState(new Set());
|
|
78
|
+
const [networkIconSuggestions, setNetworkIconSuggestions] = useState({});
|
|
47
79
|
const [agentsInNetwork, setAgentsInNetwork] = useState([]);
|
|
80
|
+
const [agentIconSuggestions, setAgentIconSuggestions] = useState(null);
|
|
48
81
|
const [selectedNetwork, setSelectedNetwork] = useState(null);
|
|
49
82
|
// Track whether we've shown the info popup so we don't keep bugging the user with it
|
|
50
83
|
const [haveShownPopup, setHaveShownPopup] = useState(false);
|
|
@@ -53,13 +86,22 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, darkMode, userInf
|
|
|
53
86
|
const [neuroSanURL, setNeuroSanURL] = useState(customURLLocalStorage?.replaceAll('"', "") || backendNeuroSanApiUrl);
|
|
54
87
|
const agentCountsRef = useRef(new Map());
|
|
55
88
|
const conversationsRef = useRef(null);
|
|
56
|
-
const [currentConversations, setCurrentConversations] = useState(
|
|
89
|
+
const [currentConversations, setCurrentConversations] = useState([]);
|
|
90
|
+
const [networkToBeDeleted, setNetworkToBeDeleted] = useState(null);
|
|
57
91
|
// State to hold thought bubble edges - avoids duplicates across layout recalculations
|
|
58
92
|
const [thoughtBubbleEdges, setThoughtBubbleEdges] = useState(new Map());
|
|
93
|
+
// For controlling alert when temporary network is created
|
|
94
|
+
const [alertContents, setAlertContents] = useState(null);
|
|
59
95
|
const customURLCallback = useCallback((url) => {
|
|
60
96
|
setNeuroSanURL(url || backendNeuroSanApiUrl);
|
|
61
97
|
setCustomURLLocalStorage(url === "" ? null : url);
|
|
62
98
|
}, [backendNeuroSanApiUrl, setCustomURLLocalStorage]);
|
|
99
|
+
// Memoized key for agent names to trigger icon suggestion updates when the set of agents changes, not just
|
|
100
|
+
// when sorting/other operations on the agents list
|
|
101
|
+
const agentNamesKey = useMemo(() => agentsInNetwork
|
|
102
|
+
.map((agent) => agent.origin)
|
|
103
|
+
.sort()
|
|
104
|
+
.join(","), [agentsInNetwork]);
|
|
63
105
|
const resetState = useCallback(() => {
|
|
64
106
|
setThoughtBubbleEdges(new Map());
|
|
65
107
|
setIsStreaming(false);
|
|
@@ -72,25 +114,36 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, darkMode, userInf
|
|
|
72
114
|
resetState();
|
|
73
115
|
}, []);
|
|
74
116
|
useEffect(() => {
|
|
75
|
-
|
|
117
|
+
;
|
|
118
|
+
(async () => {
|
|
76
119
|
try {
|
|
77
120
|
const networksTmp = await getAgentNetworks(neuroSanURL);
|
|
78
|
-
|
|
79
|
-
setNetworks(sortedNetworks);
|
|
80
|
-
// Set the first network as the selected network
|
|
81
|
-
setSelectedNetwork(sortedNetworks[0]);
|
|
121
|
+
setNetworks(networksTmp);
|
|
82
122
|
closeNotification();
|
|
83
123
|
}
|
|
84
124
|
catch (e) {
|
|
85
|
-
sendNotification(NotificationType.error, "Connection error",
|
|
86
|
-
|
|
87
|
-
`Unable to get list of Agent Networks. Verify that ${neuroSanURL} is a valid Multi-Agent Accelerator Server. Error: ${e}.`);
|
|
125
|
+
sendNotification(NotificationType.error, "Connection error", `Unable to get list of Agent Networks. Verify that ${neuroSanURL} is a valid ` +
|
|
126
|
+
`Multi-Agent Accelerator Server. Error: ${e}.`);
|
|
88
127
|
setNetworks([]);
|
|
89
128
|
setSelectedNetwork(null);
|
|
90
129
|
}
|
|
91
|
-
}
|
|
92
|
-
void getNetworks();
|
|
130
|
+
})();
|
|
93
131
|
}, [neuroSanURL]);
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
;
|
|
134
|
+
(async () => {
|
|
135
|
+
if (networks?.length > 0) {
|
|
136
|
+
try {
|
|
137
|
+
const suggestions = await getNetworkIconSuggestions(networks);
|
|
138
|
+
setNetworkIconSuggestions(suggestions);
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
console.warn("Unable to get network icon suggestions from LLM:", e);
|
|
142
|
+
setNetworkIconSuggestions({});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
})();
|
|
146
|
+
}, [networks]);
|
|
94
147
|
useEffect(() => {
|
|
95
148
|
;
|
|
96
149
|
(async () => {
|
|
@@ -101,17 +154,37 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, darkMode, userInf
|
|
|
101
154
|
.concat()
|
|
102
155
|
.sort((a, b) => a?.origin.localeCompare(b?.origin));
|
|
103
156
|
setAgentsInNetwork(agentsInNetworkSorted);
|
|
157
|
+
setAgentIconSuggestions(null);
|
|
158
|
+
closeNotification();
|
|
104
159
|
}
|
|
105
160
|
catch (e) {
|
|
106
161
|
const networkName = cleanUpAgentName(selectedNetwork);
|
|
107
|
-
sendNotification(NotificationType.error, "Connection error",
|
|
108
|
-
|
|
109
|
-
`Unable to get agent list for "${networkName}". Verify that ${neuroSanURL} is a valid Multi-Agent Accelerator Server. Error: ${e}.`);
|
|
162
|
+
sendNotification(NotificationType.error, "Connection error", `Unable to get agent list for "${networkName}". Verify that ${neuroSanURL} is a valid ` +
|
|
163
|
+
`Multi-Agent Accelerator Server. Error: ${e}.`);
|
|
110
164
|
setAgentsInNetwork([]);
|
|
111
165
|
}
|
|
112
166
|
}
|
|
167
|
+
else {
|
|
168
|
+
setAgentsInNetwork([]);
|
|
169
|
+
}
|
|
113
170
|
})();
|
|
114
171
|
}, [neuroSanURL, selectedNetwork]);
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
;
|
|
174
|
+
(async () => {
|
|
175
|
+
if (agentsInNetwork.length > 0) {
|
|
176
|
+
try {
|
|
177
|
+
const connectivity = { connectivity_info: agentsInNetwork };
|
|
178
|
+
const agentIconSuggestionsTmp = await getAgentIconSuggestions(connectivity);
|
|
179
|
+
setAgentIconSuggestions(agentIconSuggestionsTmp);
|
|
180
|
+
}
|
|
181
|
+
catch (e) {
|
|
182
|
+
console.warn("Unable to get agent icon suggestions:", e);
|
|
183
|
+
setAgentIconSuggestions(null);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
})();
|
|
187
|
+
}, [agentNamesKey]);
|
|
115
188
|
// Set up handler to allow Escape key to stop the interaction with the LLM.
|
|
116
189
|
useEffect(() => {
|
|
117
190
|
if (!isAwaitingLlm) {
|
|
@@ -131,16 +204,61 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, darkMode, userInf
|
|
|
131
204
|
setIsStreaming(false);
|
|
132
205
|
}
|
|
133
206
|
}, [isAwaitingLlm]);
|
|
207
|
+
// Reaper: remove temporary networks that have been expired for more than GRACE_PERIOD_MS
|
|
208
|
+
useEffect(() => {
|
|
209
|
+
if (temporaryNetworks.length === 0)
|
|
210
|
+
return undefined;
|
|
211
|
+
const interval = setInterval(() => {
|
|
212
|
+
const now = Date.now() / 1000; // convert to seconds since epoch
|
|
213
|
+
const currentTemporaryNetworks = useTempNetworksStore.getState().tempNetworks;
|
|
214
|
+
// Remove networks that have been expired for more than GRACE_PERIOD_MS
|
|
215
|
+
useTempNetworksStore
|
|
216
|
+
.getState()
|
|
217
|
+
.setTempNetworks(currentTemporaryNetworks.filter((n) => n.reservation.expiration_time_in_seconds > now - GRACE_PERIOD_MS / 1000));
|
|
218
|
+
// Figure out which networks have expired on the server (not including our grace period) so we can
|
|
219
|
+
// deselect them if they're currently selected
|
|
220
|
+
const expiredNetwork = currentTemporaryNetworks.filter((network) => network.reservation.expiration_time_in_seconds <= now);
|
|
221
|
+
// If the selected network is one of the expired ones, deselect it
|
|
222
|
+
if (expiredNetwork.some((n) => n.agentInfo.agent_name === selectedNetwork)) {
|
|
223
|
+
setSelectedNetwork(null);
|
|
224
|
+
agentCountsRef.current = new Map();
|
|
225
|
+
}
|
|
226
|
+
}, 10_000); // check every 10s
|
|
227
|
+
return () => clearInterval(interval);
|
|
228
|
+
}, [temporaryNetworks, selectedNetwork]);
|
|
134
229
|
const onChunkReceived = useCallback((chunk) => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
230
|
+
// Extract ChatMessage structure
|
|
231
|
+
const chatMessage = chatMessageFromChunk(chunk);
|
|
232
|
+
if (!chatMessage) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
// Conversations between agents
|
|
236
|
+
const result = extractConversations(chatMessage, conversationsRef.current);
|
|
237
|
+
if (result != null) {
|
|
238
|
+
conversationsRef.current = result;
|
|
239
|
+
setCurrentConversations(result);
|
|
140
240
|
}
|
|
141
|
-
|
|
241
|
+
// Agent hit counts
|
|
242
|
+
agentCountsRef.current = getUpdatedAgentCounts(agentCountsRef.current, chatMessage?.origin);
|
|
243
|
+
// Temporary networks/reservations
|
|
244
|
+
const reservationsResult = extractReservations(chatMessage);
|
|
245
|
+
// Handle agent reservations (temporary networks) that come in through the chat stream.
|
|
246
|
+
if (reservationsResult?.length > 0) {
|
|
247
|
+
const newTemporaryNetworks = convertReservationsToNetworks(reservationsResult);
|
|
248
|
+
const currentNetworks = useTempNetworksStore.getState().tempNetworks;
|
|
249
|
+
useTempNetworksStore.getState().setTempNetworks([...currentNetworks, ...newTemporaryNetworks]);
|
|
250
|
+
// record the new temporary networks so we can select them for the user. For now, we only
|
|
251
|
+
// care about the first one.
|
|
252
|
+
setNewlyAddedTemporaryNetworks(new Set(newTemporaryNetworks.map((network) => network.agentInfo.agent_name)));
|
|
253
|
+
}
|
|
254
|
+
return true;
|
|
142
255
|
}, []);
|
|
143
256
|
const onStreamingStarted = useCallback(() => {
|
|
257
|
+
// Reset agent counts
|
|
258
|
+
agentCountsRef.current = new Map();
|
|
259
|
+
// Reset newly added temporary networks
|
|
260
|
+
setNewlyAddedTemporaryNetworks(new Set());
|
|
261
|
+
setAlertContents(null);
|
|
144
262
|
// Show info popup only once per session
|
|
145
263
|
if (!haveShownPopup) {
|
|
146
264
|
sendNotification(NotificationType.info, "Agents working", "Click the stop button or hit Escape to exit.");
|
|
@@ -150,21 +268,55 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, darkMode, userInf
|
|
|
150
268
|
setIsStreaming(true);
|
|
151
269
|
}, [haveShownPopup]);
|
|
152
270
|
const onStreamingComplete = useCallback(() => {
|
|
271
|
+
const network = newlyAddedTemporaryNetworks?.values().next().value;
|
|
272
|
+
if (network?.length > 0) {
|
|
273
|
+
// We show an Alert after streaming completes (in case of Zen mode where the user might miss it)
|
|
274
|
+
const agentNameDisplay = cleanUpAgentName(removeTrailingUuid(network));
|
|
275
|
+
setAlertContents(`A temporary network "${agentNameDisplay}" has been created.`);
|
|
276
|
+
}
|
|
153
277
|
// When streaming is complete, clean up any refs and state
|
|
154
278
|
conversationsRef.current = null;
|
|
155
|
-
agentCountsRef.current = new Map();
|
|
156
279
|
setCurrentConversations(null);
|
|
157
280
|
resetState();
|
|
158
|
-
}, []);
|
|
281
|
+
}, [newlyAddedTemporaryNetworks]);
|
|
282
|
+
useEffect(() => {
|
|
283
|
+
if (alertContents?.length > 0) {
|
|
284
|
+
// Set a timer to clear the alert after a few seconds so it doesn't overstay its welcome
|
|
285
|
+
const timeoutId = window.setTimeout(() => {
|
|
286
|
+
setAlertContents(null);
|
|
287
|
+
}, 10_000);
|
|
288
|
+
return () => {
|
|
289
|
+
window.clearTimeout(timeoutId);
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
return undefined;
|
|
294
|
+
}
|
|
295
|
+
}, [alertContents]);
|
|
296
|
+
const [confirmationModalOpen, setConfirmationModalOpen] = useState(false);
|
|
297
|
+
const handleDeleteNetwork = (networkId, isExpired) => {
|
|
298
|
+
if (isExpired) {
|
|
299
|
+
// It's expired so just delete it without confirmation
|
|
300
|
+
const tempNetworksWithoutThisOne = temporaryNetworks.filter((network) => network.agentInfo.agent_name !== networkId);
|
|
301
|
+
useTempNetworksStore.getState().setTempNetworks(tempNetworksWithoutThisOne);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
setNetworkToBeDeleted(networkId);
|
|
305
|
+
setConfirmationModalOpen(true);
|
|
306
|
+
}
|
|
307
|
+
};
|
|
159
308
|
const getLeftPanel = () => {
|
|
160
|
-
return (_jsx(Slide, { id: "multi-agent-accelerator-grid-sidebar-slide", in: !isAwaitingLlm, direction: "right", timeout: GROW_ANIMATION_TIME_MS, onExited: () => {
|
|
309
|
+
return (_jsx(Slide, { id: "multi-agent-accelerator-grid-sidebar-slide", in: !enableZenMode || !isAwaitingLlm, direction: "right", timeout: GROW_ANIMATION_TIME_MS, onExited: () => {
|
|
161
310
|
setIsStreaming(true);
|
|
162
|
-
}, children: _jsx(Grid, { id: "multi-agent-accelerator-grid-sidebar", size: isStreaming ? 0 : 3.25, sx: {
|
|
311
|
+
}, children: _jsx(Grid, { id: "multi-agent-accelerator-grid-sidebar", size: enableZenMode && isStreaming ? 0 : 3.25, sx: {
|
|
163
312
|
height: "100%",
|
|
164
|
-
}, children: _jsx(Sidebar, { customURLLocalStorage: customURLLocalStorage, customURLCallback: customURLCallback, id: "multi-agent-accelerator-sidebar", isAwaitingLlm: isAwaitingLlm, networks: networks,
|
|
313
|
+
}, children: _jsx(Sidebar, { customURLLocalStorage: customURLLocalStorage, customURLCallback: customURLCallback, id: "multi-agent-accelerator-sidebar", isAwaitingLlm: isAwaitingLlm, networks: networks, networkIconSuggestions: networkIconSuggestions, newlyAddedTemporaryNetworks: newlyAddedTemporaryNetworks, onDeleteNetwork: handleDeleteNetwork, setSelectedNetwork: (newNetwork) => {
|
|
314
|
+
agentCountsRef.current = new Map();
|
|
315
|
+
setSelectedNetwork(newNetwork);
|
|
316
|
+
}, temporaryNetworks: temporaryNetworks }) }) }));
|
|
165
317
|
};
|
|
166
318
|
const getCenterPanel = () => {
|
|
167
|
-
return (_jsx(Grid, { id: "multi-agent-accelerator-grid-agent-flow", size: isStreaming ? 18 : 8.25, sx: {
|
|
319
|
+
return (_jsx(Grid, { id: "multi-agent-accelerator-grid-agent-flow", size: enableZenMode && isStreaming ? 18 : 8.25, sx: {
|
|
168
320
|
height: "100%",
|
|
169
321
|
}, children: _jsx(ReactFlowProvider, { children: _jsx(Box, { id: "multi-agent-accelerator-agent-flow-container", sx: {
|
|
170
322
|
display: "flex",
|
|
@@ -174,35 +326,42 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, darkMode, userInf
|
|
|
174
326
|
height: "100%",
|
|
175
327
|
maxWidth: 1000,
|
|
176
328
|
margin: "0 auto",
|
|
177
|
-
}, children: _jsx(AgentFlow, { agentCounts: agentCountsRef.current, agentsInNetwork: agentsInNetwork, id: "multi-agent-accelerator-agent-flow", currentConversations: currentConversations, isAwaitingLlm: isAwaitingLlm, isStreaming: isStreaming, thoughtBubbleEdges: thoughtBubbleEdges, setThoughtBubbleEdges: setThoughtBubbleEdges }) }) }) }));
|
|
329
|
+
}, children: _jsx(AgentFlow, { agentCounts: agentCountsRef.current, agentsInNetwork: agentsInNetwork, agentIconSuggestions: agentIconSuggestions, id: "multi-agent-accelerator-agent-flow", currentConversations: currentConversations, isAwaitingLlm: isAwaitingLlm, isStreaming: isStreaming, thoughtBubbleEdges: thoughtBubbleEdges, setThoughtBubbleEdges: setThoughtBubbleEdges }) }) }) }));
|
|
178
330
|
};
|
|
179
331
|
const getRightPanel = () => {
|
|
180
|
-
return (_jsx(Slide, { id: "multi-agent-accelerator-grid-agent-chat-common-slide", in: !isAwaitingLlm, direction: "left", timeout: GROW_ANIMATION_TIME_MS, onExited: () => {
|
|
332
|
+
return (_jsx(Slide, { id: "multi-agent-accelerator-grid-agent-chat-common-slide", in: !enableZenMode || !isAwaitingLlm, direction: "left", timeout: GROW_ANIMATION_TIME_MS, onExited: () => {
|
|
181
333
|
setIsStreaming(true);
|
|
182
|
-
}, children: _jsx(Grid, { id: "multi-agent-accelerator-grid-agent-chat-common", size: isStreaming ? 0 : 6.5, sx: {
|
|
334
|
+
}, children: _jsx(Grid, { id: "multi-agent-accelerator-grid-agent-chat-common", size: enableZenMode && isStreaming ? 0 : 6.5, sx: {
|
|
183
335
|
height: "100%",
|
|
184
|
-
}, children: _jsx(ChatCommon, { ref: chatRef, neuroSanURL: neuroSanURL, id: "agent-network-ui", currentUser: userInfo.userName, userImage: userInfo.userImage, setIsAwaitingLlm: setIsAwaitingLlm, isAwaitingLlm: isAwaitingLlm, targetAgent: selectedNetwork, onChunkReceived: onChunkReceived, onStreamingComplete: onStreamingComplete, onStreamingStarted: onStreamingStarted, clearChatOnNewAgent: true,
|
|
336
|
+
}, children: _jsx(ChatCommon, { ref: chatRef, neuroSanURL: neuroSanURL, id: "agent-network-ui", currentUser: userInfo.userName, userImage: userInfo.userImage, setIsAwaitingLlm: setIsAwaitingLlm, isAwaitingLlm: isAwaitingLlm, targetAgent: selectedNetwork, onChunkReceived: onChunkReceived, onStreamingComplete: onStreamingComplete, onStreamingStarted: onStreamingStarted, clearChatOnNewAgent: true }, selectedNetwork ?? "no-network") }) }));
|
|
185
337
|
};
|
|
186
338
|
const getStopButton = () => {
|
|
187
|
-
return (_jsx(_Fragment, { children: isAwaitingLlm && (_jsx(Box, { id: "stop-button-container", sx: {
|
|
339
|
+
return (_jsx(_Fragment, { children: isAwaitingLlm && enableZenMode && (_jsx(Box, { id: "stop-button-container", sx: {
|
|
188
340
|
position: "absolute",
|
|
189
341
|
bottom: "1rem",
|
|
190
342
|
right: "1rem",
|
|
191
343
|
zIndex: 10,
|
|
192
344
|
}, children: _jsx(SmallLlmChatButton, { "aria-label": "Stop", disabled: !isAwaitingLlm, id: "stop-output-button", onClick: handleExternalStop, posBottom: 8, posRight: 23, children: _jsx(StopCircle, { fontSize: "small", id: "stop-button-icon", sx: { color: "var(--bs-white)" } }) }) })) }));
|
|
193
345
|
};
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
346
|
+
const getConfirmationModal = () => confirmationModalOpen ? (_jsx(ConfirmationModal, { id: "delete-network-confirmation-modal", content: `The network "${cleanUpAgentName(removeTrailingUuid(networkToBeDeleted))}" will be deleted. ` +
|
|
347
|
+
"This action cannot be undone. Are you sure you want to proceed?", handleCancel: () => {
|
|
348
|
+
setConfirmationModalOpen(false);
|
|
349
|
+
setNetworkToBeDeleted(null);
|
|
350
|
+
}, handleOk: () => {
|
|
351
|
+
useTempNetworksStore
|
|
352
|
+
.getState()
|
|
353
|
+
.setTempNetworks(temporaryNetworks.filter((network) => network.agentInfo.agent_name !== networkToBeDeleted));
|
|
354
|
+
setNetworkToBeDeleted(null);
|
|
355
|
+
setConfirmationModalOpen(false);
|
|
356
|
+
}, title: "Delete Network" })) : null;
|
|
357
|
+
const getAlert = () => (_jsx(Collapse, { in: alertContents?.length > 0, timeout: 1000, children: _jsx(MUIAlert, { id: "temporary-network-created-alert", closeable: true, severity: "success", sx: { marginTop: "1rem", marginBottom: 0 }, children: alertContents }) }));
|
|
358
|
+
return (_jsxs(_Fragment, { children: [getAlert(), getConfirmationModal(), _jsxs(Grid, { id: "multi-agent-accelerator-grid", container: true, columns: 18, sx: {
|
|
359
|
+
display: "flex",
|
|
360
|
+
flex: 1,
|
|
361
|
+
height: "85%",
|
|
362
|
+
justifyContent: isAwaitingLlm ? "center" : "unset",
|
|
363
|
+
marginTop: "1rem",
|
|
364
|
+
overflow: "hidden",
|
|
365
|
+
position: "relative",
|
|
366
|
+
}, children: [getLeftPanel(), getCenterPanel(), getRightPanel(), getStopButton()] })] }));
|
|
208
367
|
};
|
|
@@ -14,12 +14,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
14
14
|
See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
import { getBezierPath } from "@xyflow/react";
|
|
17
18
|
import { useEffect, useRef } from "react";
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
// Prettier and ESlint conflict over this
|
|
21
|
-
// eslint-disable-next-line newline-per-chained-call
|
|
22
|
-
const green = getComputedStyle(document.documentElement).getPropertyValue("--bs-green").trim();
|
|
19
|
+
import { useSettingsStore } from "../../state/Settings.js";
|
|
20
|
+
const createFunnelParticleOnPath = (pathEl, canvasOffset, baseProgress, plasmaColor) => {
|
|
23
21
|
const totalLength = pathEl.getTotalLength();
|
|
24
22
|
const speed = 0.02 + Math.random() * 0.003;
|
|
25
23
|
const life = 100;
|
|
@@ -55,8 +53,8 @@ function createFunnelParticleOnPath(pathEl, canvasOffset, baseProgress) {
|
|
|
55
53
|
ctx.beginPath();
|
|
56
54
|
ctx.globalAlpha = alpha * 0.9 * pulse;
|
|
57
55
|
ctx.shadowBlur = 8 + 8 * pulse; // Lowered for performance
|
|
58
|
-
ctx.shadowColor =
|
|
59
|
-
ctx.fillStyle =
|
|
56
|
+
ctx.shadowColor = plasmaColor;
|
|
57
|
+
ctx.fillStyle = plasmaColor;
|
|
60
58
|
ctx.arc(x, y, 2, 0, Math.PI * 2);
|
|
61
59
|
ctx.fill();
|
|
62
60
|
ctx.globalAlpha = 1;
|
|
@@ -65,12 +63,13 @@ function createFunnelParticleOnPath(pathEl, canvasOffset, baseProgress) {
|
|
|
65
63
|
};
|
|
66
64
|
const isAlive = () => progress * totalLength < totalLength * 0.98;
|
|
67
65
|
return { update, draw, isAlive };
|
|
68
|
-
}
|
|
66
|
+
};
|
|
69
67
|
export const PlasmaEdge = ({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, }) => {
|
|
70
68
|
const canvasRef = useRef(null);
|
|
71
69
|
const pathRef = useRef(null);
|
|
72
|
-
const animationRef = useRef();
|
|
70
|
+
const animationRef = useRef(null);
|
|
73
71
|
const particles = useRef([]);
|
|
72
|
+
const plasmaColor = useSettingsStore((state) => state.settings.appearance.plasmaColor);
|
|
74
73
|
const [edgePath] = getBezierPath({
|
|
75
74
|
sourceX,
|
|
76
75
|
sourceY,
|
|
@@ -106,7 +105,7 @@ export const PlasmaEdge = ({ sourceX, sourceY, targetX, targetY, sourcePosition,
|
|
|
106
105
|
if (particles.current.length < MAX_PARTICLES) {
|
|
107
106
|
const t = Math.random();
|
|
108
107
|
if (Math.random() < 1 - t) {
|
|
109
|
-
particles.current.push(createFunnelParticleOnPath(pathEl, canvasOffset, t));
|
|
108
|
+
particles.current.push(createFunnelParticleOnPath(pathEl, canvasOffset, t, plasmaColor));
|
|
110
109
|
}
|
|
111
110
|
}
|
|
112
111
|
}
|
|
@@ -118,7 +117,10 @@ export const PlasmaEdge = ({ sourceX, sourceY, targetX, targetY, sourcePosition,
|
|
|
118
117
|
animationRef.current = requestAnimationFrame(animate);
|
|
119
118
|
};
|
|
120
119
|
animate();
|
|
121
|
-
return () =>
|
|
122
|
-
|
|
120
|
+
return () => {
|
|
121
|
+
if (animationRef.current !== undefined)
|
|
122
|
+
cancelAnimationFrame(animationRef.current);
|
|
123
|
+
};
|
|
124
|
+
}, [edgePath, width, height, plasmaColor, x, y]);
|
|
123
125
|
return (_jsxs(_Fragment, { children: [_jsx("foreignObject", { id: `foreign-object-${x}-${y}`, width: width, height: height, x: x, y: y, style: { pointerEvents: "none", overflow: "visible" }, children: _jsx("canvas", { id: `canvas-${x}-${y}`, ref: canvasRef }) }), _jsx("path", { id: `path-${edgePath}`, ref: pathRef, d: edgePath, fill: "none", stroke: "none", style: { position: "absolute", visibility: "hidden" } })] }));
|
|
124
126
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TreeItemProps } from "@mui/x-tree-view/TreeItem";
|
|
2
|
+
import { FC } from "react";
|
|
3
|
+
import { NodeIndex } from "./TreeBuilder.js";
|
|
4
|
+
export interface AgentNetworkNodeProps extends TreeItemProps {
|
|
5
|
+
readonly nodeIndex: NodeIndex;
|
|
6
|
+
readonly onDeleteNetwork?: (network: string, isExpired: boolean) => void;
|
|
7
|
+
readonly networkIconSuggestions: Record<string, string>;
|
|
8
|
+
readonly temporaryNetworkExpirationTimes?: Record<string, Date>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Custom Tree Item for MUI RichTreeView to display agent networks with tags
|
|
12
|
+
* @param props - see AgentNetworkNode interface
|
|
13
|
+
* @returns JSX.Element containing the custom tree item
|
|
14
|
+
*/
|
|
15
|
+
export declare const AgentNetworkTreeItem: FC<AgentNetworkNodeProps>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Need to disable restricted imports because we want to import all MUI icons dynamically
|
|
3
|
+
// eslint-disable-next-line no-restricted-imports
|
|
4
|
+
import * as MuiIcons from "@mui/icons-material";
|
|
5
|
+
import BookmarkIcon from "@mui/icons-material/Bookmark";
|
|
6
|
+
import Delete from "@mui/icons-material/Delete";
|
|
7
|
+
import Box from "@mui/material/Box";
|
|
8
|
+
import Chip from "@mui/material/Chip";
|
|
9
|
+
import { useTheme } from "@mui/material/styles";
|
|
10
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
11
|
+
import { TreeItemContent, TreeItemGroupTransition, TreeItemLabel, TreeItemRoot, } from "@mui/x-tree-view/TreeItem";
|
|
12
|
+
import { TreeItemProvider } from "@mui/x-tree-view/TreeItemProvider";
|
|
13
|
+
import { useTreeItem } from "@mui/x-tree-view/useTreeItem";
|
|
14
|
+
import { useRef } from "react";
|
|
15
|
+
import { cleanUpAgentName } from "../../AgentChat/Utils.js";
|
|
16
|
+
// Palette of colors we can use for tags
|
|
17
|
+
const TAG_COLORS = [
|
|
18
|
+
"--bs-accent2-light",
|
|
19
|
+
"--bs-accent1-medium",
|
|
20
|
+
"--bs-accent3-medium",
|
|
21
|
+
"--bs-accent3-dark",
|
|
22
|
+
"--bs-green",
|
|
23
|
+
"--bs-orange",
|
|
24
|
+
"--bs-pink",
|
|
25
|
+
"--bs-secondary",
|
|
26
|
+
"--bs-yellow",
|
|
27
|
+
];
|
|
28
|
+
// Keep track of which tags have which colors so that the same tag always has the same color
|
|
29
|
+
const tagsToColors = new Map();
|
|
30
|
+
/**
|
|
31
|
+
* Helper function to determine if a temporary network is expired based on its expiration date
|
|
32
|
+
* @param expirationDate - Date object representing the expiration time of the temporary network
|
|
33
|
+
* @returns boolean indicating whether the temporary network is expired
|
|
34
|
+
*/
|
|
35
|
+
const isTemporaryNetworkExpired = (expirationDate) => {
|
|
36
|
+
return Date.now() > expirationDate.getTime();
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Custom Tree Item for MUI RichTreeView to display agent networks with tags
|
|
40
|
+
* @param props - see AgentNetworkNode interface
|
|
41
|
+
* @returns JSX.Element containing the custom tree item
|
|
42
|
+
*/
|
|
43
|
+
export const AgentNetworkTreeItem = ({ children, disabled, itemId, label, networkIconSuggestions, nodeIndex, onDeleteNetwork, temporaryNetworkExpirationTimes, }) => {
|
|
44
|
+
const theme = useTheme();
|
|
45
|
+
// We know all labels are strings because we set them that way in the tree view items
|
|
46
|
+
const labelString = label;
|
|
47
|
+
const displayLabel = nodeIndex.get(itemId)?.displayName || cleanUpAgentName(labelString);
|
|
48
|
+
const { getContextProviderProps, getRootProps, getContentProps, getLabelProps, getGroupTransitionProps } = useTreeItem({ itemId, children, label, disabled });
|
|
49
|
+
const rootRef = useRef(null);
|
|
50
|
+
const isParent = Array.isArray(children) && children.length > 0;
|
|
51
|
+
const isChild = !isParent;
|
|
52
|
+
const agentNode = nodeIndex?.get(itemId)?.agentInfo;
|
|
53
|
+
// Only child items (the actual networks, not the containing folders) have tags. Retrieve tags from the
|
|
54
|
+
// networkFolders data structure passed in as a prop. This could in theory be a custom property for the
|
|
55
|
+
// RichTreeView item, but that isn't well-supported at this time.
|
|
56
|
+
// Discussion: https://stackoverflow.com/questions/69481071/material-ui-how-to-pass-custom-props-to-a-custom-treeitem
|
|
57
|
+
const tags = isChild ? agentNode?.tags || [] : [];
|
|
58
|
+
// Assign colors to tags as needed and store in tagsToColors map
|
|
59
|
+
for (const tag of tags) {
|
|
60
|
+
if (!tagsToColors.has(tag)) {
|
|
61
|
+
const color = TAG_COLORS[tagsToColors.size % TAG_COLORS.length];
|
|
62
|
+
tagsToColors.set(tag, color);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Determine if expired (temporary networks only)
|
|
66
|
+
const expirationTime = temporaryNetworkExpirationTimes?.[itemId];
|
|
67
|
+
const isTemporaryNetwork = Boolean(expirationTime);
|
|
68
|
+
const isExpired = isChild && isTemporaryNetwork && isTemporaryNetworkExpired(expirationTime);
|
|
69
|
+
const iconNameSuggestion = isTemporaryNetwork ? "HourglassTop" : isChild ? networkIconSuggestions?.[itemId] : null;
|
|
70
|
+
let muiIconElement = null;
|
|
71
|
+
if (iconNameSuggestion && MuiIcons[iconNameSuggestion]) {
|
|
72
|
+
const IconComponent = MuiIcons[iconNameSuggestion];
|
|
73
|
+
muiIconElement = _jsx(IconComponent, { sx: { fontSize: "1rem" } });
|
|
74
|
+
}
|
|
75
|
+
else if (iconNameSuggestion) {
|
|
76
|
+
console.warn(`Icon "${iconNameSuggestion}" not found in MUI icons library.`);
|
|
77
|
+
}
|
|
78
|
+
return (_jsx(TreeItemProvider, { ...getContextProviderProps(), children: _jsxs(TreeItemRoot, { ...getRootProps(), ref: rootRef, children: [_jsx(TreeItemContent, { ...getContentProps(), sx: {
|
|
79
|
+
cursor: isExpired ? "not-allowed" : "pointer",
|
|
80
|
+
}, children: _jsxs(Box, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between", width: "100%" }, children: [_jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: "0.25rem" }, children: [_jsx(Tooltip, { title: isChild && isExpired
|
|
81
|
+
? "Expired"
|
|
82
|
+
: expirationTime && `Expires at ${expirationTime.toLocaleString()}`, children: _jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: "0.25rem" }, children: [muiIconElement, _jsx(TreeItemLabel, { ...getLabelProps(), sx: {
|
|
83
|
+
fontWeight: isParent ? "bold" : "normal",
|
|
84
|
+
fontSize: isParent ? "1rem" : "0.9rem",
|
|
85
|
+
color: isParent ? "var(--heading-color)" : null,
|
|
86
|
+
opacity: isExpired ? 0.25 : 1,
|
|
87
|
+
"&:hover": {
|
|
88
|
+
textDecoration: "underline",
|
|
89
|
+
},
|
|
90
|
+
}, children: displayLabel })] }) }), isChild && tags?.length > 0 ? (_jsx(Tooltip, { title: tags
|
|
91
|
+
.slice()
|
|
92
|
+
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
|
|
93
|
+
.map((tag) => (_jsx(Chip, { label: tag, style: {
|
|
94
|
+
margin: "0.25rem",
|
|
95
|
+
backgroundColor: `var(${tagsToColors.get(tag) || TAG_COLORS[0]})`,
|
|
96
|
+
} }, tag))), placement: "right", arrow: true, children: _jsx(BookmarkIcon, { sx: { fontSize: "0.75rem", color: "var(--bs-accent1-medium)" } }) })) : null] }), isChild && isTemporaryNetwork && (_jsx(Tooltip, { title: "Delete network", children: _jsx(Delete, { onClick: (e) => {
|
|
97
|
+
e.stopPropagation();
|
|
98
|
+
onDeleteNetwork?.(itemId, isExpired);
|
|
99
|
+
}, sx: {
|
|
100
|
+
cursor: "pointer",
|
|
101
|
+
fontSize: "1rem",
|
|
102
|
+
"&:hover": { color: theme.palette.warning.main },
|
|
103
|
+
} }) }))] }) }, labelString), children && _jsx(TreeItemGroupTransition, { ...getGroupTransitionProps() })] }) }));
|
|
104
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { NetworkIconSuggestions } from "../../../controller/Types/NetworkIconSuggestions.js";
|
|
3
|
+
import { AgentInfo } from "../../../generated/neuro-san/NeuroSanClient.js";
|
|
4
|
+
import { TemporaryNetwork } from "../../../state/TemporaryNetworks.js";
|
|
5
|
+
export interface SidebarProps {
|
|
6
|
+
readonly customURLCallback: (url: string) => void;
|
|
7
|
+
readonly customURLLocalStorage?: string;
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly isAwaitingLlm: boolean;
|
|
10
|
+
readonly networkIconSuggestions?: NetworkIconSuggestions;
|
|
11
|
+
readonly networks: readonly AgentInfo[];
|
|
12
|
+
readonly onDeleteNetwork?: (network: string, isExpired: boolean) => void;
|
|
13
|
+
readonly setSelectedNetwork: (network: string) => void;
|
|
14
|
+
readonly temporaryNetworks?: readonly TemporaryNetwork[];
|
|
15
|
+
readonly newlyAddedTemporaryNetworks?: Set<string>;
|
|
16
|
+
}
|
|
17
|
+
export declare const Sidebar: FC<SidebarProps>;
|