fix: provider settings UI, OpenRouter model field, merge resolution, i18n

This commit is contained in:
paisley
2026-03-08 13:56:46 +08:00
parent 12b1cb2b32
commit 1be7e28b63
4 changed files with 54 additions and 67 deletions

View File

@@ -72,16 +72,19 @@ function fallbackModelsEqual(a?: string[], b?: string[]): boolean {
return left.length === right.length && left.every((model, index) => model === right[index]);
}
function getAuthModeLabel(authMode: ProviderAccount['authMode']): string {
function getAuthModeLabel(
authMode: ProviderAccount['authMode'],
t: (key: string) => string
): string {
switch (authMode) {
case 'api_key':
return 'API Key';
return t('aiProviders.authModes.apiKey');
case 'oauth_device':
return 'OAuth Device';
return t('aiProviders.authModes.oauthDevice');
case 'oauth_browser':
return 'OAuth Browser';
return t('aiProviders.authModes.oauthBrowser');
case 'local':
return 'Local';
return t('aiProviders.authModes.local');
default:
return authMode;
}
@@ -174,14 +177,6 @@ export function ProvidersSettings() {
return (
<div className="space-y-4">
{accounts.length > 0 && (
<ProviderAccountsOverview
accounts={accounts}
vendors={vendors}
defaultAccountId={defaultAccountId}
/>
)}
<div className="flex justify-end">
<Button size="sm" onClick={() => setShowAddDialog(true)}>
<Plus className="h-4 w-4 mr-2" />
@@ -259,58 +254,6 @@ export function ProvidersSettings() {
);
}
function ProviderAccountsOverview({
accounts,
vendors,
defaultAccountId,
}: {
accounts: ProviderAccount[];
vendors: ProviderVendorInfo[];
defaultAccountId: string | null;
}) {
const vendorMap = new Map(vendors.map((vendor) => [vendor.id, vendor]));
return (
<Card>
<CardHeader className="pb-3">
<CardTitle>Provider Accounts</CardTitle>
<CardDescription>
Account-aware provider metadata is now available and will back the next UI migration step.
</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
{accounts.map((account) => {
const vendor = vendorMap.get(account.vendorId);
return (
<div
key={account.id}
className="flex items-center justify-between rounded-lg border p-3"
>
<div className="min-w-0">
<div className="flex items-center gap-2">
<span className="font-medium truncate">{account.label}</span>
<Badge variant="secondary">{vendor?.name || account.vendorId}</Badge>
<Badge variant="outline">{getAuthModeLabel(account.authMode)}</Badge>
{account.id === defaultAccountId || account.isDefault ? (
<Badge>Default</Badge>
) : null}
</div>
<div className="mt-1 text-sm text-muted-foreground truncate">
{account.model || 'No model selected'}
</div>
</div>
<div className="text-xs text-muted-foreground">
{vendor?.supportsMultipleAccounts ? 'multi-account ready' : 'singleton vendor'}
</div>
</div>
);
})}
</CardContent>
</Card>
);
}
interface ProviderCardProps {
item: ProviderListItem;
allProviders: ProviderListItem[];
@@ -466,9 +409,14 @@ function ProviderCard({
<div className="flex items-center gap-2">
<span className="font-semibold">{account.label}</span>
<Badge variant="secondary">{vendor?.name || account.vendorId}</Badge>
<Badge variant="outline">{getAuthModeLabel(account.authMode)}</Badge>
<Badge variant="outline">{getAuthModeLabel(account.authMode, t)}</Badge>
</div>
<div className="mt-1 space-y-0.5">
<p className="text-xs text-muted-foreground capitalize">{account.vendorId}</p>
<p className="text-xs text-muted-foreground truncate">
{t('aiProviders.dialog.modelId')}: {account.model || t('aiProviders.card.none')}
</p>
</div>
<span className="text-xs text-muted-foreground capitalize">{account.vendorId}</span>
</div>
</div>
</div>

View File

@@ -13,6 +13,19 @@
"aiProviders": {
"title": "AI Providers",
"description": "Configure your AI model providers and API keys",
"overview": {
"title": "Provider Accounts",
"description": "A summary of the provider accounts and models currently configured.",
"noModelSelected": "No model selected",
"multiAccountReady": "Multi-account ready",
"singletonVendor": "Single-account vendor"
},
"authModes": {
"apiKey": "API Key",
"oauthDevice": "OAuth Device",
"oauthBrowser": "OAuth Browser",
"local": "Local"
},
"sections": {
"model": "Model Settings",
"fallback": "Fallback Settings"

View File

@@ -13,6 +13,19 @@
"aiProviders": {
"title": "AI プロバイダー",
"description": "AI モデルプロバイダーと API キーを設定",
"overview": {
"title": "プロバイダーアカウント",
"description": "現在設定されているプロバイダーアカウントとモデルの概要です。",
"noModelSelected": "モデル未選択",
"multiAccountReady": "複数アカウント対応",
"singletonVendor": "単一アカウントのプロバイダー"
},
"authModes": {
"apiKey": "API キー",
"oauthDevice": "OAuth デバイス",
"oauthBrowser": "OAuth ブラウザ",
"local": "ローカル"
},
"sections": {
"model": "モデル設定",
"fallback": "フォールバック設定"

View File

@@ -13,6 +13,19 @@
"aiProviders": {
"title": "AI 模型提供商",
"description": "配置 AI 模型提供商和 API 密钥",
"overview": {
"title": "提供商账户",
"description": "这里汇总当前已配置的 provider 账户与模型信息。",
"noModelSelected": "未选择模型",
"multiAccountReady": "支持多账户",
"singletonVendor": "单例提供商"
},
"authModes": {
"apiKey": "API 密钥",
"oauthDevice": "OAuth 设备登录",
"oauthBrowser": "OAuth 浏览器登录",
"local": "本地"
},
"sections": {
"model": "模型配置",
"fallback": "回退配置"