diff --git a/app/api/common.ts b/app/api/common.ts index b4c792d6f..495a12ccd 100644 --- a/app/api/common.ts +++ b/app/api/common.ts @@ -1,8 +1,8 @@ import { NextRequest, NextResponse } from "next/server"; import { getServerSideConfig } from "../config/server"; import { OPENAI_BASE_URL, ServiceProvider } from "../constant"; -import { isModelAvailableInServer } from "../utils/model"; import { cloudflareAIGatewayUrl } from "../utils/cloudflare"; +import { getModelProvider, isModelAvailableInServer } from "../utils/model"; const serverConfig = getServerSideConfig(); @@ -71,7 +71,7 @@ export async function requestOpenai(req: NextRequest) { .filter((v) => !!v && !v.startsWith("-") && v.includes(modelName)) .forEach((m) => { const [fullName, displayName] = m.split("="); - const [_, providerName] = fullName.split("@"); + const [_, providerName] = getModelProvider(fullName); if (providerName === "azure" && !displayName) { const [_, deployId] = (serverConfig?.azureUrl ?? "").split( "deployments/", diff --git a/app/components/auth.tsx b/app/components/auth.tsx index 539a52eec..5375bda3f 100644 --- a/app/components/auth.tsx +++ b/app/components/auth.tsx @@ -18,6 +18,8 @@ import { trackSettingsPageGuideToCPaymentClick, trackAuthorizationPageButtonToCPaymentClick, } from "../utils/auth-settings-events"; +import clsx from "clsx"; + const storage = safeLocalStorage(); export function AuthPage() { @@ -54,7 +56,7 @@ export function AuthPage() { onClick={() => navigate(Path.Home)} > -
+
@@ -163,7 +165,7 @@ function TopBanner() { onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} > -
+
{Locale.Auth.TopTips} diff --git a/app/components/button.tsx b/app/components/button.tsx index 87b4abd30..157d5d73d 100644 --- a/app/components/button.tsx +++ b/app/components/button.tsx @@ -2,6 +2,7 @@ import * as React from "react"; import styles from "./button.module.scss"; import { CSSProperties } from "react"; +import clsx from "clsx"; export type ButtonType = "primary" | "danger" | null; @@ -22,12 +23,16 @@ export function IconButton(props: { }) { return (
diff --git a/app/components/chat-list.tsx b/app/components/chat-list.tsx index 03b1a5c88..63dc4d5ff 100644 --- a/app/components/chat-list.tsx +++ b/app/components/chat-list.tsx @@ -18,6 +18,7 @@ import { Mask } from "../store/mask"; import { useRef, useEffect } from "react"; import { showConfirm } from "./ui-lib"; import { useMobileScreen } from "../utils"; +import clsx from "clsx"; export function ChatItem(props: { onClick?: () => void; @@ -45,11 +46,11 @@ export function ChatItem(props: { {(provided) => (
{ draggableRef.current = ele; @@ -63,7 +64,7 @@ export function ChatItem(props: { > {props.narrow ? (
-
+
void }) { text={Locale.Chat.Config.Reset} onClick={async () => { if (await showConfirm(Locale.Memory.ResetConfirm)) { - chatStore.updateCurrentSession( + chatStore.updateTargetSession( + session, (session) => (session.memoryPrompt = ""), ); } @@ -173,7 +176,10 @@ export function SessionConfigModel(props: { onClose: () => void }) { updateMask={(updater) => { const mask = { ...session.mask }; updater(mask); - chatStore.updateCurrentSession((session) => (session.mask = mask)); + chatStore.updateTargetSession( + session, + (session) => (session.mask = mask), + ); }} shouldSyncFromGlobal extraListItems={ @@ -206,7 +212,7 @@ function PromptToast(props: {
{props.showToast && context.length > 0 && (
props.setShowModal(true)} > @@ -327,10 +333,9 @@ export function PromptHints(props: { {props.prompts.map((prompt, i) => (
props.onPromptSelect(prompt)} onMouseEnter={() => setSelectIndex(i)} @@ -345,12 +350,14 @@ export function PromptHints(props: { function ClearContextDivider() { const chatStore = useChatStore(); + const session = chatStore.currentSession(); return (
- chatStore.updateCurrentSession( + chatStore.updateTargetSession( + session, (session) => (session.clearContextIndex = undefined), ) } @@ -388,7 +395,7 @@ export function ChatAction(props: { return (
{ props.onClick(); setTimeout(updateWidth, 1); @@ -460,6 +467,7 @@ export function ChatActions(props: { const navigate = useNavigate(); const chatStore = useChatStore(); const pluginStore = usePluginStore(); + const session = chatStore.currentSession(); // switch themes const theme = config.theme; @@ -476,10 +484,9 @@ export function ChatActions(props: { const stopAll = () => ChatControllerPool.stopAll(); // switch model - const currentModel = chatStore.currentSession().mask.modelConfig.model; + const currentModel = session.mask.modelConfig.model; const currentProviderName = - chatStore.currentSession().mask.modelConfig?.providerName || - ServiceProvider.OpenAI; + session.mask.modelConfig?.providerName || ServiceProvider.OpenAI; const allModels = useAllModels(); const models = useMemo(() => { const filteredModels = allModels.filter((m) => m.available); @@ -513,12 +520,9 @@ export function ChatActions(props: { const dalle3Sizes: DalleSize[] = ["1024x1024", "1792x1024", "1024x1792"]; const dalle3Qualitys: DalleQuality[] = ["standard", "hd"]; const dalle3Styles: DalleStyle[] = ["vivid", "natural"]; - const currentSize = - chatStore.currentSession().mask.modelConfig?.size ?? "1024x1024"; - const currentQuality = - chatStore.currentSession().mask.modelConfig?.quality ?? "standard"; - const currentStyle = - chatStore.currentSession().mask.modelConfig?.style ?? "vivid"; + const currentSize = session.mask.modelConfig?.size ?? "1024x1024"; + const currentQuality = session.mask.modelConfig?.quality ?? "standard"; + const currentStyle = session.mask.modelConfig?.style ?? "vivid"; const isMobileScreen = useMobileScreen(); @@ -536,7 +540,7 @@ export function ChatActions(props: { if (isUnavailableModel && models.length > 0) { // show next model to default model if exist let nextModel = models.find((model) => model.isDefault) || models[0]; - chatStore.updateCurrentSession((session) => { + chatStore.updateTargetSession(session, (session) => { session.mask.modelConfig.model = nextModel.name; session.mask.modelConfig.providerName = nextModel?.provider ?.providerName as ServiceProvider; @@ -547,7 +551,7 @@ export function ChatActions(props: { : nextModel.name, ); } - }, [chatStore, currentModel, models]); + }, [chatStore, currentModel, models, session]); return (
@@ -614,7 +618,7 @@ export function ChatActions(props: { text={Locale.Chat.InputActions.Clear} icon={} onClick={() => { - chatStore.updateCurrentSession((session) => { + chatStore.updateTargetSession(session, (session) => { if (session.clearContextIndex === session.messages.length) { session.clearContextIndex = undefined; } else { @@ -645,8 +649,8 @@ export function ChatActions(props: { onClose={() => setShowModelSelector(false)} onSelection={(s) => { if (s.length === 0) return; - const [model, providerName] = s[0].split("@"); - chatStore.updateCurrentSession((session) => { + const [model, providerName] = getModelProvider(s[0]); + chatStore.updateTargetSession(session, (session) => { session.mask.modelConfig.model = model as ModelType; session.mask.modelConfig.providerName = providerName as ServiceProvider; @@ -684,7 +688,7 @@ export function ChatActions(props: { onSelection={(s) => { if (s.length === 0) return; const size = s[0]; - chatStore.updateCurrentSession((session) => { + chatStore.updateTargetSession(session, (session) => { session.mask.modelConfig.size = size; }); showToast(size); @@ -711,7 +715,7 @@ export function ChatActions(props: { onSelection={(q) => { if (q.length === 0) return; const quality = q[0]; - chatStore.updateCurrentSession((session) => { + chatStore.updateTargetSession(session, (session) => { session.mask.modelConfig.quality = quality; }); showToast(quality); @@ -738,7 +742,7 @@ export function ChatActions(props: { onSelection={(s) => { if (s.length === 0) return; const style = s[0]; - chatStore.updateCurrentSession((session) => { + chatStore.updateTargetSession(session, (session) => { session.mask.modelConfig.style = style; }); showToast(style); @@ -769,7 +773,7 @@ export function ChatActions(props: { }))} onClose={() => setShowPluginSelector(false)} onSelection={(s) => { - chatStore.updateCurrentSession((session) => { + chatStore.updateTargetSession(session, (session) => { session.mask.plugin = s as string[]; }); }} @@ -812,7 +816,8 @@ export function EditMessageModal(props: { onClose: () => void }) { icon={} key="ok" onClick={() => { - chatStore.updateCurrentSession( + chatStore.updateTargetSession( + session, (session) => (session.messages = messages), ); props.onClose(); @@ -829,7 +834,8 @@ export function EditMessageModal(props: { onClose: () => void }) { type="text" value={session.topic} onInput={(e) => - chatStore.updateCurrentSession( + chatStore.updateTargetSession( + session, (session) => (session.topic = e.currentTarget.value), ) } @@ -990,7 +996,8 @@ function _Chat() { prev: () => chatStore.nextSession(-1), next: () => chatStore.nextSession(1), clear: () => - chatStore.updateCurrentSession( + chatStore.updateTargetSession( + session, (session) => (session.clearContextIndex = session.messages.length), ), fork: () => chatStore.forkSession(), @@ -1061,7 +1068,7 @@ function _Chat() { }; useEffect(() => { - chatStore.updateCurrentSession((session) => { + chatStore.updateTargetSession(session, (session) => { const stopTiming = Date.now() - REQUEST_TIMEOUT_MS; session.messages.forEach((m) => { // check if should stop all stale messages @@ -1087,7 +1094,7 @@ function _Chat() { } }); // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [session]); // check if should send message const onInputKeyDown = (e: React.KeyboardEvent) => { @@ -1118,7 +1125,8 @@ function _Chat() { }; const deleteMessage = (msgId?: string) => { - chatStore.updateCurrentSession( + chatStore.updateTargetSession( + session, (session) => (session.messages = session.messages.filter((m) => m.id !== msgId)), ); @@ -1185,7 +1193,7 @@ function _Chat() { }; const onPinMessage = (message: ChatMessage) => { - chatStore.updateCurrentSession((session) => + chatStore.updateTargetSession(session, (session) => session.mask.context.push(message), ); @@ -1588,9 +1596,12 @@ function _Chat() {
)} -
+
setIsEditingMessage(true)} > {!session.topic ? DEFAULT_TOPIC : session.topic} @@ -1711,14 +1722,17 @@ function _Chat() { }); } } - chatStore.updateCurrentSession((session) => { - const m = session.mask.context - .concat(session.messages) - .find((m) => m.id === message.id); - if (m) { - m.content = newContent; - } - }); + chatStore.updateTargetSession( + session, + (session) => { + const m = session.mask.context + .concat(session.messages) + .find((m) => m.id === message.id); + if (m) { + m.content = newContent; + } + }, + ); }} >
@@ -1861,7 +1875,7 @@ function _Chat() { )} {getMessageImages(message).length > 1 && (