@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.
- package/.docs/organized/code-examples/waterfall.md +1 -1
- package/.docs/organized/code-examples/with-a2a.md +2 -2
- package/.docs/organized/code-examples/with-ag-ui.md +3 -3
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +5 -5
- package/.docs/organized/code-examples/with-artifacts.md +5 -5
- package/.docs/organized/code-examples/with-assistant-transport.md +3 -3
- package/.docs/organized/code-examples/with-chain-of-thought.md +79 -50
- package/.docs/organized/code-examples/with-cloud-standalone.md +4 -4
- package/.docs/organized/code-examples/with-cloud.md +4 -4
- package/.docs/organized/code-examples/with-custom-thread-list.md +56 -11
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +7 -7
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +7 -7
- package/.docs/organized/code-examples/with-expo.md +16 -16
- package/.docs/organized/code-examples/with-external-store.md +2 -2
- package/.docs/organized/code-examples/with-ffmpeg.md +5 -5
- package/.docs/organized/code-examples/with-generative-ui.md +5 -5
- package/.docs/organized/code-examples/with-google-adk.md +4 -4
- package/.docs/organized/code-examples/with-heat-graph.md +1 -1
- package/.docs/organized/code-examples/with-interactables.md +5 -5
- package/.docs/organized/code-examples/with-langchain.md +3 -3
- package/.docs/organized/code-examples/with-langgraph.md +3 -3
- package/.docs/organized/code-examples/with-livekit.md +8 -8
- package/.docs/organized/code-examples/with-opencode.md +99 -54
- package/.docs/organized/code-examples/with-parent-id-grouping.md +4 -4
- package/.docs/organized/code-examples/with-react-hook-form.md +5 -5
- package/.docs/organized/code-examples/with-react-ink.md +1 -1
- package/.docs/organized/code-examples/with-react-router.md +8 -8
- package/.docs/organized/code-examples/with-store.md +1 -1
- package/.docs/organized/code-examples/with-tanstack.md +5 -5
- package/.docs/organized/code-examples/with-tap-runtime.md +2 -2
- package/.docs/raw/docs/(docs)/cli.mdx +2 -1
- package/.docs/raw/docs/(docs)/copilots/assistant-frame.mdx +1 -0
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +10 -3
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +8 -3
- package/.docs/raw/docs/(docs)/copilots/make-assistant-visible.mdx +1 -0
- package/.docs/raw/docs/(docs)/copilots/model-context.mdx +1 -0
- package/.docs/raw/docs/(docs)/copilots/motivation.mdx +1 -0
- package/.docs/raw/docs/(docs)/copilots/use-assistant-instructions.mdx +1 -0
- package/.docs/raw/docs/(docs)/devtools.mdx +1 -0
- package/.docs/raw/docs/(docs)/index.mdx +1 -0
- package/.docs/raw/docs/(docs)/installation.mdx +1 -0
- package/.docs/raw/docs/(docs)/rtl.mdx +1 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/attachments.mdx +34 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/feedback-speech.mdx +41 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/index.mdx +26 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/persistence.mdx +34 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/runtime.mdx +31 -0
- package/.docs/raw/docs/(reference)/api-reference/context-providers/index.mdx +20 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/index.mdx +26 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/model-context.mdx +72 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/runtimes.mdx +41 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/state.mdx +48 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +30 -0
- package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +23 -0
- package/.docs/raw/docs/(reference)/api-reference/overview.mdx +21 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +7 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +65 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +50 -6
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +15 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +36 -1
- package/.docs/raw/docs/(reference)/api-reference/runtimes/index.mdx +38 -0
- package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +5 -0
- package/.docs/raw/docs/(reference)/migrations/v0-14.mdx +144 -6
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +230 -2
- package/.docs/raw/docs/cloud/ai-sdk.mdx +221 -3
- package/.docs/raw/docs/cloud/langgraph.mdx +274 -2
- package/.docs/raw/docs/{(docs)/guides → guides}/attachments.mdx +41 -36
- package/.docs/raw/docs/guides/branching.mdx +76 -0
- package/.docs/raw/docs/guides/chain-of-thought.mdx +166 -0
- package/.docs/raw/docs/{(docs)/guides → guides}/context-api.mdx +50 -22
- package/.docs/raw/docs/{(docs)/guides → guides}/dictation.mdx +2 -0
- package/.docs/raw/docs/guides/editing.mdx +102 -0
- package/.docs/raw/docs/guides/index.mdx +103 -0
- package/.docs/raw/docs/{(docs)/guides → guides}/interactables.mdx +49 -0
- package/.docs/raw/docs/{(docs)/guides → guides}/latex.mdx +51 -8
- package/.docs/raw/docs/{(docs)/guides → guides}/mentions.mdx +61 -86
- package/.docs/raw/docs/{(docs)/guides → guides}/message-timing.mdx +8 -2
- package/.docs/raw/docs/{(docs)/guides → guides}/multi-agent.mdx +64 -4
- package/.docs/raw/docs/{(docs)/guides → guides}/quoting.mdx +10 -17
- package/.docs/raw/docs/{(docs)/guides → guides}/slash-commands.mdx +103 -37
- package/.docs/raw/docs/guides/speech.mdx +156 -0
- package/.docs/raw/docs/{(docs)/guides → guides}/suggestions.mdx +21 -83
- package/.docs/raw/docs/{(docs)/guides → guides}/tool-ui.mdx +108 -36
- package/.docs/raw/docs/{(docs)/guides → guides}/tools.mdx +131 -35
- package/.docs/raw/docs/{(docs)/guides → guides}/voice.mdx +39 -0
- package/.docs/raw/docs/ink/index.mdx +1 -3
- package/.docs/raw/docs/ink/migration.mdx +1 -3
- package/.docs/raw/docs/ink/primitives.mdx +37 -1
- package/.docs/raw/docs/integrations/attachments/custom-adapter.mdx +520 -0
- package/.docs/raw/docs/integrations/auth/better-auth.mdx +191 -0
- package/.docs/raw/docs/integrations/auth/clerk.mdx +172 -0
- package/.docs/raw/docs/integrations/auth/next-auth.mdx +196 -0
- package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +79 -0
- package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +188 -0
- package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +57 -0
- package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +201 -0
- package/.docs/raw/docs/integrations/gateways/index.mdx +157 -0
- package/.docs/raw/docs/integrations/index.mdx +173 -0
- package/.docs/raw/docs/integrations/observability/helicone.mdx +130 -0
- package/.docs/raw/docs/integrations/observability/langfuse.mdx +156 -0
- package/.docs/raw/docs/integrations/observability/langsmith.mdx +146 -0
- package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +712 -0
- package/.docs/raw/docs/integrations/tools/mcp.mdx +267 -0
- package/.docs/raw/docs/primitives/action-bar.mdx +1 -0
- package/.docs/raw/docs/primitives/assistant-modal.mdx +1 -0
- package/.docs/raw/docs/primitives/attachment.mdx +1 -0
- package/.docs/raw/docs/primitives/branch-picker.mdx +1 -0
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +90 -85
- package/.docs/raw/docs/primitives/composer.mdx +2 -1
- package/.docs/raw/docs/primitives/error.mdx +1 -0
- package/.docs/raw/docs/primitives/index.mdx +2 -1
- package/.docs/raw/docs/primitives/message.mdx +68 -5
- package/.docs/raw/docs/primitives/selection-toolbar.mdx +1 -0
- package/.docs/raw/docs/primitives/suggestion.mdx +1 -0
- package/.docs/raw/docs/primitives/thread-list.mdx +39 -0
- package/.docs/raw/docs/primitives/thread.mdx +16 -13
- package/.docs/raw/docs/react-native/index.mdx +1 -3
- package/.docs/raw/docs/react-native/migration.mdx +1 -3
- package/.docs/raw/docs/runtimes/a2a/client-and-hooks.mdx +396 -0
- package/.docs/raw/docs/runtimes/a2a/overview.mdx +60 -0
- package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +216 -0
- package/.docs/raw/docs/runtimes/ag-ui/overview.mdx +70 -0
- package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +243 -0
- package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +123 -0
- package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +52 -0
- package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +71 -131
- package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +69 -63
- package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +330 -123
- package/.docs/raw/docs/runtimes/concepts/adapters.mdx +265 -0
- package/.docs/raw/docs/runtimes/concepts/architecture.mdx +125 -0
- package/.docs/raw/docs/runtimes/concepts/stability.mdx +67 -0
- package/.docs/raw/docs/runtimes/concepts/threads.mdx +428 -0
- package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +703 -0
- package/.docs/raw/docs/runtimes/custom/data-stream.mdx +323 -0
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +253 -1236
- package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +746 -0
- package/.docs/raw/docs/runtimes/custom/overview.mdx +71 -0
- package/.docs/raw/docs/runtimes/google-adk/api.mdx +256 -0
- package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +717 -0
- package/.docs/raw/docs/runtimes/google-adk/overview.mdx +69 -0
- package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +229 -0
- package/.docs/raw/docs/runtimes/langchain.mdx +533 -0
- package/.docs/raw/docs/runtimes/langgraph/generative-ui.mdx +305 -0
- package/.docs/raw/docs/runtimes/langgraph/interrupts.mdx +104 -0
- package/.docs/raw/docs/runtimes/langgraph/overview.mdx +84 -0
- package/.docs/raw/docs/runtimes/langgraph/quickstart.mdx +496 -0
- package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +127 -0
- package/.docs/raw/docs/runtimes/langgraph/threads.mdx +113 -0
- package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +3 -3
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +0 -23
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +1 -1
- package/.docs/raw/docs/runtimes/opencode/hooks.mdx +191 -0
- package/.docs/raw/docs/runtimes/opencode/overview.mdx +48 -0
- package/.docs/raw/docs/runtimes/opencode/quickstart.mdx +119 -0
- package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +71 -203
- package/.docs/raw/docs/ui/accordion.mdx +1 -0
- package/.docs/raw/docs/ui/assistant-modal.mdx +1 -0
- package/.docs/raw/docs/ui/assistant-sidebar.mdx +1 -0
- package/.docs/raw/docs/ui/attachment.mdx +1 -0
- package/.docs/raw/docs/ui/badge.mdx +1 -0
- package/.docs/raw/docs/ui/composer-trigger-popover.mdx +1 -0
- package/.docs/raw/docs/ui/context-display.mdx +1 -0
- package/.docs/raw/docs/ui/diff-viewer.mdx +1 -0
- package/.docs/raw/docs/ui/directive-text.mdx +1 -0
- package/.docs/raw/docs/ui/file.mdx +1 -0
- package/.docs/raw/docs/ui/image.mdx +1 -0
- package/.docs/raw/docs/ui/markdown.mdx +2 -14
- package/.docs/raw/docs/ui/mermaid.mdx +1 -0
- package/.docs/raw/docs/ui/message-timing.mdx +3 -2
- package/.docs/raw/docs/ui/model-selector.mdx +1 -0
- package/.docs/raw/docs/ui/part-grouping.mdx +325 -313
- package/.docs/raw/docs/ui/quote.mdx +1 -0
- package/.docs/raw/docs/ui/reasoning.mdx +66 -33
- package/.docs/raw/docs/ui/scrollbar.mdx +1 -0
- package/.docs/raw/docs/ui/select.mdx +1 -0
- package/.docs/raw/docs/ui/sources.mdx +1 -0
- package/.docs/raw/docs/ui/streamdown.mdx +1 -0
- package/.docs/raw/docs/ui/syntax-highlighting.mdx +1 -0
- package/.docs/raw/docs/ui/tabs.mdx +1 -0
- package/.docs/raw/docs/ui/thread-list.mdx +17 -0
- package/.docs/raw/docs/ui/thread.mdx +56 -1
- package/.docs/raw/docs/ui/tool-fallback.mdx +1 -0
- package/.docs/raw/docs/ui/tool-group.mdx +39 -11
- package/.docs/raw/docs/ui/voice.mdx +1 -0
- package/.docs/raw/docs/utilities/heat-graph.mdx +1 -0
- package/.docs/raw/docs/utilities/react-o11y.mdx +278 -0
- package/.docs/raw/docs/utilities/tw-shimmer.mdx +1 -0
- package/package.json +3 -3
- package/src/tools/tests/path-traversal.test.ts +1 -1
- package/.docs/raw/docs/(docs)/guides/branching.mdx +0 -65
- package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +0 -164
- package/.docs/raw/docs/(docs)/guides/editing.mdx +0 -66
- package/.docs/raw/docs/(docs)/guides/speech.mdx +0 -38
- package/.docs/raw/docs/runtimes/a2a/index.mdx +0 -298
- package/.docs/raw/docs/runtimes/assistant-transport.mdx +0 -1033
- package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +0 -314
- package/.docs/raw/docs/runtimes/custom/local.mdx +0 -1464
- package/.docs/raw/docs/runtimes/data-stream.mdx +0 -422
- package/.docs/raw/docs/runtimes/google-adk/index.mdx +0 -686
- package/.docs/raw/docs/runtimes/helicone.mdx +0 -61
- package/.docs/raw/docs/runtimes/langchain/comparison.mdx +0 -60
- package/.docs/raw/docs/runtimes/langchain/index.mdx +0 -210
- package/.docs/raw/docs/runtimes/langgraph/index.mdx +0 -699
- package/.docs/raw/docs/runtimes/langgraph/tutorial/index.mdx +0 -12
- package/.docs/raw/docs/runtimes/langserve.mdx +0 -116
- package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +0 -218
- package/.docs/raw/docs/runtimes/mastra/overview.mdx +0 -18
- package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +0 -217
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Text-to-Speech (Speech Synthesis)
|
|
3
|
+
description: Read messages aloud with Web Speech API or a custom TTS adapter.
|
|
4
|
+
platforms: ["react"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import { SpeechSample } from "@/components/docs/samples/speech";
|
|
8
|
+
|
|
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
|
+
|
|
11
|
+
<SpeechSample />
|
|
12
|
+
|
|
13
|
+
## SpeechSynthesisAdapter
|
|
14
|
+
|
|
15
|
+
The `SpeechSynthesisAdapter` interface has a single method:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import type { SpeechSynthesisAdapter } from "@assistant-ui/react";
|
|
19
|
+
|
|
20
|
+
type SpeechSynthesisAdapter = {
|
|
21
|
+
speak: (text: string) => SpeechSynthesisAdapter.Utterance;
|
|
22
|
+
};
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`speak` is called with the plain text of an assistant message and must return an `Utterance` object:
|
|
26
|
+
|
|
27
|
+
```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 };
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Currently the following built-in adapter is available:
|
|
40
|
+
|
|
41
|
+
- `WebSpeechSynthesisAdapter`: uses the browser's `Web Speech API` (`SpeechSynthesis`)
|
|
42
|
+
|
|
43
|
+
## WebSpeechSynthesisAdapter
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { WebSpeechSynthesisAdapter } from "@assistant-ui/react";
|
|
47
|
+
|
|
48
|
+
const runtime = useChatRuntime({
|
|
49
|
+
adapters: {
|
|
50
|
+
speech: new WebSpeechSynthesisAdapter(),
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## UI
|
|
56
|
+
|
|
57
|
+
The default action bar does not include a speech button. Add `ActionBarPrimitive.Speak` and `ActionBarPrimitive.StopSpeaking` to your assistant message action bar:
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { ActionBarPrimitive, useMessageTTS } from "@assistant-ui/react";
|
|
61
|
+
import { AudioLinesIcon, StopCircleIcon } from "lucide-react";
|
|
62
|
+
|
|
63
|
+
const AssistantActionBar = () => {
|
|
64
|
+
const isSpeaking = useMessageTTS();
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<ActionBarPrimitive.Root>
|
|
68
|
+
{!isSpeaking && (
|
|
69
|
+
<ActionBarPrimitive.Speak>
|
|
70
|
+
<AudioLinesIcon />
|
|
71
|
+
</ActionBarPrimitive.Speak>
|
|
72
|
+
)}
|
|
73
|
+
{isSpeaking && (
|
|
74
|
+
<ActionBarPrimitive.StopSpeaking>
|
|
75
|
+
<StopCircleIcon />
|
|
76
|
+
</ActionBarPrimitive.StopSpeaking>
|
|
77
|
+
)}
|
|
78
|
+
<ActionBarPrimitive.Copy />
|
|
79
|
+
</ActionBarPrimitive.Root>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`ActionBarPrimitive.Speak` is automatically disabled when no speech adapter is configured.
|
|
85
|
+
|
|
86
|
+
## Custom Adapters
|
|
87
|
+
|
|
88
|
+
Implement `SpeechSynthesisAdapter` to call any external TTS API:
|
|
89
|
+
|
|
90
|
+
```tsx title="lib/custom-tts-adapter.ts"
|
|
91
|
+
import type { SpeechSynthesisAdapter } from "@assistant-ui/react";
|
|
92
|
+
|
|
93
|
+
export class CustomTTSAdapter implements SpeechSynthesisAdapter {
|
|
94
|
+
private apiUrl: string;
|
|
95
|
+
|
|
96
|
+
constructor(options: { apiUrl: string }) {
|
|
97
|
+
this.apiUrl = options.apiUrl;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
speak(text: string): SpeechSynthesisAdapter.Utterance {
|
|
101
|
+
const subscribers = new Set<() => void>();
|
|
102
|
+
let status: SpeechSynthesisAdapter.Status = { type: "starting" };
|
|
103
|
+
let audio: HTMLAudioElement | null = null;
|
|
104
|
+
|
|
105
|
+
const notify = () => {
|
|
106
|
+
for (const cb of subscribers) cb();
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const finish = (reason: "finished" | "cancelled" | "error", error?: unknown) => {
|
|
110
|
+
if (status.type === "ended") return;
|
|
111
|
+
status = { type: "ended", reason, error };
|
|
112
|
+
notify();
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
fetch(this.apiUrl, {
|
|
116
|
+
method: "POST",
|
|
117
|
+
headers: { "Content-Type": "application/json" },
|
|
118
|
+
body: JSON.stringify({ text }),
|
|
119
|
+
})
|
|
120
|
+
.then((res) => res.blob())
|
|
121
|
+
.then((blob) => {
|
|
122
|
+
audio = new Audio(URL.createObjectURL(blob));
|
|
123
|
+
status = { type: "running" };
|
|
124
|
+
notify();
|
|
125
|
+
audio.onended = () => finish("finished");
|
|
126
|
+
audio.onerror = (e) => finish("error", e);
|
|
127
|
+
audio.play();
|
|
128
|
+
})
|
|
129
|
+
.catch((err) => finish("error", err));
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
get status() { return status; },
|
|
133
|
+
cancel: () => {
|
|
134
|
+
audio?.pause();
|
|
135
|
+
finish("cancelled");
|
|
136
|
+
},
|
|
137
|
+
subscribe: (cb) => {
|
|
138
|
+
subscribers.add(cb);
|
|
139
|
+
return () => subscribers.delete(cb);
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Wire it up the same way as the built-in adapter:
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
import { CustomTTSAdapter } from "@/lib/custom-tts-adapter";
|
|
150
|
+
|
|
151
|
+
const runtime = useChatRuntime({
|
|
152
|
+
adapters: {
|
|
153
|
+
speech: new CustomTTSAdapter({ apiUrl: "/api/tts" }),
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
```
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Suggestions
|
|
3
3
|
description: Display suggested prompts to help users get started with your assistant.
|
|
4
|
+
platforms: ["react"]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
Suggestions are pre-defined prompts that help users discover what your assistant can do. They appear in the welcome screen and provide a quick way to start conversations.
|
|
@@ -85,7 +86,7 @@ The default Thread component from the shadcn registry already includes suggestio
|
|
|
85
86
|
|
|
86
87
|
### Customizing Suggestion Display
|
|
87
88
|
|
|
88
|
-
If you want to customize how suggestions are displayed, you can modify your Thread component:
|
|
89
|
+
If you want to customize how suggestions are displayed, you can modify your Thread component. The idiomatic pattern is to wrap the suggestions in `AuiIf` so they only appear when the thread is empty:
|
|
89
90
|
|
|
90
91
|
```tsx
|
|
91
92
|
import {
|
|
@@ -96,17 +97,18 @@ import {
|
|
|
96
97
|
|
|
97
98
|
const ThreadWelcome = () => {
|
|
98
99
|
return (
|
|
99
|
-
<
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
100
|
+
<AuiIf condition={(s) => s.thread.isEmpty}>
|
|
101
|
+
<div className="flex flex-col items-center justify-center">
|
|
102
|
+
<h1>Welcome!</h1>
|
|
103
|
+
<p>How can I help you today?</p>
|
|
104
|
+
|
|
105
|
+
<div className="grid grid-cols-2 gap-2">
|
|
106
|
+
<ThreadPrimitive.Suggestions>
|
|
107
|
+
{() => <SuggestionItem />}
|
|
108
|
+
</ThreadPrimitive.Suggestions>
|
|
109
|
+
</div>
|
|
108
110
|
</div>
|
|
109
|
-
</
|
|
111
|
+
</AuiIf>
|
|
110
112
|
);
|
|
111
113
|
};
|
|
112
114
|
|
|
@@ -126,53 +128,13 @@ const SuggestionItem = () => {
|
|
|
126
128
|
};
|
|
127
129
|
```
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
### ThreadPrimitive.Suggestions
|
|
132
|
-
|
|
133
|
-
Renders all suggestions from the suggestions scope.
|
|
134
|
-
|
|
135
|
-
```tsx
|
|
136
|
-
<ThreadPrimitive.Suggestions>
|
|
137
|
-
{() => <CustomSuggestionComponent />}
|
|
138
|
-
</ThreadPrimitive.Suggestions>
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### SuggestionPrimitive.Title
|
|
142
|
-
|
|
143
|
-
Displays the suggestion's title (the first part when using object format, or the full text when using strings).
|
|
144
|
-
|
|
145
|
-
```tsx
|
|
146
|
-
<SuggestionPrimitive.Title />
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### SuggestionPrimitive.Description
|
|
131
|
+
### Dismissal
|
|
150
132
|
|
|
151
|
-
|
|
133
|
+
Suggestions dismiss automatically once the user sends a message because `thread.isEmpty` becomes false. No extra state management is needed. If you want to dismiss suggestions without sending (for example, after a user clicks away), manage a local boolean and combine it with the `AuiIf` condition or a plain conditional render.
|
|
152
134
|
|
|
153
|
-
|
|
154
|
-
<SuggestionPrimitive.Description />
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### SuggestionPrimitive.Trigger
|
|
158
|
-
|
|
159
|
-
A button that triggers the suggestion action when clicked.
|
|
160
|
-
|
|
161
|
-
```tsx
|
|
162
|
-
<SuggestionPrimitive.Trigger
|
|
163
|
-
send={true}
|
|
164
|
-
clearComposer={true}
|
|
165
|
-
asChild
|
|
166
|
-
>
|
|
167
|
-
<button>Click me</button>
|
|
168
|
-
</SuggestionPrimitive.Trigger>
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
**Props:**
|
|
135
|
+
## Suggestion Primitives
|
|
172
136
|
|
|
173
|
-
|
|
174
|
-
- `clearComposer` (boolean, default: true): When `send` is false, determines if the composer is cleared before adding the suggestion (true) or if the suggestion is appended (false).
|
|
175
|
-
- `asChild` (boolean): Merge props with child element instead of rendering a button.
|
|
137
|
+
The primitives available for rendering suggestions are `ThreadPrimitive.Suggestions`, `ThreadPrimitive.SuggestionByIndex`, `SuggestionPrimitive.Title`, `SuggestionPrimitive.Description`, and `SuggestionPrimitive.Trigger`. `ThreadPrimitive.SuggestionByIndex` is useful when you need layout control over a specific suggestion slot rather than iterating all of them. For the full prop reference and usage patterns, see the [Suggestion primitive docs](/docs/primitives/suggestion).
|
|
176
138
|
|
|
177
139
|
## Dynamic Suggestions
|
|
178
140
|
|
|
@@ -213,30 +175,6 @@ function MyRuntimeProvider({ children }: { children: React.ReactNode }) {
|
|
|
213
175
|
}
|
|
214
176
|
```
|
|
215
177
|
|
|
216
|
-
## Context-Aware Suggestions
|
|
217
|
-
|
|
218
|
-
Suggestions can be tailored to different contexts or user intents:
|
|
219
|
-
|
|
220
|
-
```tsx
|
|
221
|
-
const suggestions = [
|
|
222
|
-
{
|
|
223
|
-
title: "Code Review",
|
|
224
|
-
label: "Get feedback on your code",
|
|
225
|
-
prompt: "Can you review this code for me?",
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
title: "Debug Help",
|
|
229
|
-
label: "Find and fix issues",
|
|
230
|
-
prompt: "Help me debug this error",
|
|
231
|
-
},
|
|
232
|
-
{
|
|
233
|
-
title: "Best Practices",
|
|
234
|
-
label: "Learn recommended patterns",
|
|
235
|
-
prompt: "What are the best practices for this?",
|
|
236
|
-
},
|
|
237
|
-
];
|
|
238
|
-
```
|
|
239
|
-
|
|
240
178
|
## Best Practices
|
|
241
179
|
|
|
242
180
|
1. **Keep suggestions concise**: Use clear, actionable prompts that users can understand at a glance
|
|
@@ -246,11 +184,11 @@ const suggestions = [
|
|
|
246
184
|
5. **Limit the number**: 3-6 suggestions work best to avoid overwhelming users
|
|
247
185
|
6. **Make them actionable**: Each suggestion should lead to a meaningful interaction
|
|
248
186
|
|
|
249
|
-
##
|
|
187
|
+
## Switching from `ThreadPrimitive.Suggestion`
|
|
250
188
|
|
|
251
|
-
If
|
|
189
|
+
If your codebase uses the inline `ThreadPrimitive.Suggestion` component (which renders one suggestion at a time with hardcoded `prompt` / `send` props), you can move to the runtime-driven `Suggestions()` API for centralized configuration. The inline component is still supported, but the runtime-driven approach scales better when suggestions need to update dynamically.
|
|
252
190
|
|
|
253
|
-
###
|
|
191
|
+
### Inline form
|
|
254
192
|
|
|
255
193
|
```tsx
|
|
256
194
|
<ThreadPrimitive.Suggestion
|
|
@@ -259,7 +197,7 @@ If you're using the deprecated `ThreadPrimitive.Suggestion` component, migrate t
|
|
|
259
197
|
/>
|
|
260
198
|
```
|
|
261
199
|
|
|
262
|
-
###
|
|
200
|
+
### Runtime-driven form
|
|
263
201
|
|
|
264
202
|
1. Configure suggestions in your runtime provider:
|
|
265
203
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Generative UI
|
|
3
3
|
description: Render tool calls as interactive UI instead of plain text.
|
|
4
|
+
platforms: ["react"]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
import { ToolUISample } from "@/components/docs/samples/tool-ui";
|
|
@@ -26,7 +27,7 @@ There are two main approaches to creating tool UIs in assistant-ui:
|
|
|
26
27
|
|
|
27
28
|
### 1. Client-Defined Tools (`makeAssistantTool`)
|
|
28
29
|
|
|
29
|
-
If you're creating tools on the client side, use `makeAssistantTool` to register them with the assistant context. Then create a UI component with `makeAssistantToolUI
|
|
30
|
+
If you're creating tools on the client side, use `makeAssistantTool` to register them with the assistant context. Then create a UI component with `makeAssistantToolUI`. This component-based API coexists with the [Tools()](/docs/guides/tools) toolkit API; pick whichever fits your codebase better.
|
|
30
31
|
|
|
31
32
|
```tsx
|
|
32
33
|
import { makeAssistantTool, tool } from "@assistant-ui/react";
|
|
@@ -503,44 +504,97 @@ render: ({ status, args }) => {
|
|
|
503
504
|
};
|
|
504
505
|
```
|
|
505
506
|
|
|
506
|
-
###
|
|
507
|
+
### Deferred Rendering
|
|
507
508
|
|
|
508
|
-
<Callout type="
|
|
509
|
-
|
|
510
|
-
The hook exists internally but is not part of the public API. This section is
|
|
511
|
-
included for reference and may become available in a future release.
|
|
509
|
+
<Callout type="info">
|
|
510
|
+
This section applies when the model **drives** the component through a tool call (args arrive incrementally and you want to wait for the final shape). If your backend or orchestrator pushes the component instead, prefer [Data-Part Generative UI](#data-part-generative-ui) with `makeAssistantDataUI`. Data parts arrive as terminal events, so the renderer only fires once with the final data, no deferred rendering needed.
|
|
512
511
|
</Callout>
|
|
513
512
|
|
|
514
|
-
|
|
513
|
+
Sometimes you want to capture a tool call's streaming arguments but only render the final UI once the call completes. This is useful when partial args would render misleading or jarring intermediate states (a chart that flashes through half-populated data), when the component is expensive to mount (heavy visualizations, embedded iframes, third-party widgets), or when the model controls *whether* the component appears at all.
|
|
514
|
+
|
|
515
|
+
#### Inline at the end of streaming
|
|
516
|
+
|
|
517
|
+
Return `null` from the tool UI's `render` until `status.type === "complete"`. The streaming args still arrive in `args` as the model emits them, you just ignore them until the call is done:
|
|
518
|
+
|
|
519
|
+
```tsx
|
|
520
|
+
const ChartToolUI = makeAssistantToolUI<
|
|
521
|
+
{ title: string; series: number[] },
|
|
522
|
+
void
|
|
523
|
+
>({
|
|
524
|
+
toolName: "renderChart",
|
|
525
|
+
render: ({ args, status }) => {
|
|
526
|
+
if (status.type !== "complete") return null;
|
|
527
|
+
return <Chart title={args.title} data={args.series} />;
|
|
528
|
+
},
|
|
529
|
+
});
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
The chart mounts once, with the final args, after streaming finishes. No re-renders during the stream.
|
|
533
|
+
|
|
534
|
+
The same `render` shape works inside the [`Tools()`](/docs/guides/tools) toolkit's `render` field, with `useAssistantToolUI`, and with `MessagePrimitive.Parts`'s inline `tools.by_name` overrides. The deferred-rendering pattern applies regardless of how you registered the tool UI.
|
|
535
|
+
|
|
536
|
+
#### Below the message body
|
|
537
|
+
|
|
538
|
+
If the component should sit *outside* the message parts (for example, a card attached under the avatar block rather than inline with text), gate at the message level with [`AuiIf`](/docs/api-reference/primitives/assistant-if) and read `s.message.status`:
|
|
515
539
|
|
|
516
540
|
```tsx
|
|
517
|
-
import {
|
|
541
|
+
import { MessagePrimitive, AuiIf, useAuiState } from "@assistant-ui/react";
|
|
542
|
+
|
|
543
|
+
function PostMessageCard() {
|
|
544
|
+
const parts = useAuiState((s) => s.message.parts);
|
|
545
|
+
const chartCall = parts.find(
|
|
546
|
+
(p) => p.type === "tool-call" && p.toolName === "renderChart",
|
|
547
|
+
);
|
|
548
|
+
if (!chartCall) return null;
|
|
549
|
+
return <Chart {...chartCall.args} />;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
<MessagePrimitive.Root>
|
|
553
|
+
<MessagePrimitive.Parts />
|
|
554
|
+
|
|
555
|
+
<AuiIf
|
|
556
|
+
condition={(s) =>
|
|
557
|
+
s.message.role === "assistant" &&
|
|
558
|
+
s.message.status?.type === "complete"
|
|
559
|
+
}
|
|
560
|
+
>
|
|
561
|
+
<PostMessageCard />
|
|
562
|
+
</AuiIf>
|
|
563
|
+
</MessagePrimitive.Root>;
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
The `AuiIf` predicate fires whenever the assistant state changes; children mount only when both checks pass. `PostMessageCard` then reads the captured tool-call part from `s.message.parts` and renders from its args.
|
|
567
|
+
|
|
568
|
+
For the opposite pattern (showing partial data as it streams in), see [Field-Level Streaming State](#field-level-streaming-state) and [Partial Results & Streaming](#partial-results--streaming) below.
|
|
569
|
+
|
|
570
|
+
### Field-Level Streaming State
|
|
571
|
+
|
|
572
|
+
Use `useToolArgsStatus` to react to per-field streaming state. The hook returns a `propStatus` map where each top-level key in the args object resolves from `"streaming"` to `"complete"` as the partial JSON arrives. Call it inside a tool-call message part context:
|
|
518
573
|
|
|
519
|
-
|
|
574
|
+
```tsx
|
|
575
|
+
import { useToolArgsStatus } from "@assistant-ui/react";
|
|
576
|
+
|
|
577
|
+
const FormToolUI = makeAssistantToolUI<{ email: string; phone: string }, unknown>({
|
|
520
578
|
toolName: "submitForm",
|
|
521
579
|
render: ({ args }) => {
|
|
522
|
-
const
|
|
523
|
-
const phoneStatus = useToolArgsFieldStatus(["phone"]);
|
|
580
|
+
const { propStatus } = useToolArgsStatus<{ email: string; phone: string }>();
|
|
524
581
|
|
|
525
582
|
return (
|
|
526
583
|
<form className="space-y-4">
|
|
527
584
|
<div>
|
|
528
585
|
<input
|
|
529
586
|
type="email"
|
|
530
|
-
value={args.email}
|
|
531
|
-
className={
|
|
587
|
+
value={args.email ?? ""}
|
|
588
|
+
className={propStatus.email === "streaming" ? "loading" : ""}
|
|
532
589
|
disabled
|
|
533
590
|
/>
|
|
534
|
-
{emailStatus.type === "incomplete" && (
|
|
535
|
-
<span className="text-red-500">Invalid email</span>
|
|
536
|
-
)}
|
|
537
591
|
</div>
|
|
538
592
|
|
|
539
593
|
<div>
|
|
540
594
|
<input
|
|
541
595
|
type="tel"
|
|
542
|
-
value={args.phone}
|
|
543
|
-
className={
|
|
596
|
+
value={args.phone ?? ""}
|
|
597
|
+
className={propStatus.phone === "streaming" ? "loading" : ""}
|
|
544
598
|
disabled
|
|
545
599
|
/>
|
|
546
600
|
</div>
|
|
@@ -596,24 +650,7 @@ const AnalysisToolUI = makeAssistantToolUI<
|
|
|
596
650
|
|
|
597
651
|
### Custom Tool Fallback
|
|
598
652
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
```tsx
|
|
602
|
-
<Thread
|
|
603
|
-
components={{
|
|
604
|
-
ToolFallback: ({ toolName, args, result }) => (
|
|
605
|
-
<div className="tool-fallback rounded bg-gray-100 p-3">
|
|
606
|
-
<code className="text-sm">
|
|
607
|
-
{toolName}({JSON.stringify(args)})
|
|
608
|
-
</code>
|
|
609
|
-
{result && (
|
|
610
|
-
<pre className="mt-2 text-xs">{JSON.stringify(result, null, 2)}</pre>
|
|
611
|
-
)}
|
|
612
|
-
</div>
|
|
613
|
-
),
|
|
614
|
-
}}
|
|
615
|
-
/>
|
|
616
|
-
```
|
|
653
|
+
For tools that have no dedicated UI, add the `ToolFallback` shadcn component to your project. See the [ToolFallback install guide](/docs/ui/tool-fallback) for setup instructions and the [ToolGroup guide](/docs/ui/tool-group) for grouping consecutive tool calls into a collapsible container.
|
|
617
654
|
|
|
618
655
|
## Execution Context
|
|
619
656
|
|
|
@@ -777,6 +814,41 @@ const WeatherUI = makeAssistantToolUI({
|
|
|
777
814
|
|
|
778
815
|
`propStatus` maps each key to `"streaming"` | `"complete"` once the key appears in the partial JSON. Keys not yet present in the stream are absent from `propStatus`.
|
|
779
816
|
|
|
817
|
+
## Data-Part Generative UI
|
|
818
|
+
|
|
819
|
+
Alongside tool-call rendering, assistant-ui supports a second generative UI mechanism based on `DataMessagePart`. Instead of attaching UI to a tool invocation, the backend (or the LangGraph graph) emits named data events that are appended as `{ type: "data", name, data }` parts on the parent assistant message.
|
|
820
|
+
|
|
821
|
+
**When to choose which:**
|
|
822
|
+
|
|
823
|
+
- **Tool UI**: the **model** decides what to render by calling a tool whose args become the component's data. Register the renderer via the [`Tools()`](/docs/guides/tools) toolkit's `render` field (recommended), or standalone with `makeAssistantToolUI` / `useAssistantToolUI` when the tool itself is defined elsewhere (backend, MCP, LangGraph). Args stream incrementally, so you observe partial state via `status` / `useToolArgsStatus` and may need [Deferred Rendering](#deferred-rendering) for components that should only mount with final data.
|
|
824
|
+
- **Data UI** (`makeAssistantDataUI`): the **backend or orchestrator** decides what to render and pushes a named data event onto the assistant message. Data parts arrive as terminal events with no streaming partials, so the renderer naturally fires once with the final data.
|
|
825
|
+
|
|
826
|
+
If you want a component to appear only after the message is complete and you control the backend, Data UI is usually the more direct fit; reach for Tool UI's deferred pattern when the model itself must drive the choice.
|
|
827
|
+
|
|
828
|
+
Use `makeAssistantDataUI` to register a renderer for a named data part:
|
|
829
|
+
|
|
830
|
+
```tsx
|
|
831
|
+
import { makeAssistantDataUI } from "@assistant-ui/react";
|
|
832
|
+
|
|
833
|
+
type ChartProps = { series: number[]; title: string };
|
|
834
|
+
|
|
835
|
+
export const ChartUI = makeAssistantDataUI<ChartProps>({
|
|
836
|
+
name: "chart",
|
|
837
|
+
render: ({ data }) => (
|
|
838
|
+
<div>
|
|
839
|
+
<h3>{data.title}</h3>
|
|
840
|
+
<Chart series={data.series} />
|
|
841
|
+
</div>
|
|
842
|
+
),
|
|
843
|
+
});
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
Mount `<ChartUI />` once inside the `AssistantRuntimeProvider` tree; it renders nothing itself and only registers the renderer.
|
|
847
|
+
|
|
848
|
+
For LangGraph-specific patterns (emitting UI from a Python/TypeScript graph node via `push_ui_message` / `typedUi`, dynamic loading with `LoadExternalComponent`, and the `useLangGraphUIMessages` escape hatch), see [LangGraph Generative UI](/docs/runtimes/langgraph/generative-ui).
|
|
849
|
+
|
|
850
|
+
A fallback renderer for unmatched data parts is available internally but `setFallbackDataUI` is not yet a public API.
|
|
851
|
+
|
|
780
852
|
## Related Guides
|
|
781
853
|
|
|
782
854
|
- [Tools Guide](/docs/guides/tools) - Learn how to create and use tools with AI models
|