@copilotkitnext/react 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/.turbo/turbo-build$colon$css.log +9 -0
  2. package/.turbo/turbo-build.log +28 -0
  3. package/.turbo/turbo-check-types.log +0 -0
  4. package/.turbo/turbo-lint.log +78 -0
  5. package/.turbo/turbo-test.log +79 -0
  6. package/LICENSE +11 -0
  7. package/components.json +20 -0
  8. package/dist/index.d.mts +363 -0
  9. package/dist/index.d.ts +363 -0
  10. package/dist/index.js +2322 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/index.mjs +2291 -0
  13. package/dist/index.mjs.map +1 -0
  14. package/dist/styles.css +2 -0
  15. package/eslint.config.mjs +11 -0
  16. package/package.json +84 -0
  17. package/postcss.config.js +7 -0
  18. package/src/__tests__/setup.ts +2 -0
  19. package/src/components/chat/CopilotChat.tsx +90 -0
  20. package/src/components/chat/CopilotChatAssistantMessage.tsx +478 -0
  21. package/src/components/chat/CopilotChatAudioRecorder.tsx +157 -0
  22. package/src/components/chat/CopilotChatInput.tsx +596 -0
  23. package/src/components/chat/CopilotChatMessageView.tsx +85 -0
  24. package/src/components/chat/CopilotChatToolCallsView.tsx +43 -0
  25. package/src/components/chat/CopilotChatUserMessage.tsx +337 -0
  26. package/src/components/chat/CopilotChatView.tsx +385 -0
  27. package/src/components/chat/__tests__/CopilotChatAssistantMessage.test.tsx +684 -0
  28. package/src/components/chat/__tests__/CopilotChatInput.test.tsx +531 -0
  29. package/src/components/chat/__tests__/setup.ts +1 -0
  30. package/src/components/chat/index.ts +35 -0
  31. package/src/components/index.ts +4 -0
  32. package/src/components/ui/button.tsx +123 -0
  33. package/src/components/ui/dropdown-menu.tsx +257 -0
  34. package/src/components/ui/tooltip.tsx +59 -0
  35. package/src/hooks/index.ts +6 -0
  36. package/src/hooks/use-agent-context.tsx +17 -0
  37. package/src/hooks/use-agent.tsx +48 -0
  38. package/src/hooks/use-frontend-tool.tsx +46 -0
  39. package/src/hooks/use-human-in-the-loop.tsx +76 -0
  40. package/src/hooks/use-render-tool-call.tsx +81 -0
  41. package/src/index.ts +4 -0
  42. package/src/lib/__tests__/completePartialMarkdown.test.ts +495 -0
  43. package/src/lib/__tests__/renderSlot.test.tsx +610 -0
  44. package/src/lib/slots.tsx +55 -0
  45. package/src/lib/utils.ts +6 -0
  46. package/src/providers/CopilotChatConfigurationProvider.tsx +81 -0
  47. package/src/providers/CopilotKitProvider.tsx +269 -0
  48. package/src/providers/__tests__/CopilotKitProvider.test.tsx +487 -0
  49. package/src/providers/__tests__/CopilotKitProvider.wildcard.test.tsx +261 -0
  50. package/src/providers/index.ts +14 -0
  51. package/src/styles/globals.css +302 -0
  52. package/src/types/frontend-tool.ts +8 -0
  53. package/src/types/human-in-the-loop.ts +33 -0
  54. package/src/types/index.ts +3 -0
  55. package/src/types/react-tool-call-render.ts +29 -0
  56. package/tailwind.config.js +9 -0
  57. package/test.css +2355 -0
  58. package/tsconfig.json +23 -0
  59. package/tsup.config.ts +19 -0
  60. package/vitest.config.mjs +15 -0
