refactor: extract provider pool abstractions

This commit is contained in:
fawney19
2026-05-13 18:19:15 +08:00
parent 3c2497f019
commit 5d1460e051
55 changed files with 3469 additions and 2184 deletions

View File

@@ -12,6 +12,7 @@ aether-billing.workspace = true
aether-contracts.workspace = true
aether-data.workspace = true
aether-data-contracts.workspace = true
aether-provider-pool.workspace = true
axum.workspace = true
base64.workspace = true
chrono.workspace = true

View File

@@ -92,180 +92,11 @@ fn admin_pool_reason_indicates_ban(reason: &str) -> bool {
.any(|hint| normalized.contains(hint))
}
fn admin_pool_metadata_bucket<'a>(
upstream_metadata: Option<&'a Value>,
provider_type: &str,
) -> Option<&'a serde_json::Map<String, Value>> {
upstream_metadata
.and_then(Value::as_object)
.and_then(|metadata| metadata.get(&provider_type.trim().to_ascii_lowercase()))
.and_then(Value::as_object)
}
fn admin_pool_json_bool(value: Option<&Value>) -> Option<bool> {
match value {
Some(Value::Bool(value)) => Some(*value),
Some(Value::String(value)) => match value.trim().to_ascii_lowercase().as_str() {
"true" | "1" => Some(true),
"false" | "0" => Some(false),
_ => None,
},
_ => None,
}
}
fn admin_pool_json_f64(value: Option<&Value>) -> Option<f64> {
match value {
Some(Value::Number(number)) => number.as_f64(),
Some(Value::String(value)) => value.trim().parse::<f64>().ok(),
_ => None,
}
.filter(|value| value.is_finite())
}
fn admin_pool_quota_snapshot_matches_provider(
quota_snapshot: &serde_json::Map<String, Value>,
provider_type: &str,
) -> bool {
let normalized_provider_type = provider_type.trim().to_ascii_lowercase();
match quota_snapshot
.get("provider_type")
.and_then(Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
{
Some(provider_type) => provider_type.eq_ignore_ascii_case(&normalized_provider_type),
None => {
admin_pool_json_bool(quota_snapshot.get("exhausted")) == Some(true)
|| quota_snapshot
.get("code")
.and_then(Value::as_str)
.is_some_and(|code| !code.trim().eq_ignore_ascii_case("unknown"))
|| quota_snapshot
.get("updated_at")
.is_some_and(|value| !value.is_null())
|| quota_snapshot
.get("observed_at")
.is_some_and(|value| !value.is_null())
|| quota_snapshot
.get("usage_ratio")
.is_some_and(|value| !value.is_null())
|| quota_snapshot
.get("reset_seconds")
.is_some_and(|value| !value.is_null())
|| quota_snapshot
.get("windows")
.and_then(Value::as_array)
.is_some_and(|windows| !windows.is_empty())
|| quota_snapshot
.get("credits")
.and_then(Value::as_object)
.is_some_and(|credits| !credits.is_empty())
}
}
}
fn admin_pool_key_quota_snapshot<'a>(
key: &'a StoredProviderCatalogKey,
provider_type: &str,
) -> Option<&'a serde_json::Map<String, Value>> {
let quota_snapshot = key
.status_snapshot
.as_ref()
.and_then(Value::as_object)
.and_then(|snapshot| snapshot.get("quota"))
.and_then(Value::as_object)?;
admin_pool_quota_snapshot_matches_provider(quota_snapshot, provider_type)
.then_some(quota_snapshot)
}
pub fn admin_pool_key_account_quota_exhausted(
key: &StoredProviderCatalogKey,
provider_type: &str,
) -> bool {
if let Some(exhausted) =
admin_pool_key_quota_snapshot(key, provider_type).and_then(|quota_snapshot| {
let exhausted = admin_pool_json_bool(quota_snapshot.get("exhausted"))?;
if exhausted {
let windows_max_ratio = quota_snapshot
.get("windows")
.and_then(Value::as_array)
.filter(|w| !w.is_empty())
.and_then(|windows| {
windows
.iter()
.filter_map(Value::as_object)
.filter_map(|w| w.get("used_ratio"))
.filter_map(Value::as_f64)
.max_by(f64::total_cmp)
});
if windows_max_ratio.is_some_and(|ratio| ratio < 1.0 - 1e-6) {
return Some(false);
}
}
Some(exhausted)
})
{
return exhausted;
}
let provider_type = provider_type.trim().to_ascii_lowercase();
let Some(bucket) = admin_pool_metadata_bucket(key.upstream_metadata.as_ref(), &provider_type)
else {
return false;
};
match provider_type.as_str() {
"codex" => {
if admin_pool_json_bool(bucket.get("credits_unlimited")) == Some(true) {
return false;
}
let has_window_data = admin_pool_json_f64(bucket.get("primary_used_percent")).is_some()
|| admin_pool_json_f64(bucket.get("secondary_used_percent")).is_some();
if !has_window_data && admin_pool_json_bool(bucket.get("has_credits")) == Some(false) {
return true;
}
admin_pool_json_f64(bucket.get("primary_used_percent"))
.is_some_and(|value| value >= 100.0)
|| admin_pool_json_f64(bucket.get("secondary_used_percent"))
.is_some_and(|value| value >= 100.0)
}
"kiro" => {
if admin_pool_json_f64(bucket.get("remaining")).is_some_and(|value| value <= 0.0) {
return true;
}
if admin_pool_json_f64(bucket.get("usage_percentage"))
.is_some_and(|value| value >= 100.0)
{
return true;
}
match (
admin_pool_json_f64(bucket.get("usage_limit")),
admin_pool_json_f64(bucket.get("current_usage")),
) {
(Some(limit), Some(current)) if limit > 0.0 => current >= limit,
_ => false,
}
}
"chatgpt_web" => {
if admin_pool_json_bool(bucket.get("image_quota_blocked")) == Some(true) {
return true;
}
if admin_pool_json_f64(bucket.get("image_quota_remaining"))
.is_some_and(|value| value <= 0.0)
{
return true;
}
match (
admin_pool_json_f64(bucket.get("image_quota_total")),
admin_pool_json_f64(bucket.get("image_quota_used")),
) {
(Some(limit), Some(used)) if limit > 0.0 => used >= limit,
_ => false,
}
}
_ => false,
}
aether_provider_pool::provider_pool_key_account_quota_exhausted(key, provider_type)
}
fn admin_pool_has_proxy(key: &StoredProviderCatalogKey) -> bool {
@@ -937,148 +768,7 @@ pub fn build_admin_pool_key_payload(
}
pub fn build_admin_pool_scheduling_presets_payload() -> Value {
json!([
{
"name": "lru",
"label": "LRU 轮转",
"description": "最久未使用的 Key 优先",
"providers": [],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": "distribution_mode",
"evidence_hint": "依据 LRU 时间戳(最近未使用优先)",
},
{
"name": "cache_affinity",
"label": "缓存亲和",
"description": "优先复用最近使用过的 Key利用 Prompt Caching",
"providers": [],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": "distribution_mode",
"evidence_hint": "依据 LRU 时间戳(最近使用优先,与 LRU 轮转相反)",
},
{
"name": "cost_first",
"label": "成本优先",
"description": "优先选择窗口消耗更低的账号",
"providers": [],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据窗口成本/Token 用量,缺失时回退配额使用率",
},
{
"name": "free_first",
"label": "Free 优先",
"description": "优先消耗 Free 账号(依赖 plan_type",
"providers": ["codex", "kiro"],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据 plan_typeFree 账号优先调度)",
},
{
"name": "health_first",
"label": "健康优先",
"description": "优先选择健康分更高、失败更少的账号",
"providers": [],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据 health_by_format 聚合分(含熔断/失败衰减)",
},
{
"name": "latency_first",
"label": "延迟优先",
"description": "优先选择最近延迟更低的账号",
"providers": [],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据号池延迟窗口均值latency_window_seconds",
},
{
"name": "load_balance",
"label": "负载均衡",
"description": "随机分散 Key 使用,均匀分摊负载",
"providers": [],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": "distribution_mode",
"evidence_hint": "每次随机分值,实现完全均匀分散",
},
{
"name": "plus_first",
"label": "Plus 优先",
"description": "优先消耗 Plus 账号(依赖 plan_type",
"providers": ["codex", "kiro"],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据 plan_typePlus 账号优先调度)",
},
{
"name": "pro_first",
"label": "Pro 优先",
"description": "优先消耗 Pro 账号(依赖 plan_type",
"providers": ["codex", "kiro"],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据 plan_typePro 账号优先调度)",
},
{
"name": "priority_first",
"label": "优先级优先",
"description": "按账号优先级顺序调度(数字越小越优先)",
"providers": [],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据 internal_priority支持拖拽/手工编辑)",
},
{
"name": "quota_balanced",
"label": "额度平均",
"description": "优先选额度消耗最少的账号",
"providers": [],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据账号配额使用率;无配额时回退到窗口成本使用",
},
{
"name": "recent_refresh",
"label": "额度刷新优先",
"description": "优先选即将刷新额度的账号",
"providers": ["codex", "kiro"],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据账号额度重置倒计时next_reset / reset_seconds",
},
{
"name": "single_account",
"label": "单号优先",
"description": "集中使用同一账号(反向 LRU",
"providers": [],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": "distribution_mode",
"evidence_hint": "先按账号优先级internal_priority同级再按反向 LRU 集中",
},
{
"name": "team_first",
"label": "Team 优先",
"description": "优先消耗 Team 账号(依赖 plan_type",
"providers": ["codex", "kiro"],
"modes": Value::Null,
"default_mode": Value::Null,
"mutex_group": Value::Null,
"evidence_hint": "依据 plan_typeTeam 账号优先调度)",
}
])
aether_provider_pool::build_admin_pool_scheduling_presets_payload()
}
pub fn admin_pool_batch_delete_task_parts(request_path: &str) -> Option<(String, String)> {