feat(providers): add API key apply links and update Qwen auth mode (#232)

This commit is contained in:
paisley
2026-02-28 18:11:16 +08:00
committed by GitHub
Unverified
parent cfd387980d
commit 3353de91b8
4 changed files with 34 additions and 4 deletions

View File

@@ -327,6 +327,19 @@ function ProviderCard({
)} )}
</> </>
)} )}
{typeInfo?.apiKeyUrl && (
<div className="flex justify-start mb-1">
<a
href={typeInfo.apiKeyUrl}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-primary hover:underline flex items-center gap-1"
tabIndex={-1}
>
{t('aiProviders.oauth.getApiKey')} <ExternalLink className="h-3 w-3" />
</a>
</div>
)}
<div className="flex gap-2"> <div className="flex gap-2">
<div className="relative flex-1"> <div className="relative flex-1">
<Input <Input
@@ -708,7 +721,20 @@ function AddProviderDialog({ existingTypes, onClose, onAdd, onValidateKey }: Add
{/* API Key input — shown for non-OAuth providers or when apikey mode is selected */} {/* API Key input — shown for non-OAuth providers or when apikey mode is selected */}
{(!isOAuth || (supportsApiKey && authMode === 'apikey')) && ( {(!isOAuth || (supportsApiKey && authMode === 'apikey')) && (
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="apiKey">{t('aiProviders.dialog.apiKey')}</Label> <div className="flex items-center justify-between">
<Label htmlFor="apiKey">{t('aiProviders.dialog.apiKey')}</Label>
{typeInfo?.apiKeyUrl && (
<a
href={typeInfo.apiKeyUrl}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-primary hover:underline flex items-center gap-1"
tabIndex={-1}
>
{t('aiProviders.oauth.getApiKey')} <ExternalLink className="h-3 w-3" />
</a>
)}
</div>
<div className="relative"> <div className="relative">
<Input <Input
id="apiKey" id="apiKey"

View File

@@ -61,6 +61,7 @@
"apikeyMode": "API Key", "apikeyMode": "API Key",
"loginPrompt": "This provider requires signing in via your browser.", "loginPrompt": "This provider requires signing in via your browser.",
"loginButton": "Login with Browser", "loginButton": "Login with Browser",
"getApiKey": "Get API Key",
"waiting": "Waiting...", "waiting": "Waiting...",
"openLoginPage": "Open Login Page", "openLoginPage": "Open Login Page",
"waitingApproval": "Waiting for approval in browser...", "waitingApproval": "Waiting for approval in browser...",

View File

@@ -61,6 +61,7 @@
"apikeyMode": "API 密钥", "apikeyMode": "API 密钥",
"loginPrompt": "此提供商需要通过浏览器登录授权。", "loginPrompt": "此提供商需要通过浏览器登录授权。",
"loginButton": "浏览器登录", "loginButton": "浏览器登录",
"getApiKey": "获取 API 密钥",
"waiting": "等待中...", "waiting": "等待中...",
"openLoginPage": "打开登录页面", "openLoginPage": "打开登录页面",
"waitingApproval": "等待浏览器中的授权...", "waitingApproval": "等待浏览器中的授权...",

View File

@@ -59,6 +59,8 @@ export interface ProviderTypeInfo {
isOAuth?: boolean; isOAuth?: boolean;
/** Whether this provider also accepts a direct API key (in addition to OAuth) */ /** Whether this provider also accepts a direct API key (in addition to OAuth) */
supportsApiKey?: boolean; supportsApiKey?: boolean;
/** URL where users can apply for the API Key */
apiKeyUrl?: string;
} }
import { providerIcons } from '@/assets/providers'; import { providerIcons } from '@/assets/providers';
@@ -72,9 +74,9 @@ export const PROVIDER_TYPE_INFO: ProviderTypeInfo[] = [
{ id: 'ark', name: 'ByteDance Ark', icon: 'A', placeholder: 'your-ark-api-key', model: 'Doubao', requiresApiKey: true, defaultBaseUrl: 'https://ark.cn-beijing.volces.com/api/v3', showBaseUrl: true, showModelId: true, modelIdPlaceholder: 'ep-20260228000000-xxxxx' }, { id: 'ark', name: 'ByteDance Ark', icon: 'A', placeholder: 'your-ark-api-key', model: 'Doubao', requiresApiKey: true, defaultBaseUrl: 'https://ark.cn-beijing.volces.com/api/v3', showBaseUrl: true, showModelId: true, modelIdPlaceholder: 'ep-20260228000000-xxxxx' },
{ id: 'moonshot', name: 'Moonshot (CN)', icon: '🌙', placeholder: 'sk-...', model: 'Kimi', requiresApiKey: true, defaultBaseUrl: 'https://api.moonshot.cn/v1', defaultModelId: 'kimi-k2.5' }, { id: 'moonshot', name: 'Moonshot (CN)', icon: '🌙', placeholder: 'sk-...', model: 'Kimi', requiresApiKey: true, defaultBaseUrl: 'https://api.moonshot.cn/v1', defaultModelId: 'kimi-k2.5' },
{ id: 'siliconflow', name: 'SiliconFlow (CN)', icon: '🌊', placeholder: 'sk-...', model: 'Multi-Model', requiresApiKey: true, defaultBaseUrl: 'https://api.siliconflow.cn/v1', defaultModelId: 'Pro/moonshotai/Kimi-K2.5' }, { id: 'siliconflow', name: 'SiliconFlow (CN)', icon: '🌊', placeholder: 'sk-...', model: 'Multi-Model', requiresApiKey: true, defaultBaseUrl: 'https://api.siliconflow.cn/v1', defaultModelId: 'Pro/moonshotai/Kimi-K2.5' },
{ id: 'minimax-portal', name: 'MiniMax (Global)', icon: '☁️', placeholder: 'sk-...', model: 'MiniMax', requiresApiKey: false, isOAuth: true, supportsApiKey: true, defaultModelId: 'MiniMax-M2.5' }, { id: 'minimax-portal', name: 'MiniMax (Global)', icon: '☁️', placeholder: 'sk-...', model: 'MiniMax', requiresApiKey: false, isOAuth: true, supportsApiKey: true, defaultModelId: 'MiniMax-M2.5', apiKeyUrl: 'https://intl.minimaxi.com/' },
{ id: 'minimax-portal-cn', name: 'MiniMax (CN)', icon: '☁️', placeholder: 'sk-...', model: 'MiniMax', requiresApiKey: false, isOAuth: true, supportsApiKey: true, defaultModelId: 'MiniMax-M2.5' }, { id: 'minimax-portal-cn', name: 'MiniMax (CN)', icon: '☁️', placeholder: 'sk-...', model: 'MiniMax', requiresApiKey: false, isOAuth: true, supportsApiKey: true, defaultModelId: 'MiniMax-M2.5', apiKeyUrl: 'https://platform.minimaxi.com/' },
{ id: 'qwen-portal', name: 'Qwen', icon: '☁️', placeholder: 'sk-...', model: 'Qwen', requiresApiKey: false, isOAuth: true, supportsApiKey: true, defaultModelId: 'coder-model' }, { id: 'qwen-portal', name: 'Qwen', icon: '☁️', placeholder: 'sk-...', model: 'Qwen', requiresApiKey: false, isOAuth: true, defaultModelId: 'coder-model' },
{ id: 'ollama', name: 'Ollama', icon: '🦙', placeholder: 'Not required', requiresApiKey: false, defaultBaseUrl: 'http://localhost:11434', showBaseUrl: true, showModelId: true, modelIdPlaceholder: 'qwen3:latest' }, { id: 'ollama', name: 'Ollama', icon: '🦙', placeholder: 'Not required', requiresApiKey: false, defaultBaseUrl: 'http://localhost:11434', showBaseUrl: true, showModelId: true, modelIdPlaceholder: 'qwen3:latest' },
{ id: 'custom', name: 'Custom', icon: '⚙️', placeholder: 'API key...', requiresApiKey: true, showBaseUrl: true, showModelId: true, modelIdPlaceholder: 'your-provider/model-id' }, { id: 'custom', name: 'Custom', icon: '⚙️', placeholder: 'API key...', requiresApiKey: true, showBaseUrl: true, showModelId: true, modelIdPlaceholder: 'your-provider/model-id' },
]; ];