@copilotkitnext/react 0.0.1

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.
Files changed (60) hide show
  1. package/.turbo/turbo-build$colon$css.log +9 -0
  2. package/.turbo/turbo-build.log +28 -0
  3. package/.turbo/turbo-check-types.log +0 -0
  4. package/.turbo/turbo-lint.log +78 -0
  5. package/.turbo/turbo-test.log +79 -0
  6. package/LICENSE +11 -0
  7. package/components.json +20 -0
  8. package/dist/index.d.mts +363 -0
  9. package/dist/index.d.ts +363 -0
  10. package/dist/index.js +2322 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/index.mjs +2291 -0
  13. package/dist/index.mjs.map +1 -0
  14. package/dist/styles.css +2 -0
  15. package/eslint.config.mjs +11 -0
  16. package/package.json +84 -0
  17. package/postcss.config.js +7 -0
  18. package/src/__tests__/setup.ts +2 -0
  19. package/src/components/chat/CopilotChat.tsx +90 -0
  20. package/src/components/chat/CopilotChatAssistantMessage.tsx +478 -0
  21. package/src/components/chat/CopilotChatAudioRecorder.tsx +157 -0
  22. package/src/components/chat/CopilotChatInput.tsx +596 -0
  23. package/src/components/chat/CopilotChatMessageView.tsx +85 -0
  24. package/src/components/chat/CopilotChatToolCallsView.tsx +43 -0
  25. package/src/components/chat/CopilotChatUserMessage.tsx +337 -0
  26. package/src/components/chat/CopilotChatView.tsx +385 -0
  27. package/src/components/chat/__tests__/CopilotChatAssistantMessage.test.tsx +684 -0
  28. package/src/components/chat/__tests__/CopilotChatInput.test.tsx +531 -0
  29. package/src/components/chat/__tests__/setup.ts +1 -0
  30. package/src/components/chat/index.ts +35 -0
  31. package/src/components/index.ts +4 -0
  32. package/src/components/ui/button.tsx +123 -0
  33. package/src/components/ui/dropdown-menu.tsx +257 -0
  34. package/src/components/ui/tooltip.tsx +59 -0
  35. package/src/hooks/index.ts +6 -0
  36. package/src/hooks/use-agent-context.tsx +17 -0
  37. package/src/hooks/use-agent.tsx +48 -0
  38. package/src/hooks/use-frontend-tool.tsx +46 -0
  39. package/src/hooks/use-human-in-the-loop.tsx +76 -0
  40. package/src/hooks/use-render-tool-call.tsx +81 -0
  41. package/src/index.ts +4 -0
  42. package/src/lib/__tests__/completePartialMarkdown.test.ts +495 -0
  43. package/src/lib/__tests__/renderSlot.test.tsx +610 -0
  44. package/src/lib/slots.tsx +55 -0
  45. package/src/lib/utils.ts +6 -0
  46. package/src/providers/CopilotChatConfigurationProvider.tsx +81 -0
  47. package/src/providers/CopilotKitProvider.tsx +269 -0
  48. package/src/providers/__tests__/CopilotKitProvider.test.tsx +487 -0
  49. package/src/providers/__tests__/CopilotKitProvider.wildcard.test.tsx +261 -0
  50. package/src/providers/index.ts +14 -0
  51. package/src/styles/globals.css +302 -0
  52. package/src/types/frontend-tool.ts +8 -0
  53. package/src/types/human-in-the-loop.ts +33 -0
  54. package/src/types/index.ts +3 -0
  55. package/src/types/react-tool-call-render.ts +29 -0
  56. package/tailwind.config.js +9 -0
  57. package/test.css +2355 -0
  58. package/tsconfig.json +23 -0
  59. package/tsup.config.ts +19 -0
  60. package/vitest.config.mjs +15 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,2291 @@
