diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index 32a4cff..5cd407a 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -370,7 +370,10 @@
"load_failed": "Failed to load exclusion list",
"provider_required": "Please enter a provider first",
"scope_all": "Scope: All providers",
- "scope_provider": "Scope: {provider}"
+ "scope_provider": "Scope: {provider}",
+ "upgrade_required": "This feature requires a newer CLI Proxy API (CPA) version. Please upgrade.",
+ "upgrade_required_title": "Please upgrade CLI Proxy API",
+ "upgrade_required_desc": "The current server does not support the OAuth excluded models API. Please upgrade to the latest CLI Proxy API (CPA) version."
},
"auth_login": {
"codex_oauth_title": "Codex OAuth",
diff --git a/src/i18n/locales/zh-CN.json b/src/i18n/locales/zh-CN.json
index fe1e9d6..77b466b 100644
--- a/src/i18n/locales/zh-CN.json
+++ b/src/i18n/locales/zh-CN.json
@@ -380,7 +380,10 @@
"load_failed": "加载排除列表失败",
"provider_required": "请先填写提供商名称",
"scope_all": "当前范围:全局(显示所有提供商)",
- "scope_provider": "当前范围:{{provider}}"
+ "scope_provider": "当前范围:{{provider}}",
+ "upgrade_required": "当前 CPA 版本不支持模型排除列表,请升级 CPA 版本",
+ "upgrade_required_title": "需要升级 CPA 版本",
+ "upgrade_required_desc": "当前服务器版本不支持获取模型排除列表功能,请升级到最新版本的 CPA(CLI Proxy API)后重试。"
},
"auth_login": {
"codex_oauth_title": "Codex OAuth",
diff --git a/src/pages/AiProvidersPage.tsx b/src/pages/AiProvidersPage.tsx
index f2486e9..c5519b7 100644
--- a/src/pages/AiProvidersPage.tsx
+++ b/src/pages/AiProvidersPage.tsx
@@ -1072,8 +1072,10 @@ export function AiProvidersPage() {
};
return (
-
- {error &&
{error}
}
+
+
{t('ai_providers.title')}
+
+ {error &&
{error}
}
)}
+
);
}
diff --git a/src/pages/ApiKeysPage.module.scss b/src/pages/ApiKeysPage.module.scss
index b30bb31..224958f 100644
--- a/src/pages/ApiKeysPage.module.scss
+++ b/src/pages/ApiKeysPage.module.scss
@@ -1,3 +1,5 @@
+@use '../styles/mixins' as *;
+
.container {
width: 100%;
}
diff --git a/src/pages/ApiKeysPage.tsx b/src/pages/ApiKeysPage.tsx
index 9bf69fa..348ebd1 100644
--- a/src/pages/ApiKeysPage.tsx
+++ b/src/pages/ApiKeysPage.tsx
@@ -9,6 +9,7 @@ import { LoadingSpinner } from '@/components/ui/LoadingSpinner';
import { useAuthStore, useConfigStore, useNotificationStore } from '@/stores';
import { apiKeysApi } from '@/services/api';
import { maskApiKey } from '@/utils/format';
+import styles from './ApiKeysPage.module.scss';
export function ApiKeysPage() {
const { t } = useTranslation();
@@ -138,80 +139,84 @@ export function ApiKeysPage() {
);
return (
-
- {error && {error}
}
+
+
{t('api_keys.title')}
- {loading ? (
-
-
-
- ) : apiKeys.length === 0 ? (
-
- {t('api_keys.add_button')}
-
- }
- />
- ) : (
-
- {apiKeys.map((key, index) => (
-
-
-
#{index + 1}
-
{t('api_keys.item_title')}
-
{maskApiKey(String(key || ''))}
-
-
-
-
-
-
- ))}
-
- )}
+
+ {error && {error}
}
-
-
-
- >
- }
- >
-
+
+
+ ) : apiKeys.length === 0 ? (
+
+ {t('api_keys.add_button')}
+
+ }
+ />
+ ) : (
+
+ {apiKeys.map((key, index) => (
+
+
+
#{index + 1}
+
{t('api_keys.item_title')}
+
{maskApiKey(String(key || ''))}
+
+
+
+
+
+
+ ))}
+
+ )}
+
+
+
+
+ >
}
- placeholder={
- editingIndex !== null
- ? t('api_keys.edit_modal_key_label')
- : t('api_keys.add_modal_key_placeholder')
- }
- value={inputValue}
- onChange={(e) => setInputValue(e.target.value)}
- disabled={saving}
- />
-
-
+ >
+
setInputValue(e.target.value)}
+ disabled={saving}
+ />
+
+
+
);
}
diff --git a/src/pages/AuthFilesPage.module.scss b/src/pages/AuthFilesPage.module.scss
index 3d0e106..fc8807f 100644
--- a/src/pages/AuthFilesPage.module.scss
+++ b/src/pages/AuthFilesPage.module.scss
@@ -7,6 +7,25 @@
gap: $spacing-lg;
}
+.pageHeader {
+ display: flex;
+ flex-direction: column;
+ gap: $spacing-sm;
+}
+
+.pageTitle {
+ font-size: 28px;
+ font-weight: 700;
+ color: var(--text-primary);
+ margin: 0;
+}
+
+.description {
+ font-size: 14px;
+ color: var(--text-secondary);
+ margin: 0;
+}
+
.headerActions {
display: flex;
gap: $spacing-sm;
@@ -472,4 +491,3 @@
border: 1px solid var(--danger-color);
flex-shrink: 0;
}
-
diff --git a/src/pages/AuthFilesPage.tsx b/src/pages/AuthFilesPage.tsx
index a135a5e..c1f7252 100644
--- a/src/pages/AuthFilesPage.tsx
+++ b/src/pages/AuthFilesPage.tsx
@@ -150,11 +150,13 @@ export function AuthFilesPage() {
// OAuth 排除模型相关
const [excluded, setExcluded] = useState>({});
+ const [excludedError, setExcludedError] = useState<'unsupported' | null>(null);
const [excludedModalOpen, setExcludedModalOpen] = useState(false);
const [excludedForm, setExcludedForm] = useState({ provider: '', modelsText: '' });
const [savingExcluded, setSavingExcluded] = useState(false);
const fileInputRef = useRef(null);
+ const excludedUnsupportedRef = useRef(false);
const disableControls = connectionStatus !== 'connected';
@@ -199,11 +201,27 @@ export function AuthFilesPage() {
const loadExcluded = useCallback(async () => {
try {
const res = await authFilesApi.getOauthExcludedModels();
+ excludedUnsupportedRef.current = false;
setExcluded(res || {});
- } catch {
+ setExcludedError(null);
+ } catch (err: unknown) {
+ const status =
+ typeof err === 'object' && err !== null && 'status' in err
+ ? (err as { status?: unknown }).status
+ : undefined;
+
+ if (status === 404) {
+ setExcluded({});
+ setExcludedError('unsupported');
+ if (!excludedUnsupportedRef.current) {
+ excludedUnsupportedRef.current = true;
+ showNotification(t('oauth_excluded.upgrade_required'), 'warning');
+ }
+ return;
+ }
// 静默失败
}
- }, []);
+ }, [showNotification, t]);
useEffect(() => {
loadFiles();
@@ -651,8 +669,13 @@ export function AuthFilesPage() {
return (
+
+
{t('auth_files.title')}
+
{t('auth_files.description')}
+
+