Commit Graph

400 Commits

Author SHA1 Message Date
Jason 8e6fad7af2 fix(windows): correct window title and remove extra titlebar spacing
- Add missing "title" field to tauri.windows.conf.json to display
  "CC Switch" instead of default "Tauri app"
- Make DRAG_BAR_HEIGHT platform-aware: 0px on Windows/Linux (native
  titlebar), 28px on macOS (Overlay mode needs traffic light space)
- Apply same fix to FullScreenPanel component for consistency

Fixes the issue where Windows showed wrong title and had ~28px extra
blank space below the native titlebar introduced in v3.9.0.
2026-01-09 19:45:36 +08:00
Jason Young a268127f1f Fix/Resolve panic issues in proxy-related code (#560)
* fix(proxy): change default port from 5000 to 15721

Port 5000 conflicts with AirPlay Receiver on macOS 12+.
Also adds error handling for proxy toggle and i18n placeholder updates.

* fix(proxy): replace unwrap/expect with graceful error handling

- Handle HTTP client initialization failure with no_proxy fallback
- Fix potential panic on Unicode slicing in API key preview
- Add proper error handling for response body builder
- Handle edge case where SystemTime is before UNIX_EPOCH

* fix(proxy): handle UTF-8 char boundary when truncating request body log

Rust strings are UTF-8 encoded, slicing at a fixed byte index may cut
in the middle of a multi-byte character (e.g., Chinese, emoji), causing
a panic. Use is_char_boundary() to find the nearest safe cut point.

* fix(proxy): improve robustness and prevent panics

- Add reqwest socks feature to support SOCKS proxy environments
- Fix UTF-8 safety in masked_key/masked_access_token (use chars() instead of byte slicing)
- Fix UTF-8 boundary check in usage_script HTTP response truncation
- Add defensive checks for JSON operations in proxy service
- Remove verbose debug logs that could trigger panic-prone code paths
2026-01-09 13:09:19 +08:00
Jason 2c4c2ce83d fix(settings): navigate to About tab when clicking update badge
- Add defaultTab prop to SettingsPage for external tab control
- UpdateBadge click now opens settings directly to About tab
- Settings button still opens to General tab (default behavior)
- Change update badge text from version number to "Update available"
2026-01-06 11:27:32 +08:00
Jason 0020889a8f fix(prompts): allow saving prompts with empty content
Remove content validation requirement to allow users to save prompts
with empty content for placeholder or draft purposes.
2026-01-05 23:30:03 +08:00
Jason efa653809b style: format code with Prettier 2026-01-05 21:53:01 +08:00
Jason 4777c99b38 refactor(settings): reorder advanced tab items for better UX
Move Auto Failover section directly after Proxy section since they are
functionally related (failover depends on proxy service).
2026-01-05 16:35:36 +08:00
duskzhen 8912216cb2 fix(common): improve window dragging area in FullScreenPanel (#525)
Add data-tauri-drag-region and WebkitAppRegion styles to header area to match	App.tsx behavior, ensuring proper window dragging on macOS.
2026-01-05 16:25:38 +08:00
Jason 37396b9c70 fix(common-config): reset initialization flag when preset changes
The common config checkbox was only auto-enabled for the first preset
(custom) because hasInitializedNewMode ref was permanently locked to
true after first initialization.

Add selectedPresetId parameter to all three common config hooks and
reset the initialization flag when preset changes, allowing the
initialization logic to re-run for each preset switch.
2026-01-04 12:27:22 +08:00
Jason 63bb673bf2 refactor(common-config): extract snippet from editor content instead of active provider
- Change extraction source from current active provider to editor's live content
- Add i18n support for JSON parse error messages via invalid_json_format_error()
- Simplify API by removing unused providerId parameter
- Update button labels and error messages in zh/en/ja locales
2026-01-04 12:27:22 +08:00
Jason 188c94f2e3 feat(common-config): add extract from current provider functionality
- Add backend command to extract common config snippet from current provider
- Automatically extract common config on first run after importing default provider
- Auto-enable common config checkbox in new provider mode when snippet exists
- Refactor Gemini common config to operate on .env instead of config.json
- Add "Extract from Current" button to all three common config modals
- Update i18n translations for new extraction feature
2026-01-04 12:27:22 +08:00
Jason 2105f2d05b fix(i18n): remove hardcoded defaultValue and unused placeholder for reasoning model 2026-01-03 12:04:34 +08:00
Jason 0e085aa01a fix(prompts): change toggle color from blue to emerald
Align with the app-wide Switch component color scheme for
visual consistency across all toggle elements.
2026-01-03 10:15:28 +08:00
Jason 86e802bd4b feat(mcp): add import button to import MCP servers from apps
- Add import_mcp_from_apps command that reuses existing import logic
- Add Import button in MCP panel header (consistent with Skills)
- Fix import count to only return truly new servers (not already in DB)
- Update translations for import success/no-import messages (zh/en/ja)
2026-01-03 10:04:46 +08:00
Jason 6460c1d5dd fix(skills): move import button to header for better discoverability
- Add import button next to discover button in skills page header
- Expose openImport method via UnifiedSkillsPanel ref
- Show toast instead of dialog when no unmanaged skills found
- Remove redundant buttons from empty state view
2026-01-03 09:21:15 +08:00
Jason 6b73e55bfe fix(ui): remove hover scale effect from skill cards
The hover:scale-[1.01] effect caused cards to overflow their container
boundaries. Keeping only hover:shadow-lg provides sufficient visual
feedback without the overflow issue.
2026-01-02 23:57:22 +08:00
Jason 47aa4c6bee fix(skills): show loading indicator when refreshing discovery list
Use isFetching instead of just isLoading to show the loading spinner.
isLoading is only true on initial load, while isFetching is true
during any fetch operation including refetch.
2026-01-02 23:51:03 +08:00
Jason e69c1bd8aa fix(ui): align FullScreenPanel header with App.tsx layout
- Use same DRAG_BAR_HEIGHT (28px) and HEADER_HEIGHT (64px) as App.tsx
- Remove border-b divider line from header
- Add rounded-lg class to back button for consistency
2026-01-02 22:35:33 +08:00
Jason a17fa8098b fix(skills): remove redundant navigation buttons in skills pages
- Remove duplicate "Repo Manager" button from installed skills view
  (should only appear in discovery view)
- Remove redundant back button from SkillsPage component
  (header already provides unified navigation)
- Clean up unused openRepoManagerOnDiscovery state and related useEffect
- Remove unused onClose prop and ArrowLeft import from SkillsPage
2026-01-02 22:33:33 +08:00
Jason ff03ca1e63 feat(skills): unified management architecture with SSOT and React Query
- Introduce SSOT (Single Source of Truth) at ~/.cc-switch/skills/
- Add three-app toggle support (Claude/Codex/Gemini) for each skill
- Refactor frontend to use TanStack Query hooks instead of manual state
- Add UnifiedSkillsPanel for managing installed skills with app toggles
- Add useSkills.ts with declarative data fetching hooks
- Extend skills.ts API with unified install/uninstall/toggle methods
- Support importing unmanaged skills from app directories
- Add v2→v3 database migration for new skills table structure
2026-01-02 22:04:02 +08:00
Jason cce6ae86a5 fix: prevent env check card border overflow on hover
Add horizontal padding to the grid container to accommodate the scale
transform effect when hovering over environment check cards.
2025-12-31 22:58:03 +08:00
Dex Miller 5376ea042b Feat/usage improvements (#508)
* i18n: update cache terminology across all languages

- Change 'Cache Read' to 'Cache Hit' in all languages
- Change 'Cache Write' to 'Cache Creation' in all languages
- Update zh: 缓存读取 → 缓存命中, 缓存写入 → 缓存创建
- Update en: Cache Read → Cache Hit, Cache Write → Cache Creation
- Update ja: キャッシュ読取 → キャッシュヒット, キャッシュ書込 → キャッシュ作成

Affected keys: cacheReadTokens, cacheCreationTokens, cacheReadCost,
cacheWriteCost, cacheRead, cacheWrite

* feat(usage): add cache metrics to trend chart

- Add cache creation tokens visualization (orange line)
- Add cache hit tokens visualization (purple line)
- Add gradient definitions for new cache metrics
- Include cache data in hourly aggregation
- Display cache metrics alongside input/output tokens

This provides better visibility into cache usage patterns over time.

* fix(usage): fix timezone handling in datetime picker

- Add timestampToLocalDatetime() to convert Unix timestamp to local datetime
- Add localDatetimeToTimestamp() with validation for incomplete input
- Fix issue where typing hours/minutes would jump to previous day
- Validate datetime format completeness before conversion
- Use local timezone instead of UTC for datetime-local input

This resolves the issue where users couldn't fine-tune time selection
and the input would jump unexpectedly when editing hours or minutes.

* feat(usage): add auto-refresh for usage statistics

- Add 30-second auto-refresh interval for all usage queries
- Disable background refresh to save resources
- Apply to: summary, trends, provider stats, model stats, request logs
- Queries automatically update when tab is active
- Pause refresh when user switches to another tab

This keeps usage data fresh without manual refresh.

* fix(proxy): improve usage logging and cache token parsing

- Log requests even when usage parsing fails (with default values)
- Add detailed debug logging for usage metrics
- Support cache_read_input_tokens field in Codex responses
- Fallback to input_tokens_details.cached_tokens if needed
- Add test case for cached_tokens in input_tokens_details
- Ensure all requests are tracked in database for analytics

This fixes missing request logs when API responses lack usage data
and improves cache token detection across different response formats.

* style(rust): use inline format args in format! macros

- Replace format!("...", var) with format!("...{var}")
- Update universal provider ID formatting
- Update error message formatting
- Update config.toml generation in Codex provider

Fixes clippy::uninlined_format_args warnings.

* feat(proxy): enhance provider router logging

- Add debug logs for failover queue provider count
- Log circuit breaker state for each provider check
- Add logs for missing current provider scenarios
- Log when no current provider is configured
- Use inline format args for better readability

This improves debugging of provider selection and failover behavior.

* feat(database): update model pricing data

- Update Claude models to full version format (e.g. claude-opus-4-5-20251101)
- Add GPT-5.2 series model pricing (10 models)
- Add GPT-5.1 series model pricing (10 models)
- Add GPT-5 series model pricing (12 models)
- Add Gemini 3 series model pricing (2 models)
- Update Gemini 2.5 series model ID format (use dot separator)
- Unify display names by removing thinking level suffixes

* fix(usage): correct Gemini output token calculation

Fix Gemini API output token parsing to use totalTokenCount - promptTokenCount
instead of candidatesTokenCount alone. This ensures thoughtsTokenCount is
included in output statistics.

- Update from_gemini_response to calculate output from total - input
- Update from_gemini_stream_chunks with same logic for consistency
- Fix from_codex_stream_events to use adjusted token calculation
- Add test case for responses with thoughtsTokenCount
- Update existing tests to match new calculation logic

* fix(usage): correct cache token billing and add Codex format auto-detection

- Avoid double-billing cache tokens by subtracting from input before calculation
- Add smart Codex parser that auto-detects OpenAI vs Codex API format
- Extract model name from Codex responses for accurate tracking

* fix(proxy): improve takeover detection with live config check

- Add live config takeover detection for hot-switch decision
- Rebuild takeover when backup is missing or placeholder remains
- Make detect_takeover_in_live_config_for_app public
- Fix is_takeover_active to use actual takeover status

* refactor(usage): simplify model pricing lookup by removing suffix fallback

Replace complex suffix-stripping fallback with direct prefix/suffix cleanup.
Model IDs are now cleaned by removing vendor prefix (before /) and colon
suffix (after :), then matched exactly against pricing table.

* feat(database): add Chinese AI model pricing data

Add pricing for domestic AI models (CNY/1M tokens):
- Doubao-Seed-Code (ByteDance)
- DeepSeek V3/V3.1/V3.2
- Kimi K2/K2-Thinking/K2-Turbo (Moonshot)
- MiniMax M2/M2.1/M2.1-Lightning
- GLM-4.6/4.7 (Zhipu)
- Mimo V2 Flash (Xiaomi)

Also fix test case to use correct model ID and remove invalid currency column.

* refactor(proxy): improve header forwarding with blacklist approach

Change from whitelist to blacklist mode for request header forwarding.
Only skip headers that will be overridden (auth, host, content-length).
This preserves client's original headers and improves compatibility.

* fix(proxy): bypass timeout and retry configs when failover is disabled

When auto_failover_enabled is false, timeout and retry configurations
should not affect normal request flow. This change ensures:

- create_forwarder: passes 0 for all timeout/retry params when failover
  is disabled, effectively bypassing these checks
- streaming_timeout_config: returns 0 for both first_byte_timeout and
  idle_timeout when failover is disabled

This prevents unnecessary timeout errors and retry attempts when users
have explicitly disabled the failover feature.

* fix(proxy): handle zero value input in failover config fields

* refactor(proxy): remove retry logic and add enabled check for failover

* refactor(proxy): distinguish circuit-open from no-provider errors

* Align usage stats to sliding windows

* feat(proxy): add body and header filtering for upstream requests

* feat(proxy): enable transparent passthrough for headers

- Passthrough anthropic-beta header as-is from client
- Passthrough anthropic-version header from client
- Passthrough client IP headers (x-forwarded-for, x-real-ip) by default
- Filter private params (underscore-prefixed fields) from request body
- No database changes required

* feat(proxy): extract session ID from client requests for logging

- Add SessionIdExtractor to parse session ID from Claude/Codex requests
- Support extraction from metadata.user_id, headers, previous_response_id
- Pass session_id through RequestContext to usage logger
- Enable request correlation by session in proxy_request_logs
2025-12-31 22:57:00 +08:00
Calcium-Ion 8fe5c1041a feat: add Universal Provider feature (#348)
* feat: add Universal Provider feature

- Add Universal Provider data structures and type definitions
- Implement backend CRUD operations and sync functionality
- Add frontend UI components (UniversalProviderPanel, Card, FormModal)
- Add NewAPI icon and preset configuration
- Support cross-app (Claude/Codex/Gemini) configuration sync
- Add website URL field for providers
- Implement real-time refresh via event notifications
- Add i18n support (Chinese/English/Japanese)

* feat: integrate universal provider presets into add provider dialog

- Add universal provider presets (NewAPI, Custom Gateway) to preset selector
- Show universal presets with Layers icon badge in preset selector
- Open UniversalProviderFormModal when universal preset is clicked
- Pass initialPreset to auto-fill form when opened from add dialog
- Add i18n keys for addSuccess/addFailed messages
- Keep separate universal provider panel for management

* refactor: move universal provider management to add dialog

- Remove Layers button from main navigation header
- Add 'Manage' button next to universal provider presets
- Open UniversalProviderPanel from within add provider dialog
- Add i18n keys for 'manage' in all locales

* style: display universal provider presets on separate line

- Move universal provider section to a new row with border separator
- Add label '统一供应商:' to clarify the section

* style: unify universal provider label style with preset label

- Use FormLabel component for consistent styling
- Add background to 'Manage' button matching preset buttons
- Update icon size and button padding for consistency

* feat: add sync functionality and JSON preview for Universal Provider

* fix: add missing in_failover_queue field to Provider structs

After rebasing to main, the Provider struct gained a new
`in_failover_queue` field. This fix adds the missing field
to the three to_*_provider() methods in UniversalProvider.

* refactor: redesign AddProviderDialog with tab-based layout

- Add tabs to separate app-specific providers and universal providers
- Move "Add Universal Provider" button from panel header to footer
- Remove unused handleAdd callback and clean up imports
- Update emptyHint i18n text to reference the footer button

* fix: append /v1 suffix to Codex base_url in Universal Provider

Codex uses OpenAI-compatible API which requires the /v1 endpoint suffix.
The Universal Provider now automatically appends /v1 to base_url when
generating Codex provider config if not already present.

- Handle trailing slashes to avoid double slashes
- Apply fix to both backend (to_codex_provider) and frontend preview

* feat: auto-sync universal provider to apps on creation

Previously, users had to manually click sync after adding a universal
provider. Now it automatically syncs to Claude/Codex/Gemini on creation,
providing a smoother user experience.

---------

Co-authored-by: Jason <farion1231@gmail.com>
2025-12-26 22:47:24 +08:00
Jason bb2756d0fb fix(ui): improve dark mode text contrast for form labels
Replace hardcoded Tailwind color classes with design system CSS variables
to improve text visibility in dark mode:

- text-gray-900 dark:text-gray-100 → text-foreground
- text-gray-500/600 dark:text-gray-400 → text-muted-foreground
- bg-white dark:bg-gray-800 → bg-background
2025-12-25 17:37:11 +08:00
YoVinchen e6f18ba801 Feat/usage model extraction (#455)
* feat(proxy): extract model name from API response for accurate usage tracking

- Add model field extraction in TokenUsage parsing for Claude, OpenAI, and Codex
- Prioritize response model over request model in usage logging
- Update model extractors to use parsed usage.model first
- Add tests for model extraction in stream and non-stream responses

* feat(proxy): implement streaming timeout control with validation

- Add first byte timeout (0 or 1-180s) for streaming requests
- Add idle timeout (0 or 60-600s) for streaming data gaps
- Add non-streaming timeout (0 or 60-1800s) for total request
- Implement timeout logic in response processor
- Add 1800s global timeout fallback when disabled
- Add database schema migration for timeout fields
- Add i18n translations for timeout settings

* feat(proxy): add model mapping module for provider-based model substitution

- Add model_mapper.rs with ModelMapping struct to extract model configs from Provider
- Support ANTHROPIC_MODEL, ANTHROPIC_REASONING_MODEL, and default models for haiku/sonnet/opus
- Implement thinking mode detection for reasoning model priority
- Include comprehensive unit tests for all mapping scenarios

* fix(proxy): bypass circuit breaker for single provider scenario

When failover is disabled (single provider), circuit breaker open state
would block all requests causing poor UX. Now bypasses circuit breaker
check in this scenario. Also integrates model mapping into request flow.

* feat(ui): add reasoning model field to Claude provider form

Add ANTHROPIC_REASONING_MODEL configuration field for Claude providers,
allowing users to specify a dedicated model for thinking/reasoning tasks.

* feat(proxy): add openrouter_compat_mode for optional format conversion

Add configurable OpenRouter compatibility mode that enables Anthropic to
OpenAI format conversion. When enabled, rewrites endpoint to /v1/chat/completions
and transforms request/response formats. Defaults to enabled for OpenRouter.

* feat(ui): add OpenRouter compatibility mode toggle

Add UI toggle for OpenRouter providers to enable/disable compatibility
mode which uses OpenAI Chat Completions format with SSE conversion.

* feat(stream-check): use provider-configured model for health checks

Extract model from provider's settings_config (ANTHROPIC_MODEL, GEMINI_MODEL,
or Codex config.toml) instead of always using default test models.

* refactor(ui): remove timeout settings from AutoFailoverConfigPanel

Remove streaming/non-streaming timeout configuration from failover panel
as these settings have been moved to a dedicated location.

* refactor(database): migrate proxy_config to per-app three-row structure

Replace singleton proxy_config table with app_type primary key structure,
allowing independent proxy settings for Claude, Codex, and Gemini.
Add GlobalProxyConfig queries and per-app config management in DAO layer.

* feat(proxy): add GlobalProxyConfig and AppProxyConfig types

Add new type definitions for the refactored proxy configuration:
- GlobalProxyConfig: shared settings (enabled, address, port, logging)
- AppProxyConfig: per-app settings (failover, timeouts, circuit breaker)

* refactor(proxy): update service layer for per-app config structure

Adapt proxy service, handler context, and provider router to use
the new per-app configuration model. Read enabled/timeout settings
from proxy_config table instead of settings table.

* feat(commands): add global and per-app proxy config commands

Add new Tauri commands for the refactored proxy configuration:
- get_global_proxy_config / update_global_proxy_config
- get_proxy_config_for_app / update_proxy_config_for_app
Update startup restore logic to read from proxy_config table.

* feat(api): add frontend API and Query hooks for proxy config

Add TypeScript wrappers and TanStack Query hooks for:
- Global proxy config (address, port, logging)
- Per-app proxy config (failover, timeouts, circuit breaker)
- Proxy takeover status management

* refactor(ui): redesign proxy panel with inline config controls

Replace ProxySettingsDialog with inline controls in ProxyPanel.
Add per-app takeover switches and global address/port settings.
Simplify AutoFailoverConfigPanel by removing timeout settings.

* feat(i18n): add proxy takeover translations and update types

Add i18n strings for proxy takeover status in zh/en/ja.
Update TypeScript types for GlobalProxyConfig and AppProxyConfig.

* refactor(proxy): load circuit breaker config per-app instead of globally

Extract app_type from router key and read circuit breaker settings
from the corresponding proxy_config row for each application.
2025-12-25 10:40:11 +08:00
Jason 7d495aa772 feat(ui): add exit animation to FullScreenPanel dialogs
- Wrap FullScreenPanel content with AnimatePresence for exit animation
- Add exit={{ opacity: 0 }} to enable fade-out on close
- Use useRef + useEffect to preserve provider data during exit animation
- Follow React best practices by updating refs in useEffect instead of render

Affected components:
- EditProviderDialog
- UsageScriptModal
- AddProviderDialog
- McpFormModal
- ProxySettingsDialog
2025-12-23 16:18:28 +08:00
YoVinchen 1586451862 Feat/auto failover switch (#440)
* feat(failover): add auto-failover master switch with proxy integration

- Add persistent auto_failover_enabled setting in database
- Add get/set_auto_failover_enabled commands
- Provider router respects master switch state
- Proxy shutdown automatically disables failover
- Enabling failover auto-starts proxy server
- Optimistic updates for failover queue toggle

* feat(proxy): persist proxy takeover state across app restarts

- Add proxy_takeover_{app_type} settings for per-app state tracking
- Restore proxy takeover state automatically on app startup
- Preserve state on normal exit, clear on manual stop
- Add stop_with_restore_keep_state method for graceful shutdown

* fix(proxy): set takeover state for all apps in start_with_takeover

* fix(windows): hide console window when checking CLI versions

Add CREATE_NO_WINDOW flag to prevent command prompt from flashing
when detecting claude/codex/gemini CLI versions on Windows.

* refactor(failover): make auto-failover toggle per-app independent

- Change setting key from 'auto_failover_enabled' to 'auto_failover_enabled_{app_type}'
- Update provider_router to check per-app failover setting
- When failover disabled, use current provider only; when enabled, use queue order
- Add unit tests for failover enabled/disabled behavior

* feat(failover): auto-switch to higher priority provider on recovery

- After circuit breaker reset, check if recovered provider has higher priority
- Automatically switch back if queue_order is lower (higher priority)
- Stream health check now resets circuit breaker on success/degraded

* chore: remove unused start_proxy_with_takeover command

- Remove command registration from lib.rs
- Add comment clarifying failover queue is preserved on proxy stop

* feat(ui): integrate failover controls into provider cards

- Add failover toggle button to provider card actions
- Show priority badge (P1, P2, ...) for queued providers
- Highlight active provider with green border in failover mode
- Sync drag-drop order with failover queue
- Move per-app failover toggle to FailoverQueueManager
- Simplify SettingsPage failover section

* test(providers): add mocks for failover hooks in ProviderList tests

* refactor(failover): merge failover_queue table into providers

- Add in_failover_queue field to providers table
- Remove standalone failover_queue table and related indexes
- Simplify queue ordering by reusing sort_index field
- Remove reorder_failover_queue and set_failover_item_enabled commands
- Update frontend to use simplified FailoverQueueItem type

* fix(database): ensure in_failover_queue column exists for v2 databases

Add column check in create_tables to handle existing v2 databases
that were created before the failover queue refactor.

* fix(ui): differentiate active provider border color by proxy mode

- Use green border/gradient when proxy takeover is active
- Use blue border/gradient in normal mode (no proxy)
- Improves visual distinction between proxy and non-proxy states

* fix(database): clear provider health record when removing from failover queue

When a provider is removed from the failover queue, its health monitoring
is no longer needed. This change ensures the health record is also deleted
from the database to prevent stale data.

* fix(failover): improve cache cleanup for provider health and circuit breaker

- Use removeQueries instead of invalidateQueries when stopping proxy to
  completely clear health and circuit breaker caches
- Clear provider health and circuit breaker caches when removing from
  failover queue
- Refresh failover queue after drag-sort since queue order depends on
  sort_index
- Only show health badge when provider is in failover queue

* style: apply prettier formatting to App.tsx and ProviderList.tsx

* fix(proxy): handle missing health records and clear health on proxy stop

- Return default healthy state when provider health record not found
- Add clear_provider_health_for_app to clear health for specific app
- Clear app health records when stopping proxy takeover

* fix(proxy): track actual provider used in forwarding for accurate logging

Introduce ForwardResult and ForwardError structs to return the actual
provider that handled the request. This ensures usage statistics and
error logs reflect the correct provider after failover.
2025-12-23 12:37:36 +08:00
Jason 26c3f05daf feat(ui): add fade transition for view and panel switching
Add smooth fade animations when navigating between views (Settings,
MCP, Skills, Prompts) and opening full-screen panels (Add/Edit Provider).
2025-12-22 16:54:49 +08:00
TinsFox d303706d51 feat: add provider search filter (#435)
* feat: add provider search filter

* feat: add provider search overlay
2025-12-22 15:46:11 +08:00
YoVinchen a1537807eb feat(failover): add auto-failover master switch with proxy integration (#427)
* feat(failover): add auto-failover master switch with proxy integration

- Add persistent auto_failover_enabled setting in database
- Add get/set_auto_failover_enabled commands
- Provider router respects master switch state
- Proxy shutdown automatically disables failover
- Enabling failover auto-starts proxy server
- Optimistic updates for failover queue toggle

* feat(proxy): persist proxy takeover state across app restarts

- Add proxy_takeover_{app_type} settings for per-app state tracking
- Restore proxy takeover state automatically on app startup
- Preserve state on normal exit, clear on manual stop
- Add stop_with_restore_keep_state method for graceful shutdown

* fix(proxy): set takeover state for all apps in start_with_takeover
2025-12-21 22:39:50 +08:00
Jason b67cdbb18c feat(ui): add fade transition for app switching
- Add AnimatePresence + motion.div wrapper for provider list
- Use key={activeApp} to trigger enter/exit animations on app switch
- Remove redundant animate-slide-up from ProviderList to prevent
  animation conflicts and visual jitter
2025-12-21 10:27:56 +08:00
Jason c4f1e90893 style(settings): unify tab transition animations
Add framer-motion fade-in and slide-up animations to General and
Advanced tabs, matching the existing Usage and About tab animations.
2025-12-21 09:29:14 +08:00
Jason ddbff070d5 feat(settings): add option to skip Claude Code first-run confirmation
Add a new setting to automatically skip Claude Code's onboarding screen
by writing hasCompletedOnboarding=true to ~/.claude.json. The setting
defaults to enabled for better user experience.

- Add set/clear_has_completed_onboarding functions in claude_mcp.rs
- Add Tauri commands and frontend API integration
- Add toggle in WindowSettings with i18n support (en/zh/ja)
- Fix hardcoded Chinese text in tests to use i18n keys
2025-12-20 23:55:10 +08:00
Jason ca7cb398c2 i18n: complete usage panel and settings internationalization
- Add missing i18n keys for usage statistics panel (trends, cost, perMillion, etc.)
- Add i18n keys for settings advanced section (configDir, proxy, modelTest, etc.)
- Add streamCheck i18n keys for health check configuration
- Remove hardcoded Chinese fallback values from t() calls
- Add common keys (all, search, reset, actions, deleting)
2025-12-20 22:29:39 +08:00
Jason 2fb3b5405a i18n: complete internationalization for v3.8+ features
- Add health status translations (operational, degraded, failed, circuitOpen)
- Add proxy panel translations (serviceAddress, stats, stopped state)
- Add usage filter translations (appType, statusCode, searchPlaceholder)
- Add providerIcon click hints (clickToChange, clickToSelect)
- Add config load error translations for main.tsx
- Complete Japanese proxy section (failoverQueue, autoFailover)
- Fix date/time locale in usage charts and tables
- Use t() function in all hardcoded UI strings
2025-12-20 21:38:37 +08:00
Jason ec649e7718 style(switch): improve dark mode appearance
- Track (unchecked): lighten in light mode (gray-300 → gray-200),
  darken in dark mode (gray-700 → gray-900) to blend with background
- Thumb: soften in dark mode (white → gray-400) to reduce glare
2025-12-20 19:18:29 +08:00
Jason 3da5525c79 fix(ui): improve text visibility in dark mode
Replace hardcoded gray color classes with semantic color classes
to fix poor text contrast in dark mode:

- MCP panel: server names, descriptions, tags, app labels
- Prompt panel: prompt names, descriptions, empty states
- Usage footer: timestamps, refresh buttons
- Update badge: close button icon
- API key input: disabled state text
- Env warning banner: source info text

Changes:
- `text-gray-400 dark:text-gray-500` → `text-muted-foreground`
  (fixes reversed dark mode logic)
- `text-gray-500 dark:text-gray-400` → `text-muted-foreground`
- `bg-gray-100 dark:bg-gray-800` → `bg-muted`
2025-12-20 18:57:36 +08:00
Jason 5fe5ed98be style(header): unify height and styling of header toolbar sections
- Use consistent h-8 fixed height for all inner elements
- Standardize border-radius to rounded-xl across all sections
- Remove background from ProxyToggle for cleaner appearance
- Simplify ProxyToggle structure with nested container
2025-12-20 16:24:25 +08:00
Jason ba59483b33 refactor(proxy): remove global auto-start flag
- Remove global proxy auto-start flag from config and UI.
- Simplify per-app takeover start/stop and stop server when the last takeover is disabled.
- Restore live takeover detection used for crash recovery.
- Keep proxy_config.enabled column but always write 0 for compatibility.
- Tests: not run (not requested).
2025-12-20 08:48:59 +08:00
YoVinchen 5bce6d6020 Fix/about section UI (#419)
* fix(ui): improve AboutSection styling and version detection

- Add framer-motion animations for smooth page transitions
- Unify button sizes and add icons for consistency
- Add gradient backgrounds and hover effects to cards
- Add notInstalled i18n translations (zh/en/ja)
- Fix version detection when stdout/stderr is empty

* fix(proxy): persist per-app takeover state across app restarts

- Fix proxy toggle color to reflect current app's takeover state only
- Restore proxy service on startup if Live config is still in takeover state
- Preserve per-app backup records instead of clearing all on restart
- Only recover Live config when proxy service fails to start
2025-12-19 20:40:11 +08:00
Jason ec6e113cf2 chore: bump version to 3.9.0-beta.1
- Update version in package.json, Cargo.toml, tauri.conf.json
- Add CHANGELOG entry for v3.9.0-beta.1 with:
  - Local Proxy Server feature
  - Auto Failover with circuit breaker
  - Skills multi-app support
  - Provider icon colors
  - 25+ bug fixes
- Add proxy feature guide documentation (Chinese)
2025-12-18 20:53:02 +08:00
Jason 18207771ad feat(proxy): implement per-app takeover mode
Replace global live takeover with granular per-app control:
- Add start_proxy_server command (start without takeover)
- Add get_proxy_takeover_status to query each app's state
- Add set_proxy_takeover_for_app for individual app control
- Use live backup existence as SSOT for takeover state
- Refactor sync_live_to_provider to eliminate code duplication
- Update ProxyToggle to show status per active app
2025-12-18 11:28:10 +08:00
Jason 3d514c8250 fix(proxy): stabilize live takeover and provider editing
- Skip live writes when takeover is active and proxy is running
- Refresh live backups from provider edits during takeover
- Sync live tokens to DB without clobbering real keys with placeholders
- Avoid injecting extra placeholder keys into Claude live env
- Reapply takeover after proxy listen address/port changes
- In takeover mode, edit dialog uses DB config and keeps API key state in sync
2025-12-17 09:36:17 +08:00
YoVinchen ec20ff4d8c Feature/error request logging (#401)
* feat(proxy): add error mapper for HTTP status code mapping

- Add error_mapper.rs module to map ProxyError to HTTP status codes
- Implement map_proxy_error_to_status() for error classification
- Implement get_error_message() for user-friendly error messages
- Support all error types: upstream, timeout, connection, provider failures
- Include comprehensive unit tests for all mappings

* feat(proxy): enhance error logging with context support

- Add log_error_with_context() method for detailed error recording
- Support streaming flag, session_id, and provider_type fields
- Remove dead_code warning from log_error() method
- Enable comprehensive error request tracking in database

* feat(proxy): implement error capture and logging in all handlers

- Capture and log all failed requests in handle_messages (Claude)
- Capture and log all failed requests in handle_gemini (Gemini)
- Capture and log all failed requests in handle_responses (Codex)
- Capture and log all failed requests in handle_chat_completions (Codex)
- Record error status codes, messages, and latency for all failures
- Generate unique session_id for each request
- Support both streaming and non-streaming error scenarios

* style: fix clippy warnings and typescript errors

- Add allow(dead_code) for CircuitBreaker::get_state (reserved for future)
- Fix all uninlined format string warnings (27 instances)
- Use inline format syntax for better readability
- Fix unused import and parameter warnings in ProviderActions.tsx
- Achieve zero warnings in both Rust and TypeScript

* style: apply code formatting

- Remove trailing whitespace in misc.rs
- Add trailing comma in App.tsx
- Format multi-line className in ProviderCard.tsx

* feat(proxy): add settings button to proxy panel

Add configuration buttons in both running and stopped states to
provide easy access to proxy settings dialog.

* fix(speedtest): skip client build for invalid inputs

* chore(clippy): fix uninlined format args

* Merge branch 'main' into feature/error-request-logging
2025-12-16 21:02:08 +08:00
Jason e6654bd7f9 refactor(proxy): remove is_proxy_target in favor of failover_queue
- Remove `is_proxy_target` field from Provider struct (Rust & TypeScript)
- Remove related DAO methods: get_proxy_target_provider, set_proxy_target
- Remove deprecated Tauri commands: get_proxy_targets, set_proxy_target
- Add `is_available()` method to CircuitBreaker for availability checks
  without consuming HalfOpen probe permits (used in select_providers)
- Keep `allow_request()` for actual request gating with permit tracking
- Update stream_check to use failover_queue instead of is_proxy_target
- Clean up commented-out reset circuit breaker button in ProviderActions
- Remove unused useProxyTargets and useSetProxyTarget hooks
2025-12-16 15:45:15 +08:00
Jason d4f33224c6 fix(ui): add close button to all success toasts 2025-12-16 10:56:39 +08:00
Jason 5efc0cdd5e fix(ui): prevent card jitter when health badge appears
Increase min-height of the name row from 20px to 28px (min-h-7)
to accommodate the health badge height, preventing layout shift
when the badge dynamically appears.
2025-12-15 22:57:41 +08:00
Sirhexs 1172209f49 fix(usage): add fallback to provider config for usage credentials (#360)
- Make usage script credential fields optional with provider config fallback
- Optimize multi-plan card display: show plan count by default, expandable for details
- Add hint text to explain credential fallback mechanism
2025-12-15 17:09:46 +08:00
千羽 c49cfa5ac5 feat(deeplink): 深链支持用量查询配置 (#400)
## 新增功能
- 深链导入支持用量查询配置参数:
  - `usageEnabled`: 是否启用用量查询
  - `usageScript`: Base64 编码的用量查询脚本
  - `usageApiKey`: 用量查询专用 API Key
  - `usageBaseUrl`: 用量查询专用 Base URL
  - `usageAccessToken`: 访问令牌(NewAPI 模板)
  - `usageUserId`: 用户 ID(NewAPI 模板)
  - `usageAutoInterval`: 自动查询间隔(分钟)

## 修改文件
- **mod.rs**: DeepLinkImportRequest 结构体添加用量查询字段
- **parser.rs**: 解析 URL 中的用量查询参数
- **provider.rs**: 构建 ProviderMeta 包含 UsageScript 配置
- **deeplink.ts**: 添加 TypeScript 类型定义
- **DeepLinkImportDialog.tsx**: 确认对话框显示用量查询配置

## Bug 修复
- **formatters.ts**: 修复 formatJSON() 格式化时删除 "env" 键的问题

## 深链格式示例
```
ccswitch://v1/import?resource=provider&app=claude&name=xxx&usageEnabled=true&usageScript={base64}&usageAutoInterval=30
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 21:52:13 +08:00
Jason 5d424b1383 feat(proxy): implement independent failover queue management
Add a new failover queue system that operates independently from provider
sortIndex, allowing users to configure failover order per app type.

Backend changes:
- Add failover_queue table to schema.rs for persistent storage
- Create dao/failover.rs with CRUD operations for queue management
- Add Tauri commands for queue operations (get, add, remove, reorder, toggle)
- Refactor provider_router.rs select_providers() to use failover queue:
  - Current provider always takes first priority
  - Queue providers ordered by queue_order as fallback
  - Only providers with open circuit breakers are included

Frontend changes:
- Add FailoverQueueItem type to proxy.ts
- Extend failover.ts API with queue management methods
- Add React Query hooks for queue data fetching and mutations
- Create FailoverQueueManager component with drag-and-drop reordering
- Integrate queue management into SettingsPage under "Auto Failover"
- Add i18n translations for zh and en locales
2025-12-12 16:13:07 +08:00
YoVinchen 395783e22a Feat/provider icon color (#385)
* feat(ui): add color prop support to ProviderIcon component

* feat(health): add stream check core functionality

Add new stream-based health check module to replace model_test:
- Add stream_check command layer with single and batch provider checks
- Add stream_check DAO layer for config and log persistence
- Add stream_check service layer with retry mechanism and health status evaluation
- Add frontend HealthStatusIndicator component
- Add frontend useStreamCheck hook

This provides more comprehensive health checking capabilities.

* refactor(health): replace model_test with stream_check

Replace model_test module with stream_check across the codebase:
- Remove model_test command and service modules
- Update command registry in lib.rs to use stream_check commands
- Update module exports in commands/mod.rs and services/mod.rs
- Remove frontend useModelTest hook
- Update stream_check command implementation

This refactoring provides clearer naming and better separation of concerns.

* refactor(db): clean up unused database tables and optimize schema

Remove deprecated and unused database tables:
- Remove proxy_usage table (replaced by proxy_request_logs)
- Remove usage_daily_stats table (aggregation done on-the-fly)
- Rename model_test_logs to stream_check_logs with updated schema
- Remove related DAO methods for proxy_usage
- Update usage_stats service to use proxy_request_logs only
- Refactor usage_script to work with new schema

This simplifies the database schema and removes redundant data storage.

* refactor(ui): update frontend components for stream check

Update frontend components to use stream check API:
- Refactor ModelTestConfigPanel to use stream check config
- Update API layer to use stream_check commands
- Add HealthStatus type and StreamCheckResult interface
- Update ProviderList to use new health check integration
- Update AutoFailoverConfigPanel with stream check references
- Improve UI layout and configuration options

This completes the frontend migration from model_test to stream_check.

* feat(health): add configurable test models and reasoning effort support

Enhance stream check service with configurable test models:
- Add claude_model, codex_model, gemini_model to StreamCheckConfig
- Support reasoning effort syntax (model@level or model#level)
- Parse and apply reasoning_effort for OpenAI-compatible models
- Remove hardcoded model names from check functions
- Add unit tests for model parsing logic
- Remove obsolete model_test source files

This allows users to customize which models are used for health checks.
2025-12-11 17:20:44 +08:00