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.
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>
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
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
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#7405Fixes#2736Fixes#7499
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.
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.
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.
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>
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.
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>
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.
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.
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.
- 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
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
- 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.
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.
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
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#7289Fixes#7409
* 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.
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.
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.
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.
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.