Skip to content

feat: model + effort switcher (dynamically fetched from the CLI) - #20

Merged
SergKam merged 1 commit into
mainfrom
feat/model-effort-switcher
Jun 12, 2026
Merged

feat: model + effort switcher (dynamically fetched from the CLI)#20
SergKam merged 1 commit into
mainfrom
feat/model-effort-switcher

Conversation

@SergKam

@SergKam SergKam commented Jun 12, 2026

Copy link
Copy Markdown
Owner

What

A toolbar switcher next to the agent switch for the session model and reasoning effort, plus a `Model · effort` item in the status bar right after the agent name.

![placement: toolbar button next to agent switch; status bar shows Agent · Model · Effort]

Nothing is hardcoded

The model list — values, display names, descriptions, and each model's valid effort levels — is fetched at runtime from the Claude CLI's stdio control-protocol `initialize` response (`response.response.models`). Verified against the installed CLI:

value displayName supportedEffortLevels
`default` Default (recommended) low, medium, high, xhigh, max
`claude-fable-5[1m]` Fable low, medium, high, xhigh, max
`sonnet` Sonnet low, medium, high, max (no xhigh)
`haiku` Haiku (no effort)

The effort menu rebuilds itself from the selected model's `supportedEffortLevels`; Haiku shows no effort section. Effort's fixed enum isn't enumerable via the protocol, so it's read per-model rather than listed statically.

No session reset on switch

FlyCrys already spawns a fresh `claude … --resume ` process per message. So a model/effort switch needs no reset: the chosen `--model`/`--effort` apply on the next message, conversation preserved via `--resume`. (The CLI also exposes a `set_model` control request for live processes, but we don't need it given this architecture.)

Behavior

  • Eager probe at workspace init (off-thread) populates the switcher; menu shows "Fetching models…" until it lands. Empty result (CLI missing / not signed in) leaves the placeholder — no crash.
  • Persists per workspace (like the agent profile). On load, a saved model/effort no longer offered (renamed model, ZDR-excluded, unsupported effort) self-heals to Default and the correction is persisted.
  • Switcher menu = one icon (`preferences-system-symbolic`) with a Model section + an Effort section; selected entries checked. Switching to a model that doesn't support the current effort clears it.

Scope

  • `services/cli`: `AgentSpawnConfig.effort` → `--effort`; new `ModelInfo` + `probe_models()`.
  • `models/workspace_config`: persist `model_override` + `effort` (backward-compatible deserialize).
  • `ui/agent_panel`: switcher menu (parameterized GActions for arbitrary model values like `opus[1m]`), spawn wiring (override ▷ profile model ▷ default), `set_models` setter.
  • `workspace`: status label, eager probe thread + poll, persistence callback.

Checks

fmt ✅ · clippy `-D warnings` (lib+bins) ✅ · tests ✅ (105) · `--model default` accepted by the CLI ✅

Add a toolbar switcher (next to the agent switch) for the session model and
reasoning effort, plus a 'Model · effort' status-bar item after the agent name.

The model list, display names, descriptions, and each model's valid effort
levels are fetched at runtime from the Claude CLI's stdio control-protocol
`initialize` response (response.response.models) — nothing is hardcoded. Sonnet
correctly omits xhigh; Haiku omits effort entirely. Effort's fixed enum is not
enumerable via the protocol, so it's read per-model from supportedEffortLevels.

FlyCrys spawns a fresh `claude --resume` process per message, so a switch needs
no session reset: the chosen --model/--effort apply on the next message with
history preserved. A lightweight off-thread probe at workspace init populates
the switcher; the choice persists per workspace and self-heals on load if a
saved model/effort is no longer offered.

- cli: AgentSpawnConfig.effort → --effort; ModelInfo + probe_models()
- workspace_config: persist model_override + effort (backward-compatible)
- agent_panel: switcher menu (parameterized GActions), spawn wiring, set_models
- workspace: status label, eager probe thread, persistence callback
@SergKam
SergKam merged commit 64d4723 into main Jun 12, 2026
2 checks passed
@SergKam
SergKam deleted the feat/model-effort-switcher branch June 12, 2026 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant