- Add gemini_mcp.rs module for Gemini MCP file I/O operations
- Implement sync_enabled_to_gemini to export enabled MCPs to ~/.gemini/settings.json
- Implement import_from_gemini to import MCPs from Gemini config
- Add Gemini sync logic in services/mcp.rs (upsert_server, delete_server, set_enabled)
- Register Tauri commands for Gemini MCP sync and import
- Update frontend API calls and McpPanel to support Gemini
Fixes the issue where adding MCP servers in Gemini tab would not sync to ~/.gemini/settings.json
Migrate the Claude common config snippet storage from browser localStorage
to the persistent config.json file for better cross-device sync and backup support.
**Backend Changes:**
- Add `claude_common_config_snippet` field to `MultiAppConfig` struct
- Add `get_claude_common_config_snippet` and `set_claude_common_config_snippet` Tauri commands
- Include JSON validation in the setter command
**Frontend Changes:**
- Create new `lib/api/config.ts` API module
- Refactor `useCommonConfigSnippet` hook to use config.json instead of localStorage
- Add automatic one-time migration from localStorage to config.json
- Add loading state during initialization
**Benefits:**
- Cross-device synchronization via backup/restore
- More reliable persistence than browser storage
- Centralized configuration management
- Seamless migration for existing users
* feat(prompts): add prompt management across Tauri service and React UI
- backend: add commands/prompt.rs, services/prompt.rs, register in commands/mod.rs and lib.rs, refine app_config.rs
- frontend: add PromptPanel, PromptFormModal, PromptListItem, MarkdownEditor, usePromptActions, integrate in App.tsx
- api: add src/lib/api/prompts.ts
- i18n: update src/i18n/locales/{en,zh}.json
- build: update package.json and pnpm-lock.yaml
* feat(i18n): improve i18n for prompts and Markdown editor
- update src/i18n/locales/{en,zh}.json keys and strings
- apply i18n in PromptFormModal, PromptPanel, and MarkdownEditor
- align prompt text with src-tauri/src/services/prompt.rs
* feat(prompts): add enable/disable toggle and simplify panel UI
- Add PromptToggle component and integrate in prompt list items
- Implement toggleEnabled with optimistic update; enable via API, disable via upsert with enabled=false;
reload after success
- Simplify PromptPanel: remove file import and current-file preview to keep CRUD flow focused
- Tweak header controls style (use mcp variant) and minor copy: rename “Prompt Management” to “Prompts”
- i18n: add disableSuccess/disableFailed messages
- Backend (Tauri): prevent duplicate backups when importing original prompt content
* style: unify code formatting with trailing commas
* feat(prompts): add Gemini filename support to PromptFormModal
Update filename mapping to use Record<AppId, string> pattern, supporting
GEMINI.md alongside CLAUDE.md and AGENTS.md.
* fix(prompts): sync enabled prompt to file when updating
When updating a prompt that is currently enabled, automatically sync
the updated content to the corresponding live file (CLAUDE.md/AGENTS.md/GEMINI.md).
This ensures the active prompt file always reflects the latest content
when editing enabled prompts.
Add independent credential fields for usage query to support different
query endpoints and authentication methods.
Changes:
- Add `apiKey` and `baseUrl` fields to UsageScript struct
- Remove dependency on provider config credentials in query_usage
- Update test_usage_script to accept independent credential parameters
- Add credential input fields in UsageScriptModal based on template:
* General: apiKey + baseUrl
* NewAPI: baseUrl + accessToken + userId
* Custom: no additional fields (full freedom)
- Auto-clear irrelevant fields when switching templates
- Add i18n text for "credentialsConfig"
Benefits:
- Query API can use different endpoint/key than provider config
- Better separation of concerns
- More flexible for various usage query scenarios
Fixed an issue where custom/extension fields (e.g., timeout_ms, retry_count)
were silently dropped when editing Codex MCP server configurations in TOML format.
Root cause: The TOML parser functions only extracted known fields (type, command,
args, env, cwd, url, headers), discarding any additional fields during normalization.
Changes:
- mcpServerToToml: Now uses spread operator to copy all fields before stringification
- normalizeServerConfig: Added logic to preserve unknown fields after processing known ones
- Both stdio and http server types now retain custom configuration fields
This fix enables forward compatibility with future MCP protocol extensions and
allows users to add custom configurations without code changes.
- Add src/lib/schemas/common.ts with jsonConfigSchema and tomlConfigSchema
- Enhance src/lib/schemas/mcp.ts to require command for stdio and url for http via superRefine
- Keep ProviderForm as-is; future steps will wire new schemas into RHF flows
- Verified: pnpm typecheck passes
- Split error message into title and description for better UX
- Add one-click copy button to easily share error details
- Extend toast duration to 6s for improved readability
- Use extractErrorMessage utility for consistent error handling
- Add i18n keys: common.copy, notifications.switchFailedTitle
This improves debugging experience when provider switching fails,
allowing users to quickly copy and share error messages.
Previously, if updateTrayMenu() failed after a successful main operation
(like sorting, adding, or updating providers), the entire operation would
appear to fail with a misleading error message, even though the core
functionality had already succeeded.
This resulted in false negative feedback where:
- Backend data was successfully updated
- Frontend UI was successfully refreshed
- Tray menu failed to update
- User saw "operation failed" message (incorrect)
Changes:
- Wrap updateTrayMenu() calls in nested try-catch blocks
- Log tray menu failures separately with descriptive messages
- Ensure main operation success is reported accurately
- Prevent tray menu failures from triggering main operation error handlers
Files modified:
- src/hooks/useDragSort.ts (drag-and-drop sorting)
- src/lib/query/mutations.ts (add/delete/switch mutations)
- src/hooks/useProviderActions.ts (update provider)
This fixes the bug introduced in PR #179 and prevents similar issues
across all provider operations.
- Add `refetchIntervalInBackground: true` to usage query configuration
- Allows usage queries to continue running when app window is minimized or unfocused
- Existing safety mechanisms remain in place (timeout limits, minimum interval, no retry)
- Users have full control through autoQueryInterval setting
Problem:
- User configured 5-minute auto-query interval
- Actual queries executed every 10 minutes instead of 5
Root Cause:
- staleTime (5 min) conflicted with refetchInterval (5 min)
- React Query skipped refetch when data was still within staleTime
- First interval trigger at T+5min: data considered "fresh", skipped
- Second interval trigger at T+10min: data "stale", executed
Solution:
- Set staleTime to 0 for usage queries
- Ensures refetchInterval executes precisely as configured
- Auto-query is meant to fetch fresh data periodically, not use cache
Technical Details:
- Modified useUsageQuery in src/lib/query/queries.ts
- Changed: staleTime: 5 * 60 * 1000 → staleTime: 0
- Added explanatory comment in Chinese
- Manual queries still work via refetch() button
Breaking Changes:
- Removed useAutoUsageQuery hook (119 lines)
- Unified all usage queries into single useUsageQuery hook
Technical Improvements:
- Eliminated duplicate state management (React Query + manual useState)
- Fixed single source of truth principle violation
- Replaced manual setInterval with React Query's built-in refetchInterval
- Reduced UsageFooter complexity by 28% (54 → 39 lines)
New Features:
- useUsageQuery now accepts autoQueryInterval option
- Automatic query interval control (0 = disabled, min 1 minute)
- Built-in lastQueriedAt timestamp from dataUpdatedAt
- Auto-query only enabled for currently active provider
Architecture Benefits:
- Single data source: manual and auto queries share same cache
- No more state inconsistency between manual/auto query results
- Leverages React Query's caching, deduplication, and background updates
- Cleaner separation of concerns
Code Changes:
- src/lib/query/queries.ts: Enhanced useUsageQuery with auto-query support
- src/components/UsageFooter.tsx: Simplified to use single query hook
- src/hooks/useAutoUsageQuery.ts: Deleted (redundant)
- All type checks passed
- Add private helper method `execute_and_format_usage_result` to eliminate code duplication
- Refactor `query_usage` to use helper method instead of duplicating result processing
- Add new `test_usage_script` method to test temporary script without saving
- Add backend command `test_usage_script` accepting script content as parameter
- Register new command in lib.rs invoke_handler
- Add frontend `usageApi.testScript` method to call the new backend API
- Update `UsageScriptModal.handleTest` to test current editor content instead of saved script
- Improve DX: users can now test script changes before saving
This commit addresses parameter naming inconsistencies caused by Tauri v2's
requirement for camelCase parameter names in IPC commands.
Backend changes (Rust):
- Updated all command parameters from snake_case to camelCase
- Commands affected:
* provider.rs: providerId (×4), timeoutSecs
* import_export.rs: filePath (×2), defaultName
* config.rs: defaultPath
- Added #[allow(non_snake_case)] attributes for camelCase parameters
- Removed unused QueryUsageParams struct
Frontend changes (TypeScript):
- Removed redundant snake_case parameters from all invoke() calls
- Updated API files:
* usage.ts: removed debug logs, unified to providerId
* vscode.ts: updated 8 functions (providerId, timeoutSecs, filePath, defaultName)
* settings.ts: updated 4 functions (defaultPath, filePath, defaultName)
- Ensured all parameters now use camelCase exclusively
Test updates:
- Updated MSW handlers to accept both old and new parameter formats during transition
- Added i18n mock compatibility for tests
Root cause:
The issue stemmed from Tauri v2 strictly requiring camelCase for command
parameters, while the codebase was using snake_case. This caused parameters
like 'provider_id' to not be recognized by the backend, resulting in
"missing providerId parameter" errors.
BREAKING CHANGE: All Tauri command invocations now require camelCase parameters.
Any external tools or scripts calling these commands must be updated accordingly.
Fixes: Usage query always failing with "missing providerId" error
Fixes: Custom endpoint management not receiving provider ID
Fixes: Import/export dialogs not respecting default paths
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`.
Replace the previous dual-parameter approach (app_type/app/appType) with a single required `app: String` parameter across all Tauri commands. This change:
- Introduces unified `parse_app()` helper replacing complex `resolve_app_type()` logic
- Updates all backend commands in config, mcp, and provider modules
- Aligns frontend API calls to use consistent `app` parameter naming
- Simplifies MSW test handlers by removing optional parameter handling
This improves API clarity and reduces parameter ambiguity while maintaining backward compatibility through error handling.
Add `resolve_app_type` helper to support both enum and string-based app type
parameters across all provider commands. This change:
- Eliminates implicit default to Claude (previously used `unwrap_or`)
- Supports two parameter forms: `app_type` (enum, priority 1) and `app` (string, priority 2)
- Provides explicit error handling when both parameters are missing
- Updates all 14 provider command functions with consistent parameter validation
- Fixes tray menu provider switching to pass the new `app` parameter
This dual-parameter approach maintains backward compatibility while enabling
future CLI tool integration and more flexible API usage patterns.
Technical details:
- Priority order: `app_type` enum > `app` string > error
- Invalid `app` strings now return errors instead of defaulting
- All existing tests pass (45/45)
Core Improvements:
- Add sync_current_providers_live command to synchronize in-memory provider
settings to corresponding live files (~/.claude/settings.json or ~/.codex/auth.json)
- Introduce partial-success state to distinguish between 'import succeeded
but sync failed' scenario, providing clear user feedback
- Remove unused skip_live_backfill parameter from switch_provider command
- Separate responsibilities: backend handles import/backup, frontend handles
sync/error presentation
Technical Details:
- Codex: sync auth.json + config.toml with MCP configuration
- Claude: sync settings.json
- Bidirectional sync: read back after write to update in-memory settings_config
- Full i18n support (English and Chinese)
- Graceful handling when no current provider is active
Affected Files:
- Backend: import_export.rs, commands.rs, lib.rs
- Frontend: useImportExport.ts, ImportExportSection.tsx, settings.ts
- i18n: en.json, zh.json
This ensures SSOT (Single Source of Truth) consistency between config.json
and live configuration files after import operations.
- Delete src/lib/tauri-api.ts as event listener has been migrated
- Event listening now uses providersApi.onSwitched from lib/api/providers.ts
- All references to tauriEvents have been removed
- Type checking passes successfully
This completes the API layer cleanup from the refactoring plan (Phase 4).
Fixed dual-source jitter issue:
1. Horizontal shift: Use overflow-y-scroll to force scrollbar gutter
2. Vertical jump: Use keepPreviousData to maintain content during app switch
- Remove unused useDarkMode hook (now using shadcn theme-provider)
- Clean up MCP components (remove redundant code)
- Add restart API to settings
- Minor type improvements
* feat(ui): add drag-and-drop sorting for provider list
Implement drag-and-drop functionality to allow users to reorder providers with custom sort indices.
Features:
- Install @dnd-kit libraries for drag-and-drop support
- Add sortIndex field to Provider type (frontend & backend)
- Implement SortableProviderItem component with drag handle
- Add update_providers_sort_order Tauri command
- Sync tray menu order with provider list sorting
- Add i18n support for drag-related UI text
Technical details:
- Use @dnd-kit/core and @dnd-kit/sortable for smooth drag interactions
- Disable animations for immediate response after drop
- Update tray menu immediately after reordering
- Sort priority: sortIndex → createdAt → name
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ui): remove unused transition variable in ProviderList
Remove unused 'transition' destructured variable from useSortable hook
to fix TypeScript error TS6133. The transition property is hardcoded
as 'none' in the style object to prevent conflicts with drag operations.
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add provider usage query functionality
- Updated `Cargo.toml` to include `regex` and `rquickjs` dependencies for usage script execution.
- Implemented `query_provider_usage` command in `commands.rs` to handle usage queries.
- Created `UsageScript` and `UsageData` structs in `provider.rs` for managing usage script configurations and results.
- Added `execute_usage_script` function in `usage_script.rs` to run user-defined scripts for querying usage.
- Enhanced `ProviderList` component to include a button for configuring usage scripts and a modal for editing scripts.
- Introduced `UsageFooter` component to display usage information and status.
- Added `UsageScriptModal` for editing and testing usage scripts with preset templates.
- Updated Tauri API to support querying provider usage.
- Modified types in `types.ts` to include structures for usage scripts and results.
* feat(usage): support multi-plan usage display for providers
- 【Feature】
- Update `UsageResult` to support an array of `UsageData` for displaying multiple usage plans per provider.
- Refactor `query_provider_usage` command to parse both single `UsageData` objects (for backward compatibility) and arrays of `UsageData`.
- Enhance `usage_script` validation to accept either a single usage object or an array of usage objects.
- 【Frontend】
- Redesign `UsageFooter` to iterate and display details for all available usage plans, introducing `UsagePlanItem` for individual plan rendering.
- Improve usage display with color-coded remaining balance and clear plan information.
- Update `UsageScriptModal` test notification to summarize all returned plans.
- Remove redundant `isCurrent` prop from `UsageFooter` in `ProviderList`.
- 【Build】
- Change frontend development server port from `3000` to `3005` in `tauri.conf.json` and `vite.config.mts`.
* feat(usage): enhance query flexibility and display
- 【`src/types.ts`, `src-tauri/src/provider.rs`】Make `UsageData` fields optional and introduce `extra` and `invalidMessage` for more flexible reporting.
- `expiresAt` replaced by generic `extra` field.
- `isValid`, `remaining`, `unit` are now optional.
- Added `invalidMessage` to provide specific reasons for invalid status.
- 【`src-tauri/src/usage_script.rs`】Relax usage script result validation to accommodate optional fields in `UsageData`.
- 【`src/components/UsageFooter.tsx`】Update UI to display `extra` field and `invalidMessage`, and conditionally render `remaining` and `unit` based on availability.
- 【`src/components/UsageScriptModal.tsx`】
- Add a new `NewAPI` preset template demonstrating advanced extractor logic for complex API responses.
- Update script instructions to reflect optional fields and new variable syntax (`{{apiKey}}`).
- Remove old "DeepSeek" and "OpenAI" templates.
- Remove basic syntax check for `return` statement.
- 【`.vscode/settings.json`】Add `dish-ai-commit.base.language` setting.
- 【`src-tauri/src/commands.rs`】Adjust usage logging to handle optional `remaining` and `unit` fields.
* chore(config): remove VS Code settings from version control
- delete .vscode/settings.json to remove editor-specific configurations
- add /.vscode to .gitignore to prevent tracking of local VS Code settings
- ensure personalized editor preferences are not committed to the repository
* fix(provider): preserve usage script during provider update
- When updating a provider, the `usage_script` configuration within `ProviderMeta` was not explicitly merged.
- This could lead to the accidental loss of `usage_script` settings if the incoming `provider` object in the update request did not contain this field.
- Ensure `usage_script` is cloned from the existing provider's meta when merging `ProviderMeta` during an update.
* refactor(provider): enforce base_url for usage scripts and update dev ports
- 【Backend】
- `src-tauri/src/commands.rs`: Made `ANTHROPIC_BASE_URL` a required field for Claude providers and `base_url` a required field in `config.toml` for Codex providers when extracting credentials for usage script execution. This improves error handling by explicitly failing if these critical URLs are missing or malformed.
- 【Frontend】
- `src/App.tsx`, `src/components/ProviderList.tsx`: Passed `appType` prop to `ProviderList` component to ensure `updateProvider` calls within `handleSaveUsageScript` correctly identify the application type.
- 【Config】
- `src-tauri/tauri.conf.json`, `vite.config.mts`: Updated development server ports from `3005` to `3000` to standardize local development environment.
* refactor(usage): improve usage data fetching logic
- Prevent redundant API calls by tracking last fetched parameters in `useEffect`.
- Avoid concurrent API requests by adding a guard in `fetchUsage`.
- Clear usage data and last fetch parameters when usage query is disabled.
- Add `queryProviderUsage` API declaration to `window.api` interface.
* fix(usage-script): ensure usage script updates and improve reactivity
- correctly update `usage_script` from new provider meta during updates
- replace full page reload with targeted provider data refresh after saving usage script settings
- trigger usage data fetch or clear when `usageEnabled` status changes in `UsageFooter`
- reduce logging verbosity for usage script execution in backend commands and script execution
* style(usage-footer): adjust usage plan item layout
- Decrease width of extra field column from 35% to 30%
- Increase width of usage information column from 40% to 45%
- Improve visual balance and readability of usage plan items
- Add syncOtherSide parameter to upsert_mcp_server_in_config command
- Implement checkbox UI in McpFormModal for cross-app sync
- Automatically sync enabled MCP servers to both Claude and Codex when option is checked
- Add i18n support for sync option labels and hints
- 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
- 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.
- 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
- 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
- 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)
- 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
- 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
- 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.
- 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: 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>