Skip to content
Merged
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
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<a href="https://chat.vercel.ai/">
<img alt="Next.js 14 and App Router-ready AI chatbot." src="app/(chat)/opengraph-image.png">
<h1 align="center">Chat SDK</h1>
<img alt="Next.js 14 and App Router-ready OpenChat." src="app/(chat)/opengraph-image.png">
<h1 align="center">OpenChat</h1>
</a>

<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 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="#model-providers"><strong>Model Providers</strong></a> ·
<a href="#deploy-your-own"><strong>Deploy Your Own</strong></a> ·
Expand Down Expand Up @@ -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:

[![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

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.

Expand Down
22 changes: 11 additions & 11 deletions app/(chat)/api/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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 {
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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 });
Expand Down Expand Up @@ -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();
}

Expand All @@ -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();
}
}

Expand All @@ -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 });
Expand Down
24 changes: 12 additions & 12 deletions app/(chat)/api/document/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -21,19 +21,19 @@ 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 });

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 });
Expand All @@ -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();
Expand All @@ -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 {
Expand All @@ -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();
}
}

Expand All @@ -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();
Expand All @@ -106,15 +106,15 @@ 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 });

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({
Expand Down
8 changes: 4 additions & 4 deletions app/(chat)/api/history/route.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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();
Expand All @@ -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({
Expand All @@ -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 });
Expand Down
8 changes: 4 additions & 4 deletions app/(chat)/api/suggestions/route.ts
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -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({
Expand All @@ -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 });
Expand Down
18 changes: 9 additions & 9 deletions app/(chat)/api/vote/route.ts
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -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 });
Expand All @@ -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();
Expand All @@ -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({
Expand Down
Binary file modified app/(chat)/opengraph-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion components/app-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Chatbot
OpenChat
</span>
</Link>
<div className="flex flex-row gap-1">
Expand Down
2 changes: 1 addition & 1 deletion components/chat-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
>
<Link
href={"https://vercel.com/templates/next.js/nextjs-ai-chatbot"}
href={"https://vercel.com/templates/next.js/openchat"}
rel="noreferrer"
target="_noblank"
>
Expand Down
Loading