Commit Graph
2777 Commits
Author SHA1 Message Date
Jason 2db86e94da docs(release): add v4.0.5 release notes v4.0.5 2026-10-08 23:00:52 +08:00
Jason cf02f670ff chore(release): v4.0.5 2026-10-08 23:00:52 +08:00
Jason 5d24fdf9a6 feat(usage): show all history in the all-time heatmap
The all-time heatmap only covered the last 53 weeks, so older usage was
cut off. It now keeps the last 53 weeks as the default view and adds a
"Show more" toggle that lists earlier history in contiguous 53-week
spans, back to the first recorded day. Each span is titled with its
exact date range and totals, and shading is bucketed across all spans
so they stay comparable.

A new get_usage_first_date command returns the earliest local day across
request logs and daily rollups, honoring the dashboard's app, provider
and model filters, so the heatmap knows how many spans to fetch in one
trends query.
2026-10-08 22:48:02 +08:00
Sailing LoongandSailingLoong 02759c67a1 fix(proxy): mark converted function tools as non-strict for Responses (#7717)
Anthropic tool schemas treat `required` as an arbitrary subset of
`properties`, but the Responses backend strictifies a function tool when
`strict` is omitted: optional attributes land in `required` and the model
is forced to emit fields the client deliberately left optional (#7713 -
Claude Code Agent always emitting the optional `isolation` and losing
non-worktree teammates).

Set `strict: false` explicitly on the converted function tool in
anthropic_to_responses. The hosted web-search branch is untouched, and
`parameters` still passes through clean_schema unchanged, so the
client-side optionality semantics are preserved end to end. This branch
serves both plain Responses providers and the Codex OAuth backend.

Validation: with the production hunk reverted, the new test asserting
strict=false fails (field absent); restored, the transform_responses
suite and the full --lib run are green.

Co-authored-by: SailingLoong <309827397+SailingLoong@users.noreply.github.com>
2026-10-08 22:40:50 +08:00
mr-chenguang 3af55c3973 fix(codex): give the MoArk preset a model catalog and native Responses format (#7940)
* fix(codex): give the MoArk preset a model catalog and native Responses format

模力方舟的 Codex 预设没有声明 modelCatalog,Codex 因此退回通用元数据,
/model 只列出默认模型 deepseek-v4-flash-0731,其余四个模型不可见。

同时补上 apiFormat:这条路径是原生 Responses 直连,但 moark.com 不在
codex.rs 的 CODEX_NATIVE_RESPONSES_HOSTS 兜底名单里,缺省会让
resolve_codex_catalog_tool_profile 落成 ProxyChat 档案——即克隆 Codex
的 gpt-5.5 模板,给聚合平台下发 GPT-5 harness 与自由格式 apply_patch。
该档案的前提是"代理接管并改写 custom→function",而这条路径没有代理。
实测 MoArk 接受 type=="custom" 工具,但按 codex_config.rs 对聚合平台
给出的安全方向(中性模板,degraded but working)仍走 NativeResponses。

reasoningLevels 取自实测:MoArk 在 400 明文里给出自己声明的枚举,平台
不校验该字段的模型退回模型厂商官方档位,两者皆无则不写
(qwen3-coder-plus 实测 effort 完全不生效,写档位只会给出不起作用的
选择器)。

* fix(codex): declare a single none level for MoArk's Qwen3 Coder Plus

评审指出:留空 reasoningLevels 并不表示"没有档位"。后端把未填写理解为
沿用原生模板的 none/high 两档与默认 high,所以 Codex 仍会给出一个不改变
任何行为的"关闭/开启思考"选择器——正是本 PR 声称要避免的东西。改为显式
声明单档 none:apply_codex_reasoning_level_override 生成单档,模板默认
high 不在列表内,默认值随之回落 none。(空数组同样走保留模板的早退分支,
解决不了。)

同时在 codex_config.rs 的
native_responses_catalog_honors_per_model_reasoning_levels 里补两条断言:
单档 none 产出 ["none"] 且默认 none;完全不声明则沿用模板的
["none","high"] 与默认 high。

顺带按评审意见收窄 apiFormat 的归因:表单本就会在预设缺少 apiFormat 时用
codexApiFormatFromWireApi 从 wire_api = "responses" 推出 openai_responses
并写进供应商 meta,所以经表单新增的配置此前并未被错误判定为 ProxyChat,
只有缺少格式信息的存量记录才会。该字段保留,但只是让预设自身信息完整。
2026-10-08 22:39:33 +08:00
Lingbou b1752e1c89 ci(release): require deb and rpm signatures in latest.json check (#7943)
Signed-off-by: Xingqiu Xu <hilbertanjou83@gmail.com>
2026-10-08 22:31:48 +08:00
CL e40ebb6e0a fix(codex): list explicitly configured models from hidden templates (#7925)
Generated catalog entries clone the cached gpt-5.5 template, so a template the official backend marked visibility "hide" hid every explicitly configured provider model (e.g. GLM) from the Codex picker while aggregation still counted them. Pin visibility to "list" for these entries, matching the official mirror path; native official rows keep their own visibility.

Fixes #7924
2026-10-08 22:31:23 +08:00
Betsy 3c9e430f34 fix(installer): drop ProductIcon reference from MSI shortcuts (#5952)
The desktop and Start Menu shortcuts pointed their icon at ProductIcon, which
Windows Installer extracts to %APPDATA%\Microsoft\Installer\{ProductCode}\.
Every build gets a new ProductCode and a major upgrade uninstalls the old
product first, deleting that cache directory. Taskbar pins are copies the MSI
does not manage, so they kept the dead path and showed a blank document icon
once Explorer rebuilt its icon cache (usually after a reboot).

Without an explicit icon, Explorer reads it from the target exe, whose path is
stable across versions. The Icon table and ARPPRODUCTICON stay, so the
Programs and Features icon is unchanged. Pins created before this fix still
carry the dead path and need to be unpinned and pinned again once.

Fixes #5949
2026-10-08 22:27:46 +08:00
Railgun 36c8b87e60 fix(linux): restore Wayland title-bar controls on first show and tray re-show (#7947)
Tao 0.34 wraps the Wayland HeaderBar in an EventBox with above_child=true, so its input window can stack above the minimize/maximize/close buttons after the first map or a hide/show round-trip. Clear above_child on the GTK main thread whenever the main window is shown. This becomes a no-op once Tauri ships tao 0.36+ (tauri-apps/tao#1218).

Also bump the existing input-region nudge by one logical pixel instead of one physical pixel (a no-op on HiDPI), skip it for maximized windows, and run concurrent nudges one at a time so a bumped size is always restored.

Fixes #7405
Fixes #2736
Fixes #7499
2026-10-08 21:52:49 +08:00
Jason 5ae6ad3888 ci(wsl): retry flaky lib tests in the WSL2 nightly
The 9P share sometimes aborts a write mid-test with os error 995
(ERROR_OPERATION_ABORTED): a Claude Desktop config test passed in 1.3s
on one run and failed after 17s on the next with no code change.

Retry up to twice in the nightly only. The ci profile used by PRs keeps
failing on the first error, and nextest still lists retried passes as
FLAKY so repeat offenders stay visible.
2026-10-08 11:25:51 +08:00
Jason 7d8004c408 test(wsl): skip three lib tests the 9P share cannot host
The WSL2 nightly now reaches the lib suite: 3299 of 3302 pass. The rest
are limits of \\wsl.localhost, not product bugs:

- Windows cannot create symlinks on the share ("Incorrect function"),
  so the catalog escape and grokbuild symlink-cycle tests cannot build
  their fixtures. Skip when the link fails under a WSL temp dir and
  keep failing anywhere else.
- Extracting 13,248 files takes over the 180s per-test timeout on 9P.
  Production extracts to the system temp dir, so skip the entry-limit
  test when TEMP is a WSL share.
2026-10-08 11:11:24 +08:00
Jason faae0e4d7e ci(wsl): run the WSL2 nightly from a nextest archive
The nightly has failed since 10-05 with LNK1327: the contract step
re-invoked cargo with TEMP on \\wsl.localhost, cargo re-linked the lib
tests, and mt.exe cannot create its manifest temp file on a UNC path.

Build the lib tests once into a nextest archive with the native TEMP,
and run both the contract test and the lib suite from that archive, so
nothing is built while TEMP points at the WSL share. The archive is
extracted to the runner temp, and --no-tests fail replaces the manual
check that the contract test was discovered.

Supersedes #6856.
2026-10-08 10:43:48 +08:00
Lingbou d90de1ba0e fix(updater): support Linux package auto-updates (#7620)
Align the Tauri frontend packages with the Rust crates, include deb/rpm updater signatures in Linux releases, and publish package-specific entries in latest.json.

Fixes #4060

Signed-off-by: Xingqiu Xu <hilbertanjou83@gmail.com>
2026-10-08 10:10:57 +08:00
funkpopo c5233fe7ef fix(apps): enable native setup for Claude Code npm installs (#7929)
npm 12 blocks Claude Code's postinstall by default and still exits 0, leaving the 500-byte placeholder at bin/claude.exe (Windows reports it as incompatible). Pass --ignore-scripts=false --include=optional --allow-scripts=@anthropic-ai/claude-code to every Claude npm install and update fallback, including the copyable install commands on the Apps page.
2026-10-08 09:51:52 +08:00
f9db9f7056 feat(codex): support GitHub Copilot managed accounts with Responses/Chat routing (#7157)
Add a GitHub Copilot preset for Codex that uses a managed GitHub account.
The local route resolves each request's model against the account's live
Copilot /models catalogue and picks the upstream protocol the model
advertises (native Responses first, Chat Completions as fallback in auto
mode), with an optional explicit protocol override.

- Response handling, the opaque-state rectifier and Stack web_search
  stripping follow the transport actually used for each request rather
  than the stored apiFormat.
- Fetching models fills the catalogue from the account's live prompt
  limit, parallel tool calls and reasoning levels; presets keep
  conservative fallbacks.
- Codex only treats a card as managed Copilot by its provider type, so
  self-hosted relays keep their own key and endpoint.
- Copilot request identity headers are shared between the Claude and
  Codex paths.

Co-authored-by: yuwk <52391318+ump45nose@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jason <farion1231@gmail.com>
2026-10-08 00:10:45 +08:00
Jason efd236a474 docs(manual): update the user manual for v4.0
Bring the zh, en and ja user manuals up to the v4.0.4 interface: the
sidebar layout, the six Settings groups, the Direct / Routing /
Aggregation connection modes, Accounts, and the Apps page. Old
Settings paths (Advanced, Routing, Auth) and takeover wording are gone.

- Add 4.6 Aggregation Mode in all three languages and list it in the
  manual indexes.
- Rewrite 1.3 Interface Overview and 1.5 Settings around the new
  layout; refresh provider, extension, routing, usage and FAQ pages.
- Use the v4.0 release screenshots where they fit and leave
  TODO(v4 screenshot) markers elsewhere.
- Update the version section of each manual index to v4.0.4.
- Remove the 40 v3 screenshots that are no longer referenced.
2026-10-07 20:42:08 +08:00
Jason a40adef3f7 fix(usage): import Grok Build session usage after 60s instead of 10min
The settle window that delays Grok Build session imports reused the
±10-minute takeover guard window, so a finished turn in Direct mode took
10-11 minutes to show up in usage stats. The settle window only needs to
cover the few seconds between turn_completed being written and the proxy
rows for that turn landing in the database, so cut it to 60 seconds and
keep the guard window unchanged.

A compile-time assertion keeps the settle window below the guard window,
and two tests cover a 90-second-old turn importing and a proxy row that
lands a few seconds after the event still blocking the import.
2026-10-07 20:16:35 +08:00
Jason a7f66764e3 chore(github): list all ten apps in issue templates
Add Claude Desktop, Grok Build, Hermes, Pi and MiniMax Code to the app
dropdowns, bump the version examples to 4.0.4, and point to
Settings → About for the version number.
2026-10-07 20:02:36 +08:00
Jason 5dd824c730 docs(readme): update all four READMEs for v4.0
- Replace the v3.8 screenshots with six v4.0 screenshots (main, apps,
  aggregation, Codex aggregated models, session reader, usage)
- Rewrite Quick Start around the sidebar and the Direct / Routing /
  Aggregation tabs, add the Apps page and Accounts, and note that the
  project switcher is now hidden by default
- Add an Aggregation column and section; tray switching now covers
  Claude Desktop and Pi now supports MCP
- Replace v3 settings paths in the FAQ with the v4 locations and add an
  entry on restarting Codex after the aggregated model list changes
- Point the release notes link at v4.0.4
2026-10-07 20:02:36 +08:00
Jason 01ee685da8 docs(release): lead with usage stats in the v4.0.4 notes 2026-10-07 19:09:33 +08:00
Jason a29a4f3868 docs(release): add v4.0.4 release notes v4.0.4 2026-10-07 18:34:16 +08:00
Jason c2282a1073 chore(release): v4.0.4 2026-10-07 18:34:16 +08:00
Jason 5b10d1996c fix(usage): keep the speed column visible in a narrow window
At the minimum window width (900) with the sidebar expanded, the request
log table area is only 644px wide, but the table had min-w-[700px]. The
rightmost speed column was pushed into the table's horizontal scroll,
whose scrollbar sits below the last row and is usually off-screen, so
users saw the column as missing.

Lower the minimum to 620px, matching the provider, model and pricing
tables. The provider and model columns already truncate (max-w-0), so
they absorb the squeeze.
2026-10-07 12:37:37 +08:00
Jason e0b36500dc feat(profiles): hide the project switcher by default
The project switcher showed on the providers page header and in the tray
for every new install, even though most users never create a project.
Flip the default so it stays out of the way until turned on in Settings.

- Use plain #[serde(default)] for show_profile_switcher and drop the
  default_show_profile_switcher() helper; AppSettings::default() now
  sets it to false
- Change the frontend fallbacks in App.tsx and GeneralSection from
  ?? true to ?? false so the header does not flash the switcher before
  settings load

Existing users keep their current behavior: the field has been
persisted to settings.json since v3.17.0, so anyone who has saved
settings already has an explicit true.
2026-10-07 12:31:44 +08:00
Jason e09fdf046c feat(settings): give the About card's star prompt its own dismissible strip
The star prompt sat at the end of the link row with ms-auto, so it
wrapped onto a line of its own and read like a stray underlined caption.

- Move it into a tinted strip at the bottom of the card with a slowly
  spinning star (stops under prefers-reduced-motion) and a "Star on
  GitHub" button that opens the repo
- Drop the separate GitHub button while the strip is shown, since the
  star button goes to the same place
- Add a close button; dismissal is remembered per device in
  localStorage, and the plain GitHub button returns to the link row
- Add settings.starOnGithub to all four locales
2026-10-07 09:16:14 +08:00
Jason f61dc5f520 fix(macos): relaunch via LaunchServices so the window comes to the front after restart
tauri::process::restart spawns the binary directly. Since macOS 14 app
activation is cooperative, so the new process's activation request is
denied and its window stays behind other apps after an in-app update or
a config-dir restart.

restart_process now launches the bundle with `open -n` on macOS, letting
the still-frontmost old instance hand activation to the new one, and
falls back to tauri::process::restart if that fails. restart_app uses
restart_process instead of app.restart() so both restart paths behave
the same.
2026-10-06 23:52:59 +08:00
Jason d35726e286 test(hermes): batch the scan-limit fixture inserts in one transaction
first_user_messages_is_scoped_to_listed_sessions inserts 1002 rows, each
in its own autocommit. On the Windows runner every commit flushes to disk,
so the test took 150-180s and intermittently hit nextest's 180s timeout
(2.5s on Linux). Wrap the fixture inserts in a single transaction.
2026-10-06 22:14:45 +08:00
Jason 8596a233b2 docs(release): add v4.0.3 release notes v4.0.3 2026-10-06 21:20:09 +08:00
Jason 014a33a42b chore(release): v4.0.3 2026-10-06 21:20:09 +08:00
Jason f3e3a95560 docs(manual): add the auto mode server-check toggle to the Claude quick toggles table
The toggle shipped without a manual row. Describe what it changes, the
per-session notice it avoids on gateways, the new-provider default and
that official endpoints should leave it unchecked; the per-provider note
now covers three options instead of two.
2026-10-06 21:13:04 +08:00
Jason 65e79de845 feat(claude): explain each quick toggle with a help tip
The quick toggles above the Claude config editor had no explanation,
except a native title tooltip on the auto mode one. Put the standard "?"
help tip after each label: one sentence on what the toggle does, why
you would want it, and whether it is global or follows the provider.

Render the toggles from one list so every entry gets the same
checkbox + help layout, with copy under claudeConfig.<key> and
claudeConfig.<key>Help. The help button sits outside the <label>, so
opening the tip never flips the checkbox.
2026-10-06 21:13:04 +08:00
Jason 997a34fe3a refactor(claude): drop the max effort quick toggle
CLAUDE_CODE_EFFORT_LEVEL=max pins every session to the most expensive
effort and turns /effort into a no-op ("Not applied: ... overrides
effort this session"), while Claude Code deliberately keeps max
session-only (effortLevel in settings.json does not accept it). Users
who want max can still pick it per session with /effort max, or set the
variable by hand.

Remove the checkbox, its i18n keys, tests and the manual rows. Configs
that already carry the variable keep it untouched.
2026-10-06 21:13:04 +08:00
Jason cac218f3e2 refactor(claude): drop the Teammates quick toggle
Claude Code now gives every session a single implicit team: named
subagents, SendMessage and ListAgents are available without
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS (on 2.1.287 the tool list is
identical with and without it). The variable only gates tmux/iTerm2
split-pane teammates and the structured shutdown/plan-approval
messages, which no longer justifies a slot among the quick toggles.

Remove the checkbox, its i18n keys and the manual rows. Configs that
already carry the variable keep it untouched.
2026-10-06 21:13:04 +08:00
Jason 146f3196fa feat(claude): add auto mode server-check toggle and default it off for gateways
Add a "Disable auto mode server check" quick toggle to the Claude
provider editor that writes CLAUDE_CODE_AUTO_MODE_SERVER=0, with a hint
explaining that third-party gateways cannot serve the check and that
official endpoints should leave it unchecked.

New Claude providers now get the key by default unless the preset is
official or a cloud provider, or the preset already sets it. The default
form (no live base yet) also goes through the overlay so the custom
provider starts with the same value.
2026-10-06 21:13:04 +08:00
Jason 3144c820f1 feat(backup): show all backup locations and their sizes
Backup & Restore only listed database snapshots, while other backups kept
growing unseen under ~/.cc-switch: Codex session history migration copies
can reach several GB, plus skill uninstall backups, config first-write
backups, Hermes/OpenClaw config backups and files left by older versions.

A collapsible "Other Backups" section below the database list now shows
each location with its path, size and item count, and lets the user reveal
it in the file manager or delete a whole category after a confirmation that
explains what is lost (e.g. deleting the Codex unify migration backups
removes the "restore backup" option when turning that switch off).
Database snapshots are only summarized there and stay managed per file in
the list above.

The frontend only passes category ids; paths are computed by the backend
from each writer's own location, and deletes never follow symlinks. Codex
migration backups are deleted under the migration lock and skill backups
under the skills state lock, so a running migration or uninstall cannot
lose its directory mid-write.
2026-10-06 21:03:50 +08:00
Jason 58a9e8e2af fix(presets): drop the expired OpenCode Go referral code
OpenCode ended its referral program on 2026-09-28. Since then any /go page
opened with a ?ref= parameter shows a warning that referral links no longer
earn credit, so the "Get API Key" link on the five OpenCode Go presets
greeted users with that banner. Point them at the plain /go page instead.
2026-10-06 21:03:50 +08:00
Jason d68f008fe2 docs(contributing): accept large established aggregators as presets
Large, well-established aggregator platforms such as OpenRouter and
SiliconFlow can still get a regular built-in preset; the sponsors-only rule
applies to the remaining relay and aggregator services.
2026-10-06 21:03:50 +08:00
Jason 8569ddd75f feat(presets): add OpenCode Zen for Claude Code and Codex
OpenCode Zen is the pay-as-you-go side of the same workspace key that
OpenCode Go uses, so both now sit in one "OpenCode" family row (Go as the
coding subscription, Zen as pay-as-you-go).

Both presets connect directly without local routing: Claude Code talks to
Zen's native /v1/messages with ANTHROPIC_API_KEY (the endpoint only reads
x-api-key), and Codex talks to /v1/responses. Codex defaults to gpt-6-sol
because Zen currently returns 403 "Model access is disabled" for
gpt-5.6-sol. Free Zen models are rejected outside OpenCode, so no preset
defaults to them. OpenCode and Pi already ship Zen as a built-in provider
and get no preset.

Closes #6016
2026-10-06 21:03:50 +08:00
Jason 3c3b94939a docs(contributing): document which services get a built-in provider preset
Built-in presets are limited to model vendors and cloud platforms that serve
models under their own brand. Relay and aggregator services that resell other
vendors' models are included only as project sponsors; everything else keeps
working through Custom Provider.
2026-10-06 21:03:50 +08:00
minc_nice_100 eef7efdcef fix(config): let the test home override win over the legacy HOME fallback (#7812)
On Windows, get_app_config_dir() falls back to HOME/.cc-switch when the
default location has no cc-switch.db (v3.10.3 compatibility). An isolated
test home never contains a db, so with HOME pointing at the real user
directory (e.g. Git Bash) tests were redirected to the developer's real
database and wrote fixtures into it.

Short-circuit the fallback whenever CC_SWITCH_TEST_HOME is set, and read the
override via var_os so a non-Unicode value no longer silently falls back to
the real home directory. Adds a Windows-only regression test that seeds a
legacy db under HOME and asserts the test home still wins.
2026-10-06 21:00:36 +08:00
Allen Xu 04638fd4bc fix(ui): stop WebKit layout jitter on the usage page (#7901)
- Reserve the scrollbar gutter with overflow-y: scroll instead of scrollbar-gutter: stable, which WKWebView ignores for custom ::-webkit-scrollbar styles. Switching usage tabs no longer changes the content width and re-picks the chart's x-axis ticks.
- Slide SegmentThumb with left/top instead of transform, so WebKit no longer promotes the buttons above it to compositing layers and the icons stop jittering by half a pixel.
2026-10-06 20:54:13 +08:00
Harly edff2d7648 fix(proxy): handle mixed LF and CRLF SSE delimiters (#7853) 2026-10-06 20:40:07 +08:00
Allen Xu a776a3b184 feat(skills): add a select-all checkbox to the installed list header (#7887)
The header row already reserved space for a checkbox column but had none,
so selecting every Skill meant ticking each row by hand.

- The box acts on the rows the current search and filters show. It is
  checked when all of them are selected, indeterminate when some are, and
  clicking it while unchecked or indeterminate selects the rest.
- Selections outside the current filter are left alone.
2026-10-06 20:38:26 +08:00
小七 34759f69b0 fix(usage): move usage-stat writes off tokio workers with spawn_blocking (#7822)
Root cause: UsageLogger writes go through Database's single
std::sync::Mutex<Connection>, and every proxy usage-log call site ran
that blocking work directly on a tokio worker thread:

- response_processor.rs log_usage_internal (spawned via tokio::spawn)
- handlers.rs log_usage (called from spawned tasks and async handlers)
- handlers.rs log_forward_error (called inline from six async handlers)

On a slow disk the worker holds the blocking mutex across real IO,
stalling the runtime and queueing concurrent requests on the same
mutex.

Fix: wrap the DB-touching part of all three call paths in
tokio::task::spawn_blocking, matching the existing house pattern
(commands/*, tray.rs). The pricing-model-source read goes through the
same blocking mutex, so it moves into the same closure; its DAO call
is pseudo-async (no real suspension points), so block_on on the
blocking thread cannot stall the runtime. Callers still await the
result, keeping failure handling (warn) and write ordering unchanged.

Deliberately not addressed here: buffering/retrying records on write
failure. Issue #7818 explicitly tags the no-loss question as a
needs-design product decision, so records are still dropped with a
warning on write failure, unchanged from before.

Fixes #7818
2026-10-06 20:37:57 +08:00
Chris-Xie369 243cd9a93b fix(proxy): satisfy the OpenCode Go gateway's client identity requirements (#7773)
The OpenCode Go gateway rejects requests that carry no per-conversation
session id with 400 MissingSessionID. Claude Code and Codex send session
headers the gateway recognises, but requests that reach it through the
local proxy without one - Claude Desktop's model availability probe and
its own chats - always failed.

For upstreams on opencode.ai, the proxy now sends x-opencode-session when
the client did not, choosing the most stable identity available: a native
client session header, the client-provided session id, a fingerprint of
the conversation (system prompt plus first user message, with
cache_control stripped so it stays stable across turns), then the
generated id. A request that carries no User-Agent at all gets
cc-switch/<version>; a client's own UA and a configured custom UA are
never replaced. User header overrides still take precedence.

Fixes #7289
Fixes #7409
2026-10-06 19:08:16 +08:00
Allen Xu beff557e3c feat(logging): log provider switches and routing / aggregation mode changes (#7882)
* feat(logging): log provider switches and routing / aggregation mode changes

Switching providers and entering or leaving the routing / aggregation
modes left nothing in cc-switch.log, so "I clicked switch and nothing
happened" reports could not be told apart from a rule refusal, a user
cancel or a pending roll-forward.

- [SWITCH]: every ProviderService::switch logs where it went (direct
  from -> to, or proxy route from -> to) and how it ended: done, done
  with warnings, refused by the official-provider rule (INFO), or failed
  (ERROR).
- [MODE]: enter / attach, exit / detach, route changes and the direct-mode
  route memory log the mode transition (direct / routing / aggregation),
  the route or direct provider, and whether the client config was
  rewritten; failures log at ERROR.
- Frontend: the mode dialogs log when they open and what the user picked
  (cancel, switch directly anyway, start routing, confirm with a pick),
  and the frontend-only switch gates log too.

Fixes #7881

* fix(logging): drop quoted TOML source lines from switch / mode failure logs

TOML parse diagnostics quote the offending config line, which can be the
one holding a credential. Strip the quoted source lines before the new
backend failure logs write them to cc-switch.log; line/column and the
reason are kept.
2026-10-06 17:56:51 +08:00
Jason c615c3eeba feat(usage): show success rate and speed in model stats
The model stats tab lacked the success rate and speed columns the provider
tab has, and carried an extra average-cost column, so the two tabs read
inconsistently.

Compute success count and the exact / estimated speed totals per model in
get_model_stats, mirroring get_provider_stats (rollup rows count toward the
success rate but not speed, as they have no per-request timing). Extract the
success-rate and speed header/cells into shared statsColumns so both tables
render them identically, rename the cost header to "Cost", and move the
average cost per request into the cost cell's hover title.
2026-10-06 16:51:00 +08:00
Jason 6f4d365b73 fix(usage): use a short session-log label where the app is already shown
The request log table truncated "Claude Code · Session logs" in its narrow
provider column, and the request detail repeated the app name already shown
next to it. Show just "Session logs" in those two places; the provider
filter and provider stats table keep the full name since they have no app
column to tell the session-log rows of different apps apart. The hover
title still carries the full name and the explanation.
2026-10-06 16:51:00 +08:00
Jason 1400382219 fix(proxy): respect thinking-off and per-model effort floors when mapping Claude effort
When Claude Code requests are converted to OpenAI Chat / Responses, the
effort was forwarded verbatim even with thinking turned off. Claude Code
keeps sending `output_config.effort: "high"` when thinking is off, and
Workflow subagents send `thinking: disabled` together with an effort, so
GPT and Grok upstreams still reasoned at full strength.

- Clamp the effort to `low` when thinking is absent or disabled. `none`
  and `minimal` are not accepted by every whitelisted model.
- Clamp to the tiers the target model accepts: gpt-5-pro only takes
  `high`, and gpt-5.2/5.4/5.5-pro take medium/high/xhigh, so `low` is
  raised to `medium`. This also covers an explicit `/effort low` or a
  small thinking budget sent to a pro model, which used to return 400.
- The 5.x Claude models (Fable, Mythos, Opus, Sonnet) keep adaptive
  thinking on when `thinking` is omitted, and Claude Code omits it for
  Fable and Opus 5.5 when thinking is "off" because they cannot turn it
  off. That default is lost once the model is mapped to another vendor,
  so the forwarder now makes `thinking: adaptive` explicit from the
  client's model before the Chat / Responses transform. The Messages
  passthrough is unchanged.
- Add Opus 5 / 5.5 to `adaptive_thinking_is_default`, matching the
  per-model table in the Claude thinking docs.
2026-10-06 16:51:00 +08:00
Jason dd07b8f4b5 fix(usage): show localized names for session-log usage providers
Usage imported from client session logs (routing off) was labelled with
hardcoded English placeholders like "Claude (Session)", which showed up
untranslated in every locale and read ambiguously next to Claude Desktop.

Display them as "<full app name> · Session logs" in all four locales,
matching the "Session logs" wording already used elsewhere on the usage
page, with a hover hint explaining why the provider can't be told apart.
The backend placeholder names stay unchanged because the provider filter
sends them back for exact matching; only the rendered label is mapped.
2026-10-06 16:51:00 +08:00