Make advanced reasoning selection explicit in the TUI (#32746)

## Why

`Max` and `Ultra` consume usage limits faster than standard reasoning levels, so they should not be selected accidentally while navigating the normal effort scale.

## What changed

- Move `Max` and `Ultra` behind a `More reasoning…` entry with a dedicated warning and descriptions.
- Keep the reasoning shortcuts from silently increasing into advanced efforts.
- Apply `Ultra` to the active conversation without changing defaults for new threads, while preserving it across mode switches and thread resumes.
- Record applied thread settings in thread metadata, including explicit clearing of reasoning effort, so resumed threads restore their latest model settings unless the user supplied an override.

## Testing

- Add TUI coverage for the advanced picker, shortcuts, Plan mode, configuration defaults, and resumed conversations.
- Add app-server and thread-store coverage for persisting, clearing, and restoring model and reasoning settings.

GitOrigin-RevId: 6708c7c2e8d38f491bf63000ea34f83476afdfe6
This commit is contained in:
Felipe Coury
2026-07-13 09:40:51 +00:00
committed by copyberry
parent 2a4942c081
commit 769a5de257
27 changed files with 1447 additions and 92 deletions
@@ -2788,15 +2788,18 @@ impl ThreadRequestProcessor {
developer_instructions,
personality,
);
self.load_and_apply_persisted_resume_metadata(
&thread_history,
&mut request_overrides,
&mut typesafe_overrides,
)
.await;
let has_explicit_model_resume_override =
has_model_resume_override(request_overrides.as_ref(), &typesafe_overrides);
let persisted_metadata = self
.load_and_apply_persisted_resume_metadata(
&thread_history,
&mut request_overrides,
&mut typesafe_overrides,
)
.await;
// Derive a Config using the same logic as new conversation, honoring overrides if provided.
let config = match self
let mut config = match self
.config_manager
.load_for_cwd(request_overrides, typesafe_overrides, history_cwd)
.await
@@ -2808,6 +2811,13 @@ impl ThreadRequestProcessor {
return Ok(());
}
};
if !has_explicit_model_resume_override
&& persisted_metadata
.as_ref()
.is_some_and(|metadata| metadata.reasoning_effort.is_none())
{
config.model_reasoning_effort = None;
}
let response_history = thread_history.clone();