1
+ // src/components/chat/CopilotChatInput.tsx
2
+ import {
3
+ useState,
4
+ useRef as useRef2,
5
+ useEffect as useEffect2,
6
+ forwardRef as forwardRef2,
7
+ useImperativeHandle as useImperativeHandle2
8
+ } from "react";
9
+ import { twMerge as twMerge3 } from "tailwind-merge";
10
+ import { Plus, Settings2, Mic, ArrowUp, X, Check } from "lucide-react";
11
+
12
+ // src/providers/CopilotChatConfigurationProvider.tsx
13
+ import { createContext, useContext } from "react";
14
+ import { jsx } from "react/jsx-runtime";
15
+ var CopilotChatDefaultLabels = {
16
+ chatInputPlaceholder: "Type a message...",
17
+ chatInputToolbarStartTranscribeButtonLabel: "Transcribe",
18
+ chatInputToolbarCancelTranscribeButtonLabel: "Cancel",
19
+ chatInputToolbarFinishTranscribeButtonLabel: "Finish",
20
+ chatInputToolbarAddButtonLabel: "Add photos or files",
21
+ chatInputToolbarToolsButtonLabel: "Tools",
22
+ assistantMessageToolbarCopyCodeLabel: "Copy",
23
+ assistantMessageToolbarCopyCodeCopiedLabel: "Copied",
24
+ assistantMessageToolbarCopyMessageLabel: "Copy",
25
+ assistantMessageToolbarThumbsUpLabel: "Good response",
26
+ assistantMessageToolbarThumbsDownLabel: "Bad response",
27
+ assistantMessageToolbarReadAloudLabel: "Read aloud",
28
+ assistantMessageToolbarRegenerateLabel: "Regenerate",
29
+ userMessageToolbarCopyMessageLabel: "Copy",
30
+ userMessageToolbarEditMessageLabel: "Edit",
31
+ chatDisclaimerText: "AI can make mistakes. Please verify important information."
32
+ };
33
+ var CopilotChatConfiguration = createContext(null);
34
+ var CopilotChatConfigurationProvider = ({ children, labels = {}, inputValue, onSubmitInput, onChangeInput }) => {
35
+ const mergedLabels = {
36
+ ...CopilotChatDefaultLabels,
37
+ ...labels
38
+ };
39
+ const configurationValue = {
40
+ labels: mergedLabels,
41
+ inputValue,
42
+ onSubmitInput,
43
+ onChangeInput
44
+ };
45
+ return /* @__PURE__ */ jsx(CopilotChatConfiguration.Provider, { value: configurationValue, children });
46
+ };
47
+ var useCopilotChatConfiguration = () => {
48
+ const configuration = useContext(CopilotChatConfiguration);
49
+ if (!configuration) {
50
+ throw new Error(
51
+ "useCopilotChatConfiguration must be used within CopilotChatConfigurationProvider"
52
+ );
53
+ }
54
+ return configuration;
55
+ };
56
+
57
+ // src/components/ui/button.tsx
58
+ import { Slot } from "@radix-ui/react-slot";
59
+ import { cva } from "class-variance-authority";
60
+
61
+ // src/lib/utils.ts
62
+ import { clsx } from "clsx";
63
+ import { twMerge } from "tailwind-merge";
64
+ function cn(...inputs) {
65
+ return twMerge(clsx(inputs));
66
+ }
67
+
68
+ // src/components/ui/button.tsx
69
+ import { jsx as jsx2 } from "react/jsx-runtime";
70
+ var buttonVariants = cva(
71
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
72
+ {
73
+ variants: {
74
+ variant: {
75
+ default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
76
+ destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
77
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
78
+ secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
79
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 cursor-pointer",
80
+ link: "text-primary underline-offset-4 hover:underline",
81
+ assistantMessageToolbarButton: [
82
+ "cursor-pointer",
83
+ // Background and text
84
+ "p-0 text-[rgb(93,93,93)] hover:bg-[#E8E8E8]",
85
+ // Dark mode - lighter gray for better contrast
86
+ "dark:text-[rgb(243,243,243)] dark:hover:bg-[#303030]",
87
+ // Shape and sizing
88
+ "h-8 w-8",
89
+ // Interactions
90
+ "transition-colors",
91
+ // Hover states
92
+ "hover:text-[rgb(93,93,93)]",
93
+ "dark:hover:text-[rgb(243,243,243)]"
94
+ ],
95
+ chatInputToolbarPrimary: [
96
+ "cursor-pointer",
97
+ // Background and text
98
+ "bg-black text-white",
99
+ // Dark mode
100
+ "dark:bg-white dark:text-black dark:focus-visible:outline-white",
101
+ // Shape and sizing
102
+ "rounded-full",
103
+ // Interactions
104
+ "transition-colors",
105
+ // Focus states
106
+ "focus:outline-none",
107
+ // Hover states
108
+ "hover:opacity-70 disabled:hover:opacity-100",
109
+ // Disabled states
110
+ "disabled:cursor-not-allowed disabled:bg-[#00000014] disabled:text-[rgb(13,13,13)]",
111
+ "dark:disabled:bg-[#454545] dark:disabled:text-white "
112
+ ],
113
+ chatInputToolbarSecondary: [
114
+ "cursor-pointer",
115
+ // Background and text
116
+ "bg-transparent text-[#444444]",
117
+ // Dark mode
118
+ "dark:text-white dark:border-[#404040]",
119
+ // Shape and sizing
120
+ "rounded-full",
121
+ // Interactions
122
+ "transition-colors",
123
+ // Focus states
124
+ "focus:outline-none",
125
+ // Hover states
126
+ "hover:bg-[#f8f8f8] hover:text-[#333333]",
127
+ "dark:hover:bg-[#404040] dark:hover:text-[#FFFFFF]",
128
+ // Disabled states
129
+ "disabled:cursor-not-allowed disabled:opacity-50",
130
+ "disabled:hover:bg-transparent disabled:hover:text-[#444444]",
131
+ "dark:disabled:hover:bg-transparent dark:disabled:hover:text-[#CCCCCC]"
132
+ ]
133
+ },
134
+ size: {
135
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
136
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
137
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
138
+ icon: "size-9",
139
+ chatInputToolbarIcon: [
140
+ // Shape and sizing
141
+ "h-9 w-9 rounded-full"
142
+ ],
143
+ chatInputToolbarIconLabel: [
144
+ // Shape and sizing
145
+ "h-9 px-3 rounded-full",
146
+ // Layout
147
+ "gap-2",
148
+ // Typography
149
+ "font-normal"
150
+ ]
151
+ }
152
+ },
153
+ defaultVariants: {
154
+ variant: "default",
155
+ size: "default"
156
+ }
157
+ }
158
+ );
159
+ function Button({
160
+ className,
161
+ variant,
162
+ size,
163
+ asChild = false,
164
+ ...props
165
+ }) {
166
+ const Comp = asChild ? Slot : "button";
167
+ return /* @__PURE__ */ jsx2(
168
+ Comp,
169
+ {
170
+ "data-slot": "button",
171
+ className: cn(buttonVariants({ variant, size, className })),
172
+ ...props
173
+ }
174
+ );
175
+ }
176
+
177
+ // src/components/ui/tooltip.tsx
178
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
179
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
180
+ function TooltipProvider({
181
+ delayDuration = 0,
182
+ ...props
183
+ }) {
184
+ return /* @__PURE__ */ jsx3(
185
+ TooltipPrimitive.Provider,
186
+ {
187
+ "data-slot": "tooltip-provider",
188
+ delayDuration,
189
+ ...props
190
+ }
191
+ );
192
+ }
193
+ function Tooltip({
194
+ ...props
195
+ }) {
196
+ return /* @__PURE__ */ jsx3(TooltipProvider, { children: /* @__PURE__ */ jsx3(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
197
+ }
198
+ function TooltipTrigger({
199
+ ...props
200
+ }) {
201
+ return /* @__PURE__ */ jsx3(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
202
+ }
203
+ function TooltipContent({
204
+ className,
205
+ sideOffset = 0,
206
+ children,
207
+ ...props
208
+ }) {
209
+ return /* @__PURE__ */ jsx3(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
210
+ TooltipPrimitive.Content,
211
+ {
212
+ "data-slot": "tooltip-content",
213
+ sideOffset,
214
+ className: cn(
215
+ "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
216
+ className
217
+ ),
218
+ ...props,
219
+ children: [
220
+ children,
221
+ /* @__PURE__ */ jsx3(TooltipPrimitive.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
222
+ ]
223
+ }
224
+ ) });
225
+ }
226
+
227
+ // src/components/ui/dropdown-menu.tsx
228
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
229
+ import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
230
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
231
+ function DropdownMenu({
232
+ ...props
233
+ }) {
234
+ return /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
235
+ }
236
+ function DropdownMenuTrigger({
237
+ ...props
238
+ }) {
239
+ return /* @__PURE__ */ jsx4(
240
+ DropdownMenuPrimitive.Trigger,
241
+ {
242
+ "data-slot": "dropdown-menu-trigger",
243
+ ...props
244
+ }
245
+ );
246
+ }
247
+ function DropdownMenuContent({
248
+ className,
249
+ sideOffset = 4,
250
+ ...props
251
+ }) {
252
+ return /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx4(
253
+ DropdownMenuPrimitive.Content,
254
+ {
255
+ "data-slot": "dropdown-menu-content",
256
+ sideOffset,
257
+ className: cn(
258
+ "bg-popover text-popover-foreground 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 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
259
+ className
260
+ ),
261
+ ...props
262
+ }
263
+ ) });
264
+ }
265
+ function DropdownMenuItem({
266
+ className,
267
+ inset,
268
+ variant = "default",
269
+ ...props
270
+ }) {
271
+ return /* @__PURE__ */ jsx4(
272
+ DropdownMenuPrimitive.Item,
273
+ {
274
+ "data-slot": "dropdown-menu-item",
275
+ "data-inset": inset,
276
+ "data-variant": variant,
277
+ className: cn(
278
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
279
+ className
280
+ ),
281
+ ...props
282
+ }
283
+ );
284
+ }
285
+ function DropdownMenuSeparator({
286
+ className,
287
+ ...props
288
+ }) {
289
+ return /* @__PURE__ */ jsx4(
290
+ DropdownMenuPrimitive.Separator,
291
+ {
292
+ "data-slot": "dropdown-menu-separator",
293
+ className: cn("bg-border -mx-1 my-1 h-px", className),
294
+ ...props
295
+ }
296
+ );
297
+ }
298
+ function DropdownMenuSub({
299
+ ...props
300
+ }) {
301
+ return /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
302
+ }
303
+ function DropdownMenuSubTrigger({
304
+ className,
305
+ inset,
306
+ children,
307
+ ...props
308
+ }) {
309
+ return /* @__PURE__ */ jsxs2(
310
+ DropdownMenuPrimitive.SubTrigger,
311
+ {
312
+ "data-slot": "dropdown-menu-sub-trigger",
313
+ "data-inset": inset,
314
+ className: cn(
315
+ "focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
316
+ className
317
+ ),
318
+ ...props,
319
+ children: [
320
+ children,
321
+ /* @__PURE__ */ jsx4(ChevronRightIcon, { className: "ml-auto size-4" })
322
+ ]
323
+ }
324
+ );
325
+ }
326
+ function DropdownMenuSubContent({
327
+ className,
328
+ ...props
329
+ }) {
330
+ return /* @__PURE__ */ jsx4(
331
+ DropdownMenuPrimitive.SubContent,
332
+ {
333
+ "data-slot": "dropdown-menu-sub-content",
334
+ className: cn(
335
+ "bg-popover text-popover-foreground 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 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
336
+ className
337
+ ),
338
+ ...props
339
+ }
340
+ );
341
+ }
342
+
343
+ // src/components/chat/CopilotChatAudioRecorder.tsx
344
+ import { useRef, useEffect, useImperativeHandle, forwardRef } from "react";
345
+ import { twMerge as twMerge2 } from "tailwind-merge";
346
+ import { jsx as jsx5 } from "react/jsx-runtime";
347
+ var AudioRecorderError = class extends Error {
348
+ constructor(message) {
349
+ super(message);
350
+ this.name = "AudioRecorderError";
351
+ }
352
+ };
353
+ var CopilotChatAudioRecorder = forwardRef((props, ref) => {
354
+ const { className, ...divProps } = props;
355
+ const canvasRef = useRef(null);
356
+ const getLoudness = (n) => {
357
+ const elapsed = Date.now() / 1e3;
358
+ const samples = [];
359
+ for (let i = 0; i < n; i++) {
360
+ const position = i / n * 10 + elapsed * 0.5;
361
+ const wave1 = Math.sin(position * 2) * 0.3;
362
+ const wave2 = Math.sin(position * 5 + elapsed) * 0.2;
363
+ const wave3 = Math.sin(position * 0.5 + elapsed * 0.3) * 0.4;
364
+ const noise = (Math.random() - 0.5) * 0.1;
365
+ const envelope = Math.sin(elapsed * 0.7) * 0.5 + 0.5;
366
+ let amplitude = (wave1 + wave2 + wave3 + noise) * envelope;
367
+ amplitude = Math.max(0, Math.min(1, amplitude * 0.5 + 0.3));
368
+ samples.push(amplitude);
369
+ }
370
+ return samples;
371
+ };
372
+ useEffect(() => {
373
+ const canvas = canvasRef.current;
374
+ if (!canvas) return;
375
+ const ctx = canvas.getContext("2d");
376
+ if (!ctx) return;
377
+ let animationId;
378
+ const draw = () => {
379
+ const rect = canvas.getBoundingClientRect();
380
+ const dpr = window.devicePixelRatio || 1;
381
+ if (canvas.width !== rect.width * dpr || canvas.height !== rect.height * dpr) {
382
+ canvas.width = rect.width * dpr;
383
+ canvas.height = rect.height * dpr;
384
+ ctx.scale(dpr, dpr);
385
+ ctx.imageSmoothingEnabled = false;
386
+ }
387
+ const barWidth = 2;
388
+ const minHeight = 2;
389
+ const maxHeight = 20;
390
+ const gap = 2;
391
+ const numSamples = Math.ceil(rect.width / (barWidth + gap));
392
+ const loudnessData = getLoudness(numSamples);
393
+ ctx.clearRect(0, 0, rect.width, rect.height);
394
+ const computedStyle = getComputedStyle(canvas);
395
+ const currentForeground = computedStyle.color;
396
+ ctx.fillStyle = currentForeground;
397
+ const centerY = rect.height / 2;
398
+ for (let i = 0; i < loudnessData.length; i++) {
399
+ const sample = loudnessData[i] ?? 0;
400
+ const barHeight = Math.round(
401
+ sample * (maxHeight - minHeight) + minHeight
402
+ );
403
+ const x = Math.round(i * (barWidth + gap));
404
+ const y = Math.round(centerY - barHeight / 2);
405
+ ctx.fillRect(x, y, barWidth, barHeight);
406
+ }
407
+ animationId = requestAnimationFrame(draw);
408
+ };
409
+ draw();
410
+ return () => {
411
+ if (animationId) {
412
+ cancelAnimationFrame(animationId);
413
+ }
414
+ };
415
+ }, []);
416
+ useImperativeHandle(
417
+ ref,
418
+ () => ({
419
+ get state() {
420
+ return "idle";
421
+ },
422
+ start: async () => {
423
+ },
424
+ stop: () => new Promise((resolve) => {
425
+ const emptyBlob = new Blob([], { type: "audio/webm" });
426
+ resolve(emptyBlob);
427
+ }),
428
+ dispose: () => {
429
+ }
430
+ }),
431
+ []
432
+ );
433
+ return /* @__PURE__ */ jsx5("div", { className: twMerge2("h-[44px] w-full px-5", className), ...divProps, children: /* @__PURE__ */ jsx5(
434
+ "canvas",
435
+ {
436
+ ref: canvasRef,
437
+ className: "w-full h-full",
438
+ style: { imageRendering: "pixelated" }
439
+ }
440
+ ) });
441
+ });
442
+ CopilotChatAudioRecorder.displayName = "WebAudioRecorder";
443
+
444
+ // src/lib/slots.tsx
445
+ import React2 from "react";
446
+ function renderSlot(slot, DefaultComponent, props) {
447
+ if (typeof slot === "string") {
448
+ return React2.createElement(DefaultComponent, {
449
+ ...props,
450
+ className: slot
451
+ });
452
+ }
453
+ if (typeof slot === "function") {
454
+ const Comp = slot;
455
+ return React2.createElement(Comp, props);
456
+ }
457
+ if (slot && typeof slot === "object" && !React2.isValidElement(slot)) {
458
+ return React2.createElement(DefaultComponent, {
459
+ ...props,
460
+ ...slot
461
+ });
462
+ }
463
+ return React2.createElement(DefaultComponent, props);
464
+ }
465
+
466
+ // src/components/chat/CopilotChatInput.tsx
467
+ import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
468
+ function CopilotChatInput({
469
+ mode = "input",
470
+ onSubmitMessage,
471
+ onStartTranscribe,
472
+ onCancelTranscribe,
473
+ onFinishTranscribe,
474
+ onAddFile,
475
+ onChange,
476
+ value,
477
+ toolsMenu,
478
+ autoFocus = true,
479
+ additionalToolbarItems,
480
+ textArea,
481
+ sendButton,
482
+ startTranscribeButton,
483
+ cancelTranscribeButton,
484
+ finishTranscribeButton,
485
+ addFileButton,
486
+ toolsButton,
487
+ toolbar,
488
+ audioRecorder,
489
+ children,
490
+ className,
491
+ ...props
492
+ }) {
493
+ const { inputValue, onSubmitInput, onChangeInput } = useCopilotChatConfiguration();
494
+ value ??= inputValue;
495
+ onSubmitMessage ??= onSubmitInput;
496
+ onChange ??= onChangeInput;
497
+ const inputRef = useRef2(null);
498
+ const audioRecorderRef = useRef2(null);
499
+ useEffect2(() => {
500
+ const recorder = audioRecorderRef.current;
501
+ if (!recorder) {
502
+ return;
503
+ }
504
+ if (mode === "transcribe") {
505
+ recorder.start().catch(console.error);
506
+ } else {
507
+ if (recorder.state === "recording") {
508
+ recorder.stop().catch(console.error);
509
+ }
510
+ }
511
+ }, [mode]);
512
+ const handleChange = (e) => {
513
+ onChange?.(e.target.value);
514
+ };
515
+ const handleKeyDown = (e) => {
516
+ if (e.key === "Enter" && !e.shiftKey) {
517
+ e.preventDefault();
518
+ send();
519
+ }
520
+ };
521
+ const send = () => {
522
+ const trimmed = value?.trim();
523
+ if (trimmed) {
524
+ onSubmitMessage?.(trimmed);
525
+ if (inputRef.current) {
526
+ inputRef.current.focus();
527
+ }
528
+ }
529
+ };
530
+ const BoundTextArea = renderSlot(textArea, CopilotChatInput.TextArea, {
531
+ ref: inputRef,
532
+ value,
533
+ onChange: handleChange,
534
+ onKeyDown: handleKeyDown,
535
+ autoFocus
536
+ });
537
+ const BoundAudioRecorder = renderSlot(
538
+ audioRecorder,
539
+ CopilotChatAudioRecorder,
540
+ {
541
+ ref: audioRecorderRef
542
+ }
543
+ );
544
+ const BoundSendButton = renderSlot(sendButton, CopilotChatInput.SendButton, {
545
+ onClick: send,
546
+ disabled: !value?.trim() || !onSubmitMessage
547
+ });
548
+ const BoundStartTranscribeButton = renderSlot(
549
+ startTranscribeButton,
550
+ CopilotChatInput.StartTranscribeButton,
551
+ {
552
+ onClick: onStartTranscribe
553
+ }
554
+ );
555
+ const BoundCancelTranscribeButton = renderSlot(
556
+ cancelTranscribeButton,
557
+ CopilotChatInput.CancelTranscribeButton,
558
+ {
559
+ onClick: onCancelTranscribe
560
+ }
561
+ );
562
+ const BoundFinishTranscribeButton = renderSlot(
563
+ finishTranscribeButton,
564
+ CopilotChatInput.FinishTranscribeButton,
565
+ {
566
+ onClick: onFinishTranscribe
567
+ }
568
+ );
569
+ const BoundAddFileButton = renderSlot(
570
+ addFileButton,
571
+ CopilotChatInput.AddFileButton,
572
+ {
573
+ onClick: onAddFile,
574
+ disabled: mode === "transcribe"
575
+ }
576
+ );
577
+ const BoundToolsButton = renderSlot(
578
+ toolsButton,
579
+ CopilotChatInput.ToolsButton,
580
+ {
581
+ disabled: mode === "transcribe",
582
+ toolsMenu
583
+ }
584
+ );
585
+ const BoundToolbar = renderSlot(
586
+ typeof toolbar === "string" || toolbar === void 0 ? twMerge3(
587
+ toolbar,
588
+ "w-full h-[60px] bg-transparent flex items-center justify-between"
589
+ ) : toolbar,
590
+ CopilotChatInput.Toolbar,
591
+ {
592
+ children: /* @__PURE__ */ jsxs3(Fragment, { children: [
593
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center", children: [
594
+ onAddFile && BoundAddFileButton,
595
+ BoundToolsButton,
596
+ additionalToolbarItems
597
+ ] }),
598
+ /* @__PURE__ */ jsx6("div", { className: "flex items-center", children: mode === "transcribe" ? /* @__PURE__ */ jsxs3(Fragment, { children: [
599
+ onCancelTranscribe && BoundCancelTranscribeButton,
600
+ onFinishTranscribe && BoundFinishTranscribeButton
601
+ ] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
602
+ onStartTranscribe && BoundStartTranscribeButton,
603
+ BoundSendButton
604
+ ] }) })
605
+ ] })
606
+ }
607
+ );
608
+ if (children) {
609
+ return /* @__PURE__ */ jsx6(Fragment, { children: children({
610
+ textArea: BoundTextArea,
611
+ audioRecorder: BoundAudioRecorder,
612
+ sendButton: BoundSendButton,
613
+ startTranscribeButton: BoundStartTranscribeButton,
614
+ cancelTranscribeButton: BoundCancelTranscribeButton,
615
+ finishTranscribeButton: BoundFinishTranscribeButton,
616
+ addFileButton: BoundAddFileButton,
617
+ toolsButton: BoundToolsButton,
618
+ toolbar: BoundToolbar,
619
+ onSubmitMessage,
620
+ onStartTranscribe,
621
+ onCancelTranscribe,
622
+ onFinishTranscribe,
623
+ onAddFile,
624
+ mode,
625
+ toolsMenu,
626
+ autoFocus,
627
+ additionalToolbarItems
628
+ }) });
629
+ }
630
+ return /* @__PURE__ */ jsxs3(
631
+ "div",
632
+ {
633
+ className: twMerge3(
634
+ // Layout
635
+ "flex w-full flex-col items-center justify-center",
636
+ // Interaction
637
+ "cursor-text",
638
+ // Overflow and clipping
639
+ "overflow-visible bg-clip-padding contain-inline-size",
640
+ // Background
641
+ "bg-white dark:bg-[#303030]",
642
+ // Visual effects
643
+ "shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] rounded-[28px]",
644
+ className
645
+ ),
646
+ ...props,
647
+ children: [
648
+ mode === "transcribe" ? BoundAudioRecorder : BoundTextArea,
649
+ BoundToolbar
650
+ ]
651
+ }
652
+ );
653
+ }
654
+ ((CopilotChatInput2) => {
655
+ CopilotChatInput2.SendButton = ({ className, ...props }) => /* @__PURE__ */ jsx6("div", { className: "mr-[10px]", children: /* @__PURE__ */ jsx6(
656
+ Button,
657
+ {
658
+ type: "button",
659
+ variant: "chatInputToolbarPrimary",
660
+ size: "chatInputToolbarIcon",
661
+ className,
662
+ ...props,
663
+ children: /* @__PURE__ */ jsx6(ArrowUp, { className: "size-[18px]" })
664
+ }
665
+ ) });
666
+ CopilotChatInput2.ToolbarButton = ({ icon, labelKey, defaultClassName, className, ...props }) => {
667
+ const { labels } = useCopilotChatConfiguration();
668
+ return /* @__PURE__ */ jsxs3(Tooltip, { children: [
669
+ /* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx6(
670
+ Button,
671
+ {
672
+ type: "button",
673
+ variant: "chatInputToolbarSecondary",
674
+ size: "chatInputToolbarIcon",
675
+ className: twMerge3(defaultClassName, className),
676
+ ...props,
677
+ children: icon
678
+ }
679
+ ) }),
680
+ /* @__PURE__ */ jsx6(TooltipContent, { side: "bottom", children: /* @__PURE__ */ jsx6("p", { children: labels[labelKey] }) })
681
+ ] });
682
+ };
683
+ CopilotChatInput2.StartTranscribeButton = (props) => /* @__PURE__ */ jsx6(
684
+ CopilotChatInput2.ToolbarButton,
685
+ {
686
+ icon: /* @__PURE__ */ jsx6(Mic, { className: "size-[18px]" }),
687
+ labelKey: "chatInputToolbarStartTranscribeButtonLabel",
688
+ defaultClassName: "mr-2",
689
+ ...props
690
+ }
691
+ );
692
+ CopilotChatInput2.CancelTranscribeButton = (props) => /* @__PURE__ */ jsx6(
693
+ CopilotChatInput2.ToolbarButton,
694
+ {
695
+ icon: /* @__PURE__ */ jsx6(X, { className: "size-[18px]" }),
696
+ labelKey: "chatInputToolbarCancelTranscribeButtonLabel",
697
+ defaultClassName: "mr-2",
698
+ ...props
699
+ }
700
+ );
701
+ CopilotChatInput2.FinishTranscribeButton = (props) => /* @__PURE__ */ jsx6(
702
+ CopilotChatInput2.ToolbarButton,
703
+ {
704
+ icon: /* @__PURE__ */ jsx6(Check, { className: "size-[18px]" }),
705
+ labelKey: "chatInputToolbarFinishTranscribeButtonLabel",
706
+ defaultClassName: "mr-[10px]",
707
+ ...props
708
+ }
709
+ );
710
+ CopilotChatInput2.AddFileButton = (props) => /* @__PURE__ */ jsx6(
711
+ CopilotChatInput2.ToolbarButton,
712
+ {
713
+ icon: /* @__PURE__ */ jsx6(Plus, { className: "size-[20px]" }),
714
+ labelKey: "chatInputToolbarAddButtonLabel",
715
+ defaultClassName: "ml-2",
716
+ ...props
717
+ }
718
+ );
719
+ CopilotChatInput2.ToolsButton = ({ className, toolsMenu, ...props }) => {
720
+ const { labels } = useCopilotChatConfiguration();
721
+ const renderMenuItems = (items) => {
722
+ return items.map((item, index) => {
723
+ if (item === "-") {
724
+ return /* @__PURE__ */ jsx6(DropdownMenuSeparator, {}, index);
725
+ } else if (item.items && item.items.length > 0) {
726
+ return /* @__PURE__ */ jsxs3(DropdownMenuSub, { children: [
727
+ /* @__PURE__ */ jsx6(DropdownMenuSubTrigger, { children: item.label }),
728
+ /* @__PURE__ */ jsx6(DropdownMenuSubContent, { children: renderMenuItems(item.items) })
729
+ ] }, index);
730
+ } else {
731
+ return /* @__PURE__ */ jsx6(DropdownMenuItem, { onClick: item.action, children: item.label }, index);
732
+ }
733
+ });
734
+ };
735
+ if (!toolsMenu || toolsMenu.length === 0) {
736
+ return null;
737
+ }
738
+ return /* @__PURE__ */ jsxs3(DropdownMenu, { children: [
739
+ /* @__PURE__ */ jsx6(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
740
+ Button,
741
+ {
742
+ type: "button",
743
+ variant: "chatInputToolbarSecondary",
744
+ size: "chatInputToolbarIconLabel",
745
+ className,
746
+ ...props,
747
+ children: [
748
+ /* @__PURE__ */ jsx6(Settings2, { className: "size-[18px]" }),
749
+ /* @__PURE__ */ jsx6("span", { className: "text-sm font-normal", children: labels.chatInputToolbarToolsButtonLabel })
750
+ ]
751
+ }
752
+ ) }),
753
+ /* @__PURE__ */ jsx6(DropdownMenuContent, { side: "top", align: "end", children: renderMenuItems(toolsMenu) })
754
+ ] });
755
+ };
756
+ CopilotChatInput2.Toolbar = ({
757
+ className,
758
+ ...props
759
+ }) => /* @__PURE__ */ jsx6(
760
+ "div",
761
+ {
762
+ className: twMerge3(
763
+ "w-full h-[60px] bg-transparent flex items-center",
764
+ className
765
+ ),
766
+ ...props
767
+ }
768
+ );
769
+ CopilotChatInput2.TextArea = forwardRef2(
770
+ function TextArea2({ maxRows = 5, style, className, ...props }, ref) {
771
+ const internalTextareaRef = useRef2(null);
772
+ const [maxHeight, setMaxHeight] = useState(0);
773
+ const { labels } = useCopilotChatConfiguration();
774
+ useImperativeHandle2(
775
+ ref,
776
+ () => internalTextareaRef.current
777
+ );
778
+ const adjustHeight = () => {
779
+ const textarea = internalTextareaRef.current;
780
+ if (textarea && maxHeight > 0) {
781
+ textarea.style.height = "auto";
782
+ textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight)}px`;
783
+ }
784
+ };
785
+ useEffect2(() => {
786
+ const calculateMaxHeight = () => {
787
+ const textarea = internalTextareaRef.current;
788
+ if (textarea) {
789
+ const currentValue = textarea.value;
790
+ textarea.value = "";
791
+ textarea.style.height = "auto";
792
+ const computedStyle = window.getComputedStyle(textarea);
793
+ const paddingTop = parseFloat(computedStyle.paddingTop);
794
+ const paddingBottom = parseFloat(computedStyle.paddingBottom);
795
+ const contentHeight = textarea.scrollHeight - paddingTop - paddingBottom;
796
+ setMaxHeight(contentHeight * maxRows + paddingTop + paddingBottom);
797
+ textarea.value = currentValue;
798
+ if (currentValue) {
799
+ textarea.style.height = "auto";
800
+ textarea.style.height = `${Math.min(textarea.scrollHeight, contentHeight * maxRows + paddingTop + paddingBottom)}px`;
801
+ }
802
+ if (props.autoFocus) {
803
+ textarea.focus();
804
+ }
805
+ }
806
+ };
807
+ calculateMaxHeight();
808
+ }, [maxRows, props.autoFocus]);
809
+ useEffect2(() => {
810
+ adjustHeight();
811
+ }, [props.value, maxHeight]);
812
+ const handleInput = (e) => {
813
+ adjustHeight();
814
+ if (props.onChange) {
815
+ props.onChange(e);
816
+ }
817
+ };
818
+ return /* @__PURE__ */ jsx6(
819
+ "textarea",
820
+ {
821
+ ref: internalTextareaRef,
822
+ ...props,
823
+ onChange: handleInput,
824
+ style: {
825
+ overflow: "auto",
826
+ resize: "none",
827
+ maxHeight: `${maxHeight}px`,
828
+ ...style
829
+ },
830
+ placeholder: labels.chatInputPlaceholder,
831
+ className: twMerge3(
832
+ // Layout and sizing
833
+ "w-full p-5 pb-0",
834
+ // Behavior
835
+ "outline-none resize-none",
836
+ // Background
837
+ "bg-transparent",
838
+ // Typography
839
+ "antialiased font-regular leading-relaxed text-[16px]",
840
+ // Placeholder styles
841
+ "placeholder:text-[#00000077] dark:placeholder:text-[#fffc]",
842
+ className
843
+ ),
844
+ rows: 1
845
+ }
846
+ );
847
+ }
848
+ );
849
+ CopilotChatInput2.AudioRecorder = CopilotChatAudioRecorder;
850
+ })(CopilotChatInput || (CopilotChatInput = {}));
851
+ CopilotChatInput.TextArea.displayName = "CopilotChatInput.TextArea";
852
+ CopilotChatInput.SendButton.displayName = "CopilotChatInput.SendButton";
853
+ CopilotChatInput.ToolbarButton.displayName = "CopilotChatInput.ToolbarButton";
854
+ CopilotChatInput.StartTranscribeButton.displayName = "CopilotChatInput.StartTranscribeButton";
855
+ CopilotChatInput.CancelTranscribeButton.displayName = "CopilotChatInput.CancelTranscribeButton";
856
+ CopilotChatInput.FinishTranscribeButton.displayName = "CopilotChatInput.FinishTranscribeButton";
857
+ CopilotChatInput.AddFileButton.displayName = "CopilotChatInput.AddButton";
858
+ CopilotChatInput.ToolsButton.displayName = "CopilotChatInput.ToolsButton";
859
+ CopilotChatInput.Toolbar.displayName = "CopilotChatInput.Toolbar";
860
+ var CopilotChatInput_default = CopilotChatInput;
861
+
862
+ // src/components/chat/CopilotChatAssistantMessage.tsx
863
+ import { MarkdownHooks } from "react-markdown";
864
+ import remarkGfm from "remark-gfm";
865
+ import remarkMath from "remark-math";
866
+ import rehypePrettyCode from "rehype-pretty-code";
867
+ import rehypeKatex from "rehype-katex";
868
+ import { useState as useState5 } from "react";
869
+ import {
870
+ Copy,
871
+ Check as Check2,
872
+ ThumbsUp,
873
+ ThumbsDown,
874
+ Volume2,
875
+ RefreshCw
876
+ } from "lucide-react";
877
+ import { twMerge as twMerge4 } from "tailwind-merge";
878
+ import "katex/dist/katex.min.css";
879
+ import { completePartialMarkdown } from "@copilotkitnext/core";
880
+
881
+ // src/hooks/use-render-tool-call.tsx
882
+ import { useCallback } from "react";
883
+ import { ToolCallStatus } from "@copilotkitnext/core";
884
+
885
+ // src/providers/CopilotKitProvider.tsx
886
+ import {
887
+ createContext as createContext2,
888
+ useContext as useContext2,
889
+ useMemo,
890
+ useEffect as useEffect3,
891
+ useState as useState2,
892
+ useReducer,
893
+ useRef as useRef3
894
+ } from "react";
895
+ import {
896
+ CopilotKitCore
897
+ } from "@copilotkitnext/core";
898
+ import { jsx as jsx7 } from "react/jsx-runtime";
899
+ var CopilotKitContext = createContext2({
900
+ copilotkit: null,
901
+ renderToolCalls: [],
902
+ currentRenderToolCalls: [],
903
+ setCurrentRenderToolCalls: () => {
904
+ }
905
+ });
906
+ function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
907
+ const empty = useMemo(() => [], []);
908
+ const value = prop ?? empty;
909
+ const initial = useRef3(value);
910
+ useEffect3(() => {
911
+ if (warningMessage && value !== initial.current && (isMeaningfulChange ? isMeaningfulChange(initial.current, value) : true)) {
912
+ console.error(warningMessage);
913
+ }
914
+ }, [value, warningMessage]);
915
+ return value;
916
+ }
917
+ var CopilotKitProvider = ({
918
+ children,
919
+ runtimeUrl,
920
+ headers = {},
921
+ properties = {},
922
+ agents = {},
923
+ renderToolCalls,
924
+ frontendTools,
925
+ humanInTheLoop
926
+ }) => {
927
+ const renderToolCallsList = useStableArrayProp(
928
+ renderToolCalls,
929
+ "renderToolCalls must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.",
930
+ (initial, next) => {
931
+ const key = (rc) => `${rc?.agentId ?? ""}:${rc?.name ?? ""}`;
932
+ const setFrom = (arr) => new Set(arr.map(key));
933
+ const a = setFrom(initial);
934
+ const b = setFrom(next);
935
+ if (a.size !== b.size) return true;
936
+ for (const k of a) if (!b.has(k)) return true;
937
+ return false;
938
+ }
939
+ );
940
+ const frontendToolsList = useStableArrayProp(
941
+ frontendTools,
942
+ "frontendTools must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead."
943
+ );
944
+ const humanInTheLoopList = useStableArrayProp(
945
+ humanInTheLoop,
946
+ "humanInTheLoop must be a stable array. If you want to dynamically add or remove human-in-the-loop tools, use `useHumanInTheLoop` instead."
947
+ );
948
+ const initialRenderToolCalls = useMemo(() => renderToolCallsList, []);
949
+ const [currentRenderToolCalls, setCurrentRenderToolCalls] = useState2([]);
950
+ const processedHumanInTheLoopTools = useMemo(() => {
951
+ const processedTools = [];
952
+ const processedRenderToolCalls = [];
953
+ humanInTheLoopList.forEach((tool) => {
954
+ const frontendTool = {
955
+ name: tool.name,
956
+ description: tool.description,
957
+ parameters: tool.parameters,
958
+ followUp: tool.followUp,
959
+ ...tool.agentId && { agentId: tool.agentId },
960
+ handler: async () => {
961
+ return new Promise((resolve) => {
962
+ console.warn(
963
+ `Human-in-the-loop tool '${tool.name}' called but no interactive handler is set up.`
964
+ );
965
+ resolve(void 0);
966
+ });
967
+ }
968
+ };
969
+ processedTools.push(frontendTool);
970
+ if (tool.render) {
971
+ processedRenderToolCalls.push({
972
+ name: tool.name,
973
+ args: tool.parameters,
974
+ render: tool.render,
975
+ ...tool.agentId && { agentId: tool.agentId }
976
+ });
977
+ }
978
+ });
979
+ return { tools: processedTools, renderToolCalls: processedRenderToolCalls };
980
+ }, [humanInTheLoopList]);
981
+ const allTools = useMemo(() => {
982
+ const tools = {};
983
+ frontendToolsList.forEach((tool) => {
984
+ tools[tool.name] = tool;
985
+ });
986
+ processedHumanInTheLoopTools.tools.forEach((tool) => {
987
+ tools[tool.name] = tool;
988
+ });
989
+ return tools;
990
+ }, [frontendToolsList, processedHumanInTheLoopTools]);
991
+ const allRenderToolCalls = useMemo(() => {
992
+ const combined = [...renderToolCallsList];
993
+ frontendToolsList.forEach((tool) => {
994
+ if (tool.render && tool.parameters) {
995
+ combined.push({
996
+ name: tool.name,
997
+ args: tool.parameters,
998
+ render: tool.render
999
+ });
1000
+ }
1001
+ });
1002
+ combined.push(...processedHumanInTheLoopTools.renderToolCalls);
1003
+ return combined;
1004
+ }, [renderToolCallsList, frontendToolsList, processedHumanInTheLoopTools]);
1005
+ const copilotkit = useMemo(() => {
1006
+ const config = {
1007
+ // Don't set runtimeUrl during initialization to prevent server-side fetching
1008
+ runtimeUrl: void 0,
1009
+ headers,
1010
+ properties,
1011
+ agents,
1012
+ tools: allTools
1013
+ };
1014
+ const copilotkit2 = new CopilotKitCore(config);
1015
+ return copilotkit2;
1016
+ }, [allTools]);
1017
+ useEffect3(() => {
1018
+ setCurrentRenderToolCalls(
1019
+ (prev) => prev === allRenderToolCalls ? prev : allRenderToolCalls
1020
+ );
1021
+ }, [allRenderToolCalls]);
1022
+ useEffect3(() => {
1023
+ copilotkit.setRuntimeUrl(runtimeUrl);
1024
+ copilotkit.setHeaders(headers);
1025
+ copilotkit.setProperties(properties);
1026
+ copilotkit.setAgents(agents);
1027
+ }, [runtimeUrl, headers, properties, agents]);
1028
+ return /* @__PURE__ */ jsx7(
1029
+ CopilotKitContext.Provider,
1030
+ {
1031
+ value: {
1032
+ copilotkit,
1033
+ renderToolCalls: allRenderToolCalls,
1034
+ currentRenderToolCalls,
1035
+ setCurrentRenderToolCalls
1036
+ },
1037
+ children
1038
+ }
1039
+ );
1040
+ };
1041
+ var useCopilotKit = () => {
1042
+ const context = useContext2(CopilotKitContext);
1043
+ const [, forceUpdate] = useReducer((x) => x + 1, 0);
1044
+ if (!context) {
1045
+ throw new Error("useCopilotKit must be used within CopilotKitProvider");
1046
+ }
1047
+ useEffect3(() => {
1048
+ const unsubscribe = context.copilotkit.subscribe({
1049
+ onRuntimeLoaded: () => {
1050
+ forceUpdate();
1051
+ },
1052
+ onRuntimeLoadError: () => {
1053
+ forceUpdate();
1054
+ }
1055
+ });
1056
+ return () => {
1057
+ unsubscribe();
1058
+ };
1059
+ }, []);
1060
+ return context;
1061
+ };
1062
+
1063
+ // src/hooks/use-render-tool-call.tsx
1064
+ import { partialJSONParse } from "@copilotkitnext/shared";
1065
+ import { jsx as jsx8 } from "react/jsx-runtime";
1066
+ function useRenderToolCall() {
1067
+ const { currentRenderToolCalls } = useCopilotKit();
1068
+ const renderToolCall = useCallback(
1069
+ ({
1070
+ toolCall,
1071
+ toolMessage,
1072
+ isLoading
1073
+ }) => {
1074
+ const renderConfig = currentRenderToolCalls.find(
1075
+ (rc) => rc.name === toolCall.function.name
1076
+ ) || currentRenderToolCalls.find((rc) => rc.name === "*");
1077
+ if (!renderConfig) {
1078
+ return null;
1079
+ }
1080
+ const RenderComponent = renderConfig.render;
1081
+ const args = partialJSONParse(toolCall.function.arguments);
1082
+ if (toolMessage) {
1083
+ return /* @__PURE__ */ jsx8(
1084
+ RenderComponent,
1085
+ {
1086
+ args,
1087
+ status: ToolCallStatus.Complete,
1088
+ result: toolMessage.content
1089
+ },
1090
+ toolCall.id
1091
+ );
1092
+ } else if (isLoading) {
1093
+ return /* @__PURE__ */ jsx8(
1094
+ RenderComponent,
1095
+ {
1096
+ args,
1097
+ status: ToolCallStatus.InProgress,
1098
+ result: void 0
1099
+ },
1100
+ toolCall.id
1101
+ );
1102
+ } else {
1103
+ return /* @__PURE__ */ jsx8(
1104
+ RenderComponent,
1105
+ {
1106
+ args,
1107
+ status: ToolCallStatus.Complete,
1108
+ result: ""
1109
+ },
1110
+ toolCall.id
1111
+ );
1112
+ }
1113
+ },
1114
+ [currentRenderToolCalls]
1115
+ );
1116
+ return renderToolCall;
1117
+ }
1118
+
1119
+ // src/hooks/use-frontend-tool.tsx
1120
+ import { useEffect as useEffect4 } from "react";
1121
+ function useFrontendTool(tool) {
1122
+ const { renderToolCalls, copilotkit, setCurrentRenderToolCalls } = useCopilotKit();
1123
+ useEffect4(() => {
1124
+ if (tool.name in copilotkit.tools) {
1125
+ console.warn(
1126
+ `Tool '${tool.name}' already exists. It will be overridden.`
1127
+ );
1128
+ }
1129
+ copilotkit.addTool(tool);
1130
+ if (tool.render && tool.name in renderToolCalls) {
1131
+ console.warn(
1132
+ `Render component for tool '${tool.name}' already exists. It will be overridden.`
1133
+ );
1134
+ }
1135
+ if (tool.render && tool.parameters) {
1136
+ setCurrentRenderToolCalls((prev) => [
1137
+ ...prev,
1138
+ {
1139
+ name: tool.name,
1140
+ args: tool.parameters,
1141
+ render: tool.render
1142
+ }
1143
+ ]);
1144
+ }
1145
+ return () => {
1146
+ copilotkit.removeTool(tool.name);
1147
+ setCurrentRenderToolCalls(
1148
+ (prev) => prev.filter((rc) => rc.name !== tool.name)
1149
+ );
1150
+ };
1151
+ }, [tool, copilotkit, renderToolCalls, setCurrentRenderToolCalls]);
1152
+ }
1153
+
1154
+ // src/hooks/use-human-in-the-loop.tsx
1155
+ import { useState as useState3, useCallback as useCallback2, useRef as useRef4 } from "react";
1156
+ import React6 from "react";
1157
+ function useHumanInTheLoop(tool) {
1158
+ const [status, setStatus] = useState3(
1159
+ "inProgress"
1160
+ );
1161
+ const resolvePromiseRef = useRef4(null);
1162
+ const respond = useCallback2(async (result) => {
1163
+ if (resolvePromiseRef.current) {
1164
+ resolvePromiseRef.current(result);
1165
+ setStatus("complete");
1166
+ resolvePromiseRef.current = null;
1167
+ }
1168
+ }, []);
1169
+ const handler = useCallback2(async () => {
1170
+ return new Promise((resolve) => {
1171
+ setStatus("executing");
1172
+ resolvePromiseRef.current = resolve;
1173
+ });
1174
+ }, []);
1175
+ const RenderComponent = useCallback2(
1176
+ (props) => {
1177
+ const ToolComponent = tool.render;
1178
+ if (status === "inProgress" && props.status === "inProgress") {
1179
+ const enhancedProps = {
1180
+ ...props,
1181
+ name: tool.name,
1182
+ description: tool.description || "",
1183
+ respond: void 0
1184
+ };
1185
+ return React6.createElement(ToolComponent, enhancedProps);
1186
+ } else if (status === "executing" && props.status === "executing") {
1187
+ const enhancedProps = {
1188
+ ...props,
1189
+ name: tool.name,
1190
+ description: tool.description || "",
1191
+ respond
1192
+ };
1193
+ return React6.createElement(ToolComponent, enhancedProps);
1194
+ } else if (status === "complete" && props.status === "complete") {
1195
+ const enhancedProps = {
1196
+ ...props,
1197
+ name: tool.name,
1198
+ description: tool.description || "",
1199
+ respond: void 0
1200
+ };
1201
+ return React6.createElement(ToolComponent, enhancedProps);
1202
+ }
1203
+ return React6.createElement(ToolComponent, props);
1204
+ },
1205
+ [tool.render, tool.name, tool.description, status, respond]
1206
+ );
1207
+ const frontendTool = {
1208
+ ...tool,
1209
+ handler,
1210
+ render: RenderComponent
1211
+ };
1212
+ useFrontendTool(frontendTool);
1213
+ }
1214
+
1215
+ // src/hooks/use-agent.tsx
1216
+ import { useMemo as useMemo2, useEffect as useEffect5, useReducer as useReducer2, useState as useState4 } from "react";
1217
+ import { DEFAULT_AGENT_ID } from "@copilotkitnext/shared";
1218
+ function useAgent({ agentId } = {}) {
1219
+ agentId ??= DEFAULT_AGENT_ID;
1220
+ const { copilotkit } = useCopilotKit();
1221
+ const [, forceUpdate] = useReducer2((x) => x + 1, 0);
1222
+ const [isRunning, setIsRunning] = useState4(false);
1223
+ const agent = useMemo2(() => {
1224
+ return copilotkit.getAgent(agentId);
1225
+ }, [agentId, copilotkit.agents, copilotkit.didLoadRuntime, copilotkit]);
1226
+ useEffect5(() => {
1227
+ const subscription = agent?.subscribe({
1228
+ onMessagesChanged() {
1229
+ forceUpdate();
1230
+ },
1231
+ onStateChanged() {
1232
+ forceUpdate();
1233
+ },
1234
+ onRunInitialized() {
1235
+ setIsRunning(true);
1236
+ },
1237
+ onRunFinalized() {
1238
+ setIsRunning(false);
1239
+ },
1240
+ onRunFailed() {
1241
+ setIsRunning(false);
1242
+ }
1243
+ });
1244
+ return () => subscription?.unsubscribe();
1245
+ }, [agent]);
1246
+ return {
1247
+ agent,
1248
+ isRunning
1249
+ };
1250
+ }
1251
+
1252
+ // src/hooks/use-agent-context.tsx
1253
+ import { useEffect as useEffect6 } from "react";
1254
+ function useAgentContext(context) {
1255
+ const { description, value } = context;
1256
+ const { copilotkit } = useCopilotKit();
1257
+ useEffect6(() => {
1258
+ if (!copilotkit) return;
1259
+ const id = copilotkit.addContext(context);
1260
+ return () => {
1261
+ copilotkit.removeContext(id);
1262
+ };
1263
+ }, [description, value, copilotkit]);
1264
+ }
1265
+
1266
+ // src/components/chat/CopilotChatToolCallsView.tsx
1267
+ import React7 from "react";
1268
+ import { Fragment as Fragment2, jsx as jsx9 } from "react/jsx-runtime";
1269
+ function CopilotChatToolCallsView({
1270
+ message,
1271
+ messages = [],
1272
+ isLoading = false
1273
+ }) {
1274
+ const renderToolCall = useRenderToolCall();
1275
+ if (!message.toolCalls || message.toolCalls.length === 0) {
1276
+ return null;
1277
+ }
1278
+ return /* @__PURE__ */ jsx9(Fragment2, { children: message.toolCalls.map((toolCall) => {
1279
+ const toolMessage = messages.find(
1280
+ (m) => m.role === "tool" && m.toolCallId === toolCall.id
1281
+ );
1282
+ return /* @__PURE__ */ jsx9(React7.Fragment, { children: renderToolCall({
1283
+ toolCall,
1284
+ toolMessage,
1285
+ isLoading
1286
+ }) }, toolCall.id);
1287
+ }) });
1288
+ }
1289
+ var CopilotChatToolCallsView_default = CopilotChatToolCallsView;
1290
+
1291
+ // src/components/chat/CopilotChatAssistantMessage.tsx
1292
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
1293
+ function CopilotChatAssistantMessage({
1294
+ message,
1295
+ messages,
1296
+ isLoading,
1297
+ onThumbsUp,
1298
+ onThumbsDown,
1299
+ onReadAloud,
1300
+ onRegenerate,
1301
+ additionalToolbarItems,
1302
+ toolbarVisible = true,
1303
+ markdownRenderer,
1304
+ toolbar,
1305
+ copyButton,
1306
+ thumbsUpButton,
1307
+ thumbsDownButton,
1308
+ readAloudButton,
1309
+ regenerateButton,
1310
+ toolCallsView,
1311
+ children,
1312
+ className,
1313
+ ...props
1314
+ }) {
1315
+ const boundMarkdownRenderer = renderSlot(
1316
+ markdownRenderer,
1317
+ CopilotChatAssistantMessage.MarkdownRenderer,
1318
+ {
1319
+ content: message.content || ""
1320
+ }
1321
+ );
1322
+ const boundCopyButton = renderSlot(
1323
+ copyButton,
1324
+ CopilotChatAssistantMessage.CopyButton,
1325
+ {
1326
+ onClick: async () => {
1327
+ if (message.content) {
1328
+ try {
1329
+ await navigator.clipboard.writeText(message.content);
1330
+ } catch (err) {
1331
+ console.error("Failed to copy message:", err);
1332
+ }
1333
+ }
1334
+ }
1335
+ }
1336
+ );
1337
+ const boundThumbsUpButton = renderSlot(
1338
+ thumbsUpButton,
1339
+ CopilotChatAssistantMessage.ThumbsUpButton,
1340
+ {
1341
+ onClick: onThumbsUp
1342
+ }
1343
+ );
1344
+ const boundThumbsDownButton = renderSlot(
1345
+ thumbsDownButton,
1346
+ CopilotChatAssistantMessage.ThumbsDownButton,
1347
+ {
1348
+ onClick: onThumbsDown
1349
+ }
1350
+ );
1351
+ const boundReadAloudButton = renderSlot(
1352
+ readAloudButton,
1353
+ CopilotChatAssistantMessage.ReadAloudButton,
1354
+ {
1355
+ onClick: onReadAloud
1356
+ }
1357
+ );
1358
+ const boundRegenerateButton = renderSlot(
1359
+ regenerateButton,
1360
+ CopilotChatAssistantMessage.RegenerateButton,
1361
+ {
1362
+ onClick: onRegenerate
1363
+ }
1364
+ );
1365
+ const boundToolbar = renderSlot(
1366
+ toolbar,
1367
+ CopilotChatAssistantMessage.Toolbar,
1368
+ {
1369
+ children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1", children: [
1370
+ boundCopyButton,
1371
+ (onThumbsUp || thumbsUpButton) && boundThumbsUpButton,
1372
+ (onThumbsDown || thumbsDownButton) && boundThumbsDownButton,
1373
+ (onReadAloud || readAloudButton) && boundReadAloudButton,
1374
+ (onRegenerate || regenerateButton) && boundRegenerateButton,
1375
+ additionalToolbarItems
1376
+ ] })
1377
+ }
1378
+ );
1379
+ const boundToolCallsView = renderSlot(
1380
+ toolCallsView,
1381
+ CopilotChatToolCallsView_default,
1382
+ {
1383
+ message,
1384
+ messages,
1385
+ isLoading
1386
+ }
1387
+ );
1388
+ if (children) {
1389
+ return /* @__PURE__ */ jsx10(Fragment3, { children: children({
1390
+ markdownRenderer: boundMarkdownRenderer,
1391
+ toolbar: boundToolbar,
1392
+ toolCallsView: boundToolCallsView,
1393
+ copyButton: boundCopyButton,
1394
+ thumbsUpButton: boundThumbsUpButton,
1395
+ thumbsDownButton: boundThumbsDownButton,
1396
+ readAloudButton: boundReadAloudButton,
1397
+ regenerateButton: boundRegenerateButton,
1398
+ message,
1399
+ messages,
1400
+ isLoading,
1401
+ onThumbsUp,
1402
+ onThumbsDown,
1403
+ onReadAloud,
1404
+ onRegenerate,
1405
+ additionalToolbarItems,
1406
+ toolbarVisible
1407
+ }) });
1408
+ }
1409
+ return /* @__PURE__ */ jsxs4(
1410
+ "div",
1411
+ {
1412
+ className: twMerge4(
1413
+ "prose max-w-full break-words dark:prose-invert",
1414
+ className
1415
+ ),
1416
+ ...props,
1417
+ "data-message-id": message.id,
1418
+ children: [
1419
+ boundMarkdownRenderer,
1420
+ boundToolCallsView,
1421
+ toolbarVisible && boundToolbar
1422
+ ]
1423
+ }
1424
+ );
1425
+ }
1426
+ ((CopilotChatAssistantMessage2) => {
1427
+ const InlineCode = ({
1428
+ children,
1429
+ ...props
1430
+ }) => {
1431
+ return /* @__PURE__ */ jsx10(
1432
+ "code",
1433
+ {
1434
+ className: "px-[4.8px] py-[2.5px] bg-[rgb(236,236,236)] dark:bg-gray-800 rounded text-sm font-mono font-medium! text-foreground!",
1435
+ ...props,
1436
+ children
1437
+ }
1438
+ );
1439
+ };
1440
+ const CodeBlock = ({ children, className, onClick, ...props }) => {
1441
+ const { labels } = useCopilotChatConfiguration();
1442
+ const [copied, setCopied] = useState5(false);
1443
+ const getCodeContent = (node) => {
1444
+ if (typeof node === "string") return node;
1445
+ if (Array.isArray(node)) return node.map(getCodeContent).join("");
1446
+ if (node?.props?.children) return getCodeContent(node.props.children);
1447
+ return "";
1448
+ };
1449
+ const codeContent = getCodeContent(children);
1450
+ const language = props["data-language"];
1451
+ const copyToClipboard = async () => {
1452
+ if (!codeContent.trim()) return;
1453
+ try {
1454
+ setCopied(true);
1455
+ setTimeout(() => setCopied(false), 2e3);
1456
+ if (onClick) {
1457
+ onClick();
1458
+ }
1459
+ } catch (err) {
1460
+ console.error("Failed to copy code:", err);
1461
+ }
1462
+ };
1463
+ return /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
1464
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between px-4 pr-3 py-3 text-xs", children: [
1465
+ language && /* @__PURE__ */ jsx10("span", { className: "font-regular text-muted-foreground dark:text-white", children: language }),
1466
+ /* @__PURE__ */ jsxs4(
1467
+ "button",
1468
+ {
1469
+ className: cn(
1470
+ "px-2 gap-0.5 text-xs flex items-center cursor-pointer text-muted-foreground dark:text-white"
1471
+ ),
1472
+ onClick: copyToClipboard,
1473
+ title: copied ? labels.assistantMessageToolbarCopyCodeCopiedLabel : `${labels.assistantMessageToolbarCopyCodeLabel} code`,
1474
+ children: [
1475
+ copied ? /* @__PURE__ */ jsx10(Check2, { className: "h-[10px]! w-[10px]!" }) : /* @__PURE__ */ jsx10(Copy, { className: "h-[10px]! w-[10px]!" }),
1476
+ /* @__PURE__ */ jsx10("span", { className: "text-[11px]", children: copied ? labels.assistantMessageToolbarCopyCodeCopiedLabel : labels.assistantMessageToolbarCopyCodeLabel })
1477
+ ]
1478
+ }
1479
+ )
1480
+ ] }),
1481
+ /* @__PURE__ */ jsx10(
1482
+ "pre",
1483
+ {
1484
+ className: cn(
1485
+ className,
1486
+ "rounded-2xl bg-transparent border-t-0 my-1!"
1487
+ ),
1488
+ ...props,
1489
+ children
1490
+ }
1491
+ )
1492
+ ] });
1493
+ };
1494
+ CopilotChatAssistantMessage2.MarkdownRenderer = ({ content, className }) => /* @__PURE__ */ jsx10("div", { className, children: /* @__PURE__ */ jsx10(
1495
+ MarkdownHooks,
1496
+ {
1497
+ remarkPlugins: [remarkGfm, remarkMath],
1498
+ rehypePlugins: [
1499
+ [
1500
+ rehypePrettyCode,
1501
+ {
1502
+ keepBackground: false,
1503
+ theme: {
1504
+ dark: "one-dark-pro",
1505
+ light: "one-light"
1506
+ },
1507
+ bypassInlineCode: true
1508
+ }
1509
+ ],
1510
+ rehypeKatex
1511
+ ],
1512
+ components: {
1513
+ pre: CodeBlock,
1514
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1515
+ code: ({ className: className2, children, ...props }) => {
1516
+ if (typeof children === "string") {
1517
+ return /* @__PURE__ */ jsx10(InlineCode, { ...props, children });
1518
+ }
1519
+ return /* @__PURE__ */ jsx10("code", { className: className2, ...props, children });
1520
+ }
1521
+ },
1522
+ children: completePartialMarkdown(content || "")
1523
+ }
1524
+ ) });
1525
+ CopilotChatAssistantMessage2.Toolbar = ({
1526
+ className,
1527
+ ...props
1528
+ }) => /* @__PURE__ */ jsx10(
1529
+ "div",
1530
+ {
1531
+ className: twMerge4(
1532
+ "w-full bg-transparent flex items-center -ml-[5px] -mt-[0px]",
1533
+ className
1534
+ ),
1535
+ ...props
1536
+ }
1537
+ );
1538
+ CopilotChatAssistantMessage2.ToolbarButton = ({ title, children, ...props }) => {
1539
+ return /* @__PURE__ */ jsxs4(Tooltip, { children: [
1540
+ /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(
1541
+ Button,
1542
+ {
1543
+ type: "button",
1544
+ variant: "assistantMessageToolbarButton",
1545
+ "aria-label": title,
1546
+ ...props,
1547
+ children
1548
+ }
1549
+ ) }),
1550
+ /* @__PURE__ */ jsx10(TooltipContent, { side: "bottom", children: /* @__PURE__ */ jsx10("p", { children: title }) })
1551
+ ] });
1552
+ };
1553
+ CopilotChatAssistantMessage2.CopyButton = ({ className, title, onClick, ...props }) => {
1554
+ const { labels } = useCopilotChatConfiguration();
1555
+ const [copied, setCopied] = useState5(false);
1556
+ const handleClick = (event) => {
1557
+ setCopied(true);
1558
+ setTimeout(() => setCopied(false), 2e3);
1559
+ if (onClick) {
1560
+ onClick(event);
1561
+ }
1562
+ };
1563
+ return /* @__PURE__ */ jsx10(
1564
+ CopilotChatAssistantMessage2.ToolbarButton,
1565
+ {
1566
+ title: title || labels.assistantMessageToolbarCopyMessageLabel,
1567
+ onClick: handleClick,
1568
+ className,
1569
+ ...props,
1570
+ children: copied ? /* @__PURE__ */ jsx10(Check2, { className: "size-[18px]" }) : /* @__PURE__ */ jsx10(Copy, { className: "size-[18px]" })
1571
+ }
1572
+ );
1573
+ };
1574
+ CopilotChatAssistantMessage2.ThumbsUpButton = ({ title, ...props }) => {
1575
+ const { labels } = useCopilotChatConfiguration();
1576
+ return /* @__PURE__ */ jsx10(
1577
+ CopilotChatAssistantMessage2.ToolbarButton,
1578
+ {
1579
+ title: title || labels.assistantMessageToolbarThumbsUpLabel,
1580
+ ...props,
1581
+ children: /* @__PURE__ */ jsx10(ThumbsUp, { className: "size-[18px]" })
1582
+ }
1583
+ );
1584
+ };
1585
+ CopilotChatAssistantMessage2.ThumbsDownButton = ({ title, ...props }) => {
1586
+ const { labels } = useCopilotChatConfiguration();
1587
+ return /* @__PURE__ */ jsx10(
1588
+ CopilotChatAssistantMessage2.ToolbarButton,
1589
+ {
1590
+ title: title || labels.assistantMessageToolbarThumbsDownLabel,
1591
+ ...props,
1592
+ children: /* @__PURE__ */ jsx10(ThumbsDown, { className: "size-[18px]" })
1593
+ }
1594
+ );
1595
+ };
1596
+ CopilotChatAssistantMessage2.ReadAloudButton = ({ title, ...props }) => {
1597
+ const { labels } = useCopilotChatConfiguration();
1598
+ return /* @__PURE__ */ jsx10(
1599
+ CopilotChatAssistantMessage2.ToolbarButton,
1600
+ {
1601
+ title: title || labels.assistantMessageToolbarReadAloudLabel,
1602
+ ...props,
1603
+ children: /* @__PURE__ */ jsx10(Volume2, { className: "size-[20px]" })
1604
+ }
1605
+ );
1606
+ };
1607
+ CopilotChatAssistantMessage2.RegenerateButton = ({ title, ...props }) => {
1608
+ const { labels } = useCopilotChatConfiguration();
1609
+ return /* @__PURE__ */ jsx10(
1610
+ CopilotChatAssistantMessage2.ToolbarButton,
1611
+ {
1612
+ title: title || labels.assistantMessageToolbarRegenerateLabel,
1613
+ ...props,
1614
+ children: /* @__PURE__ */ jsx10(RefreshCw, { className: "size-[18px]" })
1615
+ }
1616
+ );
1617
+ };
1618
+ })(CopilotChatAssistantMessage || (CopilotChatAssistantMessage = {}));
1619
+ CopilotChatAssistantMessage.MarkdownRenderer.displayName = "CopilotChatAssistantMessage.MarkdownRenderer";
1620
+ CopilotChatAssistantMessage.Toolbar.displayName = "CopilotChatAssistantMessage.Toolbar";
1621
+ CopilotChatAssistantMessage.CopyButton.displayName = "CopilotChatAssistantMessage.CopyButton";
1622
+ CopilotChatAssistantMessage.ThumbsUpButton.displayName = "CopilotChatAssistantMessage.ThumbsUpButton";
1623
+ CopilotChatAssistantMessage.ThumbsDownButton.displayName = "CopilotChatAssistantMessage.ThumbsDownButton";
1624
+ CopilotChatAssistantMessage.ReadAloudButton.displayName = "CopilotChatAssistantMessage.ReadAloudButton";
1625
+ CopilotChatAssistantMessage.RegenerateButton.displayName = "CopilotChatAssistantMessage.RegenerateButton";
1626
+ var CopilotChatAssistantMessage_default = CopilotChatAssistantMessage;
1627
+
1628
+ // src/components/chat/CopilotChatUserMessage.tsx
1629
+ import { useState as useState6 } from "react";
1630
+ import { Copy as Copy2, Check as Check3, Edit, ChevronLeft, ChevronRight } from "lucide-react";
1631
+ import { twMerge as twMerge5 } from "tailwind-merge";
1632
+ import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
1633
+ function CopilotChatUserMessage({
1634
+ message,
1635
+ onEditMessage,
1636
+ branchIndex,
1637
+ numberOfBranches,
1638
+ onSwitchToBranch,
1639
+ additionalToolbarItems,
1640
+ messageRenderer,
1641
+ toolbar,
1642
+ copyButton,
1643
+ editButton,
1644
+ branchNavigation,
1645
+ children,
1646
+ className,
1647
+ ...props
1648
+ }) {
1649
+ const BoundMessageRenderer = renderSlot(
1650
+ messageRenderer,
1651
+ CopilotChatUserMessage.MessageRenderer,
1652
+ {
1653
+ content: message.content || ""
1654
+ }
1655
+ );
1656
+ const BoundCopyButton = renderSlot(
1657
+ copyButton,
1658
+ CopilotChatUserMessage.CopyButton,
1659
+ {
1660
+ onClick: async () => {
1661
+ if (message.content) {
1662
+ try {
1663
+ await navigator.clipboard.writeText(message.content);
1664
+ } catch (err) {
1665
+ console.error("Failed to copy message:", err);
1666
+ }
1667
+ }
1668
+ }
1669
+ }
1670
+ );
1671
+ const BoundEditButton = renderSlot(
1672
+ editButton,
1673
+ CopilotChatUserMessage.EditButton,
1674
+ {
1675
+ onClick: () => onEditMessage?.({ message })
1676
+ }
1677
+ );
1678
+ const BoundBranchNavigation = renderSlot(
1679
+ branchNavigation,
1680
+ CopilotChatUserMessage.BranchNavigation,
1681
+ {
1682
+ currentBranch: branchIndex,
1683
+ numberOfBranches,
1684
+ onSwitchToBranch,
1685
+ message
1686
+ }
1687
+ );
1688
+ const showBranchNavigation = numberOfBranches && numberOfBranches > 1 && onSwitchToBranch;
1689
+ const BoundToolbar = renderSlot(toolbar, CopilotChatUserMessage.Toolbar, {
1690
+ children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1 justify-end", children: [
1691
+ additionalToolbarItems,
1692
+ BoundCopyButton,
1693
+ onEditMessage && BoundEditButton,
1694
+ showBranchNavigation && BoundBranchNavigation
1695
+ ] })
1696
+ });
1697
+ if (children) {
1698
+ return /* @__PURE__ */ jsx11(Fragment4, { children: children({
1699
+ messageRenderer: BoundMessageRenderer,
1700
+ toolbar: BoundToolbar,
1701
+ copyButton: BoundCopyButton,
1702
+ editButton: BoundEditButton,
1703
+ branchNavigation: BoundBranchNavigation,
1704
+ message,
1705
+ branchIndex,
1706
+ numberOfBranches,
1707
+ additionalToolbarItems
1708
+ }) });
1709
+ }
1710
+ return /* @__PURE__ */ jsxs5(
1711
+ "div",
1712
+ {
1713
+ className: twMerge5("flex flex-col items-end group pt-10", className),
1714
+ "data-message-id": message.id,
1715
+ ...props,
1716
+ children: [
1717
+ BoundMessageRenderer,
1718
+ BoundToolbar
1719
+ ]
1720
+ }
1721
+ );
1722
+ }
1723
+ ((CopilotChatUserMessage2) => {
1724
+ CopilotChatUserMessage2.Container = ({ children, className, ...props }) => /* @__PURE__ */ jsx11(
1725
+ "div",
1726
+ {
1727
+ className: twMerge5("flex flex-col items-end group", className),
1728
+ ...props,
1729
+ children
1730
+ }
1731
+ );
1732
+ CopilotChatUserMessage2.MessageRenderer = ({ content, className }) => /* @__PURE__ */ jsx11(
1733
+ "div",
1734
+ {
1735
+ className: twMerge5(
1736
+ "prose dark:prose-invert bg-muted relative max-w-[80%] rounded-[18px] px-4 py-1.5 data-[multiline]:py-3 inline-block whitespace-pre-wrap",
1737
+ className
1738
+ ),
1739
+ children: content
1740
+ }
1741
+ );
1742
+ CopilotChatUserMessage2.Toolbar = ({
1743
+ className,
1744
+ ...props
1745
+ }) => /* @__PURE__ */ jsx11(
1746
+ "div",
1747
+ {
1748
+ className: twMerge5(
1749
+ "w-full bg-transparent flex items-center justify-end -mr-[5px] mt-[4px] invisible group-hover:visible",
1750
+ className
1751
+ ),
1752
+ ...props
1753
+ }
1754
+ );
1755
+ CopilotChatUserMessage2.ToolbarButton = ({ title, children, className, ...props }) => {
1756
+ return /* @__PURE__ */ jsxs5(Tooltip, { children: [
1757
+ /* @__PURE__ */ jsx11(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx11(
1758
+ Button,
1759
+ {
1760
+ type: "button",
1761
+ variant: "assistantMessageToolbarButton",
1762
+ "aria-label": title,
1763
+ className: twMerge5(className),
1764
+ ...props,
1765
+ children
1766
+ }
1767
+ ) }),
1768
+ /* @__PURE__ */ jsx11(TooltipContent, { side: "bottom", children: /* @__PURE__ */ jsx11("p", { children: title }) })
1769
+ ] });
1770
+ };
1771
+ CopilotChatUserMessage2.CopyButton = ({ className, title, onClick, ...props }) => {
1772
+ const { labels } = useCopilotChatConfiguration();
1773
+ const [copied, setCopied] = useState6(false);
1774
+ const handleClick = (event) => {
1775
+ setCopied(true);
1776
+ setTimeout(() => setCopied(false), 2e3);
1777
+ if (onClick) {
1778
+ onClick(event);
1779
+ }
1780
+ };
1781
+ return /* @__PURE__ */ jsx11(
1782
+ CopilotChatUserMessage2.ToolbarButton,
1783
+ {
1784
+ title: title || labels.userMessageToolbarCopyMessageLabel,
1785
+ onClick: handleClick,
1786
+ className,
1787
+ ...props,
1788
+ children: copied ? /* @__PURE__ */ jsx11(Check3, { className: "size-[18px]" }) : /* @__PURE__ */ jsx11(Copy2, { className: "size-[18px]" })
1789
+ }
1790
+ );
1791
+ };
1792
+ CopilotChatUserMessage2.EditButton = ({ className, title, ...props }) => {
1793
+ const { labels } = useCopilotChatConfiguration();
1794
+ return /* @__PURE__ */ jsx11(
1795
+ CopilotChatUserMessage2.ToolbarButton,
1796
+ {
1797
+ title: title || labels.userMessageToolbarEditMessageLabel,
1798
+ className,
1799
+ ...props,
1800
+ children: /* @__PURE__ */ jsx11(Edit, { className: "size-[18px]" })
1801
+ }
1802
+ );
1803
+ };
1804
+ CopilotChatUserMessage2.BranchNavigation = ({
1805
+ className,
1806
+ currentBranch = 0,
1807
+ numberOfBranches = 1,
1808
+ onSwitchToBranch,
1809
+ message,
1810
+ ...props
1811
+ }) => {
1812
+ if (!numberOfBranches || numberOfBranches <= 1 || !onSwitchToBranch) {
1813
+ return null;
1814
+ }
1815
+ const canGoPrev = currentBranch > 0;
1816
+ const canGoNext = currentBranch < numberOfBranches - 1;
1817
+ return /* @__PURE__ */ jsxs5("div", { className: twMerge5("flex items-center gap-1", className), ...props, children: [
1818
+ /* @__PURE__ */ jsx11(
1819
+ Button,
1820
+ {
1821
+ type: "button",
1822
+ variant: "assistantMessageToolbarButton",
1823
+ onClick: () => onSwitchToBranch?.({
1824
+ branchIndex: currentBranch - 1,
1825
+ numberOfBranches,
1826
+ message
1827
+ }),
1828
+ disabled: !canGoPrev,
1829
+ className: "h-6 w-6 p-0",
1830
+ children: /* @__PURE__ */ jsx11(ChevronLeft, { className: "size-[20px]" })
1831
+ }
1832
+ ),
1833
+ /* @__PURE__ */ jsxs5("span", { className: "text-sm text-muted-foreground px-0 font-medium", children: [
1834
+ currentBranch + 1,
1835
+ "/",
1836
+ numberOfBranches
1837
+ ] }),
1838
+ /* @__PURE__ */ jsx11(
1839
+ Button,
1840
+ {
1841
+ type: "button",
1842
+ variant: "assistantMessageToolbarButton",
1843
+ onClick: () => onSwitchToBranch?.({
1844
+ branchIndex: currentBranch + 1,
1845
+ numberOfBranches,
1846
+ message
1847
+ }),
1848
+ disabled: !canGoNext,
1849
+ className: "h-6 w-6 p-0",
1850
+ children: /* @__PURE__ */ jsx11(ChevronRight, { className: "size-[20px]" })
1851
+ }
1852
+ )
1853
+ ] });
1854
+ };
1855
+ })(CopilotChatUserMessage || (CopilotChatUserMessage = {}));
1856
+ CopilotChatUserMessage.Container.displayName = "CopilotChatUserMessage.Container";
1857
+ CopilotChatUserMessage.MessageRenderer.displayName = "CopilotChatUserMessage.MessageRenderer";
1858
+ CopilotChatUserMessage.Toolbar.displayName = "CopilotChatUserMessage.Toolbar";
1859
+ CopilotChatUserMessage.ToolbarButton.displayName = "CopilotChatUserMessage.ToolbarButton";
1860
+ CopilotChatUserMessage.CopyButton.displayName = "CopilotChatUserMessage.CopyButton";
1861
+ CopilotChatUserMessage.EditButton.displayName = "CopilotChatUserMessage.EditButton";
1862
+ CopilotChatUserMessage.BranchNavigation.displayName = "CopilotChatUserMessage.BranchNavigation";
1863
+ var CopilotChatUserMessage_default = CopilotChatUserMessage;
1864
+
1865
+ // src/components/chat/CopilotChatMessageView.tsx
1866
+ import { twMerge as twMerge6 } from "tailwind-merge";
1867
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
1868
+ function CopilotChatMessageView({
1869
+ messages = [],
1870
+ assistantMessage,
1871
+ userMessage,
1872
+ cursor,
1873
+ isLoading = false,
1874
+ children,
1875
+ className,
1876
+ ...props
1877
+ }) {
1878
+ const messageElements = messages.map((message) => {
1879
+ if (message.role === "assistant") {
1880
+ return renderSlot(assistantMessage, CopilotChatAssistantMessage_default, {
1881
+ key: message.id,
1882
+ message,
1883
+ messages,
1884
+ isLoading
1885
+ });
1886
+ } else if (message.role === "user") {
1887
+ return renderSlot(userMessage, CopilotChatUserMessage_default, {
1888
+ key: message.id,
1889
+ message
1890
+ });
1891
+ }
1892
+ return;
1893
+ }).filter(Boolean);
1894
+ if (children) {
1895
+ return children({ messageElements, messages, isLoading });
1896
+ }
1897
+ return /* @__PURE__ */ jsxs6("div", { className: twMerge6("flex flex-col", className), ...props, children: [
1898
+ messageElements,
1899
+ isLoading && renderSlot(cursor, CopilotChatMessageView.Cursor, {})
1900
+ ] });
1901
+ }
1902
+ CopilotChatMessageView.Cursor = function Cursor({
1903
+ className,
1904
+ ...props
1905
+ }) {
1906
+ return /* @__PURE__ */ jsx12(
1907
+ "div",
1908
+ {
1909
+ className: twMerge6(
1910
+ "w-[11px] h-[11px] rounded-full bg-foreground animate-pulse-cursor ml-1",
1911
+ className
1912
+ ),
1913
+ ...props
1914
+ }
1915
+ );
1916
+ };
1917
+ var CopilotChatMessageView_default = CopilotChatMessageView;
1918
+
1919
+ // src/components/chat/CopilotChatView.tsx
1920
+ import React8, { useRef as useRef5, useState as useState7, useEffect as useEffect7 } from "react";
1921
+ import { twMerge as twMerge7 } from "tailwind-merge";
1922
+ import { StickToBottom, useStickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
1923
+ import { ChevronDown } from "lucide-react";
1924
+ import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1925
+ function CopilotChatView({
1926
+ messageView,
1927
+ input,
1928
+ scrollView,
1929
+ scrollToBottomButton,
1930
+ feather,
1931
+ inputContainer,
1932
+ disclaimer,
1933
+ messages = [],
1934
+ autoScroll = true,
1935
+ children,
1936
+ className,
1937
+ ...props
1938
+ }) {
1939
+ const inputContainerRef = useRef5(null);
1940
+ const [inputContainerHeight, setInputContainerHeight] = useState7(0);
1941
+ const [isResizing, setIsResizing] = useState7(false);
1942
+ const resizeTimeoutRef = useRef5(null);
1943
+ useEffect7(() => {
1944
+ const element = inputContainerRef.current;
1945
+ if (!element) return;
1946
+ const resizeObserver = new ResizeObserver((entries) => {
1947
+ for (const entry of entries) {
1948
+ const newHeight = entry.contentRect.height;
1949
+ setInputContainerHeight((prevHeight) => {
1950
+ if (newHeight !== prevHeight) {
1951
+ setIsResizing(true);
1952
+ if (resizeTimeoutRef.current) {
1953
+ clearTimeout(resizeTimeoutRef.current);
1954
+ }
1955
+ resizeTimeoutRef.current = setTimeout(() => {
1956
+ setIsResizing(false);
1957
+ }, 250);
1958
+ return newHeight;
1959
+ }
1960
+ return prevHeight;
1961
+ });
1962
+ }
1963
+ });
1964
+ resizeObserver.observe(element);
1965
+ setInputContainerHeight(element.offsetHeight);
1966
+ return () => {
1967
+ resizeObserver.disconnect();
1968
+ if (resizeTimeoutRef.current) {
1969
+ clearTimeout(resizeTimeoutRef.current);
1970
+ }
1971
+ };
1972
+ }, []);
1973
+ const BoundMessageView = renderSlot(messageView, CopilotChatMessageView_default, {
1974
+ messages
1975
+ });
1976
+ const BoundInput = renderSlot(input, CopilotChatInput_default, {});
1977
+ const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
1978
+ const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {
1979
+ autoScroll,
1980
+ scrollToBottomButton,
1981
+ inputContainerHeight,
1982
+ isResizing,
1983
+ children: /* @__PURE__ */ jsx13("div", { style: { paddingBottom: `${inputContainerHeight + 32}px` }, children: /* @__PURE__ */ jsx13("div", { className: "max-w-3xl mx-auto", children: BoundMessageView }) })
1984
+ });
1985
+ const BoundScrollToBottomButton = renderSlot(
1986
+ scrollToBottomButton,
1987
+ CopilotChatView.ScrollToBottomButton,
1988
+ {}
1989
+ );
1990
+ const BoundDisclaimer = renderSlot(
1991
+ disclaimer,
1992
+ CopilotChatView.Disclaimer,
1993
+ {}
1994
+ );
1995
+ const BoundInputContainer = renderSlot(
1996
+ inputContainer,
1997
+ CopilotChatView.InputContainer,
1998
+ {
1999
+ ref: inputContainerRef,
2000
+ children: /* @__PURE__ */ jsxs7(Fragment5, { children: [
2001
+ /* @__PURE__ */ jsx13("div", { className: "max-w-3xl mx-auto py-0 px-4 sm:px-0", children: BoundInput }),
2002
+ BoundDisclaimer
2003
+ ] })
2004
+ }
2005
+ );
2006
+ if (children) {
2007
+ return children({
2008
+ messageView: BoundMessageView,
2009
+ input: BoundInput,
2010
+ scrollView: BoundScrollView,
2011
+ scrollToBottomButton: BoundScrollToBottomButton,
2012
+ feather: BoundFeather,
2013
+ inputContainer: BoundInputContainer,
2014
+ disclaimer: BoundDisclaimer
2015
+ });
2016
+ }
2017
+ return /* @__PURE__ */ jsxs7("div", { className: twMerge7("relative h-full", className), ...props, children: [
2018
+ BoundScrollView,
2019
+ BoundFeather,
2020
+ BoundInputContainer
2021
+ ] });
2022
+ }
2023
+ ((CopilotChatView2) => {
2024
+ const ScrollContent = ({ children, scrollToBottomButton, inputContainerHeight, isResizing }) => {
2025
+ const { isAtBottom, scrollToBottom } = useStickToBottomContext();
2026
+ return /* @__PURE__ */ jsxs7(Fragment5, { children: [
2027
+ /* @__PURE__ */ jsx13(StickToBottom.Content, { className: "overflow-y-scroll overflow-x-hidden", children: /* @__PURE__ */ jsx13("div", { className: "px-4 sm:px-0", children }) }),
2028
+ !isAtBottom && !isResizing && /* @__PURE__ */ jsx13(
2029
+ "div",
2030
+ {
2031
+ className: "absolute inset-x-0 flex justify-center z-10",
2032
+ style: {
2033
+ bottom: `${inputContainerHeight + 16}px`
2034
+ },
2035
+ children: renderSlot(
2036
+ scrollToBottomButton,
2037
+ CopilotChatView2.ScrollToBottomButton,
2038
+ {
2039
+ onClick: () => scrollToBottom()
2040
+ }
2041
+ )
2042
+ }
2043
+ )
2044
+ ] });
2045
+ };
2046
+ CopilotChatView2.ScrollView = ({
2047
+ children,
2048
+ autoScroll = true,
2049
+ scrollToBottomButton,
2050
+ inputContainerHeight = 0,
2051
+ isResizing = false,
2052
+ className,
2053
+ ...props
2054
+ }) => {
2055
+ const [hasMounted, setHasMounted] = useState7(false);
2056
+ const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();
2057
+ const [showScrollButton, setShowScrollButton] = useState7(false);
2058
+ useEffect7(() => {
2059
+ setHasMounted(true);
2060
+ }, []);
2061
+ useEffect7(() => {
2062
+ if (autoScroll) return;
2063
+ const scrollElement = scrollRef.current;
2064
+ if (!scrollElement) return;
2065
+ const checkScroll = () => {
2066
+ const atBottom = scrollElement.scrollHeight - scrollElement.scrollTop - scrollElement.clientHeight < 10;
2067
+ setShowScrollButton(!atBottom);
2068
+ };
2069
+ checkScroll();
2070
+ scrollElement.addEventListener("scroll", checkScroll);
2071
+ const resizeObserver = new ResizeObserver(checkScroll);
2072
+ resizeObserver.observe(scrollElement);
2073
+ return () => {
2074
+ scrollElement.removeEventListener("scroll", checkScroll);
2075
+ resizeObserver.disconnect();
2076
+ };
2077
+ }, [scrollRef, autoScroll]);
2078
+ if (!hasMounted) {
2079
+ return /* @__PURE__ */ jsx13("div", { className: "h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden", children: /* @__PURE__ */ jsx13("div", { className: "px-4 sm:px-0", children }) });
2080
+ }
2081
+ if (!autoScroll) {
2082
+ return /* @__PURE__ */ jsxs7(
2083
+ "div",
2084
+ {
2085
+ ref: scrollRef,
2086
+ className: cn("h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden relative", className),
2087
+ ...props,
2088
+ children: [
2089
+ /* @__PURE__ */ jsx13("div", { ref: contentRef, className: "px-4 sm:px-0", children }),
2090
+ showScrollButton && !isResizing && /* @__PURE__ */ jsx13(
2091
+ "div",
2092
+ {
2093
+ className: "absolute inset-x-0 flex justify-center z-10",
2094
+ style: {
2095
+ bottom: `${inputContainerHeight + 16}px`
2096
+ },
2097
+ children: renderSlot(
2098
+ scrollToBottomButton,
2099
+ CopilotChatView2.ScrollToBottomButton,
2100
+ {
2101
+ onClick: () => scrollToBottom()
2102
+ }
2103
+ )
2104
+ }
2105
+ )
2106
+ ]
2107
+ }
2108
+ );
2109
+ }
2110
+ return /* @__PURE__ */ jsx13(
2111
+ StickToBottom,
2112
+ {
2113
+ className: cn("h-full max-h-full flex flex-col min-h-0 relative", className),
2114
+ resize: "smooth",
2115
+ initial: "smooth",
2116
+ ...props,
2117
+ children: /* @__PURE__ */ jsx13(
2118
+ ScrollContent,
2119
+ {
2120
+ scrollToBottomButton,
2121
+ inputContainerHeight,
2122
+ isResizing,
2123
+ children
2124
+ }
2125
+ )
2126
+ }
2127
+ );
2128
+ };
2129
+ CopilotChatView2.ScrollToBottomButton = ({ className, ...props }) => /* @__PURE__ */ jsx13(
2130
+ Button,
2131
+ {
2132
+ variant: "outline",
2133
+ size: "sm",
2134
+ className: twMerge7(
2135
+ "rounded-full w-10 h-10 p-0",
2136
+ "bg-white dark:bg-gray-900",
2137
+ "shadow-lg border border-gray-200 dark:border-gray-700",
2138
+ "hover:bg-gray-50 dark:hover:bg-gray-800",
2139
+ "flex items-center justify-center cursor-pointer",
2140
+ className
2141
+ ),
2142
+ ...props,
2143
+ children: /* @__PURE__ */ jsx13(ChevronDown, { className: "w-4 h-4 text-gray-600 dark:text-white" })
2144
+ }
2145
+ );
2146
+ CopilotChatView2.Feather = ({
2147
+ className,
2148
+ style,
2149
+ ...props
2150
+ }) => /* @__PURE__ */ jsx13(
2151
+ "div",
2152
+ {
2153
+ className: cn(
2154
+ "absolute bottom-0 left-0 right-4 h-24 pointer-events-none z-10 bg-gradient-to-t",
2155
+ "from-white via-white to-transparent",
2156
+ "dark:from-[rgb(33,33,33)] dark:via-[rgb(33,33,33)]",
2157
+ className
2158
+ ),
2159
+ style,
2160
+ ...props
2161
+ }
2162
+ );
2163
+ CopilotChatView2.InputContainer = React8.forwardRef(({ children, className, ...props }, ref) => /* @__PURE__ */ jsx13(
2164
+ "div",
2165
+ {
2166
+ ref,
2167
+ className: cn("absolute bottom-0 left-0 right-0 z-20", className),
2168
+ ...props,
2169
+ children
2170
+ }
2171
+ ));
2172
+ CopilotChatView2.InputContainer.displayName = "CopilotChatView.InputContainer";
2173
+ CopilotChatView2.Disclaimer = ({
2174
+ className,
2175
+ ...props
2176
+ }) => {
2177
+ const { labels } = useCopilotChatConfiguration();
2178
+ return /* @__PURE__ */ jsx13(
2179
+ "div",
2180
+ {
2181
+ className: cn(
2182
+ "text-center text-xs text-muted-foreground py-3 px-4 max-w-3xl mx-auto",
2183
+ className
2184
+ ),
2185
+ ...props,
2186
+ children: labels.chatDisclaimerText
2187
+ }
2188
+ );
2189
+ };
2190
+ })(CopilotChatView || (CopilotChatView = {}));
2191
+ var CopilotChatView_default = CopilotChatView;
2192
+
2193
+ // src/components/chat/CopilotChat.tsx
2194
+ import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID2, randomUUID } from "@copilotkitnext/shared";
2195
+ import { useCallback as useCallback3, useState as useState8, useEffect as useEffect8, useMemo as useMemo3 } from "react";
2196
+ import { merge } from "ts-deepmerge";
2197
+ import { jsx as jsx14 } from "react/jsx-runtime";
2198
+ function CopilotChat({
2199
+ agentId = DEFAULT_AGENT_ID2,
2200
+ threadId,
2201
+ ...props
2202
+ }) {
2203
+ const { agent } = useAgent({ agentId });
2204
+ const [isLoading, setIsLoading] = useState8(false);
2205
+ threadId = threadId ?? useMemo3(() => randomUUID(), []);
2206
+ const subscriber = {
2207
+ onTextMessageStartEvent: () => setIsLoading(false),
2208
+ onToolCallStartEvent: () => setIsLoading(false)
2209
+ };
2210
+ useEffect8(() => {
2211
+ const connect = async () => {
2212
+ setIsLoading(true);
2213
+ await agent?.runAgent(
2214
+ {
2215
+ forwardedProps: { __copilotkitConnect: true }
2216
+ },
2217
+ subscriber
2218
+ );
2219
+ setIsLoading(false);
2220
+ };
2221
+ if (agent) {
2222
+ agent.threadId = threadId;
2223
+ if ("isCopilotKitAgent" in agent) {
2224
+ connect();
2225
+ } else {
2226
+ setIsLoading(false);
2227
+ }
2228
+ }
2229
+ return () => {
2230
+ };
2231
+ }, [threadId, agent]);
2232
+ const [inputValue, setInputValue] = useState8("");
2233
+ const onSubmitInput = useCallback3(
2234
+ async (value) => {
2235
+ setInputValue("");
2236
+ agent?.addMessage({
2237
+ id: randomUUID(),
2238
+ role: "user",
2239
+ content: value
2240
+ });
2241
+ setIsLoading(true);
2242
+ await agent?.runAgent({}, subscriber);
2243
+ setIsLoading(false);
2244
+ },
2245
+ [agent]
2246
+ );
2247
+ const mergedProps = merge(
2248
+ {
2249
+ messageView: { isLoading }
2250
+ },
2251
+ {
2252
+ ...props,
2253
+ ...typeof props.messageView === "string" ? { messageView: { className: props.messageView } } : props.messageView !== void 0 ? { messageView: props.messageView } : {}
2254
+ }
2255
+ );
2256
+ return /* @__PURE__ */ jsx14(
2257
+ CopilotChatConfigurationProvider,
2258
+ {
2259
+ inputValue,
2260
+ onSubmitInput,
2261
+ onChangeInput: setInputValue,
2262
+ children: /* @__PURE__ */ jsx14(
2263
+ CopilotChatView,
2264
+ {
2265
+ ...{ messages: agent?.messages ?? [], ...mergedProps }
2266
+ }
2267
+ )
2268
+ }
2269
+ );
2270
+ }
2271
+ export {
2272
+ AudioRecorderError,
2273
+ CopilotChat,
2274
+ CopilotChatAssistantMessage_default as CopilotChatAssistantMessage,
2275
+ CopilotChatAudioRecorder,
2276
+ CopilotChatConfigurationProvider,
2277
+ CopilotChatInput_default as CopilotChatInput,
2278
+ CopilotChatMessageView_default as CopilotChatMessageView,
2279
+ CopilotChatToolCallsView_default as CopilotChatToolCallsView,
2280
+ CopilotChatUserMessage_default as CopilotChatUserMessage,
2281
+ CopilotChatView_default as CopilotChatView,
2282
+ CopilotKitProvider,
2283
+ useAgent,
2284
+ useAgentContext,
2285
+ useCopilotChatConfiguration,
2286
+ useCopilotKit,
2287
+ useFrontendTool,
2288
+ useHumanInTheLoop,
2289
+ useRenderToolCall
2290
+ };
2291
+ //# sourceMappingURL=index.mjs.map