@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.
Files changed (114) hide show
  1. package/README.md +287 -0
  2. package/dist/Theme/Palettes.d.ts +18 -0
  3. package/dist/Theme/Palettes.js +94 -0
  4. package/dist/Theme/Theme.d.ts +22 -0
  5. package/dist/Theme/Theme.js +58 -0
  6. package/dist/components/AgentChat/ChatCommon.d.ts +4 -2
  7. package/dist/components/AgentChat/ChatCommon.js +141 -105
  8. package/dist/components/AgentChat/ControlButtons.js +3 -1
  9. package/dist/components/AgentChat/FormattedMarkdown.d.ts +4 -4
  10. package/dist/components/AgentChat/FormattedMarkdown.js +5 -7
  11. package/dist/components/AgentChat/LlmChatButton.d.ts +2 -6
  12. package/dist/components/AgentChat/LlmChatButton.js +3 -3
  13. package/dist/components/AgentChat/UserQueryDisplay.js +2 -4
  14. package/dist/components/AgentChat/Utils.d.ts +2 -1
  15. package/dist/components/AgentChat/Utils.js +4 -1
  16. package/dist/components/AgentChat/VoiceChat/MicrophoneButton.d.ts +2 -2
  17. package/dist/components/AgentChat/VoiceChat/VoiceChat.d.ts +3 -3
  18. package/dist/components/AgentChat/VoiceChat/VoiceChat.js +5 -5
  19. package/dist/components/ChatBot/ChatBot.js +2 -2
  20. package/dist/components/Common/Breadcrumbs.js +1 -1
  21. package/dist/components/Common/{confirmationModal.js → ConfirmationModal.js} +2 -5
  22. package/dist/components/Common/CustomerLogo.d.ts +17 -0
  23. package/dist/components/Common/CustomerLogo.js +49 -0
  24. package/dist/components/Common/Footer.d.ts +18 -0
  25. package/dist/components/Common/Footer.js +59 -0
  26. package/dist/components/Common/LlmChatOptionsButton.d.ts +1 -4
  27. package/dist/components/Common/LlmChatOptionsButton.js +4 -4
  28. package/dist/components/Common/LoadingSpinner.js +1 -1
  29. package/dist/components/Common/MUIAccordion.d.ts +2 -2
  30. package/dist/components/Common/MUIAccordion.js +2 -12
  31. package/dist/components/Common/MUIAlert.d.ts +2 -1
  32. package/dist/components/Common/MUIAlert.js +4 -1
  33. package/dist/components/Common/MUIDialog.d.ts +1 -1
  34. package/dist/components/Common/MUIDialog.js +1 -1
  35. package/dist/components/Common/Navbar.d.ts +3 -1
  36. package/dist/components/Common/Navbar.js +60 -35
  37. package/dist/components/Common/PageLoader.js +3 -4
  38. package/dist/components/Common/Snackbar.d.ts +4 -1
  39. package/dist/components/Common/Snackbar.js +11 -19
  40. package/dist/components/Common/notification.d.ts +3 -3
  41. package/dist/components/Common/notification.js +6 -6
  42. package/dist/components/ErrorPage/ErrorBoundary.d.ts +2 -2
  43. package/dist/components/ErrorPage/ErrorBoundary.js +1 -1
  44. package/dist/components/ErrorPage/ErrorPage.js +6 -5
  45. package/dist/components/MultiAgentAccelerator/AgentConversations.d.ts +17 -0
  46. package/dist/components/MultiAgentAccelerator/AgentConversations.js +77 -0
  47. package/dist/components/MultiAgentAccelerator/AgentCounts.d.ts +12 -0
  48. package/dist/components/MultiAgentAccelerator/AgentCounts.js +21 -0
  49. package/dist/components/MultiAgentAccelerator/AgentFlow.d.ts +6 -4
  50. package/dist/components/MultiAgentAccelerator/AgentFlow.js +106 -185
  51. package/dist/components/MultiAgentAccelerator/AgentNode.d.ts +7 -5
  52. package/dist/components/MultiAgentAccelerator/AgentNode.js +93 -50
  53. package/dist/components/MultiAgentAccelerator/GraphLayouts.d.ts +20 -17
  54. package/dist/components/MultiAgentAccelerator/GraphLayouts.js +16 -14
  55. package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +2 -3
  56. package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +214 -55
  57. package/dist/components/MultiAgentAccelerator/PlasmaEdge.d.ts +1 -1
  58. package/dist/components/MultiAgentAccelerator/PlasmaEdge.js +14 -12
  59. package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.d.ts +15 -0
  60. package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.js +104 -0
  61. package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.d.ts +17 -0
  62. package/dist/components/MultiAgentAccelerator/{Sidebar.js → Sidebar/Sidebar.js} +146 -59
  63. package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.d.ts +19 -0
  64. package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.js +113 -0
  65. package/dist/components/MultiAgentAccelerator/TemporaryNetworks.d.ts +26 -0
  66. package/dist/components/MultiAgentAccelerator/TemporaryNetworks.js +20 -0
  67. package/dist/components/MultiAgentAccelerator/ThoughtBubbleEdge.d.ts +10 -8
  68. package/dist/components/MultiAgentAccelerator/ThoughtBubbleEdge.js +1 -1
  69. package/dist/components/MultiAgentAccelerator/ThoughtBubbleOverlay.d.ts +3 -2
  70. package/dist/components/MultiAgentAccelerator/ThoughtBubbleOverlay.js +10 -13
  71. package/dist/components/MultiAgentAccelerator/const.d.ts +1 -3
  72. package/dist/components/MultiAgentAccelerator/const.js +4 -18
  73. package/dist/components/Settings/FadingCheckmark.d.ts +14 -0
  74. package/dist/components/Settings/FadingCheckmark.js +43 -0
  75. package/dist/components/Settings/SettingsDialog.d.ts +9 -0
  76. package/dist/components/Settings/SettingsDialog.js +265 -0
  77. package/dist/const.d.ts +1 -2
  78. package/dist/const.js +2 -3
  79. package/dist/controller/Types/AgentIconSuggestions.d.ts +4 -0
  80. package/dist/controller/Types/AgentIconSuggestions.js +1 -0
  81. package/dist/controller/Types/Branding.d.ts +12 -0
  82. package/dist/controller/Types/Branding.js +1 -0
  83. package/dist/controller/Types/NetworkIconSuggestions.d.ts +4 -0
  84. package/dist/controller/Types/NetworkIconSuggestions.js +1 -0
  85. package/dist/controller/agent/Agent.d.ts +32 -12
  86. package/dist/controller/agent/Agent.js +71 -19
  87. package/dist/controller/llm/LlmChat.d.ts +1 -1
  88. package/dist/controller/llm/LlmChat.js +2 -2
  89. package/dist/index.d.ts +10 -5
  90. package/dist/index.js +10 -5
  91. package/dist/state/{environment.d.ts → Environment.d.ts} +2 -0
  92. package/dist/state/{environment.js → Environment.js} +2 -0
  93. package/dist/state/Settings.d.ts +62 -0
  94. package/dist/state/Settings.js +62 -0
  95. package/dist/state/TemporaryNetworks.d.ts +32 -0
  96. package/dist/state/TemporaryNetworks.js +26 -0
  97. package/dist/tsconfig.build.tsbuildinfo +1 -1
  98. package/dist/utils/Authentication.d.ts +2 -2
  99. package/dist/utils/Authentication.js +6 -6
  100. package/dist/utils/text.d.ts +2 -2
  101. package/dist/utils/text.js +3 -5
  102. package/dist/utils/title.d.ts +1 -1
  103. package/dist/utils/title.js +2 -2
  104. package/dist/utils/useLocalStorage.d.ts +1 -1
  105. package/dist/utils/useLocalStorage.js +3 -3
  106. package/dist/utils/zIndexLayers.d.ts +1 -1
  107. package/dist/utils/zIndexLayers.js +3 -15
  108. package/package.json +23 -21
  109. package/dist/components/MultiAgentAccelerator/Sidebar.d.ts +0 -12
  110. package/dist/utils/Theme.d.ts +0 -7
  111. package/dist/utils/Theme.js +0 -7
  112. package/dist/utils/agentConversations.d.ts +0 -24
  113. package/dist/utils/agentConversations.js +0 -113
  114. /package/dist/components/Common/{confirmationModal.d.ts → ConfirmationModal.d.ts} +0 -0
