@canmingir/link 1.2.62 → 1.2.64
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/package.json
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { Button, Typography } from "@mui/material";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
3
|
-
|
|
4
1
|
import Box from "@mui/material/Box";
|
|
5
2
|
import Drawer from "@mui/material/Drawer";
|
|
6
3
|
import Iconify from "../../components/Iconify";
|
|
@@ -20,6 +17,9 @@ import { usePathname } from "../../routes/hooks/use-pathname";
|
|
|
20
17
|
import { useResponsive } from "../../hooks/use-responsive";
|
|
21
18
|
import { useUser } from "../../hooks/use-user";
|
|
22
19
|
|
|
20
|
+
import { Button, Typography } from "@mui/material";
|
|
21
|
+
import { useEffect, useState } from "react";
|
|
22
|
+
|
|
23
23
|
// ----------------------------------------------------------------------
|
|
24
24
|
|
|
25
25
|
export default function NavVertical({ openNav, onCloseNav }) {
|
|
@@ -31,15 +31,9 @@ export default function NavVertical({ openNav, onCloseNav }) {
|
|
|
31
31
|
const lgUp = useResponsive("up", "lg");
|
|
32
32
|
const { beta, name } = config();
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
if (index !== -1) {
|
|
40
|
-
sideMenu.splice(index, 1);
|
|
41
|
-
}
|
|
42
|
-
}, [hideSubheader]);
|
|
34
|
+
const filteredSideMenu = sideMenu.filter(
|
|
35
|
+
(item) => item.subheader !== hideSubheader.subheader
|
|
36
|
+
);
|
|
43
37
|
|
|
44
38
|
useEffect(() => {
|
|
45
39
|
if (openNav) {
|
|
@@ -105,7 +99,8 @@ export default function NavVertical({ openNav, onCloseNav }) {
|
|
|
105
99
|
mt: 3,
|
|
106
100
|
}}
|
|
107
101
|
>
|
|
108
|
-
<Logo maxSize={name ? 100 : 150} sx={{ ml: name ?
|
|
102
|
+
<Logo maxSize={name ? 100 : 150} sx={{ ml: name ? -8 : -10 }} />
|
|
103
|
+
|
|
109
104
|
<Typography
|
|
110
105
|
sx={{
|
|
111
106
|
ml: 2,
|
|
@@ -116,7 +111,7 @@ export default function NavVertical({ openNav, onCloseNav }) {
|
|
|
116
111
|
</Box>
|
|
117
112
|
)}
|
|
118
113
|
<NavSectionVertical
|
|
119
|
-
data={
|
|
114
|
+
data={filteredSideMenu}
|
|
120
115
|
slotProps={{
|
|
121
116
|
currentRole: user?.role,
|
|
122
117
|
}}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
1
|
import { Box, Card, Stack, Typography } from "@mui/material";
|
|
4
2
|
import { alpha, useTheme } from "@mui/material/styles";
|
|
5
3
|
|
|
4
|
+
import React from "react";
|
|
5
|
+
|
|
6
6
|
const STYLES = {
|
|
7
7
|
width: "100%",
|
|
8
8
|
display: "-webkit-box",
|
|
@@ -158,7 +158,7 @@ export function SideStripeCard({
|
|
|
158
158
|
const theme = useTheme();
|
|
159
159
|
|
|
160
160
|
return (
|
|
161
|
-
<Box sx={{ cursor: "
|
|
161
|
+
<Box sx={{ cursor: "inherit" }}>
|
|
162
162
|
<Card
|
|
163
163
|
sx={{
|
|
164
164
|
display: "flex",
|
|
@@ -315,7 +315,7 @@ export function HeaderCard({
|
|
|
315
315
|
left: 0,
|
|
316
316
|
background: `linear-gradient(135deg, ${alpha(
|
|
317
317
|
theme.palette.secondary.light,
|
|
318
|
-
0.2
|
|
318
|
+
0.2,
|
|
319
319
|
)}, ${alpha(theme.palette.primary.main, 0.3)})`,
|
|
320
320
|
borderRadius: "8px 8px 0 0",
|
|
321
321
|
transition: "height 0.3s ease-in-out",
|
|
@@ -369,7 +369,7 @@ export function AvatarRoleCard({
|
|
|
369
369
|
left: 0,
|
|
370
370
|
background: `linear-gradient(135deg, ${alpha(
|
|
371
371
|
theme.palette.secondary.light,
|
|
372
|
-
0.2
|
|
372
|
+
0.2,
|
|
373
373
|
)}, ${alpha(theme.palette.primary.main, 0.3)})`,
|
|
374
374
|
borderRadius: "8px 8px 0 0",
|
|
375
375
|
transition: "height 0.3s ease-in-out",
|
|
@@ -385,8 +385,9 @@ export function AvatarRoleCard({
|
|
|
385
385
|
direction="row"
|
|
386
386
|
sx={{
|
|
387
387
|
justifyContent: "space-between",
|
|
388
|
-
alignItems: "flex-start"
|
|
389
|
-
}}
|
|
388
|
+
alignItems: "flex-start",
|
|
389
|
+
}}
|
|
390
|
+
>
|
|
390
391
|
{leftContent}
|
|
391
392
|
{topRightContent}
|
|
392
393
|
</Stack>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Iconify } from "@canmingir/link/platform/components";
|
|
2
|
-
|
|
3
1
|
import React, { useEffect, useState } from "react";
|
|
4
2
|
import { alpha, styled } from "@mui/material/styles";
|
|
5
3
|
|
|
4
|
+
import { Iconify } from "@canmingir/link/platform/components";
|
|
5
|
+
|
|
6
6
|
const ANIMATION_DELAY_MS = 200;
|
|
7
7
|
|
|
8
8
|
const MainContainer = styled("div", {
|
|
@@ -33,7 +33,7 @@ const MainContainer = styled("div", {
|
|
|
33
33
|
border: `1px solid ${borderColor}`,
|
|
34
34
|
backdropFilter: "blur(10px)",
|
|
35
35
|
transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
|
|
36
|
-
cursor: "
|
|
36
|
+
cursor: "inherit",
|
|
37
37
|
position: "relative",
|
|
38
38
|
overflow: "hidden",
|
|
39
39
|
minWidth,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import PresetSelector from "../PresetSelector/PresetSelector";
|
|
2
1
|
import Editor from "@monaco-editor/react";
|
|
3
2
|
import { Iconify } from "@canmingir/link/platform/components";
|
|
3
|
+
import PresetSelector from "../PresetSelector/PresetSelector";
|
|
4
4
|
import { Scrollbar } from "@canmingir/link/platform/components";
|
|
5
5
|
import Stack from "@mui/material/Stack";
|
|
6
6
|
import { alpha } from "@mui/material/styles";
|
|
@@ -16,8 +16,8 @@ import {
|
|
|
16
16
|
Typography,
|
|
17
17
|
} from "@mui/material";
|
|
18
18
|
import { LoadingMessage, MessageList } from "../ChatMessage";
|
|
19
|
-
import { ToolDecision, ToolRenderers } from "../ChatMessage/ToolMessage";
|
|
20
19
|
import React, { memo, useCallback, useRef, useState } from "react";
|
|
20
|
+
import { ToolDecision, ToolRenderers } from "../ChatMessage/ToolMessage";
|
|
21
21
|
|
|
22
22
|
const DRAWER_WIDTH = 400;
|
|
23
23
|
|
|
@@ -43,6 +43,8 @@ interface ChatDrawerProps {
|
|
|
43
43
|
onNewSession?: () => void;
|
|
44
44
|
toolRenderers?: ToolRenderers;
|
|
45
45
|
onToolDecision?: (toolCallId: string, decision: ToolDecision) => void;
|
|
46
|
+
embedded?: boolean;
|
|
47
|
+
footer?: React.ReactNode;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
const DEFAULT_JSON = `{\n \n}`;
|
|
@@ -65,6 +67,8 @@ const ChatDrawer = ({
|
|
|
65
67
|
highlightedMessage,
|
|
66
68
|
toolRenderers,
|
|
67
69
|
onToolDecision,
|
|
70
|
+
embedded,
|
|
71
|
+
footer,
|
|
68
72
|
}: ChatDrawerProps) => {
|
|
69
73
|
const inputRef = useRef(null);
|
|
70
74
|
const [inputMode, setInputMode] = useState<InputMode>("chat");
|
|
@@ -124,115 +128,105 @@ const ChatDrawer = ({
|
|
|
124
128
|
[handleJsonSend]
|
|
125
129
|
);
|
|
126
130
|
|
|
127
|
-
|
|
128
|
-
<
|
|
129
|
-
anchor="right"
|
|
130
|
-
open={open}
|
|
131
|
-
onClose={onClose}
|
|
132
|
-
variant="persistent"
|
|
131
|
+
const content = (
|
|
132
|
+
<Box
|
|
133
133
|
sx={{
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
},
|
|
134
|
+
display: "flex",
|
|
135
|
+
flexDirection: "column",
|
|
136
|
+
height: "100%",
|
|
137
|
+
width: "100%",
|
|
138
|
+
minWidth: 0,
|
|
139
|
+
maxWidth: "100%",
|
|
140
|
+
bgcolor: (theme) => theme.palette.background.default,
|
|
142
141
|
}}
|
|
143
142
|
>
|
|
143
|
+
{/* Header */}
|
|
144
144
|
<Box
|
|
145
145
|
sx={{
|
|
146
|
+
bgcolor: (theme) => alpha(theme.palette.grey[900], 0.9),
|
|
146
147
|
display: "flex",
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
justifyContent: "space-between",
|
|
149
|
+
alignItems: "center",
|
|
150
|
+
p: 2,
|
|
151
|
+
borderBottom: (theme) =>
|
|
152
|
+
`1px solid ${alpha(theme.palette.divider, 0.1)}`,
|
|
150
153
|
}}
|
|
151
154
|
>
|
|
152
|
-
{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
alignItems: "center",
|
|
159
|
-
p: 2,
|
|
160
|
-
borderBottom: (theme) =>
|
|
161
|
-
`1px solid ${alpha(theme.palette.divider, 0.1)}`,
|
|
162
|
-
}}
|
|
163
|
-
>
|
|
164
|
-
<Typography variant="h6" sx={{ color: "white", fontWeight: 600 }}>
|
|
165
|
-
{title}
|
|
166
|
-
</Typography>
|
|
167
|
-
<Stack direction="row" spacing={1}>
|
|
168
|
-
{!readOnly && (
|
|
169
|
-
<IconButton onClick={onMuteToggle} size="small">
|
|
170
|
-
<Iconify
|
|
171
|
-
icon={
|
|
172
|
-
mute
|
|
173
|
-
? "solar:volume-cross-bold-duotone"
|
|
174
|
-
: "solar:volume-loud-bold-duotone"
|
|
175
|
-
}
|
|
176
|
-
sx={{ width: 20, height: 20, color: "white" }}
|
|
177
|
-
/>
|
|
178
|
-
</IconButton>
|
|
179
|
-
)}
|
|
180
|
-
<IconButton onClick={onClose} size="small">
|
|
155
|
+
<Typography variant="h6" sx={{ color: "white", fontWeight: 600 }}>
|
|
156
|
+
{title}
|
|
157
|
+
</Typography>
|
|
158
|
+
<Stack direction="row" spacing={1}>
|
|
159
|
+
{!readOnly && (
|
|
160
|
+
<IconButton onClick={onMuteToggle} size="small">
|
|
181
161
|
<Iconify
|
|
182
|
-
icon=
|
|
183
|
-
|
|
162
|
+
icon={
|
|
163
|
+
mute
|
|
164
|
+
? "solar:volume-cross-bold-duotone"
|
|
165
|
+
: "solar:volume-loud-bold-duotone"
|
|
166
|
+
}
|
|
167
|
+
sx={{ width: 20, height: 20, color: "white" }}
|
|
184
168
|
/>
|
|
185
169
|
</IconButton>
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
<PresetSelector
|
|
192
|
-
Presets={Presets}
|
|
193
|
-
selectedPreset={selectedPreset}
|
|
194
|
-
onPresetChange={onPresetChange}
|
|
170
|
+
)}
|
|
171
|
+
<IconButton onClick={onClose} size="small">
|
|
172
|
+
<Iconify
|
|
173
|
+
icon="mdi:chevron-right"
|
|
174
|
+
sx={{ width: 24, height: 24, color: "white" }}
|
|
195
175
|
/>
|
|
196
|
-
</
|
|
197
|
-
|
|
176
|
+
</IconButton>
|
|
177
|
+
</Stack>
|
|
178
|
+
</Box>
|
|
198
179
|
|
|
199
|
-
|
|
200
|
-
<Box sx={{
|
|
201
|
-
<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
selectedId={selectedConversationId}
|
|
207
|
-
messagesEndRef={messagesEndRef}
|
|
208
|
-
highlightedMessage={highlightedMessage}
|
|
209
|
-
toolRenderers={toolRenderers}
|
|
210
|
-
onToolDecision={onToolDecision}
|
|
211
|
-
/>
|
|
212
|
-
{showLoading && <LoadingMessage messagesEndRef={messagesEndRef} />}
|
|
213
|
-
</Scrollbar>
|
|
180
|
+
{Presets.length > 0 && !readOnly && (
|
|
181
|
+
<Box sx={{ px: 2, pt: 1 }}>
|
|
182
|
+
<PresetSelector
|
|
183
|
+
Presets={Presets}
|
|
184
|
+
selectedPreset={selectedPreset}
|
|
185
|
+
onPresetChange={onPresetChange}
|
|
186
|
+
/>
|
|
214
187
|
</Box>
|
|
188
|
+
)}
|
|
189
|
+
|
|
190
|
+
{/* Messages */}
|
|
191
|
+
<Box sx={{ flex: 1, minWidth: 0, overflow: "hidden", p: 2 }}>
|
|
192
|
+
<Scrollbar sx={{ height: "100%", width: "100%" }}>
|
|
193
|
+
<MessageList
|
|
194
|
+
messages={
|
|
195
|
+
history as { id: string; content: string; role: string }[]
|
|
196
|
+
}
|
|
197
|
+
selectedId={selectedConversationId}
|
|
198
|
+
messagesEndRef={messagesEndRef}
|
|
199
|
+
highlightedMessage={highlightedMessage}
|
|
200
|
+
toolRenderers={toolRenderers}
|
|
201
|
+
onToolDecision={onToolDecision}
|
|
202
|
+
/>
|
|
203
|
+
{showLoading && <LoadingMessage messagesEndRef={messagesEndRef} />}
|
|
204
|
+
</Scrollbar>
|
|
205
|
+
</Box>
|
|
206
|
+
|
|
207
|
+
{footer}
|
|
215
208
|
|
|
216
|
-
|
|
217
|
-
|
|
209
|
+
{/* Input Area */}
|
|
210
|
+
{!readOnly && (
|
|
211
|
+
<Box
|
|
212
|
+
sx={{
|
|
213
|
+
borderTop: (theme) =>
|
|
214
|
+
`1px solid ${alpha(theme.palette.divider, 0.1)}`,
|
|
215
|
+
bgcolor: (theme) => alpha(theme.palette.grey[900], 0.5),
|
|
216
|
+
}}
|
|
217
|
+
>
|
|
218
|
+
{/* Mode Toggle */}
|
|
218
219
|
<Box
|
|
219
220
|
sx={{
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
display: "flex",
|
|
222
|
+
alignItems: "center",
|
|
223
|
+
px: 2,
|
|
224
|
+
pt: 1.5,
|
|
225
|
+
pb: 1,
|
|
226
|
+
gap: 1,
|
|
223
227
|
}}
|
|
224
228
|
>
|
|
225
|
-
{
|
|
226
|
-
<Box
|
|
227
|
-
sx={{
|
|
228
|
-
display: "flex",
|
|
229
|
-
alignItems: "center",
|
|
230
|
-
px: 2,
|
|
231
|
-
pt: 1.5,
|
|
232
|
-
pb: 1,
|
|
233
|
-
gap: 1,
|
|
234
|
-
}}
|
|
235
|
-
>
|
|
229
|
+
{!embedded && (
|
|
236
230
|
<ToggleButtonGroup
|
|
237
231
|
value={inputMode}
|
|
238
232
|
exclusive
|
|
@@ -265,6 +259,7 @@ const ChatDrawer = ({
|
|
|
265
259
|
/>
|
|
266
260
|
Chat
|
|
267
261
|
</ToggleButton>
|
|
262
|
+
|
|
268
263
|
<ToggleButton value="json">
|
|
269
264
|
<Iconify
|
|
270
265
|
icon="solar:code-bold-duotone"
|
|
@@ -273,133 +268,177 @@ const ChatDrawer = ({
|
|
|
273
268
|
JSON
|
|
274
269
|
</ToggleButton>
|
|
275
270
|
</ToggleButtonGroup>
|
|
276
|
-
</Box>
|
|
277
|
-
|
|
278
|
-
{/* Chat Input */}
|
|
279
|
-
{inputMode === "chat" && (
|
|
280
|
-
<Box sx={{ px: 2, pb: 2 }}>
|
|
281
|
-
<TextField
|
|
282
|
-
variant="outlined"
|
|
283
|
-
autoComplete="off"
|
|
284
|
-
fullWidth
|
|
285
|
-
placeholder="Type a message..."
|
|
286
|
-
inputRef={inputRef}
|
|
287
|
-
onKeyDown={handleKeyDown}
|
|
288
|
-
size="small"
|
|
289
|
-
sx={{
|
|
290
|
-
"& .MuiOutlinedInput-root": {
|
|
291
|
-
bgcolor: (theme) =>
|
|
292
|
-
alpha(theme.palette.background.paper, 0.8),
|
|
293
|
-
},
|
|
294
|
-
}}
|
|
295
|
-
slotProps={{
|
|
296
|
-
input: {
|
|
297
|
-
endAdornment: (
|
|
298
|
-
<IconButton
|
|
299
|
-
onClick={() => {
|
|
300
|
-
const content = inputRef.current?.value?.trim();
|
|
301
|
-
if (content) {
|
|
302
|
-
onSend(content);
|
|
303
|
-
inputRef.current.value = "";
|
|
304
|
-
}
|
|
305
|
-
}}
|
|
306
|
-
size="small"
|
|
307
|
-
>
|
|
308
|
-
<Iconify
|
|
309
|
-
icon="material-symbols:send"
|
|
310
|
-
sx={{ width: 20, height: 20 }}
|
|
311
|
-
/>
|
|
312
|
-
</IconButton>
|
|
313
|
-
),
|
|
314
|
-
},
|
|
315
|
-
}}
|
|
316
|
-
/>
|
|
317
|
-
</Box>
|
|
318
271
|
)}
|
|
272
|
+
</Box>
|
|
319
273
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
options={{
|
|
343
|
-
minimap: { enabled: false },
|
|
344
|
-
fontSize: 12,
|
|
345
|
-
lineNumbers: "off",
|
|
346
|
-
scrollBeyondLastLine: false,
|
|
347
|
-
wordWrap: "on",
|
|
348
|
-
tabSize: 2,
|
|
349
|
-
folding: false,
|
|
350
|
-
glyphMargin: false,
|
|
351
|
-
lineDecorationsWidth: 0,
|
|
352
|
-
lineNumbersMinChars: 0,
|
|
353
|
-
padding: { top: 8, bottom: 8 },
|
|
354
|
-
}}
|
|
355
|
-
/>
|
|
356
|
-
</Box>
|
|
357
|
-
|
|
358
|
-
<Box
|
|
359
|
-
sx={{
|
|
360
|
-
display: "flex",
|
|
361
|
-
alignItems: "center",
|
|
362
|
-
justifyContent: "space-between",
|
|
363
|
-
mt: 1,
|
|
364
|
-
}}
|
|
365
|
-
>
|
|
366
|
-
<Typography
|
|
367
|
-
variant="caption"
|
|
368
|
-
sx={{
|
|
369
|
-
color: jsonError
|
|
370
|
-
? "error.main"
|
|
371
|
-
: (theme) => alpha(theme.palette.text.secondary, 0.5),
|
|
372
|
-
fontSize: "0.7rem",
|
|
373
|
-
}}
|
|
374
|
-
>
|
|
375
|
-
{jsonError ?? "⌘↵ to send"}
|
|
376
|
-
</Typography>
|
|
377
|
-
<Tooltip title="Send JSON (⌘↵)" placement="top">
|
|
378
|
-
<span>
|
|
274
|
+
{/* Chat Input */}
|
|
275
|
+
{inputMode === "chat" && (
|
|
276
|
+
<Box sx={{ px: 2, pb: 2 }}>
|
|
277
|
+
<TextField
|
|
278
|
+
variant="outlined"
|
|
279
|
+
autoComplete="off"
|
|
280
|
+
fullWidth
|
|
281
|
+
multiline
|
|
282
|
+
maxRows={9}
|
|
283
|
+
placeholder="Type a message..."
|
|
284
|
+
inputRef={inputRef}
|
|
285
|
+
onKeyDown={handleKeyDown}
|
|
286
|
+
size="small"
|
|
287
|
+
sx={{
|
|
288
|
+
"& .MuiOutlinedInput-root": {
|
|
289
|
+
bgcolor: (theme) =>
|
|
290
|
+
alpha(theme.palette.background.paper, 0.8),
|
|
291
|
+
},
|
|
292
|
+
}}
|
|
293
|
+
slotProps={{
|
|
294
|
+
input: {
|
|
295
|
+
endAdornment: (
|
|
379
296
|
<IconButton
|
|
380
|
-
onClick={handleJsonSend}
|
|
381
|
-
size="small"
|
|
382
|
-
disabled={!!jsonError}
|
|
383
297
|
sx={{
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
298
|
+
alignSelf: "flex-end",
|
|
299
|
+
mb: 0.5,
|
|
300
|
+
}}
|
|
301
|
+
onClick={() => {
|
|
302
|
+
const content = inputRef.current?.value?.trim();
|
|
303
|
+
if (content) {
|
|
304
|
+
onSend(content);
|
|
305
|
+
inputRef.current.value = "";
|
|
306
|
+
}
|
|
388
307
|
}}
|
|
308
|
+
size="small"
|
|
389
309
|
>
|
|
390
310
|
<Iconify
|
|
391
311
|
icon="material-symbols:send"
|
|
392
|
-
sx={{ width:
|
|
312
|
+
sx={{ width: 20, height: 20 }}
|
|
393
313
|
/>
|
|
394
314
|
</IconButton>
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
315
|
+
),
|
|
316
|
+
},
|
|
317
|
+
}}
|
|
318
|
+
/>
|
|
319
|
+
</Box>
|
|
320
|
+
)}
|
|
321
|
+
|
|
322
|
+
{/* JSON Input */}
|
|
323
|
+
{inputMode === "json" && (
|
|
324
|
+
<Box sx={{ px: 2, pb: 2 }} onKeyDown={handleJsonKeyDown}>
|
|
325
|
+
<Box
|
|
326
|
+
sx={{
|
|
327
|
+
border: (theme) =>
|
|
328
|
+
`1px solid ${
|
|
329
|
+
jsonError
|
|
330
|
+
? theme.palette.error.main
|
|
331
|
+
: alpha(theme.palette.primary.main, 0.3)
|
|
332
|
+
}`,
|
|
333
|
+
borderRadius: 1,
|
|
334
|
+
overflow: "hidden",
|
|
335
|
+
bgcolor: "#1e1e1e",
|
|
336
|
+
}}
|
|
337
|
+
>
|
|
338
|
+
<Editor
|
|
339
|
+
height="160px"
|
|
340
|
+
defaultLanguage="json"
|
|
341
|
+
value={jsonValue}
|
|
342
|
+
onChange={handleJsonChange}
|
|
343
|
+
theme="vs-dark"
|
|
344
|
+
options={{
|
|
345
|
+
minimap: { enabled: false },
|
|
346
|
+
fontSize: 12,
|
|
347
|
+
lineNumbers: "off",
|
|
348
|
+
scrollBeyondLastLine: false,
|
|
349
|
+
wordWrap: "on",
|
|
350
|
+
tabSize: 2,
|
|
351
|
+
folding: false,
|
|
352
|
+
glyphMargin: false,
|
|
353
|
+
lineDecorationsWidth: 0,
|
|
354
|
+
lineNumbersMinChars: 0,
|
|
355
|
+
padding: { top: 8, bottom: 8 },
|
|
356
|
+
}}
|
|
357
|
+
/>
|
|
398
358
|
</Box>
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
359
|
+
|
|
360
|
+
<Box
|
|
361
|
+
sx={{
|
|
362
|
+
display: "flex",
|
|
363
|
+
alignItems: "center",
|
|
364
|
+
justifyContent: "space-between",
|
|
365
|
+
mt: 1,
|
|
366
|
+
}}
|
|
367
|
+
>
|
|
368
|
+
<Typography
|
|
369
|
+
variant="caption"
|
|
370
|
+
sx={{
|
|
371
|
+
color: jsonError
|
|
372
|
+
? "error.main"
|
|
373
|
+
: (theme) => alpha(theme.palette.text.secondary, 0.5),
|
|
374
|
+
fontSize: "0.7rem",
|
|
375
|
+
}}
|
|
376
|
+
>
|
|
377
|
+
{jsonError ?? "⌘↵ to send"}
|
|
378
|
+
</Typography>
|
|
379
|
+
<Tooltip title="Send JSON (⌘↵)" placement="top">
|
|
380
|
+
<span>
|
|
381
|
+
<IconButton
|
|
382
|
+
onClick={handleJsonSend}
|
|
383
|
+
size="small"
|
|
384
|
+
disabled={!!jsonError}
|
|
385
|
+
sx={{
|
|
386
|
+
color: (theme) =>
|
|
387
|
+
jsonError
|
|
388
|
+
? theme.palette.action.disabled
|
|
389
|
+
: theme.palette.primary.light,
|
|
390
|
+
}}
|
|
391
|
+
>
|
|
392
|
+
<Iconify
|
|
393
|
+
icon="material-symbols:send"
|
|
394
|
+
sx={{ width: 18, height: 18 }}
|
|
395
|
+
/>
|
|
396
|
+
</IconButton>
|
|
397
|
+
</span>
|
|
398
|
+
</Tooltip>
|
|
399
|
+
</Box>
|
|
400
|
+
</Box>
|
|
401
|
+
)}
|
|
402
|
+
</Box>
|
|
403
|
+
)}
|
|
404
|
+
</Box>
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
if (embedded) {
|
|
408
|
+
return (
|
|
409
|
+
<Box
|
|
410
|
+
sx={{
|
|
411
|
+
display: open ? "flex" : "none",
|
|
412
|
+
flexDirection: "column",
|
|
413
|
+
width: "100%",
|
|
414
|
+
height: "100%",
|
|
415
|
+
overflow: "hidden",
|
|
416
|
+
boxShadow: (theme) => theme.shadows[4],
|
|
417
|
+
}}
|
|
418
|
+
>
|
|
419
|
+
{content}
|
|
402
420
|
</Box>
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return (
|
|
425
|
+
<Drawer
|
|
426
|
+
anchor="right"
|
|
427
|
+
open={open}
|
|
428
|
+
onClose={onClose}
|
|
429
|
+
variant="persistent"
|
|
430
|
+
sx={{
|
|
431
|
+
width: open ? DRAWER_WIDTH : 0,
|
|
432
|
+
flexShrink: 0,
|
|
433
|
+
"& .MuiDrawer-paper": {
|
|
434
|
+
width: DRAWER_WIDTH,
|
|
435
|
+
boxSizing: "border-box",
|
|
436
|
+
border: "none",
|
|
437
|
+
boxShadow: (theme) => theme.shadows[8],
|
|
438
|
+
},
|
|
439
|
+
}}
|
|
440
|
+
>
|
|
441
|
+
{content}
|
|
403
442
|
</Drawer>
|
|
404
443
|
);
|
|
405
444
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import ChatDrawer from "./ChatDrawer";
|
|
2
|
+
import MessageSfx from "./messageSFX.mp3";
|
|
2
3
|
import SessionPopover from "./SessionPopover";
|
|
3
4
|
import SidebarSessionList from "./SidebarSessionList";
|
|
4
5
|
import { StoredSession } from "./types";
|
|
5
|
-
import { ToolDecision, ToolRenderers } from "../ChatMessage/ToolMessage";
|
|
6
6
|
import { useEvent } from "@nucleoidai/react-event";
|
|
7
7
|
import useSound from "use-sound";
|
|
8
8
|
|
|
9
|
-
import MessageSfx from "./messageSFX.mp3";
|
|
10
9
|
import React, { memo, useCallback, useEffect, useRef, useState } from "react";
|
|
10
|
+
import { ToolDecision, ToolRenderers } from "../ChatMessage/ToolMessage";
|
|
11
11
|
|
|
12
12
|
type Message = { id?: string; content: string; role: string };
|
|
13
13
|
|
|
@@ -34,6 +34,8 @@ interface SidebarChatProps {
|
|
|
34
34
|
clearAllSessions?: () => void;
|
|
35
35
|
toolRenderers?: ToolRenderers;
|
|
36
36
|
onToolDecision?: (toolCallId: string, decision: ToolDecision) => void;
|
|
37
|
+
embedded?: boolean;
|
|
38
|
+
footer?: React.ReactNode;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
const SidebarChat = ({
|
|
@@ -58,6 +60,8 @@ const SidebarChat = ({
|
|
|
58
60
|
clearAllSessions = () => {},
|
|
59
61
|
toolRenderers,
|
|
60
62
|
onToolDecision,
|
|
63
|
+
embedded,
|
|
64
|
+
footer,
|
|
61
65
|
}: SidebarChatProps) => {
|
|
62
66
|
const [aiResponded] = useEvent("AI_RESPONDED", null);
|
|
63
67
|
const [conversationSent] = useEvent("CONVERSATION_SENT", null);
|
|
@@ -169,7 +173,7 @@ const SidebarChat = ({
|
|
|
169
173
|
|
|
170
174
|
return (
|
|
171
175
|
<>
|
|
172
|
-
{!open && (
|
|
176
|
+
{!open && !embedded && (
|
|
173
177
|
<SidebarSessionList
|
|
174
178
|
sessions={storedSessions}
|
|
175
179
|
currentSessionId={currentSessionId}
|
|
@@ -183,17 +187,19 @@ const SidebarChat = ({
|
|
|
183
187
|
/>
|
|
184
188
|
)}
|
|
185
189
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
190
|
+
{!embedded && (
|
|
191
|
+
<SessionPopover
|
|
192
|
+
anchorEl={popoverAnchor}
|
|
193
|
+
onClose={() => setPopoverAnchor(null)}
|
|
194
|
+
onOpenFullChat={handleOpenFromPopover}
|
|
195
|
+
sessions={storedSessions}
|
|
196
|
+
activeSessionId={activeLogSessionId}
|
|
197
|
+
currentSessionId={currentSessionId}
|
|
198
|
+
selectedConversationId={selectedConversationId}
|
|
199
|
+
messagesEndRef={messagesEndRef}
|
|
200
|
+
highlightedMessage={highlightedMessage}
|
|
201
|
+
/>
|
|
202
|
+
)}
|
|
197
203
|
|
|
198
204
|
<ChatDrawer
|
|
199
205
|
title={title}
|
|
@@ -214,6 +220,8 @@ const SidebarChat = ({
|
|
|
214
220
|
onNewSession={onNewSession}
|
|
215
221
|
toolRenderers={toolRenderers}
|
|
216
222
|
onToolDecision={onToolDecision}
|
|
223
|
+
embedded={embedded}
|
|
224
|
+
footer={footer}
|
|
217
225
|
/>
|
|
218
226
|
</>
|
|
219
227
|
);
|