Commit Graph

432 Commits

Author SHA1 Message Date
YoVinchen 51bf29582d fix(codex): show custom config before common config in merge preview
Replace deep_merge_toml with deep_merge_toml_preserve_order so that
custom config keys appear at the top and common-only keys appear below.
2026-01-30 10:38:59 +08:00
YoVinchen aa1231903f refactor(common-config): consolidate hooks and migrate Gemini to ENV format
- Delete redundant wrapper hooks (useCommonConfigSnippet, useGeminiCommonConfig)
- Change Gemini common config from JSON to ENV format (.env style)
- Add backend validation with forbidden keys filtering (GEMINI_API_KEY, GOOGLE_GEMINI_BASE_URL)
- Fix localStorage migration to skip empty parsed snippets
- Add error handling for silent JSON parse failures
- Clean up debug logs and unused types
2026-01-30 10:16:57 +08:00
YoVinchen 0d67fba524 Merge branch 'main' into fix/common-config-sync-improvements 2026-01-29 22:38:35 +08:00
YoVinchen 3b61fab4b5 refactor: unify common config hooks with generic base hook and adapters
- Create useCommonConfigBase generic hook (~300 lines)
- Create commonConfigAdapters for Claude (JSON), Codex (TOML), Gemini (ENV/JSON)
- Refactor three hooks from ~1370 lines to ~430 lines (-940 lines)
- Extract useDarkMode hook from three ConfigSections components
- Remove dead code: backend _str functions, frontend JSON/TOML unused exports
- Deduplicate deepClone/deepMerge utilities
- Fix duplicate mod tests in provider.rs
2026-01-29 22:35:52 +08:00
YoVinchen 9776210da8 Merge branch 'main' into fix/common-config-sync-improvements 2026-01-29 14:44:42 +08:00
Jason 08d9bb4cab style(dao): format proxy tests with cargo fmt 2026-01-29 10:09:45 +08:00
Jason 987fc46e06 feat(skills): add install from ZIP file feature
- Add open_zip_file_dialog command for selecting ZIP files
- Add install_from_zip service method with recursive skill scanning
- Add install_skills_from_zip Tauri command
- Add frontend API methods and useInstallSkillsFromZip hook
- Add "Install from ZIP" button in Skills management page
- Support local skill ID format: local:{directory}
- Add i18n translations for new feature and error messages
2026-01-29 10:09:45 +08:00
Jason e3d335be2d feat(settings): prioritize native install path for Claude Code detection
- Move ~/.local/bin to first position in version scan search paths
- Update one-click install commands to use official native installation
  (curl script) instead of npm for Claude Code
2026-01-29 10:09:45 +08:00
Andrew Leng 0dd823ae3a fix(codex): fix 404 errors and connection timeout with custom base_url (#760)
* fix(proxy): fix Codex 404 errors with custom base_url prefixes

- handlers.rs:268: Remove hardcoded /v1 prefix in Codex forwarding
- codex.rs:140: Only add /v1 for origin-only base_urls, dedupe /v1/v1
- stream_check.rs:364: Try /responses first, fallback to /v1/responses
- provider.rs:427: Don't force /v1 for custom prefix base_urls

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(codex): always add /v1 for custom prefix base_urls

Changed logic to always add /v1 prefix unless base_url already ends with /v1.
This fixes 504 timeout errors with relay services that expect /v1 in the path.

- Most relay services follow OpenAI standard format: /v1/responses
- Users can opt-out by adding /v1 to their base_url configuration
- Updated test case to reflect new behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(proxy): allow system proxy on localhost with different ports

- Only bypass system proxy if it points to CC Switch's own port (15721)
- Allow other localhost proxies (e.g., Clash on 7890) to be used
- Add INFO level logging for request URLs to aid debugging

This fixes connection timeout issues when using local proxy tools.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(codex): don't add /v1 for custom prefix base_urls

Reverted logic to not add /v1 for base_urls with custom prefixes.
Many relay services use custom paths without /v1.

- Pure origin (e.g., https://api.openai.com) → adds /v1
- With /v1 (e.g., https://api.openai.com/v1) → no change
- Custom prefix (e.g., https://example.com/openai) → no /v1

This fixes 404 errors with relay services that don't use /v1 in their paths.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(proxy): use dynamic port for system proxy detection

Instead of hardcoding port 15721, now uses the actual configured
listen_port from proxy settings.

- Added set_proxy_port() to update the port when proxy server starts
- Added get_proxy_port() to retrieve current port for detection
- Updated server.rs to call set_proxy_port() on startup
- Updated tests to reflect new behavior

This allows users to change the proxy port in settings without
breaking the system proxy detection logic.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(proxy): change default proxy port from 15721 to 5000

Update the default fallback port in get_proxy_port() from 15721 to 5000
to match the project's standard default port configuration.

Also updated test cases to use port 5000 consistently.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(proxy): revert default port back to 15721

Revert the default fallback port in get_proxy_port() from 5000 back to 15721
to align with the project's updated default port configuration.

Also updated test cases to use port 15721 consistently.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: ozbombor <ozbombor@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 09:10:17 +08:00
YoVinchen 188c7af2e4 Merge branch 'main' into fix/common-config-sync-improvements 2026-01-29 01:13:32 +08:00
YoVinchen 7974650ad8 style: format code across frontend and backend files 2026-01-29 00:59:05 +08:00
方程 164635f638 style(tray): 简化标题标签并优化菜单分隔符 (#796)
Co-authored-by: franco <1787003204@q.comq>
2026-01-28 22:53:38 +08:00
YoVinchen 40373538d3 merge: resolve conflicts from main branch, keep both pricing and common config features 2026-01-27 12:49:36 +08:00
YoVinchen 11a9bb0c14 style(misc): inline format string variable 2026-01-27 12:35:59 +08:00
YoVinchen 9e25ecf475 fix(config): resolve common config sync issues across frontend and backend
- Fix backfill pollution: extract custom config from live when common config enabled
- Fix proxy backup: merge common config before backup to preserve full config
- Unify null override semantics: null no longer overrides in both frontend and backend
- Add missing i18n keys for common config UI
- Hide format button in readonly JsonEditor
- Add mapGeminiWarningToI18n for user-friendly warning messages
2026-01-27 12:28:46 +08:00
Dex Miller 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>
2026-01-27 10:43:05 +08:00
YoVinchen 733605ae5c merge: resolve conflict in live.rs, keep write_live_snapshot_with_merge
- Combine doc comments from both branches
- Keep write_live_snapshot_with_merge for common config runtime merge
- Fix indentation to match main branch style
2026-01-26 23:00:44 +08:00
YoVinchen 542d4635c4 fix(config): improve Gemini common config parsing robustness
- Add ENV format quote stripping (KEY="value" -> value)
- Add toast warnings for filtered forbidden keys
- Unify error codes with GEMINI_CONFIG_ERROR_CODES constants
- Remove duplicate isPlainObject, use shared implementation
- Fix type guard for filter entries
2026-01-26 22:46:24 +08:00
YoVinchen 4e4a445922 fix(config): improve Gemini merge and remove duplicate logging
Address multiple audit findings:

1. config_merge.rs:701 - Gemini merge now initializes env from common
   config when custom config has no env field, ensuring common API keys
   and base URLs are applied correctly.

2. Remove duplicate logging - merge functions now only return warnings,
   callers (live.rs, proxy.rs) handle logging in one place.

3. live.rs:169 - Unify error message style to plain English descriptions
   instead of error codes embedded in messages.

Changes:
- Add fallback to initialize env from common_env when missing
- Remove log::warn! calls from merge functions
- Use descriptive error messages consistently
2026-01-26 17:13:38 +08:00
Jason c00f431d67 feat(opencode): sync all providers to live config on directory change
Add additive mode support for OpenCode in sync_current_to_live:
- Add AppType::is_additive_mode() to distinguish switch vs additive mode
- Add AppType::all() iterator to avoid hardcoding app lists
- Add sync_all_providers_to_live() for additive mode apps
- Refactor sync_current_to_live to handle both modes

Frontend changes (directory settings):
- Track opencodeDirChanged in useDirectorySettings
- Trigger syncCurrentProvidersLiveSafe when OpenCode dir changes
- Add i18n strings for OpenCode directory settings
2026-01-26 15:46:51 +08:00
YoVinchen 73fea48049 refactor(config): extract common config merge to shared function
Address code audit findings #1, #2, #6, #7, #11:

- Extract merge logic to merge_config_for_live() in config_merge.rs
- Add is_common_config_enabled() helper function
- Add MergeResult struct with config and optional warning
- Update live.rs and proxy.rs to use the shared function
- Add logging for JSON parse failures instead of silent fallback
- Convert Chinese error messages to error codes (CODEX_CONFIG_*)
- Support both flat and wrapped formats for Gemini common config

This eliminates code duplication between live.rs and proxy.rs,
making future maintenance easier and preventing behavioral drift.
2026-01-26 15:25:13 +08:00
YoVinchen 6425826e66 fix(deeplink): disable common config for deeplink imported providers
Set common_config_enabled to false by default for providers imported
via deeplink URLs. This prevents unexpected configuration merging when
users import providers from external sources.

Deeplink imported providers should use their settings_config directly
without merging with the global common config snippet, as the imported
configuration is expected to be complete and self-contained.

Changes:
- Always return ProviderMeta with common_config_enabled = false
- Refactor build_provider_meta to handle usage_script conditionally
- Add documentation explaining the design decision
2026-01-26 14:08:00 +08:00
YoVinchen 2f18764490 feat(proxy): add common config merge to proxy live config restore
Extend the proxy service's restore_live_config function to support
common config runtime merge when restoring live configuration after
proxy takeover ends.

This ensures that when the proxy releases control and restores the
original provider configuration, the common config merge is applied
consistently with the main provider switching logic.

The merge follows the same pattern as live.rs:
- Check common_config_enabled flag per app type
- Merge common snippet with provider's custom config
- customConfig overrides commonConfig
2026-01-26 14:07:37 +08:00
YoVinchen 7ad5a76c7a feat(provider): add common config runtime merge to live config sync
Implement runtime merge of common config snippet with provider's custom
config when writing to live configuration files. This enables shared
configuration templates across providers while preserving provider-specific
overrides.

Key changes:
- Add write_live_snapshot_with_merge() function that performs runtime merge
- Support JSON merge for Claude, TOML merge for Codex, and env merge for Gemini
- Update sync_current_to_live() to use the new merge function
- Update provider switch and update operations to use merge function
- Merge rule: customConfig (provider-specific) overrides commonConfig (shared)

The merge is only performed when common_config_enabled is true for the
provider and the corresponding app type.
2026-01-26 14:07:05 +08:00
YoVinchen b1446d0227 feat(config): add core utilities for config merge and difference extraction
Add comprehensive config merge utilities for both Rust backend and TypeScript frontend
to support the new common config architecture where customConfig overrides commonConfig.

Backend (Rust):
- Add config_merge.rs module with JSON and TOML merge functions
- Support deep merge where source overrides target for nested objects
- Add extract_difference functions to identify custom-only keys
- Include compute_final_*_config functions for runtime merge calculation
- Register module in lib.rs

Frontend (TypeScript):
- Add configMerge.ts with isPlainObject, deepClone, deepEqual, deepMerge utilities
- Implement computeFinalConfig for merging common + custom configs
- Add extractDifference to identify keys unique to live config
- Add tomlConfigMerge.ts with TOML-specific merge/extract functions
- Use smol-toml for parsing and serialization

These utilities form the foundation for the refactored common config system
where providers store only custom config and merge with shared templates at runtime.
2026-01-26 13:57:48 +08:00
Jason 29a0643d74 refactor(config): consolidate get_home_dir into single public function
Follow-up to #644: Extract duplicate get_home_dir() implementations
into a single pub fn in config.rs, reducing code duplication across
codex_config.rs, gemini_config.rs, and settings.rs.

Also adds documentation comments to build.rs explaining the Windows
manifest workaround for test binaries.
2026-01-26 11:24:28 +08:00
Jason 5e92111771 feat(settings): add preferred terminal selection
Allow users to choose their preferred terminal app for opening
provider terminals. Supports platform-specific options:
- macOS: Terminal.app, iTerm2, Alacritty, Kitty, Ghostty
- Windows: cmd, PowerShell, Windows Terminal
- Linux: GNOME Terminal, Konsole, Xfce4, Alacritty, Kitty, Ghostty

Falls back to system default if selected terminal is unavailable.
2026-01-26 11:20:33 +08:00
Jason beebd9847f refactor(terminal): consolidate redundant terminal launch functions
Merge macOS Alacritty/Kitty/Ghostty launchers into a single generic
`launch_macos_open_app` function with a `use_e_flag` parameter.
Replace Windows cmd/PowerShell/wt launchers with a shared
`run_windows_start_command` helper. Reduces ~98 lines of duplicate code.
2026-01-26 11:20:33 +08:00
Xyfer d99a3c2fee fix(windows): stabilize test environment (#644)
* fix(windows): embed common-controls manifest

* fix(windows): prefer HOME for config paths

* test(windows): fix export_sql invalid path

* fix(windows): remove unused env import in config.rs
2026-01-26 11:18:14 +08:00
funnytime a0ca8c2517 feat: add silent startup option to prevent window popup on launch (issue #708) (#713) 2026-01-26 10:54:59 +08:00
YoVinchen 3da25e59cd Merge branch 'main' into fix/common-config-sync-improvements 2026-01-26 01:44:37 +08:00
Dex Miller 3434dcb87c fix(skills): prevent duplicate skill installation from different repos (#778)
- Add directory conflict detection before installation
- Fix installed status check to match repo owner and name
- Add i18n translations for conflict error messages
2026-01-25 23:35:04 +08:00
YoVinchen 0e75193e84 chore: update Cargo.lock and format providerConfigUtils 2026-01-25 03:46:45 +08:00
YoVinchen 078a3a6a53 feat(backend): add CommonConfigEnabledByApp to ProviderMeta
- Add CommonConfigEnabledByApp struct for per-app tracking
- Add common_config_enabled and common_config_enabled_by_app to ProviderMeta
- Add is_empty() method to CommonConfigSnippets
- Skip serializing empty common_config_snippets in config.json
2026-01-25 03:46:22 +08:00
Jason 1c6689a0bc chore: update Cargo.lock version to 3.10.2 2026-01-24 23:49:06 +08:00
Jason 53dd0a90f3 chore: release v3.10.2 2026-01-24 22:15:21 +08:00
Jason 779fefd86d feat(skills): add skill sync method setting (symlink/copy)
- Add SyncMethod enum (Auto/Symlink/Copy) in Rust backend
- Implement sync_to_app_dir with symlink support (cross-platform)
- Add SkillSyncMethodSettings UI component (simplified 2-button selector)
- Add i18n support for zh/en/ja
- Replace copy_to_app with configurable sync_to_app_dir
- Add skill_sync_method field to AppSettings

User can now choose between symlink (disk space saving) or copy (best compatibility) in Settings > General.
2026-01-24 18:24:05 +08:00
Jason adb868d0cf fix(prompt): clear prompt file when all prompts are disabled
When disabling a prompt, check if any other prompts remain enabled.
If all prompts are disabled, clear the prompt file to ensure UI state
matches the actual configuration that Claude Code reads.
2026-01-23 22:43:07 +08:00
Jason a6ad896db0 fix(opencode): preserve extra model fields during serialization
Add `extra` field with serde flatten to OpenCodeModel struct to capture
custom fields like cost, modalities, thinking, and variants that were
previously lost during save operations.
2026-01-23 20:42:50 +08:00
Jason 0ef670325b chore: release v3.10.1
- Bump version to 3.10.1 across all config files
- Update CHANGELOG with all fixes since v3.10.0
- Fix Rust Clippy warning by using derive(Default)
- Apply code formatting
2026-01-23 10:41:38 +08:00
Jason 07fc6b175e fix(proxy): change rectifier default state to disabled
Change the default state of the rectifier from enabled to disabled.
This allows users to opt-in to the rectifier feature rather than having it enabled by default.

Changes:
- Set RectifierConfig::default() enabled and request_thinking_signature to false
- Update serde default attributes from default_true to default
- Update unit tests to reflect new default behavior
2026-01-23 09:45:57 +08:00
Jason cfb113ac8d fix(settings): reorder window settings and change default values
Move "minimize to tray on close" to the bottom of window settings.
Change skipClaudeOnboarding default to false.
2026-01-22 23:35:41 +08:00
Jason 62a4ab2ad3 fix(terminal): keep Windows terminal window open after execution
Use /K instead of /C flag to prevent cmd window from closing
immediately after batch file execution. Also remove the buggy
errorlevel check that was checking del command's return value
instead of claude's.

Fixes #726
2026-01-22 23:04:18 +08:00
Jason aa0f191420 fix(config): correct OpenCode config path on Windows
OpenCode uses ~/.config/opencode on all platforms, not %APPDATA%\opencode
on Windows. Remove the platform-specific path handling to use unified
~/.config/opencode path across all operating systems.
2026-01-22 17:09:45 +08:00
Jason fef750bb4c chore: release v3.10.0 2026-01-21 20:01:29 +08:00
Jason 2d17bde790 feat(skills): add baoyu-skills preset repo and auto-supplement missing defaults
- Add JimLiu/baoyu-skills to default skill repositories
- Change init_default_skill_repos() from "first-run only" to "supplement missing"
- New preset repos will now auto-appear for existing users on upgrade
2026-01-21 16:20:28 +08:00
Jason a187380d6f 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
2026-01-21 11:27:44 +08:00
Jason b993b1f664 chore: fix code formatting and test setup
- Format Rust code with rustfmt (misc.rs, types.rs)
- Format TypeScript/React code with Prettier (4 files)
- Fix ProviderList test by wrapping with QueryClientProvider
2026-01-20 23:40:33 +08:00
Jason 00168877d9 fix(terminal): use temp script files to avoid escaping issues on all platforms
- macOS: Replace inline AppleScript commands with temp .sh script file
- Linux: Use temp .sh script file instead of inline bash -c command
- Windows: Add proper error capturing with output() instead of spawn()
- Remove unused escape_shell_path and generate_wrapper_script functions
- Unified approach across platforms for better maintainability
2026-01-20 22:21:01 +08:00
Jason c9e85e8cac feat(tray): sync tray menu with app visibility settings
Apply visibleApps setting to filter tray menu sections, so hidden apps
no longer appear in the system tray menu.
2026-01-20 21:05:06 +08:00