introduce variable reasoning effort

This commit is contained in:
Ahmed Ibrahim
2025-08-18 13:09:13 -07:00
parent d4385420f4
commit 1c5a7cd1ca
6 changed files with 100 additions and 7 deletions

View File

@@ -153,6 +153,7 @@ impl ModelClient {
self.effort,
self.summary,
);
trace!("reasoning: {:?}", reasoning);
// Request encrypted COT if we are not storing responses,
// otherwise reasoning items will be referenced by ID

View File

@@ -13,8 +13,6 @@ pub enum ReasoningEffort {
#[default]
Medium,
High,
/// Option to disable reasoning.
None,
}
/// A summary of the reasoning performed by the model. This can be useful for

View File

@@ -416,7 +416,7 @@ impl App<'_> {
widget.add_status_output();
}
}
SlashCommand::Effort => {
SlashCommand::ReasoningEffort => {
if self.config.model_family.supports_reasoning_summaries {
if let AppState::Chat { widget } = &mut self.app_state {
widget.open_reasoning_effort_popup();

View File

@@ -0,0 +1,93 @@
use codex_core::protocol_config_types::ReasoningEffort as ReasoningEffortConfig;
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::widgets::WidgetRef;
use super::popup_consts::MAX_POPUP_ROWS;
use super::scroll_state::ScrollState;
use super::selection_popup_common::GenericDisplayRow;
use super::selection_popup_common::render_rows;
use strum::IntoEnumIterator;
/// Payload associated with a selected item in a generic choice popup.
pub(crate) enum ChoicePayload {
ReasoningEffort(ReasoningEffortConfig),
}
pub(crate) struct ChoiceItem {
pub name: String,
pub is_current: bool,
pub description: Option<String>,
pub payload: ChoicePayload,
}
/// A simple reusable choice popup that displays a fixed list of items and
/// allows the user to select one using Up/Down/Enter.
pub(crate) struct ChoicePopup {
items: Vec<ChoiceItem>,
state: ScrollState,
}
impl ChoicePopup {
pub(crate) fn new_reasoning_effort(current: ReasoningEffortConfig) -> Self {
let items: Vec<ChoiceItem> = ReasoningEffortConfig::iter()
.map(|v| ChoiceItem {
name: v.to_string(),
is_current: v == current,
description: None,
payload: ChoicePayload::ReasoningEffort(v),
})
.collect();
let mut state = ScrollState::new();
// Default selection to the current value when present
if let Some((idx, _)) = items.iter().enumerate().find(|(_, it)| it.is_current) {
state.selected_idx = Some(idx);
}
Self { items, state }
}
pub(crate) fn move_up(&mut self) {
let len = self.items.len();
self.state.move_up_wrap(len);
self.state.ensure_visible(len, len.min(MAX_POPUP_ROWS));
}
pub(crate) fn move_down(&mut self) {
let len = self.items.len();
self.state.move_down_wrap(len);
self.state.ensure_visible(len, len.min(MAX_POPUP_ROWS));
}
pub(crate) fn selected_payload(&self) -> Option<&ChoicePayload> {
self.state
.selected_idx
.and_then(|idx| self.items.get(idx))
.map(|it| &it.payload)
}
pub(crate) fn calculate_required_height(&self) -> u16 {
self.items.len().clamp(1, MAX_POPUP_ROWS) as u16
}
}
impl WidgetRef for &ChoicePopup {
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
let rows_all: Vec<GenericDisplayRow> = if self.items.is_empty() {
Vec::new()
} else {
self.items
.iter()
.map(|item| GenericDisplayRow {
name: item.name.clone(),
match_indices: None,
is_current: item.is_current,
description: item.description.clone(),
})
.collect()
};
render_rows(area, buf, &rows_all, &self.state, MAX_POPUP_ROWS);
}
}

View File

@@ -30,7 +30,7 @@ impl CommandPopup {
pub(crate) fn filter_for_capabilities(&mut self, show_reasoning_commands: bool) {
if !show_reasoning_commands {
self.all_commands
.retain(|(_, c)| !matches!(c, SlashCommand::Effort));
.retain(|(_, c)| !matches!(c, SlashCommand::ReasoningEffort));
}
}

View File

@@ -17,9 +17,8 @@ pub enum SlashCommand {
Compact,
Diff,
Mention,
ReasoningEffort,
Status,
/// Choose model reasoning effort (only shown when supported by model family).
Effort,
Logout,
Quit,
#[cfg(debug_assertions)]
@@ -34,10 +33,12 @@ impl SlashCommand {
SlashCommand::Init => "create an AGENTS.md file with instructions for Codex",
SlashCommand::Compact => "summarize conversation to prevent hitting the context limit",
SlashCommand::Quit => "exit Codex",
SlashCommand::ReasoningEffort => {
"choose model reasoning effort (low/medium/high/minimal)"
}
SlashCommand::Diff => "show git diff (including untracked files)",
SlashCommand::Mention => "mention a file",
SlashCommand::Status => "show current session configuration and token usage",
SlashCommand::Effort => "choose model reasoning effort (low/medium/high/minimal/none)",
SlashCommand::Logout => "log out of Codex",
#[cfg(debug_assertions)]
SlashCommand::TestApproval => "test approval request",