@copilotkit/react-core 1.55.0-next.8 → 1.55.0

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 (94) hide show
  1. package/CHANGELOG.md +48 -5
  2. package/dist/{copilotkit-DNYSFuz5.mjs → copilotkit-BY5S1-0P.mjs} +2772 -858
  3. package/dist/copilotkit-BY5S1-0P.mjs.map +1 -0
  4. package/dist/{copilotkit-Dy5w3qEV.d.mts → copilotkit-BuhSUZHb.d.mts} +230 -17
  5. package/dist/copilotkit-BuhSUZHb.d.mts.map +1 -0
  6. package/dist/{copilotkit-B3Mb1yVE.cjs → copilotkit-Bz5-ImDl.cjs} +2776 -832
  7. package/dist/copilotkit-Bz5-ImDl.cjs.map +1 -0
  8. package/dist/{copilotkit-DBzgOMby.d.cts → copilotkit-dwDWYpya.d.cts} +230 -17
  9. package/dist/copilotkit-dwDWYpya.d.cts.map +1 -0
  10. package/dist/index.cjs +9 -4
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +1 -1
  13. package/dist/index.d.mts +1 -1
  14. package/dist/index.mjs +9 -4
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/index.umd.js +1624 -396
  17. package/dist/index.umd.js.map +1 -1
  18. package/dist/v2/index.cjs +13 -1
  19. package/dist/v2/index.css +1 -1
  20. package/dist/v2/index.d.cts +3 -3
  21. package/dist/v2/index.d.mts +3 -3
  22. package/dist/v2/index.mjs +3 -2
  23. package/dist/v2/index.umd.js +2746 -790
  24. package/dist/v2/index.umd.js.map +1 -1
  25. package/package.json +62 -54
  26. package/scripts/scope-preflight.mjs +1 -2
  27. package/src/components/CopilotListeners.tsx +41 -8
  28. package/src/components/copilot-provider/__tests__/copilot-messages-key.test.tsx +92 -0
  29. package/src/components/copilot-provider/copilotkit-props.tsx +4 -2
  30. package/src/components/copilot-provider/copilotkit.tsx +3 -3
  31. package/src/components/toast/toast-provider.tsx +269 -194
  32. package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +27 -16
  33. package/src/hooks/use-copilot-chat_internal.ts +15 -4
  34. package/src/v2/__tests__/A2UIMessageRenderer.test.tsx +86 -22
  35. package/src/v2/__tests__/utils/test-helpers.tsx +107 -7
  36. package/src/v2/a2ui/A2UICatalogContext.tsx +79 -0
  37. package/src/v2/a2ui/A2UIMessageRenderer.tsx +125 -37
  38. package/src/v2/a2ui/A2UIToolCallRenderer.tsx +290 -0
  39. package/src/v2/components/CopilotKitInspector.tsx +2 -0
  40. package/src/v2/components/OpenGenerativeUIRenderer.tsx +598 -0
  41. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.tsx +665 -0
  42. package/src/v2/components/chat/CopilotChat.tsx +197 -52
  43. package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +17 -2
  44. package/src/v2/components/chat/CopilotChatAttachmentQueue.tsx +481 -0
  45. package/src/v2/components/chat/CopilotChatAttachmentRenderer.tsx +139 -0
  46. package/src/v2/components/chat/CopilotChatInput.tsx +146 -77
  47. package/src/v2/components/chat/CopilotChatMessageView.tsx +260 -151
  48. package/src/v2/components/chat/CopilotChatSuggestionView.tsx +1 -0
  49. package/src/v2/components/chat/CopilotChatUserMessage.tsx +54 -0
  50. package/src/v2/components/chat/CopilotChatView.tsx +179 -66
  51. package/src/v2/components/chat/__tests__/CopilotChat.attachments.test.tsx +168 -0
  52. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +63 -2
  53. package/src/v2/components/chat/__tests__/CopilotChatInput.test.tsx +544 -1
  54. package/src/v2/components/chat/__tests__/CopilotChatPerf.e2e.test.tsx +268 -0
  55. package/src/v2/components/chat/__tests__/CopilotChatPropsRerender.e2e.test.tsx +249 -0
  56. package/src/v2/components/chat/__tests__/CopilotChatToolRendering.e2e.test.tsx +5 -2
  57. package/src/v2/components/chat/__tests__/CopilotChatToolRerenders.e2e.test.tsx +5 -2
  58. package/src/v2/components/chat/__tests__/MCPAppsActivityRenderer.e2e.test.tsx +60 -3
  59. package/src/v2/components/chat/__tests__/copilot-chat-throttle.test.tsx +138 -0
  60. package/src/v2/components/chat/index.ts +9 -0
  61. package/src/v2/components/chat/scroll-element-context.ts +13 -0
  62. package/src/v2/hooks/__tests__/use-agent-context-timing.e2e.test.tsx +8 -0
  63. package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx +327 -0
  64. package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +1003 -0
  65. package/src/v2/hooks/__tests__/use-agent.e2e.test.tsx +13 -2
  66. package/src/v2/hooks/__tests__/use-attachments.test.tsx +169 -0
  67. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.tsx +23 -4
  68. package/src/v2/hooks/__tests__/use-threads.test.tsx +54 -0
  69. package/src/v2/hooks/index.ts +5 -0
  70. package/src/v2/hooks/use-agent.tsx +220 -15
  71. package/src/v2/hooks/use-attachments.tsx +269 -0
  72. package/src/v2/hooks/use-frontend-tool.tsx +5 -2
  73. package/src/v2/hooks/use-render-activity-message.tsx +9 -2
  74. package/src/v2/hooks/use-render-custom-messages.tsx +6 -1
  75. package/src/v2/hooks/use-threads.tsx +35 -15
  76. package/src/v2/index.ts +5 -1
  77. package/src/v2/lib/__tests__/processPartialHtml.test.ts +112 -0
  78. package/src/v2/lib/__tests__/slots.test.ts +56 -0
  79. package/src/v2/lib/processPartialHtml.ts +45 -0
  80. package/src/v2/lib/slots.tsx +42 -1
  81. package/src/v2/providers/CopilotChatConfigurationProvider.tsx +9 -3
  82. package/src/v2/providers/CopilotKitProvider.tsx +268 -32
  83. package/src/v2/providers/SandboxFunctionsContext.ts +10 -0
  84. package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.tsx +198 -0
  85. package/src/v2/providers/__tests__/CopilotKitProvider.test.tsx +71 -0
  86. package/src/v2/providers/index.ts +7 -0
  87. package/src/v2/styles/globals.css +2 -1
  88. package/src/v2/types/index.ts +1 -0
  89. package/src/v2/types/sandbox-function.ts +11 -0
  90. package/dist/copilotkit-B3Mb1yVE.cjs.map +0 -1
  91. package/dist/copilotkit-DBzgOMby.d.cts.map +0 -1
  92. package/dist/copilotkit-DNYSFuz5.mjs.map +0 -1
  93. package/dist/copilotkit-Dy5w3qEV.d.mts.map +0 -1
  94. package/src/v2/components/__tests__/license-warning-banner.test.tsx +0 -46
