From f847982632b593eca0d2fdbf47e123ab107a01a1 Mon Sep 17 00:00:00 2001 From: Haze <709547807@qq.com> Date: Fri, 13 Mar 2026 18:14:54 +0800 Subject: [PATCH] feat(model): opt model provider doc url (#475) --- src/components/settings/ProvidersSettings.tsx | 15 +++--- src/lib/providers.ts | 52 ++++++++++++++++--- src/pages/Setup/index.tsx | 19 ++++++- tests/unit/providers.test.ts | 31 +++++++++-- 4 files changed, 96 insertions(+), 21 deletions(-) diff --git a/src/components/settings/ProvidersSettings.tsx b/src/components/settings/ProvidersSettings.tsx index 602eb1066..f812e5724 100644 --- a/src/components/settings/ProvidersSettings.tsx +++ b/src/components/settings/ProvidersSettings.tsx @@ -31,6 +31,7 @@ import { } from '@/stores/providers'; import { PROVIDER_TYPE_INFO, + getProviderDocsUrl, type ProviderType, getProviderIconUrl, resolveProviderApiKeyForSave, @@ -318,6 +319,7 @@ function ProviderCard({ const [saving, setSaving] = useState(false); const typeInfo = PROVIDER_TYPE_INFO.find((t) => t.id === account.vendorId); + const providerDocsUrl = getProviderDocsUrl(typeInfo, i18n.language); const showModelIdField = shouldShowProviderModelId(typeInfo, devModeUnlocked); const canEditModelConfig = Boolean(typeInfo?.showBaseUrl || showModelIdField); @@ -522,12 +524,10 @@ function ProviderCard({ {isEditing && (
- {account.vendorId === 'custom' && ( + {providerDocsUrl && (
('apikey'); const typeInfo = PROVIDER_TYPE_INFO.find((t) => t.id === selectedType); + const providerDocsUrl = getProviderDocsUrl(typeInfo, i18n.language); const showModelIdField = shouldShowProviderModelId(typeInfo, devModeUnlocked); const isOAuth = typeInfo?.isOAuth ?? false; const supportsApiKey = typeInfo?.supportsApiKey ?? false; @@ -1092,13 +1093,11 @@ function AddProviderDialog({ > {t('aiProviders.dialog.change')} - {selectedType === 'custom' && ( + {providerDocsUrl && ( <> | t.id === type); } +export function getProviderDocsUrl( + provider: Pick | undefined, + language: string +): string | undefined { + if (!provider?.docsUrl) { + return undefined; + } + + if (language.startsWith('zh') && provider.docsUrlZh) { + return provider.docsUrlZh; + } + + return provider.docsUrl; +} + export function shouldShowProviderModelId( provider: Pick | undefined, devModeUnlocked: boolean diff --git a/src/pages/Setup/index.tsx b/src/pages/Setup/index.tsx index 03439fba3..bd5c08181 100644 --- a/src/pages/Setup/index.tsx +++ b/src/pages/Setup/index.tsx @@ -97,6 +97,7 @@ import { type ProviderAccount, type ProviderType, type ProviderTypeInfo, + getProviderDocsUrl, getProviderIconUrl, resolveProviderApiKeyForSave, resolveProviderModelForSave, @@ -713,7 +714,7 @@ function ProviderContent({ onApiKeyChange, onConfiguredChange, }: ProviderContentProps) { - const { t } = useTranslation(['setup', 'settings']); + const { t, i18n } = useTranslation(['setup', 'settings']); const devModeUnlocked = useSettingsStore((state) => state.devModeUnlocked); const [showKey, setShowKey] = useState(false); const [validating, setValidating] = useState(false); @@ -975,6 +976,7 @@ function ProviderContent({ }, [providerMenuOpen]); const selectedProviderData = providers.find((p) => p.id === selectedProvider); + const providerDocsUrl = getProviderDocsUrl(selectedProviderData, i18n.language); const selectedProviderIconUrl = selectedProviderData ? getProviderIconUrl(selectedProviderData.id) : undefined; @@ -1139,7 +1141,20 @@ function ProviderContent({
{/* Provider selector — dropdown */}
- +
+ + {selectedProvider && providerDocsUrl && ( + + {t('settings:aiProviders.dialog.customDoc')} + + + )} +