fix(ai): harden responses replay and failure diagnostics

This commit is contained in:
elky
2026-07-30 17:19:54 +08:00
parent 1ab4f079c9
commit 050eb77508
29 changed files with 700 additions and 142 deletions
@@ -36,4 +36,5 @@ pub use types::{
UsageTimeSeriesQuery, UsageWriteRepository, PROVIDER_ACTUAL_SERVICE_TIER_METADATA_KEY,
PROVIDER_CACHE_TTL_MINUTES_METADATA_KEY, PROVIDER_REASONING_EFFORT_METADATA_KEY,
PROVIDER_SERVICE_TIER_METADATA_KEY, REQUESTED_REASONING_EFFORT_METADATA_KEY,
ROUTING_CANDIDATE_SKIP_REASON_METADATA_KEY, ROUTING_FAILURE_DIAGNOSTIC_METADATA_KEY,
};
@@ -7,6 +7,8 @@ pub const REQUESTED_REASONING_EFFORT_METADATA_KEY: &str = "requested_reasoning_e
pub const PROVIDER_SERVICE_TIER_METADATA_KEY: &str = "provider_service_tier";
pub const PROVIDER_ACTUAL_SERVICE_TIER_METADATA_KEY: &str = "provider_actual_service_tier";
pub const PROVIDER_CACHE_TTL_MINUTES_METADATA_KEY: &str = "provider_cache_ttl_minutes";
pub const ROUTING_CANDIDATE_SKIP_REASON_METADATA_KEY: &str = "routing_candidate_skip_reason";
pub const ROUTING_FAILURE_DIAGNOSTIC_METADATA_KEY: &str = "routing_failure_diagnostic";
pub fn extract_provider_reasoning_effort_from_body(value: Option<&Value>) -> Option<String> {
let object = value.and_then(Value::as_object)?;
@@ -827,6 +829,16 @@ impl StoredRequestUsageAudit {
.as_deref()
.or_else(|| self.request_metadata_string("local_execution_runtime_miss_reason"))
}
pub fn routing_candidate_skip_reason(&self) -> Option<&str> {
self.request_metadata_string(ROUTING_CANDIDATE_SKIP_REASON_METADATA_KEY)
}
pub fn routing_failure_diagnostic(&self) -> Option<&Value> {
self.request_metadata_object()
.and_then(|metadata| metadata.get(ROUTING_FAILURE_DIAGNOSTIC_METADATA_KEY))
.filter(|value| value.is_object())
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
@@ -2695,7 +2707,12 @@ mod tests {
"response_body_ref": "blob://legacy-response",
"client_response_body_ref": "blob://legacy-client-response",
"candidate_id": "cand-legacy",
"key_name": "primary-legacy"
"key_name": "primary-legacy",
"routing_candidate_skip_reason": "provider_request_body_build_failed",
"routing_failure_diagnostic": {
"path": "$.reasoning.summary",
"message": "invalid reasoning summary"
}
}));
assert_eq!(
@@ -2727,6 +2744,16 @@ mod tests {
usage.routing_local_execution_runtime_miss_reason(),
Some("all_candidates_skipped")
);
assert_eq!(
usage.routing_candidate_skip_reason(),
Some("provider_request_body_build_failed")
);
assert_eq!(
usage
.routing_failure_diagnostic()
.and_then(|diagnostic| diagnostic.get("path")),
Some(&json!("$.reasoning.summary"))
);
}
#[test]