@assistant-ui/mcp-docs-server 0.1.28 → 0.1.30

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 (56) hide show
  1. package/.docs/organized/code-examples/waterfall.md +18 -10
  2. package/.docs/organized/code-examples/with-a2a.md +12 -24
  3. package/.docs/organized/code-examples/with-ag-ui.md +14 -11
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +12 -12
  5. package/.docs/organized/code-examples/with-artifacts.md +14 -12
  6. package/.docs/organized/code-examples/with-assistant-transport.md +13 -14
  7. package/.docs/organized/code-examples/with-chain-of-thought.md +11 -11
  8. package/.docs/organized/code-examples/with-cloud-standalone.md +17 -14
  9. package/.docs/organized/code-examples/with-cloud.md +12 -13
  10. package/.docs/organized/code-examples/with-custom-thread-list.md +12 -12
  11. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +19 -14
  12. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +15 -15
  13. package/.docs/organized/code-examples/with-expo.md +27 -23
  14. package/.docs/organized/code-examples/with-external-store.md +11 -11
  15. package/.docs/organized/code-examples/with-ffmpeg.md +19 -14
  16. package/.docs/organized/code-examples/with-generative-ui.md +11 -11
  17. package/.docs/organized/code-examples/with-google-adk.md +10 -10
  18. package/.docs/organized/code-examples/with-heat-graph.md +8 -8
  19. package/.docs/organized/code-examples/with-interactables.md +12 -27
  20. package/.docs/organized/code-examples/with-langchain.md +437 -0
  21. package/.docs/organized/code-examples/with-langgraph.md +20 -20
  22. package/.docs/organized/code-examples/with-livekit.md +59 -18
  23. package/.docs/organized/code-examples/with-opencode.md +2392 -0
  24. package/.docs/organized/code-examples/with-parent-id-grouping.md +12 -12
  25. package/.docs/organized/code-examples/with-react-hook-form.md +223 -151
  26. package/.docs/organized/code-examples/with-react-ink.md +3 -3
  27. package/.docs/organized/code-examples/with-react-router.md +15 -15
  28. package/.docs/organized/code-examples/with-store.md +11 -8
  29. package/.docs/organized/code-examples/with-tanstack.md +14 -14
  30. package/.docs/organized/code-examples/with-tap-runtime.md +13 -9
  31. package/.docs/raw/docs/(docs)/guides/mentions.mdx +248 -109
  32. package/.docs/raw/docs/(docs)/guides/slash-commands.mdx +112 -92
  33. package/.docs/raw/docs/(docs)/guides/voice.mdx +10 -3
  34. package/.docs/raw/docs/(docs)/rtl.mdx +79 -0
  35. package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +149 -40
  36. package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +2 -0
  37. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +4 -0
  38. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +1 -1
  39. package/.docs/raw/docs/primitives/composer.mdx +94 -62
  40. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +57 -0
  41. package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +49 -3
  42. package/.docs/raw/docs/runtimes/custom/external-store.mdx +39 -1
  43. package/.docs/raw/docs/runtimes/custom/local.mdx +65 -18
  44. package/.docs/raw/docs/runtimes/google-adk/index.mdx +62 -0
  45. package/.docs/raw/docs/runtimes/langchain/comparison.mdx +60 -0
  46. package/.docs/raw/docs/runtimes/langchain/index.mdx +210 -0
  47. package/.docs/raw/docs/runtimes/langgraph/index.mdx +288 -60
  48. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +12 -4
  49. package/.docs/raw/docs/ui/composer-trigger-popover.mdx +199 -0
  50. package/.docs/raw/docs/ui/directive-text.mdx +113 -0
  51. package/.docs/raw/docs/ui/reasoning.mdx +13 -9
  52. package/dist/utils/logger.js +1 -1
  53. package/dist/utils/logger.js.map +1 -1
  54. package/package.json +4 -4
  55. package/src/utils/logger.ts +1 -1
  56. package/.docs/raw/docs/ui/mention.mdx +0 -168
