fix(providers): refresh Antigravity grouped quotas

This commit is contained in:
ZheFox
2026-09-03 10:46:44 +08:00
parent cc6f5e89b6
commit 45c840b8d3
20 changed files with 976 additions and 103 deletions
@@ -45,11 +45,11 @@
<div class="py-2">
<div
v-if="items.length > 0"
v-if="displayItems.length > 0"
class="grid grid-cols-2 gap-3"
>
<div
v-for="item in items"
v-for="item in displayItems"
:key="item.model"
>
<div class="flex items-center justify-between text-[10px] mb-0.5">
@@ -238,6 +238,48 @@ function buildItemsFromQuotaSnapshot(quota: QuotaStatusSnapshot | null | undefin
return dedupeAntigravityQuotaItemsByLabel(items)
}
function buildGroupedItemsFromQuotaSnapshot(
quota: QuotaStatusSnapshot | null | undefined,
): QuotaItem[] {
if (!quota) return []
const providerType = String(quota.provider_type || '').trim().toLowerCase()
if (providerType && providerType !== 'antigravity') return []
const windows = Array.isArray(quota.windows)
? quota.windows.filter(window => String(window?.scope || '').trim().toLowerCase() === 'quota_group')
: []
return windows
.map((window) => {
const code = String(window.code || '').trim()
const label = String(window.label || code).trim()
if (!code || !label) return null
const usedPercent =
typeof window.used_ratio === 'number'
? Math.max(Math.min(window.used_ratio * 100, 100), 0)
: typeof window.remaining_ratio === 'number'
? Math.max(Math.min((1 - window.remaining_ratio) * 100, 100), 0)
: null
if (usedPercent == null) return null
const remainingPercent =
typeof window.remaining_ratio === 'number'
? Math.max(Math.min(window.remaining_ratio * 100, 100), 0)
: Math.max(100 - usedPercent, 0)
return {
model: code,
label,
usedPercent,
remainingPercent,
resetSeconds: getQuotaWindowLiveResetSeconds(quota, window),
} satisfies QuotaItem
})
.filter((item): item is QuotaItem => item !== null)
}
const rawItems = computed<QuotaItem[]>(() => {
const snapshotItems = buildItemsFromQuotaSnapshot(props.quotaSnapshot)
if (snapshotItems.length > 0) return snapshotItems
@@ -291,6 +333,8 @@ const rawItems = computed<QuotaItem[]>(() => {
})
const items = computed<QuotaItem[]>(() => summarizeAntigravityQuotaItems(rawItems.value))
const groupedItems = computed<QuotaItem[]>(() => buildGroupedItemsFromQuotaSnapshot(props.quotaSnapshot))
const displayItems = computed<QuotaItem[]>(() => [...groupedItems.value, ...items.value])
async function handleTestModel(modelName: string) {
if (!props.providerId || testingModel.value) return
@@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest'
import { createApp, defineComponent, h } from 'vue'
import AntigravityQuotaDialog from '@/features/providers/components/AntigravityQuotaDialog.vue'
import type { UpstreamMetadata } from '@/api/endpoints/types'
import type { QuotaStatusSnapshot, UpstreamMetadata } from '@/api/endpoints/types'
vi.mock('@/components/ui', async () => {
const { defineComponent, h } = await import('vue')
@@ -77,7 +77,7 @@ vi.mock('@/utils/errorParser', () => ({
parseApiError: (value: unknown) => String(value),
}))
function mount(metadata: UpstreamMetadata) {
function mount(metadata: UpstreamMetadata, quotaSnapshot?: QuotaStatusSnapshot) {
const root = document.createElement('div')
document.body.appendChild(root)
@@ -86,6 +86,7 @@ function mount(metadata: UpstreamMetadata) {
return () => h(AntigravityQuotaDialog, {
open: true,
metadata,
quotaSnapshot,
keyName: 'Key-1',
})
},
@@ -102,6 +103,35 @@ function mount(metadata: UpstreamMetadata) {
}
describe('AntigravityQuotaDialog', () => {
it('renders grouped five-hour and weekly quota windows', () => {
const { root, unmount } = mount({}, {
code: 'ok',
provider_type: 'antigravity',
exhausted: false,
windows: [{
code: 'group:0:3p-5h',
label: 'Claude and GPT models · 5 hour',
scope: 'quota_group',
used_ratio: 0.75,
remaining_ratio: 0.25,
}, {
code: 'group:0:3p-weekly',
label: 'Claude and GPT models · weekly',
scope: 'quota_group',
used_ratio: 0.2,
remaining_ratio: 0.8,
}],
})
const text = root.textContent || ''
expect(text).toContain('Claude and GPT models · 5 hour')
expect(text).toContain('25.0%')
expect(text).toContain('Claude and GPT models · weekly')
expect(text).toContain('80.0%')
unmount()
})
it('hides quota buckets outside the shared pool summary families', () => {
const rawIdentifier = 'RateLimitResetCredit_05cbb6eeeb9c81918e011d8300f9ebfb'
const { root, unmount } = mount({