@assistant-ui/mcp-docs-server 0.1.4 → 0.1.6
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/local-ollama.md +10 -10
- package/.docs/organized/code-examples/search-agent-for-e-commerce.md +14 -14
- package/.docs/organized/code-examples/{with-vercel-ai-rsc.md → with-ai-sdk-v5.md} +259 -229
- package/.docs/organized/code-examples/with-ai-sdk.md +11 -10
- package/.docs/organized/code-examples/with-cloud.md +9 -8
- package/.docs/organized/code-examples/with-external-store.md +6 -6
- package/.docs/organized/code-examples/with-ffmpeg.md +15 -16
- package/.docs/organized/code-examples/with-langgraph.md +9 -8
- package/.docs/organized/code-examples/with-openai-assistants.md +9 -9
- package/.docs/organized/code-examples/with-parent-id-grouping.md +1377 -0
- package/.docs/organized/code-examples/with-react-hook-form.md +14 -15
- package/.docs/raw/docs/about-assistantui.mdx +9 -0
- package/.docs/raw/docs/cloud/persistence/ai-sdk.mdx +89 -32
- package/.docs/raw/docs/cloud/persistence/langgraph.mdx +187 -32
- package/.docs/raw/docs/guides/Latex.mdx +107 -0
- package/.docs/raw/docs/guides/ToolUI.mdx +0 -32
- package/.docs/raw/docs/runtimes/ai-sdk/use-chat-v5.mdx +212 -0
- package/.docs/raw/docs/runtimes/ai-sdk/use-chat.mdx +1 -1
- package/.docs/raw/docs/runtimes/custom/local.mdx +1 -1
- package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +2 -2
- package/.docs/raw/docs/ui/PartGrouping.mdx +540 -0
- package/.docs/raw/docs/ui/ToolGroup.mdx +96 -0
- package/dist/{chunk-JS4PWCVA.js → chunk-L4K23SWI.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/stdio.js +1 -1
- package/package.json +7 -7
|
@@ -1,86 +1,45 @@
|
|
|
1
|
-
# Example: with-
|
|
1
|
+
# Example: with-ai-sdk-v5
|
|
2
2
|
|
|
3
|
-
## app/
|
|
4
|
-
|
|
5
|
-
```tsx
|
|
6
|
-
"use server";
|
|
3
|
+
## app/api/chat/route.ts
|
|
7
4
|
|
|
5
|
+
```typescript
|
|
8
6
|
import { openai } from "@ai-sdk/openai";
|
|
9
|
-
import {
|
|
10
|
-
|
|
7
|
+
import {
|
|
8
|
+
streamText,
|
|
9
|
+
UIMessage,
|
|
10
|
+
convertToModelMessages,
|
|
11
|
+
tool,
|
|
12
|
+
stepCountIs,
|
|
13
|
+
} from "ai";
|
|
11
14
|
import { z } from "zod";
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
content: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ClientMessage {
|
|
19
|
-
role: "user" | "assistant";
|
|
20
|
-
display: ReactNode;
|
|
21
|
-
}
|
|
16
|
+
// Allow streaming responses up to 30 seconds
|
|
17
|
+
export const maxDuration = 30;
|
|
22
18
|
|
|
23
|
-
export async function
|
|
24
|
-
|
|
25
|
-
): Promise<ClientMessage> {
|
|
26
|
-
"use server";
|
|
27
|
-
|
|
28
|
-
const history = getMutableAIState();
|
|
29
|
-
|
|
30
|
-
const result = await streamUI({
|
|
31
|
-
model: openai("gpt-3.5-turbo"),
|
|
32
|
-
messages: [...history.get(), { role: "user", content: input }],
|
|
33
|
-
text: ({ content, done }) => {
|
|
34
|
-
if (done) {
|
|
35
|
-
history.done((messages: ServerMessage[]) => [
|
|
36
|
-
...messages,
|
|
37
|
-
{ role: "assistant", content },
|
|
38
|
-
]);
|
|
39
|
-
}
|
|
19
|
+
export async function POST(req: Request) {
|
|
20
|
+
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
40
21
|
|
|
41
|
-
|
|
42
|
-
|
|
22
|
+
const result = streamText({
|
|
23
|
+
model: openai("gpt-4o"),
|
|
24
|
+
messages: convertToModelMessages(messages),
|
|
25
|
+
stopWhen: stepCountIs(10),
|
|
43
26
|
tools: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.string()
|
|
50
|
-
.describe("The stock symbol to get information for"),
|
|
51
|
-
numOfMonths: z
|
|
52
|
-
.number()
|
|
53
|
-
.describe("The number of months to get historical information for"),
|
|
27
|
+
get_current_weather: tool({
|
|
28
|
+
name: "",
|
|
29
|
+
description: "Get the current weather",
|
|
30
|
+
inputSchema: z.object({
|
|
31
|
+
city: z.string(),
|
|
54
32
|
}),
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
...messages,
|
|
58
|
-
{
|
|
59
|
-
role: "assistant",
|
|
60
|
-
content: `Showing stock information for ${symbol}`,
|
|
61
|
-
},
|
|
62
|
-
]);
|
|
63
|
-
|
|
64
|
-
return <p className="font-bold">Test</p>;
|
|
33
|
+
execute: async ({ city }) => {
|
|
34
|
+
return `The weather in ${city} is sunny`;
|
|
65
35
|
},
|
|
66
|
-
},
|
|
36
|
+
}),
|
|
67
37
|
},
|
|
68
38
|
});
|
|
69
39
|
|
|
70
|
-
return
|
|
71
|
-
role: "assistant",
|
|
72
|
-
display: result.value,
|
|
73
|
-
};
|
|
40
|
+
return result.toUIMessageStreamResponse();
|
|
74
41
|
}
|
|
75
42
|
|
|
76
|
-
export const AI = createAI<ServerMessage[], ClientMessage[]>({
|
|
77
|
-
actions: {
|
|
78
|
-
continueConversation,
|
|
79
|
-
},
|
|
80
|
-
initialAIState: [],
|
|
81
|
-
initialUIState: [],
|
|
82
|
-
});
|
|
83
|
-
|
|
84
43
|
```
|
|
85
44
|
|
|
86
45
|
## app/globals.css
|
|
@@ -92,43 +51,41 @@ export const AI = createAI<ServerMessage[], ClientMessage[]>({
|
|
|
92
51
|
@custom-variant dark (&:is(.dark *));
|
|
93
52
|
|
|
94
53
|
@theme inline {
|
|
95
|
-
--color-background: var(--background);
|
|
96
|
-
--color-foreground: var(--foreground);
|
|
97
|
-
--font-sans: var(--font-geist-sans);
|
|
98
|
-
--font-mono: var(--font-geist-mono);
|
|
99
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
100
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
101
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
102
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
103
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
104
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
105
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
106
|
-
--color-sidebar: var(--sidebar);
|
|
107
|
-
--color-chart-5: var(--chart-5);
|
|
108
|
-
--color-chart-4: var(--chart-4);
|
|
109
|
-
--color-chart-3: var(--chart-3);
|
|
110
|
-
--color-chart-2: var(--chart-2);
|
|
111
|
-
--color-chart-1: var(--chart-1);
|
|
112
|
-
--color-ring: var(--ring);
|
|
113
|
-
--color-input: var(--input);
|
|
114
|
-
--color-border: var(--border);
|
|
115
|
-
--color-destructive: var(--destructive);
|
|
116
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
117
|
-
--color-accent: var(--accent);
|
|
118
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
119
|
-
--color-muted: var(--muted);
|
|
120
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
121
|
-
--color-secondary: var(--secondary);
|
|
122
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
123
|
-
--color-primary: var(--primary);
|
|
124
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
125
|
-
--color-popover: var(--popover);
|
|
126
|
-
--color-card-foreground: var(--card-foreground);
|
|
127
|
-
--color-card: var(--card);
|
|
128
54
|
--radius-sm: calc(var(--radius) - 4px);
|
|
129
55
|
--radius-md: calc(var(--radius) - 2px);
|
|
130
56
|
--radius-lg: var(--radius);
|
|
131
57
|
--radius-xl: calc(var(--radius) + 4px);
|
|
58
|
+
--color-background: var(--background);
|
|
59
|
+
--color-foreground: var(--foreground);
|
|
60
|
+
--color-card: var(--card);
|
|
61
|
+
--color-card-foreground: var(--card-foreground);
|
|
62
|
+
--color-popover: var(--popover);
|
|
63
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
64
|
+
--color-primary: var(--primary);
|
|
65
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
66
|
+
--color-secondary: var(--secondary);
|
|
67
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
68
|
+
--color-muted: var(--muted);
|
|
69
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
70
|
+
--color-accent: var(--accent);
|
|
71
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
72
|
+
--color-destructive: var(--destructive);
|
|
73
|
+
--color-border: var(--border);
|
|
74
|
+
--color-input: var(--input);
|
|
75
|
+
--color-ring: var(--ring);
|
|
76
|
+
--color-chart-1: var(--chart-1);
|
|
77
|
+
--color-chart-2: var(--chart-2);
|
|
78
|
+
--color-chart-3: var(--chart-3);
|
|
79
|
+
--color-chart-4: var(--chart-4);
|
|
80
|
+
--color-chart-5: var(--chart-5);
|
|
81
|
+
--color-sidebar: var(--sidebar);
|
|
82
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
83
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
84
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
85
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
86
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
87
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
88
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
132
89
|
}
|
|
133
90
|
|
|
134
91
|
:root {
|
|
@@ -215,24 +172,11 @@ export const AI = createAI<ServerMessage[], ClientMessage[]>({
|
|
|
215
172
|
|
|
216
173
|
```tsx
|
|
217
174
|
import type { Metadata } from "next";
|
|
218
|
-
import { Geist, Geist_Mono } from "next/font/google";
|
|
219
|
-
import { AI } from "./actions";
|
|
220
|
-
|
|
221
175
|
import "./globals.css";
|
|
222
176
|
|
|
223
|
-
const geistSans = Geist({
|
|
224
|
-
variable: "--font-geist-sans",
|
|
225
|
-
subsets: ["latin"],
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
const geistMono = Geist_Mono({
|
|
229
|
-
variable: "--font-geist-mono",
|
|
230
|
-
subsets: ["latin"],
|
|
231
|
-
});
|
|
232
|
-
|
|
233
177
|
export const metadata: Metadata = {
|
|
234
|
-
title: "
|
|
235
|
-
description: "
|
|
178
|
+
title: "AI SDK v5 Example",
|
|
179
|
+
description: "Example using @assistant-ui/react with AI SDK v5",
|
|
236
180
|
};
|
|
237
181
|
|
|
238
182
|
export default function RootLayout({
|
|
@@ -241,12 +185,8 @@ export default function RootLayout({
|
|
|
241
185
|
children: React.ReactNode;
|
|
242
186
|
}>) {
|
|
243
187
|
return (
|
|
244
|
-
<html lang="en"
|
|
245
|
-
<body
|
|
246
|
-
className={`${geistSans.variable} ${geistMono.variable} h-dvh antialiased`}
|
|
247
|
-
>
|
|
248
|
-
<AI>{children}</AI>
|
|
249
|
-
</body>
|
|
188
|
+
<html lang="en">
|
|
189
|
+
<body className="h-dvh">{children}</body>
|
|
250
190
|
</html>
|
|
251
191
|
);
|
|
252
192
|
}
|
|
@@ -258,60 +198,22 @@ export default function RootLayout({
|
|
|
258
198
|
```tsx
|
|
259
199
|
"use client";
|
|
260
200
|
|
|
261
|
-
import { useActions, useUIState } from "ai/rsc";
|
|
262
|
-
import { nanoid } from "nanoid";
|
|
263
|
-
import type { AI } from "./actions";
|
|
264
|
-
|
|
265
201
|
import { Thread } from "@/components/assistant-ui/thread";
|
|
266
|
-
import {
|
|
267
|
-
|
|
268
|
-
AssistantRuntimeProvider,
|
|
269
|
-
} from "@assistant-ui/react";
|
|
270
|
-
import { useVercelRSCRuntime } from "@assistant-ui/react-ai-sdk";
|
|
271
|
-
import { useState } from "react";
|
|
202
|
+
import { AssistantRuntimeProvider } from "@assistant-ui/react";
|
|
203
|
+
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
272
204
|
|
|
273
205
|
export default function Home() {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
<MyRuntimeProvider>
|
|
277
|
-
<Thread />
|
|
278
|
-
</MyRuntimeProvider>
|
|
279
|
-
</main>
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const MyRuntimeProvider = ({ children }: { children: React.ReactNode }) => {
|
|
284
|
-
const { continueConversation } = useActions();
|
|
285
|
-
const [isRunning, setIsRunning] = useState(false);
|
|
286
|
-
const [messages, setMessages] = useUIState<typeof AI>();
|
|
287
|
-
|
|
288
|
-
const onNew = async (m: AppendMessage) => {
|
|
289
|
-
if (m.content[0]?.type !== "text")
|
|
290
|
-
throw new Error("Only text messages are supported");
|
|
291
|
-
|
|
292
|
-
const input = m.content[0].text;
|
|
293
|
-
setMessages((currentConversation) => [
|
|
294
|
-
...currentConversation,
|
|
295
|
-
{ id: nanoid(), role: "user", display: input },
|
|
296
|
-
]);
|
|
297
|
-
|
|
298
|
-
try {
|
|
299
|
-
setIsRunning(true);
|
|
300
|
-
const message = await continueConversation(input);
|
|
301
|
-
setMessages((currentConversation) => [...currentConversation, message]);
|
|
302
|
-
} finally {
|
|
303
|
-
setIsRunning(false);
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
const runtime = useVercelRSCRuntime({ messages, isRunning, onNew });
|
|
206
|
+
// Using the new simplified useChatRuntime hook
|
|
207
|
+
const runtime = useChatRuntime();
|
|
308
208
|
|
|
309
209
|
return (
|
|
310
210
|
<AssistantRuntimeProvider runtime={runtime}>
|
|
311
|
-
|
|
211
|
+
<div className="h-full">
|
|
212
|
+
<Thread />
|
|
213
|
+
</div>
|
|
312
214
|
</AssistantRuntimeProvider>
|
|
313
215
|
);
|
|
314
|
-
}
|
|
216
|
+
}
|
|
315
217
|
|
|
316
218
|
```
|
|
317
219
|
|
|
@@ -332,8 +234,12 @@ const MyRuntimeProvider = ({ children }: { children: React.ReactNode }) => {
|
|
|
332
234
|
},
|
|
333
235
|
"aliases": {
|
|
334
236
|
"components": "@/components",
|
|
335
|
-
"utils": "@/lib/utils"
|
|
336
|
-
|
|
237
|
+
"utils": "@/lib/utils",
|
|
238
|
+
"ui": "@/components/ui",
|
|
239
|
+
"lib": "@/lib",
|
|
240
|
+
"hooks": "@/hooks"
|
|
241
|
+
},
|
|
242
|
+
"iconLibrary": "lucide"
|
|
337
243
|
}
|
|
338
244
|
|
|
339
245
|
```
|
|
@@ -346,13 +252,13 @@ const MyRuntimeProvider = ({ children }: { children: React.ReactNode }) => {
|
|
|
346
252
|
import "@assistant-ui/react-markdown/styles/dot.css";
|
|
347
253
|
|
|
348
254
|
import {
|
|
349
|
-
CodeHeaderProps,
|
|
255
|
+
type CodeHeaderProps,
|
|
350
256
|
MarkdownTextPrimitive,
|
|
351
257
|
unstable_memoizeMarkdownComponents as memoizeMarkdownComponents,
|
|
352
258
|
useIsMarkdownCodeBlock,
|
|
353
259
|
} from "@assistant-ui/react-markdown";
|
|
354
260
|
import remarkGfm from "remark-gfm";
|
|
355
|
-
import { FC, memo, useState } from "react";
|
|
261
|
+
import { type FC, memo, useState } from "react";
|
|
356
262
|
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
357
263
|
|
|
358
264
|
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
@@ -378,7 +284,7 @@ const CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {
|
|
|
378
284
|
};
|
|
379
285
|
|
|
380
286
|
return (
|
|
381
|
-
<div className="flex items-center justify-between gap-4 rounded-t-lg bg-zinc-900 px-4 py-2 text-sm font-semibold text-white">
|
|
287
|
+
<div className="mt-4 flex items-center justify-between gap-4 rounded-t-lg bg-zinc-900 px-4 py-2 text-sm font-semibold text-white">
|
|
382
288
|
<span className="lowercase [&>span]:text-xs">{language}</span>
|
|
383
289
|
<TooltipIconButton tooltip="Copy" onClick={onCopy}>
|
|
384
290
|
{!isCopied && <CopyIcon />}
|
|
@@ -540,7 +446,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
540
446
|
pre: ({ className, ...props }) => (
|
|
541
447
|
<pre
|
|
542
448
|
className={cn(
|
|
543
|
-
"overflow-x-auto rounded-b-lg bg-black p-4 text-white",
|
|
449
|
+
"overflow-x-auto !rounded-t-none rounded-b-lg bg-black p-4 text-white",
|
|
544
450
|
className,
|
|
545
451
|
)}
|
|
546
452
|
{...props}
|
|
@@ -570,6 +476,7 @@ import {
|
|
|
570
476
|
ActionBarPrimitive,
|
|
571
477
|
BranchPickerPrimitive,
|
|
572
478
|
ComposerPrimitive,
|
|
479
|
+
ErrorPrimitive,
|
|
573
480
|
MessagePrimitive,
|
|
574
481
|
ThreadPrimitive,
|
|
575
482
|
} from "@assistant-ui/react";
|
|
@@ -589,11 +496,12 @@ import { cn } from "@/lib/utils";
|
|
|
589
496
|
import { Button } from "@/components/ui/button";
|
|
590
497
|
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|
591
498
|
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
499
|
+
import { ToolFallback } from "./tool-fallback";
|
|
592
500
|
|
|
593
501
|
export const Thread: FC = () => {
|
|
594
502
|
return (
|
|
595
503
|
<ThreadPrimitive.Root
|
|
596
|
-
className="bg-background box-border flex h-full flex-col overflow-hidden"
|
|
504
|
+
className="text-foreground bg-background box-border flex h-full flex-col overflow-hidden"
|
|
597
505
|
style={{
|
|
598
506
|
["--thread-max-width" as string]: "42rem",
|
|
599
507
|
}}
|
|
@@ -770,7 +678,10 @@ const AssistantMessage: FC = () => {
|
|
|
770
678
|
return (
|
|
771
679
|
<MessagePrimitive.Root className="relative grid w-full max-w-[var(--thread-max-width)] grid-cols-[auto_auto_1fr] grid-rows-[auto_1fr] py-4">
|
|
772
680
|
<div className="text-foreground col-span-2 col-start-2 row-start-1 my-1.5 max-w-[calc(var(--thread-max-width)*0.8)] break-words leading-7">
|
|
773
|
-
<MessagePrimitive.Parts
|
|
681
|
+
<MessagePrimitive.Parts
|
|
682
|
+
components={{ Text: MarkdownText, tools: { Fallback: ToolFallback } }}
|
|
683
|
+
/>
|
|
684
|
+
<MessageError />
|
|
774
685
|
</div>
|
|
775
686
|
|
|
776
687
|
<AssistantActionBar />
|
|
@@ -780,6 +691,16 @@ const AssistantMessage: FC = () => {
|
|
|
780
691
|
);
|
|
781
692
|
};
|
|
782
693
|
|
|
694
|
+
const MessageError: FC = () => {
|
|
695
|
+
return (
|
|
696
|
+
<MessagePrimitive.Error>
|
|
697
|
+
<ErrorPrimitive.Root className="border-destructive bg-destructive/10 dark:bg-destructive/5 text-destructive mt-2 rounded-md border p-3 text-sm dark:text-red-200">
|
|
698
|
+
<ErrorPrimitive.Message className="line-clamp-2" />
|
|
699
|
+
</ErrorPrimitive.Root>
|
|
700
|
+
</MessagePrimitive.Error>
|
|
701
|
+
);
|
|
702
|
+
};
|
|
703
|
+
|
|
783
704
|
const AssistantActionBar: FC = () => {
|
|
784
705
|
return (
|
|
785
706
|
<ActionBarPrimitive.Root
|
|
@@ -853,6 +774,54 @@ const CircleStopIcon = () => {
|
|
|
853
774
|
|
|
854
775
|
```
|
|
855
776
|
|
|
777
|
+
## components/assistant-ui/tool-fallback.tsx
|
|
778
|
+
|
|
779
|
+
```tsx
|
|
780
|
+
import { ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
781
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
782
|
+
import { useState } from "react";
|
|
783
|
+
import { Button } from "../ui/button";
|
|
784
|
+
|
|
785
|
+
export const ToolFallback: ToolCallMessagePartComponent = ({
|
|
786
|
+
toolName,
|
|
787
|
+
argsText,
|
|
788
|
+
result,
|
|
789
|
+
}) => {
|
|
790
|
+
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
791
|
+
return (
|
|
792
|
+
<div className="mb-4 flex w-full flex-col gap-3 rounded-lg border py-3">
|
|
793
|
+
<div className="flex items-center gap-2 px-4">
|
|
794
|
+
<CheckIcon className="size-4" />
|
|
795
|
+
<p className="flex-grow">
|
|
796
|
+
Used tool: <b>{toolName}</b>
|
|
797
|
+
</p>
|
|
798
|
+
<Button onClick={() => setIsCollapsed(!isCollapsed)}>
|
|
799
|
+
{isCollapsed ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
|
800
|
+
</Button>
|
|
801
|
+
</div>
|
|
802
|
+
{!isCollapsed && (
|
|
803
|
+
<div className="flex flex-col gap-2 border-t pt-2">
|
|
804
|
+
<div className="px-4">
|
|
805
|
+
<pre className="whitespace-pre-wrap">{argsText}</pre>
|
|
806
|
+
</div>
|
|
807
|
+
{result !== undefined && (
|
|
808
|
+
<div className="border-t border-dashed px-4 pt-2">
|
|
809
|
+
<p className="font-semibold">Result:</p>
|
|
810
|
+
<pre className="whitespace-pre-wrap">
|
|
811
|
+
{typeof result === "string"
|
|
812
|
+
? result
|
|
813
|
+
: JSON.stringify(result, null, 2)}
|
|
814
|
+
</pre>
|
|
815
|
+
</div>
|
|
816
|
+
)}
|
|
817
|
+
</div>
|
|
818
|
+
)}
|
|
819
|
+
</div>
|
|
820
|
+
);
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
```
|
|
824
|
+
|
|
856
825
|
## components/assistant-ui/tooltip-icon-button.tsx
|
|
857
826
|
|
|
858
827
|
```tsx
|
|
@@ -1016,7 +985,7 @@ function TooltipContent({
|
|
|
1016
985
|
data-slot="tooltip-content"
|
|
1017
986
|
sideOffset={sideOffset}
|
|
1018
987
|
className={cn(
|
|
1019
|
-
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2
|
|
988
|
+
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--radix-tooltip-content-transform-origin) z-50 w-fit text-balance rounded-md px-3 py-1.5 text-xs",
|
|
1020
989
|
className,
|
|
1021
990
|
)}
|
|
1022
991
|
{...props}
|
|
@@ -1032,17 +1001,10 @@ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
|
1032
1001
|
|
|
1033
1002
|
```
|
|
1034
1003
|
|
|
1035
|
-
## eslint.config.ts
|
|
1036
|
-
|
|
1037
|
-
```typescript
|
|
1038
|
-
export { default } from "@assistant-ui/x-buildutils/eslint";
|
|
1039
|
-
|
|
1040
|
-
```
|
|
1041
|
-
|
|
1042
1004
|
## lib/utils.ts
|
|
1043
1005
|
|
|
1044
1006
|
```typescript
|
|
1045
|
-
import { type ClassValue
|
|
1007
|
+
import { clsx, type ClassValue } from "clsx";
|
|
1046
1008
|
import { twMerge } from "tailwind-merge";
|
|
1047
1009
|
|
|
1048
1010
|
export function cn(...inputs: ClassValue[]) {
|
|
@@ -1051,24 +1013,12 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1051
1013
|
|
|
1052
1014
|
```
|
|
1053
1015
|
|
|
1054
|
-
## next
|
|
1055
|
-
|
|
1056
|
-
```typescript
|
|
1057
|
-
/// <reference types="next" />
|
|
1058
|
-
/// <reference types="next/image-types/global" />
|
|
1059
|
-
|
|
1060
|
-
// NOTE: This file should not be edited
|
|
1061
|
-
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
|
1016
|
+
## next.config.js
|
|
1062
1017
|
|
|
1063
|
-
```
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
```typescript
|
|
1068
|
-
import type { NextConfig } from "next";
|
|
1069
|
-
|
|
1070
|
-
const nextConfig: NextConfig = {
|
|
1071
|
-
/* config options here */
|
|
1018
|
+
```javascript
|
|
1019
|
+
/** @type {import('next').NextConfig} */
|
|
1020
|
+
const nextConfig = {
|
|
1021
|
+
transpilePackages: ["@assistant-ui/react", "@assistant-ui/react-ai-sdk"],
|
|
1072
1022
|
};
|
|
1073
1023
|
|
|
1074
1024
|
export default nextConfig;
|
|
@@ -1079,51 +1029,131 @@ export default nextConfig;
|
|
|
1079
1029
|
|
|
1080
1030
|
```json
|
|
1081
1031
|
{
|
|
1082
|
-
"name": "with-
|
|
1083
|
-
"version": "0.1.0",
|
|
1032
|
+
"name": "example-with-ai-sdk-v5",
|
|
1084
1033
|
"private": true,
|
|
1085
|
-
"
|
|
1086
|
-
|
|
1087
|
-
"build": "next build",
|
|
1088
|
-
"start": "next start",
|
|
1089
|
-
"lint": "next lint"
|
|
1090
|
-
},
|
|
1034
|
+
"version": "0.0.0",
|
|
1035
|
+
"type": "module",
|
|
1091
1036
|
"dependencies": {
|
|
1092
|
-
"@ai-sdk/openai": "^
|
|
1093
|
-
"@
|
|
1037
|
+
"@ai-sdk/openai": "^2.0.0",
|
|
1038
|
+
"@ai-sdk/react": "^2.0.0",
|
|
1039
|
+
"@assistant-ui/react": "workspace:^",
|
|
1094
1040
|
"@assistant-ui/react-ai-sdk": "workspace:*",
|
|
1095
|
-
"@assistant-ui/react-markdown": "workspace
|
|
1096
|
-
"@radix-ui/react-icons": "^1.3.2",
|
|
1041
|
+
"@assistant-ui/react-markdown": "workspace:^",
|
|
1097
1042
|
"@radix-ui/react-slot": "^1.2.3",
|
|
1098
1043
|
"@radix-ui/react-tooltip": "^1.2.7",
|
|
1099
|
-
"
|
|
1044
|
+
"@tailwindcss/postcss": "^4.1.11",
|
|
1045
|
+
"ai": "^5.0.0",
|
|
1100
1046
|
"class-variance-authority": "^0.7.1",
|
|
1101
1047
|
"clsx": "^2.1.1",
|
|
1102
|
-
"lucide-react": "^0.
|
|
1103
|
-
"
|
|
1104
|
-
"
|
|
1105
|
-
"react": "19.1.
|
|
1106
|
-
"react-dom": "19.1.
|
|
1048
|
+
"lucide-react": "^0.535.0",
|
|
1049
|
+
"next": "15.4.5",
|
|
1050
|
+
"postcss": "^8.5.6",
|
|
1051
|
+
"react": "19.1.1",
|
|
1052
|
+
"react-dom": "19.1.1",
|
|
1107
1053
|
"remark-gfm": "^4.0.1",
|
|
1108
1054
|
"tailwind-merge": "^3.3.1",
|
|
1109
|
-
"
|
|
1110
|
-
"zod": "^
|
|
1055
|
+
"tailwindcss": "^4.1.11",
|
|
1056
|
+
"zod": "^4.0.14"
|
|
1111
1057
|
},
|
|
1112
1058
|
"devDependencies": {
|
|
1113
1059
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
1114
|
-
"@types/node": "^24",
|
|
1115
|
-
"@types/react": "^19",
|
|
1116
|
-
"@types/react-dom": "^19",
|
|
1060
|
+
"@types/node": "^24.1.0",
|
|
1061
|
+
"@types/react": "^19.1.9",
|
|
1062
|
+
"@types/react-dom": "^19.1.7",
|
|
1117
1063
|
"eslint": "^9",
|
|
1118
|
-
"eslint-config-next": "15.
|
|
1119
|
-
"
|
|
1120
|
-
"
|
|
1121
|
-
|
|
1064
|
+
"eslint-config-next": "15.4.5",
|
|
1065
|
+
"tw-animate-css": "^1.3.6",
|
|
1066
|
+
"typescript": "^5.9.2"
|
|
1067
|
+
},
|
|
1068
|
+
"scripts": {
|
|
1069
|
+
"dev": "next dev",
|
|
1070
|
+
"build": "next build",
|
|
1071
|
+
"start": "next start",
|
|
1072
|
+
"lint": "next lint"
|
|
1122
1073
|
}
|
|
1123
1074
|
}
|
|
1124
1075
|
|
|
1125
1076
|
```
|
|
1126
1077
|
|
|
1078
|
+
## README.md
|
|
1079
|
+
|
|
1080
|
+
```markdown
|
|
1081
|
+
# AI SDK v5 Example
|
|
1082
|
+
|
|
1083
|
+
This example demonstrates how to use `@assistant-ui/react-ai-sdk-v5` with the Vercel AI SDK v5.
|
|
1084
|
+
|
|
1085
|
+
## Getting Started
|
|
1086
|
+
|
|
1087
|
+
1. Install dependencies:
|
|
1088
|
+
|
|
1089
|
+
```bash
|
|
1090
|
+
npm install
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
2. Set up your environment variables:
|
|
1094
|
+
|
|
1095
|
+
```bash
|
|
1096
|
+
cp .env.example .env.local
|
|
1097
|
+
```
|
|
1098
|
+
|
|
1099
|
+
Add your Anthropic API key to `.env.local`:
|
|
1100
|
+
|
|
1101
|
+
```
|
|
1102
|
+
ANTHROPIC_API_KEY=your-api-key-here
|
|
1103
|
+
```
|
|
1104
|
+
|
|
1105
|
+
3. Run the development server:
|
|
1106
|
+
|
|
1107
|
+
```bash
|
|
1108
|
+
npm run dev
|
|
1109
|
+
```
|
|
1110
|
+
|
|
1111
|
+
Open [http://localhost:3000](http://localhost:3000) to see the result.
|
|
1112
|
+
|
|
1113
|
+
## Key Features
|
|
1114
|
+
|
|
1115
|
+
- Uses the new AI SDK v5 with `@ai-sdk/react` and `@ai-sdk/anthropic`
|
|
1116
|
+
- Integrates with `@assistant-ui/react` using the new `useChatRuntime` hook
|
|
1117
|
+
- No RSC support (client-side only)
|
|
1118
|
+
- Simplified integration with the `useChatRuntime` hook that wraps AI SDK v5's `useChat`
|
|
1119
|
+
- Automatically uses `AssistantChatTransport` to pass system messages and frontend tools to the backend
|
|
1120
|
+
|
|
1121
|
+
## Custom Transport Configuration
|
|
1122
|
+
|
|
1123
|
+
By default, `useChatRuntime` uses `AssistantChatTransport` which automatically forwards system messages and frontend tools to the backend.
|
|
1124
|
+
|
|
1125
|
+
### Custom API URL with Forwarding
|
|
1126
|
+
|
|
1127
|
+
When customizing the API URL, you must explicitly use `AssistantChatTransport` to keep system/tools forwarding:
|
|
1128
|
+
|
|
1129
|
+
```typescript
|
|
1130
|
+
import { AssistantChatTransport } from "@assistant-ui/react-ai-sdk";
|
|
1131
|
+
|
|
1132
|
+
const runtime = useChatRuntime({
|
|
1133
|
+
transport: new AssistantChatTransport({
|
|
1134
|
+
api: "/my-custom-api/chat", // Custom URL with system/tools forwarding
|
|
1135
|
+
}),
|
|
1136
|
+
});
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
### Disable System/Tools Forwarding
|
|
1140
|
+
|
|
1141
|
+
To use the standard AI SDK transport without forwarding:
|
|
1142
|
+
|
|
1143
|
+
```typescript
|
|
1144
|
+
import { DefaultChatTransport } from "ai";
|
|
1145
|
+
|
|
1146
|
+
const runtime = useChatRuntime({
|
|
1147
|
+
transport: new DefaultChatTransport(), // No system/tools forwarding
|
|
1148
|
+
});
|
|
1149
|
+
```
|
|
1150
|
+
|
|
1151
|
+
## API Route
|
|
1152
|
+
|
|
1153
|
+
The API route at `/api/chat` uses the new `streamText` function from AI SDK v5 to handle chat completions.
|
|
1154
|
+
|
|
1155
|
+
```
|
|
1156
|
+
|
|
1127
1157
|
## tsconfig.json
|
|
1128
1158
|
|
|
1129
1159
|
```json
|