refactor: replace message.content with message.parts (#868)

This commit is contained in:
Jeremy 2025-03-16 18:42:29 -07:00 committed by GitHub
parent 553a3d825a
commit 47a630fd53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 1311 additions and 311 deletions

View file

@ -1,5 +1,6 @@
import {
type Message,
UIMessage,
appendResponseMessages,
createDataStreamResponse,
smoothStream,
streamText,
@ -15,7 +16,7 @@ import {
import {
generateUUID,
getMostRecentUserMessage,
sanitizeResponseMessages,
getTrailingMessageId,
} from '@/lib/utils';
import { generateTitleFromUserMessage } from '../../actions';
import { createDocument } from '@/lib/ai/tools/create-document';
@ -23,7 +24,6 @@ import { updateDocument } from '@/lib/ai/tools/update-document';
import { requestSuggestions } from '@/lib/ai/tools/request-suggestions';
import { getWeather } from '@/lib/ai/tools/get-weather';
import { isProductionEnvironment } from '@/lib/constants';
import { NextResponse } from 'next/server';
import { myProvider } from '@/lib/ai/providers';
export const maxDuration = 60;
@ -36,7 +36,7 @@ export async function POST(request: Request) {
selectedChatModel,
}: {
id: string;
messages: Array<Message>;
messages: Array<UIMessage>;
selectedChatModel: string;
} = await request.json();
@ -67,7 +67,16 @@ export async function POST(request: Request) {
}
await saveMessages({
messages: [{ ...userMessage, createdAt: new Date(), chatId: id }],
messages: [
{
chatId: id,
id: userMessage.id,
role: 'user',
parts: userMessage.parts,
attachments: userMessage.experimental_attachments ?? [],
createdAt: new Date(),
},
],
});
return createDataStreamResponse({
@ -97,24 +106,36 @@ export async function POST(request: Request) {
dataStream,
}),
},
onFinish: async ({ response, reasoning }) => {
onFinish: async ({ response }) => {
if (session.user?.id) {
try {
const sanitizedResponseMessages = sanitizeResponseMessages({
messages: response.messages,
reasoning,
const assistantId = getTrailingMessageId({
messages: response.messages.filter(
(message) => message.role === 'assistant',
),
});
if (!assistantId) {
throw new Error('No assistant message found!');
}
const [, assistantMessage] = appendResponseMessages({
messages: [userMessage],
responseMessages: response.messages,
});
await saveMessages({
messages: sanitizedResponseMessages.map((message) => {
return {
id: message.id,
messages: [
{
id: assistantId,
chatId: id,
role: message.role,
content: message.content,
role: assistantMessage.role,
parts: assistantMessage.parts,
attachments:
assistantMessage.experimental_attachments ?? [],
createdAt: new Date(),
};
}),
},
],
});
} catch (error) {
console.error('Failed to save chat');
@ -138,7 +159,9 @@ export async function POST(request: Request) {
},
});
} catch (error) {
return NextResponse.json({ error }, { status: 400 });
return new Response('An error occurred while processing your request!', {
status: 404,
});
}
}
@ -167,7 +190,7 @@ export async function DELETE(request: Request) {
return new Response('Chat deleted', { status: 200 });
} catch (error) {
return new Response('An error occurred while processing your request', {
return new Response('An error occurred while processing your request!', {
status: 500,
});
}

View file

@ -4,9 +4,10 @@ import { notFound } from 'next/navigation';
import { auth } from '@/app/(auth)/auth';
import { Chat } from '@/components/chat';
import { getChatById, getMessagesByChatId } from '@/lib/db/queries';
import { convertToUIMessages } from '@/lib/utils';
import { DataStreamHandler } from '@/components/data-stream-handler';
import { DEFAULT_CHAT_MODEL } from '@/lib/ai/models';
import { DBMessage } from '@/lib/db/schema';
import { Attachment, UIMessage } from 'ai';
export default async function Page(props: { params: Promise<{ id: string }> }) {
const params = await props.params;
@ -33,6 +34,19 @@ export default async function Page(props: { params: Promise<{ id: string }> }) {
id,
});
function convertToUIMessages(messages: Array<DBMessage>): Array<UIMessage> {
return messages.map((message) => ({
id: message.id,
parts: message.parts as UIMessage['parts'],
role: message.role as UIMessage['role'],
// Note: content will soon be deprecated in @ai-sdk/react
content: '',
createdAt: message.createdAt,
experimental_attachments:
(message.attachments as Array<Attachment>) ?? [],
}));
}
const cookieStore = await cookies();
const chatModelFromCookie = cookieStore.get('chat-model');