rename openchat branding to chatbot on demo (#1421)
This commit is contained in:
parent
72597d6f68
commit
e7ef7d8f9c
22 changed files with 161 additions and 127 deletions
14
README.md
14
README.md
|
|
@ -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 OpenChat." src="app/(chat)/opengraph-image.png">
|
<img alt="Next.js 14 and App Router-ready Chatbot." src="app/(chat)/opengraph-image.png">
|
||||||
<h1 align="center">OpenChat</h1>
|
<h1 align="center">Chatbot</h1>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
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.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://openchat.dev"><strong>Read Docs</strong></a> ·
|
<a href="https://chatbot.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 OpenChat to Vercel with one click:
|
You can deploy your own version of Chatbot to Vercel with one click:
|
||||||
|
|
||||||
[](https://vercel.com/templates/next.js/openchat)
|
[](https://vercel.com/templates/next.js/chatbot)
|
||||||
|
|
||||||
## Running locally
|
## 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.
|
> 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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 { OpenChatError } from "@/lib/errors";
|
import { ChatbotError } 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 OpenChatError("bad_request:api").toResponse();
|
return new ChatbotError("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 OpenChatError("unauthorized:chat").toResponse();
|
return new ChatbotError("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 OpenChatError("rate_limit:chat").toResponse();
|
return new ChatbotError("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 OpenChatError("forbidden:chat").toResponse();
|
return new ChatbotError("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 OpenChatError) {
|
if (error instanceof ChatbotError) {
|
||||||
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 OpenChatError("bad_request:activate_gateway").toResponse();
|
return new ChatbotError("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 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");
|
const id = searchParams.get("id");
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return new OpenChatError("bad_request:api").toResponse();
|
return new ChatbotError("bad_request:api").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
|
|
||||||
if (!session?.user) {
|
if (!session?.user) {
|
||||||
return new OpenChatError("unauthorized:chat").toResponse();
|
return new ChatbotError("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 OpenChatError("forbidden:chat").toResponse();
|
return new ChatbotError("forbidden:chat").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
const deletedChat = await deleteChatById({ id });
|
const deletedChat = await deleteChatById({ id });
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,14 @@ import {
|
||||||
getDocumentsById,
|
getDocumentsById,
|
||||||
saveDocument,
|
saveDocument,
|
||||||
} from "@/lib/db/queries";
|
} from "@/lib/db/queries";
|
||||||
import { OpenChatError } from "@/lib/errors";
|
import { ChatbotError } 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 OpenChatError(
|
return new ChatbotError(
|
||||||
"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 OpenChatError("unauthorized:document").toResponse();
|
return new ChatbotError("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 OpenChatError("not_found:document").toResponse();
|
return new ChatbotError("not_found:document").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.userId !== session.user.id) {
|
if (document.userId !== session.user.id) {
|
||||||
return new OpenChatError("forbidden:document").toResponse();
|
return new ChatbotError("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 OpenChatError(
|
return new ChatbotError(
|
||||||
"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 OpenChatError("not_found:document").toResponse();
|
return new ChatbotError("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 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");
|
const timestamp = searchParams.get("timestamp");
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return new OpenChatError(
|
return new ChatbotError(
|
||||||
"bad_request:api",
|
"bad_request:api",
|
||||||
"Parameter id is required."
|
"Parameter id is required."
|
||||||
).toResponse();
|
).toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!timestamp) {
|
if (!timestamp) {
|
||||||
return new OpenChatError(
|
return new ChatbotError(
|
||||||
"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 OpenChatError("unauthorized:document").toResponse();
|
return new ChatbotError("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 OpenChatError("forbidden:document").toResponse();
|
return new ChatbotError("forbidden:document").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
const documentsDeleted = await deleteDocumentsByIdAfterTimestamp({
|
const documentsDeleted = await deleteDocumentsByIdAfterTimestamp({
|
||||||
|
|
|
||||||
|
|
@ -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 { OpenChatError } from "@/lib/errors";
|
import { ChatbotError } 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 OpenChatError(
|
return new ChatbotError(
|
||||||
"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 OpenChatError("unauthorized:chat").toResponse();
|
return new ChatbotError("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 OpenChatError("unauthorized:chat").toResponse();
|
return new ChatbotError("unauthorized:chat").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await deleteAllChatsByUserId({ userId: session.user.id });
|
const result = await deleteAllChatsByUserId({ userId: session.user.id });
|
||||||
|
|
|
||||||
|
|
@ -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 { OpenChatError } from "@/lib/errors";
|
import { ChatbotError } 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 OpenChatError(
|
return new ChatbotError(
|
||||||
"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 OpenChatError("unauthorized:suggestions").toResponse();
|
return new ChatbotError("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 OpenChatError("forbidden:api").toResponse();
|
return new ChatbotError("forbidden:api").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response.json(suggestions, { status: 200 });
|
return Response.json(suggestions, { status: 200 });
|
||||||
|
|
|
||||||
|
|
@ -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 { OpenChatError } from "@/lib/errors";
|
import { ChatbotError } 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 OpenChatError(
|
return new ChatbotError(
|
||||||
"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 OpenChatError("unauthorized:vote").toResponse();
|
return new ChatbotError("unauthorized:vote").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
const chat = await getChatById({ id: chatId });
|
const chat = await getChatById({ id: chatId });
|
||||||
|
|
||||||
if (!chat) {
|
if (!chat) {
|
||||||
return new OpenChatError("not_found:chat").toResponse();
|
return new ChatbotError("not_found:chat").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chat.userId !== session.user.id) {
|
if (chat.userId !== session.user.id) {
|
||||||
return new OpenChatError("forbidden:vote").toResponse();
|
return new ChatbotError("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 OpenChatError(
|
return new ChatbotError(
|
||||||
"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 OpenChatError("unauthorized:vote").toResponse();
|
return new ChatbotError("unauthorized:vote").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
const chat = await getChatById({ id: chatId });
|
const chat = await getChatById({ id: chatId });
|
||||||
|
|
||||||
if (!chat) {
|
if (!chat) {
|
||||||
return new OpenChatError("not_found:vote").toResponse();
|
return new ChatbotError("not_found:vote").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chat.userId !== session.user.id) {
|
if (chat.userId !== session.user.id) {
|
||||||
return new OpenChatError("forbidden:vote").toResponse();
|
return new ChatbotError("forbidden:vote").toResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
await voteMessage({
|
await voteMessage({
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 14 KiB |
|
|
@ -41,9 +41,12 @@ export function AppSidebar({ user }: { user: User | undefined }) {
|
||||||
const [showDeleteAllDialog, setShowDeleteAllDialog] = useState(false);
|
const [showDeleteAllDialog, setShowDeleteAllDialog] = useState(false);
|
||||||
|
|
||||||
const handleDeleteAll = () => {
|
const handleDeleteAll = () => {
|
||||||
const deletePromise = fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/history`, {
|
const deletePromise = fetch(
|
||||||
method: "DELETE",
|
`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/history`,
|
||||||
});
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
toast.promise(deletePromise, {
|
toast.promise(deletePromise, {
|
||||||
loading: "Deleting all chats...",
|
loading: "Deleting all chats...",
|
||||||
|
|
@ -72,7 +75,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">
|
||||||
OpenChat
|
Chatbot
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="flex flex-row gap-1">
|
<div className="flex flex-row gap-1">
|
||||||
|
|
|
||||||
|
|
@ -149,14 +149,17 @@ function PureArtifact({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentDocument.content !== updatedContent) {
|
if (currentDocument.content !== updatedContent) {
|
||||||
await fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/document?id=${artifact.documentId}`, {
|
await fetch(
|
||||||
method: "POST",
|
`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/document?id=${artifact.documentId}`,
|
||||||
body: JSON.stringify({
|
{
|
||||||
title: artifact.title,
|
method: "POST",
|
||||||
content: updatedContent,
|
body: JSON.stringify({
|
||||||
kind: artifact.kind,
|
title: artifact.title,
|
||||||
}),
|
content: updatedContent,
|
||||||
});
|
kind: artifact.kind,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
setIsContentDirty(false);
|
setIsContentDirty(false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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/openchat"}
|
href={"https://vercel.com/templates/next.js/chatbot"}
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
target="_noblank"
|
target="_noblank"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -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 { OpenChatError } from "@/lib/errors";
|
import { ChatbotError } 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 OpenChatError) {
|
if (error instanceof ChatbotError) {
|
||||||
if (
|
if (
|
||||||
error.message?.includes("AI Gateway requires a valid credit card")
|
error.message?.includes("AI Gateway requires a valid credit card")
|
||||||
) {
|
) {
|
||||||
|
|
@ -166,12 +166,18 @@ export function Chat({
|
||||||
});
|
});
|
||||||
|
|
||||||
setHasAppendedQuery(true);
|
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]);
|
}, [query, sendMessage, hasAppendedQuery, id]);
|
||||||
|
|
||||||
const { data: votes } = useSWR<Vote[]>(
|
const { data: votes } = useSWR<Vote[]>(
|
||||||
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
|
fetcher
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,14 +77,17 @@ export function PureMessageActions({
|
||||||
data-testid="message-upvote"
|
data-testid="message-upvote"
|
||||||
disabled={vote?.isUpvoted}
|
disabled={vote?.isUpvoted}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const upvote = fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote`, {
|
const upvote = fetch(
|
||||||
method: "PATCH",
|
`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote`,
|
||||||
body: JSON.stringify({
|
{
|
||||||
chatId,
|
method: "PATCH",
|
||||||
messageId: message.id,
|
body: JSON.stringify({
|
||||||
type: "up",
|
chatId,
|
||||||
}),
|
messageId: message.id,
|
||||||
});
|
type: "up",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
toast.promise(upvote, {
|
toast.promise(upvote, {
|
||||||
loading: "Upvoting Response...",
|
loading: "Upvoting Response...",
|
||||||
|
|
@ -126,14 +129,17 @@ export function PureMessageActions({
|
||||||
data-testid="message-downvote"
|
data-testid="message-downvote"
|
||||||
disabled={vote && !vote.isUpvoted}
|
disabled={vote && !vote.isUpvoted}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const downvote = fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote`, {
|
const downvote = fetch(
|
||||||
method: "PATCH",
|
`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/vote`,
|
||||||
body: JSON.stringify({
|
{
|
||||||
chatId,
|
method: "PATCH",
|
||||||
messageId: message.id,
|
body: JSON.stringify({
|
||||||
type: "down",
|
chatId,
|
||||||
}),
|
messageId: message.id,
|
||||||
});
|
type: "down",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
toast.promise(downvote, {
|
toast.promise(downvote, {
|
||||||
loading: "Downvoting Response...",
|
loading: "Downvoting Response...",
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,11 @@ function PureMultimodalInput({
|
||||||
const [uploadQueue, setUploadQueue] = useState<string[]>([]);
|
const [uploadQueue, setUploadQueue] = useState<string[]>([]);
|
||||||
|
|
||||||
const submitForm = useCallback(() => {
|
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({
|
sendMessage({
|
||||||
role: "user",
|
role: "user",
|
||||||
|
|
@ -188,10 +192,13 @@ function PureMultimodalInput({
|
||||||
formData.append("file", file);
|
formData.append("file", file);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/files/upload`, {
|
const response = await fetch(
|
||||||
method: "POST",
|
`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/files/upload`,
|
||||||
body: formData,
|
{
|
||||||
});
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
|
||||||
|
|
@ -130,9 +130,12 @@ export function SidebarHistory({ user }: { user: User | undefined }) {
|
||||||
|
|
||||||
setShowDeleteDialog(false);
|
setShowDeleteDialog(false);
|
||||||
|
|
||||||
const deletePromise = fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/chat?id=${chatToDelete}`, {
|
const deletePromise = fetch(
|
||||||
method: "DELETE",
|
`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/chat?id=${chatToDelete}`,
|
||||||
});
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
toast.promise(deletePromise, {
|
toast.promise(deletePromise, {
|
||||||
loading: "Deleting chat...",
|
loading: "Deleting chat...",
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,11 @@ function PureSuggestedActions({ chatId, sendMessage }: SuggestedActionsProps) {
|
||||||
<Suggestion
|
<Suggestion
|
||||||
className="h-auto w-full whitespace-normal p-3 text-left"
|
className="h-auto w-full whitespace-normal p-3 text-left"
|
||||||
onClick={(suggestion) => {
|
onClick={(suggestion) => {
|
||||||
window.history.pushState({}, "", `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/chat/${chatId}`);
|
window.history.pushState(
|
||||||
|
{},
|
||||||
|
"",
|
||||||
|
`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/chat/${chatId}`
|
||||||
|
);
|
||||||
sendMessage({
|
sendMessage({
|
||||||
role: "user",
|
role: "user",
|
||||||
parts: [{ type: "text", text: suggestion }],
|
parts: [{ type: "text", text: suggestion }],
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ export function useChatVisibility({
|
||||||
initialVisibilityType: VisibilityType;
|
initialVisibilityType: VisibilityType;
|
||||||
}) {
|
}) {
|
||||||
const { mutate, cache } = useSWRConfig();
|
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(
|
const { data: localVisibility, mutate: setLocalVisibility } = useSWR(
|
||||||
`${chatId}-visibility`,
|
`${chatId}-visibility`,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { registerOTel } from "@vercel/otel";
|
import { registerOTel } from "@vercel/otel";
|
||||||
|
|
||||||
export function register() {
|
export function register() {
|
||||||
registerOTel({ serviceName: "openchat" });
|
registerOTel({ serviceName: "chatbot" });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 { OpenChatError } from "../errors";
|
import { ChatbotError } 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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 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,
|
email: user.email,
|
||||||
});
|
});
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
throw new OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 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();
|
.returning();
|
||||||
return chatsDeleted;
|
return chatsDeleted;
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
throw new OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 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 {
|
try {
|
||||||
return await db.insert(message).values(messages);
|
return await db.insert(message).values(messages);
|
||||||
} catch (_error) {
|
} 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 {
|
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 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))
|
.where(eq(message.chatId, id))
|
||||||
.orderBy(asc(message.createdAt));
|
.orderBy(asc(message.createdAt));
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
throw new OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 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 {
|
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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 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;
|
return documents;
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
throw new OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"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 OpenChatError(
|
throw new ChatbotError(
|
||||||
"bad_request:database",
|
"bad_request:database",
|
||||||
"Failed to get stream ids by chat id"
|
"Failed to get stream ids by chat id"
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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://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", {
|
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://openchat.dev/docs/migration-guides/message-parts
|
// Read the migration guide at https://chatbot.dev/docs/migration-guides/message-parts
|
||||||
export const voteDeprecated = pgTable(
|
export const voteDeprecated = pgTable(
|
||||||
"Vote",
|
"Vote",
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ export const visibilityBySurface: Record<Surface, ErrorVisibility> = {
|
||||||
activate_gateway: "response",
|
activate_gateway: "response",
|
||||||
};
|
};
|
||||||
|
|
||||||
export class OpenChatError extends Error {
|
export class ChatbotError extends Error {
|
||||||
type: ErrorType;
|
type: ErrorType;
|
||||||
surface: Surface;
|
surface: Surface;
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
|
|
|
||||||
|
|
@ -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 { OpenChatError, type ErrorCode } from './errors';
|
import { ChatbotError, 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 OpenChatError(code as ErrorCode, cause);
|
throw new ChatbotError(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 OpenChatError(code as ErrorCode, cause);
|
throw new ChatbotError(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 OpenChatError('offline:chat');
|
throw new ChatbotError('offline:chat');
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "openchat",
|
"name": "chatbot",
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue