@copilotkit/react-core 1.55.0-next.9 → 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 (81) hide show
  1. package/CHANGELOG.md +36 -6
  2. package/dist/{copilotkit-DeOzjPsb.mjs → copilotkit-BY5S1-0P.mjs} +2402 -552
  3. package/dist/copilotkit-BY5S1-0P.mjs.map +1 -0
  4. package/dist/{copilotkit-BqcyhQjT.d.mts → copilotkit-BuhSUZHb.d.mts} +228 -17
  5. package/dist/copilotkit-BuhSUZHb.d.mts.map +1 -0
  6. package/dist/{copilotkit-BDNjFNmk.cjs → copilotkit-Bz5-ImDl.cjs} +2421 -541
  7. package/dist/copilotkit-Bz5-ImDl.cjs.map +1 -0
  8. package/dist/{copilotkit-l-IBF4Xp.d.cts → copilotkit-dwDWYpya.d.cts} +228 -17
  9. package/dist/copilotkit-dwDWYpya.d.cts.map +1 -0
  10. package/dist/index.cjs +1 -1
  11. package/dist/index.d.cts +1 -1
  12. package/dist/index.d.mts +1 -1
  13. package/dist/index.mjs +1 -1
  14. package/dist/index.umd.js +1400 -238
  15. package/dist/index.umd.js.map +1 -1
  16. package/dist/v2/index.cjs +13 -1
  17. package/dist/v2/index.css +1 -1
  18. package/dist/v2/index.d.cts +3 -3
  19. package/dist/v2/index.d.mts +3 -3
  20. package/dist/v2/index.mjs +3 -2
  21. package/dist/v2/index.umd.js +2442 -552
  22. package/dist/v2/index.umd.js.map +1 -1
  23. package/package.json +62 -54
  24. package/scripts/scope-preflight.mjs +1 -2
  25. package/src/components/CopilotListeners.tsx +41 -8
  26. package/src/components/copilot-provider/copilotkit-props.tsx +4 -2
  27. package/src/components/toast/toast-provider.tsx +269 -194
  28. package/src/v2/__tests__/A2UIMessageRenderer.test.tsx +86 -22
  29. package/src/v2/__tests__/utils/test-helpers.tsx +67 -0
  30. package/src/v2/a2ui/A2UICatalogContext.tsx +79 -0
  31. package/src/v2/a2ui/A2UIMessageRenderer.tsx +125 -37
  32. package/src/v2/a2ui/A2UIToolCallRenderer.tsx +290 -0
  33. package/src/v2/components/CopilotKitInspector.tsx +2 -0
  34. package/src/v2/components/OpenGenerativeUIRenderer.tsx +598 -0
  35. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.tsx +665 -0
  36. package/src/v2/components/chat/CopilotChat.tsx +193 -50
  37. package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +17 -2
  38. package/src/v2/components/chat/CopilotChatAttachmentQueue.tsx +481 -0
  39. package/src/v2/components/chat/CopilotChatAttachmentRenderer.tsx +139 -0
  40. package/src/v2/components/chat/CopilotChatInput.tsx +146 -77
  41. package/src/v2/components/chat/CopilotChatMessageView.tsx +253 -149
  42. package/src/v2/components/chat/CopilotChatSuggestionView.tsx +1 -0
  43. package/src/v2/components/chat/CopilotChatUserMessage.tsx +54 -0
  44. package/src/v2/components/chat/CopilotChatView.tsx +179 -66
  45. package/src/v2/components/chat/__tests__/CopilotChat.attachments.test.tsx +168 -0
  46. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +63 -2
  47. package/src/v2/components/chat/__tests__/CopilotChatInput.test.tsx +544 -1
  48. package/src/v2/components/chat/__tests__/CopilotChatPerf.e2e.test.tsx +268 -0
  49. package/src/v2/components/chat/__tests__/CopilotChatPropsRerender.e2e.test.tsx +249 -0
  50. package/src/v2/components/chat/__tests__/MCPAppsActivityRenderer.e2e.test.tsx +43 -2
  51. package/src/v2/components/chat/__tests__/copilot-chat-throttle.test.tsx +138 -0
  52. package/src/v2/components/chat/index.ts +9 -0
  53. package/src/v2/components/chat/scroll-element-context.ts +13 -0
  54. package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +1003 -0
  55. package/src/v2/hooks/__tests__/use-attachments.test.tsx +169 -0
  56. package/src/v2/hooks/__tests__/use-threads.test.tsx +54 -0
  57. package/src/v2/hooks/index.ts +5 -0
  58. package/src/v2/hooks/use-agent.tsx +95 -10
  59. package/src/v2/hooks/use-attachments.tsx +269 -0
  60. package/src/v2/hooks/use-frontend-tool.tsx +5 -2
  61. package/src/v2/hooks/use-render-activity-message.tsx +9 -2
  62. package/src/v2/hooks/use-threads.tsx +35 -15
  63. package/src/v2/index.ts +5 -1
  64. package/src/v2/lib/__tests__/processPartialHtml.test.ts +112 -0
  65. package/src/v2/lib/__tests__/slots.test.ts +56 -0
  66. package/src/v2/lib/processPartialHtml.ts +45 -0
  67. package/src/v2/lib/slots.tsx +42 -1
  68. package/src/v2/providers/CopilotChatConfigurationProvider.tsx +9 -3
  69. package/src/v2/providers/CopilotKitProvider.tsx +268 -32
  70. package/src/v2/providers/SandboxFunctionsContext.ts +10 -0
  71. package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.tsx +198 -0
  72. package/src/v2/providers/__tests__/CopilotKitProvider.test.tsx +71 -0
  73. package/src/v2/providers/index.ts +7 -0
  74. package/src/v2/styles/globals.css +2 -1
  75. package/src/v2/types/index.ts +1 -0
  76. package/src/v2/types/sandbox-function.ts +11 -0
  77. package/dist/copilotkit-BDNjFNmk.cjs.map +0 -1
  78. package/dist/copilotkit-BqcyhQjT.d.mts.map +0 -1
  79. package/dist/copilotkit-DeOzjPsb.mjs.map +0 -1
  80. package/dist/copilotkit-l-IBF4Xp.d.cts.map +0 -1
  81. package/src/v2/components/__tests__/license-warning-banner.test.tsx +0 -46
