ebdda09c29
`/model` with no argument now opens a two-pane modal: model on the left (deepseek-v4-pro flagship vs deepseek-v4-flash fast-and-cheap, with the current id appearing as a "current (custom)" row when it isn't one of the listed defaults), and thinking effort on the right (Off, High, Max). Tab/←/→ swaps panes, ↑/↓ moves within the focused pane, Enter applies both, Esc cancels. Effort exposes only the three rows DeepSeek behaviorally distinguishes per the Thinking Mode docs — `low`/`medium` are mapped server-side to `high`, and `xhigh` to `max`, so listing them as separate choices would mislead. The legacy variants stay valid in `~/.deepseek/settings.toml` for back-compat (the existing `cycle_next` already only visits Off→High→Max), the picker just doesn't surface them. Apply path: * mutates app.model and app.reasoning_effort * resets last_*_tokens / cache / replay-token gauges so the next-turn footer numbers reflect the new model rather than stale ones * persists `default_model` and `reasoning_effort` to settings via the existing Settings::set/save flow so the choice survives restart * forwards Op::SetModel + Op::SetCompaction to the engine so the running session picks up the new compaction budget * surfaces a one-line summary describing what changed * if persistence fails, the in-memory change still applies and a "(not persisted: ...)" suffix is appended to the status line `/model <id>` keeps working unchanged for power users; only the no-argument branch was redirected to the new modal. Files: * tui/model_picker.rs — new ModelPickerView struct + ModalView impl, plus eight unit tests (initial state, low/medium normalisation, custom model preservation, arrow navigation, focus toggle, Enter emits ModelPickerApplied with the right values, Esc closes silently, and a guard that the picker exposes exactly off/high/max). * tui/views/mod.rs — adds ModalKind::ModelPicker and ViewEvent::ModelPickerApplied carrying both new and previous model+effort so the handler can describe the diff. * tui/app.rs — adds AppAction::OpenModelPicker. * commands/core.rs — `/model` no-arg branch now returns AppAction::OpenModelPicker; `/model <id>` shortcut is unchanged. * tui/ui.rs — pushes ModelPickerView on the action and adds apply_model_picker_choice() that handles persistence + engine sync when ViewEvent::ModelPickerApplied fires. * tui/mod.rs — registers the new submodule. Closes #39 (against v0.5.2). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>