20 Commits

  • feat(claude-desktop): add 3P provider switching with proxy gateway
    Adds a new ClaudeDesktop AppType that writes Claude Desktop's third-party
    inference profile under configLibrary/, sharing _meta.json with other
    launchers (Ollama-compatible) so cc-switch can coexist with them.
    
    Two switch modes:
    - direct: provider already exposes claude-* / anthropic/claude-* model
      ids on Anthropic Messages, Claude Desktop connects to it directly.
    - proxy: cc-switch's local proxy acts as the inference gateway,
      presenting only claude-* route names to Claude Desktop and mapping
      them to real upstream models. Required after Anthropic restricted
      Claude Desktop to claude-family ids.
    
    Backend:
    - New module claude_desktop_config with snapshot/rollback, official seed
      bypass, /claude-desktop/v1/{models,messages} routes, and a single
      source of truth for default proxy routes.
    - Gateway token persisted in SQLite, validated on every proxied request.
    - get_claude_desktop_status surfaces drift signals (stale models,
      missing routes, proxy stopped, base URL mismatch, missing token).
    
    Frontend:
    - Slim ClaudeDesktopProviderForm independent from ProviderForm,
      controlled by a top-level appId guard.
    - ProviderList banner consumes the status query (5s polling) and
      renders actionable diagnostics.
    - ClaudeDesktopRouteToggle in the header to start/stop the local
      gateway without touching takeover state.
    - Three-locale i18n synchronised.
  • feat(copilot): add GitHub Copilot reverse proxy support (#930)
    * refactor(toolsearch): replace binary patch with ENABLE_TOOL_SEARCH env var toggle
    
    - Remove toolsearch_patch.rs binary patching mechanism (~590 lines)
      - Delete `toolsearch_patch.rs` and `commands/toolsearch.rs`
      - Remove auto-patch startup logic and command registration from lib.rs
      - Remove `tool_search_bypass` field from settings.rs
      - Remove frontend settings ToggleRow, useSettings hook sync logic, and API methods
      - Clean up zh/en/ja i18n keys (notifications + settings)
    
    - Add ENABLE_TOOL_SEARCH toggle to Claude provider form
      - Add checkbox in CommonConfigEditor.tsx (alongside teammates toggle)
      - When enabled, writes `"env": { "ENABLE_TOOL_SEARCH": "true" }`
      - When disabled, removes the key; takes effect on provider switch
      - Add zh/en/ja i18n key: `claudeConfig.enableToolSearch`
    
    Claude Code 2.1.76+ natively supports this env var, eliminating the need for binary patching.
    
    * feat(claude): add effortLevel high toggle to provider form
    
    - Add "high-effort thinking" checkbox to Claude provider config form
    - When checked, writes `"effortLevel": "high"`; when unchecked, removes the field
    - Add zh/en/ja i18n translations
    
    * refactor(claude): remove deprecated alwaysThinking toggle
    
    - Claude Code now enables extended thinking by default; alwaysThinkingEnabled is a no-op
    - Thinking control is now handled via effortLevel (added in prior commit)
    - Remove state, switch case, and checkbox UI from CommonConfigEditor
    - Clean up alwaysThinking i18n keys across zh/en/ja locales
    
    * feat(opencode): add setCacheKey: true to all provider presets
    
    - Add setCacheKey: true to options in all 33 regular presets
    - Add setCacheKey: true to OPENCODE_DEFAULT_CONFIG for custom providers
    - Exclude 2 OMO presets (Oh My OpenCode / Slim) which have their own config mechanism
    
    Closes #1523
    
    * fix(codex): resolve 1M context window toggle causing MCP editor flicker
    
    - Add localValueRef to short-circuit duplicate CodeMirror updateListener callbacks,
      breaking the React state → CodeMirror → stale onChange → React state feedback loop
    - Use localValueRef.current in handleContextWindowToggle and handleCompactLimitChange
      to avoid stale closure reads
    - Change compact limit input from type="number" to type="text" with inputMode="numeric"
      to remove unnecessary spinner buttons
    
    * feat(codex): add 1M context window toggle utilities and i18n keys
    
    - Add extractCodexTopLevelInt, setCodexTopLevelInt, removeCodexTopLevelField
      TOML helpers in providerConfigUtils.ts
    - Add i18n keys for contextWindow1M, autoCompactLimit in zh/en/ja locales
    
    * feat(claude): collapse model mapping fields by default
    
    - Wrap 5 model mapping inputs in a Collapsible, collapsed by default
    - Auto-expand when any model value is present (including preset-filled)
    - Show hint text when collapsed explaining most users need no config
    - Add zh/en/ja i18n keys for toggle label and collapsed hint
    - Use variant={null} to avoid ghost button hover style clash in dark mode
    
    * feat(claude): merge advanced fields into single collapsible section
    
    - Merge API format, auth field, and model mapping into a unified "Advanced Options" collapsible
    - Extend smart-expand logic to detect non-default values across all advanced fields
    - Preserve model mapping sub-header and hint with a separator line
    - Update zh/en/ja i18n keys (advancedOptionsToggle, advancedOptionsHint, modelMappingLabel, modelMappingHint)
    
    * feat(copilot): add GitHub Copilot reverse proxy support
    
    Add GitHub Copilot as a Claude provider variant with OAuth device code
    authentication and Anthropic ↔ OpenAI format transformation.
    
    Backend:
    - Add CopilotAuthManager for GitHub OAuth device code flow
    - Implement Copilot token auto-refresh (60s before expiry)
    - Persist GitHub token to ~/.cc-switch/copilot_auth.json
    - Add ProviderType::GitHubCopilot and AuthStrategy::GitHubCopilot
    - Modify forwarder to use /chat/completions for Copilot
    - Add Copilot-specific headers (Editor-Version, Editor-Plugin-Version)
    
    Frontend:
    - Add CopilotAuthSection component for OAuth UI
    - Add useCopilotAuth hook for OAuth state management
    - Auto-copy user code to clipboard and open browser
    - Use 8-second polling interval to avoid GitHub rate limits
    - Skip API Key validation for Copilot providers
    - Add GitHub Copilot preset with claude-sonnet-4 model
    
    Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
    
    * fix(copilot): remove is_expired() calls from tests
    
    Remove references to deleted is_expired() method in test code.
    Only is_expiring_soon() is needed for token refresh logic.
    
    Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
    
    * feat(copilot): add real-time model listing from Copilot API
    
    - Add fetch_models() to CopilotAuthManager calling GET /models endpoint
    - Add copilot_get_models Tauri command
    - Add copilotGetModels() frontend API wrapper
    - Modify ClaudeFormFields to show model dropdown for Copilot providers
      - Fetches available models on component mount when isCopilotPreset
      - Groups models by vendor (Anthropic, OpenAI, Google, etc.)
      - Input + dropdown button combo allows both manual entry and selection
      - Non-Copilot providers keep original plain Input behavior
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
    
    * feat(copilot): add usage query integration
    
    - Add Copilot usage API integration (fetch_usage method)
    - Add copilot_get_usage Tauri command
    - Add GitHub Copilot template in usage query modal
    - Unify naming: copilot → github_copilot
    - Add constants management (TEMPLATE_TYPES, PROVIDER_TYPES)
    - Improve error handling with detailed error messages
    - Add database migration (v5 → v6) for template type update
    - Add i18n translations (zh, en, ja)
    - Improve type safety with TemplateType
    - Apply code formatting (cargo fmt, prettier)
    
    * 修复github 登录和注销问题 ,模型选择问题
    
    * feat(copilot): add multi-account support for GitHub Copilot
    
    - Add multi-account storage structure with v1 to v2 migration
    - Add per-account token caching and auto-refresh
    - Add new Tauri commands for account management
    - Integrate account selection in Proxy forwarder
    - Add account selection UI in CopilotAuthSection
    - Save githubAccountId to ProviderMeta
    - Add i18n translations for multi-account features (zh/en/ja)
    
    * 修复用量查询Reset字段出现多余字符
    
    * refactor(auth-binding): introduce generic provider auth binding primitives
    
    - add shared authBinding types in Rust and TypeScript while keeping githubAccountId as a compatibility field\n- resolve Copilot token, models, and usage through provider-bound account lookup instead of only the implicit default account\n- fix the Unix build regression in settings.rs by restoring std::io::Write for write_all()\n- remove the accidental .github ignore entry and drop leftover Copilot form debug logs\n- keep the first migration step non-breaking by writing both authBinding and the legacy githubAccountId field from the form
    
    * refactor(auth-service): add managed auth command surface and explicit default account state
    
    - introduce generic managed auth commands and frontend auth API wrappers for provider-scoped login, status, account listing, removal, logout, and default-account selection\n- store an explicit Copilot default_account_id instead of relying on HashMap iteration order, and use it consistently for fallback token/model/usage resolution\n- sort managed accounts deterministically and surface default-account state to the UI\n- refactor the Copilot form hook to wrap a generic useManagedAuth implementation while preserving the existing component contract\n- add default-account controls to the Copilot auth section and extend Copilot auth status serialization/tests for the new state
    
    * feat(auth-center): add a dedicated settings entrypoint for managed OAuth accounts
    
    - add an Auth Center tab to Settings so managed OAuth accounts are no longer hidden inside individual provider forms\n- introduce a first AuthCenterPanel that hosts GitHub Copilot account management as the initial managed auth provider\n- keep the provider form experience intact while establishing a global account-management surface for future providers such as OpenAI\n- validate that the new settings tab works cleanly with the generic managed auth hook and existing Copilot account controls
    
    * feat(add-provider): expose managed OAuth sources alongside universal providers
    
    - add an OAuth tab to the Add Provider flow so managed auth sources sit beside app-specific and universal providers\n- reuse the new Auth Center panel inside the dialog, keeping account management discoverable during provider creation\n- make the dialog footer adapt to the OAuth tab so account setup does not pretend to create a provider directly\n- align the add-provider UX with the new architecture where OAuth accounts are global assets and providers bind to them later
    
    * fix(auth-reliability): harden managed auth persistence and refresh behavior
    
    - replace direct Copilot auth store writes with private temp-file writes and atomic rename semantics, and document the local token storage limitation\n- add per-account refresh locks plus a double-check path so concurrent requests do not stampede GitHub token refresh\n- surface legacy migration failures through auth status, expose them in the UI, and add translated copy for the new account-state labels\n- stop writing the legacy githubAccountId field from the provider form while keeping compatibility reads in place\n- add logout error recovery and Copilot model-load toasts so auth failures are no longer silently swallowed
    
    * refactor(copilot-detection): prefer provider type before URL fallbacks
    
    - update forwarder endpoint rewriting to treat providerType as the primary GitHub Copilot signal\n- keep githubcopilot.com string matching only as a compatibility fallback for older provider records without providerType\n- reduce one more path where Copilot behavior depended purely on URL heuristics
    
    * fix(copilot-auth): add cancel button to error state in CopilotAuthSection
    
    - 错误状态下仅有"重试"按钮,用户无法退出(如不可恢复的 403 未订阅错误)
    - 新增"取消"按钮,复用已有的 cancelAuth 逻辑重置为 idle 状态
    
    * 修复打包后github账号头像显示异常
    
    * 修复github copilot 来源的模型测试报错
    
    * feat(copilot-preset): add default model presets for GitHub Copilot
    
    - 补充 Copilot 预设的默认模型配置,用户选完预设即可直接使用
    - ANTHROPIC_MODEL: claude-opus-4.6
    - ANTHROPIC_DEFAULT_HAIKU_MODEL: claude-haiku-4.5
    - ANTHROPIC_DEFAULT_SONNET_MODEL: claude-sonnet-4.6
    - ANTHROPIC_DEFAULT_OPUS_MODEL: claude-opus-4.6
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
    Co-authored-by: 周梦泽 <mengze.zhou@dafeng-tech.com>
    Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
  • fix: toolbar compact mode not triggering on Windows due to left-side overflow (#1375)
    The toolbar container used `justify-end` which caused content to overflow
    to the left side. Browser `scrollWidth` does not account for left-side
    overflow, so `useAutoCompact` could never detect it and compact mode
    never activated — resulting in clipped tab labels (e.g. "aude" instead
    of "Claude") at minimum window width.
    
    Fix: remove `justify-end` from the toolbar container and use `ml-auto`
    on the child element instead. This keeps the right-aligned appearance
    but makes overflow go rightward, where `scrollWidth` correctly detects
    it and triggers compact mode.
    
    Co-authored-by: zuolan <zuolan1102@qq.com>
    Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
  • 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.
  • feat(release): add RPM and Flatpak packaging support for Linux
    - Add RPM bundle to Linux build targets in CI workflow
    - Add Flatpak manifest, desktop entry, and AppStream metainfo
    - Update release workflow to build and publish .rpm and .flatpak artifacts
    - Update README docs with new Linux package formats and installation instructions
    - Add .gitignore rules for Flatpak build artifacts
  • 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>
  • chore: unify code formatting and remove unused code
    - Apply cargo fmt to Rust code with multiline error handling
    - Apply Prettier formatting to TypeScript code with trailing commas
    - Unify #[allow(non_snake_case)] attribute formatting
    - Remove unused ProviderNotFound error variant from error.rs
    - Add vitest-report.json to .gitignore to exclude test artifacts
    - Optimize readability of error handling chains with vertical alignment
    
    All tests passing: 22 Rust tests + 126 frontend tests
  • feat: add provider usage query with JavaScript scripting support (#101)
    * feat: add provider usage query functionality
    
    - Updated `Cargo.toml` to include `regex` and `rquickjs` dependencies for usage script execution.
    - Implemented `query_provider_usage` command in `commands.rs` to handle usage queries.
    - Created `UsageScript` and `UsageData` structs in `provider.rs` for managing usage script configurations and results.
    - Added `execute_usage_script` function in `usage_script.rs` to run user-defined scripts for querying usage.
    - Enhanced `ProviderList` component to include a button for configuring usage scripts and a modal for editing scripts.
    - Introduced `UsageFooter` component to display usage information and status.
    - Added `UsageScriptModal` for editing and testing usage scripts with preset templates.
    - Updated Tauri API to support querying provider usage.
    - Modified types in `types.ts` to include structures for usage scripts and results.
    
    * feat(usage): support multi-plan usage display for providers
    
    - 【Feature】
      - Update `UsageResult` to support an array of `UsageData` for displaying multiple usage plans per provider.
      - Refactor `query_provider_usage` command to parse both single `UsageData` objects (for backward compatibility) and arrays of `UsageData`.
      - Enhance `usage_script` validation to accept either a single usage object or an array of usage objects.
    - 【Frontend】
      - Redesign `UsageFooter` to iterate and display details for all available usage plans, introducing `UsagePlanItem` for individual plan rendering.
      - Improve usage display with color-coded remaining balance and clear plan information.
      - Update `UsageScriptModal` test notification to summarize all returned plans.
      - Remove redundant `isCurrent` prop from `UsageFooter` in `ProviderList`.
    - 【Build】
      - Change frontend development server port from `3000` to `3005` in `tauri.conf.json` and `vite.config.mts`.
    
    * feat(usage): enhance query flexibility and display
    - 【`src/types.ts`, `src-tauri/src/provider.rs`】Make `UsageData` fields optional and introduce `extra` and `invalidMessage` for more flexible reporting.
      - `expiresAt` replaced by generic `extra` field.
      - `isValid`, `remaining`, `unit` are now optional.
      - Added `invalidMessage` to provide specific reasons for invalid status.
    - 【`src-tauri/src/usage_script.rs`】Relax usage script result validation to accommodate optional fields in `UsageData`.
    - 【`src/components/UsageFooter.tsx`】Update UI to display `extra` field and `invalidMessage`, and conditionally render `remaining` and `unit` based on availability.
    - 【`src/components/UsageScriptModal.tsx`】
      - Add a new `NewAPI` preset template demonstrating advanced extractor logic for complex API responses.
      - Update script instructions to reflect optional fields and new variable syntax (`{{apiKey}}`).
      - Remove old "DeepSeek" and "OpenAI" templates.
      - Remove basic syntax check for `return` statement.
    - 【`.vscode/settings.json`】Add `dish-ai-commit.base.language` setting.
    - 【`src-tauri/src/commands.rs`】Adjust usage logging to handle optional `remaining` and `unit` fields.
    
    * chore(config): remove VS Code settings from version control
    
    - delete .vscode/settings.json to remove editor-specific configurations
    - add /.vscode to .gitignore to prevent tracking of local VS Code settings
    - ensure personalized editor preferences are not committed to the repository
    
    * fix(provider): preserve usage script during provider update
    
    - When updating a provider, the `usage_script` configuration within `ProviderMeta` was not explicitly merged.
    - This could lead to the accidental loss of `usage_script` settings if the incoming `provider` object in the update request did not contain this field.
    - Ensure `usage_script` is cloned from the existing provider's meta when merging `ProviderMeta` during an update.
    
    * refactor(provider): enforce base_url for usage scripts and update dev ports
    - 【Backend】
        - `src-tauri/src/commands.rs`: Made `ANTHROPIC_BASE_URL` a required field for Claude providers and `base_url` a required field in `config.toml` for Codex providers when extracting credentials for usage script execution. This improves error handling by explicitly failing if these critical URLs are missing or malformed.
    - 【Frontend】
        - `src/App.tsx`, `src/components/ProviderList.tsx`: Passed `appType` prop to `ProviderList` component to ensure `updateProvider` calls within `handleSaveUsageScript` correctly identify the application type.
    - 【Config】
        - `src-tauri/tauri.conf.json`, `vite.config.mts`: Updated development server ports from `3005` to `3000` to standardize local development environment.
    
    * refactor(usage): improve usage data fetching logic
    
    - Prevent redundant API calls by tracking last fetched parameters in `useEffect`.
    - Avoid concurrent API requests by adding a guard in `fetchUsage`.
    - Clear usage data and last fetch parameters when usage query is disabled.
    - Add `queryProviderUsage` API declaration to `window.api` interface.
    
    * fix(usage-script): ensure usage script updates and improve reactivity
    
    - correctly update `usage_script` from new provider meta during updates
    - replace full page reload with targeted provider data refresh after saving usage script settings
    - trigger usage data fetch or clear when `usageEnabled` status changes in `UsageFooter`
    - reduce logging verbosity for usage script execution in backend commands and script execution
    
    * style(usage-footer): adjust usage plan item layout
    
    - Decrease width of extra field column from 35% to 30%
    - Increase width of usage information column from 40% to 45%
    - Improve visual balance and readability of usage plan items
  • refactor: reorganize documentation structure
    - Remove docs/ from .gitignore to track documentation files
    - Delete completed plan documents (encrypted-config-plan.md, updater-plan.md)
    - Add roadmap.md with project milestones and future features
  • enhance(ci): improve release workflow with concurrency control and updated dependencies
    - Add concurrency control to prevent multiple simultaneous releases
    - Upgrade softprops/action-gh-release from v1 to v2 for better reliability
    - Add docs/ directory to .gitignore to exclude documentation build artifacts
  • 修复 Electron 应用窗口不显示的问题
    - 修正 Electron 依赖版本为 28.0.0(解决安装问题)
    - 更新 package.json 中的启动脚本,改进并发命令执行
    - 修正主进程入口文件路径配置
    - 调整 TypeScript 编译配置的根目录设置
    - 添加 Windows 开发环境启动脚本 start-dev.bat
    - 更新 .gitignore 排除编译产物和锁文件
    
    问题原因:pnpm 默认阻止了 Electron 安装脚本执行,导致应用无法正常启动