Commit Graph

11 Commits

  • revert: restore full config overwrite + Common Config Snippet (revert 992dda5c)
    Revert the partial key-field merging refactoring introduced in 992dda5c,
    along with two dependent commits (24fa8a18, 87604b18) that referenced
    the now-removed ClaudeQuickToggles component.
    
    The whitelist-based partial merge approach had critical issues:
    - Non-whitelisted custom fields were lost during provider switching
    - Backfill permanently stripped non-key fields from the database
    - Whitelist required constant maintenance to track upstream changes
    
    This restores the proven "full config overwrite + Common Config Snippet"
    architecture where each provider stores its complete configuration and
    shared settings are managed via a separate snippet mechanism.
    
    Reverted commits:
    - 24fa8a18: context-aware JSON editor hint + hide quick toggles
    - 87604b18: hide ClaudeQuickToggles when creating
    - 992dda5c: partial key-field merging refactoring
    
    Restored:
    - Full config snapshot write (write_live_snapshot) for Claude/Codex/Gemini
    - Full config backfill (settings_config = live_config)
    - Common Config Snippet UI and backend commands
    - 6 frontend components/hooks for common config editing
    - configApi barrel export and DB snippet methods
    
    Removed:
    - ClaudeQuickToggles component
    - write_live_partial / backfill_key_fields / patch_claude_live
    - All KEY_FIELDS constants
  • refactor(provider): switch from full config overwrite to partial key-field merging (#1098)
    * refactor(provider): switch from full config overwrite to partial key-field merging
    
    Replace the provider switching mechanism for Claude/Codex/Gemini from
    full settings_config overwrite to partial key-field replacement, preserving
    user's non-provider settings (plugins, MCP, permissions, etc.) across switches.
    
    - Add write_live_partial() with per-app implementations for Claude (JSON env
      merge), Codex (auth replace + TOML partial merge), and Gemini (env merge)
    - Add backfill_key_fields() to extract only provider-specific fields when
      saving live config back to provider entries
    - Update switch_normal, sync_current_to_live, add, update to use partial merge
    - Remove common config snippet feature for Claude/Codex/Gemini (no longer
      needed with partial merging); preserve OMO common config
    - Delete 6 frontend files (3 components + 3 hooks), clean up 11 modified files
    - Remove backend extract_common_config_* methods, 3 Tauri commands,
      CommonConfigSnippets struct, and related migration code
    - Update integration tests to validate key-field-only backfill behavior
    
    * refactor(cleanup): remove dead code and redundant MCP sync after partial-merge refactor
    
    - Remove ConfigService legacy full-overwrite sync methods (~150 lines)
    - Remove redundant McpService::sync_all_enabled from switch_normal
    - Switch proxy fallback recovery from write_live_snapshot to write_live_partial
    - Remove dead ProviderService::write_gemini_live wrapper
    - Update tests to reflect partial-merge behavior (MCP preserved, not re-synced)
    
    * feat(claude): add Quick Toggles for common Claude Code preferences
    
    Add checkbox toggles for hideAttribution, alwaysThinking, and
    enableTeammates that write directly to the live settings file via
    RFC 7396 JSON Merge Patch. Mirror changes to the form editor using
    form.watch for reactive updates.
    
    * fix(provider): add missing key fields to partial-merge constants
    
    Add provider-specific fields verified against official docs to prevent
    key residue or loss during provider switching:
    
    - Claude: CLAUDE_CODE_SUBAGENT_MODEL (env), model (top-level)
    - Codex: review_model, plan_mode_reasoning_effort
    - Gemini: GOOGLE_API_KEY (official alternative to GEMINI_API_KEY)
    
    * fix(provider): expand partial-merge key fields for Bedrock, Vertex, Foundry and behavior settings
    
    Add missing env/top-level fields to CLAUDE_KEY_ENV_FIELDS and
    CLAUDE_KEY_TOP_LEVEL so that provider switching correctly replaces
    (and clears) credentials and flags for AWS Bedrock, Google Vertex AI,
    Microsoft Foundry, and provider behavior overrides like max output
    tokens and prompt caching.
    
    * feat(provider): add auth field selector for Claude providers (AUTH_TOKEN / API_KEY)
    
    Allow users to choose between ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY
    when creating or editing custom Claude providers, persisted in meta.apiKeyField.
    
    * refactor(preset): remove AiHubMix hardcoded API_KEY in favor of generic auth selector
    
    AiHubMix was the only preset that hardcoded ANTHROPIC_API_KEY before the
    generic auth field selector was introduced. Now that users can freely
    choose between AUTH_TOKEN and API_KEY via the UI, remove the special-case
    and default AiHubMix to the standard ANTHROPIC_AUTH_TOKEN.
  • feat(opencode): complete Phase 4 - MCP sync module
    Add mcp/opencode.rs with format conversion between CC Switch and OpenCode:
    - stdio ↔ local type conversion
    - command+args ↔ command array format
    - env ↔ environment field mapping
    - sse/http ↔ remote type conversion
    
    Public API:
    - sync_enabled_to_opencode: Batch sync all enabled servers
    - sync_single_server_to_opencode: Sync individual server
    - remove_server_from_opencode: Remove from live config
    - import_from_opencode: Import servers from OpenCode config
    
    Also fix test files to include new opencode field in McpApps struct.
    All 4 unit tests pass for format conversion.
  • feat(skill): implement recursive scanning for skill repositories (#309)
    Add recursive directory scanning to discover SKILL.md files in nested
    directories. When a SKILL.md is found, treat sibling directories as
    functional folders rather than separate skills.
  • fix(provider): add backfill and Gemini security flags to switch function
    The switch function was missing two important features after the SQLite
    migration:
    
    1. Backfill mechanism: Before switching providers, read the current live
       config and save it back to the current provider. This preserves any
       manual edits users made to the live config file.
    
    2. Gemini security flags: When switching to a Gemini provider, set the
       appropriate security.auth.selectedType:
       - PackyCode providers: "gemini-api-key"
       - Google OAuth providers: "oauth-personal"
    
    Also update tests to:
    - Use the new unified MCP structure (mcp.servers) instead of the legacy
      per-app structure (mcp.codex.servers)
    - Expect backfill behavior (was incorrectly marked as "no backfill")
    - Remove assertions for provider-specific file deletion (v3.7.0+ uses
      SSOT, no longer creates per-provider config files)
  • Merge feat/sqlite-migration: add database schema migration system
    This merge brings the SQLite migration system from feat/sqlite-migration branch:
    
    ## New Features
    - Schema version control with SCHEMA_VERSION constant
    - Automatic migration of missing columns for providers table
    - Dry-run validation mode for schema compatibility checks
    - JSON→SQLite migration feature gate (CC_SWITCH_ENABLE_JSON_DB_MIGRATION)
    - Settings reload mechanism after imports
    
    ## Test Updates
    - Updated tests to use SQLite database instead of config.json
    - Removed obsolete import_config_from_path tests (replaced by db.import_sql)
    - Fixed MCP tests to use unified McpServer structure (v3.7.0+)
    - Updated provider switch tests to reflect no-backfill behavior
    - Adjusted error type matching for new error variants
  • test: migrate tests to SQLite database architecture
    This commit refactors all tests to work with the new database-based
    architecture, replacing the previous JSON config approach.
    
    Key changes:
    - Add Database export to lib.rs for test access
    - Create test helper functions in support.rs:
      - create_test_state(): Creates empty test state with fresh DB
      - create_test_state_with_config(): Migrates JSON config to DB
    - Fix environment isolation in provider_service tests:
      - provider_service_switch_missing_provider_returns_error
      - provider_service_switch_codex_missing_auth_returns_error
    - Replace ignored export tests with working alternatives:
      - export_sql_writes_to_target_path (tests Database::export_sql)
      - export_sql_returns_error_for_invalid_path (tests error handling)
    - Update error type matching to align with current implementation
    
    All tests now:
    - Use isolated test environments (test_mutex + reset_test_fs)
    - Access data via Database API instead of RwLock<MultiAppConfig>
    - Work with SQLite persistence layer
    - Pass without environment pollution or race conditions
    
    Fixes test compilation errors after database migration.
  • refactor(backend): phase 5 - optimize concurrency with RwLock and async IO
    Replace Mutex with RwLock for AppState.config to enable concurrent reads,
    improving performance for tray menu building and query operations that
    previously blocked each other unnecessarily.
    
    Key changes:
    - Migrate AppState.config from Mutex<MultiAppConfig> to RwLock<MultiAppConfig>
    - Distinguish read-only operations (read()) from mutations (write()) across
      all command handlers and service layers
    - Offload blocking file I/O in import/export commands to spawn_blocking threads,
      minimizing lock hold time and preventing main thread blocking
    - Extract load_config_for_import() to separate I/O logic from state updates
    - Update all integration tests to use RwLock semantics
    
    Performance impact:
    - Concurrent reads: Multiple threads can now query config simultaneously
      (tray menu, provider list, MCP config)
    - Reduced contention: Write locks only acquired during actual mutations
    - Non-blocking I/O: Config import/export no longer freezes UI thread
    
    All existing tests pass with new locking semantics.
  • refactor(backend): phase 4 - add test hooks and extend service layer
    - Extract internal functions in commands/mcp.rs and commands/provider.rs
      to enable unit testing without Tauri context
    - Add test hooks: set_mcp_enabled_test_hook, import_mcp_from_claude_test_hook,
      import_mcp_from_codex_test_hook, import_default_config_test_hook
    - Migrate error types from String to AppError for precise error matching in tests
    - Extend ProviderService with delete() method to unify Codex/Claude cleanup logic
    - Add comprehensive test coverage:
      - tests/mcp_commands.rs: command-level tests for MCP operations
      - tests/provider_service.rs: service-level tests for switch/delete operations
    - Run cargo fmt to fix formatting issues (EOF newlines)
    - Update BACKEND_REFACTOR_PLAN.md to mark phase 3 complete
  • refactor(backend): phase 4 - extract provider service layer
    Architecture improvements:
    - Extract ProviderService with switch/backfill/write methods
    - Reduce command layer from 160 to 13 lines via delegation
    - Separate business logic (services) from state management (commands)
    - Introduce precise error handling with structured validation
    
    Refactoring details:
    - Split Codex/Claude switching into symmetric private methods
    - Add multi-layer validation for Codex auth field (existence + type)
    - Extract import_config_from_path for command and test reuse
    - Expose export_config_to_file and ProviderService in public API
    
    Test coverage:
    - Add 10+ integration tests for Claude/Codex switching flows
    - Cover import/export success and failure scenarios (JSON parse, missing file)
    - Verify state consistency on error paths (current remains unchanged)
    - Test snapshot backfill for both old and new providers after switching
  • refactor(backend): phase 3 - unify error handling and fix backup timestamp bug
    Key improvements:
    - Extract switch_provider_internal() returning AppError for better testability
    - Fix backup mtime inheritance: use read+write instead of fs::copy to ensure latest backup survives cleanup
    - Add 15+ integration tests covering provider commands, atomic writes, and rollback scenarios
    - Expose write_codex_live_atomic, AppState, and test hooks in public API
    - Extract tests/support.rs with isolated HOME and mutex utilities
    
    Test coverage:
    - Provider switching with live config backfill and MCP sync
    - Codex atomic write success and failure rollback
    - Backup retention policy with proper mtime ordering
    - Negative cases: missing auth field, invalid provider ID