@copilotkitnext/react 0.0.0-0.0.0-max-changeset-10101010101010-20260109191632
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/LICENSE +21 -0
- package/components.json +20 -0
- package/dist/index.d.mts +744 -0
- package/dist/index.d.ts +744 -0
- package/dist/index.js +4587 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4527 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +2 -0
- package/eslint.config.mjs +11 -0
- package/package.json +85 -0
- package/test.css +2355 -0
- package/vitest.config.mjs +20 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,4527 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
export * from "@ag-ui/core";
|
|
5
|
+
export * from "@ag-ui/client";
|
|
6
|
+
|
|
7
|
+
// src/components/chat/CopilotChatInput.tsx
|
|
8
|
+
import {
|
|
9
|
+
useState as useState2,
|
|
10
|
+
useRef as useRef2,
|
|
11
|
+
useEffect as useEffect2,
|
|
12
|
+
useLayoutEffect,
|
|
13
|
+
forwardRef as forwardRef2,
|
|
14
|
+
useImperativeHandle as useImperativeHandle2,
|
|
15
|
+
useCallback,
|
|
16
|
+
useMemo as useMemo2
|
|
17
|
+
} from "react";
|
|
18
|
+
import { twMerge as twMerge3 } from "tailwind-merge";
|
|
19
|
+
import { Plus, Mic, ArrowUp, X, Check, Square } from "lucide-react";
|
|
20
|
+
|
|
21
|
+
// src/providers/CopilotChatConfigurationProvider.tsx
|
|
22
|
+
import { createContext, useContext, useMemo, useState } from "react";
|
|
23
|
+
import { DEFAULT_AGENT_ID, randomUUID } from "@copilotkitnext/shared";
|
|
24
|
+
import { jsx } from "react/jsx-runtime";
|
|
25
|
+
var CopilotChatDefaultLabels = {
|
|
26
|
+
chatInputPlaceholder: "Type a message...",
|
|
27
|
+
chatInputToolbarStartTranscribeButtonLabel: "Transcribe",
|
|
28
|
+
chatInputToolbarCancelTranscribeButtonLabel: "Cancel",
|
|
29
|
+
chatInputToolbarFinishTranscribeButtonLabel: "Finish",
|
|
30
|
+
chatInputToolbarAddButtonLabel: "Add photos or files",
|
|
31
|
+
chatInputToolbarToolsButtonLabel: "Tools",
|
|
32
|
+
assistantMessageToolbarCopyCodeLabel: "Copy",
|
|
33
|
+
assistantMessageToolbarCopyCodeCopiedLabel: "Copied",
|
|
34
|
+
assistantMessageToolbarCopyMessageLabel: "Copy",
|
|
35
|
+
assistantMessageToolbarThumbsUpLabel: "Good response",
|
|
36
|
+
assistantMessageToolbarThumbsDownLabel: "Bad response",
|
|
37
|
+
assistantMessageToolbarReadAloudLabel: "Read aloud",
|
|
38
|
+
assistantMessageToolbarRegenerateLabel: "Regenerate",
|
|
39
|
+
userMessageToolbarCopyMessageLabel: "Copy",
|
|
40
|
+
userMessageToolbarEditMessageLabel: "Edit",
|
|
41
|
+
chatDisclaimerText: "AI can make mistakes. Please verify important information.",
|
|
42
|
+
chatToggleOpenLabel: "Open chat",
|
|
43
|
+
chatToggleCloseLabel: "Close chat",
|
|
44
|
+
modalHeaderTitle: "CopilotKit Chat"
|
|
45
|
+
};
|
|
46
|
+
var CopilotChatConfiguration = createContext(null);
|
|
47
|
+
var CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, isModalDefaultOpen }) => {
|
|
48
|
+
const parentConfig = useContext(CopilotChatConfiguration);
|
|
49
|
+
const mergedLabels = useMemo(
|
|
50
|
+
() => ({
|
|
51
|
+
...CopilotChatDefaultLabels,
|
|
52
|
+
...parentConfig?.labels ?? {},
|
|
53
|
+
...labels ?? {}
|
|
54
|
+
}),
|
|
55
|
+
[labels, parentConfig?.labels]
|
|
56
|
+
);
|
|
57
|
+
const resolvedAgentId = agentId ?? parentConfig?.agentId ?? DEFAULT_AGENT_ID;
|
|
58
|
+
const resolvedThreadId = useMemo(() => {
|
|
59
|
+
if (threadId) {
|
|
60
|
+
return threadId;
|
|
61
|
+
}
|
|
62
|
+
if (parentConfig?.threadId) {
|
|
63
|
+
return parentConfig.threadId;
|
|
64
|
+
}
|
|
65
|
+
return randomUUID();
|
|
66
|
+
}, [threadId, parentConfig?.threadId]);
|
|
67
|
+
const resolvedDefaultOpen = isModalDefaultOpen ?? parentConfig?.isModalDefaultOpen ?? true;
|
|
68
|
+
const [internalModalOpen, setInternalModalOpen] = useState(
|
|
69
|
+
parentConfig?.isModalOpen ?? resolvedDefaultOpen
|
|
70
|
+
);
|
|
71
|
+
const resolvedIsModalOpen = parentConfig?.isModalOpen ?? internalModalOpen;
|
|
72
|
+
const resolvedSetModalOpen = parentConfig?.setModalOpen ?? setInternalModalOpen;
|
|
73
|
+
const configurationValue = useMemo(
|
|
74
|
+
() => ({
|
|
75
|
+
labels: mergedLabels,
|
|
76
|
+
agentId: resolvedAgentId,
|
|
77
|
+
threadId: resolvedThreadId,
|
|
78
|
+
isModalOpen: resolvedIsModalOpen,
|
|
79
|
+
setModalOpen: resolvedSetModalOpen,
|
|
80
|
+
isModalDefaultOpen: resolvedDefaultOpen
|
|
81
|
+
}),
|
|
82
|
+
[
|
|
83
|
+
mergedLabels,
|
|
84
|
+
resolvedAgentId,
|
|
85
|
+
resolvedThreadId,
|
|
86
|
+
resolvedIsModalOpen,
|
|
87
|
+
resolvedSetModalOpen,
|
|
88
|
+
resolvedDefaultOpen
|
|
89
|
+
]
|
|
90
|
+
);
|
|
91
|
+
return /* @__PURE__ */ jsx(CopilotChatConfiguration.Provider, { value: configurationValue, children });
|
|
92
|
+
};
|
|
93
|
+
var useCopilotChatConfiguration = () => {
|
|
94
|
+
const configuration = useContext(CopilotChatConfiguration);
|
|
95
|
+
return configuration;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// src/components/ui/button.tsx
|
|
99
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
100
|
+
import { cva } from "class-variance-authority";
|
|
101
|
+
|
|
102
|
+
// src/lib/utils.ts
|
|
103
|
+
import { clsx } from "clsx";
|
|
104
|
+
import { twMerge } from "tailwind-merge";
|
|
105
|
+
function cn(...inputs) {
|
|
106
|
+
return twMerge(clsx(inputs));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/components/ui/button.tsx
|
|
110
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
111
|
+
var buttonVariants = cva(
|
|
112
|
+
"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",
|
|
113
|
+
{
|
|
114
|
+
variants: {
|
|
115
|
+
variant: {
|
|
116
|
+
default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
|
117
|
+
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",
|
|
118
|
+
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",
|
|
119
|
+
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
120
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 cursor-pointer",
|
|
121
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
122
|
+
assistantMessageToolbarButton: [
|
|
123
|
+
"cursor-pointer",
|
|
124
|
+
// Background and text
|
|
125
|
+
"p-0 text-[rgb(93,93,93)] hover:bg-[#E8E8E8]",
|
|
126
|
+
// Dark mode - lighter gray for better contrast
|
|
127
|
+
"dark:text-[rgb(243,243,243)] dark:hover:bg-[#303030]",
|
|
128
|
+
// Shape and sizing
|
|
129
|
+
"h-8 w-8",
|
|
130
|
+
// Interactions
|
|
131
|
+
"transition-colors",
|
|
132
|
+
// Hover states
|
|
133
|
+
"hover:text-[rgb(93,93,93)]",
|
|
134
|
+
"dark:hover:text-[rgb(243,243,243)]"
|
|
135
|
+
],
|
|
136
|
+
chatInputToolbarPrimary: [
|
|
137
|
+
"cursor-pointer",
|
|
138
|
+
// Background and text
|
|
139
|
+
"bg-black text-white",
|
|
140
|
+
// Dark mode
|
|
141
|
+
"dark:bg-white dark:text-black dark:focus-visible:outline-white",
|
|
142
|
+
// Shape and sizing
|
|
143
|
+
"rounded-full",
|
|
144
|
+
// Interactions
|
|
145
|
+
"transition-colors",
|
|
146
|
+
// Focus states
|
|
147
|
+
"focus:outline-none",
|
|
148
|
+
// Hover states
|
|
149
|
+
"hover:opacity-70 disabled:hover:opacity-100",
|
|
150
|
+
// Disabled states
|
|
151
|
+
"disabled:cursor-not-allowed disabled:bg-[#00000014] disabled:text-[rgb(13,13,13)]",
|
|
152
|
+
"dark:disabled:bg-[#454545] dark:disabled:text-white "
|
|
153
|
+
],
|
|
154
|
+
chatInputToolbarSecondary: [
|
|
155
|
+
"cursor-pointer",
|
|
156
|
+
// Background and text
|
|
157
|
+
"bg-transparent text-[#444444]",
|
|
158
|
+
// Dark mode
|
|
159
|
+
"dark:text-white dark:border-[#404040]",
|
|
160
|
+
// Shape and sizing
|
|
161
|
+
"rounded-full",
|
|
162
|
+
// Interactions
|
|
163
|
+
"transition-colors",
|
|
164
|
+
// Focus states
|
|
165
|
+
"focus:outline-none",
|
|
166
|
+
// Hover states
|
|
167
|
+
"hover:bg-[#f8f8f8] hover:text-[#333333]",
|
|
168
|
+
"dark:hover:bg-[#404040] dark:hover:text-[#FFFFFF]",
|
|
169
|
+
// Disabled states
|
|
170
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
171
|
+
"disabled:hover:bg-transparent disabled:hover:text-[#444444]",
|
|
172
|
+
"dark:disabled:hover:bg-transparent dark:disabled:hover:text-[#CCCCCC]"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
size: {
|
|
176
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
177
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
178
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
179
|
+
icon: "size-9",
|
|
180
|
+
chatInputToolbarIcon: [
|
|
181
|
+
// Shape and sizing
|
|
182
|
+
"h-9 w-9 rounded-full"
|
|
183
|
+
],
|
|
184
|
+
chatInputToolbarIconLabel: [
|
|
185
|
+
// Shape and sizing
|
|
186
|
+
"h-9 px-3 rounded-full",
|
|
187
|
+
// Layout
|
|
188
|
+
"gap-2",
|
|
189
|
+
// Typography
|
|
190
|
+
"font-normal"
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
defaultVariants: {
|
|
195
|
+
variant: "default",
|
|
196
|
+
size: "default"
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
function Button({
|
|
201
|
+
className,
|
|
202
|
+
variant,
|
|
203
|
+
size,
|
|
204
|
+
asChild = false,
|
|
205
|
+
...props
|
|
206
|
+
}) {
|
|
207
|
+
const Comp = asChild ? Slot : "button";
|
|
208
|
+
return /* @__PURE__ */ jsx2(
|
|
209
|
+
Comp,
|
|
210
|
+
{
|
|
211
|
+
"data-slot": "button",
|
|
212
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
213
|
+
...props
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/components/ui/tooltip.tsx
|
|
219
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
220
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
221
|
+
function TooltipProvider({
|
|
222
|
+
delayDuration = 0,
|
|
223
|
+
...props
|
|
224
|
+
}) {
|
|
225
|
+
return /* @__PURE__ */ jsx3(
|
|
226
|
+
TooltipPrimitive.Provider,
|
|
227
|
+
{
|
|
228
|
+
"data-slot": "tooltip-provider",
|
|
229
|
+
delayDuration,
|
|
230
|
+
...props
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
function Tooltip({
|
|
235
|
+
...props
|
|
236
|
+
}) {
|
|
237
|
+
return /* @__PURE__ */ jsx3(TooltipProvider, { children: /* @__PURE__ */ jsx3(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
|
|
238
|
+
}
|
|
239
|
+
function TooltipTrigger({
|
|
240
|
+
...props
|
|
241
|
+
}) {
|
|
242
|
+
return /* @__PURE__ */ jsx3(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
243
|
+
}
|
|
244
|
+
function TooltipContent({
|
|
245
|
+
className,
|
|
246
|
+
sideOffset = 0,
|
|
247
|
+
children,
|
|
248
|
+
...props
|
|
249
|
+
}) {
|
|
250
|
+
return /* @__PURE__ */ jsx3(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
251
|
+
TooltipPrimitive.Content,
|
|
252
|
+
{
|
|
253
|
+
"data-slot": "tooltip-content",
|
|
254
|
+
sideOffset,
|
|
255
|
+
className: cn(
|
|
256
|
+
"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",
|
|
257
|
+
className
|
|
258
|
+
),
|
|
259
|
+
...props,
|
|
260
|
+
children: [
|
|
261
|
+
children,
|
|
262
|
+
/* @__PURE__ */ jsx3(TooltipPrimitive.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
) });
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/components/ui/dropdown-menu.tsx
|
|
269
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
270
|
+
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
|
271
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
272
|
+
function DropdownMenu({
|
|
273
|
+
...props
|
|
274
|
+
}) {
|
|
275
|
+
return /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
276
|
+
}
|
|
277
|
+
function DropdownMenuTrigger({
|
|
278
|
+
...props
|
|
279
|
+
}) {
|
|
280
|
+
return /* @__PURE__ */ jsx4(
|
|
281
|
+
DropdownMenuPrimitive.Trigger,
|
|
282
|
+
{
|
|
283
|
+
"data-slot": "dropdown-menu-trigger",
|
|
284
|
+
...props
|
|
285
|
+
}
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
function DropdownMenuContent({
|
|
289
|
+
className,
|
|
290
|
+
sideOffset = 4,
|
|
291
|
+
...props
|
|
292
|
+
}) {
|
|
293
|
+
return /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx4(
|
|
294
|
+
DropdownMenuPrimitive.Content,
|
|
295
|
+
{
|
|
296
|
+
"data-slot": "dropdown-menu-content",
|
|
297
|
+
sideOffset,
|
|
298
|
+
className: cn(
|
|
299
|
+
"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",
|
|
300
|
+
className
|
|
301
|
+
),
|
|
302
|
+
...props
|
|
303
|
+
}
|
|
304
|
+
) });
|
|
305
|
+
}
|
|
306
|
+
function DropdownMenuItem({
|
|
307
|
+
className,
|
|
308
|
+
inset,
|
|
309
|
+
variant = "default",
|
|
310
|
+
...props
|
|
311
|
+
}) {
|
|
312
|
+
return /* @__PURE__ */ jsx4(
|
|
313
|
+
DropdownMenuPrimitive.Item,
|
|
314
|
+
{
|
|
315
|
+
"data-slot": "dropdown-menu-item",
|
|
316
|
+
"data-inset": inset,
|
|
317
|
+
"data-variant": variant,
|
|
318
|
+
className: cn(
|
|
319
|
+
"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",
|
|
320
|
+
className
|
|
321
|
+
),
|
|
322
|
+
...props
|
|
323
|
+
}
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
function DropdownMenuSeparator({
|
|
327
|
+
className,
|
|
328
|
+
...props
|
|
329
|
+
}) {
|
|
330
|
+
return /* @__PURE__ */ jsx4(
|
|
331
|
+
DropdownMenuPrimitive.Separator,
|
|
332
|
+
{
|
|
333
|
+
"data-slot": "dropdown-menu-separator",
|
|
334
|
+
className: cn("bg-border -mx-1 my-1 h-px", className),
|
|
335
|
+
...props
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
function DropdownMenuSub({
|
|
340
|
+
...props
|
|
341
|
+
}) {
|
|
342
|
+
return /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
|
|
343
|
+
}
|
|
344
|
+
function DropdownMenuSubTrigger({
|
|
345
|
+
className,
|
|
346
|
+
inset,
|
|
347
|
+
children,
|
|
348
|
+
...props
|
|
349
|
+
}) {
|
|
350
|
+
return /* @__PURE__ */ jsxs2(
|
|
351
|
+
DropdownMenuPrimitive.SubTrigger,
|
|
352
|
+
{
|
|
353
|
+
"data-slot": "dropdown-menu-sub-trigger",
|
|
354
|
+
"data-inset": inset,
|
|
355
|
+
className: cn(
|
|
356
|
+
"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",
|
|
357
|
+
className
|
|
358
|
+
),
|
|
359
|
+
...props,
|
|
360
|
+
children: [
|
|
361
|
+
children,
|
|
362
|
+
/* @__PURE__ */ jsx4(ChevronRightIcon, { className: "ml-auto size-4" })
|
|
363
|
+
]
|
|
364
|
+
}
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
function DropdownMenuSubContent({
|
|
368
|
+
className,
|
|
369
|
+
...props
|
|
370
|
+
}) {
|
|
371
|
+
return /* @__PURE__ */ jsx4(
|
|
372
|
+
DropdownMenuPrimitive.SubContent,
|
|
373
|
+
{
|
|
374
|
+
"data-slot": "dropdown-menu-sub-content",
|
|
375
|
+
className: cn(
|
|
376
|
+
"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",
|
|
377
|
+
className
|
|
378
|
+
),
|
|
379
|
+
...props
|
|
380
|
+
}
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/components/chat/CopilotChatAudioRecorder.tsx
|
|
385
|
+
import { useRef, useEffect, useImperativeHandle, forwardRef } from "react";
|
|
386
|
+
import { twMerge as twMerge2 } from "tailwind-merge";
|
|
387
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
388
|
+
var AudioRecorderError = class extends Error {
|
|
389
|
+
constructor(message) {
|
|
390
|
+
super(message);
|
|
391
|
+
this.name = "AudioRecorderError";
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
var CopilotChatAudioRecorder = forwardRef((props, ref) => {
|
|
395
|
+
const { className, ...divProps } = props;
|
|
396
|
+
const canvasRef = useRef(null);
|
|
397
|
+
const getLoudness = (n) => {
|
|
398
|
+
const elapsed = Date.now() / 1e3;
|
|
399
|
+
const samples = [];
|
|
400
|
+
for (let i = 0; i < n; i++) {
|
|
401
|
+
const position = i / n * 10 + elapsed * 0.5;
|
|
402
|
+
const wave1 = Math.sin(position * 2) * 0.3;
|
|
403
|
+
const wave2 = Math.sin(position * 5 + elapsed) * 0.2;
|
|
404
|
+
const wave3 = Math.sin(position * 0.5 + elapsed * 0.3) * 0.4;
|
|
405
|
+
const noise = (Math.random() - 0.5) * 0.1;
|
|
406
|
+
const envelope = Math.sin(elapsed * 0.7) * 0.5 + 0.5;
|
|
407
|
+
let amplitude = (wave1 + wave2 + wave3 + noise) * envelope;
|
|
408
|
+
amplitude = Math.max(0, Math.min(1, amplitude * 0.5 + 0.3));
|
|
409
|
+
samples.push(amplitude);
|
|
410
|
+
}
|
|
411
|
+
return samples;
|
|
412
|
+
};
|
|
413
|
+
useEffect(() => {
|
|
414
|
+
const canvas = canvasRef.current;
|
|
415
|
+
if (!canvas) return;
|
|
416
|
+
const ctx = canvas.getContext("2d");
|
|
417
|
+
if (!ctx) return;
|
|
418
|
+
let animationId;
|
|
419
|
+
const draw = () => {
|
|
420
|
+
const rect = canvas.getBoundingClientRect();
|
|
421
|
+
const dpr = window.devicePixelRatio || 1;
|
|
422
|
+
if (canvas.width !== rect.width * dpr || canvas.height !== rect.height * dpr) {
|
|
423
|
+
canvas.width = rect.width * dpr;
|
|
424
|
+
canvas.height = rect.height * dpr;
|
|
425
|
+
ctx.scale(dpr, dpr);
|
|
426
|
+
ctx.imageSmoothingEnabled = false;
|
|
427
|
+
}
|
|
428
|
+
const barWidth = 2;
|
|
429
|
+
const minHeight = 2;
|
|
430
|
+
const maxHeight = 20;
|
|
431
|
+
const gap = 2;
|
|
432
|
+
const numSamples = Math.ceil(rect.width / (barWidth + gap));
|
|
433
|
+
const loudnessData = getLoudness(numSamples);
|
|
434
|
+
ctx.clearRect(0, 0, rect.width, rect.height);
|
|
435
|
+
const computedStyle = getComputedStyle(canvas);
|
|
436
|
+
const currentForeground = computedStyle.color;
|
|
437
|
+
ctx.fillStyle = currentForeground;
|
|
438
|
+
const centerY = rect.height / 2;
|
|
439
|
+
for (let i = 0; i < loudnessData.length; i++) {
|
|
440
|
+
const sample = loudnessData[i] ?? 0;
|
|
441
|
+
const barHeight = Math.round(
|
|
442
|
+
sample * (maxHeight - minHeight) + minHeight
|
|
443
|
+
);
|
|
444
|
+
const x = Math.round(i * (barWidth + gap));
|
|
445
|
+
const y = Math.round(centerY - barHeight / 2);
|
|
446
|
+
ctx.fillRect(x, y, barWidth, barHeight);
|
|
447
|
+
}
|
|
448
|
+
animationId = requestAnimationFrame(draw);
|
|
449
|
+
};
|
|
450
|
+
draw();
|
|
451
|
+
return () => {
|
|
452
|
+
if (animationId) {
|
|
453
|
+
cancelAnimationFrame(animationId);
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
}, []);
|
|
457
|
+
useImperativeHandle(
|
|
458
|
+
ref,
|
|
459
|
+
() => ({
|
|
460
|
+
get state() {
|
|
461
|
+
return "idle";
|
|
462
|
+
},
|
|
463
|
+
start: async () => {
|
|
464
|
+
},
|
|
465
|
+
stop: () => new Promise((resolve) => {
|
|
466
|
+
const emptyBlob = new Blob([], { type: "audio/webm" });
|
|
467
|
+
resolve(emptyBlob);
|
|
468
|
+
}),
|
|
469
|
+
dispose: () => {
|
|
470
|
+
}
|
|
471
|
+
}),
|
|
472
|
+
[]
|
|
473
|
+
);
|
|
474
|
+
return /* @__PURE__ */ jsx5("div", { className: twMerge2("h-[44px] w-full px-5", className), ...divProps, children: /* @__PURE__ */ jsx5(
|
|
475
|
+
"canvas",
|
|
476
|
+
{
|
|
477
|
+
ref: canvasRef,
|
|
478
|
+
className: "w-full h-full",
|
|
479
|
+
style: { imageRendering: "pixelated" }
|
|
480
|
+
}
|
|
481
|
+
) });
|
|
482
|
+
});
|
|
483
|
+
CopilotChatAudioRecorder.displayName = "WebAudioRecorder";
|
|
484
|
+
|
|
485
|
+
// src/lib/slots.tsx
|
|
486
|
+
import React2 from "react";
|
|
487
|
+
function shallowEqual(obj1, obj2) {
|
|
488
|
+
const keys1 = Object.keys(obj1);
|
|
489
|
+
const keys2 = Object.keys(obj2);
|
|
490
|
+
if (keys1.length !== keys2.length) return false;
|
|
491
|
+
for (const key of keys1) {
|
|
492
|
+
if (obj1[key] !== obj2[key]) return false;
|
|
493
|
+
}
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
function renderSlotElement(slot, DefaultComponent, props) {
|
|
497
|
+
if (typeof slot === "string") {
|
|
498
|
+
return React2.createElement(DefaultComponent, {
|
|
499
|
+
...props,
|
|
500
|
+
className: slot
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
if (typeof slot === "function") {
|
|
504
|
+
return React2.createElement(slot, props);
|
|
505
|
+
}
|
|
506
|
+
if (slot && typeof slot === "object" && !React2.isValidElement(slot)) {
|
|
507
|
+
return React2.createElement(DefaultComponent, {
|
|
508
|
+
...props,
|
|
509
|
+
...slot
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
return React2.createElement(DefaultComponent, props);
|
|
513
|
+
}
|
|
514
|
+
var MemoizedSlotWrapper = React2.memo(
|
|
515
|
+
React2.forwardRef(function MemoizedSlotWrapper2(props, ref) {
|
|
516
|
+
const { $slot, $component, ...rest } = props;
|
|
517
|
+
const propsWithRef = ref !== null ? { ...rest, ref } : rest;
|
|
518
|
+
return renderSlotElement($slot, $component, propsWithRef);
|
|
519
|
+
}),
|
|
520
|
+
(prev, next) => {
|
|
521
|
+
if (prev.$slot !== next.$slot) return false;
|
|
522
|
+
if (prev.$component !== next.$component) return false;
|
|
523
|
+
const { $slot: _ps, $component: _pc, ...prevRest } = prev;
|
|
524
|
+
const { $slot: _ns, $component: _nc, ...nextRest } = next;
|
|
525
|
+
return shallowEqual(
|
|
526
|
+
prevRest,
|
|
527
|
+
nextRest
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
);
|
|
531
|
+
function renderSlot(slot, DefaultComponent, props) {
|
|
532
|
+
return React2.createElement(MemoizedSlotWrapper, {
|
|
533
|
+
...props,
|
|
534
|
+
$slot: slot,
|
|
535
|
+
$component: DefaultComponent
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// src/components/chat/CopilotChatInput.tsx
|
|
540
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
541
|
+
var SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
|
|
542
|
+
var SLASH_MENU_ITEM_HEIGHT_PX = 40;
|
|
543
|
+
function CopilotChatInput({
|
|
544
|
+
mode = "input",
|
|
545
|
+
onSubmitMessage,
|
|
546
|
+
onStop,
|
|
547
|
+
isRunning = false,
|
|
548
|
+
onStartTranscribe,
|
|
549
|
+
onCancelTranscribe,
|
|
550
|
+
onFinishTranscribe,
|
|
551
|
+
onAddFile,
|
|
552
|
+
onChange,
|
|
553
|
+
value,
|
|
554
|
+
toolsMenu,
|
|
555
|
+
autoFocus = true,
|
|
556
|
+
textArea,
|
|
557
|
+
sendButton,
|
|
558
|
+
startTranscribeButton,
|
|
559
|
+
cancelTranscribeButton,
|
|
560
|
+
finishTranscribeButton,
|
|
561
|
+
addMenuButton,
|
|
562
|
+
audioRecorder,
|
|
563
|
+
children,
|
|
564
|
+
className,
|
|
565
|
+
...props
|
|
566
|
+
}) {
|
|
567
|
+
const isControlled = value !== void 0;
|
|
568
|
+
const [internalValue, setInternalValue] = useState2(() => value ?? "");
|
|
569
|
+
useEffect2(() => {
|
|
570
|
+
if (!isControlled && value !== void 0) {
|
|
571
|
+
setInternalValue(value);
|
|
572
|
+
}
|
|
573
|
+
}, [isControlled, value]);
|
|
574
|
+
const resolvedValue = isControlled ? value ?? "" : internalValue;
|
|
575
|
+
const [layout, setLayout] = useState2("compact");
|
|
576
|
+
const ignoreResizeRef = useRef2(false);
|
|
577
|
+
const resizeEvaluationRafRef = useRef2(null);
|
|
578
|
+
const isExpanded = mode === "input" && layout === "expanded";
|
|
579
|
+
const [commandQuery, setCommandQuery] = useState2(null);
|
|
580
|
+
const [slashHighlightIndex, setSlashHighlightIndex] = useState2(0);
|
|
581
|
+
const inputRef = useRef2(null);
|
|
582
|
+
const gridRef = useRef2(null);
|
|
583
|
+
const addButtonContainerRef = useRef2(null);
|
|
584
|
+
const actionsContainerRef = useRef2(null);
|
|
585
|
+
const audioRecorderRef = useRef2(null);
|
|
586
|
+
const slashMenuRef = useRef2(null);
|
|
587
|
+
const config = useCopilotChatConfiguration();
|
|
588
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
589
|
+
const previousModalStateRef = useRef2(void 0);
|
|
590
|
+
const measurementCanvasRef = useRef2(null);
|
|
591
|
+
const measurementsRef = useRef2({
|
|
592
|
+
singleLineHeight: 0,
|
|
593
|
+
maxHeight: 0,
|
|
594
|
+
paddingLeft: 0,
|
|
595
|
+
paddingRight: 0
|
|
596
|
+
});
|
|
597
|
+
const commandItems = useMemo2(() => {
|
|
598
|
+
const entries = [];
|
|
599
|
+
const seen = /* @__PURE__ */ new Set();
|
|
600
|
+
const pushItem = (item) => {
|
|
601
|
+
if (item === "-") {
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
if (item.items && item.items.length > 0) {
|
|
605
|
+
for (const nested of item.items) {
|
|
606
|
+
pushItem(nested);
|
|
607
|
+
}
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
if (!seen.has(item.label)) {
|
|
611
|
+
seen.add(item.label);
|
|
612
|
+
entries.push(item);
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
if (onAddFile) {
|
|
616
|
+
pushItem({
|
|
617
|
+
label: labels.chatInputToolbarAddButtonLabel,
|
|
618
|
+
action: onAddFile
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
if (toolsMenu && toolsMenu.length > 0) {
|
|
622
|
+
for (const item of toolsMenu) {
|
|
623
|
+
pushItem(item);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
return entries;
|
|
627
|
+
}, [labels.chatInputToolbarAddButtonLabel, onAddFile, toolsMenu]);
|
|
628
|
+
const filteredCommands = useMemo2(() => {
|
|
629
|
+
if (commandQuery === null) {
|
|
630
|
+
return [];
|
|
631
|
+
}
|
|
632
|
+
if (commandItems.length === 0) {
|
|
633
|
+
return [];
|
|
634
|
+
}
|
|
635
|
+
const query = commandQuery.trim().toLowerCase();
|
|
636
|
+
if (query.length === 0) {
|
|
637
|
+
return commandItems;
|
|
638
|
+
}
|
|
639
|
+
const startsWith = [];
|
|
640
|
+
const contains = [];
|
|
641
|
+
for (const item of commandItems) {
|
|
642
|
+
const label = item.label.toLowerCase();
|
|
643
|
+
if (label.startsWith(query)) {
|
|
644
|
+
startsWith.push(item);
|
|
645
|
+
} else if (label.includes(query)) {
|
|
646
|
+
contains.push(item);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return [...startsWith, ...contains];
|
|
650
|
+
}, [commandItems, commandQuery]);
|
|
651
|
+
useEffect2(() => {
|
|
652
|
+
if (!autoFocus) {
|
|
653
|
+
previousModalStateRef.current = config?.isModalOpen;
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
if (config?.isModalOpen && !previousModalStateRef.current) {
|
|
657
|
+
inputRef.current?.focus();
|
|
658
|
+
}
|
|
659
|
+
previousModalStateRef.current = config?.isModalOpen;
|
|
660
|
+
}, [config?.isModalOpen, autoFocus]);
|
|
661
|
+
useEffect2(() => {
|
|
662
|
+
if (commandItems.length === 0 && commandQuery !== null) {
|
|
663
|
+
setCommandQuery(null);
|
|
664
|
+
}
|
|
665
|
+
}, [commandItems.length, commandQuery]);
|
|
666
|
+
const previousCommandQueryRef = useRef2(null);
|
|
667
|
+
useEffect2(() => {
|
|
668
|
+
if (commandQuery !== null && commandQuery !== previousCommandQueryRef.current && filteredCommands.length > 0) {
|
|
669
|
+
setSlashHighlightIndex(0);
|
|
670
|
+
}
|
|
671
|
+
previousCommandQueryRef.current = commandQuery;
|
|
672
|
+
}, [commandQuery, filteredCommands.length]);
|
|
673
|
+
useEffect2(() => {
|
|
674
|
+
if (commandQuery === null) {
|
|
675
|
+
setSlashHighlightIndex(0);
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
if (filteredCommands.length === 0) {
|
|
679
|
+
setSlashHighlightIndex(-1);
|
|
680
|
+
} else if (slashHighlightIndex < 0 || slashHighlightIndex >= filteredCommands.length) {
|
|
681
|
+
setSlashHighlightIndex(0);
|
|
682
|
+
}
|
|
683
|
+
}, [commandQuery, filteredCommands, slashHighlightIndex]);
|
|
684
|
+
useEffect2(() => {
|
|
685
|
+
const recorder = audioRecorderRef.current;
|
|
686
|
+
if (!recorder) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
if (mode === "transcribe") {
|
|
690
|
+
recorder.start().catch(console.error);
|
|
691
|
+
} else {
|
|
692
|
+
if (recorder.state === "recording") {
|
|
693
|
+
recorder.stop().catch(console.error);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}, [mode]);
|
|
697
|
+
useEffect2(() => {
|
|
698
|
+
if (mode !== "input") {
|
|
699
|
+
setLayout("compact");
|
|
700
|
+
setCommandQuery(null);
|
|
701
|
+
}
|
|
702
|
+
}, [mode]);
|
|
703
|
+
const updateSlashState = useCallback(
|
|
704
|
+
(value2) => {
|
|
705
|
+
if (commandItems.length === 0) {
|
|
706
|
+
setCommandQuery((prev) => prev === null ? prev : null);
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
if (value2.startsWith("/")) {
|
|
710
|
+
const firstLine = value2.split(/\r?\n/, 1)[0] ?? "";
|
|
711
|
+
const query = firstLine.slice(1);
|
|
712
|
+
setCommandQuery((prev) => prev === query ? prev : query);
|
|
713
|
+
} else {
|
|
714
|
+
setCommandQuery((prev) => prev === null ? prev : null);
|
|
715
|
+
}
|
|
716
|
+
},
|
|
717
|
+
[commandItems.length]
|
|
718
|
+
);
|
|
719
|
+
useEffect2(() => {
|
|
720
|
+
updateSlashState(resolvedValue);
|
|
721
|
+
}, [resolvedValue, updateSlashState]);
|
|
722
|
+
const handleChange = (e) => {
|
|
723
|
+
const nextValue = e.target.value;
|
|
724
|
+
if (!isControlled) {
|
|
725
|
+
setInternalValue(nextValue);
|
|
726
|
+
}
|
|
727
|
+
onChange?.(nextValue);
|
|
728
|
+
updateSlashState(nextValue);
|
|
729
|
+
};
|
|
730
|
+
const clearInputValue = useCallback(() => {
|
|
731
|
+
if (!isControlled) {
|
|
732
|
+
setInternalValue("");
|
|
733
|
+
}
|
|
734
|
+
if (onChange) {
|
|
735
|
+
onChange("");
|
|
736
|
+
}
|
|
737
|
+
}, [isControlled, onChange]);
|
|
738
|
+
const runCommand = useCallback(
|
|
739
|
+
(item) => {
|
|
740
|
+
clearInputValue();
|
|
741
|
+
item.action?.();
|
|
742
|
+
setCommandQuery(null);
|
|
743
|
+
setSlashHighlightIndex(0);
|
|
744
|
+
requestAnimationFrame(() => {
|
|
745
|
+
inputRef.current?.focus();
|
|
746
|
+
});
|
|
747
|
+
},
|
|
748
|
+
[clearInputValue]
|
|
749
|
+
);
|
|
750
|
+
const handleKeyDown = (e) => {
|
|
751
|
+
if (commandQuery !== null && mode === "input") {
|
|
752
|
+
if (e.key === "ArrowDown") {
|
|
753
|
+
if (filteredCommands.length > 0) {
|
|
754
|
+
e.preventDefault();
|
|
755
|
+
setSlashHighlightIndex((prev) => {
|
|
756
|
+
if (filteredCommands.length === 0) {
|
|
757
|
+
return prev;
|
|
758
|
+
}
|
|
759
|
+
const next = prev === -1 ? 0 : (prev + 1) % filteredCommands.length;
|
|
760
|
+
return next;
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
if (e.key === "ArrowUp") {
|
|
766
|
+
if (filteredCommands.length > 0) {
|
|
767
|
+
e.preventDefault();
|
|
768
|
+
setSlashHighlightIndex((prev) => {
|
|
769
|
+
if (filteredCommands.length === 0) {
|
|
770
|
+
return prev;
|
|
771
|
+
}
|
|
772
|
+
if (prev === -1) {
|
|
773
|
+
return filteredCommands.length - 1;
|
|
774
|
+
}
|
|
775
|
+
return prev <= 0 ? filteredCommands.length - 1 : prev - 1;
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
if (e.key === "Enter") {
|
|
781
|
+
const selected = slashHighlightIndex >= 0 ? filteredCommands[slashHighlightIndex] : void 0;
|
|
782
|
+
if (selected) {
|
|
783
|
+
e.preventDefault();
|
|
784
|
+
runCommand(selected);
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
if (e.key === "Escape") {
|
|
789
|
+
e.preventDefault();
|
|
790
|
+
setCommandQuery(null);
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
795
|
+
e.preventDefault();
|
|
796
|
+
if (isProcessing) {
|
|
797
|
+
onStop?.();
|
|
798
|
+
} else {
|
|
799
|
+
send();
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
const send = () => {
|
|
804
|
+
if (!onSubmitMessage) {
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
const trimmed = resolvedValue.trim();
|
|
808
|
+
if (!trimmed) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
onSubmitMessage(trimmed);
|
|
812
|
+
if (!isControlled) {
|
|
813
|
+
setInternalValue("");
|
|
814
|
+
onChange?.("");
|
|
815
|
+
}
|
|
816
|
+
if (inputRef.current) {
|
|
817
|
+
inputRef.current.focus();
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
const BoundTextArea = renderSlot(textArea, CopilotChatInput.TextArea, {
|
|
821
|
+
ref: inputRef,
|
|
822
|
+
value: resolvedValue,
|
|
823
|
+
onChange: handleChange,
|
|
824
|
+
onKeyDown: handleKeyDown,
|
|
825
|
+
autoFocus,
|
|
826
|
+
className: twMerge3(
|
|
827
|
+
"w-full py-3",
|
|
828
|
+
isExpanded ? "px-5" : "pr-5"
|
|
829
|
+
)
|
|
830
|
+
});
|
|
831
|
+
const isProcessing = mode !== "transcribe" && isRunning;
|
|
832
|
+
const canSend = resolvedValue.trim().length > 0 && !!onSubmitMessage;
|
|
833
|
+
const canStop = !!onStop;
|
|
834
|
+
const handleSendButtonClick = () => {
|
|
835
|
+
if (isProcessing) {
|
|
836
|
+
onStop?.();
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
send();
|
|
840
|
+
};
|
|
841
|
+
const BoundAudioRecorder = renderSlot(audioRecorder, CopilotChatAudioRecorder, {
|
|
842
|
+
ref: audioRecorderRef
|
|
843
|
+
});
|
|
844
|
+
const BoundSendButton = renderSlot(sendButton, CopilotChatInput.SendButton, {
|
|
845
|
+
onClick: handleSendButtonClick,
|
|
846
|
+
disabled: isProcessing ? !canStop : !canSend,
|
|
847
|
+
children: isProcessing && canStop ? /* @__PURE__ */ jsx6(Square, { className: "size-[18px] fill-current" }) : void 0
|
|
848
|
+
});
|
|
849
|
+
const BoundStartTranscribeButton = renderSlot(startTranscribeButton, CopilotChatInput.StartTranscribeButton, {
|
|
850
|
+
onClick: onStartTranscribe
|
|
851
|
+
});
|
|
852
|
+
const BoundCancelTranscribeButton = renderSlot(cancelTranscribeButton, CopilotChatInput.CancelTranscribeButton, {
|
|
853
|
+
onClick: onCancelTranscribe
|
|
854
|
+
});
|
|
855
|
+
const BoundFinishTranscribeButton = renderSlot(finishTranscribeButton, CopilotChatInput.FinishTranscribeButton, {
|
|
856
|
+
onClick: onFinishTranscribe
|
|
857
|
+
});
|
|
858
|
+
const BoundAddMenuButton = renderSlot(addMenuButton, CopilotChatInput.AddMenuButton, {
|
|
859
|
+
disabled: mode === "transcribe",
|
|
860
|
+
onAddFile,
|
|
861
|
+
toolsMenu
|
|
862
|
+
});
|
|
863
|
+
if (children) {
|
|
864
|
+
const childProps = {
|
|
865
|
+
textArea: BoundTextArea,
|
|
866
|
+
audioRecorder: BoundAudioRecorder,
|
|
867
|
+
sendButton: BoundSendButton,
|
|
868
|
+
startTranscribeButton: BoundStartTranscribeButton,
|
|
869
|
+
cancelTranscribeButton: BoundCancelTranscribeButton,
|
|
870
|
+
finishTranscribeButton: BoundFinishTranscribeButton,
|
|
871
|
+
addMenuButton: BoundAddMenuButton,
|
|
872
|
+
onSubmitMessage,
|
|
873
|
+
onStop,
|
|
874
|
+
isRunning,
|
|
875
|
+
onStartTranscribe,
|
|
876
|
+
onCancelTranscribe,
|
|
877
|
+
onFinishTranscribe,
|
|
878
|
+
onAddFile,
|
|
879
|
+
mode,
|
|
880
|
+
toolsMenu,
|
|
881
|
+
autoFocus
|
|
882
|
+
};
|
|
883
|
+
return /* @__PURE__ */ jsx6(Fragment, { children: children(childProps) });
|
|
884
|
+
}
|
|
885
|
+
const handleContainerClick = (e) => {
|
|
886
|
+
const target = e.target;
|
|
887
|
+
if (target.tagName !== "BUTTON" && !target.closest("button") && inputRef.current && mode === "input") {
|
|
888
|
+
inputRef.current.focus();
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
const ensureMeasurements = useCallback(() => {
|
|
892
|
+
const textarea = inputRef.current;
|
|
893
|
+
if (!textarea) {
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
const previousValue = textarea.value;
|
|
897
|
+
const previousHeight = textarea.style.height;
|
|
898
|
+
textarea.style.height = "auto";
|
|
899
|
+
const computedStyle = window.getComputedStyle(textarea);
|
|
900
|
+
const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;
|
|
901
|
+
const paddingRight = parseFloat(computedStyle.paddingRight) || 0;
|
|
902
|
+
const paddingTop = parseFloat(computedStyle.paddingTop) || 0;
|
|
903
|
+
const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;
|
|
904
|
+
textarea.value = "";
|
|
905
|
+
const singleLineHeight = textarea.scrollHeight;
|
|
906
|
+
textarea.value = previousValue;
|
|
907
|
+
const contentHeight = singleLineHeight - paddingTop - paddingBottom;
|
|
908
|
+
const maxHeight = contentHeight * 5 + paddingTop + paddingBottom;
|
|
909
|
+
measurementsRef.current = {
|
|
910
|
+
singleLineHeight,
|
|
911
|
+
maxHeight,
|
|
912
|
+
paddingLeft,
|
|
913
|
+
paddingRight
|
|
914
|
+
};
|
|
915
|
+
textarea.style.height = previousHeight;
|
|
916
|
+
textarea.style.maxHeight = `${maxHeight}px`;
|
|
917
|
+
}, []);
|
|
918
|
+
const adjustTextareaHeight = useCallback(() => {
|
|
919
|
+
const textarea = inputRef.current;
|
|
920
|
+
if (!textarea) {
|
|
921
|
+
return 0;
|
|
922
|
+
}
|
|
923
|
+
if (measurementsRef.current.singleLineHeight === 0) {
|
|
924
|
+
ensureMeasurements();
|
|
925
|
+
}
|
|
926
|
+
const { maxHeight } = measurementsRef.current;
|
|
927
|
+
if (maxHeight) {
|
|
928
|
+
textarea.style.maxHeight = `${maxHeight}px`;
|
|
929
|
+
}
|
|
930
|
+
textarea.style.height = "auto";
|
|
931
|
+
const scrollHeight = textarea.scrollHeight;
|
|
932
|
+
if (maxHeight) {
|
|
933
|
+
textarea.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
|
|
934
|
+
} else {
|
|
935
|
+
textarea.style.height = `${scrollHeight}px`;
|
|
936
|
+
}
|
|
937
|
+
return scrollHeight;
|
|
938
|
+
}, [ensureMeasurements]);
|
|
939
|
+
const updateLayout = useCallback((nextLayout) => {
|
|
940
|
+
setLayout((prev) => {
|
|
941
|
+
if (prev === nextLayout) {
|
|
942
|
+
return prev;
|
|
943
|
+
}
|
|
944
|
+
ignoreResizeRef.current = true;
|
|
945
|
+
return nextLayout;
|
|
946
|
+
});
|
|
947
|
+
}, []);
|
|
948
|
+
const evaluateLayout = useCallback(() => {
|
|
949
|
+
if (mode !== "input") {
|
|
950
|
+
updateLayout("compact");
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
|
|
954
|
+
const isMobileViewport = window.matchMedia("(max-width: 767px)").matches;
|
|
955
|
+
if (isMobileViewport) {
|
|
956
|
+
ensureMeasurements();
|
|
957
|
+
adjustTextareaHeight();
|
|
958
|
+
updateLayout("expanded");
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
const textarea = inputRef.current;
|
|
963
|
+
const grid = gridRef.current;
|
|
964
|
+
const addContainer = addButtonContainerRef.current;
|
|
965
|
+
const actionsContainer = actionsContainerRef.current;
|
|
966
|
+
if (!textarea || !grid || !addContainer || !actionsContainer) {
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
if (measurementsRef.current.singleLineHeight === 0) {
|
|
970
|
+
ensureMeasurements();
|
|
971
|
+
}
|
|
972
|
+
const scrollHeight = adjustTextareaHeight();
|
|
973
|
+
const baseline = measurementsRef.current.singleLineHeight;
|
|
974
|
+
const hasExplicitBreak = resolvedValue.includes("\n");
|
|
975
|
+
const renderedMultiline = baseline > 0 ? scrollHeight > baseline + 1 : false;
|
|
976
|
+
let shouldExpand = hasExplicitBreak || renderedMultiline;
|
|
977
|
+
if (!shouldExpand) {
|
|
978
|
+
const gridStyles = window.getComputedStyle(grid);
|
|
979
|
+
const paddingLeft = parseFloat(gridStyles.paddingLeft) || 0;
|
|
980
|
+
const paddingRight = parseFloat(gridStyles.paddingRight) || 0;
|
|
981
|
+
const columnGap = parseFloat(gridStyles.columnGap) || 0;
|
|
982
|
+
const gridAvailableWidth = grid.clientWidth - paddingLeft - paddingRight;
|
|
983
|
+
if (gridAvailableWidth > 0) {
|
|
984
|
+
const addWidth = addContainer.getBoundingClientRect().width;
|
|
985
|
+
const actionsWidth = actionsContainer.getBoundingClientRect().width;
|
|
986
|
+
const compactWidth = Math.max(gridAvailableWidth - addWidth - actionsWidth - columnGap * 2, 0);
|
|
987
|
+
const canvas = measurementCanvasRef.current ?? document.createElement("canvas");
|
|
988
|
+
if (!measurementCanvasRef.current) {
|
|
989
|
+
measurementCanvasRef.current = canvas;
|
|
990
|
+
}
|
|
991
|
+
const context = canvas.getContext("2d");
|
|
992
|
+
if (context) {
|
|
993
|
+
const textareaStyles = window.getComputedStyle(textarea);
|
|
994
|
+
const font = textareaStyles.font || `${textareaStyles.fontStyle} ${textareaStyles.fontVariant} ${textareaStyles.fontWeight} ${textareaStyles.fontSize}/${textareaStyles.lineHeight} ${textareaStyles.fontFamily}`;
|
|
995
|
+
context.font = font;
|
|
996
|
+
const compactInnerWidth = Math.max(
|
|
997
|
+
compactWidth - (measurementsRef.current.paddingLeft || 0) - (measurementsRef.current.paddingRight || 0),
|
|
998
|
+
0
|
|
999
|
+
);
|
|
1000
|
+
if (compactInnerWidth > 0) {
|
|
1001
|
+
const lines = resolvedValue.length > 0 ? resolvedValue.split("\n") : [""];
|
|
1002
|
+
let longestWidth = 0;
|
|
1003
|
+
for (const line of lines) {
|
|
1004
|
+
const metrics = context.measureText(line || " ");
|
|
1005
|
+
if (metrics.width > longestWidth) {
|
|
1006
|
+
longestWidth = metrics.width;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
if (longestWidth > compactInnerWidth) {
|
|
1010
|
+
shouldExpand = true;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
const nextLayout = shouldExpand ? "expanded" : "compact";
|
|
1017
|
+
updateLayout(nextLayout);
|
|
1018
|
+
}, [adjustTextareaHeight, ensureMeasurements, mode, resolvedValue, updateLayout]);
|
|
1019
|
+
useLayoutEffect(() => {
|
|
1020
|
+
evaluateLayout();
|
|
1021
|
+
}, [evaluateLayout]);
|
|
1022
|
+
useEffect2(() => {
|
|
1023
|
+
if (typeof ResizeObserver === "undefined") {
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
const textarea = inputRef.current;
|
|
1027
|
+
const grid = gridRef.current;
|
|
1028
|
+
const addContainer = addButtonContainerRef.current;
|
|
1029
|
+
const actionsContainer = actionsContainerRef.current;
|
|
1030
|
+
if (!textarea || !grid || !addContainer || !actionsContainer) {
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
const scheduleEvaluation = () => {
|
|
1034
|
+
if (ignoreResizeRef.current) {
|
|
1035
|
+
ignoreResizeRef.current = false;
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
if (typeof window === "undefined") {
|
|
1039
|
+
evaluateLayout();
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
if (resizeEvaluationRafRef.current !== null) {
|
|
1043
|
+
cancelAnimationFrame(resizeEvaluationRafRef.current);
|
|
1044
|
+
}
|
|
1045
|
+
resizeEvaluationRafRef.current = window.requestAnimationFrame(() => {
|
|
1046
|
+
resizeEvaluationRafRef.current = null;
|
|
1047
|
+
evaluateLayout();
|
|
1048
|
+
});
|
|
1049
|
+
};
|
|
1050
|
+
const observer = new ResizeObserver(() => {
|
|
1051
|
+
scheduleEvaluation();
|
|
1052
|
+
});
|
|
1053
|
+
observer.observe(grid);
|
|
1054
|
+
observer.observe(addContainer);
|
|
1055
|
+
observer.observe(actionsContainer);
|
|
1056
|
+
observer.observe(textarea);
|
|
1057
|
+
return () => {
|
|
1058
|
+
observer.disconnect();
|
|
1059
|
+
if (typeof window !== "undefined" && resizeEvaluationRafRef.current !== null) {
|
|
1060
|
+
cancelAnimationFrame(resizeEvaluationRafRef.current);
|
|
1061
|
+
resizeEvaluationRafRef.current = null;
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
}, [evaluateLayout]);
|
|
1065
|
+
const slashMenuVisible = commandQuery !== null && commandItems.length > 0;
|
|
1066
|
+
useEffect2(() => {
|
|
1067
|
+
if (!slashMenuVisible || slashHighlightIndex < 0) {
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
const active = slashMenuRef.current?.querySelector(
|
|
1071
|
+
`[data-slash-index="${slashHighlightIndex}"]`
|
|
1072
|
+
);
|
|
1073
|
+
active?.scrollIntoView({ block: "nearest" });
|
|
1074
|
+
}, [slashMenuVisible, slashHighlightIndex]);
|
|
1075
|
+
const slashMenu = slashMenuVisible ? /* @__PURE__ */ jsx6(
|
|
1076
|
+
"div",
|
|
1077
|
+
{
|
|
1078
|
+
"data-testid": "copilot-slash-menu",
|
|
1079
|
+
role: "listbox",
|
|
1080
|
+
"aria-label": "Slash commands",
|
|
1081
|
+
ref: slashMenuRef,
|
|
1082
|
+
className: "absolute bottom-full left-0 right-0 z-30 mb-2 max-h-64 overflow-y-auto rounded-lg border border-border bg-white shadow-lg dark:border-[#3a3a3a] dark:bg-[#1f1f1f]",
|
|
1083
|
+
style: { maxHeight: `${SLASH_MENU_MAX_VISIBLE_ITEMS * SLASH_MENU_ITEM_HEIGHT_PX}px` },
|
|
1084
|
+
children: filteredCommands.length === 0 ? /* @__PURE__ */ jsx6("div", { className: "px-3 py-2 text-sm text-muted-foreground", children: "No commands found" }) : filteredCommands.map((item, index) => {
|
|
1085
|
+
const isActive = index === slashHighlightIndex;
|
|
1086
|
+
return /* @__PURE__ */ jsx6(
|
|
1087
|
+
"button",
|
|
1088
|
+
{
|
|
1089
|
+
type: "button",
|
|
1090
|
+
role: "option",
|
|
1091
|
+
"aria-selected": isActive,
|
|
1092
|
+
"data-active": isActive ? "true" : void 0,
|
|
1093
|
+
"data-slash-index": index,
|
|
1094
|
+
className: twMerge3(
|
|
1095
|
+
"w-full px-3 py-2 text-left text-sm transition-colors",
|
|
1096
|
+
"hover:bg-muted dark:hover:bg-[#2f2f2f]",
|
|
1097
|
+
isActive ? "bg-muted dark:bg-[#2f2f2f]" : "bg-transparent"
|
|
1098
|
+
),
|
|
1099
|
+
onMouseEnter: () => setSlashHighlightIndex(index),
|
|
1100
|
+
onMouseDown: (event) => {
|
|
1101
|
+
event.preventDefault();
|
|
1102
|
+
runCommand(item);
|
|
1103
|
+
},
|
|
1104
|
+
children: item.label
|
|
1105
|
+
},
|
|
1106
|
+
`${item.label}-${index}`
|
|
1107
|
+
);
|
|
1108
|
+
})
|
|
1109
|
+
}
|
|
1110
|
+
) : null;
|
|
1111
|
+
return /* @__PURE__ */ jsx6(
|
|
1112
|
+
"div",
|
|
1113
|
+
{
|
|
1114
|
+
className: twMerge3(
|
|
1115
|
+
// Layout
|
|
1116
|
+
"flex w-full flex-col items-center justify-center",
|
|
1117
|
+
// Interaction
|
|
1118
|
+
"cursor-text",
|
|
1119
|
+
// Overflow and clipping
|
|
1120
|
+
"overflow-visible bg-clip-padding contain-inline-size",
|
|
1121
|
+
// Background
|
|
1122
|
+
"bg-white dark:bg-[#303030]",
|
|
1123
|
+
// Visual effects
|
|
1124
|
+
"shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] rounded-[28px]",
|
|
1125
|
+
className
|
|
1126
|
+
),
|
|
1127
|
+
onClick: handleContainerClick,
|
|
1128
|
+
...props,
|
|
1129
|
+
"data-layout": isExpanded ? "expanded" : "compact",
|
|
1130
|
+
children: /* @__PURE__ */ jsxs3(
|
|
1131
|
+
"div",
|
|
1132
|
+
{
|
|
1133
|
+
ref: gridRef,
|
|
1134
|
+
className: twMerge3(
|
|
1135
|
+
"grid w-full gap-x-3 gap-y-3 px-3 py-2",
|
|
1136
|
+
isExpanded ? "grid-cols-[auto_minmax(0,1fr)_auto] grid-rows-[auto_auto]" : "grid-cols-[auto_minmax(0,1fr)_auto] items-center"
|
|
1137
|
+
),
|
|
1138
|
+
"data-layout": isExpanded ? "expanded" : "compact",
|
|
1139
|
+
children: [
|
|
1140
|
+
/* @__PURE__ */ jsx6(
|
|
1141
|
+
"div",
|
|
1142
|
+
{
|
|
1143
|
+
ref: addButtonContainerRef,
|
|
1144
|
+
className: twMerge3(
|
|
1145
|
+
"flex items-center",
|
|
1146
|
+
isExpanded ? "row-start-2" : "row-start-1",
|
|
1147
|
+
"col-start-1"
|
|
1148
|
+
),
|
|
1149
|
+
children: BoundAddMenuButton
|
|
1150
|
+
}
|
|
1151
|
+
),
|
|
1152
|
+
/* @__PURE__ */ jsx6(
|
|
1153
|
+
"div",
|
|
1154
|
+
{
|
|
1155
|
+
className: twMerge3(
|
|
1156
|
+
"relative flex min-w-0 flex-col",
|
|
1157
|
+
isExpanded ? "col-span-3 row-start-1" : "col-start-2 row-start-1"
|
|
1158
|
+
),
|
|
1159
|
+
children: mode === "transcribe" ? BoundAudioRecorder : /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
1160
|
+
BoundTextArea,
|
|
1161
|
+
slashMenu
|
|
1162
|
+
] })
|
|
1163
|
+
}
|
|
1164
|
+
),
|
|
1165
|
+
/* @__PURE__ */ jsx6(
|
|
1166
|
+
"div",
|
|
1167
|
+
{
|
|
1168
|
+
ref: actionsContainerRef,
|
|
1169
|
+
className: twMerge3(
|
|
1170
|
+
"flex items-center justify-end gap-2",
|
|
1171
|
+
isExpanded ? "col-start-3 row-start-2" : "col-start-3 row-start-1"
|
|
1172
|
+
),
|
|
1173
|
+
children: mode === "transcribe" ? /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
1174
|
+
onCancelTranscribe && BoundCancelTranscribeButton,
|
|
1175
|
+
onFinishTranscribe && BoundFinishTranscribeButton
|
|
1176
|
+
] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
1177
|
+
onStartTranscribe && BoundStartTranscribeButton,
|
|
1178
|
+
BoundSendButton
|
|
1179
|
+
] })
|
|
1180
|
+
}
|
|
1181
|
+
)
|
|
1182
|
+
]
|
|
1183
|
+
}
|
|
1184
|
+
)
|
|
1185
|
+
}
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
((CopilotChatInput2) => {
|
|
1189
|
+
CopilotChatInput2.SendButton = ({ className, children, ...props }) => /* @__PURE__ */ jsx6("div", { className: "mr-[10px]", children: /* @__PURE__ */ jsx6(
|
|
1190
|
+
Button,
|
|
1191
|
+
{
|
|
1192
|
+
type: "button",
|
|
1193
|
+
variant: "chatInputToolbarPrimary",
|
|
1194
|
+
size: "chatInputToolbarIcon",
|
|
1195
|
+
className,
|
|
1196
|
+
...props,
|
|
1197
|
+
children: children ?? /* @__PURE__ */ jsx6(ArrowUp, { className: "size-[18px]" })
|
|
1198
|
+
}
|
|
1199
|
+
) });
|
|
1200
|
+
CopilotChatInput2.ToolbarButton = ({ icon, labelKey, defaultClassName, className, ...props }) => {
|
|
1201
|
+
const config = useCopilotChatConfiguration();
|
|
1202
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
1203
|
+
return /* @__PURE__ */ jsxs3(Tooltip, { children: [
|
|
1204
|
+
/* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx6(
|
|
1205
|
+
Button,
|
|
1206
|
+
{
|
|
1207
|
+
type: "button",
|
|
1208
|
+
variant: "chatInputToolbarSecondary",
|
|
1209
|
+
size: "chatInputToolbarIcon",
|
|
1210
|
+
className: twMerge3(defaultClassName, className),
|
|
1211
|
+
...props,
|
|
1212
|
+
children: icon
|
|
1213
|
+
}
|
|
1214
|
+
) }),
|
|
1215
|
+
/* @__PURE__ */ jsx6(TooltipContent, { side: "bottom", children: /* @__PURE__ */ jsx6("p", { children: labels[labelKey] }) })
|
|
1216
|
+
] });
|
|
1217
|
+
};
|
|
1218
|
+
CopilotChatInput2.StartTranscribeButton = (props) => /* @__PURE__ */ jsx6(
|
|
1219
|
+
CopilotChatInput2.ToolbarButton,
|
|
1220
|
+
{
|
|
1221
|
+
icon: /* @__PURE__ */ jsx6(Mic, { className: "size-[18px]" }),
|
|
1222
|
+
labelKey: "chatInputToolbarStartTranscribeButtonLabel",
|
|
1223
|
+
defaultClassName: "mr-2",
|
|
1224
|
+
...props
|
|
1225
|
+
}
|
|
1226
|
+
);
|
|
1227
|
+
CopilotChatInput2.CancelTranscribeButton = (props) => /* @__PURE__ */ jsx6(
|
|
1228
|
+
CopilotChatInput2.ToolbarButton,
|
|
1229
|
+
{
|
|
1230
|
+
icon: /* @__PURE__ */ jsx6(X, { className: "size-[18px]" }),
|
|
1231
|
+
labelKey: "chatInputToolbarCancelTranscribeButtonLabel",
|
|
1232
|
+
defaultClassName: "mr-2",
|
|
1233
|
+
...props
|
|
1234
|
+
}
|
|
1235
|
+
);
|
|
1236
|
+
CopilotChatInput2.FinishTranscribeButton = (props) => /* @__PURE__ */ jsx6(
|
|
1237
|
+
CopilotChatInput2.ToolbarButton,
|
|
1238
|
+
{
|
|
1239
|
+
icon: /* @__PURE__ */ jsx6(Check, { className: "size-[18px]" }),
|
|
1240
|
+
labelKey: "chatInputToolbarFinishTranscribeButtonLabel",
|
|
1241
|
+
defaultClassName: "mr-[10px]",
|
|
1242
|
+
...props
|
|
1243
|
+
}
|
|
1244
|
+
);
|
|
1245
|
+
CopilotChatInput2.AddMenuButton = ({ className, toolsMenu, onAddFile, disabled, ...props }) => {
|
|
1246
|
+
const config = useCopilotChatConfiguration();
|
|
1247
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
1248
|
+
const menuItems = useMemo2(() => {
|
|
1249
|
+
const items = [];
|
|
1250
|
+
if (onAddFile) {
|
|
1251
|
+
items.push({
|
|
1252
|
+
label: labels.chatInputToolbarAddButtonLabel,
|
|
1253
|
+
action: onAddFile
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
if (toolsMenu && toolsMenu.length > 0) {
|
|
1257
|
+
if (items.length > 0) {
|
|
1258
|
+
items.push("-");
|
|
1259
|
+
}
|
|
1260
|
+
for (const item of toolsMenu) {
|
|
1261
|
+
if (item === "-") {
|
|
1262
|
+
if (items.length === 0 || items[items.length - 1] === "-") {
|
|
1263
|
+
continue;
|
|
1264
|
+
}
|
|
1265
|
+
items.push(item);
|
|
1266
|
+
} else {
|
|
1267
|
+
items.push(item);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
while (items.length > 0 && items[items.length - 1] === "-") {
|
|
1271
|
+
items.pop();
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
return items;
|
|
1275
|
+
}, [onAddFile, toolsMenu, labels.chatInputToolbarAddButtonLabel]);
|
|
1276
|
+
const renderMenuItems = useCallback(
|
|
1277
|
+
(items) => items.map((item, index) => {
|
|
1278
|
+
if (item === "-") {
|
|
1279
|
+
return /* @__PURE__ */ jsx6(DropdownMenuSeparator, {}, `separator-${index}`);
|
|
1280
|
+
}
|
|
1281
|
+
if (item.items && item.items.length > 0) {
|
|
1282
|
+
return /* @__PURE__ */ jsxs3(DropdownMenuSub, { children: [
|
|
1283
|
+
/* @__PURE__ */ jsx6(DropdownMenuSubTrigger, { children: item.label }),
|
|
1284
|
+
/* @__PURE__ */ jsx6(DropdownMenuSubContent, { children: renderMenuItems(item.items) })
|
|
1285
|
+
] }, `group-${index}`);
|
|
1286
|
+
}
|
|
1287
|
+
return /* @__PURE__ */ jsx6(DropdownMenuItem, { onClick: item.action, children: item.label }, `item-${index}`);
|
|
1288
|
+
}),
|
|
1289
|
+
[]
|
|
1290
|
+
);
|
|
1291
|
+
const hasMenuItems = menuItems.length > 0;
|
|
1292
|
+
const isDisabled = disabled || !hasMenuItems;
|
|
1293
|
+
return /* @__PURE__ */ jsxs3(DropdownMenu, { children: [
|
|
1294
|
+
/* @__PURE__ */ jsxs3(Tooltip, { children: [
|
|
1295
|
+
/* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx6(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx6(
|
|
1296
|
+
Button,
|
|
1297
|
+
{
|
|
1298
|
+
type: "button",
|
|
1299
|
+
variant: "chatInputToolbarSecondary",
|
|
1300
|
+
size: "chatInputToolbarIcon",
|
|
1301
|
+
className: twMerge3("ml-1", className),
|
|
1302
|
+
disabled: isDisabled,
|
|
1303
|
+
...props,
|
|
1304
|
+
children: /* @__PURE__ */ jsx6(Plus, { className: "size-[20px]" })
|
|
1305
|
+
}
|
|
1306
|
+
) }) }),
|
|
1307
|
+
/* @__PURE__ */ jsx6(TooltipContent, { side: "bottom", children: /* @__PURE__ */ jsxs3("p", { className: "flex items-center gap-1 text-xs font-medium", children: [
|
|
1308
|
+
/* @__PURE__ */ jsx6("span", { children: "Add files and more" }),
|
|
1309
|
+
/* @__PURE__ */ jsx6("code", { className: "rounded bg-[#4a4a4a] px-1 py-[1px] font-mono text-[11px] text-white dark:bg-[#e0e0e0] dark:text-black", children: "/" })
|
|
1310
|
+
] }) })
|
|
1311
|
+
] }),
|
|
1312
|
+
hasMenuItems && /* @__PURE__ */ jsx6(DropdownMenuContent, { side: "top", align: "start", children: renderMenuItems(menuItems) })
|
|
1313
|
+
] });
|
|
1314
|
+
};
|
|
1315
|
+
CopilotChatInput2.TextArea = forwardRef2(function TextArea2({ style, className, autoFocus, ...props }, ref) {
|
|
1316
|
+
const internalTextareaRef = useRef2(null);
|
|
1317
|
+
const config = useCopilotChatConfiguration();
|
|
1318
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
1319
|
+
useImperativeHandle2(ref, () => internalTextareaRef.current);
|
|
1320
|
+
useEffect2(() => {
|
|
1321
|
+
const textarea = internalTextareaRef.current;
|
|
1322
|
+
if (!textarea) return;
|
|
1323
|
+
const handleFocus = () => {
|
|
1324
|
+
setTimeout(() => {
|
|
1325
|
+
textarea.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
1326
|
+
}, 300);
|
|
1327
|
+
};
|
|
1328
|
+
textarea.addEventListener("focus", handleFocus);
|
|
1329
|
+
return () => textarea.removeEventListener("focus", handleFocus);
|
|
1330
|
+
}, []);
|
|
1331
|
+
useEffect2(() => {
|
|
1332
|
+
if (autoFocus) {
|
|
1333
|
+
internalTextareaRef.current?.focus();
|
|
1334
|
+
}
|
|
1335
|
+
}, [autoFocus]);
|
|
1336
|
+
return /* @__PURE__ */ jsx6(
|
|
1337
|
+
"textarea",
|
|
1338
|
+
{
|
|
1339
|
+
ref: internalTextareaRef,
|
|
1340
|
+
...props,
|
|
1341
|
+
style: {
|
|
1342
|
+
overflow: "auto",
|
|
1343
|
+
resize: "none",
|
|
1344
|
+
...style
|
|
1345
|
+
},
|
|
1346
|
+
placeholder: labels.chatInputPlaceholder,
|
|
1347
|
+
className: twMerge3(
|
|
1348
|
+
"bg-transparent outline-none antialiased font-regular leading-relaxed text-[16px] placeholder:text-[#00000077] dark:placeholder:text-[#fffc]",
|
|
1349
|
+
className
|
|
1350
|
+
),
|
|
1351
|
+
rows: 1
|
|
1352
|
+
}
|
|
1353
|
+
);
|
|
1354
|
+
});
|
|
1355
|
+
CopilotChatInput2.AudioRecorder = CopilotChatAudioRecorder;
|
|
1356
|
+
})(CopilotChatInput || (CopilotChatInput = {}));
|
|
1357
|
+
CopilotChatInput.TextArea.displayName = "CopilotChatInput.TextArea";
|
|
1358
|
+
CopilotChatInput.SendButton.displayName = "CopilotChatInput.SendButton";
|
|
1359
|
+
CopilotChatInput.ToolbarButton.displayName = "CopilotChatInput.ToolbarButton";
|
|
1360
|
+
CopilotChatInput.StartTranscribeButton.displayName = "CopilotChatInput.StartTranscribeButton";
|
|
1361
|
+
CopilotChatInput.CancelTranscribeButton.displayName = "CopilotChatInput.CancelTranscribeButton";
|
|
1362
|
+
CopilotChatInput.FinishTranscribeButton.displayName = "CopilotChatInput.FinishTranscribeButton";
|
|
1363
|
+
CopilotChatInput.AddMenuButton.displayName = "CopilotChatInput.AddMenuButton";
|
|
1364
|
+
var CopilotChatInput_default = CopilotChatInput;
|
|
1365
|
+
|
|
1366
|
+
// src/components/chat/CopilotChatAssistantMessage.tsx
|
|
1367
|
+
import { useState as useState7 } from "react";
|
|
1368
|
+
import {
|
|
1369
|
+
Copy,
|
|
1370
|
+
Check as Check2,
|
|
1371
|
+
ThumbsUp,
|
|
1372
|
+
ThumbsDown,
|
|
1373
|
+
Volume2,
|
|
1374
|
+
RefreshCw
|
|
1375
|
+
} from "lucide-react";
|
|
1376
|
+
import { twMerge as twMerge4 } from "tailwind-merge";
|
|
1377
|
+
import "katex/dist/katex.min.css";
|
|
1378
|
+
import { Streamdown } from "streamdown";
|
|
1379
|
+
|
|
1380
|
+
// src/hooks/use-render-tool-call.tsx
|
|
1381
|
+
import React7, { useCallback as useCallback3, useMemo as useMemo4, useSyncExternalStore } from "react";
|
|
1382
|
+
import { ToolCallStatus } from "@copilotkitnext/core";
|
|
1383
|
+
|
|
1384
|
+
// src/providers/CopilotKitProvider.tsx
|
|
1385
|
+
import { createContext as createContext2, useContext as useContext2, useMemo as useMemo3, useEffect as useEffect5, useReducer, useRef as useRef4, useState as useState5 } from "react";
|
|
1386
|
+
import { z as z2 } from "zod";
|
|
1387
|
+
|
|
1388
|
+
// src/lib/react-core.ts
|
|
1389
|
+
import { CopilotKitCore } from "@copilotkitnext/core";
|
|
1390
|
+
var CopilotKitCoreReact = class extends CopilotKitCore {
|
|
1391
|
+
_renderToolCalls = [];
|
|
1392
|
+
_renderCustomMessages = [];
|
|
1393
|
+
_renderActivityMessages = [];
|
|
1394
|
+
constructor(config) {
|
|
1395
|
+
super(config);
|
|
1396
|
+
this._renderToolCalls = config.renderToolCalls ?? [];
|
|
1397
|
+
this._renderCustomMessages = config.renderCustomMessages ?? [];
|
|
1398
|
+
this._renderActivityMessages = config.renderActivityMessages ?? [];
|
|
1399
|
+
}
|
|
1400
|
+
get renderCustomMessages() {
|
|
1401
|
+
return this._renderCustomMessages;
|
|
1402
|
+
}
|
|
1403
|
+
get renderActivityMessages() {
|
|
1404
|
+
return this._renderActivityMessages;
|
|
1405
|
+
}
|
|
1406
|
+
get renderToolCalls() {
|
|
1407
|
+
return this._renderToolCalls;
|
|
1408
|
+
}
|
|
1409
|
+
setRenderToolCalls(renderToolCalls) {
|
|
1410
|
+
this._renderToolCalls = renderToolCalls;
|
|
1411
|
+
void this.notifySubscribers(
|
|
1412
|
+
(subscriber) => {
|
|
1413
|
+
const reactSubscriber = subscriber;
|
|
1414
|
+
if (reactSubscriber.onRenderToolCallsChanged) {
|
|
1415
|
+
reactSubscriber.onRenderToolCallsChanged({
|
|
1416
|
+
copilotkit: this,
|
|
1417
|
+
renderToolCalls: this.renderToolCalls
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
},
|
|
1421
|
+
"Subscriber onRenderToolCallsChanged error:"
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
// Override to accept React-specific subscriber type
|
|
1425
|
+
subscribe(subscriber) {
|
|
1426
|
+
return super.subscribe(subscriber);
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
// src/components/CopilotKitInspector.tsx
|
|
1431
|
+
import * as React4 from "react";
|
|
1432
|
+
import { createComponent } from "@lit-labs/react";
|
|
1433
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1434
|
+
var CopilotKitInspector = ({ core, ...rest }) => {
|
|
1435
|
+
const [InspectorComponent, setInspectorComponent] = React4.useState(null);
|
|
1436
|
+
React4.useEffect(() => {
|
|
1437
|
+
let mounted = true;
|
|
1438
|
+
import("@copilotkitnext/web-inspector").then((mod) => {
|
|
1439
|
+
mod.defineWebInspector?.();
|
|
1440
|
+
const Component = createComponent({
|
|
1441
|
+
tagName: mod.WEB_INSPECTOR_TAG,
|
|
1442
|
+
elementClass: mod.WebInspectorElement,
|
|
1443
|
+
react: React4
|
|
1444
|
+
});
|
|
1445
|
+
if (mounted) {
|
|
1446
|
+
setInspectorComponent(() => Component);
|
|
1447
|
+
}
|
|
1448
|
+
});
|
|
1449
|
+
return () => {
|
|
1450
|
+
mounted = false;
|
|
1451
|
+
};
|
|
1452
|
+
}, []);
|
|
1453
|
+
if (!InspectorComponent) return null;
|
|
1454
|
+
return /* @__PURE__ */ jsx7(InspectorComponent, { ...rest, core: core ?? null });
|
|
1455
|
+
};
|
|
1456
|
+
CopilotKitInspector.displayName = "CopilotKitInspector";
|
|
1457
|
+
|
|
1458
|
+
// src/components/MCPAppsActivityRenderer.tsx
|
|
1459
|
+
import { useEffect as useEffect4, useRef as useRef3, useState as useState4, useCallback as useCallback2 } from "react";
|
|
1460
|
+
import { z } from "zod";
|
|
1461
|
+
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1462
|
+
var PROTOCOL_VERSION = "2025-06-18";
|
|
1463
|
+
var MCPAppsActivityType = "mcp-apps";
|
|
1464
|
+
var MCPAppsActivityContentSchema = z.object({
|
|
1465
|
+
result: z.object({
|
|
1466
|
+
content: z.array(z.any()).optional(),
|
|
1467
|
+
structuredContent: z.any().optional(),
|
|
1468
|
+
isError: z.boolean().optional()
|
|
1469
|
+
}),
|
|
1470
|
+
resource: z.object({
|
|
1471
|
+
uri: z.string(),
|
|
1472
|
+
mimeType: z.string().optional(),
|
|
1473
|
+
text: z.string().optional(),
|
|
1474
|
+
blob: z.string().optional()
|
|
1475
|
+
}),
|
|
1476
|
+
// Server ID for proxying requests (MD5 hash of server config)
|
|
1477
|
+
serverId: z.string().optional(),
|
|
1478
|
+
// Original tool input arguments
|
|
1479
|
+
toolInput: z.record(z.unknown()).optional()
|
|
1480
|
+
});
|
|
1481
|
+
function isRequest(msg) {
|
|
1482
|
+
return "id" in msg && "method" in msg;
|
|
1483
|
+
}
|
|
1484
|
+
function isNotification(msg) {
|
|
1485
|
+
return !("id" in msg) && "method" in msg;
|
|
1486
|
+
}
|
|
1487
|
+
function extractHtmlFromResource(resource) {
|
|
1488
|
+
if (resource.text) {
|
|
1489
|
+
return resource.text;
|
|
1490
|
+
}
|
|
1491
|
+
if (resource.blob) {
|
|
1492
|
+
return atob(resource.blob);
|
|
1493
|
+
}
|
|
1494
|
+
throw new Error("Resource has no text or blob content");
|
|
1495
|
+
}
|
|
1496
|
+
var MCPAppsActivityRenderer = ({ content, agent }) => {
|
|
1497
|
+
const containerRef = useRef3(null);
|
|
1498
|
+
const iframeRef = useRef3(null);
|
|
1499
|
+
const [iframeReady, setIframeReady] = useState4(false);
|
|
1500
|
+
const [error, setError] = useState4(null);
|
|
1501
|
+
const [iframeSize, setIframeSize] = useState4({});
|
|
1502
|
+
const contentRef = useRef3(content);
|
|
1503
|
+
contentRef.current = content;
|
|
1504
|
+
const agentRef = useRef3(agent);
|
|
1505
|
+
agentRef.current = agent;
|
|
1506
|
+
const sendToIframe = useCallback2((msg) => {
|
|
1507
|
+
if (iframeRef.current?.contentWindow) {
|
|
1508
|
+
console.log("[MCPAppsRenderer] Sending to iframe:", msg);
|
|
1509
|
+
iframeRef.current.contentWindow.postMessage(msg, "*");
|
|
1510
|
+
}
|
|
1511
|
+
}, []);
|
|
1512
|
+
const sendResponse = useCallback2((id, result) => {
|
|
1513
|
+
sendToIframe({
|
|
1514
|
+
jsonrpc: "2.0",
|
|
1515
|
+
id,
|
|
1516
|
+
result
|
|
1517
|
+
});
|
|
1518
|
+
}, [sendToIframe]);
|
|
1519
|
+
const sendErrorResponse = useCallback2((id, code, message) => {
|
|
1520
|
+
sendToIframe({
|
|
1521
|
+
jsonrpc: "2.0",
|
|
1522
|
+
id,
|
|
1523
|
+
error: { code, message }
|
|
1524
|
+
});
|
|
1525
|
+
}, [sendToIframe]);
|
|
1526
|
+
const sendNotification = useCallback2((method, params) => {
|
|
1527
|
+
sendToIframe({
|
|
1528
|
+
jsonrpc: "2.0",
|
|
1529
|
+
method,
|
|
1530
|
+
params: params || {}
|
|
1531
|
+
});
|
|
1532
|
+
}, [sendToIframe]);
|
|
1533
|
+
useEffect4(() => {
|
|
1534
|
+
if (!containerRef.current) return;
|
|
1535
|
+
let mounted = true;
|
|
1536
|
+
let messageHandler = null;
|
|
1537
|
+
const setup = async () => {
|
|
1538
|
+
try {
|
|
1539
|
+
const iframe = document.createElement("iframe");
|
|
1540
|
+
iframe.style.width = "100%";
|
|
1541
|
+
iframe.style.height = "300px";
|
|
1542
|
+
iframe.style.border = "none";
|
|
1543
|
+
iframe.style.backgroundColor = "transparent";
|
|
1544
|
+
iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
|
|
1545
|
+
const sandboxReady = new Promise((resolve) => {
|
|
1546
|
+
const initialListener = (event) => {
|
|
1547
|
+
if (event.source === iframe.contentWindow) {
|
|
1548
|
+
if (event.data?.method === "ui/notifications/sandbox-proxy-ready") {
|
|
1549
|
+
window.removeEventListener("message", initialListener);
|
|
1550
|
+
resolve();
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
window.addEventListener("message", initialListener);
|
|
1555
|
+
});
|
|
1556
|
+
iframe.src = "/sandbox.html";
|
|
1557
|
+
iframeRef.current = iframe;
|
|
1558
|
+
containerRef.current?.appendChild(iframe);
|
|
1559
|
+
await sandboxReady;
|
|
1560
|
+
if (!mounted) return;
|
|
1561
|
+
console.log("[MCPAppsRenderer] Sandbox proxy ready");
|
|
1562
|
+
messageHandler = async (event) => {
|
|
1563
|
+
if (event.source !== iframe.contentWindow) return;
|
|
1564
|
+
const msg = event.data;
|
|
1565
|
+
if (!msg || typeof msg !== "object" || msg.jsonrpc !== "2.0") return;
|
|
1566
|
+
console.log("[MCPAppsRenderer] Received from iframe:", msg);
|
|
1567
|
+
if (isRequest(msg)) {
|
|
1568
|
+
switch (msg.method) {
|
|
1569
|
+
case "ui/initialize": {
|
|
1570
|
+
sendResponse(msg.id, {
|
|
1571
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
1572
|
+
hostInfo: {
|
|
1573
|
+
name: "CopilotKit MCP Apps Host",
|
|
1574
|
+
version: "1.0.0"
|
|
1575
|
+
},
|
|
1576
|
+
hostCapabilities: {
|
|
1577
|
+
openLinks: {},
|
|
1578
|
+
logging: {}
|
|
1579
|
+
},
|
|
1580
|
+
hostContext: {
|
|
1581
|
+
theme: "light",
|
|
1582
|
+
platform: "web"
|
|
1583
|
+
}
|
|
1584
|
+
});
|
|
1585
|
+
break;
|
|
1586
|
+
}
|
|
1587
|
+
case "ui/message": {
|
|
1588
|
+
console.log("[MCPAppsRenderer] ui/message request:", msg.params);
|
|
1589
|
+
sendResponse(msg.id, { isError: false });
|
|
1590
|
+
break;
|
|
1591
|
+
}
|
|
1592
|
+
case "ui/open-link": {
|
|
1593
|
+
const url = msg.params?.url;
|
|
1594
|
+
if (url) {
|
|
1595
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
1596
|
+
sendResponse(msg.id, { isError: false });
|
|
1597
|
+
} else {
|
|
1598
|
+
sendErrorResponse(msg.id, -32602, "Missing url parameter");
|
|
1599
|
+
}
|
|
1600
|
+
break;
|
|
1601
|
+
}
|
|
1602
|
+
case "tools/call": {
|
|
1603
|
+
const { serverId } = contentRef.current;
|
|
1604
|
+
const currentAgent = agentRef.current;
|
|
1605
|
+
if (!serverId) {
|
|
1606
|
+
sendErrorResponse(msg.id, -32603, "No server ID available for proxying");
|
|
1607
|
+
break;
|
|
1608
|
+
}
|
|
1609
|
+
if (!currentAgent) {
|
|
1610
|
+
sendErrorResponse(msg.id, -32603, "No agent available for proxying");
|
|
1611
|
+
break;
|
|
1612
|
+
}
|
|
1613
|
+
try {
|
|
1614
|
+
const runResult = await currentAgent.runAgent({
|
|
1615
|
+
forwardedProps: {
|
|
1616
|
+
__proxiedMCPRequest: {
|
|
1617
|
+
serverId,
|
|
1618
|
+
method: "tools/call",
|
|
1619
|
+
params: msg.params
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
});
|
|
1623
|
+
sendResponse(msg.id, runResult.result || {});
|
|
1624
|
+
} catch (err) {
|
|
1625
|
+
console.error("[MCPAppsRenderer] tools/call error:", err);
|
|
1626
|
+
sendErrorResponse(msg.id, -32603, String(err));
|
|
1627
|
+
}
|
|
1628
|
+
break;
|
|
1629
|
+
}
|
|
1630
|
+
default:
|
|
1631
|
+
sendErrorResponse(msg.id, -32601, `Method not found: ${msg.method}`);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
if (isNotification(msg)) {
|
|
1635
|
+
switch (msg.method) {
|
|
1636
|
+
case "ui/notifications/initialized": {
|
|
1637
|
+
console.log("[MCPAppsRenderer] Inner iframe initialized");
|
|
1638
|
+
if (mounted) {
|
|
1639
|
+
setIframeReady(true);
|
|
1640
|
+
}
|
|
1641
|
+
break;
|
|
1642
|
+
}
|
|
1643
|
+
case "ui/notifications/size-change": {
|
|
1644
|
+
const { width, height } = msg.params || {};
|
|
1645
|
+
console.log("[MCPAppsRenderer] Size change:", { width, height });
|
|
1646
|
+
if (mounted) {
|
|
1647
|
+
setIframeSize({
|
|
1648
|
+
width: typeof width === "number" ? width : void 0,
|
|
1649
|
+
height: typeof height === "number" ? height : void 0
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
break;
|
|
1653
|
+
}
|
|
1654
|
+
case "notifications/message": {
|
|
1655
|
+
console.log("[MCPAppsRenderer] App log:", msg.params);
|
|
1656
|
+
break;
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
};
|
|
1661
|
+
window.addEventListener("message", messageHandler);
|
|
1662
|
+
const html = extractHtmlFromResource(content.resource);
|
|
1663
|
+
sendNotification("ui/notifications/sandbox-resource-ready", { html });
|
|
1664
|
+
} catch (err) {
|
|
1665
|
+
console.error("[MCPAppsRenderer] Setup error:", err);
|
|
1666
|
+
if (mounted) {
|
|
1667
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
};
|
|
1671
|
+
setup();
|
|
1672
|
+
return () => {
|
|
1673
|
+
mounted = false;
|
|
1674
|
+
if (messageHandler) {
|
|
1675
|
+
window.removeEventListener("message", messageHandler);
|
|
1676
|
+
}
|
|
1677
|
+
if (iframeRef.current && containerRef.current?.contains(iframeRef.current)) {
|
|
1678
|
+
containerRef.current.removeChild(iframeRef.current);
|
|
1679
|
+
}
|
|
1680
|
+
iframeRef.current = null;
|
|
1681
|
+
};
|
|
1682
|
+
}, [content.resource, sendNotification, sendResponse, sendErrorResponse]);
|
|
1683
|
+
useEffect4(() => {
|
|
1684
|
+
if (iframeRef.current) {
|
|
1685
|
+
if (iframeSize.width !== void 0) {
|
|
1686
|
+
iframeRef.current.style.width = `${iframeSize.width}px`;
|
|
1687
|
+
}
|
|
1688
|
+
if (iframeSize.height !== void 0) {
|
|
1689
|
+
iframeRef.current.style.height = `${iframeSize.height}px`;
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
}, [iframeSize]);
|
|
1693
|
+
useEffect4(() => {
|
|
1694
|
+
if (iframeReady && content.toolInput) {
|
|
1695
|
+
console.log("[MCPAppsRenderer] Sending tool input:", content.toolInput);
|
|
1696
|
+
sendNotification("ui/notifications/tool-input", {
|
|
1697
|
+
arguments: content.toolInput
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
}, [iframeReady, content.toolInput, sendNotification]);
|
|
1701
|
+
useEffect4(() => {
|
|
1702
|
+
if (iframeReady && content.result) {
|
|
1703
|
+
console.log("[MCPAppsRenderer] Sending tool result:", content.result);
|
|
1704
|
+
sendNotification("ui/notifications/tool-result", content.result);
|
|
1705
|
+
}
|
|
1706
|
+
}, [iframeReady, content.result, sendNotification]);
|
|
1707
|
+
return /* @__PURE__ */ jsx8(
|
|
1708
|
+
"div",
|
|
1709
|
+
{
|
|
1710
|
+
ref: containerRef,
|
|
1711
|
+
style: {
|
|
1712
|
+
width: "100%",
|
|
1713
|
+
minHeight: "100px",
|
|
1714
|
+
borderRadius: "8px",
|
|
1715
|
+
overflow: "hidden",
|
|
1716
|
+
backgroundColor: "#f9f9f9",
|
|
1717
|
+
border: "1px solid #e0e0e0"
|
|
1718
|
+
},
|
|
1719
|
+
children: error && /* @__PURE__ */ jsxs4("div", { style: { color: "red", padding: "1rem" }, children: [
|
|
1720
|
+
"Error: ",
|
|
1721
|
+
error.message
|
|
1722
|
+
] })
|
|
1723
|
+
}
|
|
1724
|
+
);
|
|
1725
|
+
};
|
|
1726
|
+
|
|
1727
|
+
// src/providers/CopilotKitProvider.tsx
|
|
1728
|
+
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1729
|
+
var HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
|
|
1730
|
+
var COPILOT_CLOUD_CHAT_URL = "https://api.cloud.copilotkit.ai/copilotkit/v1";
|
|
1731
|
+
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
1732
|
+
var CopilotKitContext = createContext2({
|
|
1733
|
+
copilotkit: null,
|
|
1734
|
+
executingToolCallIds: EMPTY_SET
|
|
1735
|
+
});
|
|
1736
|
+
function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
|
|
1737
|
+
const empty = useMemo3(() => [], []);
|
|
1738
|
+
const value = prop ?? empty;
|
|
1739
|
+
const initial = useRef4(value);
|
|
1740
|
+
useEffect5(() => {
|
|
1741
|
+
if (warningMessage && value !== initial.current && (isMeaningfulChange ? isMeaningfulChange(initial.current, value) : true)) {
|
|
1742
|
+
console.error(warningMessage);
|
|
1743
|
+
}
|
|
1744
|
+
}, [value, warningMessage]);
|
|
1745
|
+
return value;
|
|
1746
|
+
}
|
|
1747
|
+
var CopilotKitProvider = ({
|
|
1748
|
+
children,
|
|
1749
|
+
runtimeUrl,
|
|
1750
|
+
headers = {},
|
|
1751
|
+
publicApiKey,
|
|
1752
|
+
publicLicenseKey,
|
|
1753
|
+
properties = {},
|
|
1754
|
+
agents__unsafe_dev_only: agents = {},
|
|
1755
|
+
renderToolCalls,
|
|
1756
|
+
renderActivityMessages,
|
|
1757
|
+
renderCustomMessages,
|
|
1758
|
+
frontendTools,
|
|
1759
|
+
humanInTheLoop,
|
|
1760
|
+
showDevConsole = false,
|
|
1761
|
+
useSingleEndpoint = false
|
|
1762
|
+
}) => {
|
|
1763
|
+
const [shouldRenderInspector, setShouldRenderInspector] = useState5(false);
|
|
1764
|
+
useEffect5(() => {
|
|
1765
|
+
if (typeof window === "undefined") {
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
if (showDevConsole === true) {
|
|
1769
|
+
setShouldRenderInspector(true);
|
|
1770
|
+
} else if (showDevConsole === "auto") {
|
|
1771
|
+
const localhostHosts = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
|
|
1772
|
+
if (localhostHosts.has(window.location.hostname)) {
|
|
1773
|
+
setShouldRenderInspector(true);
|
|
1774
|
+
} else {
|
|
1775
|
+
setShouldRenderInspector(false);
|
|
1776
|
+
}
|
|
1777
|
+
} else {
|
|
1778
|
+
setShouldRenderInspector(false);
|
|
1779
|
+
}
|
|
1780
|
+
}, [showDevConsole]);
|
|
1781
|
+
const renderToolCallsList = useStableArrayProp(
|
|
1782
|
+
renderToolCalls,
|
|
1783
|
+
"renderToolCalls must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.",
|
|
1784
|
+
(initial, next) => {
|
|
1785
|
+
const key = (rc) => `${rc?.agentId ?? ""}:${rc?.name ?? ""}`;
|
|
1786
|
+
const setFrom = (arr) => new Set(arr.map(key));
|
|
1787
|
+
const a = setFrom(initial);
|
|
1788
|
+
const b = setFrom(next);
|
|
1789
|
+
if (a.size !== b.size) return true;
|
|
1790
|
+
for (const k of a) if (!b.has(k)) return true;
|
|
1791
|
+
return false;
|
|
1792
|
+
}
|
|
1793
|
+
);
|
|
1794
|
+
const renderCustomMessagesList = useStableArrayProp(
|
|
1795
|
+
renderCustomMessages,
|
|
1796
|
+
"renderCustomMessages must be a stable array."
|
|
1797
|
+
);
|
|
1798
|
+
const renderActivityMessagesList = useStableArrayProp(
|
|
1799
|
+
renderActivityMessages,
|
|
1800
|
+
"renderActivityMessages must be a stable array."
|
|
1801
|
+
);
|
|
1802
|
+
const builtInActivityRenderers = useMemo3(() => [
|
|
1803
|
+
{
|
|
1804
|
+
activityType: MCPAppsActivityType,
|
|
1805
|
+
content: MCPAppsActivityContentSchema,
|
|
1806
|
+
render: MCPAppsActivityRenderer
|
|
1807
|
+
}
|
|
1808
|
+
], []);
|
|
1809
|
+
const allActivityRenderers = useMemo3(() => {
|
|
1810
|
+
return [...renderActivityMessagesList, ...builtInActivityRenderers];
|
|
1811
|
+
}, [renderActivityMessagesList, builtInActivityRenderers]);
|
|
1812
|
+
const resolvedPublicKey = publicApiKey ?? publicLicenseKey;
|
|
1813
|
+
const hasLocalAgents = agents && Object.keys(agents).length > 0;
|
|
1814
|
+
const mergedHeaders = useMemo3(() => {
|
|
1815
|
+
if (!resolvedPublicKey) return headers;
|
|
1816
|
+
if (headers[HEADER_NAME]) return headers;
|
|
1817
|
+
return {
|
|
1818
|
+
...headers,
|
|
1819
|
+
[HEADER_NAME]: resolvedPublicKey
|
|
1820
|
+
};
|
|
1821
|
+
}, [headers, resolvedPublicKey]);
|
|
1822
|
+
if (!runtimeUrl && !resolvedPublicKey && !hasLocalAgents) {
|
|
1823
|
+
const message = "Missing required prop: 'runtimeUrl' or 'publicApiKey' or 'publicLicenseKey'";
|
|
1824
|
+
if (process.env.NODE_ENV === "production") {
|
|
1825
|
+
throw new Error(message);
|
|
1826
|
+
} else {
|
|
1827
|
+
console.warn(message);
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
const chatApiEndpoint = runtimeUrl ?? (resolvedPublicKey ? COPILOT_CLOUD_CHAT_URL : void 0);
|
|
1831
|
+
const frontendToolsList = useStableArrayProp(
|
|
1832
|
+
frontendTools,
|
|
1833
|
+
"frontendTools must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead."
|
|
1834
|
+
);
|
|
1835
|
+
const humanInTheLoopList = useStableArrayProp(
|
|
1836
|
+
humanInTheLoop,
|
|
1837
|
+
"humanInTheLoop must be a stable array. If you want to dynamically add or remove human-in-the-loop tools, use `useHumanInTheLoop` instead."
|
|
1838
|
+
);
|
|
1839
|
+
const processedHumanInTheLoopTools = useMemo3(() => {
|
|
1840
|
+
const processedTools = [];
|
|
1841
|
+
const processedRenderToolCalls = [];
|
|
1842
|
+
humanInTheLoopList.forEach((tool) => {
|
|
1843
|
+
const frontendTool = {
|
|
1844
|
+
name: tool.name,
|
|
1845
|
+
description: tool.description,
|
|
1846
|
+
parameters: tool.parameters,
|
|
1847
|
+
followUp: tool.followUp,
|
|
1848
|
+
...tool.agentId && { agentId: tool.agentId },
|
|
1849
|
+
handler: async () => {
|
|
1850
|
+
return new Promise((resolve) => {
|
|
1851
|
+
console.warn(`Human-in-the-loop tool '${tool.name}' called but no interactive handler is set up.`);
|
|
1852
|
+
resolve(void 0);
|
|
1853
|
+
});
|
|
1854
|
+
}
|
|
1855
|
+
};
|
|
1856
|
+
processedTools.push(frontendTool);
|
|
1857
|
+
if (tool.render) {
|
|
1858
|
+
processedRenderToolCalls.push({
|
|
1859
|
+
name: tool.name,
|
|
1860
|
+
args: tool.parameters,
|
|
1861
|
+
render: tool.render,
|
|
1862
|
+
...tool.agentId && { agentId: tool.agentId }
|
|
1863
|
+
});
|
|
1864
|
+
}
|
|
1865
|
+
});
|
|
1866
|
+
return { tools: processedTools, renderToolCalls: processedRenderToolCalls };
|
|
1867
|
+
}, [humanInTheLoopList]);
|
|
1868
|
+
const allTools = useMemo3(() => {
|
|
1869
|
+
const tools = [];
|
|
1870
|
+
tools.push(...frontendToolsList);
|
|
1871
|
+
tools.push(...processedHumanInTheLoopTools.tools);
|
|
1872
|
+
return tools;
|
|
1873
|
+
}, [frontendToolsList, processedHumanInTheLoopTools]);
|
|
1874
|
+
const allRenderToolCalls = useMemo3(() => {
|
|
1875
|
+
const combined = [...renderToolCallsList];
|
|
1876
|
+
frontendToolsList.forEach((tool) => {
|
|
1877
|
+
if (tool.render) {
|
|
1878
|
+
const args = tool.parameters || (tool.name === "*" ? z2.any() : void 0);
|
|
1879
|
+
if (args) {
|
|
1880
|
+
combined.push({
|
|
1881
|
+
name: tool.name,
|
|
1882
|
+
args,
|
|
1883
|
+
render: tool.render
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
});
|
|
1888
|
+
combined.push(...processedHumanInTheLoopTools.renderToolCalls);
|
|
1889
|
+
return combined;
|
|
1890
|
+
}, [renderToolCallsList, frontendToolsList, processedHumanInTheLoopTools]);
|
|
1891
|
+
const copilotkit = useMemo3(() => {
|
|
1892
|
+
const copilotkit2 = new CopilotKitCoreReact({
|
|
1893
|
+
runtimeUrl: chatApiEndpoint,
|
|
1894
|
+
runtimeTransport: useSingleEndpoint ? "single" : "rest",
|
|
1895
|
+
headers: mergedHeaders,
|
|
1896
|
+
properties,
|
|
1897
|
+
agents__unsafe_dev_only: agents,
|
|
1898
|
+
tools: allTools,
|
|
1899
|
+
renderToolCalls: allRenderToolCalls,
|
|
1900
|
+
renderActivityMessages: allActivityRenderers,
|
|
1901
|
+
renderCustomMessages: renderCustomMessagesList
|
|
1902
|
+
});
|
|
1903
|
+
return copilotkit2;
|
|
1904
|
+
}, [allTools, allRenderToolCalls, allActivityRenderers, renderCustomMessagesList, useSingleEndpoint]);
|
|
1905
|
+
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
1906
|
+
useEffect5(() => {
|
|
1907
|
+
const subscription = copilotkit.subscribe({
|
|
1908
|
+
onRenderToolCallsChanged: () => {
|
|
1909
|
+
forceUpdate();
|
|
1910
|
+
}
|
|
1911
|
+
});
|
|
1912
|
+
return () => {
|
|
1913
|
+
subscription.unsubscribe();
|
|
1914
|
+
};
|
|
1915
|
+
}, [copilotkit]);
|
|
1916
|
+
const [executingToolCallIds, setExecutingToolCallIds] = useState5(() => /* @__PURE__ */ new Set());
|
|
1917
|
+
useEffect5(() => {
|
|
1918
|
+
const subscription = copilotkit.subscribe({
|
|
1919
|
+
onToolExecutionStart: ({ toolCallId }) => {
|
|
1920
|
+
setExecutingToolCallIds((prev) => {
|
|
1921
|
+
if (prev.has(toolCallId)) return prev;
|
|
1922
|
+
const next = new Set(prev);
|
|
1923
|
+
next.add(toolCallId);
|
|
1924
|
+
return next;
|
|
1925
|
+
});
|
|
1926
|
+
},
|
|
1927
|
+
onToolExecutionEnd: ({ toolCallId }) => {
|
|
1928
|
+
setExecutingToolCallIds((prev) => {
|
|
1929
|
+
if (!prev.has(toolCallId)) return prev;
|
|
1930
|
+
const next = new Set(prev);
|
|
1931
|
+
next.delete(toolCallId);
|
|
1932
|
+
return next;
|
|
1933
|
+
});
|
|
1934
|
+
}
|
|
1935
|
+
});
|
|
1936
|
+
return () => {
|
|
1937
|
+
subscription.unsubscribe();
|
|
1938
|
+
};
|
|
1939
|
+
}, [copilotkit]);
|
|
1940
|
+
useEffect5(() => {
|
|
1941
|
+
copilotkit.setRuntimeUrl(chatApiEndpoint);
|
|
1942
|
+
copilotkit.setRuntimeTransport(useSingleEndpoint ? "single" : "rest");
|
|
1943
|
+
copilotkit.setHeaders(mergedHeaders);
|
|
1944
|
+
copilotkit.setProperties(properties);
|
|
1945
|
+
copilotkit.setAgents__unsafe_dev_only(agents);
|
|
1946
|
+
}, [chatApiEndpoint, mergedHeaders, properties, agents, useSingleEndpoint]);
|
|
1947
|
+
return /* @__PURE__ */ jsxs5(
|
|
1948
|
+
CopilotKitContext.Provider,
|
|
1949
|
+
{
|
|
1950
|
+
value: {
|
|
1951
|
+
copilotkit,
|
|
1952
|
+
executingToolCallIds
|
|
1953
|
+
},
|
|
1954
|
+
children: [
|
|
1955
|
+
children,
|
|
1956
|
+
shouldRenderInspector ? /* @__PURE__ */ jsx9(CopilotKitInspector, { core: copilotkit }) : null
|
|
1957
|
+
]
|
|
1958
|
+
}
|
|
1959
|
+
);
|
|
1960
|
+
};
|
|
1961
|
+
var useCopilotKit = () => {
|
|
1962
|
+
const context = useContext2(CopilotKitContext);
|
|
1963
|
+
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
1964
|
+
if (!context) {
|
|
1965
|
+
throw new Error("useCopilotKit must be used within CopilotKitProvider");
|
|
1966
|
+
}
|
|
1967
|
+
useEffect5(() => {
|
|
1968
|
+
const subscription = context.copilotkit.subscribe({
|
|
1969
|
+
onRuntimeConnectionStatusChanged: () => {
|
|
1970
|
+
forceUpdate();
|
|
1971
|
+
}
|
|
1972
|
+
});
|
|
1973
|
+
return () => {
|
|
1974
|
+
subscription.unsubscribe();
|
|
1975
|
+
};
|
|
1976
|
+
}, []);
|
|
1977
|
+
return context;
|
|
1978
|
+
};
|
|
1979
|
+
|
|
1980
|
+
// src/hooks/use-render-tool-call.tsx
|
|
1981
|
+
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID2 } from "@copilotkitnext/shared";
|
|
1982
|
+
import { partialJSONParse } from "@copilotkitnext/shared";
|
|
1983
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1984
|
+
var ToolCallRenderer = React7.memo(
|
|
1985
|
+
function ToolCallRenderer2({
|
|
1986
|
+
toolCall,
|
|
1987
|
+
toolMessage,
|
|
1988
|
+
RenderComponent,
|
|
1989
|
+
isExecuting
|
|
1990
|
+
}) {
|
|
1991
|
+
const args = useMemo4(
|
|
1992
|
+
() => partialJSONParse(toolCall.function.arguments),
|
|
1993
|
+
[toolCall.function.arguments]
|
|
1994
|
+
);
|
|
1995
|
+
const toolName = toolCall.function.name;
|
|
1996
|
+
if (toolMessage) {
|
|
1997
|
+
return /* @__PURE__ */ jsx10(
|
|
1998
|
+
RenderComponent,
|
|
1999
|
+
{
|
|
2000
|
+
name: toolName,
|
|
2001
|
+
args,
|
|
2002
|
+
status: ToolCallStatus.Complete,
|
|
2003
|
+
result: toolMessage.content
|
|
2004
|
+
}
|
|
2005
|
+
);
|
|
2006
|
+
} else if (isExecuting) {
|
|
2007
|
+
return /* @__PURE__ */ jsx10(
|
|
2008
|
+
RenderComponent,
|
|
2009
|
+
{
|
|
2010
|
+
name: toolName,
|
|
2011
|
+
args,
|
|
2012
|
+
status: ToolCallStatus.Executing,
|
|
2013
|
+
result: void 0
|
|
2014
|
+
}
|
|
2015
|
+
);
|
|
2016
|
+
} else {
|
|
2017
|
+
return /* @__PURE__ */ jsx10(
|
|
2018
|
+
RenderComponent,
|
|
2019
|
+
{
|
|
2020
|
+
name: toolName,
|
|
2021
|
+
args,
|
|
2022
|
+
status: ToolCallStatus.InProgress,
|
|
2023
|
+
result: void 0
|
|
2024
|
+
}
|
|
2025
|
+
);
|
|
2026
|
+
}
|
|
2027
|
+
},
|
|
2028
|
+
// Custom comparison function to prevent re-renders when tool call data hasn't changed
|
|
2029
|
+
(prevProps, nextProps) => {
|
|
2030
|
+
if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
|
|
2031
|
+
if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
|
|
2032
|
+
if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
|
|
2033
|
+
const prevResult = prevProps.toolMessage?.content;
|
|
2034
|
+
const nextResult = nextProps.toolMessage?.content;
|
|
2035
|
+
if (prevResult !== nextResult) return false;
|
|
2036
|
+
if (prevProps.isExecuting !== nextProps.isExecuting) return false;
|
|
2037
|
+
if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
|
|
2038
|
+
return true;
|
|
2039
|
+
}
|
|
2040
|
+
);
|
|
2041
|
+
function useRenderToolCall() {
|
|
2042
|
+
const { copilotkit, executingToolCallIds } = useCopilotKit();
|
|
2043
|
+
const config = useCopilotChatConfiguration();
|
|
2044
|
+
const agentId = config?.agentId ?? DEFAULT_AGENT_ID2;
|
|
2045
|
+
const renderToolCalls = useSyncExternalStore(
|
|
2046
|
+
(callback) => {
|
|
2047
|
+
return copilotkit.subscribe({
|
|
2048
|
+
onRenderToolCallsChanged: callback
|
|
2049
|
+
}).unsubscribe;
|
|
2050
|
+
},
|
|
2051
|
+
() => copilotkit.renderToolCalls,
|
|
2052
|
+
() => copilotkit.renderToolCalls
|
|
2053
|
+
);
|
|
2054
|
+
const renderToolCall = useCallback3(
|
|
2055
|
+
({
|
|
2056
|
+
toolCall,
|
|
2057
|
+
toolMessage
|
|
2058
|
+
}) => {
|
|
2059
|
+
const exactMatches = renderToolCalls.filter(
|
|
2060
|
+
(rc) => rc.name === toolCall.function.name
|
|
2061
|
+
);
|
|
2062
|
+
const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
|
|
2063
|
+
if (!renderConfig) {
|
|
2064
|
+
return null;
|
|
2065
|
+
}
|
|
2066
|
+
const RenderComponent = renderConfig.render;
|
|
2067
|
+
const isExecuting = executingToolCallIds.has(toolCall.id);
|
|
2068
|
+
return /* @__PURE__ */ jsx10(
|
|
2069
|
+
ToolCallRenderer,
|
|
2070
|
+
{
|
|
2071
|
+
toolCall,
|
|
2072
|
+
toolMessage,
|
|
2073
|
+
RenderComponent,
|
|
2074
|
+
isExecuting
|
|
2075
|
+
},
|
|
2076
|
+
toolCall.id
|
|
2077
|
+
);
|
|
2078
|
+
},
|
|
2079
|
+
[renderToolCalls, executingToolCallIds, agentId]
|
|
2080
|
+
);
|
|
2081
|
+
return renderToolCall;
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
// src/hooks/use-render-custom-messages.tsx
|
|
2085
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2086
|
+
function useRenderCustomMessages() {
|
|
2087
|
+
const { copilotkit } = useCopilotKit();
|
|
2088
|
+
const config = useCopilotChatConfiguration();
|
|
2089
|
+
if (!config) {
|
|
2090
|
+
return null;
|
|
2091
|
+
}
|
|
2092
|
+
const { agentId, threadId } = config;
|
|
2093
|
+
const customMessageRenderers = copilotkit.renderCustomMessages.filter((renderer) => renderer.agentId === void 0 || renderer.agentId === agentId).sort((a, b) => {
|
|
2094
|
+
const aHasAgent = a.agentId !== void 0;
|
|
2095
|
+
const bHasAgent = b.agentId !== void 0;
|
|
2096
|
+
if (aHasAgent === bHasAgent) return 0;
|
|
2097
|
+
return aHasAgent ? -1 : 1;
|
|
2098
|
+
});
|
|
2099
|
+
return function(params) {
|
|
2100
|
+
if (!customMessageRenderers.length) {
|
|
2101
|
+
return null;
|
|
2102
|
+
}
|
|
2103
|
+
const { message, position } = params;
|
|
2104
|
+
const runId = copilotkit.getRunIdForMessage(agentId, threadId, message.id);
|
|
2105
|
+
const agent = copilotkit.getAgent(agentId);
|
|
2106
|
+
if (!agent) {
|
|
2107
|
+
throw new Error("Agent not found");
|
|
2108
|
+
}
|
|
2109
|
+
const messagesIdsInRun = agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === runId).map((msg) => msg.id);
|
|
2110
|
+
const messageIndex = agent.messages.findIndex((msg) => msg.id === message.id) ?? 0;
|
|
2111
|
+
const messageIndexInRun = Math.min(messagesIdsInRun.indexOf(message.id), 0);
|
|
2112
|
+
const numberOfMessagesInRun = messagesIdsInRun.length;
|
|
2113
|
+
const stateSnapshot = copilotkit.getStateByRun(agentId, threadId, runId);
|
|
2114
|
+
let result = null;
|
|
2115
|
+
for (const renderer of customMessageRenderers) {
|
|
2116
|
+
if (!renderer.render) {
|
|
2117
|
+
continue;
|
|
2118
|
+
}
|
|
2119
|
+
const Component = renderer.render;
|
|
2120
|
+
result = /* @__PURE__ */ jsx11(
|
|
2121
|
+
Component,
|
|
2122
|
+
{
|
|
2123
|
+
message,
|
|
2124
|
+
position,
|
|
2125
|
+
runId,
|
|
2126
|
+
messageIndex,
|
|
2127
|
+
messageIndexInRun,
|
|
2128
|
+
numberOfMessagesInRun,
|
|
2129
|
+
agentId,
|
|
2130
|
+
stateSnapshot
|
|
2131
|
+
},
|
|
2132
|
+
`${runId}-${message.id}-${position}`
|
|
2133
|
+
);
|
|
2134
|
+
if (result) {
|
|
2135
|
+
break;
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
return result;
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
// src/hooks/use-render-activity-message.tsx
|
|
2143
|
+
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID3 } from "@copilotkitnext/shared";
|
|
2144
|
+
import { useCallback as useCallback4 } from "react";
|
|
2145
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
2146
|
+
function useRenderActivityMessage() {
|
|
2147
|
+
const { copilotkit } = useCopilotKit();
|
|
2148
|
+
const config = useCopilotChatConfiguration();
|
|
2149
|
+
const agentId = config?.agentId ?? DEFAULT_AGENT_ID3;
|
|
2150
|
+
const renderers = copilotkit.renderActivityMessages;
|
|
2151
|
+
return useCallback4(
|
|
2152
|
+
(message) => {
|
|
2153
|
+
if (!renderers.length) {
|
|
2154
|
+
return null;
|
|
2155
|
+
}
|
|
2156
|
+
const matches = renderers.filter(
|
|
2157
|
+
(renderer2) => renderer2.activityType === message.activityType
|
|
2158
|
+
);
|
|
2159
|
+
const renderer = matches.find((candidate) => candidate.agentId === agentId) ?? matches.find((candidate) => candidate.agentId === void 0) ?? renderers.find((candidate) => candidate.activityType === "*");
|
|
2160
|
+
if (!renderer) {
|
|
2161
|
+
return null;
|
|
2162
|
+
}
|
|
2163
|
+
const parseResult = renderer.content.safeParse(message.content);
|
|
2164
|
+
if (!parseResult.success) {
|
|
2165
|
+
console.warn(
|
|
2166
|
+
`Failed to parse content for activity message '${message.activityType}':`,
|
|
2167
|
+
parseResult.error
|
|
2168
|
+
);
|
|
2169
|
+
return null;
|
|
2170
|
+
}
|
|
2171
|
+
const Component = renderer.render;
|
|
2172
|
+
const agent = copilotkit.getAgent(agentId);
|
|
2173
|
+
return /* @__PURE__ */ jsx12(
|
|
2174
|
+
Component,
|
|
2175
|
+
{
|
|
2176
|
+
activityType: message.activityType,
|
|
2177
|
+
content: parseResult.data,
|
|
2178
|
+
message,
|
|
2179
|
+
agent
|
|
2180
|
+
},
|
|
2181
|
+
message.id
|
|
2182
|
+
);
|
|
2183
|
+
},
|
|
2184
|
+
[agentId, copilotkit, renderers]
|
|
2185
|
+
);
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
// src/hooks/use-frontend-tool.tsx
|
|
2189
|
+
import { useEffect as useEffect6 } from "react";
|
|
2190
|
+
var EMPTY_DEPS = [];
|
|
2191
|
+
function useFrontendTool(tool, deps) {
|
|
2192
|
+
const { copilotkit } = useCopilotKit();
|
|
2193
|
+
const extraDeps = deps ?? EMPTY_DEPS;
|
|
2194
|
+
useEffect6(() => {
|
|
2195
|
+
const name = tool.name;
|
|
2196
|
+
if (copilotkit.getTool({ toolName: name, agentId: tool.agentId })) {
|
|
2197
|
+
console.warn(
|
|
2198
|
+
`Tool '${name}' already exists for agent '${tool.agentId || "global"}'. Overriding with latest registration.`
|
|
2199
|
+
);
|
|
2200
|
+
copilotkit.removeTool(name, tool.agentId);
|
|
2201
|
+
}
|
|
2202
|
+
copilotkit.addTool(tool);
|
|
2203
|
+
if (tool.render) {
|
|
2204
|
+
const keyOf = (rc) => `${rc.agentId ?? ""}:${rc.name}`;
|
|
2205
|
+
const currentRenderToolCalls = copilotkit.renderToolCalls;
|
|
2206
|
+
const mergedMap = /* @__PURE__ */ new Map();
|
|
2207
|
+
for (const rc of currentRenderToolCalls) {
|
|
2208
|
+
mergedMap.set(keyOf(rc), rc);
|
|
2209
|
+
}
|
|
2210
|
+
const newEntry = {
|
|
2211
|
+
name,
|
|
2212
|
+
args: tool.parameters,
|
|
2213
|
+
agentId: tool.agentId,
|
|
2214
|
+
render: tool.render
|
|
2215
|
+
};
|
|
2216
|
+
mergedMap.set(keyOf(newEntry), newEntry);
|
|
2217
|
+
copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));
|
|
2218
|
+
}
|
|
2219
|
+
return () => {
|
|
2220
|
+
copilotkit.removeTool(name, tool.agentId);
|
|
2221
|
+
};
|
|
2222
|
+
}, [tool.name, copilotkit, extraDeps.length, ...extraDeps]);
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
// src/hooks/use-human-in-the-loop.tsx
|
|
2226
|
+
import { useCallback as useCallback5, useRef as useRef5, useEffect as useEffect7 } from "react";
|
|
2227
|
+
import React8 from "react";
|
|
2228
|
+
function useHumanInTheLoop(tool, deps) {
|
|
2229
|
+
const { copilotkit } = useCopilotKit();
|
|
2230
|
+
const resolvePromiseRef = useRef5(null);
|
|
2231
|
+
const respond = useCallback5(async (result) => {
|
|
2232
|
+
if (resolvePromiseRef.current) {
|
|
2233
|
+
resolvePromiseRef.current(result);
|
|
2234
|
+
resolvePromiseRef.current = null;
|
|
2235
|
+
}
|
|
2236
|
+
}, []);
|
|
2237
|
+
const handler = useCallback5(async () => {
|
|
2238
|
+
return new Promise((resolve) => {
|
|
2239
|
+
resolvePromiseRef.current = resolve;
|
|
2240
|
+
});
|
|
2241
|
+
}, []);
|
|
2242
|
+
const RenderComponent = useCallback5(
|
|
2243
|
+
(props) => {
|
|
2244
|
+
const ToolComponent = tool.render;
|
|
2245
|
+
if (props.status === "inProgress") {
|
|
2246
|
+
const enhancedProps = {
|
|
2247
|
+
...props,
|
|
2248
|
+
name: tool.name,
|
|
2249
|
+
description: tool.description || "",
|
|
2250
|
+
respond: void 0
|
|
2251
|
+
};
|
|
2252
|
+
return React8.createElement(ToolComponent, enhancedProps);
|
|
2253
|
+
} else if (props.status === "executing") {
|
|
2254
|
+
const enhancedProps = {
|
|
2255
|
+
...props,
|
|
2256
|
+
name: tool.name,
|
|
2257
|
+
description: tool.description || "",
|
|
2258
|
+
respond
|
|
2259
|
+
};
|
|
2260
|
+
return React8.createElement(ToolComponent, enhancedProps);
|
|
2261
|
+
} else if (props.status === "complete") {
|
|
2262
|
+
const enhancedProps = {
|
|
2263
|
+
...props,
|
|
2264
|
+
name: tool.name,
|
|
2265
|
+
description: tool.description || "",
|
|
2266
|
+
respond: void 0
|
|
2267
|
+
};
|
|
2268
|
+
return React8.createElement(ToolComponent, enhancedProps);
|
|
2269
|
+
}
|
|
2270
|
+
return React8.createElement(ToolComponent, props);
|
|
2271
|
+
},
|
|
2272
|
+
[tool.render, tool.name, tool.description, respond]
|
|
2273
|
+
);
|
|
2274
|
+
const frontendTool = {
|
|
2275
|
+
...tool,
|
|
2276
|
+
handler,
|
|
2277
|
+
render: RenderComponent
|
|
2278
|
+
};
|
|
2279
|
+
useFrontendTool(frontendTool, deps);
|
|
2280
|
+
useEffect7(() => {
|
|
2281
|
+
return () => {
|
|
2282
|
+
const keyOf = (rc) => `${rc.agentId ?? ""}:${rc.name}`;
|
|
2283
|
+
const currentRenderToolCalls = copilotkit.renderToolCalls;
|
|
2284
|
+
const filtered = currentRenderToolCalls.filter(
|
|
2285
|
+
(rc) => keyOf(rc) !== keyOf({ name: tool.name, agentId: tool.agentId })
|
|
2286
|
+
);
|
|
2287
|
+
copilotkit.setRenderToolCalls(filtered);
|
|
2288
|
+
};
|
|
2289
|
+
}, [copilotkit, tool.name, tool.agentId]);
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
// src/hooks/use-agent.tsx
|
|
2293
|
+
import { useMemo as useMemo5, useEffect as useEffect8, useReducer as useReducer2 } from "react";
|
|
2294
|
+
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID4 } from "@copilotkitnext/shared";
|
|
2295
|
+
import { ProxiedCopilotRuntimeAgent, CopilotKitCoreRuntimeConnectionStatus } from "@copilotkitnext/core";
|
|
2296
|
+
var UseAgentUpdate = /* @__PURE__ */ ((UseAgentUpdate2) => {
|
|
2297
|
+
UseAgentUpdate2["OnMessagesChanged"] = "OnMessagesChanged";
|
|
2298
|
+
UseAgentUpdate2["OnStateChanged"] = "OnStateChanged";
|
|
2299
|
+
UseAgentUpdate2["OnRunStatusChanged"] = "OnRunStatusChanged";
|
|
2300
|
+
return UseAgentUpdate2;
|
|
2301
|
+
})(UseAgentUpdate || {});
|
|
2302
|
+
var ALL_UPDATES = [
|
|
2303
|
+
"OnMessagesChanged" /* OnMessagesChanged */,
|
|
2304
|
+
"OnStateChanged" /* OnStateChanged */,
|
|
2305
|
+
"OnRunStatusChanged" /* OnRunStatusChanged */
|
|
2306
|
+
];
|
|
2307
|
+
function useAgent({ agentId, updates } = {}) {
|
|
2308
|
+
agentId ??= DEFAULT_AGENT_ID4;
|
|
2309
|
+
const { copilotkit } = useCopilotKit();
|
|
2310
|
+
const [, forceUpdate] = useReducer2((x) => x + 1, 0);
|
|
2311
|
+
const updateFlags = useMemo5(
|
|
2312
|
+
() => updates ?? ALL_UPDATES,
|
|
2313
|
+
[JSON.stringify(updates)]
|
|
2314
|
+
);
|
|
2315
|
+
const agent = useMemo5(() => {
|
|
2316
|
+
const existing = copilotkit.getAgent(agentId);
|
|
2317
|
+
if (existing) {
|
|
2318
|
+
return existing;
|
|
2319
|
+
}
|
|
2320
|
+
const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
|
|
2321
|
+
const status = copilotkit.runtimeConnectionStatus;
|
|
2322
|
+
if (isRuntimeConfigured && (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
|
|
2323
|
+
const provisional = new ProxiedCopilotRuntimeAgent({
|
|
2324
|
+
runtimeUrl: copilotkit.runtimeUrl,
|
|
2325
|
+
agentId,
|
|
2326
|
+
transport: copilotkit.runtimeTransport
|
|
2327
|
+
});
|
|
2328
|
+
provisional.headers = { ...copilotkit.headers };
|
|
2329
|
+
return provisional;
|
|
2330
|
+
}
|
|
2331
|
+
const knownAgents = Object.keys(copilotkit.agents ?? {});
|
|
2332
|
+
const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
|
|
2333
|
+
throw new Error(
|
|
2334
|
+
`useAgent: Agent '${agentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only."
|
|
2335
|
+
);
|
|
2336
|
+
}, [
|
|
2337
|
+
agentId,
|
|
2338
|
+
copilotkit.agents,
|
|
2339
|
+
copilotkit.runtimeConnectionStatus,
|
|
2340
|
+
copilotkit.runtimeUrl,
|
|
2341
|
+
copilotkit.runtimeTransport,
|
|
2342
|
+
JSON.stringify(copilotkit.headers),
|
|
2343
|
+
copilotkit
|
|
2344
|
+
]);
|
|
2345
|
+
useEffect8(() => {
|
|
2346
|
+
if (updateFlags.length === 0) {
|
|
2347
|
+
return;
|
|
2348
|
+
}
|
|
2349
|
+
const handlers = {};
|
|
2350
|
+
if (updateFlags.includes("OnMessagesChanged" /* OnMessagesChanged */)) {
|
|
2351
|
+
handlers.onMessagesChanged = () => {
|
|
2352
|
+
forceUpdate();
|
|
2353
|
+
};
|
|
2354
|
+
}
|
|
2355
|
+
if (updateFlags.includes("OnStateChanged" /* OnStateChanged */)) {
|
|
2356
|
+
handlers.onStateChanged = () => {
|
|
2357
|
+
forceUpdate();
|
|
2358
|
+
};
|
|
2359
|
+
}
|
|
2360
|
+
if (updateFlags.includes("OnRunStatusChanged" /* OnRunStatusChanged */)) {
|
|
2361
|
+
handlers.onRunInitialized = () => {
|
|
2362
|
+
forceUpdate();
|
|
2363
|
+
};
|
|
2364
|
+
handlers.onRunFinalized = () => {
|
|
2365
|
+
forceUpdate();
|
|
2366
|
+
};
|
|
2367
|
+
handlers.onRunFailed = () => {
|
|
2368
|
+
forceUpdate();
|
|
2369
|
+
};
|
|
2370
|
+
}
|
|
2371
|
+
const subscription = agent.subscribe(handlers);
|
|
2372
|
+
return () => subscription.unsubscribe();
|
|
2373
|
+
}, [agent, forceUpdate, JSON.stringify(updateFlags)]);
|
|
2374
|
+
return {
|
|
2375
|
+
agent
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
// src/hooks/use-agent-context.tsx
|
|
2380
|
+
import { useEffect as useEffect9, useMemo as useMemo6 } from "react";
|
|
2381
|
+
function useAgentContext(context) {
|
|
2382
|
+
const { description, value } = context;
|
|
2383
|
+
const { copilotkit } = useCopilotKit();
|
|
2384
|
+
const stringValue = useMemo6(() => {
|
|
2385
|
+
if (typeof value === "string") {
|
|
2386
|
+
return value;
|
|
2387
|
+
}
|
|
2388
|
+
return JSON.stringify(value);
|
|
2389
|
+
}, [value]);
|
|
2390
|
+
useEffect9(() => {
|
|
2391
|
+
if (!copilotkit) return;
|
|
2392
|
+
const id = copilotkit.addContext({ description, value: stringValue });
|
|
2393
|
+
return () => {
|
|
2394
|
+
copilotkit.removeContext(id);
|
|
2395
|
+
};
|
|
2396
|
+
}, [description, stringValue, copilotkit]);
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
// src/hooks/use-suggestions.tsx
|
|
2400
|
+
import { useCallback as useCallback6, useEffect as useEffect10, useMemo as useMemo7, useState as useState6 } from "react";
|
|
2401
|
+
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID5 } from "@copilotkitnext/shared";
|
|
2402
|
+
function useSuggestions({ agentId } = {}) {
|
|
2403
|
+
const { copilotkit } = useCopilotKit();
|
|
2404
|
+
const config = useCopilotChatConfiguration();
|
|
2405
|
+
const resolvedAgentId = useMemo7(() => agentId ?? config?.agentId ?? DEFAULT_AGENT_ID5, [agentId, config?.agentId]);
|
|
2406
|
+
const [suggestions, setSuggestions] = useState6(() => {
|
|
2407
|
+
const result = copilotkit.getSuggestions(resolvedAgentId);
|
|
2408
|
+
return result.suggestions;
|
|
2409
|
+
});
|
|
2410
|
+
const [isLoading, setIsLoading] = useState6(() => {
|
|
2411
|
+
const result = copilotkit.getSuggestions(resolvedAgentId);
|
|
2412
|
+
return result.isLoading;
|
|
2413
|
+
});
|
|
2414
|
+
useEffect10(() => {
|
|
2415
|
+
const result = copilotkit.getSuggestions(resolvedAgentId);
|
|
2416
|
+
setSuggestions(result.suggestions);
|
|
2417
|
+
setIsLoading(result.isLoading);
|
|
2418
|
+
}, [copilotkit, resolvedAgentId]);
|
|
2419
|
+
useEffect10(() => {
|
|
2420
|
+
const subscription = copilotkit.subscribe({
|
|
2421
|
+
onSuggestionsChanged: ({ agentId: changedAgentId, suggestions: suggestions2 }) => {
|
|
2422
|
+
if (changedAgentId !== resolvedAgentId) {
|
|
2423
|
+
return;
|
|
2424
|
+
}
|
|
2425
|
+
setSuggestions(suggestions2);
|
|
2426
|
+
},
|
|
2427
|
+
onSuggestionsStartedLoading: ({ agentId: changedAgentId }) => {
|
|
2428
|
+
if (changedAgentId !== resolvedAgentId) {
|
|
2429
|
+
return;
|
|
2430
|
+
}
|
|
2431
|
+
setIsLoading(true);
|
|
2432
|
+
},
|
|
2433
|
+
onSuggestionsFinishedLoading: ({ agentId: changedAgentId }) => {
|
|
2434
|
+
if (changedAgentId !== resolvedAgentId) {
|
|
2435
|
+
return;
|
|
2436
|
+
}
|
|
2437
|
+
setIsLoading(false);
|
|
2438
|
+
},
|
|
2439
|
+
onSuggestionsConfigChanged: () => {
|
|
2440
|
+
const result = copilotkit.getSuggestions(resolvedAgentId);
|
|
2441
|
+
setSuggestions(result.suggestions);
|
|
2442
|
+
setIsLoading(result.isLoading);
|
|
2443
|
+
}
|
|
2444
|
+
});
|
|
2445
|
+
return () => {
|
|
2446
|
+
subscription.unsubscribe();
|
|
2447
|
+
};
|
|
2448
|
+
}, [copilotkit, resolvedAgentId]);
|
|
2449
|
+
const reloadSuggestions = useCallback6(() => {
|
|
2450
|
+
copilotkit.reloadSuggestions(resolvedAgentId);
|
|
2451
|
+
}, [copilotkit, resolvedAgentId]);
|
|
2452
|
+
const clearSuggestions = useCallback6(() => {
|
|
2453
|
+
copilotkit.clearSuggestions(resolvedAgentId);
|
|
2454
|
+
}, [copilotkit, resolvedAgentId]);
|
|
2455
|
+
return {
|
|
2456
|
+
suggestions,
|
|
2457
|
+
reloadSuggestions,
|
|
2458
|
+
clearSuggestions,
|
|
2459
|
+
isLoading
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
// src/hooks/use-configure-suggestions.tsx
|
|
2464
|
+
import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo8, useRef as useRef6 } from "react";
|
|
2465
|
+
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID6 } from "@copilotkitnext/shared";
|
|
2466
|
+
function useConfigureSuggestions(config, deps) {
|
|
2467
|
+
const { copilotkit } = useCopilotKit();
|
|
2468
|
+
const chatConfig = useCopilotChatConfiguration();
|
|
2469
|
+
const extraDeps = deps ?? [];
|
|
2470
|
+
const resolvedConsumerAgentId = useMemo8(() => chatConfig?.agentId ?? DEFAULT_AGENT_ID6, [chatConfig?.agentId]);
|
|
2471
|
+
const rawConsumerAgentId = useMemo8(() => config ? config.consumerAgentId : void 0, [config]);
|
|
2472
|
+
const normalizationCacheRef = useRef6({
|
|
2473
|
+
serialized: null,
|
|
2474
|
+
config: null
|
|
2475
|
+
});
|
|
2476
|
+
const { normalizedConfig, serializedConfig } = useMemo8(() => {
|
|
2477
|
+
if (!config) {
|
|
2478
|
+
normalizationCacheRef.current = { serialized: null, config: null };
|
|
2479
|
+
return { normalizedConfig: null, serializedConfig: null };
|
|
2480
|
+
}
|
|
2481
|
+
if (config.available === "disabled") {
|
|
2482
|
+
normalizationCacheRef.current = { serialized: null, config: null };
|
|
2483
|
+
return { normalizedConfig: null, serializedConfig: null };
|
|
2484
|
+
}
|
|
2485
|
+
let built;
|
|
2486
|
+
if (isDynamicConfig(config)) {
|
|
2487
|
+
built = {
|
|
2488
|
+
...config
|
|
2489
|
+
};
|
|
2490
|
+
} else {
|
|
2491
|
+
const normalizedSuggestions = normalizeStaticSuggestions(config.suggestions);
|
|
2492
|
+
const baseConfig = {
|
|
2493
|
+
...config,
|
|
2494
|
+
suggestions: normalizedSuggestions
|
|
2495
|
+
};
|
|
2496
|
+
built = baseConfig;
|
|
2497
|
+
}
|
|
2498
|
+
const serialized = JSON.stringify(built);
|
|
2499
|
+
const cache = normalizationCacheRef.current;
|
|
2500
|
+
if (cache.serialized === serialized && cache.config) {
|
|
2501
|
+
return { normalizedConfig: cache.config, serializedConfig: serialized };
|
|
2502
|
+
}
|
|
2503
|
+
normalizationCacheRef.current = { serialized, config: built };
|
|
2504
|
+
return { normalizedConfig: built, serializedConfig: serialized };
|
|
2505
|
+
}, [config, resolvedConsumerAgentId, ...extraDeps]);
|
|
2506
|
+
const latestConfigRef = useRef6(null);
|
|
2507
|
+
latestConfigRef.current = normalizedConfig;
|
|
2508
|
+
const previousSerializedConfigRef = useRef6(null);
|
|
2509
|
+
const targetAgentId = useMemo8(() => {
|
|
2510
|
+
if (!normalizedConfig) {
|
|
2511
|
+
return resolvedConsumerAgentId;
|
|
2512
|
+
}
|
|
2513
|
+
const consumer = normalizedConfig.consumerAgentId;
|
|
2514
|
+
if (!consumer || consumer === "*") {
|
|
2515
|
+
return resolvedConsumerAgentId;
|
|
2516
|
+
}
|
|
2517
|
+
return consumer;
|
|
2518
|
+
}, [normalizedConfig, resolvedConsumerAgentId]);
|
|
2519
|
+
const isGlobalConfig = rawConsumerAgentId === void 0 || rawConsumerAgentId === "*";
|
|
2520
|
+
const requestReload = useCallback7(() => {
|
|
2521
|
+
if (!normalizedConfig) {
|
|
2522
|
+
return;
|
|
2523
|
+
}
|
|
2524
|
+
if (isGlobalConfig) {
|
|
2525
|
+
const agents = Object.values(copilotkit.agents ?? {});
|
|
2526
|
+
for (const entry of agents) {
|
|
2527
|
+
const agentId = entry.agentId;
|
|
2528
|
+
if (!agentId) {
|
|
2529
|
+
continue;
|
|
2530
|
+
}
|
|
2531
|
+
if (!entry.isRunning) {
|
|
2532
|
+
copilotkit.reloadSuggestions(agentId);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
return;
|
|
2536
|
+
}
|
|
2537
|
+
if (!targetAgentId) {
|
|
2538
|
+
return;
|
|
2539
|
+
}
|
|
2540
|
+
copilotkit.reloadSuggestions(targetAgentId);
|
|
2541
|
+
}, [copilotkit, isGlobalConfig, normalizedConfig, targetAgentId]);
|
|
2542
|
+
useEffect11(() => {
|
|
2543
|
+
if (!serializedConfig || !latestConfigRef.current) {
|
|
2544
|
+
return;
|
|
2545
|
+
}
|
|
2546
|
+
const id = copilotkit.addSuggestionsConfig(latestConfigRef.current);
|
|
2547
|
+
requestReload();
|
|
2548
|
+
return () => {
|
|
2549
|
+
copilotkit.removeSuggestionsConfig(id);
|
|
2550
|
+
};
|
|
2551
|
+
}, [copilotkit, serializedConfig, requestReload]);
|
|
2552
|
+
useEffect11(() => {
|
|
2553
|
+
if (!normalizedConfig) {
|
|
2554
|
+
previousSerializedConfigRef.current = null;
|
|
2555
|
+
return;
|
|
2556
|
+
}
|
|
2557
|
+
if (serializedConfig && previousSerializedConfigRef.current === serializedConfig) {
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2560
|
+
if (serializedConfig) {
|
|
2561
|
+
previousSerializedConfigRef.current = serializedConfig;
|
|
2562
|
+
}
|
|
2563
|
+
requestReload();
|
|
2564
|
+
}, [normalizedConfig, requestReload, serializedConfig]);
|
|
2565
|
+
useEffect11(() => {
|
|
2566
|
+
if (!normalizedConfig || extraDeps.length === 0) {
|
|
2567
|
+
return;
|
|
2568
|
+
}
|
|
2569
|
+
requestReload();
|
|
2570
|
+
}, [extraDeps.length, normalizedConfig, requestReload, ...extraDeps]);
|
|
2571
|
+
}
|
|
2572
|
+
function isDynamicConfig(config) {
|
|
2573
|
+
return "instructions" in config;
|
|
2574
|
+
}
|
|
2575
|
+
function normalizeStaticSuggestions(suggestions) {
|
|
2576
|
+
return suggestions.map((suggestion) => ({
|
|
2577
|
+
...suggestion,
|
|
2578
|
+
isLoading: suggestion.isLoading ?? false
|
|
2579
|
+
}));
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
// src/components/chat/CopilotChatToolCallsView.tsx
|
|
2583
|
+
import React9 from "react";
|
|
2584
|
+
import { Fragment as Fragment2, jsx as jsx13 } from "react/jsx-runtime";
|
|
2585
|
+
function CopilotChatToolCallsView({
|
|
2586
|
+
message,
|
|
2587
|
+
messages = []
|
|
2588
|
+
}) {
|
|
2589
|
+
const renderToolCall = useRenderToolCall();
|
|
2590
|
+
if (!message.toolCalls || message.toolCalls.length === 0) {
|
|
2591
|
+
return null;
|
|
2592
|
+
}
|
|
2593
|
+
return /* @__PURE__ */ jsx13(Fragment2, { children: message.toolCalls.map((toolCall) => {
|
|
2594
|
+
const toolMessage = messages.find(
|
|
2595
|
+
(m) => m.role === "tool" && m.toolCallId === toolCall.id
|
|
2596
|
+
);
|
|
2597
|
+
return /* @__PURE__ */ jsx13(React9.Fragment, { children: renderToolCall({
|
|
2598
|
+
toolCall,
|
|
2599
|
+
toolMessage
|
|
2600
|
+
}) }, toolCall.id);
|
|
2601
|
+
}) });
|
|
2602
|
+
}
|
|
2603
|
+
var CopilotChatToolCallsView_default = CopilotChatToolCallsView;
|
|
2604
|
+
|
|
2605
|
+
// src/components/chat/CopilotChatAssistantMessage.tsx
|
|
2606
|
+
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2607
|
+
function CopilotChatAssistantMessage({
|
|
2608
|
+
message,
|
|
2609
|
+
messages,
|
|
2610
|
+
isRunning,
|
|
2611
|
+
onThumbsUp,
|
|
2612
|
+
onThumbsDown,
|
|
2613
|
+
onReadAloud,
|
|
2614
|
+
onRegenerate,
|
|
2615
|
+
additionalToolbarItems,
|
|
2616
|
+
toolbarVisible = true,
|
|
2617
|
+
markdownRenderer,
|
|
2618
|
+
toolbar,
|
|
2619
|
+
copyButton,
|
|
2620
|
+
thumbsUpButton,
|
|
2621
|
+
thumbsDownButton,
|
|
2622
|
+
readAloudButton,
|
|
2623
|
+
regenerateButton,
|
|
2624
|
+
toolCallsView,
|
|
2625
|
+
children,
|
|
2626
|
+
className,
|
|
2627
|
+
...props
|
|
2628
|
+
}) {
|
|
2629
|
+
const boundMarkdownRenderer = renderSlot(
|
|
2630
|
+
markdownRenderer,
|
|
2631
|
+
CopilotChatAssistantMessage.MarkdownRenderer,
|
|
2632
|
+
{
|
|
2633
|
+
content: message.content || ""
|
|
2634
|
+
}
|
|
2635
|
+
);
|
|
2636
|
+
const boundCopyButton = renderSlot(
|
|
2637
|
+
copyButton,
|
|
2638
|
+
CopilotChatAssistantMessage.CopyButton,
|
|
2639
|
+
{
|
|
2640
|
+
onClick: async () => {
|
|
2641
|
+
if (message.content) {
|
|
2642
|
+
try {
|
|
2643
|
+
await navigator.clipboard.writeText(message.content);
|
|
2644
|
+
} catch (err) {
|
|
2645
|
+
console.error("Failed to copy message:", err);
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
);
|
|
2651
|
+
const boundThumbsUpButton = renderSlot(
|
|
2652
|
+
thumbsUpButton,
|
|
2653
|
+
CopilotChatAssistantMessage.ThumbsUpButton,
|
|
2654
|
+
{
|
|
2655
|
+
onClick: onThumbsUp
|
|
2656
|
+
}
|
|
2657
|
+
);
|
|
2658
|
+
const boundThumbsDownButton = renderSlot(
|
|
2659
|
+
thumbsDownButton,
|
|
2660
|
+
CopilotChatAssistantMessage.ThumbsDownButton,
|
|
2661
|
+
{
|
|
2662
|
+
onClick: onThumbsDown
|
|
2663
|
+
}
|
|
2664
|
+
);
|
|
2665
|
+
const boundReadAloudButton = renderSlot(
|
|
2666
|
+
readAloudButton,
|
|
2667
|
+
CopilotChatAssistantMessage.ReadAloudButton,
|
|
2668
|
+
{
|
|
2669
|
+
onClick: onReadAloud
|
|
2670
|
+
}
|
|
2671
|
+
);
|
|
2672
|
+
const boundRegenerateButton = renderSlot(
|
|
2673
|
+
regenerateButton,
|
|
2674
|
+
CopilotChatAssistantMessage.RegenerateButton,
|
|
2675
|
+
{
|
|
2676
|
+
onClick: onRegenerate
|
|
2677
|
+
}
|
|
2678
|
+
);
|
|
2679
|
+
const boundToolbar = renderSlot(
|
|
2680
|
+
toolbar,
|
|
2681
|
+
CopilotChatAssistantMessage.Toolbar,
|
|
2682
|
+
{
|
|
2683
|
+
children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
|
|
2684
|
+
boundCopyButton,
|
|
2685
|
+
(onThumbsUp || thumbsUpButton) && boundThumbsUpButton,
|
|
2686
|
+
(onThumbsDown || thumbsDownButton) && boundThumbsDownButton,
|
|
2687
|
+
(onReadAloud || readAloudButton) && boundReadAloudButton,
|
|
2688
|
+
(onRegenerate || regenerateButton) && boundRegenerateButton,
|
|
2689
|
+
additionalToolbarItems
|
|
2690
|
+
] })
|
|
2691
|
+
}
|
|
2692
|
+
);
|
|
2693
|
+
const boundToolCallsView = renderSlot(
|
|
2694
|
+
toolCallsView,
|
|
2695
|
+
CopilotChatToolCallsView_default,
|
|
2696
|
+
{
|
|
2697
|
+
message,
|
|
2698
|
+
messages
|
|
2699
|
+
}
|
|
2700
|
+
);
|
|
2701
|
+
const hasContent = !!(message.content && message.content.trim().length > 0);
|
|
2702
|
+
const isLatestAssistantMessage = message.role === "assistant" && messages?.[messages.length - 1]?.id === message.id;
|
|
2703
|
+
const shouldShowToolbar = toolbarVisible && hasContent && !(isRunning && isLatestAssistantMessage);
|
|
2704
|
+
if (children) {
|
|
2705
|
+
return /* @__PURE__ */ jsx14(Fragment3, { children: children({
|
|
2706
|
+
markdownRenderer: boundMarkdownRenderer,
|
|
2707
|
+
toolbar: boundToolbar,
|
|
2708
|
+
toolCallsView: boundToolCallsView,
|
|
2709
|
+
copyButton: boundCopyButton,
|
|
2710
|
+
thumbsUpButton: boundThumbsUpButton,
|
|
2711
|
+
thumbsDownButton: boundThumbsDownButton,
|
|
2712
|
+
readAloudButton: boundReadAloudButton,
|
|
2713
|
+
regenerateButton: boundRegenerateButton,
|
|
2714
|
+
message,
|
|
2715
|
+
messages,
|
|
2716
|
+
isRunning,
|
|
2717
|
+
onThumbsUp,
|
|
2718
|
+
onThumbsDown,
|
|
2719
|
+
onReadAloud,
|
|
2720
|
+
onRegenerate,
|
|
2721
|
+
additionalToolbarItems,
|
|
2722
|
+
toolbarVisible: shouldShowToolbar
|
|
2723
|
+
}) });
|
|
2724
|
+
}
|
|
2725
|
+
return /* @__PURE__ */ jsxs6(
|
|
2726
|
+
"div",
|
|
2727
|
+
{
|
|
2728
|
+
className: twMerge4(
|
|
2729
|
+
"prose max-w-full break-words dark:prose-invert",
|
|
2730
|
+
className
|
|
2731
|
+
),
|
|
2732
|
+
...props,
|
|
2733
|
+
"data-message-id": message.id,
|
|
2734
|
+
children: [
|
|
2735
|
+
boundMarkdownRenderer,
|
|
2736
|
+
boundToolCallsView,
|
|
2737
|
+
shouldShowToolbar && boundToolbar
|
|
2738
|
+
]
|
|
2739
|
+
}
|
|
2740
|
+
);
|
|
2741
|
+
}
|
|
2742
|
+
((CopilotChatAssistantMessage2) => {
|
|
2743
|
+
CopilotChatAssistantMessage2.MarkdownRenderer = ({ content, className, ...props }) => /* @__PURE__ */ jsx14(Streamdown, { className, ...props, children: content ?? "" });
|
|
2744
|
+
CopilotChatAssistantMessage2.Toolbar = ({
|
|
2745
|
+
className,
|
|
2746
|
+
...props
|
|
2747
|
+
}) => /* @__PURE__ */ jsx14(
|
|
2748
|
+
"div",
|
|
2749
|
+
{
|
|
2750
|
+
className: twMerge4(
|
|
2751
|
+
"w-full bg-transparent flex items-center -ml-[5px] -mt-[0px]",
|
|
2752
|
+
className
|
|
2753
|
+
),
|
|
2754
|
+
...props
|
|
2755
|
+
}
|
|
2756
|
+
);
|
|
2757
|
+
CopilotChatAssistantMessage2.ToolbarButton = ({ title, children, ...props }) => {
|
|
2758
|
+
return /* @__PURE__ */ jsxs6(Tooltip, { children: [
|
|
2759
|
+
/* @__PURE__ */ jsx14(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx14(
|
|
2760
|
+
Button,
|
|
2761
|
+
{
|
|
2762
|
+
type: "button",
|
|
2763
|
+
variant: "assistantMessageToolbarButton",
|
|
2764
|
+
"aria-label": title,
|
|
2765
|
+
...props,
|
|
2766
|
+
children
|
|
2767
|
+
}
|
|
2768
|
+
) }),
|
|
2769
|
+
/* @__PURE__ */ jsx14(TooltipContent, { side: "bottom", children: /* @__PURE__ */ jsx14("p", { children: title }) })
|
|
2770
|
+
] });
|
|
2771
|
+
};
|
|
2772
|
+
CopilotChatAssistantMessage2.CopyButton = ({ className, title, onClick, ...props }) => {
|
|
2773
|
+
const config = useCopilotChatConfiguration();
|
|
2774
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
2775
|
+
const [copied, setCopied] = useState7(false);
|
|
2776
|
+
const handleClick = (event) => {
|
|
2777
|
+
setCopied(true);
|
|
2778
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
2779
|
+
if (onClick) {
|
|
2780
|
+
onClick(event);
|
|
2781
|
+
}
|
|
2782
|
+
};
|
|
2783
|
+
return /* @__PURE__ */ jsx14(
|
|
2784
|
+
CopilotChatAssistantMessage2.ToolbarButton,
|
|
2785
|
+
{
|
|
2786
|
+
title: title || labels.assistantMessageToolbarCopyMessageLabel,
|
|
2787
|
+
onClick: handleClick,
|
|
2788
|
+
className,
|
|
2789
|
+
...props,
|
|
2790
|
+
children: copied ? /* @__PURE__ */ jsx14(Check2, { className: "size-[18px]" }) : /* @__PURE__ */ jsx14(Copy, { className: "size-[18px]" })
|
|
2791
|
+
}
|
|
2792
|
+
);
|
|
2793
|
+
};
|
|
2794
|
+
CopilotChatAssistantMessage2.ThumbsUpButton = ({ title, ...props }) => {
|
|
2795
|
+
const config = useCopilotChatConfiguration();
|
|
2796
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
2797
|
+
return /* @__PURE__ */ jsx14(
|
|
2798
|
+
CopilotChatAssistantMessage2.ToolbarButton,
|
|
2799
|
+
{
|
|
2800
|
+
title: title || labels.assistantMessageToolbarThumbsUpLabel,
|
|
2801
|
+
...props,
|
|
2802
|
+
children: /* @__PURE__ */ jsx14(ThumbsUp, { className: "size-[18px]" })
|
|
2803
|
+
}
|
|
2804
|
+
);
|
|
2805
|
+
};
|
|
2806
|
+
CopilotChatAssistantMessage2.ThumbsDownButton = ({ title, ...props }) => {
|
|
2807
|
+
const config = useCopilotChatConfiguration();
|
|
2808
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
2809
|
+
return /* @__PURE__ */ jsx14(
|
|
2810
|
+
CopilotChatAssistantMessage2.ToolbarButton,
|
|
2811
|
+
{
|
|
2812
|
+
title: title || labels.assistantMessageToolbarThumbsDownLabel,
|
|
2813
|
+
...props,
|
|
2814
|
+
children: /* @__PURE__ */ jsx14(ThumbsDown, { className: "size-[18px]" })
|
|
2815
|
+
}
|
|
2816
|
+
);
|
|
2817
|
+
};
|
|
2818
|
+
CopilotChatAssistantMessage2.ReadAloudButton = ({ title, ...props }) => {
|
|
2819
|
+
const config = useCopilotChatConfiguration();
|
|
2820
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
2821
|
+
return /* @__PURE__ */ jsx14(
|
|
2822
|
+
CopilotChatAssistantMessage2.ToolbarButton,
|
|
2823
|
+
{
|
|
2824
|
+
title: title || labels.assistantMessageToolbarReadAloudLabel,
|
|
2825
|
+
...props,
|
|
2826
|
+
children: /* @__PURE__ */ jsx14(Volume2, { className: "size-[20px]" })
|
|
2827
|
+
}
|
|
2828
|
+
);
|
|
2829
|
+
};
|
|
2830
|
+
CopilotChatAssistantMessage2.RegenerateButton = ({ title, ...props }) => {
|
|
2831
|
+
const config = useCopilotChatConfiguration();
|
|
2832
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
2833
|
+
return /* @__PURE__ */ jsx14(
|
|
2834
|
+
CopilotChatAssistantMessage2.ToolbarButton,
|
|
2835
|
+
{
|
|
2836
|
+
title: title || labels.assistantMessageToolbarRegenerateLabel,
|
|
2837
|
+
...props,
|
|
2838
|
+
children: /* @__PURE__ */ jsx14(RefreshCw, { className: "size-[18px]" })
|
|
2839
|
+
}
|
|
2840
|
+
);
|
|
2841
|
+
};
|
|
2842
|
+
})(CopilotChatAssistantMessage || (CopilotChatAssistantMessage = {}));
|
|
2843
|
+
CopilotChatAssistantMessage.MarkdownRenderer.displayName = "CopilotChatAssistantMessage.MarkdownRenderer";
|
|
2844
|
+
CopilotChatAssistantMessage.Toolbar.displayName = "CopilotChatAssistantMessage.Toolbar";
|
|
2845
|
+
CopilotChatAssistantMessage.CopyButton.displayName = "CopilotChatAssistantMessage.CopyButton";
|
|
2846
|
+
CopilotChatAssistantMessage.ThumbsUpButton.displayName = "CopilotChatAssistantMessage.ThumbsUpButton";
|
|
2847
|
+
CopilotChatAssistantMessage.ThumbsDownButton.displayName = "CopilotChatAssistantMessage.ThumbsDownButton";
|
|
2848
|
+
CopilotChatAssistantMessage.ReadAloudButton.displayName = "CopilotChatAssistantMessage.ReadAloudButton";
|
|
2849
|
+
CopilotChatAssistantMessage.RegenerateButton.displayName = "CopilotChatAssistantMessage.RegenerateButton";
|
|
2850
|
+
var CopilotChatAssistantMessage_default = CopilotChatAssistantMessage;
|
|
2851
|
+
|
|
2852
|
+
// src/components/chat/CopilotChatUserMessage.tsx
|
|
2853
|
+
import { useMemo as useMemo9, useState as useState8 } from "react";
|
|
2854
|
+
import { Copy as Copy2, Check as Check3, Edit, ChevronLeft, ChevronRight } from "lucide-react";
|
|
2855
|
+
import { twMerge as twMerge5 } from "tailwind-merge";
|
|
2856
|
+
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2857
|
+
function flattenUserMessageContent(content) {
|
|
2858
|
+
if (!content) {
|
|
2859
|
+
return "";
|
|
2860
|
+
}
|
|
2861
|
+
if (typeof content === "string") {
|
|
2862
|
+
return content;
|
|
2863
|
+
}
|
|
2864
|
+
return content.map((part) => {
|
|
2865
|
+
if (part && typeof part === "object" && "type" in part && part.type === "text" && typeof part.text === "string") {
|
|
2866
|
+
return part.text;
|
|
2867
|
+
}
|
|
2868
|
+
return "";
|
|
2869
|
+
}).filter((text) => text.length > 0).join("\n");
|
|
2870
|
+
}
|
|
2871
|
+
function CopilotChatUserMessage({
|
|
2872
|
+
message,
|
|
2873
|
+
onEditMessage,
|
|
2874
|
+
branchIndex,
|
|
2875
|
+
numberOfBranches,
|
|
2876
|
+
onSwitchToBranch,
|
|
2877
|
+
additionalToolbarItems,
|
|
2878
|
+
messageRenderer,
|
|
2879
|
+
toolbar,
|
|
2880
|
+
copyButton,
|
|
2881
|
+
editButton,
|
|
2882
|
+
branchNavigation,
|
|
2883
|
+
children,
|
|
2884
|
+
className,
|
|
2885
|
+
...props
|
|
2886
|
+
}) {
|
|
2887
|
+
const flattenedContent = useMemo9(
|
|
2888
|
+
() => flattenUserMessageContent(message.content),
|
|
2889
|
+
[message.content]
|
|
2890
|
+
);
|
|
2891
|
+
const BoundMessageRenderer = renderSlot(
|
|
2892
|
+
messageRenderer,
|
|
2893
|
+
CopilotChatUserMessage.MessageRenderer,
|
|
2894
|
+
{
|
|
2895
|
+
content: flattenedContent
|
|
2896
|
+
}
|
|
2897
|
+
);
|
|
2898
|
+
const BoundCopyButton = renderSlot(
|
|
2899
|
+
copyButton,
|
|
2900
|
+
CopilotChatUserMessage.CopyButton,
|
|
2901
|
+
{
|
|
2902
|
+
onClick: async () => {
|
|
2903
|
+
if (flattenedContent) {
|
|
2904
|
+
try {
|
|
2905
|
+
await navigator.clipboard.writeText(flattenedContent);
|
|
2906
|
+
} catch (err) {
|
|
2907
|
+
console.error("Failed to copy message:", err);
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
);
|
|
2913
|
+
const BoundEditButton = renderSlot(
|
|
2914
|
+
editButton,
|
|
2915
|
+
CopilotChatUserMessage.EditButton,
|
|
2916
|
+
{
|
|
2917
|
+
onClick: () => onEditMessage?.({ message })
|
|
2918
|
+
}
|
|
2919
|
+
);
|
|
2920
|
+
const BoundBranchNavigation = renderSlot(
|
|
2921
|
+
branchNavigation,
|
|
2922
|
+
CopilotChatUserMessage.BranchNavigation,
|
|
2923
|
+
{
|
|
2924
|
+
currentBranch: branchIndex,
|
|
2925
|
+
numberOfBranches,
|
|
2926
|
+
onSwitchToBranch,
|
|
2927
|
+
message
|
|
2928
|
+
}
|
|
2929
|
+
);
|
|
2930
|
+
const showBranchNavigation = numberOfBranches && numberOfBranches > 1 && onSwitchToBranch;
|
|
2931
|
+
const BoundToolbar = renderSlot(toolbar, CopilotChatUserMessage.Toolbar, {
|
|
2932
|
+
children: /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1 justify-end", children: [
|
|
2933
|
+
additionalToolbarItems,
|
|
2934
|
+
BoundCopyButton,
|
|
2935
|
+
onEditMessage && BoundEditButton,
|
|
2936
|
+
showBranchNavigation && BoundBranchNavigation
|
|
2937
|
+
] })
|
|
2938
|
+
});
|
|
2939
|
+
if (children) {
|
|
2940
|
+
return /* @__PURE__ */ jsx15(Fragment4, { children: children({
|
|
2941
|
+
messageRenderer: BoundMessageRenderer,
|
|
2942
|
+
toolbar: BoundToolbar,
|
|
2943
|
+
copyButton: BoundCopyButton,
|
|
2944
|
+
editButton: BoundEditButton,
|
|
2945
|
+
branchNavigation: BoundBranchNavigation,
|
|
2946
|
+
message,
|
|
2947
|
+
branchIndex,
|
|
2948
|
+
numberOfBranches,
|
|
2949
|
+
additionalToolbarItems
|
|
2950
|
+
}) });
|
|
2951
|
+
}
|
|
2952
|
+
return /* @__PURE__ */ jsxs7(
|
|
2953
|
+
"div",
|
|
2954
|
+
{
|
|
2955
|
+
className: twMerge5("flex flex-col items-end group pt-10", className),
|
|
2956
|
+
"data-message-id": message.id,
|
|
2957
|
+
...props,
|
|
2958
|
+
children: [
|
|
2959
|
+
BoundMessageRenderer,
|
|
2960
|
+
BoundToolbar
|
|
2961
|
+
]
|
|
2962
|
+
}
|
|
2963
|
+
);
|
|
2964
|
+
}
|
|
2965
|
+
((CopilotChatUserMessage2) => {
|
|
2966
|
+
CopilotChatUserMessage2.Container = ({ children, className, ...props }) => /* @__PURE__ */ jsx15(
|
|
2967
|
+
"div",
|
|
2968
|
+
{
|
|
2969
|
+
className: twMerge5("flex flex-col items-end group", className),
|
|
2970
|
+
...props,
|
|
2971
|
+
children
|
|
2972
|
+
}
|
|
2973
|
+
);
|
|
2974
|
+
CopilotChatUserMessage2.MessageRenderer = ({ content, className }) => /* @__PURE__ */ jsx15(
|
|
2975
|
+
"div",
|
|
2976
|
+
{
|
|
2977
|
+
className: twMerge5(
|
|
2978
|
+
"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",
|
|
2979
|
+
className
|
|
2980
|
+
),
|
|
2981
|
+
children: content
|
|
2982
|
+
}
|
|
2983
|
+
);
|
|
2984
|
+
CopilotChatUserMessage2.Toolbar = ({
|
|
2985
|
+
className,
|
|
2986
|
+
...props
|
|
2987
|
+
}) => /* @__PURE__ */ jsx15(
|
|
2988
|
+
"div",
|
|
2989
|
+
{
|
|
2990
|
+
className: twMerge5(
|
|
2991
|
+
"w-full bg-transparent flex items-center justify-end -mr-[5px] mt-[4px] invisible group-hover:visible",
|
|
2992
|
+
className
|
|
2993
|
+
),
|
|
2994
|
+
...props
|
|
2995
|
+
}
|
|
2996
|
+
);
|
|
2997
|
+
CopilotChatUserMessage2.ToolbarButton = ({ title, children, className, ...props }) => {
|
|
2998
|
+
return /* @__PURE__ */ jsxs7(Tooltip, { children: [
|
|
2999
|
+
/* @__PURE__ */ jsx15(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx15(
|
|
3000
|
+
Button,
|
|
3001
|
+
{
|
|
3002
|
+
type: "button",
|
|
3003
|
+
variant: "assistantMessageToolbarButton",
|
|
3004
|
+
"aria-label": title,
|
|
3005
|
+
className: twMerge5(className),
|
|
3006
|
+
...props,
|
|
3007
|
+
children
|
|
3008
|
+
}
|
|
3009
|
+
) }),
|
|
3010
|
+
/* @__PURE__ */ jsx15(TooltipContent, { side: "bottom", children: /* @__PURE__ */ jsx15("p", { children: title }) })
|
|
3011
|
+
] });
|
|
3012
|
+
};
|
|
3013
|
+
CopilotChatUserMessage2.CopyButton = ({ className, title, onClick, ...props }) => {
|
|
3014
|
+
const config = useCopilotChatConfiguration();
|
|
3015
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
3016
|
+
const [copied, setCopied] = useState8(false);
|
|
3017
|
+
const handleClick = (event) => {
|
|
3018
|
+
setCopied(true);
|
|
3019
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
3020
|
+
if (onClick) {
|
|
3021
|
+
onClick(event);
|
|
3022
|
+
}
|
|
3023
|
+
};
|
|
3024
|
+
return /* @__PURE__ */ jsx15(
|
|
3025
|
+
CopilotChatUserMessage2.ToolbarButton,
|
|
3026
|
+
{
|
|
3027
|
+
title: title || labels.userMessageToolbarCopyMessageLabel,
|
|
3028
|
+
onClick: handleClick,
|
|
3029
|
+
className,
|
|
3030
|
+
...props,
|
|
3031
|
+
children: copied ? /* @__PURE__ */ jsx15(Check3, { className: "size-[18px]" }) : /* @__PURE__ */ jsx15(Copy2, { className: "size-[18px]" })
|
|
3032
|
+
}
|
|
3033
|
+
);
|
|
3034
|
+
};
|
|
3035
|
+
CopilotChatUserMessage2.EditButton = ({ className, title, ...props }) => {
|
|
3036
|
+
const config = useCopilotChatConfiguration();
|
|
3037
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
3038
|
+
return /* @__PURE__ */ jsx15(
|
|
3039
|
+
CopilotChatUserMessage2.ToolbarButton,
|
|
3040
|
+
{
|
|
3041
|
+
title: title || labels.userMessageToolbarEditMessageLabel,
|
|
3042
|
+
className,
|
|
3043
|
+
...props,
|
|
3044
|
+
children: /* @__PURE__ */ jsx15(Edit, { className: "size-[18px]" })
|
|
3045
|
+
}
|
|
3046
|
+
);
|
|
3047
|
+
};
|
|
3048
|
+
CopilotChatUserMessage2.BranchNavigation = ({
|
|
3049
|
+
className,
|
|
3050
|
+
currentBranch = 0,
|
|
3051
|
+
numberOfBranches = 1,
|
|
3052
|
+
onSwitchToBranch,
|
|
3053
|
+
message,
|
|
3054
|
+
...props
|
|
3055
|
+
}) => {
|
|
3056
|
+
if (!numberOfBranches || numberOfBranches <= 1 || !onSwitchToBranch) {
|
|
3057
|
+
return null;
|
|
3058
|
+
}
|
|
3059
|
+
const canGoPrev = currentBranch > 0;
|
|
3060
|
+
const canGoNext = currentBranch < numberOfBranches - 1;
|
|
3061
|
+
return /* @__PURE__ */ jsxs7("div", { className: twMerge5("flex items-center gap-1", className), ...props, children: [
|
|
3062
|
+
/* @__PURE__ */ jsx15(
|
|
3063
|
+
Button,
|
|
3064
|
+
{
|
|
3065
|
+
type: "button",
|
|
3066
|
+
variant: "assistantMessageToolbarButton",
|
|
3067
|
+
onClick: () => onSwitchToBranch?.({
|
|
3068
|
+
branchIndex: currentBranch - 1,
|
|
3069
|
+
numberOfBranches,
|
|
3070
|
+
message
|
|
3071
|
+
}),
|
|
3072
|
+
disabled: !canGoPrev,
|
|
3073
|
+
className: "h-6 w-6 p-0",
|
|
3074
|
+
children: /* @__PURE__ */ jsx15(ChevronLeft, { className: "size-[20px]" })
|
|
3075
|
+
}
|
|
3076
|
+
),
|
|
3077
|
+
/* @__PURE__ */ jsxs7("span", { className: "text-sm text-muted-foreground px-0 font-medium", children: [
|
|
3078
|
+
currentBranch + 1,
|
|
3079
|
+
"/",
|
|
3080
|
+
numberOfBranches
|
|
3081
|
+
] }),
|
|
3082
|
+
/* @__PURE__ */ jsx15(
|
|
3083
|
+
Button,
|
|
3084
|
+
{
|
|
3085
|
+
type: "button",
|
|
3086
|
+
variant: "assistantMessageToolbarButton",
|
|
3087
|
+
onClick: () => onSwitchToBranch?.({
|
|
3088
|
+
branchIndex: currentBranch + 1,
|
|
3089
|
+
numberOfBranches,
|
|
3090
|
+
message
|
|
3091
|
+
}),
|
|
3092
|
+
disabled: !canGoNext,
|
|
3093
|
+
className: "h-6 w-6 p-0",
|
|
3094
|
+
children: /* @__PURE__ */ jsx15(ChevronRight, { className: "size-[20px]" })
|
|
3095
|
+
}
|
|
3096
|
+
)
|
|
3097
|
+
] });
|
|
3098
|
+
};
|
|
3099
|
+
})(CopilotChatUserMessage || (CopilotChatUserMessage = {}));
|
|
3100
|
+
CopilotChatUserMessage.Container.displayName = "CopilotChatUserMessage.Container";
|
|
3101
|
+
CopilotChatUserMessage.MessageRenderer.displayName = "CopilotChatUserMessage.MessageRenderer";
|
|
3102
|
+
CopilotChatUserMessage.Toolbar.displayName = "CopilotChatUserMessage.Toolbar";
|
|
3103
|
+
CopilotChatUserMessage.ToolbarButton.displayName = "CopilotChatUserMessage.ToolbarButton";
|
|
3104
|
+
CopilotChatUserMessage.CopyButton.displayName = "CopilotChatUserMessage.CopyButton";
|
|
3105
|
+
CopilotChatUserMessage.EditButton.displayName = "CopilotChatUserMessage.EditButton";
|
|
3106
|
+
CopilotChatUserMessage.BranchNavigation.displayName = "CopilotChatUserMessage.BranchNavigation";
|
|
3107
|
+
var CopilotChatUserMessage_default = CopilotChatUserMessage;
|
|
3108
|
+
|
|
3109
|
+
// src/components/chat/CopilotChatSuggestionPill.tsx
|
|
3110
|
+
import React10 from "react";
|
|
3111
|
+
import { Loader2 } from "lucide-react";
|
|
3112
|
+
import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3113
|
+
var baseClasses = "group inline-flex h-7 sm:h-8 items-center gap-1 sm:gap-1.5 rounded-full border border-border/60 bg-background px-2.5 sm:px-3 text-[11px] sm:text-xs leading-none text-foreground transition-colors cursor-pointer hover:bg-accent/60 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:text-muted-foreground disabled:hover:bg-background disabled:hover:text-muted-foreground pointer-events-auto";
|
|
3114
|
+
var labelClasses = "whitespace-nowrap font-medium leading-none";
|
|
3115
|
+
var CopilotChatSuggestionPill = React10.forwardRef(function CopilotChatSuggestionPill2({ className, children, icon, isLoading, type, ...props }, ref) {
|
|
3116
|
+
const showIcon = !isLoading && icon;
|
|
3117
|
+
return /* @__PURE__ */ jsxs8(
|
|
3118
|
+
"button",
|
|
3119
|
+
{
|
|
3120
|
+
ref,
|
|
3121
|
+
"data-slot": "suggestion-pill",
|
|
3122
|
+
className: cn(baseClasses, className),
|
|
3123
|
+
type: type ?? "button",
|
|
3124
|
+
"aria-busy": isLoading || void 0,
|
|
3125
|
+
disabled: isLoading || props.disabled,
|
|
3126
|
+
...props,
|
|
3127
|
+
children: [
|
|
3128
|
+
isLoading ? /* @__PURE__ */ jsx16("span", { className: "flex h-3.5 sm:h-4 w-3.5 sm:w-4 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx16(Loader2, { className: "h-3.5 sm:h-4 w-3.5 sm:w-4 animate-spin", "aria-hidden": "true" }) }) : showIcon && /* @__PURE__ */ jsx16("span", { className: "flex h-3.5 sm:h-4 w-3.5 sm:w-4 items-center justify-center text-muted-foreground", children: icon }),
|
|
3129
|
+
/* @__PURE__ */ jsx16("span", { className: labelClasses, children })
|
|
3130
|
+
]
|
|
3131
|
+
}
|
|
3132
|
+
);
|
|
3133
|
+
});
|
|
3134
|
+
CopilotChatSuggestionPill.displayName = "CopilotChatSuggestionPill";
|
|
3135
|
+
var CopilotChatSuggestionPill_default = CopilotChatSuggestionPill;
|
|
3136
|
+
|
|
3137
|
+
// src/components/chat/CopilotChatSuggestionView.tsx
|
|
3138
|
+
import React11 from "react";
|
|
3139
|
+
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3140
|
+
var DefaultContainer = React11.forwardRef(function DefaultContainer2({ className, ...props }, ref) {
|
|
3141
|
+
return /* @__PURE__ */ jsx17(
|
|
3142
|
+
"div",
|
|
3143
|
+
{
|
|
3144
|
+
ref,
|
|
3145
|
+
className: cn(
|
|
3146
|
+
"flex flex-wrap items-center gap-1.5 sm:gap-2 pl-0 pr-4 sm:px-0 pointer-events-none",
|
|
3147
|
+
className
|
|
3148
|
+
),
|
|
3149
|
+
...props
|
|
3150
|
+
}
|
|
3151
|
+
);
|
|
3152
|
+
});
|
|
3153
|
+
var CopilotChatSuggestionView = React11.forwardRef(function CopilotChatSuggestionView2({
|
|
3154
|
+
suggestions,
|
|
3155
|
+
onSelectSuggestion,
|
|
3156
|
+
loadingIndexes,
|
|
3157
|
+
container,
|
|
3158
|
+
suggestion: suggestionSlot,
|
|
3159
|
+
className,
|
|
3160
|
+
children,
|
|
3161
|
+
...restProps
|
|
3162
|
+
}, ref) {
|
|
3163
|
+
const loadingSet = React11.useMemo(() => {
|
|
3164
|
+
if (!loadingIndexes || loadingIndexes.length === 0) {
|
|
3165
|
+
return /* @__PURE__ */ new Set();
|
|
3166
|
+
}
|
|
3167
|
+
return new Set(loadingIndexes);
|
|
3168
|
+
}, [loadingIndexes]);
|
|
3169
|
+
const ContainerElement = renderSlot(container, DefaultContainer, {
|
|
3170
|
+
ref,
|
|
3171
|
+
className,
|
|
3172
|
+
...restProps
|
|
3173
|
+
});
|
|
3174
|
+
const suggestionElements = suggestions.map((suggestion, index) => {
|
|
3175
|
+
const isLoading = loadingSet.has(index) || suggestion.isLoading === true;
|
|
3176
|
+
const pill = renderSlot(suggestionSlot, CopilotChatSuggestionPill_default, {
|
|
3177
|
+
children: suggestion.title,
|
|
3178
|
+
isLoading,
|
|
3179
|
+
type: "button",
|
|
3180
|
+
onClick: () => onSelectSuggestion?.(suggestion, index)
|
|
3181
|
+
});
|
|
3182
|
+
return React11.cloneElement(pill, {
|
|
3183
|
+
key: `${suggestion.title}-${index}`
|
|
3184
|
+
});
|
|
3185
|
+
});
|
|
3186
|
+
const boundContainer = React11.cloneElement(
|
|
3187
|
+
ContainerElement,
|
|
3188
|
+
void 0,
|
|
3189
|
+
suggestionElements
|
|
3190
|
+
);
|
|
3191
|
+
if (typeof children === "function") {
|
|
3192
|
+
const sampleSuggestion = renderSlot(suggestionSlot, CopilotChatSuggestionPill_default, {
|
|
3193
|
+
children: suggestions[0]?.title ?? "",
|
|
3194
|
+
isLoading: suggestions.length > 0 ? loadingSet.has(0) || suggestions[0]?.isLoading === true : false,
|
|
3195
|
+
type: "button"
|
|
3196
|
+
});
|
|
3197
|
+
return /* @__PURE__ */ jsx17(Fragment5, { children: children({
|
|
3198
|
+
container: boundContainer,
|
|
3199
|
+
suggestion: sampleSuggestion,
|
|
3200
|
+
suggestions,
|
|
3201
|
+
onSelectSuggestion,
|
|
3202
|
+
loadingIndexes,
|
|
3203
|
+
className,
|
|
3204
|
+
...restProps
|
|
3205
|
+
}) });
|
|
3206
|
+
}
|
|
3207
|
+
if (children) {
|
|
3208
|
+
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
3209
|
+
boundContainer,
|
|
3210
|
+
children
|
|
3211
|
+
] });
|
|
3212
|
+
}
|
|
3213
|
+
return boundContainer;
|
|
3214
|
+
});
|
|
3215
|
+
CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
|
|
3216
|
+
var CopilotChatSuggestionView_default = CopilotChatSuggestionView;
|
|
3217
|
+
|
|
3218
|
+
// src/components/chat/CopilotChatMessageView.tsx
|
|
3219
|
+
import React12, { useEffect as useEffect12, useReducer as useReducer3 } from "react";
|
|
3220
|
+
import { twMerge as twMerge6 } from "tailwind-merge";
|
|
3221
|
+
import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3222
|
+
var MemoizedAssistantMessage = React12.memo(
|
|
3223
|
+
function MemoizedAssistantMessage2({
|
|
3224
|
+
message,
|
|
3225
|
+
messages,
|
|
3226
|
+
isRunning,
|
|
3227
|
+
AssistantMessageComponent
|
|
3228
|
+
}) {
|
|
3229
|
+
return /* @__PURE__ */ jsx18(
|
|
3230
|
+
AssistantMessageComponent,
|
|
3231
|
+
{
|
|
3232
|
+
message,
|
|
3233
|
+
messages,
|
|
3234
|
+
isRunning
|
|
3235
|
+
}
|
|
3236
|
+
);
|
|
3237
|
+
},
|
|
3238
|
+
(prevProps, nextProps) => {
|
|
3239
|
+
if (prevProps.message.id !== nextProps.message.id) return false;
|
|
3240
|
+
if (prevProps.message.content !== nextProps.message.content) return false;
|
|
3241
|
+
const prevToolCalls = prevProps.message.toolCalls;
|
|
3242
|
+
const nextToolCalls = nextProps.message.toolCalls;
|
|
3243
|
+
if (prevToolCalls?.length !== nextToolCalls?.length) return false;
|
|
3244
|
+
if (prevToolCalls && nextToolCalls) {
|
|
3245
|
+
for (let i = 0; i < prevToolCalls.length; i++) {
|
|
3246
|
+
const prevTc = prevToolCalls[i];
|
|
3247
|
+
const nextTc = nextToolCalls[i];
|
|
3248
|
+
if (!prevTc || !nextTc) return false;
|
|
3249
|
+
if (prevTc.id !== nextTc.id) return false;
|
|
3250
|
+
if (prevTc.function.arguments !== nextTc.function.arguments) return false;
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
if (prevToolCalls && prevToolCalls.length > 0) {
|
|
3254
|
+
const toolCallIds = new Set(prevToolCalls.map((tc) => tc.id));
|
|
3255
|
+
const prevToolResults = prevProps.messages.filter(
|
|
3256
|
+
(m) => m.role === "tool" && toolCallIds.has(m.toolCallId)
|
|
3257
|
+
);
|
|
3258
|
+
const nextToolResults = nextProps.messages.filter(
|
|
3259
|
+
(m) => m.role === "tool" && toolCallIds.has(m.toolCallId)
|
|
3260
|
+
);
|
|
3261
|
+
if (prevToolResults.length !== nextToolResults.length) return false;
|
|
3262
|
+
for (let i = 0; i < prevToolResults.length; i++) {
|
|
3263
|
+
if (prevToolResults[i].content !== nextToolResults[i].content) return false;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
const nextIsLatest = nextProps.messages[nextProps.messages.length - 1]?.id === nextProps.message.id;
|
|
3267
|
+
if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning) return false;
|
|
3268
|
+
if (prevProps.AssistantMessageComponent !== nextProps.AssistantMessageComponent) return false;
|
|
3269
|
+
return true;
|
|
3270
|
+
}
|
|
3271
|
+
);
|
|
3272
|
+
var MemoizedUserMessage = React12.memo(
|
|
3273
|
+
function MemoizedUserMessage2({
|
|
3274
|
+
message,
|
|
3275
|
+
UserMessageComponent
|
|
3276
|
+
}) {
|
|
3277
|
+
return /* @__PURE__ */ jsx18(UserMessageComponent, { message });
|
|
3278
|
+
},
|
|
3279
|
+
(prevProps, nextProps) => {
|
|
3280
|
+
if (prevProps.message.id !== nextProps.message.id) return false;
|
|
3281
|
+
if (prevProps.message.content !== nextProps.message.content) return false;
|
|
3282
|
+
if (prevProps.UserMessageComponent !== nextProps.UserMessageComponent) return false;
|
|
3283
|
+
return true;
|
|
3284
|
+
}
|
|
3285
|
+
);
|
|
3286
|
+
var MemoizedActivityMessage = React12.memo(
|
|
3287
|
+
function MemoizedActivityMessage2({
|
|
3288
|
+
message,
|
|
3289
|
+
renderActivityMessage
|
|
3290
|
+
}) {
|
|
3291
|
+
return renderActivityMessage(message);
|
|
3292
|
+
},
|
|
3293
|
+
(prevProps, nextProps) => {
|
|
3294
|
+
if (prevProps.message.id !== nextProps.message.id) return false;
|
|
3295
|
+
if (prevProps.message.activityType !== nextProps.message.activityType) return false;
|
|
3296
|
+
if (JSON.stringify(prevProps.message.content) !== JSON.stringify(nextProps.message.content)) return false;
|
|
3297
|
+
return true;
|
|
3298
|
+
}
|
|
3299
|
+
);
|
|
3300
|
+
var MemoizedCustomMessage = React12.memo(
|
|
3301
|
+
function MemoizedCustomMessage2({
|
|
3302
|
+
message,
|
|
3303
|
+
position,
|
|
3304
|
+
renderCustomMessage
|
|
3305
|
+
}) {
|
|
3306
|
+
return renderCustomMessage({ message, position });
|
|
3307
|
+
},
|
|
3308
|
+
(prevProps, nextProps) => {
|
|
3309
|
+
if (prevProps.message.id !== nextProps.message.id) return false;
|
|
3310
|
+
if (prevProps.position !== nextProps.position) return false;
|
|
3311
|
+
if (prevProps.message.content !== nextProps.message.content) return false;
|
|
3312
|
+
if (prevProps.message.role !== nextProps.message.role) return false;
|
|
3313
|
+
if (JSON.stringify(prevProps.stateSnapshot) !== JSON.stringify(nextProps.stateSnapshot)) return false;
|
|
3314
|
+
return true;
|
|
3315
|
+
}
|
|
3316
|
+
);
|
|
3317
|
+
function CopilotChatMessageView({
|
|
3318
|
+
messages = [],
|
|
3319
|
+
assistantMessage,
|
|
3320
|
+
userMessage,
|
|
3321
|
+
cursor,
|
|
3322
|
+
isRunning = false,
|
|
3323
|
+
children,
|
|
3324
|
+
className,
|
|
3325
|
+
...props
|
|
3326
|
+
}) {
|
|
3327
|
+
const renderCustomMessage = useRenderCustomMessages();
|
|
3328
|
+
const renderActivityMessage = useRenderActivityMessage();
|
|
3329
|
+
const { copilotkit } = useCopilotKit();
|
|
3330
|
+
const config = useCopilotChatConfiguration();
|
|
3331
|
+
const [, forceUpdate] = useReducer3((x) => x + 1, 0);
|
|
3332
|
+
useEffect12(() => {
|
|
3333
|
+
if (!config?.agentId) return;
|
|
3334
|
+
const agent = copilotkit.getAgent(config.agentId);
|
|
3335
|
+
if (!agent) return;
|
|
3336
|
+
const subscription = agent.subscribe({
|
|
3337
|
+
onStateChanged: () => forceUpdate()
|
|
3338
|
+
});
|
|
3339
|
+
return () => subscription.unsubscribe();
|
|
3340
|
+
}, [config?.agentId, copilotkit]);
|
|
3341
|
+
const getStateSnapshotForMessage = (messageId) => {
|
|
3342
|
+
if (!config) return void 0;
|
|
3343
|
+
const runId = copilotkit.getRunIdForMessage(config.agentId, config.threadId, messageId);
|
|
3344
|
+
if (!runId) return void 0;
|
|
3345
|
+
return copilotkit.getStateByRun(config.agentId, config.threadId, runId);
|
|
3346
|
+
};
|
|
3347
|
+
const messageElements = messages.flatMap((message) => {
|
|
3348
|
+
const elements = [];
|
|
3349
|
+
const stateSnapshot = getStateSnapshotForMessage(message.id);
|
|
3350
|
+
if (renderCustomMessage) {
|
|
3351
|
+
elements.push(
|
|
3352
|
+
/* @__PURE__ */ jsx18(
|
|
3353
|
+
MemoizedCustomMessage,
|
|
3354
|
+
{
|
|
3355
|
+
message,
|
|
3356
|
+
position: "before",
|
|
3357
|
+
renderCustomMessage,
|
|
3358
|
+
stateSnapshot
|
|
3359
|
+
},
|
|
3360
|
+
`${message.id}-custom-before`
|
|
3361
|
+
)
|
|
3362
|
+
);
|
|
3363
|
+
}
|
|
3364
|
+
if (message.role === "assistant") {
|
|
3365
|
+
const AssistantComponent = typeof assistantMessage === "function" ? assistantMessage : CopilotChatAssistantMessage_default;
|
|
3366
|
+
elements.push(
|
|
3367
|
+
/* @__PURE__ */ jsx18(
|
|
3368
|
+
MemoizedAssistantMessage,
|
|
3369
|
+
{
|
|
3370
|
+
message,
|
|
3371
|
+
messages,
|
|
3372
|
+
isRunning,
|
|
3373
|
+
AssistantMessageComponent: AssistantComponent
|
|
3374
|
+
},
|
|
3375
|
+
message.id
|
|
3376
|
+
)
|
|
3377
|
+
);
|
|
3378
|
+
} else if (message.role === "user") {
|
|
3379
|
+
const UserComponent = typeof userMessage === "function" ? userMessage : CopilotChatUserMessage_default;
|
|
3380
|
+
elements.push(
|
|
3381
|
+
/* @__PURE__ */ jsx18(
|
|
3382
|
+
MemoizedUserMessage,
|
|
3383
|
+
{
|
|
3384
|
+
message,
|
|
3385
|
+
UserMessageComponent: UserComponent
|
|
3386
|
+
},
|
|
3387
|
+
message.id
|
|
3388
|
+
)
|
|
3389
|
+
);
|
|
3390
|
+
} else if (message.role === "activity") {
|
|
3391
|
+
elements.push(
|
|
3392
|
+
/* @__PURE__ */ jsx18(
|
|
3393
|
+
MemoizedActivityMessage,
|
|
3394
|
+
{
|
|
3395
|
+
message,
|
|
3396
|
+
renderActivityMessage
|
|
3397
|
+
},
|
|
3398
|
+
message.id
|
|
3399
|
+
)
|
|
3400
|
+
);
|
|
3401
|
+
}
|
|
3402
|
+
if (renderCustomMessage) {
|
|
3403
|
+
elements.push(
|
|
3404
|
+
/* @__PURE__ */ jsx18(
|
|
3405
|
+
MemoizedCustomMessage,
|
|
3406
|
+
{
|
|
3407
|
+
message,
|
|
3408
|
+
position: "after",
|
|
3409
|
+
renderCustomMessage,
|
|
3410
|
+
stateSnapshot
|
|
3411
|
+
},
|
|
3412
|
+
`${message.id}-custom-after`
|
|
3413
|
+
)
|
|
3414
|
+
);
|
|
3415
|
+
}
|
|
3416
|
+
return elements;
|
|
3417
|
+
}).filter(Boolean);
|
|
3418
|
+
if (children) {
|
|
3419
|
+
return children({ messageElements, messages, isRunning });
|
|
3420
|
+
}
|
|
3421
|
+
return /* @__PURE__ */ jsxs10("div", { className: twMerge6("flex flex-col", className), ...props, children: [
|
|
3422
|
+
messageElements,
|
|
3423
|
+
isRunning && renderSlot(cursor, CopilotChatMessageView.Cursor, {})
|
|
3424
|
+
] });
|
|
3425
|
+
}
|
|
3426
|
+
CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
|
|
3427
|
+
return /* @__PURE__ */ jsx18(
|
|
3428
|
+
"div",
|
|
3429
|
+
{
|
|
3430
|
+
className: twMerge6("w-[11px] h-[11px] rounded-full bg-foreground animate-pulse-cursor ml-1", className),
|
|
3431
|
+
...props
|
|
3432
|
+
}
|
|
3433
|
+
);
|
|
3434
|
+
};
|
|
3435
|
+
var CopilotChatMessageView_default = CopilotChatMessageView;
|
|
3436
|
+
|
|
3437
|
+
// src/components/chat/CopilotChatView.tsx
|
|
3438
|
+
import React13, { useRef as useRef7, useState as useState10, useEffect as useEffect14 } from "react";
|
|
3439
|
+
import { twMerge as twMerge7 } from "tailwind-merge";
|
|
3440
|
+
import { StickToBottom, useStickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
3441
|
+
import { ChevronDown } from "lucide-react";
|
|
3442
|
+
|
|
3443
|
+
// src/hooks/use-keyboard-height.tsx
|
|
3444
|
+
import { useState as useState9, useEffect as useEffect13 } from "react";
|
|
3445
|
+
function useKeyboardHeight() {
|
|
3446
|
+
const [keyboardState, setKeyboardState] = useState9({
|
|
3447
|
+
isKeyboardOpen: false,
|
|
3448
|
+
keyboardHeight: 0,
|
|
3449
|
+
availableHeight: typeof window !== "undefined" ? window.innerHeight : 0,
|
|
3450
|
+
viewportHeight: typeof window !== "undefined" ? window.innerHeight : 0
|
|
3451
|
+
});
|
|
3452
|
+
useEffect13(() => {
|
|
3453
|
+
if (typeof window === "undefined") {
|
|
3454
|
+
return;
|
|
3455
|
+
}
|
|
3456
|
+
const visualViewport = window.visualViewport;
|
|
3457
|
+
if (!visualViewport) {
|
|
3458
|
+
return;
|
|
3459
|
+
}
|
|
3460
|
+
const updateKeyboardState = () => {
|
|
3461
|
+
const layoutHeight = window.innerHeight;
|
|
3462
|
+
const visualHeight = visualViewport.height;
|
|
3463
|
+
const keyboardHeight = Math.max(0, layoutHeight - visualHeight);
|
|
3464
|
+
const isKeyboardOpen = keyboardHeight > 150;
|
|
3465
|
+
setKeyboardState({
|
|
3466
|
+
isKeyboardOpen,
|
|
3467
|
+
keyboardHeight,
|
|
3468
|
+
availableHeight: visualHeight,
|
|
3469
|
+
viewportHeight: layoutHeight
|
|
3470
|
+
});
|
|
3471
|
+
};
|
|
3472
|
+
updateKeyboardState();
|
|
3473
|
+
visualViewport.addEventListener("resize", updateKeyboardState);
|
|
3474
|
+
visualViewport.addEventListener("scroll", updateKeyboardState);
|
|
3475
|
+
return () => {
|
|
3476
|
+
visualViewport.removeEventListener("resize", updateKeyboardState);
|
|
3477
|
+
visualViewport.removeEventListener("scroll", updateKeyboardState);
|
|
3478
|
+
};
|
|
3479
|
+
}, []);
|
|
3480
|
+
return keyboardState;
|
|
3481
|
+
}
|
|
3482
|
+
|
|
3483
|
+
// src/components/chat/CopilotChatView.tsx
|
|
3484
|
+
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3485
|
+
function CopilotChatView({
|
|
3486
|
+
messageView,
|
|
3487
|
+
input,
|
|
3488
|
+
scrollView,
|
|
3489
|
+
scrollToBottomButton,
|
|
3490
|
+
feather,
|
|
3491
|
+
inputContainer,
|
|
3492
|
+
disclaimer,
|
|
3493
|
+
suggestionView,
|
|
3494
|
+
messages = [],
|
|
3495
|
+
autoScroll = true,
|
|
3496
|
+
inputProps,
|
|
3497
|
+
isRunning = false,
|
|
3498
|
+
suggestions,
|
|
3499
|
+
suggestionLoadingIndexes,
|
|
3500
|
+
onSelectSuggestion,
|
|
3501
|
+
children,
|
|
3502
|
+
className,
|
|
3503
|
+
...props
|
|
3504
|
+
}) {
|
|
3505
|
+
const inputContainerRef = useRef7(null);
|
|
3506
|
+
const [inputContainerHeight, setInputContainerHeight] = useState10(0);
|
|
3507
|
+
const [isResizing, setIsResizing] = useState10(false);
|
|
3508
|
+
const resizeTimeoutRef = useRef7(null);
|
|
3509
|
+
const { isKeyboardOpen, keyboardHeight, availableHeight } = useKeyboardHeight();
|
|
3510
|
+
useEffect14(() => {
|
|
3511
|
+
const element = inputContainerRef.current;
|
|
3512
|
+
if (!element) return;
|
|
3513
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
3514
|
+
for (const entry of entries) {
|
|
3515
|
+
const newHeight = entry.contentRect.height;
|
|
3516
|
+
setInputContainerHeight((prevHeight) => {
|
|
3517
|
+
if (newHeight !== prevHeight) {
|
|
3518
|
+
setIsResizing(true);
|
|
3519
|
+
if (resizeTimeoutRef.current) {
|
|
3520
|
+
clearTimeout(resizeTimeoutRef.current);
|
|
3521
|
+
}
|
|
3522
|
+
resizeTimeoutRef.current = setTimeout(() => {
|
|
3523
|
+
setIsResizing(false);
|
|
3524
|
+
}, 250);
|
|
3525
|
+
return newHeight;
|
|
3526
|
+
}
|
|
3527
|
+
return prevHeight;
|
|
3528
|
+
});
|
|
3529
|
+
}
|
|
3530
|
+
});
|
|
3531
|
+
resizeObserver.observe(element);
|
|
3532
|
+
setInputContainerHeight(element.offsetHeight);
|
|
3533
|
+
return () => {
|
|
3534
|
+
resizeObserver.disconnect();
|
|
3535
|
+
if (resizeTimeoutRef.current) {
|
|
3536
|
+
clearTimeout(resizeTimeoutRef.current);
|
|
3537
|
+
}
|
|
3538
|
+
};
|
|
3539
|
+
}, []);
|
|
3540
|
+
const BoundMessageView = renderSlot(messageView, CopilotChatMessageView_default, {
|
|
3541
|
+
messages,
|
|
3542
|
+
isRunning
|
|
3543
|
+
});
|
|
3544
|
+
const BoundInput = renderSlot(input, CopilotChatInput_default, inputProps ?? {});
|
|
3545
|
+
const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;
|
|
3546
|
+
const BoundSuggestionView = hasSuggestions ? renderSlot(suggestionView, CopilotChatSuggestionView_default, {
|
|
3547
|
+
suggestions,
|
|
3548
|
+
loadingIndexes: suggestionLoadingIndexes,
|
|
3549
|
+
onSelectSuggestion,
|
|
3550
|
+
className: "mb-3 lg:ml-4 lg:mr-4 ml-0 mr-0"
|
|
3551
|
+
}) : null;
|
|
3552
|
+
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
3553
|
+
const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {
|
|
3554
|
+
autoScroll,
|
|
3555
|
+
scrollToBottomButton,
|
|
3556
|
+
inputContainerHeight,
|
|
3557
|
+
isResizing,
|
|
3558
|
+
children: /* @__PURE__ */ jsx19("div", { style: { paddingBottom: `${inputContainerHeight + (hasSuggestions ? 4 : 32)}px` }, children: /* @__PURE__ */ jsxs11("div", { className: "max-w-3xl mx-auto", children: [
|
|
3559
|
+
BoundMessageView,
|
|
3560
|
+
hasSuggestions ? /* @__PURE__ */ jsx19("div", { className: "pl-0 pr-4 sm:px-0 mt-4", children: BoundSuggestionView }) : null
|
|
3561
|
+
] }) })
|
|
3562
|
+
});
|
|
3563
|
+
const BoundScrollToBottomButton = renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, {});
|
|
3564
|
+
const BoundDisclaimer = renderSlot(disclaimer, CopilotChatView.Disclaimer, {});
|
|
3565
|
+
const BoundInputContainer = renderSlot(inputContainer, CopilotChatView.InputContainer, {
|
|
3566
|
+
ref: inputContainerRef,
|
|
3567
|
+
keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,
|
|
3568
|
+
children: /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
3569
|
+
/* @__PURE__ */ jsx19("div", { className: "max-w-3xl mx-auto py-0 px-4 sm:px-0 [div[data-sidebar-chat]_&]:px-8 [div[data-popup-chat]_&]:px-6 pointer-events-auto", children: BoundInput }),
|
|
3570
|
+
BoundDisclaimer
|
|
3571
|
+
] })
|
|
3572
|
+
});
|
|
3573
|
+
if (children) {
|
|
3574
|
+
return children({
|
|
3575
|
+
messageView: BoundMessageView,
|
|
3576
|
+
input: BoundInput,
|
|
3577
|
+
scrollView: BoundScrollView,
|
|
3578
|
+
scrollToBottomButton: BoundScrollToBottomButton,
|
|
3579
|
+
feather: BoundFeather,
|
|
3580
|
+
inputContainer: BoundInputContainer,
|
|
3581
|
+
disclaimer: BoundDisclaimer,
|
|
3582
|
+
suggestionView: BoundSuggestionView ?? /* @__PURE__ */ jsx19(Fragment6, {})
|
|
3583
|
+
});
|
|
3584
|
+
}
|
|
3585
|
+
return /* @__PURE__ */ jsxs11("div", { className: twMerge7("relative h-full", className), ...props, children: [
|
|
3586
|
+
BoundScrollView,
|
|
3587
|
+
BoundFeather,
|
|
3588
|
+
BoundInputContainer
|
|
3589
|
+
] });
|
|
3590
|
+
}
|
|
3591
|
+
((CopilotChatView2) => {
|
|
3592
|
+
const ScrollContent = ({ children, scrollToBottomButton, inputContainerHeight, isResizing }) => {
|
|
3593
|
+
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
|
|
3594
|
+
return /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
3595
|
+
/* @__PURE__ */ jsx19(StickToBottom.Content, { className: "overflow-y-scroll overflow-x-hidden", children: /* @__PURE__ */ jsx19("div", { className: "px-4 sm:px-0 [div[data-sidebar-chat]_&]:px-8 [div[data-popup-chat]_&]:px-6", children }) }),
|
|
3596
|
+
!isAtBottom && !isResizing && /* @__PURE__ */ jsx19(
|
|
3597
|
+
"div",
|
|
3598
|
+
{
|
|
3599
|
+
className: "absolute inset-x-0 flex justify-center z-10 pointer-events-none",
|
|
3600
|
+
style: {
|
|
3601
|
+
bottom: `${inputContainerHeight + 16}px`
|
|
3602
|
+
},
|
|
3603
|
+
children: renderSlot(scrollToBottomButton, CopilotChatView2.ScrollToBottomButton, {
|
|
3604
|
+
onClick: () => scrollToBottom()
|
|
3605
|
+
})
|
|
3606
|
+
}
|
|
3607
|
+
)
|
|
3608
|
+
] });
|
|
3609
|
+
};
|
|
3610
|
+
CopilotChatView2.ScrollView = ({
|
|
3611
|
+
children,
|
|
3612
|
+
autoScroll = true,
|
|
3613
|
+
scrollToBottomButton,
|
|
3614
|
+
inputContainerHeight = 0,
|
|
3615
|
+
isResizing = false,
|
|
3616
|
+
className,
|
|
3617
|
+
...props
|
|
3618
|
+
}) => {
|
|
3619
|
+
const [hasMounted, setHasMounted] = useState10(false);
|
|
3620
|
+
const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();
|
|
3621
|
+
const [showScrollButton, setShowScrollButton] = useState10(false);
|
|
3622
|
+
useEffect14(() => {
|
|
3623
|
+
setHasMounted(true);
|
|
3624
|
+
}, []);
|
|
3625
|
+
useEffect14(() => {
|
|
3626
|
+
if (autoScroll) return;
|
|
3627
|
+
const scrollElement = scrollRef.current;
|
|
3628
|
+
if (!scrollElement) return;
|
|
3629
|
+
const checkScroll = () => {
|
|
3630
|
+
const atBottom = scrollElement.scrollHeight - scrollElement.scrollTop - scrollElement.clientHeight < 10;
|
|
3631
|
+
setShowScrollButton(!atBottom);
|
|
3632
|
+
};
|
|
3633
|
+
checkScroll();
|
|
3634
|
+
scrollElement.addEventListener("scroll", checkScroll);
|
|
3635
|
+
const resizeObserver = new ResizeObserver(checkScroll);
|
|
3636
|
+
resizeObserver.observe(scrollElement);
|
|
3637
|
+
return () => {
|
|
3638
|
+
scrollElement.removeEventListener("scroll", checkScroll);
|
|
3639
|
+
resizeObserver.disconnect();
|
|
3640
|
+
};
|
|
3641
|
+
}, [scrollRef, autoScroll]);
|
|
3642
|
+
if (!hasMounted) {
|
|
3643
|
+
return /* @__PURE__ */ jsx19("div", { className: "h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden", children: /* @__PURE__ */ jsx19("div", { className: "px-4 sm:px-0 [div[data-sidebar-chat]_&]:px-8 [div[data-popup-chat]_&]:px-6", children }) });
|
|
3644
|
+
}
|
|
3645
|
+
if (!autoScroll) {
|
|
3646
|
+
return /* @__PURE__ */ jsxs11(
|
|
3647
|
+
"div",
|
|
3648
|
+
{
|
|
3649
|
+
ref: scrollRef,
|
|
3650
|
+
className: cn(
|
|
3651
|
+
"h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden relative",
|
|
3652
|
+
className
|
|
3653
|
+
),
|
|
3654
|
+
...props,
|
|
3655
|
+
children: [
|
|
3656
|
+
/* @__PURE__ */ jsx19("div", { ref: contentRef, className: "px-4 sm:px-0 [div[data-sidebar-chat]_&]:px-8 [div[data-popup-chat]_&]:px-6", children }),
|
|
3657
|
+
showScrollButton && !isResizing && /* @__PURE__ */ jsx19(
|
|
3658
|
+
"div",
|
|
3659
|
+
{
|
|
3660
|
+
className: "absolute inset-x-0 flex justify-center z-10 pointer-events-none",
|
|
3661
|
+
style: {
|
|
3662
|
+
bottom: `${inputContainerHeight + 16}px`
|
|
3663
|
+
},
|
|
3664
|
+
children: renderSlot(scrollToBottomButton, CopilotChatView2.ScrollToBottomButton, {
|
|
3665
|
+
onClick: () => scrollToBottom()
|
|
3666
|
+
})
|
|
3667
|
+
}
|
|
3668
|
+
)
|
|
3669
|
+
]
|
|
3670
|
+
}
|
|
3671
|
+
);
|
|
3672
|
+
}
|
|
3673
|
+
return /* @__PURE__ */ jsx19(
|
|
3674
|
+
StickToBottom,
|
|
3675
|
+
{
|
|
3676
|
+
className: cn("h-full max-h-full flex flex-col min-h-0 relative", className),
|
|
3677
|
+
resize: "smooth",
|
|
3678
|
+
initial: "smooth",
|
|
3679
|
+
...props,
|
|
3680
|
+
children: /* @__PURE__ */ jsx19(
|
|
3681
|
+
ScrollContent,
|
|
3682
|
+
{
|
|
3683
|
+
scrollToBottomButton,
|
|
3684
|
+
inputContainerHeight,
|
|
3685
|
+
isResizing,
|
|
3686
|
+
children
|
|
3687
|
+
}
|
|
3688
|
+
)
|
|
3689
|
+
}
|
|
3690
|
+
);
|
|
3691
|
+
};
|
|
3692
|
+
CopilotChatView2.ScrollToBottomButton = ({
|
|
3693
|
+
className,
|
|
3694
|
+
...props
|
|
3695
|
+
}) => /* @__PURE__ */ jsx19(
|
|
3696
|
+
Button,
|
|
3697
|
+
{
|
|
3698
|
+
variant: "outline",
|
|
3699
|
+
size: "sm",
|
|
3700
|
+
className: twMerge7(
|
|
3701
|
+
"rounded-full w-10 h-10 p-0 pointer-events-auto",
|
|
3702
|
+
"bg-white dark:bg-gray-900",
|
|
3703
|
+
"shadow-lg border border-gray-200 dark:border-gray-700",
|
|
3704
|
+
"hover:bg-gray-50 dark:hover:bg-gray-800",
|
|
3705
|
+
"flex items-center justify-center cursor-pointer",
|
|
3706
|
+
className
|
|
3707
|
+
),
|
|
3708
|
+
...props,
|
|
3709
|
+
children: /* @__PURE__ */ jsx19(ChevronDown, { className: "w-4 h-4 text-gray-600 dark:text-white" })
|
|
3710
|
+
}
|
|
3711
|
+
);
|
|
3712
|
+
CopilotChatView2.Feather = ({ className, style, ...props }) => /* @__PURE__ */ jsx19(
|
|
3713
|
+
"div",
|
|
3714
|
+
{
|
|
3715
|
+
className: cn(
|
|
3716
|
+
"absolute bottom-0 left-0 right-4 h-24 pointer-events-none z-10 bg-gradient-to-t",
|
|
3717
|
+
"from-white via-white to-transparent",
|
|
3718
|
+
"dark:from-[rgb(33,33,33)] dark:via-[rgb(33,33,33)]",
|
|
3719
|
+
className
|
|
3720
|
+
),
|
|
3721
|
+
style,
|
|
3722
|
+
...props
|
|
3723
|
+
}
|
|
3724
|
+
);
|
|
3725
|
+
CopilotChatView2.InputContainer = React13.forwardRef(({ children, className, keyboardHeight = 0, ...props }, ref) => /* @__PURE__ */ jsx19(
|
|
3726
|
+
"div",
|
|
3727
|
+
{
|
|
3728
|
+
ref,
|
|
3729
|
+
className: cn("absolute bottom-0 left-0 right-0 z-20 pointer-events-none", className),
|
|
3730
|
+
style: {
|
|
3731
|
+
// Adjust position when keyboard is open to keep input visible
|
|
3732
|
+
transform: keyboardHeight > 0 ? `translateY(-${keyboardHeight}px)` : void 0,
|
|
3733
|
+
transition: "transform 0.2s ease-out"
|
|
3734
|
+
},
|
|
3735
|
+
...props,
|
|
3736
|
+
children
|
|
3737
|
+
}
|
|
3738
|
+
));
|
|
3739
|
+
CopilotChatView2.InputContainer.displayName = "CopilotChatView.InputContainer";
|
|
3740
|
+
CopilotChatView2.Disclaimer = ({ className, ...props }) => {
|
|
3741
|
+
const config = useCopilotChatConfiguration();
|
|
3742
|
+
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
3743
|
+
return /* @__PURE__ */ jsx19(
|
|
3744
|
+
"div",
|
|
3745
|
+
{
|
|
3746
|
+
className: cn("text-center text-xs text-muted-foreground py-3 px-4 max-w-3xl mx-auto", className),
|
|
3747
|
+
...props,
|
|
3748
|
+
children: labels.chatDisclaimerText
|
|
3749
|
+
}
|
|
3750
|
+
);
|
|
3751
|
+
};
|
|
3752
|
+
})(CopilotChatView || (CopilotChatView = {}));
|
|
3753
|
+
var CopilotChatView_default = CopilotChatView;
|
|
3754
|
+
|
|
3755
|
+
// src/components/chat/CopilotChat.tsx
|
|
3756
|
+
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID7, randomUUID as randomUUID2 } from "@copilotkitnext/shared";
|
|
3757
|
+
import { useCallback as useCallback8, useEffect as useEffect15, useMemo as useMemo10 } from "react";
|
|
3758
|
+
import { merge } from "ts-deepmerge";
|
|
3759
|
+
import { AGUIConnectNotImplementedError } from "@ag-ui/client";
|
|
3760
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
3761
|
+
function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen, ...props }) {
|
|
3762
|
+
const existingConfig = useCopilotChatConfiguration();
|
|
3763
|
+
const resolvedAgentId = agentId ?? existingConfig?.agentId ?? DEFAULT_AGENT_ID7;
|
|
3764
|
+
const resolvedThreadId = useMemo10(
|
|
3765
|
+
() => threadId ?? existingConfig?.threadId ?? randomUUID2(),
|
|
3766
|
+
[threadId, existingConfig?.threadId]
|
|
3767
|
+
);
|
|
3768
|
+
const { agent } = useAgent({ agentId: resolvedAgentId });
|
|
3769
|
+
const { copilotkit } = useCopilotKit();
|
|
3770
|
+
const { suggestions: autoSuggestions } = useSuggestions({ agentId: resolvedAgentId });
|
|
3771
|
+
const {
|
|
3772
|
+
inputProps: providedInputProps,
|
|
3773
|
+
messageView: providedMessageView,
|
|
3774
|
+
suggestionView: providedSuggestionView,
|
|
3775
|
+
...restProps
|
|
3776
|
+
} = props;
|
|
3777
|
+
useEffect15(() => {
|
|
3778
|
+
const connect = async (agent2) => {
|
|
3779
|
+
try {
|
|
3780
|
+
await copilotkit.connectAgent({ agent: agent2 });
|
|
3781
|
+
} catch (error) {
|
|
3782
|
+
if (error instanceof AGUIConnectNotImplementedError) {
|
|
3783
|
+
} else {
|
|
3784
|
+
throw error;
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
};
|
|
3788
|
+
agent.threadId = resolvedThreadId;
|
|
3789
|
+
connect(agent);
|
|
3790
|
+
return () => {
|
|
3791
|
+
};
|
|
3792
|
+
}, [resolvedThreadId, agent, copilotkit, resolvedAgentId]);
|
|
3793
|
+
const onSubmitInput = useCallback8(
|
|
3794
|
+
async (value) => {
|
|
3795
|
+
agent.addMessage({
|
|
3796
|
+
id: randomUUID2(),
|
|
3797
|
+
role: "user",
|
|
3798
|
+
content: value
|
|
3799
|
+
});
|
|
3800
|
+
try {
|
|
3801
|
+
await copilotkit.runAgent({ agent });
|
|
3802
|
+
} catch (error) {
|
|
3803
|
+
console.error("CopilotChat: runAgent failed", error);
|
|
3804
|
+
}
|
|
3805
|
+
},
|
|
3806
|
+
[agent, copilotkit]
|
|
3807
|
+
);
|
|
3808
|
+
const handleSelectSuggestion = useCallback8(
|
|
3809
|
+
async (suggestion) => {
|
|
3810
|
+
agent.addMessage({
|
|
3811
|
+
id: randomUUID2(),
|
|
3812
|
+
role: "user",
|
|
3813
|
+
content: suggestion.message
|
|
3814
|
+
});
|
|
3815
|
+
try {
|
|
3816
|
+
await copilotkit.runAgent({ agent });
|
|
3817
|
+
} catch (error) {
|
|
3818
|
+
console.error("CopilotChat: runAgent failed after selecting suggestion", error);
|
|
3819
|
+
}
|
|
3820
|
+
},
|
|
3821
|
+
[agent, copilotkit]
|
|
3822
|
+
);
|
|
3823
|
+
const stopCurrentRun = useCallback8(() => {
|
|
3824
|
+
try {
|
|
3825
|
+
copilotkit.stopAgent({ agent });
|
|
3826
|
+
} catch (error) {
|
|
3827
|
+
console.error("CopilotChat: stopAgent failed", error);
|
|
3828
|
+
try {
|
|
3829
|
+
agent.abortRun();
|
|
3830
|
+
} catch (abortError) {
|
|
3831
|
+
console.error("CopilotChat: abortRun fallback failed", abortError);
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
}, [agent, copilotkit]);
|
|
3835
|
+
const mergedProps = merge(
|
|
3836
|
+
{
|
|
3837
|
+
isRunning: agent.isRunning,
|
|
3838
|
+
suggestions: autoSuggestions,
|
|
3839
|
+
onSelectSuggestion: handleSelectSuggestion,
|
|
3840
|
+
suggestionView: providedSuggestionView
|
|
3841
|
+
},
|
|
3842
|
+
{
|
|
3843
|
+
...restProps,
|
|
3844
|
+
...typeof providedMessageView === "string" ? { messageView: { className: providedMessageView } } : providedMessageView !== void 0 ? { messageView: providedMessageView } : {}
|
|
3845
|
+
}
|
|
3846
|
+
);
|
|
3847
|
+
const providedStopHandler = providedInputProps?.onStop;
|
|
3848
|
+
const hasMessages = agent.messages.length > 0;
|
|
3849
|
+
const shouldAllowStop = agent.isRunning && hasMessages;
|
|
3850
|
+
const effectiveStopHandler = shouldAllowStop ? providedStopHandler ?? stopCurrentRun : providedStopHandler;
|
|
3851
|
+
const finalInputProps = {
|
|
3852
|
+
...providedInputProps,
|
|
3853
|
+
onSubmitMessage: onSubmitInput,
|
|
3854
|
+
onStop: effectiveStopHandler,
|
|
3855
|
+
isRunning: agent.isRunning
|
|
3856
|
+
};
|
|
3857
|
+
finalInputProps.mode = agent.isRunning ? "processing" : finalInputProps.mode ?? "input";
|
|
3858
|
+
const finalProps = merge(mergedProps, {
|
|
3859
|
+
messages: agent.messages,
|
|
3860
|
+
inputProps: finalInputProps
|
|
3861
|
+
});
|
|
3862
|
+
const RenderedChatView = renderSlot(chatView, CopilotChatView, finalProps);
|
|
3863
|
+
return /* @__PURE__ */ jsx20(
|
|
3864
|
+
CopilotChatConfigurationProvider,
|
|
3865
|
+
{
|
|
3866
|
+
agentId: resolvedAgentId,
|
|
3867
|
+
threadId: resolvedThreadId,
|
|
3868
|
+
labels,
|
|
3869
|
+
isModalDefaultOpen,
|
|
3870
|
+
children: RenderedChatView
|
|
3871
|
+
}
|
|
3872
|
+
);
|
|
3873
|
+
}
|
|
3874
|
+
((CopilotChat2) => {
|
|
3875
|
+
CopilotChat2.View = CopilotChatView;
|
|
3876
|
+
})(CopilotChat || (CopilotChat = {}));
|
|
3877
|
+
|
|
3878
|
+
// src/components/chat/CopilotChatToggleButton.tsx
|
|
3879
|
+
import React14, { useState as useState11 } from "react";
|
|
3880
|
+
import { MessageCircle, X as X2 } from "lucide-react";
|
|
3881
|
+
import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3882
|
+
var DefaultOpenIcon = ({
|
|
3883
|
+
className,
|
|
3884
|
+
...props
|
|
3885
|
+
}) => /* @__PURE__ */ jsx21(MessageCircle, { className: cn("h-6 w-6", className), strokeWidth: 1.75, fill: "currentColor", ...props });
|
|
3886
|
+
var DefaultCloseIcon = ({
|
|
3887
|
+
className,
|
|
3888
|
+
...props
|
|
3889
|
+
}) => /* @__PURE__ */ jsx21(X2, { className: cn("h-6 w-6", className), strokeWidth: 1.75, ...props });
|
|
3890
|
+
DefaultOpenIcon.displayName = "CopilotChatToggleButton.OpenIcon";
|
|
3891
|
+
DefaultCloseIcon.displayName = "CopilotChatToggleButton.CloseIcon";
|
|
3892
|
+
var ICON_TRANSITION_STYLE = Object.freeze({
|
|
3893
|
+
transition: "opacity 120ms ease-out, transform 260ms cubic-bezier(0.22, 1, 0.36, 1)"
|
|
3894
|
+
});
|
|
3895
|
+
var ICON_WRAPPER_BASE = "pointer-events-none absolute inset-0 flex items-center justify-center will-change-transform";
|
|
3896
|
+
var BUTTON_BASE_CLASSES = cn(
|
|
3897
|
+
"fixed bottom-6 right-6 z-[1100] flex h-14 w-14 items-center justify-center",
|
|
3898
|
+
"rounded-full border border-primary bg-primary text-primary-foreground",
|
|
3899
|
+
"shadow-sm transition-all duration-200 ease-out",
|
|
3900
|
+
"hover:scale-[1.04] hover:shadow-md",
|
|
3901
|
+
"cursor-pointer",
|
|
3902
|
+
"active:scale-[0.96]",
|
|
3903
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
3904
|
+
"disabled:pointer-events-none disabled:opacity-60"
|
|
3905
|
+
);
|
|
3906
|
+
var CopilotChatToggleButton = React14.forwardRef(function CopilotChatToggleButton2({ openIcon, closeIcon, className, ...buttonProps }, ref) {
|
|
3907
|
+
const { onClick, type, disabled, ...restProps } = buttonProps;
|
|
3908
|
+
const configuration = useCopilotChatConfiguration();
|
|
3909
|
+
const labels = configuration?.labels ?? CopilotChatDefaultLabels;
|
|
3910
|
+
const [fallbackOpen, setFallbackOpen] = useState11(false);
|
|
3911
|
+
const isOpen = configuration?.isModalOpen ?? fallbackOpen;
|
|
3912
|
+
const setModalOpen = configuration?.setModalOpen ?? setFallbackOpen;
|
|
3913
|
+
const handleClick = (event) => {
|
|
3914
|
+
if (disabled) {
|
|
3915
|
+
return;
|
|
3916
|
+
}
|
|
3917
|
+
if (onClick) {
|
|
3918
|
+
onClick(event);
|
|
3919
|
+
}
|
|
3920
|
+
if (event.defaultPrevented) {
|
|
3921
|
+
return;
|
|
3922
|
+
}
|
|
3923
|
+
const nextOpen = !isOpen;
|
|
3924
|
+
setModalOpen(nextOpen);
|
|
3925
|
+
};
|
|
3926
|
+
const renderedOpenIcon = renderSlot(
|
|
3927
|
+
openIcon,
|
|
3928
|
+
DefaultOpenIcon,
|
|
3929
|
+
{
|
|
3930
|
+
className: "h-6 w-6",
|
|
3931
|
+
"aria-hidden": true,
|
|
3932
|
+
focusable: false
|
|
3933
|
+
}
|
|
3934
|
+
);
|
|
3935
|
+
const renderedCloseIcon = renderSlot(
|
|
3936
|
+
closeIcon,
|
|
3937
|
+
DefaultCloseIcon,
|
|
3938
|
+
{
|
|
3939
|
+
className: "h-6 w-6",
|
|
3940
|
+
"aria-hidden": true,
|
|
3941
|
+
focusable: false
|
|
3942
|
+
}
|
|
3943
|
+
);
|
|
3944
|
+
const openIconElement = /* @__PURE__ */ jsx21(
|
|
3945
|
+
"span",
|
|
3946
|
+
{
|
|
3947
|
+
"aria-hidden": "true",
|
|
3948
|
+
"data-slot": "chat-toggle-button-open-icon",
|
|
3949
|
+
className: ICON_WRAPPER_BASE,
|
|
3950
|
+
style: {
|
|
3951
|
+
...ICON_TRANSITION_STYLE,
|
|
3952
|
+
opacity: isOpen ? 0 : 1,
|
|
3953
|
+
transform: `scale(${isOpen ? 0.75 : 1}) rotate(${isOpen ? 90 : 0}deg)`
|
|
3954
|
+
},
|
|
3955
|
+
children: renderedOpenIcon
|
|
3956
|
+
}
|
|
3957
|
+
);
|
|
3958
|
+
const closeIconElement = /* @__PURE__ */ jsx21(
|
|
3959
|
+
"span",
|
|
3960
|
+
{
|
|
3961
|
+
"aria-hidden": "true",
|
|
3962
|
+
"data-slot": "chat-toggle-button-close-icon",
|
|
3963
|
+
className: ICON_WRAPPER_BASE,
|
|
3964
|
+
style: {
|
|
3965
|
+
...ICON_TRANSITION_STYLE,
|
|
3966
|
+
opacity: isOpen ? 1 : 0,
|
|
3967
|
+
transform: `scale(${isOpen ? 1 : 0.75}) rotate(${isOpen ? 0 : -90}deg)`
|
|
3968
|
+
},
|
|
3969
|
+
children: renderedCloseIcon
|
|
3970
|
+
}
|
|
3971
|
+
);
|
|
3972
|
+
return /* @__PURE__ */ jsxs12(
|
|
3973
|
+
"button",
|
|
3974
|
+
{
|
|
3975
|
+
ref,
|
|
3976
|
+
type: type ?? "button",
|
|
3977
|
+
"data-slot": "chat-toggle-button",
|
|
3978
|
+
"data-state": isOpen ? "open" : "closed",
|
|
3979
|
+
className: cn(BUTTON_BASE_CLASSES, className),
|
|
3980
|
+
"aria-label": isOpen ? labels.chatToggleCloseLabel : labels.chatToggleOpenLabel,
|
|
3981
|
+
"aria-pressed": isOpen,
|
|
3982
|
+
disabled,
|
|
3983
|
+
onClick: handleClick,
|
|
3984
|
+
...restProps,
|
|
3985
|
+
children: [
|
|
3986
|
+
openIconElement,
|
|
3987
|
+
closeIconElement
|
|
3988
|
+
]
|
|
3989
|
+
}
|
|
3990
|
+
);
|
|
3991
|
+
});
|
|
3992
|
+
CopilotChatToggleButton.displayName = "CopilotChatToggleButton";
|
|
3993
|
+
var CopilotChatToggleButton_default = CopilotChatToggleButton;
|
|
3994
|
+
|
|
3995
|
+
// src/components/chat/CopilotSidebarView.tsx
|
|
3996
|
+
import { useEffect as useEffect16, useRef as useRef8, useState as useState12 } from "react";
|
|
3997
|
+
|
|
3998
|
+
// src/components/chat/CopilotModalHeader.tsx
|
|
3999
|
+
import { useCallback as useCallback9 } from "react";
|
|
4000
|
+
import { X as X3 } from "lucide-react";
|
|
4001
|
+
import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
4002
|
+
function CopilotModalHeader({
|
|
4003
|
+
title,
|
|
4004
|
+
titleContent,
|
|
4005
|
+
closeButton,
|
|
4006
|
+
children,
|
|
4007
|
+
className,
|
|
4008
|
+
...rest
|
|
4009
|
+
}) {
|
|
4010
|
+
const configuration = useCopilotChatConfiguration();
|
|
4011
|
+
const fallbackTitle = configuration?.labels.modalHeaderTitle ?? CopilotChatDefaultLabels.modalHeaderTitle;
|
|
4012
|
+
const resolvedTitle = title ?? fallbackTitle;
|
|
4013
|
+
const handleClose = useCallback9(() => {
|
|
4014
|
+
configuration?.setModalOpen(false);
|
|
4015
|
+
}, [configuration]);
|
|
4016
|
+
const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, {
|
|
4017
|
+
children: resolvedTitle
|
|
4018
|
+
});
|
|
4019
|
+
const BoundCloseButton = renderSlot(closeButton, CopilotModalHeader.CloseButton, {
|
|
4020
|
+
onClick: handleClose
|
|
4021
|
+
});
|
|
4022
|
+
if (children) {
|
|
4023
|
+
return children({
|
|
4024
|
+
titleContent: BoundTitle,
|
|
4025
|
+
closeButton: BoundCloseButton,
|
|
4026
|
+
title: resolvedTitle,
|
|
4027
|
+
...rest
|
|
4028
|
+
});
|
|
4029
|
+
}
|
|
4030
|
+
return /* @__PURE__ */ jsx22(
|
|
4031
|
+
"header",
|
|
4032
|
+
{
|
|
4033
|
+
"data-slot": "copilot-modal-header",
|
|
4034
|
+
className: cn(
|
|
4035
|
+
"flex items-center justify-between border-b border-border px-4 py-4",
|
|
4036
|
+
"bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80",
|
|
4037
|
+
className
|
|
4038
|
+
),
|
|
4039
|
+
...rest,
|
|
4040
|
+
children: /* @__PURE__ */ jsxs13("div", { className: "flex w-full items-center gap-2", children: [
|
|
4041
|
+
/* @__PURE__ */ jsx22("div", { className: "flex-1", "aria-hidden": "true" }),
|
|
4042
|
+
/* @__PURE__ */ jsx22("div", { className: "flex flex-1 justify-center text-center", children: BoundTitle }),
|
|
4043
|
+
/* @__PURE__ */ jsx22("div", { className: "flex flex-1 justify-end", children: BoundCloseButton })
|
|
4044
|
+
] })
|
|
4045
|
+
}
|
|
4046
|
+
);
|
|
4047
|
+
}
|
|
4048
|
+
CopilotModalHeader.displayName = "CopilotModalHeader";
|
|
4049
|
+
((CopilotModalHeader2) => {
|
|
4050
|
+
CopilotModalHeader2.Title = ({ children, className, ...props }) => /* @__PURE__ */ jsx22(
|
|
4051
|
+
"div",
|
|
4052
|
+
{
|
|
4053
|
+
className: cn(
|
|
4054
|
+
"w-full text-base font-medium leading-none tracking-tight text-foreground",
|
|
4055
|
+
className
|
|
4056
|
+
),
|
|
4057
|
+
...props,
|
|
4058
|
+
children
|
|
4059
|
+
}
|
|
4060
|
+
);
|
|
4061
|
+
CopilotModalHeader2.CloseButton = ({
|
|
4062
|
+
className,
|
|
4063
|
+
...props
|
|
4064
|
+
}) => /* @__PURE__ */ jsx22(
|
|
4065
|
+
"button",
|
|
4066
|
+
{
|
|
4067
|
+
type: "button",
|
|
4068
|
+
className: cn(
|
|
4069
|
+
"inline-flex size-8 items-center justify-center rounded-full text-muted-foreground transition cursor-pointer",
|
|
4070
|
+
"hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
4071
|
+
className
|
|
4072
|
+
),
|
|
4073
|
+
"aria-label": "Close",
|
|
4074
|
+
...props,
|
|
4075
|
+
children: /* @__PURE__ */ jsx22(X3, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
4076
|
+
}
|
|
4077
|
+
);
|
|
4078
|
+
})(CopilotModalHeader || (CopilotModalHeader = {}));
|
|
4079
|
+
CopilotModalHeader.Title.displayName = "CopilotModalHeader.Title";
|
|
4080
|
+
CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
|
|
4081
|
+
|
|
4082
|
+
// src/components/chat/CopilotSidebarView.tsx
|
|
4083
|
+
import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4084
|
+
var DEFAULT_SIDEBAR_WIDTH = 480;
|
|
4085
|
+
var SIDEBAR_TRANSITION_MS = 260;
|
|
4086
|
+
function CopilotSidebarView({ header, width, ...props }) {
|
|
4087
|
+
const configuration = useCopilotChatConfiguration();
|
|
4088
|
+
const isSidebarOpen = configuration?.isModalOpen ?? false;
|
|
4089
|
+
const sidebarRef = useRef8(null);
|
|
4090
|
+
const [sidebarWidth, setSidebarWidth] = useState12(width ?? DEFAULT_SIDEBAR_WIDTH);
|
|
4091
|
+
const widthToCss = (w) => {
|
|
4092
|
+
return typeof w === "number" ? `${w}px` : w;
|
|
4093
|
+
};
|
|
4094
|
+
const widthToMargin = (w) => {
|
|
4095
|
+
if (typeof w === "number") {
|
|
4096
|
+
return `${w}px`;
|
|
4097
|
+
}
|
|
4098
|
+
return w;
|
|
4099
|
+
};
|
|
4100
|
+
useEffect16(() => {
|
|
4101
|
+
if (width !== void 0) {
|
|
4102
|
+
return;
|
|
4103
|
+
}
|
|
4104
|
+
if (typeof window === "undefined") {
|
|
4105
|
+
return;
|
|
4106
|
+
}
|
|
4107
|
+
const element = sidebarRef.current;
|
|
4108
|
+
if (!element) {
|
|
4109
|
+
return;
|
|
4110
|
+
}
|
|
4111
|
+
const updateWidth = () => {
|
|
4112
|
+
const rect = element.getBoundingClientRect();
|
|
4113
|
+
if (rect.width > 0) {
|
|
4114
|
+
setSidebarWidth(rect.width);
|
|
4115
|
+
}
|
|
4116
|
+
};
|
|
4117
|
+
updateWidth();
|
|
4118
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
4119
|
+
const observer = new ResizeObserver(() => updateWidth());
|
|
4120
|
+
observer.observe(element);
|
|
4121
|
+
return () => observer.disconnect();
|
|
4122
|
+
}
|
|
4123
|
+
window.addEventListener("resize", updateWidth);
|
|
4124
|
+
return () => window.removeEventListener("resize", updateWidth);
|
|
4125
|
+
}, [width]);
|
|
4126
|
+
const headerElement = renderSlot(header, CopilotModalHeader, {});
|
|
4127
|
+
return /* @__PURE__ */ jsxs14(Fragment7, { children: [
|
|
4128
|
+
isSidebarOpen && /* @__PURE__ */ jsx23(
|
|
4129
|
+
"style",
|
|
4130
|
+
{
|
|
4131
|
+
dangerouslySetInnerHTML: {
|
|
4132
|
+
__html: `
|
|
4133
|
+
@media (min-width: 768px) {
|
|
4134
|
+
body {
|
|
4135
|
+
margin-inline-end: ${widthToMargin(sidebarWidth)};
|
|
4136
|
+
transition: margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease;
|
|
4137
|
+
}
|
|
4138
|
+
}`
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
),
|
|
4142
|
+
/* @__PURE__ */ jsx23(CopilotChatToggleButton_default, {}),
|
|
4143
|
+
/* @__PURE__ */ jsx23(
|
|
4144
|
+
"aside",
|
|
4145
|
+
{
|
|
4146
|
+
ref: sidebarRef,
|
|
4147
|
+
"data-copilot-sidebar": true,
|
|
4148
|
+
className: cn(
|
|
4149
|
+
"fixed right-0 top-0 z-[1200] flex",
|
|
4150
|
+
// Height with dvh fallback and safe area support
|
|
4151
|
+
"h-[100vh] h-[100dvh] max-h-screen",
|
|
4152
|
+
// Responsive width: full on mobile, custom on desktop
|
|
4153
|
+
"w-full",
|
|
4154
|
+
"border-l border-border bg-background text-foreground shadow-xl",
|
|
4155
|
+
"transition-transform duration-300 ease-out",
|
|
4156
|
+
isSidebarOpen ? "translate-x-0" : "translate-x-full pointer-events-none"
|
|
4157
|
+
),
|
|
4158
|
+
style: {
|
|
4159
|
+
// Use CSS custom property for responsive width
|
|
4160
|
+
["--sidebar-width"]: widthToCss(sidebarWidth),
|
|
4161
|
+
// Safe area insets for iOS
|
|
4162
|
+
paddingTop: "env(safe-area-inset-top)",
|
|
4163
|
+
paddingBottom: "env(safe-area-inset-bottom)"
|
|
4164
|
+
},
|
|
4165
|
+
"aria-hidden": !isSidebarOpen,
|
|
4166
|
+
"aria-label": "Copilot chat sidebar",
|
|
4167
|
+
role: "complementary",
|
|
4168
|
+
children: /* @__PURE__ */ jsxs14("div", { className: "flex h-full w-full flex-col overflow-hidden", children: [
|
|
4169
|
+
headerElement,
|
|
4170
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 overflow-hidden", "data-sidebar-chat": true, children: /* @__PURE__ */ jsx23(CopilotChatView_default, { ...props }) })
|
|
4171
|
+
] })
|
|
4172
|
+
}
|
|
4173
|
+
)
|
|
4174
|
+
] });
|
|
4175
|
+
}
|
|
4176
|
+
CopilotSidebarView.displayName = "CopilotSidebarView";
|
|
4177
|
+
|
|
4178
|
+
// src/components/chat/CopilotPopupView.tsx
|
|
4179
|
+
import { useEffect as useEffect17, useMemo as useMemo11, useRef as useRef9, useState as useState13 } from "react";
|
|
4180
|
+
import { Fragment as Fragment8, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4181
|
+
var DEFAULT_POPUP_WIDTH = 420;
|
|
4182
|
+
var DEFAULT_POPUP_HEIGHT = 560;
|
|
4183
|
+
var dimensionToCss = (value, fallback) => {
|
|
4184
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
4185
|
+
return `${value}px`;
|
|
4186
|
+
}
|
|
4187
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
4188
|
+
return value;
|
|
4189
|
+
}
|
|
4190
|
+
return `${fallback}px`;
|
|
4191
|
+
};
|
|
4192
|
+
function CopilotPopupView({
|
|
4193
|
+
header,
|
|
4194
|
+
width,
|
|
4195
|
+
height,
|
|
4196
|
+
clickOutsideToClose,
|
|
4197
|
+
className,
|
|
4198
|
+
...restProps
|
|
4199
|
+
}) {
|
|
4200
|
+
const configuration = useCopilotChatConfiguration();
|
|
4201
|
+
const isPopupOpen = configuration?.isModalOpen ?? false;
|
|
4202
|
+
const setModalOpen = configuration?.setModalOpen;
|
|
4203
|
+
const labels = configuration?.labels ?? CopilotChatDefaultLabels;
|
|
4204
|
+
const containerRef = useRef9(null);
|
|
4205
|
+
const [isRendered, setIsRendered] = useState13(isPopupOpen);
|
|
4206
|
+
const [isAnimatingOut, setIsAnimatingOut] = useState13(false);
|
|
4207
|
+
useEffect17(() => {
|
|
4208
|
+
if (isPopupOpen) {
|
|
4209
|
+
setIsRendered(true);
|
|
4210
|
+
setIsAnimatingOut(false);
|
|
4211
|
+
return;
|
|
4212
|
+
}
|
|
4213
|
+
if (!isRendered) {
|
|
4214
|
+
return;
|
|
4215
|
+
}
|
|
4216
|
+
setIsAnimatingOut(true);
|
|
4217
|
+
const timeout = setTimeout(() => {
|
|
4218
|
+
setIsRendered(false);
|
|
4219
|
+
setIsAnimatingOut(false);
|
|
4220
|
+
}, 200);
|
|
4221
|
+
return () => clearTimeout(timeout);
|
|
4222
|
+
}, [isPopupOpen, isRendered]);
|
|
4223
|
+
useEffect17(() => {
|
|
4224
|
+
if (!isPopupOpen) {
|
|
4225
|
+
return;
|
|
4226
|
+
}
|
|
4227
|
+
if (typeof window === "undefined") {
|
|
4228
|
+
return;
|
|
4229
|
+
}
|
|
4230
|
+
const handleKeyDown = (event) => {
|
|
4231
|
+
if (event.key === "Escape") {
|
|
4232
|
+
event.preventDefault();
|
|
4233
|
+
setModalOpen?.(false);
|
|
4234
|
+
}
|
|
4235
|
+
};
|
|
4236
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4237
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4238
|
+
}, [isPopupOpen, setModalOpen]);
|
|
4239
|
+
useEffect17(() => {
|
|
4240
|
+
if (!isPopupOpen) {
|
|
4241
|
+
return;
|
|
4242
|
+
}
|
|
4243
|
+
const focusTimer = setTimeout(() => {
|
|
4244
|
+
containerRef.current?.focus({ preventScroll: true });
|
|
4245
|
+
}, 200);
|
|
4246
|
+
return () => clearTimeout(focusTimer);
|
|
4247
|
+
}, [isPopupOpen]);
|
|
4248
|
+
useEffect17(() => {
|
|
4249
|
+
if (!isPopupOpen || !clickOutsideToClose) {
|
|
4250
|
+
return;
|
|
4251
|
+
}
|
|
4252
|
+
if (typeof document === "undefined") {
|
|
4253
|
+
return;
|
|
4254
|
+
}
|
|
4255
|
+
const handlePointerDown = (event) => {
|
|
4256
|
+
const target = event.target;
|
|
4257
|
+
if (!target) {
|
|
4258
|
+
return;
|
|
4259
|
+
}
|
|
4260
|
+
const container = containerRef.current;
|
|
4261
|
+
if (container?.contains(target)) {
|
|
4262
|
+
return;
|
|
4263
|
+
}
|
|
4264
|
+
const toggleButton = document.querySelector("[data-slot='chat-toggle-button']");
|
|
4265
|
+
if (toggleButton && toggleButton.contains(target)) {
|
|
4266
|
+
return;
|
|
4267
|
+
}
|
|
4268
|
+
setModalOpen?.(false);
|
|
4269
|
+
};
|
|
4270
|
+
document.addEventListener("pointerdown", handlePointerDown);
|
|
4271
|
+
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
4272
|
+
}, [isPopupOpen, clickOutsideToClose, setModalOpen]);
|
|
4273
|
+
const headerElement = useMemo11(() => renderSlot(header, CopilotModalHeader, {}), [header]);
|
|
4274
|
+
const resolvedWidth = dimensionToCss(width, DEFAULT_POPUP_WIDTH);
|
|
4275
|
+
const resolvedHeight = dimensionToCss(height, DEFAULT_POPUP_HEIGHT);
|
|
4276
|
+
const popupStyle = useMemo11(
|
|
4277
|
+
() => ({
|
|
4278
|
+
"--copilot-popup-width": resolvedWidth,
|
|
4279
|
+
"--copilot-popup-height": resolvedHeight,
|
|
4280
|
+
"--copilot-popup-max-width": "calc(100vw - 3rem)",
|
|
4281
|
+
"--copilot-popup-max-height": "calc(100dvh - 7.5rem)",
|
|
4282
|
+
paddingTop: "env(safe-area-inset-top)",
|
|
4283
|
+
paddingBottom: "env(safe-area-inset-bottom)",
|
|
4284
|
+
paddingLeft: "env(safe-area-inset-left)",
|
|
4285
|
+
paddingRight: "env(safe-area-inset-right)"
|
|
4286
|
+
}),
|
|
4287
|
+
[resolvedHeight, resolvedWidth]
|
|
4288
|
+
);
|
|
4289
|
+
const popupAnimationClass = isPopupOpen && !isAnimatingOut ? "pointer-events-auto translate-y-0 opacity-100 md:scale-100" : "pointer-events-none translate-y-4 opacity-0 md:translate-y-5 md:scale-[0.95]";
|
|
4290
|
+
const popupContent = isRendered ? /* @__PURE__ */ jsx24(
|
|
4291
|
+
"div",
|
|
4292
|
+
{
|
|
4293
|
+
className: cn(
|
|
4294
|
+
"fixed inset-0 z-[1200] flex max-w-full flex-col items-stretch",
|
|
4295
|
+
"md:inset-auto md:bottom-24 md:right-6 md:items-end md:gap-4"
|
|
4296
|
+
),
|
|
4297
|
+
children: /* @__PURE__ */ jsxs15(
|
|
4298
|
+
"div",
|
|
4299
|
+
{
|
|
4300
|
+
ref: containerRef,
|
|
4301
|
+
tabIndex: -1,
|
|
4302
|
+
role: "dialog",
|
|
4303
|
+
"aria-label": labels.modalHeaderTitle,
|
|
4304
|
+
"data-copilot-popup": true,
|
|
4305
|
+
className: cn(
|
|
4306
|
+
"relative flex h-full w-full flex-col overflow-hidden bg-background text-foreground",
|
|
4307
|
+
"origin-bottom focus:outline-none transform-gpu transition-transform transition-opacity duration-200 ease-out",
|
|
4308
|
+
"md:transition-transform md:transition-opacity",
|
|
4309
|
+
"rounded-none border border-border/0 shadow-none ring-0",
|
|
4310
|
+
"md:h-[var(--copilot-popup-height)] md:w-[var(--copilot-popup-width)]",
|
|
4311
|
+
"md:max-h-[var(--copilot-popup-max-height)] md:max-w-[var(--copilot-popup-max-width)]",
|
|
4312
|
+
"md:origin-bottom-right md:rounded-2xl md:border-border md:shadow-xl md:ring-1 md:ring-border/40",
|
|
4313
|
+
popupAnimationClass
|
|
4314
|
+
),
|
|
4315
|
+
style: popupStyle,
|
|
4316
|
+
children: [
|
|
4317
|
+
headerElement,
|
|
4318
|
+
/* @__PURE__ */ jsx24("div", { className: "flex-1 overflow-hidden", "data-popup-chat": true, children: /* @__PURE__ */ jsx24(
|
|
4319
|
+
CopilotChatView_default,
|
|
4320
|
+
{
|
|
4321
|
+
...restProps,
|
|
4322
|
+
className: cn("h-full min-h-0", className)
|
|
4323
|
+
}
|
|
4324
|
+
) })
|
|
4325
|
+
]
|
|
4326
|
+
}
|
|
4327
|
+
)
|
|
4328
|
+
}
|
|
4329
|
+
) : null;
|
|
4330
|
+
return /* @__PURE__ */ jsxs15(Fragment8, { children: [
|
|
4331
|
+
/* @__PURE__ */ jsx24(CopilotChatToggleButton_default, {}),
|
|
4332
|
+
popupContent
|
|
4333
|
+
] });
|
|
4334
|
+
}
|
|
4335
|
+
CopilotPopupView.displayName = "CopilotPopupView";
|
|
4336
|
+
|
|
4337
|
+
// src/components/chat/CopilotSidebar.tsx
|
|
4338
|
+
import { useMemo as useMemo12 } from "react";
|
|
4339
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
4340
|
+
function CopilotSidebar({ header, defaultOpen, width, ...chatProps }) {
|
|
4341
|
+
const SidebarViewOverride = useMemo12(() => {
|
|
4342
|
+
const Component = (viewProps) => {
|
|
4343
|
+
const { header: viewHeader, width: viewWidth, ...restProps } = viewProps;
|
|
4344
|
+
return /* @__PURE__ */ jsx25(
|
|
4345
|
+
CopilotSidebarView,
|
|
4346
|
+
{
|
|
4347
|
+
...restProps,
|
|
4348
|
+
header: header ?? viewHeader,
|
|
4349
|
+
width: width ?? viewWidth
|
|
4350
|
+
}
|
|
4351
|
+
);
|
|
4352
|
+
};
|
|
4353
|
+
return Object.assign(Component, CopilotChatView_default);
|
|
4354
|
+
}, [header, width]);
|
|
4355
|
+
return /* @__PURE__ */ jsx25(
|
|
4356
|
+
CopilotChat,
|
|
4357
|
+
{
|
|
4358
|
+
...chatProps,
|
|
4359
|
+
chatView: SidebarViewOverride,
|
|
4360
|
+
isModalDefaultOpen: defaultOpen
|
|
4361
|
+
}
|
|
4362
|
+
);
|
|
4363
|
+
}
|
|
4364
|
+
CopilotSidebar.displayName = "CopilotSidebar";
|
|
4365
|
+
|
|
4366
|
+
// src/components/chat/CopilotPopup.tsx
|
|
4367
|
+
import { useMemo as useMemo13 } from "react";
|
|
4368
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
4369
|
+
function CopilotPopup({
|
|
4370
|
+
header,
|
|
4371
|
+
defaultOpen,
|
|
4372
|
+
width,
|
|
4373
|
+
height,
|
|
4374
|
+
clickOutsideToClose,
|
|
4375
|
+
...chatProps
|
|
4376
|
+
}) {
|
|
4377
|
+
const PopupViewOverride = useMemo13(() => {
|
|
4378
|
+
const Component = (viewProps) => {
|
|
4379
|
+
const {
|
|
4380
|
+
header: viewHeader,
|
|
4381
|
+
width: viewWidth,
|
|
4382
|
+
height: viewHeight,
|
|
4383
|
+
clickOutsideToClose: viewClickOutsideToClose,
|
|
4384
|
+
...restProps
|
|
4385
|
+
} = viewProps;
|
|
4386
|
+
return /* @__PURE__ */ jsx26(
|
|
4387
|
+
CopilotPopupView,
|
|
4388
|
+
{
|
|
4389
|
+
...restProps,
|
|
4390
|
+
header: header ?? viewHeader,
|
|
4391
|
+
width: width ?? viewWidth,
|
|
4392
|
+
height: height ?? viewHeight,
|
|
4393
|
+
clickOutsideToClose: clickOutsideToClose ?? viewClickOutsideToClose
|
|
4394
|
+
}
|
|
4395
|
+
);
|
|
4396
|
+
};
|
|
4397
|
+
return Object.assign(Component, CopilotChatView_default);
|
|
4398
|
+
}, [clickOutsideToClose, header, height, width]);
|
|
4399
|
+
return /* @__PURE__ */ jsx26(
|
|
4400
|
+
CopilotChat,
|
|
4401
|
+
{
|
|
4402
|
+
...chatProps,
|
|
4403
|
+
chatView: PopupViewOverride,
|
|
4404
|
+
isModalDefaultOpen: defaultOpen
|
|
4405
|
+
}
|
|
4406
|
+
);
|
|
4407
|
+
}
|
|
4408
|
+
CopilotPopup.displayName = "CopilotPopup";
|
|
4409
|
+
|
|
4410
|
+
// src/types/defineToolCallRenderer.ts
|
|
4411
|
+
import { z as z3 } from "zod";
|
|
4412
|
+
function defineToolCallRenderer(def) {
|
|
4413
|
+
const argsSchema = def.name === "*" && !def.args ? z3.any() : def.args;
|
|
4414
|
+
return {
|
|
4415
|
+
name: def.name,
|
|
4416
|
+
args: argsSchema,
|
|
4417
|
+
render: def.render,
|
|
4418
|
+
...def.agentId ? { agentId: def.agentId } : {}
|
|
4419
|
+
};
|
|
4420
|
+
}
|
|
4421
|
+
|
|
4422
|
+
// src/components/WildcardToolCallRender.tsx
|
|
4423
|
+
import { useState as useState14 } from "react";
|
|
4424
|
+
import { jsx as jsx27, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4425
|
+
var WildcardToolCallRender = defineToolCallRenderer({
|
|
4426
|
+
name: "*",
|
|
4427
|
+
render: ({ args, result, name, status }) => {
|
|
4428
|
+
const [isExpanded, setIsExpanded] = useState14(false);
|
|
4429
|
+
const statusString = String(status);
|
|
4430
|
+
const isActive = statusString === "inProgress" || statusString === "executing";
|
|
4431
|
+
const isComplete = statusString === "complete";
|
|
4432
|
+
const statusStyles = isActive ? "bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-400" : isComplete ? "bg-emerald-100 text-emerald-800 dark:bg-emerald-500/15 dark:text-emerald-400" : "bg-zinc-100 text-zinc-800 dark:bg-zinc-700/40 dark:text-zinc-300";
|
|
4433
|
+
return /* @__PURE__ */ jsx27("div", { className: "mt-2 pb-2", children: /* @__PURE__ */ jsxs16("div", { className: "rounded-xl border border-zinc-200/60 dark:border-zinc-800/60 bg-white/70 dark:bg-zinc-900/50 shadow-sm backdrop-blur p-4", children: [
|
|
4434
|
+
/* @__PURE__ */ jsxs16(
|
|
4435
|
+
"div",
|
|
4436
|
+
{
|
|
4437
|
+
className: "flex items-center justify-between gap-3 cursor-pointer",
|
|
4438
|
+
onClick: () => setIsExpanded(!isExpanded),
|
|
4439
|
+
children: [
|
|
4440
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
4441
|
+
/* @__PURE__ */ jsx27(
|
|
4442
|
+
"svg",
|
|
4443
|
+
{
|
|
4444
|
+
className: `h-4 w-4 text-zinc-500 dark:text-zinc-400 transition-transform ${isExpanded ? "rotate-90" : ""}`,
|
|
4445
|
+
fill: "none",
|
|
4446
|
+
viewBox: "0 0 24 24",
|
|
4447
|
+
strokeWidth: 2,
|
|
4448
|
+
stroke: "currentColor",
|
|
4449
|
+
children: /* @__PURE__ */ jsx27(
|
|
4450
|
+
"path",
|
|
4451
|
+
{
|
|
4452
|
+
strokeLinecap: "round",
|
|
4453
|
+
strokeLinejoin: "round",
|
|
4454
|
+
d: "M8.25 4.5l7.5 7.5-7.5 7.5"
|
|
4455
|
+
}
|
|
4456
|
+
)
|
|
4457
|
+
}
|
|
4458
|
+
),
|
|
4459
|
+
/* @__PURE__ */ jsx27("span", { className: "inline-block h-2 w-2 rounded-full bg-blue-500" }),
|
|
4460
|
+
/* @__PURE__ */ jsx27("span", { className: "truncate text-sm font-medium text-zinc-900 dark:text-zinc-100", children: name })
|
|
4461
|
+
] }),
|
|
4462
|
+
/* @__PURE__ */ jsx27(
|
|
4463
|
+
"span",
|
|
4464
|
+
{
|
|
4465
|
+
className: `inline-flex items-center rounded-full px-2 py-1 text-xs font-medium ${statusStyles}`,
|
|
4466
|
+
children: String(status)
|
|
4467
|
+
}
|
|
4468
|
+
)
|
|
4469
|
+
]
|
|
4470
|
+
}
|
|
4471
|
+
),
|
|
4472
|
+
isExpanded && /* @__PURE__ */ jsxs16("div", { className: "mt-3 grid gap-4", children: [
|
|
4473
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
4474
|
+
/* @__PURE__ */ jsx27("div", { className: "text-xs uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "Arguments" }),
|
|
4475
|
+
/* @__PURE__ */ jsx27("pre", { className: "mt-2 max-h-64 overflow-auto rounded-md bg-zinc-50 dark:bg-zinc-800/60 p-3 text-xs leading-relaxed text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words", children: JSON.stringify(args ?? {}, null, 2) })
|
|
4476
|
+
] }),
|
|
4477
|
+
result !== void 0 && /* @__PURE__ */ jsxs16("div", { children: [
|
|
4478
|
+
/* @__PURE__ */ jsx27("div", { className: "text-xs uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "Result" }),
|
|
4479
|
+
/* @__PURE__ */ jsx27("pre", { className: "mt-2 max-h-64 overflow-auto rounded-md bg-zinc-50 dark:bg-zinc-800/60 p-3 text-xs leading-relaxed text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words", children: typeof result === "string" ? result : JSON.stringify(result, null, 2) })
|
|
4480
|
+
] })
|
|
4481
|
+
] })
|
|
4482
|
+
] }) });
|
|
4483
|
+
}
|
|
4484
|
+
});
|
|
4485
|
+
export {
|
|
4486
|
+
AudioRecorderError,
|
|
4487
|
+
CopilotChat,
|
|
4488
|
+
CopilotChatAssistantMessage_default as CopilotChatAssistantMessage,
|
|
4489
|
+
CopilotChatAudioRecorder,
|
|
4490
|
+
CopilotChatConfigurationProvider,
|
|
4491
|
+
CopilotChatInput_default as CopilotChatInput,
|
|
4492
|
+
CopilotChatMessageView_default as CopilotChatMessageView,
|
|
4493
|
+
CopilotChatSuggestionPill_default as CopilotChatSuggestionPill,
|
|
4494
|
+
CopilotChatSuggestionView_default as CopilotChatSuggestionView,
|
|
4495
|
+
CopilotChatToggleButton,
|
|
4496
|
+
DefaultCloseIcon as CopilotChatToggleButtonCloseIcon,
|
|
4497
|
+
DefaultOpenIcon as CopilotChatToggleButtonOpenIcon,
|
|
4498
|
+
CopilotChatToolCallsView_default as CopilotChatToolCallsView,
|
|
4499
|
+
CopilotChatUserMessage_default as CopilotChatUserMessage,
|
|
4500
|
+
CopilotChatView_default as CopilotChatView,
|
|
4501
|
+
CopilotKitCoreReact,
|
|
4502
|
+
CopilotKitInspector,
|
|
4503
|
+
CopilotKitProvider,
|
|
4504
|
+
CopilotModalHeader,
|
|
4505
|
+
CopilotPopup,
|
|
4506
|
+
CopilotPopupView,
|
|
4507
|
+
CopilotSidebar,
|
|
4508
|
+
CopilotSidebarView,
|
|
4509
|
+
MCPAppsActivityContentSchema,
|
|
4510
|
+
MCPAppsActivityRenderer,
|
|
4511
|
+
MCPAppsActivityType,
|
|
4512
|
+
UseAgentUpdate,
|
|
4513
|
+
WildcardToolCallRender,
|
|
4514
|
+
defineToolCallRenderer,
|
|
4515
|
+
useAgent,
|
|
4516
|
+
useAgentContext,
|
|
4517
|
+
useConfigureSuggestions,
|
|
4518
|
+
useCopilotChatConfiguration,
|
|
4519
|
+
useCopilotKit,
|
|
4520
|
+
useFrontendTool,
|
|
4521
|
+
useHumanInTheLoop,
|
|
4522
|
+
useRenderActivityMessage,
|
|
4523
|
+
useRenderCustomMessages,
|
|
4524
|
+
useRenderToolCall,
|
|
4525
|
+
useSuggestions
|
|
4526
|
+
};
|
|
4527
|
+
//# sourceMappingURL=index.mjs.map
|