@assistant-ui/mcp-docs-server 0.1.29 → 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 (214) hide show
  1. package/.docs/organized/code-examples/waterfall.md +15 -7
  2. package/.docs/organized/code-examples/with-a2a.md +9 -21
  3. package/.docs/organized/code-examples/with-ag-ui.md +11 -8
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +10 -10
  5. package/.docs/organized/code-examples/with-artifacts.md +12 -10
  6. package/.docs/organized/code-examples/with-assistant-transport.md +11 -12
  7. package/.docs/organized/code-examples/with-chain-of-thought.md +83 -54
  8. package/.docs/organized/code-examples/with-cloud-standalone.md +14 -11
  9. package/.docs/organized/code-examples/with-cloud.md +9 -10
  10. package/.docs/organized/code-examples/with-custom-thread-list.md +61 -16
  11. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +17 -12
  12. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +13 -13
  13. package/.docs/organized/code-examples/with-expo.md +25 -21
  14. package/.docs/organized/code-examples/with-external-store.md +8 -8
  15. package/.docs/organized/code-examples/with-ffmpeg.md +17 -12
  16. package/.docs/organized/code-examples/with-generative-ui.md +9 -9
  17. package/.docs/organized/code-examples/with-google-adk.md +8 -8
  18. package/.docs/organized/code-examples/with-heat-graph.md +5 -5
  19. package/.docs/organized/code-examples/with-interactables.md +10 -25
  20. package/.docs/organized/code-examples/with-langchain.md +437 -0
  21. package/.docs/organized/code-examples/with-langgraph.md +16 -16
  22. package/.docs/organized/code-examples/with-livekit.md +18 -13
  23. package/.docs/organized/code-examples/with-opencode.md +105 -62
  24. package/.docs/organized/code-examples/with-parent-id-grouping.md +10 -10
  25. package/.docs/organized/code-examples/with-react-hook-form.md +220 -148
  26. package/.docs/organized/code-examples/with-react-ink.md +2 -2
  27. package/.docs/organized/code-examples/with-react-router.md +12 -12
  28. package/.docs/organized/code-examples/with-store.md +8 -5
  29. package/.docs/organized/code-examples/with-tanstack.md +10 -10
  30. package/.docs/organized/code-examples/with-tap-runtime.md +10 -6
  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 +80 -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/composer.mdx +149 -40
  58. package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +65 -0
  59. package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +2 -0
  60. package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +50 -6
  61. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +15 -0
  62. package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +36 -1
  63. package/.docs/raw/docs/(reference)/api-reference/runtimes/index.mdx +38 -0
  64. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +9 -0
  65. package/.docs/raw/docs/(reference)/migrations/v0-14.mdx +144 -6
  66. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +231 -3
  67. package/.docs/raw/docs/cloud/ai-sdk.mdx +221 -3
  68. package/.docs/raw/docs/cloud/langgraph.mdx +274 -2
  69. package/.docs/raw/docs/{(docs)/guides → guides}/attachments.mdx +41 -36
  70. package/.docs/raw/docs/guides/branching.mdx +76 -0
  71. package/.docs/raw/docs/guides/chain-of-thought.mdx +166 -0
  72. package/.docs/raw/docs/{(docs)/guides → guides}/context-api.mdx +50 -22
  73. package/.docs/raw/docs/{(docs)/guides → guides}/dictation.mdx +2 -0
  74. package/.docs/raw/docs/guides/editing.mdx +102 -0
  75. package/.docs/raw/docs/guides/index.mdx +103 -0
  76. package/.docs/raw/docs/{(docs)/guides → guides}/interactables.mdx +49 -0
  77. package/.docs/raw/docs/{(docs)/guides → guides}/latex.mdx +51 -8
  78. package/.docs/raw/docs/guides/mentions.mdx +520 -0
  79. package/.docs/raw/docs/{(docs)/guides → guides}/message-timing.mdx +8 -2
  80. package/.docs/raw/docs/{(docs)/guides → guides}/multi-agent.mdx +64 -4
  81. package/.docs/raw/docs/{(docs)/guides → guides}/quoting.mdx +10 -17
  82. package/.docs/raw/docs/guides/slash-commands.mdx +361 -0
  83. package/.docs/raw/docs/guides/speech.mdx +156 -0
  84. package/.docs/raw/docs/{(docs)/guides → guides}/suggestions.mdx +21 -83
  85. package/.docs/raw/docs/{(docs)/guides → guides}/tool-ui.mdx +108 -36
  86. package/.docs/raw/docs/{(docs)/guides → guides}/tools.mdx +131 -35
  87. package/.docs/raw/docs/{(docs)/guides → guides}/voice.mdx +39 -0
  88. package/.docs/raw/docs/ink/index.mdx +1 -3
  89. package/.docs/raw/docs/ink/migration.mdx +1 -3
  90. package/.docs/raw/docs/ink/primitives.mdx +37 -1
  91. package/.docs/raw/docs/integrations/attachments/custom-adapter.mdx +520 -0
  92. package/.docs/raw/docs/integrations/auth/better-auth.mdx +191 -0
  93. package/.docs/raw/docs/integrations/auth/clerk.mdx +172 -0
  94. package/.docs/raw/docs/integrations/auth/next-auth.mdx +196 -0
  95. package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +79 -0
  96. package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +188 -0
  97. package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +57 -0
  98. package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +201 -0
  99. package/.docs/raw/docs/integrations/gateways/index.mdx +157 -0
  100. package/.docs/raw/docs/integrations/index.mdx +173 -0
  101. package/.docs/raw/docs/integrations/observability/helicone.mdx +130 -0
  102. package/.docs/raw/docs/integrations/observability/langfuse.mdx +156 -0
  103. package/.docs/raw/docs/integrations/observability/langsmith.mdx +146 -0
  104. package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +712 -0
  105. package/.docs/raw/docs/integrations/tools/mcp.mdx +267 -0
  106. package/.docs/raw/docs/primitives/action-bar.mdx +1 -0
  107. package/.docs/raw/docs/primitives/assistant-modal.mdx +1 -0
  108. package/.docs/raw/docs/primitives/attachment.mdx +1 -0
  109. package/.docs/raw/docs/primitives/branch-picker.mdx +1 -0
  110. package/.docs/raw/docs/primitives/chain-of-thought.mdx +90 -85
  111. package/.docs/raw/docs/primitives/composer.mdx +96 -63
  112. package/.docs/raw/docs/primitives/error.mdx +1 -0
  113. package/.docs/raw/docs/primitives/index.mdx +2 -1
  114. package/.docs/raw/docs/primitives/message.mdx +68 -5
  115. package/.docs/raw/docs/primitives/selection-toolbar.mdx +1 -0
  116. package/.docs/raw/docs/primitives/suggestion.mdx +1 -0
  117. package/.docs/raw/docs/primitives/thread-list.mdx +39 -0
  118. package/.docs/raw/docs/primitives/thread.mdx +16 -13
  119. package/.docs/raw/docs/react-native/index.mdx +1 -3
  120. package/.docs/raw/docs/react-native/migration.mdx +1 -3
  121. package/.docs/raw/docs/runtimes/a2a/client-and-hooks.mdx +396 -0
  122. package/.docs/raw/docs/runtimes/a2a/overview.mdx +60 -0
  123. package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +216 -0
  124. package/.docs/raw/docs/runtimes/ag-ui/overview.mdx +70 -0
  125. package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +243 -0
  126. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +123 -0
  127. package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +52 -0
  128. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +71 -131
  129. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +69 -63
  130. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +365 -101
  131. package/.docs/raw/docs/runtimes/concepts/adapters.mdx +265 -0
  132. package/.docs/raw/docs/runtimes/concepts/architecture.mdx +125 -0
  133. package/.docs/raw/docs/runtimes/concepts/stability.mdx +67 -0
  134. package/.docs/raw/docs/runtimes/concepts/threads.mdx +428 -0
  135. package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +703 -0
  136. package/.docs/raw/docs/runtimes/custom/data-stream.mdx +323 -0
  137. package/.docs/raw/docs/runtimes/custom/external-store.mdx +253 -1236
  138. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +746 -0
  139. package/.docs/raw/docs/runtimes/custom/overview.mdx +71 -0
  140. package/.docs/raw/docs/runtimes/google-adk/api.mdx +256 -0
  141. package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +717 -0
  142. package/.docs/raw/docs/runtimes/google-adk/overview.mdx +69 -0
  143. package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +229 -0
  144. package/.docs/raw/docs/runtimes/langchain.mdx +533 -0
  145. package/.docs/raw/docs/runtimes/langgraph/generative-ui.mdx +305 -0
  146. package/.docs/raw/docs/runtimes/langgraph/interrupts.mdx +104 -0
  147. package/.docs/raw/docs/runtimes/langgraph/overview.mdx +84 -0
  148. package/.docs/raw/docs/runtimes/langgraph/quickstart.mdx +496 -0
  149. package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +127 -0
  150. package/.docs/raw/docs/runtimes/langgraph/threads.mdx +113 -0
  151. package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +3 -3
  152. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +0 -23
  153. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +1 -1
  154. package/.docs/raw/docs/runtimes/opencode/hooks.mdx +191 -0
  155. package/.docs/raw/docs/runtimes/opencode/overview.mdx +48 -0
  156. package/.docs/raw/docs/runtimes/opencode/quickstart.mdx +119 -0
  157. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +74 -198
  158. package/.docs/raw/docs/ui/accordion.mdx +1 -0
  159. package/.docs/raw/docs/ui/assistant-modal.mdx +1 -0
  160. package/.docs/raw/docs/ui/assistant-sidebar.mdx +1 -0
  161. package/.docs/raw/docs/ui/attachment.mdx +1 -0
  162. package/.docs/raw/docs/ui/badge.mdx +1 -0
  163. package/.docs/raw/docs/ui/composer-trigger-popover.mdx +200 -0
  164. package/.docs/raw/docs/ui/context-display.mdx +1 -0
  165. package/.docs/raw/docs/ui/diff-viewer.mdx +1 -0
  166. package/.docs/raw/docs/ui/directive-text.mdx +114 -0
  167. package/.docs/raw/docs/ui/file.mdx +1 -0
  168. package/.docs/raw/docs/ui/image.mdx +1 -0
  169. package/.docs/raw/docs/ui/markdown.mdx +2 -14
  170. package/.docs/raw/docs/ui/mermaid.mdx +1 -0
  171. package/.docs/raw/docs/ui/message-timing.mdx +3 -2
  172. package/.docs/raw/docs/ui/model-selector.mdx +1 -0
  173. package/.docs/raw/docs/ui/part-grouping.mdx +325 -313
  174. package/.docs/raw/docs/ui/quote.mdx +1 -0
  175. package/.docs/raw/docs/ui/reasoning.mdx +69 -32
  176. package/.docs/raw/docs/ui/scrollbar.mdx +1 -0
  177. package/.docs/raw/docs/ui/select.mdx +1 -0
  178. package/.docs/raw/docs/ui/sources.mdx +1 -0
  179. package/.docs/raw/docs/ui/streamdown.mdx +1 -0
  180. package/.docs/raw/docs/ui/syntax-highlighting.mdx +1 -0
  181. package/.docs/raw/docs/ui/tabs.mdx +1 -0
  182. package/.docs/raw/docs/ui/thread-list.mdx +17 -0
  183. package/.docs/raw/docs/ui/thread.mdx +56 -1
  184. package/.docs/raw/docs/ui/tool-fallback.mdx +1 -0
  185. package/.docs/raw/docs/ui/tool-group.mdx +39 -11
  186. package/.docs/raw/docs/ui/voice.mdx +1 -0
  187. package/.docs/raw/docs/utilities/heat-graph.mdx +1 -0
  188. package/.docs/raw/docs/utilities/react-o11y.mdx +278 -0
  189. package/.docs/raw/docs/utilities/tw-shimmer.mdx +1 -0
  190. package/dist/utils/logger.js +1 -1
  191. package/dist/utils/logger.js.map +1 -1
  192. package/package.json +4 -4
  193. package/src/tools/tests/path-traversal.test.ts +1 -1
  194. package/src/utils/logger.ts +1 -1
  195. package/.docs/raw/docs/(docs)/guides/branching.mdx +0 -65
  196. package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +0 -164
  197. package/.docs/raw/docs/(docs)/guides/editing.mdx +0 -66
  198. package/.docs/raw/docs/(docs)/guides/mentions.mdx +0 -406
  199. package/.docs/raw/docs/(docs)/guides/slash-commands.mdx +0 -275
  200. package/.docs/raw/docs/(docs)/guides/speech.mdx +0 -38
  201. package/.docs/raw/docs/runtimes/a2a/index.mdx +0 -298
  202. package/.docs/raw/docs/runtimes/assistant-transport.mdx +0 -1033
  203. package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +0 -268
  204. package/.docs/raw/docs/runtimes/custom/local.mdx +0 -1464
  205. package/.docs/raw/docs/runtimes/data-stream.mdx +0 -422
  206. package/.docs/raw/docs/runtimes/google-adk/index.mdx +0 -686
  207. package/.docs/raw/docs/runtimes/helicone.mdx +0 -61
  208. package/.docs/raw/docs/runtimes/langgraph/index.mdx +0 -607
  209. package/.docs/raw/docs/runtimes/langgraph/tutorial/index.mdx +0 -12
  210. package/.docs/raw/docs/runtimes/langserve.mdx +0 -116
  211. package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +0 -218
  212. package/.docs/raw/docs/runtimes/mastra/overview.mdx +0 -18
  213. package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +0 -217
  214. package/.docs/raw/docs/ui/mention.mdx +0 -168
