@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.
- package/README.md +3 -3
- package/dist/Theme/Palettes.d.ts +0 -9
- package/dist/Theme/Palettes.js +0 -18
- package/dist/components/AgentChat/ChatCommon/ChatCommon.d.ts +13 -4
- package/dist/components/AgentChat/ChatCommon/ChatCommon.js +131 -38
- package/dist/components/AgentChat/ChatCommon/ChatHistory.d.ts +7 -0
- package/dist/components/AgentChat/ChatCommon/ChatHistory.js +1 -1
- 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 +5 -3
- package/dist/components/AgentChat/ChatCommon/ControlButtons.js +13 -4
- package/dist/components/AgentChat/ChatCommon/ConversationTurn.d.ts +5 -5
- package/dist/components/AgentChat/ChatCommon/ConversationTurn.js +1 -0
- 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/Common/Utils.d.ts +4 -0
- package/dist/components/AgentChat/Common/Utils.js +5 -1
- package/dist/components/AgentChat/VoiceChat/MicrophoneButton.js +12 -10
- package/dist/components/Common/Breadcrumbs.js +1 -1
- 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/Common/notification.d.ts +4 -4
- 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.d.ts → AgentFlow/AgentFlow.d.ts} +15 -5
- package/dist/components/MultiAgentAccelerator/{AgentFlow.js → AgentFlow/AgentFlow.js} +125 -84
- package/dist/components/MultiAgentAccelerator/{AgentNode.d.ts → AgentFlow/AgentNode.d.ts} +1 -1
- package/dist/components/MultiAgentAccelerator/{AgentNode.js → AgentFlow/AgentNode.js} +26 -30
- package/dist/components/MultiAgentAccelerator/AgentFlow/GraphLayouts.d.ts +43 -0
- package/dist/components/MultiAgentAccelerator/{GraphLayouts.js → AgentFlow/GraphLayouts.js} +10 -41
- package/dist/components/MultiAgentAccelerator/AgentFlow/GraphStructure.d.ts +21 -0
- package/dist/components/MultiAgentAccelerator/AgentFlow/GraphStructure.js +27 -0
- package/dist/components/MultiAgentAccelerator/AgentFlow/PlasmaEdge.d.ts +7 -0
- package/dist/components/MultiAgentAccelerator/{PlasmaEdge.js → AgentFlow/PlasmaEdge.js} +13 -8
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +3 -9
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +137 -103
- package/dist/components/MultiAgentAccelerator/Schema/SlyData.d.ts +17 -0
- package/dist/components/MultiAgentAccelerator/Schema/SlyData.js +23 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.d.ts +0 -5
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.js +38 -28
- package/dist/components/MultiAgentAccelerator/Sidebar/ImportNetworkModal.d.ts +67 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/ImportNetworkModal.js +585 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.d.ts +5 -4
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.js +77 -168
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.d.ts +31 -13
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.js +177 -100
- package/dist/components/MultiAgentAccelerator/TemporaryNetworks.d.ts +22 -0
- package/dist/components/MultiAgentAccelerator/TemporaryNetworks.js +74 -3
- package/dist/components/MultiAgentAccelerator/{ThoughtBubbleEdge.d.ts → ThoughtBubbles/ThoughtBubbleEdge.d.ts} +1 -1
- package/dist/components/MultiAgentAccelerator/{ThoughtBubbleOverlay.js → ThoughtBubbles/ThoughtBubbleOverlay.js} +1 -1
- package/dist/components/MultiAgentAccelerator/Tour/MainTourSteps.js +15 -8
- package/dist/components/MultiAgentAccelerator/const.d.ts +3 -0
- package/dist/components/MultiAgentAccelerator/const.js +6 -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 +373 -183
- package/dist/components/Settings/SettingsRow.d.ts +18 -0
- package/dist/components/Settings/SettingsRow.js +35 -0
- package/dist/controller/agent/Agent.d.ts +16 -25
- package/dist/controller/agent/Agent.js +24 -54
- package/dist/controller/agent/IconSuggestions.d.ts +35 -0
- package/dist/controller/agent/IconSuggestions.js +85 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -3
- package/dist/state/IconSuggestions.d.ts +27 -0
- package/dist/state/IconSuggestions.js +50 -0
- package/dist/state/Settings.d.ts +97 -6
- package/dist/state/Settings.js +110 -8
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/BrowserNavigation.js +2 -0
- package/dist/utils/File.d.ts +4 -1
- package/dist/utils/File.js +4 -9
- package/dist/utils/text.js +3 -7
- package/dist/utils/title.js +1 -1
- package/package.json +9 -6
- 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/components/MultiAgentAccelerator/GraphLayouts.d.ts +0 -36
- package/dist/components/MultiAgentAccelerator/PlasmaEdge.d.ts +0 -3
- package/dist/utils/useLocalStorage.d.ts +0 -1
- package/dist/utils/useLocalStorage.js +0 -55
- /package/dist/components/MultiAgentAccelerator/{ThoughtBubbleEdge.js → ThoughtBubbles/ThoughtBubbleEdge.js} +0 -0
- /package/dist/components/MultiAgentAccelerator/{ThoughtBubbleOverlay.d.ts → ThoughtBubbles/ThoughtBubbleOverlay.d.ts} +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// "Parent agents" are those that have tools, aka agents with "child agents". A lone single-agent
|
|
2
|
+
// network is treated as its own parent.
|
|
3
|
+
export const getParentAgents = (agents) => agents.length === 1 ? agents : agents.filter((agent) => (agent.tools?.length ?? 0) > 0);
|
|
4
|
+
/**
|
|
5
|
+
* Determines the frontman of an agent network — the single source of truth for "who is the frontman".
|
|
6
|
+
*
|
|
7
|
+
* The frontman is the agent with no parent: a "parent" agent (one that has tools) that is not itself
|
|
8
|
+
* listed as a tool by any other agent. A lone single-agent network is its own frontman. Returns
|
|
9
|
+
* undefined when no agent qualifies (e.g. a fully cyclic network); callers decide how to fall back.
|
|
10
|
+
*
|
|
11
|
+
* Consumed by the graph layouts (to seed the depth-0 node) and by the network import flow.
|
|
12
|
+
*/
|
|
13
|
+
export const getFrontman = (agents) => {
|
|
14
|
+
const parentAgents = getParentAgents(agents);
|
|
15
|
+
// Child agents are everything referenced as a tool by a parent.
|
|
16
|
+
const childAgents = new Set(parentAgents.flatMap((agent) => agent.tools ?? []));
|
|
17
|
+
return parentAgents.find((agent) => agent.origin !== undefined && !childAgents.has(agent.origin));
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Returns the "origins" (node names) of the _immediate_ parents of a node in the agent network. Grandparents and
|
|
21
|
+
* higher are not included.
|
|
22
|
+
*
|
|
23
|
+
* @param node Node ID for which to find parents
|
|
24
|
+
* @param parentAgents Full list of parent agents in the network
|
|
25
|
+
* @returns The IDs of the immediate parent nodes for the given node or empty array if no parents are found (frontman)
|
|
26
|
+
*/
|
|
27
|
+
export const getParents = (node, parentAgents) => parentAgents.filter((agent) => agent.tools.includes(node)).map((parentNode) => parentNode.origin);
|
|
@@ -16,7 +16,11 @@ limitations under the License.
|
|
|
16
16
|
*/
|
|
17
17
|
import { getBezierPath } from "@xyflow/react";
|
|
18
18
|
import { useEffect, useRef } from "react";
|
|
19
|
-
import { useSettingsStore } from "
|
|
19
|
+
import { useSettingsStore } from "../../../state/Settings.js";
|
|
20
|
+
//#region Constants
|
|
21
|
+
const DEFAULT_MAX_PARTICLES = 250;
|
|
22
|
+
const DEFAULT_PARTICLES_PER_FRAME = 25;
|
|
23
|
+
//#endregion Interfaces and Types
|
|
20
24
|
const createFunnelParticleOnPath = (pathEl, canvasOffset, baseProgress, plasmaColor) => {
|
|
21
25
|
const totalLength = pathEl.getTotalLength();
|
|
22
26
|
const speed = 0.02 + Math.random() * 0.003;
|
|
@@ -64,7 +68,7 @@ const createFunnelParticleOnPath = (pathEl, canvasOffset, baseProgress, plasmaCo
|
|
|
64
68
|
const isAlive = () => progress * totalLength < totalLength * 0.98;
|
|
65
69
|
return { update, draw, isAlive };
|
|
66
70
|
};
|
|
67
|
-
export const PlasmaEdge = ({
|
|
71
|
+
export const PlasmaEdge = ({ maxParticles = DEFAULT_MAX_PARTICLES, particlesPerFrame = DEFAULT_PARTICLES_PER_FRAME, sourcePosition, sourceX, sourceY, targetPosition, targetX, targetY, }) => {
|
|
68
72
|
const canvasRef = useRef(null);
|
|
69
73
|
const pathRef = useRef(null);
|
|
70
74
|
const animationRef = useRef(null);
|
|
@@ -97,12 +101,10 @@ export const PlasmaEdge = ({ sourceX, sourceY, targetX, targetY, sourcePosition,
|
|
|
97
101
|
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
98
102
|
ctx.scale(dpr, dpr);
|
|
99
103
|
const canvasOffset = { x, y };
|
|
100
|
-
const MAX_PARTICLES = 250;
|
|
101
|
-
const PARTICLES_PER_FRAME = 25;
|
|
102
104
|
const animate = () => {
|
|
103
105
|
ctx.clearRect(0, 0, width, height);
|
|
104
|
-
for (let i = 0; i <
|
|
105
|
-
if (particles.current.length <
|
|
106
|
+
for (let i = 0; i < particlesPerFrame; i += 1) {
|
|
107
|
+
if (particles.current.length < maxParticles) {
|
|
106
108
|
const t = Math.random();
|
|
107
109
|
if (Math.random() < 1 - t) {
|
|
108
110
|
particles.current.push(createFunnelParticleOnPath(pathEl, canvasOffset, t, plasmaColor));
|
|
@@ -118,9 +120,12 @@ export const PlasmaEdge = ({ sourceX, sourceY, targetX, targetY, sourcePosition,
|
|
|
118
120
|
};
|
|
119
121
|
animate();
|
|
120
122
|
return () => {
|
|
121
|
-
if (animationRef.current !== undefined)
|
|
123
|
+
if (animationRef.current !== undefined) {
|
|
122
124
|
cancelAnimationFrame(animationRef.current);
|
|
125
|
+
animationRef.current = undefined;
|
|
126
|
+
}
|
|
127
|
+
particles.current = [];
|
|
123
128
|
};
|
|
124
|
-
}, [edgePath, width, height, plasmaColor, x, y]);
|
|
129
|
+
}, [edgePath, width, height, plasmaColor, x, y, particlesPerFrame, maxParticles]);
|
|
125
130
|
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" } })] }));
|
|
126
131
|
};
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
2
|
export interface MultiAgentAcceleratorProps {
|
|
3
|
-
readonly
|
|
4
|
-
|
|
5
|
-
userImage: string;
|
|
6
|
-
};
|
|
7
|
-
readonly backendNeuroSanApiUrl: string;
|
|
3
|
+
readonly username: string;
|
|
4
|
+
readonly defaultNeuroSanUrl: string;
|
|
8
5
|
}
|
|
9
|
-
export declare const GRACE_PERIOD_MS: number;
|
|
10
|
-
export declare const SHOW_TOUR_DELAY_MS = 5000;
|
|
11
6
|
/**
|
|
12
7
|
* Main Multi-Agent Accelerator component that contains the sidebar, agent flow, and chat components.
|
|
13
8
|
* @param backendNeuroSanApiUrl Initial URL of the backend Neuro-San API. User can change this in the UI.
|
|
14
|
-
* @param
|
|
15
|
-
* @param userInfo Information about the current user, including userName and userImage.
|
|
9
|
+
* @param username Identifier to use for interactions with the backend (for personalization and tracking).
|
|
16
10
|
*/
|
|
17
11
|
export declare const MultiAgentAccelerator: FC<MultiAgentAcceleratorProps>;
|
|
@@ -15,89 +15,59 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import StopCircle from "@mui/icons-material/StopCircle";
|
|
18
|
+
import Backdrop from "@mui/material/Backdrop";
|
|
18
19
|
import Box from "@mui/material/Box";
|
|
20
|
+
import CircularProgress from "@mui/material/CircularProgress";
|
|
19
21
|
import Grid from "@mui/material/Grid";
|
|
22
|
+
import Paper from "@mui/material/Paper";
|
|
20
23
|
import Slide from "@mui/material/Slide";
|
|
21
24
|
import { useTheme } from "@mui/material/styles";
|
|
25
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
22
26
|
import Typography from "@mui/material/Typography";
|
|
23
27
|
import { ReactFlowProvider } from "@xyflow/react";
|
|
24
28
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
25
29
|
import { useJoyride } from "react-joyride";
|
|
26
30
|
import { extractConversations } from "./AgentConversations.js";
|
|
27
31
|
import { getUpdatedAgentCounts } from "./AgentCounts.js";
|
|
28
|
-
import { AgentFlow } from "./AgentFlow.js";
|
|
32
|
+
import { AgentFlow } from "./AgentFlow/AgentFlow.js";
|
|
29
33
|
import { extractAgentNetworkDesignerProgress } from "./AgentNetworkDesigner.js";
|
|
30
|
-
import { AGENT_NETWORK_DEFINITION_KEY, AGENT_NETWORK_DESIGNER_ID, AGENT_NETWORK_HOCON, AGENT_NETWORK_NAME_KEY, TRIGGER_APP_TOUR_EVENT_NAME, } from "./const.js";
|
|
34
|
+
import { AGENT_NETWORK_DEFINITION_KEY, AGENT_NETWORK_DESIGNER_ID, AGENT_NETWORK_HOCON, AGENT_NETWORK_NAME_KEY, EXPIRED_NETWORKS_CHECK_INTERVAL_MS, GRACE_PERIOD_MS, SHOW_TOUR_DELAY_MS, TRIGGER_APP_TOUR_EVENT_NAME, } from "./const.js";
|
|
35
|
+
import { ImportNetworkModal } from "./Sidebar/ImportNetworkModal.js";
|
|
31
36
|
import { Sidebar } from "./Sidebar/Sidebar.js";
|
|
32
|
-
import { extractTemporaryNetworksFromMessage, isTemporaryNetwork,
|
|
33
|
-
import {
|
|
37
|
+
import { extractTemporaryNetworksFromMessage, IMPORT_FAILURE_DETAIL, importNetworkFromJson, isTemporaryNetwork, notifySaveError, streamNetworkDesignerUpsert, } from "./TemporaryNetworks.js";
|
|
38
|
+
import { MAIN_TOUR_STEPS } from "./Tour/MainTourSteps.js";
|
|
39
|
+
import { getAgentFunction, getAgentNetworks, getConnectivity } from "../../controller/agent/Agent.js";
|
|
40
|
+
import { getAgentIconSuggestions, getNetworkIconSuggestions } from "../../controller/agent/IconSuggestions.js";
|
|
34
41
|
import { useAgentChatHistoryStore } from "../../state/ChatHistory.js";
|
|
35
|
-
import { useSettingsStore } from "../../state/Settings.js";
|
|
36
42
|
import { useTempNetworksStore } from "../../state/TemporaryNetworks.js";
|
|
37
43
|
import { TourPromptState, useTourStore } from "../../state/Tour.js";
|
|
38
|
-
import { useLocalStorage } from "../../utils/useLocalStorage.js";
|
|
39
44
|
import { getZIndex } from "../../utils/zIndexLayers.js";
|
|
40
45
|
import { ChatCommon } from "../AgentChat/ChatCommon/ChatCommon.js";
|
|
41
|
-
import {
|
|
46
|
+
import { LlmChatButton } from "../AgentChat/Common/LlmChatButton.js";
|
|
42
47
|
import { isLegacyAgentType } from "../AgentChat/Common/Types.js";
|
|
43
48
|
import { chatMessageFromChunk, cleanUpAgentName, removeTrailingUuid } from "../AgentChat/Common/Utils.js";
|
|
44
49
|
import { ConfirmationModal, StyledButton } from "../Common/ConfirmationModal.js";
|
|
45
|
-
import {
|
|
46
|
-
import { MAIN_TOUR_STEPS } from "./Tour/MainTourSteps.js";
|
|
50
|
+
import { MUIAlert } from "../Common/MUIAlert.js";
|
|
47
51
|
import { MUIDialog } from "../Common/MUIDialog.js";
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
export const GRACE_PERIOD_MS = 5 * 60 * 1000; // 5 minutes
|
|
52
|
+
import { closeNotification, NotificationType, sendNotification } from "../Common/notification.js";
|
|
53
|
+
import { BYOK } from "./Schema/SlyData.js";
|
|
54
|
+
import { getApiKey, LLM_PROVIDER_API_KEY_FIELD, useSettingsStore } from "../../state/Settings.js";
|
|
52
55
|
// Animation time for the left and right panels to slide in or out when launching the animation
|
|
53
56
|
const GROW_ANIMATION_TIME_MS = 800;
|
|
54
57
|
// Optimization to avoid creating a new empty map on every render
|
|
55
58
|
const EMPTY_THOUGHT_BUBBLE_EDGES = new Map();
|
|
56
|
-
// We show the tour modal after this amount of time so as not to "pounce" on the user when they first open the app
|
|
57
|
-
export const SHOW_TOUR_DELAY_MS = 5000;
|
|
58
|
-
// #region: Agent-save helpers
|
|
59
|
-
/**
|
|
60
|
-
* Extracts TemporaryNetworks from a single streamed chunk, merging into `accumulated`.
|
|
61
|
-
* Returns `accumulated` unchanged if the chunk yields no reservations or on parse error.
|
|
62
|
-
*/
|
|
63
|
-
const collectNetworksFromChunk = (chunk, updated, accumulated) => {
|
|
64
|
-
try {
|
|
65
|
-
const chatMessage = chatMessageFromChunk(chunk);
|
|
66
|
-
if (!chatMessage)
|
|
67
|
-
return accumulated;
|
|
68
|
-
// Always use the user's edited definition as the authoritative value.
|
|
69
|
-
const converted = extractTemporaryNetworksFromMessage(chatMessage, updated);
|
|
70
|
-
if (converted.length === 0)
|
|
71
|
-
return accumulated;
|
|
72
|
-
return mergeNetworks(accumulated, converted);
|
|
73
|
-
}
|
|
74
|
-
catch (e) {
|
|
75
|
-
console.warn("Failed to process chunk from network designer:", e);
|
|
76
|
-
return accumulated;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
/** Logs and notifies about a save error. Suppresses AbortError (user-cancelled). */
|
|
80
|
-
const notifySaveError = (agentName, e) => {
|
|
81
|
-
if (e instanceof DOMException && e.name === "AbortError")
|
|
82
|
-
return;
|
|
83
|
-
console.error("Failed to submit agent network update:", e);
|
|
84
|
-
const detail = e instanceof DOMException && e.name === "TimeoutError"
|
|
85
|
-
? "The request timed out waiting for the server. Please try again."
|
|
86
|
-
: String(e);
|
|
87
|
-
sendNotification(NotificationType.error, `Failed to update network "${agentName}".`, detail);
|
|
88
|
-
};
|
|
89
|
-
// #endregion: Agent-save helpers
|
|
90
59
|
/**
|
|
91
60
|
* Main Multi-Agent Accelerator component that contains the sidebar, agent flow, and chat components.
|
|
92
61
|
* @param backendNeuroSanApiUrl Initial URL of the backend Neuro-San API. User can change this in the UI.
|
|
93
|
-
* @param
|
|
94
|
-
* @param userInfo Information about the current user, including userName and userImage.
|
|
62
|
+
* @param username Identifier to use for interactions with the backend (for personalization and tracking).
|
|
95
63
|
*/
|
|
96
|
-
export const MultiAgentAccelerator = ({
|
|
64
|
+
export const MultiAgentAccelerator = ({ defaultNeuroSanUrl, username, }) => {
|
|
97
65
|
// MUI theme
|
|
98
66
|
const theme = useTheme();
|
|
99
67
|
const enableZenMode = useSettingsStore((state) => state.settings.behavior.enableZenMode);
|
|
100
68
|
const apiKeys = useSettingsStore((state) => state.settings.apiKeys);
|
|
69
|
+
// Display option for agent/network names
|
|
70
|
+
const useNativeNames = useSettingsStore((state) => state.settings.appearance.useNativeNames);
|
|
101
71
|
// Stores whether are currently awaiting LLM response (for knowing when to show spinners)
|
|
102
72
|
const [isAwaitingLlm, setIsAwaitingLlm] = useState(false);
|
|
103
73
|
const [isEditingNetwork, setIsEditingNetwork] = useState(false);
|
|
@@ -109,6 +79,8 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
109
79
|
const temporaryNetworks = useTempNetworksStore((state) => state.tempNetworks);
|
|
110
80
|
// Track newly added temp networks so we can highlight them
|
|
111
81
|
const [newlyAddedTemporaryNetworks, setNewlyAddedTemporaryNetworks] = useState(new Set());
|
|
82
|
+
// True while a file import is in-flight (after modal confirm, before the new network appears)
|
|
83
|
+
const [isImporting, setIsImporting] = useState(false);
|
|
112
84
|
const [networkIconSuggestions, setNetworkIconSuggestions] = useState({});
|
|
113
85
|
const [agentsInNetwork, setAgentsInNetwork] = useState([]);
|
|
114
86
|
const [sampleQueries, setSampleQueries] = useState([]);
|
|
@@ -118,11 +90,10 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
118
90
|
const [agentIconSuggestions, setAgentIconSuggestions] = useState(null);
|
|
119
91
|
const [selectedNetwork, setSelectedNetwork] = useState(null);
|
|
120
92
|
const [networkDescription, setNetworkDescription] = useState("");
|
|
121
|
-
const networkDisplayName = useMemo(() => cleanUpAgentName(removeTrailingUuid(selectedNetwork)), [selectedNetwork]);
|
|
122
|
-
|
|
123
|
-
const [
|
|
124
|
-
|
|
125
|
-
const [neuroSanURL, setNeuroSanURL] = useState(customURLLocalStorage?.replaceAll('"', "") || backendNeuroSanApiUrl);
|
|
93
|
+
const networkDisplayName = useMemo(() => (useNativeNames ? selectedNetwork : cleanUpAgentName(removeTrailingUuid(selectedNetwork))), [selectedNetwork, useNativeNames]);
|
|
94
|
+
// LLM providers for which BYOK keys are supported by the current network
|
|
95
|
+
const [supportedByokProviders, setSupportedByokProviders] = useState(new Set());
|
|
96
|
+
const neuroSanURL = useSettingsStore((state) => state.settings.externalServices.neuroSanUrl) ?? defaultNeuroSanUrl;
|
|
126
97
|
// Tracks how many times each agent has been involved in the conversation
|
|
127
98
|
const [agentCounts, setAgentCounts] = useState(new Map());
|
|
128
99
|
// Common function to change the selected network and reset related state
|
|
@@ -136,12 +107,9 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
136
107
|
// State to hold thought bubble edges - avoids duplicates across layout recalculations
|
|
137
108
|
const [thoughtBubbleEdges, setThoughtBubbleEdges] = useState(new Map());
|
|
138
109
|
const [confirmationModalOpen, setConfirmationModalOpen] = useState(false);
|
|
110
|
+
const [importModalOpen, setImportModalOpen] = useState(false);
|
|
139
111
|
const [tourModalOpen, setTourModalOpen] = useState(false);
|
|
140
112
|
const [haveShownTourModal, setHaveShownTourModal] = useState(false);
|
|
141
|
-
const customURLCallback = useCallback((url) => {
|
|
142
|
-
setNeuroSanURL(url || backendNeuroSanApiUrl);
|
|
143
|
-
setCustomURLLocalStorage(url === "" ? null : url);
|
|
144
|
-
}, [backendNeuroSanApiUrl, setCustomURLLocalStorage]);
|
|
145
113
|
// Memoized key for agent names to trigger icon suggestion updates when the set of agents changes, not just
|
|
146
114
|
// when sorting/other operations on the agents list
|
|
147
115
|
const agentNamesKey = useMemo(() => agentsInNetwork
|
|
@@ -209,16 +177,14 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
209
177
|
* Builds the API keys object to be sent as extraSlyData with each request, based on the LLM providers required
|
|
210
178
|
* by the currently selected network. Only includes keys for providers that are required.
|
|
211
179
|
*/
|
|
212
|
-
const getApiKeys = () => {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return { llm_config: llmConfig };
|
|
221
|
-
};
|
|
180
|
+
const getApiKeys = () => ({
|
|
181
|
+
llm_config: Object.fromEntries([...supportedByokProviders]
|
|
182
|
+
.map((provider) => [
|
|
183
|
+
LLM_PROVIDER_API_KEY_FIELD[provider],
|
|
184
|
+
getApiKey(apiKeys, provider),
|
|
185
|
+
])
|
|
186
|
+
.filter((entry) => Boolean(entry[1]))),
|
|
187
|
+
});
|
|
222
188
|
/**
|
|
223
189
|
* Builds the extraSlyData object to be sent with each request, including information for Agent Network Designer
|
|
224
190
|
* and (if required) API keys for LLM providers.
|
|
@@ -245,7 +211,7 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
245
211
|
return undefined;
|
|
246
212
|
};
|
|
247
213
|
// Whether any API keys are required
|
|
248
|
-
const anyApiKeysRequired =
|
|
214
|
+
const anyApiKeysRequired = supportedByokProviders.size > 0;
|
|
249
215
|
// Build base extraSlyData
|
|
250
216
|
const baseExtraSlyData = buildExtraSlyData();
|
|
251
217
|
// Add API keys to extraSlyData if needed, merging with baseExtraSlyData if it exists
|
|
@@ -260,7 +226,33 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
260
226
|
chatRef.current?.handleStop();
|
|
261
227
|
resetState();
|
|
262
228
|
}, [resetState]);
|
|
263
|
-
|
|
229
|
+
/**
|
|
230
|
+
* Maps an API key name to the corresponding LLM provider
|
|
231
|
+
*/
|
|
232
|
+
const apiKeyToProvider = useCallback((key) => {
|
|
233
|
+
switch (key) {
|
|
234
|
+
case "openai_api_key":
|
|
235
|
+
return "OpenAI";
|
|
236
|
+
case "anthropic_api_key":
|
|
237
|
+
return "Anthropic";
|
|
238
|
+
default:
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}, []);
|
|
242
|
+
/**
|
|
243
|
+
* Given a SlyData schema, returns the set of LLM providers that are supported by the agent network.
|
|
244
|
+
* @note Semantics are "oneOf": a key must be supplied for at least one of the named providers
|
|
245
|
+
*/
|
|
246
|
+
const getSupportedLlmProviders = useCallback((schema) => {
|
|
247
|
+
const parsed = BYOK.safeParse(schema);
|
|
248
|
+
if (!parsed.success || !parsed.data.required?.includes("llm_config")) {
|
|
249
|
+
return new Set();
|
|
250
|
+
}
|
|
251
|
+
const providerKeys = Object.keys(parsed.data.properties?.llm_config?.properties ?? {});
|
|
252
|
+
return new Set(providerKeys
|
|
253
|
+
.map((key) => apiKeyToProvider(key))
|
|
254
|
+
.filter((provider) => provider !== null));
|
|
255
|
+
}, [apiKeyToProvider]);
|
|
264
256
|
useEffect(() => {
|
|
265
257
|
;
|
|
266
258
|
(async () => {
|
|
@@ -281,23 +273,14 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
281
273
|
const fetchAgentDetails = async () => {
|
|
282
274
|
// It is a Neuro-san agent, so get the function and connectivity info
|
|
283
275
|
try {
|
|
284
|
-
|
|
276
|
+
// Reset before fetching
|
|
277
|
+
setNetworkDescription("");
|
|
278
|
+
setSupportedByokProviders(new Set());
|
|
279
|
+
// Get agent function from server
|
|
280
|
+
const agentFunction = await getAgentFunction(neuroSanURL, selectedNetwork, username);
|
|
285
281
|
setNetworkDescription(agentFunction?.function?.description || "");
|
|
286
282
|
const schema = agentFunction?.function?.sly_data_schema;
|
|
287
|
-
|
|
288
|
-
const llmConfig = isRecord(schemaProperties) ? schemaProperties["llm_config"] : undefined;
|
|
289
|
-
const llmConfigRequired = isRecord(llmConfig) ? llmConfig["required"] : undefined;
|
|
290
|
-
setProviderKeysRequired(new Set((Array.isArray(llmConfigRequired) ? llmConfigRequired : []).flatMap((key) => {
|
|
291
|
-
if (key === "openai_api_key") {
|
|
292
|
-
return ["OpenAI"];
|
|
293
|
-
}
|
|
294
|
-
if (key === "anthropic_api_key") {
|
|
295
|
-
return ["Anthropic"];
|
|
296
|
-
}
|
|
297
|
-
console.warn(`Unknown API key requirement "${key}" for network ${selectedNetwork}. Skipping.`);
|
|
298
|
-
// Will get dropped by flatMap
|
|
299
|
-
return [];
|
|
300
|
-
})));
|
|
283
|
+
setSupportedByokProviders(getSupportedLlmProviders(schema));
|
|
301
284
|
}
|
|
302
285
|
catch (e) {
|
|
303
286
|
console.warn(`Unable to get agent details for network ${selectedNetwork}:`, e);
|
|
@@ -308,7 +291,7 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
308
291
|
if (selectedNetwork && !isLegacyAgentType(selectedNetwork)) {
|
|
309
292
|
void fetchAgentDetails();
|
|
310
293
|
}
|
|
311
|
-
}, [neuroSanURL, selectedNetwork,
|
|
294
|
+
}, [getSupportedLlmProviders, neuroSanURL, selectedNetwork, username]);
|
|
312
295
|
useEffect(() => {
|
|
313
296
|
;
|
|
314
297
|
(async () => {
|
|
@@ -329,7 +312,7 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
329
312
|
(async () => {
|
|
330
313
|
if (selectedNetwork) {
|
|
331
314
|
try {
|
|
332
|
-
const connectivity = await getConnectivity(neuroSanURL, selectedNetwork,
|
|
315
|
+
const connectivity = await getConnectivity(neuroSanURL, selectedNetwork, username);
|
|
333
316
|
const agentsInNetworkSorted = [...connectivity.connectivity_info].sort((a, b) => a?.origin.localeCompare(b?.origin));
|
|
334
317
|
setAgentsInNetwork(agentsInNetworkSorted);
|
|
335
318
|
const sampleQueriesTmp = connectivity?.metadata?.["sample_queries"];
|
|
@@ -352,7 +335,7 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
352
335
|
setAgentsInNetwork([]);
|
|
353
336
|
}
|
|
354
337
|
})();
|
|
355
|
-
}, [networkDisplayName, neuroSanURL, selectedNetwork,
|
|
338
|
+
}, [networkDisplayName, neuroSanURL, selectedNetwork, username]);
|
|
356
339
|
useEffect(() => {
|
|
357
340
|
;
|
|
358
341
|
(async () => {
|
|
@@ -474,10 +457,7 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
474
457
|
*/
|
|
475
458
|
const onSaveAgent = useCallback(async (agentName, updated, agentNetworkName, signal) => {
|
|
476
459
|
try {
|
|
477
|
-
|
|
478
|
-
await sendNetworkDesignerUpdate(neuroSanURL, signal, agentName, updated, agentNetworkName, userInfo.userName, (chunk) => {
|
|
479
|
-
newNetworks = collectNetworksFromChunk(chunk, updated, newNetworks);
|
|
480
|
-
});
|
|
460
|
+
const newNetworks = await streamNetworkDesignerUpsert(neuroSanURL, signal, agentName, updated, agentNetworkName, username);
|
|
481
461
|
if (newNetworks.length === 0) {
|
|
482
462
|
sendNotification(NotificationType.error, `Failed to update network "${agentName}".`, "The network designer did not return a reservation. Please try again.");
|
|
483
463
|
return;
|
|
@@ -499,7 +479,36 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
499
479
|
catch (e) {
|
|
500
480
|
notifySaveError(agentName, e);
|
|
501
481
|
}
|
|
502
|
-
}, [neuroSanURL,
|
|
482
|
+
}, [neuroSanURL, username, selectedNetwork]);
|
|
483
|
+
/**
|
|
484
|
+
* Handles an import from the ImportNetworkModal: converts the JSON content to a
|
|
485
|
+
* network definition, streams it through the network designer to obtain a reservation,
|
|
486
|
+
* then upserts the result into the temporary-networks store and navigates to the new network.
|
|
487
|
+
*/
|
|
488
|
+
const handleImportNetwork = useCallback(async (agentNetworkName, content) => {
|
|
489
|
+
setIsImporting(true);
|
|
490
|
+
try {
|
|
491
|
+
const result = await importNetworkFromJson(content, agentNetworkName, neuroSanURL, username);
|
|
492
|
+
if ("failure" in result) {
|
|
493
|
+
sendNotification(NotificationType.error, `Failed to import "${agentNetworkName}".`, IMPORT_FAILURE_DETAIL[result.failure]);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
useTempNetworksStore.getState().upsertTempNetworks(result.networks);
|
|
497
|
+
// An import defines a single network, so the designer returns one reservation. Highlight and
|
|
498
|
+
// navigate to it; any further entries (none expected) are still upserted above.
|
|
499
|
+
const newNetworkName = result.networks[0]?.agentInfo.agent_name;
|
|
500
|
+
if (newNetworkName) {
|
|
501
|
+
setNewlyAddedTemporaryNetworks(new Set([newNetworkName]));
|
|
502
|
+
changeSelectedNetwork(newNetworkName);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
catch (e) {
|
|
506
|
+
notifySaveError(agentNetworkName, e);
|
|
507
|
+
}
|
|
508
|
+
finally {
|
|
509
|
+
setIsImporting(false);
|
|
510
|
+
}
|
|
511
|
+
}, [changeSelectedNetwork, neuroSanURL, username]);
|
|
503
512
|
const onStreamingStarted = useCallback(() => {
|
|
504
513
|
// Reset agent counts
|
|
505
514
|
setAgentCounts(new Map());
|
|
@@ -519,7 +528,7 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
519
528
|
}, [resetState]);
|
|
520
529
|
const handleDeleteNetwork = (networkId, isExpired) => {
|
|
521
530
|
if (isExpired) {
|
|
522
|
-
// It's expired so just delete it without confirmation
|
|
531
|
+
// It's expired, so just delete it without confirmation
|
|
523
532
|
const tempNetworksWithoutThisOne = temporaryNetworks.filter((network) => network.agentInfo.agent_name !== networkId);
|
|
524
533
|
useTempNetworksStore.getState().setTempNetworks(tempNetworksWithoutThisOne);
|
|
525
534
|
useAgentChatHistoryStore.getState().resetHistory(networkId);
|
|
@@ -563,14 +572,17 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
563
572
|
}
|
|
564
573
|
}, [tourRequested, selectedNetwork, agentsInNetwork, networks, controls, setTourStatus]);
|
|
565
574
|
const getMissingApiKeys = () => {
|
|
566
|
-
|
|
575
|
+
// Calculate intersection of what we have (apiKeys) and what is required (providerKeysRequired)
|
|
576
|
+
const intersection = new Set([...supportedByokProviders].filter((provider) => getApiKey(apiKeys, provider)));
|
|
577
|
+
return intersection.size === 0 ? supportedByokProviders : new Set();
|
|
567
578
|
};
|
|
579
|
+
const hasMissingApiKeys = getMissingApiKeys().size > 0;
|
|
568
580
|
const getLeftPanel = () => {
|
|
569
581
|
return (_jsx(Slide, { id: "multi-agent-accelerator-grid-sidebar-slide", in: !enableZenMode || !isAwaitingLlm, direction: "right", timeout: GROW_ANIMATION_TIME_MS, onExited: () => {
|
|
570
582
|
setIsStreaming(true);
|
|
571
583
|
}, children: _jsx(Grid, { id: "multi-agent-accelerator-grid-sidebar", size: enableZenMode && isStreaming ? 0 : 3.25, sx: {
|
|
572
584
|
height: "100%",
|
|
573
|
-
}, children: _jsx(Sidebar, {
|
|
585
|
+
}, children: _jsx(Sidebar, { id: "multi-agent-accelerator-sidebar", isAwaitingLlm: isAwaitingLlm, isImporting: isImporting, networkIconSuggestions: networkIconSuggestions, networks: networks, neuroSanServerURL: neuroSanURL, newlyAddedTemporaryNetworks: newlyAddedTemporaryNetworks, onDeleteNetwork: handleDeleteNetwork, onEditNetwork: handleEditNetwork, onImportClick: () => setImportModalOpen(true), setSelectedNetwork: (newNetwork) => changeSelectedNetwork(newNetwork), temporaryNetworks: temporaryNetworks }) }) }));
|
|
574
586
|
};
|
|
575
587
|
const getCenterPanel = () => {
|
|
576
588
|
return (_jsx(Grid, { id: "multi-agent-accelerator-grid-agent-flow", size: enableZenMode && isStreaming ? 18 : 8.25, sx: {
|
|
@@ -583,7 +595,7 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
583
595
|
height: "100%",
|
|
584
596
|
maxWidth: 1000,
|
|
585
597
|
margin: "0 auto",
|
|
586
|
-
}, children: _jsx(AgentFlow, { agentCounts: agentCounts, agentsInNetwork: agentsInNetwork, agentIconSuggestions: agentIconSuggestions, id: "multi-agent-accelerator-agent-flow", currentConversations: currentConversations, currentUser:
|
|
598
|
+
}, children: _jsx(AgentFlow, { agentCounts: agentCounts, agentsInNetwork: agentsInNetwork, agentIconSuggestions: agentIconSuggestions, id: "multi-agent-accelerator-agent-flow", currentConversations: currentConversations, currentUser: username, isAwaitingLlm: isAwaitingLlm, isEditMode: isEditingNetwork, isStreaming: isStreaming, isSelectedNetworkTemporary: isSelectedNetworkTemporary, networkDisplayName: networkDisplayName || "", networkId: isSelectedNetworkTemporary ? selectedNetwork : "", neuroSanURL: neuroSanURL, onEnterEditMode: () => setIsEditingNetwork(true), onExitEditMode: () => setIsEditingNetwork(false), onNetworkReplaced: (_old, newId) => changeSelectedNetwork(newId), onSaveAgent: onSaveAgent, thoughtBubbleEdges: thoughtBubbleEdges, setThoughtBubbleEdges: setThoughtBubbleEdges }, "multi-agent-accelerator-agent-flow") }) }) }));
|
|
587
599
|
};
|
|
588
600
|
const getRightPanel = () => {
|
|
589
601
|
return (_jsx(Slide, { id: "multi-agent-accelerator-grid-agent-chat-common-slide", in: !enableZenMode || !isAwaitingLlm, direction: "left", timeout: GROW_ANIMATION_TIME_MS, onExited: () => {
|
|
@@ -592,17 +604,21 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
592
604
|
height: "100%",
|
|
593
605
|
}, children: _jsx(ChatCommon, { agentPlaceholders: {
|
|
594
606
|
[AGENT_NETWORK_DESIGNER_ID]: "Describe in plain language the network you would like to build.",
|
|
595
|
-
}, currentUser:
|
|
607
|
+
}, currentUser: username, customAgentGreetings: {
|
|
596
608
|
[AGENT_NETWORK_DESIGNER_ID]: "Let's build a network together!",
|
|
597
|
-
}, extraSlyData: extraSlyData, id: "agent-network-ui", isAwaitingLlm: isAwaitingLlm,
|
|
609
|
+
}, extraSlyData: extraSlyData, id: "agent-network-ui", isAwaitingLlm: isAwaitingLlm, hasMissingApiKeys: hasMissingApiKeys, networkDescription: networkDescription, neuroSanURL: neuroSanURL, onChunkReceived: onChunkReceived, onStreamingComplete: onStreamingComplete, onStreamingStarted: onStreamingStarted, ref: chatRef, sampleQueries: sampleQueries, setIsAwaitingLlm: setIsAwaitingLlm, selectedNetwork: selectedNetwork, setSelectedNetwork: changeSelectedNetwork }, selectedNetwork ?? "no-network") }) }));
|
|
598
610
|
};
|
|
599
611
|
const getStopButton = () => {
|
|
600
612
|
return (_jsx(_Fragment, { children: isAwaitingLlm && enableZenMode && (_jsx(Box, { id: "stop-button-container", sx: {
|
|
601
613
|
position: "absolute",
|
|
602
614
|
bottom: "1rem",
|
|
603
615
|
right: "1rem",
|
|
604
|
-
zIndex:
|
|
605
|
-
}, children: _jsx(
|
|
616
|
+
zIndex: getZIndex(2, theme),
|
|
617
|
+
}, children: _jsx(Tooltip, { title: "Stop response (Esc)", children: _jsx(LlmChatButton, { "aria-label": "Stop", id: "stop-output-button", onClick: handleExternalStop, sx: {
|
|
618
|
+
"&:hover": {
|
|
619
|
+
backgroundColor: "error.main",
|
|
620
|
+
},
|
|
621
|
+
}, children: _jsx(StopCircle, { fontSize: "large", id: "stop-button-icon" }) }) }) })) }));
|
|
606
622
|
};
|
|
607
623
|
const getDeleteNetworkConfirmationModal = () => confirmationModalOpen ? (_jsx(ConfirmationModal, { id: "delete-network-confirmation-modal", content: `The network "${cleanUpAgentName(removeTrailingUuid(networkToBeDeleted))}" will be deleted. ` +
|
|
608
624
|
"This action cannot be undone. Are you sure you want to proceed?", handleCancel: () => {
|
|
@@ -619,6 +635,17 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
619
635
|
setNetworkToBeDeleted(null);
|
|
620
636
|
setConfirmationModalOpen(false);
|
|
621
637
|
}, title: "Delete Network" })) : null;
|
|
638
|
+
const getImportNetworkModal = () => (_jsx(ImportNetworkModal, { existingNetworkNames: temporaryNetworks.map((n) => n.agentNetworkName), isOpen: importModalOpen, onClose: () => setImportModalOpen(false), onImport: handleImportNetwork }));
|
|
639
|
+
// Blocking overlay shown while an imported network is being created on the backend.
|
|
640
|
+
const getImportBackdrop = () => (_jsx(Backdrop, { id: "multi-agent-accelerator-import-backdrop", "data-testid": "multi-agent-accelerator-import-backdrop", open: isImporting, sx: { zIndex: getZIndex(3, theme) }, children: _jsxs(Paper, { elevation: 6, role: "status", "aria-live": "polite", sx: {
|
|
641
|
+
display: "flex",
|
|
642
|
+
alignItems: "center",
|
|
643
|
+
gap: 2,
|
|
644
|
+
px: 4,
|
|
645
|
+
py: 2.5,
|
|
646
|
+
borderRadius: 2,
|
|
647
|
+
maxWidth: 480,
|
|
648
|
+
}, children: [_jsx(CircularProgress, { id: "multi-agent-accelerator-import-spinner", size: 24 }), _jsx(Typography, { id: "multi-agent-accelerator-import-title", variant: "body1", sx: { fontWeight: "bold" }, children: "Importing network..." })] }) }));
|
|
622
649
|
const getTourModal = () => tourModalOpen && (_jsx(MUIDialog, { contentSx: { fontSize: "0.8rem", minWidth: "550px", paddingTop: "0" }, footer: _jsxs(_Fragment, { children: [_jsx(StyledButton, { id: "tour-dont-show-again", onClick: () => {
|
|
623
650
|
setTourStatus(TourPromptState.DontShowAgain);
|
|
624
651
|
dismissTourModal();
|
|
@@ -660,7 +687,14 @@ export const MultiAgentAccelerator = ({ backendNeuroSanApiUrl, userInfo, }) => {
|
|
|
660
687
|
opacity: "95%",
|
|
661
688
|
width: "100%",
|
|
662
689
|
}, children: [_jsx(Typography, { variant: "h6", sx: { padding: "0.5rem 1rem", fontWeight: "bold", color: "white" }, children: "Network Preview" }), agentsInNetworkDesigner?.length > 0 ? (_jsx(AgentFlow, { id: "and-network-preview", agentsInNetwork: agentsInNetworkDesigner, isAgentNetworkDesignerMode: true, isAwaitingLlm: false, isStreaming: false, thoughtBubbleEdges: EMPTY_THOUGHT_BUBBLE_EDGES }, "and-network-preview")) : (_jsx(Typography, { variant: "body1", sx: { color: "white" }, children: "Awaiting status from Agent Network Designer..." }))] }) }) }));
|
|
663
|
-
|
|
690
|
+
const getMissingApiKeysAlert = () => hasMissingApiKeys && (_jsx(MUIAlert, { closeable: false, id: "llm-chat-missing-api-keys-alert", severity: "warning", sx: {
|
|
691
|
+
my: 1.5,
|
|
692
|
+
"& .MuiAlert-message": {
|
|
693
|
+
width: "100%",
|
|
694
|
+
textAlign: "center",
|
|
695
|
+
},
|
|
696
|
+
}, children: _jsxs(Typography, { sx: { fontSize: "larger" }, children: ["API key(s) required for at least one of these providers:", " ", _jsx("strong", { children: [...getMissingApiKeys()].join(", ") }), ". Please add the required key(s) in \"Settings\" to use this Network."] }) }));
|
|
697
|
+
return (_jsxs(_Fragment, { children: [getMissingApiKeysAlert(), Tour, getTourModal(), getProgressPopper(), getDeleteNetworkConfirmationModal(), getImportNetworkModal(), getImportBackdrop(), _jsxs(Grid, { id: "multi-agent-accelerator-grid", container: true, columns: 18, sx: {
|
|
664
698
|
display: "flex",
|
|
665
699
|
flex: 1,
|
|
666
700
|
height: "85%",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for sly_data BYOK structure
|
|
4
|
+
*/
|
|
5
|
+
export declare const BYOK: z.ZodObject<{
|
|
6
|
+
type: z.ZodOptional<z.ZodString>;
|
|
7
|
+
required: z.ZodOptional<z.ZodTuple<[z.ZodLiteral<"llm_config">], null>>;
|
|
8
|
+
properties: z.ZodOptional<z.ZodObject<{
|
|
9
|
+
llm_config: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
type: z.ZodOptional<z.ZodString>;
|
|
11
|
+
properties: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
12
|
+
type: z.ZodOptional<z.ZodString>;
|
|
13
|
+
description: z.ZodOptional<z.ZodString>;
|
|
14
|
+
}, z.core.$loose>>>;
|
|
15
|
+
}, z.core.$loose>>;
|
|
16
|
+
}, z.core.$loose>>;
|
|
17
|
+
}, z.core.$loose>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for sly_data BYOK structure
|
|
4
|
+
*/
|
|
5
|
+
export const BYOK = z.looseObject({
|
|
6
|
+
type: z.string().optional(),
|
|
7
|
+
required: z.tuple([z.literal("llm_config")]).optional(),
|
|
8
|
+
properties: z
|
|
9
|
+
.looseObject({
|
|
10
|
+
llm_config: z
|
|
11
|
+
.looseObject({
|
|
12
|
+
type: z.string().optional(),
|
|
13
|
+
properties: z
|
|
14
|
+
.record(z.string(), z.looseObject({
|
|
15
|
+
type: z.string().optional(),
|
|
16
|
+
description: z.string().optional(),
|
|
17
|
+
}))
|
|
18
|
+
.optional(),
|
|
19
|
+
})
|
|
20
|
+
.optional(),
|
|
21
|
+
})
|
|
22
|
+
.optional(),
|
|
23
|
+
});
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { TreeItemProps } from "@mui/x-tree-view/TreeItem";
|
|
2
2
|
import { FC } from "react";
|
|
3
|
-
import { NodeIndex } from "./TreeBuilder.js";
|
|
4
3
|
export interface AgentNetworkNodeProps extends TreeItemProps {
|
|
5
|
-
readonly nodeIndex: NodeIndex;
|
|
6
4
|
readonly onDeleteNetwork?: (network: string, isExpired: boolean) => void;
|
|
7
5
|
readonly onEditNetwork?: (network: string) => void;
|
|
8
|
-
readonly networkIconSuggestions: Record<string, string>;
|
|
9
|
-
readonly temporaryNetworkExpirationTimes?: Record<string, Date>;
|
|
10
|
-
readonly temporaryNetworkHoconStrings?: Record<string, string | null>;
|
|
11
6
|
}
|
|
12
7
|
/**
|
|
13
8
|
* Custom Tree Item for MUI RichTreeView to display agent networks with tags
|