|
@@ -9,6 +9,7 @@ import CopyIcon from "../icons/copy.svg";
|
|
|
import ClearIcon from "../icons/clear.svg";
|
|
import ClearIcon from "../icons/clear.svg";
|
|
|
import LoadingIcon from "../icons/three-dots.svg";
|
|
import LoadingIcon from "../icons/three-dots.svg";
|
|
|
import EditIcon from "../icons/edit.svg";
|
|
import EditIcon from "../icons/edit.svg";
|
|
|
|
|
+import FireIcon from "../icons/fire.svg";
|
|
|
import EyeIcon from "../icons/eye.svg";
|
|
import EyeIcon from "../icons/eye.svg";
|
|
|
import DownloadIcon from "../icons/download.svg";
|
|
import DownloadIcon from "../icons/download.svg";
|
|
|
import UploadIcon from "../icons/upload.svg";
|
|
import UploadIcon from "../icons/upload.svg";
|
|
@@ -18,7 +19,7 @@ import ConfirmIcon from "../icons/confirm.svg";
|
|
|
import ConnectionIcon from "../icons/connection.svg";
|
|
import ConnectionIcon from "../icons/connection.svg";
|
|
|
import CloudSuccessIcon from "../icons/cloud-success.svg";
|
|
import CloudSuccessIcon from "../icons/cloud-success.svg";
|
|
|
import CloudFailIcon from "../icons/cloud-fail.svg";
|
|
import CloudFailIcon from "../icons/cloud-fail.svg";
|
|
|
-
|
|
|
|
|
|
|
+import { trackSettingsPageGuideToCPaymentClick } from "../utils/auth-settings-events";
|
|
|
import {
|
|
import {
|
|
|
Input,
|
|
Input,
|
|
|
List,
|
|
List,
|
|
@@ -48,7 +49,7 @@ import Locale, {
|
|
|
changeLang,
|
|
changeLang,
|
|
|
getLang,
|
|
getLang,
|
|
|
} from "../locales";
|
|
} from "../locales";
|
|
|
-import { copyToClipboard } from "../utils";
|
|
|
|
|
|
|
+import { copyToClipboard, clientUpdate, semverCompare } from "../utils";
|
|
|
import Link from "next/link";
|
|
import Link from "next/link";
|
|
|
import {
|
|
import {
|
|
|
Anthropic,
|
|
Anthropic,
|
|
@@ -58,6 +59,7 @@ import {
|
|
|
ByteDance,
|
|
ByteDance,
|
|
|
Alibaba,
|
|
Alibaba,
|
|
|
Moonshot,
|
|
Moonshot,
|
|
|
|
|
+ XAI,
|
|
|
Google,
|
|
Google,
|
|
|
GoogleSafetySettingsThreshold,
|
|
GoogleSafetySettingsThreshold,
|
|
|
OPENAI_BASE_URL,
|
|
OPENAI_BASE_URL,
|
|
@@ -69,6 +71,9 @@ import {
|
|
|
UPDATE_URL,
|
|
UPDATE_URL,
|
|
|
Stability,
|
|
Stability,
|
|
|
Iflytek,
|
|
Iflytek,
|
|
|
|
|
+ SAAS_CHAT_URL,
|
|
|
|
|
+ ChatGLM,
|
|
|
|
|
+ DeepSeek,
|
|
|
} from "../constant";
|
|
} from "../constant";
|
|
|
import { Prompt, SearchService, usePromptStore } from "../store/prompt";
|
|
import { Prompt, SearchService, usePromptStore } from "../store/prompt";
|
|
|
import { ErrorBoundary } from "./error";
|
|
import { ErrorBoundary } from "./error";
|
|
@@ -81,6 +86,7 @@ import { nanoid } from "nanoid";
|
|
|
import { useMaskStore } from "../store/mask";
|
|
import { useMaskStore } from "../store/mask";
|
|
|
import { ProviderType } from "../utils/cloud";
|
|
import { ProviderType } from "../utils/cloud";
|
|
|
import { TTSConfigList } from "./tts-config";
|
|
import { TTSConfigList } from "./tts-config";
|
|
|
|
|
+import { RealtimeConfigList } from "./realtime-chat/realtime-config";
|
|
|
|
|
|
|
|
function EditPromptModal(props: { id: string; onClose: () => void }) {
|
|
function EditPromptModal(props: { id: string; onClose: () => void }) {
|
|
|
const promptStore = usePromptStore();
|
|
const promptStore = usePromptStore();
|
|
@@ -583,7 +589,7 @@ export function Settings() {
|
|
|
const [checkingUpdate, setCheckingUpdate] = useState(false);
|
|
const [checkingUpdate, setCheckingUpdate] = useState(false);
|
|
|
const currentVersion = updateStore.formatVersion(updateStore.version);
|
|
const currentVersion = updateStore.formatVersion(updateStore.version);
|
|
|
const remoteId = updateStore.formatVersion(updateStore.remoteVersion);
|
|
const remoteId = updateStore.formatVersion(updateStore.remoteVersion);
|
|
|
- const hasNewVersion = currentVersion !== remoteId;
|
|
|
|
|
|
|
+ const hasNewVersion = semverCompare(currentVersion, remoteId) === -1;
|
|
|
const updateUrl = getClientConfig()?.isApp ? RELEASE_URL : UPDATE_URL;
|
|
const updateUrl = getClientConfig()?.isApp ? RELEASE_URL : UPDATE_URL;
|
|
|
|
|
|
|
|
function checkUpdate(force = false) {
|
|
function checkUpdate(force = false) {
|
|
@@ -686,6 +692,31 @@ export function Settings() {
|
|
|
</ListItem>
|
|
</ListItem>
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
|
|
+ const saasStartComponent = (
|
|
|
|
|
+ <ListItem
|
|
|
|
|
+ className={styles["subtitle-button"]}
|
|
|
|
|
+ title={
|
|
|
|
|
+ Locale.Settings.Access.SaasStart.Title +
|
|
|
|
|
+ `${Locale.Settings.Access.SaasStart.Label}`
|
|
|
|
|
+ }
|
|
|
|
|
+ subTitle={Locale.Settings.Access.SaasStart.SubTitle}
|
|
|
|
|
+ >
|
|
|
|
|
+ <IconButton
|
|
|
|
|
+ aria={
|
|
|
|
|
+ Locale.Settings.Access.SaasStart.Title +
|
|
|
|
|
+ Locale.Settings.Access.SaasStart.ChatNow
|
|
|
|
|
+ }
|
|
|
|
|
+ icon={<FireIcon />}
|
|
|
|
|
+ type={"primary"}
|
|
|
|
|
+ text={Locale.Settings.Access.SaasStart.ChatNow}
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ trackSettingsPageGuideToCPaymentClick();
|
|
|
|
|
+ window.location.href = SAAS_CHAT_URL;
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </ListItem>
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
const useCustomConfigComponent = // Conditionally render the following ListItem based on clientConfig.isApp
|
|
const useCustomConfigComponent = // Conditionally render the following ListItem based on clientConfig.isApp
|
|
|
!clientConfig?.isApp && ( // only show if isApp is false
|
|
!clientConfig?.isApp && ( // only show if isApp is false
|
|
|
<ListItem
|
|
<ListItem
|
|
@@ -1167,6 +1198,127 @@ 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
|
|
|
|
|
+ title={Locale.Settings.Access.XAI.Endpoint.Title}
|
|
|
|
|
+ subTitle={
|
|
|
|
|
+ Locale.Settings.Access.XAI.Endpoint.SubTitle + XAI.ExampleEndpoint
|
|
|
|
|
+ }
|
|
|
|
|
+ >
|
|
|
|
|
+ <input
|
|
|
|
|
+ aria-label={Locale.Settings.Access.XAI.Endpoint.Title}
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ value={accessStore.xaiUrl}
|
|
|
|
|
+ placeholder={XAI.ExampleEndpoint}
|
|
|
|
|
+ onChange={(e) =>
|
|
|
|
|
+ accessStore.update(
|
|
|
|
|
+ (access) => (access.xaiUrl = e.currentTarget.value),
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ ></input>
|
|
|
|
|
+ </ListItem>
|
|
|
|
|
+ <ListItem
|
|
|
|
|
+ title={Locale.Settings.Access.XAI.ApiKey.Title}
|
|
|
|
|
+ subTitle={Locale.Settings.Access.XAI.ApiKey.SubTitle}
|
|
|
|
|
+ >
|
|
|
|
|
+ <PasswordInput
|
|
|
|
|
+ aria-label={Locale.Settings.Access.XAI.ApiKey.Title}
|
|
|
|
|
+ value={accessStore.xaiApiKey}
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ placeholder={Locale.Settings.Access.XAI.ApiKey.Placeholder}
|
|
|
|
|
+ onChange={(e) => {
|
|
|
|
|
+ accessStore.update(
|
|
|
|
|
+ (access) => (access.xaiApiKey = e.currentTarget.value),
|
|
|
|
|
+ );
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </ListItem>
|
|
|
|
|
+ </>
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ const chatglmConfigComponent = accessStore.provider ===
|
|
|
|
|
+ ServiceProvider.ChatGLM && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <ListItem
|
|
|
|
|
+ title={Locale.Settings.Access.ChatGLM.Endpoint.Title}
|
|
|
|
|
+ subTitle={
|
|
|
|
|
+ Locale.Settings.Access.ChatGLM.Endpoint.SubTitle +
|
|
|
|
|
+ ChatGLM.ExampleEndpoint
|
|
|
|
|
+ }
|
|
|
|
|
+ >
|
|
|
|
|
+ <input
|
|
|
|
|
+ aria-label={Locale.Settings.Access.ChatGLM.Endpoint.Title}
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ value={accessStore.chatglmUrl}
|
|
|
|
|
+ placeholder={ChatGLM.ExampleEndpoint}
|
|
|
|
|
+ onChange={(e) =>
|
|
|
|
|
+ accessStore.update(
|
|
|
|
|
+ (access) => (access.chatglmUrl = e.currentTarget.value),
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ ></input>
|
|
|
|
|
+ </ListItem>
|
|
|
|
|
+ <ListItem
|
|
|
|
|
+ title={Locale.Settings.Access.ChatGLM.ApiKey.Title}
|
|
|
|
|
+ subTitle={Locale.Settings.Access.ChatGLM.ApiKey.SubTitle}
|
|
|
|
|
+ >
|
|
|
|
|
+ <PasswordInput
|
|
|
|
|
+ aria-label={Locale.Settings.Access.ChatGLM.ApiKey.Title}
|
|
|
|
|
+ value={accessStore.chatglmApiKey}
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ placeholder={Locale.Settings.Access.ChatGLM.ApiKey.Placeholder}
|
|
|
|
|
+ onChange={(e) => {
|
|
|
|
|
+ accessStore.update(
|
|
|
|
|
+ (access) => (access.chatglmApiKey = e.currentTarget.value),
|
|
|
|
|
+ );
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </ListItem>
|
|
|
|
|
+ </>
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
const stabilityConfigComponent = accessStore.provider ===
|
|
const stabilityConfigComponent = accessStore.provider ===
|
|
|
ServiceProvider.Stability && (
|
|
ServiceProvider.Stability && (
|
|
|
<>
|
|
<>
|
|
@@ -1330,9 +1482,17 @@ export function Settings() {
|
|
|
{checkingUpdate ? (
|
|
{checkingUpdate ? (
|
|
|
<LoadingIcon />
|
|
<LoadingIcon />
|
|
|
) : hasNewVersion ? (
|
|
) : hasNewVersion ? (
|
|
|
- <Link href={updateUrl} target="_blank" className="link">
|
|
|
|
|
- {Locale.Settings.Update.GoToUpdate}
|
|
|
|
|
- </Link>
|
|
|
|
|
|
|
+ clientConfig?.isApp ? (
|
|
|
|
|
+ <IconButton
|
|
|
|
|
+ icon={<ResetIcon></ResetIcon>}
|
|
|
|
|
+ text={Locale.Settings.Update.GoToUpdate}
|
|
|
|
|
+ onClick={() => clientUpdate()}
|
|
|
|
|
+ />
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <Link href={updateUrl} target="_blank" className="link">
|
|
|
|
|
+ {Locale.Settings.Update.GoToUpdate}
|
|
|
|
|
+ </Link>
|
|
|
|
|
+ )
|
|
|
) : (
|
|
) : (
|
|
|
<IconButton
|
|
<IconButton
|
|
|
icon={<ResetIcon></ResetIcon>}
|
|
icon={<ResetIcon></ResetIcon>}
|
|
@@ -1465,6 +1625,39 @@ export function Settings() {
|
|
|
}
|
|
}
|
|
|
></input>
|
|
></input>
|
|
|
</ListItem>
|
|
</ListItem>
|
|
|
|
|
+
|
|
|
|
|
+ <ListItem
|
|
|
|
|
+ title={Locale.Mask.Config.Artifacts.Title}
|
|
|
|
|
+ subTitle={Locale.Mask.Config.Artifacts.SubTitle}
|
|
|
|
|
+ >
|
|
|
|
|
+ <input
|
|
|
|
|
+ aria-label={Locale.Mask.Config.Artifacts.Title}
|
|
|
|
|
+ type="checkbox"
|
|
|
|
|
+ checked={config.enableArtifacts}
|
|
|
|
|
+ onChange={(e) =>
|
|
|
|
|
+ updateConfig(
|
|
|
|
|
+ (config) =>
|
|
|
|
|
+ (config.enableArtifacts = e.currentTarget.checked),
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ ></input>
|
|
|
|
|
+ </ListItem>
|
|
|
|
|
+ <ListItem
|
|
|
|
|
+ title={Locale.Mask.Config.CodeFold.Title}
|
|
|
|
|
+ subTitle={Locale.Mask.Config.CodeFold.SubTitle}
|
|
|
|
|
+ >
|
|
|
|
|
+ <input
|
|
|
|
|
+ aria-label={Locale.Mask.Config.CodeFold.Title}
|
|
|
|
|
+ type="checkbox"
|
|
|
|
|
+ checked={config.enableCodeFold}
|
|
|
|
|
+ data-testid="enable-code-fold-checkbox"
|
|
|
|
|
+ onChange={(e) =>
|
|
|
|
|
+ updateConfig(
|
|
|
|
|
+ (config) => (config.enableCodeFold = e.currentTarget.checked),
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ ></input>
|
|
|
|
|
+ </ListItem>
|
|
|
</List>
|
|
</List>
|
|
|
|
|
|
|
|
<SyncItems />
|
|
<SyncItems />
|
|
@@ -1541,6 +1734,7 @@ export function Settings() {
|
|
|
</List>
|
|
</List>
|
|
|
|
|
|
|
|
<List id={SlotID.CustomModel}>
|
|
<List id={SlotID.CustomModel}>
|
|
|
|
|
+ {saasStartComponent}
|
|
|
{accessCodeComponent}
|
|
{accessCodeComponent}
|
|
|
|
|
|
|
|
{!accessStore.hideUserApiKey && (
|
|
{!accessStore.hideUserApiKey && (
|
|
@@ -1581,8 +1775,11 @@ export function Settings() {
|
|
|
{alibabaConfigComponent}
|
|
{alibabaConfigComponent}
|
|
|
{tencentConfigComponent}
|
|
{tencentConfigComponent}
|
|
|
{moonshotConfigComponent}
|
|
{moonshotConfigComponent}
|
|
|
|
|
+ {deepseekConfigComponent}
|
|
|
{stabilityConfigComponent}
|
|
{stabilityConfigComponent}
|
|
|
{lflytekConfigComponent}
|
|
{lflytekConfigComponent}
|
|
|
|
|
+ {XAIConfigComponent}
|
|
|
|
|
+ {chatglmConfigComponent}
|
|
|
</>
|
|
</>
|
|
|
)}
|
|
)}
|
|
|
</>
|
|
</>
|
|
@@ -1617,9 +1814,11 @@ export function Settings() {
|
|
|
<ListItem
|
|
<ListItem
|
|
|
title={Locale.Settings.Access.CustomModel.Title}
|
|
title={Locale.Settings.Access.CustomModel.Title}
|
|
|
subTitle={Locale.Settings.Access.CustomModel.SubTitle}
|
|
subTitle={Locale.Settings.Access.CustomModel.SubTitle}
|
|
|
|
|
+ vertical={true}
|
|
|
>
|
|
>
|
|
|
<input
|
|
<input
|
|
|
aria-label={Locale.Settings.Access.CustomModel.Title}
|
|
aria-label={Locale.Settings.Access.CustomModel.Title}
|
|
|
|
|
+ style={{ width: "100%", maxWidth: "unset", textAlign: "left" }}
|
|
|
type="text"
|
|
type="text"
|
|
|
value={config.customModels}
|
|
value={config.customModels}
|
|
|
placeholder="model1,model2,model3"
|
|
placeholder="model1,model2,model3"
|
|
@@ -1646,7 +1845,18 @@ export function Settings() {
|
|
|
{shouldShowPromptModal && (
|
|
{shouldShowPromptModal && (
|
|
|
<UserPromptModal onClose={() => setShowPromptModal(false)} />
|
|
<UserPromptModal onClose={() => setShowPromptModal(false)} />
|
|
|
)}
|
|
)}
|
|
|
-
|
|
|
|
|
|
|
+ <List>
|
|
|
|
|
+ <RealtimeConfigList
|
|
|
|
|
+ realtimeConfig={config.realtimeConfig}
|
|
|
|
|
+ updateConfig={(updater) => {
|
|
|
|
|
+ const realtimeConfig = { ...config.realtimeConfig };
|
|
|
|
|
+ updater(realtimeConfig);
|
|
|
|
|
+ config.update(
|
|
|
|
|
+ (config) => (config.realtimeConfig = realtimeConfig),
|
|
|
|
|
+ );
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
<List>
|
|
<List>
|
|
|
<TTSConfigList
|
|
<TTSConfigList
|
|
|
ttsConfig={config.ttsConfig}
|
|
ttsConfig={config.ttsConfig}
|