mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-04 19:45:34 +08:00
cf978c1346db4799dbb60585f6fac1b0d4497179
13 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4f78451405 |
storage(pi): isolate typed provider writes and canonical restore
Replace the generic Provider save/upsert surface with strict typed create/update/rename/endpoint operations. Keep aggregate hydration read-only, preserve nullable endpoint timestamps end to end, and make service create own the initial endpoint set atomically. Restore SQL and binary backups only through UntrustedScratch, migrate and copy fixed data columns into a fresh CanonicalStage, validate the canonical result, then publish through the Backup API. The imported schema is never eligible to become the live schema. Old save_provider callsite classification ========================================== Inventory authority: abandoned 5a385fc8 tree. The old definition at src-tauri/src/database/dao/providers.rs:180 is deleted and is not a callsite. Production callsites: - src-tauri/src/commands/provider.rs:253 [create] Claude Desktop import creates one absent aggregate; it now strict-inserts the row and initial endpoints in one transaction. - src-tauri/src/database/dao/providers.rs:638 [create] official seed first proves absence, then strict-creates; a racing insert is a conflict. - src-tauri/src/database/dao/providers.rs:704 [create] on-demand seed first proves absence, then strict-creates; it cannot overwrite an existing row. - src-tauri/src/services/omo.rs:291 [create] OMO import constructs a new aggregate and strict-creates it; OMO is not eligible for rename. - src-tauri/src/services/provider/endpoints.rs:85 [update] endpoint last-used is not a Provider-row save; it now calls the exact touch endpoint operation. - src-tauri/src/services/provider/live.rs:1567 [create/update] default live import is reconciliation: read first, then strict create or strict update. - src-tauri/src/services/provider/live.rs:1743 [update] an existing OpenCode live provider follows the strict row-update branch. - src-tauri/src/services/provider/live.rs:1770 [create] a new OpenCode live provider follows the strict aggregate-create branch. - src-tauri/src/services/provider/live.rs:1825 [update] an existing OpenClaw live provider follows the strict row-update branch. - src-tauri/src/services/provider/live.rs:1858 [create] a new OpenClaw live provider follows the strict aggregate-create branch. - src-tauri/src/services/provider/live.rs:1900 [update] an existing Hermes live provider follows the strict row-update branch. - src-tauri/src/services/provider/live.rs:1926 [create] a new Hermes live provider follows the strict aggregate-create branch. - src-tauri/src/services/provider/mod.rs:2568 [create] ProviderService::add owns strict aggregate creation and all initial endpoints. - src-tauri/src/services/provider/mod.rs:2680 [rename] an additive DB-only key change now uses the dedicated transactional rename after eligibility checks. - src-tauri/src/services/provider/mod.rs:2711 [update] OMO edit updates exactly the existing main row after its live-file coordination. - src-tauri/src/services/provider/mod.rs:2740 [update] additive-provider edit updates exactly the existing main row after resolving live ownership. - src-tauri/src/services/provider/mod.rs:2750 [update] switch-mode edit updates exactly the existing main row and never inserts. - src-tauri/src/services/provider/mod.rs:2948 [update] remove-from-live changes only the existing provider's live-managed marker. - src-tauri/src/services/provider/mod.rs:3120 [update] switch backfill updates only the existing current provider row. - src-tauri/src/services/provider/mod.rs:3174 [update] successful additive switch changes only the existing live-managed marker. - src-tauri/src/services/provider/mod.rs:3315 [update] common-config migration updates only each already-read existing row. - src-tauri/src/services/provider/mod.rs:3895 [update] Gemini credential scrub updates only each already-read existing row. - src-tauri/src/services/provider/mod.rs:4082 [update] sort ordering is routed to the dedicated sort-index state operation, not row replacement. - src-tauri/src/services/provider/mod.rs:4636 [create/update] universal-to- Claude reconciliation reads the target and selects strict create or update. - src-tauri/src/services/provider/mod.rs:4651 [create/update] universal-to- Codex reconciliation reads the target and selects strict create or update. - src-tauri/src/services/provider/mod.rs:4665 [create/update] universal-to- Gemini reconciliation reads the target and selects strict create or update. Required indirect ownership paths: - src-tauri/src/deeplink/provider.rs [create] the old indirect flow called ProviderService::add and then appended endpoints one by one. It now supplies every non-primary endpoint to one strict aggregate create, so hydration is complete atomically and a duplicate is zero-side-effect. - [restore] no old generic-save callsite is reclassified as restore. Exact aggregate replacement exists only as the sealed restore_provider_aggregate_on_tx compensation primitive. Test-only callsites: Every item below is classified [test]. Each is fixture setup, not a production write authority, and is migrated to a real ProviderService entry where the behavior is under test or to the cfg(test)-only typed fixture reconciler where the test merely needs pre-existing rows. - src-tauri/src/codex_history_migration.rs:1442 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:1452 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2174 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2176 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2199 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2219 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2247 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2267 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2288 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2320 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2393 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2449 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2498 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2555 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2604 [test] migration fixture setup. - src-tauri/src/codex_history_migration.rs:2625 [test] migration fixture setup. - src-tauri/src/database/dao/providers.rs:754 [test] DAO fixture setup. - src-tauri/src/proxy/provider_router.rs:351 [test] router fixture setup. - src-tauri/src/proxy/provider_router.rs:352 [test] router fixture setup. - src-tauri/src/proxy/provider_router.rs:377 [test] router fixture setup. - src-tauri/src/proxy/provider_router.rs:378 [test] router fixture setup. - src-tauri/src/proxy/provider_router.rs:410 [test] router fixture setup. - src-tauri/src/proxy/provider_router.rs:411 [test] router fixture setup. - src-tauri/src/proxy/provider_router.rs:447 [test] router fixture setup. - src-tauri/src/proxy/provider_router.rs:448 [test] router fixture setup. - src-tauri/src/proxy/provider_router.rs:488 [test] router fixture setup. - src-tauri/src/services/provider/mod.rs:485 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:586 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:813 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:825 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:1472 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:1607 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:1737 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:1945 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:1952 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:1978 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:2006 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:2056 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:2130 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:2167 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:2207 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:2235 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:2270 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:2320 [test] service fixture setup. - src-tauri/src/services/provider/mod.rs:2362 [test] service fixture setup. - src-tauri/src/services/proxy.rs:3762 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:3948 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:4034 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:4095 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:4114 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:4263 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:4341 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:4421 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:4533 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:4651 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:4787 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5264 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5320 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5385 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5387 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5460 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5462 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5611 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5613 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5615 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5698 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5700 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:5998 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6000 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6173 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6175 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6417 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6419 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6553 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6555 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6635 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6637 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:6919 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:7173 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:7175 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:7240 [test] proxy fixture setup. - src-tauri/src/services/proxy.rs:7242 [test] proxy fixture setup. - src-tauri/tests/profile_roundtrip.rs:112 [test] profile fixture create. - src-tauri/tests/profile_roundtrip.rs:116 [test] profile fixture create. - src-tauri/tests/profile_roundtrip.rs:126 [test] profile fixture create. - src-tauri/tests/profile_roundtrip.rs:133 [test] profile fixture create. - src-tauri/tests/profile_roundtrip.rs:292 [test] profile fixture create. - src-tauri/tests/profile_roundtrip.rs:501 [test] profile fixture create. - src-tauri/tests/profile_roundtrip.rs:505 [test] profile fixture create. - src-tauri/tests/profile_roundtrip.rs:670 [test] profile fixture create. - src-tauri/tests/profile_roundtrip.rs:677 [test] profile fixture create. - src-tauri/tests/profile_roundtrip.rs:762 [test] Linux Desktop fixture create. - src-tauri/tests/profile_roundtrip.rs:769 [test] Linux Desktop fixture create. - src-tauri/tests/provider_commands.rs:69 [test] command fixture create. - src-tauri/tests/provider_service.rs:2927 [test] service fixture create. |
||
|
|
1c0ee0c58a |
feat(grokbuild): add first-class Grok Build support (#5453)
* feat(grokbuild): add backend integration * feat(grokbuild): add provider and management UI * test(grokbuild): cover configuration and integrations * fix(grokbuild): address backend review feedback * fix(grokbuild): complete UI review feedback * feat(grokbuild): add CLI lifecycle management * fix(grokbuild): align provider icon fallback * test(grokbuild): cover provider icon persistence |
||
|
|
2d478876fa |
fix: align Claude MCP path for custom config dirs (#3431)
* fix claude mcp path for custom config dir * fix claude mcp custom profile isolation * fix claude mcp override path edges * fix ci test isolation |
||
|
|
60a9b330e5 |
Refactor Codex live-write routing and cover default auth overwrite
Collapse the two duplicated write_codex_live_atomic branches in
write_codex_live_for_provider into a single should_write_auth guard.
This is behavior-preserving: `if A {X} else if B {X} else {Y}` becomes
`if A || B {X} else {Y}`.
Adapt the Codex switch tests to the new opt-in default for
preserve_codex_official_auth_on_switch (flipped off in
|
||
|
|
dc04165f18 |
feat(tray): show cached provider usage in the system tray menu (#2184)
* feat: add Rust-side write-through usage cache Introduce an in-memory UsageCache on AppState that the existing usage query commands populate on success. The cache is read-only to the rest of the app today; the next commit consumes it from the tray menu. - New services::usage_cache module with split maps: subscription keyed by AppType, script keyed by (AppType, provider_id). - AppType gains Eq + Hash so it can be used as a HashMap key. - commands::subscription::get_subscription_quota now takes State<AppState> and writes through on success (signature change is invisible to the frontend — Tauri injects State automatically). - commands::provider::queryProviderUsage body extracted into an inner async fn; the public command wraps it with write-through, covering Copilot, coding-plan, balance, and generic script paths uniformly. Cache is in-memory only; auto-query interval and the upcoming tray refresh action rebuild it after restarts. * feat(tray): surface cached usage in the system tray menu Read UsageCache populated by the previous commit and render it in three places, scoped to whatever TRAY_SECTIONS covers (Claude/Codex/Gemini): 1. Inline suffix on each provider submenu item "AnyProvider · 🟢 5h 18% / 7d 23%" 2. Disabled summary row per visible app under "Show Main" "Claude · Anthropic Official · 🟢 5h 18% / 7d 23%" 3. "Refresh all usage" menu item that triggers get_subscription_quota + queryProviderUsage for every applicable provider, then rebuilds the tray menu via the existing refresh_tray_menu path. Color encoding uses emoji (🟢 <70% / 🟠 70-89% / 🔴 ≥90%) since Tauri 2 tray labels are plain text. Missing cache entry leaves the label unchanged — tray never issues network requests when opened. Three new i18n-ready strings live in TrayTexts (en/zh/ja), following the existing pattern for tray text. Closes #2178. * feat(usage): bridge tray UsageCache writes to frontend React Query Why: tray hover triggers backend-only refresh that wrote to UsageCache but never notified the frontend, leaving main UI stale while tray showed fresh numbers. Emit a payload-carrying event after each cache write so React Query can setQueryData directly, keeping both views in sync without duplicate fetches. * fix(tray): skip hidden apps on hover refresh and drop stale disabled-script cache Address P2 findings from automated review on #2184: 1. refresh_all_usage_in_tray now filters TRAY_SECTIONS by settings.visible_apps before scheduling subscription/script queries, matching create_tray_menu and preventing wasted external API calls (and rate-limit/auth-error log noise) for apps the user has hidden. 2. format_usage_suffix only trusts the script cache when provider.meta.usage_script is still enabled; when a script is disabled/removed the cached suffix is now invalidated so the tray label no longer shows stale data indefinitely. * refactor: consolidate codex provider helpers and fix test semantics - Add Provider::is_codex_oauth() and Provider::codex_fast_mode_enabled() to eliminate duplicated meta extraction in claude.rs and stream_check.rs - Fix non-codex-oauth tests to pass codex_fast_mode=false (was true, harmless but semantically misleading) - Remove redundant is_dir() guard after resolve_skill_source_dir already guarantees the returned path is a directory * style: apply cargo fmt * fix(tray): reflect failed refreshes in cache and support Gemini flash-lite Follow-up to the tray usage-display feature addressing review feedback: - Write snapshots for both Ok(success:false) and Err paths in queryProviderUsage / get_subscription_quota so stale success data no longer persists across failed refreshes; the original Err is still returned to the frontend onError handler. - Include gemini_flash_lite tier in the tray summary with label "l". Matches the frontend SubscriptionQuotaFooter and keeps the worst emoji correct when lite is the highest utilization. - Add TIER_GEMINI_PRO / _FLASH / _FLASH_LITE constants in services/subscription.rs and reuse them in classify_gemini_model and sort_order. - Extract Provider::has_usage_script_enabled() to remove the duplicated meta.usage_script chain at two call sites. - Use db.get_provider_by_id in refresh_all_usage_in_tray instead of materialising the full provider map, and parallelise subscription and script futures via futures::future::join. - Narrow refresh_all_usage_in_tray to each section's effective current provider (script if enabled, else subscription when the provider is official). Hover refreshes now issue at most TRAY_SECTIONS.len() outbound requests. - Add 10 unit tests in tray::tests covering Claude/Codex h/w dispatch, Gemini p/f/l dispatch (including lite-only and lite-worst cases), and success/failure guards. --------- Co-authored-by: Jason <farion1231@gmail.com> |
||
|
|
7097a0d710 |
fix: replace implicit app inference with explicit selection for Skills import and sync
Skills import previously inferred app enablement from filesystem presence, causing incorrect multi-app activation when the same skill directory existed under multiple app paths. Now the frontend submits explicit app selections via ImportSkillSelection, and schema migration preserves a snapshot of legacy app mappings to avoid lossy reconstruction. Also adds reconciliation to sync_to_app (removes disabled/orphaned symlinks) and MCP sync_all_enabled (removes disabled servers from live config). |
||
|
|
60007ee4e8 |
fix(windows): restore default home dir resolution to prevent data loss
v3.10.3 introduced HOME env priority on Windows for test isolation, which caused database path to change when HOME differs from USERPROFILE (common in Git/MSYS environments), making providers appear to disappear. Changes: - Use CC_SWITCH_TEST_HOME for test isolation instead of HOME - Add legacy fallback to detect v3.10.3 database location on Windows - Add logging for legacy path detection to aid debugging |
||
|
|
83a5597756 |
fix: resolve test failures and clippy warnings
- tests/App.test.tsx: remove outdated SettingsPage mock, use dynamic import - database/tests.rs: remove unused field, use struct init syntax - deeplink/tests.rs: use idiomatic assert!() instead of assert_eq!(true) - support.rs: add #[allow(dead_code)] for test utilities - usage_stats.rs: code formatting |
||
|
|
1926af4988 |
fix(proxy): update live backup when hot-switching provider in proxy mode
When proxy is active, switching providers only updated the database flags but not the live backup. This caused the wrong provider config to be restored when stopping the proxy. Added `update_live_backup_from_provider()` method to ProxyService that generates backup from provider's settings_config instead of reading from live files (which are already taken over by proxy). |
||
|
|
1e3a978ecb |
fix(proxy): wait for server shutdown before exiting app
The previous cleanup logic only sent a shutdown signal but didn't wait for the proxy server to actually stop. This caused a race condition where the app would exit before cleanup completed, leaving Live configs in an inconsistent state. Changes: - Add `server_handle` field to ProxyServer to track the spawned task - Modify `stop()` to wait for server task completion (5s timeout) - Add 100ms delay before process exit to ensure I/O flush - Export ProxyService and fix test files that were missing proxy_service field |
||
|
|
67aa275599 |
test: migrate tests to SQLite database architecture
This commit refactors all tests to work with the new database-based architecture, replacing the previous JSON config approach. Key changes: - Add Database export to lib.rs for test access - Create test helper functions in support.rs: - create_test_state(): Creates empty test state with fresh DB - create_test_state_with_config(): Migrates JSON config to DB - Fix environment isolation in provider_service tests: - provider_service_switch_missing_provider_returns_error - provider_service_switch_codex_missing_auth_returns_error - Replace ignored export tests with working alternatives: - export_sql_writes_to_target_path (tests Database::export_sql) - export_sql_returns_error_for_invalid_path (tests error handling) - Update error type matching to align with current implementation All tests now: - Use isolated test environments (test_mutex + reset_test_fs) - Access data via Database API instead of RwLock<MultiAppConfig> - Work with SQLite persistence layer - Pass without environment pollution or race conditions Fixes test compilation errors after database migration. |
||
|
|
8a05e7bd3d |
feat(gemini): add Gemini provider integration (#202)
* feat(gemini): add Gemini provider integration - Add gemini_config.rs module for .env file parsing - Extend AppType enum to support Gemini - Implement GeminiConfigEditor and GeminiFormFields components - Add GeminiIcon with standardized 1024x1024 viewBox - Add Gemini provider presets configuration - Update i18n translations for Gemini support - Extend ProviderService and McpService for Gemini * fix(gemini): resolve TypeScript errors, add i18n support, and fix MCP logic **Critical Fixes:** - Fix TS2741 errors in tests/msw/state.ts by adding missing Gemini type definitions - Fix ProviderCard.extractApiUrl to support GOOGLE_GEMINI_BASE_URL display - Add missing apps.gemini i18n keys (zh/en) for proper app name display - Fix MCP service Gemini cross-app duplication logic to prevent self-copy **Technical Details:** - tests/msw/state.ts: Add gemini default providers, current ID, and MCP config - ProviderCard.tsx: Check both ANTHROPIC_BASE_URL and GOOGLE_GEMINI_BASE_URL - services/mcp.rs: Skip Gemini in sync_other_side logic with unreachable!() guards - Run pnpm format to auto-fix code style issues **Verification:** - ✅ pnpm typecheck passes - ✅ pnpm format completed * feat(gemini): enhance authentication and config parsing - Add strict and lenient .env parsing modes - Implement PackyCode partner authentication detection - Support Google OAuth official authentication - Auto-configure security.auth.selectedType for PackyCode - Add comprehensive test coverage for all auth types - Update i18n for OAuth hints and Gemini config --------- Co-authored-by: Jason <farion1231@gmail.com> |
||
|
|
8e980e6974 |
refactor(backend): phase 3 - unify error handling and fix backup timestamp bug
Key improvements: - Extract switch_provider_internal() returning AppError for better testability - Fix backup mtime inheritance: use read+write instead of fs::copy to ensure latest backup survives cleanup - Add 15+ integration tests covering provider commands, atomic writes, and rollback scenarios - Expose write_codex_live_atomic, AppState, and test hooks in public API - Extract tests/support.rs with isolated HOME and mutex utilities Test coverage: - Provider switching with live config backfill and MCP sync - Codex atomic write success and failure rollback - Backup retention policy with proper mtime ordering - Negative cases: missing auth field, invalid provider ID |