Add provider key cycle stats reset handling

This commit is contained in:
fawney19
2026-05-07 03:23:20 +08:00
parent 6c0ac2e8da
commit 10e679bb2f
35 changed files with 1443 additions and 273 deletions

View File

@@ -136,7 +136,7 @@ fn classify_block_reason(reason: &str) -> (&'static str, &'static str) {
.iter()
.any(|keyword| lowered.contains(keyword))
{
return ("oauth_expired", "Token 失效");
return ("oauth_token_invalid", "Token 失效");
}
if looks_like_account_verification(reason) {
return ("account_verification", "需要验证");
@@ -344,23 +344,23 @@ fn resolve_from_oauth_invalid_reason(reason: Option<&str>) -> Option<PoolAccount
.unwrap_or_else(|| "OAuth Token 已过期且无法续期".to_string());
return Some(PoolAccountState {
blocked: true,
code: Some("oauth_expired".to_string()),
code: Some("oauth_token_invalid".to_string()),
label: Some("Token 失效".to_string()),
reason: Some(cleaned),
source: Some("oauth_invalid".to_string()),
recoverable: true,
recoverable: false,
});
}
if text.starts_with(OAUTH_REFRESH_FAILED_PREFIX) {
let cleaned = clean_text(Some(text.trim_start_matches(OAUTH_REFRESH_FAILED_PREFIX)))
.unwrap_or_else(|| "OAuth Token 续期失败".to_string());
return Some(PoolAccountState {
blocked: false,
code: Some("oauth_refresh_failed".to_string()),
label: Some("续期失败".to_string()),
blocked: true,
code: Some("oauth_token_invalid".to_string()),
label: Some("Token 失效".to_string()),
reason: Some(cleaned),
source: Some("oauth_refresh".to_string()),
recoverable: true,
recoverable: false,
});
}
if text.starts_with(OAUTH_REQUEST_FAILED_PREFIX) {
@@ -446,6 +446,38 @@ pub fn resolve_account_status_snapshot(
};
}
if let Some(cleaned) = tagged_reason(&text, "OAUTH_EXPIRED") {
let reason = if cleaned.is_empty() {
"OAuth Token 已过期且无法续期".to_string()
} else {
cleaned
};
return AccountStatusSnapshot {
code: "oauth_token_invalid".to_string(),
label: Some("Token 失效".to_string()),
reason: Some(reason),
blocked: true,
source: Some("oauth_invalid".to_string()),
recoverable: false,
};
}
if let Some(cleaned) = tagged_reason(&text, "REFRESH_FAILED") {
let reason = if cleaned.is_empty() {
"OAuth Token 续期失败".to_string()
} else {
cleaned
};
return AccountStatusSnapshot {
code: "oauth_token_invalid".to_string(),
label: Some("Token 失效".to_string()),
reason: Some(reason),
blocked: true,
source: Some("oauth_refresh".to_string()),
recoverable: false,
};
}
if text.starts_with('[') {
return AccountStatusSnapshot::default();
}
@@ -546,29 +578,46 @@ mod tests {
}
#[test]
fn resolves_refresh_failed_as_recoverable_pool_state() {
fn resolves_refresh_failed_as_token_invalid_pool_state() {
let state = resolve_pool_account_state(
Some("codex"),
None,
Some("[REFRESH_FAILED] Token 续期失败 (401): refresh_token 已失效"),
);
assert!(!state.blocked);
assert!(state.recoverable);
assert_eq!(state.code.as_deref(), Some("oauth_refresh_failed"));
assert!(state.blocked);
assert!(!state.recoverable);
assert_eq!(state.code.as_deref(), Some("oauth_token_invalid"));
assert_eq!(state.label.as_deref(), Some("Token 失效"));
assert!(!should_auto_remove_account_state(&state));
}
#[test]
fn account_snapshot_ignores_refresh_failed_reason() {
fn account_snapshot_marks_refresh_failed_as_token_invalid() {
let snapshot = resolve_account_status_snapshot(
Some("codex"),
None,
Some("[REFRESH_FAILED] Token 续期失败 (401): refresh_token 已失效"),
);
assert_eq!(snapshot.code, "ok");
assert!(!snapshot.blocked);
assert_eq!(snapshot.code, "oauth_token_invalid");
assert_eq!(snapshot.label.as_deref(), Some("Token 失效"));
assert!(snapshot.blocked);
assert!(!snapshot.recoverable);
}
#[test]
fn account_snapshot_marks_oauth_expired_as_token_invalid() {
let snapshot = resolve_account_status_snapshot(
Some("codex"),
None,
Some("[OAUTH_EXPIRED] Codex Token 无效或已过期 (401)"),
);
assert_eq!(snapshot.code, "oauth_token_invalid");
assert_eq!(snapshot.label.as_deref(), Some("Token 失效"));
assert!(snapshot.blocked);
assert!(!snapshot.recoverable);
}
#[test]