@copilotkit/react-core 1.54.1 → 1.55.0-next.7

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 (183) hide show
  1. package/CHANGELOG.md +117 -116
  2. package/dist/copilotkit-B3Mb1yVE.cjs +7975 -0
  3. package/dist/copilotkit-B3Mb1yVE.cjs.map +1 -0
  4. package/dist/copilotkit-DBzgOMby.d.cts +2182 -0
  5. package/dist/copilotkit-DBzgOMby.d.cts.map +1 -0
  6. package/dist/copilotkit-DNYSFuz5.mjs +7562 -0
  7. package/dist/copilotkit-DNYSFuz5.mjs.map +1 -0
  8. package/dist/copilotkit-Dy5w3qEV.d.mts +2182 -0
  9. package/dist/copilotkit-Dy5w3qEV.d.mts.map +1 -0
  10. package/dist/index.cjs +27 -28
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +3 -3
  13. package/dist/index.d.cts.map +1 -1
  14. package/dist/index.d.mts +3 -3
  15. package/dist/index.d.mts.map +1 -1
  16. package/dist/index.mjs +4 -5
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/index.umd.js +1941 -35
  19. package/dist/index.umd.js.map +1 -1
  20. package/dist/v2/index.cjs +77 -7
  21. package/dist/v2/index.css +1 -2
  22. package/dist/v2/index.d.cts +6 -4
  23. package/dist/v2/index.d.mts +6 -4
  24. package/dist/v2/index.mjs +7 -4
  25. package/dist/v2/index.umd.js +5725 -24
  26. package/dist/v2/index.umd.js.map +1 -1
  27. package/package.json +37 -9
  28. package/scripts/scope-preflight.mjs +101 -0
  29. package/src/components/CopilotListeners.tsx +2 -6
  30. package/src/components/copilot-provider/copilot-messages.tsx +1 -1
  31. package/src/components/copilot-provider/copilotkit-props.tsx +1 -1
  32. package/src/components/copilot-provider/copilotkit.tsx +4 -4
  33. package/src/context/copilot-messages-context.tsx +1 -1
  34. package/src/hooks/__tests__/use-coagent-config.test.ts +2 -2
  35. package/src/hooks/__tests__/use-coagent-state-render.e2e.test.tsx +2 -2
  36. package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +3 -7
  37. package/src/hooks/__tests__/use-frontend-tool-available.test.tsx +1 -1
  38. package/src/hooks/__tests__/use-frontend-tool-remount.e2e.test.tsx +4 -4
  39. package/src/hooks/use-agent-nodename.ts +1 -1
  40. package/src/hooks/use-coagent-state-render-bridge.tsx +1 -4
  41. package/src/hooks/use-coagent.ts +1 -1
  42. package/src/hooks/use-configure-chat-suggestions.tsx +2 -2
  43. package/src/hooks/use-copilot-chat-suggestions.tsx +2 -2
  44. package/src/hooks/use-copilot-chat_internal.ts +2 -2
  45. package/src/hooks/use-copilot-readable.ts +1 -1
  46. package/src/hooks/use-frontend-tool.ts +2 -2
  47. package/src/hooks/use-human-in-the-loop.ts +2 -2
  48. package/src/hooks/use-langgraph-interrupt.ts +2 -5
  49. package/src/hooks/use-lazy-tool-renderer.tsx +1 -1
  50. package/src/hooks/use-render-tool-call.ts +1 -1
  51. package/src/lib/copilot-task.ts +1 -1
  52. package/src/setupTests.ts +18 -14
  53. package/src/v2/__tests__/A2UIMessageRenderer.test.tsx +176 -0
  54. package/src/v2/__tests__/globalSetup.ts +14 -0
  55. package/src/v2/__tests__/setup.ts +93 -0
  56. package/src/v2/__tests__/utils/test-helpers.tsx +470 -0
  57. package/src/v2/a2ui/A2UIMessageRenderer.tsx +206 -0
  58. package/src/v2/components/CopilotKitInspector.tsx +50 -0
  59. package/src/v2/components/MCPAppsActivityRenderer.tsx +785 -0
  60. package/src/v2/components/WildcardToolCallRender.tsx +86 -0
  61. package/src/v2/components/__tests__/license-warning-banner.test.tsx +46 -0
  62. package/src/v2/components/chat/CopilotChat.tsx +431 -0
  63. package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +375 -0
  64. package/src/v2/components/chat/CopilotChatAudioRecorder.tsx +350 -0
  65. package/src/v2/components/chat/CopilotChatInput.tsx +1302 -0
  66. package/src/v2/components/chat/CopilotChatMessageView.tsx +556 -0
  67. package/src/v2/components/chat/CopilotChatReasoningMessage.tsx +252 -0
  68. package/src/v2/components/chat/CopilotChatSuggestionPill.tsx +59 -0
  69. package/src/v2/components/chat/CopilotChatSuggestionView.tsx +133 -0
  70. package/src/v2/components/chat/CopilotChatToggleButton.tsx +171 -0
  71. package/src/v2/components/chat/CopilotChatToolCallsView.tsx +40 -0
  72. package/src/v2/components/chat/CopilotChatUserMessage.tsx +388 -0
  73. package/src/v2/components/chat/CopilotChatView.tsx +598 -0
  74. package/src/v2/components/chat/CopilotModalHeader.tsx +129 -0
  75. package/src/v2/components/chat/CopilotPopup.tsx +81 -0
  76. package/src/v2/components/chat/CopilotPopupView.tsx +317 -0
  77. package/src/v2/components/chat/CopilotSidebar.tsx +76 -0
  78. package/src/v2/components/chat/CopilotSidebarView.tsx +255 -0
  79. package/src/v2/components/chat/__tests__/CopilotChat.e2e.test.tsx +1113 -0
  80. package/src/v2/components/chat/__tests__/CopilotChat.onError.test.tsx +73 -0
  81. package/src/v2/components/chat/__tests__/CopilotChat.slots.e2e.test.tsx +432 -0
  82. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +150 -0
  83. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.slots.e2e.test.tsx +624 -0
  84. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.test.tsx +702 -0
  85. package/src/v2/components/chat/__tests__/CopilotChatCssClasses.test.tsx +107 -0
  86. package/src/v2/components/chat/__tests__/CopilotChatInput.slots.e2e.test.tsx +929 -0
  87. package/src/v2/components/chat/__tests__/CopilotChatInput.test.tsx +986 -0
  88. package/src/v2/components/chat/__tests__/CopilotChatMessageView.slots.e2e.test.tsx +1004 -0
  89. package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.tsx +169 -0
  90. package/src/v2/components/chat/__tests__/CopilotChatSuggestionView.slots.e2e.test.tsx +530 -0
  91. package/src/v2/components/chat/__tests__/CopilotChatToolRendering.e2e.test.tsx +782 -0
  92. package/src/v2/components/chat/__tests__/CopilotChatToolRerenders.e2e.test.tsx +2413 -0
  93. package/src/v2/components/chat/__tests__/CopilotChatUserMessage.slots.e2e.test.tsx +621 -0
  94. package/src/v2/components/chat/__tests__/CopilotChatView.onClick.e2e.test.tsx +853 -0
  95. package/src/v2/components/chat/__tests__/CopilotChatView.slots.e2e.test.tsx +1050 -0
  96. package/src/v2/components/chat/__tests__/CopilotModalHeader.slots.e2e.test.tsx +484 -0
  97. package/src/v2/components/chat/__tests__/CopilotPopupView.slots.e2e.test.tsx +612 -0
  98. package/src/v2/components/chat/__tests__/CopilotSidebarView.slots.e2e.test.tsx +502 -0
  99. package/src/v2/components/chat/__tests__/MCPAppsActivityRenderer.e2e.test.tsx +1011 -0
  100. package/src/v2/components/chat/__tests__/setup.ts +1 -0
  101. package/src/v2/components/chat/index.ts +79 -0
  102. package/src/v2/components/index.ts +7 -0
  103. package/src/v2/components/license-warning-banner.tsx +198 -0
  104. package/src/v2/components/ui/button.tsx +123 -0
  105. package/src/v2/components/ui/dropdown-menu.tsx +258 -0
  106. package/src/v2/components/ui/tooltip.tsx +60 -0
  107. package/src/v2/hooks/__tests__/standard-schema-types.test.tsx +152 -0
  108. package/src/v2/hooks/__tests__/standard-schema.test.tsx +282 -0
  109. package/src/v2/hooks/__tests__/use-agent-context-timing.e2e.test.tsx +132 -0
  110. package/src/v2/hooks/__tests__/use-agent-context.test.tsx +401 -0
  111. package/src/v2/hooks/__tests__/use-agent-error-state.test.tsx +44 -0
  112. package/src/v2/hooks/__tests__/use-agent-stability.test.tsx +205 -0
  113. package/src/v2/hooks/__tests__/use-agent.e2e.test.tsx +148 -0
  114. package/src/v2/hooks/__tests__/use-component.test.tsx +123 -0
  115. package/src/v2/hooks/__tests__/use-configure-suggestions.e2e.test.tsx +696 -0
  116. package/src/v2/hooks/__tests__/use-default-render-tool.test.tsx +153 -0
  117. package/src/v2/hooks/__tests__/use-frontend-tool-available.test.tsx +167 -0
  118. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.tsx +2129 -0
  119. package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.tsx +1261 -0
  120. package/src/v2/hooks/__tests__/use-interrupt.test.tsx +397 -0
  121. package/src/v2/hooks/__tests__/use-katex-styles.test.tsx +56 -0
  122. package/src/v2/hooks/__tests__/use-keyboard-height.test.tsx +192 -0
  123. package/src/v2/hooks/__tests__/use-render-tool.test.tsx +259 -0
  124. package/src/v2/hooks/__tests__/use-suggestions.e2e.test.tsx +524 -0
  125. package/src/v2/hooks/__tests__/use-threads.test.tsx +433 -0
  126. package/src/v2/hooks/__tests__/zod-regression.test.tsx +311 -0
  127. package/src/v2/hooks/index.ts +18 -0
  128. package/src/v2/hooks/use-agent-context.tsx +45 -0
  129. package/src/v2/hooks/use-agent.tsx +155 -0
  130. package/src/v2/hooks/use-component.tsx +89 -0
  131. package/src/v2/hooks/use-configure-suggestions.tsx +187 -0
  132. package/src/v2/hooks/use-default-render-tool.tsx +254 -0
  133. package/src/v2/hooks/use-frontend-tool.tsx +43 -0
  134. package/src/v2/hooks/use-human-in-the-loop.tsx +81 -0
  135. package/src/v2/hooks/use-interrupt.tsx +305 -0
  136. package/src/v2/hooks/use-keyboard-height.tsx +67 -0
  137. package/src/v2/hooks/use-render-activity-message.tsx +73 -0
  138. package/src/v2/hooks/use-render-custom-messages.tsx +93 -0
  139. package/src/v2/hooks/use-render-tool-call.tsx +175 -0
  140. package/src/v2/hooks/use-render-tool.tsx +181 -0
  141. package/src/v2/hooks/use-suggestions.tsx +91 -0
  142. package/src/v2/hooks/use-threads.tsx +256 -0
  143. package/src/v2/hooks/useKatexStyles.ts +27 -0
  144. package/src/v2/index.css +1 -1
  145. package/src/v2/index.ts +18 -2
  146. package/src/v2/lib/__tests__/completePartialMarkdown.test.ts +495 -0
  147. package/src/v2/lib/__tests__/renderSlot.test.tsx +588 -0
  148. package/src/v2/lib/react-core.ts +156 -0
  149. package/src/v2/lib/slots.tsx +143 -0
  150. package/src/v2/lib/transcription-client.ts +184 -0
  151. package/src/v2/lib/utils.ts +8 -0
  152. package/src/v2/providers/CopilotChatConfigurationProvider.tsx +162 -0
  153. package/src/v2/providers/CopilotKitProvider.tsx +600 -0
  154. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.tsx +546 -0
  155. package/src/v2/providers/__tests__/CopilotKitProvider.license.test.tsx +101 -0
  156. package/src/v2/providers/__tests__/CopilotKitProvider.onError.test.tsx +69 -0
  157. package/src/v2/providers/__tests__/CopilotKitProvider.renderCustomMessages.e2e.test.tsx +881 -0
  158. package/src/v2/providers/__tests__/CopilotKitProvider.stability.test.tsx +740 -0
  159. package/src/v2/providers/__tests__/CopilotKitProvider.test.tsx +642 -0
  160. package/src/v2/providers/__tests__/CopilotKitProvider.wildcard.test.tsx +294 -0
  161. package/src/v2/providers/index.ts +14 -0
  162. package/src/v2/styles/globals.css +230 -0
  163. package/src/v2/types/__tests__/defineToolCallRenderer.test.tsx +525 -0
  164. package/src/v2/types/defineToolCallRenderer.ts +65 -0
  165. package/src/v2/types/frontend-tool.ts +8 -0
  166. package/src/v2/types/human-in-the-loop.ts +33 -0
  167. package/src/v2/types/index.ts +7 -0
  168. package/src/v2/types/interrupt.ts +15 -0
  169. package/src/v2/types/react-activity-message-renderer.ts +27 -0
  170. package/src/v2/types/react-custom-message-renderer.ts +17 -0
  171. package/src/v2/types/react-tool-call-renderer.ts +32 -0
  172. package/tsdown.config.ts +34 -10
  173. package/vitest.config.mjs +4 -3
  174. package/LICENSE +0 -21
  175. package/dist/copilotkit-BRPQ2sqS.d.cts +0 -670
  176. package/dist/copilotkit-BRPQ2sqS.d.cts.map +0 -1
  177. package/dist/copilotkit-C94ayZbs.cjs +0 -2161
  178. package/dist/copilotkit-C94ayZbs.cjs.map +0 -1
  179. package/dist/copilotkit-CwZMFmSK.d.mts +0 -670
  180. package/dist/copilotkit-CwZMFmSK.d.mts.map +0 -1
  181. package/dist/copilotkit-Yh_Ld_FX.mjs +0 -2031
  182. package/dist/copilotkit-Yh_Ld_FX.mjs.map +0 -1
  183. package/dist/v2/index.css.map +0 -1
