Commit Graph

224 Commits

  • 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(codex): add requires_openai_auth flag to provider config template
    Add requires_openai_auth = true to the generated config.toml template
    for custom Codex providers to ensure proper authentication handling.
  • 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
  • refactor(mcp): improve UI consistency and i18n
    - Add MCP-specific green button style (buttonStyles.mcp)
    - Unify MCP panel and form buttons with emerald theme
    - Adjust MCP entry button width to match AppSwitcher (px-3)
    - Reduce JSON editor height from h-64 to h-48
    - Update translations: "Add/Edit Server" → "Add/Edit MCP"
    - Change form label to "MCP Title (Unique)" for clarity
    - Move config wizard button to right side of JSON label
    - Fix McpListItem enabled state check (explicit true check)
  • feat(mcp): show inline duplicate ID error and block submit in add mode
    - Display red hint next to title when ID exists
    
    - Disable Add/Save button and prevent submit on duplicate
    
    - Accept existing IDs via prop for real-time validation
    
    - Remove overwrite confirmation dialog on add
    
    - i18n: add duplicate-ID error strings and remove unused overwrite prompt
    
    - files:
    
      - src/components/mcp/McpFormModal.tsx
    
      - src/components/mcp/McpPanel.tsx
    
      - src/i18n/locales/en.json
    
      - src/i18n/locales/zh.json
  • fix(mcp): properly save and display description field
    - Initialize formDescription from initialData.description when editing
    - Save formDescription to server object before submitting
    - Display only description in list items, hide technical details
    - Show empty space when description is not available
  • refactor(mcp): optimize panel UI dimensions and simplify state
    - Reduce max width from 4xl (896px) to 3xl (768px)
    - Adjust max height from 90vh to 85vh with min-height 600px
    - Remove config path display, keep only server count
    - Remove McpStatus state, calculate count directly from servers
    - Simplify reload function by removing redundant status updates
  • chore(mcp): clear built-in MCP presets; keep logic intact
    - Remove sample presets from  while preserving seeding/display logic
    - Add inline notes for future preset/hidden strategy and per-client (claude/codex) split
    - Make preset seeding a no-op with empty list; no behavior change elsewhere
    - Verified
    > cc-switch@3.4.0 typecheck /Users/jasonyoung/Code/cc-switch
    > tsc --noEmit passes; UI reads/writes continue to work
  • 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
  • feat(mcp): inline presets in panel with one-click enable
    - Show not-installed MCP presets directly in the list, consistent with existing UI (no modal)
    - Toggle now supports enabling presets by writing to ~/.claude.json (mcpServers) and refreshing list
    - Keep installed MCP entries unchanged (edit/delete/toggle)
    
    fix(mcp): robust error handling and pre-submit validation
    
    - Use extractErrorMessage in MCP panel and form to surface backend details
    - Prevent pasting full config (with mcpServers) into single-server JSON field
    - Add required-field checks: stdio requires non-empty command; http requires non-empty url
    
    i18n: add messages for single-server validation and preset labels
    
    chore: add data-only MCP presets file (no new dependencies)
  • fix(mcp): improve error handling and notification visibility
    - Increase notification z-index to z-[80] to prevent overlay issues
    - Make MCP save operation async with proper error propagation
    - Display specific backend error messages in form validation
    - Ensure errors are visible in both form and panel layers
  • 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
  • feat(mcp): add configuration wizard and simplify form modal
    - Simplify McpFormModal to 3 inputs: title (required), description (optional), and JSON config (optional)
    - Add JSON validation similar to ProviderForm (must be object, real-time error display)
    - Create McpWizardModal component for quick configuration:
      - 5 input fields: type (stdio/sse), command (required), args, cwd, env
      - Real-time JSON preview
      - Emerald theme color (consistent with MCP button)
      - Z-index 70 (above McpFormModal's 60)
    - Add "or use configuration wizard" link next to JSON config label
    - Update i18n translations (zh/en) for form and wizard
    - All changes pass TypeScript typecheck and Prettier formatting
  • refactor(mcp): redesign MCP management panel UI
    - Redesign MCP panel to match main interface style
    - Add toggle switch for each MCP server to enable/disable
    - Use emerald theme color consistent with MCP button
    - Create card-based layout with one MCP per row
    - Add dedicated form modal for add/edit operations
    - Implement proper empty state with friendly prompts
    - Add comprehensive i18n support (zh/en)
    - Extend McpServer type to support enabled field
    - Backend already supports enabled field via serde_json::Value
    
    Components:
    - McpPanel: Main panel container with header and list
    - McpListItem: Card-based list item with toggle and actions
    - McpFormModal: Independent modal for add/edit forms
    - McpToggle: Emerald-themed toggle switch component
    
    All changes passed TypeScript type checking and production build.
  • 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
  • i18n: add translations for MCP UI (zh/en)
    - Add mcp.* keys for panel, actions, validation, messages
  • feat(mcp): implement MCP management panel (list, form, templates)
    - Add McpPanel with enable toggle, server list and add/edit form
    - Quick template: mcp-fetch (uvx mcp-server-fetch)
    - Command validation UI and open ~/.claude shortcut
    - Wire MCP button in App to open panel
  • feat(mcp): add front-end API wrappers and types
    - Add McpServer and McpStatus types
    - Add window.api wrappers for MCP commands
    - Extend vite-env.d.ts global typings for MCP APIs
  • 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
  • fix(frontend): align Tauri invoke param names to backend (snake_case)
    - pick_directory: pass `default_path` instead of `defaultPath` (src/lib/tauri-api.ts:156)
    - export_config_to_file/import_config_from_file: pass `file_path` instead of `filePath` (src/lib/tauri-api.ts:394, 408)
    - save_file_dialog: pass `default_name` instead of `defaultName` (src/lib/tauri-api.ts:418)
    
    - reason: Tauri commands match params by exact name; camelCase caused missing args and runtime failures in directory picker, import/export, and save dialog
    - verify: pnpm typecheck OK; cargo check OK; command signatures confirmed (pick_directory at src-tauri/src/commands.rs:584, export/import/save dialog at src-tauri/src/import_export.rs:84, 102, 140)
    - follow-ups: run `pnpm format`; consider Clippy cleanups; short-circuit same provider switch
  • fix: correct i18n key references in ProviderForm
    - Fix providerForm.websiteLabel -> providerForm.websiteUrl (line 1498)
    - Fix codexConfig namespace to providerForm for API key placeholders (lines 1681-1682)
      - codexConfig.codexOfficialNoApiKey -> providerForm.codexOfficialNoApiKey
      - codexConfig.codexApiKeyAutoFill -> providerForm.codexApiKeyAutoFill
    
    All i18n keys now properly reference existing locale definitions.
  • fix: custom endpoints not saved when creating new provider
    When creating a new provider, custom endpoints added in the speed test
    modal were not being saved properly. The issue was in ProviderForm.tsx
    where the CustomEndpoint object was constructed without the optional
    lastUsed field.
    
    This caused inconsistency between:
    - Edit mode: uses backend API (addCustomEndpoint) which correctly
      constructs complete CustomEndpoint objects
    - Create mode: directly constructs objects in frontend, missing the
      lastUsed field
    
    Fixed by explicitly setting lastUsed to undefined when constructing
    custom endpoints in create mode, ensuring structural consistency with
    the TypeScript CustomEndpoint interface.
  • refactor: replace 'Done' button with standard 'Save' button in endpoint speed test
    - Import Save icon from lucide-react
    - Replace endpointTest.done translation key with common.save for consistency
    - Add Save icon to button with flex layout matching other save buttons in the app
  • i18n: localize provider preset names and sorting logic
    - Replace hardcoded Chinese preset names with English versions (Claude Official, Zhipu GLM, Qwen Coder, ModelScope, Codex Official, KAT-Coder)
    - Update ProviderList sorting to use locale-aware comparison based on current language (zh-CN for Chinese, en-US for English)
    - Reorder presets: move KAT-Coder before PackyCode for better grouping
  • - i18n: complete remaining internationalization across the UI
    - Locales: add and align keys (common.enterValidValue, apiKeyInput.*, jsonEditor.*, claudeConfig.*); fix zh common.unknown mapping
    - ProviderForm: localize labels/placeholders/hints/errors; unify JSON/auth validation to providerForm.*; add wizard CTA for Codex custom with i18n; cancel uses common.cancel
    - CodexConfigEditor: i18n for quick wizard, labels/placeholders/hints, common config modal (title/help/buttons)
    - ClaudeConfigEditor: i18n for main label, common-config toggle/button, modal title/help, footer buttons
    - EndpointSpeedTest: localize failed/noEndpoints/done and aria labels
    - ApiKeyInput: i18n for placeholder and show/hide aria
    - JsonEditor: i18n linter messages
    - PresetSelector: remove hardcoded defaults, use i18n keys
    - UpdateBadge: i18n close aria
    - Build/typecheck: pass; scan shows no visible hardcoded Chinese strings outside locales
  • 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: update GLM provider model configuration (#90)
    - Update GLM-4.5 to GLM-4.6 as default Sonnet and Opus models
    - Use new model naming convention (glm-4.5-air, glm-4.6)
    - Align with latest GLM API model naming standards
  • fix: update layout for Claude app type provider display (#87)
    * feat: add .node-version file with Node.js version 22.4.1
    
    * fix: update layout for Claude app type provider display
  • fix: eliminate layout shift when switching app types with Claude plugin sync
    - Separate sync button containers for Codex and Claude modes
    - Only render the container in corresponding app type to prevent layout jumping
    - Apply same fix pattern as commit 0bcc04a for VS Code sync button
  • feat: add optional apiKeyUrl field to provider presets
    Allow third-party providers to specify a dedicated API key URL separate from the main website URL for easier key acquisition.
  • Update AI model versions in provider presets
    - Update DeepSeek model from V3.1-Terminus to V3.2-Exp
    - Update ModelScope model from GLM-4.5 to GLM-4.6
  • fix: eliminate layout shift when switching between Claude and Codex
    - Wrap VS Code sync button in fixed-width container to maintain stable layout
    - Only render the container in Codex mode to avoid unnecessary space in Claude mode
    - Change card transition from 'all' to specific properties (border-color, box-shadow) to prevent layout animations
    - These changes prevent the horizontal position jumping of provider cards during app switching
  • 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: integrate i18next for internationalization support (#65)
    * feat: integrate i18next for internationalization support
    
    - Added i18next and react-i18next dependencies for localization.
    - Updated various components to utilize translation functions for user-facing text.
    - Enhanced user experience by providing multilingual support across the application.
    
    * feat: improve i18n implementation with better translations and accessibility
    
    - Add proper i18n keys for language switcher tooltips and aria-labels
    - Replace hardcoded Chinese console error messages with i18n keys
    - Add missing translation keys for new UI elements
    - Improve accessibility with proper aria-label attributes
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • fix: remove unnecessary openai auth requirement from third-party config
    Remove the env_key and requires_openai_auth fields from third-party provider config generation as they are not needed for custom API endpoints.
  • feat: improve SettingsModal UX with scrolling and save icon
    - Add scrollable content area with max height constraint
    - Add Save icon to save button for better visual clarity
  • 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>
  • refactor: consolidate chatgpt.config cleanup logic
    Merged duplicate try-catch blocks that handle invalid chatgpt.config values.
    Now handles all edge cases (scalar values, arrays, empty objects) in a single
    unified check, reducing code duplication and improving performance by parsing
    JSON only once.