fix(openai): use a catalog-supported warmup reasoning effort (#425)

Scheduled account warmup sent reasoning.effort=none, but the Codex model
catalog lists low as the lowest supported level for every model an account
can see. Upstream answers HTTP 200 with an SSE error event (unsupported_value
on reasoning.effort), which the warmup terminal check records as
response_failed, so the cycle ends with warmed_up=0 and never starts the 5h
window.

Send low instead and cover the upstream payload with a regression test.
This commit is contained in:
dudukee
2026-10-14 11:42:48 +08:00
committed by GitHub
parent 286031a441
commit b5bd63b585
2 changed files with 40 additions and 5 deletions
@@ -164,10 +164,8 @@ impl CodexCredentialQuotaService {
"service_tier".to_owned(),
Value::String("default".to_owned()),
);
body.insert(
"reasoning".to_owned(),
serde_json::json!({"effort": "none"}),
);
// 目录里各模型的最低档都是 low,none 会收到上游 error 终态并让整次预热记为失败
body.insert("reasoning".to_owned(), serde_json::json!({"effort": "low"}));
body.insert("text".to_owned(), serde_json::json!({"verbosity": "low"}));
let upstream_request = CodexResponsesRequest::from_body(body);
@@ -1,4 +1,4 @@
//! 验证额度预热按 SSE 终态判定结果并跳过过期凭据
//! 验证额度预热按 SSE 终态判定结果、请求档位并跳过过期凭据
use super::*;
@@ -40,6 +40,43 @@ async fn warmup_consumes_completed_sse_and_persists_rate_limit_event() {
assert!(store.quota_json("acct_warmup_completed").is_some());
}
#[tokio::test]
async fn warmup_sends_the_lowest_reasoning_effort_supported_by_the_catalog() {
let server = MockServer::start().await;
let sse = concat!(
"event: response.completed\n",
"data: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_warmup_effort\",\"status\":\"completed\",\"output\":[]}}\n\n",
"data: [DONE]\n\n",
);
Mock::given(method("POST"))
.and(path("/codex/responses"))
.respond_with(ResponseTemplate::new(200).set_body_raw(sse, "text/event-stream"))
.expect(1)
.mount(&server)
.await;
let store = Arc::new(MemoryAccountStore::default());
create_account(&store, "acct_warmup_effort").await;
let service = quota_service_with_base_url(
&store,
reqwest::Client::builder()
.no_proxy()
.build()
.expect("client"),
server.uri(),
);
let summary = service.execute_warmup("test-model").await.expect("warmup");
assert_eq!(summary.warmed_up, 1);
let requests = server.received_requests().await.expect("recorded requests");
let decoded =
zstd::stream::decode_all(requests[0].body.as_slice()).expect("zstd body should decode");
let body: serde_json::Value =
serde_json::from_slice(&decoded).expect("warmup body should be valid JSON");
// 上游按目录拒绝目录外的档位,none 曾让全部定时预热只留下 error 终态
assert_eq!(body["reasoning"]["effort"], "low");
}
#[tokio::test]
async fn warmup_rejects_failed_sse_despite_successful_http_headers() {
let server = MockServer::start().await;