@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
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Mentions
3
3
  description: Let users @-mention tools or custom items in the composer to guide the LLM.
4
+ platforms: ["react"]
4
5
  ---
5
6
 
6
7
  Mentions let users type `@` in the composer to open a popover picker, select an item (e.g. a tool), and insert a directive into the message text. The LLM can then use the directive as a hint.
@@ -82,6 +83,63 @@ const myAdapter: Unstable_TriggerAdapter = {
82
83
  };
83
84
  ```
84
85
 
86
+ ### Async Mention Search
87
+
88
+ The adapter interface is synchronous, but the data it reads can come from any async source. Load results into React state (or a query cache) and read the current snapshot inside the adapter methods. The adapter re-creates on each render, so the popover always sees the latest results.
89
+
90
+ **With React state and `useEffect`:**
91
+
92
+ ```tsx
93
+ import { useState, useEffect, useMemo } from "react";
94
+ import type { Unstable_TriggerAdapter } from "@assistant-ui/core";
95
+
96
+ function useUserMentionAdapter(query: string) {
97
+ const [users, setUsers] = useState<{ id: string; name: string }[]>([]);
98
+
99
+ useEffect(() => {
100
+ if (!query) return;
101
+ let cancelled = false;
102
+ fetchUsers(query).then((results) => {
103
+ if (!cancelled) setUsers(results);
104
+ });
105
+ return () => { cancelled = true; };
106
+ }, [query]);
107
+
108
+ const adapter: Unstable_TriggerAdapter = useMemo(() => ({
109
+ categories: () => [],
110
+ categoryItems: () => [],
111
+ search: () =>
112
+ users.map((u) => ({ id: u.id, type: "user", label: u.name })),
113
+ }), [users]);
114
+
115
+ return adapter;
116
+ }
117
+ ```
118
+
119
+ `query` here is the text the user typed after `@`. You can read it from `unstable_useTriggerPopoverScopeContext` if you need it inside the component tree, or pass it as state from a controlled input.
120
+
121
+ **With React Query:**
122
+
123
+ ```tsx
124
+ import { useQuery } from "@tanstack/react-query";
125
+ import type { Unstable_TriggerAdapter } from "@assistant-ui/core";
126
+
127
+ function useMentionAdapter(query: string): Unstable_TriggerAdapter {
128
+ const { data = [] } = useQuery({
129
+ queryKey: ["mention-search", query],
130
+ queryFn: () => fetchUsers(query),
131
+ enabled: query.length > 0,
132
+ });
133
+
134
+ return useMemo(() => ({
135
+ categories: () => [],
136
+ categoryItems: () => [],
137
+ search: () =>
138
+ data.map((u) => ({ id: u.id, type: "user", label: u.name })),
139
+ }), [data]);
140
+ }
141
+ ```
142
+
85
143
  Pass the adapter to `TriggerPopover` and declare a `Directive` sub-primitive to bind the insertion behavior:
86
144
 
87
145
  ```tsx
@@ -333,27 +391,7 @@ import { LexicalComposerInput } from "@assistant-ui/react-lexical";
333
391
 
334
392
  ## Rendering Mentions in Messages
335
393
 
336
- Use `DirectiveText` as the `Text` component for user messages so directives render as inline chips instead of raw syntax:
337
-
338
- ```tsx
339
- import { DirectiveText } from "@/components/assistant-ui/directive-text";
340
-
341
- <MessagePrimitive.Parts
342
- components={{
343
- Text: DirectiveText,
344
- }}
345
- />
346
- ```
347
-
348
- For assistant messages, keep using your markdown renderer (e.g. `MarkdownText`) — the LLM typically does not emit directive syntax.
349
-
350
- For a custom formatter, use `createDirectiveText`:
351
-
352
- ```tsx
353
- import { createDirectiveText } from "@/components/assistant-ui/directive-text";
354
-
355
- const MyDirectiveText = createDirectiveText(myFormatter);
356
- ```
394
+ Use `DirectiveText` as the `Text` component for user messages so directives render as inline chips instead of raw syntax. See the [Directive Text](/docs/ui/directive-text) guide for setup and customization.
357
395
 
358
396
  ## Processing Mentions on the Backend
359
397
 
@@ -467,74 +505,11 @@ Use the trigger popover primitives to build a fully custom popover:
467
505
 
468
506
  ### Primitives Reference
