feat: Add validation for reasoning_effort settings to prevent users from specifying erroneous values

This commit is contained in:
2026-07-16 13:12:11 -06:00
parent 5843a9ac15
commit 0f7877aafc
2 changed files with 67 additions and 1 deletions
+65 -1
View File
@@ -2025,6 +2025,18 @@ impl RequestContext {
} }
"reasoning_effort" => { "reasoning_effort" => {
let value: Option<String> = super::parse_value(value)?; let value: Option<String> = 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()) { if !self.set_reasoning_effort_on_role_like(value.clone()) {
self.update_app_config(|app| app.reasoning_effort = value); self.update_app_config(|app| app.reasoning_effort = value);
} }
@@ -2342,7 +2354,6 @@ impl RequestContext {
"continuation_prompt", "continuation_prompt",
"temperature", "temperature",
"top_p", "top_p",
"reasoning_effort",
"enabled_tools", "enabled_tools",
"enabled_mcp_servers", "enabled_mcp_servers",
"inject_todo_instructions", "inject_todo_instructions",
@@ -2363,6 +2374,9 @@ impl RequestContext {
"save", "save",
"highlight", "highlight",
]; ];
if !self.current_model().reasoning_levels().is_empty() {
values.push("reasoning_effort");
}
values.sort_unstable(); values.sort_unstable();
values values
.into_iter() .into_iter()
@@ -2733,6 +2747,22 @@ impl RequestContext {
None 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.use_role_obj(role)?;
self.rebuild_tool_scope(app, mcp_servers, abort_signal) self.rebuild_tool_scope(app, mcp_servers, abort_signal)
.await .await
@@ -2788,6 +2818,23 @@ impl RequestContext {
None 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()) self.rebuild_tool_scope(app, mcp_servers, abort_signal.clone())
.await?; .await?;
@@ -2842,6 +2889,23 @@ impl RequestContext {
) )
.await?; .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); let is_graph_agent = graph::agent_has_graph(agent_name);
if is_graph_agent && session_name.is_some() { if is_graph_agent && session_name.is_some() {
bail!( bail!(
+2
View File
@@ -31,6 +31,7 @@ impl Completer for ReplCompleter {
let ctx = self.ctx.read(); let ctx = self.ctx.read();
let state = ctx.state(); let state = ctx.state();
let model_has_reasoning = !ctx.current_model().reasoning_levels().is_empty();
let command_filter = parts let command_filter = parts
.iter() .iter()
@@ -44,6 +45,7 @@ impl Completer for ReplCompleter {
.filter(|cmd| { .filter(|cmd| {
cmd.is_valid(state) cmd.is_valid(state)
&& (command_filter.len() == 1 || cmd.name.starts_with(&command_filter[..2])) && (command_filter.len() == 1 || cmd.name.starts_with(&command_filter[..2]))
&& (cmd.name != ".reasoning" || model_has_reasoning)
}) })
.collect(); .collect();
let commands = fuzzy_filter(commands, |v| v.name, &command_filter); let commands = fuzzy_filter(commands, |v| v.name, &command_filter);