Anthropic fallbacks previously reused Antigravity defaults, leaking Gemini models into Claude-only groups. Composite aliases were also emitted with generic metadata and could be scheduled to accounts that did not own the exact mapping, while generated configs could default to a model absent from the downloaded catalog.
Keep provider defaults separated, derive alias capabilities from unique upstream targets with conservative fallback, require exact mapping ownership during scheduling, filter media targets, and choose generated config defaults from the fetched catalog.
Codex treats the downloaded model catalog as a capability contract. Slug-only entries hide supported reasoning levels, can advertise invalid image inputs, and expose automatic or media-only models in the model picker. Generate complete route-aware metadata, preserve official manifests, filter non-agent models, and compute validators from the final catalog.
Codex model discovery expects a top-level models manifest, but Composite and other non-OpenAI groups either reached the OpenAI live-manifest handler or had no Codex-specific response at all. API key users also had no supported way to fetch that manifest and reference it from config.toml.
Generate minimal manifests from each group's effective model list while preserving the official OpenAI live path and the ordinary /models response. Add the Use Key flow for authenticated catalog download and model_catalog_json configuration without writing the API key into the downloaded file.
The quota cell used the noun label "5-hour window/weekly window" and the
balance cell the balance value itself as the click target for a manual
refresh. Both read as passive captions, so users could not discover the
manual probe and reported the feature as missing ("only OpenAI has a
refresh button").
- Split data display from the refresh action: bars/balance render as
static rows (snapshot already paints on mount), with a dedicated
action button below, aligned with the OpenAI "Query" and Grok
"Probe" buttons (same icon, blue action styling).
- Label the control with a verb (cnProviders.probe: 查询 / Query) and
give the balance cell a tooltip (it previously had none).
- Keep the tier/label layout classes and data-test hooks intact.
- Extend the quota cell spec and add a balance cell spec covering
snapshot rendering, explicit action labeling and failure passthrough.
- ChannelsView platformOrder now includes the three CN provider
platforms so channel pricing can be configured for them; composite
group expansion/attachment stays limited to the five main platforms
(matches backend isConcreteRequestPlatform and composite-routes
target_platform validation)
- SyncPricingModels maps kimi->moonshot, zhipu->zhipu,
deepseek->deepseek; also fixes gemini mapping to "google" which
matched zero catalog entries (provider key is "gemini")
- Add CN platform colors to channel pricing model tag classes
Default codex_fingerprint_mode to off. v0.1.175 treated a missing key as
"session", so upgrading silently rewrote installation/session/thread/turn/
window identifiers for every existing OAuth account that had never configured
this field. The quota regressions in #5555, #5556 and #5582 line up with that
version boundary, with A/B reports that rolling back to v0.1.173 restores
quota. Convergence is now explicit opt-in (#5610).
Only accounts that never set the field change behaviour; explicit off /
device / session / full keep working exactly as configured. That required
flipping the persistence condition in all three account modals from
"!== 'session'" to "!== 'off'": the old rule deleted the key when it equalled
the default, which after the flip would have silently discarded an
administrator's explicit opt-in to session.
Also extend convergence to the passthrough path, which previously left client
identifiers untouched:
- resolve the ids once in forwardOpenAIPassthrough and rewrite
client_metadata on the raw bytes (gjson extract + sjson splice) because
passthrough is a hot path that must not fully unmarshal multi-MB bodies;
a shared core keeps the raw and map variants from drifting
- both request builders apply the staged ids at the same relative position
(after session isolation, before identity enforcement) so headers and body
share one id set and turn_id stays consistent
- stage the ids unconditionally, including nil: a failover from a converged
account to an off account must not leave the previous account's ids behind
The security audit group (Risk Control + Prompt Audit) was hidden from
the sidebar via `hideInSimpleMode`, but nothing else in the stack
restricts it in simple mode:
- `router/index.ts` simple-mode `restrictedPaths` does not cover
`/admin/risk-control` or `/admin/prompt-audit`
- the `/risk-control` and `/prompt-audit` admin route groups have no
`RunMode` gate, and neither does `internal/securityaudit/` nor
`service/content_moderation.go`
- `SettingsView.vue` renders the risk control toggle together with a
`<router-link to="/admin/risk-control">` shortcut, and the settings
page stays visible in simple mode
The feature is therefore fully usable in simple mode and already
reachable through the settings page — only the sidebar entry was
missing. Drop the flag so the menu matches actual behaviour.
The group remains gated by `risk_control_enabled` (opt-in, default
false) through `featureFlag: flagRiskControl`.
Resolves three conflicts, all of the "both branches appended to the same
block" shape. Every one is resolved as a union of both sides; nothing from
either parent is dropped.
- handler/admin/setting_handler_update.go: keep ChannelMonitorHideThroughput
(V2) alongside GrokDefaultTextModel / GrokCrossClientModelMapEnabled /
GrokDefaultBaseURLMode (#5408). UpdateSettings writes every key on each
save, so dropping either side would reset those settings to zero values.
- service/domain_constants.go: keep SettingKeyChannelMonitorHideThroughput
and the three SettingKeyGrok* constants.
- repository/migrations_runner.go: keep the 195 checksum rule (V2) and the
218/219/220 rules (#5408).