Use model catalog default for reasoning summary fallback (#12873)

## Summary
- make `Config.model_reasoning_summary` optional so unset means use
model default
- resolve the optional config value to a concrete summary when building
`TurnContext`
- add protocol support for `default_reasoning_summary` in model metadata

## Validation
- `cargo test -p codex-core --lib client::tests -- --nocapture`

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
pakrym-oai
2026-02-26 09:31:13 -08:00
committed by GitHub
parent f0a85ded18
commit ba41e84a50
24 changed files with 175 additions and 40 deletions

View File

@@ -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;
@@ -980,7 +981,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,
@@ -1014,7 +1017,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?;
@@ -1058,7 +1061,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?;
@@ -1089,6 +1092,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(()));
@@ -1441,7 +1498,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");