@assistant-ui/mcp-docs-server 0.1.30 → 0.1.31

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 (208) hide show
  1. package/.docs/organized/code-examples/waterfall.md +1 -1
  2. package/.docs/organized/code-examples/with-a2a.md +2 -2
  3. package/.docs/organized/code-examples/with-ag-ui.md +3 -3
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +5 -5
  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 +79 -50
  8. package/.docs/organized/code-examples/with-cloud-standalone.md +4 -4
  9. package/.docs/organized/code-examples/with-cloud.md +4 -4
  10. package/.docs/organized/code-examples/with-custom-thread-list.md +56 -11
  11. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +7 -7
  12. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +7 -7
  13. package/.docs/organized/code-examples/with-expo.md +16 -16
  14. package/.docs/organized/code-examples/with-external-store.md +2 -2
  15. package/.docs/organized/code-examples/with-ffmpeg.md +5 -5
  16. package/.docs/organized/code-examples/with-generative-ui.md +5 -5
  17. package/.docs/organized/code-examples/with-google-adk.md +4 -4
  18. package/.docs/organized/code-examples/with-heat-graph.md +1 -1
  19. package/.docs/organized/code-examples/with-interactables.md +5 -5
  20. package/.docs/organized/code-examples/with-langchain.md +3 -3
  21. package/.docs/organized/code-examples/with-langgraph.md +3 -3
  22. package/.docs/organized/code-examples/with-livekit.md +8 -8
  23. package/.docs/organized/code-examples/with-opencode.md +99 -54
  24. package/.docs/organized/code-examples/with-parent-id-grouping.md +4 -4
  25. package/.docs/organized/code-examples/with-react-hook-form.md +5 -5
  26. package/.docs/organized/code-examples/with-react-ink.md +1 -1
  27. package/.docs/organized/code-examples/with-react-router.md +8 -8
  28. package/.docs/organized/code-examples/with-store.md +1 -1
  29. package/.docs/organized/code-examples/with-tanstack.md +5 -5
  30. package/.docs/organized/code-examples/with-tap-runtime.md +2 -2
  31. package/.docs/raw/docs/(docs)/cli.mdx +2 -1
  32. package/.docs/raw/docs/(docs)/copilots/assistant-frame.mdx +1 -0
  33. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +10 -3
  34. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +8 -3
  35. package/.docs/raw/docs/(docs)/copilots/make-assistant-visible.mdx +1 -0
  36. package/.docs/raw/docs/(docs)/copilots/model-context.mdx +1 -0
  37. package/.docs/raw/docs/(docs)/copilots/motivation.mdx +1 -0
  38. package/.docs/raw/docs/(docs)/copilots/use-assistant-instructions.mdx +1 -0
  39. package/.docs/raw/docs/(docs)/devtools.mdx +1 -0
  40. package/.docs/raw/docs/(docs)/index.mdx +1 -0
  41. package/.docs/raw/docs/(docs)/installation.mdx +1 -0
  42. package/.docs/raw/docs/(docs)/rtl.mdx +1 -0
  43. package/.docs/raw/docs/(reference)/api-reference/adapters/attachments.mdx +34 -0
  44. package/.docs/raw/docs/(reference)/api-reference/adapters/feedback-speech.mdx +41 -0
  45. package/.docs/raw/docs/(reference)/api-reference/adapters/index.mdx +26 -0
  46. package/.docs/raw/docs/(reference)/api-reference/adapters/persistence.mdx +34 -0
  47. package/.docs/raw/docs/(reference)/api-reference/adapters/runtime.mdx +31 -0
  48. package/.docs/raw/docs/(reference)/api-reference/context-providers/index.mdx +20 -0
  49. package/.docs/raw/docs/(reference)/api-reference/hooks/index.mdx +26 -0
  50. package/.docs/raw/docs/(reference)/api-reference/hooks/model-context.mdx +72 -0
  51. package/.docs/raw/docs/(reference)/api-reference/hooks/runtimes.mdx +41 -0
  52. package/.docs/raw/docs/(reference)/api-reference/hooks/state.mdx +48 -0
  53. package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +30 -0
  54. package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +23 -0
  55. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +21 -0
  56. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +7 -0
  57. package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +65 -0
  58. package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +50 -6
  59. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +15 -0
  60. package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +36 -1
  61. package/.docs/raw/docs/(reference)/api-reference/runtimes/index.mdx +38 -0
  62. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +5 -0
  63. package/.docs/raw/docs/(reference)/migrations/v0-14.mdx +144 -6
  64. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +230 -2
  65. package/.docs/raw/docs/cloud/ai-sdk.mdx +221 -3
  66. package/.docs/raw/docs/cloud/langgraph.mdx +274 -2
  67. package/.docs/raw/docs/{(docs)/guides → guides}/attachments.mdx +41 -36
  68. package/.docs/raw/docs/guides/branching.mdx +76 -0
  69. package/.docs/raw/docs/guides/chain-of-thought.mdx +166 -0
  70. package/.docs/raw/docs/{(docs)/guides → guides}/context-api.mdx +50 -22
  71. package/.docs/raw/docs/{(docs)/guides → guides}/dictation.mdx +2 -0
  72. package/.docs/raw/docs/guides/editing.mdx +102 -0
  73. package/.docs/raw/docs/guides/index.mdx +103 -0
  74. package/.docs/raw/docs/{(docs)/guides → guides}/interactables.mdx +49 -0
  75. package/.docs/raw/docs/{(docs)/guides → guides}/latex.mdx +51 -8
  76. package/.docs/raw/docs/{(docs)/guides → guides}/mentions.mdx +61 -86
  77. package/.docs/raw/docs/{(docs)/guides → guides}/message-timing.mdx +8 -2
  78. package/.docs/raw/docs/{(docs)/guides → guides}/multi-agent.mdx +64 -4
  79. package/.docs/raw/docs/{(docs)/guides → guides}/quoting.mdx +10 -17
  80. package/.docs/raw/docs/{(docs)/guides → guides}/slash-commands.mdx +103 -37
  81. package/.docs/raw/docs/guides/speech.mdx +156 -0
  82. package/.docs/raw/docs/{(docs)/guides → guides}/suggestions.mdx +21 -83
  83. package/.docs/raw/docs/{(docs)/guides → guides}/tool-ui.mdx +108 -36
  84. package/.docs/raw/docs/{(docs)/guides → guides}/tools.mdx +131 -35
  85. package/.docs/raw/docs/{(docs)/guides → guides}/voice.mdx +39 -0
  86. package/.docs/raw/docs/ink/index.mdx +1 -3
  87. package/.docs/raw/docs/ink/migration.mdx +1 -3
  88. package/.docs/raw/docs/ink/primitives.mdx +37 -1
  89. package/.docs/raw/docs/integrations/attachments/custom-adapter.mdx +520 -0
  90. package/.docs/raw/docs/integrations/auth/better-auth.mdx +191 -0
  91. package/.docs/raw/docs/integrations/auth/clerk.mdx +172 -0
  92. package/.docs/raw/docs/integrations/auth/next-auth.mdx +196 -0
  93. package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +79 -0
  94. package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +188 -0
  95. package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +57 -0
  96. package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +201 -0
  97. package/.docs/raw/docs/integrations/gateways/index.mdx +157 -0
  98. package/.docs/raw/docs/integrations/index.mdx +173 -0
  99. package/.docs/raw/docs/integrations/observability/helicone.mdx +130 -0
  100. package/.docs/raw/docs/integrations/observability/langfuse.mdx +156 -0
  101. package/.docs/raw/docs/integrations/observability/langsmith.mdx +146 -0
  102. package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +712 -0
  103. package/.docs/raw/docs/integrations/tools/mcp.mdx +267 -0
  104. package/.docs/raw/docs/primitives/action-bar.mdx +1 -0
  105. package/.docs/raw/docs/primitives/assistant-modal.mdx +1 -0
  106. package/.docs/raw/docs/primitives/attachment.mdx +1 -0
  107. package/.docs/raw/docs/primitives/branch-picker.mdx +1 -0
  108. package/.docs/raw/docs/primitives/chain-of-thought.mdx +90 -85
  109. package/.docs/raw/docs/primitives/composer.mdx +2 -1
  110. package/.docs/raw/docs/primitives/error.mdx +1 -0
  111. package/.docs/raw/docs/primitives/index.mdx +2 -1
  112. package/.docs/raw/docs/primitives/message.mdx +68 -5
  113. package/.docs/raw/docs/primitives/selection-toolbar.mdx +1 -0
  114. package/.docs/raw/docs/primitives/suggestion.mdx +1 -0
  115. package/.docs/raw/docs/primitives/thread-list.mdx +39 -0
  116. package/.docs/raw/docs/primitives/thread.mdx +16 -13
  117. package/.docs/raw/docs/react-native/index.mdx +1 -3
  118. package/.docs/raw/docs/react-native/migration.mdx +1 -3
  119. package/.docs/raw/docs/runtimes/a2a/client-and-hooks.mdx +396 -0
  120. package/.docs/raw/docs/runtimes/a2a/overview.mdx +60 -0
  121. package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +216 -0
  122. package/.docs/raw/docs/runtimes/ag-ui/overview.mdx +70 -0
  123. package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +243 -0
  124. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +123 -0
  125. package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +52 -0
  126. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +71 -131
  127. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +69 -63
  128. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +330 -123
  129. package/.docs/raw/docs/runtimes/concepts/adapters.mdx +265 -0
  130. package/.docs/raw/docs/runtimes/concepts/architecture.mdx +125 -0
  131. package/.docs/raw/docs/runtimes/concepts/stability.mdx +67 -0
  132. package/.docs/raw/docs/runtimes/concepts/threads.mdx +428 -0
  133. package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +703 -0
  134. package/.docs/raw/docs/runtimes/custom/data-stream.mdx +323 -0
  135. package/.docs/raw/docs/runtimes/custom/external-store.mdx +253 -1236
  136. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +746 -0
  137. package/.docs/raw/docs/runtimes/custom/overview.mdx +71 -0
  138. package/.docs/raw/docs/runtimes/google-adk/api.mdx +256 -0
  139. package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +717 -0
  140. package/.docs/raw/docs/runtimes/google-adk/overview.mdx +69 -0
  141. package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +229 -0
  142. package/.docs/raw/docs/runtimes/langchain.mdx +533 -0
  143. package/.docs/raw/docs/runtimes/langgraph/generative-ui.mdx +305 -0
  144. package/.docs/raw/docs/runtimes/langgraph/interrupts.mdx +104 -0
  145. package/.docs/raw/docs/runtimes/langgraph/overview.mdx +84 -0
  146. package/.docs/raw/docs/runtimes/langgraph/quickstart.mdx +496 -0
  147. package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +127 -0
  148. package/.docs/raw/docs/runtimes/langgraph/threads.mdx +113 -0
  149. package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +3 -3
  150. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +0 -23
  151. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +1 -1
  152. package/.docs/raw/docs/runtimes/opencode/hooks.mdx +191 -0
  153. package/.docs/raw/docs/runtimes/opencode/overview.mdx +48 -0
  154. package/.docs/raw/docs/runtimes/opencode/quickstart.mdx +119 -0
  155. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +71 -203
  156. package/.docs/raw/docs/ui/accordion.mdx +1 -0
  157. package/.docs/raw/docs/ui/assistant-modal.mdx +1 -0
  158. package/.docs/raw/docs/ui/assistant-sidebar.mdx +1 -0
  159. package/.docs/raw/docs/ui/attachment.mdx +1 -0
  160. package/.docs/raw/docs/ui/badge.mdx +1 -0
  161. package/.docs/raw/docs/ui/composer-trigger-popover.mdx +1 -0
  162. package/.docs/raw/docs/ui/context-display.mdx +1 -0
  163. package/.docs/raw/docs/ui/diff-viewer.mdx +1 -0
  164. package/.docs/raw/docs/ui/directive-text.mdx +1 -0
  165. package/.docs/raw/docs/ui/file.mdx +1 -0
  166. package/.docs/raw/docs/ui/image.mdx +1 -0
  167. package/.docs/raw/docs/ui/markdown.mdx +2 -14
  168. package/.docs/raw/docs/ui/mermaid.mdx +1 -0
  169. package/.docs/raw/docs/ui/message-timing.mdx +3 -2
  170. package/.docs/raw/docs/ui/model-selector.mdx +1 -0
  171. package/.docs/raw/docs/ui/part-grouping.mdx +325 -313
  172. package/.docs/raw/docs/ui/quote.mdx +1 -0
  173. package/.docs/raw/docs/ui/reasoning.mdx +66 -33
  174. package/.docs/raw/docs/ui/scrollbar.mdx +1 -0
  175. package/.docs/raw/docs/ui/select.mdx +1 -0
  176. package/.docs/raw/docs/ui/sources.mdx +1 -0
  177. package/.docs/raw/docs/ui/streamdown.mdx +1 -0
  178. package/.docs/raw/docs/ui/syntax-highlighting.mdx +1 -0
  179. package/.docs/raw/docs/ui/tabs.mdx +1 -0
  180. package/.docs/raw/docs/ui/thread-list.mdx +17 -0
  181. package/.docs/raw/docs/ui/thread.mdx +56 -1
  182. package/.docs/raw/docs/ui/tool-fallback.mdx +1 -0
  183. package/.docs/raw/docs/ui/tool-group.mdx +39 -11
  184. package/.docs/raw/docs/ui/voice.mdx +1 -0
  185. package/.docs/raw/docs/utilities/heat-graph.mdx +1 -0
  186. package/.docs/raw/docs/utilities/react-o11y.mdx +278 -0
  187. package/.docs/raw/docs/utilities/tw-shimmer.mdx +1 -0
  188. package/package.json +3 -3
  189. package/src/tools/tests/path-traversal.test.ts +1 -1
  190. package/.docs/raw/docs/(docs)/guides/branching.mdx +0 -65
  191. package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +0 -164
  192. package/.docs/raw/docs/(docs)/guides/editing.mdx +0 -66
  193. package/.docs/raw/docs/(docs)/guides/speech.mdx +0 -38
  194. package/.docs/raw/docs/runtimes/a2a/index.mdx +0 -298
  195. package/.docs/raw/docs/runtimes/assistant-transport.mdx +0 -1033
  196. package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +0 -314
  197. package/.docs/raw/docs/runtimes/custom/local.mdx +0 -1464
  198. package/.docs/raw/docs/runtimes/data-stream.mdx +0 -422
  199. package/.docs/raw/docs/runtimes/google-adk/index.mdx +0 -686
  200. package/.docs/raw/docs/runtimes/helicone.mdx +0 -61
  201. package/.docs/raw/docs/runtimes/langchain/comparison.mdx +0 -60
  202. package/.docs/raw/docs/runtimes/langchain/index.mdx +0 -210
  203. package/.docs/raw/docs/runtimes/langgraph/index.mdx +0 -699
  204. package/.docs/raw/docs/runtimes/langgraph/tutorial/index.mdx +0 -12
  205. package/.docs/raw/docs/runtimes/langserve.mdx +0 -116
  206. package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +0 -218
  207. package/.docs/raw/docs/runtimes/mastra/overview.mdx +0 -18
  208. package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +0 -217
