@assistant-ui/mcp-docs-server 0.1.36 → 0.1.39

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 (246) hide show
  1. package/.docs/organized/code-examples/waterfall.md +8 -9
  2. package/.docs/organized/code-examples/with-a2a.md +16 -11
  3. package/.docs/organized/code-examples/with-ag-ui.md +16 -11
  4. package/.docs/organized/code-examples/{with-ai-sdk-v6.md → with-ai-sdk-v7.md} +32 -21
  5. package/.docs/organized/code-examples/with-artifacts.md +17 -10
  6. package/.docs/organized/code-examples/with-assistant-transport.md +15 -8
  7. package/.docs/organized/code-examples/with-browser-extension.md +15 -8
  8. package/.docs/organized/code-examples/with-chain-of-thought.md +17 -10
  9. package/.docs/organized/code-examples/with-cloud-standalone.md +10 -9
  10. package/.docs/organized/code-examples/with-cloud.md +18 -13
  11. package/.docs/organized/code-examples/with-custom-thread-list.md +17 -10
  12. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +20 -13
  13. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +20 -13
  14. package/.docs/organized/code-examples/with-eve.md +16 -9
  15. package/.docs/organized/code-examples/with-expo.md +26 -23
  16. package/.docs/organized/code-examples/with-external-store.md +16 -11
  17. package/.docs/organized/code-examples/with-ffmpeg.md +18 -13
  18. package/.docs/organized/code-examples/with-generative-ui.md +20 -15
  19. package/.docs/organized/code-examples/with-google-adk.md +16 -9
  20. package/.docs/organized/code-examples/with-heat-graph.md +8 -9
  21. package/.docs/organized/code-examples/with-image-generation.md +17 -10
  22. package/.docs/organized/code-examples/with-interactables.md +19 -15
  23. package/.docs/organized/code-examples/with-langchain.md +17 -10
  24. package/.docs/organized/code-examples/with-langgraph.md +17 -10
  25. package/.docs/organized/code-examples/with-livekit.md +21 -14
  26. package/.docs/organized/code-examples/with-mcp.md +40 -18
  27. package/.docs/organized/code-examples/with-opencode.md +22 -17
  28. package/.docs/organized/code-examples/with-pi.md +47 -12
  29. package/.docs/organized/code-examples/with-react-hook-form.md +19 -14
  30. package/.docs/organized/code-examples/with-react-ink-web.md +6 -6
  31. package/.docs/organized/code-examples/with-react-ink.md +2 -2
  32. package/.docs/organized/code-examples/with-react-router.md +20 -15
  33. package/.docs/organized/code-examples/with-resumable-stream.md +19 -12
  34. package/.docs/organized/code-examples/with-store.md +8 -9
  35. package/.docs/organized/code-examples/with-tanstack.md +17 -11
  36. package/.docs/organized/code-examples/with-tap-runtime.md +16 -11
  37. package/.docs/organized/code-examples/with-virtualized-thread.md +17 -12
  38. package/.docs/raw/docs/(docs)/base-ui.mdx +39 -0
  39. package/.docs/raw/docs/(docs)/cli.mdx +18 -2
  40. package/.docs/raw/docs/(docs)/installation.mdx +15 -1
  41. package/.docs/raw/docs/(docs)/rtl.mdx +2 -4
  42. package/.docs/raw/docs/(reference)/api-reference/generative-ui/actions.mdx +56 -0
  43. package/.docs/raw/docs/(reference)/api-reference/generative-ui/components.mdx +86 -0
  44. package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +19 -1
  45. package/.docs/raw/docs/(reference)/api-reference/generative-ui/json-generative-ui.mdx +42 -0
  46. package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +53 -2
  47. package/.docs/raw/docs/(reference)/api-reference/generative-ui/slack.mdx +81 -0
  48. package/.docs/raw/docs/(reference)/api-reference/generative-ui/teams.mdx +86 -0
  49. package/.docs/raw/docs/(reference)/api-reference/generative-ui/tokens.mdx +62 -0
  50. package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +4 -1
  51. package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +4 -2
  52. package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +37 -0
  53. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +1 -0
  54. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +29 -29
  55. package/.docs/raw/docs/(reference)/api-reference/primitives/composition.mdx +1 -0
  56. package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +3 -0
  57. package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +2 -0
  58. package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +0 -2
  59. package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +12 -9
  60. package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +4 -0
  61. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +7 -1
  62. package/.docs/raw/docs/cloud/langgraph.mdx +4 -2
  63. package/.docs/raw/docs/guides/chatgpt-subscription.mdx +108 -0
  64. package/.docs/raw/docs/guides/dictation.mdx +185 -257
  65. package/.docs/raw/docs/guides/index.mdx +10 -0
  66. package/.docs/raw/docs/guides/mentions.mdx +31 -3
  67. package/.docs/raw/docs/guides/resumable-streams.mdx +12 -1
  68. package/.docs/raw/docs/guides/speech.mdx +47 -29
  69. package/.docs/raw/docs/guides/suggestions.mdx +70 -1
  70. package/.docs/raw/docs/guides/voice.mdx +197 -267
  71. package/.docs/raw/docs/ink/primitives.mdx +35 -1
  72. package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +13 -7
  73. package/.docs/raw/docs/integrations/frameworks/cloudflare-agents/overview.mdx +3 -3
  74. package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +1 -1
  75. package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +3 -3
  76. package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +1 -1
  77. package/.docs/raw/docs/integrations/gateways/index.mdx +2 -2
  78. package/.docs/raw/docs/integrations/index.mdx +1 -1
  79. package/.docs/raw/docs/integrations/observability/helicone.mdx +1 -1
  80. package/.docs/raw/docs/integrations/observability/langfuse.mdx +1 -1
  81. package/.docs/raw/docs/integrations/observability/langsmith.mdx +3 -3
  82. package/.docs/raw/docs/migrations/index.mdx +50 -0
  83. package/.docs/raw/docs/migrations/react-langgraph-v0-7.mdx +2 -2
  84. package/.docs/raw/docs/migrations/toolkit-tools.mdx +4 -2
  85. package/.docs/raw/docs/primitives/chain-of-thought.mdx +6 -1
  86. package/.docs/raw/docs/primitives/composer.mdx +16 -0
  87. package/.docs/raw/docs/primitives/selection-toolbar.mdx +25 -0
  88. package/.docs/raw/docs/primitives/thread-list.mdx +30 -6
  89. package/.docs/raw/docs/react-native/primitives.mdx +23 -0
  90. package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +1 -1
  91. package/.docs/raw/docs/runtimes/ag-ui/agent-state.mdx +124 -0
  92. package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +1 -1
  93. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +13 -2
  94. package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +13 -4
  95. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +11 -11
  96. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +5 -5
  97. package/.docs/raw/docs/runtimes/ai-sdk/{v6.mdx → v6-legacy.mdx} +8 -6
  98. package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +717 -0
  99. package/.docs/raw/docs/runtimes/concepts/adapters.mdx +1 -1
  100. package/.docs/raw/docs/runtimes/concepts/architecture.mdx +1 -1
  101. package/.docs/raw/docs/runtimes/custom/data-stream.mdx +10 -19
  102. package/.docs/raw/docs/runtimes/custom/external-store.mdx +1 -1
  103. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +2 -0
  104. package/.docs/raw/docs/runtimes/eve/overview.mdx +1 -1
  105. package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +1 -1
  106. package/.docs/raw/docs/runtimes/langchain.mdx +2 -2
  107. package/.docs/raw/docs/runtimes/langgraph/agent-state.mdx +181 -0
  108. package/.docs/raw/docs/runtimes/opencode/hooks.mdx +1 -1
  109. package/.docs/raw/docs/tools/backend.mdx +6 -3
  110. package/.docs/raw/docs/tools/defining-tools.mdx +12 -1
  111. package/.docs/raw/docs/tools/generative-ui.mdx +95 -0
  112. package/.docs/raw/docs/tools/mcp-apps.mdx +37 -10
  113. package/.docs/raw/docs/tools/mcp.mdx +105 -3
  114. package/.docs/raw/docs/tools/tool-ui.mdx +6 -4
  115. package/.docs/raw/docs/tools/user-managed-mcp.mdx +41 -4
  116. package/.docs/raw/docs/ui/accordion.mdx +16 -10
  117. package/.docs/raw/docs/ui/assistant-modal.mdx +8 -4
  118. package/.docs/raw/docs/ui/attachment.mdx +5 -1
  119. package/.docs/raw/docs/ui/badge.mdx +23 -12
  120. package/.docs/raw/docs/ui/follow-up-suggestions.mdx +80 -0
  121. package/.docs/raw/docs/ui/model-selector.mdx +69 -6
  122. package/.docs/raw/docs/ui/select.mdx +22 -14
  123. package/.docs/raw/docs/ui/sources.mdx +1 -1
  124. package/.docs/raw/docs/ui/tabs.mdx +25 -14
  125. package/.docs/raw/docs/utilities/heat-graph.mdx +2 -2
  126. package/README.md +1 -1
  127. package/dist/constants.d.ts +2 -1
  128. package/dist/constants.d.ts.map +1 -1
  129. package/dist/constants.js +2 -1
  130. package/dist/constants.js.map +1 -1
  131. package/dist/index.d.ts +0 -1
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +51 -0
  134. package/dist/index.js.map +1 -1
  135. package/dist/prepare-docs/code-examples.d.ts.map +1 -1
  136. package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
  137. package/dist/prepare-docs/copy-raw.js +0 -4
  138. package/dist/prepare-docs/copy-raw.js.map +1 -1
  139. package/dist/prompts/xulux-playground.d.ts +12 -0
  140. package/dist/prompts/xulux-playground.d.ts.map +1 -0
  141. package/dist/prompts/xulux-playground.js +33 -0
  142. package/dist/prompts/xulux-playground.js.map +1 -0
  143. package/dist/tools/docs.d.ts +2 -4
  144. package/dist/tools/docs.d.ts.map +1 -1
  145. package/dist/tools/docs.js +38 -10
  146. package/dist/tools/docs.js.map +1 -1
  147. package/dist/tools/examples.d.ts +5 -5
  148. package/dist/tools/examples.d.ts.map +1 -1
  149. package/dist/tools/examples.js +10 -7
  150. package/dist/tools/examples.js.map +1 -1
  151. package/dist/tools/resources.d.ts +6 -0
  152. package/dist/tools/resources.d.ts.map +1 -0
  153. package/dist/tools/resources.js +74 -0
  154. package/dist/tools/resources.js.map +1 -0
  155. package/dist/tools/search.d.ts +30 -0
  156. package/dist/tools/search.d.ts.map +1 -0
  157. package/dist/tools/search.js +39 -0
  158. package/dist/tools/search.js.map +1 -0
  159. package/dist/tools/tests/test-setup.d.ts.map +1 -1
  160. package/dist/tools/tests/test-setup.js +7 -1
  161. package/dist/tools/tests/test-setup.js.map +1 -1
  162. package/dist/tools/xulux-templates.d.ts +72 -0
  163. package/dist/tools/xulux-templates.d.ts.map +1 -0
  164. package/dist/tools/xulux-templates.js +82 -0
  165. package/dist/tools/xulux-templates.js.map +1 -0
  166. package/dist/utils/cache.d.ts +5 -0
  167. package/dist/utils/cache.d.ts.map +1 -0
  168. package/dist/utils/cache.js +18 -0
  169. package/dist/utils/cache.js.map +1 -0
  170. package/dist/utils/logger.d.ts.map +1 -1
  171. package/dist/utils/mcp-format.d.ts +1 -0
  172. package/dist/utils/mcp-format.d.ts.map +1 -1
  173. package/dist/utils/mcp-format.js +7 -4
  174. package/dist/utils/mcp-format.js.map +1 -1
  175. package/dist/utils/mdx.d.ts +2 -1
  176. package/dist/utils/mdx.d.ts.map +1 -1
  177. package/dist/utils/mdx.js +19 -2
  178. package/dist/utils/mdx.js.map +1 -1
  179. package/dist/utils/paths.d.ts +2 -1
  180. package/dist/utils/paths.d.ts.map +1 -1
  181. package/dist/utils/paths.js +20 -1
  182. package/dist/utils/paths.js.map +1 -1
  183. package/dist/utils/search.d.ts +10 -0
  184. package/dist/utils/search.d.ts.map +1 -0
  185. package/dist/utils/search.js +97 -0
  186. package/dist/utils/search.js.map +1 -0
  187. package/dist/utils/security.d.ts.map +1 -1
  188. package/dist/xulux/catalog-client.d.ts +14 -0
  189. package/dist/xulux/catalog-client.d.ts.map +1 -0
  190. package/dist/xulux/catalog-client.js +67 -0
  191. package/dist/xulux/catalog-client.js.map +1 -0
  192. package/dist/xulux/fallback-catalog.d.ts +7 -0
  193. package/dist/xulux/fallback-catalog.d.ts.map +1 -0
  194. package/dist/xulux/fallback-catalog.js +47 -0
  195. package/dist/xulux/fallback-catalog.js.map +1 -0
  196. package/dist/xulux/fetch-sandbox.d.ts +5 -0
  197. package/dist/xulux/fetch-sandbox.d.ts.map +1 -0
  198. package/dist/xulux/fetch-sandbox.js +40 -0
  199. package/dist/xulux/fetch-sandbox.js.map +1 -0
  200. package/dist/xulux/template-service.d.ts +84 -0
  201. package/dist/xulux/template-service.d.ts.map +1 -0
  202. package/dist/xulux/template-service.js +223 -0
  203. package/dist/xulux/template-service.js.map +1 -0
  204. package/dist/xulux/types.d.ts +55 -0
  205. package/dist/xulux/types.d.ts.map +1 -0
  206. package/dist/xulux/types.js +6 -0
  207. package/dist/xulux/types.js.map +1 -0
  208. package/package.json +5 -5
  209. package/src/constants.ts +2 -0
  210. package/src/index.ts +67 -0
  211. package/src/prepare-docs/copy-raw.ts +0 -5
  212. package/src/prompts/xulux-playground.ts +36 -0
  213. package/src/tools/docs.ts +52 -4
  214. package/src/tools/examples.ts +18 -11
  215. package/src/tools/resources.ts +114 -0
  216. package/src/tools/search.ts +46 -0
  217. package/src/tools/tests/completions.test.ts +46 -0
  218. package/src/tools/tests/directory-size-cap.test.ts +50 -0
  219. package/src/tools/tests/docs.test.ts +20 -0
  220. package/src/tools/tests/examples.test.ts +5 -5
  221. package/src/tools/tests/listings-cache.test.ts +19 -0
  222. package/src/tools/tests/mcp-protocol.test.ts +92 -1
  223. package/src/tools/tests/resources.test.ts +102 -0
  224. package/src/tools/tests/search.test.ts +37 -0
  225. package/src/tools/tests/test-setup.ts +10 -0
  226. package/src/tools/tests/xulux-templates.test.ts +262 -0
  227. package/src/tools/xulux-templates.ts +141 -0
  228. package/src/utils/cache.ts +20 -0
  229. package/src/utils/mcp-format.ts +8 -6
  230. package/src/utils/mdx.ts +21 -1
  231. package/src/utils/paths.ts +25 -0
  232. package/src/utils/search.ts +131 -0
  233. package/src/utils/tests/cache.test.ts +51 -0
  234. package/src/utils/tests/mcp-format.test.ts +22 -0
  235. package/src/utils/tests/security.test.ts +1 -1
  236. package/src/xulux/catalog-client.ts +105 -0
  237. package/src/xulux/fallback-catalog.ts +63 -0
  238. package/src/xulux/fetch-sandbox.ts +56 -0
  239. package/src/xulux/template-service.ts +406 -0
  240. package/src/xulux/types.ts +60 -0
  241. package/.docs/raw/blog/2024-07-29-hello/index.mdx +0 -64
  242. package/.docs/raw/blog/2024-09-11/index.mdx +0 -10
  243. package/.docs/raw/blog/2024-12-15/index.mdx +0 -10
  244. package/.docs/raw/blog/2025-01-31-changelog/index.mdx +0 -127
  245. package/.docs/raw/blog/2026-03-launch-week/index.mdx +0 -258
  246. package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +0 -464
