@cognizant-ai-lab/ui-common 1.5.0 → 1.6.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 (81) hide show
  1. package/dist/Theme/Theme.js +3 -3
  2. package/dist/components/AgentChat/ChatCommon/ChatCommon.d.ts +11 -1
  3. package/dist/components/AgentChat/ChatCommon/ChatCommon.js +284 -285
  4. package/dist/components/AgentChat/ChatCommon/ChatHistory.d.ts +1 -7
  5. package/dist/components/AgentChat/ChatCommon/ChatHistory.js +33 -22
  6. package/dist/components/AgentChat/ChatCommon/ControlButtons.js +2 -2
  7. package/dist/components/AgentChat/ChatCommon/Conversation.d.ts +13 -0
  8. package/dist/components/AgentChat/ChatCommon/Conversation.js +80 -0
  9. package/dist/components/AgentChat/ChatCommon/ConversationTurn.d.ts +23 -0
  10. package/dist/components/AgentChat/ChatCommon/ConversationTurn.js +11 -0
  11. package/dist/components/AgentChat/ChatCommon/FormattedMarkdown.js +5 -3
  12. package/dist/components/AgentChat/ChatCommon/SampleQueries.d.ts +3 -0
  13. package/dist/components/AgentChat/ChatCommon/SampleQueries.js +6 -3
  14. package/dist/components/AgentChat/ChatCommon/Thinking.d.ts +12 -0
  15. package/dist/components/AgentChat/ChatCommon/Thinking.js +51 -0
  16. package/dist/components/AgentChat/Common/LlmChatButton.d.ts +2 -2
  17. package/dist/components/AgentChat/Common/Types.d.ts +6 -5
  18. package/dist/components/AgentChat/Common/Types.js +5 -0
  19. package/dist/components/AgentChat/Common/Utils.d.ts +1 -1
  20. package/dist/components/AgentChat/Common/Utils.js +14 -9
  21. package/dist/components/Common/AccordionLite.d.ts +14 -0
  22. package/dist/components/Common/AccordionLite.js +25 -0
  23. package/dist/components/Common/ConfirmationModal.d.ts +1 -0
  24. package/dist/components/Common/ConfirmationModal.js +1 -1
  25. package/dist/components/Common/CustomerLogo.js +1 -1
  26. package/dist/components/Common/MUIAlert.d.ts +1 -0
  27. package/dist/components/Common/MUIAlert.js +3 -4
  28. package/dist/components/Common/Navbar.d.ts +2 -1
  29. package/dist/components/Common/Navbar.js +8 -4
  30. package/dist/components/Common/notification.d.ts +1 -1
  31. package/dist/components/Common/notification.js +17 -12
  32. package/dist/components/MultiAgentAccelerator/AgentFlow.d.ts +8 -0
  33. package/dist/components/MultiAgentAccelerator/AgentFlow.js +282 -82
  34. package/dist/components/MultiAgentAccelerator/AgentNode.d.ts +3 -1
  35. package/dist/components/MultiAgentAccelerator/AgentNode.js +64 -28
  36. package/dist/components/MultiAgentAccelerator/AgentNodePopup.d.ts +1 -4
  37. package/dist/components/MultiAgentAccelerator/AgentNodePopup.js +4 -5
  38. package/dist/components/MultiAgentAccelerator/GraphLayouts.js +19 -9
  39. package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +2 -2
  40. package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +268 -60
  41. package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.d.ts +1 -0
  42. package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.js +28 -12
  43. package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.d.ts +1 -0
  44. package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.js +21 -5
  45. package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.d.ts +4 -3
  46. package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.js +8 -2
  47. package/dist/components/MultiAgentAccelerator/TemporaryNetworks.d.ts +19 -2
  48. package/dist/components/MultiAgentAccelerator/TemporaryNetworks.js +40 -5
  49. package/dist/components/MultiAgentAccelerator/ThoughtBubbleOverlay.js +27 -14
  50. package/dist/components/MultiAgentAccelerator/Tour/MainTourSteps.d.ts +7 -0
  51. package/dist/components/MultiAgentAccelerator/Tour/MainTourSteps.js +88 -0
  52. package/dist/components/MultiAgentAccelerator/const.d.ts +7 -10
  53. package/dist/components/MultiAgentAccelerator/const.js +9 -10
  54. package/dist/const.d.ts +5 -1
  55. package/dist/const.js +5 -2
  56. package/dist/controller/agent/Agent.d.ts +10 -0
  57. package/dist/controller/agent/Agent.js +17 -1
  58. package/dist/controller/llm/LlmChat.js +2 -2
  59. package/dist/index.d.ts +0 -1
  60. package/dist/index.js +0 -1
  61. package/dist/state/TemporaryNetworks.d.ts +5 -15
  62. package/dist/state/TemporaryNetworks.js +15 -34
  63. package/dist/state/Tour.d.ts +29 -0
  64. package/dist/state/Tour.js +22 -0
  65. package/dist/state/UserInfo.d.ts +2 -1
  66. package/dist/tsconfig.build.tsbuildinfo +1 -1
  67. package/dist/utils/Authentication.js +12 -3
  68. package/dist/utils/File.d.ts +7 -0
  69. package/dist/utils/File.js +14 -3
  70. package/dist/utils/text.js +2 -2
  71. package/dist/utils/title.js +1 -1
  72. package/dist/utils/zIndexLayers.js +3 -0
  73. package/package.json +15 -11
  74. package/dist/components/AgentChat/ChatCommon/AgentConnectivity.d.ts +0 -14
  75. package/dist/components/AgentChat/ChatCommon/AgentConnectivity.js +0 -23
  76. package/dist/components/AgentChat/ChatCommon/Greetings.d.ts +0 -1
  77. package/dist/components/AgentChat/ChatCommon/Greetings.js +0 -38
  78. package/dist/components/AgentChat/ChatCommon/UserQueryDisplay.d.ts +0 -7
  79. package/dist/components/AgentChat/ChatCommon/UserQueryDisplay.js +0 -32
  80. package/dist/components/Common/LlmChatOptionsButton.d.ts +0 -6
  81. package/dist/components/Common/LlmChatOptionsButton.js +0 -31
