@assistant-ui/mcp-docs-server 0.1.23 → 0.1.25

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 (137) hide show
  1. package/.docs/organized/code-examples/waterfall.md +5 -3
  2. package/.docs/organized/code-examples/with-a2a.md +676 -0
  3. package/.docs/organized/code-examples/with-ag-ui.md +7 -8
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +28 -16
  5. package/.docs/organized/code-examples/with-artifacts.md +5 -5
  6. package/.docs/organized/code-examples/with-assistant-transport.md +3 -3
  7. package/.docs/organized/code-examples/with-chain-of-thought.md +34 -26
  8. package/.docs/organized/code-examples/with-cloud-standalone.md +10 -8
  9. package/.docs/organized/code-examples/with-cloud.md +5 -5
  10. package/.docs/organized/code-examples/with-custom-thread-list.md +7 -7
  11. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +8 -8
  12. package/.docs/organized/code-examples/with-expo.md +571 -539
  13. package/.docs/organized/code-examples/with-external-store.md +3 -4
  14. package/.docs/organized/code-examples/with-ffmpeg.md +5 -5
  15. package/.docs/organized/code-examples/with-google-adk.md +353 -0
  16. package/.docs/organized/code-examples/with-heat-graph.md +304 -0
  17. package/.docs/organized/code-examples/with-langgraph.md +25 -23
  18. package/.docs/organized/code-examples/with-parent-id-grouping.md +4 -4
  19. package/.docs/organized/code-examples/with-react-hook-form.md +6 -9
  20. package/.docs/organized/code-examples/with-react-ink.md +265 -0
  21. package/.docs/organized/code-examples/with-react-router.md +10 -11
  22. package/.docs/organized/code-examples/with-store.md +29 -18
  23. package/.docs/organized/code-examples/with-tanstack.md +7 -7
  24. package/.docs/organized/code-examples/with-tap-runtime.md +6 -4
  25. package/.docs/raw/blog/2025-01-31-changelog/index.mdx +1 -1
  26. package/.docs/raw/blog/2026-03-launch-week/index.mdx +227 -0
  27. package/.docs/raw/docs/(docs)/architecture.mdx +1 -1
  28. package/.docs/raw/docs/(docs)/cli.mdx +14 -9
  29. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +8 -3
  30. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +5 -1
  31. package/.docs/raw/docs/(docs)/copilots/{make-assistant-readable.mdx → make-assistant-visible.mdx} +14 -5
  32. package/.docs/raw/docs/(docs)/copilots/model-context.mdx +11 -11
  33. package/.docs/raw/docs/(docs)/copilots/motivation.mdx +2 -2
  34. package/.docs/raw/docs/(docs)/devtools.mdx +3 -2
  35. package/.docs/raw/docs/(docs)/guides/attachments.mdx +9 -11
  36. package/.docs/raw/docs/(docs)/guides/branching.mdx +11 -6
  37. package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +18 -16
  38. package/.docs/raw/docs/(docs)/guides/context-api.mdx +81 -43
  39. package/.docs/raw/docs/(docs)/guides/dictation.mdx +5 -5
  40. package/.docs/raw/docs/(docs)/guides/editing.mdx +16 -7
  41. package/.docs/raw/docs/(docs)/guides/latex.mdx +3 -0
  42. package/.docs/raw/docs/(docs)/guides/message-timing.mdx +2 -1
  43. package/.docs/raw/docs/(docs)/guides/multi-agent.mdx +173 -0
  44. package/.docs/raw/docs/(docs)/guides/quoting.mdx +55 -206
  45. package/.docs/raw/docs/(docs)/guides/speech.mdx +1 -4
  46. package/.docs/raw/docs/(docs)/guides/suggestions.mdx +9 -15
  47. package/.docs/raw/docs/(docs)/guides/tool-ui.mdx +17 -7
  48. package/.docs/raw/docs/(docs)/guides/tools.mdx +24 -9
  49. package/.docs/raw/docs/(docs)/index.mdx +3 -3
  50. package/.docs/raw/docs/(docs)/installation.mdx +69 -46
  51. package/.docs/raw/docs/(reference)/api-reference/context-providers/text-message-part-provider.mdx +20 -6
  52. package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +24 -4
  53. package/.docs/raw/docs/(reference)/api-reference/integrations/react-hook-form.mdx +1 -1
  54. package/.docs/raw/docs/(reference)/api-reference/integrations/vercel-ai-sdk.mdx +20 -19
  55. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +28 -53
  56. package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar.mdx +4 -4
  57. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-modal.mdx +7 -1
  58. package/.docs/raw/docs/(reference)/api-reference/primitives/attachment.mdx +20 -14
  59. package/.docs/raw/docs/(reference)/api-reference/primitives/branch-picker.mdx +1 -1
  60. package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +99 -45
  61. package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +52 -40
  62. package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +343 -23
  63. package/.docs/raw/docs/(reference)/api-reference/primitives/suggestion.mdx +4 -6
  64. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list-item.mdx +4 -2
  65. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +3 -5
  66. package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +169 -22
  67. package/.docs/raw/docs/(reference)/api-reference/runtimes/assistant-runtime.mdx +14 -4
  68. package/.docs/raw/docs/(reference)/api-reference/runtimes/attachment-runtime.mdx +15 -26
  69. package/.docs/raw/docs/(reference)/api-reference/runtimes/composer-runtime.mdx +39 -21
  70. package/.docs/raw/docs/(reference)/api-reference/runtimes/message-part-runtime.mdx +33 -9
  71. package/.docs/raw/docs/(reference)/api-reference/runtimes/message-runtime.mdx +48 -21
  72. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-item-runtime.mdx +36 -7
  73. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +30 -10
  74. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-runtime.mdx +12 -10
  75. package/.docs/raw/docs/(reference)/migrations/deprecation-policy.mdx +1 -1
  76. package/.docs/raw/docs/(reference)/migrations/react-langgraph-v0-7.mdx +9 -4
  77. package/.docs/raw/docs/(reference)/migrations/v0-11.mdx +7 -5
  78. package/.docs/raw/docs/(reference)/migrations/v0-12.mdx +9 -7
  79. package/.docs/raw/docs/(reference)/migrations/v0-14.mdx +159 -0
  80. package/.docs/raw/docs/(reference)/react-compatibility.mdx +5 -134
  81. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +89 -7
  82. package/.docs/raw/docs/cloud/ai-sdk.mdx +19 -5
  83. package/.docs/raw/docs/cloud/langgraph.mdx +13 -3
  84. package/.docs/raw/docs/ink/adapters.mdx +41 -0
  85. package/.docs/raw/docs/ink/custom-backend.mdx +203 -0
  86. package/.docs/raw/docs/ink/hooks.mdx +448 -0
  87. package/.docs/raw/docs/ink/index.mdx +239 -0
  88. package/.docs/raw/docs/ink/migration.mdx +140 -0
  89. package/.docs/raw/docs/ink/primitives.mdx +699 -0
  90. package/.docs/raw/docs/react-native/adapters.mdx +63 -87
  91. package/.docs/raw/docs/react-native/custom-backend.mdx +11 -14
  92. package/.docs/raw/docs/react-native/hooks.mdx +214 -232
  93. package/.docs/raw/docs/react-native/index.mdx +118 -159
  94. package/.docs/raw/docs/react-native/migration.mdx +144 -0
  95. package/.docs/raw/docs/react-native/primitives.mdx +431 -302
  96. package/.docs/raw/docs/runtimes/a2a/index.mdx +294 -0
  97. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +9 -9
  98. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +14 -3
  99. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +53 -0
  100. package/.docs/raw/docs/runtimes/assistant-transport.mdx +59 -25
  101. package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +13 -6
  102. package/.docs/raw/docs/runtimes/custom/external-store.mdx +138 -38
  103. package/.docs/raw/docs/runtimes/custom/local.mdx +184 -42
  104. package/.docs/raw/docs/runtimes/data-stream.mdx +92 -19
  105. package/.docs/raw/docs/runtimes/google-adk/index.mdx +624 -0
  106. package/.docs/raw/docs/runtimes/helicone.mdx +6 -6
  107. package/.docs/raw/docs/runtimes/langgraph/index.mdx +38 -27
  108. package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +1 -1
  109. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +15 -20
  110. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +7 -11
  111. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +8 -11
  112. package/.docs/raw/docs/runtimes/langserve.mdx +6 -7
  113. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +18 -3
  114. package/.docs/raw/docs/ui/context-display.mdx +147 -0
  115. package/.docs/raw/docs/ui/file.mdx +5 -4
  116. package/.docs/raw/docs/ui/image.mdx +5 -4
  117. package/.docs/raw/docs/ui/markdown.mdx +3 -1
  118. package/.docs/raw/docs/ui/model-selector.mdx +8 -8
  119. package/.docs/raw/docs/ui/part-grouping.mdx +7 -10
  120. package/.docs/raw/docs/ui/quote.mdx +210 -0
  121. package/.docs/raw/docs/ui/reasoning.mdx +12 -11
  122. package/.docs/raw/docs/ui/sources.mdx +88 -17
  123. package/.docs/raw/docs/ui/streamdown.mdx +16 -7
  124. package/.docs/raw/docs/ui/thread-list.mdx +11 -13
  125. package/.docs/raw/docs/ui/thread.mdx +28 -33
  126. package/.docs/raw/docs/ui/tool-fallback.mdx +5 -6
  127. package/.docs/raw/docs/ui/tool-group.mdx +9 -8
  128. package/.docs/raw/docs/utilities/heat-graph.mdx +236 -0
  129. package/.docs/raw/docs/utilities/tw-shimmer.mdx +211 -0
  130. package/package.json +4 -4
  131. package/.docs/raw/docs/(reference)/legacy/styled/assistant-modal.mdx +0 -77
  132. package/.docs/raw/docs/(reference)/legacy/styled/decomposition.mdx +0 -635
  133. package/.docs/raw/docs/(reference)/legacy/styled/markdown.mdx +0 -77
  134. package/.docs/raw/docs/(reference)/legacy/styled/scrollbar.mdx +0 -72
  135. package/.docs/raw/docs/(reference)/legacy/styled/thread-width.mdx +0 -22
  136. package/.docs/raw/docs/(reference)/legacy/styled/thread.mdx +0 -77
  137. /package/.docs/raw/docs/cloud/{overview.mdx → index.mdx} +0 -0
