mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-05-26 07:30:18 +09:00
Merge branch 'ChatGPTNextWeb:main' into main
This commit is contained in:
commit
6d72a04854
@ -14,6 +14,7 @@ const DANGER_CONFIG = {
|
||||
disableFastLink: serverConfig.disableFastLink,
|
||||
customModels: serverConfig.customModels,
|
||||
defaultModel: serverConfig.defaultModel,
|
||||
visionModels: serverConfig.visionModels,
|
||||
};
|
||||
|
||||
declare global {
|
||||
|
@ -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(
|
||||
|
@ -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 (
|
||||
<div className="modal-mask">
|
||||
@ -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);
|
||||
|
||||
|
@ -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 && (
|
||||
<>
|
||||
<ListItem
|
||||
title={Locale.Settings.Access.DeepSeek.Endpoint.Title}
|
||||
subTitle={
|
||||
Locale.Settings.Access.DeepSeek.Endpoint.SubTitle +
|
||||
DeepSeek.ExampleEndpoint
|
||||
}
|
||||
>
|
||||
<input
|
||||
aria-label={Locale.Settings.Access.DeepSeek.Endpoint.Title}
|
||||
type="text"
|
||||
value={accessStore.deepseekUrl}
|
||||
placeholder={DeepSeek.ExampleEndpoint}
|
||||
onChange={(e) =>
|
||||
accessStore.update(
|
||||
(access) => (access.deepseekUrl = e.currentTarget.value),
|
||||
)
|
||||
}
|
||||
></input>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
title={Locale.Settings.Access.DeepSeek.ApiKey.Title}
|
||||
subTitle={Locale.Settings.Access.DeepSeek.ApiKey.SubTitle}
|
||||
>
|
||||
<PasswordInput
|
||||
aria-label={Locale.Settings.Access.DeepSeek.ApiKey.Title}
|
||||
value={accessStore.deepseekApiKey}
|
||||
type="text"
|
||||
placeholder={Locale.Settings.Access.DeepSeek.ApiKey.Placeholder}
|
||||
onChange={(e) => {
|
||||
accessStore.update(
|
||||
(access) => (access.deepseekApiKey = e.currentTarget.value),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</ListItem>
|
||||
</>
|
||||
);
|
||||
|
||||
const XAIConfigComponent = accessStore.provider === ServiceProvider.XAI && (
|
||||
<>
|
||||
<ListItem
|
||||
@ -1815,6 +1857,7 @@ export function Settings() {
|
||||
{alibabaConfigComponent}
|
||||
{tencentConfigComponent}
|
||||
{moonshotConfigComponent}
|
||||
{deepseekConfigComponent}
|
||||
{stabilityConfigComponent}
|
||||
{lflytekConfigComponent}
|
||||
{XAIConfigComponent}
|
||||
|
@ -40,7 +40,6 @@ export const getBuildConfig = () => {
|
||||
buildMode,
|
||||
isApp,
|
||||
template: process.env.DEFAULT_INPUT_TEMPLATE ?? DEFAULT_INPUT_TEMPLATE,
|
||||
visionModels: process.env.VISION_MODELS || "",
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
@ -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: "接口密钥",
|
||||
|
@ -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",
|
||||
|
@ -100,6 +100,7 @@ const tw = {
|
||||
copyLastMessage: "複製最後一個回覆",
|
||||
copyLastCode: "複製最後一個程式碼區塊",
|
||||
showShortcutKey: "顯示快捷方式",
|
||||
clearContext: "清除上下文",
|
||||
},
|
||||
},
|
||||
Export: {
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user