@@ -8,11 +8,13 @@ import { SpeechSample } from "@/components/docs/samples/speech";
8
8
 
9
9
  assistant-ui supports text-to-speech via the `SpeechSynthesisAdapter` interface. When a speech adapter is configured, users can trigger playback for any assistant message.
10
10
 
11
+ Speech is the read-aloud mode: one message at a time, text to audio. For a live duplex conversation, see [Realtime Voice](/docs/guides/voice). For push-to-talk input into the composer, see [Dictation](/docs/guides/dictation).
12
+
11
13
  <SpeechSample />
12
14
 
13
15
  ## SpeechSynthesisAdapter
14
16
 
15
- The `SpeechSynthesisAdapter` interface has a single method:
17
+ The adapter has a single method. The type lives in `@assistant-ui/core` and is re-exported from `@assistant-ui/react`:
16
18
 
17
19
  ```tsx
18
20
  import type { SpeechSynthesisAdapter } from "@assistant-ui/react";
@@ -22,26 +24,30 @@ type SpeechSynthesisAdapter = {
22
24
  };
23
25
  ```
24
26
 
25
- `speak` is called with the plain text of an assistant message and must return an `Utterance` object:
27
+ `speak` receives the plain text of an assistant message and returns an `Utterance`:
26
28
 