@@ -0,0 +1,294 @@
1
+ ---
2
+ title: A2A Protocol
3
+ description: Connect to A2A (Agent-to-Agent) v1.0 protocol servers.
4
+ ---
5
+
6
+ `@assistant-ui/react-a2a` provides a runtime adapter for the [A2A (Agent-to-Agent) v1.0 protocol](https://github.com/a2aproject/A2A), enabling your assistant-ui frontend to communicate with any A2A-compliant agent server.
7
+
8
+ ## Requirements
9
+
10
+ - An A2A v1.0 compatible agent server
11
+ - React 18 or 19
12
+
13
+ ## Installation
14
+
15
+ <InstallCommand npm={["@assistant-ui/react", "@assistant-ui/react-a2a"]} />
16
+
17
+ ## Getting Started
18
+
19
+ <Steps>
20
+ <Step>
21
+ ### Set up the Runtime Provider
22
+
23
+ Create a runtime provider component that connects to your A2A server.
24
+
25
+ ```tsx title="app/MyRuntimeProvider.tsx"
26
+ "use client";
27
+
28
+ import { AssistantRuntimeProvider } from "@assistant-ui/react";
29
+ import { useA2ARuntime } from "@assistant-ui/react-a2a";
30
+
31
+ export function MyRuntimeProvider({
32
+ children,
33
+ }: {
34
+ children: React.ReactNode;
35
+ }) {
36
+ const runtime = useA2ARuntime({
37
+ baseUrl: "http://localhost:9999",
38
+ });
39
+
40
+ return (
41
+ <AssistantRuntimeProvider runtime={runtime}>
42
+ {children}
43
+ </AssistantRuntimeProvider>
44
+ );
45
+ }
46
+ ```
47
+
48
+ </Step>
49
+ <Step>
50
+ ### Add the Thread component
51
+
52
+ ```tsx title="app/page.tsx"
53
+ import { Thread } from "@assistant-ui/react";
54
+ import { MyRuntimeProvider } from "./MyRuntimeProvider";
55
+
56
+ export default function Page() {
57
+ return (
58
+ <MyRuntimeProvider>
59
+ <Thread />
60
+ </MyRuntimeProvider>
61
+ );
62
+ }
63
+ ```
64
+
65
+ </Step>
66
+ <Step>
67
+ ### Setup UI Components
68
+
69
+ Follow the [UI Setup](/docs/ui) guide to setup the UI components.
70
+
71
+ </Step>
72
+ </Steps>
73
+
74
+ ## A2AClient
75
+
76
+ The built-in `A2AClient` handles all communication with the A2A server, including JSON serialization, SSE streaming, ProtoJSON enum normalization, and structured error handling.
77
+
78
+ ```ts
79
+ import { A2AClient } from "@assistant-ui/react-a2a";
80
+
81
+ const client = new A2AClient({
82
+ baseUrl: "https://my-agent.example.com",
83
+ headers: { Authorization: "Bearer <token>" },
84
+ tenant: "my-org", // optional, for multi-tenant servers
85
+ extensions: ["urn:a2a:ext:my-extension"], // optional
86
+ });
87
+ ```
88
+
89
+ You can pass a pre-built client to `useA2ARuntime`:
90
+
91
+ ```tsx
92
+ const runtime = useA2ARuntime({ client });
93
+ ```
94
+
95
+ ### Client Options
96
+
97
+ | Option | Type | Description |
98
+ | --- | --- | --- |
99
+ | `baseUrl` | `string` | Base URL of the A2A server |
100
+ | `headers` | `Record<string, string>` or `() => Record<string, string>` | Static or dynamic headers (e.g. for auth tokens) |
101
+ | `tenant` | `string` | Tenant ID for multi-tenant servers (prepended to URL paths) |
102
+ | `extensions` | `string[]` | Extension URIs to negotiate via `A2A-Extensions` header |
103
+
104
+ ### Client Methods
105
+
106
+ | Method | Description |
107
+ | --- | --- |
108
+ | `sendMessage(message, configuration?, metadata?)` | Send a message (non-streaming) |
109
+ | `streamMessage(message, configuration?, metadata?)` | Send a message with SSE streaming |
110
+ | `getTask(taskId, historyLength?)` | Get a task by ID |
111
+ | `listTasks(request?)` | List tasks with filtering and pagination |
112
+ | `cancelTask(taskId, metadata?)` | Cancel an in-progress task |
113
+ | `subscribeToTask(taskId)` | Subscribe to SSE updates for a task |
114
+ | `getAgentCard()` | Fetch the agent card from `/.well-known/agent-card.json` |
115
+ | `getExtendedAgentCard()` | Fetch the extended (authenticated) agent card |
116
+ | `createTaskPushNotificationConfig(config)` | Create a push notification config |
117
+ | `getTaskPushNotificationConfig(taskId, configId)` | Get a push notification config |
118
+ | `listTaskPushNotificationConfigs(taskId)` | List push notification configs |
119
+ | `deleteTaskPushNotificationConfig(taskId, configId)` | Delete a push notification config |
120
+
121
+ ## useA2ARuntime Options
122
+
123
+ | Option | Type | Description |
124
+ | --- | --- | --- |
125
+ | `client` | `A2AClient` | Pre-built A2A client instance (provide this OR `baseUrl`) |
126
+ | `baseUrl` | `string` | A2A server URL (creates a client automatically) |
127
+ | `headers` | see above | Headers for the auto-created client |
128
+ | `contextId` | `string` | Initial context ID for the conversation |
129
+ | `configuration` | `A2ASendMessageConfiguration` | Default send message configuration |
130
+ | `onError` | `(error: Error) => void` | Error callback |
131
+ | `onCancel` | `() => void` | Cancellation callback |
132
+ | `adapters.attachments` | `AttachmentAdapter` | Custom attachment handling |
133
+ | `adapters.speech` | `SpeechSynthesisAdapter` | Text-to-speech |
134
+ | `adapters.feedback` | `FeedbackAdapter` | Feedback collection |
135
+ | `adapters.history` | `ThreadHistoryAdapter` | Message persistence |
136
+ | `adapters.threadList` | `UseA2AThreadListAdapter` | Thread switching |
137
+
138
+ ## Hooks
139
+
140
+ ### useA2ATask
141
+
142
+ Returns the current A2A task object, including task state and status message.
143
+
144
+ ```tsx
145
+ import { useA2ATask } from "@assistant-ui/react-a2a";
146
+
147
+ function TaskStatus() {
148
+ const task = useA2ATask();
149
+
150
+ if (!task) return null;
151
+
152
+ return <div>Task {task.id}: {task.status.state}</div>;
153
+ }
154
+ ```
155
+
156
+ ### useA2AArtifacts
157
+
158
+ Returns the artifacts generated by the current task.
159
+
160
+ ```tsx
161
+ import { useA2AArtifacts } from "@assistant-ui/react-a2a";
162
+
163
+ function ArtifactList() {
164
+ const artifacts = useA2AArtifacts();
165
+
166
+ return (
167
+ <ul>
168
+ {artifacts.map((artifact) => (
169
+ <li key={artifact.artifactId}>
170
+ {artifact.name}: {artifact.parts.length} parts
171
+ </li>
172
+ ))}
173
+ </ul>
174
+ );
175
+ }
176
+ ```
177
+
178
+ ### useA2AAgentCard
179
+
180
+ Returns the agent card fetched from the server on initialization.
181
+
182
+ ```tsx
183
+ import { useA2AAgentCard } from "@assistant-ui/react-a2a";
184
+
185
+ function AgentInfo() {
186
+ const card = useA2AAgentCard();
187
+
188
+ if (!card) return null;
189
+
190
+ return (
191
+ <div>
192
+ <h3>{card.name}</h3>
193
+ <p>{card.description}</p>
194
+ <div>Skills: {card.skills.map((s) => s.name).join(", ")}</div>
195
+ </div>
196
+ );
197
+ }
198
+ ```
199
+
200
+ ## Task States
201
+
202
+ The A2A protocol defines 9 task states. The runtime maps them to assistant-ui message statuses:
203
+
204
+ | A2A Task State | Description | Message Status |
205
+ | --- | --- | --- |
206
+ | `unspecified` | Unknown/default state | `running` |
207
+ | `submitted` | Task acknowledged | `running` |
208
+ | `working` | Task in progress | `running` |
209
+ | `completed` | Task finished | `complete` |
210
+ | `failed` | Task errored | `incomplete (error)` |
211
+ | `canceled` | Task cancelled | `incomplete (cancelled)` |
212
+ | `rejected` | Agent declined task | `incomplete (error)` |
213
+ | `input_required` | Agent needs user input | `requires-action` |
214
+ | `auth_required` | Authentication needed | `requires-action` |
215
+
216
+ <Callout type="info">
217
+ When a task enters `input_required`, the user can continue the conversation normally. The runtime will send the next message with the same `taskId` to resume the task.
218
+ </Callout>
219
+
220
+ ## Artifacts
221
+
222
+ A2A agents can produce artifacts (files, code, data) alongside their responses. Artifacts are accumulated during streaming and accessible via the `useA2AArtifacts` hook.
223
+
224
+ The runtime supports:
225
+ - **Incremental artifact streaming** via `append` mode
226
+ - **Artifact completion notification** via `onArtifactComplete` callback
227
+ - **Automatic reset** of artifacts on each new run
228
+
229
+ ```tsx
230
+ const runtime = useA2ARuntime({
231
+ baseUrl: "http://localhost:9999",
232
+ onArtifactComplete: (artifact) => {
233
+ console.log("Artifact ready:", artifact.name);
234
+ },
235
+ });
236
+ ```
237
+
238
+ ## Streaming vs Non-Streaming
239
+
240
+ The runtime automatically selects the communication mode based on the agent's capabilities:
241
+
242
+ - If the agent card indicates `capabilities.streaming: true` (or unset), the runtime uses `POST /message:stream` with SSE
243
+ - If `capabilities.streaming: false`, the runtime falls back to `POST /message:send`
244
+
245
+ ## Error Handling
246
+
247
+ The client throws `A2AError` instances with structured error information following the `google.rpc.Status` format:
248
+
249
+ ```tsx
250
+ import { A2AError } from "@assistant-ui/react-a2a";
251
+
252
+ const runtime = useA2ARuntime({
253
+ baseUrl: "http://localhost:9999",
254
+ onError: (error) => {
255
+ if (error instanceof A2AError) {
256
+ console.log(error.code); // HTTP status code
257
+ console.log(error.status); // e.g. "NOT_FOUND"
258
+ console.log(error.details); // google.rpc.ErrorInfo details
259
+ }
260
+ },
261
+ });
262
+ ```
263
+
264
+ ## Multi-Tenancy
265
+
266
+ For multi-tenant A2A servers, pass a `tenant` option to the client:
267
+
268
+ ```ts
269
+ const client = new A2AClient({
270
+ baseUrl: "https://agent.example.com",
271
+ tenant: "my-org",
272
+ });
273
+ ```
274
+
275
+ This prepends `/{tenant}` to all API paths (e.g. `/my-org/message:send`).
276
+
277
+ ## Features
278
+
279
+ | Feature | Supported |
280
+ | --- | --- |
281
+ | Streaming (SSE) | Yes |
282
+ | Non-streaming fallback | Yes |
283
+ | All 9 task states | Yes |
284
+ | Artifacts (text, data, file) | Yes |
285
+ | Agent card discovery | Yes |
286
+ | Multi-tenancy | Yes |
287
+ | Structured errors | Yes |
288
+ | Push notifications CRUD | Yes |
289
+ | Extension negotiation | Yes |
290
+ | Task cancellation | Yes |
291
+ | Message editing | Yes |
292
+ | Message reload | Yes |
293
+ | History persistence | Yes |
294
+ | Thread list management | Yes |
@@ -10,7 +10,7 @@ If you're using AI SDK v4 (legacy), you can integrate with assistant-ui using th
10
10
 
11
11
  <Callout type="warning">
12
12
  AI SDK v4 is now considered legacy. We recommend upgrading to [AI SDK
13
- v5](/docs/runtimes/ai-sdk/use-chat) for improved features and better
13
+ v6](/docs/runtimes/ai-sdk/v6) for improved features and better
14
14
  TypeScript support. This documentation is provided for projects that haven't
