Commit Graph

746 Commits

Author SHA1 Message Date
YoVinchen 188c7af2e4 Merge branch 'main' into fix/common-config-sync-improvements 2026-01-29 01:13:32 +08:00
YoVinchen de59facad6 feat(ui): add auto-height support for JsonEditor component
Add autoHeight prop to dynamically resize editor based on content lines.
Apply to config preview sections in Codex, Gemini, and CommonConfig forms.
2026-01-29 01:12:48 +08:00
YoVinchen 7974650ad8 style: format code across frontend and backend files 2026-01-29 00:59:05 +08:00
YoVinchen 3f68f78331 fix(config): defer common config save until form submission
- Change handleExtract and handleCommonConfigSnippetChange to use delayed save pattern
- Add hasUnsavedCommonConfig state to track pending changes
- Add getPendingCommonConfigSnippet and markCommonConfigSaved helper functions
- Remove immediate backend API calls, save only on form submit
- Add extractSuccessNeedSave and saveCommonConfigFailed i18n keys
2026-01-29 00:54:48 +08:00
makoMako fcb5163710 fix(settings): correct Gemini default visibility to true (#818)
Frontend fallback value for visibleApps had gemini: false, which was
inconsistent with backend default (gemini: true). This caused Gemini
to be hidden by default on first install.

Fixes #817

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 21:35:10 +08:00
Jason 3095bf8e5c chore(presets): upgrade Kimi/Moonshot providers to k2.5 model
- Update Moonshot preset models from kimi-k2-thinking to kimi-k2.5
- Update OpenCode Kimi preset name and model to k2.5
- Remove explicit model config from Kimi preset (use API defaults)
2026-01-27 23:38:34 +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 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
Jason c74f801d66 fix(settings): correct footer layout in advanced settings tab
- Establish proper flexbox height chain from App to SettingsPage
- Move save button to fixed footer outside scrollable area
- Align footer styling with FullScreenPanel for consistency
2026-01-27 10:46:27 +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 d5d7c87fd6 fix(dialog): support wrapped format for Gemini common config
Address audit finding: EditProviderDialog.tsx:121 only parsed flat JSON
format, not the wrapped {"env": {...}} format.

Changes:
- Detect if common config is wrapped or flat format
- Extract env object from either format
- Properly compute difference for live settings extraction

This ensures backward compatibility with existing wrapped-format data.
2026-01-26 17:13:07 +08:00
YoVinchen 1e1080c813 fix(form): use JSON parsing for Gemini common config snippet
Address audit finding: ProviderForm.tsx:944 was using envStringToObj()
(KEY=VALUE format) to parse Gemini common config, but it's stored as JSON.

Changes:
- Add parseGeminiCommonConfig() helper function
- Support both flat {"KEY": "VALUE"} and wrapped {"env": {...}} formats
- Properly extract difference between custom and common env

This prevents common config values from being incorrectly saved as
custom config when the formats don't match.
2026-01-26 17:11:18 +08:00
YoVinchen e393dda68e fix(form): add type guard for Gemini env values
Address code audit finding #10:

Replace unsafe type assertion with proper type guard when extracting
custom env config. Convert all values to strings explicitly using
String() to prevent runtime type errors when env contains non-string
values (numbers, booleans, etc).

Before: envObj = customConfig as Record<string, string>
After: Iterate and convert each value with String(value)
2026-01-26 15:55:58 +08:00
YoVinchen 0ecf6891c0 refactor(hooks): improve error handling and user feedback
Address code audit findings #3, #5, #9:

Save queue improvements:
- Add error logging in enqueueSave() catch handlers
- Use console.error with [SaveQueue] prefix for debugging
- Prevent silent failures in async save operations

Extract operation improvements:
- Add toast.success() notification after extract completes
- Notify user that custom config was automatically updated
- Add error logging for failed settingsConfig updates

I18n improvements:
- Replace MCP i18n keys with dedicated Codex keys:
  - codexConfig.tomlFormatError
  - codexConfig.tomlSyntaxError
  - codexConfig.extractedTomlInvalid
- Avoid namespace pollution between modules
2026-01-26 15:55:40 +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 cfab768f95 fix(dialog): unify Gemini common config format parsing
Address code audit finding #4:

The frontend was incorrectly parsing Gemini common config as KEY=VALUE
format while the backend expects JSON format. Unify to use JSON parsing
{"KEY": "VALUE"} which matches the format stored by useGeminiCommonConfig.

Also add type guard when converting to string record to prevent type
assertion issues with non-string values.
2026-01-26 15:29:19 +08:00
YoVinchen e54e4d47ae feat(dialog): extract custom config from live settings on edit
Update EditProviderDialog to extract custom configuration from live
settings when common config is enabled, ensuring the edit form shows
only the provider-specific values.

When loading live settings for editing:
- Check if common config is enabled for the provider and app type
- Fetch the common config snippet from database
- Extract the difference (custom config) from live settings
- Handle all three formats: Claude (JSON), Codex (TOML), Gemini (env)

This prevents the merged common config values from appearing in the
edit form, which would cause them to be saved as custom config and
result in duplicate values after the next merge.
2026-01-26 14:12:42 +08:00
YoVinchen 403c3f0690 feat(form): extract custom config difference on provider save
Update ProviderForm to extract only the custom (provider-specific)
configuration when saving, removing common config values that would
be merged at runtime.

Changes:
- Import configMerge utilities (extractDifference, extractTomlDifference)
- Pass finalConfig from hooks to config editor components
- On save, extract difference between current config and common snippet
- Apply extraction for all three app types (Claude JSON, Codex TOML, Gemini env)

This ensures the database stores only the provider's unique configuration,
while the common config is stored separately and merged at runtime when
writing to live files.
2026-01-26 14:11:13 +08:00
YoVinchen b3b3c0732a feat(ui): add merge preview to common config editor components
Add real-time merge preview functionality to all config editor components
(Claude, Codex, Gemini) that shows the final merged configuration when
common config is enabled.

UI changes:
- Add finalConfig/finalEnv prop to display merged result
- Add toggle button to show/hide merge preview (Eye/EyeOff icons)
- Auto-show preview when common config is enabled
- Display custom config editor with label when preview is visible
- Show read-only merged preview below custom config
- Add visual indicators: "只读" badge, green hint text

The preview helps users understand how their custom configuration
combines with the shared common config template before saving.
2026-01-26 14:09:39 +08:00
YoVinchen 2ff329f6c0 refactor(hooks): redesign common config hooks for runtime merge architecture
Refactor all three common config hooks (Claude, Codex, Gemini) to support
the new runtime merge architecture where:
- settingsConfig stores only custom (provider-specific) configuration
- commonConfigSnippet stores shared template configuration in database
- finalConfig is computed at runtime: merge(commonConfig, customConfig)
- Toggling common config only changes enabled state, not settingsConfig

Key changes across all hooks:
- Add finalConfig/finalEnv return value for merge preview
- Use configMerge utilities (computeFinalConfig, extractDifference)
- Remove direct config manipulation on toggle (no more inject/remove)
- Add proper TypeScript return type interfaces
- Simplify state management by removing unnecessary refs
- Improve code organization with clear section comments

This refactor enables:
- Clean separation between custom and common configuration
- Real-time merge preview in the UI
- Consistent behavior across Claude (JSON), Codex (TOML), and Gemini (env)
2026-01-26 14:09:13 +08:00
YoVinchen 5817c9aa77 feat(editor): add readOnly mode to JsonEditor component
Add a readOnly prop to the JsonEditor component that:
- Enables CodeMirror's EditorState.readOnly extension
- Applies visual styling (reduced opacity, default cursor)
- Prevents user modifications to the editor content

This feature is needed for displaying merged config previews where
users should see the final result but not edit it directly.
2026-01-26 14:08:34 +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 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
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 0938bd5e41 Merge branch 'main' into fix/common-config-sync-improvements 2026-01-25 13:39:38 +08:00
YoVinchen 62523ee17e refactor(config): improve TOML common config merge without markers
- Remove cc-switch:common-config:start/end marker injection
- Allow table definitions in common config snippets
- Add intelligent TOML structure parsing and merging
- Keep legacy marker cleanup for backward compatibility
2026-01-25 04:38:38 +08:00
YoVinchen 0e75193e84 chore: update Cargo.lock and format providerConfigUtils 2026-01-25 03:46:45 +08:00
YoVinchen d52f8855ea fix(form): add common config loading check and meta persistence
- Check common config loading state before submit
- Add validation for common config errors on submit
- Add TOML validation for Codex before submit
- Persist commonConfigEnabledByApp to provider meta
- Pass currentProviderId to common config hooks for sync skip
2026-01-25 03:45:51 +08:00
YoVinchen 628a659c0e refactor(hooks): improve config state hooks for codex and gemini
- Improve type safety in config state management
- Better error handling for config parsing
2026-01-25 03:45:19 +08:00
YoVinchen 86cfa452e9 feat(types): add CommonConfigEnabledByApp type for per-app tracking
- Add CommonConfigEnabledByApp type for claude/codex/gemini
- Add commonConfigEnabled field to ProviderMeta
- Add commonConfigEnabledByApp field with higher priority
2026-01-25 03:44:30 +08:00
YoVinchen 06d69caf79 feat(i18n): add common config sync related translations
- Add providerForm.commonConfigLoading key
- Add providerForm.commonConfigSyncFailed key
- Support zh/en/ja languages
2026-01-25 03:43:07 +08:00
YoVinchen 58f7be1517 fix(gemini): add clearing sync and save queue for common config
- Trigger sync when clearing common config to remove from all providers
- Add saveSequenceRef and enqueueSave for ordered async saves
- Add toast notification for sync failures
- Prevent stale sync operations with sequence ID check
2026-01-25 03:42:52 +08:00
YoVinchen 5d48dd7908 fix(codex): add TOML validation and clearing sync for common config
- Add TomlValidationErrorCode type for structured error handling
- Add TOML syntax validation in getSnippetApplyError
- Trigger sync when clearing common config
- Add saveSequenceRef and enqueueSave for ordered async saves
- Add toast notification for sync failures
2026-01-25 03:42:32 +08:00
YoVinchen 0e7e04581d fix(claude): add clearing sync and save queue for common config
- Trigger sync when clearing common config to remove from all providers
- Add saveSequenceRef and enqueueSave for ordered async saves
- Add toast notification for sync failures
- Prevent stale sync operations with sequence ID check
2026-01-25 03:41:29 +08:00
YoVinchen 788e138ece fix(utils): add type validation and error codes for config utilities
- Add isPlainObject validation in replaceGeminiCommonConfigSnippet
- Return error codes instead of hardcoded Chinese strings
- Add CONFIG_NOT_OBJECT, ENV_NOT_OBJECT, COMMON_CONFIG_JSON_INVALID codes
- Use TOML marker constants to avoid hardcoded strings
2026-01-25 03:39:02 +08:00
YoVinchen b692bb4053 fix(sync): add in-flight lock and callback support for common config sync
- Add SyncResult interface for structured sync results
- Add SyncResultCallback type for async notification
- Add syncInFlight lock per appType to prevent concurrent syncs
- Add executeSyncWithLock function for concurrency control
- Add meta fallback detection with automatic backfill
- Improve error handling with detailed error messages
2026-01-25 03:38:45 +08:00
Jason 9404341f14 feat(ui): replace update badge dot with ArrowUpCircle icon
- Replace blue dot indicator with lucide ArrowUpCircle icon
- Change color scheme from blue to green for better visibility
- Enlarge button (h-8 w-8) and icon (h-5 w-5) for better UX
- Move UpdateBadge from title area to after settings icon
2026-01-24 23:32:05 +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 096c1d57c4 feat(partner): add RightCode as official partner
Update RightCode referral link to use CCSWITCH affiliate code and mark
as official partner with promotional messages in all supported languages.
2026-01-23 22:59:48 +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 d6cf4390ac fix(form): backfill model fields when editing Claude provider
Use lazy initialization in useState to parse model values from config
on first render, matching the pattern used in useApiKeyState. This
fixes an issue where model fields were not populated in edit mode.
2026-01-23 19:13:38 +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 79d3ecc1b8 feat(icons): update RightCode provider icon
- Import new detailed RC icon from rc.svg (128x128 viewBox)
- Add icon configuration to Claude provider preset
- Remove duplicate old RC icon definition to fix TS1117 error
2026-01-23 09:25:09 +08:00
Jason 9c249d9486 fix(ui): increase app icon collapse threshold from 3 to 4
Improve readability by keeping app names visible when 3 apps are shown.
Icons now only collapse to compact mode when 4 or more apps are visible.
2026-01-23 00:12:33 +08:00
Jason 15f60e8ce2 fix(ui): improve ProviderIcon color validation to prevent black icons
Enhance the effectiveColor logic in ProviderIcon to properly validate
the color prop before using it. Now only uses color when it's a valid
non-empty string, otherwise falls back to icon metadata defaultColor.

This fixes the issue where Gemini icons would turn black when selected
in ProviderCard due to null/undefined/empty string color values being
passed through.
2026-01-23 00:02:11 +08:00
Jason 3d733a3b80 fix(ui): unify layout padding across all panels
Remove max-width constraints and standardize padding to px-6 for consistent full-width layout across header and all content panels.
2026-01-22 23:55:19 +08:00