@@ -0,0 +1,259 @@
1
+ import React from "react";
2
+ import { render } from "@testing-library/react";
3
+ import { describe, it, expect, beforeEach, vi } from "vitest";
4
+ import { z } from "zod";
5
+ import { useRenderTool, type RenderToolProps } from "../use-render-tool";
6
+ import { useCopilotKit } from "../../providers/CopilotKitProvider";
7
+ import type { ReactToolCallRenderer } from "../../types/react-tool-call-renderer";
8
+
9
+ vi.mock("../../providers/CopilotKitProvider", () => ({
10
+ useCopilotKit: vi.fn(),
11
+ }));
12
+
13
+ type MockCore = {
14
+ renderToolCalls: ReactToolCallRenderer[];
15
+ setRenderToolCalls: ReturnType<typeof vi.fn>;
16
+ addHookRenderToolCall: ReturnType<typeof vi.fn>;
17
+ removeHookRenderToolCall: ReturnType<typeof vi.fn>;
18
+ };
19
+
20
+ const mockUseCopilotKit = useCopilotKit as ReturnType<typeof vi.fn>;
21
+
22
+ function createMockCore(
23
+ initialRenderToolCalls: ReactToolCallRenderer[] = [],
24
+ ): MockCore {
25
+ const hookEntries = new Map<string, ReactToolCallRenderer>();
26
+
27
+ const core: MockCore = {
28
+ get renderToolCalls() {
29
+ if (hookEntries.size === 0) return initialRenderToolCalls;
30
+ const merged = new Map<string, ReactToolCallRenderer>();
31
+ for (const rc of initialRenderToolCalls) {
32
+ merged.set(`${rc.agentId ?? ""}:${rc.name}`, rc);
33
+ }
34
+ for (const [key, rc] of hookEntries) {
35
+ merged.set(key, rc);
36
+ }
37
+ return Array.from(merged.values());
38
+ },
39
+ setRenderToolCalls: vi.fn((next: ReactToolCallRenderer[]) => {
40
+ initialRenderToolCalls = next;
41
+ }),
42
+ addHookRenderToolCall: vi.fn((entry: ReactToolCallRenderer) => {
43
+ const key = `${entry.agentId ?? ""}:${entry.name}`;
44
+ hookEntries.set(key, entry);
45
+ }),
46
+ removeHookRenderToolCall: vi.fn((name: string, agentId?: string) => {
47
+ const key = `${agentId ?? ""}:${name}`;
48
+ hookEntries.delete(key);
49
+ }),
50
+ };
51
+
52
+ return core;
53
+ }
54
+
55
+ describe("useRenderTool", () => {
56
+ beforeEach(() => {
57
+ vi.clearAllMocks();
58
+ });
59
+
60
+ it("registers a named renderer with parameters schema", () => {
61
+ const core = createMockCore();
62
+ mockUseCopilotKit.mockReturnValue({ copilotkit: core });
63
+
64
+ const schema = z.object({ query: z.string() });
65
+ const renderFn = vi.fn((_props: RenderToolProps<typeof schema>) => (
66
+ <div>render</div>
67
+ ));
68
+
69
+ const Harness: React.FC = () => {
70
+ useRenderTool(
71
+ {
72
+ name: "searchDocs",
73
+ parameters: schema,
74
+ render: renderFn,
75
+ },
76
+ [],
77
+ );
78
+ return null;
79
+ };
80
+
81
+ render(<Harness />);
82
+
83
+ expect(core.addHookRenderToolCall).toHaveBeenCalledTimes(1);
84
+ const renderer = core.renderToolCalls.find(
85
+ (item) => item.name === "searchDocs",
86
+ );
87
+ expect(renderer).toBeDefined();
88
+ expect(renderer?.args).toBe(schema);
89
+ expect(typeof renderer?.render).toBe("function");
90
+ });
91
+
92
+ it("registers wildcard renderer and defaults parameters schema to z.any", () => {
93
+ const core = createMockCore();
94
+ mockUseCopilotKit.mockReturnValue({ copilotkit: core });
95
+
96
+ const wildcardRender = vi.fn(() => <div>wildcard</div>);
97
+
98
+ const Harness: React.FC = () => {
99
+ useRenderTool(
100
+ {
101
+ name: "*",
102
+ render: wildcardRender,
103
+ },
104
+ [],
105
+ );
106
+ return null;
107
+ };
108
+
109
+ render(<Harness />);
110
+
111
+ const renderer = core.renderToolCalls.find((item) => item.name === "*");
112
+ expect(renderer).toBeDefined();
113
+ expect(typeof renderer?.render).toBe("function");
114
+ expect(renderer?.args.safeParse({ arbitrary: true }).success).toBe(true);
115
+ });
116
+
117
+ it("deduplicates by agentId:name and keeps unrelated entries", () => {
118
+ const oldRenderer: ReactToolCallRenderer = {
119
+ name: "searchDocs",
120
+ agentId: "agent-1",
121
+ args: z.object({ query: z.string() }),
122
+ render: () => <div>old</div>,
123
+ };
124
+ const untouchedRenderer: ReactToolCallRenderer = {
125
+ name: "otherTool",
126
+ args: z.object({ id: z.string() }),
127
+ render: () => <div>other</div>,
128
+ };
129
+
130
+ const core = createMockCore([oldRenderer, untouchedRenderer]);
131
+ mockUseCopilotKit.mockReturnValue({ copilotkit: core });
132
+
133
+ const newRender = vi.fn(() => <div>new</div>);
134
+
135
+ const Harness: React.FC = () => {
136
+ useRenderTool(
137
+ {
138
+ name: "searchDocs",
139
+ agentId: "agent-1",
140
+ parameters: z.object({ query: z.string() }),
141
+ render: newRender,
142
+ },
143
+ [],
144
+ );
145
+ return null;
146
+ };
147
+
148
+ render(<Harness />);
149
+
150
+ const updated = core.renderToolCalls.find(
151
+ (item) => item.name === "searchDocs" && item.agentId === "agent-1",
152
+ );
153
+ const untouched = core.renderToolCalls.find(
154
+ (item) => item.name === "otherTool",
155
+ );
156
+
157
+ expect(core.renderToolCalls).toHaveLength(2);
158
+ expect(typeof updated?.render).toBe("function");
159
+ expect(untouched).toBe(untouchedRenderer);
160
+ });
161
+
162
+ it("keeps separate entries for same name across different agentId values", () => {
163
+ const core = createMockCore();
164
+ mockUseCopilotKit.mockReturnValue({ copilotkit: core });
165
+
166
+ const RendererA: React.FC = () => {
167
+ useRenderTool(
168
+ {
169
+ name: "summarize",
170
+ agentId: "agent-a",
171
+ parameters: z.object({ text: z.string() }),
172
+ render: () => <div>A</div>,
173
+ },
174
+ [],
175
+ );
176
+ return null;
177
+ };
178
+
179
+ const RendererB: React.FC = () => {
180
+ useRenderTool(
181
+ {
182
+ name: "summarize",
183
+ agentId: "agent-b",
184
+ parameters: z.object({ text: z.string() }),
185
+ render: () => <div>B</div>,
186
+ },
187
+ [],
188
+ );
189
+ return null;
190
+ };
191
+
192
+ render(
193
+ <>
194
+ <RendererA />
195
+ <RendererB />
196
+ </>,
197
+ );
198
+
199
+ const byName = core.renderToolCalls.filter(
200
+ (item) => item.name === "summarize",
201
+ );
202
+ expect(byName).toHaveLength(2);
203
+ expect(byName.map((item) => item.agentId).sort()).toEqual([
204
+ "agent-a",
205
+ "agent-b",
206
+ ]);
207
+ });
208
+
209
+ it("re-registers when deps change", () => {
210
+ const core = createMockCore();
211
+ mockUseCopilotKit.mockReturnValue({ copilotkit: core });
212
+
213
+ const Harness: React.FC<{ version: string }> = ({ version }) => {
214
+ useRenderTool(
215
+ {
216
+ name: "searchDocs",
217
+ parameters: z.object({ query: z.string() }),
218
+ render: () => <div>{version}</div>,
219
+ },
220
+ [version],
221
+ );
222
+ return null;
223
+ };
224
+
225
+ const ui = render(<Harness version="v1" />);
226
+ expect(core.addHookRenderToolCall).toHaveBeenCalledTimes(1);
227
+
228
+ ui.rerender(<Harness version="v2" />);
229
+ expect(core.addHookRenderToolCall).toHaveBeenCalledTimes(2);
230
+ });
231
+
232
+ it("does not remove renderer on unmount", () => {
233
+ const core = createMockCore();
234
+ mockUseCopilotKit.mockReturnValue({ copilotkit: core });
235
+
236
+ const Harness: React.FC = () => {
237
+ useRenderTool(
238
+ {
239
+ name: "searchDocs",
240
+ parameters: z.object({ query: z.string() }),
241
+ render: () => <div>render</div>,
242
+ },
243
+ [],
244
+ );
245
+ return null;
246
+ };
247
+
248
+ const ui = render(<Harness />);
249
+ const callsAfterMount = core.addHookRenderToolCall.mock.calls.length;
250
+ ui.unmount();
251
+
252
+ // No additional calls after unmount — renderer kept for chat history
253
+ expect(core.addHookRenderToolCall).toHaveBeenCalledTimes(callsAfterMount);
254
+ expect(core.removeHookRenderToolCall).not.toHaveBeenCalled();
255
+ expect(
256
+ core.renderToolCalls.find((item) => item.name === "searchDocs"),
257
+ ).toBeDefined();
258
+ });
259
+ });