@assistant-ui/mcp-docs-server 0.1.26 → 0.1.27

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 (39) hide show
  1. package/.docs/organized/code-examples/waterfall.md +1 -1
  2. package/.docs/organized/code-examples/with-a2a.md +1 -1
  3. package/.docs/organized/code-examples/with-ag-ui.md +2 -2
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +3 -3
  5. package/.docs/organized/code-examples/with-artifacts.md +3 -3
  6. package/.docs/organized/code-examples/with-assistant-transport.md +1 -1
  7. package/.docs/organized/code-examples/with-chain-of-thought.md +3 -3
  8. package/.docs/organized/code-examples/with-cloud-standalone.md +3 -3
  9. package/.docs/organized/code-examples/with-cloud.md +3 -3
  10. package/.docs/organized/code-examples/with-custom-thread-list.md +3 -3
  11. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +511 -0
  12. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +5 -5
  13. package/.docs/organized/code-examples/with-expo.md +17 -17
  14. package/.docs/organized/code-examples/with-external-store.md +1 -1
  15. package/.docs/organized/code-examples/with-ffmpeg.md +216 -62
  16. package/.docs/organized/code-examples/with-google-adk.md +2 -2
  17. package/.docs/organized/code-examples/with-heat-graph.md +1 -1
  18. package/.docs/organized/code-examples/with-interactables.md +66 -8
  19. package/.docs/organized/code-examples/with-langgraph.md +2 -2
  20. package/.docs/organized/code-examples/with-livekit.md +591 -0
  21. package/.docs/organized/code-examples/with-parent-id-grouping.md +2 -2
  22. package/.docs/organized/code-examples/with-react-hook-form.md +3 -3
  23. package/.docs/organized/code-examples/with-react-ink.md +1 -1
  24. package/.docs/organized/code-examples/with-react-router.md +6 -6
  25. package/.docs/organized/code-examples/with-store.md +7 -2
  26. package/.docs/organized/code-examples/with-tanstack.md +3 -3
  27. package/.docs/organized/code-examples/with-tap-runtime.md +1 -1
  28. package/.docs/raw/docs/(docs)/copilots/model-context.mdx +9 -1
  29. package/.docs/raw/docs/(docs)/guides/interactables.mdx +99 -37
  30. package/.docs/raw/docs/(docs)/guides/tool-ui.mdx +29 -0
  31. package/.docs/raw/docs/(docs)/guides/voice.mdx +333 -0
  32. package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +23 -0
  33. package/.docs/raw/docs/runtimes/a2a/index.mdx +4 -0
  34. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +2 -2
  35. package/.docs/raw/docs/runtimes/assistant-transport.mdx +6 -2
  36. package/.docs/raw/docs/ui/context-display.mdx +2 -2
  37. package/.docs/raw/docs/ui/model-selector.mdx +1 -1
  38. package/.docs/raw/docs/ui/voice.mdx +172 -0
  39. package/package.json +3 -4
@@ -769,7 +769,7 @@ export default nextConfig;
769
769
  "@assistant-ui/react-o11y": "workspace:*",
770
770
  "@assistant-ui/store": "workspace:*",
771
771
  "@assistant-ui/tap": "workspace:*",
772
- "next": "^16.2.1",
772
+ "next": "^16.2.2",
773
773
  "react": "^19.2.4",
774
774
  "react-dom": "^19.2.4"
775
775
  },
@@ -569,7 +569,7 @@ export default nextConfig;
569
569
  "class-variance-authority": "^0.7.1",
570
570
  "clsx": "^2.1.1",
571
571
  "lucide-react": "^1.7.0",
572
- "next": "^16.2.1",
572
+ "next": "^16.2.2",
573
573
  "react": "^19.2.4",
574
574
  "react-dom": "^19.2.4",
575
575
  "tailwind-merge": "^3.5.0"
@@ -413,7 +413,7 @@ export default nextConfig;
413
413
  "start": "next start"
414
414
  },
