e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
117 lines
3.5 KiB
Plaintext
117 lines
3.5 KiB
Plaintext
---
|
|
title: AI SDK Chat Persistence
|
|
description: Vercel AI SDK chat with thread persistence — open-source React example combining the AI SDK and assistant-ui for streaming, thread management, and message history.
|
|
---
|
|
|
|
import { Base } from "@/components/examples/base";
|
|
|
|
<div className="not-prose h-[600px]">
|
|
<Base />
|
|
</div>
|
|
|
|
## Overview
|
|
|
|
This example demonstrates integrating assistant-ui with the Vercel AI SDK for building production-ready chat interfaces. It showcases a complete chat application with thread management, message persistence, and a collapsible sidebar for conversation history.
|
|
|
|
## Features
|
|
|
|
- **AI SDK Integration**: Seamless connection with Vercel's `ai` package
|
|
- **Thread Management**: Create, switch, and delete conversation threads
|
|
- **Collapsible Sidebar**: Toggle sidebar visibility for focused chat
|
|
- **Model Picker**: Switch between different AI models
|
|
- **Responsive Design**: Mobile-friendly with sheet-based navigation
|
|
- **Real-time Streaming**: Live message streaming with loading states
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
npm install @assistant-ui/react @assistant-ui/react-ai-sdk ai@^6 @ai-sdk/react@^3 @ai-sdk/openai
|
|
```
|
|
|
|
## Code
|
|
|
|
### Client Component
|
|
|
|
```tsx
|
|
"use client";
|
|
|
|
import { AssistantRuntimeProvider } from "@assistant-ui/react";
|
|
import { Thread } from "@/components/assistant-ui/thread";
|
|
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
|
|
export default function Chat() {
|
|
const runtime = useChatRuntime();
|
|
|
|
return (
|
|
<AssistantRuntimeProvider runtime={runtime}>
|
|
<div className="flex h-full">
|
|
<Sidebar />
|
|
<main className="flex-1">
|
|
<Thread />
|
|
</main>
|
|
</div>
|
|
</AssistantRuntimeProvider>
|
|
);
|
|
}
|
|
```
|
|
|
|
### API Route
|
|
|
|
```ts
|
|
// app/api/chat/route.ts
|
|
import { openai } from "@ai-sdk/openai";
|
|
import { streamText, convertToModelMessages } from "ai";
|
|
import type { UIMessage } from "ai";
|
|
|
|
export async function POST(req: Request) {
|
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
|
|
const result = streamText({
|
|
model: openai("gpt-5.4-nano"),
|
|
messages: await convertToModelMessages(messages),
|
|
// Optional: Add system prompt
|
|
system: "You are a helpful assistant.",
|
|
});
|
|
|
|
return result.toUIMessageStreamResponse();
|
|
}
|
|
```
|
|
|
|
### Key Integration Points
|
|
|
|
| Hook/Function | Purpose |
|
|
|---------------|---------|
|
|
| `useChatRuntime` | Connects AI SDK to assistant-ui |
|
|
| `streamText` | Server-side streaming response generation |
|
|
| `toUIMessageStreamResponse` | Converts stream to Response object |
|
|
|
|
### Adding Persistence
|
|
|
|
<Callout type="info">
|
|
`useChatRuntime()` on its own does not persist threads across reloads. The snippet below is a minimal server-side save sketch. For full thread persistence (history reload, branching) use [Assistant Cloud](/docs/cloud) or the [custom persistence adapter](/docs/integrations/persistence/custom-adapter).
|
|
</Callout>
|
|
|
|
To persist conversations, add a database and modify the API route. `useChatRuntime` sends the current thread id as `id` in the request body, so you can read it alongside `messages`:
|
|
|
|
```ts
|
|
// In your POST /api/chat handler:
|
|
const { id: threadId, messages } = await req.json();
|
|
|
|
// Save the latest user message
|
|
const last = messages.at(-1);
|
|
if (last) {
|
|
await db.messages.create({
|
|
threadId,
|
|
role: last.role,
|
|
parts: last.parts,
|
|
});
|
|
}
|
|
|
|
// Load messages when opening a thread (e.g., from a ThreadHistoryAdapter):
|
|
const savedMessages = await db.messages.findMany({ threadId });
|
|
```
|
|
|
|
## Source
|
|
|
|
<SourceLink href="https://github.com/assistant-ui/assistant-ui/blob/main/apps/docs/components/examples/base.tsx" />
|