rebrand ai-chatbot to openchat across app and api (#1418)

This commit is contained in:
dancer 2026-02-20 15:28:40 -08:00 committed by GitHub
parent 9d5d8a3ea7
commit f7b6b55a8b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 90 additions and 90 deletions

View file

@ -1,14 +1,14 @@
<a href="https://chat.vercel.ai/"> <a href="https://chat.vercel.ai/">
<img alt="Next.js 14 and App Router-ready AI chatbot." src="app/(chat)/opengraph-image.png"> <img alt="Next.js 14 and App Router-ready OpenChat." src="app/(chat)/opengraph-image.png">
<h1 align="center">Chat SDK</h1> <h1 align="center">OpenChat</h1>
</a> </a>
<p align="center"> <p align="center">
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 (formerly AI Chatbot) is a free, open-source template built with Next.js and the AI SDK that helps you quickly build powerful chatbot applications.
</p> </p>
<p align="center"> <p align="center">
<a href="https://chat-sdk.dev"><strong>Read Docs</strong></a> · <a href="https://openchat.dev"><strong>Read Docs</strong></a> ·
<a href="#features"><strong>Features</strong></a> · <a href="#features"><strong>Features</strong></a> ·
<a href="#model-providers"><strong>Model Providers</strong></a> · <a href="#model-providers"><strong>Model Providers</strong></a> ·
<a href="#deploy-your-own"><strong>Deploy Your Own</strong></a> · <a href="#deploy-your-own"><strong>Deploy Your Own</strong></a> ·
@ -48,13 +48,13 @@ With the [AI SDK](https://ai-sdk.dev/docs/introduction), you can also switch to
## Deploy Your Own ## 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:
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/templates/next.js/nextjs-ai-chatbot) [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/templates/next.js/openchat)
## Running locally ## 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. > 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.

View file

@ -30,7 +30,7 @@ import {
updateMessage, updateMessage,
} from "@/lib/db/queries"; } from "@/lib/db/queries";
import type { DBMessage } from "@/lib/db/schema"; import type { DBMessage } from "@/lib/db/schema";
import { ChatSDKError } from "@/lib/errors"; import { OpenChatError } from "@/lib/errors";
import type { ChatMessage } from "@/lib/types"; import type { ChatMessage } from "@/lib/types";
import { convertToUIMessages, generateUUID } from "@/lib/utils"; import { convertToUIMessages, generateUUID } from "@/lib/utils";
import { generateTitleFromUserMessage } from "../../actions"; import { generateTitleFromUserMessage } from "../../actions";
@ -55,7 +55,7 @@ export async function POST(request: Request) {
const json = await request.json(); const json = await request.json();
requestBody = postRequestBodySchema.parse(json); requestBody = postRequestBodySchema.parse(json);
} catch (_) { } catch (_) {
return new ChatSDKError("bad_request:api").toResponse(); return new OpenChatError("bad_request:api").toResponse();
} }
try { try {
@ -65,7 +65,7 @@ export async function POST(request: Request) {
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("unauthorized:chat").toResponse(); return new OpenChatError("unauthorized:chat").toResponse();
} }
const userType: UserType = session.user.type; const userType: UserType = session.user.type;
@ -76,7 +76,7 @@ export async function POST(request: Request) {
}); });
if (messageCount > entitlementsByUserType[userType].maxMessagesPerDay) { if (messageCount > entitlementsByUserType[userType].maxMessagesPerDay) {
return new ChatSDKError("rate_limit:chat").toResponse(); return new OpenChatError("rate_limit:chat").toResponse();
} }
const isToolApprovalFlow = Boolean(messages); const isToolApprovalFlow = Boolean(messages);
@ -87,7 +87,7 @@ export async function POST(request: Request) {
if (chat) { if (chat) {
if (chat.userId !== session.user.id) { if (chat.userId !== session.user.id) {
return new ChatSDKError("forbidden:chat").toResponse(); return new OpenChatError("forbidden:chat").toResponse();
} }
if (!isToolApprovalFlow) { if (!isToolApprovalFlow) {
messagesFromDb = await getMessagesByChatId({ id }); messagesFromDb = await getMessagesByChatId({ id });
@ -244,7 +244,7 @@ export async function POST(request: Request) {
} catch (error) { } catch (error) {
const vercelId = request.headers.get("x-vercel-id"); const vercelId = request.headers.get("x-vercel-id");
if (error instanceof ChatSDKError) { if (error instanceof OpenChatError) {
return error.toResponse(); 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" "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 }); 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"); const id = searchParams.get("id");
if (!id) { if (!id) {
return new ChatSDKError("bad_request:api").toResponse(); return new OpenChatError("bad_request:api").toResponse();
} }
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("unauthorized:chat").toResponse(); return new OpenChatError("unauthorized:chat").toResponse();
} }
const chat = await getChatById({ id }); const chat = await getChatById({ id });
if (chat?.userId !== session.user.id) { if (chat?.userId !== session.user.id) {
return new ChatSDKError("forbidden:chat").toResponse(); return new OpenChatError("forbidden:chat").toResponse();
} }
const deletedChat = await deleteChatById({ id }); const deletedChat = await deleteChatById({ id });

View file

@ -5,14 +5,14 @@ import {
getDocumentsById, getDocumentsById,
saveDocument, saveDocument,
} from "@/lib/db/queries"; } from "@/lib/db/queries";
import { ChatSDKError } from "@/lib/errors"; import { OpenChatError } from "@/lib/errors";
export async function GET(request: Request) { export async function GET(request: Request) {
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const id = searchParams.get("id"); const id = searchParams.get("id");
if (!id) { if (!id) {
return new ChatSDKError( return new OpenChatError(
"bad_request:api", "bad_request:api",
"Parameter id is missing" "Parameter id is missing"
).toResponse(); ).toResponse();
@ -21,7 +21,7 @@ export async function GET(request: Request) {
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("unauthorized:document").toResponse(); return new OpenChatError("unauthorized:document").toResponse();
} }
const documents = await getDocumentsById({ id }); const documents = await getDocumentsById({ id });
@ -29,11 +29,11 @@ export async function GET(request: Request) {
const [document] = documents; const [document] = documents;
if (!document) { if (!document) {
return new ChatSDKError("not_found:document").toResponse(); return new OpenChatError("not_found:document").toResponse();
} }
if (document.userId !== session.user.id) { if (document.userId !== session.user.id) {
return new ChatSDKError("forbidden:document").toResponse(); return new OpenChatError("forbidden:document").toResponse();
} }
return Response.json(documents, { status: 200 }); return Response.json(documents, { status: 200 });
@ -44,7 +44,7 @@ export async function POST(request: Request) {
const id = searchParams.get("id"); const id = searchParams.get("id");
if (!id) { if (!id) {
return new ChatSDKError( return new OpenChatError(
"bad_request:api", "bad_request:api",
"Parameter id is required." "Parameter id is required."
).toResponse(); ).toResponse();
@ -53,7 +53,7 @@ export async function POST(request: Request) {
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("not_found:document").toResponse(); return new OpenChatError("not_found:document").toResponse();
} }
const { const {
@ -69,7 +69,7 @@ export async function POST(request: Request) {
const [doc] = documents; const [doc] = documents;
if (doc.userId !== session.user.id) { 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"); const timestamp = searchParams.get("timestamp");
if (!id) { if (!id) {
return new ChatSDKError( return new OpenChatError(
"bad_request:api", "bad_request:api",
"Parameter id is required." "Parameter id is required."
).toResponse(); ).toResponse();
} }
if (!timestamp) { if (!timestamp) {
return new ChatSDKError( return new OpenChatError(
"bad_request:api", "bad_request:api",
"Parameter timestamp is required." "Parameter timestamp is required."
).toResponse(); ).toResponse();
@ -106,7 +106,7 @@ export async function DELETE(request: Request) {
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("unauthorized:document").toResponse(); return new OpenChatError("unauthorized:document").toResponse();
} }
const documents = await getDocumentsById({ id }); const documents = await getDocumentsById({ id });
@ -114,7 +114,7 @@ export async function DELETE(request: Request) {
const [document] = documents; const [document] = documents;
if (document.userId !== session.user.id) { if (document.userId !== session.user.id) {
return new ChatSDKError("forbidden:document").toResponse(); return new OpenChatError("forbidden:document").toResponse();
} }
const documentsDeleted = await deleteDocumentsByIdAfterTimestamp({ const documentsDeleted = await deleteDocumentsByIdAfterTimestamp({

View file

@ -1,7 +1,7 @@
import type { NextRequest } from "next/server"; import type { NextRequest } from "next/server";
import { auth } from "@/app/(auth)/auth"; import { auth } from "@/app/(auth)/auth";
import { deleteAllChatsByUserId, getChatsByUserId } from "@/lib/db/queries"; import { deleteAllChatsByUserId, getChatsByUserId } from "@/lib/db/queries";
import { ChatSDKError } from "@/lib/errors"; import { OpenChatError } from "@/lib/errors";
export async function GET(request: NextRequest) { export async function GET(request: NextRequest) {
const { searchParams } = request.nextUrl; const { searchParams } = request.nextUrl;
@ -11,7 +11,7 @@ export async function GET(request: NextRequest) {
const endingBefore = searchParams.get("ending_before"); const endingBefore = searchParams.get("ending_before");
if (startingAfter && endingBefore) { if (startingAfter && endingBefore) {
return new ChatSDKError( return new OpenChatError(
"bad_request:api", "bad_request:api",
"Only one of starting_after or ending_before can be provided." "Only one of starting_after or ending_before can be provided."
).toResponse(); ).toResponse();
@ -20,7 +20,7 @@ export async function GET(request: NextRequest) {
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("unauthorized:chat").toResponse(); return new OpenChatError("unauthorized:chat").toResponse();
} }
const chats = await getChatsByUserId({ const chats = await getChatsByUserId({
@ -37,7 +37,7 @@ export async function DELETE() {
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("unauthorized:chat").toResponse(); return new OpenChatError("unauthorized:chat").toResponse();
} }
const result = await deleteAllChatsByUserId({ userId: session.user.id }); const result = await deleteAllChatsByUserId({ userId: session.user.id });

View file

@ -1,13 +1,13 @@
import { auth } from "@/app/(auth)/auth"; import { auth } from "@/app/(auth)/auth";
import { getSuggestionsByDocumentId } from "@/lib/db/queries"; import { getSuggestionsByDocumentId } from "@/lib/db/queries";
import { ChatSDKError } from "@/lib/errors"; import { OpenChatError } from "@/lib/errors";
export async function GET(request: Request) { export async function GET(request: Request) {
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const documentId = searchParams.get("documentId"); const documentId = searchParams.get("documentId");
if (!documentId) { if (!documentId) {
return new ChatSDKError( return new OpenChatError(
"bad_request:api", "bad_request:api",
"Parameter documentId is required." "Parameter documentId is required."
).toResponse(); ).toResponse();
@ -16,7 +16,7 @@ export async function GET(request: Request) {
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("unauthorized:suggestions").toResponse(); return new OpenChatError("unauthorized:suggestions").toResponse();
} }
const suggestions = await getSuggestionsByDocumentId({ const suggestions = await getSuggestionsByDocumentId({
@ -30,7 +30,7 @@ export async function GET(request: Request) {
} }
if (suggestion.userId !== session.user.id) { if (suggestion.userId !== session.user.id) {
return new ChatSDKError("forbidden:api").toResponse(); return new OpenChatError("forbidden:api").toResponse();
} }
return Response.json(suggestions, { status: 200 }); return Response.json(suggestions, { status: 200 });

View file

@ -1,13 +1,13 @@
import { auth } from "@/app/(auth)/auth"; import { auth } from "@/app/(auth)/auth";
import { getChatById, getVotesByChatId, voteMessage } from "@/lib/db/queries"; import { getChatById, getVotesByChatId, voteMessage } from "@/lib/db/queries";
import { ChatSDKError } from "@/lib/errors"; import { OpenChatError } from "@/lib/errors";
export async function GET(request: Request) { export async function GET(request: Request) {
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const chatId = searchParams.get("chatId"); const chatId = searchParams.get("chatId");
if (!chatId) { if (!chatId) {
return new ChatSDKError( return new OpenChatError(
"bad_request:api", "bad_request:api",
"Parameter chatId is required." "Parameter chatId is required."
).toResponse(); ).toResponse();
@ -16,17 +16,17 @@ export async function GET(request: Request) {
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("unauthorized:vote").toResponse(); return new OpenChatError("unauthorized:vote").toResponse();
} }
const chat = await getChatById({ id: chatId }); const chat = await getChatById({ id: chatId });
if (!chat) { if (!chat) {
return new ChatSDKError("not_found:chat").toResponse(); return new OpenChatError("not_found:chat").toResponse();
} }
if (chat.userId !== session.user.id) { if (chat.userId !== session.user.id) {
return new ChatSDKError("forbidden:vote").toResponse(); return new OpenChatError("forbidden:vote").toResponse();
} }
const votes = await getVotesByChatId({ id: chatId }); const votes = await getVotesByChatId({ id: chatId });
@ -43,7 +43,7 @@ export async function PATCH(request: Request) {
await request.json(); await request.json();
if (!chatId || !messageId || !type) { if (!chatId || !messageId || !type) {
return new ChatSDKError( return new OpenChatError(
"bad_request:api", "bad_request:api",
"Parameters chatId, messageId, and type are required." "Parameters chatId, messageId, and type are required."
).toResponse(); ).toResponse();
@ -52,17 +52,17 @@ export async function PATCH(request: Request) {
const session = await auth(); const session = await auth();
if (!session?.user) { if (!session?.user) {
return new ChatSDKError("unauthorized:vote").toResponse(); return new OpenChatError("unauthorized:vote").toResponse();
} }
const chat = await getChatById({ id: chatId }); const chat = await getChatById({ id: chatId });
if (!chat) { if (!chat) {
return new ChatSDKError("not_found:vote").toResponse(); return new OpenChatError("not_found:vote").toResponse();
} }
if (chat.userId !== session.user.id) { if (chat.userId !== session.user.id) {
return new ChatSDKError("forbidden:vote").toResponse(); return new OpenChatError("forbidden:vote").toResponse();
} }
await voteMessage({ await voteMessage({

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Before After
Before After

View file

@ -72,7 +72,7 @@ export function AppSidebar({ user }: { user: User | undefined }) {
}} }}
> >
<span className="cursor-pointer rounded-md px-2 font-semibold text-lg hover:bg-muted"> <span className="cursor-pointer rounded-md px-2 font-semibold text-lg hover:bg-muted">
Chatbot OpenChat
</span> </span>
</Link> </Link>
<div className="flex flex-row gap-1"> <div className="flex flex-row gap-1">

View file

@ -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" 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"
> >
<Link <Link
href={"https://vercel.com/templates/next.js/nextjs-ai-chatbot"} href={"https://vercel.com/templates/next.js/openchat"}
rel="noreferrer" rel="noreferrer"
target="_noblank" target="_noblank"
> >

View file

@ -21,7 +21,7 @@ import { useArtifactSelector } from "@/hooks/use-artifact";
import { useAutoResume } from "@/hooks/use-auto-resume"; import { useAutoResume } from "@/hooks/use-auto-resume";
import { useChatVisibility } from "@/hooks/use-chat-visibility"; import { useChatVisibility } from "@/hooks/use-chat-visibility";
import type { Vote } from "@/lib/db/schema"; 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 type { Attachment, ChatMessage } from "@/lib/types";
import { fetcher, fetchWithErrorHandlers, generateUUID } from "@/lib/utils"; import { fetcher, fetchWithErrorHandlers, generateUUID } from "@/lib/utils";
import { Artifact } from "./artifact"; import { Artifact } from "./artifact";
@ -138,7 +138,7 @@ export function Chat({
mutate(unstable_serialize(getChatHistoryPaginationKey)); mutate(unstable_serialize(getChatHistoryPaginationKey));
}, },
onError: (error) => { onError: (error) => {
if (error instanceof ChatSDKError) { if (error instanceof OpenChatError) {
if ( if (
error.message?.includes("AI Gateway requires a valid credit card") error.message?.includes("AI Gateway requires a valid credit card")
) { ) {

View file

@ -44,9 +44,9 @@ function PureMessages({
useDataStream(); useDataStream();
return ( return (
<div className="relative flex-1"> <div className="relative flex-1 bg-background">
<div <div
className="absolute inset-0 touch-pan-y overflow-y-auto" className="absolute inset-0 touch-pan-y overflow-y-auto bg-background"
ref={messagesContainerRef} ref={messagesContainerRef}
> >
<div className="mx-auto flex min-w-0 max-w-4xl flex-col gap-4 px-2 py-4 md:gap-6 md:px-4"> <div className="mx-auto flex min-w-0 max-w-4xl flex-col gap-4 px-2 py-4 md:gap-6 md:px-4">

View file

@ -1,5 +1,5 @@
import { registerOTel } from "@vercel/otel"; import { registerOTel } from "@vercel/otel";
export function register() { export function register() {
registerOTel({ serviceName: "ai-chatbot" }); registerOTel({ serviceName: "openchat" });
} }

View file

@ -16,7 +16,7 @@ import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres"; import postgres from "postgres";
import type { ArtifactKind } from "@/components/artifact"; import type { ArtifactKind } from "@/components/artifact";
import type { VisibilityType } from "@/components/visibility-selector"; import type { VisibilityType } from "@/components/visibility-selector";
import { ChatSDKError } from "../errors"; import { OpenChatError } from "../errors";
import { generateUUID } from "../utils"; import { generateUUID } from "../utils";
import { import {
type Chat, type Chat,
@ -45,7 +45,7 @@ export async function getUser(email: string): Promise<User[]> {
try { try {
return await db.select().from(user).where(eq(user.email, email)); return await db.select().from(user).where(eq(user.email, email));
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get user by email" "Failed to get user by email"
); );
@ -58,7 +58,7 @@ export async function createUser(email: string, password: string) {
try { try {
return await db.insert(user).values({ email, password: hashedPassword }); return await db.insert(user).values({ email, password: hashedPassword });
} catch (_error) { } 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, email: user.email,
}); });
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to create guest user" "Failed to create guest user"
); );
@ -99,7 +99,7 @@ export async function saveChat({
visibility, visibility,
}); });
} catch (_error) { } 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(); .returning();
return chatsDeleted; return chatsDeleted;
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to delete chat by id" "Failed to delete chat by id"
); );
@ -146,7 +146,7 @@ export async function deleteAllChatsByUserId({ userId }: { userId: string }) {
return { deletedCount: deletedChats.length }; return { deletedCount: deletedChats.length };
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to delete all chats by user id" "Failed to delete all chats by user id"
); );
@ -189,7 +189,7 @@ export async function getChatsByUserId({
.limit(1); .limit(1);
if (!selectedChat) { if (!selectedChat) {
throw new ChatSDKError( throw new OpenChatError(
"not_found:database", "not_found:database",
`Chat with id ${startingAfter} not found` `Chat with id ${startingAfter} not found`
); );
@ -204,7 +204,7 @@ export async function getChatsByUserId({
.limit(1); .limit(1);
if (!selectedChat) { if (!selectedChat) {
throw new ChatSDKError( throw new OpenChatError(
"not_found:database", "not_found:database",
`Chat with id ${endingBefore} not found` `Chat with id ${endingBefore} not found`
); );
@ -222,7 +222,7 @@ export async function getChatsByUserId({
hasMore, hasMore,
}; };
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get chats by user id" "Failed to get chats by user id"
); );
@ -238,7 +238,7 @@ export async function getChatById({ id }: { id: string }) {
return selectedChat; return selectedChat;
} catch (_error) { } 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 { try {
return await db.insert(message).values(messages); return await db.insert(message).values(messages);
} catch (_error) { } 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 { try {
return await db.update(message).set({ parts }).where(eq(message.id, id)); return await db.update(message).set({ parts }).where(eq(message.id, id));
} catch (_error) { } 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)) .where(eq(message.chatId, id))
.orderBy(asc(message.createdAt)); .orderBy(asc(message.createdAt));
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get messages by chat id" "Failed to get messages by chat id"
); );
@ -306,7 +306,7 @@ export async function voteMessage({
isUpvoted: type === "up", isUpvoted: type === "up",
}); });
} catch (_error) { } 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 { try {
return await db.select().from(vote).where(eq(vote.chatId, id)); return await db.select().from(vote).where(eq(vote.chatId, id));
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get votes by chat id" "Failed to get votes by chat id"
); );
@ -347,7 +347,7 @@ export async function saveDocument({
}) })
.returning(); .returning();
} catch (_error) { } 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; return documents;
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get documents by id" "Failed to get documents by id"
); );
@ -378,7 +378,7 @@ export async function getDocumentById({ id }: { id: string }) {
return selectedDocument; return selectedDocument;
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get document by id" "Failed to get document by id"
); );
@ -407,7 +407,7 @@ export async function deleteDocumentsByIdAfterTimestamp({
.where(and(eq(document.id, id), gt(document.createdAt, timestamp))) .where(and(eq(document.id, id), gt(document.createdAt, timestamp)))
.returning(); .returning();
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to delete documents by id after timestamp" "Failed to delete documents by id after timestamp"
); );
@ -422,7 +422,7 @@ export async function saveSuggestions({
try { try {
return await db.insert(suggestion).values(suggestions); return await db.insert(suggestion).values(suggestions);
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to save suggestions" "Failed to save suggestions"
); );
@ -440,7 +440,7 @@ export async function getSuggestionsByDocumentId({
.from(suggestion) .from(suggestion)
.where(eq(suggestion.documentId, documentId)); .where(eq(suggestion.documentId, documentId));
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get suggestions by document id" "Failed to get suggestions by document id"
); );
@ -451,7 +451,7 @@ export async function getMessageById({ id }: { id: string }) {
try { try {
return await db.select().from(message).where(eq(message.id, id)); return await db.select().from(message).where(eq(message.id, id));
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get message by id" "Failed to get message by id"
); );
@ -491,7 +491,7 @@ export async function deleteMessagesByChatIdAfterTimestamp({
); );
} }
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to delete messages by chat id after timestamp" "Failed to delete messages by chat id after timestamp"
); );
@ -508,7 +508,7 @@ export async function updateChatVisibilityById({
try { try {
return await db.update(chat).set({ visibility }).where(eq(chat.id, chatId)); return await db.update(chat).set({ visibility }).where(eq(chat.id, chatId));
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to update chat visibility by id" "Failed to update chat visibility by id"
); );
@ -557,7 +557,7 @@ export async function getMessageCountByUserId({
return stats?.count ?? 0; return stats?.count ?? 0;
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get message count by user id" "Failed to get message count by user id"
); );
@ -576,7 +576,7 @@ export async function createStreamId({
.insert(stream) .insert(stream)
.values({ id: streamId, chatId, createdAt: new Date() }); .values({ id: streamId, chatId, createdAt: new Date() });
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to create stream id" "Failed to create stream id"
); );
@ -594,7 +594,7 @@ export async function getStreamIdsByChatId({ chatId }: { chatId: string }) {
return streamIds.map(({ id }) => id); return streamIds.map(({ id }) => id);
} catch (_error) { } catch (_error) {
throw new ChatSDKError( throw new OpenChatError(
"bad_request:database", "bad_request:database",
"Failed to get stream ids by chat id" "Failed to get stream ids by chat id"
); );

View file

@ -34,7 +34,7 @@ export const chat = pgTable("Chat", {
export type Chat = InferSelectModel<typeof chat>; export type Chat = InferSelectModel<typeof chat>;
// DEPRECATED: The following schema is deprecated and will be removed in the future. // 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", { export const messageDeprecated = pgTable("Message", {
id: uuid("id").primaryKey().notNull().defaultRandom(), id: uuid("id").primaryKey().notNull().defaultRandom(),
chatId: uuid("chatId") chatId: uuid("chatId")
@ -61,7 +61,7 @@ export const message = pgTable("Message_v2", {
export type DBMessage = InferSelectModel<typeof message>; export type DBMessage = InferSelectModel<typeof message>;
// DEPRECATED: The following schema is deprecated and will be removed in the future. // 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( export const voteDeprecated = pgTable(
"Vote", "Vote",
{ {

View file

@ -35,7 +35,7 @@ export const visibilityBySurface: Record<Surface, ErrorVisibility> = {
activate_gateway: "response", activate_gateway: "response",
}; };
export class ChatSDKError extends Error { export class OpenChatError extends Error {
type: ErrorType; type: ErrorType;
surface: Surface; surface: Surface;
statusCode: number; statusCode: number;

View file

@ -8,7 +8,7 @@ import { type ClassValue, clsx } from 'clsx';
import { formatISO } from 'date-fns'; import { formatISO } from 'date-fns';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
import type { DBMessage, Document } from '@/lib/db/schema'; 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'; import type { ChatMessage, ChatTools, CustomUIDataTypes } from './types';
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {
@ -20,7 +20,7 @@ export const fetcher = async (url: string) => {
if (!response.ok) { if (!response.ok) {
const { code, cause } = await response.json(); const { code, cause } = await response.json();
throw new ChatSDKError(code as ErrorCode, cause); throw new OpenChatError(code as ErrorCode, cause);
} }
return response.json(); return response.json();
@ -35,13 +35,13 @@ export async function fetchWithErrorHandlers(
if (!response.ok) { if (!response.ok) {
const { code, cause } = await response.json(); const { code, cause } = await response.json();
throw new ChatSDKError(code as ErrorCode, cause); throw new OpenChatError(code as ErrorCode, cause);
} }
return response; return response;
} catch (error: unknown) { } catch (error: unknown) {
if (typeof navigator !== 'undefined' && !navigator.onLine) { if (typeof navigator !== 'undefined' && !navigator.onLine) {
throw new ChatSDKError('offline:chat'); throw new OpenChatError('offline:chat');
} }
throw error; throw error;

View file

@ -1,5 +1,5 @@
{ {
"name": "ai-chatbot", "name": "openchat",
"version": "3.1.0", "version": "3.1.0",
"private": true, "private": true,
"scripts": { "scripts": {