diff --git a/app/api/config/route.ts b/app/api/config/route.ts index b0d9da03103..855a5db017e 100644 --- a/app/api/config/route.ts +++ b/app/api/config/route.ts @@ -14,6 +14,7 @@ const DANGER_CONFIG = { disableFastLink: serverConfig.disableFastLink, customModels: serverConfig.customModels, defaultModel: serverConfig.defaultModel, + visionModels: serverConfig.visionModels, }; declare global { diff --git a/app/components/chat.tsx b/app/components/chat.tsx index f34f7d78e09..9990a359e14 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -900,6 +900,12 @@ export function ShortcutKeyModal(props: { onClose: () => void }) { title: Locale.Chat.ShortcutKey.showShortcutKey, keys: isMac ? ["⌘", "/"] : ["Ctrl", "/"], }, + { + title: Locale.Chat.ShortcutKey.clearContext, + keys: isMac + ? ["⌘", "Shift", "backspace"] + : ["Ctrl", "Shift", "backspace"], + }, ]; return (
@@ -1552,7 +1558,7 @@ function _Chat() { const [showShortcutKeyModal, setShowShortcutKeyModal] = useState(false); useEffect(() => { - const handleKeyDown = (event: any) => { + const handleKeyDown = (event: KeyboardEvent) => { // 打开新聊天 command + shift + o if ( (event.metaKey || event.ctrlKey) && @@ -1603,14 +1609,30 @@ function _Chat() { event.preventDefault(); setShowShortcutKeyModal(true); } + // 清除上下文 command + shift + backspace + else if ( + (event.metaKey || event.ctrlKey) && + event.shiftKey && + event.key.toLowerCase() === "backspace" + ) { + event.preventDefault(); + chatStore.updateTargetSession(session, (session) => { + if (session.clearContextIndex === session.messages.length) { + session.clearContextIndex = undefined; + } else { + session.clearContextIndex = session.messages.length; + session.memoryPrompt = ""; // will clear memory + } + }); + } }; - window.addEventListener("keydown", handleKeyDown); + document.addEventListener("keydown", handleKeyDown); return () => { - window.removeEventListener("keydown", handleKeyDown); + document.removeEventListener("keydown", handleKeyDown); }; - }, [messages, chatStore, navigate]); + }, [messages, chatStore, navigate, session]); const [showChatSidePanel, setShowChatSidePanel] = useState(false); diff --git a/app/config/build.ts b/app/config/build.ts index aa7c10729b6..b2b1ad49da1 100644 --- a/app/config/build.ts +++ b/app/config/build.ts @@ -40,7 +40,6 @@ export const getBuildConfig = () => { buildMode, isApp, template: process.env.DEFAULT_INPUT_TEMPLATE ?? DEFAULT_INPUT_TEMPLATE, - visionModels: process.env.VISION_MODELS || "", }; }; diff --git a/app/config/server.ts b/app/config/server.ts index d5ffaab5467..73faa881527 100644 --- a/app/config/server.ts +++ b/app/config/server.ts @@ -23,6 +23,7 @@ declare global { DISABLE_FAST_LINK?: string; // disallow parse settings from url or not CUSTOM_MODELS?: string; // to control custom models DEFAULT_MODEL?: string; // to control default model in every new chat window + VISION_MODELS?: string; // to control vision models // stability only STABILITY_URL?: string; @@ -128,6 +129,7 @@ export const getServerSideConfig = () => { const disableGPT4 = !!process.env.DISABLE_GPT4; let customModels = process.env.CUSTOM_MODELS ?? ""; let defaultModel = process.env.DEFAULT_MODEL ?? ""; + let visionModels = process.env.VISION_MODELS ?? ""; if (disableGPT4) { if (customModels) customModels += ","; @@ -249,6 +251,7 @@ export const getServerSideConfig = () => { disableFastLink: !!process.env.DISABLE_FAST_LINK, customModels, defaultModel, + visionModels, allowedWebDavEndpoints, }; }; diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 182a4ce541c..25f49be7d19 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -106,6 +106,7 @@ const cn = { copyLastMessage: "复制最后一个回复", copyLastCode: "复制最后一个代码块", showShortcutKey: "显示快捷方式", + clearContext: "清除上下文", }, }, Export: { diff --git a/app/locales/en.ts b/app/locales/en.ts index 27f44e5d9d7..3eb750d445e 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -107,6 +107,7 @@ const en: LocaleType = { copyLastMessage: "Copy Last Reply", copyLastCode: "Copy Last Code Block", showShortcutKey: "Show Shortcuts", + clearContext: "Clear Context", }, }, Export: { diff --git a/app/locales/tw.ts b/app/locales/tw.ts index f10c793ab80..83dd547b8ed 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -100,6 +100,7 @@ const tw = { copyLastMessage: "複製最後一個回覆", copyLastCode: "複製最後一個程式碼區塊", showShortcutKey: "顯示快捷方式", + clearContext: "清除上下文", }, }, Export: { diff --git a/app/store/access.ts b/app/store/access.ts index 3c7f84adac0..1fed5dfeda7 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -131,6 +131,7 @@ const DEFAULT_ACCESS_STATE = { disableFastLink: false, customModels: "", defaultModel: "", + visionModels: "", // tts config edgeTTSVoiceName: "zh-CN-YunxiNeural", @@ -145,7 +146,10 @@ export const useAccessStore = createPersistStore( return get().needCode; }, - + getVisionModels() { + this.fetch(); + return get().visionModels; + }, edgeVoiceName() { this.fetch(); diff --git a/app/utils.ts b/app/utils.ts index 810dc7842b1..4f5b7b0b7de 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -6,7 +6,7 @@ import { ServiceProvider } from "./constant"; // import { fetch as tauriFetch, ResponseType } from "@tauri-apps/api/http"; import { fetch as tauriStreamFetch } from "./utils/stream"; import { VISION_MODEL_REGEXES, EXCLUDE_VISION_MODEL_REGEXES } from "./constant"; -import { getClientConfig } from "./config/client"; +import { useAccessStore } from "./store"; import { ModelSize } from "./typing"; export function trimTopic(topic: string) { @@ -255,8 +255,8 @@ export function getMessageImages(message: RequestMessage): string[] { } export function isVisionModel(model: string) { - const clientConfig = getClientConfig(); - const envVisionModels = clientConfig?.visionModels + const visionModels = useAccessStore.getState().visionModels; + const envVisionModels = visionModels ?.split(",") .map((m) => m.trim()); if (envVisionModels?.includes(model)) {