415
415
  "dependencies": {
416
- "@ag-ui/client": "^0.0.48",
416
+ "@ag-ui/client": "^0.0.49",
417
417
  "@assistant-ui/react": "workspace:*",
418
418
  "@assistant-ui/react-ag-ui": "workspace:*",
419
419
  "@assistant-ui/react-markdown": "workspace:*",
@@ -421,7 +421,7 @@ export default nextConfig;
421
421
  "class-variance-authority": "^0.7.1",
422
422
  "clsx": "^2.1.1",
423
423
  "lucide-react": "^1.7.0",
424
- "next": "^16.2.1",
424
+ "next": "^16.2.2",
425
425
  "react": "^19.2.4",
426
426
  "react-dom": "^19.2.4",
427
427
  "tailwind-merge": "^3.5.0"
@@ -315,16 +315,16 @@ export default nextConfig;
315
315
  "start": "next start"
316
316
  },
317
317
  "dependencies": {
318
- "@ai-sdk/openai": "^3.0.48",
318
+ "@ai-sdk/openai": "^3.0.50",
319
319
  "@assistant-ui/react": "workspace:*",
320
320
  "@assistant-ui/react-ai-sdk": "workspace:*",
321
321
  "@assistant-ui/react-markdown": "workspace:*",
322
322
  "@assistant-ui/ui": "workspace:*",
323
- "ai": "^6.0.138",
323
+ "ai": "^6.0.144",
324
324
  "class-variance-authority": "^0.7.1",
325
325
  "clsx": "^2.1.1",
326
326
  "lucide-react": "^1.7.0",
327
- "next": "^16.2.1",
327
+ "next": "^16.2.2",
328
328
  "react": "^19.2.4",
329
329
  "react-dom": "^19.2.4",
330
330
  "tailwind-merge": "^3.5.0",
@@ -413,16 +413,16 @@ export default nextConfig;
413
413
  "start": "next start"
414
414
  },
415
415
  "dependencies": {
416
- "@ai-sdk/openai": "^3.0.48",
416
+ "@ai-sdk/openai": "^3.0.50",
417
417
  "@assistant-ui/react": "workspace:*",
418
418
  "@assistant-ui/react-ai-sdk": "workspace:*",
419
419
  "@assistant-ui/react-markdown": "workspace:*",
420
420
  "@assistant-ui/ui": "workspace:*",
421
- "ai": "^6.0.138",
421
+ "ai": "^6.0.144",
422
422
  "class-variance-authority": "^0.7.1",
423
423
  "clsx": "^2.1.1",
424
424
  "lucide-react": "^1.7.0",
425
- "next": "^16.2.1",
425
+ "next": "^16.2.2",
426
426
  "react": "^19.2.4",
427
427
  "react-dom": "^19.2.4",
428
428
  "tailwind-merge": "^3.5.0",
@@ -424,7 +424,7 @@ export default nextConfig;
424
424
  "class-variance-authority": "^0.7.1",
425
425
  "clsx": "^2.1.1",
426
426
  "lucide-react": "^1.7.0",
427
- "next": "^16.2.1",
427
+ "next": "^16.2.2",
428
428
  "react": "^19.2.4",
429
429
  "react-dom": "^19.2.4",
430
430
  "tailwind-merge": "^3.5.0",
@@ -557,16 +557,16 @@ export default nextConfig;
557
557
  "start": "next start"
558
558
  },
559
559
  "dependencies": {
560
- "@ai-sdk/openai": "^3.0.48",
560
+ "@ai-sdk/openai": "^3.0.50",
561
561
  "@assistant-ui/react": "workspace:*",
562
562
  "@assistant-ui/react-ai-sdk": "workspace:*",
563
563
  "@assistant-ui/react-markdown": "workspace:*",
564
564
  "@assistant-ui/ui": "workspace:*",
565
- "ai": "^6.0.138",
565
+ "ai": "^6.0.144",
566
566
  "class-variance-authority": "^0.7.1",
567
567
  "clsx": "^2.1.1",
568
568
  "lucide-react": "^1.7.0",
569
- "next": "^16.2.1",
569
+ "next": "^16.2.2",
570
570
  "react": "^19.2.4",
571
571
  "react-dom": "^19.2.4",
572
572
  "tailwind-merge": "^3.5.0",
@@ -565,13 +565,13 @@ export default nextConfig;
565
565
  "start": "next start"
566
566
  },
