@copilotkit/a2ui-renderer 1.57.2 → 1.57.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@copilotkit/a2ui-renderer",
3
- "version": "1.57.2",
3
+ "version": "1.57.4",
4
4
  "private": false,
5
5
  "description": "A2UI Renderer for CopilotKit - render A2UI surfaces in React applications",
6
6
  "keywords": [
@@ -9,6 +9,7 @@
9
9
  "copilotkit",
10
10
  "react",
11
11
  "renderer",
12
+ "tanstack-intent",
12
13
  "ui"
13
14
  ],
14
15
  "homepage": "https://github.com/CopilotKit/CopilotKit",
@@ -19,7 +20,8 @@
19
20
  "directory": "packages/a2ui-renderer"
20
21
  },
21
22
  "files": [
22
- "dist"
23
+ "dist",
24
+ "skills"
23
25
  ],
24
26
  "type": "module",
25
27
  "main": "./dist/index.cjs",
@@ -44,6 +46,7 @@
44
46
  "zod-to-json-schema": "^3.24.1"
45
47
  },
46
48
  "devDependencies": {
49
+ "@tanstack/intent": "^0.0.29",
47
50
  "@testing-library/react": "^16.0.0",
48
51
  "@types/markdown-it": "^14.1.2",
49
52
  "@types/react": "^19.2.3",
@@ -0,0 +1,308 @@
1
+ ---
2
+ name: a2ui-renderer
3
+ description: >
4
+ Render A2UI (Agent-to-UI declarative surfaces) in CopilotKit v2. Enable the
5
+ runtime via CopilotRuntime({ a2ui: {...} }), then enable the provider via
6
+ <CopilotKitProvider a2ui={{ theme }}>. Auto-activates via /info — do NOT
7
+ manually pass renderActivityMessages. createA2UIMessageRenderer ships from
8
+ @copilotkit/react-core/v2; low-level primitives (A2UIProvider, A2UIRenderer,
9
+ createCatalog) ship from @copilotkit/a2ui-renderer. Covers theme
10
+ customization, createSurface dedup, action-bridge try/finally cleanup. Load
11
+ when an agent emits A2UI operations (createSurface / updateComponents /
12
+ updateDataModel), when wiring a2ui on CopilotRuntime, or when styling A2UI
13
+ surfaces.
14
+ type: framework
15
+ library: copilotkit
16
+ framework: react
17
+ library_version: "1.56.2"
18
+ requires:
19
+ - copilotkit/react-core
20
+ - copilotkit/runtime
21
+ sources:
22
+ - "CopilotKit/CopilotKit:packages/a2ui-renderer/src/index.ts"
23
+ - "CopilotKit/CopilotKit:packages/a2ui-renderer/src/react-renderer/index.ts"
24
+ - "CopilotKit/CopilotKit:packages/react-core/src/v2/a2ui/A2UIMessageRenderer.tsx"
25
+ - "CopilotKit/CopilotKit:packages/react-core/src/v2/providers/CopilotKitProvider.tsx"
26
+ - "CopilotKit/CopilotKit:packages/runtime/src/v2/runtime/core/runtime.ts"
27
+ ---
28
+
29
+ This skill builds on copilotkit/react-core (for CopilotKitProvider fundamentals) and
30
+ copilotkit/runtime (for CopilotRuntime fundamentals). Read those first.
31
+
32
+ ## Setup
33
+
34
+ A2UI has two halves. The runtime declares a2ui middleware; the client enables
35
+ the a2ui prop on the provider. Once both are set, `/info` flags A2UI and the
36
+ client auto-mounts `createA2UIMessageRenderer` — you do NOT wire
37
+ `renderActivityMessages` yourself.
38
+
39
+ ### Runtime side (`app/routes/api.copilotkit.$.tsx`)
40
+
41
+ ```tsx
42
+ import type { Route } from "./+types/api.copilotkit.$";
43
+ import {
44
+ CopilotRuntime,
45
+ createCopilotRuntimeHandler,
46
+ BuiltInAgent,
47
+ convertInputToTanStackAI,
48
+ } from "@copilotkit/runtime/v2";
49
+ import { chat } from "@tanstack/ai";
50
+ import { openaiText } from "@tanstack/ai-openai";
51
+
52
+ const agent = new BuiltInAgent({
53
+ type: "tanstack",
54
+ factory: ({ input, abortController }) => {
55
+ const { messages, systemPrompts } = convertInputToTanStackAI(input);
56
+ return chat({
57
+ adapter: openaiText("gpt-4o"),
58
+ messages,
59
+ systemPrompts,
60
+ abortController,
61
+ });
62
+ },
63
+ });
64
+
65
+ const runtime = new CopilotRuntime({
66
+ agents: { default: agent },
67
+ // Enabling this key causes /info to advertise A2UI to the client.
68
+ a2ui: {},
69
+ });
70
+
71
+ const handler = createCopilotRuntimeHandler({
72
+ runtime,
73
+ basePath: "/api/copilotkit",
74
+ });
75
+
76
+ export async function loader({ request }: Route.LoaderArgs) {
77
+ return handler(request);
78
+ }
79
+ export async function action({ request }: Route.ActionArgs) {
80
+ return handler(request);
81
+ }
82
+ ```
83
+
84
+ ### Client side (`app/root.tsx` or the app shell)
85
+
86
+ ```tsx
87
+ import { CopilotKitProvider, CopilotChat } from "@copilotkit/react-core/v2";
88
+ import "@copilotkit/react-core/v2/styles.css";
89
+
90
+ export default function App() {
91
+ return (
92
+ <CopilotKitProvider
93
+ runtimeUrl="/api/copilotkit"
94
+ a2ui={{
95
+ theme: {
96
+ // Theme object forwarded to A2UIProvider → ThemeProvider.
97
+ // Tokens map to A2UI's basic catalog CSS vars.
98
+ colors: { primary: "#0ea5e9" },
99
+ },
100
+ }}
101
+ >
102
+ <CopilotChat agentId="default" className="h-full" />
103
+ </CopilotKitProvider>
104
+ );
105
+ }
106
+ ```
107
+
108
+ ## Core Patterns
109
+
110
+ ### Custom catalog
111
+
112
+ Pass a custom catalog to extend the built-in component set. `createCatalog`
113
+ and `extractSchema` let the agent see what components it may render.
114
+
115
+ ```tsx
116
+ import { createCatalog } from "@copilotkit/a2ui-renderer";
117
+ import { z } from "zod";
118
+
119
+ const theme = { colors: { primary: "#0ea5e9" } };
120
+
121
+ // Definitions are platform-agnostic (Zod schemas + descriptions).
122
+ // Renderers are platform-specific (React components).
123
+ // TypeScript enforces that renderer keys match definition keys exactly.
124
+ const definitions = {
125
+ ProductCard: {
126
+ description: "A product card with title and price",
127
+ props: z.object({ title: z.string(), price: z.number() }),
128
+ },
129
+ };
130
+
131
+ const catalog = createCatalog(
132
+ definitions,
133
+ {
134
+ ProductCard: ({ props }) => (
135
+ <div className="rounded-xl border p-3">
136
+ <div className="font-medium">{props.title}</div>
137
+ <div className="text-sm text-muted-foreground">${props.price}</div>
138
+ </div>
139
+ ),
140
+ },
141
+ { includeBasicCatalog: true },
142
+ );
143
+
144
+ <CopilotKitProvider runtimeUrl="/api/copilotkit" a2ui={{ theme, catalog }}>
145
+ <CopilotChat agentId="default" />
146
+ </CopilotKitProvider>;
147
+ ```
148
+
149
+ `extractSchema(definitions)` is available for passing a JSON-serializable
150
+ view of the definitions to the runtime's `a2ui.schema` config — it is not
151
+ a generic type helper. Type parameters erase at runtime; the agent needs a
152
+ real runtime schema value (Zod).
153
+
154
+ ### Override the loading skeleton
155
+
156
+ ```tsx
157
+ <CopilotKitProvider
158
+ runtimeUrl="/api/copilotkit"
159
+ a2ui={{
160
+ theme,
161
+ loadingComponent: () => <div className="animate-pulse">Building UI…</div>,
162
+ }}
163
+ >
164
+ <CopilotChat agentId="default" />
165
+ </CopilotKitProvider>
166
+ ```
167
+
168
+ ## Common Mistakes
169
+
170
+ ### CRITICAL forgetting runtime.a2ui
171
+
172
+ Wrong:
173
+
174
+ ```tsx
175
+ // server
176
+ new CopilotRuntime({ agents: { default: agent } });
177
+ // client
178
+ <CopilotKitProvider runtimeUrl="/api/copilotkit" a2ui={{ theme }} />;
179
+ ```
180
+
181
+ Correct:
182
+
183
+ ```tsx
184
+ // server
185
+ new CopilotRuntime({ agents: { default: agent }, a2ui: {} });
186
+ // client
187
+ <CopilotKitProvider runtimeUrl="/api/copilotkit" a2ui={{ theme }} />;
188
+ ```
189
+
190
+ Without `runtime.a2ui`, `/info` never flags A2UI and the provider's a2ui prop
191
+ silently no-ops — the renderer never mounts.
192
+
193
+ Source: packages/runtime/src/v2/runtime/core/runtime.ts:55-58,217,242
194
+
195
+ ### HIGH manually wiring renderActivityMessages for A2UI
196
+
197
+ Wrong:
198
+
199
+ ```tsx
200
+ import { createA2UIMessageRenderer } from "@copilotkit/react-core/v2";
201
+
202
+ <CopilotKitProvider
203
+ runtimeUrl="/api/copilotkit"
204
+ renderActivityMessages={[createA2UIMessageRenderer({ theme })]}
205
+ />;
206
+ ```
207
+
208
+ Correct:
209
+
210
+ ```tsx
211
+ <CopilotKitProvider runtimeUrl="/api/copilotkit" a2ui={{ theme }} />
212
+ ```
213
+
214
+ CopilotKitProvider auto-detects runtime A2UI via `/info` and injects the
215
+ built-in renderer. Passing it through `renderActivityMessages` duplicates the
216
+ renderer and can race with the auto-injected one.
217
+
218
+ Source: packages/react-core/src/v2/providers/CopilotKitProvider.tsx:188-222,294-296
219
+
220
+ ### MEDIUM re-emitting createSurface on every snapshot
221
+
222
+ Wrong:
223
+
224
+ ```python
225
+ # Pseudocode — inside your agent generator. Exact API names/kwargs vary by
226
+ # A2UI SDK version; consult your SDK's docs for real call shapes.
227
+ async def agent_generator():
228
+ # agent re-emits createSurface operation on every state delta
229
+ async for update in stream:
230
+ yield a2ui.create_surface(surface_id="main", ...) # every tick
231
+ yield a2ui.update_components(...)
232
+ ```
233
+
234
+ Correct:
235
+
236
+ ```python
237
+ # Pseudocode — inside your agent generator.
238
+ # Emit createSurface once per surfaceId; use updateComponents / updateDataModel
239
+ # for changes.
240
+ async def agent_generator():
241
+ yield a2ui.create_surface(surface_id="main", ...) # once
242
+ async for update in stream:
243
+ yield a2ui.update_components(surface_id="main", ...)
244
+ ```
245
+
246
+ The MessageProcessor dedups on `surfaceId` but re-emitting is an agent-side
247
+ bug — the client re-runs reconciliation logic for nothing and flickers.
248
+
249
+ Source: packages/react-core/src/v2/a2ui/A2UIMessageRenderer.tsx:218-226
250
+
251
+ ### MEDIUM custom action bridge without a2uiAction cleanup
252
+
253
+ Wrong:
254
+
255
+ ```ts
256
+ copilotkit.setProperties({ ...copilotkit.properties, a2uiAction: msg });
257
+ await copilotkit.runAgent({ agent });
258
+ // no finally — a2uiAction leaks into the next run's properties
259
+ ```
260
+
261
+ Correct:
262
+
263
+ ```ts
264
+ try {
265
+ copilotkit.setProperties({ ...copilotkit.properties, a2uiAction: msg });
266
+ await copilotkit.runAgent({ agent });
267
+ } finally {
268
+ if (copilotkit.properties) {
269
+ const { a2uiAction, ...rest } = copilotkit.properties;
270
+ copilotkit.setProperties(rest);
271
+ }
272
+ }
273
+ ```
274
+
275
+ The built-in bridge always strips `a2uiAction` in `finally`, guarded by a
276
+ `copilotkit.properties` null-check so it can't mask the original `runAgent`
277
+ error with a `TypeError` during destructuring. Skipping cleanup keeps the
278
+ previous action attached to subsequent runs.
279
+
280
+ Source: packages/react-core/src/v2/a2ui/A2UIMessageRenderer.tsx:146-167
281
+
282
+ ### MEDIUM installing @copilotkitnext/a2ui-renderer
283
+
284
+ Wrong:
285
+
286
+ ```ts
287
+ import { createA2UIMessageRenderer } from "@copilotkitnext/a2ui-renderer";
288
+ ```
289
+
290
+ Correct:
291
+
292
+ ```ts
293
+ // Low-level primitives (rarely needed — CopilotKitProvider a2ui prop is the default path):
294
+ import {
295
+ A2UIProvider,
296
+ A2UIRenderer,
297
+ createCatalog,
298
+ } from "@copilotkit/a2ui-renderer";
299
+ // Auto-mounted renderer lives in react-core/v2:
300
+ import { createA2UIMessageRenderer } from "@copilotkit/react-core/v2";
301
+ ```
302
+
303
+ This package ships as `@copilotkit/a2ui-renderer`, not
304
+ `@copilotkitnext/a2ui-renderer`. The `@copilotkitnext/` scope is reserved
305
+ for other packages that ship under it separately — do not assume it applies
306
+ here.
307
+
308
+ Source: packages/a2ui-renderer/package.json