From e787af96240815c01ac6d89a04a0f66791dfef49 Mon Sep 17 00:00:00 2001 From: Benjamin Carlsson Date: Mon, 9 Nov 2026 07:18:42 +0000 Subject: [PATCH] Include Codex Apps configuration in cloud prewarm requests (#60389) ## What changed Set `plugins_mcp.product_sku` to `"codex"` in cloud thread prewarm requests for both default environments and selected projects. ## Testing Update request payload assertions to verify the Codex plugins configuration alongside managed environment defaults, model overrides, and deferred project readiness. GitOrigin-RevId: c4ab95aa8e3440c816c5cd136444a038f4532eb9 --- codex-rs/cloud-client/src/client_tests.rs | 26 ++++++++++++++++++----- codex-rs/cloud-client/src/prewarm.rs | 10 +++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/codex-rs/cloud-client/src/client_tests.rs b/codex-rs/cloud-client/src/client_tests.rs index 754c9479a1..8adcec2803 100644 --- a/codex-rs/cloud-client/src/client_tests.rs +++ b/codex-rs/cloud-client/src/client_tests.rs @@ -231,6 +231,9 @@ async fn activation_preserves_native_settings_and_thread_metadata() { assert!(server.requests.try_recv().is_err()); } +// Native Prewarm pluginsMcp (28) with productSku (1) set to "codex". +const PREWARM_CODEX_PLUGINS: &[u8] = b"\xe2\x01\x07\x0a\x05codex"; + #[tokio::test] async fn prewarm_defers_readiness_only_for_selected_projects() { let mut fixture = fixture_responses(vec![ @@ -246,7 +249,12 @@ async fn prewarm_defers_readiness_only_for_selected_projects() { .await, Err(Error::InvalidResponse) )); - assert_request(&mut fixture, "Prewarm", b"\x52\x04\x0a\x02\x0a\x00").await; + let expected = [ + b"\x52\x04\x0a\x02\x0a\x00".as_slice(), + PREWARM_CODEX_PLUGINS, + ] + .concat(); + assert_request(&mut fixture, "Prewarm", &expected).await; assert!(matches!( fixture @@ -274,7 +282,9 @@ async fn prewarm_defers_readiness_only_for_selected_projects() { b"git@github.com:acme/app.git", b"\x0a\x21\x2a\x1f", b"https://github.com/acme/lib.git", - b"\x12\x03App\xe8\x01\x01", + b"\x12\x03App", + PREWARM_CODEX_PLUGINS, + b"\xe8\x01\x01", ] .concat(); assert_request(&mut fixture, "Prewarm", &expected).await; @@ -326,7 +336,7 @@ async fn prewarm_uses_managed_defaults_and_preserves_resolved_settings() { .await; let expected = server.client.activate("t").await.unwrap(); assert_request(&mut server, "UpdateConfig", &[56, 1, 0x92, 1, 1, b't']).await; - for (model, model_provider, request) in [ + for (model, model_provider, mut request) in [ (None, None, vec![0x52, 4, 0x0a, 2, 0x0a, 0]), ( Some("m".to_owned()), @@ -344,7 +354,8 @@ async fn prewarm_uses_managed_defaults_and_preserves_resolved_settings() { serde_json::to_value(&expected).unwrap() ); assert_eq!(actual.thread.protobuf().as_ref(), native_thread.as_slice()); - // Exactly one default managed selection; no custom settings or Aeon mode. + // Exactly one default managed selection with Codex Apps. + request.extend_from_slice(PREWARM_CODEX_PLUGINS); assert_request(&mut server, "Prewarm", &request).await; assert!(server.requests.try_recv().is_err()); } @@ -369,7 +380,12 @@ async fn prewarm_uses_managed_defaults_and_preserves_resolved_settings() { .await, Err(Error::InvalidResponse) )); - assert_request(&mut server, "Prewarm", &[0x52, 4, 0x0a, 2, 0x0a, 0]).await; + let expected = [ + b"\x52\x04\x0a\x02\x0a\x00".as_slice(), + PREWARM_CODEX_PLUGINS, + ] + .concat(); + assert_request(&mut server, "Prewarm", &expected).await; assert!(server.requests.try_recv().is_err()); } diff --git a/codex-rs/cloud-client/src/prewarm.rs b/codex-rs/cloud-client/src/prewarm.rs index d5461514c8..c97ab6b8e5 100644 --- a/codex-rs/cloud-client/src/prewarm.rs +++ b/codex-rs/cloud-client/src/prewarm.rs @@ -72,6 +72,9 @@ impl Client { wire::PrewarmRequest { model, model_provider, + plugins_mcp: Some(wire::PluginsMcp { + product_sku: Some("codex".to_owned()), + }), deferred_environment, environments: Some(wire::EnvironmentList { values: vec![wire::EnvironmentSelection { @@ -118,10 +121,17 @@ mod wire { pub model: Option, #[prost(string, optional, tag = "16")] pub model_provider: Option, + #[prost(message, optional, tag = "28")] + pub plugins_mcp: Option, #[prost(bool, optional, tag = "29")] pub deferred_environment: Option, } #[derive(Clone, Message)] + pub(super) struct PluginsMcp { + #[prost(string, optional, tag = "1")] + pub product_sku: Option, + } + #[derive(Clone, Message)] pub(super) struct EnvironmentList { #[prost(message, repeated, tag = "1")] pub values: Vec,