567
567
  "dependencies": {
568
- "@ai-sdk/openai": "^3.0.48",
568
+ "@ai-sdk/openai": "^3.0.50",
569
569
  "@assistant-ui/cloud-ai-sdk": "workspace:*",
570
- "ai": "^6.0.138",
570
+ "ai": "^6.0.144",
571
571
  "class-variance-authority": "^0.7.1",
572
572
  "clsx": "^2.1.1",
573
573
  "lucide-react": "^1.7.0",
574
- "next": "^16.2.1",
574
+ "next": "^16.2.2",
575
575
  "react": "^19.2.4",
576
576
  "react-dom": "^19.2.4",
577
577
  "tailwind-merge": "^3.5.0"
@@ -327,16 +327,16 @@ export default nextConfig;
327
327
  "start": "next start"
328
328
  },
329
329
  "dependencies": {
330
- "@ai-sdk/openai": "^3.0.48",
330
+ "@ai-sdk/openai": "^3.0.50",
331
331
  "@assistant-ui/react": "workspace:*",
332
332
  "@assistant-ui/react-ai-sdk": "workspace:*",
333
333
  "@assistant-ui/react-markdown": "workspace:*",
334
334
  "@assistant-ui/ui": "workspace:*",
335
- "ai": "^6.0.138",
335
+ "ai": "^6.0.144",
336
336
  "class-variance-authority": "^0.7.1",
337
337
  "clsx": "^2.1.1",
338
338
  "lucide-react": "^1.7.0",
339
- "next": "^16.2.1",
339
+ "next": "^16.2.2",
340
340
  "react": "^19.2.4",
341
341
  "react-dom": "^19.2.4",
342
342
  "tailwind-merge": "^3.5.0"
@@ -414,17 +414,17 @@ export default nextConfig;
414
414
  "start": "next start"
415
415
  },
