@copilotkitnext/react 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/.turbo/turbo-build$colon$css.log +0 -9
- package/.turbo/turbo-build.log +0 -30
- package/.turbo/turbo-check-types.log +0 -0
- package/.turbo/turbo-lint.log +0 -78
- package/.turbo/turbo-test.log +0 -79
- package/postcss.config.js +0 -7
- package/src/__tests__/setup.ts +0 -2
- package/src/components/chat/CopilotChat.tsx +0 -90
- package/src/components/chat/CopilotChatAssistantMessage.tsx +0 -478
- package/src/components/chat/CopilotChatAudioRecorder.tsx +0 -157
- package/src/components/chat/CopilotChatInput.tsx +0 -596
- package/src/components/chat/CopilotChatMessageView.tsx +0 -85
- package/src/components/chat/CopilotChatToolCallsView.tsx +0 -43
- package/src/components/chat/CopilotChatUserMessage.tsx +0 -337
- package/src/components/chat/CopilotChatView.tsx +0 -385
- package/src/components/chat/__tests__/CopilotChatAssistantMessage.test.tsx +0 -684
- package/src/components/chat/__tests__/CopilotChatInput.test.tsx +0 -531
- package/src/components/chat/__tests__/setup.ts +0 -1
- package/src/components/chat/index.ts +0 -35
- package/src/components/index.ts +0 -4
- package/src/components/ui/button.tsx +0 -123
- package/src/components/ui/dropdown-menu.tsx +0 -257
- package/src/components/ui/tooltip.tsx +0 -59
- package/src/hooks/index.ts +0 -6
- package/src/hooks/use-agent-context.tsx +0 -17
- package/src/hooks/use-agent.tsx +0 -48
- package/src/hooks/use-frontend-tool.tsx +0 -46
- package/src/hooks/use-human-in-the-loop.tsx +0 -76
- package/src/hooks/use-render-tool-call.tsx +0 -81
- package/src/index.ts +0 -4
- package/src/lib/__tests__/completePartialMarkdown.test.ts +0 -495
- package/src/lib/__tests__/renderSlot.test.tsx +0 -610
- package/src/lib/slots.tsx +0 -55
- package/src/lib/utils.ts +0 -6
- package/src/providers/CopilotChatConfigurationProvider.tsx +0 -81
- package/src/providers/CopilotKitProvider.tsx +0 -269
- package/src/providers/__tests__/CopilotKitProvider.test.tsx +0 -487
- package/src/providers/__tests__/CopilotKitProvider.wildcard.test.tsx +0 -261
- package/src/providers/index.ts +0 -14
- package/src/styles/globals.css +0 -302
- package/src/types/frontend-tool.ts +0 -8
- package/src/types/human-in-the-loop.ts +0 -33
- package/src/types/index.ts +0 -3
- package/src/types/react-tool-call-render.ts +0 -29
- package/tailwind.config.js +0 -9
- package/tsconfig.json +0 -23
- package/tsup.config.ts +0 -19
|
@@ -1,385 +0,0 @@
|
|
|
1
|
-
import React, { useRef, useState, useEffect } from "react";
|
|
2
|
-
import { WithSlots, renderSlot } from "@/lib/slots";
|
|
3
|
-
import CopilotChatMessageView from "./CopilotChatMessageView";
|
|
4
|
-
import CopilotChatInput from "./CopilotChatInput";
|
|
5
|
-
import { Message } from "@ag-ui/core";
|
|
6
|
-
import { twMerge } from "tailwind-merge";
|
|
7
|
-
import { StickToBottom, useStickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
8
|
-
import { ChevronDown } from "lucide-react";
|
|
9
|
-
import { Button } from "@/components/ui/button";
|
|
10
|
-
import { cn } from "@/lib/utils";
|
|
11
|
-
import { useCopilotChatConfiguration } from "@/providers/CopilotChatConfigurationProvider";
|
|
12
|
-
|
|
13
|
-
export type CopilotChatViewProps = WithSlots<
|
|
14
|
-
{
|
|
15
|
-
messageView: typeof CopilotChatMessageView;
|
|
16
|
-
scrollView: React.FC<React.HTMLAttributes<HTMLDivElement>>;
|
|
17
|
-
scrollToBottomButton: React.FC<
|
|
18
|
-
React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
19
|
-
>;
|
|
20
|
-
input: typeof CopilotChatInput;
|
|
21
|
-
inputContainer: React.FC<
|
|
22
|
-
React.HTMLAttributes<HTMLDivElement> & { children: React.ReactNode }
|
|
23
|
-
>;
|
|
24
|
-
feather: React.FC<React.HTMLAttributes<HTMLDivElement>>;
|
|
25
|
-
disclaimer: React.FC<React.HTMLAttributes<HTMLDivElement>>;
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
messages?: Message[];
|
|
29
|
-
autoScroll?: boolean;
|
|
30
|
-
} & React.HTMLAttributes<HTMLDivElement>
|
|
31
|
-
>;
|
|
32
|
-
|
|
33
|
-
export function CopilotChatView({
|
|
34
|
-
messageView,
|
|
35
|
-
input,
|
|
36
|
-
scrollView,
|
|
37
|
-
scrollToBottomButton,
|
|
38
|
-
feather,
|
|
39
|
-
inputContainer,
|
|
40
|
-
disclaimer,
|
|
41
|
-
messages = [],
|
|
42
|
-
autoScroll = true,
|
|
43
|
-
children,
|
|
44
|
-
className,
|
|
45
|
-
...props
|
|
46
|
-
}: CopilotChatViewProps) {
|
|
47
|
-
const inputContainerRef = useRef<HTMLDivElement>(null);
|
|
48
|
-
const [inputContainerHeight, setInputContainerHeight] = useState(0);
|
|
49
|
-
const [isResizing, setIsResizing] = useState(false);
|
|
50
|
-
const resizeTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
51
|
-
|
|
52
|
-
// Track input container height changes
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
const element = inputContainerRef.current;
|
|
55
|
-
if (!element) return;
|
|
56
|
-
|
|
57
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
58
|
-
for (const entry of entries) {
|
|
59
|
-
const newHeight = entry.contentRect.height;
|
|
60
|
-
|
|
61
|
-
// Update height and set resizing state
|
|
62
|
-
setInputContainerHeight((prevHeight) => {
|
|
63
|
-
if (newHeight !== prevHeight) {
|
|
64
|
-
setIsResizing(true);
|
|
65
|
-
|
|
66
|
-
// Clear existing timeout
|
|
67
|
-
if (resizeTimeoutRef.current) {
|
|
68
|
-
clearTimeout(resizeTimeoutRef.current);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Set isResizing to false after a short delay
|
|
72
|
-
resizeTimeoutRef.current = setTimeout(() => {
|
|
73
|
-
setIsResizing(false);
|
|
74
|
-
}, 250);
|
|
75
|
-
|
|
76
|
-
return newHeight;
|
|
77
|
-
}
|
|
78
|
-
return prevHeight;
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
resizeObserver.observe(element);
|
|
84
|
-
|
|
85
|
-
// Set initial height
|
|
86
|
-
setInputContainerHeight(element.offsetHeight);
|
|
87
|
-
|
|
88
|
-
return () => {
|
|
89
|
-
resizeObserver.disconnect();
|
|
90
|
-
if (resizeTimeoutRef.current) {
|
|
91
|
-
clearTimeout(resizeTimeoutRef.current);
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
}, []);
|
|
95
|
-
|
|
96
|
-
const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {
|
|
97
|
-
messages,
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const BoundInput = renderSlot(input, CopilotChatInput, {});
|
|
101
|
-
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
102
|
-
const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {
|
|
103
|
-
autoScroll,
|
|
104
|
-
scrollToBottomButton,
|
|
105
|
-
inputContainerHeight,
|
|
106
|
-
isResizing,
|
|
107
|
-
children: (
|
|
108
|
-
<div style={{ paddingBottom: `${inputContainerHeight + 32}px` }}>
|
|
109
|
-
<div className="max-w-3xl mx-auto">{BoundMessageView}</div>
|
|
110
|
-
</div>
|
|
111
|
-
),
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
const BoundScrollToBottomButton = renderSlot(
|
|
115
|
-
scrollToBottomButton,
|
|
116
|
-
CopilotChatView.ScrollToBottomButton,
|
|
117
|
-
{}
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
const BoundDisclaimer = renderSlot(
|
|
121
|
-
disclaimer,
|
|
122
|
-
CopilotChatView.Disclaimer,
|
|
123
|
-
{}
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
const BoundInputContainer = renderSlot(
|
|
127
|
-
inputContainer,
|
|
128
|
-
CopilotChatView.InputContainer,
|
|
129
|
-
{
|
|
130
|
-
ref: inputContainerRef,
|
|
131
|
-
children: (
|
|
132
|
-
<>
|
|
133
|
-
<div className="max-w-3xl mx-auto py-0 px-4 sm:px-0">
|
|
134
|
-
{BoundInput}
|
|
135
|
-
</div>
|
|
136
|
-
{BoundDisclaimer}
|
|
137
|
-
</>
|
|
138
|
-
),
|
|
139
|
-
}
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
if (children) {
|
|
143
|
-
return children({
|
|
144
|
-
messageView: BoundMessageView,
|
|
145
|
-
input: BoundInput,
|
|
146
|
-
scrollView: BoundScrollView,
|
|
147
|
-
scrollToBottomButton: BoundScrollToBottomButton,
|
|
148
|
-
feather: BoundFeather,
|
|
149
|
-
inputContainer: BoundInputContainer,
|
|
150
|
-
disclaimer: BoundDisclaimer,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
<div className={twMerge("relative h-full", className)} {...props}>
|
|
156
|
-
{BoundScrollView}
|
|
157
|
-
|
|
158
|
-
{BoundFeather}
|
|
159
|
-
|
|
160
|
-
{BoundInputContainer}
|
|
161
|
-
</div>
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export namespace CopilotChatView {
|
|
166
|
-
// Inner component that has access to StickToBottom context
|
|
167
|
-
const ScrollContent: React.FC<{
|
|
168
|
-
children: React.ReactNode;
|
|
169
|
-
scrollToBottomButton?: React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>;
|
|
170
|
-
inputContainerHeight: number;
|
|
171
|
-
isResizing: boolean;
|
|
172
|
-
}> = ({ children, scrollToBottomButton, inputContainerHeight, isResizing }) => {
|
|
173
|
-
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
|
|
174
|
-
|
|
175
|
-
return (
|
|
176
|
-
<>
|
|
177
|
-
<StickToBottom.Content className="overflow-y-scroll overflow-x-hidden">
|
|
178
|
-
<div className="px-4 sm:px-0">{children}</div>
|
|
179
|
-
</StickToBottom.Content>
|
|
180
|
-
|
|
181
|
-
{/* Scroll to bottom button - hidden during resize */}
|
|
182
|
-
{!isAtBottom && !isResizing && (
|
|
183
|
-
<div
|
|
184
|
-
className="absolute inset-x-0 flex justify-center z-10"
|
|
185
|
-
style={{
|
|
186
|
-
bottom: `${inputContainerHeight + 16}px`,
|
|
187
|
-
}}
|
|
188
|
-
>
|
|
189
|
-
{renderSlot(
|
|
190
|
-
scrollToBottomButton,
|
|
191
|
-
CopilotChatView.ScrollToBottomButton,
|
|
192
|
-
{
|
|
193
|
-
onClick: () => scrollToBottom(),
|
|
194
|
-
}
|
|
195
|
-
)}
|
|
196
|
-
</div>
|
|
197
|
-
)}
|
|
198
|
-
</>
|
|
199
|
-
);
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
export const ScrollView: React.FC<
|
|
203
|
-
React.HTMLAttributes<HTMLDivElement> & {
|
|
204
|
-
autoScroll?: boolean;
|
|
205
|
-
scrollToBottomButton?: React.FC<
|
|
206
|
-
React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
207
|
-
>;
|
|
208
|
-
inputContainerHeight?: number;
|
|
209
|
-
isResizing?: boolean;
|
|
210
|
-
}
|
|
211
|
-
> = ({
|
|
212
|
-
children,
|
|
213
|
-
autoScroll = true,
|
|
214
|
-
scrollToBottomButton,
|
|
215
|
-
inputContainerHeight = 0,
|
|
216
|
-
isResizing = false,
|
|
217
|
-
className,
|
|
218
|
-
...props
|
|
219
|
-
}) => {
|
|
220
|
-
const [hasMounted, setHasMounted] = useState(false);
|
|
221
|
-
const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();
|
|
222
|
-
const [showScrollButton, setShowScrollButton] = useState(false);
|
|
223
|
-
|
|
224
|
-
useEffect(() => {
|
|
225
|
-
setHasMounted(true);
|
|
226
|
-
}, []);
|
|
227
|
-
|
|
228
|
-
// Monitor scroll position for non-autoscroll mode
|
|
229
|
-
useEffect(() => {
|
|
230
|
-
if (autoScroll) return; // Skip for autoscroll mode
|
|
231
|
-
|
|
232
|
-
const scrollElement = scrollRef.current;
|
|
233
|
-
if (!scrollElement) return;
|
|
234
|
-
|
|
235
|
-
const checkScroll = () => {
|
|
236
|
-
const atBottom =
|
|
237
|
-
(scrollElement.scrollHeight - scrollElement.scrollTop - scrollElement.clientHeight < 10);
|
|
238
|
-
setShowScrollButton(!atBottom);
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
checkScroll();
|
|
242
|
-
scrollElement.addEventListener('scroll', checkScroll);
|
|
243
|
-
|
|
244
|
-
// Also check on resize
|
|
245
|
-
const resizeObserver = new ResizeObserver(checkScroll);
|
|
246
|
-
resizeObserver.observe(scrollElement);
|
|
247
|
-
|
|
248
|
-
return () => {
|
|
249
|
-
scrollElement.removeEventListener('scroll', checkScroll);
|
|
250
|
-
resizeObserver.disconnect();
|
|
251
|
-
};
|
|
252
|
-
}, [scrollRef, autoScroll]);
|
|
253
|
-
|
|
254
|
-
if (!hasMounted) {
|
|
255
|
-
return (
|
|
256
|
-
<div className="h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden">
|
|
257
|
-
<div className="px-4 sm:px-0">{children}</div>
|
|
258
|
-
</div>
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// When autoScroll is false, we don't use StickToBottom
|
|
263
|
-
if (!autoScroll) {
|
|
264
|
-
return (
|
|
265
|
-
<div
|
|
266
|
-
ref={scrollRef}
|
|
267
|
-
className={cn("h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden relative", className)}
|
|
268
|
-
{...props}
|
|
269
|
-
>
|
|
270
|
-
<div ref={contentRef} className="px-4 sm:px-0">
|
|
271
|
-
{children}
|
|
272
|
-
</div>
|
|
273
|
-
|
|
274
|
-
{/* Scroll to bottom button for manual mode */}
|
|
275
|
-
{showScrollButton && !isResizing && (
|
|
276
|
-
<div
|
|
277
|
-
className="absolute inset-x-0 flex justify-center z-10"
|
|
278
|
-
style={{
|
|
279
|
-
bottom: `${inputContainerHeight + 16}px`,
|
|
280
|
-
}}
|
|
281
|
-
>
|
|
282
|
-
{renderSlot(
|
|
283
|
-
scrollToBottomButton,
|
|
284
|
-
CopilotChatView.ScrollToBottomButton,
|
|
285
|
-
{
|
|
286
|
-
onClick: () => scrollToBottom(),
|
|
287
|
-
}
|
|
288
|
-
)}
|
|
289
|
-
</div>
|
|
290
|
-
)}
|
|
291
|
-
</div>
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
return (
|
|
296
|
-
<StickToBottom
|
|
297
|
-
className={cn("h-full max-h-full flex flex-col min-h-0 relative", className)}
|
|
298
|
-
resize="smooth"
|
|
299
|
-
initial="smooth"
|
|
300
|
-
{...props}
|
|
301
|
-
>
|
|
302
|
-
<ScrollContent
|
|
303
|
-
scrollToBottomButton={scrollToBottomButton}
|
|
304
|
-
inputContainerHeight={inputContainerHeight}
|
|
305
|
-
isResizing={isResizing}
|
|
306
|
-
>
|
|
307
|
-
{children}
|
|
308
|
-
</ScrollContent>
|
|
309
|
-
</StickToBottom>
|
|
310
|
-
);
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
export const ScrollToBottomButton: React.FC<
|
|
314
|
-
React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
315
|
-
> = ({ className, ...props }) => (
|
|
316
|
-
<Button
|
|
317
|
-
variant="outline"
|
|
318
|
-
size="sm"
|
|
319
|
-
className={twMerge(
|
|
320
|
-
"rounded-full w-10 h-10 p-0",
|
|
321
|
-
"bg-white dark:bg-gray-900",
|
|
322
|
-
"shadow-lg border border-gray-200 dark:border-gray-700",
|
|
323
|
-
"hover:bg-gray-50 dark:hover:bg-gray-800",
|
|
324
|
-
"flex items-center justify-center cursor-pointer",
|
|
325
|
-
className
|
|
326
|
-
)}
|
|
327
|
-
{...props}
|
|
328
|
-
>
|
|
329
|
-
<ChevronDown className="w-4 h-4 text-gray-600 dark:text-white" />
|
|
330
|
-
</Button>
|
|
331
|
-
);
|
|
332
|
-
|
|
333
|
-
export const Feather: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({
|
|
334
|
-
className,
|
|
335
|
-
style,
|
|
336
|
-
...props
|
|
337
|
-
}) => (
|
|
338
|
-
<div
|
|
339
|
-
className={cn(
|
|
340
|
-
"absolute bottom-0 left-0 right-4 h-24 pointer-events-none z-10 bg-gradient-to-t",
|
|
341
|
-
"from-white via-white to-transparent",
|
|
342
|
-
"dark:from-[rgb(33,33,33)] dark:via-[rgb(33,33,33)]",
|
|
343
|
-
className
|
|
344
|
-
)}
|
|
345
|
-
style={style}
|
|
346
|
-
{...props}
|
|
347
|
-
/>
|
|
348
|
-
);
|
|
349
|
-
|
|
350
|
-
export const InputContainer = React.forwardRef<
|
|
351
|
-
HTMLDivElement,
|
|
352
|
-
React.HTMLAttributes<HTMLDivElement> & { children: React.ReactNode }
|
|
353
|
-
>(({ children, className, ...props }, ref) => (
|
|
354
|
-
<div
|
|
355
|
-
ref={ref}
|
|
356
|
-
className={cn("absolute bottom-0 left-0 right-0 z-20", className)}
|
|
357
|
-
{...props}
|
|
358
|
-
>
|
|
359
|
-
{children}
|
|
360
|
-
</div>
|
|
361
|
-
));
|
|
362
|
-
|
|
363
|
-
InputContainer.displayName = "CopilotChatView.InputContainer";
|
|
364
|
-
|
|
365
|
-
export const Disclaimer: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({
|
|
366
|
-
className,
|
|
367
|
-
...props
|
|
368
|
-
}) => {
|
|
369
|
-
const { labels } = useCopilotChatConfiguration();
|
|
370
|
-
|
|
371
|
-
return (
|
|
372
|
-
<div
|
|
373
|
-
className={cn(
|
|
374
|
-
"text-center text-xs text-muted-foreground py-3 px-4 max-w-3xl mx-auto",
|
|
375
|
-
className
|
|
376
|
-
)}
|
|
377
|
-
{...props}
|
|
378
|
-
>
|
|
379
|
-
{labels.chatDisclaimerText}
|
|
380
|
-
</div>
|
|
381
|
-
);
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
export default CopilotChatView;
|