From 2beaf6ca44a45d83689d77770c985e5efa14cfc8 Mon Sep 17 00:00:00 2001 From: Cooper Gamble Date: Wed, 20 May 2026 19:43:04 +0000 Subject: [PATCH] [codex-core] retry remote v2 compact auth recovery [ci changed_files] --- codex-rs/core/src/compact_remote_v2.rs | 60 +++++++++++-------- .../core/tests/suite/client_websockets.rs | 10 ++++ 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/codex-rs/core/src/compact_remote_v2.rs b/codex-rs/core/src/compact_remote_v2.rs index 101317a0ee..e971769a02 100644 --- a/codex-rs/core/src/compact_remote_v2.rs +++ b/codex-rs/core/src/compact_remote_v2.rs @@ -277,31 +277,43 @@ async fn run_remote_compaction_request_v2( prompt: &Prompt, turn_metadata_header: Option<&str>, ) -> CodexResult<(ResponseItem, String)> { - let stream = client_session - .stream( - prompt, - &turn_context.model_info, - &turn_context.session_telemetry, - turn_context.reasoning_effort, - turn_context.reasoning_summary, - turn_context.config.service_tier.clone(), - turn_metadata_header, - &InferenceTraceContext::disabled(), - ) - .or_else(|err| async { - let total_usage_breakdown = sess.get_total_token_usage_breakdown().await; - let compact_request_log_data = - build_compact_request_log_data(&prompt.input, &prompt.base_instructions.text); - log_remote_compact_failure( - turn_context, - &compact_request_log_data, - total_usage_breakdown, - &err, - ); + let mut websocket_auth_recovery_retries = 0; + loop { + let stream = client_session + .stream( + prompt, + &turn_context.model_info, + &turn_context.session_telemetry, + turn_context.reasoning_effort, + turn_context.reasoning_summary, + turn_context.config.service_tier.clone(), + turn_metadata_header, + &InferenceTraceContext::disabled(), + ) + .or_else(|err| async { + let total_usage_breakdown = sess.get_total_token_usage_breakdown().await; + let compact_request_log_data = + build_compact_request_log_data(&prompt.input, &prompt.base_instructions.text); + log_remote_compact_failure( + turn_context, + &compact_request_log_data, + total_usage_breakdown, + &err, + ); + Err(err) + }) + .await?; + + match collect_compaction_output(stream).await { Err(err) - }) - .await?; - collect_compaction_output(stream).await + if crate::client::is_websocket_auth_recovery_retry(&err) + && websocket_auth_recovery_retries == 0 => + { + websocket_auth_recovery_retries += 1; + } + result => return result, + } + } } async fn collect_compaction_output( diff --git a/codex-rs/core/tests/suite/client_websockets.rs b/codex-rs/core/tests/suite/client_websockets.rs index 5cc53958af..f1d3755224 100755 --- a/codex-rs/core/tests/suite/client_websockets.rs +++ b/codex-rs/core/tests/suite/client_websockets.rs @@ -1767,6 +1767,10 @@ async fn responses_websocket_revoked_managed_auth_compact_retries_reloaded_auth( .with_home(codex_home.clone()) .with_auth(auth) .with_config(|config| { + config + .features + .enable(Feature::RemoteCompactionV2) + .expect("test config should allow feature update"); config.model_provider.request_max_retries = Some(0); config.model_provider.stream_max_retries = Some(0); }); @@ -1785,6 +1789,12 @@ async fn responses_websocket_revoked_managed_auth_compact_retries_reloaded_auth( .await .expect("compact submission should succeed"); wait_for_event(&test.codex, |msg| matches!(msg, EventMsg::TurnComplete(_))).await; + assert!( + server + .wait_for_handshakes(/*expected*/ 2, Duration::from_secs(10)) + .await, + "compact auth recovery should reconnect with replacement auth" + ); let persisted_auth = CodexAuth::from_auth_storage( codex_home.path(),