mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-08 02:17:46 +08:00
完善 Antigravity 配额展示与 CI 断言
This commit is contained in:
@@ -120,6 +120,7 @@ import { useToast } from '@/composables/useToast'
|
||||
import { parseApiError } from '@/utils/errorParser'
|
||||
import {
|
||||
compareAntigravityQuotaItems,
|
||||
dedupeAntigravityQuotaItemsByLabel,
|
||||
resolveAntigravityQuotaLabel,
|
||||
} from '@/features/providers/utils/antigravityQuota'
|
||||
|
||||
@@ -232,7 +233,7 @@ function buildItemsFromQuotaSnapshot(quota: QuotaStatusSnapshot | null | undefin
|
||||
.filter((item): item is QuotaItem => item !== null)
|
||||
|
||||
items.sort(compareAntigravityQuotaItems)
|
||||
return items
|
||||
return dedupeAntigravityQuotaItemsByLabel(items)
|
||||
}
|
||||
|
||||
const items = computed<QuotaItem[]>(() => {
|
||||
@@ -284,7 +285,7 @@ const items = computed<QuotaItem[]>(() => {
|
||||
}
|
||||
|
||||
result.sort(compareAntigravityQuotaItems)
|
||||
return result
|
||||
return dedupeAntigravityQuotaItemsByLabel(result)
|
||||
})
|
||||
|
||||
async function handleTestModel(modelName: string) {
|
||||
|
||||
@@ -959,6 +959,7 @@ import ProviderQuotaSectionHeader from '@/features/providers/components/Provider
|
||||
import { useProxyNodesStore } from '@/stores/proxy-nodes'
|
||||
import {
|
||||
compareAntigravityQuotaItems,
|
||||
dedupeAntigravityQuotaItemsByLabel,
|
||||
resolveAntigravityQuotaLabel,
|
||||
} from '@/features/providers/utils/antigravityQuota'
|
||||
import {
|
||||
@@ -3418,7 +3419,7 @@ function getAntigravityQuotaItems(metadata: UpstreamMetadata | null | undefined)
|
||||
}
|
||||
|
||||
items.sort(compareAntigravityQuotaItems)
|
||||
return items
|
||||
return dedupeAntigravityQuotaItemsByLabel(items)
|
||||
}
|
||||
|
||||
function getAntigravityQuotaItemsFromSnapshot(key: EndpointAPIKey): AntigravityQuotaItem[] {
|
||||
@@ -3462,7 +3463,7 @@ function getAntigravityQuotaItemsFromSnapshot(key: EndpointAPIKey): AntigravityQ
|
||||
.filter((item): item is AntigravityQuotaItem => item !== null)
|
||||
|
||||
items.sort(compareAntigravityQuotaItems)
|
||||
return items
|
||||
return dedupeAntigravityQuotaItemsByLabel(items)
|
||||
}
|
||||
|
||||
const ANTIGRAVITY_QUOTA_PREVIEW_LIMIT = 6
|
||||
|
||||
+34
-2
@@ -164,12 +164,44 @@ describe('AntigravityQuotaDialog', () => {
|
||||
|
||||
expect(text).not.toContain('gemini-pro-agent')
|
||||
expect(text).not.toContain('claude-opus-4-6-thinking')
|
||||
expect(text.indexOf('Claude Opus 4.6 (Thinking)')).toBeLessThan(text.indexOf('Gemini 3.1 Pro (High)'))
|
||||
expect(text.indexOf('Gemini 3.1 Pro (High)')).toBeLessThan(text.indexOf('Gemini 3.5 Flash (High)'))
|
||||
expect(text.indexOf('Gemini 3.5 Flash (High)')).toBeLessThan(text.indexOf('Gemini 3.5 Flash (Medium)'))
|
||||
expect(text.indexOf('Gemini 3.5 Flash (Medium)')).toBeLessThan(text.indexOf('Claude Opus 4.6 (Thinking)'))
|
||||
expect(text.indexOf('Claude Opus 4.6 (Thinking)')).toBeLessThan(text.indexOf('Tab Flash Lite Preview'))
|
||||
expect(text.indexOf('Gemini 3.5 Flash (Medium)')).toBeLessThan(text.indexOf('Tab Flash Lite Preview'))
|
||||
expect(text.indexOf('Tab Flash Lite Preview')).toBeLessThan(text.indexOf('chat_20706'))
|
||||
|
||||
unmount()
|
||||
})
|
||||
|
||||
it('renders one row for duplicate quota labels and keeps the preferred active bucket', () => {
|
||||
const { root, unmount } = mount({
|
||||
antigravity: {
|
||||
quota_by_model: {
|
||||
'gemini-3.1-pro-high': {
|
||||
display_name: 'Gemini 3.1 Pro (High)',
|
||||
remaining_fraction: 0.95,
|
||||
used_percent: 5,
|
||||
},
|
||||
'gemini-pro-agent': {
|
||||
display_name: 'Gemini 3.1 Pro (High)',
|
||||
remaining_fraction: 0.4,
|
||||
used_percent: 60,
|
||||
},
|
||||
'gemini-3-flash-agent': {
|
||||
display_name: 'Gemini 3.5 Flash (High)',
|
||||
remaining_fraction: 0.9,
|
||||
used_percent: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
const text = root.textContent || ''
|
||||
|
||||
expect(text.match(/Gemini 3\.1 Pro \(High\)/g)).toHaveLength(1)
|
||||
expect(text).toContain('40.0%')
|
||||
expect(text).not.toContain('95.0%')
|
||||
expect(text.indexOf('Gemini 3.1 Pro (High)')).toBeLessThan(text.indexOf('Gemini 3.5 Flash (High)'))
|
||||
|
||||
unmount()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest'
|
||||
|
||||
import {
|
||||
compareAntigravityQuotaItems,
|
||||
dedupeAntigravityQuotaItemsByLabel,
|
||||
resolveAntigravityQuotaLabel,
|
||||
} from '@/features/providers/utils/antigravityQuota'
|
||||
|
||||
@@ -120,14 +121,55 @@ describe('antigravityQuota', () => {
|
||||
].sort(compareAntigravityQuotaItems)
|
||||
|
||||
expect(items.map(item => item.model)).toEqual([
|
||||
'claude-opus-4-6-thinking',
|
||||
'gemini-pro-agent',
|
||||
'gemini-3-flash-agent',
|
||||
'gemini-3.5-flash-low',
|
||||
'gemini-3.5-flash-extra-low',
|
||||
'claude-opus-4-6-thinking',
|
||||
'gemini-2.5-flash-lite',
|
||||
'tab_flash_lite_preview',
|
||||
'chat_20706',
|
||||
])
|
||||
})
|
||||
|
||||
it('deduplicates display labels while keeping the current preferred quota bucket', () => {
|
||||
const items = dedupeAntigravityQuotaItemsByLabel([
|
||||
{
|
||||
model: 'gemini-3.1-pro-high',
|
||||
label: 'Gemini 3.1 Pro (High)',
|
||||
remainingPercent: 95,
|
||||
resetSeconds: null,
|
||||
},
|
||||
{
|
||||
model: 'gemini-pro-agent',
|
||||
label: 'Gemini 3.1 Pro (High)',
|
||||
remainingPercent: 40,
|
||||
resetSeconds: null,
|
||||
},
|
||||
{
|
||||
model: 'claude-sonnet-4-6-thinking',
|
||||
label: 'Claude Sonnet 4.6 (Thinking)',
|
||||
remainingPercent: 95,
|
||||
resetSeconds: null,
|
||||
},
|
||||
{
|
||||
model: 'claude-sonnet-4-6',
|
||||
label: 'Claude Sonnet 4.6 (Thinking)',
|
||||
remainingPercent: 40,
|
||||
resetSeconds: null,
|
||||
},
|
||||
{
|
||||
model: 'gemini-3-flash-agent',
|
||||
label: 'Gemini 3.5 Flash (High)',
|
||||
remainingPercent: 80,
|
||||
resetSeconds: null,
|
||||
},
|
||||
])
|
||||
|
||||
expect(items.map(item => item.model)).toEqual([
|
||||
'claude-sonnet-4-6',
|
||||
'gemini-pro-agent',
|
||||
'gemini-3-flash-agent',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -29,15 +29,15 @@ const ANTIGRAVITY_MODEL_LABELS: Record<string, string> = {
|
||||
}
|
||||
|
||||
const ANTIGRAVITY_MODEL_PRIORITY: Record<string, number> = {
|
||||
'gemini-pro-agent': 10,
|
||||
'gemini-3.1-pro-high': 10,
|
||||
'gemini-3.1-pro-low': 20,
|
||||
'gemini-3-flash-agent': 30,
|
||||
'gemini-3.5-flash-low': 40,
|
||||
'gemini-3.5-flash-extra-low': 50,
|
||||
'claude-opus-4-6-thinking': 60,
|
||||
'claude-sonnet-4-6': 70,
|
||||
'claude-sonnet-4-6-thinking': 70,
|
||||
'claude-opus-4-6-thinking': 10,
|
||||
'claude-sonnet-4-6': 20,
|
||||
'claude-sonnet-4-6-thinking': 25,
|
||||
'gemini-pro-agent': 30,
|
||||
'gemini-3.1-pro-high': 35,
|
||||
'gemini-3.1-pro-low': 40,
|
||||
'gemini-3-flash-agent': 50,
|
||||
'gemini-3.5-flash-low': 60,
|
||||
'gemini-3.5-flash-extra-low': 70,
|
||||
'gemini-3.1-flash-image': 80,
|
||||
'gemini-3.1-flash-lite': 90,
|
||||
'gemini-3-flash': 180,
|
||||
@@ -78,7 +78,7 @@ function getAntigravityModelPriority(model: string): number {
|
||||
const normalizedModel = model.trim()
|
||||
const explicit = ANTIGRAVITY_MODEL_PRIORITY[normalizedModel]
|
||||
if (explicit !== undefined) return explicit
|
||||
if (normalizedModel.startsWith('claude-')) return 90
|
||||
if (normalizedModel.startsWith('claude-')) return 30
|
||||
if (normalizedModel.startsWith('gemini-3.')) return 200
|
||||
if (normalizedModel.startsWith('gemini-2.')) return 390
|
||||
if (normalizedModel.startsWith('gemini-')) return 490
|
||||
@@ -100,3 +100,18 @@ export function compareAntigravityQuotaItems<T extends AntigravityQuotaSortableI
|
||||
|| a.label.localeCompare(b.label)
|
||||
|| a.model.localeCompare(b.model)
|
||||
}
|
||||
|
||||
export function dedupeAntigravityQuotaItemsByLabel<T extends AntigravityQuotaSortableItem>(
|
||||
items: T[],
|
||||
): T[] {
|
||||
const selectedByLabel = new Map<string, T>()
|
||||
for (const item of items) {
|
||||
const label = item.label.trim()
|
||||
if (!label) continue
|
||||
const selected = selectedByLabel.get(label)
|
||||
if (!selected || compareAntigravityQuotaItems(item, selected) < 0) {
|
||||
selectedByLabel.set(label, item)
|
||||
}
|
||||
}
|
||||
return Array.from(selectedByLabel.values()).sort(compareAntigravityQuotaItems)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user