Commit Graph

636 Commits

  • feat(mcp): add smart JSON parser for flexible input formats
    Support multiple MCP configuration input formats:
    - Pure config object: { "command": "npx", ... }
    - Key-value pair fragment: "server-name": { "command": "npx", ... }
    - Wrapped object: { "server-name": { "command": "npx", ... } }
    
    The parser automatically:
    - Detects and wraps JSON fragments into complete objects
    - Extracts server name from single-key objects
    - Auto-fills ID and Name fields when applicable
    - Formats the config for display
    
    This improves UX by allowing users to paste configs directly from
    .claude.json or .codex/config.toml without manual editing.
  • refactor(mcp): improve form label layout and simplify text
    - Simplify config label from "Full JSON configuration or use" to "Full JSON Configuration"
    - Align wizard button to the right using justify-between layout
    - Apply same pattern to TOML configuration label
    - Improve visual balance with cleaner left-right alignment
  • feat(mcp): enhance form UX with default apps and JSON formatter
    - Enable all apps (Claude, Codex, Gemini) by default when adding MCP servers
    - Improve config label with clearer wording: "Full JSON configuration or use [Config Wizard]"
    - Add JSON format button to beautify configuration with 2-space indentation
    - Update tests to reflect new default behavior
    - Clean up redundant explicit prop passing
    
    This provides a more streamlined experience by enabling all apps out of the box
    and making it easier to format JSON configurations.
  • 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" }
    }
  • refactor(codex): simplify custom template with minimal config
    **Changes:**
    - Remove all comments from custom template (align with Claude/Gemini)
    - Remove base_url field from template (user fills in form instead)
    - Simplify getCodexCustomTemplate() - no locale parameter needed
    - Keep preset configurations unchanged with their baseUrl values
    
    **Template now contains only:**
    - model_provider, model, model_reasoning_effort
    - disable_response_storage
    - [model_providers.custom] section with minimal fields
    
    **Benefits:**
    -  Cleaner, more focused template
    -  Consistent with other apps (no comments)
    -  Forces users to fill base_url via form field
    -  Reduced template size from 35+ lines to 12 lines
    
    Net change: -74 lines (codexTemplates.ts)
  • refactor(codex): extract template to config with i18n support
    **Changes:**
    - Create src/config/codexTemplates.ts with getCodexCustomTemplate factory
    - Support both Chinese and English templates based on i18n.language
    - Remove 70 lines of duplicated template strings from ProviderForm.tsx
    - Update both useEffect and handlePresetChange to use template factory
    - Clean up unused "Custom (Blank Template)" preset entry
    
    **Benefits:**
    -  Eliminates code duplication (35-line template repeated twice)
    -  Adds internationalization support for English users
    -  Follows project architecture (templates in config/ directory)
    -  Improves maintainability (single source of truth)
    -  Net reduction: 34 lines (81 additions, 115 deletions)
    
    **Technical Details:**
    - Template selection logic: (i18n.language || "zh").startsWith("zh") ? "zh" : "en"
    - Templates are identical except for comments language
    - Both auth and config are returned as a single CodexTemplate object
    
    Addresses DRY principle violation and architectural concerns identified
    in code review.
  • refactor(codex): remove configuration wizard and unify provider setup experience
    - Remove CodexQuickWizardModal component (~300 lines)
    - Add "Custom (Blank Template)" preset with annotated TOML template
    - Unify configuration experience across Claude/Codex/Gemini
    - Remove wizard-related i18n keys, keep apiUrlLabel for CodexFormFields
    - Simplify component integration by removing wizard state management
    
    This change reduces code complexity by ~250 lines while providing better
    user education through commented configuration templates in Chinese.
    
    Users can now:
    1. Select "Custom (Blank Template)" preset
    2. See annotated TOML template with inline documentation
    3. Follow step-by-step comments to configure custom providers
    
    BREAKING CHANGE: Configuration wizard UI removed, replaced with template-based approach
  • style(mcp): refine panel layout for better visual hierarchy and compactness
    - Replace checkboxes with toggle switches for app selection (more intuitive for enable/disable actions)
    - Change switch color from blue to emerald to match MCP button theme
    - Stack app options vertically with labels on left to save horizontal space
    - Reduce panel width from max-w-4xl to max-w-3xl for more compact design
    - Move docs button next to server name for better information grouping
  • 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
  • refactor(mcp): complete form refactoring for unified MCP management
    Complete the v3.7.0 MCP refactoring by updating the form layer to match
    the unified architecture already implemented in data/service/API layers.
    
    **Breaking Changes:**
    - Remove confusing `appId` parameter from McpFormModal
    - Replace with `defaultFormat` (json/toml) and `defaultEnabledApps` (array)
    
    **Form Enhancements:**
    - Add app enablement checkboxes (Claude/Codex/Gemini) directly in the form
    - Smart defaults: new servers default to Claude enabled, editing preserves state
    - Support "draft" mode: servers can be created without enabling any apps
    
    **Architecture Improvements:**
    - Eliminate semantic confusion: format selection separate from app targeting
    - One-step workflow: configure and enable apps in single form submission
    - Consistent with unified backend: `apps: { claude, codex, gemini }`
    
    **Testing:**
    - Update test mocks to use `useUpsertMcpServer` hook
    - Add test case for creating servers with no apps enabled
    - Fix parameter references from `appId` to `defaultFormat`
    
    **i18n:**
    - Add `mcp.form.enabledApps` translation (zh/en)
    - Add `mcp.form.noAppsWarning` translation (zh/en)
    
    This completes the MCP management refactoring, ensuring all layers
    (data, service, API, UI) follow the same unified architecture pattern.
  • 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)
  • refactor(frontend): remove redundant 'Sync All' button from MCP panel
    All MCP operations already auto-sync to live configs:
    - upsert_server() → sync_server_to_apps()
    - toggle_app() → sync_server_to_app() or remove_server_from_app()
    - delete_server() → remove_server_from_all_apps()
    
    The manual 'Sync All' button was redundant and could confuse users
    into thinking they need to manually sync after each change.
    
    Changes:
    - Remove 'Sync All' button from UnifiedMcpPanel header
    - Remove useSyncAllMcpServers hook
    - Remove handleSyncAll function and syncAllMutation state
    - Remove RefreshCw icon import
    - Remove sync-related i18n translations (en/zh)
    
    Note: Backend sync_all_mcp_servers command remains for potential
    future use (e.g., recovery tool), but is no longer exposed in UI.
  • refactor(frontend): remove MCP import functionality for v3.7.0
    Auto-migration at startup is sufficient for upgrading from v3.6.x.
    Manual import adds unnecessary complexity since:
    - Gemini MCP support launches with v3.7.0 (no legacy data)
    - Existing Claude/Codex MCP configs are auto-migrated on first run
    - All MCP management should happen within CC Switch
    
    Changes:
    - Remove McpImportDialog component
    - Remove "Import" button from UnifiedMcpPanel
    - Remove import-related i18n translations (en/zh)
    - Simplify user experience with single management interface
    
    Note: Backend import commands (import_mcp_from_*) remain for
    backward compatibility but are no longer exposed in UI.
  • feat(frontend): add MCP import dialog for v3.7.0
    Implement import functionality to migrate MCP servers from existing configs:
    
    **New Component:**
    - src/components/mcp/McpImportDialog.tsx: Import dialog with card-based source selection
    
    **Features:**
    - Import from Claude (~/.claude/claude.json or settings.json)
    - Import from Codex (~/.codex/config.toml)
    - Import from Gemini (config file)
    - Card-based UI with icons and descriptions
    - Loading states with spinner animation
    - Auto-refresh after successful import
    
    **Integration:**
    - Add import button to UnifiedMcpPanel header
    - Handle import completion with refetch
    - Toast notifications for success/info/error cases
    
    **I18n:**
    - Add mcp.unifiedPanel.import namespace (zh/en)
    - Import button, dialog title, descriptions
    - Success/error messages with count interpolation
    
    **UX:**
    - Smart disable: other sources disabled during import
    - Clear feedback: count of imported servers
    - Friendly messages: "No servers found" when empty
    
    TypeScript type check passes 
  • feat(frontend): implement unified MCP panel for v3.7.0
    Complete Phase 3 (P0) frontend implementation for unified MCP management:
    
    **New Files:**
    - src/hooks/useMcp.ts: React Query hooks for unified MCP operations
    - src/components/mcp/UnifiedMcpPanel.tsx: Unified MCP management panel
    - src/components/ui/checkbox.tsx: Checkbox component from shadcn/ui
    
    **Features:**
    - Unified panel with three-column layout: server info + app checkboxes + actions
    - Multi-app control: Claude/Codex/Gemini checkboxes for each server
    - Real-time stats: Show enabled server counts per app
    - Full CRUD operations: Add, edit, delete, sync all servers
    
    **Integration:**
    - Replace old app-specific McpPanel with UnifiedMcpPanel in App.tsx
    - Update McpFormModal to support unified mode with apps field
    - Add i18n support: mcp.unifiedPanel namespace (zh/en)
    
    **Type Safety:**
    - Ensure McpServer.apps field always initialized
    - Fix all test files to include apps field
    - TypeScript type check passes 
    
    **Architecture:**
    - Single source of truth: mcp.servers manages all MCP configs
    - Per-server app control: apps.claude/codex/gemini boolean flags
    - Backward compatible: McpFormModal supports both unified and legacy modes
    
    Next: P1 tasks (import dialogs, sub-components, tests)
  • docs: add comprehensive v3.7.0 unified MCP refactor plan
    ## Document Overview
    Created detailed refactoring plan document covering:
    - Project goals and architecture changes
    - Data structure migration strategy (v3.6.x → v3.7.0)
    - Complete development progress tracking
    - Frontend remaining tasks roadmap
    - Testing plan and delivery checklist
    
    ## Completed Work (Documented)
     Phase 1: Backend data structure migration
      - McpApps, McpServer, McpRoot definitions
      - Automatic migration logic
      - Integration into load() method
    
     Phase 2: Backend services refactor
      - Complete McpService rewrite
      - Single-server sync functions
      - New Tauri commands
      - Backward compatibility layer
      - All compilation errors fixed
    
     Phase 3 (Partial): Frontend types and API
      - Updated TypeScript types (McpApps, McpServer)
      - New API methods (getAllServers, toggleApp, etc.)
    
    ## Remaining Work (Documented)
    📝 React Query hooks (useMcp.ts)
    📝 UnifiedMcpPanel component
    📝 i18n translations
    📝 Main app integration
    📝 Sub-components (table, form, import dialog)
    
    ## Key Highlights
    - Detailed UI wireframes and component structure
    - Step-by-step migration flow documentation
    - Risk assessment and mitigation strategies
    - Technical insights and architecture benefits
    
    Related: v3.7.0 unified MCP management
  • feat(frontend): add unified MCP types and API layer for v3.7.0
    ## Type Definitions
    - Update McpServer interface with new apps field (McpApps)
    - Add McpApps interface for multi-app enable state
    - Add McpServersMap type for server collections
    - Mark enabled field as deprecated (use apps instead)
    - Maintain backward compatibility with optional fields
    
    ## API Layer Updates
    - Add unified MCP management methods to mcpApi:
      * getAllServers() - retrieve all servers with apps state
      * upsertUnifiedServer() - add/update server with apps
      * deleteUnifiedServer() - remove server
      * toggleApp() - enable/disable server for specific app
      * syncAllServers() - sync all enabled servers to live configs
    - Import new McpServersMap type
    
    ## Code Organization
    - Keep all types in src/types.ts (removed duplicate types/mcp.ts)
    - Follow existing project structure conventions
    
    Related: v3.7.0 unified MCP management
  • 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
  • fix(i18n): add missing Gemini MCP panel title and fix ternary logic
    - Add mcp.geminiTitle to both zh.json and en.json
    - Fix McpPanel title logic to handle all three apps (claude/codex/gemini)
    - Previous logic would incorrectly display codexTitle for gemini
  • 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(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.
  • fix(i18n): deduplicate category labels by reusing providerForm keys
    - Change ProviderForm to use providerForm.category* instead of providerPreset.category*
    - Remove duplicate category keys from providerPreset namespace in both zh.json and en.json
    - Fix naming inconsistency: use categoryAggregation (not categoryAggregator)
    - Fixes issue where English UI would show Chinese defaultValue fallbacks
    
    This ensures single source of truth for category labels and improves maintainability.
  • 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(ui): prevent URL overflow in provider cards
    Add max-width constraint to URL display to prevent long URLs from breaking card layout.
  • refactor(i18n): remove unnecessary translation for brand names
    - Use hardcoded "Claude", "Codex", "Gemini" instead of i18n keys
    - Brand names should not be translated across different locales
    - Simplifies code by removing useTranslation hook from AppSwitcher
    - Reduces maintenance overhead in translation files
  • fix(i18n): add internationalization support for app names
    - Add i18n for Claude/Codex/Gemini app names in AppSwitcher
    - Use useTranslation hook with existing translation keys
    - Fix ASCII diagram alignment in README files
  • 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(gemini): add Google Official branding with Gemini icon (#211)
    Update Google Gemini preset to match Claude Official styling:
    - Rename 'Google' to 'Google Official'
    - Add GeminiIcon support in preset selector
    - Add custom theme with Google blue (#4285F4) background
    - Update PresetTheme type to support 'gemini' icon type
    
    Changes:
    - Add GeminiPresetTheme interface
    - Add theme config to Google Official preset
    - Import and render GeminiIcon in ProviderPresetSelector
    - Update PresetTheme icon type to include 'gemini'
  • 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.
  • refactor(endpoint): separate edit and create mode endpoint management (#192)
    Optimize custom endpoint management logic to distinguish between edit and create modes:
    - Edit mode: endpoints are read/written directly to backend via API
    - Create mode: use draftCustomEndpoints to stage, save on submit
    - Remove duplicate endpoint loading in useSpeedTestEndpoints
    - Add isSaving state and initialCustomUrls tracking
  • 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>
  • feat(presets): add Kimi For Coding and BaiLing provider presets
    Add two new Chinese official provider presets:
    - Kimi For Coding: AI coding assistant from Kimi
    - BaiLing: Claude-compatible API from AliPay TBox
  • docs: add TypeScript Trending badge and improve contributing tone
    - Add 🔥 TypeScript Trending badge celebrating daily/weekly/monthly rankings
    - Refine contributing guidelines with friendlier, more welcoming language
    - Replace directive tone with collaborative suggestions for feature PRs
  • 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(sponsor): add PackyCode as official partner
    - Add PackyCode to sponsor section in README (both EN/ZH)
    - Add PackyCode logo to assets/partners/logos/
    - Mark PackyCode as partner in provider presets (Claude & Codex)
    - Add promotion message to i18n files with 10% discount info
  • refactor(usage-script): replace native checkbox with Switch component
    Upgrade the enable toggle from native checkbox to shadcn/ui Switch component
    for better UX and UI consistency with settings page.
    
    **Improvements**:
    1. Use modern toggle UI (Switch) instead of traditional checkbox
    2. Adopt the same layout pattern as settings page (ToggleRow style)
    3. Add bordered container with proper spacing for better visual hierarchy
    4. Maintain full accessibility support (aria-label)
    
    **Layout changes**:
    - Before: Simple label + checkbox horizontal layout
    - After: Bordered container, label on left, Switch on right, vertically centered
  • fix(usage-script): replace FormLabel with Label to fix white screen crash
    FormLabel component requires FormField context and throws error when used
    standalone, causing the entire component to crash with a white screen.
    
    Root cause:
    - FormLabel internally calls useFormField() hook
    - useFormField() requires FormFieldContext (must be within <FormField>)
    - Without context, it throws: "useFormField should be used within <FormField>"
    - Uncaught error crashes React rendering tree
    
    Solution:
    - Replace FormLabel with standalone Label component
    - Label component from @/components/ui/label doesn't depend on form context
    - Maintains same styling (text-sm font-medium) without requiring context
    
    This fixes the white screen issue when clicking the usage panel.