Commit Graph

207 Commits

  • test: simplify boolean assertions in import_export_sync tests
    Replace verbose assert_eq!(value, true) with idiomatic assert!(value) for improved readability and adherence to Rust best practices
  • style: apply code formatting across backend and frontend (#252)
    Apply cargo fmt and prettier formatting to improve code readability.
    No functional changes.
    
    Changes:
    - Rust: multi-line assertion formatting (gemini_config, env_checker)
    - Rust: simplify chained method calls (provider)
    - TypeScript: add trailing commas to function parameters (codexProviderPresets)
  • chore(release): bump version to v3.7.0 and rebrand to include Gemini CLI
    - Update version from 3.6.2 to 3.7.0 across all config files
    - Update project description to "All-in-One Assistant for Claude Code, Codex & Gemini CLI"
    - Update Chinese description to "Claude Code / Codex / Gemini CLI 全方位辅助工具"
    - Sync version in package.json, Cargo.toml, tauri.conf.json
    - Update branding in README.md, README_ZH.md and i18n locale files
  • feat: update Gemini default model and remove Google Official preset model
    Updated default model from gemini-2.5-pro to gemini-3-pro-preview across:
    - Provider presets (PackyCode, Custom)
    - Form field placeholders
    - Default configurations
    - Test cases
    
    Google Official preset now has empty env config, allowing users to choose
    their own model or use application defaults, which is more appropriate for
    OAuth-based authentication.
    
    Changes:
    - geminiProviderPresets.ts: updated model to gemini-3-pro-preview, removed model from Google Official
    - GeminiFormFields.tsx: updated placeholder to gemini-3-pro-preview
    - GeminiConfigSections.tsx: updated placeholder to gemini-3-pro-preview
    - ProviderForm.tsx: updated default config to gemini-3-pro-preview
    - gemini_config.rs: updated test examples to gemini-3-pro-preview
  • fix: read both .env and settings.json for Gemini live config
    Previously, when editing a Gemini provider, only the .env file was read,
    missing the settings.json file that contains MCP configuration and other
    settings. This caused the config field in the edit form to be empty or
    show outdated data.
    
    This fix ensures both files are read and merged into the complete
    structure { "env": {...}, "config": {...} }, matching the behavior
    of Codex provider.
    
    Fixed in:
    - read_live_settings(): now reads both .env and settings.json
    - import_default_config(): now reads both files when importing
  • fix: resolve winreg API compatibility issue on Windows
    - Update RegValue.to_string() usage to match current winreg API
      which returns String directly instead of Result
    - Add conditional compilation for std::fs import (Unix only)
  • feat: add model configuration support and fix Gemini deeplink bug (#251)
    * feat(providers): add notes field for provider management
    
    - Add notes field to Provider model (backend and frontend)
    - Display notes with higher priority than URL in provider card
    - Style notes as non-clickable text to differentiate from URLs
    - Add notes input field in provider form
    - Add i18n support (zh/en) for notes field
    
    * chore: format code and clean up unused props
    
    - Run cargo fmt on Rust backend code
    - Format TypeScript imports and code style
    - Remove unused appId prop from ProviderPresetSelector
    - Clean up unused variables in tests
    - Integrate notes field handling in provider dialogs
    
    * feat(deeplink): implement ccswitch:// protocol for provider import
    
    Add deep link support to enable one-click provider configuration import via ccswitch:// URLs.
    
    Backend:
    - Implement URL parsing and validation (src-tauri/src/deeplink.rs)
    - Add Tauri commands for parse and import (src-tauri/src/commands/deeplink.rs)
    - Register ccswitch:// protocol in macOS Info.plist
    - Add comprehensive unit tests (src-tauri/tests/deeplink_import.rs)
    
    Frontend:
    - Create confirmation dialog with security review UI (src/components/DeepLinkImportDialog.tsx)
    - Add API wrapper (src/lib/api/deeplink.ts)
    - Integrate event listeners in App.tsx
    
    Configuration:
    - Update Tauri config for deep link handling
    - Add i18n support for Chinese and English
    - Include test page for deep link validation (deeplink-test.html)
    
    Files: 15 changed, 1312 insertions(+)
    
    * chore(deeplink): integrate deep link handling into app lifecycle
    
    Wire up deep link infrastructure with app initialization and event handling.
    
    Backend Integration:
    - Register deep link module and commands in mod.rs
    - Add URL handling in app setup (src-tauri/src/lib.rs:handle_deeplink_url)
    - Handle deep links from single instance callback (Windows/Linux CLI)
    - Handle deep links from macOS system events
    - Add tauri-plugin-deep-link dependency (Cargo.toml)
    
    Frontend Integration:
    - Listen for deeplink-import/deeplink-error events in App.tsx
    - Update DeepLinkImportDialog component imports
    
    Configuration:
    - Enable deep link plugin in tauri.conf.json
    - Update Cargo.lock for new dependencies
    
    Localization:
    - Add Chinese translations for deep link UI (zh.json)
    - Add English translations for deep link UI (en.json)
    
    Files: 9 changed, 359 insertions(+), 18 deletions(-)
    
    * refactor(deeplink): enhance Codex provider template generation
    
    Align deep link import with UI preset generation logic by:
    - Adding complete config.toml template matching frontend defaults
    - Generating safe provider name from sanitized input
    - Including model_provider, reasoning_effort, and wire_api settings
    - Removing minimal template that only contained base_url
    - Cleaning up deprecated test file deeplink-test.html
    
    * style: fix clippy uninlined_format_args warnings
    
    Apply clippy --fix to use inline format arguments in:
    - src/mcp.rs (8 fixes)
    - src/services/env_manager.rs (10 fixes)
    
    * style: apply code formatting and cleanup
    
    - Format TypeScript files with Prettier (App.tsx, EnvWarningBanner.tsx, formatters.ts)
    - Organize Rust imports and module order alphabetically
    - Add newline at end of JSON files (en.json, zh.json)
    - Update Cargo.lock for dependency changes
    
    * feat: add model name configuration support for Codex and fix Gemini model handling
    
    - Add visual model name input field for Codex providers
      - Add model name extraction and update utilities in providerConfigUtils
      - Implement model name state management in useCodexConfigState hook
      - Add conditional model field rendering in CodexFormFields (non-official only)
      - Integrate model name sync with TOML config in ProviderForm
    
    - Fix Gemini deeplink model injection bug
      - Correct environment variable name from GOOGLE_GEMINI_MODEL to GEMINI_MODEL
      - Add test cases for Gemini model injection (with/without model)
      - All tests passing (9/9)
    
    - Fix Gemini model field binding in edit mode
      - Add geminiModel state to useGeminiConfigState hook
      - Extract model value during initialization and reset
      - Sync model field with geminiEnv state to prevent data loss on submit
      - Fix missing model value display when editing Gemini providers
    
    Changes:
      - 6 files changed, 245 insertions(+), 13 deletions(-)
  • Add Gemini environment variable detection (#250)
    * feat(env): add environment variable conflict detection and management
    
    实现了系统环境变量冲突检测与管理功能:
    
    核心功能:
    - 自动检测会影响 Claude/Codex 的系统环境变量
    - 支持 Windows 注册表和 Unix shell 配置文件检测
    - 提供可视化的环境变量冲突警告横幅
    - 支持批量选择和删除环境变量
    - 删除前自动备份,支持后续恢复
    
    技术实现:
    - Rust 后端: 跨平台环境变量检测与管理
    - React 前端: EnvWarningBanner 组件交互界面
    - 国际化支持: 中英文界面
    - 类型安全: 完整的 TypeScript 类型定义
    
    * refactor(env): remove unused imports and function
    
    Remove unused HashMap and PathBuf imports, and delete the unused get_source_description function to clean up the code.
    
    * feat: Add Gemini environment variable detection
  • 添加Claude和Codex环境变量检查 (#242)
    * feat(env): add environment variable conflict detection and management
    
    实现了系统环境变量冲突检测与管理功能:
    
    核心功能:
    - 自动检测会影响 Claude/Codex 的系统环境变量
    - 支持 Windows 注册表和 Unix shell 配置文件检测
    - 提供可视化的环境变量冲突警告横幅
    - 支持批量选择和删除环境变量
    - 删除前自动备份,支持后续恢复
    
    技术实现:
    - Rust 后端: 跨平台环境变量检测与管理
    - React 前端: EnvWarningBanner 组件交互界面
    - 国际化支持: 中英文界面
    - 类型安全: 完整的 TypeScript 类型定义
    
    * refactor(env): remove unused imports and function
    
    Remove unused HashMap and PathBuf imports, and delete the unused get_source_description function to clean up the code.
  • Feat/claude skills management (#237)
    * feat(skills): add Claude Skills management feature
    
    Implement complete Skills management system with repository discovery,
    installation, and lifecycle management capabilities.
    
    Backend:
    - Add SkillService with GitHub integration and installation logic
    - Implement skill commands (list, install, uninstall, check updates)
    - Support multiple skill repositories with caching
    
    Frontend:
    - Add Skills management page with repository browser
    - Create SkillCard and RepoManager components
    - Add badge, card, table UI components
    - Integrate Skills API with Tauri commands
    
    Files: 10 files changed, 1488 insertions(+)
    
    * feat(skills): integrate Skills feature into application
    
    Integrate Skills management feature with complete dependency updates,
    configuration structure extensions, and internationalization support.
    
    Dependencies:
    - Add @radix-ui/react-visually-hidden for accessibility
    - Add anyhow, zip, serde_yaml, tempfile for Skills backend
    - Enable chrono serde feature for timestamp serialization
    
    Backend Integration:
    - Extend MultiAppConfig with SkillStore field
    - Implement skills.json migration from legacy location
    - Register SkillService and skill commands in main app
    - Export skill module in commands and services
    
    Frontend Integration:
    - Add Skills page route and dialog in App
    - Integrate Skills UI with main navigation
    
    Internationalization:
    - Add complete Chinese translations for Skills UI
    - Add complete English translations for Skills UI
    
    Code Quality:
    - Remove redundant blank lines in gemini_mcp.rs
    - Format log statements in mcp.rs
    
    Tests:
    - Update import_export_sync tests for SkillStore
    - Update mcp_commands tests for new structure
    
    Files: 16 files changed, 540 insertions(+), 39 deletions(-)
    
    * style(skills): improve SkillsPage typography and spacing
    
    Optimize visual hierarchy and readability of Skills page:
    - Reduce title size from 2xl to lg with tighter tracking
    - Improve description spacing and color contrast
    - Enhance empty state with better text hierarchy
    - Use explicit gray colors for better dark mode support
    
    * feat(skills): support custom subdirectory path for skill scanning
    
    Add optional skillsPath field to SkillRepo to enable scanning skills
    from subdirectories (e.g., "skills/") instead of repository root.
    
    Changes:
    - Backend: Add skillsPath field with subdirectory scanning logic
    - Frontend: Add skillsPath input field and display in repo list
    - Presets: Add cexll/myclaude repo with skills/ subdirectory
    - Code quality: Fix clippy warnings (dedup logic, string formatting)
    
    Backward compatible: skillsPath is optional, defaults to root scanning.
    
    * refactor(skills): improve repo manager dialog layout
    
    Optimize dialog structure with fixed header and scrollable content:
    - Add flexbox layout with fixed header and scrollable body
    - Remove outer border wrapper for cleaner appearance
    - Match SkillsPage design pattern for consistency
    - Improve UX with better content hierarchy
  • feat(window): center window on screen by default
    Add `center: true` to main window configuration to improve initial
    window positioning on Windows and other platforms. This addresses
    user feedback about the window appearing in the top-left corner.
  • fix(provider): sync MCP config for all apps on provider switch
    Previously, only Codex provider switches triggered MCP synchronization,
    which could cause MCP configuration loss when switching Claude or Gemini
    providers.
    
    Changes:
    - Enable MCP sync for all app types (Claude, Codex, Gemini) during provider switch
    - Migrate to v3.7.0 unified MCP sync mechanism using McpService::sync_all_enabled()
    - Replace app-specific sync_enabled_to_codex() with unified sync for all apps
    - Remove unused mcp module import
    
    This ensures MCP servers remain properly configured across all applications
    after provider switches, preventing configuration loss.
  • fix(mcp): correct Codex MCP configuration format to [mcp_servers]
    BREAKING CHANGE: The [mcp.servers] format was completely incorrect and not
    any official Codex format. The only correct format is [mcp_servers] at the
    top level of config.toml.
    
    Changes:
    - Remove incorrect [mcp.servers] nested table support
    - Always use [mcp_servers] top-level table (official Codex format)
    - Auto-migrate and cleanup erroneous [mcp.servers] entries on write
    - Preserve error-tolerant import for migrating old incorrect configs
    - Simplify sync logic by removing format selection branches (~60 lines)
    - Update all documentation and tests to reflect correct format
    - Add warning logs when detecting and cleaning incorrect format
    
    Backend (Rust):
    - mcp.rs: Simplify sync_enabled_to_codex by removing Target enum
    - mcp.rs: sync_single_server_to_codex now always uses [mcp_servers]
    - mcp.rs: remove_server_from_codex cleans both locations
    - mcp.rs: Update import_from_codex comments to clarify format status
    - tests: Rename test to sync_enabled_to_codex_migrates_erroneous_*
    - tests: Update assertions to verify migration behavior
    
    Frontend (TypeScript):
    - tomlUtils.ts: Prioritize [mcp_servers] format in parsing
    - tomlUtils.ts: Update error messages to guide correct format
    
    Documentation:
    - README.md: Correct MCP format reference to [mcp_servers]
    - CLAUDE.md: Add comprehensive format specification with examples
    
    All 79 tests pass. This ensures backward compatibility while enforcing
    the correct Codex official standard going forward.
    
    Refs: https://github.com/openai/codex/issues/3441
  • feat(mcp): support extended fields for Codex TOML conversion
    ## Problem
    Previously, the Codex MCP configuration used a whitelist-only approach
    for TOML conversion, which caused custom fields (like `timeout`,
    `startup_timeout_ms`, etc.) to be silently dropped during JSON → TOML
    conversion. Only Claude and Gemini (JSON format) could preserve
    arbitrary fields.
    
    ## Solution
    Implemented a three-tier field handling strategy:
    
    1. **Core fields** (type, command, args, url, headers, env, cwd)
       - Strong-typed manual processing (existing behavior preserved)
    
    2. **Extended fields** (19 common optional fields)
       - White-listed fields with automatic type conversion:
         - General: timeout, timeout_ms, startup_timeout_ms/sec,
           connection_timeout, read_timeout, debug, log_level, disabled
         - stdio: shell, encoding, working_dir, restart_on_exit,
           max_restart_count
         - http/sse: retry_count, max_retry_attempts, retry_delay,
           cache_tools_list, verify_ssl, insecure, proxy
    
    3. **Custom fields** (generic converter)
       - Automatic type inference for:
         - String → TOML String
         - Number (i64/f64) → TOML Integer/Float
         - Boolean → TOML Boolean
         - Simple arrays → TOML Array
         - Shallow objects (string values only) → TOML Inline Table
       - Unsupported types (null, mixed arrays, nested objects) are
         gracefully skipped with debug logging
    
    ## Changes
    
    ### Core Implementation
    - **json_value_to_toml_item()** (mcp.rs:843-947)
      Generic JSON → TOML value converter with smart type inference
    
    - **json_server_to_toml_table()** (mcp.rs:949-1072)
      Refactored to use three-tier strategy, processes all fields beyond
      core whitelist
    
    - **build_servers_table()** (mcp.rs:616-633)
      Now reuses the generic converter for consistency
    
    - **import_from_codex()** (mcp.rs:432-605)
      Extended with generic TOML → JSON converter for bidirectional
      field preservation
    
    ### Logging
    - DEBUG: Extended field conversions
    - INFO: Custom field conversions
    - WARN: Skipped unsupported types (with reason)
    
    ## Testing
    -  All 24 integration tests pass
    -  Compilation clean (zero errors)
    -  Backward compatible with existing configs
    
    ## Design Decision: No Auto Field Mapping
    Explicitly NOT implementing automatic field mapping (e.g., Claude's
    `timeout` → Codex's `startup_timeout_ms`) due to:
    - Unit ambiguity (seconds vs milliseconds)
    - Semantic ambiguity (same field name, different meanings)
    - Risk of data corruption (30s → 30ms causes immediate timeout)
    - Breaks user expectation of "what you see is what you get"
    
    Recommendation: Use application-specific field names as documented.
    
    ## Example
    User adds `timeout: 30` in MCP panel:
    
    **Claude/Gemini** (~/.claude.json):
    ```json
    {"mcpServers": {"srv": {"timeout": 30}}}
    ```
    
    **Codex** (~/.codex/config.toml):
    ```toml
    [mcp.servers.srv]
    timeout = 30  #  Now preserved!
    ```
    
    Fixes the whitelist limitation reported in user feedback.
  • feat(mcp): add SSE (Server-Sent Events) transport type support
    Add comprehensive support for SSE transport type to MCP server configuration,
    enabling real-time streaming connections alongside existing stdio and http types.
    
    Backend Changes:
    - Add SSE type validation in mcp.rs validate_server_spec()
    - Extend Codex TOML import/export to handle SSE servers
    - Update claude_mcp.rs legacy API for backward compatibility
    - Unify http/sse handling in json_server_to_toml_table()
    
    Frontend Changes:
    - Extend McpServerSpec type definition to include "sse"
    - Add SSE radio button to configuration wizard UI
    - Update wizard form logic to handle SSE url and headers
    - Add SSE validation in McpFormModal submission
    
    Validation & Error Handling:
    - Add SSE support in useMcpValidation hook (TOML/JSON)
    - Extend tomlUtils normalizeServerConfig for SSE parsing
    - Update Zod schemas (common.ts, mcp.ts) with SSE enum
    - Add SSE error message mapping in errorUtils
    
    Internationalization:
    - Add "typeSse" translations (zh: "sse", en: "sse")
    
    Tests:
    - Add SSE validation test cases in useMcpValidation.test.tsx
    
    SSE Configuration Format:
    {
      "type": "sse",
      "url": "https://api.example.com/sse",
      "headers": { "Authorization": "Bearer token" }
    }
  • style(ui): migrate color scheme to macOS native design system
    - Update primary blue from Linear style (#3498db) to macOS system blue (#0A84FF)
    - Align gray scale with macOS dark mode palette (#1C1C1E, #2C2C2E, etc.)
    - Adjust dark mode background to match macOS systemBackground (HSL 240 5% 12%)
    - Refine scrollbar colors to use native macOS gray tones
    - Remove transparent titleBarStyle for better stability
  • feat(config): unify common config snippets persistence across all apps
    - Add unified `common_config_snippets` structure to MultiAppConfig
    - Implement `get_common_config_snippet` and `set_common_config_snippet` commands
    - Replace localStorage with config.json persistence for Codex and Gemini
    - Auto-migrate legacy `claude_common_config_snippet` to new unified structure
    - Deprecate individual API methods in favor of unified interface
    - Add automatic migration from localStorage on first load
    
    BREAKING CHANGE: Common config snippets now stored in unified `common_config_snippets` object instead of separate fields
  • refactor(prompt): optimize auto-import logic with unified save
    - Change auto_import_prompt_if_exists return type to Result<bool>
    - Remove redundant save() calls by introducing updated flag
    - Eliminate unnecessary clone() in app type iterations
    - Remove semantic contradiction in let _ = ...? pattern
    - Improve code semantics and maintainability
    
    Performance: Reduce disk I/O by 50%+ through unified save logic
  • fix(prompt): correct live file backfill priority in enable flow (#225)
    Fix backfill logic in prompt enable workflow:
    - Prioritize backfilling live file content to currently enabled prompt (prevent data loss)
    - Create backup only when no enabled prompt exists and content is new (avoid duplicate backups)
    - Implement staged persistence (save after backfill + save after enable)
    - Add explicit logging for backfill/backup operations
    
    Also simplify string formatting in prompt_files.rs with inline format strings.
  • test(mcp): update import tests for v3.7.0 unified structure
    - Fix import_from_claude_merges_into_config: check unified mcp.servers
    - Fix import_from_codex_adds_servers_from_mcp_servers_table: verify apps.codex enabled
    - Fix import_from_codex_merges_into_existing_entries: test smart merge preserves existing config
    - Replace cc_switch_lib::app_config:: with public exports (McpServer, McpApps)
    
    All 24 import_export_sync tests now passing.
  • fix(mcp): migrate import functions to unified v3.7.0 structure
    - Rewrite import_from_claude/codex/gemini to write directly to mcp.servers
    - Implement skip-on-error strategy for fault tolerance (single invalid item no longer aborts entire batch)
    - Smart merge logic: existing servers only enable corresponding app, preserve other configs
    - Remove deprecated markers from service layer
    - Export McpApps type for test usage
    - Update mcp_commands tests to use unified structure
    
    Fixes runtime import issue where data was written to legacy structure (mcp.claude/codex.servers)
    but unified panel reads from new structure (mcp.servers), causing "imported but invisible" bug.
  • fix(mcp): initialize McpRoot with v3.7.0 unified structure by default
    Problem:
    - On first launch, McpRoot::default() created `servers: None`
    - McpService::get_all_servers() would incorrectly return error "old structure detected"
    - This confused new users who had no legacy MCP data
    
    Root Cause:
    - Derived Default trait sets Option<T> fields to None
    - New installations should start with v3.7.0 structure immediately
    
    Solution:
    - Explicitly implement Default for McpRoot
    - Initialize `servers: Some(HashMap::new())` for v3.7.0+ structure
    - Legacy fields (claude/codex/gemini) remain empty, only used for deserializing old configs
    
    Impact:
    - First-time users get correct v3.7.0 structure immediately
    - migrate_mcp_to_unified() correctly detects already-migrated state
    - No false "old structure" errors on fresh installs
  • refactor(mcp): complete v3.7.0 cleanup - remove legacy code and warnings
    This commit finalizes the v3.7.0 unified MCP architecture migration by
    removing all deprecated code paths and eliminating compiler warnings.
    
    Frontend Changes (~950 lines removed):
    - Remove deprecated components: McpPanel, McpListItem, McpToggle
    - Remove deprecated hook: useMcpActions
    - Remove unused API methods: importFrom*, syncEnabledTo*, syncAllServers
    - Simplify McpFormModal by removing dual-mode logic (unified/legacy)
    - Remove syncOtherSide checkbox and conflict detection
    - Clean up unused imports and state variables
    - Delete associated test files
    
    Backend Changes (~400 lines cleaned):
    - Remove unused Tauri commands: import_mcp_from_*, sync_enabled_mcp_to_*
    - Delete unused Gemini MCP functions: get_mcp_status, upsert/delete_mcp_server
    - Add #[allow(deprecated)] to compatibility layer commands
    - Add #[allow(dead_code)] to legacy helper functions for future migration
    - Simplify boolean expression in mcp.rs per Clippy suggestion
    
    API Deprecation:
    - Mark legacy APIs with @deprecated JSDoc (getConfig, upsertServerInConfig, etc.)
    - Preserve backward compatibility for v3.x, planned removal in v4.0
    
    Verification:
    -  Zero TypeScript errors (pnpm typecheck)
    -  Zero Clippy warnings (cargo clippy)
    -  All code formatted (prettier + cargo fmt)
    -  Builds successfully
    
    Total cleanup: ~1,350 lines of code removed/marked
    Breaking changes: None (all legacy APIs still functional)
  • fix(mcp): resolve compilation errors and add backward compatibility
    ## Compilation Fixes
    - Add deprecated compatibility methods to McpService:
      * get_servers() - filters servers by app
      * set_enabled() - delegates to toggle_app()
      * sync_enabled() - syncs enabled servers for specific app
      * import_from_claude/codex/gemini() - wraps mcp:: functions
    - Fix toml_edit type conversion in sync_single_server_to_codex():
      * Add json_server_to_toml_table() helper function
      * Manually construct toml_edit::Table instead of invalid serde conversion
    - Fix get_codex_config_path() calls (returns PathBuf, not Result)
    - Update upsert_mcp_server_in_config() to work with unified structure:
      * Converts old per-app API to unified McpServer structure
      * Preserves existing server data when updating
      * Supports sync_other_side parameter for multi-app enable
    - Update delete_mcp_server_in_config() to ignore app parameter
    
    ## Backward Compatibility
    - All old v3.6.x commands continue to work with deprecation warnings
    - Frontend migration can be done incrementally
    - Old commands transparently use new unified backend
    
    ## Status
     Backend compiles successfully (cargo check passes)
    ⚠️ 16 warnings (8 deprecation + 8 unused functions - expected)
  • feat(mcp): implement unified MCP management for v3.7.0
    BREAKING CHANGE: Migrate from app-specific MCP storage to unified structure
    
    ## Phase 1: Data Structure Migration
    - Add McpApps struct with claude/codex/gemini boolean fields
    - Add McpServer struct for unified server definition
    - Add migration logic in MultiAppConfig::migrate_mcp_to_unified()
    - Integrate automatic migration into MultiAppConfig::load()
    - Support backward compatibility through Optional fields
    
    ## Phase 2: Backend Services Refactor
    - Completely rewrite services/mcp.rs for unified management:
      * get_all_servers() - retrieve all MCP servers
      * upsert_server() - add/update unified server
      * delete_server() - remove server
      * toggle_app() - enable/disable server for specific app
      * sync_all_enabled() - sync to all live configs
    - Add single-server sync functions to mcp.rs:
      * sync_single_server_to_claude/codex/gemini()
      * remove_server_from_claude/codex/gemini()
    - Add read_mcp_servers_map() to claude_mcp.rs and gemini_mcp.rs
    - Add new Tauri commands to commands/mcp.rs:
      * get_mcp_servers, upsert_mcp_server, delete_mcp_server
      * toggle_mcp_app, sync_all_mcp_servers
    - Register new commands in lib.rs
    
    ## Migration Strategy
    - Detects old structure (mcp.claude/codex/gemini.servers)
    - Merges into unified mcp.servers with apps markers
    - Handles conflicts by merging enabled apps
    - Clears old structures after migration
    - Saves migrated config automatically
    
    ## Known Issues
    - Old commands still need compatibility layer (WIP)
    - toml_edit type conversion needs fixing (WIP)
    - Frontend not yet implemented (Phase 3 pending)
    
    Related: v3.6.2 -> v3.7.0
  • feat(gemini): implement full MCP management functionality
    - Add gemini_mcp.rs module for Gemini MCP file I/O operations
    - Implement sync_enabled_to_gemini to export enabled MCPs to ~/.gemini/settings.json
    - Implement import_from_gemini to import MCPs from Gemini config
    - Add Gemini sync logic in services/mcp.rs (upsert_server, delete_server, set_enabled)
    - Register Tauri commands for Gemini MCP sync and import
    - Update frontend API calls and McpPanel to support Gemini
    
    Fixes the issue where adding MCP servers in Gemini tab would not sync to ~/.gemini/settings.json
  • feat: migrate Claude common config snippet from localStorage to config.json
    Migrate the Claude common config snippet storage from browser localStorage
    to the persistent config.json file for better cross-device sync and backup support.
    
    **Backend Changes:**
    - Add `claude_common_config_snippet` field to `MultiAppConfig` struct
    - Add `get_claude_common_config_snippet` and `set_claude_common_config_snippet` Tauri commands
    - Include JSON validation in the setter command
    
    **Frontend Changes:**
    - Create new `lib/api/config.ts` API module
    - Refactor `useCommonConfigSnippet` hook to use config.json instead of localStorage
    - Add automatic one-time migration from localStorage to config.json
    - Add loading state during initialization
    
    **Benefits:**
    - Cross-device synchronization via backup/restore
    - More reliable persistence than browser storage
    - Centralized configuration management
    - Seamless migration for existing users
  • fix(prompt): improve i18n and error handling for auto-import
    Address code review feedback for PR #214:
    
    - Replace hardcoded Chinese strings with English in auto-imported prompts
      - Prompt name: "Auto-imported Prompt" instead of "初始提示词"
      - Description: "Automatically imported on first launch"
    - Remove panic risk by replacing expect() with proper error propagation
    - Use AppError::localized for bilingual error messages
    - Extract get_base_dir_with_fallback() helper to eliminate code duplication
    - Update test assertions to match new English strings
    - Suppress false-positive dead_code warning on TempHome.dir field
    
    All 5 tests passing with zero compiler warnings.
  • refactor(prompt): extract file path logic and implement auto-import on first launch (#214)
    - Extract prompt file path logic to dedicated prompt_files module
    - Refactor PromptService to use centralized path resolution
    - Implement auto-import for existing prompt files on first startup
    - Add comprehensive unit tests for auto-import functionality
  • fix(usage-script): add input validation and boundary checks (#208)
    - Backend: validate auto-query interval ≤ 1440 minutes (24 hours)
    - Frontend: add number input sanitization and blur validation
    - Add user-friendly error messages for invalid inputs
    - Support auto-clamping to valid ranges with toast notifications
  • fix(gemini): relax validation when adding providers (#210)
    Allow users to create Gemini provider configurations without API key
    and fill it in later. Split validation into two modes:
    
    - validate_gemini_settings: Basic structure check (used when adding)
    - validate_gemini_settings_strict: Full validation (used when switching)
    
    This fixes the error 'Gemini config missing required field: GEMINI_API_KEY'
    when trying to add Gemini providers from presets like PackyCode or Google.
    
    Changes:
    - Add validate_gemini_settings_strict for switching validation
    - Update write_gemini_live to use strict validation
    - Add comprehensive tests for both validation modes
  • feat(tray): add Gemini support to system tray menu (#209)
    Refactor tray menu system to support three applications (Claude/Codex/Gemini):
    - Introduce generic TrayAppSection structure and TRAY_SECTIONS array
    - Implement append_provider_section and handle_provider_tray_event helper functions
    - Enhance Gemini provider service with .env config read/write support
    - Implement Gemini LiveSnapshot for atomic operations and rollback
    - Update README documentation to reflect Gemini tray quick switching feature
  • feat(prompts+i18n): add prompt management and improve prompt editor i18n (#193)
    * feat(prompts): add prompt management across Tauri service and React UI
    
    - backend: add commands/prompt.rs, services/prompt.rs, register in commands/mod.rs and lib.rs, refine app_config.rs
    - frontend: add PromptPanel, PromptFormModal, PromptListItem, MarkdownEditor, usePromptActions, integrate in App.tsx
    - api: add src/lib/api/prompts.ts
    - i18n: update src/i18n/locales/{en,zh}.json
    - build: update package.json and pnpm-lock.yaml
    
    * feat(i18n): improve i18n for prompts and Markdown editor
    
    - update src/i18n/locales/{en,zh}.json keys and strings
    - apply i18n in PromptFormModal, PromptPanel, and MarkdownEditor
    - align prompt text with src-tauri/src/services/prompt.rs
    
    * feat(prompts): add enable/disable toggle and simplify panel UI
    
    - Add PromptToggle component and integrate in prompt list items
    - Implement toggleEnabled with optimistic update; enable via API, disable via upsert with enabled=false;
      reload after success
    - Simplify PromptPanel: remove file import and current-file preview to keep CRUD flow focused
    - Tweak header controls style (use mcp variant) and minor copy: rename “Prompt Management” to “Prompts”
    - i18n: add disableSuccess/disableFailed messages
    - Backend (Tauri): prevent duplicate backups when importing original prompt content
    
    * style: unify code formatting with trailing commas
    
    * feat(prompts): add Gemini filename support to PromptFormModal
    
    Update filename mapping to use Record<AppId, string> pattern, supporting
    GEMINI.md alongside CLAUDE.md and AGENTS.md.
    
    * fix(prompts): sync enabled prompt to file when updating
    
    When updating a prompt that is currently enabled, automatically sync
    the updated content to the corresponding live file (CLAUDE.md/AGENTS.md/GEMINI.md).
    
    This ensures the active prompt file always reflects the latest content
    when editing enabled prompts.
  • feat(gemini): add Gemini provider integration (#202)
    * feat(gemini): add Gemini provider integration
    
    - Add gemini_config.rs module for .env file parsing
    - Extend AppType enum to support Gemini
    - Implement GeminiConfigEditor and GeminiFormFields components
    - Add GeminiIcon with standardized 1024x1024 viewBox
    - Add Gemini provider presets configuration
    - Update i18n translations for Gemini support
    - Extend ProviderService and McpService for Gemini
    
    * fix(gemini): resolve TypeScript errors, add i18n support, and fix MCP logic
    
    **Critical Fixes:**
    - Fix TS2741 errors in tests/msw/state.ts by adding missing Gemini type definitions
    - Fix ProviderCard.extractApiUrl to support GOOGLE_GEMINI_BASE_URL display
    - Add missing apps.gemini i18n keys (zh/en) for proper app name display
    - Fix MCP service Gemini cross-app duplication logic to prevent self-copy
    
    **Technical Details:**
    - tests/msw/state.ts: Add gemini default providers, current ID, and MCP config
    - ProviderCard.tsx: Check both ANTHROPIC_BASE_URL and GOOGLE_GEMINI_BASE_URL
    - services/mcp.rs: Skip Gemini in sync_other_side logic with unreachable!() guards
    - Run pnpm format to auto-fix code style issues
    
    **Verification:**
    -  pnpm typecheck passes
    -  pnpm format completed
    
    * feat(gemini): enhance authentication and config parsing
    
    - Add strict and lenient .env parsing modes
    - Implement PackyCode partner authentication detection
    - Support Google OAuth official authentication
    - Auto-configure security.auth.selectedType for PackyCode
    - Add comprehensive test coverage for all auth types
    - Update i18n for OAuth hints and Gemini config
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • chore(release): prepare for v3.6.1 release
    - Bump version to 3.6.1 across all config files
      - package.json, Cargo.toml, tauri.conf.json
      - README.md and README_ZH.md version badges
      - Auto-updated Cargo.lock
    - Add release notes documentation
      - docs/release-note-v3.6.0-en.md (archive)
      - docs/release-note-v3.6.1-zh.md (cumulative format)
      - docs/release-note-v3.6.1-en.md (cumulative format)
    - Enlarge PackyCode sponsor logo by 50% (100px → 150px)
    - Update roadmap checklist (homebrew support marked as done)
  • feat(usage-query): decouple credentials from provider config
    Add independent credential fields for usage query to support different
    query endpoints and authentication methods.
    
    Changes:
    - Add `apiKey` and `baseUrl` fields to UsageScript struct
    - Remove dependency on provider config credentials in query_usage
    - Update test_usage_script to accept independent credential parameters
    - Add credential input fields in UsageScriptModal based on template:
      * General: apiKey + baseUrl
      * NewAPI: baseUrl + accessToken + userId
      * Custom: no additional fields (full freedom)
    - Auto-clear irrelevant fields when switching templates
    - Add i18n text for "credentialsConfig"
    
    Benefits:
    - Query API can use different endpoint/key than provider config
    - Better separation of concerns
    - More flexible for various usage query scenarios
  • fix(tray): replace unwrap with safe pattern matching in menu handler
    Replace unwrap() calls with safe pattern matching to prevent panics
    when handling invalid tray menu item IDs. Now logs errors and returns
    gracefully instead of crashing the application.
  • fix(provider): set category to custom for imported default config
    Ensure that when importing default configuration from live files,
    the created provider is properly marked with category "custom" for
    correct UI display and filtering.
  • Release v3.6.0: Major architecture refactoring and feature enhancements
    New Features:
    - Provider duplication and manual sorting via drag-and-drop
    - Custom endpoint management for aggregator providers
    - Usage query with auto-refresh interval and test script API
    - Config editor improvements (JSON format button, real-time TOML validation)
    - Auto-sync on directory change for WSL environment support
    - Load live config when editing active provider to protect manual modifications
    - New provider presets: DMXAPI, Azure Codex, AnyRouter, AiHubMix, MiniMax
    - Partner promotion mechanism (Zhipu GLM Z.ai)
    
    Architecture Improvements:
    - Backend: 5-phase refactoring (error handling → command split → services → concurrency)
    - Frontend: 4-stage refactoring (tests → hooks → components → cleanup)
    - Testing: 100% hooks unit test coverage, integration tests for critical flows
    
    Documentation:
    - Complete README rewrite with detailed architecture overview
    - Separate Chinese (README_ZH.md) and English (README.md) versions
    - Comprehensive v3.6.0 changelog with categorized changes
    - New bilingual screenshots and partner banners
    
    Bug Fixes:
    - Fixed configuration sync issues (apiKeyUrl priority, MCP sync, import sync)
    - Fixed usage query interval timing and refresh button animation
    - Fixed UI issues (edit mode alignment, language switch state)
    - Fixed endpoint speed test and provider duplicate insertion position
    - Force exit on config error to prevent silent fallback
    
    Technical Details:
    - Updated to Tauri 2.8.x, TailwindCSS 4.x, TanStack Query v5.90.x
    - Removed legacy v1 migration logic for better startup performance
    - Standardized command parameters (unified to camelCase `app`)
    - Result pattern for graceful error handling
  • chore: apply cargo fmt before release
    - Format code in app_config.rs to comply with rustfmt rules
    - Remove extra blank line in config.rs
    - Format test code in app_config_load.rs for consistency
  • refactor(cleanup): remove dead code and optimize Option checks
    - Remove 5 unused functions that were left over from migration refactoring:
      - get_archive_root, ensure_unique_path, archive_file (config.rs)
      - read_config_text_from_path, read_and_validate_config_from_path (codex_config.rs)
    - Simplify is_v1 check using is_some_and instead of map_or for better readability
    - Remove outdated comments about removed functions
    
    This eliminates all dead_code warnings and improves code maintainability.
  • refactor(migration): remove legacy v1 copy file migration logic
    Remove the entire migration module (435 lines) that was used for
    one-time migration from v3.1.0 to v3.2.0. This cleans up technical
    debt and improves startup performance.
    
    Changes:
    - Delete src-tauri/src/migration.rs (copy file scanning and merging)
    - Remove migration module reference from lib.rs
    - Simplify startup logic to only ensure config structure exists
    - Remove automatic deduplication and archiving logic
    
    BREAKING CHANGE: Users upgrading from v3.1.0 must first upgrade to
    v3.2.x to automatically migrate their configurations.
  • refactor(config): remove v1 auto-migration and improve error handling
    BREAKING CHANGE: Runtime auto-migration from v1 to v2 config format has been removed.
    
    Changes:
    - Remove automatic v1→v2 migration logic from MultiAppConfig::load()
    - Improve v1 detection using structural analysis (checks for 'apps' key absence)
    - Return clear error with migration instructions when v1 config is detected
    - Add comprehensive tests for config loading edge cases
    - Fix false positive detection when v1 config contains 'version' or 'mcp' fields
    
    Migration path for users:
    1. Install v3.2.x to perform one-time auto-migration, OR
    2. Manually edit ~/.cc-switch/config.json to v2 format
    
    Rationale:
    - Separates concerns: load() should be read-only, not perform side effects
    - Fail-fast principle: unsupported formats should error immediately
    - Simplifies code maintenance by removing migration logic from hot path
    
    Tests added:
    - load_v1_config_returns_error_and_does_not_write
    - load_v1_with_extra_version_still_treated_as_v1
    - load_invalid_json_returns_parse_error_and_does_not_write
    - load_valid_v2_config_succeeds
  • chore: unify code formatting and remove unused code
    - Apply cargo fmt to Rust code with multiline error handling
    - Apply Prettier formatting to TypeScript code with trailing commas
    - Unify #[allow(non_snake_case)] attribute formatting
    - Remove unused ProviderNotFound error variant from error.rs
    - Add vitest-report.json to .gitignore to exclude test artifacts
    - Optimize readability of error handling chains with vertical alignment
    
    All tests passing: 22 Rust tests + 126 frontend tests
  • refactor(usage): consolidate query logic to eliminate DRY violations
    Breaking Changes:
    - Removed useAutoUsageQuery hook (119 lines)
    - Unified all usage queries into single useUsageQuery hook
    
    Technical Improvements:
    - Eliminated duplicate state management (React Query + manual useState)
    - Fixed single source of truth principle violation
    - Replaced manual setInterval with React Query's built-in refetchInterval
    - Reduced UsageFooter complexity by 28% (54 → 39 lines)
    
    New Features:
    - useUsageQuery now accepts autoQueryInterval option
    - Automatic query interval control (0 = disabled, min 1 minute)
    - Built-in lastQueriedAt timestamp from dataUpdatedAt
    - Auto-query only enabled for currently active provider
    
    Architecture Benefits:
    - Single data source: manual and auto queries share same cache
    - No more state inconsistency between manual/auto query results
    - Leverages React Query's caching, deduplication, and background updates
    - Cleaner separation of concerns
    
    Code Changes:
    - src/lib/query/queries.ts: Enhanced useUsageQuery with auto-query support
    - src/components/UsageFooter.tsx: Simplified to use single query hook
    - src/hooks/useAutoUsageQuery.ts: Deleted (redundant)
    - All type checks passed
  • feat(usage): add auto-refresh interval for usage queries
    New Features:
    - Users can configure auto-query interval in "Configure Usage Query" dialog
    - Interval in minutes (0 = disabled, recommend 5-60 minutes)
    - Auto-query only enabled for currently active provider
    - Display last query timestamp in relative time format (e.g., "5 min ago")
    - Execute first query immediately when enabled, then repeat at intervals
    
    Technical Implementation:
    - Backend: Add auto_query_interval field to UsageScript struct
    - Frontend: Create useAutoUsageQuery Hook to manage timers and query state
    - UI: Add auto-query interval input field in UsageScriptModal
    - Integration: Display auto-query results and timestamp in UsageFooter
    - i18n: Add Chinese and English translations
    
    UX Improvements:
    - Minimum interval protection (1 minute) to prevent API abuse
    - Auto-cleanup timers on component unmount
    - Silent failure handling for auto-queries, non-intrusive to users
    - Prioritize auto-query results, fallback to manual query results
    - Timestamp display positioned next to refresh button for better clarity
  • refactor(i18n): complete error message internationalization and code cleanup
    Replaced all remaining hardcoded error types with AppError::localized for
    full bilingual support and simplified error handling logic.
    
    Backend changes:
    - usage_script.rs: Converted InvalidHttpMethod to localized error
    - provider.rs: Replaced all 7 ProviderNotFound instances with localized errors
      * Line 436: Delete provider validation
      * Line 625: Update provider metadata
      * Line 785: Test usage script provider lookup
      * Line 855: Query usage provider lookup
      * Line 924: Prepare Codex provider switch
      * Line 1011: Prepare Claude provider switch
      * Line 1272: Delete provider snapshot
    - provider.rs: Simplified error message formatting (removed 40+ lines)
      * Removed redundant string matching fallback logic
      * Now uses clean language-based selection for Localized errors
      * Falls back to default Display for other error types
    - error.rs: Removed unused error variants
      * Deleted InvalidHttpMethod (replaced with localized)
      * Deleted ProviderNotFound (replaced with localized)
    
    Code quality improvements:
    - Reduced complexity: 40+ lines of string matching removed
    - Better maintainability: Centralized error message handling
    - Type safety: All provider errors now use consistent localized format
    
    Impact:
    - 100% i18n coverage for provider and usage script error messages
    - Cleaner, more maintainable error handling code
    - No unused error variants remaining
  • fix(i18n): internationalize test script related error messages
    Fixed 5 hardcoded Chinese error messages to support bilingual display:
    
    Backend changes (services):
    - provider.rs: Fixed 4 error messages:
      * Data format error when deserializing array (line 731)
      * Data format error when deserializing single object (line 738)
      * Regex initialization failure (line 1163)
      * App type not found (line 1191)
    - speedtest.rs: Fixed 1 error message:
      * HTTP client creation failure (line 104)
    
    All errors now use AppError::localized to provide both Chinese and English messages.
    
    Impact:
    - Users will now see properly localized error messages when testing usage scripts
    - Error messages respect the application language setting
    - Better user experience for English-speaking users
  • feat(i18n): complete internationalization for usage query feature
    Fully internationalized the usage query feature to support both Chinese and English.
    
    Frontend changes:
    - Refactored UsageScriptModal to use i18n translation keys
    - Replaced hardcoded Chinese template names with constants
    - Implemented dynamic template generation with i18n support
    - Internationalized all labels, placeholders, and code comments
    - Added template name mapping for translation
    
    Backend changes:
    - Replaced all hardcoded Chinese error messages in usage_script.rs
    - Converted 33 error instances from AppError::Message to AppError::localized
    - Added bilingual error messages for runtime, parsing, HTTP, and validation errors
    
    Translation updates:
    - Added 11 new translation key pairs to zh.json and en.json
    - Covered template names, field labels, placeholders, and code comments
    
    Impact:
    - 100% i18n coverage for usage query functionality
    - All user-facing text and error messages now support language switching
    - Better user experience for English-speaking users