@@ -0,0 +1,437 @@
1
+ # Example: with-langchain
2
+
3
+ ## app/globals.css
4
+
5
+ ```css
6
+ @import "tailwindcss";
7
+ @import "tw-animate-css";
8
+
9
+ @source "../../../packages/ui/src";
10
+
11
+ @custom-variant dark (&:is(.dark *));
12
+
13
+ @theme inline {
14
+ --radius-sm: calc(var(--radius) - 4px);
15
+ --radius-md: calc(var(--radius) - 2px);
16
+ --radius-lg: var(--radius);
17
+ --radius-xl: calc(var(--radius) + 4px);
18
+ --color-background: var(--background);
19
+ --color-foreground: var(--foreground);
20
+ --color-card: var(--card);
21
+ --color-card-foreground: var(--card-foreground);
22
+ --color-popover: var(--popover);
23
+ --color-popover-foreground: var(--popover-foreground);
24
+ --color-primary: var(--primary);
25
+ --color-primary-foreground: var(--primary-foreground);
26
+ --color-secondary: var(--secondary);
27
+ --color-secondary-foreground: var(--secondary-foreground);
28
+ --color-muted: var(--muted);
29
+ --color-muted-foreground: var(--muted-foreground);
30
+ --color-accent: var(--accent);
31
+ --color-accent-foreground: var(--accent-foreground);
32
+ --color-destructive: var(--destructive);
33
+ --color-border: var(--border);
34
+ --color-input: var(--input);
35
+ --color-ring: var(--ring);
36
+ --color-chart-1: var(--chart-1);
37
+ --color-chart-2: var(--chart-2);
38
+ --color-chart-3: var(--chart-3);
39
+ --color-chart-4: var(--chart-4);
40
+ --color-chart-5: var(--chart-5);
41
+ --color-sidebar: var(--sidebar);
42
+ --color-sidebar-foreground: var(--sidebar-foreground);
43
+ --color-sidebar-primary: var(--sidebar-primary);
44
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
45
+ --color-sidebar-accent: var(--sidebar-accent);
46
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
47
+ --color-sidebar-border: var(--sidebar-border);
48
+ --color-sidebar-ring: var(--sidebar-ring);
49
+ }
50
+
51
+ :root {
52
+ --radius: 0.625rem;
53
+ --background: oklch(1 0 0);
54
+ --foreground: oklch(0.141 0.005 285.823);
55
+ --card: oklch(1 0 0);
56
+ --card-foreground: oklch(0.141 0.005 285.823);
57
+ --popover: oklch(1 0 0);
58
+ --popover-foreground: oklch(0.141 0.005 285.823);
59
+ --primary: oklch(0.21 0.006 285.885);
60
+ --primary-foreground: oklch(0.985 0 0);
61
+ --secondary: oklch(0.967 0.001 286.375);
62
+ --secondary-foreground: oklch(0.21 0.006 285.885);
63
+ --muted: oklch(0.967 0.001 286.375);
64
+ --muted-foreground: oklch(0.552 0.016 285.938);
65
+ --accent: oklch(0.967 0.001 286.375);
66
+ --accent-foreground: oklch(0.21 0.006 285.885);
67
+ --destructive: oklch(0.577 0.245 27.325);
68
+ --border: oklch(0.92 0.004 286.32);
69
+ --input: oklch(0.92 0.004 286.32);
70
+ --ring: oklch(0.705 0.015 286.067);
71
+ --chart-1: oklch(0.646 0.222 41.116);
72
+ --chart-2: oklch(0.6 0.118 184.704);
73
+ --chart-3: oklch(0.398 0.07 227.392);
74
+ --chart-4: oklch(0.828 0.189 84.429);
75
+ --chart-5: oklch(0.769 0.188 70.08);
76
+ --sidebar: oklch(0.985 0 0);
77
+ --sidebar-foreground: oklch(0.141 0.005 285.823);
78
+ --sidebar-primary: oklch(0.21 0.006 285.885);
79
+ --sidebar-primary-foreground: oklch(0.985 0 0);
80
+ --sidebar-accent: oklch(0.967 0.001 286.375);
81
+ --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
82
+ --sidebar-border: oklch(0.92 0.004 286.32);
83
+ --sidebar-ring: oklch(0.705 0.015 286.067);
84
+ }
85
+
86
+ .dark {
87
+ --background: oklch(0.141 0.005 285.823);
88
+ --foreground: oklch(0.985 0 0);
89
+ --card: oklch(0.21 0.006 285.885);
90
+ --card-foreground: oklch(0.985 0 0);
91
+ --popover: oklch(0.21 0.006 285.885);
92
+ --popover-foreground: oklch(0.985 0 0);
93
+ --primary: oklch(0.92 0.004 286.32);
94
+ --primary-foreground: oklch(0.21 0.006 285.885);
95
+ --secondary: oklch(0.274 0.006 286.033);
96
+ --secondary-foreground: oklch(0.985 0 0);
97
+ --muted: oklch(0.274 0.006 286.033);
98
+ --muted-foreground: oklch(0.705 0.015 286.067);
99
+ --accent: oklch(0.274 0.006 286.033);
100
+ --accent-foreground: oklch(0.985 0 0);
101
+ --destructive: oklch(0.704 0.191 22.216);
102
+ --border: oklch(1 0 0 / 10%);
103
+ --input: oklch(1 0 0 / 15%);
104
+ --ring: oklch(0.552 0.016 285.938);
105
+ --chart-1: oklch(0.488 0.243 264.376);
106
+ --chart-2: oklch(0.696 0.17 162.48);
107
+ --chart-3: oklch(0.769 0.188 70.08);
108
+ --chart-4: oklch(0.627 0.265 303.9);
109
+ --chart-5: oklch(0.645 0.246 16.439);
110
+ --sidebar: oklch(0.21 0.006 285.885);
111
+ --sidebar-foreground: oklch(0.985 0 0);
112
+ --sidebar-primary: oklch(0.488 0.243 264.376);
113
+ --sidebar-primary-foreground: oklch(0.985 0 0);
114
+ --sidebar-accent: oklch(0.274 0.006 286.033);
115
+ --sidebar-accent-foreground: oklch(0.985 0 0);
116
+ --sidebar-border: oklch(1 0 0 / 10%);
117
+ --sidebar-ring: oklch(0.552 0.016 285.938);
118
+ }
119
+
120
+ @layer base {
121
+ * {
122
+ @apply border-border outline-ring/50;
123
+ }
124
+ body {
125
+ @apply bg-background text-foreground;
126
+ }
127
+ }
128
+
129
+ ```
130
+
131
+ ## app/layout.tsx
132
+
133
+ ```tsx
134
+ import type { Metadata } from "next";
135
+ import "./globals.css";
136
+ import { MyRuntimeProvider } from "./MyRuntimeProvider";
137
+
138
+ export const metadata: Metadata = {
139
+ title: "LangChain useStream Example",
140
+ description:
141
+ "Example using @assistant-ui/react-langchain with LangChain's useStream hook.",
142
+ };
143
+
144
+ export default function RootLayout({
145
+ children,
146
+ }: Readonly<{
147
+ children: React.ReactNode;
148
+ }>) {
149
+ return (
150
+ <MyRuntimeProvider>
151
+ <html lang="en">
152
+ <body className="h-dvh">{children}</body>
153
+ </html>
154
+ </MyRuntimeProvider>
155
+ );
156
+ }
157
+
158
+ ```
159
+
160
+ ## app/MyRuntimeProvider.tsx
161
+
162
+ ```tsx
163
+ "use client";
164
+
165
+ import { AssistantRuntimeProvider } from "@assistant-ui/react";
166
+ import { useStreamRuntime } from "@assistant-ui/react-langchain";
167
+
168
+ export function MyRuntimeProvider({
169
+ children,
170
+ }: Readonly<{
171
+ children: React.ReactNode;
172
+ }>) {
173
+ const runtime = useStreamRuntime({
174
+ assistantId: process.env.NEXT_PUBLIC_LANGGRAPH_ASSISTANT_ID!,
175
+ apiUrl: process.env.NEXT_PUBLIC_LANGGRAPH_API_URL,
176
+ });
177
+
178
+ return (
179
+ <AssistantRuntimeProvider runtime={runtime}>
180
+ {children}
181
+ </AssistantRuntimeProvider>
182
+ );
183
+ }
184
+
185
+ ```
186
+
187
+ ## app/page.tsx
188
+
189
+ ```tsx
190
+ "use client";
191
+
192
+ import { Thread } from "@/components/assistant-ui/thread";
193
+ import { TodosPanel } from "@/components/TodosPanel";
194
+
195
+ export default function Home() {
196
+ return (
197
+ <div className="flex h-dvh">
198
+ <div className="flex-grow">
199
+ <Thread />
200
+ </div>
201
+ <aside className="w-80 overflow-y-auto border-l p-4">
202
+ <TodosPanel />
203
+ </aside>
204
+ </div>
205
+ );
206
+ }
207
+
208
+ ```
209
+
210
+ ## components.json
211
+
212
+ ```json
213
+ {
214
+ "$schema": "https://ui.shadcn.com/schema.json",
215
+ "style": "new-york",
216
+ "rsc": true,
217
+ "tsx": true,
218
+ "tailwind": {
219
+ "config": "",
220
+ "css": "app/globals.css",
221
+ "baseColor": "zinc",
222
+ "cssVariables": true,
223
+ "prefix": ""
224
+ },
225
+ "aliases": {
226
+ "components": "@/components",
227
+ "utils": "@/lib/utils",
228
+ "ui": "@/components/ui",
229
+ "lib": "@/lib",
230
+ "hooks": "@/hooks"
231
+ },
232
+ "iconLibrary": "lucide",
233
+ "registries": {
234
+ "@assistant-ui": "https://r.assistant-ui.com/{name}.json"
235
+ }
236
+ }
237
+
238
+ ```
239
+
240
+ ## components/TodosPanel.tsx
241
+
242
+ ```tsx
243
+ "use client";
244
+
245
+ import { useLangChainState } from "@assistant-ui/react-langchain";
246
+
247
+ type Todo = {
248
+ id?: string;
249
+ content: string;
250
+ status?: "pending" | "in_progress" | "completed";
251
+ };
252
+
253
+ const statusIcon = (status: Todo["status"]) => {
254
+ switch (status) {
255
+ case "completed":
256
+ return "✓";
257
+ case "in_progress":
258
+ return "◐";
259
+ default:
260
+ return "○";
261
+ }
262
+ };
263
+
264
+ export function TodosPanel() {
265
+ const todos = useLangChainState<Todo[]>("todos", []);
266
+
267
+ if (todos.length === 0) {
268
+ return (
269
+ <div className="text-muted-foreground text-sm">
270
+ Todos from the agent will appear here. This panel reads{" "}
271
+ <code className="rounded bg-muted px-1">state.todos</code> via{" "}
272
+ <code className="rounded bg-muted px-1">useLangChainState</code>.
273
+ </div>
274
+ );
275
+ }
276
+
277
+ return (
278
+ <div className="space-y-2">
279
+ <h2 className="font-semibold text-muted-foreground text-sm uppercase tracking-wide">
280
+ Agent todos
281
+ </h2>
282
+ <ul className="space-y-1">
283
+ {todos.map((todo, i) => (
284
+ <li
285
+ key={todo.id ?? i}
286
+ className="flex items-start gap-2 text-sm leading-relaxed"
287
+ >
288
+ <span aria-hidden>{statusIcon(todo.status)}</span>
289
+ <span
290
+ className={
291
+ todo.status === "completed"
292
+ ? "text-muted-foreground line-through"
293
+ : undefined
294
+ }
295
+ >
296
+ {todo.content}
297
+ </span>
298
+ </li>
299
+ ))}
300
+ </ul>
301
+ </div>
302
+ );
303
+ }
304
+
305
+ ```
306
+
307
+ ## next.config.ts
308
+
309
+ ```typescript
310
+ import type { NextConfig } from "next";
311
+
312
+ const nextConfig: NextConfig = {
313
+ transpilePackages: ["@assistant-ui/react", "@assistant-ui/react-langchain"],
314
+ };
315
+
316
+ export default nextConfig;
317
+
318
+ ```
319
+
320
+ ## package.json
321
+
322
+ ```json
323
+ {
324
+ "name": "with-langchain",
325
+ "version": "0.0.0",
326
+ "private": true,
327
+ "type": "module",
328
+ "scripts": {
329
+ "dev": "next dev",
330
+ "build": "next build",
331
+ "start": "next start"
332
+ },
333
+ "dependencies": {
334
+ "@assistant-ui/react": "workspace:*",
335
+ "@assistant-ui/react-langchain": "workspace:*",
336
+ "@assistant-ui/react-markdown": "workspace:*",
337
+ "@assistant-ui/ui": "workspace:*",
338
+ "@langchain/langgraph-sdk": "^1.8.9",
339
+ "@langchain/react": "^0.3.3",
340
+ "class-variance-authority": "^0.7.1",
341
+ "clsx": "^2.1.1",
342
+ "lucide-react": "^1.8.0",
343
+ "next": "^16.2.4",
344
+ "react": "^19.2.5",
345
+ "react-dom": "^19.2.5",
346
+ "tailwind-merge": "^3.5.0"
347
+ },
348
+ "devDependencies": {
349
+ "@assistant-ui/x-buildutils": "workspace:*",
350
+ "@tailwindcss/postcss": "^4.2.4",
351
+ "@types/node": "^25.6.0",
352
+ "@types/react": "^19.2.14",
353
+ "@types/react-dom": "^19.2.3",
354
+ "postcss": "^8.5.10",
355
+ "tailwindcss": "^4.2.4",
356
+ "tw-animate-css": "^1.4.0",
357
+ "typescript": "^6.0.3"
358
+ }
359
+ }
360
+
361
+ ```
362
+
363
+ ## README.md
364
+
365
+ ```markdown
366
+ # LangChain `useStream` Example
367
+
368
+ Demonstrates `@assistant-ui/react-langchain`, which wraps `useStream` from `@langchain/react` and exposes it as an assistant-ui runtime.
369
+
370
+ > assistant-ui also ships `@assistant-ui/react-langgraph`, which integrates with `@langchain/langgraph-sdk` directly and currently has a broader feature set. Pick the adapter that matches your upstream choice. See [the comparison](https://www.assistant-ui.com/docs/runtimes/langchain/comparison).
371
+
372
+ ## Quick Start
373
+
374
+ ```bash
375
+ pnpm install
376
+ ```
377
+
378
+ ### Environment Variables
379
+
380
+ Create `.env.local`:
381
+
382
+ ```sh
383
+ NEXT_PUBLIC_LANGGRAPH_API_URL=http://localhost:2024
384
+ NEXT_PUBLIC_LANGGRAPH_ASSISTANT_ID=your_graph_id
385
+ ```
386
+
387
+ Start a local LangGraph server via [LangGraph Studio](https://github.com/langchain-ai/langgraph-studio) pointing at your graph, or use [LangSmith](https://www.langchain.com/langsmith) for a hosted deployment.
388
+
389
+ ### Run
390
+
391
+ ```bash
392
+ pnpm dev
393
+ ```
394
+
395
+ Open [http://localhost:3000](http://localhost:3000).
396
+
397
+ ## Key Features
398
+
399
+ - `useStreamRuntime` — thin wrapper around `useStream` from `@langchain/react`.
400
+ - `useLangChainState<T>(key)` — reads arbitrary custom state keys (demo uses `state.todos` in `TodosPanel`).
401
+ - No hand-written stream generator, no `create` / `load` / `getCheckpointId` glue.
402
+
403
+ ## Files of interest
404
+
405
+ - `app/MyRuntimeProvider.tsx` — entire runtime setup in ~15 lines.
406
+ - `components/TodosPanel.tsx` — demonstrates `useLangChainState<Todo[]>("todos", [])`.
407
+
408
+ ## Related Documentation
409
+
410
+ - [assistant-ui Documentation](https://www.assistant-ui.com/docs)
411
+ - [LangChain useStream Integration](https://www.assistant-ui.com/docs/runtimes/langchain)
412
+ - [react-langgraph vs react-langchain](https://www.assistant-ui.com/docs/runtimes/langchain/comparison)
413
+
414
+ ```
415
+
416
+ ## tsconfig.json
417
+
418
+ ```json
419
+ {
420
+ "extends": "@assistant-ui/x-buildutils/ts/next",
421
+ "compilerOptions": {
422
+ "paths": {
423
+ "@/*": ["./*"],
424
+ "@/components/assistant-ui/*": [
425
+ "../../packages/ui/src/components/assistant-ui/*"
426
+ ],
427
+ "@/components/ui/*": ["../../packages/ui/src/components/ui/*"],
428
+ "@/lib/utils": ["../../packages/ui/src/lib/utils"],
429
+ "@assistant-ui/ui/*": ["../../packages/ui/src/*"]
430
+ }
431
+ },
432
+ "include": ["**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
433
+ "exclude": ["node_modules"]
434
+ }
435
+
436
+ ```
437
+
@@ -3,7 +3,7 @@
3
3
  ## app/api/[..._path]/route.ts
