feat(ai-providers): add Gemini proxy URL support in provider edit UI

This commit is contained in:
Supra4E8C
2026-02-13 20:38:54 +08:00
parent ef448806aa
commit 06201a9fc4
8 changed files with 25 additions and 0 deletions

View File

@@ -125,6 +125,12 @@ export function GeminiSection({
<span className={styles.fieldValue}>{item.baseUrl}</span>
</div>
)}
{item.proxyUrl && (
<div className={styles.fieldRow}>
<span className={styles.fieldLabel}>{t('common.proxy_url')}:</span>
<span className={styles.fieldValue}>{item.proxyUrl}</span>
</div>
)}
{headerEntries.length > 0 && (
<div className={styles.headerBadgeList}>
{headerEntries.map(([key, value]) => (

View File

@@ -194,6 +194,8 @@
"gemini_keys_add_btn": "Add Key",
"gemini_base_url_label": "Base URL (Optional):",
"gemini_base_url_placeholder": "e.g.: https://generativelanguage.googleapis.com",
"gemini_add_modal_proxy_label": "Proxy URL (Optional):",
"gemini_add_modal_proxy_placeholder": "e.g.: socks5://proxy.example.com:1080",
"gemini_edit_modal_title": "Edit Gemini API Key",
"gemini_edit_modal_key_label": "API Key:",
"gemini_delete_confirm": "Are you sure you want to delete this Gemini key?",

View File

@@ -194,6 +194,8 @@
"gemini_keys_add_btn": "Добавить ключ",
"gemini_base_url_label": "Базовый URL (необязательно):",
"gemini_base_url_placeholder": "например: https://generativelanguage.googleapis.com",
"gemini_add_modal_proxy_label": "URL прокси (необязательно):",
"gemini_add_modal_proxy_placeholder": "например: socks5://proxy.example.com:1080",
"gemini_edit_modal_title": "Редактирование API-ключа Gemini",
"gemini_edit_modal_key_label": "API-ключ:",
"gemini_delete_confirm": "Удалить этот ключ Gemini?",

View File

@@ -194,6 +194,8 @@
"gemini_keys_add_btn": "添加密钥",
"gemini_base_url_label": "Base URL (可选)",
"gemini_base_url_placeholder": "例如: https://generativelanguage.googleapis.com",
"gemini_add_modal_proxy_label": "代理 URL (可选):",
"gemini_add_modal_proxy_placeholder": "例如: socks5://proxy.example.com:1080",
"gemini_edit_modal_title": "编辑Gemini API密钥",
"gemini_edit_modal_key_label": "API密钥:",
"gemini_delete_confirm": "确定要删除这个Gemini密钥吗",

View File

@@ -21,6 +21,7 @@ const buildEmptyForm = (): GeminiFormState => ({
apiKey: '',
prefix: '',
baseUrl: '',
proxyUrl: '',
headers: [],
excludedModels: [],
excludedText: '',
@@ -138,6 +139,7 @@ export function AiProvidersGeminiEditPage() {
apiKey: form.apiKey.trim(),
prefix: form.prefix?.trim() || undefined,
baseUrl: form.baseUrl?.trim() || undefined,
proxyUrl: form.proxyUrl?.trim() || undefined,
headers: buildHeaderObject(form.headers),
excludedModels: parseExcludedModels(form.excludedText),
};
@@ -218,6 +220,13 @@ export function AiProvidersGeminiEditPage() {
onChange={(e) => setForm((prev) => ({ ...prev, baseUrl: e.target.value }))}
disabled={disableControls || saving}
/>
<Input
label={t('ai_providers.gemini_add_modal_proxy_label')}
placeholder={t('ai_providers.gemini_add_modal_proxy_placeholder')}
value={form.proxyUrl ?? ''}
onChange={(e) => setForm((prev) => ({ ...prev, proxyUrl: e.target.value }))}
disabled={disableControls || saving}
/>
<HeaderInputList
entries={form.headers}
onChange={(entries) => setForm((prev) => ({ ...prev, headers: entries }))}

View File

@@ -99,6 +99,7 @@ const serializeGeminiKey = (config: GeminiKeyConfig) => {
const payload: Record<string, unknown> = { 'api-key': config.apiKey };
if (config.prefix?.trim()) payload.prefix = config.prefix.trim();
if (config.baseUrl) payload['base-url'] = config.baseUrl;
if (config.proxyUrl) payload['proxy-url'] = config.proxyUrl;
const headers = serializeHeaders(config.headers);
if (headers) payload.headers = headers;
if (config.excludedModels && config.excludedModels.length) {

View File

@@ -153,6 +153,8 @@ const normalizeGeminiKeyConfig = (item: unknown): GeminiKeyConfig | null => {
if (prefix) config.prefix = prefix;
const baseUrl = record ? record['base-url'] ?? record.baseUrl ?? record['base_url'] : undefined;
if (baseUrl) config.baseUrl = String(baseUrl);
const proxyUrl = record ? record['proxy-url'] ?? record.proxyUrl ?? record['proxy_url'] : undefined;
if (proxyUrl) config.proxyUrl = String(proxyUrl);
const headers = normalizeHeaders(record?.headers);
if (headers) config.headers = headers;
const excludedModels = normalizeExcludedModels(record?.['excluded-models'] ?? record?.excludedModels);

View File

@@ -20,6 +20,7 @@ export interface GeminiKeyConfig {
apiKey: string;
prefix?: string;
baseUrl?: string;
proxyUrl?: string;
headers?: Record<string, string>;
excludedModels?: string[];
}