diff --git a/app/api/config/route.ts b/app/api/config/route.ts
index b0d9da031..855a5db01 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/api/deepseek.ts b/app/api/deepseek.ts
index 06d97a0d6..a9879eced 100644
--- a/app/api/deepseek.ts
+++ b/app/api/deepseek.ts
@@ -91,7 +91,7 @@ async function request(req: NextRequest) {
isModelNotavailableInServer(
serverConfig.customModels,
jsonBody?.model as string,
- ServiceProvider.Moonshot as string,
+ ServiceProvider.DeepSeek as string,
)
) {
return NextResponse.json(
diff --git a/app/components/chat.tsx b/app/components/chat.tsx
index f34f7d78e..9990a359e 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/components/settings.tsx b/app/components/settings.tsx
index 5a16039b7..41b0f881d 100644
--- a/app/components/settings.tsx
+++ b/app/components/settings.tsx
@@ -72,6 +72,7 @@ import {
Iflytek,
SAAS_CHAT_URL,
ChatGLM,
+ DeepSeek,
} from "../constant";
import { Prompt, SearchService, usePromptStore } from "../store/prompt";
import { ErrorBoundary } from "./error";
@@ -1278,6 +1279,47 @@ export function Settings() {
>
);
+ const deepseekConfigComponent = accessStore.provider ===
+ ServiceProvider.DeepSeek && (
+ <>
+
+
+ accessStore.update(
+ (access) => (access.deepseekUrl = e.currentTarget.value),
+ )
+ }
+ >
+
+
+ {
+ accessStore.update(
+ (access) => (access.deepseekApiKey = e.currentTarget.value),
+ );
+ }}
+ />
+
+ >
+ );
+
const XAIConfigComponent = accessStore.provider === ServiceProvider.XAI && (
<>
{
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 ced406e90..367f65738 100644
--- a/app/config/server.ts
+++ b/app/config/server.ts
@@ -29,6 +29,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;
@@ -134,6 +135,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 += ",";
@@ -264,6 +266,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 5773b68c6..3ec07b8aa 100644
--- a/app/locales/cn.ts
+++ b/app/locales/cn.ts
@@ -106,6 +106,7 @@ const cn = {
copyLastMessage: "复制最后一个回复",
copyLastCode: "复制最后一个代码块",
showShortcutKey: "显示快捷方式",
+ clearContext: "清除上下文",
},
},
Export: {
@@ -488,6 +489,17 @@ const cn = {
SubTitle: "样例:",
},
},
+ DeepSeek: {
+ ApiKey: {
+ Title: "接口密钥",
+ SubTitle: "使用自定义DeepSeek API Key",
+ Placeholder: "DeepSeek API Key",
+ },
+ Endpoint: {
+ Title: "接口地址",
+ SubTitle: "样例:",
+ },
+ },
XAI: {
ApiKey: {
Title: "接口密钥",
diff --git a/app/locales/en.ts b/app/locales/en.ts
index 5e800049e..514258a9c 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: {
@@ -473,6 +474,17 @@ const en: LocaleType = {
SubTitle: "Example: ",
},
},
+ DeepSeek: {
+ ApiKey: {
+ Title: "DeepSeek API Key",
+ SubTitle: "Use a custom DeepSeek API Key",
+ Placeholder: "DeepSeek API Key",
+ },
+ Endpoint: {
+ Title: "Endpoint Address",
+ SubTitle: "Example: ",
+ },
+ },
XAI: {
ApiKey: {
Title: "XAI API Key",
diff --git a/app/locales/tw.ts b/app/locales/tw.ts
index f10c793ab..83dd547b8 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 4414f7ac6..fb744c14e 100644
--- a/app/store/access.ts
+++ b/app/store/access.ts
@@ -130,6 +130,7 @@ const DEFAULT_ACCESS_STATE = {
disableFastLink: false,
customModels: "",
defaultModel: "",
+ visionModels: "",
// tts config
edgeTTSVoiceName: "zh-CN-YunxiNeural",
@@ -142,7 +143,10 @@ export const useAccessStore = createPersistStore(
this.fetch();
return get().needCode;
},
-
+ getVisionModels() {
+ this.fetch();
+ return get().visionModels;
+ },
edgeVoiceName() {
this.fetch();
return get().edgeTTSVoiceName;
diff --git a/app/utils.ts b/app/utils.ts
index e7f332555..684af7a08 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)) {