27
29
  ```tsx
28
- type Utterance = {
29
- status: SpeechSynthesisAdapter.Status;
30
- cancel: () => void;
31
- subscribe: (callback: () => void) => Unsubscribe;
32
- };
33
-
34
- type Status =
35
- | { type: "starting" | "running" }
36
- | { type: "ended"; reason: "finished" | "cancelled" | "error"; error?: unknown };
30
+ namespace SpeechSynthesisAdapter {
31
+ type Status =
32
+ | { type: "starting" | "running" }
33
+ | {
34
+ type: "ended";
35
+ reason: "finished" | "cancelled" | "error";
36
+ error?: unknown;
37
+ };
38
+
39
+ type Utterance = {
40
+ status: Status;
41
+ cancel: () => void;
42
+ subscribe: (callback: () => void) => Unsubscribe;
43
+ };
44
+ }
37
45
  ```
38
46
 
39
- Currently the following built-in adapter is available:
40
-
41
- - `WebSpeechSynthesisAdapter`: uses the browser's `Web Speech API` (`SpeechSynthesis`)
42
-
43
47
  ## WebSpeechSynthesisAdapter
44
48
 
49
+ The built-in adapter uses the browser's Web Speech API (`SpeechSynthesis` / `SpeechSynthesisUtterance`):
50
+
45
51
  ```tsx
46
52
  import { WebSpeechSynthesisAdapter } from "@assistant-ui/react";
47
53
 
@@ -52,7 +58,9 @@ const runtime = useChatRuntime({
52
58
  });
53
59
  ```
