@yourgpt/copilot-sdk 0.1.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 +61 -0
- package/dist/chunk-2ZCWVAAK.cjs +1915 -0
- package/dist/chunk-2ZCWVAAK.cjs.map +1 -0
- package/dist/chunk-N4OA2J32.js +1844 -0
- package/dist/chunk-N4OA2J32.js.map +1 -0
- package/dist/chunk-QUGTRQSS.js +3100 -0
- package/dist/chunk-QUGTRQSS.js.map +1 -0
- package/dist/chunk-W6KQT7YZ.cjs +3152 -0
- package/dist/chunk-W6KQT7YZ.cjs.map +1 -0
- package/dist/core/index.cjs +288 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +870 -0
- package/dist/core/index.d.ts +870 -0
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -0
- package/dist/react/index.cjs +137 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +1824 -0
- package/dist/react/index.d.ts +1824 -0
- package/dist/react/index.js +4 -0
- package/dist/react/index.js.map +1 -0
- package/dist/styles.css +48 -0
- package/dist/thread-C2FjuGLb.d.cts +1225 -0
- package/dist/thread-C2FjuGLb.d.ts +1225 -0
- package/dist/ui/index.cjs +4116 -0
- package/dist/ui/index.cjs.map +1 -0
- package/dist/ui/index.d.cts +1143 -0
- package/dist/ui/index.d.ts +1143 -0
- package/dist/ui/index.js +4019 -0
- package/dist/ui/index.js.map +1 -0
- package/package.json +100 -0
package/dist/ui/index.js
ADDED
|
@@ -0,0 +1,4019 @@
|
|
|
1
|
+
import { useCopilot } from '../chunk-QUGTRQSS.js';
|
|
2
|
+
import '../chunk-N4OA2J32.js';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
6
|
+
import { marked } from 'marked';
|
|
7
|
+
import * as React8 from 'react';
|
|
8
|
+
import React8__default, { memo, createContext, useId, useMemo, useState, useEffect, useRef, useLayoutEffect, useCallback, useContext } from 'react';
|
|
9
|
+
import ReactMarkdown from 'react-markdown';
|
|
10
|
+
import remarkBreaks from 'remark-breaks';
|
|
11
|
+
import remarkGfm from 'remark-gfm';
|
|
12
|
+
import { codeToHtml } from 'shiki';
|
|
13
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
14
|
+
import { cva } from 'class-variance-authority';
|
|
15
|
+
import { useStickToBottomContext, StickToBottom as StickToBottom$1 } from 'use-stick-to-bottom';
|
|
16
|
+
import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
|
|
17
|
+
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
18
|
+
import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
|
|
19
|
+
|
|
20
|
+
function cn(...inputs) {
|
|
21
|
+
return twMerge(clsx(inputs));
|
|
22
|
+
}
|
|
23
|
+
function CircularLoader({
|
|
24
|
+
className,
|
|
25
|
+
size = "md"
|
|
26
|
+
}) {
|
|
27
|
+
const sizeClasses = {
|
|
28
|
+
sm: "size-4",
|
|
29
|
+
md: "size-5",
|
|
30
|
+
lg: "size-6"
|
|
31
|
+
};
|
|
32
|
+
return /* @__PURE__ */ jsx(
|
|
33
|
+
"div",
|
|
34
|
+
{
|
|
35
|
+
className: cn(
|
|
36
|
+
"border-primary animate-spin rounded-full border-2 border-t-transparent",
|
|
37
|
+
sizeClasses[size],
|
|
38
|
+
className
|
|
39
|
+
),
|
|
40
|
+
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
function ClassicLoader({
|
|
45
|
+
className,
|
|
46
|
+
size = "md"
|
|
47
|
+
}) {
|
|
48
|
+
const sizeClasses = {
|
|
49
|
+
sm: "size-4",
|
|
50
|
+
md: "size-5",
|
|
51
|
+
lg: "size-6"
|
|
52
|
+
};
|
|
53
|
+
const barSizes = {
|
|
54
|
+
sm: { height: "6px", width: "1.5px" },
|
|
55
|
+
md: { height: "8px", width: "2px" },
|
|
56
|
+
lg: { height: "10px", width: "2.5px" }
|
|
57
|
+
};
|
|
58
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative", sizeClasses[size], className), children: [
|
|
59
|
+
/* @__PURE__ */ jsx("div", { className: "absolute h-full w-full", children: [...Array(12)].map((_, i) => /* @__PURE__ */ jsx(
|
|
60
|
+
"div",
|
|
61
|
+
{
|
|
62
|
+
className: "bg-primary absolute animate-[spinner-fade_1.2s_linear_infinite] rounded-full",
|
|
63
|
+
style: {
|
|
64
|
+
top: "0",
|
|
65
|
+
left: "50%",
|
|
66
|
+
marginLeft: size === "sm" ? "-0.75px" : size === "lg" ? "-1.25px" : "-1px",
|
|
67
|
+
transformOrigin: `${size === "sm" ? "0.75px" : size === "lg" ? "1.25px" : "1px"} ${size === "sm" ? "10px" : size === "lg" ? "14px" : "12px"}`,
|
|
68
|
+
transform: `rotate(${i * 30}deg)`,
|
|
69
|
+
opacity: 0,
|
|
70
|
+
animationDelay: `${i * 0.1}s`,
|
|
71
|
+
height: barSizes[size].height,
|
|
72
|
+
width: barSizes[size].width
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
i
|
|
76
|
+
)) }),
|
|
77
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
78
|
+
] });
|
|
79
|
+
}
|
|
80
|
+
function PulseLoader({
|
|
81
|
+
className,
|
|
82
|
+
size = "md"
|
|
83
|
+
}) {
|
|
84
|
+
const sizeClasses = {
|
|
85
|
+
sm: "size-4",
|
|
86
|
+
md: "size-5",
|
|
87
|
+
lg: "size-6"
|
|
88
|
+
};
|
|
89
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative", sizeClasses[size], className), children: [
|
|
90
|
+
/* @__PURE__ */ jsx("div", { className: "border-primary absolute inset-0 animate-[thin-pulse_1.5s_ease-in-out_infinite] rounded-full border-2" }),
|
|
91
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
92
|
+
] });
|
|
93
|
+
}
|
|
94
|
+
function PulseDotLoader({
|
|
95
|
+
className,
|
|
96
|
+
size = "md"
|
|
97
|
+
}) {
|
|
98
|
+
const sizeClasses = {
|
|
99
|
+
sm: "size-1",
|
|
100
|
+
md: "size-2",
|
|
101
|
+
lg: "size-3"
|
|
102
|
+
};
|
|
103
|
+
return /* @__PURE__ */ jsx(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
className: cn(
|
|
107
|
+
"bg-primary animate-[pulse-dot_1.2s_ease-in-out_infinite] rounded-full",
|
|
108
|
+
sizeClasses[size],
|
|
109
|
+
className
|
|
110
|
+
),
|
|
111
|
+
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
function DotsLoader({
|
|
116
|
+
className,
|
|
117
|
+
size = "md"
|
|
118
|
+
}) {
|
|
119
|
+
const dotSizes = {
|
|
120
|
+
sm: "h-1.5 w-1.5",
|
|
121
|
+
md: "h-2 w-2",
|
|
122
|
+
lg: "h-2.5 w-2.5"
|
|
123
|
+
};
|
|
124
|
+
const containerSizes = {
|
|
125
|
+
sm: "h-4",
|
|
126
|
+
md: "h-5",
|
|
127
|
+
lg: "h-6"
|
|
128
|
+
};
|
|
129
|
+
return /* @__PURE__ */ jsxs(
|
|
130
|
+
"div",
|
|
131
|
+
{
|
|
132
|
+
className: cn(
|
|
133
|
+
"flex items-center space-x-1",
|
|
134
|
+
containerSizes[size],
|
|
135
|
+
className
|
|
136
|
+
),
|
|
137
|
+
children: [
|
|
138
|
+
[...Array(3)].map((_, i) => /* @__PURE__ */ jsx(
|
|
139
|
+
"div",
|
|
140
|
+
{
|
|
141
|
+
className: cn(
|
|
142
|
+
"bg-primary animate-[bounce-dots_1.4s_ease-in-out_infinite] rounded-full",
|
|
143
|
+
dotSizes[size]
|
|
144
|
+
),
|
|
145
|
+
style: {
|
|
146
|
+
animationDelay: `${i * 160}ms`
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
i
|
|
150
|
+
)),
|
|
151
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
function TypingLoader({
|
|
157
|
+
className,
|
|
158
|
+
size = "md"
|
|
159
|
+
}) {
|
|
160
|
+
const dotSizes = {
|
|
161
|
+
sm: "h-1 w-1",
|
|
162
|
+
md: "h-1.5 w-1.5",
|
|
163
|
+
lg: "h-2 w-2"
|
|
164
|
+
};
|
|
165
|
+
const containerSizes = {
|
|
166
|
+
sm: "h-4",
|
|
167
|
+
md: "h-5",
|
|
168
|
+
lg: "h-6"
|
|
169
|
+
};
|
|
170
|
+
return /* @__PURE__ */ jsxs(
|
|
171
|
+
"div",
|
|
172
|
+
{
|
|
173
|
+
className: cn(
|
|
174
|
+
"flex items-center space-x-1",
|
|
175
|
+
containerSizes[size],
|
|
176
|
+
className
|
|
177
|
+
),
|
|
178
|
+
children: [
|
|
179
|
+
[...Array(3)].map((_, i) => /* @__PURE__ */ jsx(
|
|
180
|
+
"div",
|
|
181
|
+
{
|
|
182
|
+
className: cn(
|
|
183
|
+
"bg-primary animate-[typing_1s_infinite] rounded-full",
|
|
184
|
+
dotSizes[size]
|
|
185
|
+
),
|
|
186
|
+
style: {
|
|
187
|
+
animationDelay: `${i * 250}ms`
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
i
|
|
191
|
+
)),
|
|
192
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
function WaveLoader({
|
|
198
|
+
className,
|
|
199
|
+
size = "md"
|
|
200
|
+
}) {
|
|
201
|
+
const barWidths = {
|
|
202
|
+
sm: "w-0.5",
|
|
203
|
+
md: "w-0.5",
|
|
204
|
+
lg: "w-1"
|
|
205
|
+
};
|
|
206
|
+
const containerSizes = {
|
|
207
|
+
sm: "h-4",
|
|
208
|
+
md: "h-5",
|
|
209
|
+
lg: "h-6"
|
|
210
|
+
};
|
|
211
|
+
const heights = {
|
|
212
|
+
sm: ["6px", "9px", "12px", "9px", "6px"],
|
|
213
|
+
md: ["8px", "12px", "16px", "12px", "8px"],
|
|
214
|
+
lg: ["10px", "15px", "20px", "15px", "10px"]
|
|
215
|
+
};
|
|
216
|
+
return /* @__PURE__ */ jsxs(
|
|
217
|
+
"div",
|
|
218
|
+
{
|
|
219
|
+
className: cn(
|
|
220
|
+
"flex items-center gap-0.5",
|
|
221
|
+
containerSizes[size],
|
|
222
|
+
className
|
|
223
|
+
),
|
|
224
|
+
children: [
|
|
225
|
+
[...Array(5)].map((_, i) => /* @__PURE__ */ jsx(
|
|
226
|
+
"div",
|
|
227
|
+
{
|
|
228
|
+
className: cn(
|
|
229
|
+
"bg-primary animate-[wave_1s_ease-in-out_infinite] rounded-full",
|
|
230
|
+
barWidths[size]
|
|
231
|
+
),
|
|
232
|
+
style: {
|
|
233
|
+
animationDelay: `${i * 100}ms`,
|
|
234
|
+
height: heights[size][i]
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
i
|
|
238
|
+
)),
|
|
239
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
240
|
+
]
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
function BarsLoader({
|
|
245
|
+
className,
|
|
246
|
+
size = "md"
|
|
247
|
+
}) {
|
|
248
|
+
const barWidths = {
|
|
249
|
+
sm: "w-1",
|
|
250
|
+
md: "w-1.5",
|
|
251
|
+
lg: "w-2"
|
|
252
|
+
};
|
|
253
|
+
const containerSizes = {
|
|
254
|
+
sm: "h-4 gap-1",
|
|
255
|
+
md: "h-5 gap-1.5",
|
|
256
|
+
lg: "h-6 gap-2"
|
|
257
|
+
};
|
|
258
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex", containerSizes[size], className), children: [
|
|
259
|
+
[...Array(3)].map((_, i) => /* @__PURE__ */ jsx(
|
|
260
|
+
"div",
|
|
261
|
+
{
|
|
262
|
+
className: cn(
|
|
263
|
+
"bg-primary h-full animate-[wave-bars_1.2s_ease-in-out_infinite]",
|
|
264
|
+
barWidths[size]
|
|
265
|
+
),
|
|
266
|
+
style: {
|
|
267
|
+
animationDelay: `${i * 0.2}s`
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
i
|
|
271
|
+
)),
|
|
272
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
273
|
+
] });
|
|
274
|
+
}
|
|
275
|
+
function TerminalLoader({
|
|
276
|
+
className,
|
|
277
|
+
size = "md"
|
|
278
|
+
}) {
|
|
279
|
+
const cursorSizes = {
|
|
280
|
+
sm: "h-3 w-1.5",
|
|
281
|
+
md: "h-4 w-2",
|
|
282
|
+
lg: "h-5 w-2.5"
|
|
283
|
+
};
|
|
284
|
+
const textSizes = {
|
|
285
|
+
sm: "text-xs",
|
|
286
|
+
md: "text-sm",
|
|
287
|
+
lg: "text-base"
|
|
288
|
+
};
|
|
289
|
+
const containerSizes = {
|
|
290
|
+
sm: "h-4",
|
|
291
|
+
md: "h-5",
|
|
292
|
+
lg: "h-6"
|
|
293
|
+
};
|
|
294
|
+
return /* @__PURE__ */ jsxs(
|
|
295
|
+
"div",
|
|
296
|
+
{
|
|
297
|
+
className: cn(
|
|
298
|
+
"flex items-center space-x-1",
|
|
299
|
+
containerSizes[size],
|
|
300
|
+
className
|
|
301
|
+
),
|
|
302
|
+
children: [
|
|
303
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-primary font-mono", textSizes[size]), children: ">" }),
|
|
304
|
+
/* @__PURE__ */ jsx(
|
|
305
|
+
"div",
|
|
306
|
+
{
|
|
307
|
+
className: cn(
|
|
308
|
+
"bg-primary animate-[blink_1s_step-end_infinite]",
|
|
309
|
+
cursorSizes[size]
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
),
|
|
313
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
314
|
+
]
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
function TextBlinkLoader({
|
|
319
|
+
text = "Thinking",
|
|
320
|
+
className,
|
|
321
|
+
size = "md"
|
|
322
|
+
}) {
|
|
323
|
+
const textSizes = {
|
|
324
|
+
sm: "text-xs",
|
|
325
|
+
md: "text-sm",
|
|
326
|
+
lg: "text-base"
|
|
327
|
+
};
|
|
328
|
+
return /* @__PURE__ */ jsx(
|
|
329
|
+
"div",
|
|
330
|
+
{
|
|
331
|
+
className: cn(
|
|
332
|
+
"animate-[text-blink_2s_ease-in-out_infinite] font-medium",
|
|
333
|
+
textSizes[size],
|
|
334
|
+
className
|
|
335
|
+
),
|
|
336
|
+
children: text
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
function TextShimmerLoader({
|
|
341
|
+
text = "Thinking",
|
|
342
|
+
className,
|
|
343
|
+
size = "md"
|
|
344
|
+
}) {
|
|
345
|
+
const textSizes = {
|
|
346
|
+
sm: "text-xs",
|
|
347
|
+
md: "text-sm",
|
|
348
|
+
lg: "text-base"
|
|
349
|
+
};
|
|
350
|
+
return /* @__PURE__ */ jsx(
|
|
351
|
+
"div",
|
|
352
|
+
{
|
|
353
|
+
className: cn(
|
|
354
|
+
"bg-[linear-gradient(to_right,var(--muted-foreground)_40%,var(--foreground)_60%,var(--muted-foreground)_80%)]",
|
|
355
|
+
"bg-size-[200%_auto] bg-clip-text font-medium text-transparent",
|
|
356
|
+
"animate-[shimmer_4s_infinite_linear]",
|
|
357
|
+
textSizes[size],
|
|
358
|
+
className
|
|
359
|
+
),
|
|
360
|
+
children: text
|
|
361
|
+
}
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
function TextDotsLoader({
|
|
365
|
+
className,
|
|
366
|
+
text = "Thinking",
|
|
367
|
+
size = "md"
|
|
368
|
+
}) {
|
|
369
|
+
const textSizes = {
|
|
370
|
+
sm: "text-xs",
|
|
371
|
+
md: "text-sm",
|
|
372
|
+
lg: "text-base"
|
|
373
|
+
};
|
|
374
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("inline-flex items-center", className), children: [
|
|
375
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-primary font-medium", textSizes[size]), children: text }),
|
|
376
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex", children: [
|
|
377
|
+
/* @__PURE__ */ jsx("span", { className: "text-primary animate-[loading-dots_1.4s_infinite_0.2s]", children: "." }),
|
|
378
|
+
/* @__PURE__ */ jsx("span", { className: "text-primary animate-[loading-dots_1.4s_infinite_0.4s]", children: "." }),
|
|
379
|
+
/* @__PURE__ */ jsx("span", { className: "text-primary animate-[loading-dots_1.4s_infinite_0.6s]", children: "." })
|
|
380
|
+
] })
|
|
381
|
+
] });
|
|
382
|
+
}
|
|
383
|
+
function Loader({
|
|
384
|
+
variant = "circular",
|
|
385
|
+
size = "md",
|
|
386
|
+
text,
|
|
387
|
+
className
|
|
388
|
+
}) {
|
|
389
|
+
switch (variant) {
|
|
390
|
+
case "circular":
|
|
391
|
+
return /* @__PURE__ */ jsx(CircularLoader, { size, className });
|
|
392
|
+
case "classic":
|
|
393
|
+
return /* @__PURE__ */ jsx(ClassicLoader, { size, className });
|
|
394
|
+
case "pulse":
|
|
395
|
+
return /* @__PURE__ */ jsx(PulseLoader, { size, className });
|
|
396
|
+
case "pulse-dot":
|
|
397
|
+
return /* @__PURE__ */ jsx(PulseDotLoader, { size, className });
|
|
398
|
+
case "dots":
|
|
399
|
+
return /* @__PURE__ */ jsx(DotsLoader, { size, className });
|
|
400
|
+
case "typing":
|
|
401
|
+
return /* @__PURE__ */ jsx(TypingLoader, { size, className });
|
|
402
|
+
case "wave":
|
|
403
|
+
return /* @__PURE__ */ jsx(WaveLoader, { size, className });
|
|
404
|
+
case "bars":
|
|
405
|
+
return /* @__PURE__ */ jsx(BarsLoader, { size, className });
|
|
406
|
+
case "terminal":
|
|
407
|
+
return /* @__PURE__ */ jsx(TerminalLoader, { size, className });
|
|
408
|
+
case "text-blink":
|
|
409
|
+
return /* @__PURE__ */ jsx(TextBlinkLoader, { text, size, className });
|
|
410
|
+
case "text-shimmer":
|
|
411
|
+
return /* @__PURE__ */ jsx(TextShimmerLoader, { text, size, className });
|
|
412
|
+
case "loading-dots":
|
|
413
|
+
return /* @__PURE__ */ jsx(TextDotsLoader, { text, size, className });
|
|
414
|
+
default:
|
|
415
|
+
return /* @__PURE__ */ jsx(CircularLoader, { size, className });
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function CodeBlock({ children, className, ...props }) {
|
|
419
|
+
return /* @__PURE__ */ jsx(
|
|
420
|
+
"div",
|
|
421
|
+
{
|
|
422
|
+
className: cn(
|
|
423
|
+
"not-prose flex w-full flex-col overflow-clip border",
|
|
424
|
+
"border-border bg-card text-card-foreground rounded-xl",
|
|
425
|
+
className
|
|
426
|
+
),
|
|
427
|
+
...props,
|
|
428
|
+
children
|
|
429
|
+
}
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
function CodeBlockCode({
|
|
433
|
+
code,
|
|
434
|
+
language = "tsx",
|
|
435
|
+
theme = "github-light",
|
|
436
|
+
className,
|
|
437
|
+
...props
|
|
438
|
+
}) {
|
|
439
|
+
const [highlightedHtml, setHighlightedHtml] = useState(null);
|
|
440
|
+
useEffect(() => {
|
|
441
|
+
async function highlight() {
|
|
442
|
+
if (!code) {
|
|
443
|
+
setHighlightedHtml("<pre><code></code></pre>");
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const html = await codeToHtml(code, { lang: language, theme });
|
|
447
|
+
setHighlightedHtml(html);
|
|
448
|
+
}
|
|
449
|
+
highlight();
|
|
450
|
+
}, [code, language, theme]);
|
|
451
|
+
const classNames = cn(
|
|
452
|
+
"w-full overflow-x-auto text-[13px] [&>pre]:px-4 [&>pre]:py-4",
|
|
453
|
+
className
|
|
454
|
+
);
|
|
455
|
+
return highlightedHtml ? /* @__PURE__ */ jsx(
|
|
456
|
+
"div",
|
|
457
|
+
{
|
|
458
|
+
className: classNames,
|
|
459
|
+
dangerouslySetInnerHTML: { __html: highlightedHtml },
|
|
460
|
+
...props
|
|
461
|
+
}
|
|
462
|
+
) : /* @__PURE__ */ jsx("div", { className: classNames, ...props, children: /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: code }) }) });
|
|
463
|
+
}
|
|
464
|
+
function parseMarkdownIntoBlocks(markdown) {
|
|
465
|
+
const tokens = marked.lexer(markdown);
|
|
466
|
+
return tokens.map((token) => token.raw);
|
|
467
|
+
}
|
|
468
|
+
function extractLanguage(className) {
|
|
469
|
+
if (!className) return "plaintext";
|
|
470
|
+
const match = className.match(/language-(\w+)/);
|
|
471
|
+
return match ? match[1] : "plaintext";
|
|
472
|
+
}
|
|
473
|
+
var INITIAL_COMPONENTS = {
|
|
474
|
+
code: function CodeComponent({ className, children, ...props }) {
|
|
475
|
+
const isInline = !props.node?.position?.start.line || props.node?.position?.start.line === props.node?.position?.end.line;
|
|
476
|
+
if (isInline) {
|
|
477
|
+
return /* @__PURE__ */ jsx(
|
|
478
|
+
"span",
|
|
479
|
+
{
|
|
480
|
+
className: cn(
|
|
481
|
+
"bg-primary-foreground rounded-sm px-1 font-mono text-sm",
|
|
482
|
+
className
|
|
483
|
+
),
|
|
484
|
+
...props,
|
|
485
|
+
children
|
|
486
|
+
}
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
const language = extractLanguage(className);
|
|
490
|
+
return /* @__PURE__ */ jsx(CodeBlock, { className, children: /* @__PURE__ */ jsx(CodeBlockCode, { code: children, language }) });
|
|
491
|
+
},
|
|
492
|
+
pre: function PreComponent({ children }) {
|
|
493
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
var MemoizedMarkdownBlock = memo(
|
|
497
|
+
function MarkdownBlock({
|
|
498
|
+
content,
|
|
499
|
+
components = INITIAL_COMPONENTS
|
|
500
|
+
}) {
|
|
501
|
+
return /* @__PURE__ */ jsx(
|
|
502
|
+
ReactMarkdown,
|
|
503
|
+
{
|
|
504
|
+
remarkPlugins: [remarkGfm, remarkBreaks],
|
|
505
|
+
components,
|
|
506
|
+
children: content
|
|
507
|
+
}
|
|
508
|
+
);
|
|
509
|
+
},
|
|
510
|
+
function propsAreEqual(prevProps, nextProps) {
|
|
511
|
+
return prevProps.content === nextProps.content;
|
|
512
|
+
}
|
|
513
|
+
);
|
|
514
|
+
MemoizedMarkdownBlock.displayName = "MemoizedMarkdownBlock";
|
|
515
|
+
function MarkdownComponent({
|
|
516
|
+
children,
|
|
517
|
+
id,
|
|
518
|
+
className,
|
|
519
|
+
components = INITIAL_COMPONENTS
|
|
520
|
+
}) {
|
|
521
|
+
const generatedId = useId();
|
|
522
|
+
const blockId = id ?? generatedId;
|
|
523
|
+
const blocks = useMemo(() => parseMarkdownIntoBlocks(children), [children]);
|
|
524
|
+
return /* @__PURE__ */ jsx("div", { className, children: blocks.map((block, index) => /* @__PURE__ */ jsx(
|
|
525
|
+
MemoizedMarkdownBlock,
|
|
526
|
+
{
|
|
527
|
+
content: block,
|
|
528
|
+
components
|
|
529
|
+
},
|
|
530
|
+
`${blockId}-block-${index}`
|
|
531
|
+
)) });
|
|
532
|
+
}
|
|
533
|
+
var Markdown = memo(MarkdownComponent);
|
|
534
|
+
Markdown.displayName = "Markdown";
|
|
535
|
+
var buttonVariants = cva(
|
|
536
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
537
|
+
{
|
|
538
|
+
variants: {
|
|
539
|
+
variant: {
|
|
540
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
541
|
+
destructive: "bg-destructive text-white shadow-sm hover:bg-destructive/90",
|
|
542
|
+
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
543
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
544
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
545
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
546
|
+
},
|
|
547
|
+
size: {
|
|
548
|
+
default: "h-9 px-4 py-2",
|
|
549
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
550
|
+
lg: "h-10 rounded-md px-8",
|
|
551
|
+
icon: "h-9 w-9"
|
|
552
|
+
}
|
|
553
|
+
},
|
|
554
|
+
defaultVariants: {
|
|
555
|
+
variant: "default",
|
|
556
|
+
size: "default"
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
);
|
|
560
|
+
var Button = React8.forwardRef(
|
|
561
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
562
|
+
const Comp = asChild ? Slot : "button";
|
|
563
|
+
return /* @__PURE__ */ jsx(
|
|
564
|
+
Comp,
|
|
565
|
+
{
|
|
566
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
567
|
+
ref,
|
|
568
|
+
...props
|
|
569
|
+
}
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
);
|
|
573
|
+
Button.displayName = "Button";
|
|
574
|
+
function ThumbsUpIcon({ className }) {
|
|
575
|
+
return /* @__PURE__ */ jsxs(
|
|
576
|
+
"svg",
|
|
577
|
+
{
|
|
578
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
579
|
+
viewBox: "0 0 24 24",
|
|
580
|
+
fill: "none",
|
|
581
|
+
stroke: "currentColor",
|
|
582
|
+
strokeWidth: "2",
|
|
583
|
+
strokeLinecap: "round",
|
|
584
|
+
strokeLinejoin: "round",
|
|
585
|
+
className,
|
|
586
|
+
children: [
|
|
587
|
+
/* @__PURE__ */ jsx("path", { d: "M7 10v12" }),
|
|
588
|
+
/* @__PURE__ */ jsx("path", { d: "M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z" })
|
|
589
|
+
]
|
|
590
|
+
}
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
function ThumbsDownIcon({ className }) {
|
|
594
|
+
return /* @__PURE__ */ jsxs(
|
|
595
|
+
"svg",
|
|
596
|
+
{
|
|
597
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
598
|
+
viewBox: "0 0 24 24",
|
|
599
|
+
fill: "none",
|
|
600
|
+
stroke: "currentColor",
|
|
601
|
+
strokeWidth: "2",
|
|
602
|
+
strokeLinecap: "round",
|
|
603
|
+
strokeLinejoin: "round",
|
|
604
|
+
className,
|
|
605
|
+
children: [
|
|
606
|
+
/* @__PURE__ */ jsx("path", { d: "M17 14V2" }),
|
|
607
|
+
/* @__PURE__ */ jsx("path", { d: "M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z" })
|
|
608
|
+
]
|
|
609
|
+
}
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
function XIcon({ className }) {
|
|
613
|
+
return /* @__PURE__ */ jsxs(
|
|
614
|
+
"svg",
|
|
615
|
+
{
|
|
616
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
617
|
+
viewBox: "0 0 24 24",
|
|
618
|
+
fill: "none",
|
|
619
|
+
stroke: "currentColor",
|
|
620
|
+
strokeWidth: "2",
|
|
621
|
+
strokeLinecap: "round",
|
|
622
|
+
strokeLinejoin: "round",
|
|
623
|
+
className,
|
|
624
|
+
children: [
|
|
625
|
+
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
626
|
+
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
627
|
+
]
|
|
628
|
+
}
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
function FeedbackBar({
|
|
632
|
+
className,
|
|
633
|
+
title,
|
|
634
|
+
icon,
|
|
635
|
+
onHelpful,
|
|
636
|
+
onNotHelpful,
|
|
637
|
+
onClose
|
|
638
|
+
}) {
|
|
639
|
+
return /* @__PURE__ */ jsx(
|
|
640
|
+
"div",
|
|
641
|
+
{
|
|
642
|
+
className: cn(
|
|
643
|
+
"bg-background border-border inline-flex rounded-[12px] border text-sm",
|
|
644
|
+
className
|
|
645
|
+
),
|
|
646
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center justify-between", children: [
|
|
647
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 items-center justify-start gap-4 py-3 pl-4", children: [
|
|
648
|
+
icon,
|
|
649
|
+
/* @__PURE__ */ jsx("span", { className: "text-foreground font-medium", children: title })
|
|
650
|
+
] }),
|
|
651
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-0.5 px-3 py-0", children: [
|
|
652
|
+
/* @__PURE__ */ jsx(
|
|
653
|
+
"button",
|
|
654
|
+
{
|
|
655
|
+
type: "button",
|
|
656
|
+
className: "text-muted-foreground hover:text-foreground flex size-8 items-center justify-center rounded-md transition-colors",
|
|
657
|
+
"aria-label": "Helpful",
|
|
658
|
+
onClick: onHelpful,
|
|
659
|
+
children: /* @__PURE__ */ jsx(ThumbsUpIcon, { className: "size-4" })
|
|
660
|
+
}
|
|
661
|
+
),
|
|
662
|
+
/* @__PURE__ */ jsx(
|
|
663
|
+
"button",
|
|
664
|
+
{
|
|
665
|
+
type: "button",
|
|
666
|
+
className: "text-muted-foreground hover:text-foreground flex size-8 items-center justify-center rounded-md transition-colors",
|
|
667
|
+
"aria-label": "Not helpful",
|
|
668
|
+
onClick: onNotHelpful,
|
|
669
|
+
children: /* @__PURE__ */ jsx(ThumbsDownIcon, { className: "size-4" })
|
|
670
|
+
}
|
|
671
|
+
)
|
|
672
|
+
] }),
|
|
673
|
+
/* @__PURE__ */ jsx("div", { className: "border-border flex items-center justify-center border-l", children: /* @__PURE__ */ jsx(
|
|
674
|
+
"button",
|
|
675
|
+
{
|
|
676
|
+
type: "button",
|
|
677
|
+
onClick: onClose,
|
|
678
|
+
className: "text-muted-foreground hover:text-foreground flex items-center justify-center rounded-md p-3",
|
|
679
|
+
"aria-label": "Close",
|
|
680
|
+
children: /* @__PURE__ */ jsx(XIcon, { className: "size-5" })
|
|
681
|
+
}
|
|
682
|
+
) })
|
|
683
|
+
] })
|
|
684
|
+
}
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
var StickToBottom = StickToBottom$1;
|
|
688
|
+
function useChatContainer() {
|
|
689
|
+
const context = useStickToBottomContext();
|
|
690
|
+
return {
|
|
691
|
+
isAtBottom: context.isAtBottom,
|
|
692
|
+
scrollToBottom: context.scrollToBottom
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
function ChatContainerRoot({
|
|
696
|
+
children,
|
|
697
|
+
className,
|
|
698
|
+
...props
|
|
699
|
+
}) {
|
|
700
|
+
return /* @__PURE__ */ jsx(
|
|
701
|
+
StickToBottom,
|
|
702
|
+
{
|
|
703
|
+
className: cn("flex overflow-y-auto", className),
|
|
704
|
+
resize: "smooth",
|
|
705
|
+
initial: "instant",
|
|
706
|
+
role: "log",
|
|
707
|
+
...props,
|
|
708
|
+
children
|
|
709
|
+
}
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
function ChatContainerContent({
|
|
713
|
+
children,
|
|
714
|
+
className,
|
|
715
|
+
...props
|
|
716
|
+
}) {
|
|
717
|
+
return /* @__PURE__ */ jsx(
|
|
718
|
+
StickToBottom.Content,
|
|
719
|
+
{
|
|
720
|
+
className: cn("flex w-full flex-col", className),
|
|
721
|
+
...props,
|
|
722
|
+
children
|
|
723
|
+
}
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
function ChatContainerScrollAnchor({
|
|
727
|
+
className,
|
|
728
|
+
...props
|
|
729
|
+
}) {
|
|
730
|
+
return /* @__PURE__ */ jsx(
|
|
731
|
+
"div",
|
|
732
|
+
{
|
|
733
|
+
className: cn("h-px w-full shrink-0 scroll-mt-4", className),
|
|
734
|
+
"aria-hidden": "true",
|
|
735
|
+
...props
|
|
736
|
+
}
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
function ChevronDownIcon({ className }) {
|
|
740
|
+
return /* @__PURE__ */ jsx(
|
|
741
|
+
"svg",
|
|
742
|
+
{
|
|
743
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
744
|
+
viewBox: "0 0 24 24",
|
|
745
|
+
fill: "none",
|
|
746
|
+
stroke: "currentColor",
|
|
747
|
+
strokeWidth: "2",
|
|
748
|
+
strokeLinecap: "round",
|
|
749
|
+
strokeLinejoin: "round",
|
|
750
|
+
className,
|
|
751
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
752
|
+
}
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
function ScrollButton({
|
|
756
|
+
className,
|
|
757
|
+
variant = "outline",
|
|
758
|
+
size = "sm",
|
|
759
|
+
...props
|
|
760
|
+
}) {
|
|
761
|
+
const { isAtBottom, scrollToBottom } = useChatContainer();
|
|
762
|
+
return /* @__PURE__ */ jsx(
|
|
763
|
+
Button,
|
|
764
|
+
{
|
|
765
|
+
variant,
|
|
766
|
+
size,
|
|
767
|
+
className: cn(
|
|
768
|
+
"h-10 w-10 rounded-full transition-all duration-150 ease-out",
|
|
769
|
+
!isAtBottom ? "translate-y-0 scale-100 opacity-100" : "pointer-events-none translate-y-4 scale-95 opacity-0",
|
|
770
|
+
className
|
|
771
|
+
),
|
|
772
|
+
onClick: () => scrollToBottom(),
|
|
773
|
+
...props,
|
|
774
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-5 w-5" })
|
|
775
|
+
}
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
function TooltipProvider({
|
|
779
|
+
children,
|
|
780
|
+
delayDuration = 300
|
|
781
|
+
}) {
|
|
782
|
+
return /* @__PURE__ */ jsx(Tooltip$1.Provider, { delay: delayDuration, children });
|
|
783
|
+
}
|
|
784
|
+
function Tooltip({ children, open, defaultOpen, onOpenChange }) {
|
|
785
|
+
return /* @__PURE__ */ jsx(
|
|
786
|
+
Tooltip$1.Root,
|
|
787
|
+
{
|
|
788
|
+
open,
|
|
789
|
+
defaultOpen,
|
|
790
|
+
onOpenChange,
|
|
791
|
+
children
|
|
792
|
+
}
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
function TooltipTrigger({
|
|
796
|
+
children,
|
|
797
|
+
asChild,
|
|
798
|
+
disabled,
|
|
799
|
+
...props
|
|
800
|
+
}) {
|
|
801
|
+
if (asChild && React8__default.isValidElement(children)) {
|
|
802
|
+
return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { disabled, render: children, ...props });
|
|
803
|
+
}
|
|
804
|
+
return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { disabled, ...props, children });
|
|
805
|
+
}
|
|
806
|
+
function TooltipContent({
|
|
807
|
+
children,
|
|
808
|
+
className,
|
|
809
|
+
side = "top",
|
|
810
|
+
align = "center",
|
|
811
|
+
sideOffset = 8,
|
|
812
|
+
showArrow = true
|
|
813
|
+
}) {
|
|
814
|
+
return /* @__PURE__ */ jsx(Tooltip$1.Portal, { children: /* @__PURE__ */ jsx(Tooltip$1.Positioner, { side, align, sideOffset, children: /* @__PURE__ */ jsxs(
|
|
815
|
+
Tooltip$1.Popup,
|
|
816
|
+
{
|
|
817
|
+
className: cn(
|
|
818
|
+
"z-50 rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground shadow-md",
|
|
819
|
+
"animate-in fade-in-0 zoom-in-95",
|
|
820
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
821
|
+
className
|
|
822
|
+
),
|
|
823
|
+
children: [
|
|
824
|
+
children,
|
|
825
|
+
showArrow && /* @__PURE__ */ jsx(Tooltip$1.Arrow, { className: "fill-primary" })
|
|
826
|
+
]
|
|
827
|
+
}
|
|
828
|
+
) }) });
|
|
829
|
+
}
|
|
830
|
+
var Avatar = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
831
|
+
AvatarPrimitive.Root,
|
|
832
|
+
{
|
|
833
|
+
ref,
|
|
834
|
+
className: cn(
|
|
835
|
+
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|
|
836
|
+
className
|
|
837
|
+
),
|
|
838
|
+
...props
|
|
839
|
+
}
|
|
840
|
+
));
|
|
841
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
842
|
+
var AvatarImage = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
843
|
+
AvatarPrimitive.Image,
|
|
844
|
+
{
|
|
845
|
+
ref,
|
|
846
|
+
className: cn("aspect-square h-full w-full", className),
|
|
847
|
+
...props
|
|
848
|
+
}
|
|
849
|
+
));
|
|
850
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
851
|
+
var AvatarFallback = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
852
|
+
AvatarPrimitive.Fallback,
|
|
853
|
+
{
|
|
854
|
+
ref,
|
|
855
|
+
className: cn(
|
|
856
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
|
857
|
+
className
|
|
858
|
+
),
|
|
859
|
+
...props
|
|
860
|
+
}
|
|
861
|
+
));
|
|
862
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
863
|
+
var Message = ({ children, className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex gap-3", className), ...props, children });
|
|
864
|
+
var MessageAvatar = ({
|
|
865
|
+
src,
|
|
866
|
+
alt,
|
|
867
|
+
fallback,
|
|
868
|
+
delayMs,
|
|
869
|
+
className
|
|
870
|
+
}) => {
|
|
871
|
+
return /* @__PURE__ */ jsxs(Avatar, { className: cn("size-7 shrink-0", className), children: [
|
|
872
|
+
/* @__PURE__ */ jsx(AvatarImage, { src, alt }),
|
|
873
|
+
fallback && /* @__PURE__ */ jsx(AvatarFallback, { delayMs, children: fallback })
|
|
874
|
+
] });
|
|
875
|
+
};
|
|
876
|
+
var proseSizeMap = {
|
|
877
|
+
sm: "prose-sm",
|
|
878
|
+
base: "prose-base",
|
|
879
|
+
lg: "prose-lg"
|
|
880
|
+
};
|
|
881
|
+
var MessageContent = ({
|
|
882
|
+
children,
|
|
883
|
+
markdown = false,
|
|
884
|
+
className,
|
|
885
|
+
size = "sm",
|
|
886
|
+
...props
|
|
887
|
+
}) => {
|
|
888
|
+
const classNames = cn(
|
|
889
|
+
"rounded-lg p-2 bg-secondary prose break-words whitespace-normal max-w-none",
|
|
890
|
+
"text-foreground prose-headings:text-foreground prose-p:text-foreground prose-strong:text-foreground prose-li:text-foreground prose-a:text-foreground prose-ol:text-foreground prose-ul:text-foreground prose-code:text-foreground",
|
|
891
|
+
proseSizeMap[size],
|
|
892
|
+
className
|
|
893
|
+
);
|
|
894
|
+
return markdown ? /* @__PURE__ */ jsx(Markdown, { className: classNames, ...props, children }) : /* @__PURE__ */ jsx("div", { className: classNames, ...props, children });
|
|
895
|
+
};
|
|
896
|
+
var Textarea = React8.forwardRef(({ className, ...props }, ref) => {
|
|
897
|
+
return /* @__PURE__ */ jsx(
|
|
898
|
+
"textarea",
|
|
899
|
+
{
|
|
900
|
+
className: cn(
|
|
901
|
+
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
902
|
+
className
|
|
903
|
+
),
|
|
904
|
+
ref,
|
|
905
|
+
...props
|
|
906
|
+
}
|
|
907
|
+
);
|
|
908
|
+
});
|
|
909
|
+
Textarea.displayName = "Textarea";
|
|
910
|
+
var PromptInputContext = createContext({
|
|
911
|
+
isLoading: false,
|
|
912
|
+
value: "",
|
|
913
|
+
setValue: () => {
|
|
914
|
+
},
|
|
915
|
+
maxHeight: 240,
|
|
916
|
+
onSubmit: void 0,
|
|
917
|
+
disabled: false,
|
|
918
|
+
textareaRef: { current: null }
|
|
919
|
+
});
|
|
920
|
+
function usePromptInput() {
|
|
921
|
+
return useContext(PromptInputContext);
|
|
922
|
+
}
|
|
923
|
+
function PromptInput({
|
|
924
|
+
className,
|
|
925
|
+
isLoading = false,
|
|
926
|
+
maxHeight = 240,
|
|
927
|
+
value,
|
|
928
|
+
onValueChange,
|
|
929
|
+
onSubmit,
|
|
930
|
+
children,
|
|
931
|
+
disabled = false,
|
|
932
|
+
onClick,
|
|
933
|
+
...props
|
|
934
|
+
}) {
|
|
935
|
+
const [internalValue, setInternalValue] = useState(value || "");
|
|
936
|
+
const textareaRef = useRef(null);
|
|
937
|
+
const handleChange = (newValue) => {
|
|
938
|
+
setInternalValue(newValue);
|
|
939
|
+
onValueChange?.(newValue);
|
|
940
|
+
};
|
|
941
|
+
const handleClick = (e) => {
|
|
942
|
+
if (!disabled) textareaRef.current?.focus();
|
|
943
|
+
onClick?.(e);
|
|
944
|
+
};
|
|
945
|
+
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(
|
|
946
|
+
PromptInputContext.Provider,
|
|
947
|
+
{
|
|
948
|
+
value: {
|
|
949
|
+
isLoading,
|
|
950
|
+
value: value ?? internalValue,
|
|
951
|
+
setValue: onValueChange ?? handleChange,
|
|
952
|
+
maxHeight,
|
|
953
|
+
onSubmit,
|
|
954
|
+
disabled,
|
|
955
|
+
textareaRef
|
|
956
|
+
},
|
|
957
|
+
children: /* @__PURE__ */ jsx(
|
|
958
|
+
"div",
|
|
959
|
+
{
|
|
960
|
+
onClick: handleClick,
|
|
961
|
+
className: cn(
|
|
962
|
+
"border-input bg-background cursor-text rounded-3xl border p-2 shadow-xs",
|
|
963
|
+
disabled && "cursor-not-allowed opacity-60",
|
|
964
|
+
className
|
|
965
|
+
),
|
|
966
|
+
...props,
|
|
967
|
+
children
|
|
968
|
+
}
|
|
969
|
+
)
|
|
970
|
+
}
|
|
971
|
+
) });
|
|
972
|
+
}
|
|
973
|
+
function PromptInputTextarea({
|
|
974
|
+
className,
|
|
975
|
+
onKeyDown,
|
|
976
|
+
disableAutosize = false,
|
|
977
|
+
...props
|
|
978
|
+
}) {
|
|
979
|
+
const { value, setValue, maxHeight, onSubmit, disabled, textareaRef } = usePromptInput();
|
|
980
|
+
const adjustHeight = (el) => {
|
|
981
|
+
if (!el || disableAutosize) return;
|
|
982
|
+
el.style.height = "auto";
|
|
983
|
+
if (typeof maxHeight === "number") {
|
|
984
|
+
el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;
|
|
985
|
+
} else {
|
|
986
|
+
el.style.height = `min(${el.scrollHeight}px, ${maxHeight})`;
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
const handleRef = (el) => {
|
|
990
|
+
textareaRef.current = el;
|
|
991
|
+
adjustHeight(el);
|
|
992
|
+
};
|
|
993
|
+
useLayoutEffect(() => {
|
|
994
|
+
if (!textareaRef.current || disableAutosize) return;
|
|
995
|
+
const el = textareaRef.current;
|
|
996
|
+
el.style.height = "auto";
|
|
997
|
+
if (typeof maxHeight === "number") {
|
|
998
|
+
el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;
|
|
999
|
+
} else {
|
|
1000
|
+
el.style.height = `min(${el.scrollHeight}px, ${maxHeight})`;
|
|
1001
|
+
}
|
|
1002
|
+
}, [value, maxHeight, disableAutosize]);
|
|
1003
|
+
const handleChange = (e) => {
|
|
1004
|
+
adjustHeight(e.target);
|
|
1005
|
+
setValue(e.target.value);
|
|
1006
|
+
};
|
|
1007
|
+
const handleKeyDown = (e) => {
|
|
1008
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
1009
|
+
e.preventDefault();
|
|
1010
|
+
onSubmit?.();
|
|
1011
|
+
}
|
|
1012
|
+
onKeyDown?.(e);
|
|
1013
|
+
};
|
|
1014
|
+
return /* @__PURE__ */ jsx(
|
|
1015
|
+
Textarea,
|
|
1016
|
+
{
|
|
1017
|
+
ref: handleRef,
|
|
1018
|
+
value,
|
|
1019
|
+
onChange: handleChange,
|
|
1020
|
+
onKeyDown: handleKeyDown,
|
|
1021
|
+
className: cn(
|
|
1022
|
+
"text-foreground min-h-[44px] w-full resize-none border-none bg-transparent shadow-none outline-none focus-visible:ring-0 focus-visible:ring-offset-0",
|
|
1023
|
+
className
|
|
1024
|
+
),
|
|
1025
|
+
rows: 1,
|
|
1026
|
+
disabled,
|
|
1027
|
+
...props
|
|
1028
|
+
}
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
function PromptInputActions({
|
|
1032
|
+
children,
|
|
1033
|
+
className,
|
|
1034
|
+
...props
|
|
1035
|
+
}) {
|
|
1036
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2", className), ...props, children });
|
|
1037
|
+
}
|
|
1038
|
+
function PromptInputAction({
|
|
1039
|
+
tooltip,
|
|
1040
|
+
children,
|
|
1041
|
+
className,
|
|
1042
|
+
side = "top"
|
|
1043
|
+
}) {
|
|
1044
|
+
const { disabled } = usePromptInput();
|
|
1045
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
1046
|
+
/* @__PURE__ */ jsx(
|
|
1047
|
+
TooltipTrigger,
|
|
1048
|
+
{
|
|
1049
|
+
asChild: true,
|
|
1050
|
+
disabled,
|
|
1051
|
+
onClick: (e) => e.stopPropagation(),
|
|
1052
|
+
children
|
|
1053
|
+
}
|
|
1054
|
+
),
|
|
1055
|
+
/* @__PURE__ */ jsx(TooltipContent, { side, className, showArrow: true, children: tooltip })
|
|
1056
|
+
] });
|
|
1057
|
+
}
|
|
1058
|
+
var HoverCard = HoverCardPrimitive.Root;
|
|
1059
|
+
var HoverCardTrigger = HoverCardPrimitive.Trigger;
|
|
1060
|
+
var HoverCardContent = React8.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1061
|
+
HoverCardPrimitive.Content,
|
|
1062
|
+
{
|
|
1063
|
+
ref,
|
|
1064
|
+
align,
|
|
1065
|
+
sideOffset,
|
|
1066
|
+
className: cn(
|
|
1067
|
+
"z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
|
|
1068
|
+
className
|
|
1069
|
+
),
|
|
1070
|
+
...props
|
|
1071
|
+
}
|
|
1072
|
+
));
|
|
1073
|
+
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
|
|
1074
|
+
var SourceContext = createContext(null);
|
|
1075
|
+
function useSourceContext() {
|
|
1076
|
+
const ctx = useContext(SourceContext);
|
|
1077
|
+
if (!ctx) throw new Error("Source.* must be used inside <Source>");
|
|
1078
|
+
return ctx;
|
|
1079
|
+
}
|
|
1080
|
+
function Source({ href, children }) {
|
|
1081
|
+
let domain = "";
|
|
1082
|
+
try {
|
|
1083
|
+
domain = new URL(href).hostname;
|
|
1084
|
+
} catch {
|
|
1085
|
+
domain = href.split("/").pop() || href;
|
|
1086
|
+
}
|
|
1087
|
+
return /* @__PURE__ */ jsx(SourceContext.Provider, { value: { href, domain }, children: /* @__PURE__ */ jsx(HoverCard, { openDelay: 150, closeDelay: 0, children }) });
|
|
1088
|
+
}
|
|
1089
|
+
function SourceTrigger({
|
|
1090
|
+
label,
|
|
1091
|
+
showFavicon = false,
|
|
1092
|
+
className
|
|
1093
|
+
}) {
|
|
1094
|
+
const { href, domain } = useSourceContext();
|
|
1095
|
+
const labelToShow = label ?? domain.replace("www.", "");
|
|
1096
|
+
return /* @__PURE__ */ jsx(HoverCardTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1097
|
+
"a",
|
|
1098
|
+
{
|
|
1099
|
+
href,
|
|
1100
|
+
target: "_blank",
|
|
1101
|
+
rel: "noopener noreferrer",
|
|
1102
|
+
className: cn(
|
|
1103
|
+
"bg-muted text-muted-foreground hover:bg-muted-foreground/30 hover:text-primary inline-flex h-5 max-w-32 items-center gap-1 overflow-hidden rounded-full py-0 text-xs no-underline transition-colors duration-150",
|
|
1104
|
+
showFavicon ? "pr-2 pl-1" : "px-1",
|
|
1105
|
+
className
|
|
1106
|
+
),
|
|
1107
|
+
children: [
|
|
1108
|
+
showFavicon && /* @__PURE__ */ jsx(
|
|
1109
|
+
"img",
|
|
1110
|
+
{
|
|
1111
|
+
src: `https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(
|
|
1112
|
+
href
|
|
1113
|
+
)}`,
|
|
1114
|
+
alt: "favicon",
|
|
1115
|
+
width: 14,
|
|
1116
|
+
height: 14,
|
|
1117
|
+
className: "size-3.5 rounded-full"
|
|
1118
|
+
}
|
|
1119
|
+
),
|
|
1120
|
+
/* @__PURE__ */ jsx("span", { className: "truncate tabular-nums text-center font-normal", children: labelToShow })
|
|
1121
|
+
]
|
|
1122
|
+
}
|
|
1123
|
+
) });
|
|
1124
|
+
}
|
|
1125
|
+
function SourceContent({
|
|
1126
|
+
title,
|
|
1127
|
+
description,
|
|
1128
|
+
className
|
|
1129
|
+
}) {
|
|
1130
|
+
const { href, domain } = useSourceContext();
|
|
1131
|
+
return /* @__PURE__ */ jsx(HoverCardContent, { className: cn("w-80 p-0 shadow-xs", className), children: /* @__PURE__ */ jsxs(
|
|
1132
|
+
"a",
|
|
1133
|
+
{
|
|
1134
|
+
href,
|
|
1135
|
+
target: "_blank",
|
|
1136
|
+
rel: "noopener noreferrer",
|
|
1137
|
+
className: "flex flex-col gap-2 p-3",
|
|
1138
|
+
children: [
|
|
1139
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
1140
|
+
/* @__PURE__ */ jsx(
|
|
1141
|
+
"img",
|
|
1142
|
+
{
|
|
1143
|
+
src: `https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(
|
|
1144
|
+
href
|
|
1145
|
+
)}`,
|
|
1146
|
+
alt: "favicon",
|
|
1147
|
+
className: "size-4 rounded-full",
|
|
1148
|
+
width: 16,
|
|
1149
|
+
height: 16
|
|
1150
|
+
}
|
|
1151
|
+
),
|
|
1152
|
+
/* @__PURE__ */ jsx("div", { className: "text-primary truncate text-sm", children: domain.replace("www.", "") })
|
|
1153
|
+
] }),
|
|
1154
|
+
/* @__PURE__ */ jsx("div", { className: "line-clamp-2 text-sm font-medium", children: title }),
|
|
1155
|
+
/* @__PURE__ */ jsx("div", { className: "text-muted-foreground line-clamp-2 text-sm", children: description })
|
|
1156
|
+
]
|
|
1157
|
+
}
|
|
1158
|
+
) });
|
|
1159
|
+
}
|
|
1160
|
+
var ReasoningContext = React8.createContext(
|
|
1161
|
+
null
|
|
1162
|
+
);
|
|
1163
|
+
function useReasoningContext() {
|
|
1164
|
+
const context = React8.useContext(ReasoningContext);
|
|
1165
|
+
if (!context) {
|
|
1166
|
+
throw new Error(
|
|
1167
|
+
"Reasoning components must be used within a Reasoning provider"
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
return context;
|
|
1171
|
+
}
|
|
1172
|
+
function Reasoning({
|
|
1173
|
+
children,
|
|
1174
|
+
isStreaming = false,
|
|
1175
|
+
open: controlledOpen,
|
|
1176
|
+
onOpenChange,
|
|
1177
|
+
defaultOpen = false,
|
|
1178
|
+
className
|
|
1179
|
+
}) {
|
|
1180
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React8.useState(defaultOpen);
|
|
1181
|
+
const prevStreamingRef = React8.useRef(isStreaming);
|
|
1182
|
+
const isControlled = controlledOpen !== void 0;
|
|
1183
|
+
const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
|
|
1184
|
+
const setIsOpen = React8.useCallback(
|
|
1185
|
+
(open) => {
|
|
1186
|
+
if (onOpenChange) {
|
|
1187
|
+
onOpenChange(open);
|
|
1188
|
+
}
|
|
1189
|
+
if (!isControlled) {
|
|
1190
|
+
setUncontrolledOpen(open);
|
|
1191
|
+
}
|
|
1192
|
+
},
|
|
1193
|
+
[isControlled, onOpenChange]
|
|
1194
|
+
);
|
|
1195
|
+
React8.useEffect(() => {
|
|
1196
|
+
if (isStreaming && !prevStreamingRef.current) {
|
|
1197
|
+
setIsOpen(true);
|
|
1198
|
+
} else if (!isStreaming && prevStreamingRef.current) {
|
|
1199
|
+
setIsOpen(false);
|
|
1200
|
+
}
|
|
1201
|
+
prevStreamingRef.current = isStreaming;
|
|
1202
|
+
}, [isStreaming, setIsOpen]);
|
|
1203
|
+
return /* @__PURE__ */ jsx(ReasoningContext.Provider, { value: { isOpen, setIsOpen, isStreaming }, children: /* @__PURE__ */ jsx("div", { className: cn("reasoning", className), children }) });
|
|
1204
|
+
}
|
|
1205
|
+
function ReasoningTrigger({
|
|
1206
|
+
children,
|
|
1207
|
+
className
|
|
1208
|
+
}) {
|
|
1209
|
+
const { isOpen, setIsOpen, isStreaming } = useReasoningContext();
|
|
1210
|
+
return /* @__PURE__ */ jsxs(
|
|
1211
|
+
"button",
|
|
1212
|
+
{
|
|
1213
|
+
type: "button",
|
|
1214
|
+
onClick: () => setIsOpen(!isOpen),
|
|
1215
|
+
className: cn(
|
|
1216
|
+
"flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
1217
|
+
"py-1 px-0 bg-transparent border-none cursor-pointer",
|
|
1218
|
+
className
|
|
1219
|
+
),
|
|
1220
|
+
"aria-expanded": isOpen,
|
|
1221
|
+
children: [
|
|
1222
|
+
/* @__PURE__ */ jsx(
|
|
1223
|
+
"svg",
|
|
1224
|
+
{
|
|
1225
|
+
className: cn(
|
|
1226
|
+
"size-3 transition-transform duration-200",
|
|
1227
|
+
isOpen && "rotate-90"
|
|
1228
|
+
),
|
|
1229
|
+
fill: "none",
|
|
1230
|
+
viewBox: "0 0 24 24",
|
|
1231
|
+
stroke: "currentColor",
|
|
1232
|
+
strokeWidth: 2,
|
|
1233
|
+
children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" })
|
|
1234
|
+
}
|
|
1235
|
+
),
|
|
1236
|
+
isStreaming && /* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2", children: [
|
|
1237
|
+
/* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75" }),
|
|
1238
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-primary" })
|
|
1239
|
+
] }),
|
|
1240
|
+
children
|
|
1241
|
+
]
|
|
1242
|
+
}
|
|
1243
|
+
);
|
|
1244
|
+
}
|
|
1245
|
+
function ReasoningContent({
|
|
1246
|
+
children,
|
|
1247
|
+
markdown = false,
|
|
1248
|
+
className
|
|
1249
|
+
}) {
|
|
1250
|
+
const { isOpen } = useReasoningContext();
|
|
1251
|
+
const contentRef = React8.useRef(null);
|
|
1252
|
+
const [height, setHeight] = React8.useState(0);
|
|
1253
|
+
React8.useEffect(() => {
|
|
1254
|
+
if (contentRef.current) {
|
|
1255
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
1256
|
+
for (const entry of entries) {
|
|
1257
|
+
setHeight(entry.contentRect.height);
|
|
1258
|
+
}
|
|
1259
|
+
});
|
|
1260
|
+
resizeObserver.observe(contentRef.current);
|
|
1261
|
+
return () => resizeObserver.disconnect();
|
|
1262
|
+
}
|
|
1263
|
+
}, []);
|
|
1264
|
+
return /* @__PURE__ */ jsx(
|
|
1265
|
+
"div",
|
|
1266
|
+
{
|
|
1267
|
+
className: cn(
|
|
1268
|
+
"overflow-hidden transition-[max-height] duration-200 ease-out",
|
|
1269
|
+
isOpen ? "opacity-100" : "opacity-0"
|
|
1270
|
+
),
|
|
1271
|
+
style: { maxHeight: isOpen ? height : 0 },
|
|
1272
|
+
"aria-hidden": !isOpen,
|
|
1273
|
+
children: /* @__PURE__ */ jsx(
|
|
1274
|
+
"div",
|
|
1275
|
+
{
|
|
1276
|
+
ref: contentRef,
|
|
1277
|
+
className: cn(
|
|
1278
|
+
"mt-1 pl-3 border-l-2 border-muted-foreground/20",
|
|
1279
|
+
"text-xs text-muted-foreground",
|
|
1280
|
+
className
|
|
1281
|
+
),
|
|
1282
|
+
children: markdown && typeof children === "string" ? /* @__PURE__ */ jsx(Markdown, { className: "prose-xs", children }) : /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap", children })
|
|
1283
|
+
}
|
|
1284
|
+
)
|
|
1285
|
+
}
|
|
1286
|
+
);
|
|
1287
|
+
}
|
|
1288
|
+
function SimpleReasoning({
|
|
1289
|
+
content,
|
|
1290
|
+
isStreaming = false,
|
|
1291
|
+
streamingLabel = "Thinking...",
|
|
1292
|
+
collapsedLabel = "View reasoning",
|
|
1293
|
+
markdown = true,
|
|
1294
|
+
className
|
|
1295
|
+
}) {
|
|
1296
|
+
if (!content) return null;
|
|
1297
|
+
return /* @__PURE__ */ jsxs(Reasoning, { isStreaming, className, children: [
|
|
1298
|
+
/* @__PURE__ */ jsx(ReasoningTrigger, { children: isStreaming ? streamingLabel : collapsedLabel }),
|
|
1299
|
+
/* @__PURE__ */ jsx(ReasoningContent, { markdown, children: content })
|
|
1300
|
+
] });
|
|
1301
|
+
}
|
|
1302
|
+
var CopilotUIContext = React8.createContext(
|
|
1303
|
+
null
|
|
1304
|
+
);
|
|
1305
|
+
function useCopilotUI() {
|
|
1306
|
+
const context = React8.useContext(CopilotUIContext);
|
|
1307
|
+
if (!context) {
|
|
1308
|
+
return {
|
|
1309
|
+
debug: false,
|
|
1310
|
+
defaultDebugExpanded: false,
|
|
1311
|
+
isDebug: false
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
return context;
|
|
1315
|
+
}
|
|
1316
|
+
function CopilotUIProvider({
|
|
1317
|
+
children,
|
|
1318
|
+
debug = false,
|
|
1319
|
+
defaultDebugExpanded = false
|
|
1320
|
+
}) {
|
|
1321
|
+
const value = React8.useMemo(
|
|
1322
|
+
() => ({
|
|
1323
|
+
debug,
|
|
1324
|
+
defaultDebugExpanded,
|
|
1325
|
+
isDebug: debug
|
|
1326
|
+
}),
|
|
1327
|
+
[debug, defaultDebugExpanded]
|
|
1328
|
+
);
|
|
1329
|
+
return /* @__PURE__ */ jsx(CopilotUIContext.Provider, { value, children });
|
|
1330
|
+
}
|
|
1331
|
+
function toolNameToTitle(name) {
|
|
1332
|
+
let result = name.replace(/_/g, " ");
|
|
1333
|
+
result = result.replace(/([a-z])([A-Z])/g, "$1 $2");
|
|
1334
|
+
return result.charAt(0).toUpperCase() + result.slice(1).toLowerCase();
|
|
1335
|
+
}
|
|
1336
|
+
function getDisplayTitle(step) {
|
|
1337
|
+
const fallbackTitle = toolNameToTitle(step.name);
|
|
1338
|
+
switch (step.status) {
|
|
1339
|
+
case "pending":
|
|
1340
|
+
return step.title ?? fallbackTitle;
|
|
1341
|
+
case "executing":
|
|
1342
|
+
if (step.executingTitle) return step.executingTitle;
|
|
1343
|
+
return step.title ? `${step.title}...` : `${fallbackTitle}...`;
|
|
1344
|
+
case "completed":
|
|
1345
|
+
return step.completedTitle ?? step.title ?? fallbackTitle;
|
|
1346
|
+
case "error":
|
|
1347
|
+
case "failed":
|
|
1348
|
+
case "rejected":
|
|
1349
|
+
return step.title ?? fallbackTitle;
|
|
1350
|
+
default:
|
|
1351
|
+
return fallbackTitle;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
function StatusIndicator({ status, className }) {
|
|
1355
|
+
const baseClasses = "flex-shrink-0";
|
|
1356
|
+
switch (status) {
|
|
1357
|
+
case "pending":
|
|
1358
|
+
return /* @__PURE__ */ jsx(
|
|
1359
|
+
"div",
|
|
1360
|
+
{
|
|
1361
|
+
className: cn(
|
|
1362
|
+
baseClasses,
|
|
1363
|
+
"size-3 flex items-center justify-center",
|
|
1364
|
+
className
|
|
1365
|
+
),
|
|
1366
|
+
children: /* @__PURE__ */ jsx("div", { className: "size-1.5 rounded-full bg-muted-foreground/40" })
|
|
1367
|
+
}
|
|
1368
|
+
);
|
|
1369
|
+
case "executing":
|
|
1370
|
+
return null;
|
|
1371
|
+
case "completed":
|
|
1372
|
+
return /* @__PURE__ */ jsx(
|
|
1373
|
+
"div",
|
|
1374
|
+
{
|
|
1375
|
+
className: cn(
|
|
1376
|
+
baseClasses,
|
|
1377
|
+
"size-3 flex items-center justify-center",
|
|
1378
|
+
className
|
|
1379
|
+
),
|
|
1380
|
+
children: /* @__PURE__ */ jsx(
|
|
1381
|
+
"svg",
|
|
1382
|
+
{
|
|
1383
|
+
className: "size-3 text-green-500",
|
|
1384
|
+
fill: "none",
|
|
1385
|
+
viewBox: "0 0 24 24",
|
|
1386
|
+
stroke: "currentColor",
|
|
1387
|
+
strokeWidth: 3,
|
|
1388
|
+
children: /* @__PURE__ */ jsx(
|
|
1389
|
+
"path",
|
|
1390
|
+
{
|
|
1391
|
+
strokeLinecap: "round",
|
|
1392
|
+
strokeLinejoin: "round",
|
|
1393
|
+
d: "M5 13l4 4L19 7"
|
|
1394
|
+
}
|
|
1395
|
+
)
|
|
1396
|
+
}
|
|
1397
|
+
)
|
|
1398
|
+
}
|
|
1399
|
+
);
|
|
1400
|
+
case "error":
|
|
1401
|
+
case "failed":
|
|
1402
|
+
case "rejected":
|
|
1403
|
+
return /* @__PURE__ */ jsx(
|
|
1404
|
+
"div",
|
|
1405
|
+
{
|
|
1406
|
+
className: cn(
|
|
1407
|
+
baseClasses,
|
|
1408
|
+
"size-3 flex items-center justify-center",
|
|
1409
|
+
className
|
|
1410
|
+
),
|
|
1411
|
+
children: /* @__PURE__ */ jsx(
|
|
1412
|
+
"svg",
|
|
1413
|
+
{
|
|
1414
|
+
className: "size-3 text-red-500",
|
|
1415
|
+
fill: "none",
|
|
1416
|
+
viewBox: "0 0 24 24",
|
|
1417
|
+
stroke: "currentColor",
|
|
1418
|
+
strokeWidth: 3,
|
|
1419
|
+
children: /* @__PURE__ */ jsx(
|
|
1420
|
+
"path",
|
|
1421
|
+
{
|
|
1422
|
+
strokeLinecap: "round",
|
|
1423
|
+
strokeLinejoin: "round",
|
|
1424
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
1425
|
+
}
|
|
1426
|
+
)
|
|
1427
|
+
}
|
|
1428
|
+
)
|
|
1429
|
+
}
|
|
1430
|
+
);
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
function formatResult(result) {
|
|
1434
|
+
if (!result) return "";
|
|
1435
|
+
if (result.message) return result.message;
|
|
1436
|
+
if (result.error) return result.error;
|
|
1437
|
+
if (result.data) {
|
|
1438
|
+
const data = result.data;
|
|
1439
|
+
if (data.image && typeof data.image === "string" && data.image.startsWith("data:image")) {
|
|
1440
|
+
return `Image (${data.width || "?"}x${data.height || "?"})`;
|
|
1441
|
+
}
|
|
1442
|
+
return JSON.stringify(result.data);
|
|
1443
|
+
}
|
|
1444
|
+
return result.success ? "Success" : "Failed";
|
|
1445
|
+
}
|
|
1446
|
+
function getResultImage(result) {
|
|
1447
|
+
if (!result?.data) return null;
|
|
1448
|
+
const data = result.data;
|
|
1449
|
+
if (data.image && typeof data.image === "string" && data.image.startsWith("data:image")) {
|
|
1450
|
+
return data.image;
|
|
1451
|
+
}
|
|
1452
|
+
return null;
|
|
1453
|
+
}
|
|
1454
|
+
function ToolStep({
|
|
1455
|
+
step,
|
|
1456
|
+
showLine = false,
|
|
1457
|
+
debug: debugProp,
|
|
1458
|
+
defaultExpanded,
|
|
1459
|
+
className
|
|
1460
|
+
}) {
|
|
1461
|
+
const { isDebug, defaultDebugExpanded } = useCopilotUI();
|
|
1462
|
+
const debug = debugProp ?? isDebug;
|
|
1463
|
+
const [expanded, setExpanded] = React8.useState(
|
|
1464
|
+
defaultExpanded ?? defaultDebugExpanded ?? false
|
|
1465
|
+
);
|
|
1466
|
+
const displayTitle = getDisplayTitle(step);
|
|
1467
|
+
const hasDebugContent = step.args && Object.keys(step.args).length > 0 || step.result;
|
|
1468
|
+
const isExecuting = step.status === "executing";
|
|
1469
|
+
const isCompleted = step.status === "completed";
|
|
1470
|
+
const isError = step.status === "error" || step.status === "failed" || step.status === "rejected";
|
|
1471
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
1472
|
+
showLine && /* @__PURE__ */ jsx(
|
|
1473
|
+
"div",
|
|
1474
|
+
{
|
|
1475
|
+
className: "absolute left-[5px] top-4 bottom-0 w-px bg-border",
|
|
1476
|
+
"aria-hidden": "true"
|
|
1477
|
+
}
|
|
1478
|
+
),
|
|
1479
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
1480
|
+
!isExecuting && /* @__PURE__ */ jsx(StatusIndicator, { status: step.status, className: "mt-0.5" }),
|
|
1481
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
1482
|
+
/* @__PURE__ */ jsxs(
|
|
1483
|
+
"button",
|
|
1484
|
+
{
|
|
1485
|
+
type: "button",
|
|
1486
|
+
onClick: () => debug && hasDebugContent && setExpanded(!expanded),
|
|
1487
|
+
disabled: !debug || !hasDebugContent,
|
|
1488
|
+
className: cn(
|
|
1489
|
+
"flex items-center gap-2 text-left min-w-0 w-full",
|
|
1490
|
+
debug && hasDebugContent && "cursor-pointer hover:text-foreground",
|
|
1491
|
+
!debug && "cursor-default"
|
|
1492
|
+
),
|
|
1493
|
+
children: [
|
|
1494
|
+
isExecuting ? /* @__PURE__ */ jsx(TextShimmerLoader, { text: displayTitle, size: "sm" }) : /* @__PURE__ */ jsx(
|
|
1495
|
+
"span",
|
|
1496
|
+
{
|
|
1497
|
+
className: cn(
|
|
1498
|
+
"text-sm truncate",
|
|
1499
|
+
isCompleted && "text-foreground",
|
|
1500
|
+
isError && "text-red-500",
|
|
1501
|
+
step.status === "pending" && "text-muted-foreground/60"
|
|
1502
|
+
),
|
|
1503
|
+
children: displayTitle
|
|
1504
|
+
}
|
|
1505
|
+
),
|
|
1506
|
+
debug && hasDebugContent && /* @__PURE__ */ jsx(
|
|
1507
|
+
"svg",
|
|
1508
|
+
{
|
|
1509
|
+
className: cn(
|
|
1510
|
+
"size-3 text-muted-foreground/40 transition-transform ml-auto flex-shrink-0",
|
|
1511
|
+
expanded && "rotate-90"
|
|
1512
|
+
),
|
|
1513
|
+
fill: "none",
|
|
1514
|
+
viewBox: "0 0 24 24",
|
|
1515
|
+
stroke: "currentColor",
|
|
1516
|
+
strokeWidth: 2,
|
|
1517
|
+
children: /* @__PURE__ */ jsx(
|
|
1518
|
+
"path",
|
|
1519
|
+
{
|
|
1520
|
+
strokeLinecap: "round",
|
|
1521
|
+
strokeLinejoin: "round",
|
|
1522
|
+
d: "M9 5l7 7-7 7"
|
|
1523
|
+
}
|
|
1524
|
+
)
|
|
1525
|
+
}
|
|
1526
|
+
)
|
|
1527
|
+
]
|
|
1528
|
+
}
|
|
1529
|
+
),
|
|
1530
|
+
debug && expanded && hasDebugContent && /* @__PURE__ */ jsxs("div", { className: "mt-1.5 space-y-1.5", children: [
|
|
1531
|
+
step.args && Object.keys(step.args).length > 0 && /* @__PURE__ */ jsxs("div", { className: "text-[10px] font-mono bg-muted/50 rounded px-2 py-1 overflow-x-auto", children: [
|
|
1532
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "args: " }),
|
|
1533
|
+
JSON.stringify(step.args)
|
|
1534
|
+
] }),
|
|
1535
|
+
step.result && /* @__PURE__ */ jsxs(
|
|
1536
|
+
"div",
|
|
1537
|
+
{
|
|
1538
|
+
className: cn(
|
|
1539
|
+
"text-[10px] font-mono rounded px-2 py-1 overflow-x-auto whitespace-pre-wrap break-all",
|
|
1540
|
+
step.result.success !== false ? "bg-green-500/10 text-green-600 dark:text-green-400" : "bg-red-500/10 text-red-600 dark:text-red-400"
|
|
1541
|
+
),
|
|
1542
|
+
children: [
|
|
1543
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "result: " }),
|
|
1544
|
+
formatResult(step.result),
|
|
1545
|
+
getResultImage(step.result) && /* @__PURE__ */ jsx(
|
|
1546
|
+
"img",
|
|
1547
|
+
{
|
|
1548
|
+
src: getResultImage(step.result),
|
|
1549
|
+
alt: "Screenshot",
|
|
1550
|
+
className: "mt-1.5 rounded border border-border max-w-full max-h-48 object-contain"
|
|
1551
|
+
}
|
|
1552
|
+
)
|
|
1553
|
+
]
|
|
1554
|
+
}
|
|
1555
|
+
)
|
|
1556
|
+
] }),
|
|
1557
|
+
isError && step.error && !step.result && /* @__PURE__ */ jsx("div", { className: "mt-0.5 text-[10px] font-mono bg-red-500/10 text-red-600 dark:text-red-400 rounded px-1.5 py-0.5", children: step.error })
|
|
1558
|
+
] })
|
|
1559
|
+
] })
|
|
1560
|
+
] });
|
|
1561
|
+
}
|
|
1562
|
+
function ToolSteps({
|
|
1563
|
+
steps,
|
|
1564
|
+
debug,
|
|
1565
|
+
defaultExpanded = false,
|
|
1566
|
+
className
|
|
1567
|
+
}) {
|
|
1568
|
+
if (steps.length === 0) return null;
|
|
1569
|
+
return /* @__PURE__ */ jsx("div", { className: cn("space-y-1.5", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(
|
|
1570
|
+
ToolStep,
|
|
1571
|
+
{
|
|
1572
|
+
step,
|
|
1573
|
+
showLine: index < steps.length - 1,
|
|
1574
|
+
debug,
|
|
1575
|
+
defaultExpanded
|
|
1576
|
+
},
|
|
1577
|
+
step.id
|
|
1578
|
+
)) });
|
|
1579
|
+
}
|
|
1580
|
+
function InlineToolSteps({
|
|
1581
|
+
steps,
|
|
1582
|
+
maxVisible = 5,
|
|
1583
|
+
className
|
|
1584
|
+
}) {
|
|
1585
|
+
if (steps.length === 0) return null;
|
|
1586
|
+
const visibleSteps = steps.slice(0, maxVisible);
|
|
1587
|
+
const hiddenCount = steps.length - maxVisible;
|
|
1588
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-1", className), children: [
|
|
1589
|
+
visibleSteps.map((step) => /* @__PURE__ */ jsx(
|
|
1590
|
+
"div",
|
|
1591
|
+
{
|
|
1592
|
+
title: `${step.name}: ${step.status}`,
|
|
1593
|
+
className: "flex items-center",
|
|
1594
|
+
children: /* @__PURE__ */ jsx(StatusIndicator, { status: step.status })
|
|
1595
|
+
},
|
|
1596
|
+
step.id
|
|
1597
|
+
)),
|
|
1598
|
+
hiddenCount > 0 && /* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
1599
|
+
"+",
|
|
1600
|
+
hiddenCount
|
|
1601
|
+
] })
|
|
1602
|
+
] });
|
|
1603
|
+
}
|
|
1604
|
+
function SendIcon({ className }) {
|
|
1605
|
+
return /* @__PURE__ */ jsxs(
|
|
1606
|
+
"svg",
|
|
1607
|
+
{
|
|
1608
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1609
|
+
viewBox: "0 0 24 24",
|
|
1610
|
+
fill: "none",
|
|
1611
|
+
stroke: "currentColor",
|
|
1612
|
+
strokeWidth: "2",
|
|
1613
|
+
strokeLinecap: "round",
|
|
1614
|
+
strokeLinejoin: "round",
|
|
1615
|
+
className,
|
|
1616
|
+
children: [
|
|
1617
|
+
/* @__PURE__ */ jsx("path", { d: "m22 2-7 20-4-9-9-4Z" }),
|
|
1618
|
+
/* @__PURE__ */ jsx("path", { d: "M22 2 11 13" })
|
|
1619
|
+
]
|
|
1620
|
+
}
|
|
1621
|
+
);
|
|
1622
|
+
}
|
|
1623
|
+
function StopIcon({ className }) {
|
|
1624
|
+
return /* @__PURE__ */ jsx(
|
|
1625
|
+
"svg",
|
|
1626
|
+
{
|
|
1627
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1628
|
+
viewBox: "0 0 24 24",
|
|
1629
|
+
fill: "currentColor",
|
|
1630
|
+
className,
|
|
1631
|
+
children: /* @__PURE__ */ jsx("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" })
|
|
1632
|
+
}
|
|
1633
|
+
);
|
|
1634
|
+
}
|
|
1635
|
+
function CloseIcon({ className }) {
|
|
1636
|
+
return /* @__PURE__ */ jsxs(
|
|
1637
|
+
"svg",
|
|
1638
|
+
{
|
|
1639
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1640
|
+
viewBox: "0 0 24 24",
|
|
1641
|
+
fill: "none",
|
|
1642
|
+
stroke: "currentColor",
|
|
1643
|
+
strokeWidth: "2",
|
|
1644
|
+
strokeLinecap: "round",
|
|
1645
|
+
strokeLinejoin: "round",
|
|
1646
|
+
className,
|
|
1647
|
+
children: [
|
|
1648
|
+
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
1649
|
+
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
1650
|
+
]
|
|
1651
|
+
}
|
|
1652
|
+
);
|
|
1653
|
+
}
|
|
1654
|
+
function ChevronDownIcon2({ className }) {
|
|
1655
|
+
return /* @__PURE__ */ jsx(
|
|
1656
|
+
"svg",
|
|
1657
|
+
{
|
|
1658
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1659
|
+
viewBox: "0 0 24 24",
|
|
1660
|
+
fill: "none",
|
|
1661
|
+
stroke: "currentColor",
|
|
1662
|
+
strokeWidth: "2",
|
|
1663
|
+
strokeLinecap: "round",
|
|
1664
|
+
strokeLinejoin: "round",
|
|
1665
|
+
className,
|
|
1666
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
1667
|
+
}
|
|
1668
|
+
);
|
|
1669
|
+
}
|
|
1670
|
+
function ChevronUpIcon({ className }) {
|
|
1671
|
+
return /* @__PURE__ */ jsx(
|
|
1672
|
+
"svg",
|
|
1673
|
+
{
|
|
1674
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1675
|
+
viewBox: "0 0 24 24",
|
|
1676
|
+
fill: "none",
|
|
1677
|
+
stroke: "currentColor",
|
|
1678
|
+
strokeWidth: "2",
|
|
1679
|
+
strokeLinecap: "round",
|
|
1680
|
+
strokeLinejoin: "round",
|
|
1681
|
+
className,
|
|
1682
|
+
children: /* @__PURE__ */ jsx("path", { d: "m18 15-6-6-6 6" })
|
|
1683
|
+
}
|
|
1684
|
+
);
|
|
1685
|
+
}
|
|
1686
|
+
function CopyIcon({ className }) {
|
|
1687
|
+
return /* @__PURE__ */ jsxs(
|
|
1688
|
+
"svg",
|
|
1689
|
+
{
|
|
1690
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1691
|
+
viewBox: "0 0 24 24",
|
|
1692
|
+
fill: "none",
|
|
1693
|
+
stroke: "currentColor",
|
|
1694
|
+
strokeWidth: "2",
|
|
1695
|
+
strokeLinecap: "round",
|
|
1696
|
+
strokeLinejoin: "round",
|
|
1697
|
+
className,
|
|
1698
|
+
children: [
|
|
1699
|
+
/* @__PURE__ */ jsx("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
|
|
1700
|
+
/* @__PURE__ */ jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
|
|
1701
|
+
]
|
|
1702
|
+
}
|
|
1703
|
+
);
|
|
1704
|
+
}
|
|
1705
|
+
function CheckIcon({ className }) {
|
|
1706
|
+
return /* @__PURE__ */ jsx(
|
|
1707
|
+
"svg",
|
|
1708
|
+
{
|
|
1709
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1710
|
+
viewBox: "0 0 24 24",
|
|
1711
|
+
fill: "none",
|
|
1712
|
+
stroke: "currentColor",
|
|
1713
|
+
strokeWidth: "2",
|
|
1714
|
+
strokeLinecap: "round",
|
|
1715
|
+
strokeLinejoin: "round",
|
|
1716
|
+
className,
|
|
1717
|
+
children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
|
|
1718
|
+
}
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
function ThumbsUpIcon2({ className }) {
|
|
1722
|
+
return /* @__PURE__ */ jsxs(
|
|
1723
|
+
"svg",
|
|
1724
|
+
{
|
|
1725
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1726
|
+
viewBox: "0 0 24 24",
|
|
1727
|
+
fill: "none",
|
|
1728
|
+
stroke: "currentColor",
|
|
1729
|
+
strokeWidth: "2",
|
|
1730
|
+
strokeLinecap: "round",
|
|
1731
|
+
strokeLinejoin: "round",
|
|
1732
|
+
className,
|
|
1733
|
+
children: [
|
|
1734
|
+
/* @__PURE__ */ jsx("path", { d: "M7 10v12" }),
|
|
1735
|
+
/* @__PURE__ */ jsx("path", { d: "M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z" })
|
|
1736
|
+
]
|
|
1737
|
+
}
|
|
1738
|
+
);
|
|
1739
|
+
}
|
|
1740
|
+
function ThumbsDownIcon2({ className }) {
|
|
1741
|
+
return /* @__PURE__ */ jsxs(
|
|
1742
|
+
"svg",
|
|
1743
|
+
{
|
|
1744
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1745
|
+
viewBox: "0 0 24 24",
|
|
1746
|
+
fill: "none",
|
|
1747
|
+
stroke: "currentColor",
|
|
1748
|
+
strokeWidth: "2",
|
|
1749
|
+
strokeLinecap: "round",
|
|
1750
|
+
strokeLinejoin: "round",
|
|
1751
|
+
className,
|
|
1752
|
+
children: [
|
|
1753
|
+
/* @__PURE__ */ jsx("path", { d: "M17 14V2" }),
|
|
1754
|
+
/* @__PURE__ */ jsx("path", { d: "M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z" })
|
|
1755
|
+
]
|
|
1756
|
+
}
|
|
1757
|
+
);
|
|
1758
|
+
}
|
|
1759
|
+
function RefreshIcon({ className }) {
|
|
1760
|
+
return /* @__PURE__ */ jsxs(
|
|
1761
|
+
"svg",
|
|
1762
|
+
{
|
|
1763
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1764
|
+
viewBox: "0 0 24 24",
|
|
1765
|
+
fill: "none",
|
|
1766
|
+
stroke: "currentColor",
|
|
1767
|
+
strokeWidth: "2",
|
|
1768
|
+
strokeLinecap: "round",
|
|
1769
|
+
strokeLinejoin: "round",
|
|
1770
|
+
className,
|
|
1771
|
+
children: [
|
|
1772
|
+
/* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
|
|
1773
|
+
/* @__PURE__ */ jsx("path", { d: "M21 3v5h-5" }),
|
|
1774
|
+
/* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
|
|
1775
|
+
/* @__PURE__ */ jsx("path", { d: "M8 16H3v5" })
|
|
1776
|
+
]
|
|
1777
|
+
}
|
|
1778
|
+
);
|
|
1779
|
+
}
|
|
1780
|
+
function UserIcon({ className }) {
|
|
1781
|
+
return /* @__PURE__ */ jsxs(
|
|
1782
|
+
"svg",
|
|
1783
|
+
{
|
|
1784
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1785
|
+
viewBox: "0 0 24 24",
|
|
1786
|
+
fill: "none",
|
|
1787
|
+
stroke: "currentColor",
|
|
1788
|
+
strokeWidth: "2",
|
|
1789
|
+
strokeLinecap: "round",
|
|
1790
|
+
strokeLinejoin: "round",
|
|
1791
|
+
className,
|
|
1792
|
+
children: [
|
|
1793
|
+
/* @__PURE__ */ jsx("path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" }),
|
|
1794
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "7", r: "4" })
|
|
1795
|
+
]
|
|
1796
|
+
}
|
|
1797
|
+
);
|
|
1798
|
+
}
|
|
1799
|
+
function BotIcon({ className }) {
|
|
1800
|
+
return /* @__PURE__ */ jsxs(
|
|
1801
|
+
"svg",
|
|
1802
|
+
{
|
|
1803
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1804
|
+
viewBox: "0 0 24 24",
|
|
1805
|
+
fill: "none",
|
|
1806
|
+
stroke: "currentColor",
|
|
1807
|
+
strokeWidth: "2",
|
|
1808
|
+
strokeLinecap: "round",
|
|
1809
|
+
strokeLinejoin: "round",
|
|
1810
|
+
className,
|
|
1811
|
+
children: [
|
|
1812
|
+
/* @__PURE__ */ jsx("path", { d: "M12 8V4H8" }),
|
|
1813
|
+
/* @__PURE__ */ jsx("rect", { width: "16", height: "12", x: "4", y: "8", rx: "2" }),
|
|
1814
|
+
/* @__PURE__ */ jsx("path", { d: "M2 14h2" }),
|
|
1815
|
+
/* @__PURE__ */ jsx("path", { d: "M20 14h2" }),
|
|
1816
|
+
/* @__PURE__ */ jsx("path", { d: "M15 13v2" }),
|
|
1817
|
+
/* @__PURE__ */ jsx("path", { d: "M9 13v2" })
|
|
1818
|
+
]
|
|
1819
|
+
}
|
|
1820
|
+
);
|
|
1821
|
+
}
|
|
1822
|
+
function PlusIcon({ className }) {
|
|
1823
|
+
return /* @__PURE__ */ jsxs(
|
|
1824
|
+
"svg",
|
|
1825
|
+
{
|
|
1826
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1827
|
+
width: "24",
|
|
1828
|
+
height: "24",
|
|
1829
|
+
viewBox: "0 0 24 24",
|
|
1830
|
+
fill: "none",
|
|
1831
|
+
stroke: "currentColor",
|
|
1832
|
+
strokeWidth: "2",
|
|
1833
|
+
strokeLinecap: "round",
|
|
1834
|
+
strokeLinejoin: "round",
|
|
1835
|
+
className,
|
|
1836
|
+
children: [
|
|
1837
|
+
/* @__PURE__ */ jsx("path", { d: "M5 12h14" }),
|
|
1838
|
+
/* @__PURE__ */ jsx("path", { d: "M12 5v14" })
|
|
1839
|
+
]
|
|
1840
|
+
}
|
|
1841
|
+
);
|
|
1842
|
+
}
|
|
1843
|
+
function ArrowUpIcon({ className }) {
|
|
1844
|
+
return /* @__PURE__ */ jsxs(
|
|
1845
|
+
"svg",
|
|
1846
|
+
{
|
|
1847
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1848
|
+
width: "24",
|
|
1849
|
+
height: "24",
|
|
1850
|
+
viewBox: "0 0 24 24",
|
|
1851
|
+
fill: "none",
|
|
1852
|
+
stroke: "currentColor",
|
|
1853
|
+
strokeWidth: "2",
|
|
1854
|
+
strokeLinecap: "round",
|
|
1855
|
+
strokeLinejoin: "round",
|
|
1856
|
+
className,
|
|
1857
|
+
children: [
|
|
1858
|
+
/* @__PURE__ */ jsx("path", { d: "m5 12 7-7 7 7" }),
|
|
1859
|
+
/* @__PURE__ */ jsx("path", { d: "M12 19V5" })
|
|
1860
|
+
]
|
|
1861
|
+
}
|
|
1862
|
+
);
|
|
1863
|
+
}
|
|
1864
|
+
function XIcon2({ className }) {
|
|
1865
|
+
return /* @__PURE__ */ jsxs(
|
|
1866
|
+
"svg",
|
|
1867
|
+
{
|
|
1868
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1869
|
+
width: "24",
|
|
1870
|
+
height: "24",
|
|
1871
|
+
viewBox: "0 0 24 24",
|
|
1872
|
+
fill: "none",
|
|
1873
|
+
stroke: "currentColor",
|
|
1874
|
+
strokeWidth: "2",
|
|
1875
|
+
strokeLinecap: "round",
|
|
1876
|
+
strokeLinejoin: "round",
|
|
1877
|
+
className,
|
|
1878
|
+
children: [
|
|
1879
|
+
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
1880
|
+
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
1881
|
+
]
|
|
1882
|
+
}
|
|
1883
|
+
);
|
|
1884
|
+
}
|
|
1885
|
+
function AlertTriangleIcon({ className }) {
|
|
1886
|
+
return /* @__PURE__ */ jsxs(
|
|
1887
|
+
"svg",
|
|
1888
|
+
{
|
|
1889
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1890
|
+
width: "24",
|
|
1891
|
+
height: "24",
|
|
1892
|
+
viewBox: "0 0 24 24",
|
|
1893
|
+
fill: "none",
|
|
1894
|
+
stroke: "currentColor",
|
|
1895
|
+
strokeWidth: "2",
|
|
1896
|
+
strokeLinecap: "round",
|
|
1897
|
+
strokeLinejoin: "round",
|
|
1898
|
+
className,
|
|
1899
|
+
children: [
|
|
1900
|
+
/* @__PURE__ */ jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }),
|
|
1901
|
+
/* @__PURE__ */ jsx("path", { d: "M12 9v4" }),
|
|
1902
|
+
/* @__PURE__ */ jsx("path", { d: "M12 17h.01" })
|
|
1903
|
+
]
|
|
1904
|
+
}
|
|
1905
|
+
);
|
|
1906
|
+
}
|
|
1907
|
+
var ConfirmationContext = React8.createContext(null);
|
|
1908
|
+
function useConfirmationContext() {
|
|
1909
|
+
const context = React8.useContext(ConfirmationContext);
|
|
1910
|
+
if (!context) {
|
|
1911
|
+
throw new Error(
|
|
1912
|
+
"Confirmation components must be used within a Confirmation provider"
|
|
1913
|
+
);
|
|
1914
|
+
}
|
|
1915
|
+
return context;
|
|
1916
|
+
}
|
|
1917
|
+
function Confirmation({
|
|
1918
|
+
children,
|
|
1919
|
+
state = "pending",
|
|
1920
|
+
message,
|
|
1921
|
+
onApprove,
|
|
1922
|
+
onReject,
|
|
1923
|
+
className
|
|
1924
|
+
}) {
|
|
1925
|
+
return /* @__PURE__ */ jsx(
|
|
1926
|
+
ConfirmationContext.Provider,
|
|
1927
|
+
{
|
|
1928
|
+
value: { state, message, onApprove, onReject },
|
|
1929
|
+
children: /* @__PURE__ */ jsx(
|
|
1930
|
+
"div",
|
|
1931
|
+
{
|
|
1932
|
+
className: cn(
|
|
1933
|
+
"confirmation rounded-lg border bg-card text-card-foreground",
|
|
1934
|
+
className
|
|
1935
|
+
),
|
|
1936
|
+
children
|
|
1937
|
+
}
|
|
1938
|
+
)
|
|
1939
|
+
}
|
|
1940
|
+
);
|
|
1941
|
+
}
|
|
1942
|
+
function ConfirmationPending({
|
|
1943
|
+
children,
|
|
1944
|
+
className
|
|
1945
|
+
}) {
|
|
1946
|
+
const { state } = useConfirmationContext();
|
|
1947
|
+
if (state !== "pending") return null;
|
|
1948
|
+
return /* @__PURE__ */ jsx("div", { className: cn("p-4", className), children });
|
|
1949
|
+
}
|
|
1950
|
+
function ConfirmationApproved({
|
|
1951
|
+
children,
|
|
1952
|
+
className
|
|
1953
|
+
}) {
|
|
1954
|
+
const { state } = useConfirmationContext();
|
|
1955
|
+
if (state !== "approved") return null;
|
|
1956
|
+
return /* @__PURE__ */ jsxs(
|
|
1957
|
+
"div",
|
|
1958
|
+
{
|
|
1959
|
+
className: cn(
|
|
1960
|
+
"flex items-center gap-2 px-4 py-2 text-sm text-green-600 dark:text-green-400",
|
|
1961
|
+
className
|
|
1962
|
+
),
|
|
1963
|
+
children: [
|
|
1964
|
+
/* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4" }),
|
|
1965
|
+
children || /* @__PURE__ */ jsx("span", { children: "Approved" })
|
|
1966
|
+
]
|
|
1967
|
+
}
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
function ConfirmationRejected({
|
|
1971
|
+
children,
|
|
1972
|
+
className
|
|
1973
|
+
}) {
|
|
1974
|
+
const { state } = useConfirmationContext();
|
|
1975
|
+
if (state !== "rejected") return null;
|
|
1976
|
+
return /* @__PURE__ */ jsxs(
|
|
1977
|
+
"div",
|
|
1978
|
+
{
|
|
1979
|
+
className: cn(
|
|
1980
|
+
"flex items-center gap-2 px-4 py-2 text-sm text-red-600 dark:text-red-400",
|
|
1981
|
+
className
|
|
1982
|
+
),
|
|
1983
|
+
children: [
|
|
1984
|
+
/* @__PURE__ */ jsx(XIcon2, { className: "h-4 w-4" }),
|
|
1985
|
+
children || /* @__PURE__ */ jsx("span", { children: "Rejected" })
|
|
1986
|
+
]
|
|
1987
|
+
}
|
|
1988
|
+
);
|
|
1989
|
+
}
|
|
1990
|
+
function ConfirmationMessage({
|
|
1991
|
+
children,
|
|
1992
|
+
className
|
|
1993
|
+
}) {
|
|
1994
|
+
const { message } = useConfirmationContext();
|
|
1995
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-start gap-3", className), children: [
|
|
1996
|
+
/* @__PURE__ */ jsx(AlertTriangleIcon, { className: "mt-0.5 h-5 w-5 flex-shrink-0 text-amber-500" }),
|
|
1997
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: children || message || "This action requires your approval." })
|
|
1998
|
+
] });
|
|
1999
|
+
}
|
|
2000
|
+
function ConfirmationActions({
|
|
2001
|
+
children,
|
|
2002
|
+
className,
|
|
2003
|
+
rejectLabel = "Reject",
|
|
2004
|
+
approveLabel = "Approve"
|
|
2005
|
+
}) {
|
|
2006
|
+
const { onApprove, onReject } = useConfirmationContext();
|
|
2007
|
+
if (children) {
|
|
2008
|
+
return /* @__PURE__ */ jsx("div", { className: cn("mt-3 flex justify-end gap-2", className), children });
|
|
2009
|
+
}
|
|
2010
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("mt-3 flex justify-end gap-2", className), children: [
|
|
2011
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: onReject, children: rejectLabel }),
|
|
2012
|
+
/* @__PURE__ */ jsx(Button, { variant: "default", size: "sm", onClick: onApprove, children: approveLabel })
|
|
2013
|
+
] });
|
|
2014
|
+
}
|
|
2015
|
+
function SimpleConfirmation({
|
|
2016
|
+
state,
|
|
2017
|
+
message,
|
|
2018
|
+
onApprove,
|
|
2019
|
+
onReject,
|
|
2020
|
+
rejectLabel,
|
|
2021
|
+
approveLabel,
|
|
2022
|
+
className
|
|
2023
|
+
}) {
|
|
2024
|
+
return /* @__PURE__ */ jsxs(
|
|
2025
|
+
Confirmation,
|
|
2026
|
+
{
|
|
2027
|
+
state,
|
|
2028
|
+
message,
|
|
2029
|
+
onApprove,
|
|
2030
|
+
onReject,
|
|
2031
|
+
className,
|
|
2032
|
+
children: [
|
|
2033
|
+
/* @__PURE__ */ jsxs(ConfirmationPending, { children: [
|
|
2034
|
+
/* @__PURE__ */ jsx(ConfirmationMessage, {}),
|
|
2035
|
+
/* @__PURE__ */ jsx(
|
|
2036
|
+
ConfirmationActions,
|
|
2037
|
+
{
|
|
2038
|
+
rejectLabel,
|
|
2039
|
+
approveLabel
|
|
2040
|
+
}
|
|
2041
|
+
)
|
|
2042
|
+
] }),
|
|
2043
|
+
/* @__PURE__ */ jsx(ConfirmationApproved, {}),
|
|
2044
|
+
/* @__PURE__ */ jsx(ConfirmationRejected, {})
|
|
2045
|
+
]
|
|
2046
|
+
}
|
|
2047
|
+
);
|
|
2048
|
+
}
|
|
2049
|
+
var DEFAULT_PERMISSION_OPTIONS = [
|
|
2050
|
+
{
|
|
2051
|
+
value: "ask",
|
|
2052
|
+
label: "Ask every time",
|
|
2053
|
+
description: "Always prompt before this tool runs"
|
|
2054
|
+
},
|
|
2055
|
+
{
|
|
2056
|
+
value: "allow_always",
|
|
2057
|
+
label: "Allow always",
|
|
2058
|
+
description: "Never ask again, always approve"
|
|
2059
|
+
},
|
|
2060
|
+
{
|
|
2061
|
+
value: "session",
|
|
2062
|
+
label: "Allow this session",
|
|
2063
|
+
description: "Allow until you close this page"
|
|
2064
|
+
},
|
|
2065
|
+
{
|
|
2066
|
+
value: "deny_always",
|
|
2067
|
+
label: "Deny always",
|
|
2068
|
+
description: "Never ask again, always deny"
|
|
2069
|
+
}
|
|
2070
|
+
];
|
|
2071
|
+
function PermissionConfirmation({
|
|
2072
|
+
state,
|
|
2073
|
+
toolName,
|
|
2074
|
+
message,
|
|
2075
|
+
onApprove,
|
|
2076
|
+
onReject,
|
|
2077
|
+
showPermissionOptions = true,
|
|
2078
|
+
permissionOptions = DEFAULT_PERMISSION_OPTIONS,
|
|
2079
|
+
className
|
|
2080
|
+
}) {
|
|
2081
|
+
const [selectedPermission, setSelectedPermission] = React8.useState("ask");
|
|
2082
|
+
const [showOptions, setShowOptions] = React8.useState(false);
|
|
2083
|
+
const handleApprove = () => {
|
|
2084
|
+
onApprove?.(selectedPermission);
|
|
2085
|
+
};
|
|
2086
|
+
const handleReject = () => {
|
|
2087
|
+
onReject?.(
|
|
2088
|
+
selectedPermission === "deny_always" ? "deny_always" : void 0
|
|
2089
|
+
);
|
|
2090
|
+
};
|
|
2091
|
+
if (state === "approved") {
|
|
2092
|
+
return /* @__PURE__ */ jsxs(
|
|
2093
|
+
"div",
|
|
2094
|
+
{
|
|
2095
|
+
className: cn(
|
|
2096
|
+
"flex items-center gap-2 px-4 py-2 text-sm text-green-600 dark:text-green-400 rounded-lg border bg-green-50 dark:bg-green-950/20",
|
|
2097
|
+
className
|
|
2098
|
+
),
|
|
2099
|
+
children: [
|
|
2100
|
+
/* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4" }),
|
|
2101
|
+
/* @__PURE__ */ jsx("span", { children: "Approved" })
|
|
2102
|
+
]
|
|
2103
|
+
}
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
if (state === "rejected") {
|
|
2107
|
+
return /* @__PURE__ */ jsxs(
|
|
2108
|
+
"div",
|
|
2109
|
+
{
|
|
2110
|
+
className: cn(
|
|
2111
|
+
"flex items-center gap-2 px-4 py-2 text-sm text-red-600 dark:text-red-400 rounded-lg border bg-red-50 dark:bg-red-950/20",
|
|
2112
|
+
className
|
|
2113
|
+
),
|
|
2114
|
+
children: [
|
|
2115
|
+
/* @__PURE__ */ jsx(XIcon2, { className: "h-4 w-4" }),
|
|
2116
|
+
/* @__PURE__ */ jsx("span", { children: "Rejected" })
|
|
2117
|
+
]
|
|
2118
|
+
}
|
|
2119
|
+
);
|
|
2120
|
+
}
|
|
2121
|
+
return /* @__PURE__ */ jsxs(
|
|
2122
|
+
"div",
|
|
2123
|
+
{
|
|
2124
|
+
className: cn(
|
|
2125
|
+
"rounded-lg border bg-card text-card-foreground p-4",
|
|
2126
|
+
className
|
|
2127
|
+
),
|
|
2128
|
+
children: [
|
|
2129
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 mb-3", children: [
|
|
2130
|
+
/* @__PURE__ */ jsx(AlertTriangleIcon, { className: "mt-0.5 h-5 w-5 flex-shrink-0 text-amber-500" }),
|
|
2131
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2132
|
+
toolName && /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: toolName }),
|
|
2133
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: message || "This tool requires your approval to execute." })
|
|
2134
|
+
] })
|
|
2135
|
+
] }),
|
|
2136
|
+
showPermissionOptions && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
2137
|
+
/* @__PURE__ */ jsxs(
|
|
2138
|
+
"button",
|
|
2139
|
+
{
|
|
2140
|
+
type: "button",
|
|
2141
|
+
onClick: () => setShowOptions(!showOptions),
|
|
2142
|
+
className: "flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors",
|
|
2143
|
+
children: [
|
|
2144
|
+
/* @__PURE__ */ jsx("span", { children: permissionOptions.find((o) => o.value === selectedPermission)?.label }),
|
|
2145
|
+
/* @__PURE__ */ jsx(
|
|
2146
|
+
"svg",
|
|
2147
|
+
{
|
|
2148
|
+
className: cn(
|
|
2149
|
+
"h-4 w-4 transition-transform",
|
|
2150
|
+
showOptions && "rotate-180"
|
|
2151
|
+
),
|
|
2152
|
+
fill: "none",
|
|
2153
|
+
viewBox: "0 0 24 24",
|
|
2154
|
+
stroke: "currentColor",
|
|
2155
|
+
strokeWidth: 2,
|
|
2156
|
+
children: /* @__PURE__ */ jsx(
|
|
2157
|
+
"path",
|
|
2158
|
+
{
|
|
2159
|
+
strokeLinecap: "round",
|
|
2160
|
+
strokeLinejoin: "round",
|
|
2161
|
+
d: "M19 9l-7 7-7-7"
|
|
2162
|
+
}
|
|
2163
|
+
)
|
|
2164
|
+
}
|
|
2165
|
+
)
|
|
2166
|
+
]
|
|
2167
|
+
}
|
|
2168
|
+
),
|
|
2169
|
+
showOptions && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-1 pl-1", children: permissionOptions.map((option) => /* @__PURE__ */ jsxs(
|
|
2170
|
+
"label",
|
|
2171
|
+
{
|
|
2172
|
+
className: cn(
|
|
2173
|
+
"flex items-start gap-2 p-2 rounded-md cursor-pointer transition-colors",
|
|
2174
|
+
selectedPermission === option.value ? "bg-primary/10" : "hover:bg-muted/50"
|
|
2175
|
+
),
|
|
2176
|
+
children: [
|
|
2177
|
+
/* @__PURE__ */ jsx(
|
|
2178
|
+
"input",
|
|
2179
|
+
{
|
|
2180
|
+
type: "radio",
|
|
2181
|
+
name: "permission",
|
|
2182
|
+
value: option.value,
|
|
2183
|
+
checked: selectedPermission === option.value,
|
|
2184
|
+
onChange: () => setSelectedPermission(option.value),
|
|
2185
|
+
className: "mt-0.5"
|
|
2186
|
+
}
|
|
2187
|
+
),
|
|
2188
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2189
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium", children: option.label }),
|
|
2190
|
+
option.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: option.description })
|
|
2191
|
+
] })
|
|
2192
|
+
]
|
|
2193
|
+
},
|
|
2194
|
+
option.value
|
|
2195
|
+
)) })
|
|
2196
|
+
] }),
|
|
2197
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
2198
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: handleReject, children: "Deny" }),
|
|
2199
|
+
/* @__PURE__ */ jsx(Button, { variant: "default", size: "sm", onClick: handleApprove, children: "Allow" })
|
|
2200
|
+
] })
|
|
2201
|
+
]
|
|
2202
|
+
}
|
|
2203
|
+
);
|
|
2204
|
+
}
|
|
2205
|
+
function CompactPermissionConfirmation({
|
|
2206
|
+
state,
|
|
2207
|
+
message,
|
|
2208
|
+
onApprove,
|
|
2209
|
+
onReject,
|
|
2210
|
+
className
|
|
2211
|
+
}) {
|
|
2212
|
+
const [rememberChoice, setRememberChoice] = React8.useState(false);
|
|
2213
|
+
const handleApprove = () => {
|
|
2214
|
+
onApprove?.(rememberChoice ? "allow_always" : "ask");
|
|
2215
|
+
};
|
|
2216
|
+
const handleReject = () => {
|
|
2217
|
+
onReject?.(rememberChoice ? "deny_always" : void 0);
|
|
2218
|
+
};
|
|
2219
|
+
if (state === "approved") {
|
|
2220
|
+
return /* @__PURE__ */ jsxs(
|
|
2221
|
+
"div",
|
|
2222
|
+
{
|
|
2223
|
+
className: cn(
|
|
2224
|
+
"flex items-center gap-2 px-4 py-2 text-sm text-green-600 dark:text-green-400",
|
|
2225
|
+
className
|
|
2226
|
+
),
|
|
2227
|
+
children: [
|
|
2228
|
+
/* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4" }),
|
|
2229
|
+
/* @__PURE__ */ jsx("span", { children: "Approved" })
|
|
2230
|
+
]
|
|
2231
|
+
}
|
|
2232
|
+
);
|
|
2233
|
+
}
|
|
2234
|
+
if (state === "rejected") {
|
|
2235
|
+
return /* @__PURE__ */ jsxs(
|
|
2236
|
+
"div",
|
|
2237
|
+
{
|
|
2238
|
+
className: cn(
|
|
2239
|
+
"flex items-center gap-2 px-4 py-2 text-sm text-red-600 dark:text-red-400",
|
|
2240
|
+
className
|
|
2241
|
+
),
|
|
2242
|
+
children: [
|
|
2243
|
+
/* @__PURE__ */ jsx(XIcon2, { className: "h-4 w-4" }),
|
|
2244
|
+
/* @__PURE__ */ jsx("span", { children: "Rejected" })
|
|
2245
|
+
]
|
|
2246
|
+
}
|
|
2247
|
+
);
|
|
2248
|
+
}
|
|
2249
|
+
return /* @__PURE__ */ jsxs(
|
|
2250
|
+
"div",
|
|
2251
|
+
{
|
|
2252
|
+
className: cn(
|
|
2253
|
+
"rounded-lg border bg-card text-card-foreground p-4",
|
|
2254
|
+
className
|
|
2255
|
+
),
|
|
2256
|
+
children: [
|
|
2257
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 mb-3", children: [
|
|
2258
|
+
/* @__PURE__ */ jsx(AlertTriangleIcon, { className: "mt-0.5 h-5 w-5 flex-shrink-0 text-amber-500" }),
|
|
2259
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: message || "This action requires your approval." })
|
|
2260
|
+
] }),
|
|
2261
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2262
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm text-muted-foreground cursor-pointer", children: [
|
|
2263
|
+
/* @__PURE__ */ jsx(
|
|
2264
|
+
"input",
|
|
2265
|
+
{
|
|
2266
|
+
type: "checkbox",
|
|
2267
|
+
checked: rememberChoice,
|
|
2268
|
+
onChange: (e) => setRememberChoice(e.target.checked),
|
|
2269
|
+
className: "rounded border-gray-300"
|
|
2270
|
+
}
|
|
2271
|
+
),
|
|
2272
|
+
"Don't ask again"
|
|
2273
|
+
] }),
|
|
2274
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
2275
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: handleReject, children: "Deny" }),
|
|
2276
|
+
/* @__PURE__ */ jsx(Button, { variant: "default", size: "sm", onClick: handleApprove, children: "Allow" })
|
|
2277
|
+
] })
|
|
2278
|
+
] })
|
|
2279
|
+
]
|
|
2280
|
+
}
|
|
2281
|
+
);
|
|
2282
|
+
}
|
|
2283
|
+
function parseFollowUps(content) {
|
|
2284
|
+
if (!content) {
|
|
2285
|
+
return { cleanContent: content, followUps: [] };
|
|
2286
|
+
}
|
|
2287
|
+
const followUpRegex = /\[FOLLOWUP:\s*([^\]]+)\]/gi;
|
|
2288
|
+
const matches = content.match(followUpRegex);
|
|
2289
|
+
if (!matches || matches.length === 0) {
|
|
2290
|
+
return { cleanContent: content, followUps: [] };
|
|
2291
|
+
}
|
|
2292
|
+
const lastMatch = matches[matches.length - 1];
|
|
2293
|
+
const innerContent = lastMatch.replace(/\[FOLLOWUP:\s*|\]/gi, "");
|
|
2294
|
+
const followUps = innerContent.split("|").map((q) => q.trim()).filter((q) => q.length > 0);
|
|
2295
|
+
const cleanContent = content.replace(followUpRegex, "").trim();
|
|
2296
|
+
return { cleanContent, followUps };
|
|
2297
|
+
}
|
|
2298
|
+
function FollowUpQuestions({
|
|
2299
|
+
questions,
|
|
2300
|
+
onSelect,
|
|
2301
|
+
className,
|
|
2302
|
+
buttonClassName
|
|
2303
|
+
}) {
|
|
2304
|
+
if (!questions || questions.length === 0) {
|
|
2305
|
+
return null;
|
|
2306
|
+
}
|
|
2307
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-2 mt-2", className), children: questions.map((question, index) => /* @__PURE__ */ jsx(
|
|
2308
|
+
"button",
|
|
2309
|
+
{
|
|
2310
|
+
onClick: () => onSelect(question),
|
|
2311
|
+
className: cn(
|
|
2312
|
+
"px-3 py-1.5 text-sm rounded-full",
|
|
2313
|
+
"bg-primary/10 hover:bg-primary/20 text-primary",
|
|
2314
|
+
"border border-primary/20 hover:border-primary/40",
|
|
2315
|
+
"transition-colors duration-150",
|
|
2316
|
+
"text-left whitespace-nowrap",
|
|
2317
|
+
buttonClassName
|
|
2318
|
+
),
|
|
2319
|
+
children: question
|
|
2320
|
+
},
|
|
2321
|
+
index
|
|
2322
|
+
)) });
|
|
2323
|
+
}
|
|
2324
|
+
function DevLogger({
|
|
2325
|
+
state,
|
|
2326
|
+
position = "bottom-right",
|
|
2327
|
+
className
|
|
2328
|
+
}) {
|
|
2329
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
2330
|
+
const [activeTab, setActiveTab] = useState("chat");
|
|
2331
|
+
const positionClasses = {
|
|
2332
|
+
"bottom-left": "bottom-4 left-4",
|
|
2333
|
+
"bottom-right": "bottom-4 right-4",
|
|
2334
|
+
"top-left": "top-4 left-4",
|
|
2335
|
+
"top-right": "top-4 right-4"
|
|
2336
|
+
};
|
|
2337
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2338
|
+
/* @__PURE__ */ jsx(
|
|
2339
|
+
"button",
|
|
2340
|
+
{
|
|
2341
|
+
type: "button",
|
|
2342
|
+
onClick: () => setIsOpen(true),
|
|
2343
|
+
className: cn(
|
|
2344
|
+
"fixed z-[9999] flex items-center justify-center",
|
|
2345
|
+
"w-12 h-12 rounded-full shadow-lg",
|
|
2346
|
+
"bg-orange-500 hover:bg-orange-600 text-white",
|
|
2347
|
+
"transition-transform hover:scale-110",
|
|
2348
|
+
positionClasses[position],
|
|
2349
|
+
className
|
|
2350
|
+
),
|
|
2351
|
+
title: "Open SDK DevLogger",
|
|
2352
|
+
children: /* @__PURE__ */ jsx(
|
|
2353
|
+
"svg",
|
|
2354
|
+
{
|
|
2355
|
+
className: "w-6 h-6",
|
|
2356
|
+
fill: "none",
|
|
2357
|
+
viewBox: "0 0 24 24",
|
|
2358
|
+
stroke: "currentColor",
|
|
2359
|
+
strokeWidth: 2,
|
|
2360
|
+
children: /* @__PURE__ */ jsx(
|
|
2361
|
+
"path",
|
|
2362
|
+
{
|
|
2363
|
+
strokeLinecap: "round",
|
|
2364
|
+
strokeLinejoin: "round",
|
|
2365
|
+
d: "M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
|
|
2366
|
+
}
|
|
2367
|
+
)
|
|
2368
|
+
}
|
|
2369
|
+
)
|
|
2370
|
+
}
|
|
2371
|
+
),
|
|
2372
|
+
isOpen && /* @__PURE__ */ jsx(
|
|
2373
|
+
"div",
|
|
2374
|
+
{
|
|
2375
|
+
className: "fixed inset-0 z-[10000] flex items-center justify-center bg-black/50",
|
|
2376
|
+
onClick: () => setIsOpen(false),
|
|
2377
|
+
children: /* @__PURE__ */ jsxs(
|
|
2378
|
+
"div",
|
|
2379
|
+
{
|
|
2380
|
+
className: "bg-background border rounded-lg shadow-xl w-[600px] max-h-[80vh] overflow-hidden",
|
|
2381
|
+
onClick: (e) => e.stopPropagation(),
|
|
2382
|
+
children: [
|
|
2383
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b bg-muted/50", children: [
|
|
2384
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2385
|
+
/* @__PURE__ */ jsx("div", { className: "w-3 h-3 rounded-full bg-orange-500" }),
|
|
2386
|
+
/* @__PURE__ */ jsx("h2", { className: "font-semibold text-sm", children: "Copilot SDK DevLogger" })
|
|
2387
|
+
] }),
|
|
2388
|
+
/* @__PURE__ */ jsx(
|
|
2389
|
+
"button",
|
|
2390
|
+
{
|
|
2391
|
+
type: "button",
|
|
2392
|
+
onClick: () => setIsOpen(false),
|
|
2393
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
2394
|
+
children: /* @__PURE__ */ jsx(
|
|
2395
|
+
"svg",
|
|
2396
|
+
{
|
|
2397
|
+
className: "w-5 h-5",
|
|
2398
|
+
fill: "none",
|
|
2399
|
+
viewBox: "0 0 24 24",
|
|
2400
|
+
stroke: "currentColor",
|
|
2401
|
+
children: /* @__PURE__ */ jsx(
|
|
2402
|
+
"path",
|
|
2403
|
+
{
|
|
2404
|
+
strokeLinecap: "round",
|
|
2405
|
+
strokeLinejoin: "round",
|
|
2406
|
+
strokeWidth: 2,
|
|
2407
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
2408
|
+
}
|
|
2409
|
+
)
|
|
2410
|
+
}
|
|
2411
|
+
)
|
|
2412
|
+
}
|
|
2413
|
+
)
|
|
2414
|
+
] }),
|
|
2415
|
+
/* @__PURE__ */ jsx("div", { className: "flex border-b", children: ["chat", "tools", "agent", "config"].map((tab) => /* @__PURE__ */ jsx(
|
|
2416
|
+
"button",
|
|
2417
|
+
{
|
|
2418
|
+
type: "button",
|
|
2419
|
+
onClick: () => setActiveTab(tab),
|
|
2420
|
+
className: cn(
|
|
2421
|
+
"px-4 py-2 text-sm font-medium capitalize",
|
|
2422
|
+
activeTab === tab ? "border-b-2 border-primary text-primary" : "text-muted-foreground hover:text-foreground"
|
|
2423
|
+
),
|
|
2424
|
+
children: tab
|
|
2425
|
+
},
|
|
2426
|
+
tab
|
|
2427
|
+
)) }),
|
|
2428
|
+
/* @__PURE__ */ jsxs("div", { className: "p-4 overflow-y-auto max-h-[60vh]", children: [
|
|
2429
|
+
activeTab === "chat" && /* @__PURE__ */ jsx(ChatTab, { state }),
|
|
2430
|
+
activeTab === "tools" && /* @__PURE__ */ jsx(ToolsTab, { state }),
|
|
2431
|
+
activeTab === "agent" && /* @__PURE__ */ jsx(AgentTab, { state }),
|
|
2432
|
+
activeTab === "config" && /* @__PURE__ */ jsx(ConfigTab, { state })
|
|
2433
|
+
] })
|
|
2434
|
+
]
|
|
2435
|
+
}
|
|
2436
|
+
)
|
|
2437
|
+
}
|
|
2438
|
+
)
|
|
2439
|
+
] });
|
|
2440
|
+
}
|
|
2441
|
+
function ChatTab({ state }) {
|
|
2442
|
+
return /* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs(Section, { title: "Status", children: [
|
|
2443
|
+
/* @__PURE__ */ jsx(Row, { label: "Loading", value: state.chat.isLoading ? "Yes" : "No" }),
|
|
2444
|
+
/* @__PURE__ */ jsx(Row, { label: "Message Count", value: state.chat.messageCount }),
|
|
2445
|
+
/* @__PURE__ */ jsx(Row, { label: "Thread ID", value: state.chat.threadId, mono: true }),
|
|
2446
|
+
/* @__PURE__ */ jsx(
|
|
2447
|
+
Row,
|
|
2448
|
+
{
|
|
2449
|
+
label: "Error",
|
|
2450
|
+
value: state.chat.error || "None",
|
|
2451
|
+
valueClass: state.chat.error ? "text-red-500" : "text-green-500"
|
|
2452
|
+
}
|
|
2453
|
+
)
|
|
2454
|
+
] }) });
|
|
2455
|
+
}
|
|
2456
|
+
function ToolsTab({ state }) {
|
|
2457
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
2458
|
+
/* @__PURE__ */ jsxs(Section, { title: "Smart Context", children: [
|
|
2459
|
+
/* @__PURE__ */ jsx(Row, { label: "Enabled", value: state.tools.isEnabled ? "Yes" : "No" }),
|
|
2460
|
+
/* @__PURE__ */ jsx(Row, { label: "Capturing", value: state.tools.isCapturing ? "Yes" : "No" }),
|
|
2461
|
+
/* @__PURE__ */ jsx(
|
|
2462
|
+
Row,
|
|
2463
|
+
{
|
|
2464
|
+
label: "Pending Consent",
|
|
2465
|
+
value: state.tools.pendingConsent ? "Yes" : "No"
|
|
2466
|
+
}
|
|
2467
|
+
)
|
|
2468
|
+
] }),
|
|
2469
|
+
/* @__PURE__ */ jsx(Section, { title: "Registered Tools", children: state.registered.tools.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No tools registered" }) : /* @__PURE__ */ jsx("div", { className: "space-y-1", children: state.registered.tools.map((tool) => /* @__PURE__ */ jsxs(
|
|
2470
|
+
"div",
|
|
2471
|
+
{
|
|
2472
|
+
className: "flex items-center justify-between text-sm",
|
|
2473
|
+
children: [
|
|
2474
|
+
/* @__PURE__ */ jsx("code", { className: "bg-muted px-1.5 py-0.5 rounded text-xs", children: tool.name }),
|
|
2475
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: tool.location })
|
|
2476
|
+
]
|
|
2477
|
+
},
|
|
2478
|
+
tool.name
|
|
2479
|
+
)) }) }),
|
|
2480
|
+
/* @__PURE__ */ jsxs(Section, { title: "Permissions", children: [
|
|
2481
|
+
/* @__PURE__ */ jsx(Row, { label: "Loaded", value: state.permissions.loaded ? "Yes" : "No" }),
|
|
2482
|
+
state.permissions.stored.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-1", children: state.permissions.stored.map((p) => /* @__PURE__ */ jsxs(
|
|
2483
|
+
"div",
|
|
2484
|
+
{
|
|
2485
|
+
className: "flex items-center justify-between text-sm",
|
|
2486
|
+
children: [
|
|
2487
|
+
/* @__PURE__ */ jsx("code", { className: "bg-muted px-1.5 py-0.5 rounded text-xs", children: p.toolName }),
|
|
2488
|
+
/* @__PURE__ */ jsx(Badge, { level: p.level })
|
|
2489
|
+
]
|
|
2490
|
+
},
|
|
2491
|
+
p.toolName
|
|
2492
|
+
)) })
|
|
2493
|
+
] })
|
|
2494
|
+
] });
|
|
2495
|
+
}
|
|
2496
|
+
function AgentTab({ state }) {
|
|
2497
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
2498
|
+
/* @__PURE__ */ jsxs(Section, { title: "Loop State", children: [
|
|
2499
|
+
/* @__PURE__ */ jsx(
|
|
2500
|
+
Row,
|
|
2501
|
+
{
|
|
2502
|
+
label: "Iteration",
|
|
2503
|
+
value: `${state.agentLoop.iteration} / ${state.agentLoop.maxIterations}`
|
|
2504
|
+
}
|
|
2505
|
+
),
|
|
2506
|
+
/* @__PURE__ */ jsx(
|
|
2507
|
+
Row,
|
|
2508
|
+
{
|
|
2509
|
+
label: "Pending Approvals",
|
|
2510
|
+
value: state.agentLoop.pendingApprovals
|
|
2511
|
+
}
|
|
2512
|
+
)
|
|
2513
|
+
] }),
|
|
2514
|
+
/* @__PURE__ */ jsx(Section, { title: "Tool Executions", children: state.agentLoop.toolExecutions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No executions" }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: state.agentLoop.toolExecutions.map((exec) => /* @__PURE__ */ jsxs(
|
|
2515
|
+
"div",
|
|
2516
|
+
{
|
|
2517
|
+
className: "border rounded p-2 text-sm space-y-1",
|
|
2518
|
+
children: [
|
|
2519
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2520
|
+
/* @__PURE__ */ jsx("code", { className: "font-medium", children: exec.name }),
|
|
2521
|
+
/* @__PURE__ */ jsx(StatusBadge, { status: exec.status })
|
|
2522
|
+
] }),
|
|
2523
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
|
|
2524
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2525
|
+
"ID: ",
|
|
2526
|
+
exec.id.slice(0, 12),
|
|
2527
|
+
"..."
|
|
2528
|
+
] }),
|
|
2529
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2530
|
+
"Approval: ",
|
|
2531
|
+
exec.approvalStatus
|
|
2532
|
+
] })
|
|
2533
|
+
] })
|
|
2534
|
+
]
|
|
2535
|
+
},
|
|
2536
|
+
exec.id
|
|
2537
|
+
)) }) }),
|
|
2538
|
+
/* @__PURE__ */ jsx(Section, { title: "Registered Actions", children: state.registered.actions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No actions registered" }) : /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: state.registered.actions.map((action) => /* @__PURE__ */ jsx(
|
|
2539
|
+
"code",
|
|
2540
|
+
{
|
|
2541
|
+
className: "bg-muted px-1.5 py-0.5 rounded text-xs",
|
|
2542
|
+
children: action.name
|
|
2543
|
+
},
|
|
2544
|
+
action.name
|
|
2545
|
+
)) }) }),
|
|
2546
|
+
/* @__PURE__ */ jsx(Section, { title: "Context Tree", children: /* @__PURE__ */ jsx(Row, { label: "Context Items", value: state.registered.contextCount }) })
|
|
2547
|
+
] });
|
|
2548
|
+
}
|
|
2549
|
+
function ConfigTab({ state }) {
|
|
2550
|
+
return /* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs(Section, { title: "Provider", children: [
|
|
2551
|
+
/* @__PURE__ */ jsx(Row, { label: "Provider", value: state.config.provider || "Not set" }),
|
|
2552
|
+
/* @__PURE__ */ jsx(Row, { label: "Model", value: state.config.model || "Default" }),
|
|
2553
|
+
/* @__PURE__ */ jsx(
|
|
2554
|
+
Row,
|
|
2555
|
+
{
|
|
2556
|
+
label: "Runtime URL",
|
|
2557
|
+
value: state.config.runtimeUrl || "Not set",
|
|
2558
|
+
mono: true
|
|
2559
|
+
}
|
|
2560
|
+
)
|
|
2561
|
+
] }) });
|
|
2562
|
+
}
|
|
2563
|
+
function Section({
|
|
2564
|
+
title,
|
|
2565
|
+
children
|
|
2566
|
+
}) {
|
|
2567
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
2568
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-2", children: title }),
|
|
2569
|
+
children
|
|
2570
|
+
] });
|
|
2571
|
+
}
|
|
2572
|
+
function Row({
|
|
2573
|
+
label,
|
|
2574
|
+
value,
|
|
2575
|
+
mono,
|
|
2576
|
+
valueClass
|
|
2577
|
+
}) {
|
|
2578
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-1 text-sm", children: [
|
|
2579
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label }),
|
|
2580
|
+
/* @__PURE__ */ jsx(
|
|
2581
|
+
"span",
|
|
2582
|
+
{
|
|
2583
|
+
className: cn(
|
|
2584
|
+
mono && "font-mono text-xs bg-muted px-1.5 py-0.5 rounded",
|
|
2585
|
+
valueClass
|
|
2586
|
+
),
|
|
2587
|
+
children: value
|
|
2588
|
+
}
|
|
2589
|
+
)
|
|
2590
|
+
] });
|
|
2591
|
+
}
|
|
2592
|
+
function Badge({ level }) {
|
|
2593
|
+
const colors = {
|
|
2594
|
+
allow_always: "bg-green-100 text-green-800",
|
|
2595
|
+
deny_always: "bg-red-100 text-red-800",
|
|
2596
|
+
session: "bg-blue-100 text-blue-800",
|
|
2597
|
+
ask: "bg-gray-100 text-gray-800"
|
|
2598
|
+
};
|
|
2599
|
+
return /* @__PURE__ */ jsx(
|
|
2600
|
+
"span",
|
|
2601
|
+
{
|
|
2602
|
+
className: cn(
|
|
2603
|
+
"px-1.5 py-0.5 rounded text-xs font-medium",
|
|
2604
|
+
colors[level] || colors.ask
|
|
2605
|
+
),
|
|
2606
|
+
children: level
|
|
2607
|
+
}
|
|
2608
|
+
);
|
|
2609
|
+
}
|
|
2610
|
+
function StatusBadge({ status }) {
|
|
2611
|
+
const colors = {
|
|
2612
|
+
pending: "bg-yellow-100 text-yellow-800",
|
|
2613
|
+
executing: "bg-blue-100 text-blue-800",
|
|
2614
|
+
completed: "bg-green-100 text-green-800",
|
|
2615
|
+
error: "bg-red-100 text-red-800"
|
|
2616
|
+
};
|
|
2617
|
+
return /* @__PURE__ */ jsx(
|
|
2618
|
+
"span",
|
|
2619
|
+
{
|
|
2620
|
+
className: cn(
|
|
2621
|
+
"px-1.5 py-0.5 rounded text-xs font-medium",
|
|
2622
|
+
colors[status] || "bg-gray-100 text-gray-800"
|
|
2623
|
+
),
|
|
2624
|
+
children: status
|
|
2625
|
+
}
|
|
2626
|
+
);
|
|
2627
|
+
}
|
|
2628
|
+
var icons = {
|
|
2629
|
+
vision: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
2630
|
+
/* @__PURE__ */ jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
|
|
2631
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" })
|
|
2632
|
+
] }),
|
|
2633
|
+
tools: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" }) }),
|
|
2634
|
+
thinking: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
2635
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
2636
|
+
/* @__PURE__ */ jsx("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
|
|
2637
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
|
|
2638
|
+
] }),
|
|
2639
|
+
streaming: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { d: "M22 12h-4l-3 9L9 3l-3 9H2" }) }),
|
|
2640
|
+
pdf: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
2641
|
+
/* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
2642
|
+
/* @__PURE__ */ jsx("polyline", { points: "14 2 14 8 20 8" }),
|
|
2643
|
+
/* @__PURE__ */ jsx("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
|
|
2644
|
+
/* @__PURE__ */ jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
|
|
2645
|
+
/* @__PURE__ */ jsx("polyline", { points: "10 9 9 9 8 9" })
|
|
2646
|
+
] }),
|
|
2647
|
+
audio: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
2648
|
+
/* @__PURE__ */ jsx("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
|
|
2649
|
+
/* @__PURE__ */ jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
2650
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
|
|
2651
|
+
/* @__PURE__ */ jsx("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
|
|
2652
|
+
] }),
|
|
2653
|
+
video: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
2654
|
+
/* @__PURE__ */ jsx("polygon", { points: "23 7 16 12 23 17 23 7" }),
|
|
2655
|
+
/* @__PURE__ */ jsx("rect", { x: "1", y: "5", width: "15", height: "14", rx: "2", ry: "2" })
|
|
2656
|
+
] }),
|
|
2657
|
+
json: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
2658
|
+
/* @__PURE__ */ jsx("path", { d: "M4 6h16" }),
|
|
2659
|
+
/* @__PURE__ */ jsx("path", { d: "M4 12h16" }),
|
|
2660
|
+
/* @__PURE__ */ jsx("path", { d: "M4 18h12" })
|
|
2661
|
+
] })
|
|
2662
|
+
};
|
|
2663
|
+
var labels = {
|
|
2664
|
+
vision: "Vision",
|
|
2665
|
+
tools: "Tools",
|
|
2666
|
+
thinking: "Thinking",
|
|
2667
|
+
streaming: "Streaming",
|
|
2668
|
+
pdf: "PDF",
|
|
2669
|
+
audio: "Audio",
|
|
2670
|
+
video: "Video",
|
|
2671
|
+
json: "JSON"
|
|
2672
|
+
};
|
|
2673
|
+
var descriptions = {
|
|
2674
|
+
vision: "Supports image inputs",
|
|
2675
|
+
tools: "Supports function calling",
|
|
2676
|
+
thinking: "Extended reasoning mode",
|
|
2677
|
+
streaming: "Real-time streaming",
|
|
2678
|
+
pdf: "Can process PDF files",
|
|
2679
|
+
audio: "Supports audio inputs",
|
|
2680
|
+
video: "Supports video inputs",
|
|
2681
|
+
json: "Structured JSON output"
|
|
2682
|
+
};
|
|
2683
|
+
function CapabilityBadge({
|
|
2684
|
+
type,
|
|
2685
|
+
supported = true,
|
|
2686
|
+
showLabel = false,
|
|
2687
|
+
size = "sm",
|
|
2688
|
+
className
|
|
2689
|
+
}) {
|
|
2690
|
+
const sizeClasses = {
|
|
2691
|
+
sm: "h-5 px-1.5 text-[10px]",
|
|
2692
|
+
md: "h-6 px-2 text-xs",
|
|
2693
|
+
lg: "h-7 px-2.5 text-sm"
|
|
2694
|
+
};
|
|
2695
|
+
const iconSizes = {
|
|
2696
|
+
sm: "w-3 h-3",
|
|
2697
|
+
md: "w-3.5 h-3.5",
|
|
2698
|
+
lg: "w-4 h-4"
|
|
2699
|
+
};
|
|
2700
|
+
return /* @__PURE__ */ jsxs(
|
|
2701
|
+
"div",
|
|
2702
|
+
{
|
|
2703
|
+
className: cn(
|
|
2704
|
+
"inline-flex items-center gap-1 rounded-full font-medium transition-colors",
|
|
2705
|
+
sizeClasses[size],
|
|
2706
|
+
supported ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground opacity-50",
|
|
2707
|
+
className
|
|
2708
|
+
),
|
|
2709
|
+
title: `${labels[type]}: ${descriptions[type]}`,
|
|
2710
|
+
children: [
|
|
2711
|
+
/* @__PURE__ */ jsx("span", { className: cn("flex-shrink-0", iconSizes[size]), children: icons[type] }),
|
|
2712
|
+
showLabel && /* @__PURE__ */ jsx("span", { children: labels[type] })
|
|
2713
|
+
]
|
|
2714
|
+
}
|
|
2715
|
+
);
|
|
2716
|
+
}
|
|
2717
|
+
function CapabilityList({
|
|
2718
|
+
capabilities,
|
|
2719
|
+
showLabels = false,
|
|
2720
|
+
onlySupported = true,
|
|
2721
|
+
size = "sm",
|
|
2722
|
+
className
|
|
2723
|
+
}) {
|
|
2724
|
+
const items = [
|
|
2725
|
+
{ type: "vision", supported: capabilities.supportsVision ?? false },
|
|
2726
|
+
{ type: "tools", supported: capabilities.supportsTools ?? false },
|
|
2727
|
+
{ type: "thinking", supported: capabilities.supportsThinking ?? false },
|
|
2728
|
+
{ type: "streaming", supported: capabilities.supportsStreaming ?? false },
|
|
2729
|
+
{ type: "pdf", supported: capabilities.supportsPDF ?? false },
|
|
2730
|
+
{ type: "audio", supported: capabilities.supportsAudio ?? false },
|
|
2731
|
+
{ type: "video", supported: capabilities.supportsVideo ?? false },
|
|
2732
|
+
{ type: "json", supported: capabilities.supportsJsonMode ?? false }
|
|
2733
|
+
];
|
|
2734
|
+
const filteredItems = onlySupported ? items.filter((item) => item.supported) : items;
|
|
2735
|
+
if (filteredItems.length === 0) return null;
|
|
2736
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-1", className), children: filteredItems.map((item) => /* @__PURE__ */ jsx(
|
|
2737
|
+
CapabilityBadge,
|
|
2738
|
+
{
|
|
2739
|
+
type: item.type,
|
|
2740
|
+
supported: item.supported,
|
|
2741
|
+
showLabel: showLabels,
|
|
2742
|
+
size
|
|
2743
|
+
},
|
|
2744
|
+
item.type
|
|
2745
|
+
)) });
|
|
2746
|
+
}
|
|
2747
|
+
function ModelSelector({
|
|
2748
|
+
value,
|
|
2749
|
+
onChange,
|
|
2750
|
+
providers,
|
|
2751
|
+
models,
|
|
2752
|
+
currentCapabilities,
|
|
2753
|
+
placeholder = "Select model...",
|
|
2754
|
+
disabled = false,
|
|
2755
|
+
size = "md",
|
|
2756
|
+
showCapabilities = true,
|
|
2757
|
+
className
|
|
2758
|
+
}) {
|
|
2759
|
+
const [isOpen, setIsOpen] = React8.useState(false);
|
|
2760
|
+
const containerRef = React8.useRef(null);
|
|
2761
|
+
React8.useEffect(() => {
|
|
2762
|
+
function handleClickOutside(event) {
|
|
2763
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
2764
|
+
setIsOpen(false);
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
2768
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
2769
|
+
}, []);
|
|
2770
|
+
const selectedModel = React8.useMemo(() => {
|
|
2771
|
+
if (!value) return null;
|
|
2772
|
+
if (providers) {
|
|
2773
|
+
for (const provider of providers) {
|
|
2774
|
+
const model = provider.models.find((m) => m.id === value);
|
|
2775
|
+
if (model) return { ...model, provider: provider.name };
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
if (models) {
|
|
2779
|
+
return models.find((m) => m.id === value) || null;
|
|
2780
|
+
}
|
|
2781
|
+
return null;
|
|
2782
|
+
}, [value, providers, models]);
|
|
2783
|
+
const sizeClasses = {
|
|
2784
|
+
sm: "h-8 text-xs px-2",
|
|
2785
|
+
md: "h-9 text-sm px-3",
|
|
2786
|
+
lg: "h-10 text-base px-4"
|
|
2787
|
+
};
|
|
2788
|
+
const handleSelect = (modelId, provider) => {
|
|
2789
|
+
onChange?.(modelId, provider);
|
|
2790
|
+
setIsOpen(false);
|
|
2791
|
+
};
|
|
2792
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: cn("relative", className), children: [
|
|
2793
|
+
/* @__PURE__ */ jsxs(
|
|
2794
|
+
"button",
|
|
2795
|
+
{
|
|
2796
|
+
type: "button",
|
|
2797
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
2798
|
+
disabled,
|
|
2799
|
+
className: cn(
|
|
2800
|
+
"flex items-center justify-between gap-2 w-full rounded-md border bg-background",
|
|
2801
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
2802
|
+
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
2803
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
2804
|
+
sizeClasses[size]
|
|
2805
|
+
),
|
|
2806
|
+
children: [
|
|
2807
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 min-w-0", children: selectedModel ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2808
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: selectedModel.name || selectedModel.id }),
|
|
2809
|
+
selectedModel.provider && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-[10px] uppercase", children: selectedModel.provider })
|
|
2810
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: placeholder }) }),
|
|
2811
|
+
/* @__PURE__ */ jsx(
|
|
2812
|
+
"svg",
|
|
2813
|
+
{
|
|
2814
|
+
className: cn(
|
|
2815
|
+
"w-4 h-4 flex-shrink-0 text-muted-foreground transition-transform",
|
|
2816
|
+
isOpen && "rotate-180"
|
|
2817
|
+
),
|
|
2818
|
+
fill: "none",
|
|
2819
|
+
viewBox: "0 0 24 24",
|
|
2820
|
+
stroke: "currentColor",
|
|
2821
|
+
strokeWidth: 2,
|
|
2822
|
+
children: /* @__PURE__ */ jsx(
|
|
2823
|
+
"path",
|
|
2824
|
+
{
|
|
2825
|
+
strokeLinecap: "round",
|
|
2826
|
+
strokeLinejoin: "round",
|
|
2827
|
+
d: "M19 9l-7 7-7-7"
|
|
2828
|
+
}
|
|
2829
|
+
)
|
|
2830
|
+
}
|
|
2831
|
+
)
|
|
2832
|
+
]
|
|
2833
|
+
}
|
|
2834
|
+
),
|
|
2835
|
+
showCapabilities && currentCapabilities && /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
|
|
2836
|
+
CapabilityList,
|
|
2837
|
+
{
|
|
2838
|
+
capabilities: currentCapabilities,
|
|
2839
|
+
size: "sm",
|
|
2840
|
+
onlySupported: true
|
|
2841
|
+
}
|
|
2842
|
+
) }),
|
|
2843
|
+
isOpen && /* @__PURE__ */ jsxs(
|
|
2844
|
+
"div",
|
|
2845
|
+
{
|
|
2846
|
+
className: cn(
|
|
2847
|
+
"absolute z-50 top-full left-0 right-0 mt-1",
|
|
2848
|
+
"max-h-[300px] overflow-auto",
|
|
2849
|
+
"rounded-md border bg-popover text-popover-foreground shadow-md",
|
|
2850
|
+
"animate-in fade-in-0 zoom-in-95"
|
|
2851
|
+
),
|
|
2852
|
+
children: [
|
|
2853
|
+
providers?.map((provider) => /* @__PURE__ */ jsxs("div", { children: [
|
|
2854
|
+
/* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-[10px] font-semibold text-muted-foreground uppercase tracking-wider bg-muted/50", children: provider.label || provider.name }),
|
|
2855
|
+
provider.models.map((model) => /* @__PURE__ */ jsxs(
|
|
2856
|
+
"button",
|
|
2857
|
+
{
|
|
2858
|
+
type: "button",
|
|
2859
|
+
onClick: () => handleSelect(model.id, provider.name),
|
|
2860
|
+
className: cn(
|
|
2861
|
+
"flex flex-col gap-0.5 w-full px-3 py-2 text-left",
|
|
2862
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
2863
|
+
"focus:bg-accent focus:text-accent-foreground focus:outline-none",
|
|
2864
|
+
value === model.id && "bg-accent"
|
|
2865
|
+
),
|
|
2866
|
+
children: [
|
|
2867
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2868
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: model.name || model.id }),
|
|
2869
|
+
value === model.id && /* @__PURE__ */ jsx(
|
|
2870
|
+
"svg",
|
|
2871
|
+
{
|
|
2872
|
+
className: "w-4 h-4 text-primary",
|
|
2873
|
+
fill: "none",
|
|
2874
|
+
viewBox: "0 0 24 24",
|
|
2875
|
+
stroke: "currentColor",
|
|
2876
|
+
strokeWidth: 2,
|
|
2877
|
+
children: /* @__PURE__ */ jsx(
|
|
2878
|
+
"path",
|
|
2879
|
+
{
|
|
2880
|
+
strokeLinecap: "round",
|
|
2881
|
+
strokeLinejoin: "round",
|
|
2882
|
+
d: "M5 13l4 4L19 7"
|
|
2883
|
+
}
|
|
2884
|
+
)
|
|
2885
|
+
}
|
|
2886
|
+
)
|
|
2887
|
+
] }),
|
|
2888
|
+
showCapabilities && model.capabilities && /* @__PURE__ */ jsx(
|
|
2889
|
+
CapabilityList,
|
|
2890
|
+
{
|
|
2891
|
+
capabilities: model.capabilities,
|
|
2892
|
+
size: "sm",
|
|
2893
|
+
onlySupported: true
|
|
2894
|
+
}
|
|
2895
|
+
)
|
|
2896
|
+
]
|
|
2897
|
+
},
|
|
2898
|
+
model.id
|
|
2899
|
+
))
|
|
2900
|
+
] }, provider.name)),
|
|
2901
|
+
models?.map((model) => /* @__PURE__ */ jsxs(
|
|
2902
|
+
"button",
|
|
2903
|
+
{
|
|
2904
|
+
type: "button",
|
|
2905
|
+
onClick: () => handleSelect(model.id, model.provider),
|
|
2906
|
+
className: cn(
|
|
2907
|
+
"flex flex-col gap-0.5 w-full px-3 py-2 text-left",
|
|
2908
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
2909
|
+
"focus:bg-accent focus:text-accent-foreground focus:outline-none",
|
|
2910
|
+
value === model.id && "bg-accent"
|
|
2911
|
+
),
|
|
2912
|
+
children: [
|
|
2913
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2914
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: model.name || model.id }),
|
|
2915
|
+
model.provider && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-[10px] uppercase", children: model.provider }),
|
|
2916
|
+
value === model.id && /* @__PURE__ */ jsx(
|
|
2917
|
+
"svg",
|
|
2918
|
+
{
|
|
2919
|
+
className: "w-4 h-4 text-primary ml-auto",
|
|
2920
|
+
fill: "none",
|
|
2921
|
+
viewBox: "0 0 24 24",
|
|
2922
|
+
stroke: "currentColor",
|
|
2923
|
+
strokeWidth: 2,
|
|
2924
|
+
children: /* @__PURE__ */ jsx(
|
|
2925
|
+
"path",
|
|
2926
|
+
{
|
|
2927
|
+
strokeLinecap: "round",
|
|
2928
|
+
strokeLinejoin: "round",
|
|
2929
|
+
d: "M5 13l4 4L19 7"
|
|
2930
|
+
}
|
|
2931
|
+
)
|
|
2932
|
+
}
|
|
2933
|
+
)
|
|
2934
|
+
] }),
|
|
2935
|
+
showCapabilities && model.capabilities && /* @__PURE__ */ jsx(
|
|
2936
|
+
CapabilityList,
|
|
2937
|
+
{
|
|
2938
|
+
capabilities: model.capabilities,
|
|
2939
|
+
size: "sm",
|
|
2940
|
+
onlySupported: true
|
|
2941
|
+
}
|
|
2942
|
+
)
|
|
2943
|
+
]
|
|
2944
|
+
},
|
|
2945
|
+
model.id
|
|
2946
|
+
)),
|
|
2947
|
+
!providers?.length && !models?.length && /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No models available" })
|
|
2948
|
+
]
|
|
2949
|
+
}
|
|
2950
|
+
)
|
|
2951
|
+
] });
|
|
2952
|
+
}
|
|
2953
|
+
function SimpleModelSelector({
|
|
2954
|
+
value,
|
|
2955
|
+
onChange,
|
|
2956
|
+
models,
|
|
2957
|
+
disabled = false,
|
|
2958
|
+
className
|
|
2959
|
+
}) {
|
|
2960
|
+
return /* @__PURE__ */ jsxs(
|
|
2961
|
+
"select",
|
|
2962
|
+
{
|
|
2963
|
+
value: value || "",
|
|
2964
|
+
onChange: (e) => onChange?.(e.target.value),
|
|
2965
|
+
disabled,
|
|
2966
|
+
className: cn(
|
|
2967
|
+
"h-9 px-3 rounded-md border bg-background text-sm",
|
|
2968
|
+
"focus:outline-none focus:ring-2 focus:ring-ring",
|
|
2969
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
2970
|
+
className
|
|
2971
|
+
),
|
|
2972
|
+
children: [
|
|
2973
|
+
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select model..." }),
|
|
2974
|
+
models.map((modelId) => /* @__PURE__ */ jsx("option", { value: modelId, children: modelId }, modelId))
|
|
2975
|
+
]
|
|
2976
|
+
}
|
|
2977
|
+
);
|
|
2978
|
+
}
|
|
2979
|
+
function ChatHeader({ title, onClose, className }) {
|
|
2980
|
+
return /* @__PURE__ */ jsxs(
|
|
2981
|
+
"div",
|
|
2982
|
+
{
|
|
2983
|
+
className: cn(
|
|
2984
|
+
"flex items-center justify-between border-b px-4 py-3",
|
|
2985
|
+
className
|
|
2986
|
+
),
|
|
2987
|
+
children: [
|
|
2988
|
+
/* @__PURE__ */ jsx("h2", { className: "font-semibold text-foreground", children: title || "Chat" }),
|
|
2989
|
+
onClose && /* @__PURE__ */ jsx(
|
|
2990
|
+
"button",
|
|
2991
|
+
{
|
|
2992
|
+
type: "button",
|
|
2993
|
+
onClick: onClose,
|
|
2994
|
+
className: "rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
2995
|
+
"aria-label": "Close chat",
|
|
2996
|
+
children: /* @__PURE__ */ jsx(CloseIcon, { className: "h-5 w-5" })
|
|
2997
|
+
}
|
|
2998
|
+
)
|
|
2999
|
+
]
|
|
3000
|
+
}
|
|
3001
|
+
);
|
|
3002
|
+
}
|
|
3003
|
+
function Suggestions({
|
|
3004
|
+
suggestions,
|
|
3005
|
+
onSuggestionClick,
|
|
3006
|
+
className
|
|
3007
|
+
}) {
|
|
3008
|
+
if (!suggestions.length) return null;
|
|
3009
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-2 px-4 py-2", className), children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsx(
|
|
3010
|
+
"button",
|
|
3011
|
+
{
|
|
3012
|
+
type: "button",
|
|
3013
|
+
onClick: () => onSuggestionClick?.(suggestion),
|
|
3014
|
+
className: "inline-flex items-center rounded-full border bg-background px-3 py-1.5 text-sm transition-colors hover:bg-muted",
|
|
3015
|
+
children: suggestion
|
|
3016
|
+
},
|
|
3017
|
+
index
|
|
3018
|
+
)) });
|
|
3019
|
+
}
|
|
3020
|
+
function DefaultMessage({
|
|
3021
|
+
message,
|
|
3022
|
+
userAvatar,
|
|
3023
|
+
assistantAvatar,
|
|
3024
|
+
showUserAvatar = false,
|
|
3025
|
+
userMessageClassName,
|
|
3026
|
+
assistantMessageClassName,
|
|
3027
|
+
size = "sm",
|
|
3028
|
+
isLastMessage = false,
|
|
3029
|
+
isLoading = false,
|
|
3030
|
+
toolRenderers,
|
|
3031
|
+
onApproveToolExecution,
|
|
3032
|
+
onRejectToolExecution,
|
|
3033
|
+
showFollowUps = true,
|
|
3034
|
+
onFollowUpClick,
|
|
3035
|
+
followUpClassName,
|
|
3036
|
+
followUpButtonClassName
|
|
3037
|
+
}) {
|
|
3038
|
+
const isUser = message.role === "user";
|
|
3039
|
+
const isStreaming = isLastMessage && isLoading;
|
|
3040
|
+
const { cleanContent, followUps } = React8.useMemo(() => {
|
|
3041
|
+
if (isUser || !message.content) {
|
|
3042
|
+
return { cleanContent: message.content, followUps: [] };
|
|
3043
|
+
}
|
|
3044
|
+
return parseFollowUps(message.content);
|
|
3045
|
+
}, [message.content, isUser]);
|
|
3046
|
+
const shouldShowFollowUps = showFollowUps && !isUser && isLastMessage && !isLoading && followUps.length > 0 && onFollowUpClick;
|
|
3047
|
+
if (isUser) {
|
|
3048
|
+
const hasAttachments = message.attachments && message.attachments.length > 0;
|
|
3049
|
+
return /* @__PURE__ */ jsxs(
|
|
3050
|
+
Message,
|
|
3051
|
+
{
|
|
3052
|
+
className: cn(
|
|
3053
|
+
"flex gap-2",
|
|
3054
|
+
showUserAvatar ? "justify-end" : "justify-end"
|
|
3055
|
+
),
|
|
3056
|
+
children: [
|
|
3057
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end max-w-[80%]", children: [
|
|
3058
|
+
message.content && /* @__PURE__ */ jsx(
|
|
3059
|
+
MessageContent,
|
|
3060
|
+
{
|
|
3061
|
+
className: cn(
|
|
3062
|
+
"rounded-lg px-4 py-2 bg-primary text-primary-foreground",
|
|
3063
|
+
userMessageClassName
|
|
3064
|
+
),
|
|
3065
|
+
size,
|
|
3066
|
+
children: message.content
|
|
3067
|
+
}
|
|
3068
|
+
),
|
|
3069
|
+
hasAttachments && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsx(AttachmentPreview, { attachment }, index)) })
|
|
3070
|
+
] }),
|
|
3071
|
+
showUserAvatar && /* @__PURE__ */ jsx(
|
|
3072
|
+
MessageAvatar,
|
|
3073
|
+
{
|
|
3074
|
+
src: userAvatar.src || "",
|
|
3075
|
+
alt: "User",
|
|
3076
|
+
fallback: userAvatar.fallback
|
|
3077
|
+
}
|
|
3078
|
+
)
|
|
3079
|
+
]
|
|
3080
|
+
}
|
|
3081
|
+
);
|
|
3082
|
+
}
|
|
3083
|
+
const pendingApprovalTools = message.toolExecutions?.filter(
|
|
3084
|
+
(exec) => exec.approvalStatus === "required"
|
|
3085
|
+
);
|
|
3086
|
+
const completedTools = message.toolExecutions?.filter(
|
|
3087
|
+
(exec) => exec.approvalStatus !== "required"
|
|
3088
|
+
);
|
|
3089
|
+
const toolsWithCustomRenderer = completedTools?.filter(
|
|
3090
|
+
(exec) => toolRenderers && toolRenderers[exec.name]
|
|
3091
|
+
);
|
|
3092
|
+
const toolsWithoutCustomRenderer = completedTools?.filter(
|
|
3093
|
+
(exec) => !toolRenderers || !toolRenderers[exec.name]
|
|
3094
|
+
);
|
|
3095
|
+
const toolSteps = toolsWithoutCustomRenderer?.map((exec) => ({
|
|
3096
|
+
id: exec.id,
|
|
3097
|
+
name: exec.name,
|
|
3098
|
+
args: exec.args,
|
|
3099
|
+
status: exec.status,
|
|
3100
|
+
result: exec.result,
|
|
3101
|
+
error: exec.error
|
|
3102
|
+
}));
|
|
3103
|
+
return /* @__PURE__ */ jsxs(Message, { className: "flex gap-2", children: [
|
|
3104
|
+
/* @__PURE__ */ jsx(
|
|
3105
|
+
MessageAvatar,
|
|
3106
|
+
{
|
|
3107
|
+
src: assistantAvatar.src || "",
|
|
3108
|
+
alt: "Assistant",
|
|
3109
|
+
fallback: assistantAvatar.fallback,
|
|
3110
|
+
className: "bg-primary text-primary-foreground"
|
|
3111
|
+
}
|
|
3112
|
+
),
|
|
3113
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 max-w-[80%]", children: [
|
|
3114
|
+
message.thinking && /* @__PURE__ */ jsx(
|
|
3115
|
+
SimpleReasoning,
|
|
3116
|
+
{
|
|
3117
|
+
content: message.thinking,
|
|
3118
|
+
isStreaming,
|
|
3119
|
+
className: "mb-2"
|
|
3120
|
+
}
|
|
3121
|
+
),
|
|
3122
|
+
cleanContent?.trim() && /* @__PURE__ */ jsx(
|
|
3123
|
+
MessageContent,
|
|
3124
|
+
{
|
|
3125
|
+
className: cn(
|
|
3126
|
+
"rounded-lg px-4 py-2 bg-muted",
|
|
3127
|
+
assistantMessageClassName
|
|
3128
|
+
),
|
|
3129
|
+
markdown: true,
|
|
3130
|
+
size,
|
|
3131
|
+
children: cleanContent
|
|
3132
|
+
}
|
|
3133
|
+
),
|
|
3134
|
+
toolsWithCustomRenderer && toolsWithCustomRenderer.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: toolsWithCustomRenderer.map((exec) => {
|
|
3135
|
+
const Renderer = toolRenderers[exec.name];
|
|
3136
|
+
return /* @__PURE__ */ jsx(
|
|
3137
|
+
Renderer,
|
|
3138
|
+
{
|
|
3139
|
+
execution: {
|
|
3140
|
+
id: exec.id,
|
|
3141
|
+
name: exec.name,
|
|
3142
|
+
args: exec.args,
|
|
3143
|
+
status: exec.status,
|
|
3144
|
+
result: exec.result,
|
|
3145
|
+
error: exec.error,
|
|
3146
|
+
approvalStatus: exec.approvalStatus
|
|
3147
|
+
}
|
|
3148
|
+
},
|
|
3149
|
+
exec.id
|
|
3150
|
+
);
|
|
3151
|
+
}) }),
|
|
3152
|
+
toolSteps && toolSteps.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 rounded-lg bg-muted/50 px-3 py-2", children: /* @__PURE__ */ jsx(ToolSteps, { steps: toolSteps }) }),
|
|
3153
|
+
pendingApprovalTools && pendingApprovalTools.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: pendingApprovalTools.map((tool) => /* @__PURE__ */ jsx(
|
|
3154
|
+
PermissionConfirmation,
|
|
3155
|
+
{
|
|
3156
|
+
state: "pending",
|
|
3157
|
+
toolName: tool.name,
|
|
3158
|
+
message: tool.approvalMessage || `This tool wants to execute. Do you approve?`,
|
|
3159
|
+
onApprove: (permissionLevel) => onApproveToolExecution?.(tool.id, permissionLevel),
|
|
3160
|
+
onReject: (permissionLevel) => onRejectToolExecution?.(tool.id, void 0, permissionLevel)
|
|
3161
|
+
},
|
|
3162
|
+
tool.id
|
|
3163
|
+
)) }),
|
|
3164
|
+
message.attachments && message.attachments.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsx(AttachmentPreview, { attachment }, index)) }),
|
|
3165
|
+
shouldShowFollowUps && /* @__PURE__ */ jsx(
|
|
3166
|
+
FollowUpQuestions,
|
|
3167
|
+
{
|
|
3168
|
+
questions: followUps,
|
|
3169
|
+
onSelect: onFollowUpClick,
|
|
3170
|
+
className: followUpClassName,
|
|
3171
|
+
buttonClassName: followUpButtonClassName
|
|
3172
|
+
}
|
|
3173
|
+
)
|
|
3174
|
+
] })
|
|
3175
|
+
] });
|
|
3176
|
+
}
|
|
3177
|
+
function AttachmentPreview({ attachment }) {
|
|
3178
|
+
const [expanded, setExpanded] = React8.useState(false);
|
|
3179
|
+
if (attachment.type !== "image") {
|
|
3180
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm", children: [
|
|
3181
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: attachment.type }),
|
|
3182
|
+
/* @__PURE__ */ jsx("span", { children: attachment.filename || "Attachment" })
|
|
3183
|
+
] });
|
|
3184
|
+
}
|
|
3185
|
+
let src;
|
|
3186
|
+
if (attachment.url) {
|
|
3187
|
+
src = attachment.url;
|
|
3188
|
+
} else if (attachment.data) {
|
|
3189
|
+
src = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType};base64,${attachment.data}`;
|
|
3190
|
+
} else {
|
|
3191
|
+
return null;
|
|
3192
|
+
}
|
|
3193
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3194
|
+
/* @__PURE__ */ jsx(
|
|
3195
|
+
"button",
|
|
3196
|
+
{
|
|
3197
|
+
type: "button",
|
|
3198
|
+
onClick: () => setExpanded(true),
|
|
3199
|
+
className: "relative rounded-lg overflow-hidden border bg-muted/50 hover:opacity-90 transition-opacity",
|
|
3200
|
+
children: /* @__PURE__ */ jsx(
|
|
3201
|
+
"img",
|
|
3202
|
+
{
|
|
3203
|
+
src,
|
|
3204
|
+
alt: attachment.filename || "Image",
|
|
3205
|
+
className: "max-w-[200px] max-h-[150px] object-cover"
|
|
3206
|
+
}
|
|
3207
|
+
)
|
|
3208
|
+
}
|
|
3209
|
+
),
|
|
3210
|
+
expanded && /* @__PURE__ */ jsx(
|
|
3211
|
+
"div",
|
|
3212
|
+
{
|
|
3213
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80",
|
|
3214
|
+
onClick: () => setExpanded(false),
|
|
3215
|
+
children: /* @__PURE__ */ jsxs("div", { className: "relative max-w-[90vw] max-h-[90vh]", children: [
|
|
3216
|
+
/* @__PURE__ */ jsx(
|
|
3217
|
+
"img",
|
|
3218
|
+
{
|
|
3219
|
+
src,
|
|
3220
|
+
alt: attachment.filename || "Image (expanded)",
|
|
3221
|
+
className: "max-w-full max-h-full object-contain rounded-lg"
|
|
3222
|
+
}
|
|
3223
|
+
),
|
|
3224
|
+
/* @__PURE__ */ jsx(
|
|
3225
|
+
"button",
|
|
3226
|
+
{
|
|
3227
|
+
type: "button",
|
|
3228
|
+
className: "absolute top-2 right-2 bg-white/90 rounded-full p-2 hover:bg-white transition-colors",
|
|
3229
|
+
onClick: (e) => {
|
|
3230
|
+
e.stopPropagation();
|
|
3231
|
+
setExpanded(false);
|
|
3232
|
+
},
|
|
3233
|
+
children: /* @__PURE__ */ jsx(
|
|
3234
|
+
"svg",
|
|
3235
|
+
{
|
|
3236
|
+
className: "w-4 h-4",
|
|
3237
|
+
fill: "none",
|
|
3238
|
+
viewBox: "0 0 24 24",
|
|
3239
|
+
stroke: "currentColor",
|
|
3240
|
+
strokeWidth: 2,
|
|
3241
|
+
children: /* @__PURE__ */ jsx(
|
|
3242
|
+
"path",
|
|
3243
|
+
{
|
|
3244
|
+
strokeLinecap: "round",
|
|
3245
|
+
strokeLinejoin: "round",
|
|
3246
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
3247
|
+
}
|
|
3248
|
+
)
|
|
3249
|
+
}
|
|
3250
|
+
)
|
|
3251
|
+
}
|
|
3252
|
+
)
|
|
3253
|
+
] })
|
|
3254
|
+
}
|
|
3255
|
+
)
|
|
3256
|
+
] });
|
|
3257
|
+
}
|
|
3258
|
+
var DEFAULT_MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
3259
|
+
var DEFAULT_ALLOWED_TYPES = ["image/*", "application/pdf"];
|
|
3260
|
+
function getAttachmentType(mimeType) {
|
|
3261
|
+
if (mimeType.startsWith("image/")) return "image";
|
|
3262
|
+
if (mimeType.startsWith("audio/")) return "audio";
|
|
3263
|
+
if (mimeType.startsWith("video/")) return "video";
|
|
3264
|
+
return "file";
|
|
3265
|
+
}
|
|
3266
|
+
function fileToBase64(file) {
|
|
3267
|
+
return new Promise((resolve, reject) => {
|
|
3268
|
+
const reader = new FileReader();
|
|
3269
|
+
reader.onload = () => {
|
|
3270
|
+
if (typeof reader.result === "string") {
|
|
3271
|
+
resolve(reader.result);
|
|
3272
|
+
} else {
|
|
3273
|
+
reject(new Error("Failed to read file"));
|
|
3274
|
+
}
|
|
3275
|
+
};
|
|
3276
|
+
reader.onerror = () => reject(new Error("Failed to read file"));
|
|
3277
|
+
reader.readAsDataURL(file);
|
|
3278
|
+
});
|
|
3279
|
+
}
|
|
3280
|
+
function generateAttachmentId() {
|
|
3281
|
+
return `att_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
3282
|
+
}
|
|
3283
|
+
function Chat({
|
|
3284
|
+
// Core
|
|
3285
|
+
messages = [],
|
|
3286
|
+
onSendMessage,
|
|
3287
|
+
onStop,
|
|
3288
|
+
isLoading = false,
|
|
3289
|
+
// Labels
|
|
3290
|
+
placeholder = "Type a message...",
|
|
3291
|
+
welcomeMessage,
|
|
3292
|
+
title,
|
|
3293
|
+
// Header
|
|
3294
|
+
showHeader = false,
|
|
3295
|
+
onClose,
|
|
3296
|
+
// Appearance
|
|
3297
|
+
showPoweredBy = true,
|
|
3298
|
+
showUserAvatar = false,
|
|
3299
|
+
userAvatar = { fallback: "U" },
|
|
3300
|
+
assistantAvatar = { fallback: "AI" },
|
|
3301
|
+
loaderVariant = "typing",
|
|
3302
|
+
fontSize = "sm",
|
|
3303
|
+
// Attachments
|
|
3304
|
+
maxFileSize = DEFAULT_MAX_FILE_SIZE,
|
|
3305
|
+
allowedFileTypes = DEFAULT_ALLOWED_TYPES,
|
|
3306
|
+
attachmentsEnabled = true,
|
|
3307
|
+
attachmentsDisabledTooltip = "Attachments not supported by this model",
|
|
3308
|
+
processAttachment: processAttachmentProp,
|
|
3309
|
+
// Suggestions
|
|
3310
|
+
suggestions = [],
|
|
3311
|
+
onSuggestionClick,
|
|
3312
|
+
// Tool Executions
|
|
3313
|
+
isProcessing = false,
|
|
3314
|
+
toolRenderers,
|
|
3315
|
+
onApproveToolExecution,
|
|
3316
|
+
onRejectToolExecution,
|
|
3317
|
+
// Follow-up Questions
|
|
3318
|
+
showFollowUps = true,
|
|
3319
|
+
followUpClassName,
|
|
3320
|
+
followUpButtonClassName,
|
|
3321
|
+
// Custom rendering
|
|
3322
|
+
renderMessage,
|
|
3323
|
+
renderInput,
|
|
3324
|
+
renderHeader,
|
|
3325
|
+
// Styling
|
|
3326
|
+
className,
|
|
3327
|
+
classNames = {}
|
|
3328
|
+
}) {
|
|
3329
|
+
const [input, setInput] = useState("");
|
|
3330
|
+
const [pendingAttachments, setPendingAttachments] = useState([]);
|
|
3331
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
3332
|
+
const fileInputRef = useRef(null);
|
|
3333
|
+
const fileInputId = useId();
|
|
3334
|
+
const isFileTypeAllowed = useCallback(
|
|
3335
|
+
(file) => {
|
|
3336
|
+
for (const type of allowedFileTypes) {
|
|
3337
|
+
if (type.endsWith("/*")) {
|
|
3338
|
+
const category = type.slice(0, -2);
|
|
3339
|
+
if (file.type.startsWith(category + "/")) return true;
|
|
3340
|
+
} else if (file.type === type) {
|
|
3341
|
+
return true;
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3344
|
+
return false;
|
|
3345
|
+
},
|
|
3346
|
+
[allowedFileTypes]
|
|
3347
|
+
);
|
|
3348
|
+
const handleFileSelect = useCallback(
|
|
3349
|
+
async (files) => {
|
|
3350
|
+
if (!files || !attachmentsEnabled) return;
|
|
3351
|
+
for (const file of Array.from(files)) {
|
|
3352
|
+
if (file.size > maxFileSize) {
|
|
3353
|
+
const sizeMB = (maxFileSize / (1024 * 1024)).toFixed(0);
|
|
3354
|
+
console.warn(`File ${file.name} exceeds ${sizeMB}MB limit`);
|
|
3355
|
+
continue;
|
|
3356
|
+
}
|
|
3357
|
+
if (!isFileTypeAllowed(file)) {
|
|
3358
|
+
console.warn(`File type ${file.type} is not allowed`);
|
|
3359
|
+
continue;
|
|
3360
|
+
}
|
|
3361
|
+
const id = generateAttachmentId();
|
|
3362
|
+
const previewUrl = URL.createObjectURL(file);
|
|
3363
|
+
setPendingAttachments((prev) => [
|
|
3364
|
+
...prev,
|
|
3365
|
+
{
|
|
3366
|
+
id,
|
|
3367
|
+
file,
|
|
3368
|
+
previewUrl,
|
|
3369
|
+
attachment: {
|
|
3370
|
+
type: getAttachmentType(file.type),
|
|
3371
|
+
data: "",
|
|
3372
|
+
mimeType: file.type,
|
|
3373
|
+
filename: file.name
|
|
3374
|
+
},
|
|
3375
|
+
status: "processing"
|
|
3376
|
+
}
|
|
3377
|
+
]);
|
|
3378
|
+
try {
|
|
3379
|
+
let attachment;
|
|
3380
|
+
if (processAttachmentProp) {
|
|
3381
|
+
attachment = await processAttachmentProp(file);
|
|
3382
|
+
} else {
|
|
3383
|
+
const data = await fileToBase64(file);
|
|
3384
|
+
attachment = {
|
|
3385
|
+
type: getAttachmentType(file.type),
|
|
3386
|
+
data,
|
|
3387
|
+
mimeType: file.type,
|
|
3388
|
+
filename: file.name
|
|
3389
|
+
};
|
|
3390
|
+
}
|
|
3391
|
+
setPendingAttachments(
|
|
3392
|
+
(prev) => prev.map(
|
|
3393
|
+
(att) => att.id === id ? { ...att, status: "ready", attachment } : att
|
|
3394
|
+
)
|
|
3395
|
+
);
|
|
3396
|
+
} catch (error) {
|
|
3397
|
+
setPendingAttachments(
|
|
3398
|
+
(prev) => prev.map(
|
|
3399
|
+
(att) => att.id === id ? {
|
|
3400
|
+
...att,
|
|
3401
|
+
status: "error",
|
|
3402
|
+
error: "Failed to process file"
|
|
3403
|
+
} : att
|
|
3404
|
+
)
|
|
3405
|
+
);
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
},
|
|
3409
|
+
[attachmentsEnabled, maxFileSize, isFileTypeAllowed, processAttachmentProp]
|
|
3410
|
+
);
|
|
3411
|
+
const handleInputChange = useCallback(
|
|
3412
|
+
(e) => {
|
|
3413
|
+
handleFileSelect(e.target.files);
|
|
3414
|
+
if (fileInputRef.current) {
|
|
3415
|
+
fileInputRef.current.value = "";
|
|
3416
|
+
}
|
|
3417
|
+
},
|
|
3418
|
+
[handleFileSelect]
|
|
3419
|
+
);
|
|
3420
|
+
const removePendingAttachment = useCallback((id) => {
|
|
3421
|
+
setPendingAttachments((prev) => {
|
|
3422
|
+
const att = prev.find((a) => a.id === id);
|
|
3423
|
+
if (att) {
|
|
3424
|
+
URL.revokeObjectURL(att.previewUrl);
|
|
3425
|
+
}
|
|
3426
|
+
return prev.filter((a) => a.id !== id);
|
|
3427
|
+
});
|
|
3428
|
+
}, []);
|
|
3429
|
+
const handleDragOver = useCallback(
|
|
3430
|
+
(e) => {
|
|
3431
|
+
e.preventDefault();
|
|
3432
|
+
e.stopPropagation();
|
|
3433
|
+
if (attachmentsEnabled) {
|
|
3434
|
+
setIsDragging(true);
|
|
3435
|
+
}
|
|
3436
|
+
},
|
|
3437
|
+
[attachmentsEnabled]
|
|
3438
|
+
);
|
|
3439
|
+
const handleDragLeave = useCallback((e) => {
|
|
3440
|
+
e.preventDefault();
|
|
3441
|
+
e.stopPropagation();
|
|
3442
|
+
setIsDragging(false);
|
|
3443
|
+
}, []);
|
|
3444
|
+
const handleDrop = useCallback(
|
|
3445
|
+
(e) => {
|
|
3446
|
+
e.preventDefault();
|
|
3447
|
+
e.stopPropagation();
|
|
3448
|
+
setIsDragging(false);
|
|
3449
|
+
if (attachmentsEnabled) {
|
|
3450
|
+
handleFileSelect(e.dataTransfer.files);
|
|
3451
|
+
}
|
|
3452
|
+
},
|
|
3453
|
+
[attachmentsEnabled, handleFileSelect]
|
|
3454
|
+
);
|
|
3455
|
+
const handleSubmit = useCallback(() => {
|
|
3456
|
+
const hasContent = input.trim();
|
|
3457
|
+
const hasAttachments = pendingAttachments.some(
|
|
3458
|
+
(att) => att.status === "ready"
|
|
3459
|
+
);
|
|
3460
|
+
if (!hasContent && !hasAttachments || isLoading) return;
|
|
3461
|
+
const attachments = pendingAttachments.filter((att) => att.status === "ready").map((att) => att.attachment);
|
|
3462
|
+
onSendMessage?.(input, attachments.length > 0 ? attachments : void 0);
|
|
3463
|
+
pendingAttachments.forEach((att) => URL.revokeObjectURL(att.previewUrl));
|
|
3464
|
+
setPendingAttachments([]);
|
|
3465
|
+
setInput("");
|
|
3466
|
+
}, [input, isLoading, onSendMessage, pendingAttachments]);
|
|
3467
|
+
const handleSuggestionClick = useCallback(
|
|
3468
|
+
(suggestion) => {
|
|
3469
|
+
if (onSuggestionClick) {
|
|
3470
|
+
onSuggestionClick(suggestion);
|
|
3471
|
+
} else {
|
|
3472
|
+
onSendMessage?.(suggestion);
|
|
3473
|
+
}
|
|
3474
|
+
},
|
|
3475
|
+
[onSuggestionClick, onSendMessage]
|
|
3476
|
+
);
|
|
3477
|
+
const acceptString = allowedFileTypes.join(",");
|
|
3478
|
+
return /* @__PURE__ */ jsxs(
|
|
3479
|
+
"div",
|
|
3480
|
+
{
|
|
3481
|
+
className: cn(
|
|
3482
|
+
"flex h-full flex-col bg-background relative",
|
|
3483
|
+
className,
|
|
3484
|
+
classNames.root
|
|
3485
|
+
),
|
|
3486
|
+
onDragOver: handleDragOver,
|
|
3487
|
+
onDragLeave: handleDragLeave,
|
|
3488
|
+
onDrop: handleDrop,
|
|
3489
|
+
children: [
|
|
3490
|
+
isDragging && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-50 bg-primary/10 border-2 border-dashed border-primary flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "text-primary font-medium text-lg", children: "Drop files here" }) }),
|
|
3491
|
+
showHeader && (renderHeader ? renderHeader() : /* @__PURE__ */ jsx(
|
|
3492
|
+
ChatHeader,
|
|
3493
|
+
{
|
|
3494
|
+
title,
|
|
3495
|
+
onClose,
|
|
3496
|
+
className: classNames.header
|
|
3497
|
+
}
|
|
3498
|
+
)),
|
|
3499
|
+
/* @__PURE__ */ jsxs(
|
|
3500
|
+
ChatContainerRoot,
|
|
3501
|
+
{
|
|
3502
|
+
className: cn("relative flex-1", classNames.container),
|
|
3503
|
+
children: [
|
|
3504
|
+
/* @__PURE__ */ jsxs(
|
|
3505
|
+
ChatContainerContent,
|
|
3506
|
+
{
|
|
3507
|
+
className: cn("gap-4 p-4", classNames.messageList),
|
|
3508
|
+
children: [
|
|
3509
|
+
messages.length === 0 && /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-muted-foreground", children: welcomeMessage || "Send a message to start the conversation" }),
|
|
3510
|
+
messages.map((message, index) => {
|
|
3511
|
+
const isLastMessage = index === messages.length - 1;
|
|
3512
|
+
const isEmptyAssistant = message.role === "assistant" && !message.content?.trim();
|
|
3513
|
+
const hasToolCalls = message.tool_calls && message.tool_calls.length > 0;
|
|
3514
|
+
const hasToolExecutions = message.toolExecutions && message.toolExecutions.length > 0;
|
|
3515
|
+
const hasPendingApprovals = message.toolExecutions?.some(
|
|
3516
|
+
(exec) => exec.approvalStatus === "required"
|
|
3517
|
+
);
|
|
3518
|
+
if (isEmptyAssistant) {
|
|
3519
|
+
if (hasToolCalls || hasToolExecutions) ; else if (isLastMessage && hasPendingApprovals) ; else if (isLastMessage && isLoading && !isProcessing) {
|
|
3520
|
+
return /* @__PURE__ */ jsxs(Message, { className: "flex gap-2", children: [
|
|
3521
|
+
/* @__PURE__ */ jsx(
|
|
3522
|
+
MessageAvatar,
|
|
3523
|
+
{
|
|
3524
|
+
src: assistantAvatar.src || "",
|
|
3525
|
+
alt: "Assistant",
|
|
3526
|
+
fallback: assistantAvatar.fallback,
|
|
3527
|
+
className: "bg-primary text-primary-foreground"
|
|
3528
|
+
}
|
|
3529
|
+
),
|
|
3530
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsx(Loader, { variant: loaderVariant, size: "sm" }) })
|
|
3531
|
+
] }, message.id);
|
|
3532
|
+
} else {
|
|
3533
|
+
return null;
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
const savedExecutions = message.metadata?.toolExecutions;
|
|
3537
|
+
const messageToolExecutions = message.toolExecutions || savedExecutions;
|
|
3538
|
+
const messageWithExecutions = messageToolExecutions ? { ...message, toolExecutions: messageToolExecutions } : message;
|
|
3539
|
+
const handleFollowUpClick = (question) => {
|
|
3540
|
+
if (onSuggestionClick) {
|
|
3541
|
+
onSuggestionClick(question);
|
|
3542
|
+
} else {
|
|
3543
|
+
onSendMessage?.(question);
|
|
3544
|
+
}
|
|
3545
|
+
};
|
|
3546
|
+
return renderMessage ? /* @__PURE__ */ jsx(React8__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
|
|
3547
|
+
DefaultMessage,
|
|
3548
|
+
{
|
|
3549
|
+
message: messageWithExecutions,
|
|
3550
|
+
userAvatar,
|
|
3551
|
+
assistantAvatar,
|
|
3552
|
+
showUserAvatar,
|
|
3553
|
+
userMessageClassName: classNames.userMessage,
|
|
3554
|
+
assistantMessageClassName: classNames.assistantMessage,
|
|
3555
|
+
size: fontSize,
|
|
3556
|
+
isLastMessage,
|
|
3557
|
+
isLoading,
|
|
3558
|
+
toolRenderers,
|
|
3559
|
+
onApproveToolExecution,
|
|
3560
|
+
onRejectToolExecution,
|
|
3561
|
+
showFollowUps,
|
|
3562
|
+
onFollowUpClick: handleFollowUpClick,
|
|
3563
|
+
followUpClassName,
|
|
3564
|
+
followUpButtonClassName
|
|
3565
|
+
},
|
|
3566
|
+
message.id
|
|
3567
|
+
);
|
|
3568
|
+
}),
|
|
3569
|
+
isProcessing && /* @__PURE__ */ jsxs(Message, { className: "flex gap-2", children: [
|
|
3570
|
+
/* @__PURE__ */ jsx(
|
|
3571
|
+
MessageAvatar,
|
|
3572
|
+
{
|
|
3573
|
+
src: assistantAvatar?.src || "",
|
|
3574
|
+
alt: "Assistant",
|
|
3575
|
+
fallback: assistantAvatar?.fallback || "AI",
|
|
3576
|
+
className: "bg-primary text-primary-foreground"
|
|
3577
|
+
}
|
|
3578
|
+
),
|
|
3579
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg bg-muted px-4 py-2 flex items-center gap-2", children: [
|
|
3580
|
+
/* @__PURE__ */ jsx(Loader, { variant: "dots", size: "sm" }),
|
|
3581
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Continuing..." })
|
|
3582
|
+
] })
|
|
3583
|
+
] }),
|
|
3584
|
+
isLoading && !isProcessing && (() => {
|
|
3585
|
+
const lastMessage = messages[messages.length - 1];
|
|
3586
|
+
if (lastMessage?.role === "user") {
|
|
3587
|
+
return /* @__PURE__ */ jsxs(Message, { className: "flex gap-2", children: [
|
|
3588
|
+
/* @__PURE__ */ jsx(
|
|
3589
|
+
MessageAvatar,
|
|
3590
|
+
{
|
|
3591
|
+
src: assistantAvatar?.src || "",
|
|
3592
|
+
alt: "Assistant",
|
|
3593
|
+
fallback: assistantAvatar?.fallback || "AI",
|
|
3594
|
+
className: "bg-primary text-primary-foreground"
|
|
3595
|
+
}
|
|
3596
|
+
),
|
|
3597
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsx(Loader, { variant: loaderVariant, size: "sm" }) })
|
|
3598
|
+
] });
|
|
3599
|
+
}
|
|
3600
|
+
return null;
|
|
3601
|
+
})(),
|
|
3602
|
+
/* @__PURE__ */ jsx(ChatContainerScrollAnchor, {})
|
|
3603
|
+
]
|
|
3604
|
+
}
|
|
3605
|
+
),
|
|
3606
|
+
/* @__PURE__ */ jsx("div", { className: "absolute right-4 bottom-4", children: /* @__PURE__ */ jsx(ScrollButton, { className: "shadow-sm" }) })
|
|
3607
|
+
]
|
|
3608
|
+
}
|
|
3609
|
+
),
|
|
3610
|
+
suggestions.length > 0 && !isLoading && /* @__PURE__ */ jsx(
|
|
3611
|
+
Suggestions,
|
|
3612
|
+
{
|
|
3613
|
+
suggestions,
|
|
3614
|
+
onSuggestionClick: handleSuggestionClick,
|
|
3615
|
+
className: classNames.suggestions
|
|
3616
|
+
}
|
|
3617
|
+
),
|
|
3618
|
+
renderInput ? renderInput() : /* @__PURE__ */ jsxs("div", { className: cn("p-2", classNames.input), children: [
|
|
3619
|
+
pendingAttachments.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2 p-2 mb-2 bg-muted/30 rounded-lg", children: pendingAttachments.map((att) => /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
|
|
3620
|
+
att.attachment.type === "image" ? /* @__PURE__ */ jsx(
|
|
3621
|
+
"img",
|
|
3622
|
+
{
|
|
3623
|
+
src: att.previewUrl,
|
|
3624
|
+
alt: att.file.name,
|
|
3625
|
+
className: "w-16 h-16 object-cover rounded-lg border"
|
|
3626
|
+
}
|
|
3627
|
+
) : /* @__PURE__ */ jsxs("div", { className: "w-16 h-16 bg-muted rounded-lg border flex flex-col items-center justify-center p-1", children: [
|
|
3628
|
+
/* @__PURE__ */ jsx(
|
|
3629
|
+
"svg",
|
|
3630
|
+
{
|
|
3631
|
+
className: "w-6 h-6 text-muted-foreground",
|
|
3632
|
+
fill: "none",
|
|
3633
|
+
viewBox: "0 0 24 24",
|
|
3634
|
+
stroke: "currentColor",
|
|
3635
|
+
children: /* @__PURE__ */ jsx(
|
|
3636
|
+
"path",
|
|
3637
|
+
{
|
|
3638
|
+
strokeLinecap: "round",
|
|
3639
|
+
strokeLinejoin: "round",
|
|
3640
|
+
strokeWidth: 1.5,
|
|
3641
|
+
d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
|
3642
|
+
}
|
|
3643
|
+
)
|
|
3644
|
+
}
|
|
3645
|
+
),
|
|
3646
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground truncate w-full text-center mt-1", children: att.file.name.length > 10 ? att.file.name.slice(0, 8) + "..." : att.file.name })
|
|
3647
|
+
] }),
|
|
3648
|
+
att.status === "processing" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-background/80 rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsx(Loader, { variant: "dots", size: "sm" }) }),
|
|
3649
|
+
att.status === "error" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-destructive/20 rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "text-destructive text-xs", children: "Error" }) }),
|
|
3650
|
+
/* @__PURE__ */ jsx(
|
|
3651
|
+
"button",
|
|
3652
|
+
{
|
|
3653
|
+
onClick: () => removePendingAttachment(att.id),
|
|
3654
|
+
className: "absolute -top-1.5 -right-1.5 bg-destructive text-destructive-foreground rounded-full p-0.5 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
3655
|
+
type: "button",
|
|
3656
|
+
children: /* @__PURE__ */ jsx(XIcon2, { className: "w-3 h-3" })
|
|
3657
|
+
}
|
|
3658
|
+
)
|
|
3659
|
+
] }, att.id)) }),
|
|
3660
|
+
/* @__PURE__ */ jsxs(
|
|
3661
|
+
PromptInput,
|
|
3662
|
+
{
|
|
3663
|
+
value: input,
|
|
3664
|
+
onValueChange: setInput,
|
|
3665
|
+
isLoading,
|
|
3666
|
+
onSubmit: handleSubmit,
|
|
3667
|
+
className: "",
|
|
3668
|
+
children: [
|
|
3669
|
+
/* @__PURE__ */ jsx(PromptInputTextarea, { placeholder }),
|
|
3670
|
+
/* @__PURE__ */ jsxs(PromptInputActions, { className: "flex justify-between", children: [
|
|
3671
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
|
|
3672
|
+
PromptInputAction,
|
|
3673
|
+
{
|
|
3674
|
+
tooltip: attachmentsEnabled ? "Attach files" : attachmentsDisabledTooltip,
|
|
3675
|
+
children: /* @__PURE__ */ jsxs(
|
|
3676
|
+
"label",
|
|
3677
|
+
{
|
|
3678
|
+
htmlFor: fileInputId,
|
|
3679
|
+
className: cn(
|
|
3680
|
+
"flex h-8 w-8 items-center justify-center rounded-2xl",
|
|
3681
|
+
attachmentsEnabled ? "hover:bg-secondary-foreground/10 cursor-pointer" : "opacity-50 cursor-not-allowed"
|
|
3682
|
+
),
|
|
3683
|
+
children: [
|
|
3684
|
+
/* @__PURE__ */ jsx(
|
|
3685
|
+
"input",
|
|
3686
|
+
{
|
|
3687
|
+
ref: fileInputRef,
|
|
3688
|
+
type: "file",
|
|
3689
|
+
multiple: true,
|
|
3690
|
+
accept: acceptString,
|
|
3691
|
+
onChange: handleInputChange,
|
|
3692
|
+
className: "hidden",
|
|
3693
|
+
id: fileInputId,
|
|
3694
|
+
disabled: !attachmentsEnabled
|
|
3695
|
+
}
|
|
3696
|
+
),
|
|
3697
|
+
/* @__PURE__ */ jsx(PlusIcon, { className: "text-primary size-5" })
|
|
3698
|
+
]
|
|
3699
|
+
}
|
|
3700
|
+
)
|
|
3701
|
+
}
|
|
3702
|
+
) }),
|
|
3703
|
+
/* @__PURE__ */ jsx(PromptInputAction, { tooltip: isLoading ? "Stop" : "Send", children: isLoading ? /* @__PURE__ */ jsx(
|
|
3704
|
+
Button,
|
|
3705
|
+
{
|
|
3706
|
+
size: "sm",
|
|
3707
|
+
variant: "destructive",
|
|
3708
|
+
className: "rounded-full size-9",
|
|
3709
|
+
onClick: onStop,
|
|
3710
|
+
children: /* @__PURE__ */ jsx(StopIcon, { className: "h-4 w-4" })
|
|
3711
|
+
}
|
|
3712
|
+
) : /* @__PURE__ */ jsx(
|
|
3713
|
+
Button,
|
|
3714
|
+
{
|
|
3715
|
+
size: "sm",
|
|
3716
|
+
className: "rounded-full size-9",
|
|
3717
|
+
onClick: handleSubmit,
|
|
3718
|
+
disabled: !input.trim() && !pendingAttachments.some((att) => att.status === "ready"),
|
|
3719
|
+
children: /* @__PURE__ */ jsx(ArrowUpIcon, { className: "h-4 w-4" })
|
|
3720
|
+
}
|
|
3721
|
+
) })
|
|
3722
|
+
] })
|
|
3723
|
+
]
|
|
3724
|
+
}
|
|
3725
|
+
)
|
|
3726
|
+
] })
|
|
3727
|
+
]
|
|
3728
|
+
}
|
|
3729
|
+
);
|
|
3730
|
+
}
|
|
3731
|
+
function ToolExecutionMessage({
|
|
3732
|
+
executions,
|
|
3733
|
+
assistantAvatar = { fallback: "AI" },
|
|
3734
|
+
onApprove,
|
|
3735
|
+
onReject,
|
|
3736
|
+
className
|
|
3737
|
+
}) {
|
|
3738
|
+
if (!executions || executions.length === 0) return null;
|
|
3739
|
+
const pendingApprovals = executions.filter(
|
|
3740
|
+
(exec) => exec.approvalStatus === "required"
|
|
3741
|
+
);
|
|
3742
|
+
const otherExecutions = executions.filter(
|
|
3743
|
+
(exec) => exec.approvalStatus !== "required"
|
|
3744
|
+
);
|
|
3745
|
+
const toolSteps = otherExecutions.map((exec) => ({
|
|
3746
|
+
id: exec.id,
|
|
3747
|
+
name: exec.name,
|
|
3748
|
+
args: exec.args,
|
|
3749
|
+
status: exec.status,
|
|
3750
|
+
result: exec.result,
|
|
3751
|
+
error: exec.error
|
|
3752
|
+
}));
|
|
3753
|
+
const hasExecuting = executions.some((exec) => exec.status === "executing");
|
|
3754
|
+
executions.some((exec) => exec.status === "completed");
|
|
3755
|
+
const allCompleted = executions.every(
|
|
3756
|
+
(exec) => exec.status === "completed" || exec.status === "error"
|
|
3757
|
+
);
|
|
3758
|
+
return /* @__PURE__ */ jsxs(Message, { className: cn("flex gap-2", className), children: [
|
|
3759
|
+
/* @__PURE__ */ jsx(
|
|
3760
|
+
MessageAvatar,
|
|
3761
|
+
{
|
|
3762
|
+
src: assistantAvatar.src || "",
|
|
3763
|
+
alt: "Assistant",
|
|
3764
|
+
fallback: assistantAvatar.fallback,
|
|
3765
|
+
className: "bg-primary text-primary-foreground"
|
|
3766
|
+
}
|
|
3767
|
+
),
|
|
3768
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 max-w-[85%]", children: [
|
|
3769
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 mb-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3770
|
+
hasExecuting && /* @__PURE__ */ jsxs(
|
|
3771
|
+
"svg",
|
|
3772
|
+
{
|
|
3773
|
+
className: "size-3.5 animate-spin text-primary",
|
|
3774
|
+
fill: "none",
|
|
3775
|
+
viewBox: "0 0 24 24",
|
|
3776
|
+
children: [
|
|
3777
|
+
/* @__PURE__ */ jsx(
|
|
3778
|
+
"circle",
|
|
3779
|
+
{
|
|
3780
|
+
className: "opacity-25",
|
|
3781
|
+
cx: "12",
|
|
3782
|
+
cy: "12",
|
|
3783
|
+
r: "10",
|
|
3784
|
+
stroke: "currentColor",
|
|
3785
|
+
strokeWidth: "4"
|
|
3786
|
+
}
|
|
3787
|
+
),
|
|
3788
|
+
/* @__PURE__ */ jsx(
|
|
3789
|
+
"path",
|
|
3790
|
+
{
|
|
3791
|
+
className: "opacity-75",
|
|
3792
|
+
fill: "currentColor",
|
|
3793
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
3794
|
+
}
|
|
3795
|
+
)
|
|
3796
|
+
]
|
|
3797
|
+
}
|
|
3798
|
+
),
|
|
3799
|
+
!hasExecuting && allCompleted && /* @__PURE__ */ jsx(
|
|
3800
|
+
"svg",
|
|
3801
|
+
{
|
|
3802
|
+
className: "size-3.5 text-green-500",
|
|
3803
|
+
fill: "none",
|
|
3804
|
+
viewBox: "0 0 24 24",
|
|
3805
|
+
stroke: "currentColor",
|
|
3806
|
+
strokeWidth: 2.5,
|
|
3807
|
+
children: /* @__PURE__ */ jsx(
|
|
3808
|
+
"path",
|
|
3809
|
+
{
|
|
3810
|
+
strokeLinecap: "round",
|
|
3811
|
+
strokeLinejoin: "round",
|
|
3812
|
+
d: "M5 13l4 4L19 7"
|
|
3813
|
+
}
|
|
3814
|
+
)
|
|
3815
|
+
}
|
|
3816
|
+
),
|
|
3817
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: hasExecuting ? "Running tools..." : allCompleted ? `${executions.length} tool${executions.length > 1 ? "s" : ""} completed` : "Tools" })
|
|
3818
|
+
] }) }),
|
|
3819
|
+
pendingApprovals.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-2 space-y-2", children: pendingApprovals.map((tool) => /* @__PURE__ */ jsx(
|
|
3820
|
+
PermissionConfirmation,
|
|
3821
|
+
{
|
|
3822
|
+
state: "pending",
|
|
3823
|
+
toolName: tool.name,
|
|
3824
|
+
message: tool.approvalMessage || `This tool wants to execute. Do you approve?`,
|
|
3825
|
+
onApprove: (permissionLevel) => onApprove?.(tool.id, permissionLevel),
|
|
3826
|
+
onReject: (permissionLevel) => onReject?.(tool.id, void 0, permissionLevel)
|
|
3827
|
+
},
|
|
3828
|
+
tool.id
|
|
3829
|
+
)) }),
|
|
3830
|
+
toolSteps.length > 0 && /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card px-3 py-2.5 shadow-sm", children: /* @__PURE__ */ jsx(ToolSteps, { steps: toolSteps }) })
|
|
3831
|
+
] })
|
|
3832
|
+
] });
|
|
3833
|
+
}
|
|
3834
|
+
function CopilotChat(props) {
|
|
3835
|
+
const {
|
|
3836
|
+
messages,
|
|
3837
|
+
isLoading,
|
|
3838
|
+
sendMessage,
|
|
3839
|
+
stop,
|
|
3840
|
+
toolExecutions: rawToolExecutions,
|
|
3841
|
+
approveToolExecution,
|
|
3842
|
+
rejectToolExecution
|
|
3843
|
+
} = useCopilot();
|
|
3844
|
+
const toolExecutions = rawToolExecutions.map(
|
|
3845
|
+
(exec) => ({
|
|
3846
|
+
id: exec.id,
|
|
3847
|
+
name: exec.name,
|
|
3848
|
+
args: exec.args,
|
|
3849
|
+
status: exec.status,
|
|
3850
|
+
result: exec.result,
|
|
3851
|
+
error: exec.error,
|
|
3852
|
+
timestamp: exec.startedAt ? exec.startedAt.getTime() : Date.now(),
|
|
3853
|
+
approvalStatus: exec.approvalStatus
|
|
3854
|
+
})
|
|
3855
|
+
);
|
|
3856
|
+
const toolResultsMap = /* @__PURE__ */ new Map();
|
|
3857
|
+
messages.filter((m) => m.role === "tool" && m.toolCallId).forEach((m) => {
|
|
3858
|
+
toolResultsMap.set(m.toolCallId, m.content ?? "");
|
|
3859
|
+
});
|
|
3860
|
+
const visibleMessages = messages.filter((m) => m.role !== "tool").map((m) => {
|
|
3861
|
+
let messageToolExecutions;
|
|
3862
|
+
if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
|
|
3863
|
+
const toolCallIds = new Set(
|
|
3864
|
+
m.toolCalls.map((tc) => tc.id)
|
|
3865
|
+
);
|
|
3866
|
+
const liveExecutions = toolExecutions.filter(
|
|
3867
|
+
(exec) => toolCallIds.has(exec.id)
|
|
3868
|
+
);
|
|
3869
|
+
if (liveExecutions.length > 0) {
|
|
3870
|
+
messageToolExecutions = liveExecutions.map(
|
|
3871
|
+
(exec) => {
|
|
3872
|
+
if (!exec.result && toolResultsMap.has(exec.id)) {
|
|
3873
|
+
const resultContent = toolResultsMap.get(exec.id);
|
|
3874
|
+
try {
|
|
3875
|
+
return { ...exec, result: JSON.parse(resultContent) };
|
|
3876
|
+
} catch {
|
|
3877
|
+
return {
|
|
3878
|
+
...exec,
|
|
3879
|
+
result: { success: true, message: resultContent }
|
|
3880
|
+
};
|
|
3881
|
+
}
|
|
3882
|
+
}
|
|
3883
|
+
return exec;
|
|
3884
|
+
}
|
|
3885
|
+
);
|
|
3886
|
+
} else {
|
|
3887
|
+
messageToolExecutions = m.toolCalls.map(
|
|
3888
|
+
(tc) => {
|
|
3889
|
+
const resultContent = toolResultsMap.get(tc.id);
|
|
3890
|
+
let result = void 0;
|
|
3891
|
+
if (resultContent) {
|
|
3892
|
+
try {
|
|
3893
|
+
result = JSON.parse(resultContent);
|
|
3894
|
+
} catch {
|
|
3895
|
+
result = { success: true, message: resultContent };
|
|
3896
|
+
}
|
|
3897
|
+
}
|
|
3898
|
+
let args = {};
|
|
3899
|
+
try {
|
|
3900
|
+
args = JSON.parse(tc.function.arguments || "{}");
|
|
3901
|
+
} catch {
|
|
3902
|
+
}
|
|
3903
|
+
return {
|
|
3904
|
+
id: tc.id,
|
|
3905
|
+
name: tc.function.name,
|
|
3906
|
+
args,
|
|
3907
|
+
status: result ? "completed" : "pending",
|
|
3908
|
+
result,
|
|
3909
|
+
timestamp: Date.now()
|
|
3910
|
+
// Historical - use current time
|
|
3911
|
+
};
|
|
3912
|
+
}
|
|
3913
|
+
);
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
const savedExecutions = m.metadata?.toolExecutions;
|
|
3917
|
+
if (savedExecutions && savedExecutions.length > 0 && !messageToolExecutions) {
|
|
3918
|
+
messageToolExecutions = savedExecutions;
|
|
3919
|
+
}
|
|
3920
|
+
return {
|
|
3921
|
+
id: m.id,
|
|
3922
|
+
role: m.role,
|
|
3923
|
+
content: m.content ?? "",
|
|
3924
|
+
thinking: m.thinking,
|
|
3925
|
+
// Include attachments (images, files)
|
|
3926
|
+
attachments: m.attachments,
|
|
3927
|
+
// Include tool_calls for assistant messages
|
|
3928
|
+
tool_calls: m.toolCalls,
|
|
3929
|
+
// Attach matched tool executions to assistant messages
|
|
3930
|
+
toolExecutions: messageToolExecutions
|
|
3931
|
+
};
|
|
3932
|
+
});
|
|
3933
|
+
const suggestions = visibleMessages.length === 0 && props.suggestions?.length ? props.suggestions : [];
|
|
3934
|
+
const lastMessage = messages[messages.length - 1];
|
|
3935
|
+
const isInToolFlow = lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
|
|
3936
|
+
let isProcessingToolResults = false;
|
|
3937
|
+
if (isLoading && isInToolFlow) {
|
|
3938
|
+
const currentToolCallIds = new Set(
|
|
3939
|
+
lastMessage.toolCalls?.map(
|
|
3940
|
+
(tc) => tc.id
|
|
3941
|
+
) || []
|
|
3942
|
+
);
|
|
3943
|
+
const currentExecutions = toolExecutions.filter(
|
|
3944
|
+
(exec) => currentToolCallIds.has(exec.id)
|
|
3945
|
+
);
|
|
3946
|
+
const hasCompletedTools = currentExecutions.some(
|
|
3947
|
+
(exec) => exec.status === "completed" || exec.status === "error" || exec.status === "failed"
|
|
3948
|
+
);
|
|
3949
|
+
const hasExecutingTools = currentExecutions.some(
|
|
3950
|
+
(exec) => exec.status === "executing" || exec.status === "pending"
|
|
3951
|
+
);
|
|
3952
|
+
isProcessingToolResults = hasCompletedTools && !hasExecutingTools;
|
|
3953
|
+
}
|
|
3954
|
+
return /* @__PURE__ */ jsx(
|
|
3955
|
+
Chat,
|
|
3956
|
+
{
|
|
3957
|
+
...props,
|
|
3958
|
+
messages: visibleMessages,
|
|
3959
|
+
onSendMessage: sendMessage,
|
|
3960
|
+
onStop: stop,
|
|
3961
|
+
isLoading,
|
|
3962
|
+
showPoweredBy: props.showPoweredBy ?? true,
|
|
3963
|
+
suggestions,
|
|
3964
|
+
isProcessing: isProcessingToolResults,
|
|
3965
|
+
onApproveToolExecution: approveToolExecution,
|
|
3966
|
+
onRejectToolExecution: rejectToolExecution
|
|
3967
|
+
}
|
|
3968
|
+
);
|
|
3969
|
+
}
|
|
3970
|
+
var ConnectedChat = CopilotChat;
|
|
3971
|
+
function YourGPTLogo({ className }) {
|
|
3972
|
+
return /* @__PURE__ */ jsxs(
|
|
3973
|
+
"svg",
|
|
3974
|
+
{
|
|
3975
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3976
|
+
viewBox: "0 0 24 24",
|
|
3977
|
+
fill: "none",
|
|
3978
|
+
stroke: "currentColor",
|
|
3979
|
+
strokeWidth: "2",
|
|
3980
|
+
strokeLinecap: "round",
|
|
3981
|
+
strokeLinejoin: "round",
|
|
3982
|
+
className,
|
|
3983
|
+
children: [
|
|
3984
|
+
/* @__PURE__ */ jsx("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }),
|
|
3985
|
+
/* @__PURE__ */ jsx("path", { d: "M2 17l10 5 10-5" }),
|
|
3986
|
+
/* @__PURE__ */ jsx("path", { d: "M2 12l10 5 10-5" })
|
|
3987
|
+
]
|
|
3988
|
+
}
|
|
3989
|
+
);
|
|
3990
|
+
}
|
|
3991
|
+
function PoweredBy({ className, showLogo = true }) {
|
|
3992
|
+
return /* @__PURE__ */ jsxs(
|
|
3993
|
+
"div",
|
|
3994
|
+
{
|
|
3995
|
+
className: cn(
|
|
3996
|
+
"flex items-center justify-center gap-1.5 py-2 text-xs text-muted-foreground",
|
|
3997
|
+
className
|
|
3998
|
+
),
|
|
3999
|
+
children: [
|
|
4000
|
+
/* @__PURE__ */ jsx("span", { children: "Powered by" }),
|
|
4001
|
+
showLogo && /* @__PURE__ */ jsx(YourGPTLogo, { className: "h-3 w-3" }),
|
|
4002
|
+
/* @__PURE__ */ jsx(
|
|
4003
|
+
"a",
|
|
4004
|
+
{
|
|
4005
|
+
href: "https://yourgpt.ai",
|
|
4006
|
+
target: "_blank",
|
|
4007
|
+
rel: "noopener noreferrer",
|
|
4008
|
+
className: "font-medium text-foreground hover:underline",
|
|
4009
|
+
children: "YourGPT"
|
|
4010
|
+
}
|
|
4011
|
+
)
|
|
4012
|
+
]
|
|
4013
|
+
}
|
|
4014
|
+
);
|
|
4015
|
+
}
|
|
4016
|
+
|
|
4017
|
+
export { AlertTriangleIcon, BotIcon, Button, CapabilityBadge, CapabilityList, Chat, ChatContainerContent, ChatContainerRoot, ChatContainerScrollAnchor, CheckIcon, ChevronDownIcon2 as ChevronDownIcon, ChevronUpIcon, CloseIcon, CodeBlock, CompactPermissionConfirmation, Confirmation, ConfirmationActions, ConfirmationApproved, ConfirmationMessage, ConfirmationPending, ConfirmationRejected, ConnectedChat, CopilotChat, CopilotUIProvider, CopyIcon, DEFAULT_PERMISSION_OPTIONS, DevLogger, FeedbackBar, FollowUpQuestions, InlineToolSteps, Loader, Markdown, MessageAvatar, MessageContent, Message as MessagePrimitive, ModelSelector, PermissionConfirmation, PoweredBy, PromptInput, PromptInputAction, PromptInputActions, PromptInputTextarea, Reasoning, ReasoningContent, ReasoningTrigger, RefreshIcon, ScrollButton, SendIcon, SimpleConfirmation, SimpleModelSelector, SimpleReasoning, Source, SourceContent, SourceTrigger, StopIcon, ThumbsDownIcon2 as ThumbsDownIcon, ThumbsUpIcon2 as ThumbsUpIcon, ToolExecutionMessage, ToolStep, ToolSteps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserIcon, XIcon2 as XIcon, cn, parseFollowUps, useChatContainer, useCopilotUI };
|
|
4018
|
+
//# sourceMappingURL=index.js.map
|
|
4019
|
+
//# sourceMappingURL=index.js.map
|