diff --git a/app/src/assets/pages/chat.less b/app/src/assets/pages/chat.less index 81ba726..8bb91ac 100644 --- a/app/src/assets/pages/chat.less +++ b/app/src/assets/pages/chat.less @@ -176,6 +176,28 @@ background: none !important; color: hsl(var(--text)); + .prompt-row { + border: 1px solid var(--assistant-border); + border-radius: var(--radius); + margin: 0.25rem 0; + + .grow { + min-width: 0.75rem; + } + + .value { + display: flex; + flex-direction: row; + align-items: center; + font-family: var(--font-family); + margin: 0 !important; + } + + svg { + transform: translateY(1px); + } + } + ol, ul, menu { list-style: inherit; } diff --git a/app/src/components/Markdown.tsx b/app/src/components/Markdown.tsx index c4326af..eb68b46 100644 --- a/app/src/components/Markdown.tsx +++ b/app/src/components/Markdown.tsx @@ -9,16 +9,22 @@ import rehypeRaw from "rehype-raw"; import { parseFile } from "./plugins/file.tsx"; import "@/assets/markdown/all.less"; import { useEffect, useMemo } from "react"; -import { useDispatch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { openDialog as openQuotaDialog } from "@/store/quota.ts"; import { openDialog as openSubscriptionDialog } from "@/store/subscription.ts"; import { AppDispatch } from "@/store"; import { + CalendarPlus, + Cloud, + CloudCog, + Cloudy, Codepen, Codesandbox, Copy, Github, Maximize, + Package, + Plus, RefreshCcwDot, Twitter, Wand2, @@ -41,6 +47,8 @@ import { } from "@/components/ui/dialog.tsx"; import { DialogClose } from "@radix-ui/react-dialog"; import { posterEvent } from "@/events/poster.ts"; +import { appLogo } from "@/conf/env.ts"; +import { subscriptionDataSelector } from "@/store/globals.ts"; type MarkdownProps = { children: string; @@ -109,6 +117,8 @@ function MarkdownContent({ const { t } = useTranslation(); const { toast } = useToast(); + const subscription = useSelector(subscriptionDataSelector); + useEffect(() => { document.querySelectorAll(".file-instance").forEach((el) => { const parent = el.parentElement as HTMLElement; @@ -130,6 +140,81 @@ function MarkdownContent({ children={children} skipHtml={!acceptHtml} components={{ + p({ children }) { + // if the format is `user quota is not enough error (model: gpt-3.5-turbo-1106, minimum quota: 0.01, your quota: -77.77)`, return special component + const match = children + .toString() + .match( + /user quota is not enough error \(model: (.*), minimum quota: (.*), your quota: (.*)\)/, + ); + if (match) { + const [, model, minimum, quota] = match; + const plan = subscription + .flatMap((p) => p.items.map((i) => i.models.includes(model))) + .includes(true); + + return ( +
+ {""} +
+ + {t("model")} +
+

{model}

+
+
+ + {t("your-quota")} +
+

+ {quota} + +

+
+
+ + {t("min-quota")} +
+

+ {minimum} + +

+
+ + {plan && ( + + )} +
+ ); + } + + return

{children}

; + }, a({ href, children }) { const url: string = href?.toString() || ""; diff --git a/app/src/dialogs/QuotaDialog.tsx b/app/src/dialogs/QuotaDialog.tsx index 9a6fa56..d75544f 100644 --- a/app/src/dialogs/QuotaDialog.tsx +++ b/app/src/dialogs/QuotaDialog.tsx @@ -287,7 +287,13 @@ function QuotaDialog() {
- {!useDeeptrain && ( + {useDeeptrain ? ( +
+ {t("buy.deeptrain-tip")} +
+ ) : (