@@ -97,6 +97,269 @@ export function useToast() {
97
97
  return context;
98
98
  }
99
99
 
100
+ function formatBannerMessage(message: string): string {
101
+ // Try to extract the useful message from JSON first
102
+ const jsonMatch = message.match(/'message':\s*'([^']+)'/);
103
+ if (jsonMatch) {
104
+ return jsonMatch[1];
105
+ }
106
+
107
+ // Strip technical garbage but keep the meaningful message
108
+ let cleaned = message.split(" - ")[0];
109
+ cleaned = cleaned.split(": Error code")[0];
110
+ cleaned = cleaned.replace(/:\s*\d{3}$/, "");
111
+ cleaned = cleaned.replace(/See more:.*$/g, "");
112
+ cleaned = cleaned.trim();
113
+
114
+ return cleaned || "An error occurred.";
115
+ }
116
+
117
+ function extractUrl(message: string): { url: string; text: string } | null {
118
+ const markdownMatch = /\[([^\]]+)\]\(([^)]+)\)/.exec(message);
119
+ if (markdownMatch) {
120
+ return { url: markdownMatch[2], text: "See More" };
121
+ }
122
+ const plainMatch = /(https?:\/\/[^\s)]+)/.exec(message);
123
+ if (plainMatch) {
124
+ return {
125
+ url: plainMatch[0].replace(/[.,;:'"]*$/, ""),
126
+ text: "See More",
127
+ };
128
+ }
129
+ return null;
130
+ }
131
+
132
+ function BannerErrorDisplay({
133
+ bannerError,
134
+ onDismiss,
135
+ }: {
136
+ bannerError: CopilotKitError;
137
+ onDismiss: () => void;
138
+ }) {
139
+ const [detailsExpanded, setDetailsExpanded] = useState(false);
140
+ const severity = getErrorSeverity(bannerError);
141
+ const colors = getErrorColors(severity);
142
+
143
+ // Extract optional error details attached by CopilotListeners
144
+ const details = (bannerError as any).details as
145
+ | {
146
+ code?: string;
147
+ context?: Record<string, any>;
148
+ stack?: string;
149
+ originalMessage?: string;
150
+ }
151
+ | undefined;
152
+
153
+ const link = extractUrl(bannerError.message);
154
+
155
+ return (
156
+ <div
157
+ style={{
158
+ position: "fixed",
159
+ bottom: "20px",
160
+ left: "50%",
161
+ transform: "translateX(-50%)",
162
+ zIndex: 9999,
163
+ backgroundColor: colors.background,
164
+ border: `1px solid ${colors.border}`,
165
+ borderLeft: `4px solid ${colors.border}`,
166
+ borderRadius: "8px",
167
+ padding: "12px 16px",
168
+ fontSize: "13px",
169
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
170
+ backdropFilter: "blur(8px)",
171
+ maxWidth: "min(90vw, 700px)",
172
+ width: "100%",
173
+ boxSizing: "border-box",
174
+ overflow: "hidden",
175
+ }}
176
+ >
177
+ <div
178
+ style={{
179
+ display: "flex",
180
+ justifyContent: "space-between",
181
+ alignItems: "center",
182
+ gap: "10px",
183
+ }}
184
+ >
185
+ <div
186
+ style={{
187
+ display: "flex",
188
+ alignItems: "center",
189
+ gap: "8px",
190
+ flex: 1,
191
+ minWidth: 0,
192
+ }}
193
+ >
194
+ <div
195
+ style={{
196
+ width: "12px",
197
+ height: "12px",
198
+ borderRadius: "50%",
199
+ backgroundColor: colors.border,
200
+ flexShrink: 0,
201
+ }}
202
+ />
203
+ <div
204
+ style={{
205
+ display: "flex",
206
+ alignItems: "center",
207
+ gap: "10px",
208
+ flex: 1,
209
+ minWidth: 0,
210
+ }}
211
+ >
212
+ <div
213
+ style={{
214
+ color: colors.text,
215
+ lineHeight: "1.4",
216
+ fontWeight: "400",
217
+ fontSize: "13px",
218
+ flex: 1,
219
+ wordBreak: "break-all",
220
+ overflowWrap: "break-word",
221
+ maxWidth: "550px",
222
+ overflow: "hidden",
223
+ display: "-webkit-box",
224
+ WebkitLineClamp: 10,
225
+ WebkitBoxOrient: "vertical",
226
+ }}
227
+ >
228
+ {formatBannerMessage(bannerError.message)}
229
+ </div>
230
+
231
+ {link && (
232
+ <button
233
+ onClick={() =>
234
+ window.open(link.url, "_blank", "noopener,noreferrer")
235
+ }
236
+ style={{
237
+ background: colors.border,
238
+ color: "white",
239
+ border: "none",
240
+ borderRadius: "5px",
241
+ padding: "4px 10px",
242
+ fontSize: "11px",
243
+ fontWeight: "500",
244
+ cursor: "pointer",
245
+ transition: "all 0.2s ease",
246
+ flexShrink: 0,
247
+ }}
248
+ onMouseEnter={(e) => {
249
+ e.currentTarget.style.opacity = "0.9";
250
+ e.currentTarget.style.transform = "translateY(-1px)";
251
+ }}
252
+ onMouseLeave={(e) => {
253
+ e.currentTarget.style.opacity = "1";
254
+ e.currentTarget.style.transform = "translateY(0)";
255
+ }}
256
+ >
257
+ {link.text}
258
+ </button>
259
+ )}
260
+
261
+ {details && (
262
+ <button
263
+ onClick={() => setDetailsExpanded(!detailsExpanded)}
264
+ style={{
265
+ background: "transparent",
266
+ border: `1px solid ${colors.border}`,
267
+ borderRadius: "5px",
268
+ padding: "4px 10px",
269
+ fontSize: "11px",
270
+ fontWeight: "500",
271
+ cursor: "pointer",
272
+ color: colors.text,
273
+ flexShrink: 0,
274
+ transition: "all 0.2s ease",
275
+ }}
276
+ onMouseEnter={(e) => {
277
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
278
+ }}
279
+ onMouseLeave={(e) => {
280
+ e.currentTarget.style.background = "transparent";
281
+ }}
282
+ >
283
+ {detailsExpanded ? "Hide Details" : "Show Details"}
284
+ </button>
285
+ )}
286
+ </div>
287
+ </div>
288
+ <button
289
+ onClick={onDismiss}
290
+ style={{
291
+ background: "transparent",
292
+ border: "none",
293
+ color: colors.text,
294
+ cursor: "pointer",
295
+ padding: "2px",
296
+ borderRadius: "3px",
297
+ fontSize: "14px",
298
+ lineHeight: "1",
299
+ opacity: 0.6,
300
+ transition: "all 0.2s ease",
301
+ flexShrink: 0,
302
+ }}
303
+ title="Dismiss"
304
+ onMouseEnter={(e) => {
305
+ e.currentTarget.style.opacity = "1";
306
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
307
+ }}
308
+ onMouseLeave={(e) => {
309
+ e.currentTarget.style.opacity = "0.6";
310
+ e.currentTarget.style.background = "transparent";
311
+ }}
312
+ >
313
+ x
314
+ </button>
315
+ </div>
316
+
317
+ {detailsExpanded && details && (
318
+ <div
319
+ style={{
320
+ marginTop: "10px",
321
+ padding: "10px",
322
+ background: "rgba(0, 0, 0, 0.04)",
323
+ borderRadius: "6px",
324
+ fontSize: "11px",
325
+ fontFamily: "monospace",
326
+ color: colors.text,
327
+ lineHeight: "1.5",
328
+ maxHeight: "200px",
329
+ overflowY: "auto",
330
+ whiteSpace: "pre-wrap",
331
+ wordBreak: "break-all",
332
+ }}
333
+ >
334
+ {details.code && (
335
+ <div>
336
+ <strong>Code:</strong> {details.code}
337
+ </div>
338
+ )}
339
+ {details.originalMessage && (
340
+ <div style={{ marginTop: "4px" }}>
341
+ <strong>Message:</strong> {details.originalMessage}
342
+ </div>
343
+ )}
344
+ {details.context && Object.keys(details.context).length > 0 && (
345
+ <div style={{ marginTop: "4px" }}>
346
+ <strong>Context:</strong>{" "}
347
+ {JSON.stringify(details.context, null, 2)}
348
+ </div>
349
+ )}
350
+ {details.stack && (
351
+ <div style={{ marginTop: "4px", opacity: 0.7 }}>
352
+ <strong>Stack:</strong>
353
+ {"\n"}
354
+ {details.stack}
355
+ </div>
356
+ )}
357
+ </div>
358
+ )}
359
+ </div>
360
+ );
361
+ }
362
+
100
363
  export function ToastProvider({
101
364
  enabled,
102
365
  children,
@@ -169,200 +432,12 @@ export function ToastProvider({
169
432
  return (
170
433
  <ToastContext.Provider value={value}>
171
434
  {/* Banner Error Display */}
172
- {bannerError &&
173
- (() => {
174
- const severity = getErrorSeverity(bannerError);
175
- const colors = getErrorColors(severity);
176
-
177
- return (
178
- <div
179
- style={{
180
- position: "fixed",
181
- bottom: "20px",
182
- left: "50%",
183
- transform: "translateX(-50%)",
184
- zIndex: 9999,
185
- backgroundColor: colors.background,
186
- border: `1px solid ${colors.border}`,
187
- borderLeft: `4px solid ${colors.border}`,
188
- borderRadius: "8px",
189
- padding: "12px 16px",
190
- fontSize: "13px",
191
- boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
192
- backdropFilter: "blur(8px)",
193
- maxWidth: "min(90vw, 700px)",
194
- width: "100%",
195
- boxSizing: "border-box",
196
- overflow: "hidden",
197
- }}
198
- >
199
- <div
200
- style={{
201
- display: "flex",
202
- justifyContent: "space-between",
203
- alignItems: "center",
204
- gap: "10px",
205
- }}
206
- >
207
- <div
208
- style={{
209
- display: "flex",
210
- alignItems: "center",
211
- gap: "8px",
212
- flex: 1,
213
- minWidth: 0,
214
- }}
215
- >
216
- <div
217
- style={{
218
- width: "12px",
219
- height: "12px",
220
- borderRadius: "50%",
221
- backgroundColor: colors.border,
222
- flexShrink: 0,
223
- }}
224
- />
225
- <div
226
- style={{
227
- display: "flex",
228
- alignItems: "center",
229
- gap: "10px",
230
- flex: 1,
231
- minWidth: 0,
232
- }}
233
- >
234
- <div
235
- style={{
236
- color: colors.text,
237
- lineHeight: "1.4",
238
- fontWeight: "400",
239
- fontSize: "13px",
240
- flex: 1,
241
- wordBreak: "break-all",
242
- overflowWrap: "break-word",
243
- maxWidth: "550px",
244
- overflow: "hidden",
245
- display: "-webkit-box",
246
- WebkitLineClamp: 10,
247
- WebkitBoxOrient: "vertical",
248
- }}
249
- >
250
- {(() => {
251
- let message = bannerError.message;
252
-
253
- // Try to extract the useful message from JSON first
254
- const jsonMatch = message.match(
255
- /'message':\s*'([^']+)'/,
256
- );
257
- if (jsonMatch) {
258
- return jsonMatch[1]; // Return the actual error message
259
- }
260
-
261
- // Strip technical garbage but keep the meaningful message
262
- message = message.split(" - ")[0]; // Remove everything after " - {"
263
- message = message.split(": Error code")[0]; // Remove ": Error code: 401"
264
- message = message.replace(/:\s*\d{3}$/, ""); // Remove trailing ": 401"
265
- message = message.replace(/See more:.*$/g, ""); // Remove "See more" links
266
- message = message.trim();
267
-
268
- // If it's still garbage (contains { or '), use fallback
269
- // if (message.includes("{") || message.includes("'")) {
270
- // return "Configuration error.... Please check your setup.";
271
- // }
272
-
273
- return message || "Configuration error occurred.";
274
- })()}
275
- </div>
276
-
277
- {(() => {
278
- const message = bannerError.message;
279
- const markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
280
- const plainUrlRegex = /(https?:\/\/[^\s)]+)/g;
281
-
282
- // Extract the first URL found
283
- let url = null;
284
- let buttonText = "See More";
285
-
286
- // Check for markdown links first
287
- const markdownMatch = markdownLinkRegex.exec(message);
288
- if (markdownMatch) {
289
- url = markdownMatch[2];
290
- buttonText = "See More";
291
- } else {
292
- // Check for plain URLs
293
- const urlMatch = plainUrlRegex.exec(message);
294
- if (urlMatch) {
295
- url = urlMatch[0].replace(/[.,;:'"]*$/, ""); // Remove trailing punctuation
296
- buttonText = "See More";
297
- }
298
- }
299
-
300
- if (!url) return null;
301
-
302
- return (
303
- <button
304
- onClick={() =>
305
- window.open(url, "_blank", "noopener,noreferrer")
306
- }
307
- style={{
308
- background: colors.border,
309
- color: "white",
310
- border: "none",
311
- borderRadius: "5px",
312
- padding: "4px 10px",
313
- fontSize: "11px",
314
- fontWeight: "500",
315
- cursor: "pointer",
316
- transition: "all 0.2s ease",
317
- flexShrink: 0,
318
- }}
319
- onMouseEnter={(e) => {
320
- e.currentTarget.style.opacity = "0.9";
321
- e.currentTarget.style.transform =
322
- "translateY(-1px)";
323
- }}
324
- onMouseLeave={(e) => {
325
- e.currentTarget.style.opacity = "1";
326
- e.currentTarget.style.transform = "translateY(0)";
327
- }}
328
- >
329
- {buttonText}
330
- </button>
331
- );
332
- })()}
333
- </div>
334
- </div>
335
- <button
336
- onClick={() => setBannerError(null)}
337
- style={{
338
- background: "transparent",
339
- border: "none",
340
- color: colors.text,
341
- cursor: "pointer",
342
- padding: "2px",
343
- borderRadius: "3px",
344
- fontSize: "14px",
345
- lineHeight: "1",
346
- opacity: 0.6,
347
- transition: "all 0.2s ease",
348
- flexShrink: 0,
349
- }}
350
- title="Dismiss"
351
- onMouseEnter={(e) => {
352
- e.currentTarget.style.opacity = "1";
353
- e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
354
- }}
355
- onMouseLeave={(e) => {
356
- e.currentTarget.style.opacity = "0.6";
357
- e.currentTarget.style.background = "transparent";
358
- }}
359
- >
360
- ×
361
- </button>
362
- </div>
363
- </div>
364
- );
365
- })()}
435
+ {bannerError && (
436
+ <BannerErrorDisplay
437
+ bannerError={bannerError}
438
+ onDismiss={() => setBannerError(null)}
439
+ />
440
+ )}
366
441
 
367
442
  {/* Toast Display - Deprecated: All errors now show as banners */}
368
443
  {children}
@@ -22,19 +22,25 @@ describe("A2UIMessageRenderer rendering integration", () => {
22
22
  });
23
23
 
24
24
  const content = {
25
- operations: [
25
+ a2ui_operations: [
26
26
  {
27
- beginRendering: {
27
+ version: "v0.9",
28
+ createSurface: {
28
29
  surfaceId: "test-surface",
29
- root: "root",
30
- styles: {},
30
+ catalogId: "https://a2ui.org/specification/v0_9/basic_catalog.json",
31
31
  },
32
32
  },
33
33
  {
34
- surfaceUpdate: {
34
+ version: "v0.9",
35
+ updateComponents: {
35
36
  surfaceId: "test-surface",
36
37
  components: [
37
- { id: "root", text: { literalString: "Hello World" } },
38
+ {
39
+ id: "root",
40
+ component: "Text",
41
+ text: "Hello World",
42
+ variant: "body",
43
+ },
38
44
  ],
39
45
  },
40
46
  },
@@ -69,12 +75,27 @@ describe("A2UIMessageRenderer rendering integration", () => {
69
75
  let setContent: (content: any) => void;
70
76
  const TestWrapper = () => {
71
77
  const [content, _setContent] = useState({
72
- operations: [
73
- { beginRendering: { surfaceId: "test", root: "root", styles: {} } },
78
+ a2ui_operations: [
74
79
  {
75
- surfaceUpdate: {
80
+ version: "v0.9",
81
+ createSurface: {
76
82
  surfaceId: "test",
77
- components: [{ id: "root", text: { literalString: "Initial" } }],
83
+ catalogId:
84
+ "https://a2ui.org/specification/v0_9/basic_catalog.json",
85
+ },
86
+ },
87
+ {
88
+ version: "v0.9",
89
+ updateComponents: {
90
+ surfaceId: "test",
91
+ components: [
92
+ {
93
+ id: "root",
94
+ component: "Text",
95
+ text: "Initial",
96
+ variant: "body",
97
+ },
98
+ ],
78
99
  },
79
100
  },
80
101
  ],
@@ -94,12 +115,27 @@ describe("A2UIMessageRenderer rendering integration", () => {
94
115
 
95
116
  await act(async () => {
96
117
  setContent({
97
- operations: [
98
- { beginRendering: { surfaceId: "test", root: "root", styles: {} } },
118
+ a2ui_operations: [
119
+ {
120
+ version: "v0.9",
121
+ createSurface: {
122
+ surfaceId: "test",
123
+ catalogId:
124
+ "https://a2ui.org/specification/v0_9/basic_catalog.json",
125
+ },
126
+ },
99
127
  {
100
- surfaceUpdate: {
128
+ version: "v0.9",
129
+ updateComponents: {
101
130
  surfaceId: "test",
102
- components: [{ id: "root", text: { literalString: "Updated" } }],
131
+ components: [
132
+ {
133
+ id: "root",
134
+ component: "Text",
135
+ text: "Updated",
136
+ variant: "body",
137
+ },
138
+ ],
103
139
  },
104
140
  },
105
141
  ],
@@ -119,7 +155,7 @@ describe("A2UIMessageRenderer rendering integration", () => {
119
155
  const RenderComponent = renderer.render as React.FC<any>;
120
156
 
121
157
  const TestWrapper = () => (
122
- <RenderComponent content={{ operations: [] }} agent={null} />
158
+ <RenderComponent content={{ a2ui_operations: [] }} agent={null} />
123
159
  );
124
160
 
125
161
  let container: HTMLElement;
@@ -140,19 +176,47 @@ describe("A2UIMessageRenderer rendering integration", () => {
140
176
  const RenderComponent = renderer.render as React.FC<any>;
141
177
 
142
178
  const content = {
143
- operations: [
144
- { beginRendering: { surfaceId: "s1", root: "r1", styles: {} } },
145
- { beginRendering: { surfaceId: "s2", root: "r2", styles: {} } },
179
+ a2ui_operations: [
180
+ {
181
+ version: "v0.9",
182
+ createSurface: {
183
+ surfaceId: "s1",
184
+ catalogId: "https://a2ui.org/specification/v0_9/basic_catalog.json",
185
+ },
186
+ },
187
+ {
188
+ version: "v0.9",
189
+ createSurface: {
190
+ surfaceId: "s2",
191
+ catalogId: "https://a2ui.org/specification/v0_9/basic_catalog.json",
192
+ },
193
+ },
146
194
  {
147
- surfaceUpdate: {
195
+ version: "v0.9",
196
+ updateComponents: {
148
197
  surfaceId: "s1",
149
- components: [{ id: "r1", text: { literalString: "Surface 1" } }],
198
+ components: [
199
+ {
200
+ id: "root",
201
+ component: "Text",
202
+ text: "Surface 1",
203
+ variant: "body",
204
+ },
205
+ ],
150
206
  },
151
207
  },
152
208
  {
153
- surfaceUpdate: {
209
+ version: "v0.9",
210
+ updateComponents: {
154
211
  surfaceId: "s2",
155
- components: [{ id: "r2", text: { literalString: "Surface 2" } }],
212
+ components: [
213
+ {
214
+ id: "root",
215
+ component: "Text",
216
+ text: "Surface 2",
217
+ variant: "body",
218
+ },
219
+ ],
156
220
  },
157
221
  },
158
222
  ],