Commit Graph

23 Commits

  • 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(-)
  • 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>
  • fix(toml): normalize CJK quotes to prevent parsing errors
    Add quote normalization to handle Chinese/fullwidth quotes automatically
    converted by IME. This fixes TOML parsing failures when users input
    configuration with non-ASCII quotes (" " ' ' etc.).
    
    Changes:
    - Add textNormalization utility for quote normalization
    - Apply normalization in TOML input handlers (MCP form, Codex config)
    - Disable browser auto-correction in Textarea component
    - Add defensive normalization in TOML parsing layer
  • refine(usage): enhance query robustness and error handling
    Backend improvements:
    - Add InvalidHttpMethod error enum for better error semantics
    - Clamp HTTP timeout to 2-30s to prevent config abuse
    - Strict HTTP method validation instead of silent fallback to GET
    
    Frontend improvements:
    - Add i18n support for usage query errors (en/zh)
    - Improve error handling with type-safe unknown instead of any
    - Optimize i18n import (direct import instead of dynamic)
    - Disable auto-retry for usage queries to avoid API stampede
    
    Additional changes:
    - Apply prettier formatting to affected files
    
    Files changed:
    - src-tauri/src/error.rs (+2)
    - src-tauri/src/usage_script.rs (+8 -2)
    - src/i18n/locales/{en,zh}.json (+4 -1 each)
    - src/lib/api/usage.ts (+21 -4)
    - src/lib/query/queries.ts (+1)
    - style: prettier formatting on 6 other files
  • feat: support ANTHROPIC_API_KEY field and add AiHubMix provider
    Add compatibility for providers that use ANTHROPIC_API_KEY instead of
    ANTHROPIC_AUTH_TOKEN, enabling support for AiHubMix and similar services.
    
    Changes:
    - Backend: Add fallback to ANTHROPIC_API_KEY in credential extraction
      - migration.rs: Support API_KEY during config migration
      - services/provider.rs: Extract credentials from either field
    - Frontend: Smart API key field detection and management
      - getApiKeyFromConfig: Read from either field (AUTH_TOKEN priority)
      - setApiKeyInConfig: Write to existing field, preserve user choice
      - hasApiKeyField: Detect presence of either field
    - Add AiHubMix provider preset with dual endpoint candidates
    - Define apiKeyField metadata for provider presets (documentation)
    
    Technical Details:
    - Uses or_else() for zero-cost field fallback in Rust
    - Runtime field detection ensures correct field name preservation
    - Maintains backward compatibility with existing configurations
    - Priority: ANTHROPIC_AUTH_TOKEN > ANTHROPIC_API_KEY
  • refactor(config): rename providerPresets to claudeProviderPresets
    - Rename src/config/providerPresets.ts to claudeProviderPresets.ts
    - Update all import statements across 11 files to reflect the new name
    - Establish symmetrical naming convention with codexProviderPresets.ts
    - Improve code clarity and maintainability
  • 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: 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>
  • - refactor(utils): extract Codex base_url parsing into shared helpers
    - refactor(ProviderList): use shared base_url helpers
    - refactor(App): reuse shared base_url helpers for VS Code sync
    - fix(auto-sync): global shared VS Code auto-apply state (localStorage + event broadcast)
    - feat(tray): auto-apply to VS Code on Codex provider-switched when enabled
    - behavior: manual Apply enables auto-sync; manual Remove disables; official providers clear managed keys only
    - chore(typecheck): pass pnpm typecheck
  • refactor: simplify TOML common config handling by removing markers
    - Remove COMMON_CONFIG_MARKER_START/END constants
    - Simplify config snippet addition/removal logic
    - Use natural append/replace approach instead of markers
    - Fix unused variable warning
    - Improve user experience with cleaner config output
  • fix: improve VS Code config synchronization and code formatting
    - Add automatic VS Code config sync when base_url changes in TOML
    - Improve error handling for VS Code configuration writes
    - Enhance state management with ref tracking to prevent duplicate API calls
    - Fix code formatting issues and improve readability across components
    - Optimize common configuration handling for both Claude and Codex providers
  • 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 support for Codex with TOML format
    - Added separate common config state and storage for Codex
    - Implemented TOML-based common config merging with markers
    - Created UI components for Codex common config editor
    - Added toggle and edit functionality similar to Claude config
    - Store Codex common config in localStorage separately
    - Support appending/removing common TOML snippets to config.toml
  • refactor: replace co-authored setting with flexible common config snippet feature
    - Replace single "disable co-authored" checkbox with universal "common config snippet" functionality
    - Add localStorage persistence for common config snippets
    - Implement deep merge/remove operations for complex JSON structures
    - Add modal editor for managing common config snippets
    - Optimize performance with custom deepClone function instead of JSON.parse/stringify
    - Fix deep remove logic to only delete matching values
    - Improve error handling and validation for JSON snippets
  • feat: refactor ProviderForm component with new subcomponents (#13)
    * feat: refactor ProviderForm component with new subcomponents
    
    - Introduced PresetSelector, ApiKeyInput, ClaudeConfigEditor, and CodexConfigEditor for improved modularity and readability.
    - Simplified preset selection logic for both Claude and Codex configurations.
    - Enhanced API Key input handling with dedicated components for better user experience.
    - Removed redundant code and improved state management in the ProviderForm component.
    
    * feat: add Kimi model selection to ProviderForm component
    
    - Introduced KimiModelSelector for enhanced model configuration options.
    - Implemented state management for Kimi model selection, including initialization and updates based on preset selection.
    - Improved user experience by conditionally displaying the Kimi model selector based on the selected preset.
    - Refactored related logic to ensure proper handling of Kimi-specific settings in the ProviderForm.
    
    * feat: enhance API Key input and model selection in ProviderForm
    
    - Added toggle functionality to show/hide API Key in ApiKeyInput component for improved user experience.
    - Updated placeholder text in ProviderForm to provide clearer instructions based on the selected preset.
    - Enhanced KimiModelSelector to display a more informative message when API Key is not provided.
    - Refactored provider presets to remove hardcoded API Key values for better security practices.
    
    * fix(kimi): optimize debounce implementation in model selector
    
    - Fix initial state: use empty string instead of apiKey.trim()
    - Refactor fetchModels to fetchModelsWithKey with explicit key parameter
    - Ensure consistent behavior between auto-fetch and manual refresh
    - Eliminate mental overhead from optional parameter fallback logic
    
    * fix(api-key): remove custom masking logic, use native password input
    
    - Remove getDisplayValue function with custom star masking
    - Use native browser password input behavior for better UX consistency
    - Simplify component logic while maintaining show/hide toggle functionality
    
    * chore: format code with prettier
    
    - Apply consistent code formatting across all TypeScript files
    - Fix indentation and spacing according to project style guide
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • feat: JsonEditor for inputting JSON content (#4)
    * feat(editor): add JsonEditor component for JSON configuration editing
    
    * fix(provider): update API Key visibility logic in ProviderForm component
    
    * fix(editor): stabilize JsonEditor height and restore API Key logic
    
    - Revert API Key visibility to preset-based rule and injection to non-custom preset only.
    - Reduce JsonEditor min-height from rows*22px to rows*18px to lessen layout jitter when switching presets.
    - Keep fonts/size consistent with the previous textarea for visual parity.
    
    * - fix(form): remove websiteUrl auto-extraction from JSON to prevent incorrect overrides
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • chore: format code and fix bundle identifier for v3.0.0 release
    - Format all TypeScript/React code with Prettier
    - Format all Rust code with cargo fmt
    - Fix bundle identifier from .app to .desktop to avoid macOS conflicts
    - Prepare codebase for v3.0.0 Tauri release
  • - feat(form): Support API Key ⇄ JSON two-way binding in edit modal
    - feat(utils): Add helpers to read/write/detect API Key in config
    - refactor(form): Reuse unified linking logic for preset and edit flows
    - chore: Preserve website URL extraction and signature-disable behaviors
    - build: Verify renderer build locally
  • refactor: 清理 Electron 遗留代码并优化项目结构
    - 删除 Electron 主进程代码 (src/main/)
    - 删除构建产物文件夹 (build/, dist/, release/)
    - 清理 package.json 中的 Electron 依赖和脚本
    - 删除 TypeScript 配置中的 Electron 相关文件
    - 优化前端代码结构至 Tauri 标准结构 (src/renderer → src/)
    - 删除移动端图标和不必要文件
    - 更新文档说明技术栈变更为 Tauri