4
4
 
5
5
  ```typescript
6
- import { NextRequest, NextResponse } from "next/server";
6
+ import { type NextRequest, NextResponse } from "next/server";
7
7
 
8
8
  function getCorsHeaders() {
9
9
  return {
@@ -27,7 +27,7 @@ async function handleRequest(req: NextRequest, method: string) {
27
27
  const options: RequestInit = {
28
28
  method,
29
29
  headers: {
30
- "x-api-key": process.env["LANGCHAIN_API_KEY"] || "",
30
+ "x-api-key": process.env.LANGCHAIN_API_KEY || "",
31
31
  },
32
32
  };
33
33
 
@@ -36,7 +36,7 @@ async function handleRequest(req: NextRequest, method: string) {
36
36
  }
37
37
 
38
38
  const res = await fetch(
39
- `${process.env["LANGGRAPH_API_URL"]}/${path}${queryString}`,
39
+ `${process.env.LANGGRAPH_API_URL}/${path}${queryString}`,
40
40
  options,
41
41
  );
42
42
 
@@ -250,7 +250,7 @@ import {
250
250
  getCheckpointId,
251
251
  sendMessage,
252
252
  } from "@/lib/chatApi";
253
- import { LangChainMessage } from "@assistant-ui/react-langgraph";
253
+ import type { LangChainMessage } from "@assistant-ui/react-langgraph";
254
254
 
255
255
  export function MyRuntimeProvider({
256
256
  children,
@@ -672,7 +672,7 @@ export function TransactionConfirmationPending(props: TransactionConfirmation) {
672
672
  ## components/tools/ToolFallback.tsx
673
673
 
674
674
  ```tsx
