Commit Graph

1744 Commits

  • Update 1.2-installation.md (#2949)
    增加 Windows 运行后无提示的修复方法
  • docs: recommend official Homebrew cask installation
    - Remove personal tap requirement from all READMEs (en/zh/ja)
    - Update v3.15.0 release notes to highlight official cask availability
    - Add celebration banner noting Homebrew official repository inclusion
    - Simplify installation to single command: brew install --cask cc-switch
  • Handle inline thinking in Codex Chat conversion
    - Split leading <think> blocks from Chat content into Responses reasoning output.
    - Keep assistant text output free of inline thinking tags.
    - Support streamed inline thinking blocks before normal text deltas.
    - Add regression coverage for MiniMax-style inline thinking responses.
  • Improve Codex Chat reasoning conversion
    - Convert Chat reasoning_content and reasoning fields into Responses reasoning output items.
    - Emit Responses reasoning summary SSE events for streamed Chat reasoning deltas.
    - Preserve output ordering when reasoning, text, and tool calls are streamed together.
    - Add regression coverage for data-only Chat SSE errors, multiple tool calls, and compact routing.
  • Add Chat Completions routing for Codex providers
    - Add a Codex API format selector and routing badge for Chat Completions providers.
    - Convert Codex Responses requests to upstream Chat Completions when routing is required.
    - Convert Chat Completions JSON and SSE responses back to Responses format.
    - Keep generated Codex wire_api values on Responses for Codex compatibility.
    - Add i18n labels, provider metadata handling, and focused conversion tests.
  • fix(proxy): inject only ANTHROPIC_API_KEY for managed-account Claude takeover
    - Provider: add uses_managed_account_auth / is_github_copilot helpers
      to identify managed-account providers (GitHub Copilot / Codex OAuth)
    - ProxyService: choose auth policy by provider type when taking over
      Claude Live config. Managed accounts drop token env keys and write
      only the ANTHROPIC_API_KEY placeholder; other providers keep the
      existing ANTHROPIC_AUTH_TOKEN fallback behavior
    - Forwarder: add outbound guard that refuses to send the PROXY_MANAGED
      placeholder upstream to *.githubcopilot.com and chatgpt.com
      /backend-api/codex
    - Add unit tests covering detection, injection, and the outbound guard
  • chore: remove LionCC sponsor and presets
    - Remove LionCC sponsor entry from all README files (en/zh/ja)
    - Remove LionCCAPI presets from all provider configs
    - Remove lionccapi i18n keys from all locales
    - Keep lioncc.png icon file as requested
  • - docs: update user manual for v3.15.0
    - Sync zh/en/ja manuals with Claude Desktop and Hermes support
    
    - Update install requirements, official channels, and release asset guidance
    
    - Document Usage Hero, Codex OAuth live models, Save Anyway, Hermes sessions, and Warp launch
    
    - Correct tray and app-scope descriptions to match current implementation
  • fix(skills): install correct skill from skills.sh search results (#2784)
    * fix(skills): install correct skill from skills.sh search results
    
    When multiple skills share the same directory name across different repos,
    SkillCard was passing directory to onInstall/onUninstall, causing handleInstall
    to always match the first result. Switch to using the unique key field
    (directory:repoOwner:repoName) for precise identification.
    
    * test(skills): add regression test for skills.sh install by key
    
    Verifies that clicking install on the second card when two skills share
    the same directory name correctly installs the second skill, not the first.
    
    ---------
    
    Co-authored-by: mrzhao <mrzhao@iflytek.com>
  • fix(usage): reduce price input step to 0.0001 for sub-cent precision (#2793)
    The step was 0.01, preventing input of prices like DeepSeek's cache read
    cost ($0.0028/million tokens). Extract step value to a constant and apply
    to all four price fields.
    
    Closes #2503
  • fix(terminal): Ghostty opens clean window instead of cloning existing tabs (#2801)
    When Ghostty is already running, `open -a` silently ignores `--args`,
    and `open -na` clones all existing tabs into the new instance.
    
    Add a dedicated `launch_macos_ghostty` that uses
    `--quit-after-last-window-closed=true` and `-e bash <script>` to spawn
    a single clean window running claude.
    
    Also change `launch_macos_open_app` from `open -a` to `open -na` so
    other terminals (Alacritty/Kitty/WezTerm/Kaku) correctly open a new
    window when already running.
    
    Closes #2798
  • feat: add Xiaomi MiMo Token Plan presets (#2803)
    * feat: add Xiaomi MiMo token plan presets
    
    * fix: update Xiaomi MiMo provider presets
    
    * fix: align MiMo V2.5 model specs with official documentation
    
    - Update maxTokens from 32000 to 131072 (128K) for mimo-v2.5-pro and mimo-v2.5
    - Update contextWindow from 262144 to 1048576 (1M) for mimo-v2.5
    - Aligns with official specs from Xiaomi MiMo documentation
    - Ensures consistency between OpenClaw and OpenCode presets
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • fix(gemini-native): resolve functionResponse.name and replay thought_signature for synthesized tool call IDs (#2814)
    * fix(gemini-native): resolve functionResponse.name and thought_signature replay for synthesized tool call IDs
    
    Two related bugs in the Gemini Native format conversion layer:
    
    1. **functionResponse.name resolution** (422 error): When Gemini's parallel
       function calls omit the id field, cc-switch synthesizes gemini_synth_*
       IDs. These are stored in the shadow store but can be lost in long sessions,
       causing subsequent tool_result blocks to fail. Fix: pre-scan all assistant
       messages in the request body to seed the tool_name_by_id map, and add a
       last-resort fallback that scans the current content array for matching
       tool_use blocks.
    
    2. **thought_signature replay** (400 error): The Anthropic Messages format
       strips thoughtSignature from tool_use blocks, but Gemini requires it on
       every functionCall in multi-turn tool-use exchanges. Fix: build a
       thought_signature_by_id map from shadow turns and attach thoughtSignature
       when converting tool_use back to functionCall.
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * style: run cargo fmt on transform_gemini.rs
    
    ---------
    
    Co-authored-by: Tiancrimson <tiancrimson@gmail.com>
    Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
    Co-authored-by: Jason <farion1231@gmail.com>
  • fix(session): 修复session log模式下子Agent token统计遗漏 (#2821)
    * fix(session): 修复session log模式下子Agent token统计遗漏
    
    collect_jsonl_files() 只扫描了两层目录,遗漏了子Agent的JSONL日志文件,
    导致子Agent的独立token使用数据完全未统计到session费用中。
    (仅影响session log模式,proxy代理模式不受影响)
    
    * refactor(session): optimize collect_jsonl_files logic
    
    - Replace two independent if statements with if-else for mutually exclusive conditions
    - Remove unnecessary clone() when pushing file paths
    - Add clarifying comments for main session vs subagent files
    - Apply cargo fmt for consistent formatting
    
    Performance improvement: Eliminates redundant clone() operations when
    processing .jsonl files, as a path cannot be both a file and a directory.
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • Fix race condition in useEffect hooks and type assertion bug (#2827)
    - Add active flag pattern to 3 useEffect hooks in App.tsx to prevent
      event listener leaks when component unmounts before async setup completes
    - Add guard check in useSettings.ts to prevent undefined from being
      stored in localStorage when payload.language is missing
    
    Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
  • Add Claude Desktop user guide docs
    - Add the Claude Desktop provider guide in English, Chinese, and Japanese.
    - Add localized screenshots for import, provider setup, model mapping, and local routing.
    - Link the guide from the v3.15.0 release notes and user manual indexes.
  • Add Claude Desktop official preset
    - Add Claude Desktop Official to the Claude Desktop preset list.
    - Treat selected official presets as official mode in the form.
    - Cover the official preset with a preset-order regression test.
  • - Fix proxy test helper clippy warning
    - Mark `should_force_identity_encoding` as test-only.
    
    - Keep runtime forwarding behavior unchanged.
    
    - Verified with local CI checks and no-bundle Tauri build.
  • refactor(presets): render presets in array order and prioritize partners
    Remove the category-based grouping logic from ProviderPresetSelector,
    letting the array position in each preset config file be the single
    source of truth for display order. Move partner presets (PatewayAI,
    火山Agentplan, BytePlus, DouBaoSeed) right after Shengsuanyun across
    all 6 config files so they appear earlier in the UI.
  • feat(presets): add BytePlus provider preset as partner
    Add BytePlus (international Volcengine) to Claude, Claude Desktop,
    Hermes, OpenCode, and OpenClaw with byteplus icon, 256K context window,
    and trilingual promotion text.
  • feat(presets): add 火山Agentplan provider preset as partner
    Add Volcengine Ark Agentplan to Claude, Claude Desktop, Hermes,
    OpenCode, and OpenClaw with huoshan icon and trilingual promotion.
  • chore(presets): update DouBaoSeed endpoint, links, and add as partner
    Switch Anthropic-format base URL from /api/coding to /api/compatible,
    update website/apiKey URLs to Volcengine console with tracking params,
    and promote DouBaoSeed to partner with trilingual promotion text.
  • chore(presets): switch RelaxyCode icon to custom relaxcode.png
    Replace the generic claude icon with a dedicated relaxcode.png icon
    for the RelaxyCode provider presets.
  • feat(presets): add RelaxyCode provider presets
    Add RelaxyCode as a new third-party provider with support for:
    - Claude Code preset (Anthropic native protocol)
    - Codex preset (gpt-5.5 model)
    - Claude Desktop preset (direct mode with passthrough routes)
    
    RelaxyCode is an enterprise-grade AI programming platform providing
    unified access to Claude Code, Codex, and Gemini CLI models.
  • feat(presets): add RunAPI provider presets
    Add RunAPI as a new partner provider with support for:
    - Claude Code preset (Anthropic native protocol)
    - Codex preset (gpt-5.5 model)
    - Claude Desktop preset (direct mode with passthrough routes)
    - OpenCode preset (@ai-sdk/anthropic)
    - OpenClaw preset (anthropic-messages protocol)
    - Hermes preset (anthropic_messages mode)
    - Icon configuration (runapi.jpg)
    - i18n support (zh/en/ja) with ¥14 free credit promotion
    
    RunAPI is a high-performance AI model API gateway supporting 150+
    mainstream models (OpenAI, Claude, Gemini, DeepSeek, Grok) with
    prices as low as 10% of official rates.
  • feat(presets): add ClaudeCN provider presets
    Add ClaudeCN as a new partner provider with support for:
    - Claude Code preset (Anthropic native protocol)
    - Codex preset (gpt-5.5 model)
    - Claude Desktop preset (direct mode with passthrough routes)
    - OpenCode preset (@ai-sdk/anthropic)
    - OpenClaw preset (anthropic-messages protocol)
    - Hermes preset (anthropic_messages mode)
    - Icon configuration (claudecn.png)
    - i18n support (zh/en/ja) with enterprise service promotion
    
    ClaudeCN is an enterprise-grade AI gateway operated by a registered
    company, supporting enterprise procurement processes with corporate
    payments, contracts, and compliance guarantees.
  • feat(presets): add ClaudeAPI provider presets
    Add ClaudeAPI as a new partner provider with support for:
    - Claude Code preset (using ANTHROPIC_AUTH_TOKEN field)
    - Claude Desktop preset (direct mode with passthrough routes)
    - Icon configuration (ClaudeApi.png)
    - i18n support (zh/en/ja) with test credit promotion
    
    ClaudeAPI provides official Anthropic API keys and AWS Bedrock
    routing with support for Tool Use and 1M context.
  • refactor(presets): switch 20 Claude Desktop providers from proxy to direct mode
    - Change mode from "proxy" to "direct" for 20 third-party/aggregator providers
    - Simplify PipeLLM from mappedRoutes to passthroughRoutes for consistency
    - Reduces unnecessary proxy layer overhead for providers that support direct API calls
    
    Affected providers: ShengSuanYun, AIHubMix, DMXAPI, PackyAPI, PatewayAI,
    Cubence, AIGoCode, RightCodes, AICodeMirror, AICoding, CrazyRouter,
    SSSAICode, ModelVerse, CompShare, MicuAPI, CTOK, E-FlowCode,
    VibeCodingAPI, LemonData, PipeLLM
  • feat(presets): add PatewayAI provider presets
    Add PatewayAI as a new partner provider with support for:
    - Claude Code preset (using ANTHROPIC_API_KEY field)
    - Codex preset (gpt-5.5 model)
    - Claude Desktop preset (proxy mode with passthrough routes)
    - Icon configuration (pateway.jpg)
    - i18n support (zh/en/ja) with $3 registration bonus promotion
    
    PatewayAI provides reliable API routing services for Claude Code,
    Codex, and Gemini models.
  • fix(failover): patch P1-P3 reliability gaps surfaced by team review
    - Forwarder buffers non-streaming bodies and primes streaming first
      chunk before signaling success, so body timeouts and SSE first-chunk
      failures route through the circuit breaker instead of being recorded
      as success on response-header arrival
    - Atomic enable-failover: switch to P1 before persisting the flag, and
      roll back auto-added queue entries when the switch is rejected
      (e.g. official providers)
    - Hot-reload circuit breaker config on per-app proxy config change
      instead of waiting for a proxy restart
    - FailoverToggle / FailoverQueueManager / AutoFailoverConfigPanel
      require proxy takeover for the active app; the backend command also
      rejects enabling when takeover is off
    - ProviderHealthBadge consumes the backend is_healthy flag instead of
      hardcoding the 5-failure threshold
    
    Cleanup:
    - impl From<&AppProxyConfig> for CircuitBreakerConfig and use it from
      the command layer
    - Collapse three identical TabsContent blocks into a single map
  • feat(providers): add routing support badges for Claude Code and Codex
    Add visual indicators for routing capabilities on provider cards:
    - Claude Code: "Needs Routing" badge for non-official providers with non-anthropic API formats
    - Claude Code: "No Routing Support" badge for official providers
    - Codex: "No Routing Support" badge for official providers
    
    The badges help users understand which providers support format conversion through routing.
  • chore(presets): migrate OpenClaudeCode to MicuAPI domain
    Replace all openclaudecode.cn URLs with micuapi.ai across all
    provider presets (Claude, Codex, Hermes, OpenClaw, OpenCode,
    Claude Desktop). This includes website URLs, API key URLs, and
    base URLs.
  • chore(presets): update CrazyRouter API endpoints to cn subdomain
    Update all CrazyRouter baseURL configurations from crazyrouter.com
    to cn.crazyrouter.com across all supported applications (Claude,
    Codex, Gemini, Hermes, OpenClaw, OpenCode, Claude Desktop).
    
    Website and registration URLs remain unchanged.
  • chore(partners): remove DDSHub partner integration
    Remove DDSHub from all provider presets (Claude, Claude Desktop, Codex, Hermes),
    i18n files (zh/en/ja), README docs, and icon system. Physical assets retained for
    potential future restoration.
  • fix(providers): disable model test for third-party Claude providers
    Most third-party Claude Code providers now reject requests from
    non-official clients, so the model test button would just produce
    noisy failures (or worse, trigger risk controls on the provider
    side). Treat third-party Claude providers the same way as official /
    Copilot / Codex OAuth: pass onTest=undefined so ProviderActions
    renders the test button in its existing disabled visual state.
  • feat(codex-oauth): fetch model list from ChatGPT backend on demand
    - Add `get_codex_oauth_models` Tauri command reusing the managed OAuth
      access token to hit `chatgpt.com/backend-api/codex/models`; HTTP and
      multi-shape JSON parsing live in `services::codex_oauth_models` so the
      command stays thin.
    - Unify the Claude form's "fetch models" button across normal / Copilot /
      Codex OAuth presets, drop the auto-load effect for Copilot in favor of
      explicit clicks, and guard against stale responses with a requestId ref.
    - Add Vitest coverage for both Copilot and Codex OAuth paths asserting no
      request on mount and the correct account id on click; add Rust unit
      tests for the four model-list payload shapes.
  • fix(proxy): expose real provider model names in Claude Code menu under takeover
    When proxy takeover is active, write per-role *_MODEL aliases for routing
    and *_MODEL_NAME with the upstream provider's real model name so the
    Claude Code model menu reflects the active provider instead of stale
    display names from a previous switch. Preserves the [1M] capability marker
    for Sonnet/Opus, and strips it from implicit display names.
  • fix(usage): pricing routing, SSE lifecycle, and validation hardening
    * model pricing routing: extend prefix-match families (gpt-/o1-o5/
      gemini-/deepseek-/qwen-/glm-/kimi-/minimax-) with per-family dash
      thresholds so short base IDs like gpt-5 no longer mis-match
      gpt-5-mini; strip ISO and 8-digit date suffixes via UTF-8-safe
      byte matching so claude-haiku-4-5-20251001 falls back to
      claude-haiku-4-5 pricing
    * SSE collector: SseUsageFinishGuard (RAII) guarantees finish() on
      early return or panic; AtomicBool fast path lets push() skip the
      Mutex once first-event time is recorded
    * validation: shared validate_cost_multiplier / validate_pricing_source
      helpers across DAO and service layers; PRICING_SOURCE_RESPONSE /
      PRICING_SOURCE_REQUEST constants replace string literals; price
      fields in update_model_pricing now reject empty / non-decimal /
      negative input before INSERT
    * backfill: add backfill_missing_usage_costs_for_model so a single
      price edit only scans matching rows instead of the full log table;
      startup backfill remains full-scan
    * session_usage{,_codex,_gemini}: share find_model_pricing helper from
      usage_stats; metadata_modified_nanos centralizes mtime precision
    * frontend: NON_NEGATIVE_DECIMAL_REGEX + isNonNegativeDecimalString
      replace three copies of the same multiplier regex; isUnpricedUsage
      surfaces zero-cost rows that have usage tokens (cached per row to
      avoid double evaluation); invalidate usageKeys.all on pricing mutate
      so backfilled rows refresh
  • fix(proxy): patch P0-P3 routing/lifecycle issues across forwarder paths
    * stream_check: thread Result from get_auth_headers via map_err so
      the workspace builds again
    * forwarder: scope rectifier / budget-rectifier flags per-provider so
      failover can still apply rectification on the next attempt
    * forwarder: categorize before record_result; route NonRetryable and
      ClientAbort through release_permit_neutral so client-side failures
      don't pollute circuit breaker or DB health
    * handler_context: parse Gemini model from uri.path() and strip both
      ?query and :action verb defensively in extract_gemini_model_from_path
    * forwarder + response_processor + handlers: introduce
      ActiveConnectionGuard (RAII) so active_connections decrement covers
      the full streaming body lifetime, not just response headers
    * claude_desktop_config: use sort_by_key to clear the clippy gate
  • refactor(proxy): extract handle_rectifier_retry_failure helper
    The signature (RECT-003) and budget (RECT-012) rectifier branches each
    carried ~50 lines of identical "provider error -> record + continue /
    client error -> release permit + return" handling. The only piece that
    varied between them was a log label ("整流" vs "budget 整流").
    
    Move the shared logic into RequestForwarder::handle_rectifier_retry_failure
    that returns Option<ForwardError> — None means "continue to the next
    provider", Some(err) means "terminal failure, return to the client".
    Each call site shrinks from ~50 lines to ~17, drops one level of
    indentation, and the two branches now provably cannot drift apart.
    
    forwarder.rs nets ~40 lines smaller.