feat(tui): expose auto route in turn metadata (#2410)

Harvested from #2406 with thanks to @axobase001.

Adds auto-selected model and reasoning effort to turn metadata while keeping user text isolated in its own content block. Includes the comment cleanup requested in review.

Partially addresses #2380.
This commit is contained in:
Hunter Bown
2026-05-31 02:29:21 -07:00
committed by GitHub
parent 42b25a2cb5
commit a5cef5b2f6
2 changed files with 76 additions and 10 deletions
+50 -10
View File
@@ -910,7 +910,13 @@ impl Engine {
self.emit_session_updated().await;
}
fn turn_metadata_block(&self) -> ContentBlock {
fn turn_metadata_block(
&self,
routed_model: &str,
auto_model: bool,
reasoning_effort: Option<&str>,
reasoning_effort_auto: bool,
) -> ContentBlock {
let today = chrono::Local::now().format("%Y-%m-%d").to_string();
let working_set_summary = self
.session
@@ -919,11 +925,17 @@ impl Engine {
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty());
let summary = if let Some(working_set_summary) = working_set_summary {
format!("Current local date: {today}\n{working_set_summary}")
} else {
format!("Current local date: {today}")
};
let mut lines = vec![format!("Current local date: {today}")];
if auto_model {
lines.push(format!("Auto model route: {routed_model}"));
}
if reasoning_effort_auto && let Some(reasoning_effort) = reasoning_effort {
lines.push(format!("Auto reasoning effort: {reasoning_effort}"));
}
if let Some(working_set_summary) = working_set_summary {
lines.push(working_set_summary);
}
let summary = lines.join("\n");
ContentBlock::Text {
text: format!("<turn_meta>\n{summary}\n</turn_meta>"),
@@ -932,10 +944,32 @@ impl Engine {
}
fn user_text_message_with_turn_metadata(&self, text: String) -> Message {
self.user_text_message_with_turn_metadata_for_route(
text,
&self.session.model,
self.session.auto_model,
self.session.reasoning_effort.as_deref(),
self.session.reasoning_effort_auto,
)
}
fn user_text_message_with_turn_metadata_for_route(
&self,
text: String,
routed_model: &str,
auto_model: bool,
reasoning_effort: Option<&str>,
reasoning_effort_auto: bool,
) -> Message {
Message {
role: "user".to_string(),
content: vec![
self.turn_metadata_block(),
self.turn_metadata_block(
routed_model,
auto_model,
reasoning_effort,
reasoning_effort_auto,
),
ContentBlock::Text {
text,
cache_control: None,
@@ -989,7 +1023,7 @@ impl Engine {
// failure is non-fatal (the helper logs at WARN).
if self.config.snapshots_enabled {
// Clone the user prompt now — `content` is moved into
// `user_text_message_with_turn_metadata` below, so we need
// `user_text_message_with_turn_metadata_for_route` below, so we need
// a copy for both pre- and post-turn snapshot labels. The
// label carries a truncated first line so `/restore`
// listings are human-readable.
@@ -1010,7 +1044,7 @@ impl Engine {
crate::retry_status::clear();
// Clone user prompt for post-turn snapshot label before `content`
// is moved into `user_text_message_with_turn_metadata` below.
// is moved into `user_text_message_with_turn_metadata_for_route` below.
let snapshot_prompt_post = content.clone();
// Check if we have the appropriate client
@@ -1041,7 +1075,13 @@ impl Engine {
let force_update_plan_first = should_force_update_plan_first(mode, &content);
// Add user message to session
let user_msg = self.user_text_message_with_turn_metadata(content);
let user_msg = self.user_text_message_with_turn_metadata_for_route(
content,
&model,
auto_model,
reasoning_effort.as_deref(),
reasoning_effort_auto,
);
self.session.add_message(user_msg);
let previous_goal_objective = self.config.goal_objective.clone();
+26
View File
@@ -1467,6 +1467,32 @@ fn turn_metadata_includes_current_local_date_without_working_set() {
assert!(text.contains(&format!("Current local date: {today}")));
}
#[test]
fn turn_metadata_includes_auto_model_route() {
let tmp = tempdir().expect("tempdir");
let config = EngineConfig {
workspace: tmp.path().to_path_buf(),
..Default::default()
};
let (engine, _handle) = Engine::new(config, &Config::default());
let user_msg = engine.user_text_message_with_turn_metadata_for_route(
"debug this regression".to_string(),
"deepseek-v4-pro",
true,
Some("max"),
true,
);
let first_block = user_msg.content.first().expect("turn metadata block");
let ContentBlock::Text { text, .. } = first_block else {
panic!("expected text metadata block");
};
assert!(text.contains("Auto model route: deepseek-v4-pro"));
assert!(text.contains("Auto reasoning effort: max"));
assert!(!text.contains("debug this regression"));
}
#[test]
fn user_text_message_keeps_current_turn_input_after_turn_metadata() {
let tmp = tempdir().expect("tempdir");