From 4f99920b8cbb9dc694140719a0ea0f175c250a5b Mon Sep 17 00:00:00 2001 From: sayan-oai Date: Thu, 1 Oct 2026 22:13:06 +0000 Subject: [PATCH] Expose the model selected for a running turn's next step (#50128) ## What changed Add `CodexThread::current_turn_model` to return the model slug selected for the named running turn's next step, independently of settings for future turns. Return `None` when the turn ID does not match, the task is cancelled, or the turn is no longer running. ## Testing Extend the step-settings test to verify that the accessor ignores model changes for future turns, reflects active-turn model updates, and returns `None` for a mismatched ID or a completed turn. GitOrigin-RevId: 2cae7c07fa761ed4d64befaa3419a2f9bce4b161 --- codex-rs/core/src/codex_thread.rs | 11 +++++++++++ codex-rs/core/tests/suite/step_settings.rs | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/codex-rs/core/src/codex_thread.rs b/codex-rs/core/src/codex_thread.rs index c0483af508..870f7797c8 100644 --- a/codex-rs/core/src/codex_thread.rs +++ b/codex-rs/core/src/codex_thread.rs @@ -304,6 +304,17 @@ impl CodexThread { task.turn_context.extension_data.get::() } + /// Returns the model selected for the named running turn's next step, not future turns. + /// Returns `None` if that turn is no longer running. + pub async fn current_turn_model(&self, expected_turn_id: &str) -> Option { + let active = self.session.active_turn.lock().await; + let task = active.as_ref()?.task.as_ref()?; + if task.turn_context.sub_id != expected_turn_id || task.cancellation_token.is_cancelled() { + return None; + } + Some(task.turn_context.capture_current_model_info().slug.clone()) + } + pub async fn shutdown_and_wait(&self) -> CodexResult<()> { self.io.shutdown_and_wait().await } diff --git a/codex-rs/core/tests/suite/step_settings.rs b/codex-rs/core/tests/suite/step_settings.rs index c532200b1c..8308c42436 100644 --- a/codex-rs/core/tests/suite/step_settings.rs +++ b/codex-rs/core/tests/suite/step_settings.rs @@ -1948,6 +1948,7 @@ async fn sparse_updates_preserve_divergent_active_and_future_models() -> Result< .await; let test = step_settings_test().build_with_auto_env(&server).await?; let request = start_paused_turn(&test.codex).await?; + assert_eq!(test.codex.current_turn_model("other-turn").await, None); core_test_support::submit_thread_settings( &test.codex, @@ -1957,6 +1958,10 @@ async fn sparse_updates_preserve_divergent_active_and_future_models() -> Result< }, ) .await?; + assert_eq!( + test.codex.current_turn_model(&request.turn_id).await, + Some(MODEL_A.to_string()) + ); apply_turn_settings( &test.codex, &request.turn_id, @@ -1967,6 +1972,10 @@ async fn sparse_updates_preserve_divergent_active_and_future_models() -> Result< }, ) .await?; + assert_eq!( + test.codex.current_turn_model(&request.turn_id).await, + Some(MODEL_C.to_string()) + ); answer_paused_turn(&test.codex, &request.turn_id).await?; let second_request = wait_for_event_match(&test.codex, |event| match event { EventMsg::RequestUserInput(request) => Some(request.clone()), @@ -2013,6 +2022,7 @@ async fn sparse_updates_preserve_divergent_active_and_future_models() -> Result< matches!(event, EventMsg::TurnComplete(_)) }) .await; + assert_eq!(test.codex.current_turn_model(&request.turn_id).await, None); test.submit_text_turn("start the next turn").await?; let requests = response_mock.requests();