469
507
 
470
- | Primitive | Description |
471
- | --- | --- |
472
- | `Unstable_TriggerPopoverRoot` | Root provider — groups one or more triggers, manages plugin registry |
473
- | `Unstable_TriggerPopover` | Declares a trigger (id, char, adapter) and renders the popover container |
474
- | `Unstable_TriggerPopover.Directive` | Behavior sub-primitive — inserts a formatted directive into the composer on selection |
475
- | `Unstable_TriggerPopover.Action` | Behavior sub-primitive — runs a callback on selection; inserts a chip by default |
476
- | `Unstable_TriggerPopoverCategories` | Render-function for the top-level category list |
477
- | `Unstable_TriggerPopoverCategoryItem` | Button that drills into a category (`role="option"`, auto `data-highlighted`) |
478
- | `Unstable_TriggerPopoverItems` | Render-function for items within the active category or search results |
479
- | `Unstable_TriggerPopoverItem` | Button that selects an item (`role="option"`, auto `data-highlighted`) |
480
- | `Unstable_TriggerPopoverBack` | Button that navigates back from items to categories |
481
-
482
- See the [Composer API reference](/docs/api-reference/primitives/composer) for full prop details.
508
+ See the [Composer Primitives](/docs/primitives/composer) reference for the full list of trigger popover primitives and their props.
483
509
 
484
510
  ## Combining with Slash Commands
485
511
 
