Commit Graph

1107 Commits

  • feat: session manger (#867)
    * feat: init session manger
    
    * feat: persist selected app to localStorage
    
    - Save app selection when switching providers
    - Restore last selected app on page load
    
    * feat: persist current view to localStorage
    
    - Save view selection when switching tabs
    - Restore last selected view on page load
    
    * styles: update ui
    
    * feat: Improve macOS Terminal activation and refactor Kitty launch to use  command with user's default shell.
    
    * fix: session view
    
    * feat: toc
    
    * feat: Implement FlexSearch for improved session search functionality.
    
    * feat: Redesign session manager search and filter UI for a more compact and dynamic experience.
    
    * refactor: modularize session manager by extracting components and utility functions into dedicated files.
    
    * feat: Enhance session terminal launching with support for iTerm2, Ghostty, WezTerm, and Alacritty, including UI and custom configuration options.
    
    * feat: Conditionally render terminal selection and resume session buttons only on macOS.
  • fix(stream_check): respect auth_mode for Claude health checks (#824)
    Previously, check_claude_stream always added the x-api-key header,
    ignoring the provider's auth_mode setting. This caused health check
    failures for proxy services that only support Bearer authentication.
    
    Now the function respects the auth.strategy field:
    - AuthStrategy::Anthropic: Authorization Bearer + x-api-key
    - AuthStrategy::ClaudeAuth: Authorization Bearer only
    - AuthStrategy::Bearer: Authorization Bearer only
    
    This aligns with the behavior of ClaudeAdapter::add_auth_headers
    and fixes health checks for proxy providers with auth_mode="bearer_only".
    
    Changes:
    - Modified check_claude_stream to conditionally add x-api-key header
    - Added AuthStrategy import
    - Added test_auth_strategy_imports unit test
    
    Tests: All passing (7/7 for stream_check module)
    
    Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix(skills): handle Windows path separator in installed status matching (#868)
    * fix(skills): handle Windows path separator in installed status matching
    
    Use regex to split directory path by both / and \ to correctly extract
    the install name on Windows, fixing the issue where installed skills
    were not showing as installed in the discovery page filter.
    
    Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
    
    * feat(skills): add repository filter to skills discovery page
    
    - Add dropdown to filter skills by repository (owner/name)
    - Extract unique repos from discoverable skills list
    - Add truncate style for long repo names with hover title
    - Add i18n translations for zh/en/ja
    
    Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
  • feat(ui): dynamic endpoint hint based on API format selection (#860)
    - Add apiHintOAI i18n key for OpenAI Chat Completions format hint
    - Update ClaudeFormFields to show format-specific endpoint hints
    - When API format is "openai_chat", show OAI-specific hint
    - Maintains consistency between hint and selected API format
    
    Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
  • fix(ci): add xdg-utils for ARM64 AppImage and suppress dead_code warnings
    - Add xdg-utils dependency for xdg-mime binary required by AppImage bundler
    - Remove unused McpStatus struct from gemini_mcp.rs (duplicate of claude_mcp.rs)
    - Add #![allow(dead_code)] to proxy models reserved for future type-safe API
  • 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.
  • 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
  • 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
  • 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.
  • 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
  • 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.
  • 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.
  • 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)
  • 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.
  • 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.
  • 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
  • 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.
  • 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.
  • 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)
  • 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.
  • 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)
  • 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
  • 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: "変換が必要" → "プロキシが必要"
  • 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
  • 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)
  • 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.
  • 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
  • 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.
  • 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)
  • 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
  • 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
  • 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
  • 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
  • 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>
  • 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.
  • 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
  • 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>
  • 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)
  • docs(sponsors): add AICodeMirror and reorder sponsor list
    - Add AICodeMirror as new sponsor with logo
    - Sync changes across all README languages (EN/ZH/JA)