[codex] wire per-surface integrity state transport [ci changed_files]

This commit is contained in:
Cooper Gamble
2026-06-03 10:12:52 +00:00
parent d31ede0634
commit fe2aee1632
14 changed files with 158 additions and 87 deletions
+2 -2
View File
@@ -312,7 +312,7 @@ impl AgentControl {
.session
.services
.model_client
.native_integrity_surface()
.http_state_surface()
{
new_thread
.thread
@@ -320,7 +320,7 @@ impl AgentControl {
.session
.services
.model_client
.set_native_integrity_surface(surface);
.set_http_state_surface(surface);
}
parent_thread
.codex
+4 -4
View File
@@ -10,8 +10,8 @@ use crate::context::ContextualUserFragment;
use crate::context::SubagentNotification;
use crate::init_state_db;
use assert_matches::assert_matches;
use codex_client::NativeIntegritySurface;
use codex_features::Feature;
use codex_http_state::HttpStateSurface;
use codex_login::CodexAuth;
use codex_protocol::AgentPath;
use codex_protocol::config_types::ModeKind;
@@ -1586,7 +1586,7 @@ async fn spawn_child_completion_notifies_parent_history() {
}
#[tokio::test]
async fn spawn_thread_subagent_inherits_parent_native_integrity_surface() {
async fn spawn_thread_subagent_inherits_parent_http_state_surface() {
let harness = AgentControlHarness::new().await;
let (parent_thread_id, parent_thread) = harness.start_thread().await;
parent_thread
@@ -1625,8 +1625,8 @@ async fn spawn_thread_subagent_inherits_parent_native_integrity_surface() {
.session
.services
.model_client
.native_integrity_surface(),
Some(NativeIntegritySurface::CodexDesktop)
.http_state_surface(),
Some(HttpStateSurface::CodexDesktop)
);
}
+23 -25
View File
@@ -62,8 +62,8 @@ use codex_api::build_session_headers;
use codex_api::create_text_param_for_request;
use codex_api::response_create_client_metadata;
use codex_app_server_protocol::AuthMode;
use codex_client::NativeIntegrityStateContext;
use codex_client::NativeIntegritySurface;
use codex_http_state::HttpStateContext;
use codex_http_state::HttpStateSurface;
use codex_login::AuthManager;
use codex_login::CodexAuth;
use codex_login::RefreshTokenError;
@@ -183,7 +183,7 @@ struct ModelClientState {
beta_features_header: Option<String>,
include_attestation: bool,
attestation_provider: Option<Arc<dyn AttestationProvider>>,
native_integrity_state: Option<NativeIntegrityStateContext>,
http_state: Option<HttpStateContext>,
disable_websockets: AtomicBool,
cached_websocket_session: StdMutex<WebsocketSession>,
}
@@ -333,10 +333,10 @@ impl ModelClient {
beta_features_header: Option<String>,
attestation_provider: Option<Arc<dyn AttestationProvider>>,
) -> Self {
let native_integrity_state = auth_manager.as_ref().map(|auth_manager| {
NativeIntegrityStateContext::new(
let http_state = auth_manager.as_ref().map(|auth_manager| {
HttpStateContext::new(
auth_manager.codex_home().to_path_buf(),
native_integrity_surface_for_session_source(&session_source),
http_state_surface_for_session_source(&session_source),
)
});
let model_provider = create_model_provider(provider_info, auth_manager);
@@ -363,7 +363,7 @@ impl ModelClient {
beta_features_header,
include_attestation,
attestation_provider,
native_integrity_state,
http_state,
disable_websockets: AtomicBool::new(false),
cached_websocket_session: StdMutex::new(WebsocketSession::default()),
}),
@@ -403,26 +403,26 @@ impl ModelClient {
pub(crate) fn set_app_server_client_name(&self, client_name: Option<&str>) {
let surface = client_name
.map(NativeIntegritySurface::from_app_server_client_name)
.unwrap_or(NativeIntegritySurface::CodexCli);
self.set_native_integrity_surface(surface);
.map(HttpStateSurface::from_app_server_client_name)
.unwrap_or(HttpStateSurface::CodexCli);
self.set_http_state_surface(surface);
}
pub(crate) fn native_integrity_surface(&self) -> Option<NativeIntegritySurface> {
pub(crate) fn http_state_surface(&self) -> Option<HttpStateSurface> {
self.state
.native_integrity_state
.http_state
.as_ref()
.map(NativeIntegrityStateContext::surface)
.map(HttpStateContext::surface)
}
pub(crate) fn native_integrity_state_context(&self) -> Option<NativeIntegrityStateContext> {
self.state.native_integrity_state.clone()
pub(crate) fn http_state_context(&self) -> Option<HttpStateContext> {
self.state.http_state.clone()
}
pub(crate) fn set_native_integrity_surface(&self, surface: NativeIntegritySurface) {
pub(crate) fn set_http_state_surface(&self, surface: HttpStateSurface) {
if self
.state
.native_integrity_state
.http_state
.as_ref()
.is_some_and(|state| state.set_surface(surface))
{
@@ -855,7 +855,7 @@ impl ModelClient {
let api_auth = with_native_integrity_state(
self.state.provider.api_auth().await?,
auth.as_ref(),
self.state.native_integrity_state.clone(),
self.state.http_state.clone(),
);
Ok(CurrentClientSetup {
auth,
@@ -1780,18 +1780,16 @@ fn subagent_header_value(session_source: &SessionSource) -> Option<String> {
}
}
fn native_integrity_surface_for_session_source(
session_source: &SessionSource,
) -> NativeIntegritySurface {
fn http_state_surface_for_session_source(session_source: &SessionSource) -> HttpStateSurface {
match session_source {
SessionSource::Cli => NativeIntegritySurface::CodexTui,
SessionSource::Exec => NativeIntegritySurface::CodexExec,
SessionSource::VSCode => NativeIntegritySurface::CodexVscode,
SessionSource::Cli => HttpStateSurface::CodexTui,
SessionSource::Exec => HttpStateSurface::CodexExec,
SessionSource::VSCode => HttpStateSurface::CodexVscode,
SessionSource::SubAgent(_)
| SessionSource::Internal(_)
| SessionSource::Mcp
| SessionSource::Custom(_)
| SessionSource::Unknown => NativeIntegritySurface::CodexCli,
| SessionSource::Unknown => HttpStateSurface::CodexCli,
}
}
+2 -6
View File
@@ -110,16 +110,12 @@ pub(crate) async fn run_codex_thread_interactive(
}))
.or_cancel(&cancel_token)
.await??;
if let Some(surface) = parent_session
.services
.model_client
.native_integrity_surface()
{
if let Some(surface) = parent_session.services.model_client.http_state_surface() {
codex
.session
.services
.model_client
.set_native_integrity_surface(surface);
.set_http_state_surface(surface);
}
let thread_config = codex.thread_config_snapshot().await;
let client_metadata = parent_session.app_server_client_metadata().await;
+5 -9
View File
@@ -2,7 +2,7 @@ use super::*;
use crate::mcp_tool_call::MCP_TOOL_APPROVAL_DECLINE_SYNTHETIC;
use crate::mcp_tool_call::MCP_TOOL_APPROVAL_QUESTION_ID_PREFIX;
use async_channel::bounded;
use codex_client::NativeIntegritySurface;
use codex_http_state::HttpStateSurface;
use codex_mcp::CODEX_APPS_MCP_SERVER_NAME;
use codex_protocol::config_types::ApprovalsReviewer;
use codex_protocol::models::NetworkPermissions;
@@ -183,13 +183,13 @@ async fn run_codex_thread_interactive_respects_pre_cancelled_spawn() {
}
#[tokio::test]
async fn run_codex_thread_interactive_inherits_parent_native_integrity_surface() {
async fn run_codex_thread_interactive_inherits_parent_http_state_surface() {
let (parent_session, parent_ctx, _rx_events) =
crate::session::tests::make_session_and_context_with_rx().await;
parent_session
.services
.model_client
.set_native_integrity_surface(NativeIntegritySurface::CodexDesktop);
.set_http_state_surface(HttpStateSurface::CodexDesktop);
let cancel_token = CancellationToken::new();
let delegated = run_codex_thread_interactive(
@@ -206,12 +206,8 @@ async fn run_codex_thread_interactive_inherits_parent_native_integrity_surface()
.expect("delegate should spawn");
assert_eq!(
delegated
.session
.services
.model_client
.native_integrity_surface(),
Some(NativeIntegritySurface::CodexDesktop)
delegated.session.services.model_client.http_state_surface(),
Some(HttpStateSurface::CodexDesktop)
);
cancel_token.cancel();
}
+11 -11
View File
@@ -13,7 +13,7 @@
use crate::session::session::Session;
use crate::session::turn_context::TurnContext;
use codex_api::upload_local_file;
use codex_client::NativeIntegrityStateContext;
use codex_http_state::HttpStateContext;
use codex_login::CodexAuth;
use serde_json::Value as JsonValue;
@@ -34,7 +34,7 @@ pub(crate) async fn rewrite_mcp_tool_arguments_for_openai_files(
return Ok(Some(arguments_value));
};
let auth = sess.services.auth_manager.auth().await;
let native_integrity_state = sess.services.model_client.native_integrity_state_context();
let http_state = sess.services.model_client.http_state_context();
let mut rewritten_arguments = arguments.clone();
for field_name in openai_file_input_params {
@@ -44,7 +44,7 @@ pub(crate) async fn rewrite_mcp_tool_arguments_for_openai_files(
let Some(uploaded_value) = rewrite_argument_value_for_openai_files(
turn_context,
auth.as_ref(),
native_integrity_state.clone(),
http_state.clone(),
field_name,
value,
)
@@ -65,7 +65,7 @@ pub(crate) async fn rewrite_mcp_tool_arguments_for_openai_files(
async fn rewrite_argument_value_for_openai_files(
turn_context: &TurnContext,
auth: Option<&CodexAuth>,
native_integrity_state: Option<NativeIntegrityStateContext>,
http_state: Option<HttpStateContext>,
field_name: &str,
value: &JsonValue,
) -> Result<Option<JsonValue>, String> {
@@ -74,7 +74,7 @@ async fn rewrite_argument_value_for_openai_files(
let rewritten = build_uploaded_local_argument_value(
turn_context,
auth,
native_integrity_state,
http_state,
field_name,
/*index*/ None,
path_or_file_ref,
@@ -91,7 +91,7 @@ async fn rewrite_argument_value_for_openai_files(
let rewritten = build_uploaded_local_argument_value(
turn_context,
auth,
native_integrity_state.clone(),
http_state.clone(),
field_name,
Some(index),
path_or_file_ref,
@@ -108,7 +108,7 @@ async fn rewrite_argument_value_for_openai_files(
async fn build_uploaded_local_argument_value(
turn_context: &TurnContext,
auth: Option<&CodexAuth>,
native_integrity_state: Option<NativeIntegrityStateContext>,
http_state: Option<HttpStateContext>,
field_name: &str,
index: Option<usize>,
file_path: &str,
@@ -128,7 +128,7 @@ async fn build_uploaded_local_argument_value(
let upload_auth = codex_model_provider::with_native_integrity_state(
codex_model_provider::auth_provider_from_auth(auth),
Some(auth),
native_integrity_state,
http_state,
);
let uploaded = upload_local_file(
turn_context.config.chatgpt_base_url.trim_end_matches('/'),
@@ -244,7 +244,7 @@ mod tests {
let rewritten = build_uploaded_local_argument_value(
&turn_context,
Some(&auth),
/*native_integrity_state*/ None,
/*http_state*/ None,
"file",
/*index*/ None,
"file_report.csv",
@@ -328,7 +328,7 @@ mod tests {
let rewritten = rewrite_argument_value_for_openai_files(
&turn_context,
Some(&auth),
/*native_integrity_state*/ None,
/*http_state*/ None,
"file",
&serde_json::json!("file_report.csv"),
)
@@ -446,7 +446,7 @@ mod tests {
let rewritten = rewrite_argument_value_for_openai_files(
&turn_context,
Some(&auth),
/*native_integrity_state*/ None,
/*http_state*/ None,
"files",
&serde_json::json!(["one.csv", "two.csv"]),
)