diff --git a/CHANGE_LOG.md b/CHANGE_LOG.md index e1bf5f0..af1e05d 100644 --- a/CHANGE_LOG.md +++ b/CHANGE_LOG.md @@ -2,7 +2,7 @@ ## v0.6.1 -> 2023-06-13 +> 2023-06-14 ### Fixed @@ -13,6 +13,8 @@ - Added backend capability to calculate token consumption - Display the total amount of tokens currently consumed at the menu. +- Added support for multiple simultaneous conversations, switching sessions will not break the connection of the current session. +- Added support for the newly updated model from OpenAI: gpt-3.5-turbo-0613/gpt-3.5-turbo-16k ### Changed diff --git a/CHANGE_LOG.zh_CN.md b/CHANGE_LOG.zh_CN.md index 8a1f7ae..5e1858b 100644 --- a/CHANGE_LOG.zh_CN.md +++ b/CHANGE_LOG.zh_CN.md @@ -2,7 +2,7 @@ ## v0.6.1 -> 2023-06-13 +> 2023-06-14 ### 修复 @@ -13,6 +13,8 @@ - 新增后端计算 token 消耗的能力 - 新增菜单处显示当前消耗的总 token 数量 +- 新增支持多会话同时对话,切换会话时不会断掉当前会话的链接 +- 新增支持 openai 刚更新的模型: gpt-3.5-turbo-0613/gpt-3.5-turbo-16k ### 修改 diff --git a/package.json b/package.json index 327b2cd..295ed95 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@radix-ui/react-toast": "1.1.4", "@react-email/components": "0.0.6", "@react-email/render": "0.0.7", - "@sentry/nextjs": "7.54.0", + "@sentry/nextjs": "7.55.1", "@svgr/webpack": "8.0.1", "@types/node": "20.3.1", "@types/react": "18.2.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 89e7c4f..5778a7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,17 +51,14 @@ dependencies: specifier: 0.0.7 version: 0.0.7 '@sentry/nextjs': - specifier: 7.54.0 - version: 7.54.0(next@13.4.5)(react@18.2.0) - '@splinetool/react-spline': - specifier: ^2.2.6 - version: 2.2.6(@splinetool/runtime@0.9.366)(react-dom@18.2.0)(react@18.2.0) + specifier: 7.55.1 + version: 7.55.1(next@13.4.5)(react@18.2.0) '@svgr/webpack': specifier: 8.0.1 version: 8.0.1 '@types/node': - specifier: 20.3.0 - version: 20.3.0 + specifier: 20.3.1 + version: 20.3.1 '@types/react': specifier: 18.2.12 version: 18.2.12 @@ -2908,25 +2905,25 @@ packages: selderee: 0.10.0 dev: false - /@sentry-internal/tracing@7.54.0: - resolution: {integrity: sha512-JsyhZ0wWZ+VqbHJg+azqRGdYJDkcI5R9+pnkO6SzbzxrRewqMAIwzkpPee3oI7vG99uhMEkOkMjHu0nQGwkOQw==} + /@sentry-internal/tracing@7.55.1: + resolution: {integrity: sha512-VqvqJ1VDJv0y0Hu1sTDDOYWSlzww9d3LUuUBHw3phH25+G7PZfduTRtAYemQCT4QFMz2YRaNik1kfCFwNBBfXA==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.54.0 - '@sentry/types': 7.54.0 - '@sentry/utils': 7.54.0 + '@sentry/core': 7.55.1 + '@sentry/types': 7.55.1 + '@sentry/utils': 7.55.1 tslib: 1.14.1 dev: false - /@sentry/browser@7.54.0: - resolution: {integrity: sha512-EvLAw03N9WE2m1CMl2/1YMeIs1icw9IEOVJhWmf3uJEysNJOFWXu6ZzdtHEz1E6DiJYhc1HzDya0ExZeJxNARA==} + /@sentry/browser@7.55.1: + resolution: {integrity: sha512-V+0eE1iAjHXC35S/wMx4TywCzv63+FirKj4jHcXexXfyw8pxxcLN/heKrRfmBLQIu1Nckkg5ByAUog43w+JxtA==} engines: {node: '>=8'} dependencies: - '@sentry-internal/tracing': 7.54.0 - '@sentry/core': 7.54.0 - '@sentry/replay': 7.54.0 - '@sentry/types': 7.54.0 - '@sentry/utils': 7.54.0 + '@sentry-internal/tracing': 7.55.1 + '@sentry/core': 7.55.1 + '@sentry/replay': 7.55.1 + '@sentry/types': 7.55.1 + '@sentry/utils': 7.55.1 tslib: 1.14.1 dev: false @@ -2947,27 +2944,27 @@ packages: - supports-color dev: false - /@sentry/core@7.54.0: - resolution: {integrity: sha512-MAn0E2EwgNn1pFQn4qxhU+1kz6edullWg6VE5wCmtpXWOVw6sILBUsQpeIG5djBKMcneJCdOlz5jeqcKPrLvZQ==} + /@sentry/core@7.55.1: + resolution: {integrity: sha512-ItGtcPpjYnjKaQHbvAZGgfW3jXZkF47u/ihAjnWiVZGE5bStBCUNSlQX3Z3mEmP62kNEYBeZMCD+ncqtqx8DMg==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.54.0 - '@sentry/utils': 7.54.0 + '@sentry/types': 7.55.1 + '@sentry/utils': 7.55.1 tslib: 1.14.1 dev: false - /@sentry/integrations@7.54.0: - resolution: {integrity: sha512-RolGsQzJChJzjHTJcCKSZ1HanmY33floc5o13WgU9NoDqJbLGLNcOIrAu+WynqPe8P5VTVrVb8NiwhLqWrKp4g==} + /@sentry/integrations@7.55.1: + resolution: {integrity: sha512-7R45P9h0vm0jSSNNgtYB7IF1BpWX4i8SLUG/uRUhITeUSRfB83WOimJbYyqzLFNnJWDKKc2INNBXof/iIS/mlQ==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.54.0 - '@sentry/utils': 7.54.0 + '@sentry/types': 7.55.1 + '@sentry/utils': 7.55.1 localforage: 1.10.0 tslib: 1.14.1 dev: false - /@sentry/nextjs@7.54.0(next@13.4.5)(react@18.2.0): - resolution: {integrity: sha512-F+2OinUNq1F4QOUb5mqZZVmW8EkobKsECSpttWbLOKh4/Br37G9H1P3q1/qDUTke9ZMgp57O8acUByLfROp0ag==} + /@sentry/nextjs@7.55.1(next@13.4.5)(react@18.2.0): + resolution: {integrity: sha512-0Yl+QQ5ibem6PjOdy17r7mMwnZGTYoaxU715WEGHr+zl9nPuv65Ey2uEm8dtnLyFFVpCFHD5ZXY+ml1R+xtDSw==} engines: {node: '>=8'} peerDependencies: next: ^10.0.8 || ^11.0 || ^12.0 || ^13.0 @@ -2978,12 +2975,12 @@ packages: optional: true dependencies: '@rollup/plugin-commonjs': 24.0.0(rollup@2.78.0) - '@sentry/core': 7.54.0 - '@sentry/integrations': 7.54.0 - '@sentry/node': 7.54.0 - '@sentry/react': 7.54.0(react@18.2.0) - '@sentry/types': 7.54.0 - '@sentry/utils': 7.54.0 + '@sentry/core': 7.55.1 + '@sentry/integrations': 7.55.1 + '@sentry/node': 7.55.1 + '@sentry/react': 7.55.1(react@18.2.0) + '@sentry/types': 7.55.1 + '@sentry/utils': 7.55.1 '@sentry/webpack-plugin': 1.20.0 chalk: 3.0.0 next: 13.4.5(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0) @@ -2996,14 +2993,14 @@ packages: - supports-color dev: false - /@sentry/node@7.54.0: - resolution: {integrity: sha512-k8P7WD6lra3JF3H/y9GO+twBV8qQilj3X3d8PpaVPBHHwOA9AfdBVF18qgrdlZKghKtgALapZzrQQVnTOm34rw==} + /@sentry/node@7.55.1: + resolution: {integrity: sha512-l+j9aaWcWEk5xZlQEOtqt71+dtDrzglCUpUMIHMWcupcJ4jAcAGeXA9S0GuGUddifAf0JtB6XYgsj3UYRHwQJQ==} engines: {node: '>=8'} dependencies: - '@sentry-internal/tracing': 7.54.0 - '@sentry/core': 7.54.0 - '@sentry/types': 7.54.0 - '@sentry/utils': 7.54.0 + '@sentry-internal/tracing': 7.55.1 + '@sentry/core': 7.55.1 + '@sentry/types': 7.55.1 + '@sentry/utils': 7.55.1 cookie: 0.4.2 https-proxy-agent: 5.0.1 lru_map: 0.3.3 @@ -3012,39 +3009,39 @@ packages: - supports-color dev: false - /@sentry/react@7.54.0(react@18.2.0): - resolution: {integrity: sha512-qUbwmRRpTh05m2rbC8A2zAFQYsoHhwIpxT5UXxh0P64ZlA3cSg1/DmTTgwnd1l+7gzKrc31UikXQ4y0YDbMNKg==} + /@sentry/react@7.55.1(react@18.2.0): + resolution: {integrity: sha512-LC19sgiNn9jlMM7u87DxxUt2XhKlQ26Wk83NLCys/1vgkP5+B2rUunJ9uqf6XdiY4al/tCM1YOJfPxHbbUaRxg==} engines: {node: '>=8'} peerDependencies: react: 15.x || 16.x || 17.x || 18.x dependencies: - '@sentry/browser': 7.54.0 - '@sentry/types': 7.54.0 - '@sentry/utils': 7.54.0 + '@sentry/browser': 7.55.1 + '@sentry/types': 7.55.1 + '@sentry/utils': 7.55.1 hoist-non-react-statics: 3.3.2 react: 18.2.0 tslib: 1.14.1 dev: false - /@sentry/replay@7.54.0: - resolution: {integrity: sha512-C0F0568ybphzGmKGe23duB6n5wJcgM7WLYhoeqW3o2bHeqpj1dGPSka/K3s9KzGaAgzn1zeOUYXJsOs+T/XdsA==} + /@sentry/replay@7.55.1: + resolution: {integrity: sha512-zLCBY0F0t5dZseu5Rgt7fItyYVn2ROaeF5P9oA6SaYsN+YX/9HQAS0aRgOiMwsaSxVVZ8Q39lc6FtnbWcwU1kA==} engines: {node: '>=12'} dependencies: - '@sentry/core': 7.54.0 - '@sentry/types': 7.54.0 - '@sentry/utils': 7.54.0 + '@sentry/core': 7.55.1 + '@sentry/types': 7.55.1 + '@sentry/utils': 7.55.1 dev: false - /@sentry/types@7.54.0: - resolution: {integrity: sha512-D+i9xogBeawvQi2r0NOrM7zYcUaPuijeME4O9eOTrDF20tj71hWtJLilK+KTGLYFtpGg1h+9bPaz7OHEIyVopg==} + /@sentry/types@7.55.1: + resolution: {integrity: sha512-dZDNBKFLoj0o7o0AzdzCo0wt8iRas1HD+TGg58pzeFriO7JVUkRJI25jcjtU/kyXMYdt8IHwJxAKrK2yWtKhDg==} engines: {node: '>=8'} dev: false - /@sentry/utils@7.54.0: - resolution: {integrity: sha512-3Yf5KlKjIcYLddOexSt2ovu2TWlR4Fi7M+aCK8yUTzwNzf/xwFSWOstHlD/WiDy9HvfhWAOB/ukNTuAeJmtasw==} + /@sentry/utils@7.55.1: + resolution: {integrity: sha512-NjoXwR1KoM2TzOo1BjGR55NytYz2NeYcB+c3CjC1Im0+pIU1svZ6xZy/eMwnCtw+UBqZSttjIxA7d0XSXFnySA==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.54.0 + '@sentry/types': 7.55.1 tslib: 1.14.1 dev: false @@ -3059,27 +3056,6 @@ packages: - supports-color dev: false - /@splinetool/react-spline@2.2.6(@splinetool/runtime@0.9.366)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-y9L2VEbnC6FNZZu8XMmWM9YTTTWal6kJVfP05Amf0QqDNzCSumKsJxZyGUODvuCmiAvy0PfIfEsiVKnSxvhsDw==} - peerDependencies: - '@splinetool/runtime': '*' - react: '>=17.0.0' - react-dom: '>=17.0.0' - dependencies: - '@splinetool/runtime': 0.9.366 - lodash.debounce: 4.0.8 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-merge-refs: 2.0.2 - dev: false - - /@splinetool/runtime@0.9.366: - resolution: {integrity: sha512-gcrqRTSpCz9bmSwlApJJFrlzgX/ftUZ48CTAjxKqSSVV4sTxJTwfgzgF3LajkJE3aGNO/BJttu/yTZP/YALNaQ==} - dependencies: - on-change: 4.0.2 - semver-compare: 1.0.0 - dev: false - /@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.21.8): resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} engines: {node: '>=14'} @@ -3306,13 +3282,13 @@ packages: resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} dev: false - /@types/node@20.3.0: - resolution: {integrity: sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ==} + /@types/node@20.3.1: + resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==} /@types/nodemailer@6.4.8: resolution: {integrity: sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==} dependencies: - '@types/node': 20.3.0 + '@types/node': 20.3.1 dev: true /@types/parse-json@4.0.0: @@ -6491,11 +6467,6 @@ packages: engines: {node: ^10.13.0 || >=12.0.0} dev: false - /on-change@4.0.2: - resolution: {integrity: sha512-cMtCyuJmTx/bg2HCpHo3ZLeF7FZnBOapLqZHr2AlLeJ5Ul0Zu2mUJJz051Fdwu/Et2YW04ZD+TtU+gVy0ACNCA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: false - /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -6966,10 +6937,6 @@ packages: - supports-color dev: false - /react-merge-refs@2.0.2: - resolution: {integrity: sha512-V5BGTwGa2r+/t0A/BZMS6L7VPXY0CU8xtAhkT3XUoI1WJJhhtvulvoiZkJ5Jt9YAW23m4xFWmhQ+C5HwjtTFhQ==} - dev: false - /react-property@2.0.0: resolution: {integrity: sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw==} dev: false @@ -7253,10 +7220,6 @@ packages: parseley: 0.11.0 dev: false - /semver-compare@1.0.0: - resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} - dev: false - /semver@5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true diff --git a/src/app/[locale]/(authentication)/login/page.tsx b/src/app/[locale]/(authentication)/login/page.tsx index 47fdaf4..b4f8610 100644 --- a/src/app/[locale]/(authentication)/login/page.tsx +++ b/src/app/[locale]/(authentication)/login/page.tsx @@ -1,6 +1,6 @@ import { cn } from "@/lib"; import Logo from "@/components/site/logo"; -import AuthForm from "@/components/authForm"; +import AuthForm from "@/components/site/authForm"; export default function Login() { return ( diff --git a/src/app/[locale]/(home)/page.tsx b/src/app/[locale]/(home)/page.tsx index 5678f31..28ab47b 100644 --- a/src/app/[locale]/(home)/page.tsx +++ b/src/app/[locale]/(home)/page.tsx @@ -4,7 +4,7 @@ import MobileMenu from "@/components/menu/mobile"; import Setting from "@/components/setting"; import PromptMark from "@/components/prompt/market"; import Navbar from "@/components/navbar"; -import Welcome from "@/components/welcome"; +import Welcome from "@/components/site/welcome"; import ChatSection from "@/components/chatSection"; import "@/utils/plugin/polyfill-client"; diff --git a/src/app/[locale]/(share)/share/[id]/page.tsx b/src/app/[locale]/(share)/share/[id]/page.tsx index adb3a5f..526a251 100644 --- a/src/app/[locale]/(share)/share/[id]/page.tsx +++ b/src/app/[locale]/(share)/share/[id]/page.tsx @@ -8,7 +8,7 @@ import type { Share } from "@prisma/client"; import { AiOutlineUser } from "react-icons/ai"; import { SiMicrosoftazure } from "react-icons/si"; import Button from "@/components/ui/Button"; -import CopyIcon from "@/components/copyIcon"; +import CopyIcon from "@/components/site/copyIcon"; import ChatContent from "@/components/chatContent"; import BasicInfo from "@/components/share/basicInfo"; import NotFound from "@/components/share/notFound"; diff --git a/src/app/api/azure/route.ts b/src/app/api/azure/route.ts index f06665f..03142be 100644 --- a/src/app/api/azure/route.ts +++ b/src/app/api/azure/route.ts @@ -2,8 +2,7 @@ import { headers } from "next/headers"; import { NextResponse } from "next/server"; import { getServerSession } from "next-auth/next"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; -import { isUndefined } from "@/lib"; -import { GPTTokens } from "@/lib/gpt-tokens"; +import { isUndefined, calcTokens } from "@/lib"; import type { supportModelType } from "@/lib/gpt-tokens"; import { prisma } from "@/lib/prisma"; @@ -70,8 +69,7 @@ const stream = async ( if (userId) { const final = [...messages, { role: "assistant", content: resultContent }]; - const tokenInfo = new GPTTokens({ model, messages: final }); - const { usedTokens, usedUSD } = tokenInfo; + const { usedTokens, usedUSD } = calcTokens(final, model); const findUser = await prisma.user.findUnique({ where: { id: userId }, @@ -171,13 +169,6 @@ export async function POST(request: Request) { session?.user.id ); - if (session) { - await prisma.user.update({ - data: { recentlyUse: new Date() }, - where: { id: session?.user.id }, - }); - } - return new Response(readable, response); } catch (error: any) { console.log(error, "azure error"); diff --git a/src/app/api/openai/route.ts b/src/app/api/openai/route.ts index 6976669..da0462b 100644 --- a/src/app/api/openai/route.ts +++ b/src/app/api/openai/route.ts @@ -2,8 +2,7 @@ import { headers } from "next/headers"; import { NextResponse } from "next/server"; import { getServerSession } from "next-auth/next"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; -import { isUndefined } from "@/lib"; -import { GPTTokens } from "@/lib/gpt-tokens"; +import { isUndefined, calcTokens } from "@/lib"; import type { supportModelType } from "@/lib/gpt-tokens"; import { prisma } from "@/lib/prisma"; @@ -78,8 +77,14 @@ const stream = async ( if (userId) { const final = [...messages, { role: "assistant", content: resultContent }]; - const tokenInfo = new GPTTokens({ model, messages: final }); - const { usedTokens, usedUSD } = tokenInfo; + const { usedTokens, usedUSD } = calcTokens(final, model, true); + + console.log("\n\n"); + console.log(final, "final"); + console.log(model, "model"); + console.log(usedTokens, "usedTokens"); + console.log(usedUSD, "usedUSD"); + console.log("\n\n"); const findUser = await prisma.user.findUnique({ where: { id: userId }, @@ -163,13 +168,6 @@ export async function POST(request: Request) { }), }); - if (session) { - await prisma.user.update({ - data: { recentlyUse: new Date() }, - where: { id: session?.user.id }, - }); - } - if (response.status !== 200) { return new Response(response.body, { status: 500 }); } diff --git a/src/app/api/user/route.ts b/src/app/api/user/route.ts index e87ec0f..bab1dbe 100644 --- a/src/app/api/user/route.ts +++ b/src/app/api/user/route.ts @@ -43,7 +43,7 @@ export async function PUT(request: Request) { return NextResponse.json({ error: 0 }, { status: 200 }); } -export async function GET(request: Request) { +export async function GET() { const session = await getServerSession(authOptions); if (!session) return LResponseError("Please log in first"); @@ -55,6 +55,11 @@ export async function GET(request: Request) { if (!user) return LResponseError("User does not exist"); + await prisma.user.update({ + data: { recentlyUse: new Date() }, + where: { id: session?.user.id }, + }); + const response = { costTokens: user.costTokens, costUSD: user.costUSD, diff --git a/src/components/announcement/index.tsx b/src/components/announcement/index.tsx index 081fde1..3823cf7 100644 --- a/src/components/announcement/index.tsx +++ b/src/components/announcement/index.tsx @@ -2,29 +2,38 @@ import * as React from "react"; import * as Toast from "@radix-ui/react-toast"; -import { useTranslations } from "next-intl"; +import { useTranslations, useLocale } from "next-intl"; import { AiOutlineCheck } from "react-icons/ai"; import { cn } from "@/lib"; import pkg from "../../../package.json"; export default function Announcement() { + const locale = useLocale(); const t = useTranslations("zLog"); const [open, setOpen] = React.useState(false); + const url = + locale === "zh-CN" + ? "https://docs.ltopx.com/zh-CN/change-log" + : "https://docs.ltopx.com/change-log"; + const onClick = () => { localStorage.setItem("announcement_version", pkg.version); }; React.useEffect(() => { - // const announcement_version = localStorage.getItem("announcement_version"); - // if (pkg.version !== announcement_version) setOpen(true); + const announcement_version = localStorage.getItem("announcement_version"); + if (pkg.version !== announcement_version) setOpen(true); }, []); return ( {t("title")} - -
    -
  • {t("text1")}
  • -
  • {t("text2")}
  • -
  • {t("text3")}
  • -
  • {t("text4")}
  • -
+ +
+
    +
  • {t("text1")}
  • +
  • {t("text2")}
  • +
  • {t("text3")}
  • +
  • {t("text4")}
  • +
+ +