675
- import { ToolCallMessagePartComponent } from "@assistant-ui/react";
675
+ import type { ToolCallMessagePartComponent } from "@assistant-ui/react";
676
676
  import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
677
677
  import { useState } from "react";
678
678
  import { Button } from "@/components/ui/button";
@@ -721,8 +721,8 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
721
721
  ## lib/chatApi.ts
722
722
 
723
723
  ```typescript
724
- import { ThreadState, Client } from "@langchain/langgraph-sdk";
725
- import {
724
+ import { type ThreadState, Client } from "@langchain/langgraph-sdk";
725
+ import type {
726
726
  LangChainMessage,
727
727
  LangGraphMessagesEvent,
728
728
  LangGraphSendMessageConfig,
@@ -730,7 +730,7 @@ import {
730
730
 
731
731
  const createClient = () => {
732
732
  const apiUrl =
733
- process.env["NEXT_PUBLIC_LANGGRAPH_API_URL"] ||
733
+ process.env.NEXT_PUBLIC_LANGGRAPH_API_URL ||
734
734
  new URL("/api", window.location.href).href;
735
735
  return new Client({
736
736
  apiUrl,
@@ -816,7 +816,7 @@ export const sendMessage = (params: {
816
816
 
817
817
  return client.runs.stream(
818
818
  params.threadId,
819
- process.env["NEXT_PUBLIC_LANGGRAPH_ASSISTANT_ID"]!,
819
+ process.env.NEXT_PUBLIC_LANGGRAPH_ASSISTANT_ID!,
820
820
  {
821
821
  input: params.messages.length > 0 ? { messages: params.messages } : null,
822
822
  config: {
@@ -824,7 +824,7 @@ export const sendMessage = (params: {
824
824
  model_name: "openai",
825
825
  },
826
826
  },
827
- streamMode: ["messages-tuple", "values"],
827
+ streamMode: ["messages-tuple", "values", "custom"],
828
828
  ...(checkpointId && { checkpoint_id: checkpointId }),
829
829
  ...restConfig,
830
830
  },
@@ -871,25 +871,25 @@ export default nextConfig;
871
871
  "@assistant-ui/react-langgraph": "workspace:*",
872
872
  "@assistant-ui/react-markdown": "workspace:*",
873
873
  "@assistant-ui/ui": "workspace:*",
874
- "@langchain/langgraph-sdk": "^1.8.8",
874
+ "@langchain/langgraph-sdk": "^1.8.9",
875
875
  "class-variance-authority": "^0.7.1",
876
876
  "clsx": "^2.1.1",
877
- "lucide-react": "^1.7.0",
878
- "next": "^16.2.2",
879
- "react": "^19.2.4",
880
- "react-dom": "^19.2.4",
877
+ "lucide-react": "^1.8.0",
878
+ "next": "^16.2.4",
879
+ "react": "^19.2.5",
880
+ "react-dom": "^19.2.5",
881
881
  "tailwind-merge": "^3.5.0"
882
882
  },
883
883
  "devDependencies": {
884
884
  "@assistant-ui/x-buildutils": "workspace:*",
885
- "@tailwindcss/postcss": "^4.2.2",
886
- "@types/node": "^25.5.2",
885
+ "@tailwindcss/postcss": "^4.2.4",
886
+ "@types/node": "^25.6.0",
887
887
  "@types/react": "^19.2.14",
888
888
  "@types/react-dom": "^19.2.3",
889
- "postcss": "^8.5.8",
890
- "tailwindcss": "^4.2.2",
889
+ "postcss": "^8.5.10",
890
+ "tailwindcss": "^4.2.4",
891
891
  "tw-animate-css": "^1.4.0",
892
- "typescript": "5.9.3"
892
+ "typescript": "^6.0.3"
893
893
  }
894
894
  }
895
895
 
@@ -4,7 +4,12 @@
4
4
 
5
5
  ```typescript