@@ -0,0 +1,520 @@
1
+ ---
2
+ title: Mentions
3
+ description: Let users @-mention tools or custom items in the composer to guide the LLM.
4
+ platforms: ["react"]
5
+ ---
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.
8
+
9
+ ## How It Works
10
+
11
+ ```
12
+ User types "@" → Trigger detected → Adapter provides categories/items
13
+ ↓
14
+ Directive inserted ← User selects item from popover
15
+ ↓
16
+ Message sent with ":tool[Label]{name=id}" in text
17
+ ```
18
+
19
+ The mention system has three layers:
20
+
21
+ 1. **Trigger detection** — the composer input watches for a trigger character (`@` by default) and extracts the query
22
+ 2. **Adapter** — provides the categories and items to display in the popover (e.g. registered tools)
23
+ 3. **Formatter** — serializes a selected item into directive text (`:type[label]{name=id}`) and parses it back for rendering
24
+
25
+ Under the hood, mentions are one kind of [trigger popover](/docs/guides/slash-commands#trigger-popover-architecture). A mention declares its behavior with a `<TriggerPopover.Directive>` sub-primitive, which writes the formatter-serialized directive into the composer on selection.
26
+
27
+ ## Quick Start
28
+
29
+ The fastest path is the pre-built [Mention UI components](/docs/ui/composer-trigger-popover), which wire everything together with two shadcn components — the popover picker and the message-side chip renderer:
30
+
31
+ ```bash
32
+ npx shadcn@latest add "https://r.assistant-ui.com/composer-trigger-popover" "https://r.assistant-ui.com/directive-text"
33
+ ```
34
+
35
+ See the [Composer Trigger Popover](/docs/ui/composer-trigger-popover) and [Directive Text](/docs/ui/directive-text) guides for setup steps.
36
+
37
+ The rest of this guide covers the underlying concepts and customization points.
38
+
39
+ ## Trigger Adapter
40
+
41
+ A `Unstable_TriggerAdapter` provides the data for the popover. All methods are **synchronous** — use external state management (React Query, SWR, local state) for async data, then expose loaded results through the adapter.
42
+
43
+ ```ts
44
+ import type { Unstable_TriggerAdapter } from "@assistant-ui/core";
45
+
46
+ const myAdapter: Unstable_TriggerAdapter = {
47
+ categories() {
48
+ return [
49
+ { id: "tools", label: "Tools" },
50
+ { id: "users", label: "Users" },
51
+ ];
52
+ },
53
+
54
+ categoryItems(categoryId) {
55
+ if (categoryId === "tools") {
56
+ return [
57
+ { id: "search", type: "tool", label: "Search" },
58
+ { id: "calculator", type: "tool", label: "Calculator" },
59
+ ];
60
+ }
61
+ if (categoryId === "users") {
62
+ return [
63
+ { id: "alice", type: "user", label: "Alice" },
64
+ { id: "bob", type: "user", label: "Bob" },
65
+ ];
66
+ }
67
+ return [];
68
+ },
69
+
70
+ // Optional — global search across all categories
71
+ search(query) {
72
+ const lower = query.toLowerCase();
73
+ const all = [
74
+ ...this.categoryItems("tools"),
75
+ ...this.categoryItems("users"),
76
+ ];
77
+ return all.filter(
78
+ (item) =>
79
+ item.label.toLowerCase().includes(lower) ||
80
+ item.id.toLowerCase().includes(lower),
81
+ );
82
+ },
83
+ };
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
+
143
+ Pass the adapter to `TriggerPopover` and declare a `Directive` sub-primitive to bind the insertion behavior:
144
+
145
+ ```tsx
146
+ import { ComposerPrimitive } from "@assistant-ui/react";
147
+ import { unstable_defaultDirectiveFormatter } from "@assistant-ui/core";
148
+
149
+ <ComposerPrimitive.Unstable_TriggerPopoverRoot>
150
+ <ComposerPrimitive.Root>
151
+ <ComposerPrimitive.Input placeholder="Type @ to mention..." />
152
+ <ComposerPrimitive.Unstable_TriggerPopover
153
+ char="@"
154
+ adapter={myAdapter}
155
+ >
156
+ <ComposerPrimitive.Unstable_TriggerPopover.Directive
157
+ formatter={unstable_defaultDirectiveFormatter}
158
+ />
159
+ <ComposerPrimitive.Unstable_TriggerPopoverCategories>
160
+ {(categories) =>
161
+ categories.map((cat) => (
162
+ <ComposerPrimitive.Unstable_TriggerPopoverCategoryItem
163
+ key={cat.id}
164
+ categoryId={cat.id}
165
+ >
166
+ {cat.label}
167
+ </ComposerPrimitive.Unstable_TriggerPopoverCategoryItem>
168
+ ))
169
+ }
170
+ </ComposerPrimitive.Unstable_TriggerPopoverCategories>
171
+ <ComposerPrimitive.Unstable_TriggerPopoverItems>
172
+ {(items) =>
173
+ items.map((item) => (
174
+ <ComposerPrimitive.Unstable_TriggerPopoverItem
175
+ key={item.id}
176
+ item={item}
177
+ >
178
+ {item.label}
179
+ </ComposerPrimitive.Unstable_TriggerPopoverItem>
180
+ ))
181
+ }
182
+ </ComposerPrimitive.Unstable_TriggerPopoverItems>
183
+ </ComposerPrimitive.Unstable_TriggerPopover>
184
+ </ComposerPrimitive.Root>
185
+ </ComposerPrimitive.Unstable_TriggerPopoverRoot>
186
+ ```
187
+
188
+ Exactly one behavior sub-primitive (`Directive` or `Action`) is allowed per `TriggerPopover`. The parent reads the registered behavior and wires the selection machinery.
189
+
190
+ ### Built-in Mention Adapter
191
+
192
+ `unstable_useMentionAdapter` covers the common cases: mention registered tools, add your own items, mix tools with custom items, or show multi-category drill-down.
193
+
194
+ **Tools from model context (default):**
195
+
196
+ ```tsx
197
+ import { unstable_useMentionAdapter } from "@assistant-ui/react";
198
+
199
+ const mention = unstable_useMentionAdapter();
200
+ // → { adapter, directive } — spread into <ComposerTriggerPopover {...mention} />
201
+ // Default: single "Tools" category reading from useAssistantTool registrations
202
+ ```
203
+
204
+ **Custom items only (no tools):**
205
+
206
+ ```tsx
207
+ const mention = unstable_useMentionAdapter({
208
+ items: [
209
+ { id: "alice", type: "user", label: "Alice", icon: "User" },
210
+ { id: "bob", type: "user", label: "Bob", icon: "User" },
211
+ ],
212
+ });
213
+ ```
214
+
215
+ **Mix custom items with model-context tools (flat):**
216
+
217
+ ```tsx
218
+ const mention = unstable_useMentionAdapter({
219
+ items: [{ id: "kb", type: "doc", label: "Knowledge Base", icon: "Book" }],
220
+ includeModelContextTools: true,
221
+ });
222
+ ```
223
+
224
+ **Multi-category drill-down:**
225
+
226
+ ```tsx
227
+ const mention = unstable_useMentionAdapter({
228
+ categories: [
229
+ {
230
+ id: "users",
231
+ label: "Users",
232
+ items: [
233
+ { id: "alice", type: "user", label: "Alice", icon: "User" },
234
+ { id: "bob", type: "user", label: "Bob", icon: "User" },
235
+ ],
236
+ },
237
+ {
238
+ id: "files",
239
+ label: "Files",
240
+ items: [
241
+ { id: "readme", type: "file", label: "README.md", icon: "FileText" },
242
+ ],
243
+ },
244
+ ],
245
+ // Tools auto-appended as their own category (default id "tools", label "Tools")
246
+ includeModelContextTools: true,
247
+ });
248
+ ```
249
+
250
+ **Tool formatting and category override:**
251
+
252
+ ```tsx
253
+ const mention = unstable_useMentionAdapter({
254
+ categories: [{ id: "users", label: "Users", items: [...] }],
255
+ includeModelContextTools: {
256
+ category: { id: "integrations", label: "Integrations" },
257
+ formatLabel: (name) =>
258
+ name.replaceAll("_", " ").replace(/\b\w/g, (c) => c.toUpperCase()),
259
+ icon: "Wrench",
260
+ },
261
+ });
262
+ ```
263
+
264
+ **Options summary:**
265
+
266
+ | Option | Type | Behavior |
267
+ | --- | --- | --- |
268
+ | `items` | `Unstable_Mention[]` | Flat list (ignored when `categories` is set) |
269
+ | `categories` | `{id, label, items}[]` | Drill-down groups |
270
+ | `includeModelContextTools` | `boolean \| object` | Default: `true` iff neither `items` nor `categories` |
271
+ | `formatter` | `Unstable_DirectiveFormatter` | Override directive serialization (default: `unstable_defaultDirectiveFormatter`) |
272
+ | `onInserted` | `(item) => void` | Fires after the directive is inserted into the composer |
273
+ | `iconMap` | `Record<string, IconComponent>` | Maps `metadata.icon` / category `id` strings to React components |
274
+ | `fallbackIcon` | `IconComponent` | Fallback when no entry in `iconMap` matches |
275
+
276
+ `icon` on each mention is a shortcut for `metadata.icon` that the picker UI resolves via `iconMap`. Dedup between custom items and model-context tools is by `id` — explicit items win.
277
+
278
+ The hook returns `{ adapter, directive, iconMap?, fallbackIcon? }` — spread into `<ComposerTriggerPopover {...mention} />` for one-line wiring. Callers consuming the raw primitives instead destructure: `mention.adapter`, `mention.directive.formatter`, etc.
279
+
280
+ ## Directive Format
281
+
282
+ When a user selects a mention item, it is serialized into the composer text as a **directive**. The default format is:
283
+
284
+ ```
285
+ :type[label]{name=id}
286
+ ```
287
+
288
+ For example, selecting a tool named "get_weather" with label "Get Weather" produces:
289
+
290
+ ```
291
+ :tool[Get Weather]{name=get_weather}
292
+ ```
293
+
294
+ When `id` equals `label`, the `{name=…}` attribute is omitted for brevity:
295
+
296
+ ```
297
+ :tool[search]
298
+ ```
299
+
300
+ ### Custom Formatter
301
+
302
+ Implement `Unstable_DirectiveFormatter` to use a different format:
303
+
304
+ ```ts
305
+ import type { Unstable_DirectiveFormatter } from "@assistant-ui/core";
306
+
307
+ const slashFormatter: Unstable_DirectiveFormatter = {
308
+ serialize(item) {
309
+ return `/${item.id}`;
310
+ },
311
+
312
+ parse(text) {
313
+ const segments = [];
314
+ const re = /\/(\w+)/g;
315
+ let lastIndex = 0;
316
+ let match;
317
+
318
+ while ((match = re.exec(text)) !== null) {
319
+ if (match.index > lastIndex) {
320
+ segments.push({ kind: "text" as const, text: text.slice(lastIndex, match.index) });
321
+ }
322
+ segments.push({
323
+ kind: "mention" as const,
324
+ type: "tool",
325
+ label: match[1]!,
326
+ id: match[1]!,
327
+ });
328
+ lastIndex = re.lastIndex;
329
+ }
330
+
331
+ if (lastIndex < text.length) {
332
+ segments.push({ kind: "text" as const, text: text.slice(lastIndex) });
333
+ }
334
+
335
+ return segments;
336
+ },
337
+ };
338
+ ```
339
+
340
+ Pass it to the trigger's `Directive` sub-primitive and the message renderer:
341
+
342
+ ```tsx
343
+ // Composer
344
+ <ComposerPrimitive.Unstable_TriggerPopover
345
+ char="@"
346
+ adapter={adapter}
347
+ >
348
+ <ComposerPrimitive.Unstable_TriggerPopover.Directive formatter={slashFormatter} />
349
+ ...
350
+ </ComposerPrimitive.Unstable_TriggerPopover>
351
+
352
+ // User messages
353
+ const SlashDirectiveText = createDirectiveText(slashFormatter);
354
+ <MessagePrimitive.Parts components={{ Text: SlashDirectiveText }} />
355
+ ```
356
+
357
+ ## Textarea vs Lexical
358
+
359
+ The mention system supports two input modes:
360
+
361
+ | | Textarea (default) | Lexical |
362
+ | --- | --- | --- |
363
+ | **Input component** | `ComposerPrimitive.Input` | `LexicalComposerInput` |
364
+ | **Mention display in composer** | Raw directive text (`:tool[Label]`) | Inline chips (atomic nodes) |
365
+ | **Dependencies** | None | `@assistant-ui/react-lexical`, `lexical`, `@lexical/react` |
366
+ | **Best for** | Simple setups, minimal bundle | Rich editing, polished UX |
367
+
368
+ With **textarea**, selecting a mention inserts the directive string directly into the text. The user sees `:tool[Get Weather]{name=get_weather}` in the input.
369
+
370
+ With **Lexical**, selected mentions appear as styled inline chips that behave as atomic units — they can be selected, deleted, and undone as a whole. The underlying text still uses the directive format.
371
+
372
+ ```tsx
373
+ import { LexicalComposerInput } from "@assistant-ui/react-lexical";
374
+
375
+ <ComposerPrimitive.Unstable_TriggerPopoverRoot>
376
+ <ComposerPrimitive.Root>
377
+ <LexicalComposerInput placeholder="Type @ to mention..." />
378
+ <ComposerPrimitive.Send />
379
+ <ComposerPrimitive.Unstable_TriggerPopover
380
+ char="@"
381
+ adapter={adapter}
382
+ >
383
+ <ComposerPrimitive.Unstable_TriggerPopover.Directive formatter={formatter} />
384
+ ...
385
+ </ComposerPrimitive.Unstable_TriggerPopover>
386
+ </ComposerPrimitive.Root>
387
+ </ComposerPrimitive.Unstable_TriggerPopoverRoot>
388
+ ```
389
+
390
+ `LexicalComposerInput` automatically discovers every `Directive` trigger registered under `TriggerPopoverRoot` and renders their selections as inline chips.
391
+
392
+ ## Rendering Mentions in Messages
393
+
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.
395
+
396
+ ## Processing Mentions on the Backend
397
+
398
+ The message text arrives at your backend with directives inline. Parse them to extract mentioned items:
399
+
400
+ ```ts
401
+ // Default format: :type[label]{name=id}
402
+ const DIRECTIVE_RE = /:([\w-]+)\[([^\]]+)\](?:\{name=([^}]+)\})?/g;
403
+
404
+ function parseMentions(text: string) {
405
+ const mentions = [];
406
+ let match;
407
+ while ((match = DIRECTIVE_RE.exec(text)) !== null) {
408
+ mentions.push({
409
+ type: match[1], // e.g. "tool"
410
+ label: match[2], // e.g. "Get Weather"
411
+ id: match[3] ?? match[2], // e.g. "get_weather"
412
+ });
413
+ }
414
+ return mentions;
415
+ }
416
+
417
+ // Example:
418
+ // parseMentions("Use :tool[Get Weather]{name=get_weather} to check")
419
+ // → [{ type: "tool", label: "Get Weather", id: "get_weather" }]
420
+ ```
421
+
422
+ You can use the extracted mentions to:
423
+ - Force-enable specific tools for the LLM call
424
+ - Add context about mentioned users or documents to the system prompt
425
+ - Log which tools users request most often
426
+
427
+ ## Reading Mention State
428
+
429
+ Use `unstable_useTriggerPopoverScopeContext` inside the `TriggerPopover` to programmatically access the popover state for that trigger:
430
+
431
+ ```tsx
432
+ import { unstable_useTriggerPopoverScopeContext } from "@assistant-ui/react";
433
+
434
+ function MyPopoverContent() {
435
+ const scope = unstable_useTriggerPopoverScopeContext();
436
+
437
+ // scope.open — whether the popover is visible
438
+ // scope.query — current search text after the trigger
439
+ // scope.categories — filtered category list
440
+ // scope.items — filtered item list
441
+ // scope.highlightedIndex — keyboard-navigated index
442
+ // scope.isSearchMode — true when global search is active
443
+ // scope.selectItem(item) — programmatically select an item
444
+ // scope.close() — close the popover
445
+
446
+ return null;
447
+ }
448
+ ```
449
+
450
+ This hook must be used inside a `ComposerPrimitive.Unstable_TriggerPopover`.
451
+
452
+ To iterate every registered trigger (e.g. from a custom input implementation), use `unstable_useTriggerPopoverTriggers` inside `TriggerPopoverRoot`.
453
+
454
+ ## Building a Custom Popover
455
+
456
+ Use the trigger popover primitives to build a fully custom popover:
457
+
458
+ ```tsx
459
+ <ComposerPrimitive.Unstable_TriggerPopoverRoot>
460
+ <ComposerPrimitive.Root>
461
+ <ComposerPrimitive.Input />
462
+
463
+ <ComposerPrimitive.Unstable_TriggerPopover
464
+ char="@"
465
+ adapter={adapter}
466
+ className="popover"
467
+ >
468
+ <ComposerPrimitive.Unstable_TriggerPopover.Directive formatter={formatter} />
469
+
470
+ <ComposerPrimitive.Unstable_TriggerPopoverBack>
471
+ ← Back
472
+ </ComposerPrimitive.Unstable_TriggerPopoverBack>
473
+
474
+ <ComposerPrimitive.Unstable_TriggerPopoverCategories>
475
+ {(categories) =>
476
+ categories.map((cat) => (
477
+ <ComposerPrimitive.Unstable_TriggerPopoverCategoryItem
478
+ key={cat.id}
479
+ categoryId={cat.id}
480
+ >
481
+ {cat.label}
482
+ </ComposerPrimitive.Unstable_TriggerPopoverCategoryItem>
483
+ ))
484
+ }
485
+ </ComposerPrimitive.Unstable_TriggerPopoverCategories>
486
+
487
+ <ComposerPrimitive.Unstable_TriggerPopoverItems>
488
+ {(items) =>
489
+ items.map((item) => (
490
+ <ComposerPrimitive.Unstable_TriggerPopoverItem
491
+ key={item.id}
492
+ item={item}
493
+ >
494
+ {item.label}
495
+ </ComposerPrimitive.Unstable_TriggerPopoverItem>
496
+ ))
497
+ }
498
+ </ComposerPrimitive.Unstable_TriggerPopoverItems>
499
+ </ComposerPrimitive.Unstable_TriggerPopover>
500
+
501
+ <ComposerPrimitive.Send />
502
+ </ComposerPrimitive.Root>
503
+ </ComposerPrimitive.Unstable_TriggerPopoverRoot>
504
+ ```
505
+
506
+ ### Primitives Reference
507
+
508
+ See the [Composer Primitives](/docs/primitives/composer) reference for the full list of trigger popover primitives and their props.
509
+
510
+ ## Combining with Slash Commands
511
+
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.
513
+
514
+ ## Related
515
+
516
+ - [ComposerTriggerPopover UI Component](/docs/ui/composer-trigger-popover) — pre-built shadcn component
517
+ - [DirectiveText UI Component](/docs/ui/directive-text) — renders mention chips in user messages
518
+ - [Slash Commands Guide](/docs/guides/slash-commands) — `/` command system built on the same architecture
519
+ - [Tools Guide](/docs/guides/tools) — register tools that appear in the mention picker
520
+ - [Composer Primitives](/docs/primitives/composer) — underlying composer primitives
@@ -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