Merge remote-tracking branch 'zhefox/main' into zhefox-main

# Conflicts:
#	crates/aether-admin/src/provider/quota.rs
#	crates/aether-ai/formats/src/formats/openai/chat/stream.rs
#	crates/aether-ai/formats/src/formats/openai/responses/mod.rs
#	crates/aether-provider/pool/src/provider.rs
#	crates/aether-provider/pool/src/quota.rs
This commit is contained in:
zhefox
2026-09-02 15:25:27 +08:00
229 changed files with 51071 additions and 896 deletions
+93
View File
@@ -846,6 +846,99 @@ mod tests {
assert!(provider_pool_key_account_quota_exhausted(&active, "codex"));
}
#[test]
fn antigravity_model_quota_exhaustion_does_not_block_other_models() {
let service = ProviderPoolService::with_builtin_adapters();
let mut key = sample_key(None);
key.status_snapshot = Some(json!({
"quota": {
"version": 2,
"provider_type": "antigravity",
"exhausted": false,
"windows": [
{
"code": "model:gemini-3.1-pro-high",
"scope": "model",
"model": "gemini-3.1-pro-high",
"used_ratio": 1.0,
"is_exhausted": true
},
{
"code": "model:gemini-3-flash-agent",
"scope": "model",
"model": "gemini-3-flash-agent",
"used_ratio": 0.1,
"is_exhausted": false
}
]
}
}));
let exhausted =
service.member_signals("antigravity", &key, None, Some("gemini-3.1-pro-high"));
let available =
service.member_signals("antigravity", &key, None, Some("gemini-3-flash-agent"));
assert!(exhausted.quota_exhausted);
assert!(!available.quota_exhausted);
}
#[test]
fn codex_standard_and_spark_quota_families_are_independent() {
let service = ProviderPoolService::with_builtin_adapters();
let mut standard_exhausted = sample_key(None);
standard_exhausted.status_snapshot = Some(json!({
"quota": {
"version": 2,
"provider_type": "codex",
"exhausted": true,
"allowed": false,
"limit_reached": true,
"windows": [
{ "code": "weekly", "used_ratio": 1.0, "is_exhausted": true },
{ "code": "5h", "used_ratio": 0.5, "is_exhausted": false },
{ "code": "spark_weekly", "used_ratio": 0.2, "is_exhausted": false },
{ "code": "spark_5h", "used_ratio": 0.1, "is_exhausted": false }
]
}
}));
let standard =
service.member_signals("codex", &standard_exhausted, None, Some("gpt-5.3-codex"));
let spark = service.member_signals(
"codex",
&standard_exhausted,
None,
Some("gpt-5.3-codex-spark"),
);
assert!(standard.quota_exhausted);
assert!(!standard.quota_hard_blocked);
assert!(!spark.quota_exhausted);
assert!(!spark.quota_hard_blocked);
let mut spark_exhausted = sample_key(None);
spark_exhausted.status_snapshot = Some(json!({
"quota": {
"version": 2,
"provider_type": "codex",
"exhausted": false,
"windows": [
{ "code": "weekly", "used_ratio": 0.2, "is_exhausted": false },
{ "code": "5h", "used_ratio": 0.1, "is_exhausted": false },
{ "code": "spark_weekly", "used_ratio": 1.0, "is_exhausted": true },
{ "code": "spark_5h", "used_ratio": 0.4, "is_exhausted": false }
]
}
}));
let standard =
service.member_signals("codex", &spark_exhausted, None, Some("gpt-5.3-codex"));
let spark =
service.member_signals("codex", &spark_exhausted, None, Some("gpt-5.3-codex-spark"));
assert!(!standard.quota_exhausted);
assert!(spark.quota_exhausted);
}
#[test]
fn provider_quota_exhaustion_metadata_expires_after_reset_at() {
let now = std::time::SystemTime::now()
+44 -8
View File
@@ -94,14 +94,7 @@ pub fn build_admin_pool_scheduling_presets_payload() -> Value {
"依据 LRU 时间戳(最近未使用优先)",
&service,
),
provider_pool_preset_payload(
"cache_affinity",
"缓存亲和",
"优先复用最近使用过的 Key,利用 Prompt Caching",
None,
"依据 LRU 时间戳(最近使用优先,与 LRU 轮转相反)",
&service,
),
cache_affinity_preset_payload(&service),
provider_pool_preset_payload(
"cost_first",
"成本优先",
@@ -220,6 +213,23 @@ fn legacy_free_team_first_preset_payload(service: &ProviderPoolService) -> Value
payload
}
fn cache_affinity_preset_payload(service: &ProviderPoolService) -> Value {
let mut payload = provider_pool_preset_payload(
"cache_affinity",
"缓存亲和",
"同一用户持续复用 Key,首次分配可集中或轮转",
None,
"先复用用户粘性 Key,未命中时按所选二级模式分配",
service,
);
payload["modes"] = json!([
{"value": "single_account", "label": "单号优先"},
{"value": "lru", "label": "LRU 轮号"}
]);
payload["default_mode"] = json!("single_account");
payload
}
fn provider_pool_preset_payload(
name: &'static str,
label: &'static str,
@@ -274,3 +284,29 @@ fn provider_pool_preset_mutex_group(preset: &str) -> Option<&'static str> {
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::build_admin_pool_scheduling_presets_payload;
use serde_json::json;
#[test]
fn cache_affinity_preset_exposes_secondary_distribution_modes() {
let payload = build_admin_pool_scheduling_presets_payload();
let cache_affinity = payload
.as_array()
.expect("preset payload should be an array")
.iter()
.find(|preset| preset["name"] == "cache_affinity")
.expect("cache affinity preset should exist");
assert_eq!(cache_affinity["default_mode"], json!("single_account"));
assert_eq!(
cache_affinity["modes"],
json!([
{"value": "single_account", "label": "单号优先"},
{"value": "lru", "label": "LRU 轮号"}
])
);
}
}