@@ -18,21 +18,27 @@ limitations under the License.
18
18
  // eslint-disable-next-line no-restricted-imports
19
19
  import * as MuiIcons from "@mui/icons-material";
20
20
  import AutoAwesomeIcon from "@mui/icons-material/AutoAwesome";
21
+ import EditIcon from "@mui/icons-material/Edit";
21
22
  import HandymanIcon from "@mui/icons-material/Handyman";
22
23
  import PersonIcon from "@mui/icons-material/Person";
23
24
  import TravelExploreIcon from "@mui/icons-material/TravelExplore";
25
+ import IconButton from "@mui/material/IconButton";
24
26
  import { keyframes, styled, useTheme } from "@mui/material/styles";
25
27
  import Tooltip from "@mui/material/Tooltip";
26
28
  import Typography from "@mui/material/Typography";
27
29
  import { Handle, Position } from "@xyflow/react";
28
- import { DISPLAY_AS_CODED_TOOL, DISPLAY_AS_EXTERNAL_AGENT, DISPLAY_AS_LANGCHAIN_TOOL, DISPLAY_AS_LLM_AGENT, isEditableAgent, } from "./const.js";
30
+ import { useState } from "react";
31
+ import { DisplayAs } from "./const.js";
29
32
  import { useSettingsStore } from "../../state/Settings.js";
30
33
  import { usePalette } from "../../Theme/Palettes.js";
31
34
  import { isLightColor } from "../../Theme/Theme.js";
32
35
  import { getZIndex } from "../../utils/zIndexLayers.js";
36
+ // A zero-width space character, used to give the browser a hint where to break long names
37
+ const ZERO_WIDTH_SPACE = "\u200B";
33
38
  // Node dimensions
34
39
  export const NODE_HEIGHT = 100;
35
40
  export const NODE_WIDTH = 100;
41
+ export const FRONTMAN_SIZE_MULTIPLIER = 1.25;
36
42
  // Icon sizes
37
43
  // These are used to set the size of the icons displayed in the agent nodes.
38
44
  const AGENT_ICON_SIZE = "2.25rem";