@@ -0,0 +1,157 @@
1
+ import { useRef, useEffect, useImperativeHandle, forwardRef } from "react";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ /** Finite-state machine for every recorder implementation */
5
+ export type AudioRecorderState = "idle" | "recording" | "processing";
6
+
7
+ /** Error subclass so callers can `instanceof`-guard recorder failures */
8
+ export class AudioRecorderError extends Error {
9
+ constructor(message: string) {
10
+ super(message);
11
+ this.name = "AudioRecorderError";
12
+ }
13
+ }
14
+
15
+ export const CopilotChatAudioRecorder = forwardRef<
16
+ any,
17
+ React.HTMLAttributes<HTMLDivElement>
18
+ >((props, ref) => {
19
+ const { className, ...divProps } = props;
20
+ const canvasRef = useRef<HTMLCanvasElement>(null);
21
+
22
+ // Generate fake waveform that moves with time
23
+ const getLoudness = (n: number): number[] => {
24
+ const elapsed = Date.now() / 1000; // Use current timestamp directly
25
+ const samples: number[] = [];
26
+
27
+ for (let i = 0; i < n; i++) {
28
+ // Create a position that moves from left to right over time
29
+ const position = (i / n) * 10 + elapsed * 0.5; // Scroll speed (slower)
30
+
31
+ // Generate waveform using multiple sine waves for realism
32
+ const wave1 = Math.sin(position * 2) * 0.3;
33
+ const wave2 = Math.sin(position * 5 + elapsed) * 0.2;
34
+ const wave3 = Math.sin(position * 0.5 + elapsed * 0.3) * 0.4;
35
+
36
+ // Add some randomness for natural variation
37
+ const noise = (Math.random() - 0.5) * 0.1;
38
+
39
+ // Combine waves and add envelope for realistic amplitude variation
40
+ const envelope = Math.sin(elapsed * 0.7) * 0.5 + 0.5; // Slow amplitude modulation
41
+ let amplitude = (wave1 + wave2 + wave3 + noise) * envelope;
42
+
43
+ // Clamp to 0-1 range
44
+ amplitude = Math.max(0, Math.min(1, amplitude * 0.5 + 0.3));
45
+
46
+ samples.push(amplitude);
47
+ }
48
+
49
+ return samples;
50
+ };
51
+
52
+ // No setup needed - stub implementation
53
+
54
+ // Canvas rendering with 60fps animation
55
+ useEffect(() => {
56
+ const canvas = canvasRef.current;
57
+ if (!canvas) return;
58
+
59
+ const ctx = canvas.getContext("2d");
60
+ if (!ctx) return;
61
+
62
+ let animationId: number;
63
+
64
+ const draw = () => {
65
+ const rect = canvas.getBoundingClientRect();
66
+ const dpr = window.devicePixelRatio || 1;
67
+
68
+ // Update canvas dimensions if container resized
69
+ if (
70
+ canvas.width !== rect.width * dpr ||
71
+ canvas.height !== rect.height * dpr
72
+ ) {
73
+ canvas.width = rect.width * dpr;
74
+ canvas.height = rect.height * dpr;
75
+ ctx.scale(dpr, dpr);
76
+ ctx.imageSmoothingEnabled = false;
77
+ }
78
+
79
+ // Configuration
80
+ const barWidth = 2;
81
+ const minHeight = 2;
82
+ const maxHeight = 20;
83
+ const gap = 2;
84
+ const numSamples = Math.ceil(rect.width / (barWidth + gap));
85
+
86
+ // Get loudness data
87
+ const loudnessData = getLoudness(numSamples);
88
+
89
+ // Clear canvas
90
+ ctx.clearRect(0, 0, rect.width, rect.height);
91
+
92
+ // Get current foreground color
93
+ const computedStyle = getComputedStyle(canvas);
94
+ const currentForeground = computedStyle.color;
95
+
96
+ // Draw bars
97
+ ctx.fillStyle = currentForeground;
98
+ const centerY = rect.height / 2;
99
+
100
+ for (let i = 0; i < loudnessData.length; i++) {
101
+ const sample = loudnessData[i] ?? 0;
102
+ const barHeight = Math.round(
103
+ sample * (maxHeight - minHeight) + minHeight
104
+ );
105
+ const x = Math.round(i * (barWidth + gap));
106
+ const y = Math.round(centerY - barHeight / 2);
107
+
108
+ ctx.fillRect(x, y, barWidth, barHeight);
109
+ }
110
+
111
+ animationId = requestAnimationFrame(draw);
112
+ };
113
+
114
+ draw();
115
+
116
+ return () => {
117
+ if (animationId) {
118
+ cancelAnimationFrame(animationId);
119
+ }
120
+ };
121
+ }, []);
122
+
123
+ // Expose AudioRecorder API
124
+ useImperativeHandle(
125
+ ref,
126
+ () => ({
127
+ get state() {
128
+ return "idle" as AudioRecorderState;
129
+ },
130
+ start: async () => {
131
+ // Stub implementation - no actual recording
132
+ },
133
+ stop: () =>
134
+ new Promise<Blob>((resolve) => {
135
+ // Stub implementation - return empty blob
136
+ const emptyBlob = new Blob([], { type: "audio/webm" });
137
+ resolve(emptyBlob);
138
+ }),
139
+ dispose: () => {
140
+ // No cleanup needed
141
+ },
142
+ }),
143
+ []
144
+ );
145
+
146
+ return (
147
+ <div className={twMerge("h-[44px] w-full px-5", className)} {...divProps}>
148
+ <canvas
149
+ ref={canvasRef}
150
+ className="w-full h-full"
151
+ style={{ imageRendering: "pixelated" }}
152
+ />
153
+ </div>
154
+ );
155
+ });
156
+
157
+ CopilotChatAudioRecorder.displayName = "WebAudioRecorder";