From e93dc98a48d597df322436ffe8d03bfd7ec63b3b Mon Sep 17 00:00:00 2001 From: joeflorencio-openai Date: Sun, 31 May 2026 11:52:18 -0700 Subject: [PATCH] Add config bundle transport types (#24617) ## Summary PR 1 of 5 in the cloud-managed config client stack. Adds the generated backend models and client transport surface for the config bundle endpoint. This bundle endpoint is the replacement backend surface for legacy cloud requirements; the final PR in the stack switches runtime consumers over to it. ## Details - This is transport-only plumbing: no runtime config behavior changes in this PR. - The bundle endpoint is the new shared backend surface for cloud-delivered config and requirements data. - Both supported path styles are wired here: `/api/codex/config/bundle` and `/wham/config/bundle`. - The response types come from generated backend models so later PRs consume the backend contract directly instead of maintaining hand-written mirror structs. ## Validation Validated through the targeted stack checks after rebasing onto current `main`: - Rust crate tests for config/hooks/cloud-config/backend-client/app-server-protocol - Filtered `codex-core` and `codex-app-server` `cloud_config_bundle` tests - Python generated-file contract test - `cargo shear --deny-warnings` - Targeted `argument-comment-lint` for config/hooks --- codex-rs/backend-client/src/client.rs | 18 +++++++++ codex-rs/backend-client/src/lib.rs | 4 ++ codex-rs/backend-client/src/types.rs | 4 ++ .../src/models/config_bundle_response.rs | 40 +++++++++++++++++++ .../src/models/delivered_config_toml.rs | 32 +++++++++++++++ .../src/models/delivered_requirements_toml.rs | 32 +++++++++++++++ .../src/models/delivered_toml_fragment.rs | 28 +++++++++++++ .../src/models/mod.rs | 12 ++++++ 8 files changed, 170 insertions(+) create mode 100644 codex-rs/codex-backend-openapi-models/src/models/config_bundle_response.rs create mode 100644 codex-rs/codex-backend-openapi-models/src/models/delivered_config_toml.rs create mode 100644 codex-rs/codex-backend-openapi-models/src/models/delivered_requirements_toml.rs create mode 100644 codex-rs/codex-backend-openapi-models/src/models/delivered_toml_fragment.rs diff --git a/codex-rs/backend-client/src/client.rs b/codex-rs/backend-client/src/client.rs index 6365d527e..46c83fdde 100644 --- a/codex-rs/backend-client/src/client.rs +++ b/codex-rs/backend-client/src/client.rs @@ -1,4 +1,5 @@ use crate::types::CodeTaskDetailsResponse; +use crate::types::ConfigBundleResponse; use crate::types::ConfigFileResponse; use crate::types::PaginatedListTaskListItem; use crate::types::RateLimitReachedKind as BackendRateLimitReachedKind; @@ -408,6 +409,23 @@ impl Client { .map_err(RequestError::from) } + /// Fetch the selected cloud-managed config bundle from codex-backend. + /// + /// `GET /api/codex/config/bundle` (Codex API style) or + /// `GET /wham/config/bundle` (ChatGPT backend-api style). + pub async fn get_config_bundle( + &self, + ) -> std::result::Result { + let url = match self.path_style { + PathStyle::CodexApi => format!("{}/api/codex/config/bundle", self.base_url), + PathStyle::ChatGptApi => format!("{}/wham/config/bundle", self.base_url), + }; + let req = self.http.get(&url).headers(self.headers()); + let (body, ct) = self.exec_request_detailed(req, "GET", &url).await?; + self.decode_json::(&url, &ct, &body) + .map_err(RequestError::from) + } + /// Create a new task (user turn) by POSTing to the appropriate backend path /// based on `path_style`. Returns the created task id. pub async fn create_task(&self, request_body: serde_json::Value) -> Result { diff --git a/codex-rs/backend-client/src/lib.rs b/codex-rs/backend-client/src/lib.rs index 300da8156..00b5bd369 100644 --- a/codex-rs/backend-client/src/lib.rs +++ b/codex-rs/backend-client/src/lib.rs @@ -6,7 +6,11 @@ pub use client::Client; pub use client::RequestError; pub use types::CodeTaskDetailsResponse; pub use types::CodeTaskDetailsResponseExt; +pub use types::ConfigBundleResponse; pub use types::ConfigFileResponse; +pub use types::DeliveredConfigToml; +pub use types::DeliveredRequirementsToml; +pub use types::DeliveredTomlFragment; pub use types::PaginatedListTaskListItem; pub use types::TaskListItem; pub use types::TurnAttemptsSiblingTurnsResponse; diff --git a/codex-rs/backend-client/src/types.rs b/codex-rs/backend-client/src/types.rs index d8d24ab9f..67304f100 100644 --- a/codex-rs/backend-client/src/types.rs +++ b/codex-rs/backend-client/src/types.rs @@ -1,5 +1,9 @@ +pub use codex_backend_openapi_models::models::ConfigBundleResponse; pub use codex_backend_openapi_models::models::ConfigFileResponse; pub use codex_backend_openapi_models::models::CreditStatusDetails; +pub use codex_backend_openapi_models::models::DeliveredConfigToml; +pub use codex_backend_openapi_models::models::DeliveredRequirementsToml; +pub use codex_backend_openapi_models::models::DeliveredTomlFragment; pub use codex_backend_openapi_models::models::PaginatedListTaskListItem; pub use codex_backend_openapi_models::models::PlanType; pub use codex_backend_openapi_models::models::RateLimitReachedKind; diff --git a/codex-rs/codex-backend-openapi-models/src/models/config_bundle_response.rs b/codex-rs/codex-backend-openapi-models/src/models/config_bundle_response.rs new file mode 100644 index 000000000..9337d57a2 --- /dev/null +++ b/codex-rs/codex-backend-openapi-models/src/models/config_bundle_response.rs @@ -0,0 +1,40 @@ +/* + * codex-backend + * + * codex-backend + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + +use crate::models; +use serde::Deserialize; +use serde::Serialize; + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct ConfigBundleResponse { + #[serde( + rename = "config_toml", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub config_toml: Option>>, + #[serde( + rename = "requirements_toml", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub requirements_toml: Option>>, +} + +impl ConfigBundleResponse { + pub fn new() -> ConfigBundleResponse { + ConfigBundleResponse { + config_toml: None, + requirements_toml: None, + } + } +} diff --git a/codex-rs/codex-backend-openapi-models/src/models/delivered_config_toml.rs b/codex-rs/codex-backend-openapi-models/src/models/delivered_config_toml.rs new file mode 100644 index 000000000..0183eced4 --- /dev/null +++ b/codex-rs/codex-backend-openapi-models/src/models/delivered_config_toml.rs @@ -0,0 +1,32 @@ +/* + * codex-backend + * + * codex-backend + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + +use crate::models; +use serde::Deserialize; +use serde::Serialize; + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct DeliveredConfigToml { + #[serde( + rename = "enterprise_managed", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub enterprise_managed: Option>>, +} + +impl DeliveredConfigToml { + pub fn new() -> DeliveredConfigToml { + DeliveredConfigToml { + enterprise_managed: None, + } + } +} diff --git a/codex-rs/codex-backend-openapi-models/src/models/delivered_requirements_toml.rs b/codex-rs/codex-backend-openapi-models/src/models/delivered_requirements_toml.rs new file mode 100644 index 000000000..953087d73 --- /dev/null +++ b/codex-rs/codex-backend-openapi-models/src/models/delivered_requirements_toml.rs @@ -0,0 +1,32 @@ +/* + * codex-backend + * + * codex-backend + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + +use crate::models; +use serde::Deserialize; +use serde::Serialize; + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct DeliveredRequirementsToml { + #[serde( + rename = "enterprise_managed", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub enterprise_managed: Option>>, +} + +impl DeliveredRequirementsToml { + pub fn new() -> DeliveredRequirementsToml { + DeliveredRequirementsToml { + enterprise_managed: None, + } + } +} diff --git a/codex-rs/codex-backend-openapi-models/src/models/delivered_toml_fragment.rs b/codex-rs/codex-backend-openapi-models/src/models/delivered_toml_fragment.rs new file mode 100644 index 000000000..4d44a0e1f --- /dev/null +++ b/codex-rs/codex-backend-openapi-models/src/models/delivered_toml_fragment.rs @@ -0,0 +1,28 @@ +/* + * codex-backend + * + * codex-backend + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + +use serde::Deserialize; +use serde::Serialize; + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct DeliveredTomlFragment { + #[serde(rename = "id")] + pub id: String, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "contents")] + pub contents: String, +} + +impl DeliveredTomlFragment { + pub fn new(id: String, name: String, contents: String) -> DeliveredTomlFragment { + DeliveredTomlFragment { id, name, contents } + } +} diff --git a/codex-rs/codex-backend-openapi-models/src/models/mod.rs b/codex-rs/codex-backend-openapi-models/src/models/mod.rs index c881822b3..f0504a9c8 100644 --- a/codex-rs/codex-backend-openapi-models/src/models/mod.rs +++ b/codex-rs/codex-backend-openapi-models/src/models/mod.rs @@ -4,9 +4,21 @@ // The process for this will change // Config +pub(crate) mod config_bundle_response; +pub use self::config_bundle_response::ConfigBundleResponse; + pub(crate) mod config_file_response; pub use self::config_file_response::ConfigFileResponse; +pub(crate) mod delivered_config_toml; +pub use self::delivered_config_toml::DeliveredConfigToml; + +pub(crate) mod delivered_requirements_toml; +pub use self::delivered_requirements_toml::DeliveredRequirementsToml; + +pub(crate) mod delivered_toml_fragment; +pub use self::delivered_toml_fragment::DeliveredTomlFragment; + // Cloud Tasks pub(crate) mod code_task_details_response; pub use self::code_task_details_response::CodeTaskDetailsResponse;