@@ -82,11 +88,11 @@ export const AgentNode = (props) => {
82
88
  const palette = usePalette();
83
89
  // Unpack the node-specific data
84
90
  const data = props.data;
85
- const { agentCounts, agentName, depth, displayAs, getConversations, agentIconSuggestion, isAwaitingLlm, isTemporaryNetwork, } = data;
91
+ const { agentCounts, agentName, depth, displayAs, getConversations, agentIconSuggestion, isAwaitingLlm, isEditable } = data;
86
92
  // Determine if this is the Frontman node (depth 0)
87
93
  const isFrontman = depth === 0;
88
94
  // Determine max agent count for heatmap scaling
89
- const maxAgentCount = agentCounts ? Math.max(...Array.from(agentCounts.values())) : 0;
95
+ const maxAgentCount = agentCounts ? Math.max(...agentCounts.values()) : 0;
90
96
  // Unpack the node-specific id
91
97
  const agentId = props.id;
92
98
  // "Active" agents are those at either end of the current communication from the incoming chat messages.
@@ -134,13 +140,13 @@ export const AgentNode = (props) => {
134
140
  }
135
141
  else {
136
142
  switch (displayAs) {
137
- case DISPLAY_AS_EXTERNAL_AGENT:
143
+ case DisplayAs.EXTERNAL_AGENT:
138
144
  return (_jsx(TravelExploreIcon, { id: id, sx: { fontSize: AGENT_ICON_SIZE } }));
139
145
  // This should be a supported type but we're not seeing it?
140
- case DISPLAY_AS_LANGCHAIN_TOOL:
141
- case DISPLAY_AS_CODED_TOOL:
146
+ case DisplayAs.LANGCHAIN_TOOL:
147
+ case DisplayAs.CODED_TOOL:
142
148
  return (_jsx(HandymanIcon, { id: id, sx: { fontSize: AGENT_ICON_SIZE } }));
143
- case DISPLAY_AS_LLM_AGENT:
149
+ case DisplayAs.LLM_AGENT:
144
150
  default:
145
151
  return (_jsx(AutoAwesomeIcon, { id: id, sx: { fontSize: AGENT_ICON_SIZE } }));
146
152
  }
@@ -153,25 +159,55 @@ export const AgentNode = (props) => {
153
159
  const glowColor = isLightColor(theme.palette.background.default)
154
160
  ? theme.palette.common.black
155
161
  : theme.palette.common.white;
156
- const isClickableNode = isTemporaryNetwork && isEditableAgent(displayAs);
157
- return (_jsxs(_Fragment, { children: [_jsxs(AnimatedNode, { id: agentId, "data-testid": agentId, glowColor: glowColor, isActive: isActiveAgent, sx: {
158
- backgroundColor,
159
- color,
160
- cursor: isClickableNode ? "pointer" : "grab",
161
- height: NODE_HEIGHT * (isFrontman ? 1.25 : 1.0),
162
- width: NODE_WIDTH * (isFrontman ? 1.25 : 1.0),
163
- zIndex: getZIndex(1, theme),
164
- }, children: [getDisplayAsIcon(), _jsx(Handle, { id: `${agentId}-left-handle`, position: Position.Left, type: "source", style: { visibility: handleVisibility } }), _jsx(Handle, { id: `${agentId}-right-handle`, position: Position.Right, type: "source", style: { visibility: handleVisibility } }), _jsx(Handle, { id: `${agentId}-top-handle`, position: Position.Top, type: "source", style: { visibility: handleVisibility } }), _jsx(Handle, { id: `${agentId}-bottom-handle`, position: Position.Bottom, type: "source", style: { visibility: handleVisibility } })] }), _jsx(Tooltip, { id: `${agentId}-tooltip`, title: agentName, placement: "top", disableInteractive: true, children: _jsx(Typography, { id: `${agentId}-name`, sx: {
165
- display: "-webkit-box",
166
- fontSize: "18px",
167
- fontWeight: "bold",
168
- lineHeight: "1.4em",
169
- overflow: "hidden",
170
- textAlign: "center",
171
- textOverflow: "ellipsis",
172
- WebkitBoxOrient: "vertical",
173
- WebkitLineClamp: 2,
174
- width: `${NODE_WIDTH}px`,
175
- zIndex: 10,
176
- }, children: agentName }) })] }));
162
+ const [isHovered, setIsHovered] = useState(false);
163
+ const wrappedAgentName = agentName
164
+ // Allow wrap after underscore
165
+ .replaceAll("_", `_${ZERO_WIDTH_SPACE}`)
166
+ // Allow wrap before capitals in camel/PascalCase (e.g., CustomerSupport -> Customer|Support)
167
+ .replaceAll(/(?<lower>[\da-z])(?<upper>[A-Z])/gu, `$<lower>${ZERO_WIDTH_SPACE}$<upper>`)
168
+ // Also split abbreviation->word boundary (e.g., HTTPServer -> HTTP|Server), but not H|T|T|P
169
+ .replaceAll(/(?<abbr>[A-Z])(?<word>[A-Z][a-z])/gu, `$<abbr>${ZERO_WIDTH_SPACE}$<word>`);
170
+ const height = NODE_HEIGHT * (isFrontman ? FRONTMAN_SIZE_MULTIPLIER : 1.0);
171
+ const width = height;
172
+ const getEditButton = () => (_jsx(Tooltip, { title: "Edit", placement: "top", disableInteractive: true, children: _jsx(IconButton, { sx: {
173
+ position: "absolute",
174
+ top: 0,
175
+ right: 0,
176
+ backgroundColor: "rgba(0,0,0,0.45)",
177
+ borderRadius: "50%",
178
+ padding: "3px",
179
+ zIndex: 2,
180
+ cursor: "pointer",
181
+ "&:hover": { backgroundColor: "rgba(0,0,0,0.65)" },
182
+ }, children: _jsx(EditIcon, { id: `${agentId}-edit-icon`, sx: { fontSize: "1rem", color: "white" } }) }) }));
183
+ const getNodeName = () => (_jsx(Tooltip, { id: `${agentId}-tooltip`, title: agentName, placement: "top", disableInteractive: true, children: _jsx(Typography, { id: `${agentId}-name`, sx: {
184
+ backgroundColor: theme.palette.background.paper,
185
+ border: `1px solid ${theme.palette.divider}`,
186
+ borderRadius: 1,
187
+ color: theme.palette.text.primary,
188
+ display: "-webkit-box",
189
+ fontSize: "16px",
190
+ fontWeight: "700",
191
+ marginTop: "0.5rem",
192
+ overflow: "hidden",
193
+ overflowWrap: "anywhere",
194
+ paddingLeft: 0.75,
195
+ paddingRight: 0.75,
196
+ paddingBottom: 0.45,
197
+ paddingTop: 0.45,
198
+ textAlign: "center",
199
+ WebkitBoxOrient: "vertical",
200
+ WebkitLineClamp: 4,
201
+ width,
202
+ zIndex: getZIndex(1, theme),
203
+ }, children: wrappedAgentName }) }));
204
+ const getNode = () => (_jsxs(AnimatedNode, { id: agentId, "data-testid": agentId, glowColor: glowColor, isActive: isActiveAgent, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), sx: {
205
+ backgroundColor,
206
+ color,
207
+ cursor: isEditable ? "pointer" : "grab",
208
+ height,
209
+ width,
210
+ zIndex: getZIndex(1, theme),
211
+ }, children: [getDisplayAsIcon(), isHovered && isEditable && getEditButton(), _jsx(Handle, { id: `${agentId}-left-handle`, position: Position.Left, type: "source", style: { visibility: handleVisibility } }), _jsx(Handle, { id: `${agentId}-right-handle`, position: Position.Right, type: "source", style: { visibility: handleVisibility } }), _jsx(Handle, { id: `${agentId}-top-handle`, position: Position.Top, type: "source", style: { visibility: handleVisibility } }), _jsx(Handle, { id: `${agentId}-bottom-handle`, position: Position.Bottom, type: "source", style: { visibility: handleVisibility } })] }));
212
+ return (_jsxs(_Fragment, { children: [getNode(), getNodeName()] }));
177
213
  };
@@ -17,10 +17,7 @@ export interface AgentNodePopupProps {
17
17
  readonly initialInstructions?: string;
18
18
  /** Initial description text shown in the editable field. Defaults to an empty string. */
19
19
  readonly initialDescription?: string;
20
- /**
21
- * When true the dialog is in a saving state: the Save button is disabled and shows a spinner.
22
- * Defaults to false.
23
- */
20
+ /** When true the save API call is in-flight; shows an "Applying changes..." button and disables both actions. */
24
21
  readonly isSaving?: boolean;
25
22
  }
26
23
  /**
@@ -17,7 +17,6 @@ limitations under the License.
17
17
  import Box from "@mui/material/Box";
18
18
  import Button from "@mui/material/Button";
19
19
  import CircularProgress from "@mui/material/CircularProgress";
20
- import LinearProgress from "@mui/material/LinearProgress";
21
20
  import TextField from "@mui/material/TextField";
22
21
  import { useEffect, useState } from "react";
23
22
  import { ConfirmationModal } from "../Common/ConfirmationModal.js";
@@ -64,18 +63,18 @@ export const AgentNodePopup = ({ agentName, isOpen, onClose, onSave, initialInst
64
63
  justifyContent: "flex-end",
65
64
  width: "100%",
66
65
  gap: 1,
67
- }, children: _jsxs(Box, { sx: { display: "flex", gap: 1 }, children: [_jsx(Button, { id: "agent-node-popup-cancel-btn", onClick: handleClose, variant: "outlined", size: "small", disabled: isSaving, children: "Cancel" }), _jsx(Button, { id: "agent-node-popup-save-btn", onClick: handleSave, variant: "contained", size: "small", disabled: isSaving || !isDirty, startIcon: isSaving ? (_jsx(CircularProgress, { size: 14, color: "inherit" })) : undefined, children: isSaving ? "Applying changes" : "Save" })] }) }));
66
+ }, children: _jsxs(Box, { sx: { display: "flex", gap: 1 }, children: [_jsx(Button, { id: "agent-node-popup-cancel-btn", onClick: handleClose, variant: "outlined", size: "small", disabled: isSaving, children: "Cancel" }), _jsx(Button, { id: "agent-node-popup-save-btn", onClick: handleSave, variant: "contained", size: "small", disabled: isSaving || !isDirty, startIcon: isSaving ? (_jsx(CircularProgress, { size: 14, color: "inherit" })) : undefined, children: isSaving ? "Applying changes..." : "Save" })] }) }));
68
67
  const getConfirmationModal = () => (_jsx(ConfirmationModal, { id: "agent-node-popup-unsaved-changes-modal", cancelBtnLabel: "Discard changes", closeable: false, content: _jsx("p", { children: "You have unsaved edits. Are you sure you want to discard your changes and close the dialog?" }), handleCancel: () => {
69
68
  setDisplayConfirmationModal(false);
70
69
  setInstructionsText(initialInstructions);
71
70
  setDescriptionText(initialDescription);
72
71
  onClose();
73
72
  }, handleOk: handleSave, maskCloseable: false, okBtnLabel: "Save changes", title: "Unsaved Changes" }));
74
- return (_jsxs(_Fragment, { children: [displayConfirmationModal && getConfirmationModal(), _jsxs(MUIDialog, { dialogSx: isSaving ? { "& *, & *::before, & *::after": { cursor: "wait !important" } } : undefined, footer: footer, id: "agent-node-popup", isOpen: isOpen, onClose: handleClose, paperProps: { minWidth: "480px", maxWidth: "600px", width: "100%" }, title: agentName, children: [isSaving && (_jsx(LinearProgress, { "aria-label": "Saving agent", sx: { mb: 2, borderRadius: 1 } })), _jsx(TextField, { disabled: isSaving, fullWidth: true, id: "agent-node-popup-description-field", label: "Description", multiline: true, onChange: (e) => setDescriptionText(e.target.value), onKeyDown: (e) => {
73
+ return (_jsxs(_Fragment, { children: [displayConfirmationModal && getConfirmationModal(), _jsxs(MUIDialog, { footer: footer, id: "agent-node-popup", isOpen: isOpen, onClose: handleClose, paperProps: { minWidth: "480px", maxWidth: "600px", width: "100%" }, title: agentName, children: [_jsx(TextField, { disabled: isSaving, fullWidth: true, id: "agent-node-popup-description-field", label: "Description", multiline: true, onChange: (e) => setDescriptionText(e.target.value), onKeyDown: (e) => {
75
74
  if (e.key !== "Escape")
76
75
  e.stopPropagation();
77
- }, placeholder: "Enter a short description of this agent\u2026", rows: 6, size: "small", sx: { "& .MuiInputBase-input": { fontSize: "0.85rem" } }, value: descriptionText }), _jsx(TextField, { autoFocus: true, disabled: isSaving, fullWidth: true, id: "agent-node-popup-instructions-field", label: "Instructions", multiline: true, onChange: (e) => setInstructionsText(e.target.value), onKeyDown: (e) => {
76
+ }, placeholder: "Enter a short description of this agent\u2026", rows: 6, slotProps: { htmlInput: { style: { fontSize: "0.85rem" } } }, size: "small", value: descriptionText }), _jsx(TextField, { autoFocus: true, disabled: isSaving, fullWidth: true, id: "agent-node-popup-instructions-field", label: "Instructions", multiline: true, onChange: (e) => setInstructionsText(e.target.value), onKeyDown: (e) => {
78
77
  if (e.key !== "Escape")
79
78
  e.stopPropagation();
80
- }, placeholder: "Enter instructions for this agent\u2026", rows: 6, size: "small", sx: { "& .MuiInputBase-input": { fontSize: "0.85rem" }, marginTop: 2 }, value: instructionsText })] })] }));
79
+ }, placeholder: "Enter instructions for this agent\u2026", rows: 6, slotProps: { htmlInput: { style: { fontSize: "0.85rem" } } }, size: "small", sx: { marginTop: 2 }, value: instructionsText })] })] }));
81
80
  };
@@ -19,10 +19,13 @@ limitations under the License.
19
19
  import dagre from "@dagrejs/dagre";
20
20
  import { MarkerType } from "@xyflow/react";
21
21
  import cloneDeep from "lodash-es/cloneDeep.js";
22
- import { NODE_HEIGHT, NODE_WIDTH } from "./AgentNode.js";
22
+ import { FRONTMAN_SIZE_MULTIPLIER, NODE_HEIGHT, NODE_WIDTH } from "./AgentNode.js";
23
23
  import { BASE_RADIUS, DEFAULT_FRONTMAN_X_POS, DEFAULT_FRONTMAN_Y_POS, LEVEL_SPACING } from "./const.js";
24
+ import { isEditableAgent } from "./TemporaryNetworks.js";
24
25
  import { cleanUpAgentName, KNOWN_MESSAGE_TYPES_FOR_PLASMA } from "../AgentChat/Common/Utils.js";
25
26
  export const MAX_GLOBAL_THOUGHT_BUBBLES = 5;
27
+ const FRONTMAN_OFFSET_X = (NODE_WIDTH * (FRONTMAN_SIZE_MULTIPLIER - 1)) / 2;
28
+ const FRONTMAN_OFFSET_Y = (NODE_HEIGHT * (FRONTMAN_SIZE_MULTIPLIER - 1)) / 2;
26
29
  export const addThoughtBubbleEdge = (thoughtBubbleEdges, conversationId, edge) => {
27
30
  // Add with timestamp for age-based cleanup
28
31
  thoughtBubbleEdges.set(conversationId, {
@@ -31,7 +34,7 @@ export const addThoughtBubbleEdge = (thoughtBubbleEdges, conversationId, edge) =
31
34
  });
32
35
  // Enforce max limit - remove oldest if over limit
33
36
  if (thoughtBubbleEdges.size > MAX_GLOBAL_THOUGHT_BUBBLES) {
34
- const entries = Array.from(thoughtBubbleEdges.entries());
37
+ const entries = [...thoughtBubbleEdges.entries()];
35
38
  const sorted = entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
36
39
  const toRemove = sorted.slice(0, sorted.length - MAX_GLOBAL_THOUGHT_BUBBLES);
37
40
  toRemove.forEach(([id]) => {
@@ -43,7 +46,7 @@ export const removeThoughtBubbleEdge = (thoughtBubbleEdges, conversationId) => {
43
46
  thoughtBubbleEdges.delete(conversationId);
44
47
  };
45
48
  export const getThoughtBubbleEdges = (thoughtBubbleEdges) => {
46
- return Array.from(thoughtBubbleEdges.values()).map((item) => item.edge);
49
+ return [...thoughtBubbleEdges.values()].map((item) => item.edge);
47
50
  };
48
51
  // Helper function for plasma edges to check if two agents are in the same conversation
49
52
  const areInSameConversation = (conversations, sourceAgent, targetAgent) => {
@@ -190,9 +193,13 @@ isAwaitingLlm, isAgentNetworkDesignerMode, thoughtBubbleEdges, agentIconSuggesti
190
193
  getConversations: () => currentConversations,
191
194
  isAwaitingLlm,
192
195
  agentIconSuggestion: agentIconSuggestions?.[nodeId],
193
- isTemporaryNetwork,
196
+ isEditable: isTemporaryNetwork &&
197
+ isEditableAgent(agentsInNetwork.find((a) => a.origin === nodeId)?.display_as),
194
198
  },
195
- position: isFrontman ? { x: DEFAULT_FRONTMAN_X_POS, y: DEFAULT_FRONTMAN_Y_POS } : { x, y },
199
+ // position: allow for Frontman being larger
200
+ position: isFrontman
201
+ ? { x: DEFAULT_FRONTMAN_X_POS - FRONTMAN_OFFSET_X, y: DEFAULT_FRONTMAN_Y_POS - FRONTMAN_OFFSET_Y }
202
+ : { x, y },
196
203
  style: {
197
204
  border: "none",
198
205
  background: "transparent",
@@ -232,7 +239,7 @@ isAwaitingLlm, isAgentNetworkDesignerMode, thoughtBubbleEdges, agentIconSuggesti
232
239
  isAwaitingLlm,
233
240
  depth: undefined, // Depth will be computed later,
234
241
  agentIconSuggestion: agentIconSuggestions?.[nodeId],
235
- isTemporaryNetwork,
242
+ isEditable: isTemporaryNetwork && isEditableAgent(agentsInNetwork.find((a) => a.origin === nodeId)?.display_as),
236
243
  },
237
244
  position: isFrontman ? { x: DEFAULT_FRONTMAN_X_POS, y: DEFAULT_FRONTMAN_Y_POS } : { x: 0, y: 0 },
238
245
  style: {
@@ -273,15 +280,18 @@ isAwaitingLlm, isAgentNetworkDesignerMode, thoughtBubbleEdges, agentIconSuggesti
273
280
  // Compute the layout using dagre
274
281
  dagre.layout(dagreGraph);
275
282
  // Get x positions for the nodes in nodesTmp. Keep only unique values and sort numerically
276
- const xPositions = Array.from(new Set(nodesTmp.map((node) => dagreGraph.node(node.id).x))).sort((a, b) => a - b);
283
+ const xPositions = [...new Set(nodesTmp.map((node) => dagreGraph.node(node.id).x))].sort((a, b) => a - b);
277
284
  // Convert dagre's layout to what our flow graph needs
278
285
  nodesTmp.forEach((node) => {
279
286
  const nodeWithPosition = dagreGraph.node(node.id);
287
+ const isFrontman = frontman?.origin === node.id;
280
288
  // We are shifting the dagre node position (anchor=center) to the top left
281
289
  // so it matches the React Flow node anchor point (top left).
290
+ const x = nodeWithPosition.x - NODE_WIDTH / 2 - (isFrontman ? FRONTMAN_OFFSET_X : 0);
291
+ const y = nodeWithPosition.y - NODE_HEIGHT / 2 - (isFrontman ? FRONTMAN_OFFSET_Y : 0);
282
292
  node.position = {
283
- x: nodeWithPosition.x - NODE_WIDTH / 2,
284
- y: nodeWithPosition.y - NODE_HEIGHT / 2,
293
+ x,
294
+ y,
285
295
  };
286
296
  // Depth is index of x position in xPositions array
287
297
  // Create a new data object with updated depth
@@ -1,5 +1,5 @@
1
1
  import { FC } from "react";
2
- interface MultiAgentAcceleratorProps {
2
+ export interface MultiAgentAcceleratorProps {
3
3
  readonly userInfo: {
4
4
  userName: string;
5
5
  userImage: string;
@@ -7,6 +7,7 @@ interface MultiAgentAcceleratorProps {
7
7
  readonly backendNeuroSanApiUrl: string;
8
8
  }
9
9
  export declare const GRACE_PERIOD_MS: number;
10
+ export declare const SHOW_TOUR_DELAY_MS = 5000;
10
11
  /**
11
12
  * Main Multi-Agent Accelerator component that contains the sidebar, agent flow, and chat components.
12
13
  * @param backendNeuroSanApiUrl Initial URL of the backend Neuro-San API. User can change this in the UI.
@@ -14,4 +15,3 @@ export declare const GRACE_PERIOD_MS: number;
14
15
  * @param userInfo Information about the current user, including userName and userImage.
15
16
  */
16
17
  export declare const MultiAgentAccelerator: FC<MultiAgentAcceleratorProps>;
17
- export {};