Commit Graph

1774 Commits

  • fix(settings): surface "installed but not runnable" state in tool cards
    After an install/update command succeeds, re-probe the tool version: if it
    still can't be detected the tool is installed-but-unrunnable (e.g. Node too
    old), so report a warning toast and show "installed · can't run" with the
    cause, instead of a misleading "success" plus a stale version number.
    
    Read the backend `installed_but_broken` flag rather than matching error
    text; the card's current-version line, action button (no useless "install"
    for a broken tool), and a "check environment" hint all key off it. Drop the
    now-redundant version-clearing setState (the refresh merge already nulls it),
    flatten the action ternary, and use extractErrorMessage in the catch path.
    
    Adds toolNotRunnable / toolActionInstalledNotRunnable / installedNotRunnable
    / toolCheckEnv i18n keys (zh/en/ja).
  • fix(misc): probe tool versions faithfully instead of masking unrunnable installs
    Unify the three probe paths (try_get_version / try_get_version_wsl /
    scan_cli_version) on a cross-platform ShellProbe enum that distinguishes
    "not installed" (shell exit 127) from "installed but --version failed"
    (e.g. Node too old to run the freshly-upgraded CLI).
    
    The found-but-broken case is now reported as-is and no longer falls back to
    scan_cli_version. Previously the fallback surfaced a stale runnable copy
    installed elsewhere (e.g. a Homebrew node vs the nvm node the upgrade wrote
    to), making an upgrade look like it had no effect ("succeeded but version
    unchanged").
    
    Expose the state via a structured `installed_but_broken` flag on ToolVersion
    so the frontend no longer infers it by string-matching the error text. Also
    fixes a WSL path that could mislabel a genuinely-missing tool as broken, and
    extracts the NOT_INSTALLED constant.
  • fix(settings): run batch updates per-tool and lock actions while busy
    Update All previously sent every tool to the backend as one script, where
    set -e (or errorlevel on Windows) aborts the whole batch on the first
    failure, skipping the rest and not refreshing versions for tools that did
    succeed. Run each tool as its own call instead: failures are isolated,
    each tool's version refreshes as soon as it finishes, and the result is
    summarized in a toast (success / partial / failure) listing which tools
    failed.
    
    Also derive an isAnyBusy flag and disable all install/update buttons,
    the refresh button and the WSL shell selectors while any action is
    running, so users can't trigger concurrent global npm/pip writes.
    
    Add the toolActionPartial i18n key (zh/en/ja).
  • feat(misc): broaden CLI version detection to PATH and Windows managers
    Extend scan_cli_version search paths with the PATH environment variable
    and common Windows Node/version-manager locations (pnpm, Volta, nvm,
    Scoop, Yarn). Entries from PATH are skipped when they point at the
    Microsoft\WindowsApps App Execution Alias directory, which is what
    previously caused bogus launches on Windows.
    
    Add unit tests for PATH dedup, child-dir suffix expansion, and the
    WindowsApps alias skip.
  • docs: update settings manual for tool management and Hermes
    Add Hermes to the environment-check table and app-switcher list, fix the
    OpenCode install command (opencode-ai), and describe the new update/install
    flow. Align with the final implementation: drop the removed Install Missing
    action, note that installs run silently with in-button progress, and rename
    the section to Manual Install Commands (now collapsible).
  • feat(settings): expand About page into a tool management panel
    List all managed apps with current/latest versions, with per-tool install
    and update buttons plus an Update All action. Installs and updates now run
    silently: the button shows a spinner for the full duration, versions refresh
    automatically when done, and failures surface the backend error detail in a
    toast.
    
    While loading, the button keeps its label and only swaps the icon for a
    spinner, so width stays constant across zh/en/ja instead of jumping when the
    text changes (e.g. Update -> Updating...).
    
    Also collapses and renames the install-commands area to Manual Install
    Commands, and removes the managed-apps badge row and the Install Missing
    batch button.
  • feat: add silent install/update lifecycle for managed CLI tools
    Expand tool version detection to all six managed apps (including Hermes
    via PyPI), and add a run_tool_lifecycle_action command that installs or
    updates CLI tools silently: it captures the subprocess output and blocks
    until the command actually finishes instead of popping a terminal window
    (Windows uses CREATE_NO_WINDOW). On failure the last lines of stderr are
    returned so the UI can surface a useful message.
    
    Also restores the Windows version-detection path by gating try_get_version
    behind cfg(not(windows)) so it no longer risks triggering the App
    Execution Alias / protocol handler that previously disabled Windows.
  • refactor(proxy): replace panic-prone unwrap/expect with safe patterns
    Harden the proxy module against panics by removing optimistic
    unwrap()/expect() calls in favor of pattern matching and graceful
    fallbacks:
    
    - copilot_optimizer/cache_injector: bind Value::Array/String directly
      instead of is_array()+as_array().unwrap(); use is_none_or and in-place
      string mutation
    - hyper_client: gate the raw-write path with if-let + filter instead of
      has_cases + unwrap()
    - gemini_shadow: recover poisoned RwLock via into_inner() rather than
      panicking, with warn logging
    - streaming_codex_chat: replace expect("tool state exists") with
      let-else (return/continue)
    - merge_tool_results: early-return when messages is absent
    - sse: fall back to from_utf8_lossy on the UTF-8 boundary slice
    
    No behavior change on the happy path; all proxy tests pass.
  • test: align stale tests with merged Codex preset and bucket changes
    CI on main was red because two tests did not follow intentional changes
    that were already merged into the codebase:
    
    - codexChatProviderPresets.test.ts still expected the "Kimi For Coding"
      preset, which was removed in 16c3ef3f. Drop the corresponding entry
      from the expected presets map.
    - import_export_sync.rs still asserted the legacy per-provider
      model_provider id ("rightcode"), but 9fac15b8 unified Codex
      third-party providers into the stable "custom" history bucket. Mirror
      the assertion update already applied to provider_service.rs.
    
    No production code changed; both fixes only update test expectations.
  • fix: coerce empty tool-call arguments to {} in Codex Chat transform
    No-argument tool calls produced empty argument strings that passed
    through both the streaming response path and the request transform
    verbatim. Strict OpenAI-compatible upstreams (e.g. Minimax) reject
    `arguments: ""` with a 400 "invalid function arguments json string",
    while lenient ones (OpenAI, Kimi) silently treat it as an empty object.
    
    Add canonicalize_tool_arguments / canonicalize_tool_arguments_str helpers
    that coerce empty/whitespace arguments to "{}" and apply them at the four
    tool-call argument sites (streaming finalize + three request/response
    transform paths). Leave function_call_output content untouched, where an
    empty string is valid.
  • docs: document Codex Chat reasoning auto-detection
    Add a "Reasoning Auto-Detection" subsection to the Codex local-routing
    manual (zh/en/ja) with the provider capability matrix, and record the
    feature plus the streaming-usage and tool-call reasoning backfill fixes
    in the changelog. Drop the removed Kimi For Coding preset from the
    changelog's Codex Chat preset list.
  • feat: adaptive reasoning detection for Codex Chat providers
    Auto-detect each Chat-routed Codex provider's reasoning interface from
    its name, base URL, and model, then inject the matching thinking
    parameter without manual configuration:
    
    - Platform-first inference (OpenRouter, SiliconFlow) overrides model
      rules, since the same model exposes different reasoning controls
      depending on the hosting platform.
    - Effort tiers are forwarded only to providers that support them
      (DeepSeek, OpenRouter, and StepFun's step-3.5-flash-2603); on/off-only
      providers (Kimi, GLM, Qwen, MiniMax, MiMo, SiliconFlow) drop the level
      instead of sending a field the upstream rejects.
    - OpenRouter uses the native reasoning:{effort} object, clamps max to
      xhigh (its enum has no max), and forwards an explicit effort:"none" so
      reasoning can be turned off.
    - StepFun falls back to inference so per-model effort support is honored
      (the static preset would have forced effort on step-3.5-flash too).
    
    Includes the Codex provider-form reasoning controls, i18n strings
    (zh/en/ja), and response-side reasoning extraction.
  • fix: inject stream_options.include_usage for Codex Chat streaming
    Responses-to-Chat conversion did not set stream_options.include_usage,
    so OpenAI-compatible upstreams (kimi/MiniMax, etc.) omitted the trailing
    usage chunk in streaming mode. This caused token/cost/cache stats to be
    recorded as zero for third-party streaming requests routed through the
    Codex Chat path.
    
    Inject include_usage when the request is streaming, merging into any
    client-provided stream_options instead of overwriting it. Add tests for
    the streaming, non-streaming, and merge cases.
  • feat: remove Kimi For Coding preset from Codex
    The Kimi For Coding preset pins users to a single coding-only model
    (kimi-for-coding), restricting model selection. Drop it from the Codex
    presets and trim the corresponding row in the trilingual user manual.
    The general Kimi preset (Moonshot platform) is kept, and presets for
    other apps are unchanged.
  • fix: backfill placeholder reasoning_content for bare tool-call messages
    Thinking models like kimi/Moonshot and DeepSeek reject any assistant
    message carrying tool_calls without a non-empty reasoning_content. When
    cross-turn history recovery misses (proxy restart drops the in-memory
    cache, ambiguous call_id, or a turn produced no reasoning upstream), the
    converted assistant message has none and the whole request fails with
    'reasoning_content is missing in assistant tool call message'.
    
    Add a final-stage backfill that runs after all input items are
    processed, so genuine trailing reasoning items still attach first and a
    placeholder is only injected when none remains. Mirrors the placeholder
    behavior in transform::anthropic_to_openai_with_reasoning_content.
  • fix: reclassify ClaudeAPI as aggregator to re-enable model test
    ClaudeAPI supports the health/stream check, but the third_party
    category triggers the isClaudeThirdParty gate in ProviderCard that
    disables the model test button for third-party Claude providers.
    Recategorizing as aggregator restores the test action; the partner
    star is unaffected since it is driven by isPartner, not category.
    
    Applied to both the Claude Code and Claude Desktop presets.
  • docs: document Codex Chat provider support in changelog and manual
    Backfill the empty [Unreleased] CHANGELOG section with the Codex Chat
    Completions feature (Chat-to-Responses bridge, 23 third-party presets,
    model mapping table, Stream Check routing, error-envelope conversion,
    "custom" history bucket) plus the community fixes landed since v3.15.0.
    
    Update the zh/en/ja user manual: split the Codex preset tables by
    upstream protocol (native Responses vs Chat Completions), add a "Codex
    Local Routing and Model Mapping" section covering the Needs Local
    Routing toggle and the model catalog, and note Chat-format probing in
    the Stream Check guide. Manual wording matches the live UI strings.
  • feat: convert Codex Chat error responses to Responses envelope
    The Codex Chat-to-Responses bridge already rewrites successful upstream
    responses to the Responses shape, but the error branch in
    handle_codex_chat_to_responses_transform passed Chat-shaped error bodies
    through untouched (MiniMax base_resp, raw OpenAI Chat error, text/plain
    "Unauthorized" pages, etc.), leaving Codex clients unable to recognize the
    error.
    
    Add chat_error_to_response_error in transform_codex_chat to regularize all
    upstream error shapes into the standard {error: {message, type, code, param}}
    envelope, then wire it through a new handle_codex_chat_error_response that
    preserves the original HTTP status code. Non-JSON error bodies (HTML, plain
    text) are wrapped as Value::String and truncated to 1KB at a UTF-8 char
    boundary to keep diagnostic context without flooding the response.
    
    Also fix a pre-existing append-vs-insert pitfall in three rebuilt-body
    branches (Claude transform, Codex Chat normal, Codex Chat error): http
    Builder::header is append, so leaking the upstream Content-Type produced
    two Content-Type headers when the rewritten body was JSON. Remove the
    upstream value before writing application/json.
  • feat: route Codex Chat providers through Stream Check
    Codex Chat providers (apiFormat=openai_chat, e.g. DeepSeek, MiniMax, Kimi)
    were incorrectly probed via /v1/responses by Stream Check, which the upstream
    rejects. Detect chat routing via codex_provider_uses_chat_completions and
    issue the probe against /chat/completions with a Chat-shaped body.
    
    Also align URL fallback order with the production CodexAdapter::build_url:
    origin-only base URLs (https://api.deepseek.com) must hit /v1/<endpoint>
    first; bare /<endpoint> only as a fallback. The previous order made any
    non-404 error on the bare path (401/400/405) flag the provider as down even
    though /v1/<endpoint> would have succeeded.
    
    - Lift origin-only detection into proxy::providers::is_origin_only_url so
      both build_url and Stream Check share a single source of truth.
    - Collapse resolve_codex_stream_urls and resolve_codex_chat_stream_urls into
      a generic resolve_codex_endpoint_urls(base_url, is_full_url, endpoint),
      which also gives the Responses path a symmetric "full endpoint without
      is_full_url flag" fallback for free.
    - Restrict reasoning_effort propagation in the Chat branch to OpenAI o-series
      models, mirroring transform_codex_chat's runtime check.
  • refactor: rewrite Codex local routing toggle hints for clarity
    Reframe OFF/ON hints as action guidance (when to enable) rather than
    scenario descriptions, mirroring the Claude Desktop model mapping copy
    style. Synced across zh/en/ja locales and the component-level
    defaultValue fallback. The switch label "Needs Local Routing" is kept
    unchanged to preserve the routing-layer semantics specific to Codex.
  • fix: collapse mid-stream system messages in Codex Responses to Chat conversion
    MiniMax's OpenAI-compatible chat endpoint strict-rejects any non-leading
    role=system message with "invalid params, chat content has invalid message
    role: system (2013)". The Codex client uses role=developer (and occasionally
    role=system) to inject collaboration_mode / permissions / skills blocks
    mid-conversation, and responses_role_to_chat_role maps both to chat's
    system role. The converted messages array therefore frequently contained
    system entries past index 0, which DeepSeek and OpenAI tolerate but MiniMax
    flags as 2013.
    
    Collapse all system messages into a single leading system message before
    returning the chat request. The rewrite preserves every system fragment
    (joined by "\n\n" in original order) and leaves non-system messages
    untouched, so it is lossless for permissive backends as well.
    
    - Add collapse_system_messages_to_head in transform_codex_chat.rs.
    - Run it on the messages vector at the end of responses_to_chat_completions
      before serializing.
    - Cover the new path with two unit tests: one repros the MiniMax-shaped
      input (developer items between users) and asserts no system role past
      index 0; the other verifies non-system order is preserved and content
      is joined with "\n\n".
  • feat: add Chat Completions routing for 22 Codex third-party presets
    Enable openai_chat routing with explicit model catalogs across the major
    Chinese/Asian providers (DeepSeek, Zhipu GLM, Kimi, MiniMax, Baidu Qianfan,
    Bailian, StepFun, Volcengine Agent Plan, BytePlus, DouBaoSeed, ModelScope,
    Longcat, BaiLing, Xiaomi MiMo, SiliconFlow, Novita AI, Nvidia, etc.). Each
    preset declares its context window so the UI can size catalog rows when the
    preset is picked.
    
    Also lands two consistency fixes uncovered along the way:
    - Include setCodexCatalogModels in resetCodexConfig's useCallback deps to
      match the new third parameter it consumes.
    - Realign TheRouter Codex test to the "custom" model_provider bucket
      established by the recent third-party unification; the previous assertion
      predated that refactor and had been failing on HEAD.
  • fix: preserve Codex model catalog on live read of active provider
    Editing the currently active Codex provider triggered `read_live_settings`,
    which returned only { auth, config }, omitting `modelCatalog`. The form's
    mapping table then initialized to empty, and a subsequent save wiped the
    DB's `modelCatalog` field — silently destroying user-configured model
    mappings after every CC Switch restart.
    
    The mappings already live on disk as a projection in
    `~/.codex/cc-switch-model-catalog.json` (pointed at by `config.toml`'s
    `model_catalog_json`). Reverse-parse that file so live reads return the
    same shape the save path writes.
    
    - Add `read_codex_model_catalog_simplified_from_live` to recover
      `{ model, displayName?, contextWindow? }` entries from the catalog file.
    - Skip user-managed external catalogs (filename != cc-switch-model-catalog.json)
      so we don't downgrade their richer structure to the simplified table.
    - Squash display_name == slug and context_window == default (config's
      `model_context_window`, or 128_000 fallback) so blank inputs round-trip
      back to blank instead of materializing fallback values in the UI.
    - Collapse all failure modes (missing file, parse error, no matching
      field) to Ok(None) so the editor stays openable when the projection
      file is absent or corrupt.
    - Wire the new function into `read_live_settings`'s Codex branch.
    - Cover the new pure helpers with 7 unit tests in codex_config::tests.
  • feat: unify Codex third-party providers into stable "custom" history bucket
    Codex filters resume history by `model_provider`, so switching between
    provider-specific ids like `rightcode` and `aihubmix` made past sessions
    appear to vanish. Collapse all third-party providers into a single
    stable bucket so cross-switch history stays visible.
    
    - Normalize live `model_provider` to "custom" on every Codex write
      (reserved built-in ids like openai/ollama are preserved).
    - Add device-level one-shot migration that rewrites historical JSONL
      session files and the `state_5.sqlite` threads table from legacy
      provider ids into the "custom" bucket. Backs up originals under
      `~/.cc-switch/backups/codex-history-provider-migration-v1/` and uses
      the SQLite Backup API for the state DB.
    - Record completion in `settings.json` under `localMigrations` so the
      migration is strictly idempotent across launches.
    - Update Codex provider preset templates to emit `model_provider = "custom"`
      out of the box.
  • feat: preserve user-selected catalog model in Codex Chat requests
    When Codex client sends a model from the catalog (e.g., user selected via /model),
    preserve that choice instead of always replacing with config.toml's default model.
    
    - Check if request model exists in modelCatalog before falling back to config model
    - Remove CODEX_CHAT_CLIENT_MODEL constant (no longer needed)
    - Add test coverage for catalog model preservation
  • fix: prevent infinite render loop in Codex model catalog
    Break bidirectional sync cycle between catalogRows (child) and catalogModels (parent):
    - Remove catalogModels from child→parent effect dependencies
    - Track last sent data in ref to avoid redundant callbacks
    - Sync ref when parent pushes new data to prevent false positives
    
    Fixes severe UI jittering when adding/editing catalog entries.
  • fix: Codex model catalog WYSIWYG and config consolidation
    - Remove mergeCodexDefaultCatalogModelForSave implicit injection (P1)
      The model mapping table is now the single source of truth; no hidden
      entries are prepended on save.
    
    - Sync first catalog row model into config.toml on save
      Ensures Codex default request model matches the table's first entry
      instead of retaining a stale template value.
    
    - Remove API Format selector from CodexFormFields (P3)
      wire_api is always 'responses'; the selector confused users into
      thinking they were changing the upstream protocol. Only the 'Needs
      Local Routing' toggle remains.
    
    - Add restart hint to model mapping i18n text (P2)
      model_catalog_json is loaded at Codex startup; users are now informed
      that a restart is needed after changes.
    
    - Unify write_codex_live_with_catalog helper (P4)
      Replaces three scattered prepare+write call sites in config.rs,
      provider/live.rs, and proxy.rs with a single entry point.
    
    - Clean up useCodexConfigState dead state (P3 follow-up)
      Remove codexModelName, codexContextWindow, codexAutoCompactLimit and
      their handlers/effects since no component consumes them after the UI
      consolidation.
  • - Restore Codex Chat reasoning fallback
    - Add unique call-id fallback when Codex omits or rewrites previous_response_id.
    
    - Keep ambiguous call ids unresolved to avoid cross-request history leaks.
    
    - Cover fallback and ambiguity behavior with regression tests.
  • - Optimize Codex Chat cache stability
    - Stop deriving Codex session/cache identity from `previous_response_id`.
      - Canonicalize parseable JSON string payloads in Chat and Responses tool conversions.
      - Add regression coverage for cache-sensitive conversion behavior.
  • Add Codex Chat-to-Responses bridge
    - Add Codex provider API format selection and model mapping for Chat-only upstreams.
    - Convert Codex Responses requests to Chat Completions and rebuild Chat responses as Responses output.
    - Preserve reasoning_content across non-streaming, streaming, tool calls, and previous_response_id follow-ups.
    - Add a bounded Codex Chat history cache for restoring tool calls before tool outputs.
    - Cover Chat bridge, compact routing, streaming, and history recovery with focused tests.
  • 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.