mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-09 04:30:20 +08:00
Merge pull request #770 from zhefox/main
fix(pool): show Antigravity quota reset times
This commit is contained in:
@@ -443,7 +443,18 @@ fn provider_quota_metadata_bucket<'a>(
|
||||
fn provider_quota_timestamp_unix_secs(value: Option<&Value>) -> Option<u64> {
|
||||
let mut parsed = match value {
|
||||
Some(Value::Number(number)) => number.as_f64(),
|
||||
Some(Value::String(text)) => text.trim().parse::<f64>().ok(),
|
||||
Some(Value::String(text)) => {
|
||||
let text = text.trim();
|
||||
if let Ok(timestamp) = text.parse::<f64>() {
|
||||
Some(timestamp)
|
||||
} else {
|
||||
return chrono::DateTime::parse_from_rfc3339(text)
|
||||
.ok()?
|
||||
.timestamp()
|
||||
.try_into()
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}?;
|
||||
if !parsed.is_finite() || parsed <= 0.0 {
|
||||
@@ -560,7 +571,10 @@ fn model_quota_window_snapshot(
|
||||
.map(|value| value.clamp(0.0, 1.0))
|
||||
.or_else(|| used_ratio.map(|value| (1.0 - value).max(0.0)));
|
||||
let reset_at = provider_quota_timestamp_unix_secs(
|
||||
item.get("reset_at").or_else(|| item.get("next_reset_at")),
|
||||
item.get("reset_at")
|
||||
.or_else(|| item.get("next_reset_at"))
|
||||
.or_else(|| item.get("reset_time"))
|
||||
.or_else(|| item.get("next_reset_time")),
|
||||
);
|
||||
let reset_seconds = quota_window_reset_seconds(observed_at_unix_secs, reset_at);
|
||||
let is_exhausted = item
|
||||
@@ -4083,7 +4097,8 @@ mod tests {
|
||||
},
|
||||
"claude-sonnet-4-6": {
|
||||
"display_name": "Claude Sonnet 4.6 (Thinking)",
|
||||
"remaining_fraction": 0.3
|
||||
"remaining_fraction": 0.3,
|
||||
"reset_time": "2026-04-07T12:34:56Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4128,6 +4143,16 @@ mod tests {
|
||||
label_for_model("claude-sonnet-4-6"),
|
||||
Some(json!("Claude Sonnet 4.6 (Thinking)"))
|
||||
);
|
||||
let claude_window = windows
|
||||
.iter()
|
||||
.filter_map(Value::as_object)
|
||||
.find(|window| window.get("model") == Some(&json!("claude-sonnet-4-6")))
|
||||
.expect("Claude quota window should exist");
|
||||
assert_eq!(
|
||||
claude_window.get("reset_at"),
|
||||
Some(&json!(1_775_565_296u64))
|
||||
);
|
||||
assert_eq!(claude_window.get("reset_seconds"), Some(&json!(12_011u64)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -6753,6 +6753,10 @@ mod tests {
|
||||
["display_name"],
|
||||
json!("Key-1")
|
||||
);
|
||||
assert_eq!(
|
||||
parsed["models"]["RateLimitResetCredit_05cbb6eeeb9c81918e011d8300f9ebfb"]["reset_time"],
|
||||
json!("2030-01-01T00:00:00Z")
|
||||
);
|
||||
assert_eq!(
|
||||
parsed["models"]["gemini-3-pro-preview"]["display_name"],
|
||||
json!("Gemini 3 Pro Preview")
|
||||
|
||||
@@ -99,7 +99,7 @@ describe('pool key display panels', () => {
|
||||
label: 'Gemini额度',
|
||||
remainingPercent: 90.6,
|
||||
resetText: '1h 后重置',
|
||||
meterText: '90.6–100',
|
||||
meterText: '90.6%–100%',
|
||||
barClass: 'bg-emerald-500',
|
||||
meterClass: 'text-emerald-600',
|
||||
},
|
||||
@@ -107,7 +107,7 @@ describe('pool key display panels', () => {
|
||||
label: 'Claude额度',
|
||||
remainingPercent: 100,
|
||||
resetText: '1h 后重置',
|
||||
meterText: '100',
|
||||
meterText: '100%',
|
||||
barClass: 'bg-emerald-500',
|
||||
meterClass: 'text-emerald-600',
|
||||
},
|
||||
@@ -121,8 +121,12 @@ describe('pool key display panels', () => {
|
||||
'Gemini额度',
|
||||
'Claude额度',
|
||||
])
|
||||
expect(Array.from(root.querySelectorAll('[data-testid="pool-quota-meter-text"]')).map(node => node.textContent)).toEqual(['90.6–100', '100'])
|
||||
expect(Array.from(root.querySelectorAll('[data-testid="pool-quota-meter-text"]')).map(node => node.textContent)).toEqual(['90.6%–100%', '100%'])
|
||||
expect(root.querySelectorAll('[data-testid="pool-quota-progress-track"]')).toHaveLength(2)
|
||||
expect(Array.from(root.querySelectorAll('[data-testid="pool-quota-reset-text"]')).map(node => node.textContent)).toEqual([
|
||||
'1h 后重置',
|
||||
'1h 后重置',
|
||||
])
|
||||
|
||||
app.unmount()
|
||||
root.remove()
|
||||
|
||||
@@ -15,9 +15,10 @@ describe('summarizeAntigravityQuotaItems', () => {
|
||||
])
|
||||
|
||||
expect(items.map(item => [item.label, item.remainingPercent, item.detail])).toEqual([
|
||||
['Gemini额度', 90.6, '90.6–95'],
|
||||
['Claude额度', 82, '82–100'],
|
||||
['Gemini额度', 90.6, '90.6%–95%'],
|
||||
['Claude额度', 82, '82%–100%'],
|
||||
])
|
||||
expect(items.map(item => item.resetSeconds)).toEqual([180, 120])
|
||||
expect(items[1]?.model).toBe('claude-sonnet-4-6')
|
||||
})
|
||||
})
|
||||
@@ -158,5 +158,6 @@ export function summarizeAntigravityQuotaItems<T extends AntigravityQuotaSortabl
|
||||
|
||||
function formatAntigravityQuotaValue(value: number): string {
|
||||
const rounded = Math.round(value)
|
||||
return Math.abs(value - rounded) < 1e-6 ? String(rounded) : value.toFixed(1)
|
||||
const formatted = Math.abs(value - rounded) < 1e-6 ? String(rounded) : value.toFixed(1)
|
||||
return `${formatted}%`
|
||||
}
|
||||
|
||||
@@ -3883,12 +3883,6 @@ function buildQuotaProgressItemsFromSnapshot(key: PoolKeyDetail): QuotaProgressI
|
||||
}
|
||||
})
|
||||
.filter((item): item is QuotaProgressItem & { model: string, resetSeconds: number | null } => item != null)))
|
||||
.map(item => ({
|
||||
...item,
|
||||
resetAtSeconds: null,
|
||||
resetSeconds: null,
|
||||
allowDynamicReset: false,
|
||||
}))
|
||||
}
|
||||
|
||||
if (providerType === 'gemini_cli') {
|
||||
|
||||
Reference in New Issue
Block a user