- Chat SDK is a free, open-source template built with Next.js and the AI SDK that helps you quickly build powerful chatbot applications.
+ OpenChat is a free, open-source template built with Next.js and the AI SDK that helps you quickly build powerful chatbot applications.
- Read Docs ·
+ Read Docs ·
Features ·
Model Providers ·
Deploy Your Own ·
@@ -48,13 +48,13 @@ With the [AI SDK](https://ai-sdk.dev/docs/introduction), you can also switch to
## Deploy Your Own
-You can deploy your own version of the Next.js AI Chatbot to Vercel with one click:
+You can deploy your own version of OpenChat to Vercel with one click:
-[](https://vercel.com/templates/next.js/nextjs-ai-chatbot)
+[](https://vercel.com/templates/next.js/openchat)
## Running locally
-You will need to use the environment variables [defined in `.env.example`](.env.example) to run Next.js AI Chatbot. It's recommended you use [Vercel Environment Variables](https://vercel.com/docs/projects/environment-variables) for this, but a `.env` file is all that is necessary.
+You will need to use the environment variables [defined in `.env.example`](.env.example) to run OpenChat. It's recommended you use [Vercel Environment Variables](https://vercel.com/docs/projects/environment-variables) for this, but a `.env` file is all that is necessary.
> Note: You should not commit your `.env` file or it will expose secrets that will allow others to control access to your various AI and authentication provider accounts.
diff --git a/components/chat-header.tsx b/components/chat-header.tsx
index a330805b5e..528d623111 100644
--- a/components/chat-header.tsx
+++ b/components/chat-header.tsx
@@ -55,7 +55,7 @@ function PureChatHeader({
className="order-3 hidden bg-zinc-900 px-2 text-zinc-50 hover:bg-zinc-800 md:ml-auto md:flex md:h-fit dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-200"
>
diff --git a/instrumentation.ts b/instrumentation.ts
index 4b3bdee4b2..632a2f7454 100644
--- a/instrumentation.ts
+++ b/instrumentation.ts
@@ -1,5 +1,5 @@
import { registerOTel } from "@vercel/otel";
export function register() {
- registerOTel({ serviceName: "ai-chatbot" });
+ registerOTel({ serviceName: "openchat" });
}
diff --git a/lib/db/schema.ts b/lib/db/schema.ts
index da060e271b..803e652689 100644
--- a/lib/db/schema.ts
+++ b/lib/db/schema.ts
@@ -34,7 +34,7 @@ export const chat = pgTable("Chat", {
export type Chat = InferSelectModel;
// DEPRECATED: The following schema is deprecated and will be removed in the future.
-// Read the migration guide at https://chat-sdk.dev/docs/migration-guides/message-parts
+// Read the migration guide at https://openchat.dev/docs/migration-guides/message-parts
export const messageDeprecated = pgTable("Message", {
id: uuid("id").primaryKey().notNull().defaultRandom(),
chatId: uuid("chatId")
@@ -61,7 +61,7 @@ export const message = pgTable("Message_v2", {
export type DBMessage = InferSelectModel;
// DEPRECATED: The following schema is deprecated and will be removed in the future.
-// Read the migration guide at https://chat-sdk.dev/docs/migration-guides/message-parts
+// Read the migration guide at https://openchat.dev/docs/migration-guides/message-parts
export const voteDeprecated = pgTable(
"Vote",
{
diff --git a/package.json b/package.json
index 5ca72b5f17..77050da857 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "ai-chatbot",
+ "name": "openchat",
"version": "3.1.0",
"private": true,
"scripts": {
From e1562aefb52bb033209bea856937bc9f923a4e6f Mon Sep 17 00:00:00 2001
From: dancer <144584931+dancer@users.noreply.github.com>
Date: Fri, 20 Feb 2026 20:16:46 +0000
Subject: [PATCH 2/9] rename chatsdkerror to openchaterror
---
app/(chat)/api/chat/route.ts | 22 ++++++------
app/(chat)/api/document/route.ts | 24 ++++++-------
app/(chat)/api/history/route.ts | 8 ++---
app/(chat)/api/suggestions/route.ts | 8 ++---
app/(chat)/api/vote/route.ts | 18 +++++-----
components/chat.tsx | 4 +--
lib/db/queries.ts | 56 ++++++++++++++---------------
lib/errors.ts | 2 +-
lib/utils.ts | 8 ++---
9 files changed, 75 insertions(+), 75 deletions(-)
diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts
index 36458196dc..a659bdf3fd 100644
--- a/app/(chat)/api/chat/route.ts
+++ b/app/(chat)/api/chat/route.ts
@@ -30,7 +30,7 @@ import {
updateMessage,
} from "@/lib/db/queries";
import type { DBMessage } from "@/lib/db/schema";
-import { ChatSDKError } from "@/lib/errors";
+import { OpenChatError } from "@/lib/errors";
import type { ChatMessage } from "@/lib/types";
import { convertToUIMessages, generateUUID } from "@/lib/utils";
import { generateTitleFromUserMessage } from "../../actions";
@@ -55,7 +55,7 @@ export async function POST(request: Request) {
const json = await request.json();
requestBody = postRequestBodySchema.parse(json);
} catch (_) {
- return new ChatSDKError("bad_request:api").toResponse();
+ return new OpenChatError("bad_request:api").toResponse();
}
try {
@@ -65,7 +65,7 @@ export async function POST(request: Request) {
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("unauthorized:chat").toResponse();
+ return new OpenChatError("unauthorized:chat").toResponse();
}
const userType: UserType = session.user.type;
@@ -76,7 +76,7 @@ export async function POST(request: Request) {
});
if (messageCount > entitlementsByUserType[userType].maxMessagesPerDay) {
- return new ChatSDKError("rate_limit:chat").toResponse();
+ return new OpenChatError("rate_limit:chat").toResponse();
}
const isToolApprovalFlow = Boolean(messages);
@@ -87,7 +87,7 @@ export async function POST(request: Request) {
if (chat) {
if (chat.userId !== session.user.id) {
- return new ChatSDKError("forbidden:chat").toResponse();
+ return new OpenChatError("forbidden:chat").toResponse();
}
if (!isToolApprovalFlow) {
messagesFromDb = await getMessagesByChatId({ id });
@@ -244,7 +244,7 @@ export async function POST(request: Request) {
} catch (error) {
const vercelId = request.headers.get("x-vercel-id");
- if (error instanceof ChatSDKError) {
+ if (error instanceof OpenChatError) {
return error.toResponse();
}
@@ -254,11 +254,11 @@ export async function POST(request: Request) {
"AI Gateway requires a valid credit card on file to service requests"
)
) {
- return new ChatSDKError("bad_request:activate_gateway").toResponse();
+ return new OpenChatError("bad_request:activate_gateway").toResponse();
}
console.error("Unhandled error in chat API:", error, { vercelId });
- return new ChatSDKError("offline:chat").toResponse();
+ return new OpenChatError("offline:chat").toResponse();
}
}
@@ -267,19 +267,19 @@ export async function DELETE(request: Request) {
const id = searchParams.get("id");
if (!id) {
- return new ChatSDKError("bad_request:api").toResponse();
+ return new OpenChatError("bad_request:api").toResponse();
}
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("unauthorized:chat").toResponse();
+ return new OpenChatError("unauthorized:chat").toResponse();
}
const chat = await getChatById({ id });
if (chat?.userId !== session.user.id) {
- return new ChatSDKError("forbidden:chat").toResponse();
+ return new OpenChatError("forbidden:chat").toResponse();
}
const deletedChat = await deleteChatById({ id });
diff --git a/app/(chat)/api/document/route.ts b/app/(chat)/api/document/route.ts
index 0ea78ff553..2caa241f6e 100644
--- a/app/(chat)/api/document/route.ts
+++ b/app/(chat)/api/document/route.ts
@@ -5,14 +5,14 @@ import {
getDocumentsById,
saveDocument,
} from "@/lib/db/queries";
-import { ChatSDKError } from "@/lib/errors";
+import { OpenChatError } from "@/lib/errors";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get("id");
if (!id) {
- return new ChatSDKError(
+ return new OpenChatError(
"bad_request:api",
"Parameter id is missing"
).toResponse();
@@ -21,7 +21,7 @@ export async function GET(request: Request) {
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("unauthorized:document").toResponse();
+ return new OpenChatError("unauthorized:document").toResponse();
}
const documents = await getDocumentsById({ id });
@@ -29,11 +29,11 @@ export async function GET(request: Request) {
const [document] = documents;
if (!document) {
- return new ChatSDKError("not_found:document").toResponse();
+ return new OpenChatError("not_found:document").toResponse();
}
if (document.userId !== session.user.id) {
- return new ChatSDKError("forbidden:document").toResponse();
+ return new OpenChatError("forbidden:document").toResponse();
}
return Response.json(documents, { status: 200 });
@@ -44,7 +44,7 @@ export async function POST(request: Request) {
const id = searchParams.get("id");
if (!id) {
- return new ChatSDKError(
+ return new OpenChatError(
"bad_request:api",
"Parameter id is required."
).toResponse();
@@ -53,7 +53,7 @@ export async function POST(request: Request) {
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("not_found:document").toResponse();
+ return new OpenChatError("not_found:document").toResponse();
}
const {
@@ -69,7 +69,7 @@ export async function POST(request: Request) {
const [doc] = documents;
if (doc.userId !== session.user.id) {
- return new ChatSDKError("forbidden:document").toResponse();
+ return new OpenChatError("forbidden:document").toResponse();
}
}
@@ -90,14 +90,14 @@ export async function DELETE(request: Request) {
const timestamp = searchParams.get("timestamp");
if (!id) {
- return new ChatSDKError(
+ return new OpenChatError(
"bad_request:api",
"Parameter id is required."
).toResponse();
}
if (!timestamp) {
- return new ChatSDKError(
+ return new OpenChatError(
"bad_request:api",
"Parameter timestamp is required."
).toResponse();
@@ -106,7 +106,7 @@ export async function DELETE(request: Request) {
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("unauthorized:document").toResponse();
+ return new OpenChatError("unauthorized:document").toResponse();
}
const documents = await getDocumentsById({ id });
@@ -114,7 +114,7 @@ export async function DELETE(request: Request) {
const [document] = documents;
if (document.userId !== session.user.id) {
- return new ChatSDKError("forbidden:document").toResponse();
+ return new OpenChatError("forbidden:document").toResponse();
}
const documentsDeleted = await deleteDocumentsByIdAfterTimestamp({
diff --git a/app/(chat)/api/history/route.ts b/app/(chat)/api/history/route.ts
index 23615e305a..c7223ec260 100644
--- a/app/(chat)/api/history/route.ts
+++ b/app/(chat)/api/history/route.ts
@@ -1,7 +1,7 @@
import type { NextRequest } from "next/server";
import { auth } from "@/app/(auth)/auth";
import { deleteAllChatsByUserId, getChatsByUserId } from "@/lib/db/queries";
-import { ChatSDKError } from "@/lib/errors";
+import { OpenChatError } from "@/lib/errors";
export async function GET(request: NextRequest) {
const { searchParams } = request.nextUrl;
@@ -11,7 +11,7 @@ export async function GET(request: NextRequest) {
const endingBefore = searchParams.get("ending_before");
if (startingAfter && endingBefore) {
- return new ChatSDKError(
+ return new OpenChatError(
"bad_request:api",
"Only one of starting_after or ending_before can be provided."
).toResponse();
@@ -20,7 +20,7 @@ export async function GET(request: NextRequest) {
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("unauthorized:chat").toResponse();
+ return new OpenChatError("unauthorized:chat").toResponse();
}
const chats = await getChatsByUserId({
@@ -37,7 +37,7 @@ export async function DELETE() {
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("unauthorized:chat").toResponse();
+ return new OpenChatError("unauthorized:chat").toResponse();
}
const result = await deleteAllChatsByUserId({ userId: session.user.id });
diff --git a/app/(chat)/api/suggestions/route.ts b/app/(chat)/api/suggestions/route.ts
index 8801004eff..054994b09b 100644
--- a/app/(chat)/api/suggestions/route.ts
+++ b/app/(chat)/api/suggestions/route.ts
@@ -1,13 +1,13 @@
import { auth } from "@/app/(auth)/auth";
import { getSuggestionsByDocumentId } from "@/lib/db/queries";
-import { ChatSDKError } from "@/lib/errors";
+import { OpenChatError } from "@/lib/errors";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const documentId = searchParams.get("documentId");
if (!documentId) {
- return new ChatSDKError(
+ return new OpenChatError(
"bad_request:api",
"Parameter documentId is required."
).toResponse();
@@ -16,7 +16,7 @@ export async function GET(request: Request) {
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("unauthorized:suggestions").toResponse();
+ return new OpenChatError("unauthorized:suggestions").toResponse();
}
const suggestions = await getSuggestionsByDocumentId({
@@ -30,7 +30,7 @@ export async function GET(request: Request) {
}
if (suggestion.userId !== session.user.id) {
- return new ChatSDKError("forbidden:api").toResponse();
+ return new OpenChatError("forbidden:api").toResponse();
}
return Response.json(suggestions, { status: 200 });
diff --git a/app/(chat)/api/vote/route.ts b/app/(chat)/api/vote/route.ts
index 2c0ce3f788..d2c8ce170a 100644
--- a/app/(chat)/api/vote/route.ts
+++ b/app/(chat)/api/vote/route.ts
@@ -1,13 +1,13 @@
import { auth } from "@/app/(auth)/auth";
import { getChatById, getVotesByChatId, voteMessage } from "@/lib/db/queries";
-import { ChatSDKError } from "@/lib/errors";
+import { OpenChatError } from "@/lib/errors";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const chatId = searchParams.get("chatId");
if (!chatId) {
- return new ChatSDKError(
+ return new OpenChatError(
"bad_request:api",
"Parameter chatId is required."
).toResponse();
@@ -16,17 +16,17 @@ export async function GET(request: Request) {
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("unauthorized:vote").toResponse();
+ return new OpenChatError("unauthorized:vote").toResponse();
}
const chat = await getChatById({ id: chatId });
if (!chat) {
- return new ChatSDKError("not_found:chat").toResponse();
+ return new OpenChatError("not_found:chat").toResponse();
}
if (chat.userId !== session.user.id) {
- return new ChatSDKError("forbidden:vote").toResponse();
+ return new OpenChatError("forbidden:vote").toResponse();
}
const votes = await getVotesByChatId({ id: chatId });
@@ -43,7 +43,7 @@ export async function PATCH(request: Request) {
await request.json();
if (!chatId || !messageId || !type) {
- return new ChatSDKError(
+ return new OpenChatError(
"bad_request:api",
"Parameters chatId, messageId, and type are required."
).toResponse();
@@ -52,17 +52,17 @@ export async function PATCH(request: Request) {
const session = await auth();
if (!session?.user) {
- return new ChatSDKError("unauthorized:vote").toResponse();
+ return new OpenChatError("unauthorized:vote").toResponse();
}
const chat = await getChatById({ id: chatId });
if (!chat) {
- return new ChatSDKError("not_found:vote").toResponse();
+ return new OpenChatError("not_found:vote").toResponse();
}
if (chat.userId !== session.user.id) {
- return new ChatSDKError("forbidden:vote").toResponse();
+ return new OpenChatError("forbidden:vote").toResponse();
}
await voteMessage({
diff --git a/components/chat.tsx b/components/chat.tsx
index 13902a4a57..92642462ce 100644
--- a/components/chat.tsx
+++ b/components/chat.tsx
@@ -21,7 +21,7 @@ import { useArtifactSelector } from "@/hooks/use-artifact";
import { useAutoResume } from "@/hooks/use-auto-resume";
import { useChatVisibility } from "@/hooks/use-chat-visibility";
import type { Vote } from "@/lib/db/schema";
-import { ChatSDKError } from "@/lib/errors";
+import { OpenChatError } from "@/lib/errors";
import type { Attachment, ChatMessage } from "@/lib/types";
import { fetcher, fetchWithErrorHandlers, generateUUID } from "@/lib/utils";
import { Artifact } from "./artifact";
@@ -138,7 +138,7 @@ export function Chat({
mutate(unstable_serialize(getChatHistoryPaginationKey));
},
onError: (error) => {
- if (error instanceof ChatSDKError) {
+ if (error instanceof OpenChatError) {
if (
error.message?.includes("AI Gateway requires a valid credit card")
) {
diff --git a/lib/db/queries.ts b/lib/db/queries.ts
index 2855423a26..63f012e951 100644
--- a/lib/db/queries.ts
+++ b/lib/db/queries.ts
@@ -16,7 +16,7 @@ import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import type { ArtifactKind } from "@/components/artifact";
import type { VisibilityType } from "@/components/visibility-selector";
-import { ChatSDKError } from "../errors";
+import { OpenChatError } from "../errors";
import { generateUUID } from "../utils";
import {
type Chat,
@@ -45,7 +45,7 @@ export async function getUser(email: string): Promise {
try {
return await db.select().from(user).where(eq(user.email, email));
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get user by email"
);
@@ -58,7 +58,7 @@ export async function createUser(email: string, password: string) {
try {
return await db.insert(user).values({ email, password: hashedPassword });
} catch (_error) {
- throw new ChatSDKError("bad_request:database", "Failed to create user");
+ throw new OpenChatError("bad_request:database", "Failed to create user");
}
}
@@ -72,7 +72,7 @@ export async function createGuestUser() {
email: user.email,
});
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to create guest user"
);
@@ -99,7 +99,7 @@ export async function saveChat({
visibility,
});
} catch (_error) {
- throw new ChatSDKError("bad_request:database", "Failed to save chat");
+ throw new OpenChatError("bad_request:database", "Failed to save chat");
}
}
@@ -115,7 +115,7 @@ export async function deleteChatById({ id }: { id: string }) {
.returning();
return chatsDeleted;
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to delete chat by id"
);
@@ -146,7 +146,7 @@ export async function deleteAllChatsByUserId({ userId }: { userId: string }) {
return { deletedCount: deletedChats.length };
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to delete all chats by user id"
);
@@ -189,7 +189,7 @@ export async function getChatsByUserId({
.limit(1);
if (!selectedChat) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"not_found:database",
`Chat with id ${startingAfter} not found`
);
@@ -204,7 +204,7 @@ export async function getChatsByUserId({
.limit(1);
if (!selectedChat) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"not_found:database",
`Chat with id ${endingBefore} not found`
);
@@ -222,7 +222,7 @@ export async function getChatsByUserId({
hasMore,
};
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get chats by user id"
);
@@ -238,7 +238,7 @@ export async function getChatById({ id }: { id: string }) {
return selectedChat;
} catch (_error) {
- throw new ChatSDKError("bad_request:database", "Failed to get chat by id");
+ throw new OpenChatError("bad_request:database", "Failed to get chat by id");
}
}
@@ -246,7 +246,7 @@ export async function saveMessages({ messages }: { messages: DBMessage[] }) {
try {
return await db.insert(message).values(messages);
} catch (_error) {
- throw new ChatSDKError("bad_request:database", "Failed to save messages");
+ throw new OpenChatError("bad_request:database", "Failed to save messages");
}
}
@@ -260,7 +260,7 @@ export async function updateMessage({
try {
return await db.update(message).set({ parts }).where(eq(message.id, id));
} catch (_error) {
- throw new ChatSDKError("bad_request:database", "Failed to update message");
+ throw new OpenChatError("bad_request:database", "Failed to update message");
}
}
@@ -272,7 +272,7 @@ export async function getMessagesByChatId({ id }: { id: string }) {
.where(eq(message.chatId, id))
.orderBy(asc(message.createdAt));
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get messages by chat id"
);
@@ -306,7 +306,7 @@ export async function voteMessage({
isUpvoted: type === "up",
});
} catch (_error) {
- throw new ChatSDKError("bad_request:database", "Failed to vote message");
+ throw new OpenChatError("bad_request:database", "Failed to vote message");
}
}
@@ -314,7 +314,7 @@ export async function getVotesByChatId({ id }: { id: string }) {
try {
return await db.select().from(vote).where(eq(vote.chatId, id));
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get votes by chat id"
);
@@ -347,7 +347,7 @@ export async function saveDocument({
})
.returning();
} catch (_error) {
- throw new ChatSDKError("bad_request:database", "Failed to save document");
+ throw new OpenChatError("bad_request:database", "Failed to save document");
}
}
@@ -361,7 +361,7 @@ export async function getDocumentsById({ id }: { id: string }) {
return documents;
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get documents by id"
);
@@ -378,7 +378,7 @@ export async function getDocumentById({ id }: { id: string }) {
return selectedDocument;
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get document by id"
);
@@ -407,7 +407,7 @@ export async function deleteDocumentsByIdAfterTimestamp({
.where(and(eq(document.id, id), gt(document.createdAt, timestamp)))
.returning();
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to delete documents by id after timestamp"
);
@@ -422,7 +422,7 @@ export async function saveSuggestions({
try {
return await db.insert(suggestion).values(suggestions);
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to save suggestions"
);
@@ -440,7 +440,7 @@ export async function getSuggestionsByDocumentId({
.from(suggestion)
.where(eq(suggestion.documentId, documentId));
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get suggestions by document id"
);
@@ -451,7 +451,7 @@ export async function getMessageById({ id }: { id: string }) {
try {
return await db.select().from(message).where(eq(message.id, id));
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get message by id"
);
@@ -491,7 +491,7 @@ export async function deleteMessagesByChatIdAfterTimestamp({
);
}
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to delete messages by chat id after timestamp"
);
@@ -508,7 +508,7 @@ export async function updateChatVisibilityById({
try {
return await db.update(chat).set({ visibility }).where(eq(chat.id, chatId));
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to update chat visibility by id"
);
@@ -557,7 +557,7 @@ export async function getMessageCountByUserId({
return stats?.count ?? 0;
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get message count by user id"
);
@@ -576,7 +576,7 @@ export async function createStreamId({
.insert(stream)
.values({ id: streamId, chatId, createdAt: new Date() });
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to create stream id"
);
@@ -594,7 +594,7 @@ export async function getStreamIdsByChatId({ chatId }: { chatId: string }) {
return streamIds.map(({ id }) => id);
} catch (_error) {
- throw new ChatSDKError(
+ throw new OpenChatError(
"bad_request:database",
"Failed to get stream ids by chat id"
);
diff --git a/lib/errors.ts b/lib/errors.ts
index 090682216e..bfa5d4d2cb 100644
--- a/lib/errors.ts
+++ b/lib/errors.ts
@@ -35,7 +35,7 @@ export const visibilityBySurface: Record = {
activate_gateway: "response",
};
-export class ChatSDKError extends Error {
+export class OpenChatError extends Error {
type: ErrorType;
surface: Surface;
statusCode: number;
diff --git a/lib/utils.ts b/lib/utils.ts
index 7f0c2d5c3f..01c13ea1e5 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -8,7 +8,7 @@ import { type ClassValue, clsx } from 'clsx';
import { formatISO } from 'date-fns';
import { twMerge } from 'tailwind-merge';
import type { DBMessage, Document } from '@/lib/db/schema';
-import { ChatSDKError, type ErrorCode } from './errors';
+import { OpenChatError, type ErrorCode } from './errors';
import type { ChatMessage, ChatTools, CustomUIDataTypes } from './types';
export function cn(...inputs: ClassValue[]) {
@@ -20,7 +20,7 @@ export const fetcher = async (url: string) => {
if (!response.ok) {
const { code, cause } = await response.json();
- throw new ChatSDKError(code as ErrorCode, cause);
+ throw new OpenChatError(code as ErrorCode, cause);
}
return response.json();
@@ -35,13 +35,13 @@ export async function fetchWithErrorHandlers(
if (!response.ok) {
const { code, cause } = await response.json();
- throw new ChatSDKError(code as ErrorCode, cause);
+ throw new OpenChatError(code as ErrorCode, cause);
}
return response;
} catch (error: unknown) {
if (typeof navigator !== 'undefined' && !navigator.onLine) {
- throw new ChatSDKError('offline:chat');
+ throw new OpenChatError('offline:chat');
}
throw error;
From c4f6e96812f720fd14f432445040f932a5bb4217 Mon Sep 17 00:00:00 2001
From: dancer <144584931+dancer@users.noreply.github.com>
Date: Fri, 20 Feb 2026 20:16:53 +0000
Subject: [PATCH 3/9] update next type route import path
---
next-env.d.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/next-env.d.ts b/next-env.d.ts
index c4b7818fbb..9edff1c7ca 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-import "./.next/dev/types/routes.d.ts";
+import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
From 3c0d5104dc034d63998d5f0c956e35eafb542a0a Mon Sep 17 00:00:00 2001
From: dancer <144584931+dancer@users.noreply.github.com>
Date: Fri, 20 Feb 2026 20:24:06 +0000
Subject: [PATCH 4/9] sync next-env route import with main
---
next-env.d.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/next-env.d.ts b/next-env.d.ts
index 9edff1c7ca..c4b7818fbb 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-import "./.next/types/routes.d.ts";
+import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
From 1a40efaee38fb7c5a45be72af1979e0861d2defb Mon Sep 17 00:00:00 2001
From: dancer <144584931+dancer@users.noreply.github.com>
Date: Fri, 20 Feb 2026 20:35:50 +0000
Subject: [PATCH 5/9] fix dark mode background seam and sidebar title
---
components/app-sidebar.tsx | 2 +-
components/messages.tsx | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/components/app-sidebar.tsx b/components/app-sidebar.tsx
index ec3f27356a..ff9c2f0105 100644
--- a/components/app-sidebar.tsx
+++ b/components/app-sidebar.tsx
@@ -72,7 +72,7 @@ export function AppSidebar({ user }: { user: User | undefined }) {
}}
>
- Chatbot
+ OpenChat
From ee01fa0cd88e6b79c13e93b7d29ebd05d4626c39 Mon Sep 17 00:00:00 2001
From: dancer <144584931+dancer@users.noreply.github.com>
Date: Fri, 20 Feb 2026 23:22:39 +0000
Subject: [PATCH 6/9] add rename notice to readme
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index d133527daf..15425366cd 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,8 @@
OpenChat is a free, open-source template built with Next.js and the AI SDK that helps you quickly build powerful chatbot applications.
+> **Update:** AI-Chatbot has been renamed to **OpenChat**. It is the same open-source template you know, just under a new name. All links and references below have been updated to reflect this change.
+
Read Docs ·
Features ·
From 58a00fb7f23bb3b6ccb019a935a10acebce84d84 Mon Sep 17 00:00:00 2001
From: dancer <144584931+dancer@users.noreply.github.com>
Date: Fri, 20 Feb 2026 23:24:17 +0000
Subject: [PATCH 7/9] remove readme rename notice
---
README.md | 2 --
1 file changed, 2 deletions(-)
diff --git a/README.md b/README.md
index 15425366cd..d133527daf 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,6 @@
OpenChat is a free, open-source template built with Next.js and the AI SDK that helps you quickly build powerful chatbot applications.
-> **Update:** AI-Chatbot has been renamed to **OpenChat**. It is the same open-source template you know, just under a new name. All links and references below have been updated to reflect this change.
-