Feat: add model reroute notification (#12001)

### Summary
Builiding off
5c75aa7b89 (diff-058ae8f109a8b84b4b79bbfa45f522c2233b9d9e139696044ae374d50b6196e0),
we have created a `model/rerouted` notification that captures the event
so that consumers can render as expected. Keep the `EventMsg::Warning`
path in core so that this does not affect TUI rendering.

`model/rerouted` is meant to be generic to account for future usage
including capacity planning etc.
This commit is contained in:
Shijie Rao
2026-02-17 11:02:23 -08:00
committed by GitHub
parent a1b8e34938
commit 48018e9eac
28 changed files with 605 additions and 146 deletions

View File

@@ -1,6 +1,7 @@
use anyhow::Result;
use codex_core::protocol::AskForApproval;
use codex_core::protocol::EventMsg;
use codex_core::protocol::ModelRerouteReason;
use codex_core::protocol::Op;
use codex_core::protocol::SandboxPolicy;
use codex_protocol::config_types::ReasoningSummary;
@@ -54,6 +55,17 @@ async fn openai_model_header_mismatch_emits_warning_event_and_warning_item() ->
})
.await?;
let reroute = wait_for_event(&test.codex, |event| {
matches!(event, EventMsg::ModelReroute(_))
})
.await;
let EventMsg::ModelReroute(reroute) = reroute else {
panic!("expected model reroute event");
};
assert_eq!(reroute.from_model, REQUESTED_MODEL);
assert_eq!(reroute.to_model, SERVER_MODEL);
assert_eq!(reroute.reason, ModelRerouteReason::HighRiskCyberActivity);
let warning = wait_for_event(&test.codex, |event| matches!(event, EventMsg::Warning(_))).await;
let EventMsg::Warning(warning) = warning else {
panic!("expected warning event");
@@ -138,6 +150,17 @@ async fn response_model_field_mismatch_emits_warning_when_header_matches_request
})
.await?;
let reroute = wait_for_event(&test.codex, |event| {
matches!(event, EventMsg::ModelReroute(_))
})
.await;
let EventMsg::ModelReroute(reroute) = reroute else {
panic!("expected model reroute event");
};
assert_eq!(reroute.from_model, REQUESTED_MODEL);
assert_eq!(reroute.to_model, SERVER_MODEL);
assert_eq!(reroute.reason, ModelRerouteReason::HighRiskCyberActivity);
let warning = wait_for_event(&test.codex, |event| {
matches!(
event,
@@ -151,7 +174,8 @@ async fn response_model_field_mismatch_emits_warning_when_header_matches_request
let EventMsg::Warning(warning) = warning else {
panic!("expected warning event");
};
assert!(warning.message.contains("gpt-5.2 as a fallback"));
assert!(warning.message.contains(REQUESTED_MODEL));
assert!(warning.message.contains(SERVER_MODEL));
let _ = wait_for_event(&test.codex, |event| {
matches!(event, EventMsg::TurnComplete(_))