Commit Graph

1101 Commits

Author SHA1 Message Date
YoVinchen ea29bc20a0 merge: resolve conflicts between fix/common-config-sync-improvements and main
Merged both feature sets:
- common-config: commonConfigEnabled, commonConfigEnabledByApp fields
- api-format: apiFormat field for Claude provider OpenAI compatibility

Key resolution in live.rs: apply sanitize_claude_settings_for_live()
to merged config before writing to ensure internal fields are stripped.
2026-01-31 21:03:08 +08:00
Jason b8bd1d30d9 docs(changelog): add Linux ARM64 and error display fix to v3.10.3 2026-01-31 20:46:20 +08:00
YoVinchen 0ef8c127c5 fix(common-config): improve error handling, layer separation, and reliability across sync system
P0 Fixes:
- Enable toml `preserve_order` feature for reliable key ordering
- Extract pure detection functions to utils/commonConfigDetection.ts (fix layer inversion)
- Return structured result from preserveCodexConfigFormat to prevent data loss

P1 Fixes:
- Handle pure TOML strings in Codex config instead of silent skip
- Surface extractDiff errors in useCodexCommonConfig instead of swallowing
- Log parse errors in detectCommonConfigEnabledByContent for debugging

P2 Fixes:
- Use parsing-based assertions in Rust TOML ordering tests
- Add schema warning when Codex config field is wrong type
- Add depth/node limits to isSubset function (prevent stack overflow)
- Replace hardcoded "{}" check with adapter.hasValidContent()

P3 Fixes:
- Refactor Gemini errors to structured GeminiConfigErrorInfo format
- Add mapGeminiErrorToI18n for type-safe error-to-i18n mapping
2026-01-31 20:39:28 +08:00
Jason 4abf259a6d feat(ci): add Linux ARM64 build support
- Add ubuntu-22.04-arm runner to build matrix
- Rename Linux artifacts with architecture suffix (x86_64/arm64)
- Update pnpm cache key with runner.arch to avoid cross-arch pollution
- Add linux-aarch64 platform to latest.json for Tauri updater
2026-01-31 20:38:18 +08:00
Jason faa82a5b86 fix(mutations): use extractErrorMessage for complete error display
Provider add/update/delete mutations were using error.message directly,
which doesn't extract Tauri invoke errors properly. Now using the same
extractErrorMessage pattern as the rest of the codebase.
2026-01-31 20:15:39 +08:00
Jason b5b45c2703 chore: bump version to 3.10.3
- Update version in package.json, Cargo.toml, and tauri.conf.json
- Add missing changelog entries for OpenCode API key link and AICodeMirror preset
- Fix Prettier formatting for new hook files
2026-01-31 17:29:09 +08:00
Jason bd8a323600 feat(opencode): add API key link support for OpenCode provider form
Enable API key link feature for OpenCode app, allowing users to access
provider websites for key registration directly from the form.
2026-01-31 17:16:36 +08:00
Jason 151e43a808 feat(providers): add AICodeMirror partner preset for all apps
Register AICodeMirror icon, add i18n partner promotion texts (zh/en/ja),
and fix trailing whitespace in codexProviderPresets.
2026-01-31 16:05:50 +08:00
YoVinchen d66f196378 refactor(common-config): consolidate hasContent methods into adapters
- Add hasContent method to CommonConfigAdapter interface
- Move isSubset utility to configMerge.ts for reuse
- Export preserveCodexConfigFormat from adapters for hook use
- Add hasContentByAppType dispatcher for unified content detection
- Remove dead code from providerConfigUtils (hasCommonConfigSnippet,
  hasTomlCommonConfigSnippet, hasGeminiCommonConfigSnippet)
