mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-04 08:27:46 +08:00
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:
@@ -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()
|
||||
|
||||
@@ -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 轮号"}
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user