From 146b42fb68eaddf9b63dcb0cdbbcf0e6efde0936 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 14 Nov 2025 08:32:30 +0800 Subject: [PATCH] feat(gemini): add config.json editor and common config functionality Implements dual-editor pattern for Gemini providers, following the Codex architecture: - Environment variables (.env format) editor - Extended configuration (config.json) editor with common config support New Components: - GeminiConfigSections: Separate sections for env and config editing - GeminiCommonConfigModal: Modal for editing common config snippets New Hooks: - useGeminiConfigState: Manages env/config separation and conversion - Converts between .env string format and JSON object - Validates JSON config structure - Extracts API Key and Base URL from env - useGeminiCommonConfig: Handles common config snippets - Deep merge algorithm for combining configs - Remove common config logic for toggling off - localStorage persistence for snippets Features: - Format buttons for both env and config editors - Common config toggle with deep merge/remove - Error validation and display - Auto-open modal on common config errors Configuration Structure: { "env": { "GOOGLE_GEMINI_BASE_URL": "https://...", "GEMINI_API_KEY": "sk-...", "GEMINI_MODEL": "gemini-2.5-pro" }, "config": { "timeout": 30000, "maxRetries": 3 } } This brings Gemini providers to feature parity with Claude and Codex. --- .../forms/GeminiCommonConfigModal.tsx | 122 +++++++ .../providers/forms/GeminiConfigEditor.tsx | 193 ++++------- .../providers/forms/GeminiConfigSections.tsx | 237 ++++++++++++++ src/components/providers/forms/hooks/index.ts | 2 + .../forms/hooks/useCommonConfigSnippet.ts | 9 +- .../forms/hooks/useGeminiCommonConfig.ts | 299 ++++++++++++++++++ .../forms/hooks/useGeminiConfigState.ts | 217 +++++++++++++ 7 files changed, 948 insertions(+), 131 deletions(-) create mode 100644 src/components/providers/forms/GeminiCommonConfigModal.tsx create mode 100644 src/components/providers/forms/GeminiConfigSections.tsx create mode 100644 src/components/providers/forms/hooks/useGeminiCommonConfig.ts create mode 100644 src/components/providers/forms/hooks/useGeminiConfigState.ts diff --git a/src/components/providers/forms/GeminiCommonConfigModal.tsx b/src/components/providers/forms/GeminiCommonConfigModal.tsx new file mode 100644 index 0000000..76696b7 --- /dev/null +++ b/src/components/providers/forms/GeminiCommonConfigModal.tsx @@ -0,0 +1,122 @@ +import React from "react"; +import { Save, Wand2 } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import { toast } from "sonner"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { formatJSON } from "@/utils/formatters"; + +interface GeminiCommonConfigModalProps { + isOpen: boolean; + onClose: () => void; + value: string; + onChange: (value: string) => void; + error?: string; +} + +/** + * GeminiCommonConfigModal - Common Gemini configuration editor modal + * Allows editing of common JSON configuration shared across Gemini providers + */ +export const GeminiCommonConfigModal: React.FC< + GeminiCommonConfigModalProps +> = ({ isOpen, onClose, value, onChange, error }) => { + const { t } = useTranslation(); + + const handleFormat = () => { + if (!value.trim()) return; + + try { + const formatted = formatJSON(value); + onChange(formatted); + toast.success(t("common.formatSuccess", { defaultValue: "格式化成功" })); + } catch (error) { + const errorMessage = + error instanceof Error ? error.message : String(error); + toast.error( + t("common.formatError", { + defaultValue: "格式化失败:{{error}}", + error: errorMessage, + }), + ); + } + }; + + return ( + !open && onClose()}> + + + + {t("geminiConfig.editCommonConfigTitle", { + defaultValue: "编辑 Gemini 通用配置片段", + })} + + + +
+

+ {t("geminiConfig.commonConfigHint", { + defaultValue: + "通用配置片段将合并到所有启用它的 Gemini 供应商配置中", + })} +

+ +