@@ -23,14 +23,17 @@ import ClearIcon from "@mui/icons-material/Clear";
23
23
  import CloseIcon from "@mui/icons-material/Close";
24
24
  import VerticalAlignBottomIcon from "@mui/icons-material/VerticalAlignBottom";
25
25
  import WrapTextIcon from "@mui/icons-material/WrapText";
26
- import { Box, Input, useColorScheme } from "@mui/material";
26
+ import Box from "@mui/material/Box";
27
+ import Chip from "@mui/material/Chip";
27
28
  import CircularProgress from "@mui/material/CircularProgress";
28
29
  import IconButton from "@mui/material/IconButton";
30
+ import Input from "@mui/material/Input";
29
31
  import InputAdornment from "@mui/material/InputAdornment";
32
+ import { alpha, useTheme } from "@mui/material/styles";
30
33
  import Tooltip from "@mui/material/Tooltip";
31
34
  import Typography from "@mui/material/Typography";
32
35
  import { jsonrepair } from "jsonrepair";
33
- import { cloneElement, forwardRef, isValidElement, useEffect, useImperativeHandle, useRef, useState, } from "react";
36
+ import { isValidElement, useEffect, useImperativeHandle, useRef, useState, } from "react";
34
37
  import ReactMarkdown from "react-markdown";
35
38
  import SyntaxHighlighter from "react-syntax-highlighter";
36
39
  import { ControlButtons } from "./ControlButtons.js";
@@ -40,14 +43,13 @@ import { SendButton } from "./SendButton.js";
40
43
  import { HLJS_THEMES } from "./SyntaxHighlighterThemes.js";
41
44
  import { isLegacyAgentType } from "./Types.js";
42
45
  import { UserQueryDisplay } from "./UserQueryDisplay.js";
43
- import { chatMessageFromChunk, checkError, cleanUpAgentName } from "./Utils.js";
46
+ import { chatMessageFromChunk, checkError, cleanUpAgentName, removeTrailingUuid } from "./Utils.js";
44
47
  import { MicrophoneButton } from "./VoiceChat/MicrophoneButton.js";
45
48
  import { cleanupAndStopSpeechRecognition, setupSpeechRecognition } from "./VoiceChat/VoiceChat.js";
46
49
  import { getAgentFunction, getConnectivity, sendChatQuery } from "../../controller/agent/Agent.js";
47
50
  import { sendLlmRequest } from "../../controller/llm/LlmChat.js";
48
51
  import { ChatMessageType, } from "../../generated/neuro-san/NeuroSanClient.js";
49
52
  import { hashString, hasOnlyWhitespace } from "../../utils/text.js";
50
- import { isDarkMode } from "../../utils/Theme.js";
51
53
  import { LlmChatOptionsButton } from "../Common/LlmChatOptionsButton.js";
52
54
  import { MUIAccordion } from "../Common/MUIAccordion.js";
53
55
  import { MUIAlert } from "../Common/MUIAlert.js";
@@ -59,18 +61,25 @@ const AGENT_IMAGE = "/agent.svg";
59
61
  // How many times to retry the entire agent interaction process. Some networks have a well-defined success condition.
60
62
  // For others, it's just "whenever the stream is done".
61
63
  const MAX_AGENT_RETRIES = 3;
64
+ // Maximum number of sample queries to show
65
+ const MAX_SAMPLE_QUERIES = 5;
66
+ // Maximum length of query to show in sample query chips
67
+ const QUERY_TRUNCATE_LENGTH = 80;
62
68
  /**
63
69
  * Common chat component for agent chat. This component is used by all agent chat components to provide a consistent
64
70
  * experience for users when chatting with agents. It handles user input as well as displaying and nicely formatting
65
71
  * agent responses. Customization for inputs and outputs is provided via event handlers-like props.
66
72
  */