54
60
 
55
- ## UI
61
+ When a speech adapter is provided, `capabilities.speech` is set to `true` automatically.
62
+
63
+ ## UI: ActionBarPrimitive.Speak
56
64
 
57
65
  The default action bar does not include a speech button. Add `ActionBarPrimitive.Speak` and `ActionBarPrimitive.StopSpeaking` to your assistant message action bar:
58
66
 
@@ -79,21 +87,17 @@ const AssistantActionBar = () => {
79
87
  };
80
88
  ```
81
89
 
82
- `ActionBarPrimitive.Speak` is automatically disabled when no speech adapter is configured.
90
+ `ActionBarPrimitive.Speak` is disabled when no speech adapter is configured. While playback is active, `message.speech` holds the current speech state so the UI can switch to `StopSpeaking`.
83
91
 
84
- ## Custom Adapters
92
+ ## Custom adapters
85
93
 
86
- Implement `SpeechSynthesisAdapter` to call any external TTS API:
94
+ Implement `SpeechSynthesisAdapter` to call any external TTS provider. Fetch audio from your API, play it with `HTMLAudioElement`, and drive utterance status through `subscribe`:
87
95
 
88
96
  ```tsx title="lib/custom-tts-adapter.ts"
89
97
  import type { SpeechSynthesisAdapter } from "@assistant-ui/react";