@@ -36,6 +36,9 @@ Create a new project in the [assistant-cloud dashboard](https://cloud.assistant-
36
36
 
37
37
  Add the following environment variables to your project:
38
38
 
39
+ <PlatformTabs>
40
+ <Tab value="React">
41
+
39
42
  ```bash title=".env.local"
40
43
  # Frontend API URL from your cloud project settings
41
44
  NEXT_PUBLIC_ASSISTANT_BASE_URL=https://proj-[YOUR-ID].assistant-api.com
@@ -44,6 +47,31 @@ NEXT_PUBLIC_ASSISTANT_BASE_URL=https://proj-[YOUR-ID].assistant-api.com
44
47
  ASSISTANT_API_KEY=your-api-key-here
45
48
  ```
46
49
 
50
+ </Tab>
51
+ <Tab value="React Native">
52
+
53
+ ```bash title=".env"
54
+ # Client API URL from your cloud project settings
55
+ EXPO_PUBLIC_ASSISTANT_BASE_URL=https://proj-[YOUR-ID].assistant-api.com
56
+
57
+ # API key for server-side operations; do not ship this in your app bundle
58
+ ASSISTANT_API_KEY=your-api-key-here
59
+ ```
60
+
61
+ </Tab>
62
+ <Tab value="React Ink">
63
+
64
+ ```bash title=".env"
65
+ # Client API URL from your cloud project settings
66
+ ASSISTANT_BASE_URL=https://proj-[YOUR-ID].assistant-api.com
67
+
68
+ # API key for server-side operations; do not ship this in your CLI bundle
69
+ ASSISTANT_API_KEY=your-api-key-here
70
+ ```
71
+
72
+ </Tab>
73
+ </PlatformTabs>
74
+
47
75
  </Step>
48
76
 
49
77
  <Step>
@@ -52,8 +80,24 @@ ASSISTANT_API_KEY=your-api-key-here
52
80
 
53
81
  Install the required packages:
54
82
 
83
+ <PlatformTabs>
84
+ <Tab value="React">
85
+
55
86
  <InstallCommand npm={["@assistant-ui/react", "@assistant-ui/react-langgraph"]} />
56
87
 
88
+ </Tab>
89
+ <Tab value="React Native">
90
+
91
+ <InstallCommand expo={["@assistant-ui/react-native", "@assistant-ui/react-langgraph", "assistant-cloud"]} />
92
+
93
+ </Tab>
94
+ <Tab value="React Ink">
95
+
96
+ <InstallCommand npm={["@assistant-ui/react-ink", "@assistant-ui/react-langgraph", "assistant-cloud", "ink", "react"]} />
97
+
98
+ </Tab>
99
+ </PlatformTabs>
100
+
57
101
  </Step>
58
102
 
59
103
  <Step>
@@ -62,6 +106,9 @@ Install the required packages:
62
106
 
63
107
  Create a runtime provider that integrates LangGraph with assistant-cloud. Choose between anonymous mode for demos/prototypes or authenticated mode for production:
64
108
 
109
+ <PlatformTabs>
110
+ <Tab value="React">
111
+
65
112
  <Tabs items={["Anonymous", "Authenticated (Clerk)"]}>
66
113
 
67
114
  <Tab value="Anonymous">
@@ -204,6 +251,135 @@ export function MyRuntimeProvider({
204
251
 
205
252
  </Tabs>
206
253
 
254
+ </Tab>
255
+ <Tab value="React Native">
256
+
257
+ ```tsx title="components/runtime-provider.tsx"
258
+ import { useMemo, type ReactNode } from "react";
259
+ import { AssistantRuntimeProvider } from "@assistant-ui/react-native";
260
+ import { AssistantCloud } from "assistant-cloud";
261
+ import {
262
+ type LangChainMessage,
263
+ useLangGraphRuntime,
264
+ } from "@assistant-ui/react-langgraph";
265
+ import { createThread, deleteThread, getThreadState, sendMessage } from "@/lib/chatApi";
266
+
267
+ async function getAssistantToken() {
268
+ // Return a user token from your auth provider.
269
+ return "...";
270
+ }
271
+
272
+ export function MyRuntimeProvider({ children }: { children: ReactNode }) {
273
+ const cloud = useMemo(
274
+ () =>
275
+ new AssistantCloud({
276
+ baseUrl: process.env.EXPO_PUBLIC_ASSISTANT_BASE_URL!,
277
+ authToken: getAssistantToken,
278
+ }),
279
+ [],
280
+ );
281
+
282
+ const runtime = useLangGraphRuntime({
283
+ cloud,
284
+ stream: async function* (messages, { initialize }) {
285
+ const { externalId } = await initialize();
286
+ if (!externalId) throw new Error("Thread not found");
287
+
288
+ return sendMessage({
289
+ threadId: externalId,
290
+ messages,
291
+ });
292
+ },
293
+ create: async () => {
294
+ const { thread_id } = await createThread();
295
+ return { externalId: thread_id };
296
+ },
297
+ load: async (externalId) => {
298
+ const state = await getThreadState(externalId);
299
+ return {
300
+ messages:
301
+ (state.values as { messages?: LangChainMessage[] }).messages ?? [],
302
+ };
303
+ },
304
+ delete: async (externalId) => {
305
+ await deleteThread(externalId);
306
+ },
307
+ });
308
+
309
+ return (
310
+ <AssistantRuntimeProvider runtime={runtime}>
311
+ {children}
312
+ </AssistantRuntimeProvider>
313
+ );
314
+ }
315
+ ```
316
+
317
+ </Tab>
318
+ <Tab value="React Ink">
319
+
320
+ ```tsx title="runtime-provider.tsx"
321
+ import { useMemo, type ReactNode } from "react";
322
+ import { AssistantRuntimeProvider } from "@assistant-ui/react-ink";
323
+ import { AssistantCloud } from "assistant-cloud";
324
+ import {
325
+ type LangChainMessage,
326
+ useLangGraphRuntime,
327
+ } from "@assistant-ui/react-langgraph";
328
+ import { createThread, deleteThread, getThreadState, sendMessage } from "./chat-api.js";
329
+
330
+ async function getAssistantToken() {
331
+ // Return a user token from your auth provider.
332
+ return "...";
333
+ }
334
+
335
+ export function MyRuntimeProvider({ children }: { children: ReactNode }) {
336
+ const cloud = useMemo(
337
+ () =>
338
+ new AssistantCloud({
339
+ baseUrl: process.env.ASSISTANT_BASE_URL!,
340
+ authToken: getAssistantToken,
341
+ }),
342
+ [],
343
+ );
344
+
345
+ const runtime = useLangGraphRuntime({
346
+ cloud,
347
+ stream: async function* (messages, { initialize }) {
348
+ const { externalId } = await initialize();
349
+ if (!externalId) throw new Error("Thread not found");
350
+
351
+ return sendMessage({
352
+ threadId: externalId,
353
+ messages,
354
+ });
355
+ },
356
+ create: async () => {
357
+ const { thread_id } = await createThread();
358
+ return { externalId: thread_id };
359
+ },
360
+ load: async (externalId) => {
361
+ const state = await getThreadState(externalId);
362
+ return {
363
+ messages:
364
+ (state.values as { messages?: LangChainMessage[] }).messages ?? [],
365
+ };
366
+ },
367
+ delete: async (externalId) => {
368
+ await deleteThread(externalId);
369
+ },
370
+ });
371
+
372
+ return (
373
+ <AssistantRuntimeProvider runtime={runtime}>
374
+ {children}
375
+ </AssistantRuntimeProvider>
376
+ );
377
+ }
378
+ ```
379
+
380
+ </Tab>
381
+ </PlatformTabs>
382
+
207
383
  <Callout type="info">
208
384
  The `useLangGraphRuntime` hook accepts `cloud`, `create`, `load`, and `delete` parameters for simplified thread management. The runtime handles the thread lifecycle internally.
209
385
 
@@ -220,6 +396,9 @@ export function MyRuntimeProvider({
220
396
 
221
397
  Install the thread list component:
222
398
 
399
+ <PlatformTabs>
400
+ <Tab value="React">
401
+
223
402
  <Tabs items={["assistant-ui", "shadcn (namespace)", "shadcn"]}>
224
403
  <Tab>
225
404
 
@@ -260,17 +439,110 @@ export default function ChatPage() {
260
439
  }
261
440
  ```
262
441
 
442
+ </Tab>
443
+ <Tab value="React Native">
444
+
445
+ Follow the [React Native setup](/docs/react-native) for `Thread`, then compose it with the native thread-list primitives:
446
+
447
+ ```tsx title="app/chat.tsx"
448
+ import { Text, View } from "react-native";
449
+ import {
450
+ ThreadListItemPrimitive,
451
+ ThreadListPrimitive,
452
+ } from "@assistant-ui/react-native";
453
+ import { Thread } from "@/components/assistant-ui/thread";
454
+
455
+ function ThreadList() {
456
+ return (
457
+ <ThreadListPrimitive.Root>
458
+ <ThreadListPrimitive.New>
459
+ <Text>New chat</Text>
460
+ </ThreadListPrimitive.New>
461
+ <ThreadListPrimitive.Items
462
+ renderItem={({ threadId }) => (
463
+ <ThreadListItemPrimitive.Root key={threadId}>
464
+ <ThreadListItemPrimitive.Trigger>
465
+ <ThreadListItemPrimitive.Title fallback="New conversation" />
466
+ </ThreadListItemPrimitive.Trigger>
467
+ </ThreadListItemPrimitive.Root>
468
+ )}
469
+ />
470
+ </ThreadListPrimitive.Root>
471
+ );
472
+ }
473
+
474
+ export default function ChatPage() {
475
+ return (
476
+ <MyRuntimeProvider>
477
+ <View style={{ flex: 1 }}>
478
+ <ThreadList />
479
+ <Thread />
480
+ </View>
481
+ </MyRuntimeProvider>
482
+ );
483
+ }
484
+ ```
485
+
486
+ </Tab>
487
+ <Tab value="React Ink">
488
+
489
+ Follow the [Ink setup](/docs/ink) for `Thread`, then compose it with the terminal thread-list primitives:
490
+
491
+ ```tsx title="chat.tsx"
492
+ import { Box, Text } from "ink";
493
+ import {
494
+ ThreadListItemPrimitive,
495
+ ThreadListPrimitive,
496
+ } from "@assistant-ui/react-ink";
497
+ import { Thread } from "./components/thread.js";
498
+
499
+ function ThreadList() {
500
+ return (
501
+ <ThreadListPrimitive.Root>
502
+ <ThreadListPrimitive.New>
503
+ <Text color="green">[New chat]</Text>
504
+ </ThreadListPrimitive.New>
505
+ <ThreadListPrimitive.Items
506
+ renderItem={({ threadId }) => (
507
+ <ThreadListItemPrimitive.Root key={threadId}>
508
+ <ThreadListItemPrimitive.Trigger>
509
+ <ThreadListItemPrimitive.Title fallback="New conversation" />
510
+ </ThreadListItemPrimitive.Trigger>
511
+ </ThreadListItemPrimitive.Root>
512
+ )}
513
+ />
514
+ </ThreadListPrimitive.Root>
515
+ );
516
+ }
517
+
518
+ export function ChatPage() {
519
+ return (
520
+ <MyRuntimeProvider>
521
+ <Box flexDirection="column">
522
+ <ThreadList />
523
+ <Thread />
524
+ </Box>
525
+ </MyRuntimeProvider>
526
+ );
527
+ }
528
+ ```
529
+
530
+ </Tab>
531
+ </PlatformTabs>
532
+
263
533
  </Step>
264
534
 
265
535
  </Steps>
266
536
 
267
537
  ## Authentication
268
538
 
269
- The examples above show two authentication modes:
539
+ The React runtime-provider tab shows two authentication modes:
270
540
 
271
- - **Anonymous**: Suitable for demos and prototypes. Creates a browser session-based user ID.
541
+ - **Anonymous**: Suitable for React demos and prototypes. Creates a browser session-based user ID.
272
542
  - **Authenticated**: For production use with user accounts. The authenticated example uses [Clerk](https://clerk.com/), but you can integrate any auth provider.
273
543
 
544
+ The React Native and React Ink tabs use explicit `authToken` callbacks, which is the recommended shape outside browser-session-based demos.
545
+
274
546
  For other authentication providers or custom implementations, see the [Cloud Authorization](/docs/cloud/authorization) guide.
275
547
 
276
548
  ## Next Steps
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Attachments
3
3
  description: Let users attach files, images, and documents to messages.
4
+ platforms: ["react"]
4
5
  ---
5
6
 
6
7
  import { AttachmentSample } from "@/components/docs/samples/attachment";
@@ -57,37 +58,7 @@ const runtime = useChatRuntime();
57
58
 
58
59
  ### Add UI Components
59
60
 
60
- Integrate attachment components into your chat interface:
61
-
62
- ```tsx title="/components/assistant-ui/thread.tsx"
63
- // In your Composer component
64
- import {
65
- ComposerAttachments,
66
- ComposerAddAttachment,
67
- } from "@/components/assistant-ui/attachment";
68
-
69
- const Composer = () => {
70
- return (
71
- <ComposerPrimitive.Root>
72
- <ComposerAttachments />
73
- <ComposerAddAttachment />
74
- <ComposerPrimitive.Input placeholder="Type a message..." />
75
- </ComposerPrimitive.Root>
76
- );
77
- };
78
-
79
- // In your UserMessage component
80
- import { UserMessageAttachments } from "@/components/assistant-ui/attachment";
81
-
82
- const UserMessage = () => {
83
- return (
84
- <MessagePrimitive.Root>
85
- <UserMessageAttachments />
86
- <MessagePrimitive.Parts />
87
- </MessagePrimitive.Root>
88
- );
89
- };
90
- ```
61
+ Integrate the attachment components into your chat interface. See [Attachment UI components](/docs/ui/attachment) for the full install and usage guide.
91
62
 
92
63
  </Step>
93
64
  </Steps>
@@ -143,7 +114,7 @@ const compositeAdapter = new CompositeAttachmentAdapter([
143
114
 
144
115
  ## Creating Custom Attachment Adapters
145
116
 
146
- Build your own adapters for specialized file handling. Below are complete examples for common use cases.
117
+ Build your own adapters for specialized file handling. Below are complete examples for common use cases. For `PendingAttachment` and `CompleteAttachment` type definitions, see [Attachment types](/docs/ui/attachment#attachment-types).
147
118
 
148
119
  ### Vision-Capable Image Adapter
149
120
 
@@ -364,7 +335,7 @@ Provide real-time upload progress using async generators:
364
335
 
365
336
  ```tsx
366
337
  class UploadAttachmentAdapter implements AttachmentAdapter {
367
- accept = "*/*";
338
+ accept = "*";
368
339
 
369
340
  async *add({ file }: { file: File }) {
370
341
  const id = generateId();
@@ -391,8 +362,8 @@ class UploadAttachmentAdapter implements AttachmentAdapter {
391
362
  } as PendingAttachment;
392
363
  }
393
364
 
394
- // Return final pending state
395
- return {
365
+ // Yield final progress so the 100% state reaches the composer
366
+ yield {
396
367
  id,
397
368
  type: "file",
398
369
  name: file.name,
@@ -490,6 +461,40 @@ class ValidatedImageAdapter implements AttachmentAdapter {
490
461
  }
491
462
  ```
492
463
 
464
+ To surface failures in the UI, subscribe to `composer.attachmentAddError`. It fires whenever an add operation produces a failure, in either of two ways:
465
+
466
+ 1. `addAttachment()` rejects: no adapter is configured, the file type does not match `accept`, or the adapter's `add()` throws.
467
+ 2. `addAttachment()` resolves but the adapter returned (or, for async-iterator adapters, yielded) an attachment whose `status.reason === "error"`. The promise resolves successfully, yet the event still fires so the UI can react.
468
+
469
+ The event payload carries a `reason` discriminator and a human-readable `message`, so you can branch UI on the failure mode:
470
+
471
+ | `reason` | When It Fires |
472
+ | ---------------- | ------------------------------------------------------------------------------------------------------ |
473
+ | `no-adapter` | `addAttachment(File)` was called but no `AttachmentAdapter` is configured. |
474
+ | `not-accepted` | The file's content type (or filename extension) did not match `adapter.accept`. External `CreateAttachment` descriptors also trigger this when their `contentType` does not match `adapter.accept`. |
475
+ | `adapter-error` | The adapter's `add()` threw, or returned/yielded an attachment with `status.reason === "error"`. If the adapter produced any attachment before failing, the errored attachment is also visible in `composer.attachments`; if it threw before producing one, the event is the only signal. |
476
+
477
+ ```tsx
478
+ import { toast } from "sonner"; // or your toast library of choice
479
+ import { useAuiEvent } from "@assistant-ui/react";
480
+
481
+ function AttachmentErrorToast() {
482
+ useAuiEvent("composer.attachmentAddError", ({ reason, message, error }) => {
483
+ if (reason === "not-accepted") {
484
+ toast.error("This file type is not supported.");
485
+ } else if (reason === "no-adapter") {
486
+ toast.error("Attachments are not configured for this composer.");
487
+ } else {
488
+ if (error) console.error(error); // underlying Error, useful for logging
489
+ toast.error(message || "Attachment failed to upload.");
490
+ }
491
+ });
492
+ return null;
493
+ }
494
+ ```
495
+
496
+ `attachmentId` is included when the failure is associated with an attachment that was registered (typically `adapter-error` cases). It is `undefined` for `no-adapter` and `not-accepted` failures because those reject before any attachment is registered.
497
+
493
498
  ### External Source Attachments
494
499
 
495
500
  Add attachments from external sources (URLs, API data, CMS references) without needing a `File` object or an `AttachmentAdapter`:
@@ -513,7 +518,7 @@ await aui.composer().addAttachment({
513
518
  });
514
519
  ```
515
520
 
516
- External attachments are added as complete attachments directly — they skip the `AttachmentAdapter` entirely and can be removed without one.
521
+ External attachments are added as complete attachments directly. They bypass the `AttachmentAdapter`'s `add()` step (no upload), but `adapter.accept` is still enforced when an `AttachmentAdapter` is configured: a `CreateAttachment` whose `contentType` does not match `adapter.accept` is rejected and emits `composer.attachmentAddError`. If `contentType` is omitted, the descriptor's filename extension is matched against `adapter.accept` only when `accept` itself contains explicit extension entries (e.g. `.png,.pdf`); MIME-wildcard `accept` strings such as `image/*` always require a matching `contentType`. When no `AttachmentAdapter` is configured, external attachments are added without any content-type check, and they can be removed without an adapter.
517
522
 
518
523
  ### Multiple File Selection
519
524
 
@@ -0,0 +1,76 @@
1
+ ---
2
+ title: Message Branching
3
+ description: Navigate between alternative message versions created by editing or reloading.
4
+ platforms: ["react"]
5
+ ---
6
+
7
+ import { BranchingSample } from "@/components/docs/samples/branching";
8
+
9
+ Branching lets users navigate between alternative versions of a message. A new branch is created when:
10
+
11
+ - A user message is edited
12
+ - An assistant message is reloaded (reload creates a new branch on the same message)
13
+
14
+ Branches are automatically tracked by assistant-ui by observing changes to the `messages` array.
15
+
16
+ ## Shortest Working Pattern
17
+
18
+ <BranchingSample />
19
+
20
+ Place a branch picker inside your message component:
21
+
22
+ ```tsx
23
+ import { BranchPickerPrimitive } from "@assistant-ui/react";
24
+
25
+ const BranchPicker = () => (
26
+ <BranchPickerPrimitive.Root hideWhenSingleBranch>
27
+ <BranchPickerPrimitive.Previous />
28
+ <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
29
+ <BranchPickerPrimitive.Next />
30
+ </BranchPickerPrimitive.Root>
31
+ );
32
+ ```
33
+
34
+ `BranchPickerPrimitive.Previous` and `.Next` automatically disable at branch boundaries and while a run is in flight (unless the runtime supports `switchBranchDuringRun`). For the full primitive API, see [BranchPickerPrimitive](/docs/primitives/branch-picker).
35
+
36
+ ## Triggering Reload
37
+
38
+ `ActionBarPrimitive.Reload` creates a new branch on an assistant message and re-runs from there:
39
+
40
+ ```tsx
41
+ import { ActionBarPrimitive, MessagePrimitive } from "@assistant-ui/react";
42
+
43
+ const AssistantMessage = () => (
44
+ <MessagePrimitive.Root>
45
+ <MessagePrimitive.Parts />
46
+ <ActionBarPrimitive.Root>
47
+ <ActionBarPrimitive.Reload />
48
+ </ActionBarPrimitive.Root>
49
+ </MessagePrimitive.Root>
50
+ );
51
+ ```
52
+
53
+ `Reload` is disabled while `thread.isRunning` or `thread.isDisabled` is true. See [ActionBarPrimitive](/docs/primitives/action-bar) for the full reference.
54
+
55
+ ## Programmatic Branch Navigation
56
+
57
+ For headless or keyboard-shortcut flows, navigate directly to a branch by id via `aui.message().switchToBranch`:
58
+
59
+ ```tsx
60
+ import { useAui } from "@assistant-ui/react";
61
+
62
+ const SwitchToBranch = ({ branchId }: { branchId: string }) => {
63
+ const aui = useAui();
64
+ return (
65
+ <button onClick={() => aui.message().switchToBranch({ branchId })}>
66
+ Go to branch
67
+ </button>
68
+ );
69
+ };
70
+ ```
71
+
72
+ This must be called inside a message context (e.g. nested within `MessagePrimitive.Root`).
73
+
74
+ ## Grouped Parts After Branching
75
+
76
+ Each branch is a distinct message version with its own content parts. `MessagePrimitive.GroupedParts` provides hierarchical adjacent grouping of those parts, useful when a message mixes tool calls and text across branches. See the [MessagePrimitive](/docs/primitives/message) reference for `GroupedParts` usage.
@@ -0,0 +1,166 @@
1
+ ---
2
+ title: Chain of Thought
3
+ description: Group reasoning and tool calls into a collapsible accordion UI.
4
+ platforms: ["react"]
5
+ ---
6
+
7
+ LLMs often produce reasoning steps and tool calls in succession. Chain of Thought lets you visually group these consecutive parts into a single collapsible accordion, giving users a clean "thinking" UI.
8
+
9
+ ## Overview
10
+
11
+ When a model like OpenAI's `o4-mini` responds, it may emit a sequence of reasoning tokens and tool calls before producing its final text answer. Use `MessagePrimitive.GroupedParts` to group those adjacent reasoning and tool-call parts into a single collapsible "thinking" section.
12
+
13
+ <Callout type="info">
14
+ The older `components.ChainOfThought` prop on `MessagePrimitive.Parts` and `components` prop on `ChainOfThoughtPrimitive.Parts` are legacy APIs. They still work for existing code, but new code should use `MessagePrimitive.GroupedParts`.
15
+ </Callout>
16
+
17
+ ## Quick Start
18
+
19
+ <Steps>
20
+ <Step>
21
+
22
+ ### Wire GroupedParts into your assistant message
23
+
24
+ Return the same top-level group for reasoning and tool calls, with nested groups for each type:
25
+
26
+ ```tsx
27
+ import {
28
+ MessagePrimitive,
29
+ } from "@assistant-ui/react";
30
+ import { MarkdownText } from "@/components/assistant-ui/markdown-text";
31
+ import {
32
+ Reasoning,
33
+ ReasoningContent,
34
+ ReasoningRoot,
35
+ ReasoningText,
36
+ ReasoningTrigger,
37
+ } from "@/components/assistant-ui/reasoning";
38
+ import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
39
+ import {
40
+ ToolGroupContent,
41
+ ToolGroupRoot,
42
+ ToolGroupTrigger,
43
+ } from "@/components/assistant-ui/tool-group";
44
+ import type { FC } from "react";
45
+
46
+ const AssistantMessage: FC = () => {
47
+ return (
48
+ <MessagePrimitive.Root>
49
+ <MessagePrimitive.GroupedParts
50
+ groupBy={(part) => {
51
+ if (part.type === "reasoning")
52
+ return ["group-chainOfThought", "group-reasoning"];
53
+ if (part.type === "tool-call")
54
+ return ["group-chainOfThought", "group-tool"];
55
+ return null;
56
+ }}
57
+ >
58
+ {({ part, children }) => {
59
+ switch (part.type) {
60
+ case "group-chainOfThought":
61
+ return <div className="my-2">{children}</div>;
62
+ case "group-reasoning": {
63
+ const running = part.status.type === "running";
64
+ return (
65
+ <ReasoningRoot defaultOpen={running}>
66
+ <ReasoningTrigger active={running} />
67
+ <ReasoningContent aria-busy={running}>
68
+ <ReasoningText>{children}</ReasoningText>
69
+ </ReasoningContent>
70
+ </ReasoningRoot>
71
+ );
72
+ }
73
+ case "group-tool":
74
+ return (
75
+ <ToolGroupRoot>
76
+ <ToolGroupTrigger
77
+ count={part.indices.length}
78
+ active={part.status.type === "running"}
79
+ />
80
+ <ToolGroupContent>{children}</ToolGroupContent>
81
+ </ToolGroupRoot>
82
+ );
83
+ case "text":
84
+ return <MarkdownText />;
85
+ case "reasoning":
86
+ return <Reasoning {...part} />;
87
+ case "tool-call":
88
+ return part.toolUI ?? <ToolFallback {...part} />;
89
+ default:
90
+ return null;
91
+ }
92
+ }}
93
+ </MessagePrimitive.GroupedParts>
94
+ </MessagePrimitive.Root>
95
+ );
96
+ };
97
+ ```
98
+
99
+ </Step>
100
+ <Step>
101
+
102
+ ### Use a Reasoning Model
103
+
104
+ Chain of Thought is most useful with models that produce reasoning tokens (e.g. OpenAI `o4-mini`). Here's an example backend route using the AI SDK:
105
+
106
+ ```tsx title="app/api/chat/route.ts"
107
+ import { openai } from "@ai-sdk/openai";
108
+ import { streamText, convertToModelMessages } from "ai";
109
+
110
+ export async function POST(req: Request) {
111
+ const { messages } = await req.json();
112
+
113
+ const result = streamText({
114
+ model: openai("o4-mini"),
115
+ messages: await convertToModelMessages(messages),
116
+ });
117
+
118
+ return result.toUIMessageStreamResponse();
119
+ }
120
+ ```
121
+
122
+ </Step>
123
+ </Steps>
124
+
125
+ ## LangGraph
126
+
127
+ Chain-of-thought parts are surfaced by the AI SDK's built-in reasoning stream. LangGraph does not emit reasoning tokens in that format, so reasoning grouping will not activate automatically. If you want to display reasoning text from a LangGraph agent, emit it as a custom data part from your graph and render it with `makeAssistantDataUI`. See [generative UI with LangGraph](/docs/runtimes/langgraph/generative-ui) for details.
128
+
129
+ ## Legacy: ChainOfThoughtPrimitive
130
+
131
+ ### Reading Collapsed State
132
+
133
+ For existing `ChainOfThoughtPrimitive` code, use `AuiIf` to conditionally render based on the accordion state:
134
+
135
+ ```tsx
136
+ import { AuiIf, ChainOfThoughtPrimitive } from "@assistant-ui/react";
137
+ import { ChevronDownIcon, ChevronRightIcon } from "lucide-react";
138
+
139
+ const ChainOfThoughtAccordionTrigger = () => {
140
+ return (
141
+ <ChainOfThoughtPrimitive.AccordionTrigger className="flex w-full cursor-pointer items-center gap-2 px-4 py-2 text-sm">
142
+ <AuiIf condition={(s) => s.chainOfThought.collapsed}>
143
+ <ChevronRightIcon className="size-4" />
144
+ </AuiIf>
145
+ <AuiIf condition={(s) => !s.chainOfThought.collapsed}>
146
+ <ChevronDownIcon className="size-4" />
147
+ </AuiIf>
148
+ Thinking
149
+ </ChainOfThoughtPrimitive.AccordionTrigger>
150
+ );
151
+ };
152
+ ```
153
+
154
+ ### API Reference
155
+
156
+ For lower-level legacy compatibility details, see the [`ChainOfThought` primitive reference](/docs/primitives/chain-of-thought).
157
+
158
+ ## Full Example
159
+
160
+ See the complete [with-chain-of-thought example](https://github.com/assistant-ui/assistant-ui/tree/main/examples/with-chain-of-thought) for a working implementation with tool calls and reasoning.
161
+
162
+ ## Related Guides
163
+
164
+ - [Reasoning](/docs/ui/reasoning) — reasoning UI primitives for grouped parts
165
+ - [Generative UI](/docs/guides/tool-ui) — custom UI for tool calls
166
+ - [Tools](/docs/guides/tools) — defining and using tools