Commit Graph

9 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(-)
  • 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: add partner promotion feature for Zhipu GLM
    - Add isPartner and partnerPromotionKey fields to Provider and ProviderPreset types
    - Display gold star badge on partner presets in selector
    - Show promotional message in API Key section for partners
    - Configure Zhipu GLM as official partner with 10% discount promotion
    - Support both Claude and Codex provider presets
    - Add i18n support for partner promotion messages (zh/en)
  • refactor(endpoints): implement deferred submission and fix clear-all bug
    Implement Solution A (complete deferred submission) for custom endpoint
    management, replacing the dual-mode system with unified local staging.
    
    Changes:
    - Remove immediate backend saves from EndpointSpeedTest
      * handleAddEndpoint: local state update only
      * handleRemoveEndpoint: local state update only
      * handleSelect: remove lastUsed timestamp update
    - Add explicit clear detection in ProviderForm
      * Distinguish "user cleared endpoints" from "user didn't modify"
      * Pass empty object {} as clear signal vs null for no-change
    - Fix mergeProviderMeta to handle three distinct cases:
      * null/undefined: don't modify endpoints (no meta sent)
      * empty object {}: explicitly clear endpoints (send empty meta)
      * with data: add/update endpoints (overwrite)
    
    Fixed Critical Bug:
    When users deleted all custom endpoints, changes were not saved because:
    - draftCustomEndpoints=[] resulted in customEndpointsToSave=null
    - mergeProviderMeta(meta, null) returned undefined
    - Backend interpreted missing meta as "don't modify", preserving old values
    
    Solution:
    Detect when user had endpoints and cleared them (hadEndpoints && length===0),
    then pass empty object to mergeProviderMeta as explicit clear signal.
    
    Architecture Improvements:
    - Transaction atomicity: all fields submitted together on form save
    - UX consistency: add/edit modes behave identically
    - Cancel button: true rollback with no immediate saves
    - Code simplification: removed ~40 lines of immediate save error handling
    
    Testing:
    - TypeScript type check: passed
    - Rust backend tests: 10/10 passed
    - Build: successful
  • refactor(types): rename AppType to AppId for semantic clarity
    Rename `AppType` to `AppId` across the entire frontend codebase to better
    reflect its purpose as an application identifier rather than a type category.
    This aligns frontend naming with backend command parameter conventions.
    
    Changes:
    - Rename type `AppType` to `AppId` in src/lib/api/types.ts
    - Remove `AppType` export from src/lib/api/index.ts
    - Update all component props from `appType` to `appId` (43 files)
    - Update all variable names from `appType` to `appId`
    - Synchronize documentation (CHANGELOG, refactoring plans)
    - Update test files and MSW mocks
    
    BREAKING CHANGE: `AppType` type is no longer exported. Use `AppId` instead.
    All component props have been renamed from `appType` to `appId`.
  • i18n: complete internationalization for provider and usage query panels
    - Add 45+ new translation keys for usage query and usage script features
    - Fix duplicate provider object in translation files that caused missing translations
    - Remove all hardcoded Chinese text and defaultValue fallbacks from components
    - Add proper translations for:
      * Usage footer (query status, plan usage display)
      * Usage script modal (script editor, validation, test controls)
      * Provider forms (basic fields, endpoints, model selectors)
      * Provider dialogs (add/edit hints and titles)
    
    Modified 16 files:
    - 2 translation files (zh.json, en.json)
    - 14 component files (removed defaultValue, added t() calls)
    
    All UI text now properly supports Chinese/English switching.
  • refactor: unify directory structure and extract shared components
    - Migrate all form components from ProviderForm/ to providers/forms/
    - Create shared components to eliminate code duplication:
      * ApiKeySection: unified API key input with "Get API Key" link
      * EndpointField: unified endpoint URL input with manage button
    - Refactor ClaudeFormFields (-31% lines) and CodexFormFields (-33% lines)
    - Update all import paths to use new locations
    - Reduce code duplication from ~12% to ~7%
    
    This change improves maintainability and makes the codebase more DRY.
  • feat: add useSpeedTestEndpoints hook to collect all endpoint candidates for speed test modal
    - Create useSpeedTestEndpoints hook that collects endpoints from:
      1. Current baseUrl/codexBaseUrl
      2. Initial data URL (edit mode)
      3. Preset's endpointCandidates array
    - Pass speedTestEndpoints to ClaudeFormFields and CodexFormFields
    - Update EndpointSpeedTest to use collected endpoints instead of just current URL
    - Fix PackyCode preset endpoints not appearing in speed test modal
  • refactor: split ProviderForm into smaller focused components
    - Created ProviderPresetSelector component (80 lines)
    - Created BasicFormFields component (60 lines)
    - Created ClaudeFormFields component (272 lines)
    - Created CodexFormFields component (131 lines)
    - Reduced ProviderForm from 866 to 544 lines (37% reduction)
    
    Each component now has a clear single responsibility:
    - ProviderPresetSelector: Handles preset selection UI
    - BasicFormFields: Name and website URL inputs
    - ClaudeFormFields: All Claude-specific form fields
    - CodexFormFields: All Codex-specific form fields
    - ProviderForm: Orchestrates hooks and component composition
    
    Benefits:
    - Better code organization and maintainability
    - Easier to test individual components
    - Clearer separation of concerns
    - More reusable components