diff --git a/app/api/auth.ts b/app/api/auth.ts index 86a8b1ad..fa9f9f4c 100644 --- a/app/api/auth.ts +++ b/app/api/auth.ts @@ -2,6 +2,7 @@ import { NextRequest } from "next/server"; import { getServerSideConfig } from "../config/server"; import md5 from "spark-md5"; import { ACCESS_CODE_PREFIX } from "../constant"; +import { OPENAI_URL } from "./common"; function getIP(req: NextRequest) { let ip = req.ip ?? req.headers.get("x-real-ip"); @@ -55,7 +56,7 @@ export function auth(req: NextRequest) { } else { console.log("[Auth] admin did not provide an api key"); return { - error: true, + error: serverConfig.baseUrl?.includes(OPENAI_URL), msg: "admin did not provide an api key", }; } diff --git a/app/api/common.ts b/app/api/common.ts index 06a67931..eb073922 100644 --- a/app/api/common.ts +++ b/app/api/common.ts @@ -1,6 +1,6 @@ import { NextRequest } from "next/server"; -const OPENAI_URL = "api.openai.com"; +export const OPENAI_URL = "api.openai.com"; const DEFAULT_PROTOCOL = "https"; const PROTOCOL = process.env.PROTOCOL ?? DEFAULT_PROTOCOL; const BASE_URL = process.env.BASE_URL ?? OPENAI_URL; @@ -45,8 +45,8 @@ export async function requestOpenai(req: NextRequest) { signal: controller.signal, }); } catch (err: unknown) { - if (err instanceof Error && err.name === 'AbortError') { - console.log('Fetch aborted'); + if (err instanceof Error && err.name === "AbortError") { + console.log("Fetch aborted"); } else { throw err; } diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 758900a9..fffa8b88 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -143,6 +143,7 @@ export function SessionConfigModel(props: { onClose: () => void }) { updater(mask); chatStore.updateCurrentSession((session) => (session.mask = mask)); }} + shouldSyncFromGlobal extraListItems={ session.mask.modelConfig.sendMemory ? ( ; extraListItems?: JSX.Element; readonly?: boolean; + shouldSyncFromGlobal?: boolean; }) { const [showPicker, setShowPicker] = useState(false); @@ -49,9 +50,15 @@ export function MaskConfig(props: { const config = { ...props.mask.modelConfig }; updater(config); - props.updateMask((mask) => (mask.modelConfig = config)); + props.updateMask((mask) => { + mask.modelConfig = config; + // if user changed current session mask, it will disable auto sync + mask.syncGlobalConfig = false; + }); }; + const globalConfig = useAppConfig(); + return ( <> - props.updateMask((mask) => (mask.name = e.currentTarget.value)) + props.updateMask((mask) => { + mask.name = e.currentTarget.value; + }) } > + + { + if ( + e.currentTarget.checked && + confirm(Locale.Mask.Config.Sync.Confirm) + ) { + props.updateMask((mask) => { + mask.syncGlobalConfig = e.currentTarget.checked; + mask.modelConfig = { ...globalConfig.modelConfig }; + }); + } + }} + > + @@ -330,7 +359,7 @@ export function MaskPage() { {AllLangs.map((lang) => ( ))} @@ -358,7 +387,7 @@ export function MaskPage() {
{m.name}
{`${Locale.Mask.Item.Info(m.context.length)} / ${ - Locale.Settings.Lang.Options[m.lang] + ALL_LANG_OPTIONS[m.lang] } / ${m.modelConfig.model}`}
diff --git a/app/components/settings.tsx b/app/components/settings.tsx index eb83d890..9029fdf2 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -31,7 +31,12 @@ import { useAppConfig, } from "../store"; -import Locale, { AllLangs, changeLang, getLang } from "../locales"; +import Locale, { + AllLangs, + ALL_LANG_OPTIONS, + changeLang, + getLang, +} from "../locales"; import { copyToClipboard } from "../utils"; import Link from "next/link"; import { Path, UPDATE_URL } from "../constant"; @@ -419,7 +424,7 @@ export function Settings() { > {AllLangs.map((lang) => ( ))} diff --git a/app/config/server.ts b/app/config/server.ts index 23fec868..b978e726 100644 --- a/app/config/server.ts +++ b/app/config/server.ts @@ -5,6 +5,7 @@ declare global { interface ProcessEnv { OPENAI_API_KEY?: string; CODE?: string; + BASE_URL?: string; PROXY_URL?: string; VERCEL?: string; HIDE_USER_API_KEY?: string; // disable user's api key input @@ -38,6 +39,7 @@ export const getServerSideConfig = () => { code: process.env.CODE, codes: ACCESS_CODES, needCode: ACCESS_CODES.size > 0, + baseUrl: process.env.BASE_URL, proxyUrl: process.env.PROXY_URL, isVercel: !!process.env.VERCEL, hideUserApiKey: !!process.env.HIDE_USER_API_KEY, diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 035e9c2e..9f0ea044 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -69,21 +69,6 @@ const cn = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "所有语言", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "头像", FontSize: { @@ -220,6 +205,11 @@ const cn = { Config: { Avatar: "角色头像", Name: "角色名称", + Sync: { + Title: "使用全局设置", + SubTitle: "当前对话是否使用全局模型设置", + Confirm: "当前对话的自定义设置将会被自动覆盖,确认启用全局设置?", + }, }, }, NewChat: { @@ -247,5 +237,6 @@ type DeepPartial = T extends object } : T; export type LocaleType = DeepPartial; +export type RequiredLocaleType = typeof cn; export default cn; diff --git a/app/locales/cs.ts b/app/locales/cs.ts index 6933535e..734db37f 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -71,21 +71,6 @@ const cs: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "Všechny jazyky", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "Avatar", FontSize: { diff --git a/app/locales/de.ts b/app/locales/de.ts index b609a0bb..7b0ca5cc 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -72,21 +72,6 @@ const de: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "Alle Sprachen", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "Avatar", FontSize: { diff --git a/app/locales/en.ts b/app/locales/en.ts index efafc3b0..dc02aa66 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -1,7 +1,7 @@ import { SubmitKey } from "../store/config"; -import type { LocaleType } from "./index"; +import { RequiredLocaleType } from "./index"; -const en: LocaleType = { +const en: RequiredLocaleType = { WIP: "Coming Soon...", Error: { Unauthorized: @@ -71,21 +71,6 @@ const en: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "All Languages", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "Avatar", FontSize: { @@ -223,6 +208,11 @@ const en: LocaleType = { Config: { Avatar: "Bot Avatar", Name: "Bot Name", + Sync: { + Title: "Use Global Config", + SubTitle: "Use global config in this chat", + Confirm: "Confirm to override custom config with global config?", + }, }, }, NewChat: { diff --git a/app/locales/es.ts b/app/locales/es.ts index 6e88b460..15f731cb 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -71,21 +71,6 @@ const es: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "Todos los idiomas", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어" - }, }, Avatar: "Avatar", FontSize: { diff --git a/app/locales/fr.ts b/app/locales/fr.ts index 31433678..046cebe6 100644 --- a/app/locales/fr.ts +++ b/app/locales/fr.ts @@ -72,21 +72,6 @@ const fr: LocaleType = { Lang: { Name: "Language", // ATTENTION : si vous souhaitez ajouter une nouvelle traduction, ne traduisez pas cette valeur, laissez-la sous forme de `Language` All: "Toutes les langues", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Vietnamese", - ru: "Русский", - cs: "Čeština", - ko: "한국어" - }, }, Avatar: "Avatar", diff --git a/app/locales/index.ts b/app/locales/index.ts index e44b7589..22c417da 100644 --- a/app/locales/index.ts +++ b/app/locales/index.ts @@ -13,7 +13,7 @@ import CS from "./cs"; import KO from "./ko"; import { merge } from "../utils/merge"; -export type { LocaleType } from "./cn"; +export type { LocaleType, RequiredLocaleType } from "./cn"; export const AllLangs = [ "en", @@ -32,6 +32,22 @@ export const AllLangs = [ ] as const; export type Lang = (typeof AllLangs)[number]; +export const ALL_LANG_OPTIONS: Record = { + cn: "简体中文", + en: "English", + tw: "繁體中文", + fr: "Français", + es: "Español", + it: "Italiano", + tr: "Türkçe", + jp: "日本語", + de: "Deutsch", + vi: "Tiếng Việt", + ru: "Русский", + cs: "Čeština", + ko: "한국어", +}; + const LANG_KEY = "lang"; const DEFAULT_LANG = "en"; diff --git a/app/locales/it.ts b/app/locales/it.ts index 655a6a89..0d87588f 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -71,21 +71,6 @@ const it: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "Tutte le lingue", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "Avatar", FontSize: { diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 5e386b28..8002d045 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -71,21 +71,6 @@ const jp: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "所有语言", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어" - }, }, Avatar: "アバター", FontSize: { diff --git a/app/locales/ko.ts b/app/locales/ko.ts index 0ccb40e4..12b8db28 100644 --- a/app/locales/ko.ts +++ b/app/locales/ko.ts @@ -71,27 +71,12 @@ const ko: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "All Languages", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "아바타", FontSize: { - Title: "글꼴 크기", - SubTitle: "채팅 내용의 글꼴 크기 조정", - }, + Title: "글꼴 크기", + SubTitle: "채팅 내용의 글꼴 크기 조정", + }, Update: { Version: (x: string) => `버전: ${x}`, IsLatest: "최신 버전", @@ -135,8 +120,7 @@ const ko: LocaleType = { }, CompressThreshold: { Title: "기록 압축 임계값", - SubTitle: - "미압축 메시지 길이가 임계값을 초과하면 압축됨", + SubTitle: "미압축 메시지 길이가 임계값을 초과하면 압축됨", }, Token: { Title: "API 키", @@ -165,11 +149,10 @@ const ko: LocaleType = { MaxTokens: { Title: "최대 토큰 수 (max_tokens)", SubTitle: "입력 토큰과 생성된 토큰의 최대 길이", - }, + }, PresencePenalty: { Title: "존재 페널티 (presence_penalty)", - SubTitle: - "값이 클수록 새로운 주제에 대해 대화할 가능성이 높아집니다.", + SubTitle: "값이 클수록 새로운 주제에 대해 대화할 가능성이 높아집니다.", }, }, Store: { @@ -178,8 +161,7 @@ const ko: LocaleType = { Error: "문제가 발생했습니다. 나중에 다시 시도해주세요.", Prompt: { History: (content: string) => - "이것은 AI와 사용자 간의 대화 기록을 요약한 내용입니다: " + - content, + "이것은 AI와 사용자 간의 대화 기록을 요약한 내용입니다: " + content, Topic: "다음과 같이 대화 내용을 요약하는 4~5단어 제목을 생성해주세요. 따옴표, 구두점, 인용부호, 기호 또는 추가 텍스트를 제거하십시오. 따옴표로 감싸진 부분을 제거하십시오.", Summarize: @@ -232,7 +214,8 @@ const ko: LocaleType = { SubTitle: "마스크 뒤의 영혼과 대화하세요", More: "더 보기", NotShow: "다시 표시하지 않음", - ConfirmNoShow: "비활성화하시겠습니까? 나중에 설정에서 다시 활성화할 수 있습니다.", + ConfirmNoShow: + "비활성화하시겠습니까? 나중에 설정에서 다시 활성화할 수 있습니다.", }, UI: { @@ -242,6 +225,6 @@ const ko: LocaleType = { Create: "생성", Edit: "편집", }, - }; +}; export default ko; diff --git a/app/locales/ru.ts b/app/locales/ru.ts index 32930626..3993ea43 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -71,21 +71,6 @@ const ru: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "Все языки", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "Аватар", FontSize: { diff --git a/app/locales/tr.ts b/app/locales/tr.ts index 86bcd95b..e26091fe 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -71,21 +71,6 @@ const tr: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "Tüm Diller", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "Avatar", FontSize: { diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 5295f0e8..025e5e61 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -69,21 +69,6 @@ const tw: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "所有语言", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "大頭貼", FontSize: { diff --git a/app/locales/vi.ts b/app/locales/vi.ts index 5f346b31..78eeaf40 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -71,21 +71,6 @@ const vi: LocaleType = { Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "Tất cả ngôn ngữ", - Options: { - cn: "简体中文", - en: "English", - tw: "繁體中文", - fr: "Français", - es: "Español", - it: "Italiano", - tr: "Türkçe", - jp: "日本語", - de: "Deutsch", - vi: "Tiếng Việt", - ru: "Русский", - cs: "Čeština", - ko: "한국어", - }, }, Avatar: "Ảnh đại diện", FontSize: { diff --git a/app/store/chat.ts b/app/store/chat.ts index dff88c7c..e063a12c 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -5,9 +5,9 @@ import { trimTopic } from "../utils"; import Locale from "../locales"; import { showToast } from "../components/ui-lib"; -import { ModelType } from "./config"; +import { ModelType, useAppConfig } from "./config"; import { createEmptyMask, Mask } from "./mask"; -import { REQUEST_TIMEOUT_MS, StoreKey } from "../constant"; +import { StoreKey } from "../constant"; import { api, RequestMessage } from "../client/api"; import { ChatControllerPool } from "../client/controller"; import { prettyObject } from "../utils/format"; @@ -38,7 +38,6 @@ export interface ChatStat { export interface ChatSession { id: number; - topic: string; memoryPrompt: string; @@ -69,6 +68,7 @@ function createEmptySession(): ChatSession { }, lastUpdate: Date.now(), lastSummarizeIndex: 0, + mask: createEmptyMask(), }; } @@ -463,7 +463,7 @@ export const useChatStore = create()( if ( historyMsgLength > modelConfig.compressMessageLengthThreshold && - session.mask.modelConfig.sendMemory + modelConfig.sendMemory ) { api.llm.chat({ messages: toBeSummarizedMsgs.concat({ diff --git a/app/store/mask.ts b/app/store/mask.ts index efd774eb..a691a7cf 100644 --- a/app/store/mask.ts +++ b/app/store/mask.ts @@ -11,6 +11,7 @@ export type Mask = { avatar: string; name: string; context: ChatMessage[]; + syncGlobalConfig?: boolean; modelConfig: ModelConfig; lang: Lang; builtin: boolean; @@ -39,6 +40,7 @@ export const createEmptyMask = () => avatar: DEFAULT_MASK_AVATAR, name: DEFAULT_TOPIC, context: [], + syncGlobalConfig: true, // use global config as default modelConfig: { ...useAppConfig.getState().modelConfig }, lang: getLang(), builtin: false,