@backstage-community/plugin-mcp-chat 0.0.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 +361 -0
- package/config.d.ts +47 -0
- package/dist/api/McpChatApi.esm.js +55 -0
- package/dist/api/McpChatApi.esm.js.map +1 -0
- package/dist/api/index.esm.js +8 -0
- package/dist/api/index.esm.js.map +1 -0
- package/dist/components/BotIcon/BotIcon.esm.js +57 -0
- package/dist/components/BotIcon/BotIcon.esm.js.map +1 -0
- package/dist/components/ChatContainer/ChatContainer.esm.js +246 -0
- package/dist/components/ChatContainer/ChatContainer.esm.js.map +1 -0
- package/dist/components/ChatContainer/ChatMessage.esm.js +466 -0
- package/dist/components/ChatContainer/ChatMessage.esm.js.map +1 -0
- package/dist/components/ChatContainer/QuickStart.esm.js +271 -0
- package/dist/components/ChatContainer/QuickStart.esm.js.map +1 -0
- package/dist/components/ChatContainer/TypingIndicator.esm.js +154 -0
- package/dist/components/ChatContainer/TypingIndicator.esm.js.map +1 -0
- package/dist/components/ChatPage/ChatPage.esm.js +142 -0
- package/dist/components/ChatPage/ChatPage.esm.js.map +1 -0
- package/dist/components/ChatPage/index.esm.js +2 -0
- package/dist/components/ChatPage/index.esm.js.map +1 -0
- package/dist/components/RightPane/ActiveMcpServers.esm.js +159 -0
- package/dist/components/RightPane/ActiveMcpServers.esm.js.map +1 -0
- package/dist/components/RightPane/ActiveTools.esm.js +308 -0
- package/dist/components/RightPane/ActiveTools.esm.js.map +1 -0
- package/dist/components/RightPane/ProviderStatus.esm.js +225 -0
- package/dist/components/RightPane/ProviderStatus.esm.js.map +1 -0
- package/dist/components/RightPane/RightPane.esm.js +242 -0
- package/dist/components/RightPane/RightPane.esm.js.map +1 -0
- package/dist/hooks/useAvailableTools.esm.js +33 -0
- package/dist/hooks/useAvailableTools.esm.js.map +1 -0
- package/dist/hooks/useMcpServers.esm.js +40 -0
- package/dist/hooks/useMcpServers.esm.js.map +1 -0
- package/dist/hooks/useProviderStatus.esm.js +22 -0
- package/dist/hooks/useProviderStatus.esm.js.map +1 -0
- package/dist/index.d.ts +150 -0
- package/dist/index.esm.js +3 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/plugin.esm.js +33 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/routes.esm.js +8 -0
- package/dist/routes.esm.js.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { useTheme } from '@mui/material/styles';
|
|
4
|
+
import BuildIcon from '@mui/icons-material/Build';
|
|
5
|
+
import CodeIcon from '@mui/icons-material/Code';
|
|
6
|
+
import FileCopyIcon from '@mui/icons-material/FileCopy';
|
|
7
|
+
import PersonIcon from '@mui/icons-material/Person';
|
|
8
|
+
import Avatar from '@mui/material/Avatar';
|
|
9
|
+
import Box from '@mui/material/Box';
|
|
10
|
+
import Card from '@mui/material/Card';
|
|
11
|
+
import Chip from '@mui/material/Chip';
|
|
12
|
+
import Collapse from '@mui/material/Collapse';
|
|
13
|
+
import IconButton from '@mui/material/IconButton';
|
|
14
|
+
import Typography from '@mui/material/Typography';
|
|
15
|
+
import ReactMarkdown from 'react-markdown';
|
|
16
|
+
import { BotIcon } from '../BotIcon/BotIcon.esm.js';
|
|
17
|
+
|
|
18
|
+
const ChatMessage = ({ message }) => {
|
|
19
|
+
const theme = useTheme();
|
|
20
|
+
const isDarkMode = theme.palette.mode === "dark";
|
|
21
|
+
const [copiedText, setCopiedText] = useState(null);
|
|
22
|
+
const [selectedTool, setSelectedTool] = useState(null);
|
|
23
|
+
const getAvatarBackgroundColor = () => {
|
|
24
|
+
if (message.isUser) return theme.palette.success.main;
|
|
25
|
+
return isDarkMode ? theme.palette.background.paper : theme.palette.background.paper;
|
|
26
|
+
};
|
|
27
|
+
const getAvatarColor = () => {
|
|
28
|
+
if (message.isUser) return theme.palette.success.contrastText;
|
|
29
|
+
return isDarkMode ? theme.palette.text.primary : theme.palette.text.secondary;
|
|
30
|
+
};
|
|
31
|
+
const getCardBackgroundColor = () => {
|
|
32
|
+
if (!message.isUser) return "transparent";
|
|
33
|
+
return isDarkMode ? theme.palette.background.paper : theme.palette.background.default;
|
|
34
|
+
};
|
|
35
|
+
const getCardBorder = () => {
|
|
36
|
+
if (!message.isUser) return "none";
|
|
37
|
+
return `1px solid ${theme.palette.divider}`;
|
|
38
|
+
};
|
|
39
|
+
const handleCopyCode = async (text) => {
|
|
40
|
+
try {
|
|
41
|
+
await window.navigator.clipboard.writeText(text);
|
|
42
|
+
setCopiedText(text);
|
|
43
|
+
setTimeout(() => setCopiedText(null), 2e3);
|
|
44
|
+
} catch (err) {
|
|
45
|
+
console.error("Failed to copy text:", err);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const handleTooltipToggle = (toolName) => {
|
|
49
|
+
setSelectedTool(selectedTool === toolName ? null : toolName);
|
|
50
|
+
};
|
|
51
|
+
const getToolResponseForTool = (toolName) => {
|
|
52
|
+
if (!message.toolsUsed || !message.toolResponses) {
|
|
53
|
+
return "No tools used or no tool responses available";
|
|
54
|
+
}
|
|
55
|
+
const toolResponse = message.toolResponses.find(
|
|
56
|
+
(response) => response.name === toolName
|
|
57
|
+
);
|
|
58
|
+
if (!toolResponse) {
|
|
59
|
+
return `No response data found for tool: ${toolName}`;
|
|
60
|
+
}
|
|
61
|
+
return JSON.stringify(toolResponse, null, 2);
|
|
62
|
+
};
|
|
63
|
+
const handleCopyToolResponse = async (toolName) => {
|
|
64
|
+
try {
|
|
65
|
+
const toolResponse = getToolResponseForTool(toolName);
|
|
66
|
+
await window.navigator.clipboard.writeText(toolResponse);
|
|
67
|
+
setCopiedText(toolResponse);
|
|
68
|
+
setTimeout(() => setCopiedText(null), 2e3);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
console.error("Failed to copy tool response:", err);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const CodeBlock = ({ children, ...props }) => {
|
|
74
|
+
const codeText = children?.props?.children || "";
|
|
75
|
+
return /* @__PURE__ */ jsxs(Box, { sx: { position: "relative" }, children: [
|
|
76
|
+
/* @__PURE__ */ jsx("pre", { ...props, children }),
|
|
77
|
+
/* @__PURE__ */ jsx(
|
|
78
|
+
IconButton,
|
|
79
|
+
{
|
|
80
|
+
size: "small",
|
|
81
|
+
onClick: () => handleCopyCode(codeText),
|
|
82
|
+
title: copiedText === codeText ? "Copied!" : "Copy code",
|
|
83
|
+
sx: {
|
|
84
|
+
position: "absolute",
|
|
85
|
+
top: theme.spacing(0.5),
|
|
86
|
+
right: theme.spacing(0.5),
|
|
87
|
+
padding: theme.spacing(0.5),
|
|
88
|
+
minWidth: "auto",
|
|
89
|
+
backgroundColor: "rgba(255, 255, 255, 0.8)",
|
|
90
|
+
"&:hover": {
|
|
91
|
+
backgroundColor: "rgba(255, 255, 255, 0.9)"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
children: /* @__PURE__ */ jsx(FileCopyIcon, { fontSize: "small" })
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
] });
|
|
98
|
+
};
|
|
99
|
+
const formatMessage = (text) => {
|
|
100
|
+
if (!text || !text.trim()) {
|
|
101
|
+
return /* @__PURE__ */ jsx(
|
|
102
|
+
Typography,
|
|
103
|
+
{
|
|
104
|
+
variant: "body1",
|
|
105
|
+
sx: {
|
|
106
|
+
fontSize: "0.95rem",
|
|
107
|
+
lineHeight: message.isUser ? 1.5 : 1.6,
|
|
108
|
+
color: theme.palette.text.primary,
|
|
109
|
+
fontWeight: message.isUser ? 500 : "normal",
|
|
110
|
+
fontFamily: message.isUser ? "inherit" : '"Helvetica Neue", Helvetica, Arial, sans-serif'
|
|
111
|
+
},
|
|
112
|
+
children: text
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const hasMarkdown = /[#*_`\[\]]/g.test(text) || text.includes("```") || text.includes("\n") || text.includes("|") || // tables
|
|
117
|
+
text.includes("> ");
|
|
118
|
+
if (hasMarkdown) {
|
|
119
|
+
return /* @__PURE__ */ jsx(
|
|
120
|
+
Box,
|
|
121
|
+
{
|
|
122
|
+
sx: {
|
|
123
|
+
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif',
|
|
124
|
+
"& h1, & h2, & h3, & h4, & h5, & h6": {
|
|
125
|
+
marginTop: theme.spacing(2),
|
|
126
|
+
marginBottom: theme.spacing(1),
|
|
127
|
+
fontWeight: 600,
|
|
128
|
+
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif'
|
|
129
|
+
},
|
|
130
|
+
"& h1": {
|
|
131
|
+
fontSize: "1.5rem"
|
|
132
|
+
},
|
|
133
|
+
"& h2": {
|
|
134
|
+
fontSize: "1.3rem"
|
|
135
|
+
},
|
|
136
|
+
"& h3": {
|
|
137
|
+
fontSize: "1.1rem"
|
|
138
|
+
},
|
|
139
|
+
"& p": {
|
|
140
|
+
margin: theme.spacing(0.5, 0),
|
|
141
|
+
lineHeight: 1.6,
|
|
142
|
+
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif'
|
|
143
|
+
},
|
|
144
|
+
"& ul, & ol": {
|
|
145
|
+
margin: theme.spacing(0.5, 0),
|
|
146
|
+
paddingLeft: theme.spacing(3),
|
|
147
|
+
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif'
|
|
148
|
+
},
|
|
149
|
+
"& li": {
|
|
150
|
+
margin: theme.spacing(0.25, 0),
|
|
151
|
+
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif'
|
|
152
|
+
},
|
|
153
|
+
"& blockquote": {
|
|
154
|
+
borderLeft: `4px solid ${theme.palette.primary.main}`,
|
|
155
|
+
paddingLeft: theme.spacing(2),
|
|
156
|
+
margin: theme.spacing(1, 0),
|
|
157
|
+
fontStyle: "italic",
|
|
158
|
+
backgroundColor: theme.palette.background.default,
|
|
159
|
+
padding: theme.spacing(1, 1, 1, 2),
|
|
160
|
+
borderRadius: theme.spacing(0.5)
|
|
161
|
+
},
|
|
162
|
+
"& code": {
|
|
163
|
+
backgroundColor: theme.palette.action.hover,
|
|
164
|
+
color: theme.palette.text.primary,
|
|
165
|
+
padding: "2px 4px",
|
|
166
|
+
borderRadius: "3px",
|
|
167
|
+
fontFamily: "monospace",
|
|
168
|
+
fontSize: "0.875em"
|
|
169
|
+
},
|
|
170
|
+
"& pre": {
|
|
171
|
+
backgroundColor: theme.palette.background.default,
|
|
172
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
173
|
+
borderRadius: theme.spacing(0.5),
|
|
174
|
+
padding: theme.spacing(1.5),
|
|
175
|
+
fontFamily: "monospace",
|
|
176
|
+
fontSize: "0.875rem",
|
|
177
|
+
margin: theme.spacing(1, 0),
|
|
178
|
+
overflow: "auto",
|
|
179
|
+
position: "relative",
|
|
180
|
+
"& code": {
|
|
181
|
+
backgroundColor: "transparent",
|
|
182
|
+
padding: 0,
|
|
183
|
+
color: theme.palette.text.primary
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
"& table": {
|
|
187
|
+
borderCollapse: "collapse",
|
|
188
|
+
width: "100%",
|
|
189
|
+
margin: theme.spacing(1, 0)
|
|
190
|
+
},
|
|
191
|
+
"& th, & td": {
|
|
192
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
193
|
+
padding: theme.spacing(0.5, 1),
|
|
194
|
+
textAlign: "left"
|
|
195
|
+
},
|
|
196
|
+
"& th": {
|
|
197
|
+
backgroundColor: theme.palette.action.hover,
|
|
198
|
+
fontWeight: 600
|
|
199
|
+
},
|
|
200
|
+
"& a": {
|
|
201
|
+
color: theme.palette.primary.main,
|
|
202
|
+
textDecoration: "none",
|
|
203
|
+
"&:hover": {
|
|
204
|
+
textDecoration: "underline"
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
"& hr": {
|
|
208
|
+
border: "none",
|
|
209
|
+
borderTop: `1px solid ${theme.palette.divider}`,
|
|
210
|
+
margin: theme.spacing(2, 0)
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
children: /* @__PURE__ */ jsx(
|
|
214
|
+
ReactMarkdown,
|
|
215
|
+
{
|
|
216
|
+
components: {
|
|
217
|
+
pre: CodeBlock
|
|
218
|
+
},
|
|
219
|
+
children: text
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
return /* @__PURE__ */ jsx(
|
|
226
|
+
Typography,
|
|
227
|
+
{
|
|
228
|
+
variant: "body1",
|
|
229
|
+
sx: {
|
|
230
|
+
fontSize: "0.95rem",
|
|
231
|
+
lineHeight: message.isUser ? 1.5 : 1.6,
|
|
232
|
+
color: theme.palette.text.primary,
|
|
233
|
+
fontWeight: message.isUser ? 500 : "normal",
|
|
234
|
+
fontFamily: message.isUser ? "inherit" : '"Helvetica Neue", Helvetica, Arial, sans-serif'
|
|
235
|
+
},
|
|
236
|
+
children: text
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
};
|
|
240
|
+
return /* @__PURE__ */ jsxs(
|
|
241
|
+
Box,
|
|
242
|
+
{
|
|
243
|
+
"data-testid": "message-container",
|
|
244
|
+
className: message.isUser ? "user-message" : "bot-message",
|
|
245
|
+
sx: {
|
|
246
|
+
display: "flex",
|
|
247
|
+
alignItems: "flex-start",
|
|
248
|
+
gap: theme.spacing(4),
|
|
249
|
+
marginBottom: theme.spacing(3)
|
|
250
|
+
},
|
|
251
|
+
children: [
|
|
252
|
+
/* @__PURE__ */ jsx(
|
|
253
|
+
Avatar,
|
|
254
|
+
{
|
|
255
|
+
sx: {
|
|
256
|
+
width: message.isUser ? 32 : 35,
|
|
257
|
+
height: message.isUser ? 32 : 35,
|
|
258
|
+
fontSize: "1rem",
|
|
259
|
+
marginTop: theme.spacing(0.25),
|
|
260
|
+
backgroundColor: getAvatarBackgroundColor(),
|
|
261
|
+
color: getAvatarColor()
|
|
262
|
+
},
|
|
263
|
+
children: message.isUser ? /* @__PURE__ */ jsx(PersonIcon, { "data-testid": "person-icon" }) : /* @__PURE__ */ jsx(
|
|
264
|
+
BotIcon,
|
|
265
|
+
{
|
|
266
|
+
"data-testid": "bot-icon",
|
|
267
|
+
color: isDarkMode ? theme.palette.text.primary : theme.palette.text.secondary
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
}
|
|
271
|
+
),
|
|
272
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
|
|
273
|
+
Card,
|
|
274
|
+
{
|
|
275
|
+
sx: {
|
|
276
|
+
maxWidth: "100%",
|
|
277
|
+
position: "relative",
|
|
278
|
+
backgroundColor: getCardBackgroundColor(),
|
|
279
|
+
color: "inherit",
|
|
280
|
+
border: getCardBorder(),
|
|
281
|
+
borderRadius: message.isUser ? theme.spacing(1) : 0,
|
|
282
|
+
boxShadow: message.isUser ? theme.shadows[1] : "none",
|
|
283
|
+
"&:hover .message-actions": {
|
|
284
|
+
opacity: 1
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
children: /* @__PURE__ */ jsxs(
|
|
288
|
+
Box,
|
|
289
|
+
{
|
|
290
|
+
sx: {
|
|
291
|
+
padding: message.isUser ? theme.spacing(1) : 0
|
|
292
|
+
},
|
|
293
|
+
children: [
|
|
294
|
+
formatMessage(message.text),
|
|
295
|
+
(message.toolsUsed || message.tools) && (message.toolsUsed || message.tools).length > 0 && /* @__PURE__ */ jsxs(
|
|
296
|
+
Box,
|
|
297
|
+
{
|
|
298
|
+
sx: {
|
|
299
|
+
marginTop: theme.spacing(1.5),
|
|
300
|
+
padding: theme.spacing(1, 0),
|
|
301
|
+
borderTop: `1px solid ${theme.palette.divider}`
|
|
302
|
+
},
|
|
303
|
+
children: [
|
|
304
|
+
/* @__PURE__ */ jsxs(
|
|
305
|
+
Box,
|
|
306
|
+
{
|
|
307
|
+
sx: {
|
|
308
|
+
display: "flex",
|
|
309
|
+
alignItems: "center",
|
|
310
|
+
gap: theme.spacing(0.5),
|
|
311
|
+
marginBottom: theme.spacing(1),
|
|
312
|
+
color: theme.palette.text.primary,
|
|
313
|
+
fontSize: "0.85rem",
|
|
314
|
+
fontWeight: 600,
|
|
315
|
+
flexWrap: "wrap"
|
|
316
|
+
},
|
|
317
|
+
children: [
|
|
318
|
+
/* @__PURE__ */ jsx(BuildIcon, { fontSize: "small" }),
|
|
319
|
+
/* @__PURE__ */ jsxs(
|
|
320
|
+
Typography,
|
|
321
|
+
{
|
|
322
|
+
variant: "caption",
|
|
323
|
+
style: { fontWeight: "bold" },
|
|
324
|
+
children: [
|
|
325
|
+
"Tools used (",
|
|
326
|
+
(message.toolsUsed || message.tools).length,
|
|
327
|
+
")"
|
|
328
|
+
]
|
|
329
|
+
}
|
|
330
|
+
),
|
|
331
|
+
(message.toolsUsed || message.tools).map((tool) => /* @__PURE__ */ jsx(
|
|
332
|
+
Chip,
|
|
333
|
+
{
|
|
334
|
+
label: tool,
|
|
335
|
+
size: "small",
|
|
336
|
+
clickable: true,
|
|
337
|
+
onClick: () => handleTooltipToggle(tool),
|
|
338
|
+
icon: /* @__PURE__ */ jsx(CodeIcon, { fontSize: "small" }),
|
|
339
|
+
sx: {
|
|
340
|
+
height: 24,
|
|
341
|
+
fontSize: "0.75rem",
|
|
342
|
+
fontWeight: 500,
|
|
343
|
+
backgroundColor: "transparent",
|
|
344
|
+
color: selectedTool === tool ? theme.palette.primary.main : theme.palette.text.secondary,
|
|
345
|
+
margin: "0 4px 0 8px",
|
|
346
|
+
border: selectedTool === tool ? `2px solid ${theme.palette.primary.main}` : `1px solid ${theme.palette.divider}`,
|
|
347
|
+
cursor: "pointer",
|
|
348
|
+
transition: "all 0.2s ease",
|
|
349
|
+
"&:hover": {
|
|
350
|
+
backgroundColor: theme.palette.action.hover,
|
|
351
|
+
color: theme.palette.text.primary,
|
|
352
|
+
transform: "translateY(-1px)"
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
tool
|
|
357
|
+
))
|
|
358
|
+
]
|
|
359
|
+
}
|
|
360
|
+
),
|
|
361
|
+
(message.toolsUsed || message.tools).map((tool) => /* @__PURE__ */ jsx(
|
|
362
|
+
Collapse,
|
|
363
|
+
{
|
|
364
|
+
in: selectedTool === tool,
|
|
365
|
+
children: /* @__PURE__ */ jsxs(
|
|
366
|
+
Card,
|
|
367
|
+
{
|
|
368
|
+
sx: {
|
|
369
|
+
marginTop: theme.spacing(1),
|
|
370
|
+
backgroundColor: theme.palette.background.default,
|
|
371
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
372
|
+
borderRadius: theme.spacing(1)
|
|
373
|
+
},
|
|
374
|
+
children: [
|
|
375
|
+
/* @__PURE__ */ jsxs(
|
|
376
|
+
Box,
|
|
377
|
+
{
|
|
378
|
+
sx: {
|
|
379
|
+
display: "flex",
|
|
380
|
+
justifyContent: "space-between",
|
|
381
|
+
alignItems: "center",
|
|
382
|
+
padding: theme.spacing(1, 1.5),
|
|
383
|
+
backgroundColor: theme.palette.action.hover,
|
|
384
|
+
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
385
|
+
borderRadius: theme.spacing(1, 1, 0, 0)
|
|
386
|
+
},
|
|
387
|
+
children: [
|
|
388
|
+
/* @__PURE__ */ jsxs(
|
|
389
|
+
Typography,
|
|
390
|
+
{
|
|
391
|
+
sx: {
|
|
392
|
+
fontSize: "0.875rem",
|
|
393
|
+
fontWeight: 600,
|
|
394
|
+
color: theme.palette.text.primary
|
|
395
|
+
},
|
|
396
|
+
children: [
|
|
397
|
+
tool,
|
|
398
|
+
" Response"
|
|
399
|
+
]
|
|
400
|
+
}
|
|
401
|
+
),
|
|
402
|
+
/* @__PURE__ */ jsx(
|
|
403
|
+
IconButton,
|
|
404
|
+
{
|
|
405
|
+
size: "small",
|
|
406
|
+
onClick: () => handleCopyToolResponse(tool),
|
|
407
|
+
title: copiedText ? "Copied!" : "Copy response",
|
|
408
|
+
sx: {
|
|
409
|
+
color: theme.palette.text.primary
|
|
410
|
+
},
|
|
411
|
+
children: /* @__PURE__ */ jsx(FileCopyIcon, { fontSize: "small" })
|
|
412
|
+
}
|
|
413
|
+
)
|
|
414
|
+
]
|
|
415
|
+
}
|
|
416
|
+
),
|
|
417
|
+
/* @__PURE__ */ jsx(
|
|
418
|
+
Box,
|
|
419
|
+
{
|
|
420
|
+
sx: {
|
|
421
|
+
padding: theme.spacing(1.5),
|
|
422
|
+
maxHeight: "300px",
|
|
423
|
+
overflow: "auto"
|
|
424
|
+
},
|
|
425
|
+
children: /* @__PURE__ */ jsx(
|
|
426
|
+
Box,
|
|
427
|
+
{
|
|
428
|
+
sx: {
|
|
429
|
+
backgroundColor: theme.palette.background.paper,
|
|
430
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
431
|
+
borderRadius: theme.spacing(0.5),
|
|
432
|
+
padding: theme.spacing(1.5),
|
|
433
|
+
fontFamily: 'Monaco, Menlo, "Ubuntu Mono", Consolas, source-code-pro, monospace',
|
|
434
|
+
fontSize: "0.8rem",
|
|
435
|
+
lineHeight: 1.4,
|
|
436
|
+
overflow: "auto",
|
|
437
|
+
whiteSpace: "pre-wrap",
|
|
438
|
+
wordBreak: "break-word",
|
|
439
|
+
color: theme.palette.text.primary
|
|
440
|
+
},
|
|
441
|
+
children: getToolResponseForTool(tool)
|
|
442
|
+
}
|
|
443
|
+
)
|
|
444
|
+
}
|
|
445
|
+
)
|
|
446
|
+
]
|
|
447
|
+
}
|
|
448
|
+
)
|
|
449
|
+
},
|
|
450
|
+
`collapse-${tool}`
|
|
451
|
+
))
|
|
452
|
+
]
|
|
453
|
+
}
|
|
454
|
+
)
|
|
455
|
+
]
|
|
456
|
+
}
|
|
457
|
+
)
|
|
458
|
+
}
|
|
459
|
+
) })
|
|
460
|
+
]
|
|
461
|
+
}
|
|
462
|
+
);
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
export { ChatMessage };
|
|
466
|
+
//# sourceMappingURL=ChatMessage.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatMessage.esm.js","sources":["../../../src/components/ChatContainer/ChatMessage.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState } from 'react';\n\nimport { useTheme } from '@mui/material/styles';\nimport BuildIcon from '@mui/icons-material/Build';\nimport CodeIcon from '@mui/icons-material/Code';\nimport FileCopyIcon from '@mui/icons-material/FileCopy';\nimport PersonIcon from '@mui/icons-material/Person';\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport Card from '@mui/material/Card';\nimport Chip from '@mui/material/Chip';\nimport Collapse from '@mui/material/Collapse';\nimport IconButton from '@mui/material/IconButton';\nimport Typography from '@mui/material/Typography';\nimport ReactMarkdown from 'react-markdown';\nimport { BotIcon } from '../BotIcon';\n\ninterface ChatMessageProps {\n message: {\n id: string;\n text: string;\n isUser: boolean;\n timestamp: Date;\n tools?: string[];\n toolsUsed?: string[];\n toolResponses?: any[];\n };\n onFeedback?: (messageId: string, type: 'like' | 'dislike') => void;\n onCopy?: (text: string) => void;\n}\n\nexport const ChatMessage = ({ message }: ChatMessageProps) => {\n const theme = useTheme();\n const isDarkMode = theme.palette.mode === 'dark';\n const [copiedText, setCopiedText] = useState<string | null>(null);\n const [selectedTool, setSelectedTool] = useState<string | null>(null);\n\n // Helper functions to avoid nested ternary expressions\n const getAvatarBackgroundColor = () => {\n if (message.isUser) return theme.palette.success.main;\n return isDarkMode\n ? theme.palette.background.paper\n : theme.palette.background.paper;\n };\n\n const getAvatarColor = () => {\n if (message.isUser) return theme.palette.success.contrastText;\n return isDarkMode\n ? theme.palette.text.primary\n : theme.palette.text.secondary;\n };\n\n const getCardBackgroundColor = () => {\n if (!message.isUser) return 'transparent';\n return isDarkMode\n ? theme.palette.background.paper\n : theme.palette.background.default;\n };\n\n const getCardBorder = () => {\n if (!message.isUser) return 'none';\n return `1px solid ${theme.palette.divider}`;\n };\n\n const handleCopyCode = async (text: string) => {\n try {\n await window.navigator.clipboard.writeText(text);\n setCopiedText(text);\n setTimeout(() => setCopiedText(null), 2000);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('Failed to copy text:', err);\n }\n };\n\n const handleTooltipToggle = (toolName: string) => {\n setSelectedTool(selectedTool === toolName ? null : toolName);\n };\n\n const getToolResponseForTool = (toolName: string) => {\n if (!message.toolsUsed || !message.toolResponses) {\n return 'No tools used or no tool responses available';\n }\n\n const toolResponse = message.toolResponses.find(\n response => response.name === toolName,\n );\n\n if (!toolResponse) {\n return `No response data found for tool: ${toolName}`;\n }\n\n return JSON.stringify(toolResponse, null, 2);\n };\n\n const handleCopyToolResponse = async (toolName: string) => {\n try {\n const toolResponse = getToolResponseForTool(toolName);\n await window.navigator.clipboard.writeText(toolResponse);\n setCopiedText(toolResponse);\n setTimeout(() => setCopiedText(null), 2000);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('Failed to copy tool response:', err);\n }\n };\n\n const CodeBlock = ({ children, ...props }: any) => {\n const codeText = children?.props?.children || '';\n return (\n <Box sx={{ position: 'relative' }}>\n <pre {...props}>{children}</pre>\n <IconButton\n size=\"small\"\n onClick={() => handleCopyCode(codeText)}\n title={copiedText === codeText ? 'Copied!' : 'Copy code'}\n sx={{\n position: 'absolute',\n top: theme.spacing(0.5),\n right: theme.spacing(0.5),\n padding: theme.spacing(0.5),\n minWidth: 'auto',\n backgroundColor: 'rgba(255, 255, 255, 0.8)',\n '&:hover': {\n backgroundColor: 'rgba(255, 255, 255, 0.9)',\n },\n }}\n >\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Box>\n );\n };\n\n const formatMessage = (text: string) => {\n // Don't render empty or whitespace-only messages as markdown\n if (!text || !text.trim()) {\n return (\n <Typography\n variant=\"body1\"\n sx={{\n fontSize: '0.95rem',\n lineHeight: message.isUser ? 1.5 : 1.6,\n color: theme.palette.text.primary,\n fontWeight: message.isUser ? 500 : 'normal',\n fontFamily: message.isUser\n ? 'inherit'\n : '\"Helvetica Neue\", Helvetica, Arial, sans-serif',\n }}\n >\n {text}\n </Typography>\n );\n }\n\n // Check if the message contains markdown-like content\n const hasMarkdown =\n /[#*_`\\[\\]]/g.test(text) ||\n text.includes('```') ||\n text.includes('\\n') ||\n text.includes('|') || // tables\n text.includes('> '); // blockquotes\n\n if (hasMarkdown) {\n return (\n <Box\n sx={{\n fontFamily: '\"Helvetica Neue\", Helvetica, Arial, sans-serif',\n '& h1, & h2, & h3, & h4, & h5, & h6': {\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n fontWeight: 600,\n fontFamily: '\"Helvetica Neue\", Helvetica, Arial, sans-serif',\n },\n '& h1': {\n fontSize: '1.5rem',\n },\n '& h2': {\n fontSize: '1.3rem',\n },\n '& h3': {\n fontSize: '1.1rem',\n },\n '& p': {\n margin: theme.spacing(0.5, 0),\n lineHeight: 1.6,\n fontFamily: '\"Helvetica Neue\", Helvetica, Arial, sans-serif',\n },\n '& ul, & ol': {\n margin: theme.spacing(0.5, 0),\n paddingLeft: theme.spacing(3),\n fontFamily: '\"Helvetica Neue\", Helvetica, Arial, sans-serif',\n },\n '& li': {\n margin: theme.spacing(0.25, 0),\n fontFamily: '\"Helvetica Neue\", Helvetica, Arial, sans-serif',\n },\n '& blockquote': {\n borderLeft: `4px solid ${theme.palette.primary.main}`,\n paddingLeft: theme.spacing(2),\n margin: theme.spacing(1, 0),\n fontStyle: 'italic',\n backgroundColor: theme.palette.background.default,\n padding: theme.spacing(1, 1, 1, 2),\n borderRadius: theme.spacing(0.5),\n },\n '& code': {\n backgroundColor: theme.palette.action.hover,\n color: theme.palette.text.primary,\n padding: '2px 4px',\n borderRadius: '3px',\n fontFamily: 'monospace',\n fontSize: '0.875em',\n },\n '& pre': {\n backgroundColor: theme.palette.background.default,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.spacing(0.5),\n padding: theme.spacing(1.5),\n fontFamily: 'monospace',\n fontSize: '0.875rem',\n margin: theme.spacing(1, 0),\n overflow: 'auto',\n position: 'relative',\n '& code': {\n backgroundColor: 'transparent',\n padding: 0,\n color: theme.palette.text.primary,\n },\n },\n '& table': {\n borderCollapse: 'collapse',\n width: '100%',\n margin: theme.spacing(1, 0),\n },\n '& th, & td': {\n border: `1px solid ${theme.palette.divider}`,\n padding: theme.spacing(0.5, 1),\n textAlign: 'left',\n },\n '& th': {\n backgroundColor: theme.palette.action.hover,\n fontWeight: 600,\n },\n '& a': {\n color: theme.palette.primary.main,\n textDecoration: 'none',\n '&:hover': {\n textDecoration: 'underline',\n },\n },\n '& hr': {\n border: 'none',\n borderTop: `1px solid ${theme.palette.divider}`,\n margin: theme.spacing(2, 0),\n },\n }}\n >\n <ReactMarkdown\n components={{\n pre: CodeBlock,\n }}\n >\n {text}\n </ReactMarkdown>\n </Box>\n );\n }\n\n // For simple text messages, use Typography with appropriate styling\n return (\n <Typography\n variant=\"body1\"\n sx={{\n fontSize: '0.95rem',\n lineHeight: message.isUser ? 1.5 : 1.6,\n color: theme.palette.text.primary,\n fontWeight: message.isUser ? 500 : 'normal',\n fontFamily: message.isUser\n ? 'inherit'\n : '\"Helvetica Neue\", Helvetica, Arial, sans-serif',\n }}\n >\n {text}\n </Typography>\n );\n };\n\n return (\n <Box\n data-testid=\"message-container\"\n className={message.isUser ? 'user-message' : 'bot-message'}\n sx={{\n display: 'flex',\n alignItems: 'flex-start',\n gap: theme.spacing(4),\n marginBottom: theme.spacing(3),\n }}\n >\n <Avatar\n sx={{\n width: message.isUser ? 32 : 35,\n height: message.isUser ? 32 : 35,\n fontSize: '1rem',\n marginTop: theme.spacing(0.25),\n backgroundColor: getAvatarBackgroundColor(),\n color: getAvatarColor(),\n }}\n >\n {message.isUser ? (\n <PersonIcon data-testid=\"person-icon\" />\n ) : (\n <BotIcon\n data-testid=\"bot-icon\"\n color={\n isDarkMode\n ? theme.palette.text.primary\n : theme.palette.text.secondary\n }\n />\n )}\n </Avatar>\n\n <Box>\n <Card\n sx={{\n maxWidth: '100%',\n position: 'relative',\n backgroundColor: getCardBackgroundColor(),\n color: 'inherit',\n border: getCardBorder(),\n borderRadius: message.isUser ? theme.spacing(1) : 0,\n boxShadow: message.isUser ? theme.shadows[1] : 'none',\n '&:hover .message-actions': {\n opacity: 1,\n },\n }}\n >\n <Box\n sx={{\n padding: message.isUser ? theme.spacing(1) : 0,\n }}\n >\n {formatMessage(message.text)}\n\n {/* Show tools section for tools that were used */}\n {(message.toolsUsed || message.tools) &&\n (message.toolsUsed || message.tools)!.length > 0 && (\n <Box\n sx={{\n marginTop: theme.spacing(1.5),\n padding: theme.spacing(1, 0),\n borderTop: `1px solid ${theme.palette.divider}`,\n }}\n >\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n marginBottom: theme.spacing(1),\n color: theme.palette.text.primary,\n fontSize: '0.85rem',\n fontWeight: 600,\n flexWrap: 'wrap',\n }}\n >\n <BuildIcon fontSize=\"small\" />\n <Typography\n variant=\"caption\"\n style={{ fontWeight: 'bold' }}\n >\n Tools used ({(message.toolsUsed || message.tools)!.length}\n )\n </Typography>\n {(message.toolsUsed || message.tools)!.map(tool => (\n <Chip\n key={tool}\n label={tool}\n size=\"small\"\n clickable\n onClick={() => handleTooltipToggle(tool)}\n icon={<CodeIcon fontSize=\"small\" />}\n sx={{\n height: 24,\n fontSize: '0.75rem',\n fontWeight: 500,\n backgroundColor: 'transparent',\n color:\n selectedTool === tool\n ? theme.palette.primary.main\n : theme.palette.text.secondary,\n margin: '0 4px 0 8px',\n border:\n selectedTool === tool\n ? `2px solid ${theme.palette.primary.main}`\n : `1px solid ${theme.palette.divider}`,\n cursor: 'pointer',\n transition: 'all 0.2s ease',\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n color: theme.palette.text.primary,\n transform: 'translateY(-1px)',\n },\n }}\n />\n ))}\n </Box>\n\n {/* Tool responses - shown below the chips */}\n {(message.toolsUsed || message.tools)!.map(tool => (\n <Collapse\n key={`collapse-${tool}`}\n in={selectedTool === tool}\n >\n <Card\n sx={{\n marginTop: theme.spacing(1),\n backgroundColor: theme.palette.background.default,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.spacing(1),\n }}\n >\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: theme.spacing(1, 1.5),\n backgroundColor: theme.palette.action.hover,\n borderBottom: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.spacing(1, 1, 0, 0),\n }}\n >\n <Typography\n sx={{\n fontSize: '0.875rem',\n fontWeight: 600,\n color: theme.palette.text.primary,\n }}\n >\n {tool} Response\n </Typography>\n <IconButton\n size=\"small\"\n onClick={() => handleCopyToolResponse(tool)}\n title={copiedText ? 'Copied!' : 'Copy response'}\n sx={{\n color: theme.palette.text.primary,\n }}\n >\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Box>\n <Box\n sx={{\n padding: theme.spacing(1.5),\n maxHeight: '300px',\n overflow: 'auto',\n }}\n >\n <Box\n sx={{\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.spacing(0.5),\n padding: theme.spacing(1.5),\n fontFamily:\n 'Monaco, Menlo, \"Ubuntu Mono\", Consolas, source-code-pro, monospace',\n fontSize: '0.8rem',\n lineHeight: 1.4,\n overflow: 'auto',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n color: theme.palette.text.primary,\n }}\n >\n {getToolResponseForTool(tool)}\n </Box>\n </Box>\n </Card>\n </Collapse>\n ))}\n </Box>\n )}\n </Box>\n </Card>\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|