644 Commits

  • feat(config): add RightCode provider and rename Z.ai GLM
    - Add RightCode provider preset with GPT-5.2 models
    - Rename "Z.ai GLM" to "Zhipu GLM en" for clarity
  • fix(config): remove icon config from provider preset
    Remove unused icon and iconColor fields from Requesty Cloud preset
  • feat(icons): replace MCP button icon with official MCP logo
    Use inline SVG for MCP icon to support currentColor inheritance,
    enabling proper hover color transitions.
  • feat(icons): add new provider icons and fix SiliconFlow iconColor
    - Add rc.svg for RightCode (optimized from 96KB to 581 bytes)
    - Add catcoder.svg for KAT-Coder (快手)
    - Add mcp.svg for Model Context Protocol
    - Add siliconflow.svg for SiliconFlow
    - Register all new icons in index.ts
    - Add icon config for RightCode in claude/codex presets
    - Add icon config for KAT-Coder in claude/opencode presets
    - Fix SiliconFlow iconColor from #000000 to #6E29F6
  • fix(icon): auto-apply default color from metadata when color prop is not provided
    When ProviderIcon is used without a color prop, it now automatically
    fetches the defaultColor from icon metadata. This fixes the issue where
    Gemini app icon turns black when selected in AppSwitcher, because the
    component was inheriting the parent's text-foreground color.
  • 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
  • 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
  • feat(settings): add app visibility settings
    Allow users to choose which apps (Claude, Codex, Gemini, OpenCode) to display on the homepage.
    
    - Add VisibleApps type and settings field in both frontend and backend
    - Refactor AppSwitcher to render apps dynamically based on visibility
    - Extract ToggleRow component for reuse
    - Add i18n support for app visibility settings
  • feat(settings): set Gemini visibility to false by default
    New users will see Claude, Codex, and OpenCode by default, with Gemini hidden.
  • Feat/provider individual config (#663)
    * refactor(ui): simplify UpdateBadge to minimal dot indicator
    
    * feat(provider): add individual test and proxy config for providers
    
    Add support for provider-specific model test and proxy configurations:
    
    - Add ProviderTestConfig and ProviderProxyConfig types in Rust and TypeScript
    - Create ProviderAdvancedConfig component with collapsible panels
    - Update stream_check service to merge provider config with global config
    - Proxy config UI follows global proxy style (single URL input)
    
    Provider-level configs stored in meta field, no database schema changes needed.
    
    * feat(ui): add failover toggle and improve proxy controls
    
    - Add FailoverToggle component with slide animation
    - Simplify ProxyToggle style to match FailoverToggle
    - Add usage statistics button when proxy is active
    - Fix i18n parameter passing for failover messages
    - Add missing failover translation keys (inQueue, addQueue, priority)
    - Replace AboutSection icon with app logo
    
    * fix(proxy): support system proxy fallback and provider-level proxy config
    
    - Remove no_proxy() calls in http_client.rs to allow system proxy fallback
    - Add get_for_provider() to build HTTP client with provider-specific proxy
    - Update forwarder.rs and stream_check.rs to use provider proxy config
    - Fix EditProviderDialog.tsx to include provider.meta in useMemo deps
    - Add useEffect in ProviderAdvancedConfig.tsx to sync expand state
    
    Fixes #636
    Fixes #583
    
    * fix(ui): sync toast theme with app setting
    
    * feat(settings): add log config management
    
    Fixes #612
    Fixes #514
    
    * fix(proxy): increase request body size limit to 200MB
    
    Fixes #666
    
    * docs(proxy): update timeout config descriptions and defaults
    
    Fixes #612
    
    * fix(proxy): filter x-goog-api-key header to prevent duplication
    
    * fix(proxy): prevent proxy recursion when system proxy points to localhost
    
    Detect if HTTP_PROXY, HTTPS_PROXY, or ALL_PROXY environment variables
    point to loopback addresses (localhost, 127.0.0.1), and bypass system
    proxy in such cases to avoid infinite request loops.
    
    * fix(i18n): add providerAdvanced i18n keys and fix failover toast parameter
    
    - Add providerAdvanced.* i18n keys to en.json, zh.json, and ja.json
    - Fix failover toggleFailed toast to pass detail parameter
    - Remove Chinese fallback text from UI for English/Japanese users
    
    * fix(tray): restore tray-provider events and enable Auto failover properly
    
    - Emit provider-switched event on tray provider click (backward compatibility)
    - Auto button now: starts proxy, takes over live config, enables failover
    
    * fix(log): enable dynamic log level and single file mode
    
    - Initialize log at Trace level for dynamic adjustment
    - Change rotation strategy to KeepSome(1) for single file
    - Set max file size to 1GB
    - Delete old log file on startup for clean start
    
    * fix(tray): fix clippy uninlined format args warning
    
    Use inline format arguments: {app_type_str} instead of {}
    
    * fix(provider): allow typing :// in endpoint URL inputs
    
    Change input type from "url" to "text" to prevent browser
    URL validation from blocking :// input.
    
    Closes #681
    
    * fix(stream-check): use Gemini native streaming API format
    
    - Change endpoint from OpenAI-compatible to native streamGenerateContent
    - Add alt=sse parameter for SSE format response
    - Use x-goog-api-key header instead of Bearer token
    - Convert request body to Gemini contents/parts format
    
    * feat(proxy): add request logging for debugging
    
    Add debug logs for outgoing requests including URL and body content
    with byte size, matching the existing response logging format.
    
    * fix(log): prevent usize underflow in KeepSome rotation strategy
    
    KeepSome(n) internally computes n-2, so n=1 causes underflow.
    Use KeepSome(2) as the minimum safe value.
  • feat: 添加 ESC 键快捷返回功能 (#670)
    * feat: 添加 ESC 键快捷返回功能
    
    - FullScreenPanel 组件支持 ESC 键关闭
    - App.tsx 主页面支持 ESC 键返回主界面
    - 优化键盘事件处理,合并多个监听器
    - 使用事件捕获阶段避免冲突
    - 适用于所有子页面:MCP、设置、Prompts、Skills 等
    - 跨平台兼容:macOS、Windows、Linux
    
    * perf: 优化 ESC 键处理逻辑
    
    - 使用 useRef 避免闭包陷阱,提升性能
    - 修复输入框中按 ESC 会关闭面板的问题
    - 检测焦点元素,不干扰输入框的 ESC 行为
    - 改进用户体验,避免意外关闭导致数据丢失
    
    * fix: enhance global keyboard shortcuts and improve useModelState sync
    
    - App & FullScreenPanel: Use `isTextEditableTarget` to prevent shortcuts (ESC, etc.) from triggering while editing text.
    - useModelState: Prevent overwriting user input during config synchronization.
    - App: Add `Cmd/Ctrl + ,` shortcut to open settings.
    - Add `isTextEditableTarget` utility.
  • fix(provider): fix stale data shown when reopening edit dialog after save (#654)
    Add `open` to initialData useMemo dependencies to ensure latest provider
    data is read each time the dialog opens.
  • feat(opencode): add model-level options editor
    Add support for configuring per-model options like provider routing.
    Each model row now has an expand/collapse toggle to show a key-value
    editor for model-specific options (e.g., provider order, fallbacks).
    
    - Add options field to OpenCodeModel in Rust and TypeScript
    - Add expandable key-value editor UI for each model
    - Use local state pattern for option key input to prevent focus loss
    - Add i18n translations for zh/en/ja
  • feat(opencode): add extra options editor for SDK configuration
    Add key-value pair editor for configuring additional SDK options like
    timeout, setCacheKey, etc. Values are automatically parsed to appropriate
    types (number, boolean, object) on save.
    
    - Add `extra` field with serde flatten in Rust backend
    - Add index signature to OpenCodeProviderOptions type
    - Create ExtraOptionKeyInput component with local state pattern
    - Place extra options section above models configuration
  • fix(opencode): prevent model ID input focus loss on keystroke
    Use local state + onBlur pattern for ModelIdInput to keep React key
    stable during editing. Previously, each keystroke changed the object
    key, causing React to unmount/remount the input and lose focus.
  • fix(opencode): use AGENTS.md as prompt filename
    OpenCode follows the same convention as Codex, using AGENTS.md
    instead of OPENCODE.md for the system prompt file.
  • fix(opencode): hide test model button for unsupported adapter
    OpenCode lacks a dedicated adapter and falls back to Codex adapter,
    which has incompatible config structure. Hide the test button in UI
    to prevent users from triggering unsupported operations.
  • fix(opencode): generate unique provider key when duplicating
    OpenCode uses user-provided provider keys as IDs instead of random UUIDs.
    When duplicating a provider, generate a unique key by appending "-copy"
    suffix (or "-copy-2", "-copy-3", etc. if already exists).
  • feat(opencode): add manual provider key input with duplicate check
    - Add Provider Key input field for OpenCode providers (between icon and name)
    - User must manually enter a unique key instead of auto-generating from name
    - Real-time validation: format check and duplicate detection
    - Key is immutable after creation (disabled in edit mode)
    - Remove slugify auto-generation logic from mutations
    - Add beforeNameSlot prop to BasicFormFields for extensibility
    - Add i18n translations for zh/en/ja
  • fix(opencode): fix add/remove provider flow and toast messages
    - Create separate removeFromLiveConfig API for additive mode apps
      (remove only removes from live config, not database)
    - Fix useSwitchProviderMutation to invalidate opencodeLiveProviderIds
      cache so button state updates correctly after add operation
    - Show appropriate toast messages:
      - Add: "已添加到配置" / "Added to config"
      - Remove: "已从配置移除" / "Removed from config"
    - Add i18n texts for addToConfigSuccess and removeFromConfigSuccess
  • fix(opencode): distinguish remove and delete confirmation dialogs
    Separate the confirmation dialogs for "remove from config" and "delete
    provider" operations in OpenCode mode to help users understand the
    different impacts of each action.
  • fix(opencode): enable usage auto-query for providers in config
    For OpenCode (additive mode), use isInConfig instead of isCurrent to
    determine whether to enable usage auto-query. This allows providers
    that have been added to the config to have their usage queried
    automatically.
  • fix(opencode): allow delete button for all providers in additive mode
    OpenCode uses additive mode where the main "Remove" button removes from
    live config, while the delete button should delete from database. The
    delete button should always be enabled for OpenCode providers.
  • fix(opencode): remove current provider concept for additive mode
    OpenCode uses additive mode where all providers coexist in config file,
    so there's no "current" provider concept. This commit:
    
    - Skip setting is_current in switch_normal for OpenCode
    - Return empty string from ProviderService::current for OpenCode
    - Disable active provider highlight in ProviderCard for OpenCode
  • fix(opencode): show Base URL field for all SDK types
    Previously Base URL was only shown for @ai-sdk/openai-compatible.
    Now it's always visible to support proxy scenarios for official SDKs
    like DeepSeek, Anthropic, etc.
  • fix(opencode): skip reading live config when editing provider
    OpenCode's read_live_settings returns the full opencode.json file
    instead of just the provider fragment. This caused the edit dialog
    to save the complete config structure as settingsConfig, creating
    nested provider configurations.
    
    For OpenCode's additive mode, use DB config directly since each
    provider's config is stored independently.
  • fix(opencode): prevent config nesting and use slugified provider IDs
    - Skip backfill logic for OpenCode (additive mode doesn't need it)
    - Add defensive check in write_live_snapshot to extract provider fragment
    - Use slugified name as provider ID for readable config keys
  • feat(opencode): add provider presets and fix preset selection handler
    - Add 19 new provider presets for OpenCode (cn_official, aggregator, third_party)
    - Add OpenCode handling branch in handlePresetChange to properly populate
      form fields (baseURL, apiKey, npm, models) when selecting a preset
    - Add OpenCode reset logic in custom mode branch
  • fix(opencode): hide common config snippet UI and prevent auto-merge
    - Add `enabled` parameter to useCommonConfigSnippet hook
    - Skip all loading and auto-merge logic when enabled=false
    - Replace CommonConfigEditor with simplified JsonEditor for OpenCode
    - Prevent Claude's common config snippet from being injected into OpenCode
  • refactor(opencode): simplify API format selector
    - Reduce npm package options from 10 to 4 core API formats (OpenAI, OpenAI Compatible, Anthropic, Google)
    - Rename "AI SDK Package" to "API Format" in i18n (zh/en/ja)
    - Remove check icon from Select dropdown items for cleaner UI
  • fix(ui): resolve Select dropdown not appearing in FullScreenPanel
    - Increase SelectContent z-index from z-50 to z-[100] to appear above FullScreenPanel (z-[60])
    - Replace form.watch() with form.getValues() in useCallback handlers for correct react-hook-form usage
    - Remove max-w-[56rem] constraints from various panels for consistent full-width layout
  • feat(provider): hide universal tab for OpenCode
    OpenCode doesn't support universal providers, so the tab is
    hidden to avoid confusion for users.
  • feat(opencode): add OpenCode toggle switches to MCP and Skills panels
    - Add opencode to AppType and SkillApps interfaces in skills.ts
    - Add OpenCode Switch component to UnifiedMcpPanel list items
    - Add OpenCode Switch component to UnifiedSkillsPanel list items
    - Include OpenCode in enabled counts and header statistics for both panels
  • feat(opencode): add OpenCode icon to icon system
    Register OpenCode SVG icon in the icons index so AppSwitcher displays
    the proper logo instead of fallback initials.
  • feat(opencode): implement isInConfig semantics for additive provider management
    OpenCode uses additive provider management where providers can exist in
    the database but not necessarily in the live opencode.json config. This
    commit implements proper isInConfig state:
    
    Backend:
    - Add get_opencode_live_provider_ids command to query live config
    
    Frontend:
    - Add getOpenCodeLiveProviderIds API method
    - ProviderList queries live provider IDs and computes isInConfig
    - ProviderCard receives and passes isInConfig to ProviderActions
    - ProviderActions already handles the add/remove button logic
  • feat(opencode): hide proxy UI for OpenCode
    OpenCode uses additive provider management (multiple providers coexist),
    so proxy/failover features are not applicable. This commit:
    - Conditionally renders ProxyToggle only for non-OpenCode apps
    - Fixes toast message label to properly handle opencode app type
  • feat(opencode): add OpenCode button to AppSwitcher
    Add the fourth tab button for OpenCode in the app switcher component,
    making the OpenCode providers page accessible from the main navigation.
  • fix(opencode): address issues found during OpenCode integration review
    - Fix MCP server not removed from opencode.json when unchecked in edit modal
    - Fix Windows atomic write failure when opencode.json already exists
    - Fix i18n keys mismatch in OpenCodeFormFields (use opencode.* namespace)
    - Fix unit test missing apps.opencode field assertion
  • feat(opencode): Phase 10 - Internationalization for OpenCode
    Update i18n translation files (zh.json, en.json, ja.json):
    
    - Add "opencode" to apps section: "OpenCode"
    - Add provider section keys:
      - addOpenCodeProvider: Add OpenCode Provider
      - addToConfig: Add (for additive mode button)
      - removeFromConfig: Remove
      - inConfig: Added
    - Add new "opencode" section with UI labels:
      - npmPackage: AI SDK Package
      - npmPackageHint: Package selection hint
      - baseUrl, baseUrlHint: Base URL configuration
      - models, modelsHint: Model configuration
      - addModel, modelId, modelName: Model editor labels
      - noModels: Empty state message
    - Add "opencode" to mcp.unifiedPanel.apps section
    - Add "opencode" to skills.apps section
  • feat(opencode): Phase 9 - Frontend UI components for OpenCode
    - Create OpenCodeFormFields.tsx with:
      - NPM package selector (from AI SDK ecosystem)
      - API Key input using shared ApiKeySection component
      - Base URL input (shown for openai-compatible)
      - Dynamic models editor (add/remove models)
    
    - Update ProviderForm.tsx:
      - Import OpenCode presets and form fields
      - Add OPENCODE_DEFAULT_CONFIG constant
      - Add OpenCode to PresetEntry type union
      - Add OpenCode preset entries in useMemo
      - Add OpenCode state hooks (npm, apiKey, baseUrl, models)
      - Add OpenCode change handlers syncing to form
      - Add OpenCodeFormFields rendering section
      - Add OpenCode config editor using CommonConfigEditor
    
    - Update ProviderActions.tsx for OpenCode additive mode:
      - Add appId and isInConfig props
      - Implement "Add to Config" / "Remove from Config" buttons
      - Disable failover mode for OpenCode
      - Update delete button logic for additive mode
    
    - Update ProviderCard.tsx:
      - Pass appId and isInConfig to ProviderActions
    
    - Update AddProviderDialog.tsx:
      - Add OpenCode base URL extraction from options.baseURL
  • feat(opencode): Phase 8 - OpenCode provider presets configuration
    - Create src/config/opencodeProviderPresets.ts with:
      - OpenCodeProviderPreset interface for preset structure
      - opencodeNpmPackages: AI SDK npm package options
      - Provider presets: OpenAI, Anthropic, Google, DeepSeek, Mistral, Groq
      - OpenAI Compatible custom template for third-party providers
    - Each preset uses OpenCodeProviderConfig with npm, options, models structure
    - Includes apiKeyUrl for quick access to API key pages
    - Template values for dynamic API key input
  • feat(opencode): Phase 7 - Frontend TypeScript type definitions
    - Add "opencode" to AppId type in lib/api/types.ts
    - Extend McpApps interface with opencode field in types.ts
    - Add OpenCode-specific types: OpenCodeModel, OpenCodeProviderOptions,
      OpenCodeProviderConfig, OpenCodeMcpServerSpec
    - Add opencodeConfigDir to Settings interface
    - Add importOpenCodeFromLive() to providersApi
    - Fix type errors across components:
      - AppSwitcher: add opencode to icon/name mappings
      - McpFormModal: add opencode to enabledApps state
      - PromptFormModal/Panel: add opencode filename mapping
      - EndpointSpeedTest: add opencode timeout config
      - useBaseUrlState: add opencode to appType union
      - ProxyToggle: add opencode label
      - App.tsx: handle opencode fallback for SkillsPage
    - Update ProxyTakeoverStatus with opencode field (always false)
    - Fix test mocks in tests/msw/state.ts
  • feat(usage): improve custom template system with variable hints and validation fixes (#628)
    * feat(usage): improve custom template with variables display and explicit type detection
    
    Combine two feature improvements:
    1. Display supported variables ({{baseUrl}}, {{apiKey}}) with actual values in custom template mode
    2. Add explicit templateType field for accurate template mode detection
    
    ## Changes
    
    ### Frontend
    - Display template variables with actual values extracted from provider settings
    - Add templateType field to UsageScript for explicit mode detection
    - Support template mode persistence across sessions
    
    ### Backend
    - Add template_type field to UsageScript struct
    - Improve validation logic based on explicit template type
    - Maintain backward compatibility with type inference
    
    ### I18n
    - Add "Supported Variables" section translation (zh/en/ja)
    
    ### Benefits
    - More accurate template mode detection (no more guessing)
    - Better user experience with variable hints
    - Clearer validation rules per template type
    
    * fix(usage): resolve custom template cache and validation issues
    
    Combine three bug fixes to make custom template mode work correctly:
    
    1. **Update cache after test**: Testing usage script successfully now updates the main list cache immediately
    2. **Fix same-origin check**: Custom template mode can now access different domains (SSRF protection still active)
    3. **Fix field naming**: Unified to use autoQueryInterval consistently between frontend and backend
    
    ## Problems Solved
    
    - Main provider list showing "Query failed" after successful test
    - Custom templates blocked by overly strict same-origin validation
    - Auto-query intervals not saved correctly due to inconsistent naming
    
    ## Changes
    
    ### Frontend (UsageScriptModal)
    - Import useQueryClient and update cache after successful test
    - Invalidate usage cache when saving script configuration
    - Use standardized autoQueryInterval field name
    
    ### Backend (usage_script.rs)
    - Allow custom template mode to bypass same-origin checks
    - Maintain SSRF protection for all modes
    
    ### Hooks (useProviderActions)
    - Invalidate usage query cache when saving script
    
    ## Impact
    
    Users can now use custom templates freely while security validations remain intact for general templates.
    
    * fix(usage): correct provider credential field names
    
    - Claude: support both ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN
    - Gemini: use GEMINI_API_KEY instead of GOOGLE_GEMINI_API_KEY
    - Codex: use OPENAI_API_KEY and parse base_url from TOML config string
    
    Addresses review feedback from PR #628
    
    * style: format code
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • feat(proxy): add thinking signature rectifier for Claude API (#595)
    * feat(proxy): add thinking signature rectifier for Claude API
    
    Add automatic request rectification when Anthropic API returns signature
    validation errors. This improves compatibility when switching between
    different Claude providers or when historical messages contain incompatible
    thinking block signatures.
    
    - Add thinking_rectifier.rs module with trigger detection and rectification
    - Integrate rectifier into forwarder error handling flow
    - Remove thinking/redacted_thinking blocks and signature fields on retry
    - Delete top-level thinking field when assistant message lacks thinking prefix
    
    * fix(proxy): complete rectifier retry path with failover switch and chain continuation
    
    - Add failover switch trigger on rectifier retry success when provider differs from start
    - Replace direct error return with error categorization on rectifier retry failure
    - Continue failover chain for retryable errors instead of terminating early
    
    * feat(proxy): add rectifier config with master switch
    
    - Add RectifierConfig struct with enabled and requestThinkingSignature fields
    - Update should_rectify_thinking_signature to check master switch first
    - Add tests for master switch functionality
    
    * feat(db): add rectifier config storage in settings table
    
    Store rectifier config as JSON in single key for extensibility
    
    * feat(commands): add get/set rectifier config commands
    
    * feat(ui): add rectifier config panel in advanced settings
    
    - Add RectifierConfigPanel component with master switch and thinking signature toggle
    - Add API wrapper for rectifier config
    - Add i18n translations for zh/en/ja
    
    * feat(proxy): integrate rectifier config into request forwarding
    
    - Load rectifier config from database in RequestContext
    - Pass config to RequestForwarder for runtime checking
    - Use should_rectify_thinking_signature with config parameter
    
    * test(proxy): add nested JSON error detection test for thinking rectifier
    
    * fix(proxy): resolve HalfOpen permit leak and RectifierConfig default values
    
    - Fix RectifierConfig::default() to return enabled=true (was false due to derive)
    - Add release_permit_neutral() for releasing permits without affecting health stats
    - Fix 3 permit leak points in rectifier retry branches
    - Add unit tests for default values and permit release
    
    * style(ui): format ProviderCard style attribute
    
    * fix(rectifier): add detection for signature field required error
    
    Add support for detecting "signature: Field required" error pattern
    in the thinking signature rectifier. This enables automatic request
    rectification when upstream API returns this specific validation error.
  • refactor(ui): unify pricing edit modal with FullScreenPanel
    Replace Dialog component with FullScreenPanel in PricingEditModal
    to match the UI style of other edit dialogs (provider, MCP).
    
    Changes:
    - Switch from small centered Dialog to full-screen panel
    - Add back button in header and fixed footer for actions
    - Add Save/Plus icons to submit button