From 0f7877aafca6ea1b8b7bfeebca9867e28800c499 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 16 Jul 2026 13:12:11 -0600 Subject: [PATCH] feat: Add validation for reasoning_effort settings to prevent users from specifying erroneous values --- src/config/request_context.rs | 66 ++++++++++++++++++++++++++++++++++- src/repl/completer.rs | 2 ++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/config/request_context.rs b/src/config/request_context.rs index 8ee2c74..c72140f 100644 --- a/src/config/request_context.rs +++ b/src/config/request_context.rs @@ -2025,6 +2025,18 @@ impl RequestContext { } "reasoning_effort" => { let value: Option = super::parse_value(value)?; + if let Some(ref level) = value { + let levels = self.current_model().reasoning_levels(); + if levels.is_empty() { + bail!("The current model does not support reasoning effort configuration"); + } + if !levels.iter().any(|l| l == level) { + bail!( + "Invalid reasoning effort '{level}'. Supported levels for this model: {}", + levels.join(", ") + ); + } + } if !self.set_reasoning_effort_on_role_like(value.clone()) { self.update_app_config(|app| app.reasoning_effort = value); } @@ -2342,7 +2354,6 @@ impl RequestContext { "continuation_prompt", "temperature", "top_p", - "reasoning_effort", "enabled_tools", "enabled_mcp_servers", "inject_todo_instructions", @@ -2363,6 +2374,9 @@ impl RequestContext { "save", "highlight", ]; + if !self.current_model().reasoning_levels().is_empty() { + values.push("reasoning_effort"); + } values.sort_unstable(); values .into_iter() @@ -2733,6 +2747,22 @@ impl RequestContext { None }; + if let Some(ref effort) = role.reasoning_effort() { + let levels = role.model().reasoning_levels(); + if levels.is_empty() { + bail!( + "Role has reasoning_effort '{}' configured but the model does not support reasoning effort", + effort + ); + } + if !levels.iter().any(|l| l == effort) { + bail!( + "Role's reasoning_effort '{}' is not valid for the model. Supported levels: {}", + effort, + levels.join(", ") + ); + } + } self.use_role_obj(role)?; self.rebuild_tool_scope(app, mcp_servers, abort_signal) .await @@ -2788,6 +2818,23 @@ impl RequestContext { None }; + if let Some(ref effort) = session.reasoning_effort() { + let levels = session.model().reasoning_levels(); + if levels.is_empty() { + bail!( + "Session has reasoning_effort '{}' configured but the model does not support reasoning effort", + effort + ); + } + if !levels.iter().any(|l| l == effort) { + bail!( + "Session's reasoning_effort '{}' is not valid for the model. Supported levels: {}", + effort, + levels.join(", ") + ); + } + } + self.rebuild_tool_scope(app, mcp_servers, abort_signal.clone()) .await?; @@ -2842,6 +2889,23 @@ impl RequestContext { ) .await?; + if let Some(ref effort) = agent.reasoning_effort() { + let levels = agent.model().reasoning_levels(); + if levels.is_empty() { + bail!( + "Agent has reasoning_effort '{}' configured but the model does not support reasoning effort", + effort + ); + } + if !levels.iter().any(|l| l == effort) { + bail!( + "Agent's reasoning_effort '{}' is not valid for the model. Supported levels: {}", + effort, + levels.join(", ") + ); + } + } + let is_graph_agent = graph::agent_has_graph(agent_name); if is_graph_agent && session_name.is_some() { bail!( diff --git a/src/repl/completer.rs b/src/repl/completer.rs index cad23d6..880c789 100644 --- a/src/repl/completer.rs +++ b/src/repl/completer.rs @@ -31,6 +31,7 @@ impl Completer for ReplCompleter { let ctx = self.ctx.read(); let state = ctx.state(); + let model_has_reasoning = !ctx.current_model().reasoning_levels().is_empty(); let command_filter = parts .iter() @@ -44,6 +45,7 @@ impl Completer for ReplCompleter { .filter(|cmd| { cmd.is_valid(state) && (command_filter.len() == 1 || cmd.name.starts_with(&command_filter[..2])) + && (cmd.name != ".reasoning" || model_has_reasoning) }) .collect(); let commands = fuzzy_filter(commands, |v| v.name, &command_filter);