@cognizant-ai-lab/ui-common 1.7.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/Theme/Palettes.d.ts +0 -9
- package/dist/Theme/Palettes.js +0 -18
- package/dist/components/AgentChat/ChatCommon/ChatCommon.d.ts +13 -4
- package/dist/components/AgentChat/ChatCommon/ChatCommon.js +131 -38
- package/dist/components/AgentChat/ChatCommon/ChatHistory.d.ts +7 -0
- package/dist/components/AgentChat/ChatCommon/ChatHistory.js +1 -1
- package/dist/components/AgentChat/ChatCommon/Const.d.ts +1 -0
- package/dist/components/AgentChat/ChatCommon/Const.js +2 -0
- package/dist/components/AgentChat/ChatCommon/ControlButtons.d.ts +5 -3
- package/dist/components/AgentChat/ChatCommon/ControlButtons.js +13 -4
- package/dist/components/AgentChat/ChatCommon/ConversationTurn.d.ts +5 -5
- package/dist/components/AgentChat/ChatCommon/ConversationTurn.js +1 -0
- package/dist/components/AgentChat/ChatCommon/FormattedMarkdown.js +3 -0
- package/dist/components/AgentChat/ChatCommon/SendButton.js +7 -6
- package/dist/components/AgentChat/ChatCommon/SyntaxHighlighterThemes.js +1 -1
- package/dist/components/AgentChat/ChatCommon/Thinking.d.ts +1 -0
- package/dist/components/AgentChat/ChatCommon/Thinking.js +10 -7
- package/dist/components/AgentChat/Common/LlmChatButton.d.ts +0 -2
- package/dist/components/AgentChat/Common/LlmChatButton.js +6 -9
- package/dist/components/AgentChat/Common/Utils.d.ts +4 -0
- package/dist/components/AgentChat/Common/Utils.js +5 -1
- package/dist/components/AgentChat/VoiceChat/MicrophoneButton.js +12 -10
- package/dist/components/Common/Breadcrumbs.js +1 -1
- package/dist/components/Common/Navbar.js +24 -22
- package/dist/components/Common/StatusLight.d.ts +9 -0
- package/dist/components/Common/StatusLight.js +21 -0
- package/dist/components/Common/notification.d.ts +4 -4
- package/dist/components/ErrorPage/ErrorBoundary.js +1 -1
- package/dist/components/ErrorPage/ErrorPage.d.ts +3 -3
- package/dist/components/ErrorPage/ErrorPage.js +4 -3
- package/dist/components/Logo/Common.d.ts +4 -0
- package/dist/components/Logo/Common.js +8 -0
- package/dist/components/Logo/CustomerLogo.d.ts +23 -0
- package/dist/components/Logo/CustomerLogo.js +41 -0
- package/dist/components/MultiAgentAccelerator/AgentConversations.js +0 -1
- package/dist/components/MultiAgentAccelerator/{AgentFlow.d.ts → AgentFlow/AgentFlow.d.ts} +15 -5
- package/dist/components/MultiAgentAccelerator/{AgentFlow.js → AgentFlow/AgentFlow.js} +125 -84
- package/dist/components/MultiAgentAccelerator/{AgentNode.d.ts → AgentFlow/AgentNode.d.ts} +1 -1
- package/dist/components/MultiAgentAccelerator/{AgentNode.js → AgentFlow/AgentNode.js} +26 -30
- package/dist/components/MultiAgentAccelerator/AgentFlow/GraphLayouts.d.ts +43 -0
- package/dist/components/MultiAgentAccelerator/{GraphLayouts.js → AgentFlow/GraphLayouts.js} +10 -41
- package/dist/components/MultiAgentAccelerator/AgentFlow/GraphStructure.d.ts +21 -0
- package/dist/components/MultiAgentAccelerator/AgentFlow/GraphStructure.js +27 -0
- package/dist/components/MultiAgentAccelerator/AgentFlow/PlasmaEdge.d.ts +7 -0
- package/dist/components/MultiAgentAccelerator/{PlasmaEdge.js → AgentFlow/PlasmaEdge.js} +13 -8
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +3 -9
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +137 -103
- package/dist/components/MultiAgentAccelerator/Schema/SlyData.d.ts +17 -0
- package/dist/components/MultiAgentAccelerator/Schema/SlyData.js +23 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.d.ts +0 -5
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.js +38 -28
- package/dist/components/MultiAgentAccelerator/Sidebar/ImportNetworkModal.d.ts +67 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/ImportNetworkModal.js +585 -0
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.d.ts +5 -4
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.js +77 -168
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.d.ts +31 -13
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.js +177 -100
- package/dist/components/MultiAgentAccelerator/TemporaryNetworks.d.ts +22 -0
- package/dist/components/MultiAgentAccelerator/TemporaryNetworks.js +74 -3
- package/dist/components/MultiAgentAccelerator/{ThoughtBubbleEdge.d.ts → ThoughtBubbles/ThoughtBubbleEdge.d.ts} +1 -1
- package/dist/components/MultiAgentAccelerator/{ThoughtBubbleOverlay.js → ThoughtBubbles/ThoughtBubbleOverlay.js} +1 -1
- package/dist/components/MultiAgentAccelerator/Tour/MainTourSteps.js +15 -8
- package/dist/components/MultiAgentAccelerator/const.d.ts +3 -0
- package/dist/components/MultiAgentAccelerator/const.js +6 -0
- package/dist/components/Settings/ApiKeyInput.js +7 -8
- package/dist/components/Settings/InfoTip.d.ts +8 -0
- package/dist/components/Settings/InfoTip.js +14 -0
- package/dist/components/Settings/SettingsDialog.js +373 -183
- package/dist/components/Settings/SettingsRow.d.ts +18 -0
- package/dist/components/Settings/SettingsRow.js +35 -0
- package/dist/controller/agent/Agent.d.ts +16 -25
- package/dist/controller/agent/Agent.js +24 -54
- package/dist/controller/agent/IconSuggestions.d.ts +35 -0
- package/dist/controller/agent/IconSuggestions.js +85 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -3
- package/dist/state/IconSuggestions.d.ts +27 -0
- package/dist/state/IconSuggestions.js +50 -0
- package/dist/state/Settings.d.ts +97 -6
- package/dist/state/Settings.js +110 -8
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/BrowserNavigation.js +2 -0
- package/dist/utils/File.d.ts +4 -1
- package/dist/utils/File.js +4 -9
- package/dist/utils/text.js +3 -7
- package/dist/utils/title.js +1 -1
- package/package.json +9 -6
- package/dist/components/Common/CustomerLogo.d.ts +0 -17
- package/dist/components/Common/CustomerLogo.js +0 -47
- package/dist/components/Common/MUIAccordion.d.ts +0 -17
- package/dist/components/Common/MUIAccordion.js +0 -66
- package/dist/components/MultiAgentAccelerator/GraphLayouts.d.ts +0 -36
- package/dist/components/MultiAgentAccelerator/PlasmaEdge.d.ts +0 -3
- package/dist/utils/useLocalStorage.d.ts +0 -1
- package/dist/utils/useLocalStorage.js +0 -55
- /package/dist/components/MultiAgentAccelerator/{ThoughtBubbleEdge.js → ThoughtBubbles/ThoughtBubbleEdge.js} +0 -0
- /package/dist/components/MultiAgentAccelerator/{ThoughtBubbleOverlay.d.ts → ThoughtBubbles/ThoughtBubbleOverlay.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -72,7 +72,7 @@ via the chat interface, and visualize the agent network flow.
|
|
|
72
72
|
Among the technologies and libraries used in this package are:
|
|
73
73
|
|
|
74
74
|
- ESLint and Prettier (for code quality)
|
|
75
|
-
-
|
|
75
|
+
- Vitest and React Testing Library (for testing)
|
|
76
76
|
- MUI
|
|
77
77
|
- next-auth (for authentication)
|
|
78
78
|
- React
|
|
@@ -160,9 +160,9 @@ async function checkServer() {
|
|
|
160
160
|
const result = await testConnection("https://api.example.com")
|
|
161
161
|
|
|
162
162
|
if (result.success) {
|
|
163
|
-
console.log(`Connected
|
|
163
|
+
console.log(`Connected!`)
|
|
164
164
|
} else {
|
|
165
|
-
console.error(`Connection failed: ${result.
|
|
165
|
+
console.error(`Connection failed: ${result.statusText}`)
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
```
|
package/dist/Theme/Palettes.d.ts
CHANGED
|
@@ -7,12 +7,3 @@ export declare const PALETTES: {
|
|
|
7
7
|
coldToHot: string[];
|
|
8
8
|
visionImpaired: string[];
|
|
9
9
|
};
|
|
10
|
-
export type PaletteKey = keyof typeof PALETTES | "brand";
|
|
11
|
-
/**
|
|
12
|
-
* Custom hook to get the current color palette based on user settings.
|
|
13
|
-
* If the user has selected custom branding, it will return the palette for that.
|
|
14
|
-
* Otherwise, it will return one of the predefined palettes from the PALETTES object based on the user's selection.
|
|
15
|
-
*
|
|
16
|
-
* @returns An array of color hex codes representing the current color palette.
|
|
17
|
-
*/
|
|
18
|
-
export declare const usePalette: () => string[];
|
package/dist/Theme/Palettes.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// Palettes for progressive coloring of nodes based on depth or heatmap value
|
|
2
|
-
import { useSettingsStore } from "../state/Settings.js";
|
|
3
2
|
export const PALETTES = {
|
|
4
3
|
blue: [
|
|
5
4
|
"#f7fbff",
|
|
@@ -75,20 +74,3 @@ export const PALETTES = {
|
|
|
75
74
|
"#b6dbff",
|
|
76
75
|
],
|
|
77
76
|
};
|
|
78
|
-
/**
|
|
79
|
-
* Custom hook to get the current color palette based on user settings.
|
|
80
|
-
* If the user has selected custom branding, it will return the palette for that.
|
|
81
|
-
* Otherwise, it will return one of the predefined palettes from the PALETTES object based on the user's selection.
|
|
82
|
-
*
|
|
83
|
-
* @returns An array of color hex codes representing the current color palette.
|
|
84
|
-
*/
|
|
85
|
-
export const usePalette = () => {
|
|
86
|
-
const brandPalette = useSettingsStore((state) => state.settings.branding.rangePalette);
|
|
87
|
-
const paletteKey = useSettingsStore((state) => state.settings.appearance.rangePalette);
|
|
88
|
-
if (paletteKey === "brand" && brandPalette) {
|
|
89
|
-
return brandPalette;
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
return PALETTES[paletteKey];
|
|
93
|
-
}
|
|
94
|
-
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dispatch, Ref, SetStateAction } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { MessageRole } from "./ConversationTurn.js";
|
|
3
3
|
import { CombinedAgentType } from "../Common/Types.js";
|
|
4
4
|
export interface ChatCommonProps {
|
|
5
5
|
/**
|
|
@@ -22,6 +22,10 @@ export interface ChatCommonProps {
|
|
|
22
22
|
* The network to send the request to.
|
|
23
23
|
*/
|
|
24
24
|
readonly selectedNetwork: string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Setter for changing the selected network.
|
|
27
|
+
*/
|
|
28
|
+
readonly setSelectedNetwork?: (network: string | null) => void;
|
|
25
29
|
/**
|
|
26
30
|
* Special endpoint for legacy agents since they do not have a single unified endpoint like Neuro-san agents.
|
|
27
31
|
*/
|
|
@@ -92,15 +96,20 @@ export interface ChatCommonProps {
|
|
|
92
96
|
*/
|
|
93
97
|
readonly sampleQueries?: string[];
|
|
94
98
|
/**
|
|
95
|
-
*
|
|
99
|
+
* If true, indicates that the user is missing API keys for one or more LLM providers.
|
|
96
100
|
*/
|
|
97
|
-
readonly
|
|
101
|
+
readonly hasMissingApiKeys?: boolean;
|
|
98
102
|
}
|
|
99
103
|
export type ChatCommonHandle = {
|
|
100
104
|
handleStop: () => void;
|
|
101
105
|
handleClearChat: () => void;
|
|
102
106
|
};
|
|
103
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Helper function to convert a message role to a label for exporting chat history.
|
|
109
|
+
* @param role The message role to convert
|
|
110
|
+
* @returns The label for the message role
|
|
111
|
+
*/
|
|
112
|
+
export declare const roleToExportLabel: (role: MessageRole) => string;
|
|
104
113
|
/**
|
|
105
114
|
* Common chat component for agent chat. This component is used by all agent chat components to provide a consistent
|
|
106
115
|
* experience for users when chatting with agents. It handles user input as well as displaying and nicely formatting
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
|
|
4
4
|
|
|
@@ -18,6 +18,7 @@ limitations under the License.
|
|
|
18
18
|
* See main function description.
|
|
19
19
|
*/
|
|
20
20
|
import { AIMessage, HumanMessage } from "@langchain/core/messages";
|
|
21
|
+
import AddBoxRounded from "@mui/icons-material/AddBoxRounded";
|
|
21
22
|
import ClearIcon from "@mui/icons-material/Clear";
|
|
22
23
|
import CloseIcon from "@mui/icons-material/Close";
|
|
23
24
|
import TuneIcon from "@mui/icons-material/Tune";
|
|
@@ -36,7 +37,8 @@ import Typography from "@mui/material/Typography";
|
|
|
36
37
|
import { isEmpty } from "lodash-es";
|
|
37
38
|
import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from "react";
|
|
38
39
|
import { v4 as uuid } from "uuid";
|
|
39
|
-
import { ChatHistory } from "./ChatHistory.js";
|
|
40
|
+
import { ChatHistory, toTurns } from "./ChatHistory.js";
|
|
41
|
+
import { MAX_TURNS } from "./Const.js";
|
|
40
42
|
import { ControlButtons } from "./ControlButtons.js";
|
|
41
43
|
import { Conversation } from "./Conversation.js";
|
|
42
44
|
import { MessageRole } from "./ConversationTurn.js";
|
|
@@ -47,11 +49,18 @@ import { sendChatQuery } from "../../../controller/agent/Agent.js";
|
|
|
47
49
|
import { sendLlmRequest, StreamingUnit } from "../../../controller/llm/LlmChat.js";
|
|
48
50
|
import { ChatMessageType } from "../../../generated/neuro-san/NeuroSanClient.js";
|
|
49
51
|
import { useAgentChatHistoryStore } from "../../../state/ChatHistory.js";
|
|
52
|
+
import { useSettingsStore } from "../../../state/Settings.js";
|
|
53
|
+
import { downloadFile, toSafeFilename } from "../../../utils/File.js";
|
|
50
54
|
import { hasOnlyWhitespace } from "../../../utils/text.js";
|
|
55
|
+
import { getZIndex } from "../../../utils/zIndexLayers.js";
|
|
56
|
+
import { ConfirmationModal } from "../../Common/ConfirmationModal.js";
|
|
57
|
+
import { AGENT_NETWORK_DESIGNER_ID } from "../../MultiAgentAccelerator/const.js";
|
|
51
58
|
import { givesFinalAnswer, isLegacyAgentType } from "../Common/Types.js";
|
|
52
59
|
import { chatMessageFromChunk, checkError, cleanUpAgentName, removeTrailingUuid } from "../Common/Utils.js";
|
|
53
60
|
import { MicrophoneButton } from "../VoiceChat/MicrophoneButton.js";
|
|
54
61
|
import { cleanupAndStopSpeechRecognition, setupSpeechRecognition } from "../VoiceChat/VoiceChat.js";
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region Constants
|
|
55
64
|
// Define fancy EMPTY constant to avoid linter error about using object literals as default props
|
|
56
65
|
const EMPTY = {};
|
|
57
66
|
// How many times to retry the entire agent interaction process. Some networks have a well-defined success condition.
|
|
@@ -63,15 +72,29 @@ const MAX_AGENT_RETRIES = 3;
|
|
|
63
72
|
* @returns The final answer from the agent, if it exists or undefined if it doesn't
|
|
64
73
|
*/
|
|
65
74
|
const extractFinalAnswer = (response) => /Final Answer: (?<finalAnswerText>.*)/su.exec(response)?.groups?.["finalAnswerText"];
|
|
66
|
-
//
|
|
67
|
-
|
|
75
|
+
// List of message roles that are exported when saving chat history.
|
|
76
|
+
const EXPORTED_MESSAGE_TYPES = [MessageRole.User, MessageRole.FinalAnswer, MessageRole.Warning, MessageRole.Error];
|
|
77
|
+
const EXPORT_ROLE_LABELS = {
|
|
78
|
+
[MessageRole.User]: "User",
|
|
79
|
+
[MessageRole.Agent]: "Assistant",
|
|
80
|
+
[MessageRole.FinalAnswer]: "Assistant",
|
|
81
|
+
[MessageRole.Warning]: "Warning",
|
|
82
|
+
[MessageRole.Error]: "Error",
|
|
83
|
+
};
|
|
84
|
+
//#endregion
|
|
85
|
+
/**
|
|
86
|
+
* Helper function to convert a message role to a label for exporting chat history.
|
|
87
|
+
* @param role The message role to convert
|
|
88
|
+
* @returns The label for the message role
|
|
89
|
+
*/
|
|
90
|
+
export const roleToExportLabel = (role) => EXPORT_ROLE_LABELS[role];
|
|
68
91
|
/**
|
|
69
92
|
* Common chat component for agent chat. This component is used by all agent chat components to provide a consistent
|
|
70
93
|
* experience for users when chatting with agents. It handles user input as well as displaying and nicely formatting
|
|
71
94
|
* agent responses. Customization for inputs and outputs is provided via event handlers-like props.
|
|
72
95
|
*/
|
|
73
96
|
export const ChatCommon = ({ ref, ...props }) => {
|
|
74
|
-
const {
|
|
97
|
+
const { agentPlaceholders = EMPTY, backgroundColor, currentUser, customAgentGreetings = EMPTY, extraParams, extraSlyData, id, isAwaitingLlm, legacyAgentEndpoint, hasMissingApiKeys = false, networkDescription, neuroSanURL, onChunkReceived, onClose, onSend, onStreamingComplete, onStreamingStarted, sampleQueries, selectedNetwork, setIsAwaitingLlm, setPreviousResponse, setSelectedNetwork, title, } = props;
|
|
75
98
|
// MUI theme
|
|
76
99
|
const theme = useTheme();
|
|
77
100
|
// User LLM chat input
|
|
@@ -100,6 +123,12 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
100
123
|
// (see store implementation for details)
|
|
101
124
|
const storedChatHistory = useAgentChatHistoryStore((state) => selectedNetwork ? state?.history?.[selectedNetwork] : undefined);
|
|
102
125
|
const agentChatHistory = useMemo(() => storedChatHistory ?? { chatHistory: [], chatContext: null, slyData: {} }, [storedChatHistory]);
|
|
126
|
+
// For saving chat history. Specifically, exclude "Agent" messages as they are verbose and not useful in a saved
|
|
127
|
+
// export.
|
|
128
|
+
const exportableTurns = turns.filter((turn) => EXPORTED_MESSAGE_TYPES.includes(turn.role));
|
|
129
|
+
const enableSaveChatButton = turns.length > 0 || agentChatHistory?.chatHistory?.length > 0;
|
|
130
|
+
// Display option for agent/network names
|
|
131
|
+
const useNativeNames = useSettingsStore((state) => state.settings.appearance.useNativeNames);
|
|
103
132
|
// Access store for context items
|
|
104
133
|
const updateChatContext = useAgentChatHistoryStore((state) => state.updateChatContext);
|
|
105
134
|
const updateChatHistory = useAgentChatHistoryStore((state) => state.updateChatHistory);
|
|
@@ -134,7 +163,7 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
134
163
|
};
|
|
135
164
|
// Keeps track of whether the agent completed its task
|
|
136
165
|
const succeeded = useRef(false);
|
|
137
|
-
const
|
|
166
|
+
const networkDisplayName = useMemo(() => (useNativeNames ? selectedNetwork : cleanUpAgentName(removeTrailingUuid(selectedNetwork))), [selectedNetwork, useNativeNames]);
|
|
138
167
|
useEffect(() => {
|
|
139
168
|
// Set up speech recognition
|
|
140
169
|
const handlers = setupSpeechRecognition(setChatInput, setVoiceInputState, speechRecognitionRef);
|
|
@@ -169,7 +198,11 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
169
198
|
const legacyTurnIdRef = useRef(null);
|
|
170
199
|
const handleLegacyAgentChunk = useCallback((chunk) => {
|
|
171
200
|
currentResponse.current += chunk;
|
|
172
|
-
if (
|
|
201
|
+
if (legacyTurnIdRef.current) {
|
|
202
|
+
// We already have a turn for this response, so just update the text of that turn.
|
|
203
|
+
setTurns((prev) => prev.map((t) => (t.id === legacyTurnIdRef.current ? { ...t, text: currentResponse.current } : t)));
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
173
206
|
// We don't yet have a turn for this response, so create one. On subsequent chunks, we'll just
|
|
174
207
|
// update the text of this turn.
|
|
175
208
|
legacyTurnIdRef.current = uuid();
|
|
@@ -180,10 +213,6 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
180
213
|
text: currentResponse.current,
|
|
181
214
|
});
|
|
182
215
|
}
|
|
183
|
-
else {
|
|
184
|
-
// We already have a turn for this response, so just update the text of that turn.
|
|
185
|
-
setTurns((prev) => prev.map((t) => (t.id === legacyTurnIdRef.current ? { ...t, text: currentResponse.current } : t)));
|
|
186
|
-
}
|
|
187
216
|
}, [addTurn]);
|
|
188
217
|
const handleNeuroSanAgentChunk = useCallback((chunk) => {
|
|
189
218
|
// For Neuro-san agents, we expect a ChatMessage structure in the chunk.
|
|
@@ -219,9 +248,7 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
219
248
|
// This is the normal happy path for an incoming message.
|
|
220
249
|
// The backend sometimes sends messages with no text content, and we don't want to display those to the
|
|
221
250
|
// user. Agent name is the last tool in the origin array. If it's not there, use a default name.
|
|
222
|
-
const agentName = chatMessage.origin?.
|
|
223
|
-
? cleanUpAgentName(chatMessage.origin[chatMessage.origin.length - 1].tool)
|
|
224
|
-
: "Agent";
|
|
251
|
+
const agentName = chatMessage.origin?.at(-1)?.tool ?? "agent";
|
|
225
252
|
addTurn({
|
|
226
253
|
agentName,
|
|
227
254
|
id: uuid(),
|
|
@@ -283,8 +310,8 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
283
310
|
else {
|
|
284
311
|
// It's a Neuro-san agent.
|
|
285
312
|
// Some coded tools (data generator...) expect the username provided in slyData.
|
|
286
|
-
const
|
|
287
|
-
await sendChatQuery(neuroSanURL, controller?.current.signal, query, selectedNetwork, handleChunk, agentChatHistory.chatContext,
|
|
313
|
+
const slyDataWithUsername = { ...agentChatHistory?.slyData, ...extraSlyData, login: currentUser };
|
|
314
|
+
await sendChatQuery(neuroSanURL, controller?.current.signal, query, selectedNetwork, handleChunk, agentChatHistory.chatContext, slyDataWithUsername, currentUser, StreamingUnit.Line);
|
|
288
315
|
}
|
|
289
316
|
}
|
|
290
317
|
catch (error) {
|
|
@@ -469,6 +496,44 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
469
496
|
resetState();
|
|
470
497
|
}
|
|
471
498
|
}, [addTurn, resetState]);
|
|
499
|
+
const formatTurns = (items) => items.map((turn) => `${roleToExportLabel(turn.role)}: ${turn.text}`).join("\n\n");
|
|
500
|
+
/**
|
|
501
|
+
* Save the current chat history and session to a file
|
|
502
|
+
*/
|
|
503
|
+
const handleSaveChat = () => {
|
|
504
|
+
const chatHistory = agentChatHistory?.chatHistory;
|
|
505
|
+
const chatHistoryTurns = toTurns(chatHistory);
|
|
506
|
+
// Get the current date and time in a human-readable format, including the local time zone
|
|
507
|
+
const exportedAt = new Date();
|
|
508
|
+
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
509
|
+
const exportedAtText = exportedAt.toLocaleString(undefined, {
|
|
510
|
+
year: "numeric",
|
|
511
|
+
month: "short",
|
|
512
|
+
day: "numeric",
|
|
513
|
+
hour: "numeric",
|
|
514
|
+
minute: "2-digit",
|
|
515
|
+
second: "2-digit",
|
|
516
|
+
timeZoneName: "short",
|
|
517
|
+
});
|
|
518
|
+
const allHistoryText = [
|
|
519
|
+
"Chat export",
|
|
520
|
+
`Network: ${selectedNetwork}`,
|
|
521
|
+
`Exported: ${exportedAtText} (${timeZone})`,
|
|
522
|
+
"",
|
|
523
|
+
"====================",
|
|
524
|
+
"Previous history",
|
|
525
|
+
"====================",
|
|
526
|
+
formatTurns(chatHistoryTurns) || "No persisted chat history.",
|
|
527
|
+
"",
|
|
528
|
+
"====================",
|
|
529
|
+
"Current session",
|
|
530
|
+
"====================",
|
|
531
|
+
formatTurns(exportableTurns) || "No current session turns.",
|
|
532
|
+
].join("\n");
|
|
533
|
+
// Download the file
|
|
534
|
+
const filename = `${toSafeFilename(`${selectedNetwork}-history`)}.txt`;
|
|
535
|
+
downloadFile(allHistoryText, filename, "text/plain");
|
|
536
|
+
};
|
|
472
537
|
// Regex to check if user has typed anything besides whitespace
|
|
473
538
|
const userInputEmpty = !chatInput || chatInput.length === 0 || hasOnlyWhitespace(chatInput);
|
|
474
539
|
// Enable Send button when there is user input and not awaiting a response
|
|
@@ -477,7 +542,8 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
477
542
|
const shouldEnableRegenerateButton = previousUserQuery && !isAwaitingLlm;
|
|
478
543
|
// Enable Clear Chat button if not awaiting response and there is chat output to clear
|
|
479
544
|
const enableClearChatButton = !isAwaitingLlm && (turns.length > 0 || agentChatHistory?.chatHistory?.length > 0);
|
|
480
|
-
const
|
|
545
|
+
const [clearChatConfirmationDialogOpen, setClearChatConfirmationDialogOpen] = useState(false);
|
|
546
|
+
const getPlaceholder = () => agentPlaceholders[selectedNetwork] || `Chat with ${networkDisplayName}`;
|
|
481
547
|
const handleClearChat = useCallback(() => {
|
|
482
548
|
setTurns([]);
|
|
483
549
|
resetHistory(selectedNetwork);
|
|
@@ -495,7 +561,7 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
495
561
|
left: 0,
|
|
496
562
|
right: 0,
|
|
497
563
|
bottom: 0,
|
|
498
|
-
zIndex: theme
|
|
564
|
+
zIndex: getZIndex(2, theme),
|
|
499
565
|
cursor: "not-allowed",
|
|
500
566
|
// Capture all pointer events to prevent interaction with the chat when no agent is selected
|
|
501
567
|
pointerEvents: "all",
|
|
@@ -516,14 +582,17 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
516
582
|
paddingTop: "0.25rem",
|
|
517
583
|
paddingBottom: "0.25rem",
|
|
518
584
|
}, 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}` }) }))] }));
|
|
519
|
-
const getOptionsMenuButton = () => (_jsx(Box, { sx: {
|
|
585
|
+
const getOptionsMenuButton = () => (_jsx(Box, { id: `${id}-options-menu-button-container`, sx: {
|
|
586
|
+
backgroundColor: theme.palette.background.paper,
|
|
587
|
+
borderRadius: "var(--bs-border-radius)",
|
|
520
588
|
position: "absolute",
|
|
521
|
-
|
|
522
|
-
|
|
589
|
+
right: theme.spacing(2.5),
|
|
590
|
+
top: theme.spacing(1),
|
|
591
|
+
zIndex: getZIndex(2, theme),
|
|
523
592
|
}, children: _jsx(IconButton, { onClick: (e) => {
|
|
524
593
|
setOptionsMenuAnchorEl(e.currentTarget);
|
|
525
594
|
setOptionsMenuOpen(true);
|
|
526
|
-
}, children: _jsx(TuneIcon, {
|
|
595
|
+
}, children: _jsx(TuneIcon, { fontSize: "small" }) }) }));
|
|
527
596
|
const agentGreeting = customAgentGreetings[selectedNetwork] ?? "Hi, how can I help?";
|
|
528
597
|
const handleOptionsMenuClose = () => {
|
|
529
598
|
setOptionsMenuAnchorEl(null);
|
|
@@ -546,6 +615,21 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
546
615
|
},
|
|
547
616
|
},
|
|
548
617
|
}, children: [_jsxs(MenuItem, { onClick: handleToggleAutoScroll, children: [_jsx(ListItemIcon, { children: _jsx(Checkbox, { checked: autoScrollEnabled, tabIndex: -1, sx: { pointerEvents: "none" } }) }), _jsx(ListItemText, { primary: "Auto-scroll output" })] }), _jsxs(MenuItem, { onClick: handleToggleWrapOutput, children: [_jsx(ListItemIcon, { children: _jsx(Checkbox, { checked: shouldWrapOutput, tabIndex: -1, sx: { pointerEvents: "none" } }) }), _jsx(ListItemText, { primary: "Wrap output" })] })] }));
|
|
618
|
+
const getNetworkIntro = () => (_jsxs(Box, { sx: { marginBottom: "0.5rem", marginTop: "1rem" }, children: [_jsxs(Typography, { component: "span", sx: { fontWeight: 700 }, variant: "inherit", children: [networkDisplayName, networkDescription && ":"] }), networkDescription && (_jsxs(Typography, { component: "span", sx: { ml: 0.5 }, variant: "inherit", children: [" ", networkDescription] }))] }));
|
|
619
|
+
const getChatHistory = () => (_jsx(_Fragment, { children: agentChatHistory?.chatHistory?.length > 0 && (_jsx(Box, { sx: { my: "0.5rem" }, children: _jsx(ChatHistory, { id: id, messages: agentChatHistory.chatHistory }) })) }));
|
|
620
|
+
const getAgentGreeting = () => _jsx(Box, { sx: { marginBottom: "0.5rem", marginTop: "1rem" }, children: agentGreeting });
|
|
621
|
+
const getControlButtons = () => (_jsx(Box, { sx: {
|
|
622
|
+
bottom: theme.spacing(3),
|
|
623
|
+
right: theme.spacing(3),
|
|
624
|
+
position: "absolute",
|
|
625
|
+
zIndex: getZIndex(2, theme),
|
|
626
|
+
}, children: _jsx(ControlButtons, { enableClearChatButton: enableClearChatButton, enableSaveChatButton: enableSaveChatButton, handleClearChat: () => setClearChatConfirmationDialogOpen(true), handleSave: handleSaveChat, handleSend: handleSend, handleStop: handleStop, isAwaitingLlm: isAwaitingLlm, previousUserQuery: previousUserQuery, shouldEnableRegenerateButton: shouldEnableRegenerateButton }) }));
|
|
627
|
+
const getWorkingSpinner = () => (_jsx(_Fragment, { children: 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: {
|
|
628
|
+
color: "var(--bs-primary)",
|
|
629
|
+
}, size: "1rem" })] })) }));
|
|
630
|
+
const getThinking = () => (_jsx(_Fragment, { children: !isAwaitingLlm && turns.length > 0 && (
|
|
631
|
+
// Only show thinking once streaming is complete
|
|
632
|
+
_jsx(Thinking, { id: id, turns: turns, useNativeNames: useNativeNames })) }));
|
|
549
633
|
const getResponseBox = () => (_jsxs(Box, { id: "llm-response-div", sx: {
|
|
550
634
|
...divStyle,
|
|
551
635
|
border: "var(--bs-border-width) var(--bs-border-style)",
|
|
@@ -555,7 +639,16 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
555
639
|
marginLeft: "10px",
|
|
556
640
|
position: "relative",
|
|
557
641
|
overflowY: "auto",
|
|
558
|
-
}, children: [
|
|
642
|
+
}, children: [clearChatConfirmationDialogOpen ? (_jsx(ConfirmationModal, { id: `${id}-clear-chat-confirmation-modal`, content: "This will clear the current chat session and any persisted chat history for this " +
|
|
643
|
+
"network. This operation cannot be undone. Are you sure you wish to continue?", handleCancel: () => {
|
|
644
|
+
setClearChatConfirmationDialogOpen(false);
|
|
645
|
+
}, handleOk: () => {
|
|
646
|
+
setClearChatConfirmationDialogOpen(false);
|
|
647
|
+
setTurns([]);
|
|
648
|
+
resetHistory(selectedNetwork);
|
|
649
|
+
setPreviousUserQuery("");
|
|
650
|
+
currentResponse.current = "";
|
|
651
|
+
}, okBtnLabel: "Yes, clear chat", title: `Clear all chat including history for ${networkDisplayName}?` })) : null, _jsxs(Box, { id: "llm-responses", ref: chatOutputRef, sx: {
|
|
559
652
|
backgroundColor,
|
|
560
653
|
borderRadius: "0.5rem",
|
|
561
654
|
fontSize: "16px",
|
|
@@ -566,16 +659,12 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
566
659
|
paddingTop: "7.5px",
|
|
567
660
|
scrollbarGutter: "stable",
|
|
568
661
|
width: "100%",
|
|
569
|
-
}, tabIndex: -1, children: [getOptionsMenu(), getOptionsMenuButton(),
|
|
570
|
-
// Only show thinking once streaming is complete
|
|
571
|
-
_jsx(Thinking, { id: id, turns: turns })), 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: {
|
|
572
|
-
color: "var(--bs-primary)",
|
|
573
|
-
}, size: "1rem" })] }))] }), _jsx(ControlButtons, { enableClearChatButton: enableClearChatButton, handleClearChat: handleClearChat, handleSend: handleSend, handleStop: handleStop, isAwaitingLlm: isAwaitingLlm, previousUserQuery: previousUserQuery, shouldEnableRegenerateButton: shouldEnableRegenerateButton })] }));
|
|
662
|
+
}, tabIndex: -1, children: [getOptionsMenu(), getOptionsMenuButton(), getChatHistory(), getNetworkIntro(), getAgentGreeting(), _jsx(SampleQueries, { disabled: isAwaitingLlm, handleSend: handleSend, sampleQueries: sampleQueries }), _jsx(Conversation, { id: id, includeAgentMessages: !givesFinalAnswer(selectedNetwork), shouldWrapOutput: shouldWrapOutput, turns: turns }), getThinking(), getWorkingSpinner(), getControlButtons()] })] }));
|
|
574
663
|
const getUserInputBox = () => (_jsxs(Box, { id: "user-input-div", sx: {
|
|
575
664
|
...divStyle,
|
|
665
|
+
alignItems: "center",
|
|
576
666
|
display: "flex",
|
|
577
667
|
margin: "10px",
|
|
578
|
-
alignItems: "flex-end",
|
|
579
668
|
position: "relative",
|
|
580
669
|
}, children: [_jsx(Input, { autoComplete: "off", id: "user-input", multiline: true, placeholder: getPlaceholder(), ref: chatInputRef, sx: {
|
|
581
670
|
border: "var(--bs-border-style) var(--bs-border-width) var(--bs-gray-light)",
|
|
@@ -604,7 +693,7 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
604
693
|
}, sx: {
|
|
605
694
|
color: "var(--bs-primary)",
|
|
606
695
|
opacity: userInputEmpty ? "25%" : "100%",
|
|
607
|
-
}, disabled: userInputEmpty, tabIndex: -1, edge: "end", children: _jsx(ClearIcon, { id: "clear-input-icon" }) })] }) }), _jsx(MicrophoneButton, { isMicOn: isMicOn, onMicToggle: setIsMicOn, speechRecognitionRef: speechRecognitionRef, voiceInputState: voiceInputState
|
|
696
|
+
}, disabled: userInputEmpty, tabIndex: -1, edge: "end", children: _jsx(ClearIcon, { id: "clear-input-icon" }) })] }) }), _jsxs(Box, { sx: { display: "flex", gap: "0.25rem", position: "relative", alignItems: "center" }, children: [_jsx(MicrophoneButton, { isMicOn: isMicOn, onMicToggle: setIsMicOn, setVoiceInputState: setVoiceInputState, speechRecognitionRef: speechRecognitionRef, voiceInputState: voiceInputState }), _jsx(SendButton, { enableSendButton: shouldEnableSendButton, id: "submit-query-button", onClickCallback: () => handleSend(chatInput) })] })] }));
|
|
608
697
|
const getChatBox = () => (_jsxs(Box, { id: `llm-chat-${id}`, sx: {
|
|
609
698
|
display: "flex",
|
|
610
699
|
flexDirection: "column",
|
|
@@ -614,16 +703,20 @@ export const ChatCommon = ({ ref, ...props }) => {
|
|
|
614
703
|
pointerEvents: selectedNetwork ? "auto" : "none",
|
|
615
704
|
position: "relative",
|
|
616
705
|
}, children: [title && getTitle(), getResponseBox(), getUserInputBox()] }));
|
|
706
|
+
const getSelectNetworkOverlayBody = () => (_jsxs(Typography, { component: "span", children: ["Please select a Network from the list to start the chat, or click", _jsx(IconButton, { onClick: () => setSelectedNetwork?.(AGENT_NETWORK_DESIGNER_ID), "aria-label": "select-network-designer", sx: {
|
|
707
|
+
px: 0.5,
|
|
708
|
+
verticalAlign: "middle",
|
|
709
|
+
mb: "4px",
|
|
710
|
+
}, children: _jsx(AddBoxRounded, { sx: {
|
|
711
|
+
color: "var(--bs-secondary)",
|
|
712
|
+
fontSize: "1rem",
|
|
713
|
+
} }) }), "to design your own network!"] }));
|
|
617
714
|
return (_jsx(Box, { id: `llm-chat-${id}`, sx: {
|
|
618
|
-
display: "flex",
|
|
619
|
-
flexDirection: "column",
|
|
620
|
-
flexGrow: 1,
|
|
621
715
|
height: "100%",
|
|
622
716
|
position: "relative",
|
|
623
717
|
}, children: selectedNetwork
|
|
624
|
-
?
|
|
625
|
-
?
|
|
626
|
-
:
|
|
627
|
-
|
|
628
|
-
: getErrorOverlay("Please select a Network from the list to start the chat.") }));
|
|
718
|
+
? hasMissingApiKeys
|
|
719
|
+
? getErrorOverlay("")
|
|
720
|
+
: getChatBox() // Parent will display error for this case
|
|
721
|
+
: getErrorOverlay(getSelectNetworkOverlayBody()) }));
|
|
629
722
|
};
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { BaseMessage } from "@langchain/core/messages";
|
|
2
2
|
import { FC } from "react";
|
|
3
|
+
import { ConversationTurn } from "./ConversationTurn.js";
|
|
3
4
|
interface ChatHistoryProps {
|
|
4
5
|
readonly messages: BaseMessage[];
|
|
5
6
|
readonly id: string;
|
|
6
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Helper function to convert from BaseMessage format used in persisted chat history to ConversationTurn format used for
|
|
10
|
+
* rendering the conversation.
|
|
11
|
+
* @param chatHistory
|
|
12
|
+
*/
|
|
13
|
+
export declare const toTurns: (chatHistory: BaseMessage[]) => ConversationTurn[];
|
|
7
14
|
/**
|
|
8
15
|
* Component for displaying chat history from previous interactions with the agent.
|
|
9
16
|
*/
|
|
@@ -10,7 +10,7 @@ import { AccordionLite } from "../../Common/AccordionLite.js";
|
|
|
10
10
|
* rendering the conversation.
|
|
11
11
|
* @param chatHistory
|
|
12
12
|
*/
|
|
13
|
-
const toTurns = (chatHistory) => chatHistory
|
|
13
|
+
export const toTurns = (chatHistory) => chatHistory
|
|
14
14
|
.filter((message) => message.type === "human" || message.type === "ai")
|
|
15
15
|
.map((message) => {
|
|
16
16
|
const role = message.type === "human" ? MessageRole.User : MessageRole.Agent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const MAX_TURNS = 50;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
2
|
interface ControlButtonsProps {
|
|
3
|
-
handleClearChat: () => void;
|
|
4
3
|
enableClearChatButton: boolean;
|
|
5
|
-
|
|
4
|
+
enableSaveChatButton: boolean;
|
|
5
|
+
handleClearChat: () => void;
|
|
6
|
+
handleSave: () => void;
|
|
6
7
|
handleSend: (query: string) => void;
|
|
7
8
|
handleStop: () => void;
|
|
9
|
+
isAwaitingLlm: boolean;
|
|
8
10
|
previousUserQuery: string;
|
|
9
11
|
shouldEnableRegenerateButton: boolean;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
|
-
* Generate the Control Buttons for a chat window
|
|
14
|
+
* Generate the Control Buttons for a chat window (resend, clear chat, stop)
|
|
13
15
|
* @returns A fragment containing the Control Buttons.
|
|
14
16
|
*/
|
|
15
17
|
export declare const ControlButtons: FC<ControlButtonsProps>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
|
|
4
4
|
|
|
@@ -16,11 +16,20 @@ limitations under the License.
|
|
|
16
16
|
*/
|
|
17
17
|
import DeleteOutlined from "@mui/icons-material/DeleteOutlined";
|
|
18
18
|
import Loop from "@mui/icons-material/Loop";
|
|
19
|
+
import SaveIcon from "@mui/icons-material/Save";
|
|
19
20
|
import StopCircle from "@mui/icons-material/StopCircle";
|
|
21
|
+
import Box from "@mui/material/Box";
|
|
22
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
20
23
|
import { SmallLlmChatButton } from "../Common/LlmChatButton.js";
|
|
21
|
-
|
|
24
|
+
//#endregion: Types
|
|
22
25
|
/**
|
|
23
|
-
* Generate the Control Buttons for a chat window
|
|
26
|
+
* Generate the Control Buttons for a chat window (resend, clear chat, stop)
|
|
24
27
|
* @returns A fragment containing the Control Buttons.
|
|
25
28
|
*/
|
|
26
|
-
export const ControlButtons = ({
|
|
29
|
+
export const ControlButtons = ({ enableClearChatButton, enableSaveChatButton, handleClearChat, handleSave, handleSend, handleStop, isAwaitingLlm, previousUserQuery, shouldEnableRegenerateButton, }) => (_jsx(_Fragment, { children: isAwaitingLlm ? (
|
|
30
|
+
// Stop Button
|
|
31
|
+
_jsx(Tooltip, { title: "Terminate request", children: _jsx(SmallLlmChatButton, { "aria-label": "Stop", disabled: !isAwaitingLlm, id: "stop-output-button", onClick: () => handleStop(), children: _jsx(StopCircle, { fontSize: "small", id: "stop-button-icon" }) }) })) : (_jsxs(Box, { sx: { display: "flex", gap: 1 }, children: [_jsx(Tooltip, { title: "Save Chat", children: _jsx("span", { children: _jsx(SmallLlmChatButton, { "aria-label": "Save Chat", disabled: !enableSaveChatButton, id: "save-chat-button", onClick: handleSave, children: _jsx(SaveIcon, { fontSize: "small", id: "save-button-icon" }) }) }) }), _jsx(Tooltip, { title: "Clear Chat", children: _jsx("span", { children: _jsx(SmallLlmChatButton, { "aria-label": "Clear Chat", disabled: !enableClearChatButton, id: "clear-chat-button", onClick: handleClearChat, children: _jsx(DeleteOutlined, { fontSize: "small", id: "stop-button-icon", sx: {
|
|
32
|
+
"&:hover": {
|
|
33
|
+
color: "error.main",
|
|
34
|
+
},
|
|
35
|
+
} }) }) }) }), _jsx(Tooltip, { title: "Resend last query", children: _jsx("span", { children: _jsx(SmallLlmChatButton, { "aria-label": "Regenerate", disabled: !shouldEnableRegenerateButton, id: "regenerate-output-button", onClick: () => handleSend(previousUserQuery), children: _jsx(Loop, { fontSize: "small", id: "generate-icon" }) }) }) })] })) }));
|
|
@@ -3,11 +3,11 @@ import { ChatMessageType } from "../../../generated/neuro-san/NeuroSanClient.js"
|
|
|
3
3
|
* The various messages roles in a conversation turn.
|
|
4
4
|
*/
|
|
5
5
|
export declare enum MessageRole {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
Agent = "Agent",
|
|
7
|
+
Error = "Error",
|
|
8
|
+
FinalAnswer = "FinalAnswer",
|
|
9
|
+
User = "User",
|
|
10
|
+
Warning = "Warning"
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* Represents a single turn in a conversation, which may include a message from the user or agent, or an error
|
|
@@ -53,6 +53,9 @@ export const FormattedMarkdown = ({ id, nodesList, style, wrapLongLines = false,
|
|
|
53
53
|
// If not, do our best to synthesize a key
|
|
54
54
|
return `${hashString(node?.toString() || "")}-${index}`;
|
|
55
55
|
};
|
|
56
|
+
if (!nodesList || nodesList.length === 0) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
56
59
|
// Walk through the nodes list. If we encounter a string node, we'll aggregate it with other string nodes.
|
|
57
60
|
const formattedOutput = [];
|
|
58
61
|
let currentTextNodes = [];
|
|
@@ -15,14 +15,15 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import SendIcon from "@mui/icons-material/Send";
|
|
18
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
18
19
|
import { LlmChatButton } from "../Common/LlmChatButton.js";
|
|
19
|
-
|
|
20
|
+
//#endregion: Types
|
|
20
21
|
/**
|
|
21
22
|
* Generate the Send Button for a chat window.
|
|
22
23
|
* @returns The Send Button.
|
|
23
24
|
*/
|
|
24
|
-
export const SendButton = ({ enableSendButton, id, onClickCallback }) => (_jsx(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
export const SendButton = ({ enableSendButton, id, onClickCallback }) => (_jsx(Tooltip, { placement: "top", title: enableSendButton ? "Send" : "Enter a message to enable the send button", children: _jsx("span", { style: {
|
|
26
|
+
display: "inline-block",
|
|
27
|
+
cursor: enableSendButton ? "inherit" : "not-allowed",
|
|
28
|
+
}, children: _jsx(LlmChatButton, { "aria-label": "Send", disabled: !enableSendButton, id: id, onClick: onClickCallback, tabIndex: 0, children: _jsx(SendIcon, { fontSize: "small", id: "stop-button-icon" // Could update this but it would impact QA
|
|
29
|
+
}) }) }) }));
|
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|
|
17
17
|
* List of available hljs themes for the syntax highlighter.
|
|
18
18
|
* See: https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/src/styles/hljs/index.js
|
|
19
19
|
*/
|
|
20
|
-
import { a11yDark, a11yLight, atelierDuneDark, docco } from "react-syntax-highlighter/dist/
|
|
20
|
+
import { a11yDark, a11yLight, atelierDuneDark, docco } from "react-syntax-highlighter/dist/esm/styles/hljs";
|
|
21
21
|
// hljs themes
|
|
22
22
|
export const HLJS_THEMES = {
|
|
23
23
|
a11yDark,
|
|
@@ -3,6 +3,7 @@ import { ConversationTurn } from "./ConversationTurn.js";
|
|
|
3
3
|
interface ThinkingProps {
|
|
4
4
|
readonly id: string;
|
|
5
5
|
readonly turns: ConversationTurn[];
|
|
6
|
+
readonly useNativeNames: boolean;
|
|
6
7
|
}
|
|
7
8
|
/**
|
|
8
9
|
* Component to render the "thinking" section of the chat, which includes all messages from the agent that are
|