mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-06-16 13:34:04 +08:00
c460a404dc8faf7231e3f7932d8fdb50bb93d22a
31 Commits
-
fix(failover): patch P1-P3 reliability gaps surfaced by team review
- Forwarder buffers non-streaming bodies and primes streaming first chunk before signaling success, so body timeouts and SSE first-chunk failures route through the circuit breaker instead of being recorded as success on response-header arrival - Atomic enable-failover: switch to P1 before persisting the flag, and roll back auto-added queue entries when the switch is rejected (e.g. official providers) - Hot-reload circuit breaker config on per-app proxy config change instead of waiting for a proxy restart - FailoverToggle / FailoverQueueManager / AutoFailoverConfigPanel require proxy takeover for the active app; the backend command also rejects enabling when takeover is off - ProviderHealthBadge consumes the backend is_healthy flag instead of hardcoding the 5-failure threshold Cleanup: - impl From<&AppProxyConfig> for CircuitBreakerConfig and use it from the command layer - Collapse three identical TabsContent blocks into a single map
Jason ·
2026-05-14 21:35:02 +08:00 -
fix(proxy-ui): accept IPv6 listen addresses in ProxyPanel validation
The backend already understands `::` -> `::1` and wraps IPv6 literals in brackets (services/proxy.rs), but the panel's save-time validator only accepted localhost, 0.0.0.0, and IPv4 dotted-quads. Users who wanted to listen on an IPv6 loopback had to bypass the UI and edit config directly. Add an isValidIpv6 helper that requires at least one ':' and round-trips through `new URL('http://[<addr>]/')` so the platform's built-in IPv6 parser does the heavy lifting (covers compressed `::`, full 8-group form, zone IDs). Update the invalidAddress copy in zh / en / ja so the error message reflects the new accepted set.Jason ·
2026-05-13 23:36:44 +08:00 -
feat(claude-desktop): add 3P provider switching with proxy gateway
Adds a new ClaudeDesktop AppType that writes Claude Desktop's third-party inference profile under configLibrary/, sharing _meta.json with other launchers (Ollama-compatible) so cc-switch can coexist with them. Two switch modes: - direct: provider already exposes claude-* / anthropic/claude-* model ids on Anthropic Messages, Claude Desktop connects to it directly. - proxy: cc-switch's local proxy acts as the inference gateway, presenting only claude-* route names to Claude Desktop and mapping them to real upstream models. Required after Anthropic restricted Claude Desktop to claude-family ids. Backend: - New module claude_desktop_config with snapshot/rollback, official seed bypass, /claude-desktop/v1/{models,messages} routes, and a single source of truth for default proxy routes. - Gateway token persisted in SQLite, validated on every proxied request. - get_claude_desktop_status surfaces drift signals (stale models, missing routes, proxy stopped, base URL mismatch, missing token). Frontend: - Slim ClaudeDesktopProviderForm independent from ProviderForm, controlled by a top-level appId guard. - ProviderList banner consumes the status query (5s polling) and renders actionable diagnostics. - ClaudeDesktopRouteToggle in the header to start/stop the local gateway without touching takeover state. - Three-locale i18n synchronised.Jason ·
2026-05-08 22:34:46 +08:00 -
Style/add provider.notes (#2138)
* style(FailoverQueueManager): 显示供应商备注信息 * style(FailoverQueueItem): 添加供应商备注字段以支持备注信息显示 * style(FailoverQueueManager): 显示供应商备注信息 * style(FailoverQueueItem): 添加供应商备注字段以支持备注信息显示 * style(FailoverQueueManager): 更新供应商备注信息的显示样式 * style(FailoverQueueItem): 添加条件序列化以优化供应商备注字段
Coconut-Fish ·
2026-04-18 17:48:58 +08:00 -
fix: comprehensive i18n audit - add 69 missing keys and fix hardcoded Chinese
- Add 69 missing translation keys to zh/en/ja (usage, proxy, sessionManager, deeplink, codexConfig, openclaw, circuitBreaker, streamCheck, etc.) - Replace 15 hardcoded Chinese strings in CircuitBreakerConfigPanel with t() calls - Fix ColorPicker component to use i18n for default label - Add i18n interpolation params to ProxyToggle tooltip translations - All three language files synchronized at 1838 keys
Jason ·
2026-03-08 20:41:44 +08:00 -
refactor: move proxy toggle into panel and surface app takeover options
Move the proxy on/off switch from the accordion header into the panel content area, placing it right above the app takeover section. This ensures users see the takeover options immediately after enabling the proxy, preventing the common pitfall of running the proxy without actually taking over any app. - Simplify accordion trigger to standard style with Badge only - Add AnimatePresence animation for takeover section reveal - Remove duplicate takeover switches from running info card - Update stoppedDescription i18n to reference "above toggle" - Add proxy.takeover.hint key in zh/en/ja
Jason ·
2026-02-28 09:13:32 +08:00 -
feat(settings): add enableLocalProxy toggle to gate main page proxy UI
New users often accidentally trigger ProxyToggle/FailoverToggle on the main page. Add a settings toggle (default off) so the proxy controls only appear when explicitly enabled. The proxy service start/stop in settings remains independent of this visibility flag.
Jason ·
2026-02-19 23:06:22 +08:00 -
fix(failover): switch to P1 immediately when enabling auto failover
Previously, enabling auto failover kept using the current provider until the first failure, causing inconsistency when the current provider was not in the failover queue. When stopping proxy, the restored config would not match user expectations. New behavior: - Enable auto failover = immediately switch to queue P1 - Subsequent routing follows queue order (P1→P2→...) - Auto-add current provider to queue if queue is empty Changes: - Add switch_proxy_target() for hot-switching during proxy mode - Update provider_router to use queue order when failover enabled - Sync tray menu Auto click with the same logic - Update UI tooltips to reflect new semantics - Add tests for queue-only routing scenario
Jason ·
2026-01-21 11:27:44 +08:00 -
Feat/provider individual config (#663)
* refactor(ui): simplify UpdateBadge to minimal dot indicator * feat(provider): add individual test and proxy config for providers Add support for provider-specific model test and proxy configurations: - Add ProviderTestConfig and ProviderProxyConfig types in Rust and TypeScript - Create ProviderAdvancedConfig component with collapsible panels - Update stream_check service to merge provider config with global config - Proxy config UI follows global proxy style (single URL input) Provider-level configs stored in meta field, no database schema changes needed. * feat(ui): add failover toggle and improve proxy controls - Add FailoverToggle component with slide animation - Simplify ProxyToggle style to match FailoverToggle - Add usage statistics button when proxy is active - Fix i18n parameter passing for failover messages - Add missing failover translation keys (inQueue, addQueue, priority) - Replace AboutSection icon with app logo * fix(proxy): support system proxy fallback and provider-level proxy config - Remove no_proxy() calls in http_client.rs to allow system proxy fallback - Add get_for_provider() to build HTTP client with provider-specific proxy - Update forwarder.rs and stream_check.rs to use provider proxy config - Fix EditProviderDialog.tsx to include provider.meta in useMemo deps - Add useEffect in ProviderAdvancedConfig.tsx to sync expand state Fixes #636 Fixes #583 * fix(ui): sync toast theme with app setting * feat(settings): add log config management Fixes #612 Fixes #514 * fix(proxy): increase request body size limit to 200MB Fixes #666 * docs(proxy): update timeout config descriptions and defaults Fixes #612 * fix(proxy): filter x-goog-api-key header to prevent duplication * fix(proxy): prevent proxy recursion when system proxy points to localhost Detect if HTTP_PROXY, HTTPS_PROXY, or ALL_PROXY environment variables point to loopback addresses (localhost, 127.0.0.1), and bypass system proxy in such cases to avoid infinite request loops. * fix(i18n): add providerAdvanced i18n keys and fix failover toast parameter - Add providerAdvanced.* i18n keys to en.json, zh.json, and ja.json - Fix failover toggleFailed toast to pass detail parameter - Remove Chinese fallback text from UI for English/Japanese users * fix(tray): restore tray-provider events and enable Auto failover properly - Emit provider-switched event on tray provider click (backward compatibility) - Auto button now: starts proxy, takes over live config, enables failover * fix(log): enable dynamic log level and single file mode - Initialize log at Trace level for dynamic adjustment - Change rotation strategy to KeepSome(1) for single file - Set max file size to 1GB - Delete old log file on startup for clean start * fix(tray): fix clippy uninlined format args warning Use inline format arguments: {app_type_str} instead of {} * fix(provider): allow typing :// in endpoint URL inputs Change input type from "url" to "text" to prevent browser URL validation from blocking :// input. Closes #681 * fix(stream-check): use Gemini native streaming API format - Change endpoint from OpenAI-compatible to native streamGenerateContent - Add alt=sse parameter for SSE format response - Use x-goog-api-key header instead of Bearer token - Convert request body to Gemini contents/parts format * feat(proxy): add request logging for debugging Add debug logs for outgoing requests including URL and body content with byte size, matching the existing response logging format. * fix(log): prevent usize underflow in KeepSome rotation strategy KeepSome(n) internally computes n-2, so n=1 causes underflow. Use KeepSome(2) as the minimum safe value.
Dex Miller ·
2026-01-20 21:02:44 +08:00 -
feat(opencode): Phase 7 - Frontend TypeScript type definitions
- Add "opencode" to AppId type in lib/api/types.ts - Extend McpApps interface with opencode field in types.ts - Add OpenCode-specific types: OpenCodeModel, OpenCodeProviderOptions, OpenCodeProviderConfig, OpenCodeMcpServerSpec - Add opencodeConfigDir to Settings interface - Add importOpenCodeFromLive() to providersApi - Fix type errors across components: - AppSwitcher: add opencode to icon/name mappings - McpFormModal: add opencode to enabledApps state - PromptFormModal/Panel: add opencode filename mapping - EndpointSpeedTest: add opencode timeout config - useBaseUrlState: add opencode to appType union - ProxyToggle: add opencode label - App.tsx: handle opencode fallback for SkillsPage - Update ProxyTakeoverStatus with opencode field (always false) - Fix test mocks in tests/msw/state.ts
Jason ·
2026-01-15 16:25:14 +08:00 -
Feature/global proxy (#596)
* refactor(proxy): simplify logging for better readability - Delete 17 verbose debug logs from handlers, streaming, and response_processor - Convert excessive INFO logs to DEBUG level for internal processing details - Add 2 critical INFO logs in forwarder.rs for failover scenarios: - Log when switching to next provider after failure - Log when all providers have been exhausted - Fix clippy uninlined_format_args warning This reduces log noise while maintaining visibility into key user-facing decisions. * fix: replace unsafe unwrap() calls with proper error handling - database/dao/mcp.rs: Use map_err for serde_json serialization - database/dao/providers.rs: Use map_err for settings_config and meta serialization - commands/misc.rs: Use expect() for compile-time regex pattern - services/prompt.rs: Use unwrap_or_default() for SystemTime - deeplink/provider.rs: Replace unwrap() with is_none_or pattern for Option checks Reduces potential panic points from 26 to 1 (static regex init, safe). * refactor(proxy): simplify verbose logging output - Remove response JSON full output logging in response_processor - Remove per-request INFO logs in provider_router (failover status, provider selection) - Change model mapping log from INFO to DEBUG - Change usage logging failure from INFO to WARN - Remove redundant debug logs for circuit breaker operations Reduces log noise significantly while preserving important warnings and errors. * feat(proxy): add structured log codes for i18n support Add error code system to proxy module logs for multi-language support: - CB-001~006: Circuit breaker state transitions and triggers - SRV-001~004: Proxy server lifecycle events - FWD-001~002: Request forwarding and failover - FO-001~005: Failover switch operations - USG-001~002: Usage logging errors Log format: [CODE] Chinese message Frontend/log tools can map codes to any language. New file: src/proxy/log_codes.rs - centralized code definitions * chore: bump version to 3.9.1 * style: format code with prettier and rustfmt * fix(ui): allow number inputs to be fully cleared before saving - Convert numeric state to string type for controlled inputs - Use isNaN() check instead of || fallback to allow 0 values - Apply fix to ProxyPanel, CircuitBreakerConfigPanel, AutoFailoverConfigPanel, and ModelTestConfigPanel * feat(pricing): support @ separator in model name matching - Refactor model name cleaning into chained method calls - Add @ to - replacement (e.g., gpt-5.2-codex@low → gpt-5.2-codex-low) - Add test case for @ separator matching * feat(proxy): add global proxy settings support Add ability to configure a global HTTP/HTTPS proxy for all outbound requests including provider API calls, speed tests, and stream checks. * fix(proxy): improve validation and error handling in proxy config panels - Add StopTimeout/StopFailed error types for proper stop() error reporting - Replace silent clamp with validation-and-block in config panels - Add listenAddress format validation in ProxyPanel - Use log_codes constants instead of hardcoded strings - Use once_cell::Lazy for regex precompilation * fix(proxy): harden error handling and input validation - Handle RwLock poisoning in settings.rs with unwrap_or_else - Add fallback for dirs::home_dir() in config modules - Normalize localhost to 127.0.0.1 in ProxyPanel - Format IPv6 addresses with brackets for valid URLs - Strict port validation with pure digit regex - Treat NaN as validation failure in config panels - Log warning on cost_multiplier parse failure - Align timeoutSeconds range to [0, 300] across all panels * feat(proxy): add local proxy auto-scan and fix hot-reload - Add scan_local_proxies command to detect common proxy ports - Fix SkillService not using updated proxy after hot-reload - Move global proxy settings to advanced tab - Add error handling for scan failures * fix(proxy): allow localhost input in proxy address field * fix(proxy): restore request timeout and fix proxy hot-reload issues - Add URL scheme validation in build_client (http/https/socks5/socks5h) - Restore per-request timeout for speedtest, stream_check, usage_script, forwarder - Fix set_global_proxy_url to validate before persisting to DB - Mask proxy credentials in all log outputs - Fix forwarder hot-reload by fetching client on each request * style: format code with prettier * fix(proxy): improve global proxy stability and error handling - Fix RwLock silent failures with explicit error propagation - Handle init() duplicate calls gracefully with warning log - Align fallback client config with build_client settings - Make scan_local_proxies async to avoid UI blocking - Add mixed mode support for Clash 7890 port (http+socks5) - Use multiple test targets for better proxy connectivity test - Clear invalid proxy config on init failure - Restore timeout constraints in usage_script - Fix mask_url output for URLs without port - Add structured error codes [GP-001 to GP-009] * feat(proxy): add username/password authentication support - Add separate username and password input fields - Implement password visibility toggle with eye icon - Add clear button to reset all proxy fields - Auto-extract auth info from saved URL and merge on save - Update i18n translations (zh/en/ja) * fix(proxy): fix double encoding issue in proxy auth and add debug logs - Remove encodeURIComponent in mergeAuth() since URL object's username/password setters already do percent-encoding automatically - Add GP-010 debug log for database read operations - Add GP-011 debug log to track incoming URL info (length, has_auth) - Fix username.trim() in fallback branch for consistent behavior
Dex Miller ·
2026-01-13 10:55:53 +08:00 -
Refactor/simplify proxy logs (#585)
* refactor(proxy): simplify logging for better readability - Delete 17 verbose debug logs from handlers, streaming, and response_processor - Convert excessive INFO logs to DEBUG level for internal processing details - Add 2 critical INFO logs in forwarder.rs for failover scenarios: - Log when switching to next provider after failure - Log when all providers have been exhausted - Fix clippy uninlined_format_args warning This reduces log noise while maintaining visibility into key user-facing decisions. * fix: replace unsafe unwrap() calls with proper error handling - database/dao/mcp.rs: Use map_err for serde_json serialization - database/dao/providers.rs: Use map_err for settings_config and meta serialization - commands/misc.rs: Use expect() for compile-time regex pattern - services/prompt.rs: Use unwrap_or_default() for SystemTime - deeplink/provider.rs: Replace unwrap() with is_none_or pattern for Option checks Reduces potential panic points from 26 to 1 (static regex init, safe). * refactor(proxy): simplify verbose logging output - Remove response JSON full output logging in response_processor - Remove per-request INFO logs in provider_router (failover status, provider selection) - Change model mapping log from INFO to DEBUG - Change usage logging failure from INFO to WARN - Remove redundant debug logs for circuit breaker operations Reduces log noise significantly while preserving important warnings and errors. * feat(proxy): add structured log codes for i18n support Add error code system to proxy module logs for multi-language support: - CB-001~006: Circuit breaker state transitions and triggers - SRV-001~004: Proxy server lifecycle events - FWD-001~002: Request forwarding and failover - FO-001~005: Failover switch operations - USG-001~002: Usage logging errors Log format: [CODE] Chinese message Frontend/log tools can map codes to any language. New file: src/proxy/log_codes.rs - centralized code definitions * chore: bump version to 3.9.1 * style: format code with prettier and rustfmt * fix(ui): allow number inputs to be fully cleared before saving - Convert numeric state to string type for controlled inputs - Use isNaN() check instead of || fallback to allow 0 values - Apply fix to ProxyPanel, CircuitBreakerConfigPanel, AutoFailoverConfigPanel, and ModelTestConfigPanel * feat(pricing): support @ separator in model name matching - Refactor model name cleaning into chained method calls - Add @ to - replacement (e.g., gpt-5.2-codex@low → gpt-5.2-codex-low) - Add test case for @ separator matching * fix(proxy): improve validation and error handling in proxy config panels - Add StopTimeout/StopFailed error types for proper stop() error reporting - Replace silent clamp with validation-and-block in config panels - Add listenAddress format validation in ProxyPanel - Use log_codes constants instead of hardcoded strings - Use once_cell::Lazy for regex precompilation * fix(proxy): harden error handling and input validation - Handle RwLock poisoning in settings.rs with unwrap_or_else - Add fallback for dirs::home_dir() in config modules - Normalize localhost to 127.0.0.1 in ProxyPanel - Format IPv6 addresses with brackets for valid URLs - Strict port validation with pure digit regex - Treat NaN as validation failure in config panels - Log warning on cost_multiplier parse failure - Align timeoutSeconds range to [0, 300] across all panels
Dex Miller ·
2026-01-11 20:50:54 +08:00 -
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
Jason Young ·
2026-01-09 13:09:19 +08:00 -
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_logsDex Miller ·
2025-12-31 22:57:00 +08:00 -
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.
YoVinchen ·
2025-12-25 10:40:11 +08:00 -
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.YoVinchen ·
2025-12-23 12:37:36 +08:00 -
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_takeoverYoVinchen ·
2025-12-21 22:39:50 +08:00 -
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
Jason ·
2025-12-20 21:38:37 +08:00 -
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
Jason ·
2025-12-20 16:24:25 +08:00 -
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).
Jason ·
2025-12-20 08:48:59 +08:00 -
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)
Jason ·
2025-12-18 20:53:02 +08:00 -
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
Jason ·
2025-12-18 11:28:10 +08:00 -
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
YoVinchen ·
2025-12-16 21:02:08 +08:00 -
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
Jason ·
2025-12-16 15:45:15 +08:00 -
Jason ·
2025-12-16 10:56:39 +08:00 -
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
Jason ·
2025-12-12 16:13:07 +08:00 -
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.
YoVinchen ·
2025-12-11 17:20:44 +08:00 -
refactor(proxy): simplify provider selection to use is_current directly
Changes: - Modify provider_router to select provider based on is_current flag instead of is_proxy_target queue - Remove proxy target toggle UI from ProviderCard - Remove proxyPriority and allProviders props from ProviderList - Remove isProxyTarget prop from ProviderHealthBadge - Use start_with_takeover() for auto-start to ensure proper setup This simplifies the proxy architecture by directly using the current provider for proxying, eliminating the need for separate proxy target management. Switching providers now immediately takes effect in proxy mode.
Jason ·
2025-12-10 21:08:41 +08:00 -
fix(proxy): resolve 404 error and auto-setup proxy targets
Issues fixed: 1. Route prefix mismatch - Live config was set to use /claude, /codex, /gemini prefixes but server only had routes without prefixes 2. Proxy targets not auto-configured - start_with_takeover only modified Live config but didn't set is_proxy_target=true for current providers Changes: - Add prefixed routes (/claude/v1/messages, /codex/v1/*, /gemini/v1beta/*) to server.rs for backward compatibility - Remove URL prefixes from takeover_live_configs() - server can route by API endpoint path alone (/v1/messages=Claude, /v1/chat/completions=Codex) - Add setup_proxy_targets() method that automatically sets current providers as proxy targets when starting proxy with takeover - Unify proxy toggle in SettingsPage to use takeover mode (same as main UI) - Fix error message extraction in useProxyStatus hooks - Fix provider switch logic to check both takeover flag AND proxy running state
Jason ·
2025-12-10 19:58:43 +08:00 -
Feat/auto failover (#367)
* feat(db): add circuit breaker config table and provider proxy target APIs Add database support for auto-failover feature: - Add circuit_breaker_config table for storing failover thresholds - Add get/update_circuit_breaker_config methods in proxy DAO - Add reset_provider_health method for manual recovery - Add set_proxy_target and get_proxy_targets methods in providers DAO for managing multi-provider failover configuration * feat(proxy): implement circuit breaker and provider router for auto-failover Add core failover logic: - CircuitBreaker: Tracks provider health with three states: - Closed: Normal operation, requests pass through - Open: Circuit broken after consecutive failures, skip provider - HalfOpen: Testing recovery with limited requests - ProviderRouter: Routes requests across multiple providers with: - Health tracking and automatic failover - Configurable failure/success thresholds - Auto-disable proxy target after reaching failure threshold - Support for manual circuit breaker reset - Export new types in proxy module * feat(proxy): add failover Tauri commands and integrate with forwarder Expose failover functionality to frontend: - Add Tauri commands: get_proxy_targets, set_proxy_target, get_provider_health, reset_circuit_breaker, get/update_circuit_breaker_config, get_circuit_breaker_stats - Register all new commands in lib.rs invoke handler - Update forwarder with improved error handling and logging - Integrate ProviderRouter with proxy server startup - Add provider health tracking in request handlers * feat(frontend): add failover API layer and TanStack Query hooks Add frontend data layer for failover management: - Add failover.ts API: Tauri invoke wrappers for all failover commands - Add failover.ts query hooks: TanStack Query mutations and queries - useProxyTargets, useProviderHealth queries - useSetProxyTarget, useResetCircuitBreaker mutations - useCircuitBreakerConfig query and mutation - Update queries.ts with provider health query key - Update mutations.ts to invalidate health on provider changes - Add CircuitBreakerConfig and ProviderHealth types * feat(ui): add auto-failover configuration UI and provider health display Add comprehensive UI for failover management: Components: - ProviderHealthBadge: Display provider health status with color coding - CircuitBreakerConfigPanel: Configure failure/success thresholds, timeout duration, and error rate limits - AutoFailoverConfigPanel: Manage proxy targets with drag-and-drop priority ordering and individual enable/disable controls - ProxyPanel: Integrate failover tabs for unified proxy management Provider enhancements: - ProviderCard: Show health badge and proxy target indicator - ProviderActions: Add "Set as Proxy Target" action - EditProviderDialog: Add is_proxy_target toggle - ProviderList: Support proxy target filtering mode Other: - Update App.tsx routing for settings integration - Update useProviderActions hook with proxy target mutation - Fix ProviderList tests for updated component API * fix(usage): stabilize date range to prevent infinite re-renders * feat(backend): add tool version check command Add get_tool_versions command to check local and latest versions of Claude, Codex, and Gemini CLI tools: - Detect local installed versions via command line execution - Fetch latest versions from npm registry (Claude, Gemini) and GitHub releases API (Codex) - Return comprehensive version info including error details for uninstalled tools - Register command in Tauri invoke handler * style(ui): format accordion component code style Apply consistent code formatting to accordion component: - Convert double quotes to semicolons at line endings - Adjust indentation to 2-space standard - Align with project code style conventions * refactor(providers): update provider card styling to use theme tokens Replace hardcoded color classes with semantic design tokens: - Use bg-card, border-border, text-card-foreground instead of glass-card - Replace gray/white color literals with muted/foreground tokens - Change proxy target indicator color from purple to green - Improve hover states with border-border-active - Ensure consistent dark mode support via CSS variables * refactor(proxy): simplify auto-failover config panel structure Restructure AutoFailoverConfigPanel for better integration: - Remove internal Card wrapper and expansion toggle (now handled by parent) - Extract enabled state to props for external control - Simplify loading state display - Clean up redundant CardHeader/CardContent wrappers - ProxyPanel: reduce complexity by delegating to parent components * feat(settings): enhance settings page with accordion layout and tool versions Major settings page improvements: AboutSection: - Add local tool version detection (Claude, Codex, Gemini) - Display installed vs latest version comparison with visual indicators - Show update availability badges and environment check cards SettingsPage: - Reorganize advanced settings into collapsible accordion sections - Add proxy control panel with inline status toggle - Integrate auto-failover configuration with accordion UI - Add database and cost calculation config sections DirectorySettings & WindowSettings: - Minor styling adjustments for consistency settings.ts API: - Add getToolVersions() wrapper for new backend command * refactor(usage): restructure usage dashboard components Comprehensive usage statistics panel refactoring: UsageDashboard: - Reorganize layout with improved section headers - Add better loading states and empty state handling ModelStatsTable & ProviderStatsTable: - Minor styling updates for consistency ModelTestConfigPanel & PricingConfigPanel: - Simplify component structure - Remove redundant Card wrappers - Improve form field organization RequestLogTable: - Enhance table layout with better column sizing - Improve pagination controls UsageSummaryCards: - Update card styling with semantic tokens - Better responsive grid layout UsageTrendChart: - Refine chart container styling - Improve legend and tooltip display * chore(deps): add accordion and animation dependencies Package updates: - Add @radix-ui/react-accordion for collapsible sections - Add cmdk for command palette support - Add framer-motion for enhanced animations Tailwind config: - Add accordion-up/accordion-down animations - Update darkMode config to support both selector and class - Reorganize color and keyframe definitions for clarity * style(app): update header and app switcher styling App.tsx: - Replace glass-header with explicit bg-background/80 backdrop-blur - Update navigation button container to use bg-muted AppSwitcher: - Replace hardcoded gray colors with semantic muted/foreground tokens - Ensure consistent dark mode support via CSS variables - Add group class for better hover state transitions
YoVinchen ·
2025-12-08 21:14:06 +08:00 -
Feat/proxy server (#355)
* feat(proxy): implement local HTTP proxy server with multi-provider failover Add a complete HTTP proxy server implementation built on Axum framework, enabling local API request forwarding with automatic provider failover and load balancing capabilities. Backend Implementation (Rust): - Add proxy server module with 7 core components: * server.rs: Axum HTTP server lifecycle management (start/stop/status) * router.rs: API routing configuration for Claude/OpenAI/Gemini endpoints * handlers.rs: Request/response handling and transformation * forwarder.rs: Upstream forwarding logic with retry mechanism (652 lines) * error.rs: Comprehensive error handling and HTTP status mapping * types.rs: Shared types (ProxyConfig, ProxyStatus, ProxyServerInfo) * health.rs: Provider health check infrastructure Service Layer: - Add ProxyService (services/proxy.rs, 157 lines): * Manage proxy server lifecycle * Handle configuration updates * Track runtime status and metrics Database Layer: - Add proxy configuration DAO (dao/proxy.rs, 242 lines): * Persist proxy settings (listen address, port, timeout) * Store provider priority and availability flags - Update schema with proxy_config table (schema.rs): * Support runtime configuration persistence Tauri Commands: - Add 6 command endpoints (commands/proxy.rs): * start_proxy_server: Launch proxy server * stop_proxy_server: Gracefully shutdown server * get_proxy_status: Query runtime status * get_proxy_config: Retrieve current configuration * update_proxy_config: Modify settings without restart * is_proxy_running: Check server state Frontend Implementation (React + TypeScript): - Add ProxyPanel component (222 lines): * Real-time server status display * Start/stop controls * Provider availability monitoring - Add ProxySettingsDialog component (420 lines): * Configuration editor (address, port, timeout) * Provider priority management * Settings validation - Add React hooks: * useProxyConfig: Manage proxy configuration state * useProxyStatus: Poll and display server status - Add TypeScript types (types/proxy.ts): * Define ProxyConfig, ProxyStatus interfaces Provider Integration: - Extend Provider model with availability field (providers.rs): * Track provider health for failover logic - Update ProviderCard UI to display proxy status - Integrate proxy controls in Settings page Dependencies: - Add Axum 0.7 (async web framework) - Add Tower 0.4 (middleware and service abstractions) - Add Tower-HTTP (CORS layer) - Add Tokio sync primitives (oneshot, RwLock) Technical Details: - Graceful shutdown via oneshot channel - Shared state with Arc<RwLock<T>> for thread-safe config updates - CORS enabled for cross-origin frontend access - Request/response streaming support - Automatic retry with exponential backoff (forwarder) - API key extraction from multiple config formats (Claude/Codex/Gemini) File Statistics: - 41 files changed - 3491 insertions(+), 41 deletions(-) - Core modules: 1393 lines (server + forwarder + handlers) - Frontend UI: 642 lines (ProxyPanel + ProxySettingsDialog) - Database/DAO: 326 lines This implementation provides the foundation for advanced features like: - Multi-provider load balancing - Automatic failover on provider errors - Request logging and analytics - Usage tracking and cost monitoring * fix(proxy): resolve UI/UX issues and database constraint error Simplify proxy control interface and fix database persistence issues: Backend Fixes: - Fix NOT NULL constraint error in proxy_config.created_at field * Use COALESCE to preserve created_at on updates * Ensure proper INSERT OR REPLACE behavior - Remove redundant enabled field validation on startup * Auto-enable when user clicks start button * Persist enabled state after successful start - Preserve enabled state during config updates * Prevent accidental service shutdown on config save Frontend Improvements: - Remove duplicate proxy enable switch from settings dialog * Keep only runtime toggle in ProxyPanel * Simplify user experience with single control point - Hide proxy target button when proxy service is stopped * Add isProxyRunning prop to ProviderCard * Conditionally render proxy controls based on service status - Update form schema to omit enabled field * Managed automatically by backend Files: 5 changed, 81 insertions(+), 94 deletions(-) * fix(proxy): improve URL building and Gemini request handling - Refactor URL construction with version path deduplication (/v1, /v1beta) - Preserve query parameters for Gemini API requests - Support GOOGLE_GEMINI_API_KEY field name (with fallback) - Change default proxy port from 5000 to 15721 - Fix test: use Option type for is_proxy_target field * refactor(proxy): remove unused request handlers and routes - Remove unused GET/DELETE request forwarding methods - Remove count_tokens, get/delete response handlers - Simplify router by removing unused endpoints - Keep only essential routes: /v1/messages, /v1/responses, /v1beta/* * Merge branch 'main' into feat/proxy-server * fix(proxy): resolve clippy warnings for dead code and uninlined format args - Add #[allow(dead_code)] to unused ProviderUnhealthy variant - Inline format string arguments in handlers.rs and codex.rs log macros - Refactor error response handling to properly pass through upstream errors - Add URL deduplication logic for /v1/v1 paths in CodexAdapter * feat(proxy): implement provider adapter pattern with OpenRouter support This major refactoring introduces a modular provider adapter architecture to support format transformation between different AI API formats. New features: - Add ProviderAdapter trait for unified provider abstraction - Implement Claude, Codex, and Gemini adapters with specific logic - Add Anthropic ↔ OpenAI format transformation for OpenRouter compatibility - Support model mapping from provider configuration (ANTHROPIC_MODEL, etc.) - Add OpenRouter preset to Claude provider presets Refactoring: - Extract authentication logic into auth.rs with AuthInfo and AuthStrategy - Move URL building and request transformation to individual adapters - Simplify ProviderRouter to only use proxy target providers - Refactor RequestForwarder to use adapter-based request/response handling - Use whitelist mode for header forwarding (only pass necessary headers) Architecture: - providers/adapter.rs: ProviderAdapter trait definition - providers/auth.rs: AuthInfo, AuthStrategy types - providers/claude.rs: Claude adapter with OpenRouter detection - providers/codex.rs: Codex (OpenAI) adapter - providers/gemini.rs: Gemini (Google) adapter - providers/models/: Anthropic and OpenAI API data models - providers/transform.rs: Bidirectional format transformation * feat(proxy): add streaming SSE transform and thinking parameter support New features: - Add OpenAI → Anthropic SSE streaming response transformation - Support thinking parameter detection for reasoning model selection - Add ANTHROPIC_REASONING_MODEL config option for extended thinking Changes: - streaming.rs: Implement SSE event parsing and Anthropic format conversion - transform.rs: Add thinking detection logic and reasoning model mapping - handlers.rs: Integrate streaming transform for OpenRouter compatibility - Cargo.toml: Add async-stream and bytes dependencies * feat(db): add usage tracking schema and types Add database tables for proxy request logs and model pricing. Extend Provider and error types to support usage statistics. * feat(proxy): implement usage tracking subsystem Add request logger with automatic cost calculation. Implement token parser for Claude/OpenAI/Gemini responses. Add cost calculator based on model pricing configuration. * feat(proxy): integrate usage logging into request handlers Add usage logging to forwarder and streaming handlers. Track token usage and costs for each proxy request. * feat(commands): add usage statistics Tauri commands Register usage commands for summary, trends, logs, and pricing. Expose usage stats service through Tauri command layer. * feat(api): add frontend usage API and query hooks Add TypeScript types for usage statistics. Implement usage API with Tauri invoke calls. Add TanStack Query hooks for usage data fetching. * feat(ui): add usage dashboard components Add UsageDashboard with summary cards, trend chart, and data tables. Implement model pricing configuration panel. Add request log viewer with filtering and detail panel. * fix(ui): integrate usage dashboard and fix type errors Add usage dashboard tab to settings page. Fix UsageScriptModal TypeScript type annotations. * deps: add recharts for charts and rust_decimal/uuid for usage tracking - recharts: Chart visualization for usage trends - rust_decimal: Precise cost calculations - uuid: Request ID generation * feat(proxy): add ProviderType enum for fine-grained provider detection Introduce ProviderType enum to distinguish between different provider implementations (Claude, ClaudeAuth, Codex, Gemini, GeminiCli, OpenRouter). This enables proper authentication handling and request transformation based on the actual provider type rather than just AppType. - Add ProviderType enum with detection logic from config - Enhance Claude adapter with OpenRouter detection - Enhance Gemini adapter with CLI mode detection - Add helper methods for provider type inference * feat(database): extend schema with streaming and timing fields Add new columns to proxy_request_logs table for enhanced usage tracking: - first_token_ms and duration_ms for performance metrics - provider_type and is_streaming for request classification - cost_multiplier for flexible pricing Update model pricing with accurate rates for Claude/GPT/Gemini models. Add ensure_model_pricing_seeded() call on database initialization. Add test for model pricing auto-seeding verification. * feat(proxy/usage): enhance token parser and logger for multi-format support Parser enhancements: - Add OpenAI Chat Completions format parsing (prompt_tokens/completion_tokens) - Add model field to TokenUsage for actual model name extraction - Add from_codex_response_adjusted() for proper cache token handling - Add debug logging for better stream event tracing Logger enhancements: - Add first_token_ms, provider_type, is_streaming, cost_multiplier fields - Extend RequestLog struct with full metadata tracking - Update log_with_calculation() signature for new fields Calculator: Update tests with model field in TokenUsage. * feat(proxy): enhance proxy server with session tracking and OpenAI route Error handling: - Add StreamIdleTimeout and AuthError variants for better error classification Module exports: - Export ResponseType, StreamHandler, NonStreamHandler from response_handler - Export ProxySession, ClientFormat from session module Server routing: - Add /v1/chat/completions route for OpenAI Chat Completions API Handlers: - Add log_usage_with_session() for enhanced usage tracking with session context - Add first_token_ms timing measurement for streaming responses - Use SseUsageCollector with start_time for accurate latency calculation - Track is_streaming flag in usage logs * feat(services): add pagination and enhanced filtering for request logs Usage stats service: - Change get_request_logs() from limit/offset to page/page_size pagination - Return PaginatedLogs with total count, page, and page_size - Add appType and providerName filters with LIKE search - Add is_streaming, first_token_ms, duration_ms to RequestLogDetail - Join with providers table for provider name lookup Commands: - Update get_request_logs command signature for pagination params Module exports: - Export PaginatedLogs struct * feat(frontend): update usage types and API for pagination support Types (usage.ts): - Add isStreaming, firstTokenMs, durationMs to RequestLog - Add PaginatedLogs interface with data, total, page, pageSize - Change LogFilters: providerId -> appType + providerName API (usage.ts): - Change getRequestLogs params from limit/offset to page/pageSize - Return PaginatedLogs instead of RequestLog[] - Pass filters object directly to backend Query (usage.ts): - Update usageKeys.logs key generation for pagination - Update useRequestLogs hook signature * refactor(ui): enhance RequestLogTable with filtering and pagination UI improvements: - Add filter bar with app type, provider name, model, status selectors - Add date range picker (startDate/endDate) - Add search/reset/refresh buttons Pagination: - Implement proper page-based pagination with page info display - Show total count and current page range - Add prev/next navigation buttons Features: - Default to last 24 hours filter - Streamlined table columns layout - Query invalidation on refresh * style(config): format mcpPresets code style Apply consistent formatting to createNpxCommand function and sequential-thinking server configuration. * fix(ui): update SettingsPage tab styles for improved appearance (#342) * feat(model-test): add provider model availability testing Implement standalone model testing feature to verify provider API connectivity: - Add ModelTestService for Claude/Codex/Gemini endpoint testing - Create model_test_logs table for test result persistence - Add test button to ProviderCard with loading state - Include ModelTestConfigPanel for customizing test parameters * fix(proxy): resolve token parsing for OpenRouter streaming responses Problem: - OpenRouter and similar third-party services return streaming responses where input_tokens appear in message_delta instead of message_start - The previous implementation only extracted input_tokens from message_start, causing input_tokens to be recorded as 0 for these providers Changes: - streaming.rs: Add prompt_tokens field to Usage struct and include input_tokens in the transformed message_delta event when converting OpenAI format to Anthropic format - parser.rs: Update from_claude_stream_events() to handle input_tokens from both message_start (native Claude API) and message_delta (OpenRouter) - Use if-let pattern instead of direct unwrap for safer parsing - Only update input_tokens from message_delta if not already set - logger.rs: Adjust test parameters to match updated function signature Tests: - Add test_openrouter_stream_parsing() for OpenRouter format validation - Add test_native_claude_stream_parsing() for native Claude API validation * fix(pricing): standardize model ID format for pricing lookup Normalize model IDs by removing vendor prefixes and converting dots to hyphens to ensure consistent pricing lookups across different API response formats. Changes: - Update seed data to use hyphen format (e.g., gpt-5-1, gemini-2-5-pro) - Add normalize_model_id() function to strip vendor prefixes (anthropic/, openai/) - Convert dots to hyphens in model IDs (claude-haiku-4.5 → claude-haiku-4-5) - Try both original and normalized IDs for exact matching - Use normalized ID for suffix-based fallback matching - Add comprehensive test cases for prefix and dot handling - Add warning log when no pricing found This ensures pricing lookups work correctly for: - Models with vendor prefixes: anthropic/claude-haiku-4.5 - Models with dots in version: claude-sonnet-4.5 - Models with date suffixes: claude-haiku-4-5-20240229 * style(rust): apply clippy formatting suggestions Apply automatic clippy fixes for uninlined_format_args warnings across Rust codebase. Replace format string placeholders with inline variable syntax for improved readability. Changes: - Convert format!("{}", var) to format!("{var}") - Apply to model_test.rs, parser.rs, and usage_stats.rs - Fix line length issues by breaking long function calls - Improve code formatting consistency All changes are automatic formatting with no functional impact. * fix(ui): restore card borders in usage statistics panels Restore proper card styling for ModelTestConfigPanel and PricingConfigPanel by adding back border and rounded-lg classes. The transparent background styling was causing visual inconsistency. Changes: - Replace border-none bg-transparent shadow-none with border rounded-lg - Apply to both loading and error states for consistency - Format TypeScript code for better readability - Break long function signatures across multiple lines This ensures the usage statistics panels have consistent visual appearance with proper borders and rounded corners. * feat(pricing): add GPT-5 Codex model pricing presets Add pricing configuration for GPT-5 Codex variants to support cost tracking for Codex-specific models. Changes: - Add gpt-5-codex model with standard GPT-5 pricing - Add gpt-5-1-codex model with standard GPT-5.1 pricing - Input: $1.25/M tokens, Output: $10/M tokens - Cache read: $0.125/M tokens, Cache creation: $0 This ensures accurate cost calculation for Codex API requests using GPT-5 Codex models.
YoVinchen ·
2025-12-05 11:26:41 +08:00