90
98
 
91
99
  export class CustomTTSAdapter implements SpeechSynthesisAdapter {
92
- private apiUrl: string;
93
-
94
- constructor(options: { apiUrl: string }) {
95
- this.apiUrl = options.apiUrl;
96
- }
100
+ constructor(private apiUrl: string) {}
97
101
 
98
102
  speak(text: string): SpeechSynthesisAdapter.Utterance {
99
103
  const subscribers = new Set<() => void>();
@@ -104,7 +108,10 @@ export class CustomTTSAdapter implements SpeechSynthesisAdapter {
104
108
  for (const cb of subscribers) cb();
105
109
  };
106
110
 
107
- const finish = (reason: "finished" | "cancelled" | "error", error?: unknown) => {
111
+ const finish = (
112
+ reason: "finished" | "cancelled" | "error",
113
+ error?: unknown,
114
+ ) => {
108
115
  if (status.type === "ended") return;
109
116
  status = { type: "ended", reason, error };
110
117
  notify();
@@ -117,17 +124,20 @@ export class CustomTTSAdapter implements SpeechSynthesisAdapter {
117
124
  })
118
125
  .then((res) => res.blob())
119
126
  .then((blob) => {
127
+ if (status.type === "ended") return;
120
128
  audio = new Audio(URL.createObjectURL(blob));
121
129
  status = { type: "running" };
122
130
  notify();
123
131
  audio.onended = () => finish("finished");
124
132
  audio.onerror = (e) => finish("error", e);
125
- audio.play();
133
+ audio.play().catch((err) => finish("error", err));
126
134
  })
127
135
  .catch((err) => finish("error", err));
128
136
 
129
137
  return {
130
- get status() { return status; },
138
+ get status() {
139
+ return status;
140
+ },
131
141
  cancel: () => {
132
142
  audio?.pause();
133
143
  finish("cancelled");
@@ -141,14 +151,22 @@ export class CustomTTSAdapter implements SpeechSynthesisAdapter {
141
151
  }
142
152
  ```
143
153
 
144
- Wire it up the same way as the built-in adapter:
154
+ Wire it on the same `adapters.speech` slot as the built-in adapter:
145
155
 
146
156
  ```tsx
147
157
  import { CustomTTSAdapter } from "@/lib/custom-tts-adapter";
148
158
 
149
159
  const runtime = useChatRuntime({
150
160
  adapters: {
151
- speech: new CustomTTSAdapter({ apiUrl: "/api/tts" }),
161
+ speech: new CustomTTSAdapter("/api/tts"),
152
162
  },
153
163
  });
154
164
  ```
165
+
166
+ Use this shape for any provider TTS (OpenAI, ElevenLabs, cloud speech APIs, and so on). Keep the server route responsible for API keys; the adapter only needs a URL that returns audio bytes.
167
+
168
+ ## Related guides
169
+
170
+ - [Realtime Voice](/docs/guides/voice): duplex voice sessions with `RealtimeVoiceAdapter`, `createVoiceSession`, and the voice UI component.
171
+ - [Dictation](/docs/guides/dictation): speech-to-text into the composer with `DictationAdapter` and `ComposerPrimitive.Dictate`.
172
+ - [Speech and Dictation API reference](/docs/api-reference/voice/speech-dictation): generated type docs.
@@ -163,6 +163,30 @@ const runtime = useLocalRuntime(myChatModel, {
163
163
  });
164
164
  ```
165
165
 
166
+ For LLM-powered follow ups, use `createSuggestionAdapter`. It builds a deterministic transcript prompt from recent messages and calls your `complete` function. Forward the optional `signal` so in-flight generation can be cancelled when a new run starts.
167
+
168
+ ```tsx
169
+ import { createSuggestionAdapter, useLocalRuntime } from "@assistant-ui/react";
170
+
171
+ const suggestionAdapter = createSuggestionAdapter({
172
+ async complete({ prompt, signal }) {
173
+ const response = await fetch("/api/suggestions", {
174
+ method: "POST",
175
+ headers: { "Content-Type": "application/json" },
176
+ body: JSON.stringify({ prompt }),
177
+ signal,
178
+ });
179
+ const data: string[] = await response.json();
180
+ return data;
181
+ },
182
+ count: 3,
183
+ });
184
+
185
+ const runtime = useLocalRuntime(myChatModel, {
186
+ adapters: { suggestion: suggestionAdapter },
187
+ });
188
+ ```
189
+
166
190
  ### External store runtime
167
191
 
168
192
  `useExternalStoreRuntime` exposes a `suggestions` field, so you can drive follow ups straight from your application state.
@@ -190,7 +214,52 @@ const [suggestions, setSuggestions] = useState<ThreadSuggestion[]>([]);
190
214
  const runtime = useChatRuntime({ suggestions });
191
215
  ```
192
216
 
193
- The local runtime clears its suggestions when a new run starts. External store and AI SDK runtimes keep whatever state you push, so you control the lifetime.
217
+ They also accept the same `suggestion` adapter as the local runtime under `adapters`, so one adapter works across both runtimes. When set, the adapter owns `thread.suggestions` after each run settles, and any static `suggestions` option is ignored. Pair it with `createSuggestionAdapter` for built-in prompt construction:
218
+
219
+ ```tsx
220
+ import { createSuggestionAdapter } from "@assistant-ui/react";
221
+ import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
222
+
223
+ const runtime = useChatRuntime({
224
+ adapters: {
225
+ suggestion: createSuggestionAdapter({
226
+ async complete({ prompt, signal }) {
227
+ const response = await fetch("/api/suggestions", {
228
+ method: "POST",
229
+ headers: { "Content-Type": "application/json" },
230
+ body: JSON.stringify({ prompt }),
231
+ signal,
232
+ });
233
+ return response.json();
234
+ },
235
+ }),
236
+ },
237
+ });
238
+ ```
239
+
240
+ Example route that returns suggestion strings with the AI SDK:
241
+
242
+ ```ts
243
+ // app/api/suggestions/route.ts
244
+ import { generateObject } from "ai";
245
+ import { z } from "zod";
246
+
247
+ export async function POST(req: Request) {
248
+ const { prompt } = await req.json();
249
+
250
+ const { object } = await generateObject({
251
+ model: yourModel,
252
+ schema: z.object({
253
+ suggestions: z.array(z.string()).min(1).max(5),
254
+ }),
255
+ prompt,
256
+ });
257
+
258
+ return Response.json(object.suggestions);
259
+ }
260
+ ```
261
+
262
+ The local runtime clears its suggestions when a new run starts. External store runtimes keep whatever state you push, so you control the lifetime. With `adapters.suggestion` on the AI SDK runtime, suggestions clear on run start and regenerate after settle, matching the local runtime.
194
263
 
195
264
  ### Rendering runtime suggestions
196
265