diff --git a/src-tauri/src/services/provider/gemini_auth.rs b/src-tauri/src/services/provider/gemini_auth.rs index 3f0106abb..245fe438f 100644 --- a/src-tauri/src/services/provider/gemini_auth.rs +++ b/src-tauri/src/services/provider/gemini_auth.rs @@ -4,7 +4,6 @@ use crate::error::AppError; use crate::provider::Provider; -use crate::settings; /// Gemini authentication type enumeration /// @@ -19,10 +18,6 @@ pub(crate) enum GeminiAuthType { Generic, } -// Authentication type constants -const PACKYCODE_SECURITY_SELECTED_TYPE: &str = "gemini-api-key"; -const GOOGLE_OAUTH_SECURITY_SELECTED_TYPE: &str = "oauth-personal"; - // Partner Promotion Key constants const PACKYCODE_PARTNER_KEY: &str = "packycode"; const GOOGLE_OFFICIAL_PARTNER_KEY: &str = "google-official"; @@ -194,59 +189,13 @@ pub(crate) fn is_google_official_gemini(provider: &Provider) -> bool { name_lower == "google" || name_lower.starts_with("google ") } -/// Ensure PackyCode Gemini provider security flag is correctly set -/// -/// PackyCode is an official partner using API Key authentication mode. -/// -/// # Why write to two settings.json files -/// -/// 1. **`~/.cc-switch/settings.json`** (application-level config): -/// - CC-Switch application global settings -/// - Ensures app knows current authentication type -/// - Used for UI display and other app logic -/// -/// 2. **`~/.gemini/settings.json`** (Gemini client config): -/// - Configuration file read by Gemini CLI client -/// - Directly affects Gemini client authentication behavior -/// - Ensures Gemini uses correct authentication method to connect API -/// -/// # Value set -/// -/// ```json -/// { -/// "security": { -/// "auth": { -/// "selectedType": "gemini-api-key" -/// } -/// } -/// } -/// ``` -/// -/// # Error handling -/// -/// If provider is not PackyCode, function returns `Ok(())` immediately without any operation. -pub(crate) fn ensure_packycode_security_flag(provider: &Provider) -> Result<(), AppError> { - if !is_packycode_gemini(provider) { - return Ok(()); - } - - // Write to application-level settings.json (~/.cc-switch/settings.json) - settings::ensure_security_auth_selected_type(PACKYCODE_SECURITY_SELECTED_TYPE)?; - - // Write to Gemini directory settings.json (~/.gemini/settings.json) - use crate::gemini_config::write_packycode_settings; - write_packycode_settings()?; - - Ok(()) -} - /// Ensure Google Official Gemini provider security flag is correctly set (OAuth mode) /// /// Google Official Gemini uses OAuth personal authentication, no API Key needed. /// -/// # Why write to two settings.json files +/// # What it does /// -/// Same as `ensure_packycode_security_flag`, need to configure both app-level and client-level settings. +/// Writes to **`~/.gemini/settings.json`** (Gemini client config). /// /// # Value set /// @@ -276,9 +225,6 @@ pub(crate) fn ensure_google_oauth_security_flag(provider: &Provider) -> Result<( return Ok(()); } - // Write to application-level settings.json (~/.cc-switch/settings.json) - settings::ensure_security_auth_selected_type(GOOGLE_OAUTH_SECURITY_SELECTED_TYPE)?; - // Write to Gemini directory settings.json (~/.gemini/settings.json) use crate::gemini_config::write_google_oauth_settings; write_google_oauth_settings()?; diff --git a/src-tauri/src/services/provider/live.rs b/src-tauri/src/services/provider/live.rs index a6a4b3367..691b98349 100644 --- a/src-tauri/src/services/provider/live.rs +++ b/src-tauri/src/services/provider/live.rs @@ -15,8 +15,7 @@ use crate::services::mcp::McpService; use crate::store::AppState; use super::gemini_auth::{ - detect_gemini_auth_type, ensure_google_oauth_security_flag, ensure_packycode_security_flag, - GeminiAuthType, + detect_gemini_auth_type, ensure_google_oauth_security_flag, GeminiAuthType, }; use super::normalize_claude_models_in_value; @@ -375,10 +374,14 @@ pub(crate) fn write_gemini_live(provider: &Provider) -> Result<(), AppError> { write_json_file(&settings_path, &config_value)?; } + // Set security.auth.selectedType based on auth type + // - Google Official: OAuth mode + // - All others: API Key mode match auth_type { GeminiAuthType::GoogleOfficial => ensure_google_oauth_security_flag(provider)?, - GeminiAuthType::Packycode => ensure_packycode_security_flag(provider)?, - GeminiAuthType::Generic => {} + GeminiAuthType::Packycode | GeminiAuthType::Generic => { + crate::gemini_config::write_packycode_settings()?; + } } Ok(()) diff --git a/src-tauri/src/services/provider/mod.rs b/src-tauri/src/services/provider/mod.rs index c3a1494db..8b0cd7fb1 100644 --- a/src-tauri/src/services/provider/mod.rs +++ b/src-tauri/src/services/provider/mod.rs @@ -28,10 +28,7 @@ pub use live::{import_default_config, read_live_settings, sync_current_from_db}; pub(crate) use live::write_live_snapshot; // Internal re-exports -use gemini_auth::{ - detect_gemini_auth_type, ensure_google_oauth_security_flag, ensure_packycode_security_flag, - GeminiAuthType, -}; +use gemini_auth::{detect_gemini_auth_type, ensure_google_oauth_security_flag, GeminiAuthType}; use live::write_gemini_live; use usage::validate_usage_script; @@ -202,13 +199,17 @@ impl ProviderService { // Sync to live write_live_snapshot(&app_type, provider)?; - // Gemini needs additional security flag handling (PackyCode or Google OAuth) + // Gemini needs additional security flag handling + // - Google Official: uses OAuth authentication + // - All others (PackyCode, Generic): use API Key authentication if matches!(app_type, AppType::Gemini) { let auth_type = detect_gemini_auth_type(provider); match auth_type { GeminiAuthType::GoogleOfficial => ensure_google_oauth_security_flag(provider)?, - GeminiAuthType::Packycode => ensure_packycode_security_flag(provider)?, - GeminiAuthType::Generic => {} + GeminiAuthType::Packycode | GeminiAuthType::Generic => { + // All non-Google providers use API Key mode + crate::gemini_config::write_packycode_settings()?; + } } } diff --git a/src-tauri/src/settings.rs b/src-tauri/src/settings.rs index 99d044e46..fa394a593 100644 --- a/src-tauri/src/settings.rs +++ b/src-tauri/src/settings.rs @@ -17,20 +17,6 @@ pub struct CustomEndpoint { pub last_used: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct SecurityAuthSettings { - #[serde(default, skip_serializing_if = "Option::is_none")] - pub selected_type: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct SecuritySettings { - #[serde(default, skip_serializing_if = "Option::is_none")] - pub auth: Option, -} - /// 应用设置结构,允许覆盖默认配置目录 #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -53,8 +39,6 @@ pub struct AppSettings { /// 是否开机自启 #[serde(default)] pub launch_on_startup: bool, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub security: Option, /// Claude 自定义端点列表 #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub custom_endpoints_claude: HashMap, @@ -82,7 +66,6 @@ impl Default for AppSettings { gemini_config_dir: None, language: None, launch_on_startup: false, - security: None, custom_endpoints_claude: HashMap::new(), custom_endpoints_codex: HashMap::new(), } @@ -269,27 +252,6 @@ pub fn reload_settings() -> Result<(), AppError> { Ok(()) } -pub fn ensure_security_auth_selected_type(selected_type: &str) -> Result<(), AppError> { - let mut settings = get_settings(); - let current = settings - .security - .as_ref() - .and_then(|sec| sec.auth.as_ref()) - .and_then(|auth| auth.selected_type.as_deref()); - - if current == Some(selected_type) { - return Ok(()); - } - - let mut security = settings.security.unwrap_or_default(); - let mut auth = security.auth.unwrap_or_default(); - auth.selected_type = Some(selected_type.to_string()); - security.auth = Some(auth); - settings.security = Some(security); - - update_settings(settings) -} - pub fn get_claude_override_dir() -> Option { let settings = settings_store().read().ok()?; settings