Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/(chat)/actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use server"

import { generateText, Message } from "ai"
import { generateText, UIMessage } from "ai"
import { cookies } from "next/headers"

import {
Expand All @@ -19,7 +19,7 @@ export async function saveChatModelAsCookie(model: string) {
export async function generateTitleFromUserMessage({
message,
}: {
message: Message
message: UIMessage
}) {
const { text: title } = await generateText({
model: myProvider.languageModel("title-model"),
Expand Down
162 changes: 81 additions & 81 deletions app/(chat)/api/chat/route.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
type Message,
createDataStreamResponse,
smoothStream,
streamText,
} from "ai"
import { type UIMessage, smoothStream, streamText, stepCountIs } from "ai"

import { getSession } from "@/app/(auth)/server-auth"
import { myProvider } from "@/lib/ai/models"
Expand Down Expand Up @@ -34,7 +29,7 @@ export async function POST(request: Request) {
// Parse request body
let requestData: {
id: string
messages: Array<Message>
messages: Array<UIMessage>
selectedChatModel: string
}
try {
Expand Down Expand Up @@ -79,10 +74,18 @@ export async function POST(request: Request) {
return new Response("Failed to create or retrieve chat", { status: 500 })
}

// Save user message
// Save user message to database (convert UIMessage to DB format)
try {
await saveMessages({
messages: [{ ...userMessage, createdAt: new Date(), chatId: id }],
messages: [
{
id: userMessage.id,
role: userMessage.role as any,
content: userMessage.parts,
createdAt: new Date(),
chatId: id,
},
],
})
} catch (error) {
console.error("Failed to save user message:", error)
Expand All @@ -91,85 +94,82 @@ export async function POST(request: Request) {

console.log("selectedChatModel", selectedChatModel)

return createDataStreamResponse({
execute: (dataStream) => {
try {
const result = streamText({
model: myProvider.languageModel(selectedChatModel),
system: systemPrompt({
selectedChatModel,
textAttachmentStrings: getTextAttachmentStrings(messages),
}),
messages: removeTextAttachments(messages),
maxSteps: 5,
temperature: 1, // GPT-5 only supports temperature value of 1
experimental_activeTools: selectedChatModel.includes("reasoning")
? []
: ["createDocument", "updateDocument", "requestSuggestions"],
experimental_transform: smoothStream({ chunking: "word" }),
experimental_generateMessageId: generateUUID,
tools: {
createDocument: createDocument({
session,
dataStream,
selectedModelId: selectedChatModel,
}),
updateDocument: updateDocument({
session,
dataStream,
selectedModelId: selectedChatModel,
}),
requestSuggestions: requestSuggestions({
session,
dataStream,
}),
},
onFinish: async ({ response, reasoning }) => {
if (session.user?.id) {
try {
const sanitizedResponseMessages = sanitizeResponseMessages({
messages: response.messages,
reasoning,
})
// Convert UIMessages to ModelMessage format for the AI SDK
const messagesForAI = messages.map((msg) => ({
role: msg.role as "user" | "assistant" | "system",
content: msg.parts as any,
}))

try {
const result = streamText({
model: myProvider.languageModel(selectedChatModel),

system: systemPrompt({
selectedChatModel,
textAttachmentStrings: getTextAttachmentStrings(messages),
}),

messages: messagesForAI,

// GPT-5 only supports temperature value of 1
temperature: 1,

// Note: Tools integration needs update for v5 dataStream API
// For now, disabling tools to get basic streaming working
// tools: {
// createDocument: createDocument({
// session,
// selectedModelId: selectedChatModel,
// }),
// updateDocument: updateDocument({
// session,
// selectedModelId: selectedChatModel,
// }),
// requestSuggestions: requestSuggestions({
// session,
// }),
// },

onFinish: async ({ response }) => {
if (session.user?.id) {
try {
// In v5, save the assistant response messages
for (const message of response.messages) {
if (message.role === "assistant") {
await saveMessages({
messages: sanitizedResponseMessages.map((message) => {
return {
id: message.id,
messages: [
{
id: generateUUID(),
chatId: id,
role: message.role,
content: message.content,
role: "assistant",
content: message.content as any,
createdAt: new Date(),
}
}),
},
],
})
} catch (error) {
console.error("Failed to save assistant messages:", error)
}
}
},
experimental_telemetry: {
isEnabled: true,
functionId: "stream-text",
},
})

result.mergeIntoDataStream(dataStream, {
sendReasoning: true,
})
} catch (error) {
console.error("Error in streamText execution:", error)
dataStream.writeData({
type: "error",
content: `Error: ${error instanceof Error ? error.message : String(error)}`,
})
}
},
onError: (error) => {
console.error("DataStream error:", error)
return `Error: ${error instanceof Error ? error.message : "An unknown error occurred"}`
},
})
} catch (error) {
console.error("Failed to save assistant messages:", error)
}
}
},

experimental_telemetry: {
isEnabled: true,
functionId: "stream-text",
},
})

// In v5, convert the stream result to a proper response
return result.toTextStreamResponse()
} catch (error) {
console.error("Error in streamText execution:", error)
return new Response(
`Error: ${error instanceof Error ? error.message : String(error)}`,
{ status: 500 },
)
}
} catch (error) {
console.error("Unexpected error in POST handler:", error)
return new Response(
Expand Down
2 changes: 1 addition & 1 deletion app/(chat)/api/files/upload/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { put } from "@vercel/blob"
import { NextResponse } from "next/server"
import { z } from "zod"
import { z } from "zod/v3"

import { getSession } from "@/app/(auth)/server-auth"

Expand Down
26 changes: 19 additions & 7 deletions blocks/code/server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { z } from "zod"
import { z } from "zod/v3"
import { streamObject } from "ai"
import { myProvider } from "@/lib/ai/models"
import { codePrompt, updateDocumentPrompt } from "@/lib/ai/prompts/prompts"
Expand Down Expand Up @@ -27,9 +27,15 @@ export const codeDocumentHandler = createDocumentHandler<"code">({
const { code } = object

if (code) {
dataStream.writeData({
type: "code-delta",
content: code ?? "",
dataStream.write({
type: "data",

value: [
{
type: "code-delta",
content: code ?? "",
},
],
})

draftContent = code
Expand Down Expand Up @@ -65,9 +71,15 @@ export const codeDocumentHandler = createDocumentHandler<"code">({
const { code } = object

if (code) {
dataStream.writeData({
type: "code-delta",
content: code ?? "",
dataStream.write({
type: "data",

value: [
{
type: "code-delta",
content: code ?? "",
},
],
})

draftContent = code
Expand Down
24 changes: 18 additions & 6 deletions blocks/image/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ export const imageDocumentHandler = createDocumentHandler<"image">({

draftContent = image.base64

dataStream.writeData({
type: "image-delta",
content: image.base64,
dataStream.write({
type: "data",

value: [
{
type: "image-delta",
content: image.base64,
},
],
})

return draftContent
Expand All @@ -33,9 +39,15 @@ export const imageDocumentHandler = createDocumentHandler<"image">({

draftContent = image.base64

dataStream.writeData({
type: "image-delta",
content: image.base64,
dataStream.write({
type: "data",

value: [
{
type: "image-delta",
content: image.base64,
},
],
})

return draftContent
Expand Down
38 changes: 28 additions & 10 deletions blocks/sheet/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { myProvider } from "@/lib/ai/models"
import { updateDocumentPrompt } from "@/lib/ai/prompts/prompts"
import { createDocumentHandler } from "@/lib/blocks/server"
import { streamObject } from "ai"
import { z } from "zod"
import { z } from "zod/v3"

/**
* @deprecated
Expand All @@ -29,19 +29,31 @@ export const sheetDocumentHandler = createDocumentHandler<"sheet">({
const { csv } = object

if (csv) {
dataStream.writeData({
type: "sheet-delta",
content: csv,
dataStream.write({
type: "data",

value: [
{
type: "sheet-delta",
content: csv,
},
],
})

draftContent = csv
}
}
}

dataStream.writeData({
type: "sheet-delta",
content: draftContent,
dataStream.write({
type: "data",

value: [
{
type: "sheet-delta",
content: draftContent,
},
],
})

return draftContent
Expand All @@ -66,9 +78,15 @@ export const sheetDocumentHandler = createDocumentHandler<"sheet">({
const { csv } = object

if (csv) {
dataStream.writeData({
type: "sheet-delta",
content: csv,
dataStream.write({
type: "data",

value: [
{
type: "sheet-delta",
content: csv,
},
],
})

draftContent = csv
Expand Down
Loading