style: apply cargo fmt across gateway and aether-ai crates

This commit is contained in:
AAEE86
2026-08-17 14:53:53 +08:00
committed by ZheFox
parent 6fc02dad3e
commit 4a0775c4ea
13 changed files with 159 additions and 131 deletions
@@ -97,10 +97,13 @@ impl AttemptProviderOutcome {
}
pub(crate) const fn stream_timeout(self) -> bool {
matches!(self, Self::Aborted {
stream_timeout: true,
..
})
matches!(
self,
Self::Aborted {
stream_timeout: true,
..
}
)
}
pub(crate) const fn is_terminal(self) -> bool {
@@ -161,10 +164,9 @@ impl AttemptTerminalFacts {
/// `None` 一致。
pub(crate) const fn forced_error(self) -> Option<&'static str> {
match (self.provider, self.delivery) {
(
AttemptProviderOutcome::Aborted { reason, .. },
AttemptClientDelivery::Complete,
) => Some(reason),
(AttemptProviderOutcome::Aborted { reason, .. }, AttemptClientDelivery::Complete) => {
Some(reason)
}
_ => None,
}
}
@@ -352,16 +354,11 @@ pub(crate) const fn classify_attempt_settlement(
},
candidate_status,
candidate_error,
provider_effect: classify_attempt_provider_effect(
void,
projects_provider_failure,
failed,
),
provider_effect: classify_attempt_provider_effect(void, projects_provider_failure, failed),
submit_execution_report: !void,
}
}
/// 每一段记账 I/O 的等待上界。
///
/// WS 用 `Bounded(5s)`relay loop 是单任务,一段慢依赖会拖住整条连接的收发。
@@ -895,7 +892,6 @@ mod tests {
);
}
#[test]
fn the_recorded_reason_prefers_the_client_delivery_failure() {
assert_eq!(
@@ -934,7 +930,6 @@ mod tests {
);
}
/// §1.6 结算表,逐行。
#[test]
fn settlement_table_row_provider_cancelled_is_void_regardless_of_delivery() {
@@ -943,8 +938,13 @@ mod tests {
AttemptClientDelivery::Aborted { reason: "gone" },
] {
for report_represents_failure in [false, true] {
let settlement =
settle(provider_cancelled(), delivery, report_represents_failure, true, false);
let settlement = settle(
provider_cancelled(),
delivery,
report_represents_failure,
true,
false,
);
assert_eq!(
settlement,
AttemptSettlement {
@@ -961,7 +961,6 @@ mod tests {
}
}
#[test]
fn settlement_table_row_aborted_provider_with_aborted_delivery_is_void() {
let settlement = settle(
@@ -986,10 +985,15 @@ mod tests {
);
}
#[test]
fn settlement_table_row_clean_provider_terminal_is_a_billed_success() {
let settlement = settle(terminal(200), AttemptClientDelivery::Complete, false, true, false);
let settlement = settle(
terminal(200),
AttemptClientDelivery::Complete,
false,
true,
false,
);
assert_eq!(
settlement,
AttemptSettlement {
@@ -1003,12 +1007,17 @@ mod tests {
);
}
/// 合法 `response.incomplete`:记账层判失败,但供应商工作正常,
/// 不扣健康分、只释放 lease,并且账单照记。
#[test]
fn settlement_table_row_legitimate_incomplete_is_billed_without_provider_failure() {
let settlement = settle(terminal(200), AttemptClientDelivery::Complete, true, true, false);
let settlement = settle(
terminal(200),
AttemptClientDelivery::Complete,
true,
true,
false,
);
assert_eq!(
settlement,
AttemptSettlement {
@@ -1022,11 +1031,13 @@ mod tests {
);
}
#[test]
fn settlement_table_row_provider_abort_projects_a_provider_failure() {
let settlement = settle(
aborted(502, "upstream WebSocket closed before provider terminal event"),
aborted(
502,
"upstream WebSocket closed before provider terminal event",
),
AttemptClientDelivery::Complete,
true,
false,
@@ -1045,7 +1056,6 @@ mod tests {
);
}
/// ✱ 修正后的那一行:provider 终态已到达,客户端投递失败不再作废账单。
///
/// 供应商已经完成推理并消耗 token,客户端还能用 `previous_response_id`
@@ -1075,7 +1085,13 @@ mod tests {
);
// 除了 candidate 的错误分类,其余判定与「投递成功」完全一致。
let delivered = settle(terminal(200), AttemptClientDelivery::Complete, false, true, false);
let delivered = settle(
terminal(200),
AttemptClientDelivery::Complete,
false,
true,
false,
);
assert_eq!(settlement.status_code, delivered.status_code);
assert_eq!(settlement.billing, delivered.billing);
assert_eq!(settlement.candidate_status, delivered.candidate_status);
@@ -1087,7 +1103,6 @@ mod tests {
assert_ne!(settlement.candidate_error, delivered.candidate_error);
}
/// 供应商还没给出终态时,客户端投递失败仍然作废账单:这一轮确实没有产出。
#[test]
fn a_delivery_failure_without_a_provider_terminal_still_voids_the_bill() {
@@ -1110,23 +1125,32 @@ mod tests {
assert!(!settlement.submit_execution_report);
}
/// 供应商自己声明取消时,即使内容送到了客户端也不计费。
#[test]
fn a_provider_declared_cancellation_is_void_even_when_delivered() {
let settlement =
settle(provider_cancelled(), AttemptClientDelivery::Complete, false, true, false);
let settlement = settle(
provider_cancelled(),
AttemptClientDelivery::Complete,
false,
true,
false,
);
assert_eq!(settlement.billing, AttemptBilling::Void);
assert_eq!(settlement.candidate_error, AttemptCandidateError::Cancelled);
}
/// 记账层判 Success,但摘要没观察到 finish:现状会写出
/// 「candidate=Success + error_type=stream_missing_terminal_event」,
/// 所以状态与错误分类必须各自独立。
#[test]
fn a_missing_terminal_can_coexist_with_a_successful_candidate_status() {
let settlement = settle(terminal(200), AttemptClientDelivery::Complete, false, false, false);
let settlement = settle(
terminal(200),
AttemptClientDelivery::Complete,
false,
false,
false,
);
assert_eq!(settlement.candidate_status, AttemptCandidateStatus::Success);
assert_eq!(
settlement.candidate_error,
@@ -1139,10 +1163,15 @@ mod tests {
);
}
#[test]
fn a_parser_error_projects_a_provider_failure_even_on_a_clean_status_code() {
let settlement = settle(terminal(200), AttemptClientDelivery::Complete, true, true, true);
let settlement = settle(
terminal(200),
AttemptClientDelivery::Complete,
true,
true,
true,
);
assert_eq!(
settlement.provider_effect,
AttemptProviderEffect::ProviderFailure
@@ -1150,7 +1179,6 @@ mod tests {
assert_eq!(settlement.billing, AttemptBilling::Billed);
}
#[test]
fn a_legitimate_incomplete_still_releases_the_pool_key_lease() {
// 共享 usage 判定目前仍把 response.incomplete 记成终态失败,于是会出现
@@ -1162,7 +1190,6 @@ mod tests {
assert!(effect.releases_pool_key_lease());
}
#[test]
fn every_provider_effect_releases_the_pool_key_lease() {
for (cancelled, projects_provider_failure, failed, expected) in [
@@ -1172,36 +1199,18 @@ mod tests {
false,
AttemptProviderEffect::ReleasePoolKeyLease,
),
(
true,
true,
true,
AttemptProviderEffect::ReleasePoolKeyLease,
),
(
false,
true,
true,
AttemptProviderEffect::ProviderFailure,
),
(true, true, true, AttemptProviderEffect::ReleasePoolKeyLease),
(false, true, true, AttemptProviderEffect::ProviderFailure),
(
false,
false,
true,
AttemptProviderEffect::ReleasePoolKeyLease,
),
(
false,
false,
false,
AttemptProviderEffect::ProviderSuccess,
),
(false, false, false, AttemptProviderEffect::ProviderSuccess),
] {
let effect = classify_attempt_provider_effect(
cancelled,
projects_provider_failure,
failed,
);
let effect =
classify_attempt_provider_effect(cancelled, projects_provider_failure, failed);
assert_eq!(
effect, expected,
"cancelled={cancelled} projects_provider_failure={projects_provider_failure} failed={failed}"
@@ -1213,7 +1222,6 @@ mod tests {
}
}
/// 每一个结算分支都必须释放 lease:这条不变量跨越整张结算表。
#[test]
fn every_settlement_branch_releases_the_pool_key_lease() {
@@ -1291,9 +1299,13 @@ mod stage_tests {
if !effects_completed {
let released = Arc::clone(&lease_released);
let _ = guard
.await_stage("trace", "pool_lease_release_after_effect_timeout", async move {
released.store(true, Ordering::SeqCst);
})
.await_stage(
"trace",
"pool_lease_release_after_effect_timeout",
async move {
released.store(true, Ordering::SeqCst);
},
)
.await;
}
assert!(
@@ -1423,14 +1435,22 @@ mod stage_tests {
Some("websocket_cancelled".to_string())
);
assert_eq!(
candidate_error_fields(AttemptCandidateError::ClientDeliveryFailed, None, "write failed"),
candidate_error_fields(
AttemptCandidateError::ClientDeliveryFailed,
None,
"write failed"
),
(
Some("client_delivery_failed".to_string()),
Some("write failed".to_string())
)
);
assert_eq!(
candidate_error_fields(AttemptCandidateError::TerminalError, Some("parser"), "reason"),
candidate_error_fields(
AttemptCandidateError::TerminalError,
Some("parser"),
"reason"
),
(
Some("stream_terminal_error".to_string()),
Some("parser".to_string())
@@ -3,8 +3,8 @@ use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
pub(crate) mod attempt_lifecycle;
pub(crate) mod admission;
pub(crate) mod attempt_lifecycle;
mod chatgpt_web_image;
mod constants;
mod fallback;
@@ -570,4 +570,3 @@ async fn wait_for_connection_permit_loss(permit: Option<&aether_runtime::Admissi
}
}
}
@@ -77,8 +77,7 @@ mod tests {
#[test]
fn structured_events_reach_the_terminal_summary_without_sse_text() {
let context = report_context();
let created =
json!({"type": "response.created", "response": {"id": "resp_ws", "model": "gpt-5-codex"}});
let created = json!({"type": "response.created", "response": {"id": "resp_ws", "model": "gpt-5-codex"}});
let completed = json!({
"type": "response.completed",
"response": {
@@ -191,8 +191,8 @@ mod tests {
use super::super::request::{
build_planning_parts, normalize_followup_response_create, planned_response_create_event,
};
use super::super::turn_state::LogicalTurn;
use super::super::turn::prepare_responses_websocket_turn_decision;
use super::super::turn_state::LogicalTurn;
use super::{
redact_responses_websocket_client_event, ResponsesWebSocketRedactionRestorer,
ResponsesWebSocketTurnRedaction, MAX_RETAINED_TURN_REDACTION_SESSIONS,
@@ -595,11 +595,7 @@ mod tests {
let effective_event = redacted_client_event(&state, &decision).await;
// 配额透明重试重放 LogicalTurn 里保存的事件,所以保存的必须
// 已经是脱敏版,否则重试会把原文发给新的上游账号。
let active = LogicalTurn::new(
effective_event.clone(),
2,
"logical-turn-2".to_string(),
);
let active = LogicalTurn::new(effective_event.clone(), 2, "logical-turn-2".to_string());
assert_redacted_json(&active.client_event, "quota retry replay event");
let template = decision_template(
@@ -535,14 +535,12 @@ mod tests {
normalize_followup_response_create, planned_response_create_event,
response_create_model_or_current,
};
use super::super::state::{
BoundResponsesConnection, ExhaustedResponsesWebSocketExclusions,
};
use super::super::turn_state::{LogicalTurn, ResponsesTurnState};
use super::super::state::{BoundResponsesConnection, ExhaustedResponsesWebSocketExclusions};
use super::super::turn::{
ResponsesWebSocketTurnDeadline, ResponsesWebSocketTurnObservation,
ResponsesWebSocketTurnOutcome, ResponsesWebSocketTurnTimeoutPhase,
};
use super::super::turn_state::{LogicalTurn, ResponsesTurnState};
use super::super::upstream::bind_responses_upstream;
use crate::ai_serving::{AiExecutionDecision, ResponsesWebSocketBodyNormalization};
use crate::handlers::proxy::websocket::session::wait_for_optional_deadline;
@@ -144,7 +144,11 @@ mod tests {
}
);
assert_eq!(
attempt_facts_for_outcome(None, AttemptClientDelivery::Complete, ResponsesWebSocketTurnOutcome::upstream_closed()),
attempt_facts_for_outcome(
None,
AttemptClientDelivery::Complete,
ResponsesWebSocketTurnOutcome::upstream_closed()
),
AttemptTerminalFacts {
provider: aborted(
502,
@@ -154,7 +158,11 @@ mod tests {
}
);
assert_eq!(
attempt_facts_for_outcome(None, AttemptClientDelivery::Complete, ResponsesWebSocketTurnOutcome::client_disconnected()),
attempt_facts_for_outcome(
None,
AttemptClientDelivery::Complete,
ResponsesWebSocketTurnOutcome::client_disconnected()
),
AttemptTerminalFacts {
provider: aborted(499, "client disconnected before provider terminal event"),
delivery: AttemptClientDelivery::Aborted {
@@ -164,11 +172,17 @@ mod tests {
);
// 超时一族必须保留 stream_timeout 标记,否则 pool stream timeout 效果丢失。
let first_event_timeout =
attempt_facts_for_outcome(None, AttemptClientDelivery::Complete, ResponsesWebSocketTurnOutcome::first_event_timeout());
let first_event_timeout = attempt_facts_for_outcome(
None,
AttemptClientDelivery::Complete,
ResponsesWebSocketTurnOutcome::first_event_timeout(),
);
assert!(first_event_timeout.provider.stream_timeout());
let terminal_timeout =
attempt_facts_for_outcome(None, AttemptClientDelivery::Complete, ResponsesWebSocketTurnOutcome::terminal_timeout());
let terminal_timeout = attempt_facts_for_outcome(
None,
AttemptClientDelivery::Complete,
ResponsesWebSocketTurnOutcome::terminal_timeout(),
);
assert!(terminal_timeout.provider.stream_timeout());
// 非 504 的失败不得被当成流式超时。
assert!(!attempt_facts_for_outcome(
@@ -192,7 +206,6 @@ mod tests {
.stream_timeout());
}
/// `Cancelled` 不携带 provider 信息,已观察到的终态不能被它覆盖;
/// `ProviderTerminal` / `Failure` 本身就是权威的 provider 事实。
#[test]
@@ -220,12 +233,14 @@ mod tests {
);
assert_eq!(
facts.provider,
aborted(502, "upstream WebSocket closed before provider terminal event")
aborted(
502,
"upstream WebSocket closed before provider terminal event"
)
);
assert_eq!(facts.delivery, AttemptClientDelivery::Complete);
}
/// 结算信号的选择:provider 终态已到达就用它,否则才是 client 断开。
/// 这是修正的核心——旧实现无条件用 client_disconnected() 覆盖,
/// 于是已完成的响应被记成 void billing。
@@ -245,14 +260,13 @@ mod tests {
);
}
/// 明确记录的投递失败不会被结算信号推出的「投递成功」覆盖。
#[test]
fn a_recorded_delivery_failure_survives_a_provider_terminal_settle_signal() {
let facts = attempt_facts_for_outcome(
Some(terminal(200)),
AttemptClientDelivery::Aborted {
reason: "write failed"
reason: "write failed",
},
ResponsesWebSocketTurnOutcome::ProviderTerminal {
status_code: 200,
@@ -104,4 +104,3 @@ impl ExhaustedResponsesWebSocketExclusions {
.retain(|_, expires_at| *expires_at > now_unix_secs);
}
}
@@ -35,11 +35,6 @@ use super::admission::ResponsesWebSocketTurnAdmission;
use super::frame::ParsedResponsesWebSocketFrame;
use super::observation::ResponsesStructuredTerminalObserver;
use super::settlement::attempt_facts_for_outcome;
use crate::execution_runtime::attempt_lifecycle::{
attempt_billing_is_void, AttemptBodyCapture, AttemptClientDelivery, AttemptLifecycleSeed,
AttemptProviderOutcome, AttemptStageGuard, AttemptTerminalFacts, AttemptTerminalFactsInput,
ExecutionAttemptLifecycle,
};
use crate::ai_serving::{build_openai_responses_stream_plan_from_decision, AiExecutionDecision};
use crate::clock::current_unix_ms;
use crate::control::{
@@ -47,6 +42,11 @@ use crate::control::{
request_model_local_rejection, GatewayControlDecision, GatewayLocalAuthRejection,
};
use crate::execution_runtime::attach_provider_response_headers_to_report_context;
use crate::execution_runtime::attempt_lifecycle::{
attempt_billing_is_void, AttemptBodyCapture, AttemptClientDelivery, AttemptLifecycleSeed,
AttemptProviderOutcome, AttemptStageGuard, AttemptTerminalFacts, AttemptTerminalFactsInput,
ExecutionAttemptLifecycle,
};
use crate::orchestration::{
apply_local_stream_failure_effects, apply_local_stream_success_effects,
release_local_pool_key_lease, release_pool_key_lease_from_report_context,
@@ -599,11 +599,9 @@ impl ResponsesProviderAttempt {
if let Some(outcome) = provider_terminal_outcome(frame) {
// provider 的终态是独立事实:先记下来,之后即使客户端投递失败、
// 结算信号变成 Cancelled,这条事实也不会被擦掉。
self.provider_outcome
.get_or_insert(
attempt_facts_for_outcome(None, AttemptClientDelivery::Complete, outcome)
.provider,
);
self.provider_outcome.get_or_insert(
attempt_facts_for_outcome(None, AttemptClientDelivery::Complete, outcome).provider,
);
return Some(ResponsesWebSocketTurnObservation::Terminal(outcome));
}
if frame.is_started() {
@@ -668,8 +666,7 @@ impl ResponsesProviderAttempt {
/// execution report)由共享的 [`ExecutionAttemptLifecycle::settle`] 负责,
/// 这里只提供 WS 观察到的终态事实。
async fn settle(mut self, state: &AppState, outcome: ResponsesWebSocketTurnOutcome) {
let facts =
attempt_facts_for_outcome(self.provider_outcome, self.client_delivery, outcome);
let facts = attempt_facts_for_outcome(self.provider_outcome, self.client_delivery, outcome);
if let Some(reason) = facts.delivery.aborted_reason() {
let report_context = attach_client_delivery_to_report_context(
self.lifecycle.take_report_context(),
@@ -959,17 +956,16 @@ mod tests {
use super::super::settlement::{
attempt_facts_for_outcome, settle_signal_for_client_delivery_failure,
};
use super::{
attach_client_delivery_to_report_context, prepare_websocket_report_context,
provider_terminal_outcome, resolve_responses_websocket_turn_timeouts,
websocket_event_as_sse_line, ResponsesWebSocketTurnDeadline, ResponsesWebSocketTurnOutcome,
ResponsesWebSocketTurnTimeoutPhase,
};
use crate::execution_runtime::attempt_lifecycle::{
classify_attempt_settlement, AttemptBilling, AttemptCandidateError, AttemptCandidateStatus,
AttemptClientDelivery, AttemptProviderEffect, AttemptSettlementInputs,
};
use super::{
attach_client_delivery_to_report_context, prepare_websocket_report_context,
provider_terminal_outcome,
resolve_responses_websocket_turn_timeouts, websocket_event_as_sse_line,
ResponsesWebSocketTurnDeadline, ResponsesWebSocketTurnOutcome,
ResponsesWebSocketTurnTimeoutPhase,
};
#[test]
fn followup_context_uses_a_fresh_request_and_candidate() {
@@ -1194,7 +1190,10 @@ mod tests {
reason: "gateway could not relay the provider event to the client",
};
let signal = settle_signal_for_client_delivery_failure(Some(observed));
assert_eq!(signal, observed, "a reached terminal must remain the signal");
assert_eq!(
signal, observed,
"a reached terminal must remain the signal"
);
let facts = attempt_facts_for_outcome(Some(recorded_provider), delivery, signal);
@@ -1223,10 +1222,7 @@ mod tests {
});
assert_eq!(settlement.billing, AttemptBilling::Billed);
assert_eq!(settlement.status_code, 200);
assert_eq!(
settlement.candidate_status,
AttemptCandidateStatus::Success
);
assert_eq!(settlement.candidate_status, AttemptCandidateStatus::Success);
assert_eq!(
settlement.provider_effect,
AttemptProviderEffect::ProviderSuccess
@@ -208,7 +208,11 @@ mod tests {
state.begin(logical(), FakeAttempt(1));
let detached = state.detach_attempt();
assert_eq!(detached, Some(FakeAttempt(1)), "the attempt is settled once");
assert_eq!(
detached,
Some(FakeAttempt(1)),
"the attempt is settled once"
);
assert!(matches!(state, ResponsesTurnState::Replanning { .. }));
// 结算已经发生,没有第二个 attempt 可交。
@@ -250,7 +254,9 @@ mod tests {
assert!(!state.accepts_new_response_create());
assert!(state.attempt().is_none());
assert_eq!(
state.logical().map(|logical| logical.logical_turn_id.clone()),
state
.logical()
.map(|logical| logical.logical_turn_id.clone()),
Some("logical-turn".to_string())
);
// 幂等:已经没有 attempt 了,再取一次不会伪造一个出来。
@@ -24,9 +24,7 @@ const DEFAULT_UPSTREAM_HANDSHAKE_DEADLINE_MS: u64 = 30_000;
/// 从 decision.timeouts 推导实际 handshake 绝对 deadline。
/// 取 first_byte_ms / total_ms / DEFAULT 三者中的最小正值。
pub(super) fn resolve_upstream_handshake_deadline(
decision: &AiExecutionDecision,
) -> Duration {
pub(super) fn resolve_upstream_handshake_deadline(decision: &AiExecutionDecision) -> Duration {
let mut deadline_ms = DEFAULT_UPSTREAM_HANDSHAKE_DEADLINE_MS;
if let Some(timeouts) = decision.timeouts.as_ref() {
if let Some(first_byte_ms) = timeouts.first_byte_ms.filter(|v| *v > 0) {
@@ -48,12 +46,10 @@ pub(super) async fn bind_responses_upstream(
// 绝对 deadline:从此刻起必须在限定时间内完成握手 + 首条事件发送,
// 防止慢 TLS / 慢 HTTP Upgrade 无限占用 connection permit。
let handshake_deadline = resolve_upstream_handshake_deadline(decision);
tokio::time::timeout(handshake_deadline, bind_responses_upstream_inner(
decision,
normalization,
initial_event,
adapter,
))
tokio::time::timeout(
handshake_deadline,
bind_responses_upstream_inner(decision, normalization, initial_event, adapter),
)
.await
.map_err(|_| "responses_websocket_upstream_handshake_timeout")?
}
@@ -2728,7 +2728,10 @@ mod structured_entry_tests {
assert_entries_agree("unknown events", &events);
let summary = summary_via_push_event(&events);
assert!(summary.observed_finish);
assert!(summary.unknown_event_count > 0, "unknown events are counted");
assert!(
summary.unknown_event_count > 0,
"unknown events are counted"
);
}
/// 供应商声明的 service tier 通过两条入口都要落到摘要上。
@@ -268,7 +268,9 @@ async fn provider_quota_exhaustion_transparently_retries_onto_another_key() -> R
// 客户端只应该看到重试之后那次成功的响应,看不到 429。
let completed = receive_event(&mut client, "response.completed").await?;
assert_eq!(
completed.pointer("/response/status").and_then(Value::as_str),
completed
.pointer("/response/status")
.and_then(Value::as_str),
Some("completed")
);
@@ -832,8 +834,8 @@ async fn run_mock_upstream(
}
UpstreamBehavior::QuotaExhaustedThenComplete => {
if turn == 1 {
let _ = send_mock_event(&mut socket, codex_quota_exhausted_error())
.await;
let _ =
send_mock_event(&mut socket, codex_quota_exhausted_error()).await;
break;
}
if send_mock_turn(&mut socket, &response_id).await.is_err() {