@cognizant-ai-lab/ui-common 1.3.3 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +287 -0
- package/dist/Theme/Palettes.d.ts +18 -0
- package/dist/Theme/Palettes.js +94 -0
- package/dist/Theme/Theme.d.ts +22 -0
- package/dist/Theme/Theme.js +58 -0
- package/dist/components/AgentChat/ChatCommon.d.ts +4 -2
- package/dist/components/AgentChat/ChatCommon.js +141 -105
- package/dist/components/AgentChat/ControlButtons.js +3 -1
- package/dist/components/AgentChat/FormattedMarkdown.d.ts +4 -4
- package/dist/components/AgentChat/FormattedMarkdown.js +5 -7
- package/dist/components/AgentChat/LlmChatButton.d.ts +2 -6
- package/dist/components/AgentChat/LlmChatButton.js +3 -3
- package/dist/components/AgentChat/UserQueryDisplay.js +2 -4
- package/dist/components/AgentChat/Utils.d.ts +2 -1
- package/dist/components/AgentChat/Utils.js +4 -1
- package/dist/components/AgentChat/VoiceChat/MicrophoneButton.d.ts +2 -2
- package/dist/components/AgentChat/VoiceChat/VoiceChat.d.ts +3 -3
- package/dist/components/AgentChat/VoiceChat/VoiceChat.js +5 -5
- package/dist/components/ChatBot/ChatBot.js +2 -2
- package/dist/components/Common/Breadcrumbs.js +1 -1
- package/dist/components/Common/{confirmationModal.js → ConfirmationModal.js} +2 -5
- package/dist/components/Common/CustomerLogo.d.ts +17 -0
- package/dist/components/Common/CustomerLogo.js +49 -0
- package/dist/components/Common/Footer.d.ts +18 -0
- package/dist/components/Common/Footer.js +59 -0
- package/dist/components/Common/LlmChatOptionsButton.d.ts +1 -4
- package/dist/components/Common/LlmChatOptionsButton.js +4 -4
- package/dist/components/Common/LoadingSpinner.js +1 -1
- package/dist/components/Common/MUIAccordion.d.ts +2 -2
- package/dist/components/Common/MUIAccordion.js +2 -12
- package/dist/components/Common/MUIAlert.d.ts +2 -1
- package/dist/components/Common/MUIAlert.js +4 -1
- package/dist/components/Common/MUIDialog.d.ts +1 -1
- package/dist/components/Common/MUIDialog.js +1 -1
- package/dist/components/Common/Navbar.d.ts +3 -1
- package/dist/components/Common/Navbar.js +60 -35
- package/dist/components/Common/PageLoader.js +3 -4
- package/dist/components/Common/Snackbar.d.ts +4 -1
- package/dist/components/Common/Snackbar.js +11 -19
- package/dist/components/Common/notification.d.ts +3 -3
- package/dist/components/Common/notification.js +6 -6
- package/dist/components/ErrorPage/ErrorBoundary.d.ts +2 -2
- package/dist/components/ErrorPage/ErrorBoundary.js +1 -1
- package/dist/components/ErrorPage/ErrorPage.js +6 -5
- package/dist/components/MultiAgentAccelerator/AgentConversations.d.ts +17 -0
- package/dist/components/MultiAgentAccelerator/AgentConversations.js +77 -0
- package/dist/components/MultiAgentAccelerator/AgentCounts.d.ts +12 -0
- package/dist/components/MultiAgentAccelerator/AgentCounts.js +21 -0
- package/dist/components/MultiAgentAccelerator/AgentFlow.d.ts +6 -4
- package/dist/components/MultiAgentAccelerator/AgentFlow.js +106 -185
- package/dist/components/MultiAgentAccelerator/AgentNode.d.ts +7 -5
- package/dist/components/MultiAgentAccelerator/AgentNode.js +93 -50
- package/dist/components/MultiAgentAccelerator/GraphLayouts.d.ts +20 -17
- package/dist/components/MultiAgentAccelerator/GraphLayouts.js +16 -14
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +2 -3
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +214 -55
- package/dist/components/MultiAgentAccelerator/PlasmaEdge.d.ts +1 -1
- package/dist/components/MultiAgentAccelerator/PlasmaEdge.js +14 -12
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.d.ts +15 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.js +104 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.d.ts +17 -0
- package/dist/components/MultiAgentAccelerator/{Sidebar.js → Sidebar/Sidebar.js} +146 -59
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.d.ts +19 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.js +113 -0
- package/dist/components/MultiAgentAccelerator/TemporaryNetworks.d.ts +26 -0
- package/dist/components/MultiAgentAccelerator/TemporaryNetworks.js +20 -0
- package/dist/components/MultiAgentAccelerator/ThoughtBubbleEdge.d.ts +10 -8
- package/dist/components/MultiAgentAccelerator/ThoughtBubbleEdge.js +1 -1
- package/dist/components/MultiAgentAccelerator/ThoughtBubbleOverlay.d.ts +3 -2
- package/dist/components/MultiAgentAccelerator/ThoughtBubbleOverlay.js +10 -13
- package/dist/components/MultiAgentAccelerator/const.d.ts +1 -3
- package/dist/components/MultiAgentAccelerator/const.js +4 -18
- package/dist/components/Settings/FadingCheckmark.d.ts +14 -0
- package/dist/components/Settings/FadingCheckmark.js +43 -0
- package/dist/components/Settings/SettingsDialog.d.ts +9 -0
- package/dist/components/Settings/SettingsDialog.js +265 -0
- package/dist/const.d.ts +1 -2
- package/dist/const.js +2 -3
- package/dist/controller/Types/AgentIconSuggestions.d.ts +4 -0
- package/dist/controller/Types/AgentIconSuggestions.js +1 -0
- package/dist/controller/Types/Branding.d.ts +12 -0
- package/dist/controller/Types/Branding.js +1 -0
- package/dist/controller/Types/NetworkIconSuggestions.d.ts +4 -0
- package/dist/controller/Types/NetworkIconSuggestions.js +1 -0
- package/dist/controller/agent/Agent.d.ts +32 -12
- package/dist/controller/agent/Agent.js +71 -19
- package/dist/controller/llm/LlmChat.d.ts +1 -1
- package/dist/controller/llm/LlmChat.js +2 -2
- package/dist/index.d.ts +10 -5
- package/dist/index.js +10 -5
- package/dist/state/{environment.d.ts → Environment.d.ts} +2 -0
- package/dist/state/{environment.js → Environment.js} +2 -0
- package/dist/state/Settings.d.ts +62 -0
- package/dist/state/Settings.js +62 -0
- package/dist/state/TemporaryNetworks.d.ts +32 -0
- package/dist/state/TemporaryNetworks.js +26 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/Authentication.d.ts +2 -2
- package/dist/utils/Authentication.js +6 -6
- package/dist/utils/text.d.ts +2 -2
- package/dist/utils/text.js +3 -5
- package/dist/utils/title.d.ts +1 -1
- package/dist/utils/title.js +2 -2
- package/dist/utils/useLocalStorage.d.ts +1 -1
- package/dist/utils/useLocalStorage.js +3 -3
- package/dist/utils/zIndexLayers.d.ts +1 -1
- package/dist/utils/zIndexLayers.js +3 -15
- package/package.json +23 -21
- package/dist/components/MultiAgentAccelerator/Sidebar.d.ts +0 -12
- package/dist/utils/Theme.d.ts +0 -7
- package/dist/utils/Theme.js +0 -7
- package/dist/utils/agentConversations.d.ts +0 -24
- package/dist/utils/agentConversations.js +0 -113
- /package/dist/components/Common/{confirmationModal.d.ts → ConfirmationModal.d.ts} +0 -0
|
@@ -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
|
|
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 {
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
237
|
-
0 9px 28px 8px
|
|
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
|
-
|
|
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: "
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
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
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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<
|
|
7
|
-
|
|
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:
|
|
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.
|
|
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,
|
|
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:
|
|
15
|
+
speechRecognitionRef: RefObject<SpeechRecognition | null>;
|
|
16
16
|
/**
|
|
17
17
|
* Current voice input state
|
|
18
18
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dispatch,
|
|
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
|
|
32
|
-
export declare
|
|
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>;
|