67
- export const ChatCommon = forwardRef((props, ref) => {
73
+ export const ChatCommon = ({ ref, ...props }) => {
68
74
  const slyData = useRef({});
69
75
  const { id, currentUser, userImage, setIsAwaitingLlm, isAwaitingLlm, onChunkReceived, onStreamingStarted, onStreamingComplete, onSend, setPreviousResponse, targetAgent, legacyAgentEndpoint, agentPlaceholders = EMPTY, clearChatOnNewAgent = false, extraParams, backgroundColor, title, onClose, neuroSanURL, } = props;
70
76
  // Expose the handleStop method to parent components via ref for external control (e.g., to cancel chat requests)
71
77
  useImperativeHandle(ref, () => ({
72
78
  handleStop,
73
79
  }));
80
+ // MUI theme
81
+ const theme = useTheme();
82
+ const shadowColor = theme.palette.mode === "dark" ? theme.palette.common.white : theme.palette.common.black;
74
83
  // User LLM chat input
75
84
  const [chatInput, setChatInput] = useState("");
76
85
  // Previous user query (for "regenerate" feature)
@@ -136,8 +145,7 @@ export const ChatCommon = forwardRef((props, ref) => {
136
145
  };
137
146
  // Keeps track of whether the agent completed its task
138
147
  const succeeded = useRef(false);
139
- const { mode, systemMode } = useColorScheme();
140
- const darkMode = isDarkMode(mode, systemMode);
148
+ const darkMode = theme.palette.mode === "dark";
141
149
  const { atelierDuneDark, a11yLight } = HLJS_THEMES;
142
150
  useEffect(() => {
143
151
  // Set up speech recognition
@@ -145,21 +153,6 @@ export const ChatCommon = forwardRef((props, ref) => {
145
153
  // Clean up function
146
154
  return () => cleanupAndStopSpeechRecognition(speechRecognitionRef, handlers);
147
155
  }, []);
148
- // Hide/show existing accordions based on showThinking state
149
- useEffect(() => {
150
- setChatOutput((currentOutput) => currentOutput.map((item) => {
151
- if (isValidElement(item) && item.type === MUIAccordion) {
152
- const itemAsAccordion = item;
153
- return cloneElement(itemAsAccordion, {
154
- sx: {
155
- ...item.props.sx,
156
- display: showThinking || item.key === finalAnswerKey?.current ? "block" : "none",
157
- },
158
- });
159
- }
160
- return item;
161
- }));
162
- }, [showThinking, darkMode]);
163
156
  // Sync ref with state variable for use within timer etc.
164
157
  useEffect(() => {
165
158
  autoScrollEnabledRef.current = autoScrollEnabled;
@@ -226,23 +219,23 @@ export const ChatCommon = forwardRef((props, ref) => {
226
219
  return (_jsx(MUIAccordion, { id: `${hashedSummary}-panel`, defaultExpandedPanelKey: isFinalAnswer ? 1 : null, items: [
227
220
  {
228
221
  title: summary,
229
- content: (_jsx("div", { id: `${summary}-details`, children: repairedJson ? (_jsx(SyntaxHighlighter, { id: "syntax-highlighter", language: "json", style: darkMode ? atelierDuneDark : a11yLight, showLineNumbers: false, wrapLongLines: shouldWrapOutput, children: repairedJson })) : (_jsx(ReactMarkdown, { children: logLine || "No further details" }, hashString(logLine))) })),
222
+ content: (_jsx("div", { id: `${summary}-details`, children: repairedJson ? (_jsx(SyntaxHighlighter, { id: "syntax-highlighter", language: "json", style: darkMode ? atelierDuneDark : a11yLight, showLineNumbers: false, wrapLongLines: shouldWrapOutput, children: repairedJson })) : (_jsx(ReactMarkdown, { children: logLine }, hashString(logLine))) })),
230
223
  },
231
224
  ], sx: {
232
225
  fontSize: "large",
233
226
  marginBottom: "1rem",
234
- display: showThinking || isFinalAnswer ? "block" : "none",
235
227
  boxShadow: isFinalAnswer
236
- ? `0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12),
237
- 0 9px 28px 8px rgba(0, 0, 0, 0.05)`
228
+ ? `0 6px 16px 0 ${alpha(shadowColor, 0.08)}, 0 3px 6px -4px ${alpha(shadowColor, 0.12)},
229
+ 0 9px 28px 8px ${alpha(shadowColor, 0.05)}`
238
230
  : "none",
239
231
  } }, hashedSummary));
240
232
  };
241
- /**
242
- * Introduce the agent to the user with a friendly greeting
243
- */
233
+ const agentDisplayName = cleanUpAgentName(removeTrailingUuid(targetAgent));
244
234
  const introduceAgent = () => {
245
- updateOutput(_jsx(UserQueryDisplay, { userQuery: cleanUpAgentName(targetAgent), title: targetAgent, userImage: AGENT_IMAGE }));
235
+ /**
236
+ * Introduce the agent to the user with a friendly greeting
237
+ */
238
+ updateOutput(_jsx(UserQueryDisplay, { userQuery: agentDisplayName, title: targetAgent, userImage: AGENT_IMAGE }));
246
239
  // Random greeting
247
240
  const greeting = AGENT_GREETINGS[Math.floor(Math.random() * AGENT_GREETINGS.length)];
248
241
  updateOutput(greeting);
@@ -259,6 +252,27 @@ export const ChatCommon = forwardRef((props, ref) => {
259
252
  .sort((a, b) => a.origin.localeCompare(b.origin))
260
253
  // Render each origin and its tools
261
254
  .map((info) => (_jsxs("li", { id: info.origin, children: [_jsx("b", { id: info.origin, children: info.origin }), _jsx("ul", { id: `${info.origin}-tools`, style: { marginLeft: "8px" }, children: info?.tools?.map((tool) => (_jsx("li", { id: tool, children: tool }, tool))) })] }, info.origin))) }));
255
+ /**
256
+ * Render sample queries as clickable chips. Agents may or may not have sample queries defined.
257
+ * @param sampleQueries The sample queries to render (from "connectivity" API)
258
+ * @returns A ReactNode representing the sample queries as clickable chips. If a user clicks a chip, it will
259
+ * send the query to the agent.
260
+ */
261
+ const renderSampleQueries = (sampleQueries) => {
262
+ return sampleQueries?.length > 0 ? (_jsx(Box, { id: "sample-queries-box", sx: { marginTop: "2rem", marginBottom: "1rem" }, children: sampleQueries.slice(0, MAX_SAMPLE_QUERIES).map((query) => (_jsx(Tooltip, { id: `tooltip-${query}`, title: `Click to send query: "${query}"`, children: _jsx(Chip, { id: `sample-query-${query}`, label: query.length > QUERY_TRUNCATE_LENGTH
263
+ ? `${query.slice(0, QUERY_TRUNCATE_LENGTH)}...`
264
+ : query, onClick: async () => {
265
+ await handleSend(query);
266
+ }, sx: {
267
+ color: "var(--bs-white)",
268
+ marginRight: "1rem",
269
+ marginBottom: "1rem",
270
+ backgroundColor: "var(--bs-accent1-medium)",
271
+ "&:hover": {
272
+ backgroundColor: "var(--bs-accent1-dark)",
273
+ },
274
+ } }, query) }, `tooltip-${query}`))) })) : null;
275
+ };
262
276
  useEffect(() => {
263
277
  const newAgent = async () => {
264
278
  if (clearChatOnNewAgent) {
@@ -288,10 +302,9 @@ export const ChatCommon = forwardRef((props, ref) => {
288
302
  updateOutput(_jsx(MUIAccordion, { id: `${id}-agent-details`, sx: {
289
303
  marginTop: "1rem",
290
304
  marginBottom: "1rem",
291
- borderColor: darkMode ? "var(--bs-white)" : "var(--bs-border-color)",
292
305
  }, items: [
293
306
  {
294
- title: "Agent Details",
307
+ title: "Network Details",
295
308
  content: [
296
309
  `My description is: "${agentFunction?.function?.description}"`,
297
310
  _jsx("h6", { id: "connectivity-header", style: { marginTop: "1rem" }, children: "I can connect you to the following agents" }, "item-1"),
@@ -299,6 +312,7 @@ export const ChatCommon = forwardRef((props, ref) => {
299
312
  ],
300
313
  },
301
314
  ] }));
315
+ updateOutput(renderSampleQueries(connectivity?.metadata?.["sample_queries"] ?? []));
302
316
  }
303
317
  catch (e) {
304
318
  sendNotification(NotificationType.error, `Failed to get connectivity info for ${cleanUpAgentName(targetAgent)}. Error: ${e}`);
@@ -358,7 +372,7 @@ export const ChatCommon = forwardRef((props, ref) => {
358
372
  // Give container a chance to process the chunk first
359
373
  const onChunkReceivedResult = onChunkReceived?.(chunk) ?? true;
360
374
  succeeded.current = succeeded.current || onChunkReceivedResult;
361
- // For legacy agents, we either get plain text or markdown. Just output it as-is.
375
+ // For legacy agents, we either get plain text or Markdown. Just output it as-is.
362
376
  if (isLegacyAgentType(targetAgent)) {
363
377
  // Display output as-is
364
378
  updateOutput(chunk);
@@ -407,7 +421,7 @@ export const ChatCommon = forwardRef((props, ref) => {
407
421
  updateOutput(processLogLine(chatMessage.text, agentName, chatMessage.type));
408
422
  }
409
423
  };
410
- async function doQueryLoop(query) {
424
+ const doQueryLoop = async (query) => {
411
425
  succeeded.current = false;
412
426
  let attemptNumber = 0;
413
427
  let wasAborted = false;
@@ -435,7 +449,7 @@ export const ChatCommon = forwardRef((props, ref) => {
435
449
  // AbortErrors are handled elsewhere. We also want to stop retries here.
436
450
  break;
437
451
  }
438
- if (!wasAborted) {
452
+ else {
439
453
  if (error instanceof Error) {
440
454
  console.error(error, error.stack);
441
455
  }
@@ -444,7 +458,7 @@ export const ChatCommon = forwardRef((props, ref) => {
444
458
  }
445
459
  } while (attemptNumber < MAX_AGENT_RETRIES && !succeeded.current);
446
460
  return { wasAborted };
447
- }
461
+ };
448
462
  const handleSend = async (query) => {
449
463
  // Record user query in chat history
450
464
  chatHistory.current = [...chatHistory.current, new HumanMessage(previousUserQuery)];
@@ -460,7 +474,7 @@ export const ChatCommon = forwardRef((props, ref) => {
460
474
  // user, but currently we do for orchestration.
461
475
  updateOutput(_jsx(UserQueryDisplay, { userQuery: query, title: currentUser, userImage: userImage }));
462
476
  // Add ID block for agent
463
- updateOutput(_jsx(UserQueryDisplay, { userQuery: cleanUpAgentName(targetAgent), title: targetAgent, userImage: AGENT_IMAGE }));
477
+ updateOutput(_jsx(UserQueryDisplay, { userQuery: cleanUpAgentName(removeTrailingUuid(targetAgent)), title: targetAgent, userImage: AGENT_IMAGE }));
464
478
  // Allow clients to do something when streaming starts
465
479
  onStreamingStarted?.();
466
480
  // Set up the abort controller
@@ -500,82 +514,104 @@ export const ChatCommon = forwardRef((props, ref) => {
500
514
  onStreamingComplete?.();
501
515
  }
502
516
  };
517
+ const getPlaceholder = () => !targetAgent ? null : agentPlaceholders[targetAgent] || `Chat with ${agentDisplayName}`;
503
518
  return (_jsxs(Box, { id: `llm-chat-${id}`, sx: {
504
519
  display: "flex",
505
520
  flexDirection: "column",
506
521
  flexGrow: 1,
507
522
  height: "100%",
508
- }, children: [title && (_jsxs(Box, { id: `llm-chat-title-container-${id}`, sx: {
509
- alignItems: "center",
510
- borderTopLeftRadius: "var(--bs-border-radius)",
511
- borderTopRightRadius: "var(--bs-border-radius)",
512
- display: "flex",
513
- justifyContent: "space-between",
514
- paddingLeft: "1rem",
515
- paddingRight: "0.5rem",
516
- paddingTop: "0.25rem",
517
- paddingBottom: "0.25rem",
518
- }, children: [_jsx(Typography, { id: `llm-chat-title-${id}-text`, sx: { fontSize: "0.9rem" }, children: title }), onClose && (_jsx(IconButton, { "data-testid": `close-button-${id}`, id: `close-button-${id}`, onClick: onClose, children: _jsx(CloseIcon, { id: `close-icon-${id}` }) }))] })), _jsxs(Box, { id: "llm-response-div", sx: {
519
- ...divStyle,
520
- border: "var(--bs-border-width) var(--bs-border-style)",
521
- borderRadius: "var(--bs-border-radius)",
523
+ position: "relative",
524
+ }, children: [!targetAgent && (_jsx(Box, { id: "chat-disabled-overlay", sx: {
525
+ position: "absolute",
526
+ top: 0,
527
+ left: 0,
528
+ right: 0,
529
+ bottom: 0,
530
+ zIndex: theme.zIndex.modal - 1,
531
+ cursor: "not-allowed",
532
+ // Capture all pointer events to prevent interaction with the chat when no agent is selected
533
+ pointerEvents: "all",
534
+ } })), _jsxs(Box, { id: "chat-content", sx: {
522
535
  display: "flex",
536
+ flexDirection: "column",
523
537
  flexGrow: 1,
524
538
  height: "100%",
525
- margin: "10px",
526
- position: "relative",
527
- overflowY: "auto",
528
- }, children: [_jsx(Tooltip, { id: "show-thinking", title: showThinking ? "Displaying agent thinking" : "Hiding agent thinking", children: _jsx("span", { id: "show-thinking-span", children: _jsx(LlmChatOptionsButton, { enabled: showThinking, id: "show-thinking-button", onClick: () => setShowThinking(!showThinking), posRight: 150, disabled: isAwaitingLlm, children: _jsx(AccountTreeIcon, { id: "show-thinking-icon", sx: { color: "var(--bs-white)", fontSize: "0.85rem" } }) }) }) }), _jsx(Tooltip, { id: "enable-autoscroll", title: autoScrollEnabled ? "Autoscroll enabled" : "Autoscroll disabled", children: _jsx(LlmChatOptionsButton, { enabled: autoScrollEnabled, id: "autoscroll-button", onClick: () => setAutoScrollEnabled(!autoScrollEnabled), posRight: 80, children: _jsx(VerticalAlignBottomIcon, { id: "autoscroll-icon", sx: { color: "var(--bs-white)", fontSize: "0.85rem" } }) }) }), _jsx(Tooltip, { id: "wrap-tooltip", title: shouldWrapOutput ? "Text wrapping enabled" : "Text wrapping disabled", children: _jsx(LlmChatOptionsButton, { enabled: shouldWrapOutput, id: "wrap-button", onClick: () => setShouldWrapOutput(!shouldWrapOutput), posRight: 10, children: _jsx(WrapTextIcon, { id: "wrap-icon", sx: { color: "var(--bs-white)", fontSize: "0.85rem" } }) }) }), _jsxs(Box, { id: "llm-responses", ref: chatOutputRef, sx: {
529
- backgroundColor: backgroundColor || "var(--bs-secondary-blue)",
530
- borderWidth: "1px",
531
- borderRadius: "0.5rem",
532
- fontSize: "smaller",
533
- resize: "none",
534
- overflowY: "auto", // Enable vertical scrollbar
535
- paddingBottom: "60px",
536
- paddingTop: "7.5px",
537
- paddingLeft: "15px",
538
- paddingRight: "15px",
539
- width: "100%",
540
- }, tabIndex: -1, children: [_jsx(FormattedMarkdown, { id: `${id}-formatted-markdown`, nodesList: chatOutput, style: darkMode ? atelierDuneDark : a11yLight, wrapLongLines: shouldWrapOutput }), isAwaitingLlm && (_jsxs(Box, { id: "awaitingOutputContainer", sx: { display: "flex", alignItems: "center", fontSize: "smaller" }, children: [_jsx("span", { id: "working-span", style: { marginRight: "1rem" }, children: "Working..." }), _jsx(CircularProgress, { id: "awaitingOutputSpinner", sx: {
541
- color: "var(--bs-primary)",
542
- }, size: "1rem" })] }))] }), _jsx(ControlButtons, { clearChatOnClickCallback: () => {
543
- setChatOutput([]);
544
- chatHistory.current = [];
545
- chatContext.current = null;
546
- setPreviousUserQuery("");
547
- currentResponse.current = "";
548
- lastAIMessage.current = "";
549
- introduceAgent();
550
- }, enableClearChatButton: enableClearChatButton, isAwaitingLlm: isAwaitingLlm, handleSend: handleSend, handleStop: handleStop, previousUserQuery: previousUserQuery, shouldEnableRegenerateButton: shouldEnableRegenerateButton })] }), _jsxs(Box, { id: "user-input-div", style: { ...divStyle, display: "flex", margin: "10px", alignItems: "flex-end", position: "relative" }, children: [_jsx(Input, { autoComplete: "off", id: "user-input", multiline: true, placeholder: agentPlaceholders[targetAgent] || `Chat with ${cleanUpAgentName(targetAgent)}`, ref: chatInputRef, sx: {
551
- border: "var(--bs-border-style) var(--bs-border-width) var(--bs-gray-light)",
539
+ opacity: targetAgent ? 1 : 0.4,
540
+ pointerEvents: targetAgent ? "auto" : "none",
541
+ }, children: [title && (_jsxs(Box, { id: `llm-chat-title-container-${id}`, sx: {
542
+ alignItems: "center",
543
+ borderTopLeftRadius: "var(--bs-border-radius)",
544
+ borderTopRightRadius: "var(--bs-border-radius)",
545
+ display: "flex",
546
+ justifyContent: "space-between",
547
+ paddingLeft: "1rem",
548
+ paddingRight: "0.5rem",
549
+ paddingTop: "0.25rem",
550
+ paddingBottom: "0.25rem",
551
+ }, children: [_jsx(Typography, { id: `llm-chat-title-${id}-text`, sx: { fontSize: "0.9rem" }, children: title }), onClose && (_jsx(IconButton, { "data-testid": `close-button-${id}`, id: `close-button-${id}`, onClick: onClose, children: _jsx(CloseIcon, { id: `close-icon-${id}` }) }))] })), _jsxs(Box, { id: "llm-response-div", sx: {
552
+ ...divStyle,
553
+ border: "var(--bs-border-width) var(--bs-border-style)",
552
554
  borderRadius: "var(--bs-border-radius)",
553
555
  display: "flex",
554
556
  flexGrow: 1,
555
- fontSize: "smaller",
556
- marginRight: "0.75rem",
557
- paddingBottom: "0.5rem",
558
- paddingTop: "0.5rem",
559
- paddingLeft: "1rem",
560
- paddingRight: "1rem",
561
- transition: "margin-right 0.2s",
562
- }, onChange: (event) => {
563
- setChatInput(event.target.value);
564
- }, onKeyDown: async (event) => {
565
- if (event.key === "Enter" && !event.shiftKey) {
566
- event.preventDefault();
567
- await handleSend(chatInput);
568
- }
569
- }, value: chatInput, endAdornment: _jsxs(InputAdornment, { id: "input-adornments", position: "end", disableTypography: true, children: [voiceInputState.isProcessingSpeech && (_jsx(CircularProgress, { size: 16, sx: {
570
- color: "var(--bs-primary)",
571
- marginRight: "0.5rem",
572
- } })), _jsx(IconButton, { id: "clear-input-button", onClick: () => {
573
- setChatInput("");
574
- }, sx: {
575
- color: "var(--bs-primary)",
576
- opacity: userInputEmpty ? "25%" : "100%",
577
- }, disabled: userInputEmpty, tabIndex: -1, edge: "end", children: _jsx(ClearIcon, { id: "clear-input-icon" }) })] }) }), _jsx(MicrophoneButton, { isMicOn: isMicOn, onMicToggle: setIsMicOn, speechRecognitionRef: speechRecognitionRef, voiceInputState: voiceInputState, setVoiceInputState: setVoiceInputState }), _jsx(SendButton, { enableSendButton: shouldEnableSendButton, id: "submit-query-button", onClickCallback: () => handleSend(chatInput) })] })] }));
578
- });
579
- // Set a useful display name for the component for debugging purposes. We have to do it here because we're using
580
- // forwardRef in the main definition.
581
- ChatCommon.displayName = "ChatCommon";
557
+ height: "100%",
558
+ margin: "10px",
559
+ position: "relative",
560
+ overflowY: "auto",
561
+ }, children: [_jsx(Tooltip, { id: "show-thinking", title: showThinking ? "Displaying agent thinking" : "Hiding agent thinking", children: _jsx("span", { id: "show-thinking-span", children: _jsx(LlmChatOptionsButton, { enabled: showThinking, id: "show-thinking-button", onClick: () => setShowThinking(!showThinking), posRight: 150, disabled: isAwaitingLlm, children: _jsx(AccountTreeIcon, { id: "show-thinking-icon", sx: { color: "var(--bs-white)", fontSize: "0.85rem" } }) }) }) }), _jsx(Tooltip, { id: "enable-autoscroll", title: autoScrollEnabled ? "Autoscroll enabled" : "Autoscroll disabled", children: _jsx(LlmChatOptionsButton, { enabled: autoScrollEnabled, id: "autoscroll-button", onClick: () => setAutoScrollEnabled(!autoScrollEnabled), posRight: 80, children: _jsx(VerticalAlignBottomIcon, { id: "autoscroll-icon", sx: { color: "var(--bs-white)", fontSize: "0.85rem" } }) }) }), _jsx(Tooltip, { id: "wrap-tooltip", title: shouldWrapOutput ? "Text wrapping enabled" : "Text wrapping disabled", children: _jsx(LlmChatOptionsButton, { enabled: shouldWrapOutput, id: "wrap-button", onClick: () => setShouldWrapOutput(!shouldWrapOutput), posRight: 10, children: _jsx(WrapTextIcon, { id: "wrap-icon", sx: { color: "var(--bs-white)", fontSize: "0.85rem" } }) }) }), _jsxs(Box, { id: "llm-responses", ref: chatOutputRef, sx: {
562
+ backgroundColor: backgroundColor || undefined,
563
+ borderWidth: "1px",
564
+ borderRadius: "0.5rem",
565
+ fontSize: "smaller",
566
+ resize: "none",
567
+ overflowY: "auto", // Enable vertical scrollbar
568
+ paddingBottom: "60px",
569
+ paddingTop: "7.5px",
570
+ paddingLeft: "15px",
571
+ paddingRight: "15px",
572
+ width: "100%",
573
+ }, tabIndex: -1, children: [_jsx(FormattedMarkdown, { id: `${id}-formatted-markdown`, nodesList: chatOutput.map((item) => {
574
+ if (isValidElement(item) && item.type === MUIAccordion) {
575
+ const shouldShow = showThinking || item.key === finalAnswerKey.current;
576
+ return (_jsx(Box, { sx: { display: shouldShow ? "block" : "none" }, children: item }, item.key));
577
+ }
578
+ return item;
579
+ }), style: darkMode ? atelierDuneDark : a11yLight, wrapLongLines: shouldWrapOutput }), isAwaitingLlm && (_jsxs(Box, { id: "awaitingOutputContainer", sx: { display: "flex", alignItems: "center", fontSize: "smaller" }, children: [_jsx("span", { id: "working-span", style: { marginRight: "1rem" }, children: "Working..." }), _jsx(CircularProgress, { id: "awaitingOutputSpinner", sx: {
580
+ color: "var(--bs-primary)",
581
+ }, size: "1rem" })] }))] }), _jsx(ControlButtons, { clearChatOnClickCallback: () => {
582
+ setChatOutput([]);
583
+ chatHistory.current = [];
584
+ chatContext.current = null;
585
+ setPreviousUserQuery("");
586
+ currentResponse.current = "";
587
+ lastAIMessage.current = "";
588
+ introduceAgent();
589
+ }, enableClearChatButton: enableClearChatButton, isAwaitingLlm: isAwaitingLlm, handleSend: handleSend, handleStop: handleStop, previousUserQuery: previousUserQuery, shouldEnableRegenerateButton: shouldEnableRegenerateButton })] }), _jsxs(Box, { id: "user-input-div", style: { ...divStyle, display: "flex", margin: "10px", alignItems: "flex-end", position: "relative" }, children: [_jsx(Input, { autoComplete: "off", id: "user-input", multiline: true, placeholder: getPlaceholder(), ref: chatInputRef, sx: {
590
+ border: "var(--bs-border-style) var(--bs-border-width) var(--bs-gray-light)",
591
+ borderRadius: "var(--bs-border-radius)",
592
+ display: "flex",
593
+ flexGrow: 1,
594
+ fontSize: "smaller",
595
+ marginRight: "0.75rem",
596
+ paddingBottom: "0.5rem",
597
+ paddingTop: "0.5rem",
598
+ paddingLeft: "1rem",
599
+ paddingRight: "1rem",
600
+ transition: "margin-right 0.2s",
601
+ }, onChange: (event) => {
602
+ setChatInput(event.target.value);
603
+ }, onKeyDown: async (event) => {
604
+ if (event.key === "Enter" && !event.shiftKey) {
605
+ event.preventDefault();
606
+ await handleSend(chatInput);
607
+ }
608
+ }, value: chatInput, endAdornment: _jsxs(InputAdornment, { id: "input-adornments", position: "end", disableTypography: true, children: [voiceInputState.isProcessingSpeech && (_jsx(CircularProgress, { size: 16, sx: {
609
+ color: "var(--bs-primary)",
610
+ marginRight: "0.5rem",
611
+ } })), _jsx(IconButton, { id: "clear-input-button", onClick: () => {
612
+ setChatInput("");
613
+ }, sx: {
614
+ color: "var(--bs-primary)",
615
+ opacity: userInputEmpty ? "25%" : "100%",
616
+ }, disabled: userInputEmpty, tabIndex: -1, edge: "end", children: _jsx(ClearIcon, { id: "clear-input-icon" }) })] }) }), _jsx(MicrophoneButton, { isMicOn: isMicOn, onMicToggle: setIsMicOn, speechRecognitionRef: speechRecognitionRef, voiceInputState: voiceInputState, setVoiceInputState: setVoiceInputState }), _jsx(SendButton, { enableSendButton: shouldEnableSendButton, id: "submit-query-button", onClickCallback: () => handleSend(chatInput) })] })] })] }));
617
+ };
@@ -14,7 +14,9 @@ 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 { DeleteOutline, Loop, StopCircle } from "@mui/icons-material";
17
+ import DeleteOutline from "@mui/icons-material/DeleteOutline";
18
+ import Loop from "@mui/icons-material/Loop";
19
+ import StopCircle from "@mui/icons-material/StopCircle";
18
20
  import { SmallLlmChatButton } from "./LlmChatButton.js";
19
21
  // #endregion: Types
20
22
  /**
@@ -5,7 +5,7 @@ import { SyntaxHighlighterProps } from "react-syntax-highlighter";
5
5
  */
6
6
  interface FormattedMarkdownProps {
7
7
  /**
8
- * The id for the div that will contain the formatted markdown.
8
+ * The id for the div that will contain the formatted Markdown.
9
9
  */
10
10
  readonly id: string;
11
11
  /**
@@ -17,15 +17,15 @@ interface FormattedMarkdownProps {
17
17
  */
18
18
  readonly style: SyntaxHighlighterProps["style"];
19
19
  /**
20
- * Whether to wrap long lines in the markdown.
20
+ * Whether to wrap long lines in the Markdown.
21
21
  */
22
22
  readonly wrapLongLines: boolean;
23
23
  }
24
24
  /**
25
- * Format the output to ensure that text nodes are formatted as markdown but other nodes are passed along as-is.
25
+ * Format the output to ensure that text nodes are formatted as Markdown but other nodes are passed along as-is.
26
26
  *
27
27
  * @param props The props for the component. @see FormattedMarkdownProps
28
- * @returns The formatted output. Consecutive string nodes will be aggregated and wrapped in a markdown component,
28
+ * @returns The formatted output. Consecutive string nodes will be aggregated and wrapped in a Markdown component,
29
29
  * while other nodes will be passed along as-is.
30
30
  */
31
31
  export declare const FormattedMarkdown: ({ id, nodesList, style, wrapLongLines, }: FormattedMarkdownProps) => ReactJSX.Element;
@@ -21,10 +21,10 @@ import rehypeRaw from "rehype-raw";
21
21
  import rehypeSlug from "rehype-slug";
22
22
  import { hashString } from "../../utils/text.js";
23
23
  /**
24
- * Format the output to ensure that text nodes are formatted as markdown but other nodes are passed along as-is.
24
+ * Format the output to ensure that text nodes are formatted as Markdown but other nodes are passed along as-is.
25
25
  *
26
26
  * @param props The props for the component. @see FormattedMarkdownProps
27
- * @returns The formatted output. Consecutive string nodes will be aggregated and wrapped in a markdown component,
27
+ * @returns The formatted output. Consecutive string nodes will be aggregated and wrapped in a Markdown component,
28
28
  * while other nodes will be passed along as-is.
29
29
  */
30
30
  export const FormattedMarkdown = ({ id, nodesList, style, wrapLongLines = false, }) => {
@@ -32,18 +32,16 @@ export const FormattedMarkdown = ({ id, nodesList, style, wrapLongLines = false,
32
32
  * Get the formatted output for a given string. The string is assumed to be in Markdown format.
33
33
  * @param stringToFormat The string to format.
34
34
  * @param index The index of the string in the nodes list. Used as "salt" to generate a unique key.
35
- * @returns The formatted markdown.
35
+ * @returns The formatted Markdown.
36
36
  */
37
37
  const getFormattedMarkdown = (stringToFormat, index) => (_jsx(ReactMarkdown, { rehypePlugins: [rehypeRaw, rehypeSlug], components: {
38
- code(codeProps) {
38
+ code: (codeProps) => {
39
39
  const { children, className, ...rest } = codeProps;
40
40
  const match = /language-(?<language>\w+)/u.exec(className || "");
41
41
  return match ? (_jsx(SyntaxHighlighter, { id: `syntax-highlighter-${match.groups["language"]}`, PreTag: "div", language: match.groups["language"], style: style, children: String(children).replace(/\n$/u, "") })) : (_jsx("code", { id: `code-${className}`, ...rest, className: className, style: wrapLongLines ? { whiteSpace: "pre-wrap", wordBreak: "break-word" } : {}, children: children }));
42
42
  },
43
43
  // Handle links specially since we want them to open in a new tab
44
- a({ ...codeProps }) {
45
- return (_jsx("a", { ...codeProps, id: "reference-link", target: "_blank", rel: "noopener noreferrer", children: codeProps.children }));
46
- },
44
+ a: ({ ...codeProps }) => (_jsx("a", { ...codeProps, id: "reference-link", target: "_blank", rel: "noopener noreferrer", children: codeProps.children })),
47
45
  }, children: stringToFormat }, `${hashString(stringToFormat)}-${index}`));
48
46
  const getNodeKey = (node, index) => {
49
47
  // If it has a key, use that
@@ -3,10 +3,6 @@ type LLMChatGroupConfigBtnProps = {
3
3
  posRight?: number;
4
4
  posBottom?: number;
5
5
  };
6
- export declare const LlmChatButton: import("@emotion/styled").StyledComponent<import("@mui/material").ButtonOwnProps & Omit<import("@mui/material").ButtonBaseOwnProps, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
7
- ref?: import("react").Ref<HTMLButtonElement>;
8
- }, "className" | "style" | "classes" | "action" | "centerRipple" | "children" | "disabled" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "sx" | "tabIndex" | "TouchRippleProps" | "touchRippleRef" | "href" | "color" | "disableElevation" | "disableFocusRipple" | "endIcon" | "fullWidth" | "loading" | "loadingIndicator" | "loadingPosition" | "size" | "startIcon" | "variant"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme> & LLMChatGroupConfigBtnProps, {}, {}>;
9
- export declare const SmallLlmChatButton: import("@emotion/styled").StyledComponent<import("@mui/material").ButtonOwnProps & Omit<import("@mui/material").ButtonBaseOwnProps, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
10
- ref?: import("react").Ref<HTMLButtonElement>;
11
- }, "className" | "style" | "classes" | "action" | "centerRipple" | "children" | "disabled" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "sx" | "tabIndex" | "TouchRippleProps" | "touchRippleRef" | "href" | "color" | "disableElevation" | "disableFocusRipple" | "endIcon" | "fullWidth" | "loading" | "loadingIndicator" | "loadingPosition" | "size" | "startIcon" | "variant"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme> & LLMChatGroupConfigBtnProps, {}, {}>;
6
+ export declare const LlmChatButton: import("@emotion/styled").StyledComponent<import("@mui/material/Button").ButtonOwnProps & Omit<import("@mui/material/ButtonBase").ButtonBaseOwnProps, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "className" | "style" | "classes" | "action" | "centerRipple" | "children" | "disabled" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "sx" | "tabIndex" | "TouchRippleProps" | "touchRippleRef" | "href" | "color" | "disableElevation" | "disableFocusRipple" | "endIcon" | "fullWidth" | "loading" | "loadingIndicator" | "loadingPosition" | "size" | "startIcon" | "variant"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme> & LLMChatGroupConfigBtnProps, {}, {}>;
7
+ export declare const SmallLlmChatButton: import("@emotion/styled").StyledComponent<import("@mui/material/Button").ButtonOwnProps & Omit<import("@mui/material/ButtonBase").ButtonBaseOwnProps, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "className" | "style" | "classes" | "action" | "centerRipple" | "children" | "disabled" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "sx" | "tabIndex" | "TouchRippleProps" | "touchRippleRef" | "href" | "color" | "disableElevation" | "disableFocusRipple" | "endIcon" | "fullWidth" | "loading" | "loadingIndicator" | "loadingPosition" | "size" | "startIcon" | "variant"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme> & LLMChatGroupConfigBtnProps, {}, {}>;
12
8
  export {};
@@ -13,13 +13,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
- import { styled } from "@mui/material";
17
16
  import Button from "@mui/material/Button";
17
+ import { styled } from "@mui/material/styles";
18
18
  // #endregion: Types
19
19
  export const LlmChatButton = styled(Button, {
20
20
  shouldForwardProp: (prop) => !["posRight", "posBottom"].includes(String(prop)),
21
- })(({ disabled, posRight, posBottom }) => ({
22
- background: "var(--bs-primary) !important",
21
+ })(({ theme, disabled, posRight, posBottom }) => ({
22
+ background: `${theme.palette.primary.main} !important`,
23
23
  borderRadius: "var(--bs-border-radius)",
24
24
  bottom: posBottom !== undefined ? posBottom : 0,
25
25
  cursor: disabled ? "default" : "pointer",
@@ -14,16 +14,14 @@ 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 { styled } from "@mui/material";
17
+ import { styled } from "@mui/material/styles";
18
18
  import { DEFAULT_USER_IMAGE } from "../../const.js";
19
19
  // #region: Styled Components
20
20
  const UserQueryContainer = styled("div")(({ theme }) => ({
21
- backgroundColor: theme.palette.background.default,
21
+ backgroundColor: theme.palette.background.paper,
22
22
  border: "var(--bs-border-width) var(--bs-border-style)",
23
- borderColor: theme.palette.mode === "dark" ? "var(--bs-white)" : "var(--bs-border-color)",
24
23
  borderRadius: "var(--bs-border-radius)",
25
24
  boxShadow: `0 0px 6px 0 ${theme.palette.mode === "dark" ? "var(--bs-accent2-light)" : "rgba(var(--bs-primary-rgb), 0.15)"}`,
26
- color: theme.palette.mode === "dark" ? "var(--bs-white)" : "var(--bs-primary)",
27
25
  display: "inline-flex",
28
26
  padding: "10px",
29
27
  }));
@@ -3,8 +3,9 @@ export declare const KNOWN_MESSAGE_TYPES: ChatMessageType[];
3
3
  export declare const KNOWN_MESSAGE_TYPES_FOR_PLASMA: ChatMessageType[];
4
4
  export declare const chatMessageFromChunk: (chunk: string) => ChatMessage | null;
5
5
  export declare const checkError: (chatMessageJson: object) => string | null;
6
+ export declare const removeTrailingUuid: (agentName: string) => string;
6
7
  /**
7
- * Convert FOO_BAR to more human "Foo Bar"
8
+ * Convert FOO_BAR to more human "Foo Bar".
8
9
  * @param agentName Agent name in SNAKE_CASE format.
9
10
  * @returns User-friendly agent name.
10
11
  */
@@ -54,8 +54,11 @@ export const checkError = (chatMessageJson) => {
54
54
  return null;
55
55
  }
56
56
  };
57
+ export const removeTrailingUuid = (agentName) => {
58
+ return agentName?.replace(/-[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/u, "");
59
+ };
57
60
  /**
58
- * Convert FOO_BAR to more human "Foo Bar"
61
+ * Convert FOO_BAR to more human "Foo Bar".
59
62
  * @param agentName Agent name in SNAKE_CASE format.
60
63
  * @returns User-friendly agent name.
61
64
  */
@@ -1,4 +1,4 @@
1
- import { Dispatch, FC, MutableRefObject, SetStateAction } from "react";
1
+ import { Dispatch, FC, RefObject, SetStateAction } from "react";
2
2
  import { SpeechRecognitionState } from "./VoiceChat.js";
3
3
  export interface MicrophoneButtonProps {
4
4
  /**
@@ -12,7 +12,7 @@ export interface MicrophoneButtonProps {
12
12
  /**
13
13
  * Reference to the SpeechRecognition instance
14
14
  */
15
- speechRecognitionRef: MutableRefObject<SpeechRecognition | null>;
15
+ speechRecognitionRef: RefObject<SpeechRecognition | null>;
16
16
  /**
17
17
  * Current voice input state
18
18
  */
@@ -1,4 +1,4 @@
1
- import { Dispatch, MutableRefObject, SetStateAction } from "react";
1
+ import { Dispatch, RefObject, SetStateAction } from "react";
2
2
  export interface SpeechRecognitionHandlers {
3
3
  end: () => void;
4
4
  error: (event: SpeechRecognitionErrorEvent) => void;
@@ -28,6 +28,6 @@ export interface SpeechRecognitionState {
28
28
  isProcessingSpeech: boolean;
29
29
  }
30
30
  export declare const checkSpeechSupport: () => boolean;
31
- export declare function cleanupAndStopSpeechRecognition(speechRecognitionRef: MutableRefObject<SpeechRecognition | null>, handlers: SpeechRecognitionHandlers | null): void;
32
- export declare function setupSpeechRecognition(setChatInput: Dispatch<SetStateAction<string>>, setVoiceInputState: Dispatch<SetStateAction<SpeechRecognitionState>>, speechRecognitionRef: MutableRefObject<SpeechRecognition | null>): SpeechRecognitionHandlers | null;
31
+ export declare const cleanupAndStopSpeechRecognition: (speechRecognitionRef: RefObject<SpeechRecognition | null>, handlers: SpeechRecognitionHandlers | null) => void;
32
+ export declare const setupSpeechRecognition: (setChatInput: Dispatch<SetStateAction<string>>, setVoiceInputState: Dispatch<SetStateAction<SpeechRecognitionState>>, speechRecognitionRef: RefObject<SpeechRecognition | null>) => SpeechRecognitionHandlers | null;
33
33
  export declare const toggleListening: (isMicOn: boolean, recognition: SpeechRecognition | null) => Promise<void>;