mirror of
https://github.com/openai/codex.git
synced 2026-09-15 12:08:01 +00:00
core: forward windows sandbox headers on Responses requests
This commit is contained in:
@@ -50,6 +50,7 @@ use codex_otel::OtelManager;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig;
|
||||
use codex_protocol::config_types::Verbosity as VerbosityConfig;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
@@ -87,6 +88,10 @@ pub const X_CODEX_TURN_STATE_HEADER: &str = "x-codex-turn-state";
|
||||
pub const X_CODEX_TURN_METADATA_HEADER: &str = "x-codex-turn-metadata";
|
||||
pub const X_RESPONSESAPI_INCLUDE_TIMING_METRICS_HEADER: &str =
|
||||
"x-responsesapi-include-timing-metrics";
|
||||
pub const X_OPENAI_INTERNAL_CODEX_EXPERIMENTAL_WINDOWS_SANDBOX_HEADER: &str =
|
||||
"x-openai-internal-codex-experimental-windows-sandbox";
|
||||
pub const X_OPENAI_INTERNAL_CODEX_ELEVATED_WINDOWS_SANDBOX_HEADER: &str =
|
||||
"x-openai-internal-codex-elevated-windows-sandbox";
|
||||
|
||||
/// Session-scoped state shared by all [`ModelClient`] clones.
|
||||
///
|
||||
@@ -103,6 +108,7 @@ struct ModelClientState {
|
||||
enable_request_compression: bool,
|
||||
include_timing_metrics: bool,
|
||||
beta_features_header: Option<String>,
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
disable_websockets: AtomicBool,
|
||||
}
|
||||
|
||||
@@ -171,6 +177,7 @@ impl ModelClient {
|
||||
enable_request_compression: bool,
|
||||
include_timing_metrics: bool,
|
||||
beta_features_header: Option<String>,
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
) -> Self {
|
||||
Self {
|
||||
state: Arc::new(ModelClientState {
|
||||
@@ -183,6 +190,7 @@ impl ModelClient {
|
||||
enable_request_compression,
|
||||
include_timing_metrics,
|
||||
beta_features_header,
|
||||
windows_sandbox_level,
|
||||
disable_websockets: AtomicBool::new(false),
|
||||
}),
|
||||
}
|
||||
@@ -406,6 +414,7 @@ impl ModelClientSession {
|
||||
self.client.state.beta_features_header.as_deref(),
|
||||
web_search_eligible,
|
||||
Some(&self.turn_state),
|
||||
self.client.state.windows_sandbox_level,
|
||||
turn_metadata_header.as_ref(),
|
||||
),
|
||||
compression,
|
||||
@@ -775,10 +784,12 @@ fn build_api_prompt(prompt: &Prompt, instructions: String, tools_json: Vec<Value
|
||||
/// - `x-oai-web-search-eligible`: whether this turn is allowed to use web search.
|
||||
/// - `x-codex-turn-state`: sticky routing token captured earlier in the turn.
|
||||
/// - `x-codex-turn-metadata`: optional per-turn metadata for observability.
|
||||
/// - `x-openai-internal-codex-*-windows-sandbox`: windows sandbox settings for analytics.
|
||||
fn build_responses_headers(
|
||||
beta_features_header: Option<&str>,
|
||||
web_search_eligible: bool,
|
||||
turn_state: Option<&Arc<OnceLock<String>>>,
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
turn_metadata_header: Option<&HeaderValue>,
|
||||
) -> ApiHeaderMap {
|
||||
let mut headers = ApiHeaderMap::new();
|
||||
@@ -788,6 +799,22 @@ fn build_responses_headers(
|
||||
{
|
||||
headers.insert("x-codex-beta-features", header_value);
|
||||
}
|
||||
headers.insert(
|
||||
X_OPENAI_INTERNAL_CODEX_EXPERIMENTAL_WINDOWS_SANDBOX_HEADER,
|
||||
HeaderValue::from_static(if windows_sandbox_level == WindowsSandboxLevel::Disabled {
|
||||
"false"
|
||||
} else {
|
||||
"true"
|
||||
}),
|
||||
);
|
||||
headers.insert(
|
||||
X_OPENAI_INTERNAL_CODEX_ELEVATED_WINDOWS_SANDBOX_HEADER,
|
||||
HeaderValue::from_static(if windows_sandbox_level == WindowsSandboxLevel::Elevated {
|
||||
"true"
|
||||
} else {
|
||||
"false"
|
||||
}),
|
||||
);
|
||||
headers.insert(
|
||||
WEB_SEARCH_ELIGIBLE_HEADER,
|
||||
HeaderValue::from_static(if web_search_eligible { "true" } else { "false" }),
|
||||
|
||||
@@ -1039,6 +1039,7 @@ impl Session {
|
||||
config.features.enabled(Feature::EnableRequestCompression),
|
||||
config.features.enabled(Feature::RuntimeMetrics),
|
||||
Self::build_model_client_beta_features_header(config.as_ref()),
|
||||
session_configuration.windows_sandbox_level,
|
||||
),
|
||||
};
|
||||
|
||||
@@ -5755,6 +5756,7 @@ mod tests {
|
||||
config.features.enabled(Feature::EnableRequestCompression),
|
||||
config.features.enabled(Feature::RuntimeMetrics),
|
||||
Session::build_model_client_beta_features_header(config.as_ref()),
|
||||
session_configuration.windows_sandbox_level,
|
||||
),
|
||||
};
|
||||
|
||||
@@ -5885,6 +5887,7 @@ mod tests {
|
||||
config.features.enabled(Feature::EnableRequestCompression),
|
||||
config.features.enabled(Feature::RuntimeMetrics),
|
||||
Session::build_model_client_beta_features_header(config.as_ref()),
|
||||
session_configuration.windows_sandbox_level,
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
@@ -132,6 +132,8 @@ pub mod util;
|
||||
pub use apply_patch::CODEX_APPLY_PATCH_ARG1;
|
||||
pub use client::WEB_SEARCH_ELIGIBLE_HEADER;
|
||||
pub use client::X_CODEX_TURN_METADATA_HEADER;
|
||||
pub use client::X_OPENAI_INTERNAL_CODEX_ELEVATED_WINDOWS_SANDBOX_HEADER;
|
||||
pub use client::X_OPENAI_INTERNAL_CODEX_EXPERIMENTAL_WINDOWS_SANDBOX_HEADER;
|
||||
pub use command_safety::is_dangerous_command;
|
||||
pub use command_safety::is_safe_command;
|
||||
pub use exec_policy::ExecPolicyError;
|
||||
|
||||
@@ -12,11 +12,15 @@ use codex_core::ResponseEvent;
|
||||
use codex_core::ResponseItem;
|
||||
use codex_core::WEB_SEARCH_ELIGIBLE_HEADER;
|
||||
use codex_core::WireApi;
|
||||
use codex_core::X_OPENAI_INTERNAL_CODEX_ELEVATED_WINDOWS_SANDBOX_HEADER;
|
||||
use codex_core::X_OPENAI_INTERNAL_CODEX_EXPERIMENTAL_WINDOWS_SANDBOX_HEADER;
|
||||
use codex_core::features::Feature;
|
||||
use codex_core::models_manager::manager::ModelsManager;
|
||||
use codex_otel::OtelManager;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::WebSearchMode;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use core_test_support::load_default_config_for_test;
|
||||
@@ -98,6 +102,7 @@ async fn responses_stream_includes_subagent_header_on_review() {
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
WindowsSandboxLevel::Disabled,
|
||||
);
|
||||
let mut client_session = client.new_session();
|
||||
|
||||
@@ -209,6 +214,7 @@ async fn responses_stream_includes_subagent_header_on_other() {
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
WindowsSandboxLevel::Disabled,
|
||||
);
|
||||
let mut client_session = client.new_session();
|
||||
|
||||
@@ -308,6 +314,72 @@ async fn responses_stream_includes_web_search_eligible_header_false_when_disable
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn responses_stream_includes_windows_sandbox_headers_false_by_default() {
|
||||
core_test_support::skip_if_no_network!();
|
||||
|
||||
let server = responses::start_mock_server().await;
|
||||
let response_body = responses::sse(vec![
|
||||
responses::ev_response_created("resp-1"),
|
||||
responses::ev_completed("resp-1"),
|
||||
]);
|
||||
|
||||
let request_recorder = responses::mount_sse_once(&server, response_body).await;
|
||||
|
||||
let test = test_codex().build(&server).await.expect("build test codex");
|
||||
test.submit_turn("hello").await.expect("submit test prompt");
|
||||
|
||||
let request = request_recorder.single_request();
|
||||
assert_eq!(
|
||||
request
|
||||
.header(X_OPENAI_INTERNAL_CODEX_EXPERIMENTAL_WINDOWS_SANDBOX_HEADER)
|
||||
.as_deref(),
|
||||
Some("false")
|
||||
);
|
||||
assert_eq!(
|
||||
request
|
||||
.header(X_OPENAI_INTERNAL_CODEX_ELEVATED_WINDOWS_SANDBOX_HEADER)
|
||||
.as_deref(),
|
||||
Some("false")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn responses_stream_includes_windows_sandbox_headers_when_enabled() {
|
||||
core_test_support::skip_if_no_network!();
|
||||
|
||||
let server = responses::start_mock_server().await;
|
||||
let response_body = responses::sse(vec![
|
||||
responses::ev_response_created("resp-1"),
|
||||
responses::ev_completed("resp-1"),
|
||||
]);
|
||||
|
||||
let request_recorder = responses::mount_sse_once(&server, response_body).await;
|
||||
|
||||
let test = test_codex()
|
||||
.with_config(|config| {
|
||||
config.features.enable(Feature::WindowsSandboxElevated);
|
||||
})
|
||||
.build(&server)
|
||||
.await
|
||||
.expect("build test codex");
|
||||
test.submit_turn("hello").await.expect("submit test prompt");
|
||||
|
||||
let request = request_recorder.single_request();
|
||||
assert_eq!(
|
||||
request
|
||||
.header(X_OPENAI_INTERNAL_CODEX_EXPERIMENTAL_WINDOWS_SANDBOX_HEADER)
|
||||
.as_deref(),
|
||||
Some("true")
|
||||
);
|
||||
assert_eq!(
|
||||
request
|
||||
.header(X_OPENAI_INTERNAL_CODEX_ELEVATED_WINDOWS_SANDBOX_HEADER)
|
||||
.as_deref(),
|
||||
Some("true")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn responses_respects_model_info_overrides_from_config() {
|
||||
core_test_support::skip_if_no_network!();
|
||||
@@ -378,6 +450,7 @@ async fn responses_respects_model_info_overrides_from_config() {
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
WindowsSandboxLevel::Disabled,
|
||||
);
|
||||
let mut client_session = client.new_session();
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::Settings;
|
||||
use codex_protocol::config_types::Verbosity;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::models::FunctionCallOutputPayload;
|
||||
use codex_protocol::models::MessagePhase;
|
||||
use codex_protocol::models::ReasoningItemContent;
|
||||
@@ -1273,6 +1274,7 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() {
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
WindowsSandboxLevel::Disabled,
|
||||
);
|
||||
let mut client_session = client.new_session();
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ use codex_otel::metrics::MetricsConfig;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::account::PlanType;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use core_test_support::load_default_config_for_test;
|
||||
@@ -465,6 +466,7 @@ async fn websocket_harness_with_runtime_metrics(
|
||||
false,
|
||||
runtime_metrics_enabled,
|
||||
None,
|
||||
WindowsSandboxLevel::Disabled,
|
||||
);
|
||||
|
||||
WebsocketTestHarness {
|
||||
|
||||
Reference in New Issue
Block a user