Retry compaction after model 404

This commit is contained in:
celia-oai
2026-07-09 18:50:36 -07:00
parent 1f0566d3f5
commit 0f6d974bda
4 changed files with 29 additions and 7 deletions

View File

@@ -2,8 +2,17 @@ use codex_analytics::CompactionImplementation;
use codex_analytics::CompactionReason;
use codex_otel::SessionTelemetry;
use codex_protocol::error::CodexErr;
use http::StatusCode;
use tracing::warn;
pub(crate) fn should_retry_with_current_model(error: &CodexErr) -> bool {
match error {
CodexErr::InvalidRequest(_) => true,
CodexErr::UnexpectedStatus(response) => response.status == StatusCode::NOT_FOUND,
_ => false,
}
}
pub(crate) fn record_model_fallback(
session_telemetry: &SessionTelemetry,
previous_model: &str,

View File

@@ -8,6 +8,7 @@ use crate::compact::build_compaction_initial_context;
use crate::compact::compaction_status_from_result;
use crate::compact::insert_initial_context_before_last_real_user_or_summary;
use crate::compact_model_fallback::record_model_fallback;
use crate::compact_model_fallback::should_retry_with_current_model;
use crate::context::world_state::WorldState;
use crate::context_manager::ContextManager;
use crate::hook_runtime::PostCompactHookOutcome;
@@ -218,7 +219,7 @@ async fn run_remote_compact_task_inner_impl(
let Some(fallback_step_context) = fallback_step_context else {
return Err(error);
};
if !matches!(&error, CodexErr::InvalidRequest(_)) {
if !should_retry_with_current_model(&error) {
return Err(error);
}
let fallback_turn_context = &fallback_step_context.turn;

View File

@@ -9,6 +9,7 @@ use crate::compact::CompactionAnalyticsDetails;
use crate::compact::InitialContextInjection;
use crate::compact::compaction_status_from_result;
use crate::compact_model_fallback::record_model_fallback;
use crate::compact_model_fallback::should_retry_with_current_model;
use crate::compact_remote::process_compacted_history;
use crate::compact_remote::should_keep_compacted_history_item;
use crate::hook_runtime::PostCompactHookOutcome;
@@ -230,7 +231,7 @@ async fn run_remote_compact_task_inner_impl(
let Some(fallback_step_context) = fallback_step_context else {
return Err(error);
};
if !matches!(&error, CodexErr::InvalidRequest(_)) {
if !should_retry_with_current_model(&error) {
return Err(error);
}
let fallback_turn_context = &fallback_step_context.turn;

View File

@@ -289,6 +289,17 @@ fn invalid_request_response(message: impl Into<String>) -> wiremock::ResponseTem
}))
}
fn model_not_found_response(model: &str) -> wiremock::ResponseTemplate {
wiremock::ResponseTemplate::new(/*status*/ 404).set_body_json(json!({
"error": {
"message": format!("Model not found {model}"),
"type": "invalid_request_error",
"param": "model",
"code": null,
}
}))
}
fn write_global_file(
home: &TempDir,
filename: &str,
@@ -2293,7 +2304,7 @@ async fn pre_sampling_compact_runs_when_comp_hash_changes() {
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn pre_sampling_compact_falls_back_from_retired_previous_model_after_rename() {
async fn pre_sampling_compact_falls_back_when_previous_model_is_not_found() {
skip_if_no_network!();
let server = MockServer::start().await;
@@ -2320,9 +2331,7 @@ async fn pre_sampling_compact_falls_back_from_retired_previous_model_after_renam
ev_assistant_message("m1", "before switch"),
ev_completed_with_tokens("r1", /*total_tokens*/ 100),
])),
invalid_request_response(format!(
"The '{retired_model}' model is not supported when using Codex with a ChatGPT account."
)),
model_not_found_response(retired_model),
sse_response(sse(vec![
json!({
"type": "response.output_item.done",
@@ -2384,7 +2393,9 @@ async fn pre_sampling_compact_falls_back_from_retired_previous_model_after_renam
})
.await;
let model_provider = openai_model_provider(&server);
let mut model_provider = openai_model_provider(&server);
model_provider.request_max_retries = Some(0);
model_provider.stream_max_retries = Some(0);
let mut resumed_builder = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_model(retired_model)