486
- Mentions and [slash commands](/docs/guides/slash-commands) coexist on the same composer — they're both just triggers on the shared `TriggerPopoverRoot`:
487
-
488
- ```tsx
489
- <ComposerPrimitive.Unstable_TriggerPopoverRoot>
490
- <ComposerPrimitive.Root>
491
- <ComposerPrimitive.Input placeholder="Type @ to mention, / for commands..." />
492
- <ComposerPrimitive.Send />
493
-
494
- {/* Mention popover (shows on @) */}
495
- <ComposerPrimitive.Unstable_TriggerPopover
496
- char="@"
497
- adapter={mention.adapter}
498
- >
499
- <ComposerPrimitive.Unstable_TriggerPopover.Directive {...mention.directive} />
500
- <ComposerPrimitive.Unstable_TriggerPopoverCategories>
501
- {(categories) => categories.map((cat) => (
502
- <ComposerPrimitive.Unstable_TriggerPopoverCategoryItem key={cat.id} categoryId={cat.id}>
503
- {cat.label}
504
- </ComposerPrimitive.Unstable_TriggerPopoverCategoryItem>
505
- ))}
506
- </ComposerPrimitive.Unstable_TriggerPopoverCategories>
507
- <ComposerPrimitive.Unstable_TriggerPopoverItems>
508
- {(items) => items.map((item) => (
509
- <ComposerPrimitive.Unstable_TriggerPopoverItem key={item.id} item={item}>
510
- {item.label}
511
- </ComposerPrimitive.Unstable_TriggerPopoverItem>
512
- ))}
513
- </ComposerPrimitive.Unstable_TriggerPopoverItems>
514
- </ComposerPrimitive.Unstable_TriggerPopover>
515
-
516
- {/* Slash command popover (shows on /) */}
517
- <ComposerPrimitive.Unstable_TriggerPopover
518
- char="/"
519
- adapter={slashAdapter}
520
- >
521
- <ComposerPrimitive.Unstable_TriggerPopover.Action
522
- formatter={unstable_defaultDirectiveFormatter}
523
- onExecute={(item) => commandHandlers[item.id]?.()}
524
- />
525
- <ComposerPrimitive.Unstable_TriggerPopoverItems>
526
- {(items) => items.map((item, index) => (
527
- <ComposerPrimitive.Unstable_TriggerPopoverItem key={item.id} item={item} index={index}>
528
- {item.label}
529
- </ComposerPrimitive.Unstable_TriggerPopoverItem>
530
- ))}
531
- </ComposerPrimitive.Unstable_TriggerPopoverItems>
532
- </ComposerPrimitive.Unstable_TriggerPopover>
533
- </ComposerPrimitive.Root>
534
- </ComposerPrimitive.Unstable_TriggerPopoverRoot>
535
- ```
536
-
537
- Each `TriggerPopover` declares its own scope — its popover UI reads state only from that declaration, so `@` and `/` never collide.
512
+ Mentions and slash commands coexist on the same composer. See [Combining Slash Commands and Mentions](/docs/guides/slash-commands#combining-with-mentions) for the full pattern.
538
513
 
539
514
  ## Related
540
515
 
@@ -1,10 +1,15 @@
1
1
  ---
2
2
  title: Message Timing
3
3
  description: Display stream timing metadata like duration, tokens per second, and time to first token.
4
+ platforms: ["react"]
4
5
  ---
5
6
 
6
7
  Display stream performance metrics — duration, tokens per second, TTFT — on assistant messages.
7
8
 
9
+ <Callout type="warn">
10
+ This feature is experimental. The `useMessageTiming()` API and the set of tracked fields may change in future versions.
11
+ </Callout>
12
+
8
13
  <Callout type="info">
9
14
  The [`MessageTiming`](/docs/ui/message-timing) registry component provides a ready-made badge + popover UI. This guide covers the underlying `useMessageTiming()` hook for custom implementations and runtime-specific setup.
10
15
  </Callout>
@@ -67,14 +72,15 @@ const AssistantMessage: FC = () => {
67
72
 
68
73
  | Runtime | Supported | Notes |
69
74
  |---------|:-:|-------|
70
- | DataStream | Yes | Automatic via `AssistantMessageAccumulator` |
75
+ | [Data Stream](/docs/runtimes/custom/data-stream) | Yes | Automatic via `AssistantMessageAccumulator` |
71
76
  | AI SDK (`useChatRuntime`) | Yes | Automatic via client-side tracking |
72
77
  | Local (`useLocalRuntime`) | Yes | Pass timing in `ChatModelRunResult.metadata` |
73
78
  | ExternalStore | Yes | Pass timing in `ThreadMessageLike.metadata` |
74
79
  | LangGraph | No | Not yet implemented |
75
80
  | AG-UI | No | Not yet implemented |
81
+ | OpenCode | No | Not yet implemented |
76
82
 
77
- ### DataStream
83
+ ### Data Stream
78
84
 
79
85
  Timing is tracked automatically inside `AssistantMessageAccumulator`. No setup required.
80
86
 
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Multi-Agent
3
3
  description: Render sub-agent conversations inside tool call UIs.
4
+ platforms: ["react"]
4
5
  ---
5
6
 
6
7
  In a multi-agent (orchestrator) architecture, a main agent invokes sub-agents via tool calls. Each sub-agent may produce its own conversation (user/assistant messages, tool calls, etc.). assistant-ui supports rendering these nested conversations using the `MessagePartPrimitive.Messages` primitive.
@@ -51,7 +52,10 @@ const ResearchAgentToolUI = makeAssistantToolUI({
51
52
 
52
53
  ### Provide the Messages from the Backend
53
54
 
54
- Your backend must populate the `messages` field on the tool call result. For example, with the AI SDK:
55
+ Your backend must populate the `messages` field on the tool call result.
56
+
57
+ <Tabs items={["AI SDK", "LangGraph"]}>
58
+ <Tab value="AI SDK">
55
59
 
56
60
  ```ts title="api/chat/route.ts"
57
61
  tools: {
@@ -62,7 +66,6 @@ tools: {
62
66
  const subAgentMessages = await runResearcherAgent(query);
63
67
  return {
64
68
  answer: subAgentMessages.at(-1)?.content,
65
- // The messages field is picked up by assistant-ui
66
69
  messages: subAgentMessages,
67
70
  };
68
71
  },
@@ -70,9 +73,53 @@ tools: {
70
73
  },
71
74
  ```
72
75
 
76
+ </Tab>
77
+ <Tab value="LangGraph">
78
+
79
+ With `@assistant-ui/react-langgraph`, use `unstable_createLangGraphStream` and set `unstable_allowCancellation: true` to wire up the stop button. When your graph runs a subgraph, the subgraph's messages appear on `ToolCallMessagePart.messages` automatically once you handle the `onSubgraphValues` / `onSubgraphUpdates` events.
80
+
81
+ ```ts title="runtime.ts"
82
+ import {
83
+ useLangGraphRuntime,
84
+ unstable_createLangGraphStream,
85
+ } from "@assistant-ui/react-langgraph";
86
+
87
+ const runtime = useLangGraphRuntime({
88
+ unstable_allowCancellation: true,
89
+ stream: unstable_createLangGraphStream({
90
+ client,
91
+ assistantId,
92
+ // "custom" is required for generative UI; "updates" for subgraph events
93
+ streamMode: ["messages", "updates", "custom"],
94
+ // abort the run server-side when the user clicks stop
95
+ onDisconnect: "cancel",
96
+ }),
97
+ eventHandlers: {
98
+ onSubgraphValues: (namespace, values) => {
99
+ // namespace = e.g. "tools:call_abc" — the sub-agent's node path
100
+ // values contains the subgraph state, including its messages array
101
+ },
102
+ onSubgraphUpdates: (namespace, updates) => {
103
+ // incremental state updates from the subgraph
104
+ },
105
+ onSubgraphError: (namespace, error) => {
106
+ // error scoped to the subgraph; does not mark the parent message failed
107
+ },
108
+ onMessageChunk: (chunk, metadata) => {
109
+ // metadata.namespace is set when the chunk originates from a subgraph
110
+ // use it to attribute the chunk to the correct sub-agent
111
+ },
112
+ },
113
+ });
114
+ ```
115
+
116
+ See [LangGraph Streaming](/docs/runtimes/langgraph/streaming) for the full event handler reference.
117
+
118
+ </Tab>
119
+ </Tabs>
120
+
73
121
  <Callout type="info">
74
- The exact mechanism for populating `messages` depends on your backend
75
- framework. The key requirement is that the tool result's corresponding
122
+ The key requirement is that the tool result's corresponding
76
123
  `ToolCallMessagePart` includes a `messages` array of `ThreadMessage` objects.
77
124
  </Callout>
78
125
 
@@ -95,6 +142,17 @@ function App() {
95
142
  </Step>
96
143
  </Steps>
97
144
 
145
+ ## Subgraph Namespace Events
146
+
147
+ When using LangGraph, subgraph events carry a `namespace` that identifies which sub-agent emitted them. This lets you attribute messages and state to specific sub-agents without polling or manual coordination.
148
+
149
+ - `onSubgraphValues(namespace, values)` fires when a subgraph emits a full state snapshot. Use the `values.messages` array to populate `ToolCallMessagePart.messages` for that sub-agent.
150
+ - `onSubgraphUpdates(namespace, updates)` fires for incremental state patches from a subgraph.
151
+ - `onSubgraphError(namespace, error)` fires when a subgraph fails. The parent message is not marked incomplete; only top-level errors trigger that.
152
+ - `onMessageChunk(chunk, metadata)` includes `metadata.namespace` when the chunk originates from a subgraph. Use this to display per-sub-agent streaming indicators.
153
+
154
+ The `namespace` value mirrors the pipe-separated suffix on the LangGraph event name (e.g. `values|tools:call_abc` gives `"tools:call_abc"`).
155
+
98
156
  ## Recursive Sub-Agents
99
157
 
100
158
  If a sub-agent's tool calls also have nested messages, the same pattern applies recursively:
@@ -172,3 +230,5 @@ function SubConversation({
172
230
  - [Generative UI](/docs/guides/tool-ui) — Creating tool call UIs
173
231
  - [MessagePartPrimitive](/docs/api-reference/primitives/message-part) — API reference for message part primitives
174
232
  - [Sub-Agent Model Tracking](/docs/cloud/ai-sdk#sub-agent-model-tracking) — Track delegated model usage and costs in the Cloud dashboard
233
+ - [LangGraph Streaming](/docs/runtimes/langgraph/streaming) — Event handlers, subgraph events, and message metadata
234
+ - [LangGraph Generative UI](/docs/runtimes/langgraph/generative-ui) — Structured UI components emitted by your graph
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Quote Selected Text
3
3
  description: Let users select and quote text from messages. Full guide including backend handling and programmatic API.
4
+ platforms: ["react"]
4
5
  ---
5
6
 
6
7
  import { QuoteComposerSample } from "@/components/docs/samples/quote-composer";
@@ -9,17 +10,11 @@ import { QuoteComposerSample } from "@/components/docs/samples/quote-composer";
9
10
 
10
11
  ## Get Started
11
12
 
12
- The **[Quote](/docs/ui/quote)** registry component gives you everything you need out of the box, including a floating selection toolbar, composer quote preview, and inline quote display.
13
+ Install and wire up the `quote` registry component by following the [Quote component page](/docs/ui/quote). It covers the install command, component placement, and the `injectQuoteContext` helper for forwarding quote data to the LLM.
13
14
 
14
- <InstallCommand shadcn={["quote"]} />
15
-
16
- It ships three composable pieces:
17
-
18
- - **QuoteBlock** renders quoted text inline in user messages
19
- - **SelectionToolbar** is a floating toolbar that appears on text selection
20
- - **ComposerQuotePreview** shows the pending quote inside the composer
21
-
22
- See the [Quote component page](/docs/ui/quote) for full setup steps and API reference.
15
+ <Callout type="warn">
16
+ **Limitations:** only one quote can be active at a time. `setQuote` replaces the previous quote instead of appending. The floating toolbar only appears when the selection is entirely within a single message part; cross-message and cross-part selections are ignored.
17
+ </Callout>
23
18
 
24
19
  ---
25
20
 
@@ -132,7 +127,7 @@ function CustomQuoteDisplay() {
132
127
 
133
128
  ## Programmatic API
134
129
 
135
- Set or clear quotes via the composer runtime:
130
+ Set or clear quotes via `useAui` from `@assistant-ui/react`. Call `aui.thread().composer().setQuote()` when your component is rendered outside of a specific thread context, or `aui.composer().setQuote()` when it is rendered inside a thread:
136
131
 
137
132
  ```tsx
138
133
  import { useAui } from "@assistant-ui/react";
@@ -162,12 +157,10 @@ function MyComponent() {
162
157
 
163
158
  ## Design Notes
164
159
 
165
- - **Single quote:** `setQuote` replaces the current quote instead of appending. Only one quote can be active at a time.
166
- - **Snapshot text:** The selected text is captured when the quote is created and is not linked to the source message afterward.
167
- - **Cross-message selection:** The toolbar only appears when the selection stays within a single message.
168
- - **Streaming messages:** The toolbar still works while a message is streaming because it relies on the captured selection rather than message status.
169
- - **`isEmpty` unchanged:** A quote by itself does not make the composer non-empty. The user still needs to type a reply.
170
- - **Scroll hides toolbar:** The toolbar hides on scroll because its position would otherwise become stale.
160
+ - **snapshot text:** the selected text is captured when the quote is created and is not linked to the source message afterward.
161
+ - **streaming messages:** the toolbar still works while a message is streaming because it relies on the captured selection rather than message status.
162
+ - **`isEmpty` unchanged:** a quote by itself does not make the composer non-empty; the user still needs to type a reply.
163
+ - **scroll hides toolbar:** the toolbar hides on scroll because its position would otherwise become stale.
171
164
 
172
165
  ## Related
173
166
 
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Slash Commands
3
3
  description: Let users type / in the composer to trigger predefined actions from a popover picker.
4
+ platforms: ["react"]
4
5
  ---
5
6
 
6
7
  Slash commands let users type `/` in the composer to open a popover, browse available commands, and execute one. Unlike [mentions](/docs/guides/mentions) (which only insert a directive into the message), slash commands additionally fire an **action callback** at the moment of selection.
@@ -89,6 +90,17 @@ function MyComposer() {
89
90
 
90
91
  The label defaults to `/${id}`; override via `label` on the command. Icons are strings that your `iconMap` on the picker UI resolves to components (see [ComposerTriggerPopover](/docs/ui/composer-trigger-popover)).
91
92
 
93
+ ### `unstable_useSlashCommandAdapter` options
94
+
95
+ | Option | Type | Default | Description |
96
+ | --- | --- | --- | --- |
97
+ | `commands` | `Unstable_SlashCommand[]` | — | Command definitions — each has `id`, optional `label`, `description`, `icon`, and an `execute` callback (required) |
98
+ | `removeOnExecute` | `boolean` | `false` | When `true`, strips the trigger text from the composer after executing instead of leaving a directive chip |
99
+ | `iconMap` | `Record<string, IconComponent>` | — | Maps `metadata.icon` / category `id` strings to React icon components; forwarded to `ComposerTriggerPopover` |
100
+ | `fallbackIcon` | `IconComponent` | — | Fallback when no `iconMap` entry matches; forwarded to `ComposerTriggerPopover` |
101
+
102
+ The hook returns `{ adapter, action, iconMap?, fallbackIcon? }` — spread directly into `<ComposerTriggerPopover char="/" {...slash} />` for one-line wiring.
103
+
92
104
  ### 2. Controlling the Chip
93
105
 
94
106
  By default, a selected `/summarize` is converted into a directive chip (`:command[/summarize]{name=summarize}`) in the composer text and the command's `execute` fires. This keeps an audit trail of which commands were invoked.
@@ -236,57 +248,111 @@ Slash commands and mentions live under the same `TriggerPopoverRoot`. Declare on
236
248
 
237
249
  Each `TriggerPopover` is its own scope — the `@` popover and the `/` popover read state from their own declaration and never collide. Keyboard events route to whichever popover is currently active.
238
250
 
239
- ## Keyboard Navigation
251
+ ## Commands with Arguments
252
+
253
+ Some commands accept inline arguments typed after the command word — for example `/translate en` or `/ask what is TypeScript`. Because the adapter's `search` method receives the full text after `/`, you can split on the first space to separate the command from its arguments:
240
254
 
241
- Same keyboard bindings as mentions:
255
+ ```tsx
256
+ const SLASH_COMMANDS: readonly Unstable_SlashCommand[] = [
257
+ {
258
+ id: "translate",
259
+ description: "Translate to a language, e.g. /translate en",
260
+ execute: () => {/* arguments extracted separately, see below */},
261
+ },
262
+ {
263
+ id: "ask",
264
+ description: "Ask about a topic, e.g. /ask what is TypeScript",
265
+ execute: () => {/* arguments extracted separately, see below */},
266
+ },
267
+ ];
242
268
 
243
- | Key | Action |
244
- | --- | --- |
245
- | <Kbd>ArrowDown</Kbd> | Highlight next item |
246
- | <Kbd>ArrowUp</Kbd> | Highlight previous item |
247
- | <Kbd>Enter</Kbd> | Execute highlighted command / drill into category |
248
- | <Kbd>Escape</Kbd> | Close popover |
249
- | <Kbd>Backspace</Kbd> | Go back to categories (when query is empty) |
269
+ function MyComposer() {
270
+ const composerRef = useRef<HTMLTextAreaElement>(null);
271
+ const slash = unstable_useSlashCommandAdapter({
272
+ commands: SLASH_COMMANDS.map((cmd) => ({
273
+ ...cmd,
274
+ execute: () => {
275
+ // Read the full composer text to extract arguments
276
+ const raw = composerRef.current?.value ?? "";
277
+ // Match "/<id> <args>" at start of input
278
+ const match = raw.match(new RegExp(`^\\/${cmd.id}\\s+(.*)`));
279
+ const args = match?.[1]?.trim() ?? "";
280
+ handleCommand(cmd.id, args);
281
+ },
282
+ })),
283
+ removeOnExecute: true,
284
+ });
250
285
 
251
- ## Trigger Popover Architecture
286
+ return (
287
+ <ComposerPrimitive.Unstable_TriggerPopoverRoot>
288
+ <ComposerPrimitive.Root>
289
+ <ComposerPrimitive.Input ref={composerRef} placeholder="Type / for commands..." />
290
+ <ComposerPrimitive.Unstable_TriggerPopover char="/" adapter={slash.adapter}>
291
+ <ComposerPrimitive.Unstable_TriggerPopover.Action {...slash.action} />
292
+ <ComposerPrimitive.Unstable_TriggerPopoverItems>
293
+ {(items) => items.map((item, i) => (
294
+ <ComposerPrimitive.Unstable_TriggerPopoverItem key={item.id} item={item} index={i}>
295
+ <strong>{item.label}</strong>
296
+ {item.description && <span>{item.description}</span>}
297
+ </ComposerPrimitive.Unstable_TriggerPopoverItem>
298
+ ))}
299
+ </ComposerPrimitive.Unstable_TriggerPopoverItems>
300
+ </ComposerPrimitive.Unstable_TriggerPopover>
301
+ <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
302
+ </ComposerPrimitive.Root>
303
+ </ComposerPrimitive.Unstable_TriggerPopoverRoot>
304
+ );
305
+ }
306
+ ```
307
+
308
+ `removeOnExecute: true` strips the `/translate en` text from the composer so the argument is consumed by the handler rather than sent to the LLM.
309
+
310
+ ## Async Command Loading
252
311
 
253
- Both mentions and slash commands are built on a generic **trigger popover** system:
312
+ The adapter interface is synchronous, but the command list can come from any async source. Load commands into state (or a query cache) and pass the current snapshot to the hook. Because `unstable_useSlashCommandAdapter` re-runs on every render, the adapter always reflects the latest list.
254
313
 
255
- - `ComposerPrimitive.Unstable_TriggerPopoverRoot` — root provider that groups triggers and owns the input plugin registry
256
- - `ComposerPrimitive.Unstable_TriggerPopover` — declares one trigger (id, char, adapter) and renders its popover container
257
- - Behavior sub-primitives — exactly one per `TriggerPopover`:
258
- - `Unstable_TriggerPopover.Directive` — writes a formatted directive on selection ("mention" path)
259
- - `Unstable_TriggerPopover.Action` — fires a callback on selection ("slash" path); inserts a chip by default, strip with `removeOnExecute`
260
- - Shared sub-primitives (`TriggerPopoverCategories`, `TriggerPopoverItems`, `TriggerPopoverBack`) live inside a `TriggerPopover`
314
+ **With React state:**
261
315
 
262
- You can declare any number of triggers under one root and mix behavior types.
316
+ ```tsx
317
+ function MyComposer() {
318
+ const [commands, setCommands] = useState<Unstable_SlashCommand[]>([]);
263
319
 
264
- ### ComposerInput Plugin Protocol
320
+ useEffect(() => {
321
+ fetchAvailableCommands().then(setCommands);
322
+ }, []);
265
323
 
266
- Under the hood, each `TriggerPopover` registers a **ComposerInputPlugin** with the composer input. This is a generic protocol that decouples the input from any specific trigger:
324
+ const slash = unstable_useSlashCommandAdapter({ commands });
267
325
 
268
- ```ts
269
- type ComposerInputPlugin = {
270
- handleKeyDown(e: KeyboardEvent): boolean;
271
- setCursorPosition(pos: number): void;
272
- };
326
+ return (/* ... */);
327
+ }
328
+ ```
329
+
330
+ **With React Query:**
331
+
332
+ ```tsx
333
+ function MyComposer() {
334
+ const { data: commands = [] } = useQuery({
335
+ queryKey: ["slash-commands"],
336
+ queryFn: fetchAvailableCommands,
337
+ });
338
+
339
+ const slash = unstable_useSlashCommandAdapter({ commands });
340
+
341
+ return (/* ... */);
342
+ }
273
343
  ```
274
344
 
275
- The input iterates over registered plugins for keyboard events and cursor changes. This is what enables multiple triggers to coexist without conflict.
345
+ ## Keyboard Navigation
346
+
347
+ See [ComposerTriggerPopover keyboard navigation](/docs/ui/composer-trigger-popover#keyboard-navigation) for the full key bindings table.
348
+
349
+ ## Trigger Popover Architecture
350
+
351
+ Both mentions and slash commands are built on a generic trigger popover system where each `Unstable_TriggerPopover` declares one trigger character, an adapter, and exactly one behavior sub-primitive (`Directive` or `Action`). Multiple triggers coexist under a single `Unstable_TriggerPopoverRoot`. See the [Composer Primitives](/docs/primitives/composer) reference for the complete API.
276
352
 
277
353
  ## Primitives Reference
278
354
 
279
- | Primitive | Description |
280
- | --- | --- |
281
- | `Unstable_TriggerPopoverRoot` | Root — groups triggers, provides input plugin registry |
282
- | `Unstable_TriggerPopover` | Declares a trigger and renders its popover container |
283
- | `Unstable_TriggerPopover.Directive` | Behavior sub-primitive — inserts a formatted directive on selection |
284
- | `Unstable_TriggerPopover.Action` | Behavior sub-primitive — runs `onExecute` on selection; chip-by-default |
285
- | `Unstable_TriggerPopoverCategories` | Render-function for the top-level category list |
286
- | `Unstable_TriggerPopoverCategoryItem` | Button that drills into a category (`role="option"`, auto `data-highlighted`) |
287
- | `Unstable_TriggerPopoverItems` | Render-function for items within the active category or search results |
288
- | `Unstable_TriggerPopoverItem` | Button that selects an item (`role="option"`, auto `data-highlighted`) |
289
- | `Unstable_TriggerPopoverBack` | Button that navigates back from items to categories |
355
+ See the [Composer Primitives](/docs/primitives/composer) reference for the full list of trigger popover primitives and their props.
290
356
 
291
357
  ## Related
292
358