diff --git a/README.md b/README.md index 13060cebe8..2d4918264a 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ - Next.js 14 and App Router-ready OpenChat. -

OpenChat

+ Next.js 14 and App Router-ready Chatbot. +

Chatbot

- 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. + Chatbot (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.

- 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 OpenChat to Vercel with one click: +You can deploy your own version of Chatbot to Vercel with one click: -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/templates/next.js/openchat) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/templates/next.js/chatbot) ## Running locally -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. +You will need to use the environment variables [defined in `.env.example`](.env.example) to run 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. > 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/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index a659bdf3fd..cd1169785b 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 { OpenChatError } from "@/lib/errors"; +import { ChatbotError } 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 OpenChatError("bad_request:api").toResponse(); + return new ChatbotError("bad_request:api").toResponse(); } try { @@ -65,7 +65,7 @@ export async function POST(request: Request) { const session = await auth(); if (!session?.user) { - return new OpenChatError("unauthorized:chat").toResponse(); + return new ChatbotError("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 OpenChatError("rate_limit:chat").toResponse(); + return new ChatbotError("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 OpenChatError("forbidden:chat").toResponse(); + return new ChatbotError("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 OpenChatError) { + if (error instanceof ChatbotError) { 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 OpenChatError("bad_request:activate_gateway").toResponse(); + return new ChatbotError("bad_request:activate_gateway").toResponse(); } console.error("Unhandled error in chat API:", error, { vercelId }); - return new OpenChatError("offline:chat").toResponse(); + return new ChatbotError("offline:chat").toResponse(); } } @@ -267,19 +267,19 @@ export async function DELETE(request: Request) { const id = searchParams.get("id"); if (!id) { - return new OpenChatError("bad_request:api").toResponse(); + return new ChatbotError("bad_request:api").toResponse(); } const session = await auth(); if (!session?.user) { - return new OpenChatError("unauthorized:chat").toResponse(); + return new ChatbotError("unauthorized:chat").toResponse(); } const chat = await getChatById({ id }); if (chat?.userId !== session.user.id) { - return new OpenChatError("forbidden:chat").toResponse(); + return new ChatbotError("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 2caa241f6e..fe912a1e61 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 { OpenChatError } from "@/lib/errors"; +import { ChatbotError } from "@/lib/errors"; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const id = searchParams.get("id"); if (!id) { - return new OpenChatError( + return new ChatbotError( "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 OpenChatError("unauthorized:document").toResponse(); + return new ChatbotError("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 OpenChatError("not_found:document").toResponse(); + return new ChatbotError("not_found:document").toResponse(); } if (document.userId !== session.user.id) { - return new OpenChatError("forbidden:document").toResponse(); + return new ChatbotError("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 OpenChatError( + return new ChatbotError( "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 OpenChatError("not_found:document").toResponse(); + return new ChatbotError("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 OpenChatError("forbidden:document").toResponse(); + return new ChatbotError("forbidden:document").toResponse(); } } @@ -90,14 +90,14 @@ export async function DELETE(request: Request) { const timestamp = searchParams.get("timestamp"); if (!id) { - return new OpenChatError( + return new ChatbotError( "bad_request:api", "Parameter id is required." ).toResponse(); } if (!timestamp) { - return new OpenChatError( + return new ChatbotError( "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 OpenChatError("unauthorized:document").toResponse(); + return new ChatbotError("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 OpenChatError("forbidden:document").toResponse(); + return new ChatbotError("forbidden:document").toResponse(); } const documentsDeleted = await deleteDocumentsByIdAfterTimestamp({ diff --git a/app/(chat)/api/history/route.ts b/app/(chat)/api/history/route.ts index c7223ec260..f8b7f9ed48 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 { OpenChatError } from "@/lib/errors"; +import { ChatbotError } 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 OpenChatError( + return new ChatbotError( "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 OpenChatError("unauthorized:chat").toResponse(); + return new ChatbotError("unauthorized:chat").toResponse(); } const chats = await getChatsByUserId({ @@ -37,7 +37,7 @@ export async function DELETE() { const session = await auth(); if (!session?.user) { - return new OpenChatError("unauthorized:chat").toResponse(); + return new ChatbotError("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 054994b09b..303f45ed26 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 { OpenChatError } from "@/lib/errors"; +import { ChatbotError } from "@/lib/errors"; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const documentId = searchParams.get("documentId"); if (!documentId) { - return new OpenChatError( + return new ChatbotError( "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 OpenChatError("unauthorized:suggestions").toResponse(); + return new ChatbotError("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 OpenChatError("forbidden:api").toResponse(); + return new ChatbotError("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 d2c8ce170a..4a2e4bf412 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 { OpenChatError } from "@/lib/errors"; +import { ChatbotError } from "@/lib/errors"; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const chatId = searchParams.get("chatId"); if (!chatId) { - return new OpenChatError( + return new ChatbotError( "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 OpenChatError("unauthorized:vote").toResponse(); + return new ChatbotError("unauthorized:vote").toResponse(); } const chat = await getChatById({ id: chatId }); if (!chat) { - return new OpenChatError("not_found:chat").toResponse(); + return new ChatbotError("not_found:chat").toResponse(); } if (chat.userId !== session.user.id) { - return new OpenChatError("forbidden:vote").toResponse(); + return new ChatbotError("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 OpenChatError( + return new ChatbotError( "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 OpenChatError("unauthorized:vote").toResponse(); + return new ChatbotError("unauthorized:vote").toResponse(); } const chat = await getChatById({ id: chatId }); if (!chat) { - return new OpenChatError("not_found:vote").toResponse(); + return new ChatbotError("not_found:vote").toResponse(); } if (chat.userId !== session.user.id) { - return new OpenChatError("forbidden:vote").toResponse(); + return new ChatbotError("forbidden:vote").toResponse(); } await voteMessage({ diff --git a/app/(chat)/opengraph-image.png b/app/(chat)/opengraph-image.png index 73bc344d60..c8402717a1 100644 Binary files a/app/(chat)/opengraph-image.png and b/app/(chat)/opengraph-image.png differ diff --git a/components/app-sidebar.tsx b/components/app-sidebar.tsx index 30d058bc20..1025827e48 100644 --- a/components/app-sidebar.tsx +++ b/components/app-sidebar.tsx @@ -41,9 +41,12 @@ export function AppSidebar({ user }: { user: User | undefined }) { const [showDeleteAllDialog, setShowDeleteAllDialog] = useState(false); const handleDeleteAll = () => { - const deletePromise = fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/history`, { - method: "DELETE", - }); + const deletePromise = fetch( + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/history`, + { + method: "DELETE", + } + ); toast.promise(deletePromise, { loading: "Deleting all chats...", @@ -72,7 +75,7 @@ export function AppSidebar({ user }: { user: User | undefined }) { }} > - OpenChat + Chatbot

