@assistant-ui/mcp-docs-server 0.1.21 → 0.1.22
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/with-ag-ui.md +2 -2
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +3 -3
- package/.docs/organized/code-examples/with-assistant-transport.md +2 -2
- package/.docs/organized/code-examples/with-chain-of-thought.md +598 -0
- package/.docs/organized/code-examples/with-cloud.md +3 -3
- package/.docs/organized/code-examples/with-custom-thread-list.md +3 -3
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +6 -6
- package/.docs/organized/code-examples/with-external-store.md +2 -2
- package/.docs/organized/code-examples/with-ffmpeg.md +3 -3
- package/.docs/organized/code-examples/with-langgraph.md +3 -3
- package/.docs/organized/code-examples/with-parent-id-grouping.md +2 -2
- package/.docs/organized/code-examples/with-react-hook-form.md +4 -4
- package/.docs/organized/code-examples/with-react-router.md +3 -3
- package/.docs/organized/code-examples/with-store.md +2 -2
- 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)/guides/chain-of-thought.mdx +162 -0
- package/.docs/raw/docs/(docs)/index.mdx +1 -1
- package/.docs/raw/docs/(docs)/llm.mdx +1 -1
- package/package.json +3 -3
|
@@ -419,8 +419,8 @@ export default nextConfig;
|
|
|
419
419
|
"devDependencies": {
|
|
420
420
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
421
421
|
"@tailwindcss/postcss": "^4.1.18",
|
|
422
|
-
"@types/node": "^25.2.
|
|
423
|
-
"@types/react": "^19.2.
|
|
422
|
+
"@types/node": "^25.2.1",
|
|
423
|
+
"@types/react": "^19.2.13",
|
|
424
424
|
"@types/react-dom": "^19.2.3",
|
|
425
425
|
"postcss": "^8.5.6",
|
|
426
426
|
"tailwindcss": "^4.1.18",
|
|
@@ -299,7 +299,7 @@ export default nextConfig;
|
|
|
299
299
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
300
300
|
"@radix-ui/react-slot": "^1.2.4",
|
|
301
301
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
302
|
-
"ai": "^6.0.
|
|
302
|
+
"ai": "^6.0.73",
|
|
303
303
|
"class-variance-authority": "^0.7.1",
|
|
304
304
|
"clsx": "^2.1.1",
|
|
305
305
|
"lucide-react": "^0.563.0",
|
|
@@ -312,8 +312,8 @@ export default nextConfig;
|
|
|
312
312
|
"devDependencies": {
|
|
313
313
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
314
314
|
"@tailwindcss/postcss": "^4.1.18",
|
|
315
|
-
"@types/node": "^25.2.
|
|
316
|
-
"@types/react": "^19.2.
|
|
315
|
+
"@types/node": "^25.2.1",
|
|
316
|
+
"@types/react": "^19.2.13",
|
|
317
317
|
"@types/react-dom": "^19.2.3",
|
|
318
318
|
"postcss": "^8.5.6",
|
|
319
319
|
"tailwindcss": "^4.1.18",
|
|
@@ -427,8 +427,8 @@ export default nextConfig;
|
|
|
427
427
|
"devDependencies": {
|
|
428
428
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
429
429
|
"@tailwindcss/postcss": "^4.1.18",
|
|
430
|
-
"@types/node": "^25.2.
|
|
431
|
-
"@types/react": "^19.2.
|
|
430
|
+
"@types/node": "^25.2.1",
|
|
431
|
+
"@types/react": "^19.2.13",
|
|
432
432
|
"@types/react-dom": "^19.2.3",
|
|
433
433
|
"postcss": "^8.5.6",
|
|
434
434
|
"tailwindcss": "^4.1.18",
|
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
# Example: with-chain-of-thought
|
|
2
|
+
|
|
3
|
+
## app/api/chat/route.ts
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import { openai } from "@ai-sdk/openai";
|
|
7
|
+
import {
|
|
8
|
+
streamText,
|
|
9
|
+
convertToModelMessages,
|
|
10
|
+
tool,
|
|
11
|
+
stepCountIs,
|
|
12
|
+
zodSchema,
|
|
13
|
+
} from "ai";
|
|
14
|
+
import type { UIMessage } from "ai";
|
|
15
|
+
import { frontendTools } from "@assistant-ui/react-ai-sdk";
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
|
|
18
|
+
export const maxDuration = 30;
|
|
19
|
+
|
|
20
|
+
export async function POST(req: Request) {
|
|
21
|
+
const {
|
|
22
|
+
messages,
|
|
23
|
+
tools,
|
|
24
|
+
}: { messages: UIMessage[]; tools: Record<string, any> } = await req.json();
|
|
25
|
+
|
|
26
|
+
const result = streamText({
|
|
27
|
+
// Use a reasoning model to showcase chain of thought
|
|
28
|
+
model: openai("o4-mini"),
|
|
29
|
+
messages: await convertToModelMessages(messages),
|
|
30
|
+
stopWhen: stepCountIs(10),
|
|
31
|
+
tools: {
|
|
32
|
+
// Frontend tools registered via makeAssistantTool (e.g. execute_js)
|
|
33
|
+
...frontendTools(tools),
|
|
34
|
+
|
|
35
|
+
// Backend-only tools
|
|
36
|
+
get_current_weather: tool({
|
|
37
|
+
description: "Get the current weather for a city",
|
|
38
|
+
inputSchema: zodSchema(
|
|
39
|
+
z.object({
|
|
40
|
+
city: z.string(),
|
|
41
|
+
}),
|
|
42
|
+
),
|
|
43
|
+
execute: async ({ city }) => {
|
|
44
|
+
return `The weather in ${city} is sunny, 72°F`;
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return result.toUIMessageStreamResponse();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## app/globals.css
|
|
56
|
+
|
|
57
|
+
```css
|
|
58
|
+
@import "tailwindcss";
|
|
59
|
+
@import "tw-animate-css";
|
|
60
|
+
|
|
61
|
+
@source "../../../packages/ui/src";
|
|
62
|
+
|
|
63
|
+
@custom-variant dark (&:is(.dark *));
|
|
64
|
+
|
|
65
|
+
@theme inline {
|
|
66
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
67
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
68
|
+
--radius-lg: var(--radius);
|
|
69
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
70
|
+
--color-background: var(--background);
|
|
71
|
+
--color-foreground: var(--foreground);
|
|
72
|
+
--color-card: var(--card);
|
|
73
|
+
--color-card-foreground: var(--card-foreground);
|
|
74
|
+
--color-popover: var(--popover);
|
|
75
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
76
|
+
--color-primary: var(--primary);
|
|
77
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
78
|
+
--color-secondary: var(--secondary);
|
|
79
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
80
|
+
--color-muted: var(--muted);
|
|
81
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
82
|
+
--color-accent: var(--accent);
|
|
83
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
84
|
+
--color-destructive: var(--destructive);
|
|
85
|
+
--color-border: var(--border);
|
|
86
|
+
--color-input: var(--input);
|
|
87
|
+
--color-ring: var(--ring);
|
|
88
|
+
--color-chart-1: var(--chart-1);
|
|
89
|
+
--color-chart-2: var(--chart-2);
|
|
90
|
+
--color-chart-3: var(--chart-3);
|
|
91
|
+
--color-chart-4: var(--chart-4);
|
|
92
|
+
--color-chart-5: var(--chart-5);
|
|
93
|
+
--color-sidebar: var(--sidebar);
|
|
94
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
95
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
96
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
97
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
98
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
99
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
100
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:root {
|
|
104
|
+
--radius: 0.625rem;
|
|
105
|
+
--background: oklch(1 0 0);
|
|
106
|
+
--foreground: oklch(0.141 0.005 285.823);
|
|
107
|
+
--card: oklch(1 0 0);
|
|
108
|
+
--card-foreground: oklch(0.141 0.005 285.823);
|
|
109
|
+
--popover: oklch(1 0 0);
|
|
110
|
+
--popover-foreground: oklch(0.141 0.005 285.823);
|
|
111
|
+
--primary: oklch(0.21 0.006 285.885);
|
|
112
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
113
|
+
--secondary: oklch(0.967 0.001 286.375);
|
|
114
|
+
--secondary-foreground: oklch(0.21 0.006 285.885);
|
|
115
|
+
--muted: oklch(0.967 0.001 286.375);
|
|
116
|
+
--muted-foreground: oklch(0.552 0.016 285.938);
|
|
117
|
+
--accent: oklch(0.967 0.001 286.375);
|
|
118
|
+
--accent-foreground: oklch(0.21 0.006 285.885);
|
|
119
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
120
|
+
--border: oklch(0.92 0.004 286.32);
|
|
121
|
+
--input: oklch(0.92 0.004 286.32);
|
|
122
|
+
--ring: oklch(0.705 0.015 286.067);
|
|
123
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
124
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
125
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
126
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
127
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
128
|
+
--sidebar: oklch(0.985 0 0);
|
|
129
|
+
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
|
130
|
+
--sidebar-primary: oklch(0.21 0.006 285.885);
|
|
131
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
132
|
+
--sidebar-accent: oklch(0.967 0.001 286.375);
|
|
133
|
+
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
|
134
|
+
--sidebar-border: oklch(0.92 0.004 286.32);
|
|
135
|
+
--sidebar-ring: oklch(0.705 0.015 286.067);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.dark {
|
|
139
|
+
--background: oklch(0.141 0.005 285.823);
|
|
140
|
+
--foreground: oklch(0.985 0 0);
|
|
141
|
+
--card: oklch(0.21 0.006 285.885);
|
|
142
|
+
--card-foreground: oklch(0.985 0 0);
|
|
143
|
+
--popover: oklch(0.21 0.006 285.885);
|
|
144
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
145
|
+
--primary: oklch(0.92 0.004 286.32);
|
|
146
|
+
--primary-foreground: oklch(0.21 0.006 285.885);
|
|
147
|
+
--secondary: oklch(0.274 0.006 286.033);
|
|
148
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
149
|
+
--muted: oklch(0.274 0.006 286.033);
|
|
150
|
+
--muted-foreground: oklch(0.705 0.015 286.067);
|
|
151
|
+
--accent: oklch(0.274 0.006 286.033);
|
|
152
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
153
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
154
|
+
--border: oklch(1 0 0 / 10%);
|
|
155
|
+
--input: oklch(1 0 0 / 15%);
|
|
156
|
+
--ring: oklch(0.552 0.016 285.938);
|
|
157
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
158
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
159
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
160
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
161
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
162
|
+
--sidebar: oklch(0.21 0.006 285.885);
|
|
163
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
164
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
165
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
166
|
+
--sidebar-accent: oklch(0.274 0.006 286.033);
|
|
167
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
168
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
169
|
+
--sidebar-ring: oklch(0.552 0.016 285.938);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@layer base {
|
|
173
|
+
* {
|
|
174
|
+
@apply border-border outline-ring/50;
|
|
175
|
+
}
|
|
176
|
+
body {
|
|
177
|
+
@apply bg-background text-foreground;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## app/layout.tsx
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
import type { Metadata } from "next";
|
|
187
|
+
import "./globals.css";
|
|
188
|
+
|
|
189
|
+
export const metadata: Metadata = {
|
|
190
|
+
title: "Chain of Thought Example",
|
|
191
|
+
description: "Example using ChainOfThoughtPrimitive with AI SDK",
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export default function RootLayout({
|
|
195
|
+
children,
|
|
196
|
+
}: Readonly<{
|
|
197
|
+
children: React.ReactNode;
|
|
198
|
+
}>) {
|
|
199
|
+
return (
|
|
200
|
+
<html lang="en">
|
|
201
|
+
<body className="h-dvh">{children}</body>
|
|
202
|
+
</html>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## app/MyThread.tsx
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
"use client";
|
|
212
|
+
|
|
213
|
+
import { type FC, type PropsWithChildren, useState } from "react";
|
|
214
|
+
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|
215
|
+
import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
|
|
216
|
+
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
217
|
+
import { Button } from "@/components/ui/button";
|
|
218
|
+
import {
|
|
219
|
+
AuiIf,
|
|
220
|
+
ChainOfThoughtPrimitive,
|
|
221
|
+
ComposerPrimitive,
|
|
222
|
+
MessagePrimitive,
|
|
223
|
+
ThreadPrimitive,
|
|
224
|
+
useAuiState,
|
|
225
|
+
} from "@assistant-ui/react";
|
|
226
|
+
import {
|
|
227
|
+
ArrowDownIcon,
|
|
228
|
+
ArrowUpIcon,
|
|
229
|
+
ChevronDownIcon,
|
|
230
|
+
ChevronRightIcon,
|
|
231
|
+
SquareIcon,
|
|
232
|
+
} from "lucide-react";
|
|
233
|
+
|
|
234
|
+
export const MyThread: FC = () => {
|
|
235
|
+
return (
|
|
236
|
+
<ThreadPrimitive.Root
|
|
237
|
+
className="flex h-full flex-col bg-background"
|
|
238
|
+
style={{ ["--thread-max-width" as string]: "44rem" }}
|
|
239
|
+
>
|
|
240
|
+
<ThreadPrimitive.Viewport className="flex flex-1 flex-col overflow-y-scroll scroll-smooth px-4 pt-8">
|
|
241
|
+
<ThreadPrimitive.Messages
|
|
242
|
+
components={{ UserMessage, AssistantMessage }}
|
|
243
|
+
/>
|
|
244
|
+
|
|
245
|
+
<ThreadPrimitive.ViewportFooter className="sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 pb-4">
|
|
246
|
+
<ThreadPrimitive.ScrollToBottom asChild>
|
|
247
|
+
<TooltipIconButton
|
|
248
|
+
tooltip="Scroll to bottom"
|
|
249
|
+
variant="outline"
|
|
250
|
+
className="absolute -top-12 self-center rounded-full p-4 disabled:invisible"
|
|
251
|
+
>
|
|
252
|
+
<ArrowDownIcon />
|
|
253
|
+
</TooltipIconButton>
|
|
254
|
+
</ThreadPrimitive.ScrollToBottom>
|
|
255
|
+
<Composer />
|
|
256
|
+
</ThreadPrimitive.ViewportFooter>
|
|
257
|
+
</ThreadPrimitive.Viewport>
|
|
258
|
+
</ThreadPrimitive.Root>
|
|
259
|
+
);
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const Text: FC<{ text: string }> = ({ text }) => {
|
|
263
|
+
return <p>{text}</p>;
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const UserMessage: FC = () => {
|
|
267
|
+
return (
|
|
268
|
+
<MessagePrimitive.Root className="mx-auto w-full max-w-(--thread-max-width) py-3">
|
|
269
|
+
<div className="flex justify-end">
|
|
270
|
+
<div className="max-w-[80%] rounded-2xl bg-primary px-4 py-2 text-primary-foreground">
|
|
271
|
+
<MessagePrimitive.Parts components={{ Text }} />
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
</MessagePrimitive.Root>
|
|
275
|
+
);
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const AssistantMessage: FC = () => {
|
|
279
|
+
return (
|
|
280
|
+
<MessagePrimitive.Root className="mx-auto w-full max-w-(--thread-max-width) py-3">
|
|
281
|
+
<div className="flex flex-col gap-2 px-2 leading-relaxed">
|
|
282
|
+
{/*
|
|
283
|
+
The ChainOfThought component is passed to MessagePrimitive.Parts.
|
|
284
|
+
When set, consecutive reasoning + tool-call parts are grouped together
|
|
285
|
+
and rendered through this component instead of individually.
|
|
286
|
+
*/}
|
|
287
|
+
<MessagePrimitive.Parts
|
|
288
|
+
components={{
|
|
289
|
+
Text: MarkdownText,
|
|
290
|
+
ChainOfThought,
|
|
291
|
+
}}
|
|
292
|
+
/>
|
|
293
|
+
</div>
|
|
294
|
+
</MessagePrimitive.Root>
|
|
295
|
+
);
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* ChainOfThought component — rendered by MessagePrimitive.Parts when it
|
|
300
|
+
* encounters consecutive reasoning + tool-call parts.
|
|
301
|
+
*
|
|
302
|
+
* Uses ChainOfThoughtPrimitive.Root, AccordionTrigger, and Parts to create
|
|
303
|
+
* a collapsible accordion that groups all "thinking" steps together.
|
|
304
|
+
*/
|
|
305
|
+
const ChainOfThought: FC = () => {
|
|
306
|
+
return (
|
|
307
|
+
<ChainOfThoughtPrimitive.Root className="my-2 rounded-lg border">
|
|
308
|
+
<ChainOfThoughtPrimitive.AccordionTrigger className="flex w-full cursor-pointer items-center gap-2 px-4 py-2 font-medium text-sm hover:bg-muted/50">
|
|
309
|
+
<AuiIf condition={({ chainOfThought }) => chainOfThought.collapsed}>
|
|
310
|
+
<ChevronRightIcon className="size-4 shrink-0" />
|
|
311
|
+
</AuiIf>
|
|
312
|
+
<AuiIf condition={({ chainOfThought }) => !chainOfThought.collapsed}>
|
|
313
|
+
<ChevronDownIcon className="size-4 shrink-0" />
|
|
314
|
+
</AuiIf>
|
|
315
|
+
Thinking
|
|
316
|
+
</ChainOfThoughtPrimitive.AccordionTrigger>
|
|
317
|
+
<AuiIf condition={({ chainOfThought }) => !chainOfThought.collapsed}>
|
|
318
|
+
<ChainOfThoughtPrimitive.Parts
|
|
319
|
+
components={{
|
|
320
|
+
Reasoning,
|
|
321
|
+
tools: { Fallback: ToolFallback },
|
|
322
|
+
Layout: PartLayout,
|
|
323
|
+
}}
|
|
324
|
+
/>
|
|
325
|
+
</AuiIf>
|
|
326
|
+
</ChainOfThoughtPrimitive.Root>
|
|
327
|
+
);
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
const PartLayout: FC<PropsWithChildren> = ({ children }) => {
|
|
331
|
+
const partType = useAuiState(({ part }) => part.type);
|
|
332
|
+
const [open, setOpen] = useState(true);
|
|
333
|
+
|
|
334
|
+
const label = partType === "reasoning" ? "Thinking" : "Taking action";
|
|
335
|
+
|
|
336
|
+
return (
|
|
337
|
+
<div className="border-t">
|
|
338
|
+
<button
|
|
339
|
+
type="button"
|
|
340
|
+
className="flex w-full cursor-pointer items-center gap-2 px-4 py-1.5 text-muted-foreground text-xs hover:bg-muted/50"
|
|
341
|
+
onClick={() => setOpen((o) => !o)}
|
|
342
|
+
>
|
|
343
|
+
{open ? (
|
|
344
|
+
<ChevronDownIcon className="size-3" />
|
|
345
|
+
) : (
|
|
346
|
+
<ChevronRightIcon className="size-3" />
|
|
347
|
+
)}
|
|
348
|
+
{label}
|
|
349
|
+
</button>
|
|
350
|
+
{open && children}
|
|
351
|
+
</div>
|
|
352
|
+
);
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
const Reasoning: FC<{ text: string }> = ({ text }) => {
|
|
356
|
+
return (
|
|
357
|
+
<p className="whitespace-pre-wrap px-4 py-2 text-muted-foreground text-sm italic">
|
|
358
|
+
{text}
|
|
359
|
+
</p>
|
|
360
|
+
);
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const Composer: FC = () => {
|
|
364
|
+
return (
|
|
365
|
+
<ComposerPrimitive.Root className="flex w-full flex-col rounded-2xl border border-input bg-background px-1 pt-2 outline-none transition-shadow has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-2 has-[textarea:focus-visible]:ring-ring/20">
|
|
366
|
+
<ComposerPrimitive.Input
|
|
367
|
+
placeholder="Send a message..."
|
|
368
|
+
className="mb-1 max-h-32 min-h-14 w-full resize-none bg-transparent px-4 pt-2 pb-3 text-sm outline-none placeholder:text-muted-foreground"
|
|
369
|
+
rows={1}
|
|
370
|
+
autoFocus
|
|
371
|
+
/>
|
|
372
|
+
<div className="relative mx-2 mb-2 flex items-center justify-end">
|
|
373
|
+
<AuiIf condition={({ thread }) => !thread.isRunning}>
|
|
374
|
+
<ComposerPrimitive.Send asChild>
|
|
375
|
+
<TooltipIconButton
|
|
376
|
+
tooltip="Send"
|
|
377
|
+
side="bottom"
|
|
378
|
+
variant="default"
|
|
379
|
+
size="icon"
|
|
380
|
+
className="size-8 rounded-full"
|
|
381
|
+
>
|
|
382
|
+
<ArrowUpIcon className="size-4" />
|
|
383
|
+
</TooltipIconButton>
|
|
384
|
+
</ComposerPrimitive.Send>
|
|
385
|
+
</AuiIf>
|
|
386
|
+
<AuiIf condition={({ thread }) => thread.isRunning}>
|
|
387
|
+
<ComposerPrimitive.Cancel asChild>
|
|
388
|
+
<Button
|
|
389
|
+
type="button"
|
|
390
|
+
variant="default"
|
|
391
|
+
size="icon"
|
|
392
|
+
className="size-8 rounded-full"
|
|
393
|
+
>
|
|
394
|
+
<SquareIcon className="size-3 fill-current" />
|
|
395
|
+
</Button>
|
|
396
|
+
</ComposerPrimitive.Cancel>
|
|
397
|
+
</AuiIf>
|
|
398
|
+
</div>
|
|
399
|
+
</ComposerPrimitive.Root>
|
|
400
|
+
);
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## app/page.tsx
|
|
406
|
+
|
|
407
|
+
```tsx
|
|
408
|
+
"use client";
|
|
409
|
+
|
|
410
|
+
import {
|
|
411
|
+
AssistantRuntimeProvider,
|
|
412
|
+
makeAssistantTool,
|
|
413
|
+
} from "@assistant-ui/react";
|
|
414
|
+
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
415
|
+
import { z } from "zod";
|
|
416
|
+
import { MyThread } from "./MyThread";
|
|
417
|
+
import { lastAssistantMessageIsCompleteWithApprovalResponses } from "ai";
|
|
418
|
+
|
|
419
|
+
const ExecuteJsTool = makeAssistantTool({
|
|
420
|
+
toolName: "execute_js",
|
|
421
|
+
description: "Execute JavaScript code and return the result",
|
|
422
|
+
parameters: z.object({
|
|
423
|
+
code: z.string().describe("The JavaScript code to execute"),
|
|
424
|
+
}),
|
|
425
|
+
execute: async ({ code }) => {
|
|
426
|
+
try {
|
|
427
|
+
// biome-ignore lint/security/noGlobalEval: example code
|
|
428
|
+
const result = eval(code);
|
|
429
|
+
return { success: true, result: String(result) };
|
|
430
|
+
} catch (e) {
|
|
431
|
+
return { success: false, error: String(e) };
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
render: ({ args, result, status }) => (
|
|
435
|
+
<div className="my-2 rounded-lg border bg-muted/30 p-4 text-sm">
|
|
436
|
+
<p className="mb-1 font-semibold">execute_js</p>
|
|
437
|
+
<pre className="whitespace-pre-wrap rounded bg-background p-2 font-mono text-xs">
|
|
438
|
+
{args.code}
|
|
439
|
+
</pre>
|
|
440
|
+
{status.type !== "running" && result && (
|
|
441
|
+
<div className="mt-2 border-t pt-2">
|
|
442
|
+
<p className="font-semibold text-muted-foreground">
|
|
443
|
+
{result.success ? "Result:" : "Error:"}
|
|
444
|
+
</p>
|
|
445
|
+
<pre className="whitespace-pre-wrap font-mono text-xs">
|
|
446
|
+
{result.success ? result.result : result.error}
|
|
447
|
+
</pre>
|
|
448
|
+
</div>
|
|
449
|
+
)}
|
|
450
|
+
</div>
|
|
451
|
+
),
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
export default function Home() {
|
|
455
|
+
const runtime = useChatRuntime({
|
|
456
|
+
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
return (
|
|
460
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
461
|
+
<ExecuteJsTool />
|
|
462
|
+
<div className="h-full">
|
|
463
|
+
<MyThread />
|
|
464
|
+
</div>
|
|
465
|
+
</AssistantRuntimeProvider>
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## components.json
|
|
472
|
+
|
|
473
|
+
```json
|
|
474
|
+
{
|
|
475
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
476
|
+
"style": "new-york",
|
|
477
|
+
"rsc": true,
|
|
478
|
+
"tsx": true,
|
|
479
|
+
"tailwind": {
|
|
480
|
+
"config": "",
|
|
481
|
+
"css": "app/globals.css",
|
|
482
|
+
"baseColor": "zinc",
|
|
483
|
+
"cssVariables": true,
|
|
484
|
+
"prefix": ""
|
|
485
|
+
},
|
|
486
|
+
"aliases": {
|
|
487
|
+
"components": "@/components",
|
|
488
|
+
"utils": "@/lib/utils",
|
|
489
|
+
"ui": "@/components/ui",
|
|
490
|
+
"lib": "@/lib",
|
|
491
|
+
"hooks": "@/hooks"
|
|
492
|
+
},
|
|
493
|
+
"iconLibrary": "lucide",
|
|
494
|
+
"registries": {
|
|
495
|
+
"@assistant-ui": "https://r.assistant-ui.com/{name}.json"
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
## lib/utils.ts
|
|
502
|
+
|
|
503
|
+
```typescript
|
|
504
|
+
import { clsx, type ClassValue } from "clsx";
|
|
505
|
+
import { twMerge } from "tailwind-merge";
|
|
506
|
+
|
|
507
|
+
export function cn(...inputs: ClassValue[]) {
|
|
508
|
+
return twMerge(clsx(inputs));
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
## next.config.js
|
|
514
|
+
|
|
515
|
+
```javascript
|
|
516
|
+
/** @type {import('next').NextConfig} */
|
|
517
|
+
const nextConfig = {
|
|
518
|
+
transpilePackages: ["@assistant-ui/react", "@assistant-ui/react-ai-sdk"],
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
export default nextConfig;
|
|
522
|
+
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
## package.json
|
|
526
|
+
|
|
527
|
+
```json
|
|
528
|
+
{
|
|
529
|
+
"name": "with-chain-of-thought",
|
|
530
|
+
"version": "0.0.0",
|
|
531
|
+
"private": true,
|
|
532
|
+
"type": "module",
|
|
533
|
+
"scripts": {
|
|
534
|
+
"dev": "next dev",
|
|
535
|
+
"build": "next build",
|
|
536
|
+
"start": "next start"
|
|
537
|
+
},
|
|
538
|
+
"dependencies": {
|
|
539
|
+
"@ai-sdk/openai": "^3.0.25",
|
|
540
|
+
"@assistant-ui/react": "workspace:*",
|
|
541
|
+
"@assistant-ui/react-ai-sdk": "workspace:*",
|
|
542
|
+
"@assistant-ui/react-markdown": "workspace:*",
|
|
543
|
+
"@assistant-ui/ui": "workspace:*",
|
|
544
|
+
"@radix-ui/react-avatar": "^1.1.11",
|
|
545
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
546
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
547
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
548
|
+
"@radix-ui/react-tooltip": "^1.2.8",
|
|
549
|
+
"ai": "^6.0.73",
|
|
550
|
+
"class-variance-authority": "^0.7.1",
|
|
551
|
+
"clsx": "^2.1.1",
|
|
552
|
+
"lucide-react": "^0.563.0",
|
|
553
|
+
"next": "^16.1.6",
|
|
554
|
+
"react": "^19.2.4",
|
|
555
|
+
"react-dom": "^19.2.4",
|
|
556
|
+
"tailwind-merge": "^3.4.0",
|
|
557
|
+
"zod": "^4.3.6"
|
|
558
|
+
},
|
|
559
|
+
"devDependencies": {
|
|
560
|
+
"@assistant-ui/x-buildutils": "workspace:*",
|
|
561
|
+
"@tailwindcss/postcss": "^4.1.18",
|
|
562
|
+
"@types/node": "^25.2.1",
|
|
563
|
+
"@types/react": "^19.2.13",
|
|
564
|
+
"@types/react-dom": "^19.2.3",
|
|
565
|
+
"postcss": "^8.5.6",
|
|
566
|
+
"tailwindcss": "^4.1.18",
|
|
567
|
+
"tw-animate-css": "^1.4.0",
|
|
568
|
+
"typescript": "^5.9.3"
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
## tsconfig.json
|
|
575
|
+
|
|
576
|
+
```json
|
|
577
|
+
{
|
|
578
|
+
"extends": "@assistant-ui/x-buildutils/ts/next",
|
|
579
|
+
"compilerOptions": {
|
|
580
|
+
"paths": {
|
|
581
|
+
"@/*": ["./*"],
|
|
582
|
+
"@/components/assistant-ui/*": [
|
|
583
|
+
"../../packages/ui/src/components/assistant-ui/*"
|
|
584
|
+
],
|
|
585
|
+
"@/components/ui/*": ["../../packages/ui/src/components/ui/*"],
|
|
586
|
+
"@assistant-ui/ui/*": ["../../packages/ui/src/*"],
|
|
587
|
+
"@assistant-ui/*": ["../../packages/*/src"],
|
|
588
|
+
"@assistant-ui/react/*": ["../../packages/react/src/*"],
|
|
589
|
+
"@assistant-ui/tap/*": ["../../packages/tap/src/*"],
|
|
590
|
+
"assistant-stream": ["../../packages/assistant-stream/src"]
|
|
591
|
+
}
|
|
592
|
+
},
|
|
593
|
+
"include": ["**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
594
|
+
"exclude": ["node_modules"]
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
```
|
|
598
|
+
|
|
@@ -326,7 +326,7 @@ export default nextConfig;
|
|
|
326
326
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
327
327
|
"@radix-ui/react-slot": "^1.2.4",
|
|
328
328
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
329
|
-
"ai": "^6.0.
|
|
329
|
+
"ai": "^6.0.73",
|
|
330
330
|
"class-variance-authority": "^0.7.1",
|
|
331
331
|
"clsx": "^2.1.1",
|
|
332
332
|
"lucide-react": "^0.563.0",
|
|
@@ -338,8 +338,8 @@ export default nextConfig;
|
|
|
338
338
|
"devDependencies": {
|
|
339
339
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
340
340
|
"@tailwindcss/postcss": "^4.1.18",
|
|
341
|
-
"@types/node": "^25.2.
|
|
342
|
-
"@types/react": "^19.2.
|
|
341
|
+
"@types/node": "^25.2.1",
|
|
342
|
+
"@types/react": "^19.2.13",
|
|
343
343
|
"@types/react-dom": "^19.2.3",
|
|
344
344
|
"postcss": "^8.5.6",
|
|
345
345
|
"tailwindcss": "^4.1.18",
|
|
@@ -413,7 +413,7 @@ export default nextConfig;
|
|
|
413
413
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
414
414
|
"@radix-ui/react-slot": "^1.2.4",
|
|
415
415
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
416
|
-
"ai": "^6.0.
|
|
416
|
+
"ai": "^6.0.73",
|
|
417
417
|
"assistant-stream": "workspace:*",
|
|
418
418
|
"class-variance-authority": "^0.7.1",
|
|
419
419
|
"clsx": "^2.1.1",
|
|
@@ -427,8 +427,8 @@ export default nextConfig;
|
|
|
427
427
|
"devDependencies": {
|
|
428
428
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
429
429
|
"@tailwindcss/postcss": "^4.1.18",
|
|
430
|
-
"@types/node": "^25.2.
|
|
431
|
-
"@types/react": "^19.2.
|
|
430
|
+
"@types/node": "^25.2.1",
|
|
431
|
+
"@types/react": "^19.2.13",
|
|
432
432
|
"@types/react-dom": "^19.2.3",
|
|
433
433
|
"postcss": "^8.5.6",
|
|
434
434
|
"tailwindcss": "^4.1.18",
|
|
@@ -548,23 +548,23 @@ export default nextConfig;
|
|
|
548
548
|
"type": "module",
|
|
549
549
|
"dependencies": {
|
|
550
550
|
"@ai-sdk/openai": "^3.0.25",
|
|
551
|
-
"@ai-sdk/react": "^3.0.
|
|
551
|
+
"@ai-sdk/react": "^3.0.75",
|
|
552
552
|
"@assistant-ui/react": "workspace:^",
|
|
553
553
|
"@assistant-ui/react-ai-sdk": "workspace:*",
|
|
554
554
|
"@assistant-ui/react-markdown": "workspace:^",
|
|
555
555
|
"@assistant-ui/ui": "workspace:*",
|
|
556
|
-
"@elevenlabs/client": "^0.
|
|
556
|
+
"@elevenlabs/client": "^0.14.0",
|
|
557
557
|
"@radix-ui/react-avatar": "^1.1.11",
|
|
558
558
|
"@radix-ui/react-collapsible": "^1.1.12",
|
|
559
559
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
560
560
|
"@radix-ui/react-slot": "^1.2.4",
|
|
561
561
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
562
562
|
"@tailwindcss/postcss": "^4.1.18",
|
|
563
|
-
"ai": "^6.0.
|
|
563
|
+
"ai": "^6.0.73",
|
|
564
564
|
"class-variance-authority": "^0.7.1",
|
|
565
565
|
"clsx": "^2.1.1",
|
|
566
566
|
"lucide-react": "^0.563.0",
|
|
567
|
-
"motion": "^12.
|
|
567
|
+
"motion": "^12.33.0",
|
|
568
568
|
"next": "^16.1.6",
|
|
569
569
|
"postcss": "^8.5.6",
|
|
570
570
|
"react": "^19.2.4",
|
|
@@ -575,8 +575,8 @@ export default nextConfig;
|
|
|
575
575
|
},
|
|
576
576
|
"devDependencies": {
|
|
577
577
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
578
|
-
"@types/node": "^25.2.
|
|
579
|
-
"@types/react": "^19.2.
|
|
578
|
+
"@types/node": "^25.2.1",
|
|
579
|
+
"@types/react": "^19.2.13",
|
|
580
580
|
"@types/react-dom": "^19.2.3",
|
|
581
581
|
"tw-animate-css": "^1.4.0",
|
|
582
582
|
"typescript": "^5.9.3"
|
|
@@ -323,8 +323,8 @@ export default nextConfig;
|
|
|
323
323
|
"devDependencies": {
|
|
324
324
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
325
325
|
"@tailwindcss/postcss": "^4.1.18",
|
|
326
|
-
"@types/node": "^25.2.
|
|
327
|
-
"@types/react": "^19.2.
|
|
326
|
+
"@types/node": "^25.2.1",
|
|
327
|
+
"@types/react": "^19.2.13",
|
|
328
328
|
"@types/react-dom": "^19.2.3",
|
|
329
329
|
"postcss": "^8.5.6",
|
|
330
330
|
"tailwindcss": "^4.1.18",
|
|
@@ -527,7 +527,7 @@ export default nextConfig;
|
|
|
527
527
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
528
528
|
"@radix-ui/react-slot": "^1.2.4",
|
|
529
529
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
530
|
-
"ai": "^6.0.
|
|
530
|
+
"ai": "^6.0.73",
|
|
531
531
|
"class-variance-authority": "^0.7.1",
|
|
532
532
|
"clsx": "^2.1.1",
|
|
533
533
|
"lucide-react": "^0.563.0",
|
|
@@ -540,8 +540,8 @@ export default nextConfig;
|
|
|
540
540
|
"devDependencies": {
|
|
541
541
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
542
542
|
"@tailwindcss/postcss": "^4.1.18",
|
|
543
|
-
"@types/node": "^25.2.
|
|
544
|
-
"@types/react": "^19.2.
|
|
543
|
+
"@types/node": "^25.2.1",
|
|
544
|
+
"@types/react": "^19.2.13",
|
|
545
545
|
"@types/react-dom": "^19.2.3",
|
|
546
546
|
"postcss": "^8.5.6",
|
|
547
547
|
"tailwindcss": "^4.1.18",
|
|
@@ -807,7 +807,7 @@ export default nextConfig;
|
|
|
807
807
|
"@assistant-ui/react-langgraph": "workspace:*",
|
|
808
808
|
"@assistant-ui/react-markdown": "workspace:*",
|
|
809
809
|
"@assistant-ui/ui": "workspace:*",
|
|
810
|
-
"@langchain/langgraph-sdk": "^1.5.
|
|
810
|
+
"@langchain/langgraph-sdk": "^1.5.6",
|
|
811
811
|
"@radix-ui/react-avatar": "^1.1.11",
|
|
812
812
|
"@radix-ui/react-collapsible": "^1.1.12",
|
|
813
813
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
@@ -824,8 +824,8 @@ export default nextConfig;
|
|
|
824
824
|
"devDependencies": {
|
|
825
825
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
826
826
|
"@tailwindcss/postcss": "^4.1.18",
|
|
827
|
-
"@types/node": "^25.2.
|
|
828
|
-
"@types/react": "^19.2.
|
|
827
|
+
"@types/node": "^25.2.1",
|
|
828
|
+
"@types/react": "^19.2.13",
|
|
829
829
|
"@types/react-dom": "^19.2.3",
|
|
830
830
|
"postcss": "^8.5.6",
|
|
831
831
|
"tailwindcss": "^4.1.18",
|
|
@@ -483,8 +483,8 @@ export default nextConfig;
|
|
|
483
483
|
"devDependencies": {
|
|
484
484
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
485
485
|
"@tailwindcss/postcss": "^4.1.18",
|
|
486
|
-
"@types/node": "^25.2.
|
|
487
|
-
"@types/react": "^19.2.
|
|
486
|
+
"@types/node": "^25.2.1",
|
|
487
|
+
"@types/react": "^19.2.13",
|
|
488
488
|
"@types/react-dom": "^19.2.3",
|
|
489
489
|
"postcss": "^8.5.6",
|
|
490
490
|
"tailwindcss": "^4.1.18",
|
|
@@ -540,7 +540,7 @@ export default nextConfig;
|
|
|
540
540
|
"@radix-ui/react-slot": "^1.2.4",
|
|
541
541
|
"@radix-ui/react-tabs": "^1.1.13",
|
|
542
542
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
543
|
-
"ai": "^6.0.
|
|
543
|
+
"ai": "^6.0.73",
|
|
544
544
|
"class-variance-authority": "^0.7.1",
|
|
545
545
|
"clsx": "^2.1.1",
|
|
546
546
|
"lucide-react": "^0.563.0",
|
|
@@ -548,15 +548,15 @@ export default nextConfig;
|
|
|
548
548
|
"react": "^19.2.4",
|
|
549
549
|
"react-dom": "^19.2.4",
|
|
550
550
|
"react-hook-form": "^7.71.1",
|
|
551
|
-
"react-resizable-panels": "^4.
|
|
551
|
+
"react-resizable-panels": "^4.6.0",
|
|
552
552
|
"tailwind-merge": "^3.4.0",
|
|
553
553
|
"zod": "^4.3.6"
|
|
554
554
|
},
|
|
555
555
|
"devDependencies": {
|
|
556
556
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
557
557
|
"@tailwindcss/postcss": "^4.1.18",
|
|
558
|
-
"@types/node": "^25.2.
|
|
559
|
-
"@types/react": "^19.2.
|
|
558
|
+
"@types/node": "^25.2.1",
|
|
559
|
+
"@types/react": "^19.2.13",
|
|
560
560
|
"@types/react-dom": "^19.2.3",
|
|
561
561
|
"postcss": "^8.5.6",
|
|
562
562
|
"tailwindcss": "^4.1.18",
|
|
@@ -772,7 +772,7 @@ export default function Home() {
|
|
|
772
772
|
"eventsource-parser": "^3.0.6",
|
|
773
773
|
"isbot": "^5.1.34",
|
|
774
774
|
"lucide-react": "^0.563.0",
|
|
775
|
-
"openai": "^6.
|
|
775
|
+
"openai": "^6.18.0",
|
|
776
776
|
"react": "^19.2.4",
|
|
777
777
|
"react-dom": "^19.2.4",
|
|
778
778
|
"react-router": "7.13.0",
|
|
@@ -783,8 +783,8 @@ export default function Home() {
|
|
|
783
783
|
"devDependencies": {
|
|
784
784
|
"@react-router/dev": "7.13.0",
|
|
785
785
|
"@tailwindcss/vite": "^4.1.18",
|
|
786
|
-
"@types/node": "^25.2.
|
|
787
|
-
"@types/react": "^19.2.
|
|
786
|
+
"@types/node": "^25.2.1",
|
|
787
|
+
"@types/react": "^19.2.13",
|
|
788
788
|
"@types/react-dom": "^19.2.3",
|
|
789
789
|
"tailwindcss": "^4.1.18",
|
|
790
790
|
"tw-animate-css": "^1.4.0",
|
|
@@ -492,8 +492,8 @@ export default nextConfig;
|
|
|
492
492
|
"devDependencies": {
|
|
493
493
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
494
494
|
"@tailwindcss/postcss": "^4.1.18",
|
|
495
|
-
"@types/node": "^25.2.
|
|
496
|
-
"@types/react": "^19.2.
|
|
495
|
+
"@types/node": "^25.2.1",
|
|
496
|
+
"@types/react": "^19.2.13",
|
|
497
497
|
"@types/react-dom": "^19.2.3",
|
|
498
498
|
"postcss": "^8.5.6",
|
|
499
499
|
"tailwindcss": "^4.1.18",
|
|
@@ -67,13 +67,13 @@
|
|
|
67
67
|
"@radix-ui/react-slot": "^1.2.4",
|
|
68
68
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
69
69
|
"@tailwindcss/vite": "^4.1.18",
|
|
70
|
-
"@tanstack/react-router": "^1.158.
|
|
71
|
-
"@tanstack/react-start": "^1.158.
|
|
70
|
+
"@tanstack/react-router": "^1.158.1",
|
|
71
|
+
"@tanstack/react-start": "^1.158.3",
|
|
72
72
|
"class-variance-authority": "^0.7.1",
|
|
73
73
|
"clsx": "^2.1.1",
|
|
74
74
|
"lucide-react": "^0.563.0",
|
|
75
75
|
"nitro": "^3.0.1-alpha.2",
|
|
76
|
-
"openai": "^6.
|
|
76
|
+
"openai": "^6.18.0",
|
|
77
77
|
"react": "^19.2.4",
|
|
78
78
|
"react-dom": "^19.2.4",
|
|
79
79
|
"remark-gfm": "^4.0.1",
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
86
|
-
"@types/node": "^25.2.
|
|
87
|
-
"@types/react": "^19.2.
|
|
86
|
+
"@types/node": "^25.2.1",
|
|
87
|
+
"@types/react": "^19.2.13",
|
|
88
88
|
"@types/react-dom": "^19.2.3",
|
|
89
89
|
"@vitejs/plugin-react": "^5.1.3",
|
|
90
90
|
"typescript": "^5.9.3",
|
|
@@ -619,8 +619,8 @@ export default nextConfig;
|
|
|
619
619
|
"devDependencies": {
|
|
620
620
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
621
621
|
"@tailwindcss/postcss": "^4.1.18",
|
|
622
|
-
"@types/node": "^25.2.
|
|
623
|
-
"@types/react": "^19.2.
|
|
622
|
+
"@types/node": "^25.2.1",
|
|
623
|
+
"@types/react": "^19.2.13",
|
|
624
624
|
"@types/react-dom": "^19.2.3",
|
|
625
625
|
"postcss": "^8.5.6",
|
|
626
626
|
"tailwindcss": "^4.1.18",
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Chain of Thought
|
|
3
|
+
description: Group reasoning and tool calls into a collapsible accordion UI.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
LLMs often produce reasoning steps and tool calls in succession. Chain of Thought lets you visually group these consecutive parts into a single collapsible accordion, giving users a clean "thinking" UI.
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
When a model like OpenAI's `o4-mini` responds, it may emit a sequence of reasoning tokens and tool calls before producing its final text answer. By default, these parts render individually. `ChainOfThoughtPrimitive` groups consecutive reasoning + tool-call parts together and renders them through a single component.
|
|
11
|
+
|
|
12
|
+
Key benefits:
|
|
13
|
+
|
|
14
|
+
- **Cleaner UI** — Collapse intermediate steps behind a "Thinking" toggle
|
|
15
|
+
- **Better context** — Users see that reasoning and tool calls are related
|
|
16
|
+
- **Built-in accordion** — Expand/collapse with a single click; collapsed by default
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
<Steps>
|
|
21
|
+
<Step>
|
|
22
|
+
|
|
23
|
+
### Pass a ChainOfThought component to MessagePrimitive.Parts
|
|
24
|
+
|
|
25
|
+
`MessagePrimitive.Parts` accepts a `ChainOfThought` component. When provided, consecutive reasoning and tool-call parts are automatically grouped and rendered through it.
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import {
|
|
29
|
+
AuiIf,
|
|
30
|
+
ChainOfThoughtPrimitive,
|
|
31
|
+
MessagePrimitive,
|
|
32
|
+
} from "@assistant-ui/react";
|
|
33
|
+
import type { FC } from "react";
|
|
34
|
+
|
|
35
|
+
const Reasoning: FC<{ text: string }> = ({ text }) => {
|
|
36
|
+
return (
|
|
37
|
+
<p className="whitespace-pre-wrap px-4 py-2 text-muted-foreground text-sm italic">
|
|
38
|
+
{text}
|
|
39
|
+
</p>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const ChainOfThought: FC = () => {
|
|
44
|
+
return (
|
|
45
|
+
<ChainOfThoughtPrimitive.Root className="my-2 rounded-lg border">
|
|
46
|
+
<ChainOfThoughtPrimitive.AccordionTrigger className="flex w-full cursor-pointer items-center gap-2 px-4 py-2 font-medium text-sm hover:bg-muted/50">
|
|
47
|
+
Thinking
|
|
48
|
+
</ChainOfThoughtPrimitive.AccordionTrigger>
|
|
49
|
+
<AuiIf condition={({ chainOfThought }) => !chainOfThought.collapsed}>
|
|
50
|
+
<ChainOfThoughtPrimitive.Parts
|
|
51
|
+
components={{ Reasoning, tools: { Fallback: ToolFallback } }}
|
|
52
|
+
/>
|
|
53
|
+
</AuiIf>
|
|
54
|
+
</ChainOfThoughtPrimitive.Root>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const AssistantMessage: FC = () => {
|
|
59
|
+
return (
|
|
60
|
+
<MessagePrimitive.Root>
|
|
61
|
+
<MessagePrimitive.Parts
|
|
62
|
+
components={{
|
|
63
|
+
Text: MarkdownText,
|
|
64
|
+
ChainOfThought, // groups reasoning + tool parts
|
|
65
|
+
}}
|
|
66
|
+
/>
|
|
67
|
+
</MessagePrimitive.Root>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
</Step>
|
|
73
|
+
<Step>
|
|
74
|
+
|
|
75
|
+
### Use a reasoning model
|
|
76
|
+
|
|
77
|
+
Chain of Thought is most useful with models that produce reasoning tokens (e.g. OpenAI `o4-mini`). Here's an example backend route using the Vercel AI SDK:
|
|
78
|
+
|
|
79
|
+
```tsx title="app/api/chat/route.ts"
|
|
80
|
+
import { openai } from "@ai-sdk/openai";
|
|
81
|
+
import { streamText, convertToModelMessages } from "ai";
|
|
82
|
+
|
|
83
|
+
export async function POST(req: Request) {
|
|
84
|
+
const { messages } = await req.json();
|
|
85
|
+
|
|
86
|
+
const result = streamText({
|
|
87
|
+
model: openai("o4-mini"),
|
|
88
|
+
messages: await convertToModelMessages(messages),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return result.toUIMessageStreamResponse();
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
</Step>
|
|
96
|
+
</Steps>
|
|
97
|
+
|
|
98
|
+
## API Reference
|
|
99
|
+
|
|
100
|
+
### ChainOfThoughtPrimitive.Root
|
|
101
|
+
|
|
102
|
+
Container element for the chain of thought group. Renders a `<div>`.
|
|
103
|
+
|
|
104
|
+
### ChainOfThoughtPrimitive.AccordionTrigger
|
|
105
|
+
|
|
106
|
+
A button that toggles the collapsed/expanded state. Collapsed by default.
|
|
107
|
+
|
|
108
|
+
### ChainOfThoughtPrimitive.Parts
|
|
109
|
+
|
|
110
|
+
Renders the grouped parts when expanded (nothing when collapsed).
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<AuiIf condition={({ chainOfThought }) => !chainOfThought.collapsed}>
|
|
114
|
+
<ChainOfThoughtPrimitive.Parts
|
|
115
|
+
components={{
|
|
116
|
+
Reasoning,
|
|
117
|
+
tools: { Fallback: ToolFallback },
|
|
118
|
+
Layout: ({ children }) => (
|
|
119
|
+
<div className="border-l-2 border-muted pl-4">{children}</div>
|
|
120
|
+
),
|
|
121
|
+
}}
|
|
122
|
+
/>
|
|
123
|
+
</AuiIf>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
| Prop | Type | Description |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| `components.Reasoning` | `FC<{ text: string }>` | Component to render reasoning parts |
|
|
129
|
+
| `components.tools.Fallback` | `ToolCallMessagePartComponent` | Fallback component for tool-call parts |
|
|
130
|
+
| `components.Layout` | `ComponentType<PropsWithChildren>` | Wrapper component around each rendered part when expanded |
|
|
131
|
+
|
|
132
|
+
## Reading Collapsed State
|
|
133
|
+
|
|
134
|
+
Use `AuiIf` to conditionally render based on the accordion state:
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import { AuiIf, ChainOfThoughtPrimitive } from "@assistant-ui/react";
|
|
138
|
+
import { ChevronDownIcon, ChevronRightIcon } from "lucide-react";
|
|
139
|
+
|
|
140
|
+
const ChainOfThoughtAccordionTrigger = () => {
|
|
141
|
+
return (
|
|
142
|
+
<ChainOfThoughtPrimitive.AccordionTrigger className="flex w-full cursor-pointer items-center gap-2 px-4 py-2 text-sm">
|
|
143
|
+
<AuiIf condition={({ chainOfThought }) => chainOfThought.collapsed}>
|
|
144
|
+
<ChevronRightIcon className="size-4" />
|
|
145
|
+
</AuiIf>
|
|
146
|
+
<AuiIf condition={({ chainOfThought }) => !chainOfThought.collapsed}>
|
|
147
|
+
<ChevronDownIcon className="size-4" />
|
|
148
|
+
</AuiIf>
|
|
149
|
+
Thinking
|
|
150
|
+
</ChainOfThoughtPrimitive.AccordionTrigger>
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Full Example
|
|
156
|
+
|
|
157
|
+
See the complete [with-chain-of-thought example](https://github.com/Yonom/assistant-ui/tree/main/examples/with-chain-of-thought) for a working implementation with tool calls and reasoning.
|
|
158
|
+
|
|
159
|
+
## Related Guides
|
|
160
|
+
|
|
161
|
+
- [Generative UI](/docs/guides/tool-ui) — Custom UI for tool calls
|
|
162
|
+
- [Tools](/docs/guides/tools) — Defining and using tools
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/mcp-docs-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.22",
|
|
4
4
|
"description": "MCP server for assistant-ui documentation and examples",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
],
|
|
34
34
|
"sideEffects": false,
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
37
37
|
"gray-matter": "^4.0.3",
|
|
38
38
|
"zod": "^4.3.6"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@types/node": "^25.2.
|
|
41
|
+
"@types/node": "^25.2.1",
|
|
42
42
|
"tsx": "^4.21.0",
|
|
43
43
|
"vitest": "^4.0.18",
|
|
44
44
|
"@assistant-ui/x-buildutils": "0.0.1"
|