6
6
  import { openai } from "@ai-sdk/openai";
7
- import { streamText, UIMessage, convertToModelMessages, stepCountIs } from "ai";
7
+ import {
8
+ streamText,
9
+ type UIMessage,
10
+ convertToModelMessages,
11
+ stepCountIs,
12
+ } from "ai";
8
13
 
9
14
  export const maxDuration = 30;
10
15
 
@@ -388,7 +393,13 @@ const UserMessage: FC = () => {
388
393
  ```typescript
389
394
  import type { RealtimeVoiceAdapter } from "@assistant-ui/react";
390
395
  import { createVoiceSession } from "@assistant-ui/react";
391
- import { Room, RoomEvent, type RoomOptions } from "livekit-client";
396
+ import {
397
+ Room,
398
+ RoomEvent,
399
+ Track,
400
+ type RemoteTrack,
401
+ type RoomOptions,
402
+ } from "livekit-client";
392
403
 
393
404
  export type LiveKitVoiceAdapterOptions = {
394
405
  url: string;
@@ -414,6 +425,31 @@ export class LiveKitVoiceAdapter implements RealtimeVoiceAdapter {
414
425
 
415
426
  return createVoiceSession(options, async (session) => {
416
427
  let volumeInterval: ReturnType<typeof setInterval> | null = null;
428
+ const attachedAudioElements = new Set<HTMLMediaElement>();
429
+
430
+ const attachRemoteAudio = (track: RemoteTrack) => {
431
+ if (track.kind !== Track.Kind.Audio) return;
432
+ const element = track.attach();
433
+ element.style.display = "none";
434
+ document.body.appendChild(element);
435
+ attachedAudioElements.add(element);
436
+ };
437
+
438
+ const detachRemoteAudio = (track: RemoteTrack) => {
439
+ if (track.kind !== Track.Kind.Audio) return;
440
+ for (const element of track.detach()) {
441
+ element.remove();
442
+ attachedAudioElements.delete(element);
443
+ }
444
+ };
445
+
446
+ const cleanupAudioElements = () => {
447
+ for (const element of attachedAudioElements) element.remove();
448
+ attachedAudioElements.clear();
449
+ };
450
+
451
+ room.on(RoomEvent.TrackSubscribed, attachRemoteAudio);
452
+ room.on(RoomEvent.TrackUnsubscribed, detachRemoteAudio);
417
453
 
418
454
  room.on(RoomEvent.Connected, () => {
419
455
  session.setStatus({ type: "running" });
@@ -464,18 +500,23 @@ export class LiveKitVoiceAdapter implements RealtimeVoiceAdapter {
464
500
 
465
501
  const token =
466
502
  typeof this._token === "function" ? await this._token() : this._token;
467
- if (session.isDisposed())
503
+ if (session.isDisposed()) {
504
+ cleanupAudioElements();
468
505
  return { disconnect: () => {}, mute: () => {}, unmute: () => {} };
506
+ }
469
507
 
470
508
  await room.connect(this._url, token);
471
- if (session.isDisposed())
509
+ if (session.isDisposed()) {
510
+ cleanupAudioElements();
472
511
  return { disconnect: () => {}, mute: () => {}, unmute: () => {} };
512
+ }
473
513
 
474
514
  await room.localParticipant.setMicrophoneEnabled(true);
475
515
 
476
516
  return {
477
517
  disconnect: () => {
478
518
  if (volumeInterval) clearInterval(volumeInterval);
519
+ cleanupAudioElements();
479
520
  room.disconnect();
480
521
  },
481
522
  mute: () => {
@@ -512,35 +553,35 @@ export default nextConfig;
512
553
  "version": "0.0.0",
513
554
  "type": "module",
514
555
  "dependencies": {
515
- "@ai-sdk/openai": "^3.0.51",
516
- "@ai-sdk/react": "^3.0.150",
556
+ "@ai-sdk/openai": "^3.0.53",
557
+ "@ai-sdk/react": "^3.0.170",
517
558
  "@assistant-ui/react": "workspace:^",
518
559
  "@assistant-ui/react-ai-sdk": "workspace:*",
519
560
  "@assistant-ui/react-markdown": "workspace:^",
520
561
  "@assistant-ui/ui": "workspace:*",
521
- "@tailwindcss/postcss": "^4.2.2",
522
- "ai": "^6.0.148",
562
+ "@tailwindcss/postcss": "^4.2.4",
563
+ "ai": "^6.0.168",
523
564
  "class-variance-authority": "^0.7.1",
524
565
  "clsx": "^2.1.1",
525
- "livekit-client": "^2.18.1",
526
- "livekit-server-sdk": "^2.15.0",
527
- "lucide-react": "^1.7.0",
566
+ "livekit-client": "^2.18.4",
567
+ "livekit-server-sdk": "^2.15.1",
568
+ "lucide-react": "^1.8.0",
528
569
  "motion": "^12.38.0",
529
- "next": "^16.2.2",
530
- "postcss": "^8.5.8",
531
- "react": "^19.2.4",
532
- "react-dom": "^19.2.4",
570
+ "next": "^16.2.4",
571
+ "postcss": "^8.5.10",
572
+ "react": "^19.2.5",
573
+ "react-dom": "^19.2.5",
533
574
  "tailwind-merge": "^3.5.0",
534
- "tailwindcss": "^4.2.2",
575
+ "tailwindcss": "^4.2.4",
535
576
  "zod": "^4.3.6"
536
577
  },
537
578
  "devDependencies": {
538
579
  "@assistant-ui/x-buildutils": "workspace:*",
539
- "@types/node": "^25.5.2",
580
+ "@types/node": "^25.6.0",
540
581
  "@types/react": "^19.2.14",
541
582
  "@types/react-dom": "^19.2.3",
542
583
  "tw-animate-css": "^1.4.0",
543
- "typescript": "5.9.3"
584
+ "typescript": "^6.0.3"
544
585
  },
545
586
  "scripts": {
546
587
  "dev": "next dev",