@@ -0,0 +1,198 @@
1
+ import { renderHook } from "@testing-library/react";
2
+ import React from "react";
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+ import { z } from "zod";
5
+ import { CopilotKitProvider, useCopilotKit } from "../CopilotKitProvider";
6
+ import { useSandboxFunctions } from "../SandboxFunctionsContext";
7
+ import type { SandboxFunction } from "../../types/sandbox-function";
8
+
9
+ describe("CopilotKitProvider — openGenerativeUI.sandboxFunctions", () => {
10
+ beforeEach(() => {
11
+ vi.spyOn(console, "error").mockImplementation(() => {});
12
+ vi.spyOn(console, "warn").mockImplementation(() => {});
13
+ });
14
+
15
+ afterEach(() => {
16
+ vi.restoreAllMocks();
17
+ });
18
+
19
+ const makeSandboxFunction = (
20
+ name: string,
21
+ overrides?: Partial<SandboxFunction>,
22
+ ): SandboxFunction => ({
23
+ name,
24
+ description: `${name} description`,
25
+ parameters: z.object({ value: z.string() }),
26
+ handler: vi.fn().mockResolvedValue(undefined),
27
+ ...overrides,
28
+ });
29
+
30
+ /** Helper: find the sandbox-functions context entry from the context record */
31
+ function findSandboxContext(
32
+ ctx: Record<string, { description: string; value: string }>,
33
+ ) {
34
+ return Object.values(ctx).find((c) =>
35
+ c.description.includes("Sandbox functions"),
36
+ );
37
+ }
38
+
39
+ describe("SandboxFunctionsContext", () => {
40
+ it("provides sandbox functions to children via context", () => {
41
+ const fns = [makeSandboxFunction("myFn")];
42
+
43
+ const { result } = renderHook(() => useSandboxFunctions(), {
44
+ wrapper: ({ children }) => (
45
+ <CopilotKitProvider openGenerativeUI={{ sandboxFunctions: fns }}>
46
+ {children}
47
+ </CopilotKitProvider>
48
+ ),
49
+ });
50
+
51
+ expect(result.current).toHaveLength(1);
52
+ expect(result.current[0].name).toBe("myFn");
53
+ });
54
+
55
+ it("provides empty array when openGenerativeUI is not set", () => {
56
+ const { result } = renderHook(() => useSandboxFunctions(), {
57
+ wrapper: ({ children }) => (
58
+ <CopilotKitProvider>{children}</CopilotKitProvider>
59
+ ),
60
+ });
61
+
62
+ expect(result.current).toHaveLength(0);
63
+ });
64
+
65
+ it("provides empty array when sandboxFunctions is not set", () => {
66
+ const { result } = renderHook(() => useSandboxFunctions(), {
67
+ wrapper: ({ children }) => (
68
+ <CopilotKitProvider openGenerativeUI={{}}>
69
+ {children}
70
+ </CopilotKitProvider>
71
+ ),
72
+ });
73
+
74
+ expect(result.current).toHaveLength(0);
75
+ });
76
+ });
77
+
78
+ describe("agent context registration", () => {
79
+ it("registers agent context when sandbox functions are provided", () => {
80
+ const fns = [makeSandboxFunction("addToCart")];
81
+
82
+ const { result } = renderHook(() => useCopilotKit(), {
83
+ wrapper: ({ children }) => (
84
+ <CopilotKitProvider openGenerativeUI={{ sandboxFunctions: fns }}>
85
+ {children}
86
+ </CopilotKitProvider>
87
+ ),
88
+ });
89
+
90
+ const sandboxContext = findSandboxContext(
91
+ result.current.copilotkit.context,
92
+ );
93
+ expect(sandboxContext).toBeDefined();
94
+
95
+ const parsed = JSON.parse(sandboxContext!.value);
96
+ expect(parsed).toHaveLength(1);
97
+ expect(parsed[0].name).toBe("addToCart");
98
+ expect(parsed[0].description).toBe("addToCart description");
99
+ expect(parsed[0].parameters).toBeDefined();
100
+ expect(parsed[0].parameters.type).toBe("object");
101
+ });
102
+
103
+ it("does not register agent context when sandbox functions are empty", () => {
104
+ const { result } = renderHook(() => useCopilotKit(), {
105
+ wrapper: ({ children }) => (
106
+ <CopilotKitProvider openGenerativeUI={{ sandboxFunctions: [] }}>
107
+ {children}
108
+ </CopilotKitProvider>
109
+ ),
110
+ });
111
+
112
+ const sandboxContext = findSandboxContext(
113
+ result.current.copilotkit.context,
114
+ );
115
+ expect(sandboxContext).toBeUndefined();
116
+ });
117
+
118
+ it("does not register agent context when openGenerativeUI is omitted", () => {
119
+ const { result } = renderHook(() => useCopilotKit(), {
120
+ wrapper: ({ children }) => (
121
+ <CopilotKitProvider>{children}</CopilotKitProvider>
122
+ ),
123
+ });
124
+
125
+ const sandboxContext = findSandboxContext(
126
+ result.current.copilotkit.context,
127
+ );
128
+ expect(sandboxContext).toBeUndefined();
129
+ });
130
+
131
+ it("includes multiple functions in agent context", () => {
132
+ const fns = [makeSandboxFunction("fnA"), makeSandboxFunction("fnB")];
133
+
134
+ const { result } = renderHook(() => useCopilotKit(), {
135
+ wrapper: ({ children }) => (
136
+ <CopilotKitProvider openGenerativeUI={{ sandboxFunctions: fns }}>
137
+ {children}
138
+ </CopilotKitProvider>
139
+ ),
140
+ });
141
+
142
+ const sandboxContext = findSandboxContext(
143
+ result.current.copilotkit.context,
144
+ );
145
+ const parsed = JSON.parse(sandboxContext!.value);
146
+ expect(parsed).toHaveLength(2);
147
+ expect(parsed.map((f: any) => f.name)).toEqual(["fnA", "fnB"]);
148
+ });
149
+
150
+ it("converts parameters to JSON Schema in agent context", () => {
151
+ const fns = [
152
+ makeSandboxFunction("myFn", {
153
+ parameters: z.object({
154
+ itemId: z.string(),
155
+ quantity: z.number(),
156
+ }),
157
+ }),
158
+ ];
159
+
160
+ const { result } = renderHook(() => useCopilotKit(), {
161
+ wrapper: ({ children }) => (
162
+ <CopilotKitProvider openGenerativeUI={{ sandboxFunctions: fns }}>
163
+ {children}
164
+ </CopilotKitProvider>
165
+ ),
166
+ });
167
+
168
+ const sandboxContext = findSandboxContext(
169
+ result.current.copilotkit.context,
170
+ );
171
+ const parsed = JSON.parse(sandboxContext!.value);
172
+ const params = parsed[0].parameters;
173
+
174
+ expect(params.type).toBe("object");
175
+ expect(params.properties.itemId).toEqual({ type: "string" });
176
+ expect(params.properties.quantity).toEqual({ type: "number" });
177
+ });
178
+
179
+ it("removes agent context on unmount", () => {
180
+ const fns = [makeSandboxFunction("myFn")];
181
+
182
+ const { result, unmount } = renderHook(() => useCopilotKit(), {
183
+ wrapper: ({ children }) => (
184
+ <CopilotKitProvider openGenerativeUI={{ sandboxFunctions: fns }}>
185
+ {children}
186
+ </CopilotKitProvider>
187
+ ),
188
+ });
189
+
190
+ const copilotkit = result.current.copilotkit;
191
+ expect(findSandboxContext(copilotkit.context)).toBeDefined();
192
+
193
+ unmount();
194
+
195
+ expect(findSandboxContext(copilotkit.context)).toBeUndefined();
196
+ });
197
+ });
198
+ });
@@ -573,6 +573,76 @@ describe("CopilotKitProvider", () => {
573
573
  });