416
416
  "dependencies": {
417
- "@ai-sdk/openai": "^3.0.48",
417
+ "@ai-sdk/openai": "^3.0.50",
418
418
  "@assistant-ui/react": "workspace:*",
419
419
  "@assistant-ui/react-ai-sdk": "workspace:*",
420
420
  "@assistant-ui/react-markdown": "workspace:*",
421
421
  "@assistant-ui/ui": "workspace:*",
422
- "ai": "^6.0.138",
422
+ "ai": "^6.0.144",
423
423
  "assistant-stream": "workspace:*",
424
424
  "class-variance-authority": "^0.7.1",
425
425
  "clsx": "^2.1.1",
426
426
  "lucide-react": "^1.7.0",
427
- "next": "^16.2.1",
427
+ "next": "^16.2.2",
428
428
  "react": "^19.2.4",
429
429
  "react-dom": "^19.2.4",
430
430
  "tailwind-merge": "^3.5.0",
@@ -0,0 +1,511 @@
1
+ # Example: with-elevenlabs-conversational
2
+
3
+ ## app/api/chat/route.ts
4
+
5
+ ```typescript
6
+ import { openai } from "@ai-sdk/openai";
7
+ import { streamText, UIMessage, convertToModelMessages, stepCountIs } from "ai";
8
+
9
+ export const maxDuration = 30;
10
+
11
+ export async function POST(req: Request) {
12
+ const { messages }: { messages: UIMessage[] } = await req.json();
13
+
14
+ const result = streamText({
15
+ model: openai("gpt-4o"),
16
+ messages: await convertToModelMessages(messages),
17
+ stopWhen: stepCountIs(10),
18
+ });
19
+
20
+ return result.toUIMessageStreamResponse();
21
+ }
22
+
23
+ ```
24
+
25
+ ## app/globals.css
26
+
27
+ ```css
28
+ @import "tailwindcss";
29
+ @import "tw-animate-css";
30
+
31
+ @source "../../../packages/ui/src";
32
+
33
+ @custom-variant dark (&:is(.dark *));
34
+
35
+ @theme inline {
36
+ --radius-sm: calc(var(--radius) - 4px);
37
+ --radius-md: calc(var(--radius) - 2px);
38
+ --radius-lg: var(--radius);
39
+ --radius-xl: calc(var(--radius) + 4px);
40
+ --color-background: var(--background);
41
+ --color-foreground: var(--foreground);
42
+ --color-card: var(--card);
43
+ --color-card-foreground: var(--card-foreground);
44
+ --color-popover: var(--popover);
45
+ --color-popover-foreground: var(--popover-foreground);
46
+ --color-primary: var(--primary);
47
+ --color-primary-foreground: var(--primary-foreground);
48
+ --color-secondary: var(--secondary);
49
+ --color-secondary-foreground: var(--secondary-foreground);
50
+ --color-muted: var(--muted);
51
+ --color-muted-foreground: var(--muted-foreground);
52
+ --color-accent: var(--accent);
53
+ --color-accent-foreground: var(--accent-foreground);
54
+ --color-destructive: var(--destructive);
55
+ --color-border: var(--border);
56
+ --color-input: var(--input);
57
+ --color-ring: var(--ring);
58
+ }
59
+
60
+ :root {
61
+ --radius: 0.625rem;
62
+ --background: oklch(1 0 0);
63
+ --foreground: oklch(0.141 0.005 285.823);
64
+ --primary: oklch(0.21 0.006 285.885);
65
+ --primary-foreground: oklch(0.985 0 0);
66
+ --secondary: oklch(0.967 0.001 286.375);
67
+ --secondary-foreground: oklch(0.21 0.006 285.885);
68
+ --muted: oklch(0.967 0.001 286.375);
69
+ --muted-foreground: oklch(0.552 0.016 285.938);
70
+ --accent: oklch(0.967 0.001 286.375);
71
+ --accent-foreground: oklch(0.21 0.006 285.885);
72
+ --destructive: oklch(0.577 0.245 27.325);
73
+ --border: oklch(0.92 0.004 286.32);
74
+ --input: oklch(0.92 0.004 286.32);
75
+ --ring: oklch(0.705 0.015 286.067);
76
+ --card: oklch(1 0 0);
77
+ --card-foreground: oklch(0.141 0.005 285.823);
78
+ --popover: oklch(1 0 0);
79
+ --popover-foreground: oklch(0.141 0.005 285.823);
80
+ }
81
+
82
+ @layer base {
83
+ * {
84
+ @apply border-border outline-ring/50;
85
+ }
86
+ body {
87
+ @apply bg-background text-foreground;
88
+ }
89
+ }
90
+
91
+ ```
92
+
93
+ ## app/layout.tsx
94
+
95
+ ```tsx
96
+ import type { Metadata } from "next";
97
+ import "./globals.css";
98
+
99
+ export const metadata: Metadata = {
100
+ title: "ElevenLabs Conversational AI Example",
101
+ description:
102
+ "Example using @assistant-ui/react with ElevenLabs Conversational AI for realtime voice",
103
+ };
104
+
105
+ export default function RootLayout({
106
+ children,
107
+ }: Readonly<{
108
+ children: React.ReactNode;
109
+ }>) {
110
+ return (
111
+ <html lang="en">
112
+ <body className="h-dvh">{children}</body>
113
+ </html>
114
+ );
115
+ }
116
+
117
+ ```
118
+
119
+ ## app/page.tsx
120
+
121
+ ```tsx
122
+ "use client";
123
+
124
+ import { AssistantRuntimeProvider } from "@assistant-ui/react";
125
+ import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
126
+ import { ElevenLabsVoiceAdapter } from "@/lib/elevenlabs-voice-adapter";
127
+ import { VoiceThread } from "./voice-thread";
128
+
129
+ export default function Home() {
130
+ const runtime = useChatRuntime({
131
+ adapters: {
132
+ voice: new ElevenLabsVoiceAdapter({
133
+ agentId: process.env.NEXT_PUBLIC_ELEVENLABS_AGENT_ID ?? "",
134
+ }),
135
+ },
136
+ });
137
+
138
+ return (
139
+ <AssistantRuntimeProvider runtime={runtime}>
140
+ <VoiceThread />
141
+ </AssistantRuntimeProvider>
142
+ );
143
+ }
144
+
145
+ ```
146
+
147
+ ## app/voice-thread.tsx
148
+
149
+ ```tsx
150
+ "use client";
151
+
152
+ import { MarkdownText } from "@/components/assistant-ui/markdown-text";
153
+ import {
154
+ VoiceOrb,
155
+ VoiceConnectButton,
156
+ VoiceMuteButton,
157
+ VoiceDisconnectButton,
158
+ deriveVoiceOrbState,
159
+ } from "@/components/assistant-ui/voice";
160
+ import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
161
+ import {
162
+ AuiIf,
163
+ MessagePrimitive,
164
+ ThreadPrimitive,
165
+ useAuiState,
166
+ useVoiceState,
167
+ useVoiceVolume,
168
+ } from "@assistant-ui/react";
169
+ import { ArrowDownIcon } from "lucide-react";
170
+ import type { FC } from "react";
171
+
172
+ export const VoiceThread: FC = () => {
173
+ return (
174
+ <ThreadPrimitive.Root
175
+ className="aui-root aui-thread-root flex h-full flex-col bg-background"
176
+ style={{ ["--thread-max-width" as string]: "44rem" }}
177
+ >
178
+ <ThreadPrimitive.Viewport className="aui-thread-viewport relative flex flex-1 flex-col overflow-y-scroll scroll-smooth px-4 pt-4">
179
+ <AuiIf condition={(s) => s.thread.isEmpty}>
180
+ <VoiceWelcome />
181
+ </AuiIf>
182
+
183
+ <ThreadPrimitive.Messages>
184
+ {() => <ThreadMessage />}
185
+ </ThreadPrimitive.Messages>
186
+
187
+ <ThreadPrimitive.ViewportFooter className="sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col items-center bg-background pt-4 pb-6">
188
+ <ThreadScrollToBottom />
189
+ <VoiceControlCenter />
190
+ </ThreadPrimitive.ViewportFooter>
191
+ </ThreadPrimitive.Viewport>
192
+ </ThreadPrimitive.Root>
193
+ );
194
+ };
195
+
196
+ const VoiceWelcome: FC = () => {
197
+ return (
198
+ <div className="aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col items-center justify-center gap-2">
199
+ <p className="fade-in slide-in-from-bottom-1 animate-in fill-mode-both font-semibold text-2xl duration-200">
200
+ Voice Conversation
201
+ </p>
202
+ <p className="fade-in slide-in-from-bottom-1 animate-in fill-mode-both text-muted-foreground delay-75 duration-200">
203
+ Tap connect to start speaking
204
+ </p>
205
+ </div>
206
+ );
207
+ };
208
+
209
+ const ThreadScrollToBottom: FC = () => {
210
+ return (
211
+ <ThreadPrimitive.ScrollToBottom asChild>
212
+ <TooltipIconButton
213
+ tooltip="Scroll to bottom"
214
+ variant="outline"
215
+ className="absolute -top-12 z-10 self-center rounded-full p-4 disabled:invisible dark:border-border dark:bg-background dark:hover:bg-accent"
216
+ >
217
+ <ArrowDownIcon />
218
+ </TooltipIconButton>
219
+ </ThreadPrimitive.ScrollToBottom>
220
+ );
221
+ };
222
+
223
+ const VoiceControlCenter: FC = () => {
224
+ return (
225
+ <div className="aui-voice-control-center flex flex-col items-center gap-4">
226
+ <VoiceOrb variant="blue" className="size-20" />
227
+ <VoiceWaveform />
228
+
229
+ <div className="flex items-center gap-3">
230
+ <AuiIf
231
+ condition={(s) =>
232
+ s.thread.voice == null || s.thread.voice.status.type === "ended"
233
+ }
234
+ >
235
+ <VoiceConnectButton />
236
+ </AuiIf>
237
+
238
+ <AuiIf condition={(s) => s.thread.voice?.status.type === "starting"}>
239
+ <span className="text-muted-foreground text-sm">Connecting...</span>
240
+ </AuiIf>
241
+
242
+ <AuiIf condition={(s) => s.thread.voice?.status.type === "running"}>
243
+ <VoiceMuteButton />
244
+ <VoiceDisconnectButton />
245
+ </AuiIf>
246
+ </div>
247
+ </div>
248
+ );
249
+ };
250
+
251
+ const BAR_WEIGHTS = [0.4, 0.65, 0.85, 1.0, 0.9, 0.75, 0.5];
252
+
253
+ const VoiceWaveform: FC = () => {
254
+ const voiceState = useVoiceState();
255
+ const state = deriveVoiceOrbState(voiceState);
256
+ const volume = useVoiceVolume();
257
+ const isActive = state === "listening" || state === "speaking";
258
+
259
+ return (
260
+ <div className="aui-voice-waveform flex h-8 items-center justify-center gap-[3px]">
261
+ {BAR_WEIGHTS.map((weight, i) => {
262
+ const scale = isActive ? 0.1 + volume * 0.9 * weight : 0.1;
263
+ return (
264
+ <span
265
+ key={i}
266
+ className="aui-voice-waveform-bar h-full w-[3px] origin-center rounded-full bg-foreground/50 transition-transform duration-100"
267
+ style={{ transform: `scaleY(${scale})` }}
268
+ />
269
+ );
270
+ })}
271
+ </div>
272
+ );
273
+ };
274
+
275
+ const ThreadMessage: FC = () => {
276
+ const role = useAuiState((s) => s.message.role);
277
+ if (role === "user") return <UserMessage />;
278
+ return <AssistantMessage />;
279
+ };
280
+
281
+ const AssistantMessage: FC = () => {
282
+ return (
283
+ <MessagePrimitive.Root
284
+ className="aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150"
285
+ data-role="assistant"
286
+ >
287
+ <div className="aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed">
288
+ <MessagePrimitive.Parts>
289
+ {({ part }) => {
290
+ if (part.type === "text") return <MarkdownText />;
291
+ return null;
292
+ }}
293
+ </MessagePrimitive.Parts>
294
+ </div>
295
+ </MessagePrimitive.Root>
296
+ );
297
+ };
298
+
299
+ const UserMessage: FC = () => {
300
+ return (
301
+ <MessagePrimitive.Root
302
+ className="aui-user-message-root fade-in slide-in-from-bottom-1 mx-auto flex w-full max-w-(--thread-max-width) animate-in justify-end px-2 py-3 duration-150"
303
+ data-role="user"
304
+ >
305
+ <div className="aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground">
306
+ <MessagePrimitive.Parts />
307
+ </div>
308
+ </MessagePrimitive.Root>
309
+ );
310
+ };
311
+
312
+ ```
313
+
314
+ ## components.json
315
+
316
+ ```json
317
+ {
318
+ "$schema": "https://ui.shadcn.com/schema.json",
319
+ "style": "new-york",
320
+ "rsc": true,
321
+ "tsx": true,
322
+ "tailwind": {
323
+ "config": "",
324
+ "css": "app/globals.css",
325
+ "baseColor": "zinc",
326
+ "cssVariables": true,
327
+ "prefix": ""
328
+ },
329
+ "aliases": {
330
+ "components": "@/components",
331
+ "utils": "@/lib/utils",
332
+ "ui": "@/components/ui",
333
+ "lib": "@/lib",
334
+ "hooks": "@/hooks"
335
+ },
336
+ "iconLibrary": "lucide",
337
+ "registries": {
338
+ "@assistant-ui": "https://r.assistant-ui.com/{name}.json"
339
+ }
340
+ }
341
+
342
+ ```
343
+
344
+ ## lib/elevenlabs-voice-adapter.ts
345
+
346
+ ```typescript
347
+ import type { RealtimeVoiceAdapter } from "@assistant-ui/react";
348
+ import { createVoiceSession } from "@assistant-ui/react";
349
+ import { VoiceConversation } from "@elevenlabs/client";
350
+
351
+ export type ElevenLabsVoiceAdapterOptions = {
352
+ agentId: string;
353
+ };
354
+
355
+ export class ElevenLabsVoiceAdapter implements RealtimeVoiceAdapter {
356
+ private _agentId: string;
357
+
358
+ constructor(options: ElevenLabsVoiceAdapterOptions) {
359
+ this._agentId = options.agentId;
360
+ }
361
+
362
+ connect(options: {
363
+ abortSignal?: AbortSignal;
364
+ }): RealtimeVoiceAdapter.Session {
365
+ return createVoiceSession(options, async (session) => {
366
+ let volumeInterval: ReturnType<typeof setInterval> | null = null;
367
+
368
+ const conversation = await VoiceConversation.startSession({
369
+ agentId: this._agentId,
370
+ onConnect: () => {
371
+ session.setStatus({ type: "running" });
372
+ volumeInterval = setInterval(() => {
373
+ if (session.isDisposed()) return;
374
+ const vol = Math.max(
375
+ conversation.getInputVolume(),
376
+ conversation.getOutputVolume(),
377
+ );
378
+ session.emitVolume(vol);
379
+ }, 50);
380
+ },
381
+ onDisconnect: () => {
382
+ if (volumeInterval) clearInterval(volumeInterval);
383
+ session.end("finished");
384
+ },
385
+ onError: (message) => {
386
+ if (volumeInterval) clearInterval(volumeInterval);
387
+ session.end("error", new Error(message));
388
+ },
389
+ onModeChange: ({ mode }) => {
390
+ session.emitMode(mode === "speaking" ? "speaking" : "listening");
391
+ },
392
+ onMessage: (message) => {
393
+ session.emitTranscript({
394
+ role: message.role === "user" ? "user" : "assistant",
395
+ text: message.message,
396
+ isFinal: true,
397
+ });
398
+ },
399
+ });
400
+
401
+ return {
402
+ disconnect: () => {
403
+ if (volumeInterval) clearInterval(volumeInterval);
404
+ conversation.endSession();
405
+ },
406
+ mute: () => conversation.setMicMuted(true),
407
+ unmute: () => conversation.setMicMuted(false),
408
+ };
409
+ });
410
+ }
411
+ }
412
+
413
+ ```
414
+
415
+ ## next.config.js
416
+
417
+ ```javascript
418
+ /** @type {import('next').NextConfig} */
419
+ const nextConfig = {
420
+ transpilePackages: ["@assistant-ui/react", "@assistant-ui/react-ai-sdk"],
421
+ };
422
+
423
+ export default nextConfig;
424
+
425
+ ```
426
+
427
+ ## package.json
428
+
429
+ ```json
430
+ {
431
+ "name": "with-elevenlabs-conversational",
432
+ "private": true,
433
+ "version": "0.0.0",
434
+ "type": "module",
435
+ "dependencies": {
436
+ "@ai-sdk/openai": "^3.0.50",
437
+ "@ai-sdk/react": "^3.0.146",
438
+ "@assistant-ui/react": "workspace:^",
439
+ "@assistant-ui/react-ai-sdk": "workspace:*",
440
+ "@assistant-ui/react-markdown": "workspace:^",
441
+ "@assistant-ui/ui": "workspace:*",
442
+ "@elevenlabs/client": "^1.1.0",
443
+ "@tailwindcss/postcss": "^4.2.2",
444
+ "ai": "^6.0.144",
445
+ "class-variance-authority": "^0.7.1",
446
+ "clsx": "^2.1.1",
447
+ "lucide-react": "^1.7.0",
448
+ "motion": "^12.38.0",
449
+ "next": "^16.2.2",
450
+ "postcss": "^8.5.8",
451
+ "react": "^19.2.4",
452
+ "react-dom": "^19.2.4",
453
+ "tailwind-merge": "^3.5.0",
454
+ "tailwindcss": "^4.2.2",
455
+ "zod": "^4.3.6"
456
+ },
457
+ "devDependencies": {
458
+ "@assistant-ui/x-buildutils": "workspace:*",
459
+ "@types/node": "^25.5.0",
460
+ "@types/react": "^19.2.14",
461
+ "@types/react-dom": "^19.2.3",
462
+ "tw-animate-css": "^1.4.0",
463
+ "typescript": "5.9.3"
464
+ },
465
+ "scripts": {
466
+ "dev": "next dev",
467
+ "build": "next build",
468
+ "start": "next start"
469
+ }
470
+ }
471
+
472
+ ```
473
+
474
+ ## tsconfig.json
475
+
476
+ ```json
477
+ {
478
+ "extends": "@assistant-ui/x-buildutils/ts/base",
479
+ "compilerOptions": {
480
+ "target": "ES6",
481
+ "module": "ESNext",
482
+ "incremental": true,
483
+ "plugins": [
484
+ {
485
+ "name": "next"
486
+ }
487
+ ],
488
+ "allowJs": true,
489
+ "strictNullChecks": true,
490
+ "jsx": "preserve",
491
+ "paths": {
492
+ "@/*": ["./*"],
493
+ "@/components/assistant-ui/*": [
494
+ "../../packages/ui/src/components/assistant-ui/*"
495
+ ],
496
+ "@/components/ui/*": ["../../packages/ui/src/components/ui/*"],
497
+ "@/lib/utils": ["../../packages/ui/src/lib/utils"],
498
+ "@assistant-ui/ui/*": ["../../packages/ui/src/*"],
499
+ "@assistant-ui/*": ["../../packages/*/src"],
500
+ "@assistant-ui/react/*": ["../../packages/react/src/*"],
501
+ "@assistant-ui/tap/*": ["../../packages/tap/src/*"],
502
+ "assistant-stream": ["../../packages/assistant-stream/src"],
503
+ "assistant-stream/*": ["../../packages/assistant-stream/src/*"]
504
+ }
505
+ },
506
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
507
+ "exclude": ["node_modules"]
508
+ }
509
+
510
+ ```
511
+