15
15
  migrated yet.
16
16
  </Callout>
@@ -63,9 +63,9 @@ export async function POST(req: Request) {
63
63
  ```tsx
64
64
  "use client";
65
65
 
66
- import { Thread } from "@assistant-ui/react";
67
66
  import { AssistantRuntimeProvider } from "@assistant-ui/react";
68
67
  import { useDataStreamRuntime } from "@assistant-ui/react-data-stream";
68
+ import { Thread } from "@/components/assistant-ui/thread";
69
69
 
70
70
  export default function Home() {
71
71
  const runtime = useDataStreamRuntime({
@@ -94,7 +94,7 @@ Alternatively, you can use the older version of the AI SDK integration package,
94
94
  <Callout type="warning">
95
95
  Version 0.1.10 of `@assistant-ui/react-ai-sdk` is no longer actively
96
96
  maintained. We recommend using the `@assistant-ui/react-data-stream` approach
97
- or upgrading to AI SDK v5 for continued support.
97
+ or upgrading to AI SDK v6 for continued support.
98
98
  </Callout>
99
99
 
100
100
  With this legacy version, you would use the `useVercelUseChatRuntime` hook:
@@ -103,9 +103,9 @@ With this legacy version, you would use the `useVercelUseChatRuntime` hook:
103
103
  "use client";
104
104
 
105
105
  import { useChat } from "ai/react";
106
- import { Thread } from "@assistant-ui/react";
107
106
  import { AssistantRuntimeProvider } from "@assistant-ui/react";
108
107
  import { useVercelUseChatRuntime } from "@assistant-ui/react-ai-sdk";
108
+ import { Thread } from "@/components/assistant-ui/thread";
109
109
 
110
110
  export default function Home() {
111
111
  const chat = useChat({
@@ -161,17 +161,17 @@ The `useDataStreamRuntime` hook accepts options similar to AI SDK v4's `useChat`
161
161
  already using AI SDK v4's `useChat` hook, making migration straightforward.
162
162
  </Callout>
163
163
 
164
- ## Migration to AI SDK v5
164
+ ## Migration to AI SDK v6
165
165
 
166
- When you're ready to upgrade to AI SDK v5:
166
+ When you're ready to upgrade to AI SDK v6:
167
167
 
168
168
  1. Replace `@assistant-ui/react-data-stream` with `@assistant-ui/react-ai-sdk`
169
- 2. Update your backend to use AI SDK v5's `streamText` API
169
+ 2. Update your backend to use AI SDK v6's `streamText` API
170
170
  3. Switch from `useDataStreamRuntime` to `useChatRuntime`
171
171
  4. Take advantage of improved TypeScript support and automatic system/tool forwarding
172
172
 
173
- See our [AI SDK v5 documentation](/docs/runtimes/ai-sdk/use-chat) for the complete migration guide.
173
+ See our [AI SDK v6 documentation](/docs/runtimes/ai-sdk/v6) for the complete migration guide.
174
174
 
175
175
  ## Example
176
176
 
177
- For a working example with AI SDK v4, you can adapt the patterns from our [AI SDK examples](https://github.com/assistant-ui/assistant-ui/tree/main/examples) using the `@assistant-ui/react-data-stream` package instead of the v5 integration.
177
+ For a working example with AI SDK v4, you can adapt the patterns from our [AI SDK examples](https://github.com/assistant-ui/assistant-ui/tree/main/examples) using the `@assistant-ui/react-data-stream` package instead of the v6 integration.
@@ -85,9 +85,7 @@ import { AssistantRuntimeProvider } from "@assistant-ui/react";
85
85
  import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
86
86
 
87
87
  export default function Home() {
88
- const runtime = useChatRuntime({
89
- api: "/api/chat",
90
- });
88
+ const runtime = useChatRuntime();
91
89
 
92
90
  return (
93
91
  <AssistantRuntimeProvider runtime={runtime}>
@@ -99,6 +97,18 @@ export default function Home() {
99
97
  }
100
98
  ```
101
99
 
100
+ <Callout type="info">
101
+ `useChatRuntime` was introduced in `@assistant-ui/react-ai-sdk@0.11.3`. If you're using an older 0.x version, use `useVercelUseChatRuntime` with `useChat` from `ai/react` instead:
102
+
103
+ ```tsx
104
+ import { useChat } from "ai/react";
105
+ import { useVercelUseChatRuntime } from "@assistant-ui/react-ai-sdk";
106
+
107
+ const chat = useChat({ api: "/api/chat" });
108
+ const runtime = useVercelUseChatRuntime(chat);
109
+ ```
110
+ </Callout>
111
+
102
112
  </Step>
103
113
  </Steps>
104
114
 
@@ -107,6 +117,7 @@ export default function Home() {
107
117
  | Feature | v5 | v6 |
108
118
  |---------|----|----|
109
119
  | **ai package** | `ai@^5` | `ai@^6` |
120
+ | **@assistant-ui/react-ai-sdk** | `@0.x` | `@latest` |
110
121
  | **@ai-sdk/openai** | `@ai-sdk/openai@^1` | `@ai-sdk/openai@^3` |
111
122
  | **Message type** | `Message` | `UIMessage` |
112
123
  | **convertToModelMessages** | Sync | Async (`await`) |
@@ -101,6 +101,59 @@ export default function Home() {
101
101
  </Step>
102
102
  </Steps>
103
103
 
104
+ ## Tracking Token Usage
105
+
106
+ assistant-ui exports a `useThreadTokenUsage` hook to access thread-level token usage on the client.
107
+ <Steps>
108
+ <Step>
109
+ Use `messageMetadata` in your Next.js route to attach `usage` from `finish` and `modelId` from `finish-step`.
110
+ ```tsx
111
+ import { streamText, convertToModelMessages } from "ai";
112
+ import { frontendTools } from "@assistant-ui/react-ai-sdk";
113
+ export async function POST(req: Request) {
114
+ const { messages, tools, modelName } = await req.json();
115
+ const result = streamText({
116
+ model: getModel(modelName),
117
+ messages: await convertToModelMessages(messages),
118
+ tools: frontendTools(tools),
119
+ });
120
+ return result.toUIMessageStreamResponse({
121
+ messageMetadata: ({ part }) => {
122
+ if (part.type === "finish") {
123
+ return {
124
+ usage: part.totalUsage,
125
+ };
126
+ }
127
+ if (part.type === "finish-step") {
128
+ return {
129
+ modelId: part.response.modelId,
130
+ };
131
+ }
132
+ return undefined;
133
+ },
134
+ });
135
+ }
136
+ ```
137
+ </Step>
138
+ <Step>
139
+ Use `useThreadTokenUsage` to render token usage on the client.
140
+
141
+ ```tsx
142
+ "use client";
143
+
144
+ import { useThreadTokenUsage } from "@assistant-ui/react-ai-sdk";
145
+
146
+ export function TokenCounter() {
147
+ const usage = useThreadTokenUsage();
148
+
149
+ if (!usage) return null;
150
+
151
+ return <div>{usage.totalTokens} total tokens</div>;
152
+ }
153
+ ```
154
+ </Step>
155
+ </Steps>
156
+
104
157
  ## Key Changes from v5
105
158
 
106
159
  | Feature | v5 | v6 |
@@ -69,8 +69,11 @@ The backend endpoint receives POST requests with the following payload:
69
69
  state: T, // The previous state that the frontend has access to
70
70
  commands: AssistantTransportCommand[],
71
71
  system?: string,
72
- tools?: ToolDefinition[],
73
- threadId: string // The current thread/conversation identifier
72
+ tools?: Record<string, ToolJSONSchema>, // Tool definitions keyed by tool name
73
+ threadId: string | null, // The current thread/conversation identifier (null for new threads)
74
+ parentId?: string | null, // The parent message ID (included when editing or branching)
75
+ // ...callSettings (maxTokens, temperature, topP, presencePenalty, frequencyPenalty, seed)
76
+ // ...config (apiKey, baseUrl, modelName)
74
77
  }
75
78
  ```
76
79
 
@@ -333,15 +336,17 @@ The `useAssistantTransportRuntime` hook is used to configure the runtime. It acc
333
336
  initialState: T,
334
337
  api: string,
335
338
  resumeApi?: string,
339
+ protocol?: "data-stream" | "assistant-transport",
336
340
  converter: (state: T, connectionMetadata: ConnectionMetadata) => AssistantTransportState,
337
- headers?: Record<string, string> | (() => Promise<Record<string, string>>),
338
- body?: object,
341
+ headers: Record<string, string> | Headers | (() => Promise<Record<string, string> | Headers>),
342
+ body?: object | (() => Promise<object | undefined>),
339
343
  prepareSendCommandsRequest?: (body: SendCommandsRequestBody) => Record<string, unknown> | Promise<Record<string, unknown>>,
340
344
  capabilities?: { edit?: boolean },
345
+ adapters?: { attachments?: AttachmentAdapter; history?: ThreadHistoryAdapter },
341
346
  onResponse?: (response: Response) => void,
342
347
  onFinish?: () => void,
343
- onError?: (error: Error) => void,
344
- onCancel?: () => void
348
+ onError?: (error: Error, params: { commands: AssistantTransportCommand[]; updateState: (updater: (state: T) => T) => void }) => void | Promise<void>,
349
+ onCancel?: (params: { commands: AssistantTransportCommand[]; updateState: (updater: (state: T) => T) => void; error?: Error }) => void
345
350
  }
346
351
  ```
347
352
 
@@ -354,11 +359,13 @@ The state converter is the core of your frontend integration. It transforms your
354
359
  state: T, // Your agent's state
355
360
  connectionMetadata: {
356
361
  pendingCommands: Command[], // Commands not yet sent to backend
357
- isSending: boolean // Whether a request is in flight
362
+ isSending: boolean, // Whether a request is in flight
363
+ toolStatuses: Record<string, ToolExecutionStatus> // Tool execution status tracking
358
364
  }
359
365
  ) => {
360
366
  messages: ThreadMessage[], // Messages to display
361
- isRunning: boolean // Whether the agent is running
367
+ isRunning: boolean, // Whether the agent is running
368
+ state?: ReadonlyJSONValue // Optional custom agent state
362
369
  }
363
370
  ```
364
371
 
@@ -465,7 +472,7 @@ const runtime = useAssistantTransportRuntime({
465
472
  },
466
473
  onCancel: ({ commands, updateState }) => {
467
474
  console.log("Request cancelled");
468
- console.log("Commands in transit or queued:", commands);
475
+ console.log("Commands (in-transit + queued, or queued-only if called after error):", commands);
469
476
 
470
477
  // Update state to reflect cancellation
471
478
  updateState((currentState) => ({
@@ -476,7 +483,7 @@ const runtime = useAssistantTransportRuntime({
476
483
  });
477
484
  ```
478
485
 
479
- > **Note:** `onError` receives commands that were in transit, while `onCancel` receives both in-transit and queued commands.
486
+ > **Note:** `onError` receives commands that were in transit. `onCancel` receives both in-transit and queued commands when the user cancels directly; when called after an error, it only receives queued commands (in-transit commands are passed to `onError` instead).
480
487
 
481
488
  ## Custom Headers and Body
482
489
 
@@ -600,28 +607,55 @@ for command in request.commands:
600
607
  contact us for more information.
601
608
  </Callout>
602
609
 
603
- To enable resumability, you need to:
610
+ When a user refreshes the page, switches tabs, or reconnects after a network interruption, the backend may still be generating a response. `resumeRun` allows the frontend to reconnect to the active backend stream.
604
611
 
605
- 1. Pass a `resumeApi` URL to `useAssistantTransportRuntime` that points to your sync server
606
- 2. Use the `unstable_resumeRun` API to resume a conversation
612
+ ### Setup
607
613
 
608
- ```typescript
609
- import { useAui } from "@assistant-ui/react";
614
+ Pass a `resumeApi` URL to `useAssistantTransportRuntime` that points to your sync server:
610
615
 
616
+ ```typescript
611
617
  const runtime = useAssistantTransportRuntime({
612
618
  // ... other options
613
619
  api: "http://localhost:8010/assistant",
614
620
  resumeApi: "http://localhost:8010/resume", // Sync server endpoint
615
- // ... other options
616
621
  });
622
+ ```
617
623
 
618
- // Typically called on thread switch or mount to check if sync server has anything to resume
619
- const aui = useAui();
620
- aui.thread().unstable_resumeRun({
621
- parentId: null, // Ignored (will be removed in a future version)
622
- });
624
+ ### Resuming on thread switch or page load
625
+
626
+ When switching to a thread or mounting a component, check if the backend is still running and call `resumeRun`:
627
+
628
+ ```typescript
629
+ import { useAui } from "@assistant-ui/react";
630
+ import { useEffect, useRef } from "react";
631
+
632
+ function useResumeOnMount(threadId: string) {
633
+ const aui = useAui();
634
+ const hasCheckedRef = useRef(false);
635
+
636
+ useEffect(() => {
637
+ if (hasCheckedRef.current) return;
638
+ hasCheckedRef.current = true;
639
+
640
+ const checkAndResume = async () => {
641
+ const status = await fetch(
642
+ `/api/sync-server/status/${threadId}`,
643
+ ).then((r) => r.json());
644
+
645
+ if (status.isRunning) {
646
+ const parentId =
647
+ aui.thread().getState().messages.at(-1)?.id ?? null;
648
+ aui.thread().resumeRun({ parentId });
649
+ }
650
+ };
651
+
652
+ checkAndResume();
653
+ }, [aui, threadId]);
654
+ }
623
655
  ```
624
656
 
657
+ For the AssistantTransport runtime, you do not need to pass a `stream` parameter — the runtime uses the configured `resumeApi` endpoint to reconnect.
658
+
625
659
  ## Accessing Runtime State
626
660
 
627
661
  Use the `useAssistantTransportState` hook to access the current agent state from any component:
@@ -684,12 +718,12 @@ If you're using `createMessageConverter`, you can access the original message fo
684
718
 
685
719
  ```typescript
686
720
  import { unstable_createMessageConverter as createMessageConverter } from "@assistant-ui/react";
687
- import { useMessage } from "@assistant-ui/react";
721
+ import { useAuiState } from "@assistant-ui/react";
688
722
 
689
723
  const messageConverter = createMessageConverter(yourMessageConverter);
690
724
 
691
725
  function MyMessageComponent() {
692
- const message = useMessage();
726
+ const message = useAuiState((s) => s.message);
693
727
 
694
728
  // Get the original message(s) from the converted ThreadMessage
695
729
  const originalMessage = messageConverter.toOriginalMessage(message);
@@ -764,7 +798,7 @@ export function MyRuntimeProvider({ children }) {
764
798
  },
765
799
  onCancel: ({ commands, updateState }) => {
766
800
  console.log("Request cancelled");
767
- console.log("Commands in transit or queued:", commands);
801
+ console.log("Commands (in-transit + queued, or queued-only if called after error):", commands);
768
802
  },
769
803
  });
