@assistant-ui/mcp-docs-server 0.1.3 → 0.1.5
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 +13 -13
- package/.docs/organized/code-examples/search-agent-for-e-commerce.md +18 -18
- package/.docs/organized/code-examples/{with-vercel-ai-rsc.md → with-ai-sdk-v5.md} +225 -230
- package/.docs/organized/code-examples/with-ai-sdk.md +13 -13
- package/.docs/organized/code-examples/with-cloud.md +12 -12
- package/.docs/organized/code-examples/with-external-store.md +9 -9
- package/.docs/organized/code-examples/with-ffmpeg.md +19 -19
- package/.docs/organized/code-examples/with-langgraph.md +14 -14
- package/.docs/organized/code-examples/with-openai-assistants.md +12 -12
- package/.docs/organized/code-examples/with-parent-id-grouping.md +1374 -0
- package/.docs/organized/code-examples/with-react-hook-form.md +18 -18
- package/.docs/raw/docs/about-assistantui.mdx +9 -0
- package/.docs/raw/docs/api-reference/context-providers/{TextContentPartProvider.mdx → TextMessagePartProvider.mdx} +3 -3
- package/.docs/raw/docs/api-reference/integrations/react-hook-form.mdx +2 -2
- package/.docs/raw/docs/api-reference/overview.mdx +23 -23
- package/.docs/raw/docs/api-reference/primitives/Error.mdx +5 -3
- package/.docs/raw/docs/api-reference/primitives/Message.mdx +32 -0
- package/.docs/raw/docs/api-reference/primitives/{ContentPart.mdx → MessagePart.mdx} +41 -41
- package/.docs/raw/docs/api-reference/runtimes/MessagePartRuntime.mdx +22 -0
- package/.docs/raw/docs/api-reference/runtimes/ThreadListRuntime.mdx +1 -0
- package/.docs/raw/docs/api-reference/runtimes/ThreadRuntime.mdx +1 -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/concepts/runtime-layer.mdx +7 -7
- package/.docs/raw/docs/copilots/make-assistant-tool-ui.mdx +22 -13
- package/.docs/raw/docs/copilots/make-assistant-tool.mdx +20 -14
- package/.docs/raw/docs/getting-started.mdx +11 -10
- package/.docs/raw/docs/guides/Attachments.mdx +24 -21
- package/.docs/raw/docs/guides/Latex.mdx +81 -0
- package/.docs/raw/docs/guides/ToolUI.mdx +13 -8
- package/.docs/raw/docs/migrations/v0-11.mdx +169 -0
- package/.docs/raw/docs/migrations/v0-7.mdx +8 -8
- package/.docs/raw/docs/migrations/v0-8.mdx +14 -14
- package/.docs/raw/docs/migrations/v0-9.mdx +3 -3
- package/.docs/raw/docs/runtimes/ai-sdk/rsc.mdx +2 -2
- package/.docs/raw/docs/runtimes/ai-sdk/use-assistant-hook.mdx +1 -1
- package/.docs/raw/docs/runtimes/ai-sdk/use-chat-hook.mdx +2 -2
- package/.docs/raw/docs/runtimes/ai-sdk/use-chat-v5.mdx +129 -0
- package/.docs/raw/docs/runtimes/ai-sdk/use-chat.mdx +3 -3
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +5 -5
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +2 -2
- package/.docs/raw/docs/ui/Attachment.mdx +5 -2
- package/.docs/raw/docs/ui/Markdown.mdx +2 -3
- package/.docs/raw/docs/ui/PartGrouping.mdx +540 -0
- package/.docs/raw/docs/ui/ToolFallback.mdx +2 -2
- package/.docs/raw/docs/ui/ToolGroup.mdx +96 -0
- package/package.json +8 -8
- package/.docs/raw/docs/api-reference/runtimes/ContentPartRuntime.mdx +0 -22
|
@@ -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
|
-
}
|
|
16
|
+
// Allow streaming responses up to 30 seconds
|
|
17
|
+
export const maxDuration = 30;
|
|
17
18
|
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
display: ReactNode;
|
|
21
|
-
}
|
|
19
|
+
export async function POST(req: Request) {
|
|
20
|
+
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
}
|
|
40
|
-
|
|
41
|
-
return <div>{content}</div>;
|
|
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,24 @@ 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
|
-
|
|
269
|
-
} from "@assistant-ui/react";
|
|
270
|
-
import { useVercelRSCRuntime } from "@assistant-ui/react-ai-sdk";
|
|
271
|
-
import { useState } from "react";
|
|
202
|
+
import { useChat } from "@ai-sdk/react";
|
|
203
|
+
import { AssistantRuntimeProvider } from "@assistant-ui/react";
|
|
204
|
+
import { useAISDKRuntime } from "@assistant-ui/react-ai-sdk";
|
|
272
205
|
|
|
273
206
|
export default function Home() {
|
|
274
|
-
|
|
275
|
-
<main className="h-dvh">
|
|
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
|
-
};
|
|
207
|
+
const chat = useChat();
|
|
306
208
|
|
|
307
|
-
const runtime =
|
|
209
|
+
const runtime = useAISDKRuntime(chat);
|
|
308
210
|
|
|
309
211
|
return (
|
|
310
212
|
<AssistantRuntimeProvider runtime={runtime}>
|
|
311
|
-
|
|
213
|
+
<div className="h-full">
|
|
214
|
+
<Thread />
|
|
215
|
+
</div>
|
|
312
216
|
</AssistantRuntimeProvider>
|
|
313
217
|
);
|
|
314
|
-
}
|
|
218
|
+
}
|
|
315
219
|
|
|
316
220
|
```
|
|
317
221
|
|
|
@@ -332,10 +236,13 @@ const MyRuntimeProvider = ({ children }: { children: React.ReactNode }) => {
|
|
|
332
236
|
},
|
|
333
237
|
"aliases": {
|
|
334
238
|
"components": "@/components",
|
|
335
|
-
"utils": "@/lib/utils"
|
|
336
|
-
|
|
239
|
+
"utils": "@/lib/utils",
|
|
240
|
+
"ui": "@/components/ui",
|
|
241
|
+
"lib": "@/lib",
|
|
242
|
+
"hooks": "@/hooks"
|
|
243
|
+
},
|
|
244
|
+
"iconLibrary": "lucide"
|
|
337
245
|
}
|
|
338
|
-
|
|
339
246
|
```
|
|
340
247
|
|
|
341
248
|
## components/assistant-ui/markdown-text.tsx
|
|
@@ -346,13 +253,13 @@ const MyRuntimeProvider = ({ children }: { children: React.ReactNode }) => {
|
|
|
346
253
|
import "@assistant-ui/react-markdown/styles/dot.css";
|
|
347
254
|
|
|
348
255
|
import {
|
|
349
|
-
CodeHeaderProps,
|
|
256
|
+
type CodeHeaderProps,
|
|
350
257
|
MarkdownTextPrimitive,
|
|
351
258
|
unstable_memoizeMarkdownComponents as memoizeMarkdownComponents,
|
|
352
259
|
useIsMarkdownCodeBlock,
|
|
353
260
|
} from "@assistant-ui/react-markdown";
|
|
354
261
|
import remarkGfm from "remark-gfm";
|
|
355
|
-
import { FC, memo, useState } from "react";
|
|
262
|
+
import { type FC, memo, useState } from "react";
|
|
356
263
|
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
357
264
|
|
|
358
265
|
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
@@ -378,7 +285,7 @@ const CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {
|
|
|
378
285
|
};
|
|
379
286
|
|
|
380
287
|
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">
|
|
288
|
+
<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
289
|
<span className="lowercase [&>span]:text-xs">{language}</span>
|
|
383
290
|
<TooltipIconButton tooltip="Copy" onClick={onCopy}>
|
|
384
291
|
{!isCopied && <CopyIcon />}
|
|
@@ -540,7 +447,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
540
447
|
pre: ({ className, ...props }) => (
|
|
541
448
|
<pre
|
|
542
449
|
className={cn(
|
|
543
|
-
"overflow-x-auto rounded-b-lg bg-black p-4 text-white",
|
|
450
|
+
"overflow-x-auto !rounded-t-none rounded-b-lg bg-black p-4 text-white",
|
|
544
451
|
className,
|
|
545
452
|
)}
|
|
546
453
|
{...props}
|
|
@@ -570,6 +477,7 @@ import {
|
|
|
570
477
|
ActionBarPrimitive,
|
|
571
478
|
BranchPickerPrimitive,
|
|
572
479
|
ComposerPrimitive,
|
|
480
|
+
ErrorPrimitive,
|
|
573
481
|
MessagePrimitive,
|
|
574
482
|
ThreadPrimitive,
|
|
575
483
|
} from "@assistant-ui/react";
|
|
@@ -589,11 +497,12 @@ import { cn } from "@/lib/utils";
|
|
|
589
497
|
import { Button } from "@/components/ui/button";
|
|
590
498
|
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|
591
499
|
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
500
|
+
import { ToolFallback } from "./tool-fallback";
|
|
592
501
|
|
|
593
502
|
export const Thread: FC = () => {
|
|
594
503
|
return (
|
|
595
504
|
<ThreadPrimitive.Root
|
|
596
|
-
className="bg-background box-border flex h-full flex-col overflow-hidden"
|
|
505
|
+
className="text-foreground bg-background box-border flex h-full flex-col overflow-hidden"
|
|
597
506
|
style={{
|
|
598
507
|
["--thread-max-width" as string]: "42rem",
|
|
599
508
|
}}
|
|
@@ -725,7 +634,7 @@ const UserMessage: FC = () => {
|
|
|
725
634
|
<UserActionBar />
|
|
726
635
|
|
|
727
636
|
<div className="bg-muted text-foreground col-start-2 row-start-2 max-w-[calc(var(--thread-max-width)*0.8)] break-words rounded-3xl px-5 py-2.5">
|
|
728
|
-
<MessagePrimitive.
|
|
637
|
+
<MessagePrimitive.Parts />
|
|
729
638
|
</div>
|
|
730
639
|
|
|
731
640
|
<BranchPicker className="col-span-full col-start-1 row-start-3 -mr-1 justify-end" />
|
|
@@ -770,7 +679,10 @@ const AssistantMessage: FC = () => {
|
|
|
770
679
|
return (
|
|
771
680
|
<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
681
|
<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.
|
|
682
|
+
<MessagePrimitive.Parts
|
|
683
|
+
components={{ Text: MarkdownText, tools: { Fallback: ToolFallback } }}
|
|
684
|
+
/>
|
|
685
|
+
<MessageError />
|
|
774
686
|
</div>
|
|
775
687
|
|
|
776
688
|
<AssistantActionBar />
|
|
@@ -780,6 +692,16 @@ const AssistantMessage: FC = () => {
|
|
|
780
692
|
);
|
|
781
693
|
};
|
|
782
694
|
|
|
695
|
+
const MessageError: FC = () => {
|
|
696
|
+
return (
|
|
697
|
+
<MessagePrimitive.Error>
|
|
698
|
+
<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">
|
|
699
|
+
<ErrorPrimitive.Message className="line-clamp-2" />
|
|
700
|
+
</ErrorPrimitive.Root>
|
|
701
|
+
</MessagePrimitive.Error>
|
|
702
|
+
);
|
|
703
|
+
};
|
|
704
|
+
|
|
783
705
|
const AssistantActionBar: FC = () => {
|
|
784
706
|
return (
|
|
785
707
|
<ActionBarPrimitive.Root
|
|
@@ -853,6 +775,54 @@ const CircleStopIcon = () => {
|
|
|
853
775
|
|
|
854
776
|
```
|
|
855
777
|
|
|
778
|
+
## components/assistant-ui/tool-fallback.tsx
|
|
779
|
+
|
|
780
|
+
```tsx
|
|
781
|
+
import { ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
782
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
783
|
+
import { useState } from "react";
|
|
784
|
+
import { Button } from "../ui/button";
|
|
785
|
+
|
|
786
|
+
export const ToolFallback: ToolCallMessagePartComponent = ({
|
|
787
|
+
toolName,
|
|
788
|
+
argsText,
|
|
789
|
+
result,
|
|
790
|
+
}) => {
|
|
791
|
+
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
792
|
+
return (
|
|
793
|
+
<div className="mb-4 flex w-full flex-col gap-3 rounded-lg border py-3">
|
|
794
|
+
<div className="flex items-center gap-2 px-4">
|
|
795
|
+
<CheckIcon className="size-4" />
|
|
796
|
+
<p className="flex-grow">
|
|
797
|
+
Used tool: <b>{toolName}</b>
|
|
798
|
+
</p>
|
|
799
|
+
<Button onClick={() => setIsCollapsed(!isCollapsed)}>
|
|
800
|
+
{isCollapsed ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
|
801
|
+
</Button>
|
|
802
|
+
</div>
|
|
803
|
+
{!isCollapsed && (
|
|
804
|
+
<div className="flex flex-col gap-2 border-t pt-2">
|
|
805
|
+
<div className="px-4">
|
|
806
|
+
<pre className="whitespace-pre-wrap">{argsText}</pre>
|
|
807
|
+
</div>
|
|
808
|
+
{result !== undefined && (
|
|
809
|
+
<div className="border-t border-dashed px-4 pt-2">
|
|
810
|
+
<p className="font-semibold">Result:</p>
|
|
811
|
+
<pre className="whitespace-pre-wrap">
|
|
812
|
+
{typeof result === "string"
|
|
813
|
+
? result
|
|
814
|
+
: JSON.stringify(result, null, 2)}
|
|
815
|
+
</pre>
|
|
816
|
+
</div>
|
|
817
|
+
)}
|
|
818
|
+
</div>
|
|
819
|
+
)}
|
|
820
|
+
</div>
|
|
821
|
+
);
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
```
|
|
825
|
+
|
|
856
826
|
## components/assistant-ui/tooltip-icon-button.tsx
|
|
857
827
|
|
|
858
828
|
```tsx
|
|
@@ -1016,7 +986,7 @@ function TooltipContent({
|
|
|
1016
986
|
data-slot="tooltip-content"
|
|
1017
987
|
sideOffset={sideOffset}
|
|
1018
988
|
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
|
|
989
|
+
"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
990
|
className,
|
|
1021
991
|
)}
|
|
1022
992
|
{...props}
|
|
@@ -1032,17 +1002,10 @@ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
|
1032
1002
|
|
|
1033
1003
|
```
|
|
1034
1004
|
|
|
1035
|
-
## eslint.config.ts
|
|
1036
|
-
|
|
1037
|
-
```typescript
|
|
1038
|
-
export { default } from "@assistant-ui/x-buildutils/eslint";
|
|
1039
|
-
|
|
1040
|
-
```
|
|
1041
|
-
|
|
1042
1005
|
## lib/utils.ts
|
|
1043
1006
|
|
|
1044
1007
|
```typescript
|
|
1045
|
-
import { type ClassValue
|
|
1008
|
+
import { clsx, type ClassValue } from "clsx";
|
|
1046
1009
|
import { twMerge } from "tailwind-merge";
|
|
1047
1010
|
|
|
1048
1011
|
export function cn(...inputs: ClassValue[]) {
|
|
@@ -1051,24 +1014,12 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1051
1014
|
|
|
1052
1015
|
```
|
|
1053
1016
|
|
|
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.
|
|
1062
|
-
|
|
1063
|
-
```
|
|
1064
|
-
|
|
1065
|
-
## next.config.ts
|
|
1066
|
-
|
|
1067
|
-
```typescript
|
|
1068
|
-
import type { NextConfig } from "next";
|
|
1017
|
+
## next.config.js
|
|
1069
1018
|
|
|
1070
|
-
|
|
1071
|
-
|
|
1019
|
+
```javascript
|
|
1020
|
+
/** @type {import('next').NextConfig} */
|
|
1021
|
+
const nextConfig = {
|
|
1022
|
+
transpilePackages: ["@assistant-ui/react", "@assistant-ui/react-ai-sdk"],
|
|
1072
1023
|
};
|
|
1073
1024
|
|
|
1074
1025
|
export default nextConfig;
|
|
@@ -1079,51 +1030,95 @@ export default nextConfig;
|
|
|
1079
1030
|
|
|
1080
1031
|
```json
|
|
1081
1032
|
{
|
|
1082
|
-
"name": "with-
|
|
1083
|
-
"version": "0.1.0",
|
|
1033
|
+
"name": "example-with-ai-sdk-v5",
|
|
1084
1034
|
"private": true,
|
|
1085
|
-
"
|
|
1086
|
-
|
|
1087
|
-
"build": "next build",
|
|
1088
|
-
"start": "next start",
|
|
1089
|
-
"lint": "next lint"
|
|
1090
|
-
},
|
|
1035
|
+
"version": "0.0.0",
|
|
1036
|
+
"type": "module",
|
|
1091
1037
|
"dependencies": {
|
|
1092
|
-
"@ai-sdk/openai": "^
|
|
1093
|
-
"@
|
|
1038
|
+
"@ai-sdk/openai": "^2.0.0",
|
|
1039
|
+
"@ai-sdk/react": "^2.0.0",
|
|
1040
|
+
"@assistant-ui/react": "workspace:^",
|
|
1094
1041
|
"@assistant-ui/react-ai-sdk": "workspace:*",
|
|
1095
|
-
"@assistant-ui/react-markdown": "workspace
|
|
1096
|
-
"@radix-ui/react-icons": "^1.3.2",
|
|
1042
|
+
"@assistant-ui/react-markdown": "workspace:^",
|
|
1097
1043
|
"@radix-ui/react-slot": "^1.2.3",
|
|
1098
1044
|
"@radix-ui/react-tooltip": "^1.2.7",
|
|
1099
|
-
"
|
|
1045
|
+
"@tailwindcss/postcss": "^4.1.11",
|
|
1046
|
+
"ai": "^5.0.0",
|
|
1100
1047
|
"class-variance-authority": "^0.7.1",
|
|
1101
1048
|
"clsx": "^2.1.1",
|
|
1102
|
-
"lucide-react": "^0.
|
|
1103
|
-
"
|
|
1104
|
-
"
|
|
1105
|
-
"react": "19.1.
|
|
1106
|
-
"react-dom": "19.1.
|
|
1049
|
+
"lucide-react": "^0.535.0",
|
|
1050
|
+
"next": "15.4.5",
|
|
1051
|
+
"postcss": "^8.5.6",
|
|
1052
|
+
"react": "19.1.1",
|
|
1053
|
+
"react-dom": "19.1.1",
|
|
1107
1054
|
"remark-gfm": "^4.0.1",
|
|
1108
1055
|
"tailwind-merge": "^3.3.1",
|
|
1109
|
-
"
|
|
1110
|
-
"zod": "^
|
|
1056
|
+
"tailwindcss": "^4.1.11",
|
|
1057
|
+
"zod": "^4.0.14"
|
|
1111
1058
|
},
|
|
1112
1059
|
"devDependencies": {
|
|
1113
1060
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
1114
|
-
"@types/node": "^24",
|
|
1115
|
-
"@types/react": "^19",
|
|
1116
|
-
"@types/react-dom": "^19",
|
|
1061
|
+
"@types/node": "^24.1.0",
|
|
1062
|
+
"@types/react": "^19.1.9",
|
|
1063
|
+
"@types/react-dom": "^19.1.7",
|
|
1117
1064
|
"eslint": "^9",
|
|
1118
|
-
"eslint-config-next": "15.
|
|
1119
|
-
"
|
|
1120
|
-
"
|
|
1121
|
-
|
|
1065
|
+
"eslint-config-next": "15.4.5",
|
|
1066
|
+
"tw-animate-css": "^1.3.6",
|
|
1067
|
+
"typescript": "^5.9.2"
|
|
1068
|
+
},
|
|
1069
|
+
"scripts": {
|
|
1070
|
+
"dev": "next dev",
|
|
1071
|
+
"build": "next build",
|
|
1072
|
+
"start": "next start",
|
|
1073
|
+
"lint": "next lint"
|
|
1122
1074
|
}
|
|
1123
1075
|
}
|
|
1124
1076
|
|
|
1125
1077
|
```
|
|
1126
1078
|
|
|
1079
|
+
## README.md
|
|
1080
|
+
|
|
1081
|
+
```markdown
|
|
1082
|
+
# AI SDK v5 Example
|
|
1083
|
+
|
|
1084
|
+
This example demonstrates how to use `@assistant-ui/react-ai-sdk-v5` with the Vercel AI SDK v5.
|
|
1085
|
+
|
|
1086
|
+
## Getting Started
|
|
1087
|
+
|
|
1088
|
+
1. Install dependencies:
|
|
1089
|
+
```bash
|
|
1090
|
+
npm install
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
2. Set up your environment variables:
|
|
1094
|
+
```bash
|
|
1095
|
+
cp .env.example .env.local
|
|
1096
|
+
```
|
|
1097
|
+
|
|
1098
|
+
Add your Anthropic API key to `.env.local`:
|
|
1099
|
+
```
|
|
1100
|
+
ANTHROPIC_API_KEY=your-api-key-here
|
|
1101
|
+
```
|
|
1102
|
+
|
|
1103
|
+
3. Run the development server:
|
|
1104
|
+
```bash
|
|
1105
|
+
npm run dev
|
|
1106
|
+
```
|
|
1107
|
+
|
|
1108
|
+
Open [http://localhost:3000](http://localhost:3000) to see the result.
|
|
1109
|
+
|
|
1110
|
+
## Key Features
|
|
1111
|
+
|
|
1112
|
+
- Uses the new AI SDK v5 with `@ai-sdk/react` and `@ai-sdk/anthropic`
|
|
1113
|
+
- Integrates with `@assistant-ui/react` using the v5-compatible runtime
|
|
1114
|
+
- No RSC support (client-side only)
|
|
1115
|
+
- Uses the `useChat` hook from AI SDK v5
|
|
1116
|
+
|
|
1117
|
+
## API Route
|
|
1118
|
+
|
|
1119
|
+
The API route at `/api/chat` uses the new `streamText` function from AI SDK v5 to handle chat completions.
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1127
1122
|
## tsconfig.json
|
|
1128
1123
|
|
|
1129
1124
|
```json
|