574
574
  });
575
575
 
576
+ describe("useSingleEndpoint → runtimeTransport mapping", () => {
577
+ it("maps useSingleEndpoint=true to 'single' transport", () => {
578
+ const { result } = renderHook(() => useCopilotKit(), {
579
+ wrapper: ({ children }) => (
580
+ <CopilotKitProvider useSingleEndpoint={true}>
581
+ {children}
582
+ </CopilotKitProvider>
583
+ ),
584
+ });
585
+
586
+ expect(result.current.copilotkit.runtimeTransport).toBe("single");
587
+ });
588
+
589
+ it("maps useSingleEndpoint=false to 'rest' transport", () => {
590
+ const { result } = renderHook(() => useCopilotKit(), {
591
+ wrapper: ({ children }) => (
592
+ <CopilotKitProvider useSingleEndpoint={false}>
593
+ {children}
594
+ </CopilotKitProvider>
595
+ ),
596
+ });
597
+
598
+ expect(result.current.copilotkit.runtimeTransport).toBe("rest");
599
+ });
600
+
601
+ it("maps omitted useSingleEndpoint to 'auto' transport", () => {
602
+ const { result } = renderHook(() => useCopilotKit(), {
603
+ wrapper: ({ children }) => (
604
+ <CopilotKitProvider>{children}</CopilotKitProvider>
605
+ ),
606
+ });
607
+
608
+ expect(result.current.copilotkit.runtimeTransport).toBe("auto");
609
+ });
610
+
611
+ it("updates transport when useSingleEndpoint prop changes", () => {
612
+ let capturedCopilotkit: ReturnType<typeof useCopilotKit>["copilotkit"];
613
+
614
+ function Collector({ children }: { children?: React.ReactNode }) {
615
+ const { copilotkit } = useCopilotKit();
616
+ capturedCopilotkit = copilotkit;
617
+ return <>{children}</>;
618
+ }
619
+
620
+ const { rerender } = render(
621
+ <CopilotKitProvider useSingleEndpoint={false}>
622
+ <Collector />
623
+ </CopilotKitProvider>,
624
+ );
625
+
626
+ expect(capturedCopilotkit!.runtimeTransport).toBe("rest");
627
+
628
+ rerender(
629
+ <CopilotKitProvider useSingleEndpoint={true}>
630
+ <Collector />
631
+ </CopilotKitProvider>,
632
+ );
633
+
634
+ expect(capturedCopilotkit!.runtimeTransport).toBe("single");
635
+
636
+ rerender(
637
+ <CopilotKitProvider>
638
+ <Collector />
639
+ </CopilotKitProvider>,
640
+ );
641
+
642
+ expect(capturedCopilotkit!.runtimeTransport).toBe("auto");
643
+ });
644
+ });
645
+
576
646
  describe("Edge cases", () => {
577
647
  it("handles empty arrays for tools", () => {
578
648
  const { result } = renderHook(() => useCopilotKit(), {
@@ -583,6 +653,7 @@ describe("CopilotKitProvider", () => {
583
653
  ),
584
654
  });
585
655
 
656
+ // No built-in tools when openGenerativeUI is not configured
586
657
  expect(result.current.copilotkit.tools).toHaveLength(0);
587
658
  expect(result.current.copilotkit.renderToolCalls).toHaveLength(0);
588
659
  });
@@ -12,3 +12,10 @@ export {
12
12
  type CopilotKitProviderProps,
13
13
  type CopilotKitContextValue,
14
14
  } from "./CopilotKitProvider";
15
+
16
+ export type { Anchor as InspectorAnchor } from "@copilotkit/web-inspector";
17
+
18
+ export {
19
+ SandboxFunctionsContext,
20
+ useSandboxFunctions,
21
+ } from "./SandboxFunctionsContext";
@@ -119,7 +119,8 @@
119
119
  }
120
120
 
121
121
  @theme {
122
- --animate-pulse-cursor: pulse-cursor 0.9s cubic-bezier(0.4, 0, 0.2, 1) infinite;
122
+ --animate-pulse-cursor: pulse-cursor 0.9s cubic-bezier(0.4, 0, 0.2, 1)
123
+ infinite;
123
124
  @keyframes pulse-cursor {
124
125
  0%,
125
126
  100% {
@@ -5,3 +5,4 @@ export * from "./frontend-tool";
5
5
  export * from "./human-in-the-loop";
6
6
  export * from "./defineToolCallRenderer";
7
7
  export * from "./interrupt";
8
+ export * from "./sandbox-function";
@@ -0,0 +1,11 @@
1
+ import type { StandardSchemaV1 } from "@copilotkit/shared";
2
+
3
+ export type SandboxFunction<
4
+ TParams extends StandardSchemaV1 = StandardSchemaV1,
5
+ > = {
6
+ name: string;
7
+ description: string;
8
+ parameters: TParams;
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ handler: (args: any) => Promise<unknown>;
11
+ };