The full form serves both direct and routing, so pass the app's actual mode
in: when the app is in direct mode and the upstream format needs conversion,
warn under the format that saving the in-use card breaks requests, or that
other cards need routing first. The Claude fallback model explanation now
describes the main model in direct mode.
Also fix wording that no longer matched behavior (takeover, "direct" for
pass-through formats, route-only hints that also apply in aggregation),
show the Codex default model field in the aggregation layout when the model
list is empty, hide fields the backend ignores on managed-account cards
(Codex/xAI OAuth endpoint, format and auth field; Copilot user agent and
request overrides), and remove 12 unused codexConfig strings.
Merge the model list explanation and the default-row rule into one help tip
for both the Claude and Codex aggregation layouts, keep only the restart
reminder visible, and drop the collapsed advanced-section hints. Claude's
upstream format, auth field and endpoint explanations move into help tips in
the aggregation layout only, so the Claude direct form is unchanged. The
route-only line now says the two settings apply in routing and aggregation
modes.
The default model and the sub-agent model are picked from the model
list, but the list sat collapsed inside the advanced options below them.
Show it right after the connection fields, before the default model, and
call it "Model list" as the Aggregation layout does.
The advanced section no longer opens on its own for native Responses
providers or cards with a list: that only existed to reveal the mapping.
The default model drops its own fetch button when the list above already
has one; Grok Build has no list and keeps it.
The star column in the Aggregation model lists of Claude Code and Codex
cluttered every row. The first row has always been the default model, so
drop the stars and the "make default" action, and explain the rule with a
help tip next to the "Model list" label instead.
The Codex direct form lets the default model be any row of the mapping.
When such a card opens in the Aggregation layout, move that row to the top
for display only: saving without edits keeps the stored order and model.
The add and edit forms chose the Aggregation layout from the mode the
app was actually in, with a link to toggle between the simple and the
full form. Opening a provider from the Direct or Routing tab while
Aggregation was on still showed the simple form, and the toggle was one
more control to explain.
- SwitchModePanel reports the tab being viewed (Direct / Routing /
Aggregation), and App passes it to the add and edit dialogs as
modeView. Claude Code and Codex use the simple form only when the form
is opened from the Aggregation tab; without a tab (the tray's "add"
switches apps first) the app's actual mode decides as before.
- The "Show full form" / "Back to the Aggregation form" link and its
providerForm.stackLayout.fullForm / simpleForm keys are removed.
- The dialog header shows "<app> (Aggregation mode)" while the simple
form is in use (new provider.formSubtitleStack key in all four
locales).
Fetching the model list and picking a model is the easy way to fill a
row: the context window and reasoning levels are filled from presets and
models.dev. In the full Codex form, though, fetching only added a small
dropdown arrow beside each row's model field, and nothing visible at all
when the table was empty, so users had to add a row, find the arrow and
pick a model.
- The model mapping section now shows the same searchable picker as the
Aggregation layout once models are fetched. Picked models become rows
named after the model ID, with the context window and reasoning levels
filled. The per-row dropdown stays for swapping one row's model.
- The add buttons next to "Fetch models" in the Codex model mapping and
model list, the Claude Code Aggregation model list and the OpenCode
model list are renamed to "Add manually", marking them as the fallback
for models the fetched list does not have.
- The picker's "Add selected" button is neutral instead of solid, so
Save stays the only solid button on the provider form.
From the client's side the Stack mode does what an aggregator provider
does: one endpoint, models from several providers, each request routed
by the model it names. Calling it 聚合 lets users reuse a concept they
already know instead of learning what 叠加 stacks onto.
Labels and tabs read 聚合, sentences 聚合模式 / 聚合的模型, and verb uses
become 加入聚合. zh-TW follows; en/ja keep "Stack". Code identifiers,
storage keys and logs are unchanged. Unrelated uses of 叠加 (the
Volcengine discount copy, two code comments, a CSS comment) are kept.
Switch-style apps (Claude Code, Codex, Gemini CLI, Grok Build) get a mode
row (Direct / Routing / Stack). Tabs only change what is viewed; taking
effect goes through buttons that state the consequence, with a confirm
dialog for entering a proxy mode and a one-step, undoable return to
direct. Provider cards are drawn from a per-mode presentation model
(status, buttons, chips, queue order, disabled reasons) instead of each
card inspecting proxy state, and additive apps get Added / Available
sections.
Backend: entering a mode can pick the route target in the same step,
`get_app_mode` reports the effective mode per app, and startup attach
failures are kept for the UI to surface with a retry.
Settings gains a Local Routing section (service, listen address, apps
using routing, failover tuning) replacing the old proxy tab and toggles.
Claude Desktop gets an access bar for model mapping and service state.
Rename the Stack mode to 叠加 (zh-TW 疊加) in the Chinese UI so it reads
alongside 路由 and 映射. Tags and tabs say 叠加; sentences say 叠加模式
or 叠加的模型.
- zh / zh-TW locale strings, the form defaultValues and the matching
test assertions
- the Chinese half of user-facing backend errors in mode/controller.rs,
mode/stack.rs and codex_direct.rs; the English halves are unchanged
English and Japanese keep "Stack". Code identifiers, persisted keys
(enableStackMode, the live-state stack mode), commands and log text are
unchanged.
In Stack mode the default provider no longer hides behind the routing
aliases. Claude Code's four role aliases (startup default, background
tasks, subagent aliases) all point at the first model of the default
provider's list, as its Stack id. Haiku drops the [1M] marker like the
routing contract does, and CLAUDE_CODE_SUBAGENT_MODEL is not written so
subagents follow the model picked in /model. The default provider's
whole list is published like any other member; Codex keeps publishing
the default's catalog as the route's own rows.
Claude providers get an explicit Stack model list (meta.stackModels).
Unset means the list follows the model mapping (ANTHROPIC_MODEL first,
then the tiers); an empty list is a deliberate choice and publishes
nothing.
In Stack mode the provider form opens a simplified layout: the model
list with a star for the default, plus the fields needed to reach the
provider, with a link to the full form. Both layouts share one form
state, so the default is synced when the user acts, not derived from
the layout at save time:
- Claude: when the first model of the list changes, ANTHROPIC_MODEL
follows it; an unchanged first model leaves ANTHROPIC_MODEL alone.
- Codex: the star follows config.toml's model. Starring, renaming or
removing the default row updates model on the spot; save only fills
model from the first row when it is empty. A default outside the list
is flagged with an action to add it.