From 1ac0653c89a170c70435fd7e4ec672f1136ac5cd Mon Sep 17 00:00:00 2001 From: dancer <144584931+dancer@users.noreply.github.com> Date: Tue, 24 Feb 2026 00:19:49 +0000 Subject: [PATCH 1/2] rename branding to chatbot on demo --- README.md | 14 +++---- app/(chat)/api/chat/route.ts | 22 +++++------ app/(chat)/api/document/route.ts | 24 ++++++------ app/(chat)/api/history/route.ts | 8 ++-- app/(chat)/api/suggestions/route.ts | 8 ++-- app/(chat)/api/vote/route.ts | 18 ++++----- app/(chat)/opengraph-image.png | Bin 34687 -> 14418 bytes components/app-sidebar.tsx | 2 +- components/chat-header.tsx | 2 +- components/chat.tsx | 4 +- instrumentation.ts | 2 +- lib/db/queries.ts | 56 ++++++++++++++-------------- lib/db/schema.ts | 4 +- lib/errors.ts | 2 +- lib/utils.ts | 8 ++-- package.json | 2 +- 16 files changed, 88 insertions(+), 88 deletions(-) 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 73bc344d60419a7d4a105ae604c8ed2df2aa8837..c8402717a1d1cc0f37cffefe3a2b8930588e74f3 100644 GIT binary patch literal 14418 zcmbumWmFtZ)Gj)>y99S<(BK4jCTNhs83+*EA-Dwhkl^kFhAT_rt|_ zDiJr~a{vI)a`j&tsXg7Yu&^j9Dz2}u_xJbP+S;N}C{j|=h=_>D$jFnElai7WG&D4H zbaVm&f@ja3(a_K^Ffh>5(^FAV;o;$7Vq#KIP>_(2kdu=W6BCn>k>TRvVq;^|(b3V; z(qds@;o#s95fKp*5>iuBGcq!=v$F$%KtVx4K0ZEHR#qM!9)5m)e0+RfUS1|9CJYP= zPEJm4Zf+dDS9pvP7^a<=s;PL-xB*`0==Mk~xdkdP2uc2zXzElibEadB}K6%`K;4@~VsG?y)GNiPHffi3Bon3(A9?w*vC zglSNRW{P_3@6#u2tdbNPeIu7=B@hDS<^E#ZwL0zrR`M7JKnWfI3Qs6)3J#TJ1G z3k!RBc}-1CH8wV;r>E=d>w9{7W@KcPmX^X`FaZGpHa0e9W@Zi!4r60u9UUDtHMQr@ zpC=?FgolS)Sy?$cI>yJxzj*ONOiawk$jIK_J|G}KRaN!n%a`iv>eklQK0ZDc78VW; z4pLH5Y)KL10Dy$Qma3A`TeQQa4V^e!8q5KlDATORyUSN9Xpit6~Proa%2NV~J ztxTe65<(T10Gf0ji7jYRfVki(>y`B1#)*DYj)r5#{1YCydLDa zC}_su)S;??)VnFAM^{8CjWr~nr-iXNRKqryK!ahIHox)kjX7H;`DVyR6x+WVPZmry z3&!IgIWvjRv zx^)%Y;?0xBw)Dk8pLmg;<#opU!dEJ8wFUHfa&A1HMAC6;0&$oNqR+Ck2!=>C7>a`f zRFu0$y&)a#4riv1Va$*5m;l_3bXim0Kqn&}PVJ#Ag2P?3Z`98RaeVM^n{d37Kgkg# zVmYKy$;^mhv*0o%Cx!?Q(le?`3S{=5t?&8hW;seEkc>&2ZdJMahH0^$BgWSfjp^`v zz|$Z_hfTZ?g^GG>Y#*K@QRwW ztrw`suzHvd$Cjrl#?&B2-F{lsQkl~>#d(y+_D?_y|Kv10=B@@rGkZg@)p#$|DA|6v zdg`*NPC9bhiE>iZh8fL1r}UovoaqmBT}Q3%e^{ue`TZ4}p5*4vIe#1NTl(tEcjz`; zG^;TZBRla^fZhY?F$T@8e~qjJYLq)Nv_sU&SS7*U3hmn9TBOHB!8jF;aF$?hDqfGf z-7FY6c(*4Q4j7c)&feLO*6U+gSM4wVFs_dZ#sEKT9SIXifKkEpo2@&|xI{$FVII2plcqj~<%sRfZB z^q&5PG+l7yQQA_h#6R?&7!PSXG>7&I zxuHKqq$NJq20vbj|uU2r+#=D86_fyq?4T?#U@ z5SiyFiXsK;l7YGEKCT9KkO^*1VP?O=G~xX+doZ~#PZn1aRuN|`PvHY+Yw|HI7S7+K zNv%jxIPvBMj<_cshkJ7x32+hyxnUwx8e{&--CN32;L}8K!F~lXBU2c|Unn%8O#f-` z(z+8FYB!X6`k_h$qMkbF;B%ivnxf##>6Z+b2~O2zqV(Gt9Gv=2jyN$@9xf?!xHpSU zt@zyJZA23>9N&jsMlvpr90%3_gN%4UGmG(C&!Sr8zEa7q^4euJ#S3r)+dIggnx0++ zc4H85h#GH`#$}pG|xdsK!sOm#kyRR5=c>tcz0Qa-}WKzjn^lg`7ZgcQBK)36sRqZ>oQa2)dJL zTGJEHg(ex4lkwz(0M*G=sik3&FsCHb@Oh z$1{7yW3*Amu@Yg8oociMJs_TMw8?dMXTL0J1-nQe?`&isDOO!<)A3mmqx@;$E>r~k z(dpzx$EIVGaLbY!RA5maRW|x9ILt!%UT)&+H{NUTa`W#OP_4+z*XNp*GV)p~ zKoN?ZcOkq(uFnel70iptO=Gj!T!~=6MKo!_|8y=N-V=?JA=Bpo2V-*++keJlY-+Tq zU9Fc&Ye_Rie*3$EOjeXRd$El4c|E4ndJeTG9c{PH)it)RLt~LXj7U=-x5wkR6n-y` zNrVK$QSmg%s}Hb9<1B3kHq-sV$X0ff+NIK|W*_2l)TlpLI-cso$vAgf_`hWuy`n-Z z(*2*C-t;&3zi&_9f#q(uLWrPw3{<~Kd1Yj9!4{%Sd7*l`&{u2Z+cf;=F8B1XYT^Ua zxv({6N%}+FsmY8%nF1q;`%qeNmZ9K;hZe6_9#`gN{N!RCJ#mMO${r zlwk17e9mkmoXqu$_I zR!#p@B#QR3=)}5Ux{Bphm$pczDIl4?dC6>gs$F~ue=;~AVND}WJB6S%852>j2xfj&y^2)gXkL}eows38MZv|KlqF|{C58_Yg@rn zg4?&gM;6DVhQ$$4r3QA0i$KH~5a_<7kh2)>IEg=|hNDX-NyC11q+9X98!s7Ue`S!J zL>U{3zfG40`UPTuDH%%V2*LKm{8lN#MtGzWmZR^Z1`-!%!$b487&rKAR}T^|i|)DR zEf;=8sGkelGI~lxR~h{iE~aq^WxMdedv*-NUmIV%y?!^27L#Ojug#iI@XZ2o zf@b`0b1Dy<(Bf@As05c;w%py@qqEJzqAXP*bR^-|t@7;1t|S!!?A4Ng>i8^x20oUt zRWf|$!2An50-5_7@OJ^Do~yzZ04pcllminIeem=|r_O_jXo#dwehXhRcBj>1A+)vw zbm~gSiy!0q&dT*~^NSH}7hw>om)E@RqTk&~%(HE^WC-Bm9I zKDNhfF5`WX*BN5iu46!2N%ub9DKOz!D(Nw!*onUUA$b-_^)6F}G~v~=XmXICI@tSb zLs>J@Fjvi1df4sg20-??K&}a&r(RZ_F*3GqZTfrUR>^8yTJ=fof;!m$hKwC5mzA0c z0VOPZYk+CEn~~~Z`+YVIu=H2N6o?GzsZe6A@Y8a3-Q(O?S%pRb@XerJ3vWh*$wS#) z58Gi?zvF8TJ2dkmS2=Uk$$34XtETigs_Gr2n_Ci#TDdIW$S}!v@bEL5iRDWTVpJFXH2pY}illQB^TiR9*;21tH%K?egj^wf^3I_cups81O)x9Kn{;dMh* zLtZySn3Sy@Xck(>@XY&ACX?G7@q<^C<%cwHgxv8W7cP#69#$Q7k5e|FzP#60R8W1O@yxzil;!(~XWUFDAyejMp5+`&2BCb$ zSCU!S9@9kQx-mF)t|z8~Dm=$8`Ctw8ll+5K!R`{p!&UxP%etr}N9`m{bBz#q&t$jlD+WjbJu-3Ybazn0LnVur2)1-7^pT67ZdQn^R@j7r8g)}o2_ z!Dm1uC5@@A^$5ogKMrwQ{N~^XmJ`=0HjbCcxqy0li5E0ZY3nu8+@A0yJ;`275*>+S zgY29fvdhVKtMV?tIqoN~>2ySfdr3**CF{XGQB^*W5&e@Ta(buHCnoEFZWz^;9mRQU zV>)V0*7`0l_L14j0nH>|>%#;H3q)!ACN4H#b`j8n_4z!q)qB=AQ7ax@EKTAn$lzD< zzU*`01F#Ys)VGF(LjIcPFT`tf4SKt_)+d8*LOm9oqUtBC$egW5!Dh=kBEvi(!V!XG z4|+BW0iY}B0e1Z~Oy7A%T+tz$zyY(UnV7d&qcA#V&Uc`*c#|n4gNhGnW_cK%u%B^n zKYcU^2WX@BlNR=|lH#D*W2$ja$X?3(%DS_BH?>1i-{?g&Rw8?6einO zW&@%m1db#id=cwyUlSOMEZNQSBh+@@PF2+A>`_2%dkx}&S4GO6IY=eZNx3og`EFB_ zry*MH^UJ_y3dqaAOb-%}rR!h3@u&>=qFHY=Co(kXx# z1i*HY%&Z|~KL2u$A>x|?tOp?_SfY0VL(!bY+k{FJqHMI8e}CX-gDdkp**Rq2p9;%` ze;#R%*@!(HZi%y0tE)-~0+00RH-8@#^=@HKHWFbm8=#9Qm4NHLnD8b7IX1>#x8G#z ze;>?`FuMGfFBB<7u3c|C0W7t3hG2PdeB6KU)uKIccJuE+Kz@Qu=lbqOT=xA~_FlRs zHHC)NSGty_L(Y%Z18f}Gp?H=@Q$sb_RWUuWKE6A^yoTw zASCo&=06pS)~e`2hg{Pu?8`W%p5Lc;)q>)@3Jn-?P5QnMEYL z3JcsLXBO@6V}C8sPI|CRt$<7ZX<6fn(3-Mb{ZLoJBnPlYxVuFT$xz$&fR@ z_C3vvr)bHjS6(&TJxjBGNRcAOmv@dQ*>oaggI0`rHGch|9f%wifSAR6;hxO7pu;aT zt8P*S$LEN%upsPGR>*%pMh%jKiGXj4L-`OgkJ+TJ@vs8_WDBo^6Bc75Iw!2#U*y!XKoSD*Fedb~}bIwb38$}GPGYnVa<4Io<@$VL+} zlDR695dJ&+FZHQnuuJ^(&s~C-v%)h!=^u4HPsB(N_?~hiTG6-i_g#1)gQal-v*_%w zTD5OBH z0)m6zB{R<+cjZzI3S#`riksVn&Vtn;17fVSZwWx8kR$m9)-0~_y_CHM9cQ=v050G` z$sGLa(1I}J9c*pi{bx&KhM)XX%=}IJkK%wnrr9fKTh7awuaOR)p0=4GGnUDqDH%^E z3TmzuC9X95!)KomeObqkX;BKKCMB~&F9@1G3MI7Bw=fO=)ao?@H|dS#@8oNda0@-0 z{rMRadqjNFoTLBi1&QmmGf_kT`MComPY^C-e(?T=Cqv|g>!-HqeR^z?ec62_@Ks=E zZGO?K*!%8T+GG!vEA z!-Md>wR zX1siFg$-u(pP(K58G|+Fg}PVCJhmi*=p35OPxoYZix`o8wC=H^o5iCh@gOx(A<4wO zN%+K8Vz@UJBYsI4-9vt+<^#^{uoVE}JpcU?J;{j3FP!c3v+PgzEUSmLco*Z1(giTl zKX_!+Hh;3bx+WhvP6VM>;t<~4Q;~E1-F(NF&s-av_xvKjPY9J)Jyd%J+-Up0XxoU4T9BO#BBJhr$7*kY zVF5{Pp*As%+-pVLnjNj0#A3M5XDH}#0vQej5q4>A;cR#O)FA5yXR; z7mp>2&wnHPV2wba9jx;M!wexxO@DPVkKM>1S^w$@Wkp<-tMQQ5v#rjB^cU(7=S?{R z2$2&dH620a>;tCeY*-F}pmSQ%HAehU0`jm^0x=9sflZbS-c~MF@*(V!a1TZlyF85(xjQ9|^XCV~N zFy2_OYB@cdE?t9AEWjd0d{!hqTnXGn$AbQKNz1BwLpOWy+w48C(DD5~x7YX2!Rv-- z)a7lsOGX-3s8VXfd zxbI(>VT1RYGQ|LjblQN*Q%)@pi7-s0Klp7;FFSHdQzduXR6yPvrUQ;O_#F9W6Ev#=aq4MH=4SJB z(QZ&n&(*m8t>qpTh4_a5wF54T=z7rez{48$2TS#NIzf0hpQ*YwB!&;*(#Kw&8ZnOv zY3e-ZtR(fd$2`he9PT`(EBPdr8~@?h<Xc(xAO`D-0P=7sr}Q2Y*q3Aw$@7TF7ezOW=luILH`CZ1rHayrwpxRi=F;$(1_r4h zoT8z00B@UHd|EvgAWyZ_cHkO?1{Rq~pLb-Fd}!8bYhne_R(;!duZ@j57!R#94=tg9 z71s0U4Iv;DkvTDieqfC#Bw4(OmD<$$4QRwm7S47SsjDEVfHArLd|wMmYxdux=JCab zY#56y=N(6@g5T=kj?jR@RFzG20I$yzUY`ZU3Qmi+!18P2np~+zLiT9wAEHC%m&~nZq$D>bfu9lTy>g!AO4#5@@8+;a9BdhccVR zaC!+c^a@qW;%^D^G%VH#-e<+9wKogS*~kz*k4EacV$r`Tu+dGfX0`%kmMWyvq7E$g z#R{`h8eo9w>ch{(fCMm$(Gx zsCG>nvnCc<`WXia-4&ee(Te3;&VSyH0YcB0j7lis5v zG19KS94`|;63*EV!+L#%L{Kve464}|Np;hoV|*oHp>_IYLF6l*3`Iq-$0QzS>sToT zxM!O=SGceqCj=lWPa*YH_(7| z;=@N4+bI88bbeKid{b5<32VpWVp!xyG0$?vhB)zsk#VDs+Xm=O6i7>OOY{qc;~ym2hVS)(|EroMxG$U0REzTUDT+a@mZ)WmugkZAb2hT z5NbsXHLD3B4W1=6{P_YZ-ID_=$Dg>RJ3K#Mu|BWj+0(&5^AUqNMsZ#}1eJ3X?8z_C zYkYd*98=T#sW=R*q!v66z>JWEOl>H}uOc^`}Ft$(@Y0uF& zBEP65>dU-=5oSp0b1}yBvG#^Lxk6 ze=FS|1S}RA``22U+ZGk4f-#ZNSqj4?bH#OmMYof;8)!4tOP>Nfv}bw~6oC4NjDndO zzDpI@&LOt=rdV=qcv0eyrd175Uz6Gi8%(%;ZN&#bBrmyHJ7P?I`!JH}HOA_9Fk2pi zX=es5eE}Z&TCT1M%&twZF_G_rVvSu_r!W@#E3`M2uIyg{hD#>IfoFX5PNbgE~tL0mX-#=wnixjRDnTi6D8a&#%coDYuKdHg27m8f& zG>6Y_s9scRTgr`;xK~JLbuo=r%?uk322%$puyGUQb^t%B#SL6-ERZgdg2{ zy+2}^1OS`dijEt@h-~jWfj|ocWC25(=-pmhoVTRne9>5;)Z@K8tnhOPOO5vObrjV& zl%P0F-O`~TzJ&iM3Ti%RdfkDUh((=9HBv$__-4{$H>zi{=#%$_!#%AHO@xHyuR!@L zMeC6-4j`HxpWQ(=*!QVW?>*UO3Qvacw2>Grnus<`le-c2H>Lgs)!u@h^KxtPm$89; zxb<(rZZe#HnAG7l?*-p77R3jza{1dy&ryxJ;TZI#DU{4&5WJ}$IM})mdN?pyxI7Bz zJ?T9y!V9r&z}Lk)Ejitp=M#ZNPRtxYu2~h_8$%kqxom7xm!qP4ev>6hJz7$0MPa#N z_pZ49E4uAk(03q!W}Z5Qju?eL1Z6dIVlGwO*5Cg;Dt$NJ!U?pmmkm<08QjdBW&*>P zYy!?u9@Ymh`Jo-`m47F_CM)=bSYhz9{V&<=$8;sbYTuiIP_;nY&4_usfQ8@y z+o3Q(klN<%jYW}L6xP|kWpX7q@{o?&LK(e21!q_+Egv3hleztQ9t!8vLk&}YiMfCb z{a}N+O=H`D$_G3hv5@R_)Yf0wVAeZdaDfDV;rwI7WknR=&EkwBmZ(d&(TZIUz>My! zyHIytO$;GL`Mm~1M0Eq&i8PA$6@$NAJ;{OpeJ4CR`FPU?eH^{0(IGSJ%?=b6o}ys? zsn`af7KkAhoaHPpc$rcj@^5xOttwcR%AH7^hFEldwf&2_?;=@v#ax&XDfn&0Oo3(_ zXLeXDRSp>1RNFO@i1Xy8VGp59-$aL#LAr?l!d~QyNsIU|q8ih@V-<%$NdqbCrC zhKJ#&8r4UcHUBaP`hXj@wX-;gat3n*mw#>1Uh=qGT23r?{ZU&u>SqDG#&CHh>LB;y zX5-k0P4X`ER5M$X`s%N5kUX=}{Id`r#D^_$;3Ib!_-P!SylkV=sIL}jQQ6!jty6!c zEa`fCi_5*W2W@29oLb*b4G7oN<`K!h;d?-DzJi#+XNcc8lhxPn${LmE4$LiRNcAsn z@*j#I>vKR0gLbd4ojyTyu%L-A5VO0%1v+55a1HPh&J$$g`r+xkyuBP>3G)vmOBk5k zZfK$KjvU$1Ha$X$Y**u%atgb=5m@Uj5Jx7Txdmx=n3=1la1x|#KfP=7mL}R;k$l7c z!U^2* zU+2!!&1|fCM!KEOhi@NV=fT2@QZC;eR`P`r-P6UJ#SCF_&1uN)G4-OGe<3p&#Gx=R zGnF%EY&7g;9Ddg)`Qaa-nQ*pH%VywDZ&7~t9t1j7y(dk7T^uK?!WgjTOJDFXB3}}@ z?`Nic^U5ge#UpT7I}y@W-tF`*Gy%^t-hyp)fEyz2Rv9y7q2ebiolrAt@#Do9=ec`L z3~t3{T`DZtGXe3o6DQr11tG)cwAIsC4s%TP_wH+nYaPR_+7(<5b+DSVYRcvNu}O39 z5(gnS(d^T%$wP}{{E@bEGXdv1cgN%Jll@T=Q#B_iwj`w$ID0Mkk&2pty1iH?9IG{Y-1Ud)1 z8nf%FU^Zy-6N&-&yNyi>EZmF<;;#LS9HNy#W%ET9%($|z&^03zt88I&pat%7nsNK$ zV~r+@@Okq)uN%K!sr0=kE0D~D121`u5mHrcV1j%no}KY{x5)z1u6+;NETad!HK7ik z=QCRFGK}1J>1KyEIi7g?J3*wS?7pK6pK52$YhXSYRMlMGJL8!P2BWpnYDMg`zY2oI zM)vVc=L@u7rlkiMBEVmqoL7y(^J2s!RM{``d|@!bXX@alx19AHAngw4;cw@EzYG~O z{P3!D|EM#!eUEzUZJ6+Ia?oM-HBd3XtM#;uQ>m-0};*IH5;ius##dm3vtG; zYvv;6Vzx=*wJrR0V(Su{B*X{e#m4#P$)tx6N$2>FE{2RE%+(gu2W-@<3!&Uqe04#e zGtx~xi7Am4XK<|hN)nKvvZD`Dg!=FE*y4Zs5ql~GVI>8%H0{!ua2*2X z39Sdy-~7B?H3}5r3a(uT`s>dNx|Qfn7R1eU5HnKzdL$Ic@$s$YP^}3oO%gb_cbE{u zd}D396U%caDthy-PabKeDdE94!i4rqbOH>pY@i9?!0mGE?Zw?omk`)_%O9 zT`b+~j7T4JKUSVN-Wm zyz1>>YZVA6^xH9dryG&h2w^oFdS%cMaN6t+sx=+U;CPtLmnR43hM*&bnwYEv>DA{C zx>-3G!7{~}0<7D9dPCb-$lG$+8aggZZia|OayygGt|b3}e{pcp?0i{74)Q{p9Y$&} z6bvL9xIJIeKT{L!g!8r{7J1?gq(A!BE!M zRDr%71<&R1$1w<`0wynorqrsEeCHH8SsT^d38B1=mcK-Y~grx$#jpDsH8PkPm_ zJLV7kf?}PUlf>R@RzJuUG4-u%!0c!&FCu}y)O!woryA>jHL8k*tfKhUmk*JEK}EB_ zm#a0W(pU2BBm=IurpQG!jSE=cn~rtO3$qI;j1SDCL)(Arq@~sMi)!A|m`Ew*Pc*_@ zlE58bzJZL0#^3yl9xZ1^z8sk;rN`{xUe|IX8VA#HP=MQS6<^vio&=K=kUIn-| z=u);b0sj=J#{~*1#P6{1!CX#U(T>Y5thZz6kO?_4T66!_&jm7#e-fjwD21Im_}QAd zN+n=T)Gxv_UoHQLJ{sj05c(eADjdgZ12d^nIIu$e`+8OdD7b#dok##BeTCHj`kN+O zHzFYDq9U6BrdDMWVsPZp66!!iUS*1BzeZly<*ULAHy;@&ay2;LfwlP48&+|{*j&N; ze^xUHV9G@#9#Tp9PyFu8l9@T1uGn{p^JI~HcCXv~M9E@e##C39n#Rv~?f{)(8-}7b z1227V&o@U7^o(pjiF%sj0Our(d;fNAEK}Ux);{858;~GUN4cuP3(}akcfy4Nd+74RGkC(Vp=otE zSM7*=@?`iE#eE#FK^=OS*=($D=xH`4VK~nWQCT; zwYp+v(?%E|>;%i!A{;>-rahd5&wObL28;DQcSynAYPM$MiwtiXv5C{{;#+F&1YosY zHQG5Q72kclC}pi6u^o0Aqn66DB5rusDR8<~e41a-?y}u9#@VMc?pfMGzna~&u#!R1 zTN14W7{Ugfpj)6To;Z91gZ%X%$NVWbJ1igxj=$++O=jAXBXTi_SThBqi3bLEt&<;s zSmA4wVc9wcYPL<>KMtn2TxHO%s-2r(dMdn2s~F%Gg0J1^1@C0l$+nkVikTegq920x z9%YOCYL0cSAA+)79FG>1Bg6J?_2Hs^gXJ;eUGgMm+3l@>5X0MaiSFlA3*MJmpO-HI&O*=yEU&17<|ox!VK}0(tNA^9uS?>gMVPWF z-~grhaExQ6zq5oA&k-_fTCOS}xNv6mK^QSXUBh=uU(fYMh?xhfhihaEaC}$iq%pyX zk2&_bkRjqc4TmC;(Ee}w=IxIpKThxnO@AC&cT*rwi}aO0DCW^n{g7>A`)HYnrTFt8 z^-x-=Su!shx6y>BY=P=kryT2TvefNI6D10}Gqw>K8Hn!z>gB`E=|G6^j(LA~A#=Lx z2j&WyuC~XOz0i)%XWrin7QfdW5gO(7d0x_PwHz^DO=4*HF~pUf09Nj70%wN9f1Jpn zeRa-T%+QI9VcE+;F_;O;gwdSw7E#PL<)EJ5M8NOcSu9)r;AT&bd_k$+0}K-89Bcc} zRFvJZJ??&F#&mPeVc!I_E~3z;6BA7#FvH3%6!qi5f|}131xp9T`X_2$T4w{~Om#M| z>GHW;%JiF7Le1@13?2uSKP%%LQKNVPYiAKesMZ5EZ^+v-DfW|M&u?XhY&)_J7}4Jc z9)2Gx*Oc1KB3-!^?c!xZmVpbSTuK~4dqLY3;>uJeGI}MKOi!M zMDtc^F6y1wNE3^{B!@V6mxY-WNA@J5&TP5`m0t*OwCu{V%8+#@?VdHO<@sQev6RAm zs)e5OGfNv)k(X`S)3wpM@bo93&fMK=AHwznpeZXp%we4%oIR426rJVrhLPEtYUop11@Yo7Zmf|bgAPm&jl%4l` z;cnum%Ogm$sUn0AhebrW&XnG~p*eQ0MHJR=u_^UwQ-x0sC!>EWTk?NeGlTHsJL&T{ z*=vT&^3b#PUW-trDg!WtNc?EegT`ganLF5nQv+71%#dVQk_+p{uw5Bs8@|jdK+5S zc7y$r;i9Ix#n^Eav039A(;1CfTKRF*#=RL3U$W8s{3^k>BI2dL*{|Y^1-zK)0r(yb zO{~(;o6VQ@B`?yu#lM}xOPlVQzn2Wzm7{umjrf$umxvONk)p5eYt6*=>WqhFS=LgQ zcuNK3$vZ(L=S)khsjFM4myfszI}rzU*D)Cvtl;w15AG{s$O9MlkTt9(h0vaswXTJz z??EU_UH#ju7w-QQGW#Jw>MU|J^X5O%-G<6Jg^dbz-b&qR(!LrqYo_t8!bU zJj_cq~QSD9OmPx$tJuXBa^axVnFDvI{YdN85{NTmMv)9gRJS^v#(u3%$)1Q+C zStEo{8h=sNKx(>Up1VDzJ|#v%npJAsfS`w~=&M>&G$EB+AkmPa(`i;zgjM*}>od=P zLMY~8I|wJYAe&+)R=Iqf$pbRT=%nzotTP4dVsB{#5_v`8N810&eNLjQ8pjHCa%S^L zim*F9_**Eg*zDLUh|YQtj!n+5WL#%7A%r{aB=vY#<(bbYJ;9_2|wjQQWs lO_={INPMvV%l+RZ80Dku-D2{*%gui%T57tgpOtN+{}=k)==T5s literal 34687 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