2026-01-31 15:23:49 +08:00
YoVinchen 580b32dd67 fix(codex): reorder merged TOML keys to put custom config first
When merging TOML configs, common config keys were appearing before
custom config keys. Add reorderMergedKeys() to ensure custom config
keys (model_provider, model, etc.) appear at the top, with common-only
keys appended after.
2026-01-31 15:04:57 +08:00
Jason 9d2bf08fe0 docs(changelog): release v3.10.3
Add changelog entry for v3.10.3 feature release including:
- API format selector and presets
- Pricing config enhancement
- Skills ZIP install
- Preferred terminal selection
- Silent startup option
- OpenCode environment check and directory sync
- NVIDIA NIM and n1n.ai presets
- Multiple bug fixes for Codex, proxy URL, tray menu, etc.
2026-01-30 23:18:22 +08:00
Jason 05c21e016f feat(settings): add OpenCode support to environment check and one-click install
- Add OpenCode version detection with Go path scanning
- Add GitHub Releases API for fetching latest OpenCode version
- Add OpenCode install command to one-click install section
- Update i18n hints to include OpenCode across all locales
- Fix SettingsPage indentation formatting
2026-01-30 22:23:18 +08:00
Jason 57713dd336 feat(claude): show proxy hint when switching to OpenAI Chat format provider
Display an info toast when switching to a provider that uses OpenAI Chat
format (apiFormat === "openai_chat"), reminding users to enable the proxy
service. Move toast logic from mutation to useProviderActions for better
control over notification content based on provider properties.
2026-01-30 16:40:41 +08:00
Jason 1ed122a8bd refactor(proxy): remove DeepSeek max_tokens clamp from transform layer
The max_tokens restriction was too aggressive and should be handled
upstream or by the provider itself. Simplify anthropic_to_openai by
removing provider parameter since model mapping is already done by
proxy::model_mapper.
2026-01-30 16:40:41 +08:00
Jason 78e341ccb9 feat(providers): add NVIDIA NIM preset for Claude and OpenCode
- Add NVIDIA NIM provider preset with API configuration
- Add nvidia.svg icon and register in icon system
- Add nvidia metadata with keywords and default color (#74B71B)
2026-01-30 16:40:41 +08:00
Jason 162800e18e feat(claude): add apiFormat support for provider presets
Allow preset providers to specify API format (anthropic or openai_chat),
enabling third-party proxy services that use OpenAI Chat Completions format.
2026-01-30 16:40:41 +08:00
Jason 065d5db843 fix(proxy): improve URL building and remove redundant model mapping
- Add model parameter to request logs for better debugging
- Fix duplicate /v1/v1 in URL when both base_url and endpoint have version
- Extend ?beta=true parameter to /v1/chat/completions endpoint
- Remove model mapping from transform layer (now handled by model_mapper)
- Add DeepSeek max_tokens clamping (1-8192 range)
2026-01-30 16:40:41 +08:00
Jason 70a18c1141 refactor(claude): migrate api_format from settings_config to meta
Move api_format storage from settings_config to ProviderMeta to prevent
polluting ~/.claude/settings.json when switching providers.

- Add api_format field to ProviderMeta (Rust + TypeScript)
- Update ProviderForm to read/write apiFormat from meta
- Maintain backward compatibility for legacy settings_config.api_format
  and openrouter_compat_mode fields (read-only fallback)
- Strip api_format from settings_config before writing to live config
2026-01-30 16:40:41 +08:00
Jason 964767ebaf fix(i18n): update apiFormatOpenAIChat label to mention proxy requirement
Change label from "Requires conversion" to "Requires proxy" for clarity:
- zh: "需转换" → "需开启代理"
- en: "Requires conversion" → "Requires proxy"
- ja: "変換が必要" → "プロキシが必要"
2026-01-30 16:40:41 +08:00
Jason 0c25687e09 fix(claude): improve backward compatibility for openrouter_compat_mode
Extend backward compatibility support for legacy openrouter_compat_mode field:
- Support number type (1 = enabled, 0 = disabled)
- Support string type ("true"/"1" = enabled)
- Add corresponding test cases for number and string types
2026-01-30 16:40:41 +08:00
Jason 81b975c47c feat(claude): add API format selector for third-party providers
Replace the OpenRouter-specific compatibility toggle with a generic
API format selector that allows all Claude providers to choose between:

- Anthropic Messages (native): Direct passthrough, no conversion
- OpenAI Chat Completions: Enables Anthropic ↔ OpenAI format conversion

Changes:
- Add ClaudeApiFormat type ("anthropic" | "openai_chat") to types.ts
- Replace openRouterCompatToggle with apiFormat dropdown in ClaudeFormFields
- Update ProviderForm to manage apiFormat state via settingsConfig.api_format
- Refactor claude.rs: add get_api_format() method, update needs_transform()
- Maintain backward compatibility with legacy openrouter_compat_mode field
- Update i18n translations (zh, en, ja)
2026-01-30 16:40:41 +08:00
n1n.ai e44423c307 feat: add n1n.ai provider preset (#667)
Co-authored-by: n1n <team@n1n.ai>
2026-01-30 12:45:01 +08:00
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 b8a53f9e36 fix(test): move orphaned test into describe block
Move "clears loading flag when all mutations idle" test inside
the describe("useProviderActions") block for proper test isolation.
2026-01-30 00:11:11 +08:00
YoVinchen 06cde78945 chore: remove dead code from providerConfigUtils and config API
- Remove unused functions: updateCommonConfigSnippet, replaceCommonConfigSnippet,
  replaceGeminiCommonConfigSnippet, updateTomlCommonConfigSnippet,
  replaceTomlCommonConfigSnippet and their internal helpers (~600 lines)
- Remove deprecated getClaudeCommonConfigSnippet and setClaudeCommonConfigSnippet
- Remove unused imports (deepClone, deepMerge)
2026-01-29 23:03:56 +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 982f78af0f fix(codex): fix config.toml not updated after extracting common config
The handleExtract function assumed codexConfig was JSON format, but it's
actually a pure TOML string from useCodexConfigState. JSON.parse() failed
silently, causing onConfigChange not to be called.

Changes:
- Handle both pure TOML string and legacy JSON format
- Add missing i18n key for zh.json
2026-01-29 18:38:02 +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 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
方程 164635f638 style(tray): 简化标题标签并优化菜单分隔符 (#796)
Co-authored-by: franco <1787003204@q.comq>
2026-01-28 22:53:38 +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
Jason a48502235c docs(sponsors): add AICodeMirror and reorder sponsor list
- Add AICodeMirror as new sponsor with logo
- Sync changes across all README languages (EN/ZH/JA)
2026-01-27 22:51:22 +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
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 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