10 Commits
Author SHA1 Message Date
Jason e615a6f460 refactor(forms): make provider form hints follow the app's actual mode
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.
2026-10-11 22:51:28 +08:00
Jason 84ca4f0069 refactor(stack): move aggregation layout explanations into help tips
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.
2026-10-11 22:51:28 +08:00
Jason 0dae89e25c refactor(codex): move the model list out of the advanced options
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.
2026-10-11 22:51:28 +08:00
Jason 4f08989a66 refactor(stack): explain the default model with a help tip instead of stars
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.
2026-10-11 22:51:28 +08:00
Jason fe831f0a74 feat(ui): pick the provider form layout from the tab it was opened in
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).
2026-10-05 23:21:39 +08:00
Jason 917653572e feat(ui): pick fetched models into the Codex model mapping table
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.
2026-10-05 21:24:32 +08:00
Jason 21cbc3a8b4 refactor(i18n): rename the Stack mode to 聚合 in Chinese
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.
2026-10-03 23:29:00 +08:00
Jason 4aab608f7c feat(ui): add the v7 mode layer to provider pages and routing settings
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.
2026-10-03 23:28:58 +08:00
Jason 850ba952df feat(i18n): call Stack mode 叠加 in Chinese copy
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.
2026-10-01 23:45:51 +08:00
Jason 0123011228 feat(proxy): point Claude Code aliases at the default's first Stack model
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.
2026-10-01 23:45:51 +08:00