Commit Graph

89 Commits

  • refactor: improve code quality and fix linting issues
    - Derive Default trait instead of manual implementation for McpRoot and ProviderManager
    - Remove redundant closures in codex_config.rs and config.rs
    - Simplify match statements to if let patterns in migration.rs and lib.rs
    - Remove unnecessary type conversions and borrows in lib.rs
    - Fix i18n key inconsistency: sequentialThinking → sequential-thinking
    - Format TypeScript files to match Prettier style
    
    All clippy warnings resolved, code passes all quality checks.
  • feat(mcp): add automatic key normalization for server entries
    - Add normalize_server_keys() to ensure MCP server map keys match internal id fields
    - Auto-normalize on all read/write operations (get, upsert, delete, import, sync)
    - Handle edge cases: empty/whitespace ids, key renaming, conflict resolution
    - Auto-save config when normalization detects changes
    - Apply cargo fmt for code formatting consistency
    
    This enhancement improves data integrity by automatically fixing inconsistencies
    between server entry keys and their id fields, especially after manual config edits.
  • refactor(mcp): improve data structure with metadata/spec separation
    - Separate MCP server metadata from connection spec for cleaner architecture
    - Add comprehensive server entry fields: name, description, tags, homepage, docs
    - Remove legacy format compatibility logic from extract_server_spec
    - Implement data validation and filtering in get_servers_snapshot_for
    - Add strict id consistency check in upsert_in_config_for
    - Enhance import logic with defensive programming for corrupted data
    - Simplify frontend by removing normalization logic (moved to backend)
    - Improve error messages with contextual information
    - Add comprehensive i18n support for new metadata fields
  • fix: preserve meta.custom_endpoints on update and persist preset candidates on create
    - Preserve and merge meta.custom_endpoints in update_provider to avoid losing custom endpoints added via Tauri commands during edit/save. Merge old and incoming meta; keep existing entries and timestamps, add new URLs only.
    - Persist endpoint candidates when creating a provider: union of user-added custom endpoints, selected base URL (Claude/Codex), and preset.endpointCandidates; normalize and de-duplicate. Ensures PackyCode keeps all 5 nodes after saving.
    
    Files:
    - src-tauri/src/commands.rs
    - src/components/ProviderForm.tsx
    
    Validation:
    - cargo check passes
    - Manual: create from PackyCode preset -> save -> reopen edit -> Manage & Test lists all preset nodes; edit existing provider -> add endpoint -> save -> reopen -> endpoint persists.
  • feat(settings): add 'Apply to Claude Code extension' toggle
    - Apply immediately on save (write or remove primaryApiKey)
    - Honor setting on provider switch (enabled: write for non-official, remove for official; disabled: no auto writes)
    - Remove per-provider Claude plugin buttons from ProviderList
    - Upsert primaryApiKey=any preserving other fields; respect override dir
    - Add zh/en i18n for the new setting
  • feat(provider): use live config for edit and backfill SSOT after switch
    - Edit modal (Claude+Codex): when editing the current provider, initialize form from live files (Claude: ~/.claude/settings.json; Codex: ~/.codex/auth.json + ~/.codex/config.toml) instead of SSOT.
    - Switch (Claude): after writing live settings.json for the target provider, read it back and update the provider’s SSOT to match live.
    - Switch (Codex): keep MCP sync to config.toml, then read back TOML and update the target provider’s SSOT (preserves mcp.servers/mcp_servers schema).
    - Add Tauri command read_live_provider_settings for both apps, register handler, and expose window.api.getLiveProviderSettings.
    - Types updated accordingly; cargo check and pnpm typecheck pass.
  • feat(mcp): import Codex MCP from ~/.codex/config.toml
    - Support both TOML schemas: [mcp.servers.<id>] and [mcp_servers.<id>]
    - Non-destructive merge of imported servers (enabled=true only)
    - Preserve existing TOML schema when syncing (prefer mcp_servers)
    - Remove both mcp and mcp_servers when no enabled items
    
    feat(ui): auto-import Codex MCP on panel init (app=codex)
    
    chore(tauri): add import_mcp_from_codex command and register
    
    chore(types): expose window.api.importMcpFromCodex and typings
    
    fix(ui): remove unused variable for typecheck
  • feat(mcp): app-aware MCP panel and Codex MCP sync to config.toml
    - Make MCP panel app-aware; pass appType from App and call APIs with current app
    - Show active app in title: “MCP Management · Claude Code/Codex”
    - Add sync_enabled_to_codex: project enabled servers from SSOT to ~/.codex/config.toml as [mcp.servers.*]
    - Sync on enable/disable, delete, and provider switch (post live write)
    - Add Tauri command sync_enabled_mcp_to_codex and expose window.api.syncEnabledMcpToCodex()
    - Fix Rust borrow scopes in switch_provider to avoid E0502
    - Add TS declarations for new Codex sync API
  • fix(mcp): remove SSE support; keep stdio default when type is omitted
    - Backend: reject "sse" in validators; accept missing type as stdio; require url only for http (mcp.rs, claude_mcp.rs)
    - Frontend: McpServer.type narrowed to "stdio" | "http" (optional) (src/types.ts)
    - UI: avoid undefined in list item details (McpListItem)
    - Claude-only sync after delete to update ~/.claude.json (commands.rs)
    
    Notes:
    - Ran typecheck and cargo check: both pass
    - Clippy shows advisory warnings unrelated to this change
    - Prettier check warns on a few files; limited scope changes kept minimal
  • feat(mcp): use project config as SSOT and sync enabled servers to ~/.claude.json
    - Add McpConfig to MultiAppConfig and persist MCP servers in ~/.cc-switch/config.json
    - Add Tauri commands: get_mcp_config, upsert_mcp_server_in_config, delete_mcp_server_in_config, set_mcp_enabled, sync_enabled_mcp_to_claude, import_mcp_from_claude
    - Only write enabled MCPs to ~/.claude.json (mcpServers) and strip UI-only fields (enabled/source)
    - Frontend: update API wrappers and MCP panel to read/write via config.json; seed presets on first open; import from ~/.claude.json
    - Fix warnings (remove unused mut, dead code)
    - Verified with cargo check and pnpm typecheck
  • fix(mcp): update MCP wizard to support http type and improve args input
    - Replace deprecated 'sse' type with 'http' (as per Claude Code official docs)
    - Add HTTP-specific fields: url (required) and headers (optional)
    - Implement dynamic UI: show different fields based on selected type
    - Improve args input: support multi-line input (one argument per line)
    - Add headers parsing supporting both 'KEY: VALUE' and 'KEY=VALUE' formats
    - Update backend validation to enforce type-specific required fields
    - Update i18n translations (zh/en) with new HTTP-related labels
  • refactor(mcp): switch to user-level config ~/.claude.json and remove project-level logic
    - Read/write ~/.claude.json (preserve unknown fields) for mcpServers
    - Remove settings.local.json and mcp.json handling
    - Drop enableAllProjectMcpServers command and UI toggle
    - Update types, Tauri APIs, and MCP panel to reflect new status fields
    - Keep atomic write and command validation behaviors
  • feat(mcp): add Rust module and Tauri commands for Claude MCP
    - Manage ~/.claude/settings.local.json and ~/.claude/mcp.json
    - Atomic JSON read/write with preservation of unknown fields
    - Commands: get_claude_mcp_status, read_claude_mcp_config, set_claude_mcp_enable_all_projects, upsert_claude_mcp_server, delete_claude_mcp_server, validate_mcp_command
    - Register commands in Tauri invoke handler
    - PATH-based command availability check (non-executing)
  • refactor: improve error handling and code formatting
    - Enhanced error messages in Rust backend to include file paths
    - Improved provider switching error handling with detailed messages
    - Added MCP button placeholder in UI (functionality TODO)
    - Applied code formatting across frontend components
    - Extended error notification duration to 6s for better readability
  • feat: improve endpoint speed test UI and accuracy
    - Add color-coded latency indicators (green <300ms, yellow <500ms, orange <800ms, red >=800ms)
    - Fix speed test button width to prevent layout shift during testing
    - Clear latency data before each test to properly show loading state
    - Add warmup request in speed test to avoid first packet penalty and improve accuracy
  • feat: Implement Speed Test Function
    * feat: add unified endpoint speed test for API providers
    
    Add a comprehensive endpoint latency testing system that allows users to:
    - Test multiple API endpoints concurrently
    - Auto-select the fastest endpoint based on latency
    - Add/remove custom endpoints dynamically
    - View latency results with color-coded indicators
    
    Backend (Rust):
    - Implement parallel HTTP HEAD requests with configurable timeout
    - Handle various error scenarios (timeout, connection failure, invalid URL)
    - Return structured latency data with status codes
    
    Frontend (React):
    - Create interactive speed test UI component with auto-sort by latency
    - Support endpoint management (add/remove custom endpoints)
    - Extract and update Codex base_url from TOML configuration
    - Integrate with provider presets for default endpoint candidates
    
    This feature improves user experience when selecting optimal API endpoints,
    especially useful for users with multiple provider options or proxy setups.
    
    * refactor: convert endpoint speed test to modal dialog
    
    - Transform EndpointSpeedTest component into a modal dialog
    - Add "Advanced" button next to base URL input to open modal
    - Support ESC key and backdrop click to close modal
    - Apply Linear design principles: minimal styling, clean layout
    - Remove unused showBaseUrlInput variable
    - Implement same modal pattern for both Claude and Codex
    
    * fix: prevent modal cascade closing when ESC is pressed
    
    - Add state checks to prevent parent modal from closing when child modals (endpoint speed test or template wizard) are open
    - Update ESC key handler dependencies to track all modal states
    - Ensures only the topmost modal responds to ESC key
    
    * refactor: unify speed test panel UI with project design system
    
    UI improvements:
    - Update modal border radius from rounded-lg to rounded-xl
    - Unify header padding from px-6 py-4 to p-6
    - Change speed test button color to blue theme (bg-blue-500) for consistency
    - Update footer background from bg-gray-50 to bg-gray-100
    - Style "Done" button as primary action button with blue theme
    - Adjust footer button spacing and hover states
    
    Simplify endpoint display:
    - Remove endpoint labels (e.g., "Current Address", "Custom 1")
    - Display only URL for cleaner interface
    - Clean up all label-related logic:
      * Remove label field from EndpointCandidate interface
      * Remove label generation in buildInitialEntries function
      * Remove label handling in useEffect merge logic
      * Remove label generation in handleAddEndpoint
      * Remove label parameters from claudeSpeedTestEndpoints
      * Remove label parameters from codexSpeedTestEndpoints
    
    * refactor: improve endpoint list UI consistency
    
    - Show delete button for all endpoints on hover for uniform UI
    - Change selected state to use blue theme matching main interface:
      * Blue border (border-blue-500) for selected items
      * Light blue background (bg-blue-50/dark:bg-blue-900/20)
      * Blue indicator dot (bg-blue-500/dark:bg-blue-400)
    - Switch from compact list (space-y-px) to card-based layout (space-y-2)
    - Add rounded corners to each endpoint item for better visual separation
    
    * feat: persist custom endpoints to settings.json
    
    - Extend AppSettings to store custom endpoints for Claude and Codex
    - Add Tauri commands: get/add/remove/update custom endpoints
    - Update frontend API with endpoint persistence methods
    - Modify EndpointSpeedTest to load/save custom endpoints via API
    - Track endpoint last used time for future sorting/cleanup
    - Store endpoints per app type in settings.json instead of localStorage
    
    * - feat(types): add Provider.meta and ProviderMeta (snake_case) with custom_endpoints map
    
    - feat(provider-form): persist custom endpoints on provider create by merging EndpointSpeedTest’s custom URLs into meta.custom_endpoints on submit
    
    - feat(endpoint-speed-test): add onCustomEndpointsChange callback emitting normalized custom URLs; wire it for both Claude/Codex modals
    
    - fix(api): send alias param names (app/appType/app_type and provider_id/providerId) in Tauri invokes to avoid “missing providerId” with older backends
    
    - storage: custom endpoints are stored in ~/.cc-switch/config.json under providers[<id>].meta.custom_endpoints (not in settings.json)
    
    - behavior: edit flow remains immediate writes; create flow now writes once via addProvider, removing the providerId dependency during creation
    
    * feat: add endpoint candidates support and code formatting improvements
    
    - Add endpointCandidates field to ProviderPreset and CodexProviderPreset interfaces
    - Integrate preset endpoint candidates into speed test endpoint selection
    - Add multiple endpoint options for PackyCode providers (Claude & Codex)
    - Apply consistent code formatting (trailing commas, line breaks)
    - Improve template value type safety and readability
    
    * refactor: improve endpoint management button UX
    
    Replace ambiguous "Advanced" text with intuitive "Manage & Test" label accompanied by Zap icon, making the endpoint management panel entry point more discoverable and self-explanatory for both Claude and Codex configurations.
    
    * - merge: merge origin/main, resolve conflicts and preserve both feature sets
    - feat(tauri): register import/export and file dialogs; keep endpoint speed test and custom endpoints
    - feat(api): add updateTrayMenu and onProviderSwitched; wire import/export APIs
    - feat(types): extend global API declarations (import/export)
    - chore(presets): GLM preset supports both new and legacy model keys
    - chore(rust): add chrono dependency; refresh lockfile
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • add: local config import and export (#84)
    * add: local config import and export
    
    * Fix import refresh flow and typings
    
    * Clarify import refresh messaging
    
    * Limit stored import backups
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • feat: add macOS Dock visibility management for tray mode
    - Hide Dock icon when minimizing to tray
    - Show Dock icon when restoring window from tray
    - Apply appropriate activation policy (Accessory/Regular) based on window state
    - Add error handling with logging for Dock operations
  • feat: integrate language switcher into settings with modern segment control UI
    - Move language switcher from header to settings modal for better organization
    - Implement modern segment control UI instead of radio buttons for language selection
    - Add language preference persistence in localStorage and backend settings
    - Support instant language preview with cancel/revert functionality
    - Remove standalone LanguageSwitcher component
    - Improve initial language detection logic (localStorage -> browser -> default)
    - Add proper i18n keys for language settings UI text
  • feat: support minimizing window to tray on close (#41)
    fix: grant set_skip_taskbar permission through default capability
    
    chore: align settings casing and defaults between Rust and frontend
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • feat: add portable mode support and improve update handling
    - Add portable.ini marker file creation in GitHub Actions for portable builds
    - Implement is_portable_mode() command to detect portable execution
    - Redirect portable users to GitHub releases page for manual updates
    - Change update URL to point to latest releases page
    - Integrate portable mode detection in Settings UI
  • feat: add single instance plugin to prevent multiple app instances
    Integrates tauri_plugin_single_instance to ensure only one instance of the application
    runs at a time. When attempting to launch a second instance, it will focus the existing
    window instead.
  • feat: add created_at timestamp field to Provider struct
    - Add optional created_at field to track provider creation time
    - Serialize field as camelCase (createdAt) for JSON compatibility
    - Skip serialization when field is None to maintain backward compatibility
  • feat: add config directory override support for WSL
    - Add persistent app settings with custom Claude Code and Codex config directories
    - Add config directory override UI in settings modal with manual input, browse, and reset options
    - Integrate tauri-plugin-dialog for native directory picker
    - Support WSL and other special environments where config paths need manual specification
    
    Changes:
    - settings.rs: Implement settings load/save and directory override logic
    - SettingsModal: Add config directory override UI components
    - API: Add get_config_dir and pick_directory commands
  • - feat(codex): Add “Apply to VS Code/Remove from VS Code” button on current Codex provider card
    - feat(tauri): Add commands to read/write VS Code settings.json with cross-variant detection (Code/Insiders/VSCodium/OSS)
    - fix(vscode): Use top-level keys “chatgpt.apiBase” and “chatgpt.config.preferred_auth_method”
    - fix(vscode): Handle empty settings.json (skip deletes, direct write) to avoid “Can not delete in empty document”
    - fix(windows): Make atomic writes robust by removing target before rename
    - ui(provider-list): Improve error surfacing when applying/removing
    - chore(types): Extend window.api typings and tauri-api wrappers for VS Code commands
    - deps: Add jsonc-parser
  • feat: add TOML validation for Codex config and improve code formatting
    - Add real-time TOML syntax validation for Codex config field
    - Validate config TOML when saving provider settings
    - Format code to improve readability with proper error handling blocks
    - Reorganize imports for better consistency
    
    This ensures Codex config is valid TOML before saving, preventing runtime errors.
  • fix: improve JSON validation with unified validation function
    - Extract common validateJsonConfig function for reuse
    - Apply unified validation to both main config and common config snippets
    - Add real-time JSON validation to JsonEditor component using CodeMirror linter
    - Simplify error handling without over-engineering error position extraction
  • feat: add common config snippet management system
    - Add settings module for managing common configuration snippets
    - Implement UI for creating, editing, and deleting snippets
    - Add tauri-plugin-fs for file operations
    - Replace co-authored setting with flexible snippet system
    - Enable users to define custom config snippets for frequently used settings
  • feat(macos): handle dock icon click to restore window
    Add macOS-specific handling for app.run() to catch Reopen events when
    the dock icon is clicked, automatically unminimizing and showing the
    main window with focus.
  • feat(tray): hide window on close and refine tray UX; simplify icon handling
    - Intercept CloseRequested to hide instead of exit (keep tray resident)
    - Add 'Open Main' menu item; left-click shows menu; reduce tray click logs
    - Use default app icon for tray for now; remove runtime PNG decoding
    - Drop unused image dependency and tray resources entry
    - Prepare path for future macOS template icon under icons/tray/macos
  • feat(tray): hide window on close and refine tray UX
    - Intercept CloseRequested to prevent close and hide the window so the process and tray remain running
    - Add 'Open Main Window' item at the top of the tray menu and keep left-click to only show the menu (no auto window focus)
    - Downgrade tray left-click log from info to debug to reduce console noise in dev
    - Keep native behavior: the tray menu closes after selection; removed any transient title/tooltip feedback attempts
    
    Files:
    - src-tauri/src/lib.rs
  • fix(migration): ensure config directory exists before writing marker
    - Create parent directory before checking/writing migration marker
    - Prevents runtime error for fresh installations without config directory
    - Defensive fix for edge case where ~/.cc-switch/ doesn't exist yet
  • feat(providers): add provider categorization system
    - Add ProviderCategory type with official, cn_official, aggregator, third_party, and custom categories
    - Update Provider interface and Rust struct to include optional category field
    - Enhance ProviderForm to automatically sync category when selecting presets
    - Improve PresetSelector to show category-based styling and hints
    - Add category classification to all provider presets
    - Support differentiated interactions (e.g., hide API key input for official providers)
    - Maintain backward compatibility with existing configurations
  • refactor(settings): rename Dock setting to system tray (showInDock → showInTray)
    - compat: map legacy showInDock to showInTray when loading settings
    - ui(copy): clarify “system tray (menu bar)” vs Dock in SettingsModal
    - tauri(settings): return showInTray in get_settings; adjust default fallback
    - docs(comment): align comments to “system tray” terminology across code
    - note: no functional change yet; tray visibility toggle remains unimplemented
  • feat(updater): 集成 Rust 侧 Updater/Process 插件与权限配置
    - Cargo 依赖:tauri-plugin-updater、tauri-plugin-process
    - 插件注册:process 顶层 init,updater 于 setup 中注册
    - 权限配置:capabilities 增加 updater:default、process:allow-restart
    - 配置:tauri.conf.json 启用 createUpdaterArtifacts 与 updater 占位(pubkey/endpoints)
  • fix(settings): update version display and comment out incomplete dock settings
    - Fix version display to use actual app version (3.1.1) from Tauri API
    - Comment out dock display settings as feature is not yet implemented
    - Update GitHub releases URL from yungookim to farion1231
  • refactor(types): introduce Settings and apply in API
    - style(prettier): format src files
    - style(rustfmt): format Rust sources
    - refactor(tauri-api): type-safe getSettings/saveSettings
    - refactor(d.ts): declare window.api with Settings
    
    [skip ci]
  • feat: 系统托盘 (#12)
    * feat: 系统托盘
    
    1. 添加系统托盘
    2. 托盘添加切换供应商功能
    3. 整理组件目录
    
    * feat: 优化系统托盘菜单结构
    
    - 扁平化Claude和Codex的菜单结构,直接将所有供应商添加到主菜单,简化用户交互。
    - 添加无供应商时的提示信息,提升用户体验。
    - 更新分隔符文本以增强可读性。
    
    * feat: integrate Tailwind CSS and Lucide icons
    
    - Added Tailwind CSS for styling and layout improvements.
    - Integrated Lucide icons for enhanced UI elements.
    - Updated project structure by removing unused CSS files and components.
    - Refactored configuration files to support new styling and component structure.
    - Introduced new components for managing providers with improved UI interactions.   
    
    * fix: 修复类型声明和分隔符实现问题
    
    - 修复 updateTrayMenu 返回类型不一致(Promise<void> -> Promise<boolean>)
    - 添加缺失的 UnlistenFn 类型导入
    - 使用 MenuBuilder.separator() 替代文本分隔符
    
    ---------
    
    Co-authored-by: farion1231 <farion1231@gmail.c
  • refactor(codex): unify TOML handling with robust error recovery
    - Extract common TOML read/validation logic into dedicated helper functions
    - Add graceful degradation for corrupted config files during migration
    - Centralize Codex config.toml processing to ensure consistency across operations
    - Improve error handling: log warnings for invalid files but continue processing
    - Eliminate code duplication between migration, import, and runtime operations
    
    This makes the system more resilient to user configuration issues while maintaining data integrity through unified validation logic.
  • refactor(concurrency): optimize error handling and reduce lock contention
    - Fix operation order: write live files first, then save config.json for consistency
    - Implement short-lock pattern: read state quickly, release lock before I/O operations
    - Add atomic Codex dual-file writes with rollback on failure
    - Simplify add_provider and update_provider logic with consistent structure
    - Remove unnecessary duplicate code and improve error handling reliability
    
    This ensures data consistency when operations fail and significantly improves concurrency by minimizing lock holding time during file I/O.
  • refactor(archive): remove archive on provider switches/updates
    - Remove file archiving when switching providers or updating current provider
    - Keep archive functionality only for initial migration (one-time operation)
    - Retain simple .bak backup for config.json on each save
    - Simplify code by removing unnecessary archive operations from daily workflows
    
    This change prevents unlimited archive growth while maintaining data safety through:
    1. Initial migration archives for historical data preservation
    2. Single .bak file for basic rollback capability
    3. All provider configs stored in SSOT (config.json)
  • docs(cleanup): remove 'current' as special provider; align UI/messages and migration naming to 'default' and one-time import rule
    - App: update auto-import message to '默认供应商'
    - README: clarify default import only when providers are empty
    - Plan doc: replace 'current entry' wording with current pointer (manager.current)
    - Migration: name live-imported item 'default' instead of 'current'