feat: add custom provider settings popup

This commit is contained in:
kangfenmao 2025-03-19 16:02:52 +08:00
parent c527fbdcd2
commit 530bf42abb
10 changed files with 100 additions and 4 deletions

View File

@ -1,9 +1,8 @@
import { Box } from '@renderer/components/Layout'
import { TopView } from '@renderer/components/TopView'
import { Modal } from 'antd' import { Modal } from 'antd'
import { useState } from 'react' import { useState } from 'react'
import { Box } from '../Layout'
import { TopView } from '../TopView'
interface ShowParams { interface ShowParams {
title: string title: string
} }

View File

@ -982,6 +982,7 @@
"search": "Search Providers...", "search": "Search Providers...",
"search_placeholder": "Search model id or name", "search_placeholder": "Search model id or name",
"title": "Model Provider", "title": "Model Provider",
"is_not_support_array_content": "Enable compatible mode",
"copilot": { "copilot": {
"tooltip": "You need to log in to Github before using Github Copilot", "tooltip": "You need to log in to Github before using Github Copilot",
"description": "Your GitHub account needs to subscribe to Copilot.", "description": "Your GitHub account needs to subscribe to Copilot.",

View File

@ -982,6 +982,7 @@
"search": "プロバイダーを検索...", "search": "プロバイダーを検索...",
"search_placeholder": "モデルIDまたは名前を検索", "search_placeholder": "モデルIDまたは名前を検索",
"title": "モデルプロバイダー", "title": "モデルプロバイダー",
"is_not_support_array_content": "互換モードを有効にする",
"copilot": { "copilot": {
"tooltip": "Github Copilot を使用するには、まず Github にログインする必要があります。", "tooltip": "Github Copilot を使用するには、まず Github にログインする必要があります。",
"description": "あなたのGithubアカウントはCopilotを購読する必要があります。", "description": "あなたのGithubアカウントはCopilotを購読する必要があります。",

View File

@ -982,6 +982,7 @@
"search": "Поиск поставщиков...", "search": "Поиск поставщиков...",
"search_placeholder": "Поиск по ID или имени модели", "search_placeholder": "Поиск по ID или имени модели",
"title": "Провайдеры моделей", "title": "Провайдеры моделей",
"is_not_support_array_content": "Включить совместимый режим",
"copilot": { "copilot": {
"tooltip": "Для использования Github Copilot необходимо сначала войти в Github.", "tooltip": "Для использования Github Copilot необходимо сначала войти в Github.",
"description": "Ваша учетная запись Github должна подписаться на Copilot.", "description": "Ваша учетная запись Github должна подписаться на Copilot.",

View File

@ -982,6 +982,7 @@
"search": "搜索模型平台...", "search": "搜索模型平台...",
"search_placeholder": "搜索模型 ID 或名称", "search_placeholder": "搜索模型 ID 或名称",
"title": "模型服务", "title": "模型服务",
"is_not_support_array_content": "开启兼容模式",
"copilot": { "copilot": {
"tooltip": "使用 Github Copilot 需要先登录 Github", "tooltip": "使用 Github Copilot 需要先登录 Github",
"description": "您的 Github 账号需要订阅 Copilot", "description": "您的 Github 账号需要订阅 Copilot",

View File

@ -982,6 +982,7 @@
"search": "搜尋模型平臺...", "search": "搜尋模型平臺...",
"search_placeholder": "搜尋模型 ID 或名稱", "search_placeholder": "搜尋模型 ID 或名稱",
"title": "模型提供者", "title": "模型提供者",
"is_not_support_array_content": "開啟相容模式",
"copilot": { "copilot": {
"tooltip": "使用 Github Copilot 需要先登入 Github", "tooltip": "使用 Github Copilot 需要先登入 Github",
"description": "您的 Github 帳號需要訂閱 Copilot", "description": "您的 Github 帳號需要訂閱 Copilot",

View File

@ -1,4 +1,4 @@
import { CheckOutlined, ExportOutlined, HeartOutlined, LoadingOutlined } from '@ant-design/icons' import { CheckOutlined, ExportOutlined, HeartOutlined, LoadingOutlined, SettingOutlined } from '@ant-design/icons'
import { HStack } from '@renderer/components/Layout' import { HStack } from '@renderer/components/Layout'
import OAuthButton from '@renderer/components/OAuth/OAuthButton' import OAuthButton from '@renderer/components/OAuth/OAuthButton'
import { PROVIDER_CONFIG } from '@renderer/config/providers' import { PROVIDER_CONFIG } from '@renderer/config/providers'
@ -35,6 +35,7 @@ import HealthCheckPopup from './HealthCheckPopup'
import LMStudioSettings from './LMStudioSettings' import LMStudioSettings from './LMStudioSettings'
import ModelList, { ModelStatus } from './ModelList' import ModelList, { ModelStatus } from './ModelList'
import OllamSettings from './OllamaSettings' import OllamSettings from './OllamaSettings'
import ProviderSettingsPopup from './ProviderSettingsPopup'
import SelectProviderModelPopup from './SelectProviderModelPopup' import SelectProviderModelPopup from './SelectProviderModelPopup'
interface Props { interface Props {
@ -269,6 +270,11 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
<ExportOutlined style={{ color: 'var(--color-text)', fontSize: '12px' }} /> <ExportOutlined style={{ color: 'var(--color-text)', fontSize: '12px' }} />
</Link> </Link>
)} )}
{!provider.isSystem && (
<Button type="text" style={{ width: 30 }} onClick={() => ProviderSettingsPopup.show({ provider })}>
<SettingOutlined />
</Button>
)}
</Flex> </Flex>
<Switch <Switch
value={provider.enabled} value={provider.enabled}

View File

@ -0,0 +1,80 @@
import { TopView } from '@renderer/components/TopView'
import { useProvider } from '@renderer/hooks/useProvider'
import { Provider } from '@renderer/types'
import { Checkbox, Modal } from 'antd'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
interface ShowParams {
provider: Provider
}
interface Props extends ShowParams {
resolve: (data: any) => void
}
const PopupContainer: React.FC<Props> = ({ resolve, ...props }) => {
const [open, setOpen] = useState(true)
const [isNotSupportArrayContent, setIsNotSupportArrayContent] = useState(props.provider.isNotSupportArrayContent)
const { provider, updateProvider } = useProvider(props.provider.id)
const { t } = useTranslation()
const onOk = () => {
setOpen(false)
}
const onCancel = () => {
setOpen(false)
}
const onClose = () => {
resolve({})
}
ProviderSettingsPopup.hide = onCancel
return (
<Modal
title={provider.name}
open={open}
onOk={onOk}
onCancel={onCancel}
afterClose={onClose}
transitionName="ant-move-down"
centered>
<Checkbox
checked={isNotSupportArrayContent}
onChange={(e) => {
setIsNotSupportArrayContent(e.target.checked)
updateProvider({ ...provider, isNotSupportArrayContent: e.target.checked })
}}>
{t('settings.provider.is_not_support_array_content')}
</Checkbox>
</Modal>
)
}
const TopViewKey = 'ProviderSettingsPopup'
export default class ProviderSettingsPopup {
static topviewId = 0
static hide() {
TopView.hide(TopViewKey)
}
static show(props: ShowParams) {
return new Promise<any>((resolve) => {
TopView.show(
<PopupContainer
{...props}
resolve={(v) => {
resolve(v)
TopView.hide(TopViewKey)
}}
/>,
TopViewKey
)
})
}
}

View File

@ -82,7 +82,12 @@ export default class OpenAIProvider extends BaseProvider {
* @returns True if the provider does not support files, false otherwise * @returns True if the provider does not support files, false otherwise
*/ */
private get isNotSupportFiles() { private get isNotSupportFiles() {
if (this.provider?.isNotSupportArrayContent) {
return true
}
const providers = ['deepseek', 'baichuan', 'minimax', 'xirang'] const providers = ['deepseek', 'baichuan', 'minimax', 'xirang']
return providers.includes(this.provider.id) return providers.includes(this.provider.id)
} }

View File

@ -118,6 +118,7 @@ export type Provider = {
isSystem?: boolean isSystem?: boolean
isAuthed?: boolean isAuthed?: boolean
rateLimit?: number rateLimit?: number
isNotSupportArrayContent?: boolean
} }
export type ProviderType = 'openai' | 'anthropic' | 'gemini' | 'qwenlm' | 'azure-openai' export type ProviderType = 'openai' | 'anthropic' | 'gemini' | 'qwenlm' | 'azure-openai'