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