4)P92M7W|9?;c6Ro76)iBFh?M;_m`ko2hQ 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 GhyNGpwL9qm diff --git a/components/app-sidebar.tsx b/components/app-sidebar.tsx index 30d058bc20..723655b319 100644 --- a/components/app-sidebar.tsx +++ b/components/app-sidebar.tsx @@ -72,7 +72,7 @@ export function AppSidebar({ user }: { user: User | undefined }) { }} > - OpenChat + Chatbot

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..be7fb2ae67 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") ) { 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": { From ae579c2adb6da343019b2d56b2c20578ffa7a114 Mon Sep 17 00:00:00 2001 From: dancer <144584931+dancer@users.noreply.github.com> Date: Tue, 24 Feb 2026 00:29:44 +0000 Subject: [PATCH 2/2] fix lint formatting on demo rename pr --- components/app-sidebar.tsx | 9 +++++--- components/artifact.tsx | 19 +++++++++------- components/chat.tsx | 10 +++++++-- components/message-actions.tsx | 38 ++++++++++++++++++-------------- components/multimodal-input.tsx | 17 +++++++++----- components/sidebar-history.tsx | 9 +++++--- components/suggested-actions.tsx | 6 ++++- hooks/use-chat-visibility.ts | 4 +++- 8 files changed, 73 insertions(+), 39 deletions(-) diff --git a/components/app-sidebar.tsx b/components/app-sidebar.tsx index 723655b319..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...", 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.tsx b/components/chat.tsx index be7fb2ae67..807864e923 100644 --- a/components/chat.tsx +++ b/components/chat.tsx @@ -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`,