770
804
 
@@ -861,7 +895,7 @@ export function MyRuntimeProvider({ children }) {
861
895
  },
862
896
  onCancel: ({ commands, updateState }) => {
863
897
  console.log("Request cancelled");
864
- console.log("Commands in transit or queued:", commands);
898
+ console.log("Commands (in-transit + queued, or queued-only if called after error):", commands);
865
899
  },
866
900
  });
867
901
 
@@ -6,7 +6,7 @@ description: Plug a custom thread database for multi-thread persistence.
6
6
 
7
7
  ## Overview
8
8
 
9
- `useRemoteThreadListRuntime` lets you plug a custom thread database into assistant-ui. It keeps the UI and local runtime logic in sync while you provide persistence, archiving, and metadata for every conversation. The hook is exported as `unstable_useRemoteThreadListRuntime`; we refer to it here as **Custom Thread List**.
9
+ `useRemoteThreadListRuntime` lets you plug a custom thread database into assistant-ui. It keeps the UI and local runtime logic in sync while you provide persistence, archiving, and metadata for every conversation.
10
10
 
11
11
  ## When to Use
12
12
 
@@ -63,8 +63,8 @@ When the hook mounts it calls `list()` on your adapter, hydrates existing thread
63
63
  import {
64
64
  AssistantRuntimeProvider,
65
65
  useLocalRuntime,
66
- unstable_useRemoteThreadListRuntime as useRemoteThreadListRuntime,
67
- type unstable_RemoteThreadListAdapter as RemoteThreadListAdapter,
66
+ useRemoteThreadListRuntime,
67
+ type RemoteThreadListAdapter,
68
68
  } from "@assistant-ui/react";
69
69
  import { createAssistantStream } from "assistant-stream";
70
70
  import { myModelAdapter } from "./model-adapter"; // your chat model adapter
@@ -116,12 +116,12 @@ When the hook mounts it calls `list()` on your adapter, hydrates existing thread
116
116
  title: thread.title,
117
117
  };
118
118
  },
119
- async generateTitle(remoteId, messages) {
119
+ async generateTitle(remoteId, unstable_messages) {
120
120
  return createAssistantStream(async (controller) => {
121
121
  const response = await fetch(`/api/threads/${remoteId}/title`, {
122
122
  method: "POST",
123
123
  headers: { "Content-Type": "application/json" },
124
- body: JSON.stringify({ messages }),
124
+ body: JSON.stringify({ messages: unstable_messages }),
125
125
  });
126
126
  const { title } = await response.json();
127
127
  controller.appendText(title);
@@ -198,6 +198,13 @@ When the hook mounts it calls `list()` on your adapter, hydrates existing thread
198
198
  "Return a streaming title generator. You can reuse your model endpoint or queue a background job.",
199
199
  required: true,
200
200
  },
201
+ {
202
+ name: "fetch",
203
+ type: "(threadId: string) => Promise<RemoteThreadMetadata>",
204
+ description:
205
+ "Fetch metadata for a specific thread. Used when switching to a thread not in the initial list.",
206
+ required: true,
207
+ },
201
208
  {
202
209
  name: "unstable_Provider",
203
210
  type: "ComponentType<PropsWithChildren>",
@@ -224,7 +231,7 @@ When implementing a custom history adapter, you must await thread initialization
224
231
  If you're building a history adapter that persists messages to your own database, use `aui.threadListItem().initialize()` to ensure the thread is fully initialized before saving:
225
232
 
226
233
  ```tsx
227
- import { useAui } from "@assistant-ui/react";
234
+ import { useAui } from "@assistant-ui/store";
228
235
 
229
236
  // Inside your unstable_Provider component
230
237
  const aui = useAui();