Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions codex-rs/app-server/tests/common/models_cache.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use chrono::DateTime;
use chrono::Utc;
use codex_core::test_support::all_model_presets;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::openai_models::ConfigShellToolType;
use codex_protocol::openai_models::ModelInfo;
use codex_protocol::openai_models::ModelPreset;
Expand Down Expand Up @@ -30,6 +31,7 @@ fn preset_to_info(preset: &ModelPreset, priority: i32) -> ModelInfo {
base_instructions: "base instructions".to_string(),
model_messages: None,
supports_reasoning_summaries: false,
default_reasoning_summary: ReasoningSummary::Auto,
support_verbosity: false,
default_verbosity: None,
apply_patch_tool_type: None,
Expand Down
2 changes: 2 additions & 0 deletions codex-rs/codex-api/tests/models_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use codex_api::ModelsClient;
use codex_api::provider::Provider;
use codex_api::provider::RetryConfig;
use codex_client::ReqwestTransport;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::openai_models::ConfigShellToolType;
use codex_protocol::openai_models::ModelInfo;
use codex_protocol::openai_models::ModelVisibility;
Expand Down Expand Up @@ -78,6 +79,7 @@ async fn models_client_hits_models_endpoint() {
base_instructions: "base instructions".to_string(),
model_messages: None,
supports_reasoning_summaries: false,
default_reasoning_summary: ReasoningSummary::Auto,
support_verbosity: false,
default_verbosity: None,
apply_patch_tool_type: None,
Expand Down
16 changes: 11 additions & 5 deletions codex-rs/core/src/codex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,7 @@ pub(crate) struct SessionConfiguration {
provider: ModelProviderInfo,

collaboration_mode: CollaborationMode,
model_reasoning_summary: ReasoningSummaryConfig,
model_reasoning_summary: Option<ReasoningSummaryConfig>,

/// Developer instructions that supplement the base instructions.
developer_instructions: Option<String>,
Expand Down Expand Up @@ -824,7 +824,7 @@ impl SessionConfiguration {
next_configuration.collaboration_mode = collaboration_mode;
}
if let Some(summary) = updates.reasoning_summary {
next_configuration.model_reasoning_summary = summary;
next_configuration.model_reasoning_summary = Some(summary);
}
if let Some(personality) = updates.personality {
next_configuration.personality = Some(personality);
Expand Down Expand Up @@ -985,7 +985,9 @@ impl Session {
skills_outcome: Arc<SkillLoadOutcome>,
) -> TurnContext {
let reasoning_effort = session_configuration.collaboration_mode.reasoning_effort();
let reasoning_summary = session_configuration.model_reasoning_summary;
let reasoning_summary = session_configuration
.model_reasoning_summary
.unwrap_or(model_info.default_reasoning_summary);
let otel_manager = otel_manager.clone().with_model(
session_configuration.collaboration_mode.model(),
model_info.slug.as_str(),
Expand Down Expand Up @@ -1262,7 +1264,9 @@ impl Session {
otel_manager.conversation_starts(
config.model_provider.name.as_str(),
session_configuration.collaboration_mode.reasoning_effort(),
config.model_reasoning_summary,
config
.model_reasoning_summary
.unwrap_or(ReasoningSummaryConfig::Auto),
config.model_context_window,
config.model_auto_compact_token_limit,
config.permissions.approval_policy.value(),
Expand Down Expand Up @@ -4615,7 +4619,9 @@ async fn spawn_review_thread(
let provider_for_context = provider.clone();
let otel_manager_for_context = otel_manager.clone();
let reasoning_effort = per_turn_config.model_reasoning_effort;
let reasoning_summary = per_turn_config.model_reasoning_summary;
let reasoning_summary = per_turn_config
.model_reasoning_summary
.unwrap_or(model_info.default_reasoning_summary);
let session_source = parent_turn_context.session_source.clone();

let per_turn_config = Arc::new(per_turn_config);
Expand Down
17 changes: 8 additions & 9 deletions codex-rs/core/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,9 @@ pub struct Config {
/// global default").
pub plan_mode_reasoning_effort: Option<ReasoningEffort>,

/// If not "none", the value to use for `reasoning.summary` when making a
/// request using the Responses API.
pub model_reasoning_summary: ReasoningSummary,
/// Optional value to use for `reasoning.summary` when making a request
/// using the Responses API. When unset, the model catalog default is used.
pub model_reasoning_summary: Option<ReasoningSummary>,

/// Optional override to force-enable reasoning summaries for the configured model.
pub model_supports_reasoning_summaries: Option<bool>,
Expand Down Expand Up @@ -2141,8 +2141,7 @@ impl Config {
.or(cfg.plan_mode_reasoning_effort),
model_reasoning_summary: config_profile
.model_reasoning_summary
.or(cfg.model_reasoning_summary)
.unwrap_or_default(),
.or(cfg.model_reasoning_summary),
model_supports_reasoning_summaries: cfg.model_supports_reasoning_summaries,
model_catalog,
model_verbosity: config_profile.model_verbosity.or(cfg.model_verbosity),
Expand Down Expand Up @@ -4761,7 +4760,7 @@ model_verbosity = "high"
show_raw_agent_reasoning: false,
model_reasoning_effort: Some(ReasoningEffort::High),
plan_mode_reasoning_effort: None,
model_reasoning_summary: ReasoningSummary::Detailed,
model_reasoning_summary: Some(ReasoningSummary::Detailed),
model_supports_reasoning_summaries: None,
model_catalog: None,
model_verbosity: None,
Expand Down Expand Up @@ -4887,7 +4886,7 @@ model_verbosity = "high"
show_raw_agent_reasoning: false,
model_reasoning_effort: None,
plan_mode_reasoning_effort: None,
model_reasoning_summary: ReasoningSummary::default(),
model_reasoning_summary: None,
model_supports_reasoning_summaries: None,
model_catalog: None,
model_verbosity: None,
Expand Down Expand Up @@ -5011,7 +5010,7 @@ model_verbosity = "high"
show_raw_agent_reasoning: false,
model_reasoning_effort: None,
plan_mode_reasoning_effort: None,
model_reasoning_summary: ReasoningSummary::default(),
model_reasoning_summary: None,
model_supports_reasoning_summaries: None,
model_catalog: None,
model_verbosity: None,
Expand Down Expand Up @@ -5121,7 +5120,7 @@ model_verbosity = "high"
show_raw_agent_reasoning: false,
model_reasoning_effort: Some(ReasoningEffort::High),
plan_mode_reasoning_effort: None,
model_reasoning_summary: ReasoningSummary::Detailed,
model_reasoning_summary: Some(ReasoningSummary::Detailed),
model_supports_reasoning_summaries: None,
model_catalog: None,
model_verbosity: Some(Verbosity::High),
Expand Down
2 changes: 2 additions & 0 deletions codex-rs/core/src/models_manager/model_info.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::openai_models::ConfigShellToolType;
use codex_protocol::openai_models::ModelInfo;
use codex_protocol::openai_models::ModelInstructionsVariables;
Expand Down Expand Up @@ -72,6 +73,7 @@ pub(crate) fn model_info_from_slug(slug: &str) -> ModelInfo {
base_instructions: BASE_INSTRUCTIONS.to_string(),
model_messages: local_personality_messages_for_slug(slug),
supports_reasoning_summaries: false,
default_reasoning_summary: ReasoningSummary::Auto,
support_verbosity: false,
default_verbosity: None,
apply_patch_tool_type: None,
Expand Down
6 changes: 3 additions & 3 deletions codex-rs/core/src/tools/handlers/multi_agents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ fn build_agent_shared_config(turn: &TurnContext) -> Result<Config, FunctionCallE
config.model = Some(turn.model_info.slug.clone());
config.model_provider = turn.provider.clone();
config.model_reasoning_effort = turn.reasoning_effort;
config.model_reasoning_summary = turn.reasoning_summary;
config.model_reasoning_summary = Some(turn.reasoning_summary);
config.developer_instructions = turn.developer_instructions.clone();
config.compact_prompt = turn.compact_prompt.clone();
apply_spawn_agent_runtime_overrides(&mut config, turn)?;
Expand Down Expand Up @@ -2046,7 +2046,7 @@ mod tests {
expected.model = Some(turn.model_info.slug.clone());
expected.model_provider = turn.provider.clone();
expected.model_reasoning_effort = turn.reasoning_effort;
expected.model_reasoning_summary = turn.reasoning_summary;
expected.model_reasoning_summary = Some(turn.reasoning_summary);
expected.developer_instructions = turn.developer_instructions.clone();
expected.compact_prompt = turn.compact_prompt.clone();
expected.permissions.shell_environment_policy = turn.shell_environment_policy.clone();
Expand Down Expand Up @@ -2098,7 +2098,7 @@ mod tests {
expected.model = Some(turn.model_info.slug.clone());
expected.model_provider = turn.provider.clone();
expected.model_reasoning_effort = turn.reasoning_effort;
expected.model_reasoning_summary = turn.reasoning_summary;
expected.model_reasoning_summary = Some(turn.reasoning_summary);
expected.developer_instructions = turn.developer_instructions.clone();
expected.compact_prompt = turn.compact_prompt.clone();
expected.permissions.shell_environment_policy = turn.shell_environment_policy.clone();
Expand Down
29 changes: 25 additions & 4 deletions codex-rs/core/tests/responses_headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,14 @@ async fn responses_stream_includes_subagent_header_on_review() {
}];

let mut stream = client_session
.stream(&prompt, &model_info, &otel_manager, effort, summary, None)
.stream(
&prompt,
&model_info,
&otel_manager,
effort,
summary.unwrap_or(model_info.default_reasoning_summary),
None,
)
.await
.expect("stream failed");
while let Some(event) = stream.next().await {
Expand Down Expand Up @@ -216,7 +223,14 @@ async fn responses_stream_includes_subagent_header_on_other() {
}];

let mut stream = client_session
.stream(&prompt, &model_info, &otel_manager, effort, summary, None)
.stream(
&prompt,
&model_info,
&otel_manager,
effort,
summary.unwrap_or(model_info.default_reasoning_summary),
None,
)
.await
.expect("stream failed");
while let Some(event) = stream.next().await {
Expand Down Expand Up @@ -267,7 +281,7 @@ async fn responses_respects_model_info_overrides_from_config() {
config.model_provider_id = provider.name.clone();
config.model_provider = provider.clone();
config.model_supports_reasoning_summaries = Some(true);
config.model_reasoning_summary = ReasoningSummary::Detailed;
config.model_reasoning_summary = Some(ReasoningSummary::Detailed);
let effort = config.model_reasoning_effort;
let summary = config.model_reasoning_summary;
let model = config.model.clone().expect("model configured");
Expand Down Expand Up @@ -320,7 +334,14 @@ async fn responses_respects_model_info_overrides_from_config() {
}];

let mut stream = client_session
.stream(&prompt, &model_info, &otel_manager, effort, summary, None)
.stream(
&prompt,
&model_info,
&otel_manager,
effort,
summary.unwrap_or(model_info.default_reasoning_summary),
None,
)
.await
.expect("stream failed");
while let Some(event) = stream.next().await {
Expand Down
72 changes: 68 additions & 4 deletions codex-rs/core/tests/suite/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use codex_protocol::models::ReasoningItemContent;
use codex_protocol::models::ReasoningItemReasoningSummary;
use codex_protocol::models::ResponseItem;
use codex_protocol::models::WebSearchAction;
use codex_protocol::openai_models::ModelsResponse;
use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::Op;
Expand Down Expand Up @@ -992,7 +993,9 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
sandbox_policy: config.permissions.sandbox_policy.get().clone(),
model: session_configured.model.clone(),
effort: Some(ReasoningEffort::Low),
summary: config.model_reasoning_summary,
summary: config
.model_reasoning_summary
.unwrap_or(ReasoningSummary::Auto),
collaboration_mode: Some(collaboration_mode),
final_output_json_schema: None,
personality: None,
Expand Down Expand Up @@ -1026,7 +1029,7 @@ async fn configured_reasoning_summary_is_sent() -> anyhow::Result<()> {
.await;
let TestCodex { codex, .. } = test_codex()
.with_config(|config| {
config.model_reasoning_summary = ReasoningSummary::Concise;
config.model_reasoning_summary = Some(ReasoningSummary::Concise);
})
.build(&server)
.await?;
Expand Down Expand Up @@ -1070,7 +1073,7 @@ async fn reasoning_summary_is_omitted_when_disabled() -> anyhow::Result<()> {
.await;
let TestCodex { codex, .. } = test_codex()
.with_config(|config| {
config.model_reasoning_summary = ReasoningSummary::None;
config.model_reasoning_summary = Some(ReasoningSummary::None);
})
.build(&server)
.await?;
Expand Down Expand Up @@ -1101,6 +1104,60 @@ async fn reasoning_summary_is_omitted_when_disabled() -> anyhow::Result<()> {
Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn reasoning_summary_none_overrides_model_catalog_default() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let server = MockServer::start().await;

let resp_mock = mount_sse_once(
&server,
sse(vec![ev_response_created("resp1"), ev_completed("resp1")]),
)
.await;

let mut model_catalog: ModelsResponse =
serde_json::from_str(include_str!("../../models.json")).expect("valid models.json");
let model = model_catalog
.models
.iter_mut()
.find(|model| model.slug == "gpt-5.1")
.expect("gpt-5.1 exists in bundled models.json");
model.supports_reasoning_summaries = true;
model.default_reasoning_summary = ReasoningSummary::Detailed;

let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5.1")
.with_config(move |config| {
config.model_reasoning_summary = Some(ReasoningSummary::None);
config.model_catalog = Some(model_catalog);
})
.build(&server)
.await?;

codex
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello".into(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
})
.await
.unwrap();

wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;

let request_body = resp_mock.single_request().body_json();
pretty_assertions::assert_eq!(
request_body
.get("reasoning")
.and_then(|reasoning| reasoning.get("summary")),
None
);

Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn includes_default_verbosity_in_request() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
Expand Down Expand Up @@ -1430,7 +1487,14 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() {
});

let mut stream = client_session
.stream(&prompt, &model_info, &otel_manager, effort, summary, None)
.stream(
&prompt,
&model_info,
&otel_manager,
effort,
summary.unwrap_or(ReasoningSummary::Auto),
None,
)
.await
.expect("responses stream to start");

Expand Down
10 changes: 8 additions & 2 deletions codex-rs/core/tests/suite/collaboration_instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,10 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> {
sandbox_policy: test.config.permissions.sandbox_policy.get().clone(),
model: test.session_configured.model.clone(),
effort: None,
summary: test.config.model_reasoning_summary,
summary: test
.config
.model_reasoning_summary
.unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto),
collaboration_mode: Some(collaboration_mode),
final_output_json_schema: None,
personality: None,
Expand Down Expand Up @@ -275,7 +278,10 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu
sandbox_policy: test.config.permissions.sandbox_policy.get().clone(),
model: test.session_configured.model.clone(),
effort: None,
summary: test.config.model_reasoning_summary,
summary: test
.config
.model_reasoning_summary
.unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto),
collaboration_mode: Some(turn_mode),
final_output_json_schema: None,
personality: None,
Expand Down
2 changes: 2 additions & 0 deletions codex-rs/core/tests/suite/model_switching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ async fn model_change_from_image_to_text_strips_prior_image_content() -> Result<
base_instructions: "base instructions".to_string(),
model_messages: None,
supports_reasoning_summaries: false,
default_reasoning_summary: ReasoningSummary::Auto,
support_verbosity: false,
default_verbosity: None,
apply_patch_tool_type: None,
Expand Down Expand Up @@ -391,6 +392,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result<
base_instructions: "base instructions".to_string(),
model_messages: None,
supports_reasoning_summaries: false,
default_reasoning_summary: ReasoningSummary::Auto,
support_verbosity: false,
default_verbosity: None,
apply_patch_tool_type: None,
Expand Down
Loading
Loading