diff --git a/components/artifact.tsx b/components/artifact.tsx index 5a64d90a98..333991a7f4 100644 --- a/components/artifact.tsx +++ b/components/artifact.tsx @@ -149,14 +149,17 @@ function PureArtifact({ } if (currentDocument.content !== updatedContent) { - await fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/document?id=${artifact.documentId}`, { - method: "POST", - body: JSON.stringify({ - title: artifact.title, - content: updatedContent, - kind: artifact.kind, - }), - }); + await fetch( + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/document?id=${artifact.documentId}`, + { + method: "POST", + body: JSON.stringify({ + title: artifact.title, + content: updatedContent, + kind: artifact.kind, + }), + } + ); setIsContentDirty(false); diff --git a/components/chat-header.tsx b/components/chat-header.tsx index 528d623111..1f15d08358 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/components/chat.tsx b/components/chat.tsx index bc96f2677b..807864e923 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 { OpenChatError } from "@/lib/errors"; +import { ChatbotError } 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 OpenChatError) { + if (error instanceof ChatbotError) { if ( error.message?.includes("AI Gateway requires a valid credit card") ) { @@ -166,12 +166,18 @@ export function Chat({ }); setHasAppendedQuery(true); - window.history.replaceState({}, "", `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/chat/${id}`); + window.history.replaceState( + {}, + "", + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/chat/${id}` + ); } }, [query, sendMessage, hasAppendedQuery, id]); const { data: votes } = useSWR( - messages.length >= 2 ? `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote?chatId=${id}` : null, + messages.length >= 2 + ? `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote?chatId=${id}` + : null, fetcher ); diff --git a/components/message-actions.tsx b/components/message-actions.tsx index ff5d8a9007..ae799197fd 100644 --- a/components/message-actions.tsx +++ b/components/message-actions.tsx @@ -77,14 +77,17 @@ export function PureMessageActions({ data-testid="message-upvote" disabled={vote?.isUpvoted} onClick={() => { - const upvote = fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote`, { - method: "PATCH", - body: JSON.stringify({ - chatId, - messageId: message.id, - type: "up", - }), - }); + const upvote = fetch( + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote`, + { + method: "PATCH", + body: JSON.stringify({ + chatId, + messageId: message.id, + type: "up", + }), + } + ); toast.promise(upvote, { loading: "Upvoting Response...", @@ -126,14 +129,17 @@ export function PureMessageActions({ data-testid="message-downvote" disabled={vote && !vote.isUpvoted} onClick={() => { - const downvote = fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote`, { - method: "PATCH", - body: JSON.stringify({ - chatId, - messageId: message.id, - type: "down", - }), - }); + const downvote = fetch( + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote`, + { + method: "PATCH", + body: JSON.stringify({ + chatId, + messageId: message.id, + type: "down", + }), + } + ); toast.promise(downvote, { loading: "Downvoting Response...", diff --git a/components/multimodal-input.tsx b/components/multimodal-input.tsx index 2977957c76..9ab8338a96 100644 --- a/components/multimodal-input.tsx +++ b/components/multimodal-input.tsx @@ -145,7 +145,11 @@ function PureMultimodalInput({ const [uploadQueue, setUploadQueue] = useState([]); const submitForm = useCallback(() => { - window.history.pushState({}, "", `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/chat/${chatId}`); + window.history.pushState( + {}, + "", + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/chat/${chatId}` + ); sendMessage({ role: "user", @@ -188,10 +192,13 @@ function PureMultimodalInput({ formData.append("file", file); try { - const response = await fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/files/upload`, { - method: "POST", - body: formData, - }); + const response = await fetch( + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/files/upload`, + { + method: "POST", + body: formData, + } + ); if (response.ok) { const data = await response.json(); diff --git a/components/sidebar-history.tsx b/components/sidebar-history.tsx index 80c79a8cb3..4aecfe24bf 100644 --- a/components/sidebar-history.tsx +++ b/components/sidebar-history.tsx @@ -130,9 +130,12 @@ export function SidebarHistory({ user }: { user: User | undefined }) { setShowDeleteDialog(false); - const deletePromise = fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/chat?id=${chatToDelete}`, { - method: "DELETE", - }); + const deletePromise = fetch( + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/chat?id=${chatToDelete}`, + { + method: "DELETE", + } + ); toast.promise(deletePromise, { loading: "Deleting chat...", diff --git a/components/suggested-actions.tsx b/components/suggested-actions.tsx index a278a2c921..55e7267113 100644 --- a/components/suggested-actions.tsx +++ b/components/suggested-actions.tsx @@ -37,7 +37,11 @@ function PureSuggestedActions({ chatId, sendMessage }: SuggestedActionsProps) { { - window.history.pushState({}, "", `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/chat/${chatId}`); + window.history.pushState( + {}, + "", + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/chat/${chatId}` + ); sendMessage({ role: "user", parts: [{ type: "text", text: suggestion }], diff --git a/hooks/use-chat-visibility.ts b/hooks/use-chat-visibility.ts index d9d141f480..3134e59dc2 100644 --- a/hooks/use-chat-visibility.ts +++ b/hooks/use-chat-visibility.ts @@ -18,7 +18,9 @@ export function useChatVisibility({ initialVisibilityType: VisibilityType; }) { const { mutate, cache } = useSWRConfig(); - const history: ChatHistory = cache.get(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/history`)?.data; + const history: ChatHistory = cache.get( + `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/history` + )?.data; const { data: localVisibility, mutate: setLocalVisibility } = useSWR( `${chatId}-visibility`, diff --git a/instrumentation.ts b/instrumentation.ts index 632a2f7454..f97d49bf7c 100644 --- a/instrumentation.ts +++ b/instrumentation.ts @@ -1,5 +1,5 @@ import { registerOTel } from "@vercel/otel"; export function register() { - registerOTel({ serviceName: "openchat" }); + registerOTel({ serviceName: "chatbot" }); } diff --git a/lib/db/queries.ts b/lib/db/queries.ts index 63f012e951..23cad721c9 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 { OpenChatError } from "../errors"; +import { ChatbotError } 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 OpenChatError( + throw new ChatbotError( "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 OpenChatError("bad_request:database", "Failed to create user"); + throw new ChatbotError("bad_request:database", "Failed to create user"); } } @@ -72,7 +72,7 @@ export async function createGuestUser() { email: user.email, }); } catch (_error) { - throw new OpenChatError( + throw new ChatbotError( "bad_request:database", "Failed to create guest user" ); @@ -99,7 +99,7 @@ export async function saveChat({ visibility, }); } catch (_error) { - throw new OpenChatError("bad_request:database", "Failed to save chat"); + throw new ChatbotError("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 OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "not_found:database", `Chat with id ${startingAfter} not found` ); @@ -204,7 +204,7 @@ export async function getChatsByUserId({ .limit(1); if (!selectedChat) { - throw new OpenChatError( + throw new ChatbotError( "not_found:database", `Chat with id ${endingBefore} not found` ); @@ -222,7 +222,7 @@ export async function getChatsByUserId({ hasMore, }; } catch (_error) { - throw new OpenChatError( + throw new ChatbotError( "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 OpenChatError("bad_request:database", "Failed to get chat by id"); + throw new ChatbotError("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 OpenChatError("bad_request:database", "Failed to save messages"); + throw new ChatbotError("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 OpenChatError("bad_request:database", "Failed to update message"); + throw new ChatbotError("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 OpenChatError( + throw new ChatbotError( "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 OpenChatError("bad_request:database", "Failed to vote message"); + throw new ChatbotError("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 OpenChatError( + throw new ChatbotError( "bad_request:database", "Failed to get votes by chat id" ); @@ -347,7 +347,7 @@ export async function saveDocument({ }) .returning(); } catch (_error) { - throw new OpenChatError("bad_request:database", "Failed to save document"); + throw new ChatbotError("bad_request:database", "Failed to save document"); } } @@ -361,7 +361,7 @@ export async function getDocumentsById({ id }: { id: string }) { return documents; } catch (_error) { - throw new OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "bad_request:database", "Failed to get message by id" ); @@ -491,7 +491,7 @@ export async function deleteMessagesByChatIdAfterTimestamp({ ); } } catch (_error) { - throw new OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "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 OpenChatError( + throw new ChatbotError( "bad_request:database", "Failed to get stream ids by chat id" ); diff --git a/lib/db/schema.ts b/lib/db/schema.ts index 803e652689..ade93189fe 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://openchat.dev/docs/migration-guides/message-parts +// Read the migration guide at https://chatbot.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://openchat.dev/docs/migration-guides/message-parts +// Read the migration guide at https://chatbot.dev/docs/migration-guides/message-parts export const voteDeprecated = pgTable( "Vote", { diff --git a/lib/errors.ts b/lib/errors.ts index bfa5d4d2cb..bae6668bae 100644 --- a/lib/errors.ts +++ b/lib/errors.ts @@ -35,7 +35,7 @@ export const visibilityBySurface: Record = { activate_gateway: "response", }; -export class OpenChatError extends Error { +export class ChatbotError extends Error { type: ErrorType; surface: Surface; statusCode: number; diff --git a/lib/utils.ts b/lib/utils.ts index 01c13ea1e5..6fce6ac8be 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 { OpenChatError, type ErrorCode } from './errors'; +import { ChatbotError, 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 OpenChatError(code as ErrorCode, cause); + throw new ChatbotError(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 OpenChatError(code as ErrorCode, cause); + throw new ChatbotError(code as ErrorCode, cause); } return response; } catch (error: unknown) { if (typeof navigator !== 'undefined' && !navigator.onLine) { - throw new OpenChatError('offline:chat'); + throw new ChatbotError('offline:chat'); } throw error; diff --git a/package.json b/package.json index 77050da857..5cccc5ffbf 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "openchat", + "name": "chatbot", "version": "3.1.0", "private": true, "scripts": {