mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 21:30:17 +08:00
7cbdae9eca0aa8ce58827f2cf3735a6aeb5f6c84
24 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4282856683 |
feat(usage): persist pricing basis and takeover dimensions in storage (schema v11)
- proxy_request_logs: add pricing_model column recording the basis actually used at write time (NULL = pre-v11 rows, '' = unpriced error rows) - cost backfill recomputes strictly by the persisted basis; the request_model fallback now only applies to placeholder models, so real-but-unpriced takeover rows stay at zero cost until pricing is added instead of being permanently frozen at the alias's price - backfill_missing_usage_costs_for_model can locate rows by pricing_model - usage_daily_rollups: rebuild with request_model + pricing_model in the primary key so the alias-to-real-model mapping and the pricing basis survive the 30-day prune; legacy rows migrate with '' - rollup_and_prune backfills costs before pruning: prune is irreversible and used to run before the startup backfill, permanently booking then-unpriced rows as zero - get_model_stats groups by the effective pricing model (COALESCE(NULLIF(pricing_model,''), model)) so costs aggregate under the model whose prices produced them; response-mode behavior unchanged |
||
|
|
2a24da517f |
feat: 新增 S3 兼容云存储同步 (#1351)
* Add S3 Cloud Sync design document Design for adding AWS S3 as a new Cloud Sync backend alongside WebDAV. Hybrid approach: extract shared sync protocol, add independent S3 transport. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add S3 cloud sync implementation design (reqwest + Sig V4) Updated design based on 2026-03-06 draft: switches from rust-s3 crate to hand-rolled AWS Sig V4 on existing reqwest for broader S3-compatible service support (AWS, MinIO, R2, Alibaba OSS, Tencent COS, Huawei OBS). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add S3 cloud sync implementation plan (11 tasks, TDD) Detailed step-by-step plan covering: sync_protocol extraction, S3 Sig V4 transport, settings, sync/auto-sync modules, Tauri commands, frontend presets/dynamic form, and i18n. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * deps: add hmac crate for S3 Sig V4 signing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract sync_protocol.rs from webdav_sync.rs for shared use Move transport-agnostic sync protocol logic (constants, types, snapshot building, manifest validation, artifact verification, snapshot application, utilities) into a new shared sync_protocol module so both WebDAV and the upcoming S3 transport can reuse it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use transport-neutral error keys in sync_protocol Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add S3 transport layer with AWS Sig V4 signing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add S3SyncSettings to AppSettings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add S3 sync module with upload/download/fetch Implements the S3 sync protocol layer (s3_sync.rs) that combines the shared sync_protocol with the S3 transport. Mirrors the WebDAV sync module structure with independent sync mutex, connection check, upload, download, fetch_remote_info, and sync status persistence. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add S3 auto sync worker with debounce Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add S3 sync Tauri commands and auto sync worker startup Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add S3 sync TypeScript types and API layer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add S3 sync i18n translations (en/zh/ja) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add S3 sync presets and dynamic form to sync settings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: preserve HTTP scheme for S3 custom endpoints (MinIO support) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add live S3 integration tests (env-var driven, --ignored) Run with: S3_TEST_AK=... S3_TEST_SK=... S3_TEST_BUCKET=... cargo test --lib services::s3::integration_tests -- --ignored Verifies test_connection, put_object, get_object, head_object, and 404 handling against a real S3 bucket using the project's own Sig V4 signing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove internal design docs before PR * fix: wire S3 auto-sync to DB hook & sync UI state on async load - P1: Add s3_auto_sync::notify_db_changed call in SQLite update_hook so S3 auto-sync worker receives DB change signals (was only wired for WebDAV, leaving S3 worker idle) - P2: Add useEffect to update syncType selector when s3Config loads asynchronously, preventing stale "webdav" default for S3 users * fix: satisfy clippy for s3 sync * fix: address s3 sync review feedback --------- Co-authored-by: Keith (via OpenClaw) <keithyt06@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jason <farion1231@gmail.com> |
||
|
|
b44f83f7c5 |
feat: unify Codex third-party providers into stable "custom" history bucket
Codex filters resume history by `model_provider`, so switching between provider-specific ids like `rightcode` and `aihubmix` made past sessions appear to vanish. Collapse all third-party providers into a single stable bucket so cross-switch history stays visible. - Normalize live `model_provider` to "custom" on every Codex write (reserved built-in ids like openai/ollama are preserved). - Add device-level one-shot migration that rewrites historical JSONL session files and the `state_5.sqlite` threads table from legacy provider ids into the "custom" bucket. Backs up originals under `~/.cc-switch/backups/codex-history-provider-migration-v1/` and uses the SQLite Backup API for the state DB. - Record completion in `settings.json` under `localMigrations` so the migration is strictly idempotent across launches. - Update Codex provider preset templates to emit `model_provider = "custom"` out of the box. |
||
|
|
402570ce31 |
fix(usage): pricing routing, SSE lifecycle, and validation hardening
* model pricing routing: extend prefix-match families (gpt-/o1-o5/
gemini-/deepseek-/qwen-/glm-/kimi-/minimax-) with per-family dash
thresholds so short base IDs like gpt-5 no longer mis-match
gpt-5-mini; strip ISO and 8-digit date suffixes via UTF-8-safe
byte matching so claude-haiku-4-5-20251001 falls back to
claude-haiku-4-5 pricing
* SSE collector: SseUsageFinishGuard (RAII) guarantees finish() on
early return or panic; AtomicBool fast path lets push() skip the
Mutex once first-event time is recorded
* validation: shared validate_cost_multiplier / validate_pricing_source
helpers across DAO and service layers; PRICING_SOURCE_RESPONSE /
PRICING_SOURCE_REQUEST constants replace string literals; price
fields in update_model_pricing now reject empty / non-decimal /
negative input before INSERT
* backfill: add backfill_missing_usage_costs_for_model so a single
price edit only scans matching rows instead of the full log table;
startup backfill remains full-scan
* session_usage{,_codex,_gemini}: share find_model_pricing helper from
usage_stats; metadata_modified_nanos centralizes mtime precision
* frontend: NON_NEGATIVE_DECIMAL_REGEX + isNonNegativeDecimalString
replace three copies of the same multiplier regex; isUnpricedUsage
surfaces zero-cost rows that have usage tokens (cached per row to
avoid double evaluation); invalidate usageKeys.all on pricing mutate
so backfilled rows refresh
|
||
|
|
8b3ad9caf9 |
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.
|
||
|
|
a2e9e1938b |
feat: add database migration v9→v10 for Hermes support (Phase 2)
- Bump SCHEMA_VERSION from 9 to 10 - Add enabled_hermes column to mcp_servers and skills tables - Add migrate_v9_to_v10 with table_exists guard for skills (may not exist in databases migrated from very old versions) - Update dao/mcp.rs to fully read/write enabled_hermes in all queries - Update dao/skills.rs: don't SELECT enabled_hermes (Hermes doesn't support Skills yet), keep column indices clean |
||
|
|
bb7c83c214 |
feat(pricing): add ~50 new model pricing entries and fix outdated prices
Add pricing data for 4 new providers (Qwen, xAI Grok, Mistral, Cohere) and supplement existing providers (MiniMax M2.5/M2.7, GLM-5/5.1, Doubao Seed 2.0, MiMo V2 Pro, OpenAI o1/o3/codex-mini/gpt-5-mini/nano). Fix outdated prices for deepseek-chat, deepseek-reasoner, and kimi-k2.5. Fix display_name casing "Mimo" → "MiMo" for consistency. Use prepared statement in seed_model_pricing() to avoid recompiling SQL on each of ~130 INSERT iterations. Schema migration v8→v9: DELETE + re-seed model_pricing for existing users. |
||
|
|
154342ca00 |
feat: add session log usage tracking without proxy
Parse Claude Code JSONL session files (~/.claude/projects/) and Codex SQLite database (~/.codex/state_5.sqlite) to track API usage without requiring proxy interception. This enables usage statistics for users who don't use the proxy feature. Key changes: - Add session_usage.rs: incremental JSONL parser with message.id dedup - Add session_usage_codex.rs: import thread-level token data from Codex - Add data_source column to proxy_request_logs (proxy/session_log/codex_db) - Add session_log_sync table for tracking parse offsets - Background sync every 60s + manual sync via DataSourceBar UI - Schema migration v7→v8 - i18n support for zh/en/ja |
||
|
|
e3179ad9e4 |
feat: add skill update detection via SHA-256 content hashing
- Add content_hash and updated_at fields to skills table (DB migration v6→v7) - Compute directory content hash on install/import/restore for version tracking - Add check_updates command: downloads repos, compares hashes, returns update list - Add update_skill command: backs up old files, re-downloads and replaces SSOT - Backfill content_hash for existing skills on first update check - Add "Check Updates" button and per-skill update badge/button in UnifiedSkillsPanel - Add i18n keys for zh/en/ja |
||
|
|
bf40b0138c |
feat: add usage daily rollups, incremental auto-vacuum, and sync-aware backup
- Add usage_daily_rollups table (schema v6) to aggregate proxy request logs into daily summaries, reducing query overhead for statistics - Add rollup_and_prune DAO that aggregates old detail logs (>N days) into rollup rows and deletes the originals - Update all usage stats queries to UNION detail logs with rollup data - Introduce incremental auto-vacuum for SQLite, with startup and periodic cleanup of old stream_check_logs and request log rollups - Split backup export/import into full vs sync variants: WebDAV sync now skips local-only table data (proxy_request_logs, stream_check_logs, provider_health, proxy_live_backup, usage_daily_rollups) while preserving them on import - Add enable_logging guard to skip request log writes when disabled - Apply cargo fmt formatting fixes across multiple modules |
||
|
|
e7766d4d22 |
refactor: remove OMO common config two-layer merge system
Each OMO provider now stores its complete configuration directly in settings_config.otherFields instead of relying on a shared OmoGlobalConfig merged at write time. This simplifies the data flow from a 4-tuple (agents, categories, otherFields, useCommonConfig) to a 3-tuple and eliminates an entire DB table, two Tauri commands, and ~1700 lines of merge/sync code across frontend and backend. Backend: - Delete database/dao/omo.rs (OmoGlobalConfig struct + get/save methods) - Remove get/set_config_snippet from settings DAO - Remove get/set_common_config_snippet Tauri commands - Replace merge_config() with build_config() in services/omo.rs - Simplify OmoVariant (remove config_key, known_keys) - Simplify import_from_local and build_local_file_data - Rewrite all OMO service tests Frontend: - Delete OmoCommonConfigEditor.tsx and OmoGlobalConfigFields.tsx - Delete src/lib/api/config.ts - Remove OmoGlobalConfig type and merge preview functions - Remove useGlobalConfig/useSaveGlobalConfig query hooks - Simplify useOmoDraftState (remove all common config state) - Replace OmoCommonConfigEditor with read-only JsonEditor preview - Clean i18n keys (zh/en/ja) |
||
|
|
f8820aa22c |
feat(backup): add independent backup panel, configurable policy, and rename support
Extract backup & restore into a standalone AccordionItem in Advanced settings. Add configurable auto-backup interval (disabled/6h/12h/24h/48h/7d) and retention count (3-50) via settings. Add per-backup rename with inline editing UI. |
||
|
|
3afec8a10f |
feat(backup): add pre-migration backup, periodic backup, backfill warning, and backup management UI
Four improvements to the database backup mechanism: 1. Auto backup before schema migration - creates a snapshot when upgrading from an older database version, providing a safety net beyond the existing SAVEPOINT rollback mechanism. 2. Periodic startup backup - checks on app launch whether the latest backup is older than 24 hours and creates a new one if needed, ensuring all users have recent backups regardless of usage patterns. 3. Backfill failure notification - switch now returns SwitchResult with warnings instead of silently ignoring backfill errors, so users are informed when their manual config changes may not have been saved. 4. Backup management UI - new BackupListSection in Settings > Data Management showing all backup snapshots with restore capability, including a confirmation dialog and automatic safety backup before restore. |
||
|
|
20f62bf4f8 |
feat(webdav): follow-up 补齐自动同步与大文件防护 (#1043)
* feat(webdav): add robust auto sync with failure feedback (cherry picked from commit bb6760124a62a964b36902c004e173534910728f) * fix(webdav): enforce bounded download and extraction size (cherry picked from commit 7777d6ec2b9bba07c8bbba9b04fe3ea6b15e0e79) * fix(webdav): only show auto-sync callout for auto-source errors * refactor(webdav): remove services->commands auto-sync dependency |
||
|
|
28b125b34f |
fix(openclaw): remove MCP/Skills/Prompts support from OpenClaw
OpenClaw only needs provider management functionality, not MCP, Skills, or Prompts features. This commit removes the incorrectly added support: - Revert SCHEMA_VERSION from 6 to 5 (remove v5->v6 migration) - Remove enabled_openclaw field from mcp_servers and skills tables - Remove openclaw field from McpApps and SkillApps structs - Update DAO queries to exclude enabled_openclaw column - Fix frontend components and types to exclude openclaw from MCP/Prompts - Update all related test files |
||
|
|
7f46a0b910 |
feat(core): add OpenClaw to AppType enum and database schema
- Add OpenClaw variant to AppType enum - Update is_additive_mode() to return true for OpenClaw - Update McpApps, SkillApps, McpRoot, PromptRoot structs - Add database migration v5 to v6 for enabled_openclaw columns - Update mcp_servers and skills table definitions |
||
|
|
ed47480fc7 |
feat(omo): integrate Oh My OpenCode profile management (#972)
* feat(omo): integrate Oh My OpenCode profile management into Provider system Adds full-stack OMO support: backend config read/write/import, OMO-specific provider CRUD with exclusive switching, frontend profile editor with agent/category/model configuration, global config management, and i18n support. * feat(omo): add model/variant dropdowns from enabled providers Replace model text inputs with Select dropdowns sourced from enabled OpenCode providers, add thinking-level variant selection, and prevent auto-enabling newly added OMO providers. * fix(omo): use standard provider action styles for OMO switch button * fix(omo): replace hardcoded isZh strings with proper i18n t() calls |
||
|
|
785e1b5add |
Feat/pricing config enhancement (#781)
* feat(db): add pricing config fields to proxy_config table - Add default_cost_multiplier field per app type - Add pricing_model_source field (request/response) - Add request_model field to proxy_request_logs table - Implement schema migration v5 * feat(api): add pricing config commands and provider meta fields - Add get/set commands for default cost multiplier - Add get/set commands for pricing model source - Extend ProviderMeta with cost_multiplier and pricing_model_source - Register new commands in Tauri invoke handler * fix(proxy): apply cost multiplier to total cost only - Move multiplier calculation from per-item to total cost - Add resolve_pricing_config for provider-level override - Include request_model and cost_multiplier in usage logs - Return new fields in get_request_logs API * feat(ui): add pricing config UI and usage log enhancements - Add pricing config section to provider advanced settings - Refactor PricingConfigPanel to compact table layout - Display all three apps (Claude/Codex/Gemini) in one view - Add multiplier column and request model display to logs - Add frontend API wrappers for pricing config * feat(i18n): add pricing config translations - Add zh/en/ja translations for pricing defaults config - Add translations for multiplier, requestModel, responseModel - Add provider pricing config translations * fix(pricing): align backfill cost calculation with real-time logic - Fix backfill to deduct cache_read_tokens from input (avoid double billing) - Apply multiplier only to total cost, not to each item - Add multiplier display in request detail panel with i18n support - Use AppError::localized for backend error messages - Fix init_proxy_config_rows to use per-app default values - Fix silent failure in set_default_cost_multiplier/set_pricing_model_source - Add clippy allow annotation for test mutex across await * style: format code with cargo fmt and prettier * fix(tests): correct error type assertions in proxy DAO tests The tests expected AppError::InvalidInput but the DAO functions use AppError::localized() which returns AppError::Localized variant. Updated assertions to match the correct error type with key validation. --------- Co-authored-by: Jason <farion1231@gmail.com> |
||
|
|
5658d93924 |
feat(opencode): Phase 1 - Backend data structure expansion for OpenCode support
Add OpenCode as the 4th supported application with additive provider management: - Add OpenCode variant to AppType enum with all related match statements - Add enabled_opencode field to McpApps and SkillApps structures - Add opencode field to McpRoot and PromptRoot - Add database schema migration v3→v4 with enabled_opencode columns - Add settings.rs support for opencode_config_dir and current_provider_opencode - Create opencode_config.rs module for config file I/O operations - Update all services (proxy, mcp, skill, provider, stream_check) for OpenCode - Add OpenCode support to deeplink provider and MCP parsing - Update commands/config.rs for OpenCode config status and paths Key design decisions: - OpenCode uses additive mode (no is_current needed, no proxy support) - Config path: ~/.config/opencode/opencode.json - MCP format: stdio→local, sse/http→remote conversion planned - Stream check returns error (not yet implemented for OpenCode) |
||
|
|
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 |
||
|
|
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 |
||
|
|
b1103c8a59 |
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. |
||
|
|
1ee1e9cb2e |
refactor(startup): improve first-launch import logic with per-table detection
- Replace global `is_empty_for_first_import()` with independent checks: - `is_mcp_table_empty()` for MCP server imports - `is_prompts_table_empty()` for prompt imports - Skills and providers already have built-in idempotency checks - Fix misleading logs in provider import: - Change `import_default_config` return type from `Result<()>` to `Result<bool>` - Return `true` when actually imported, `false` when skipped - Only log success message when import actually occurred - Add idempotency protection to `import_from_file_on_first_launch` This allows each data type to be independently recovered if deleted, rather than requiring all tables to be empty for any import to trigger. |
||
|
|
c3f2f0798d |
refactor(database): split monolithic database.rs into modular structure
Split the 1788-line database.rs into a well-organized module directory: - mod.rs (142 lines): Database struct and initialization - schema.rs (341 lines): Table creation and schema migrations - backup.rs (324 lines): SQL import/export and snapshot backup - migration.rs (240 lines): JSON to SQLite data migration - tests.rs (280 lines): Unit tests - dao/providers.rs (254 lines): Provider CRUD operations - dao/mcp.rs (97 lines): MCP server CRUD operations - dao/prompts.rs (88 lines): Prompt CRUD operations - dao/skills.rs (124 lines): Skills CRUD operations - dao/settings.rs (65 lines): Settings key-value storage Benefits: - Max file size reduced from 1788 to 341 lines - Clear separation of concerns (schema, backup, migration, DAOs) - Easier to navigate and maintain - All 107 tests passing with zero API changes |