mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-13 22:50:19 +08:00
fix(providers): derive Codex primary quota label from window
This commit is contained in:
@@ -189,10 +189,10 @@
|
|||||||
class="grid gap-3"
|
class="grid gap-3"
|
||||||
:class="isCodexTeamPlan(key) ? 'grid-cols-2' : 'grid-cols-1'"
|
:class="isCodexTeamPlan(key) ? 'grid-cols-2' : 'grid-cols-1'"
|
||||||
>
|
>
|
||||||
<!-- 周限额 -->
|
<!-- 主限额 -->
|
||||||
<ProviderQuotaProgressRow
|
<ProviderQuotaProgressRow
|
||||||
v-if="getCodexQuotaDisplay(key)?.primary_used_percent !== undefined"
|
v-if="getCodexQuotaDisplay(key)?.primary_used_percent !== undefined"
|
||||||
:label="legacyT('周限额')"
|
:label="legacyT(getCodexPrimaryQuotaLabel(key))"
|
||||||
:used-percent="getCodexQuotaDisplay(key)?.primary_used_percent || 0"
|
:used-percent="getCodexQuotaDisplay(key)?.primary_used_percent || 0"
|
||||||
:remaining-percent="toCodexRemainingPercent(getCodexQuotaDisplay(key)?.primary_used_percent)"
|
:remaining-percent="toCodexRemainingPercent(getCodexQuotaDisplay(key)?.primary_used_percent)"
|
||||||
:meter-class="getQuotaRemainingClass(getCodexQuotaDisplay(key)?.primary_used_percent || 0)"
|
:meter-class="getQuotaRemainingClass(getCodexQuotaDisplay(key)?.primary_used_percent || 0)"
|
||||||
@@ -1021,6 +1021,10 @@ import { formatApiFormatShort } from '@/api/endpoints/types/api-format'
|
|||||||
import { isOAuthAccountProviderType, isKeyManagedProviderType } from '../utils/providerTypeUtils'
|
import { isOAuthAccountProviderType, isKeyManagedProviderType } from '../utils/providerTypeUtils'
|
||||||
import { getOAuthOrgBadge } from '@/utils/oauthIdentity'
|
import { getOAuthOrgBadge } from '@/utils/oauthIdentity'
|
||||||
import { getOAuthRefreshFeedback } from '@/utils/oauthRefreshFeedback'
|
import { getOAuthRefreshFeedback } from '@/utils/oauthRefreshFeedback'
|
||||||
|
import {
|
||||||
|
getCodexPrimaryQuotaWindow,
|
||||||
|
getCodexQuotaWindowLimitLabel,
|
||||||
|
} from '@/utils/codexQuotaWindow'
|
||||||
import { formatCompactNumber } from '@/utils/format'
|
import { formatCompactNumber } from '@/utils/format'
|
||||||
import {
|
import {
|
||||||
canEditOAuthCredential,
|
canEditOAuthCredential,
|
||||||
@@ -1945,7 +1949,7 @@ function getCodexQuotaDisplayFromSnapshot(quota: QuotaStatusSnapshot | null | un
|
|||||||
if (updatedAt !== undefined) display.updated_at = updatedAt
|
if (updatedAt !== undefined) display.updated_at = updatedAt
|
||||||
if (quota.plan_type) display.plan_type = quota.plan_type
|
if (quota.plan_type) display.plan_type = quota.plan_type
|
||||||
|
|
||||||
const primaryWindow = getQuotaWindow(quota, 'weekly')
|
const primaryWindow = getCodexPrimaryQuotaWindow(quota.windows)
|
||||||
const primaryUsedPercent = getQuotaWindowUsedPercent(primaryWindow)
|
const primaryUsedPercent = getQuotaWindowUsedPercent(primaryWindow)
|
||||||
if (primaryUsedPercent !== undefined) display.primary_used_percent = primaryUsedPercent
|
if (primaryUsedPercent !== undefined) display.primary_used_percent = primaryUsedPercent
|
||||||
const primaryResetAt = getQuotaWindowResetAt(primaryWindow)
|
const primaryResetAt = getQuotaWindowResetAt(primaryWindow)
|
||||||
@@ -2004,6 +2008,14 @@ function getCodexQuotaDisplay(key: EndpointAPIKey): CodexUpstreamMetadata | null
|
|||||||
return mergeCodexQuotaDisplays(snapshotDisplay, metadataDisplay)
|
return mergeCodexQuotaDisplays(snapshotDisplay, metadataDisplay)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCodexPrimaryQuotaLabel(key: EndpointAPIKey): string {
|
||||||
|
return getCodexQuotaWindowLimitLabel({
|
||||||
|
code: 'weekly',
|
||||||
|
label: '周',
|
||||||
|
window_minutes: getCodexQuotaDisplay(key)?.primary_window_minutes,
|
||||||
|
}) || '周限额'
|
||||||
|
}
|
||||||
|
|
||||||
function hasCodexQuotaDisplayData(key: EndpointAPIKey): boolean {
|
function hasCodexQuotaDisplayData(key: EndpointAPIKey): boolean {
|
||||||
const codex = getCodexQuotaDisplay(key)
|
const codex = getCodexQuotaDisplay(key)
|
||||||
return !!codex && (
|
return !!codex && (
|
||||||
|
|||||||
@@ -1821,6 +1821,7 @@ const legacyExactEnglishMessages: Record<string, string> = {
|
|||||||
'账号配额': 'Account quota',
|
'账号配额': 'Account quota',
|
||||||
'模型配额': 'Model quota',
|
'模型配额': 'Model quota',
|
||||||
'周限额': 'Weekly limit',
|
'周限额': 'Weekly limit',
|
||||||
|
'月限额': 'Monthly limit',
|
||||||
'5H限额': '5H limit',
|
'5H限额': '5H limit',
|
||||||
'Spark 周': 'Spark weekly',
|
'Spark 周': 'Spark weekly',
|
||||||
'Spark 5H': 'Spark 5H',
|
'Spark 5H': 'Spark 5H',
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
|
|
||||||
import { getCodexQuotaWindowPresentation } from '../codexQuotaWindow'
|
import {
|
||||||
|
getCodexPrimaryQuotaWindow,
|
||||||
|
getCodexQuotaWindowLimitLabel,
|
||||||
|
getCodexQuotaWindowPresentation,
|
||||||
|
} from '../codexQuotaWindow'
|
||||||
|
|
||||||
describe('getCodexQuotaWindowPresentation', () => {
|
describe('getCodexQuotaWindowPresentation', () => {
|
||||||
it.each([
|
it.each([
|
||||||
@@ -25,6 +29,22 @@ describe('getCodexQuotaWindowPresentation', () => {
|
|||||||
expect(windows.sort((a, b) => a.sortOrder - b.sortOrder).map(item => item.label)).toEqual(['5H', '周'])
|
expect(windows.sort((a, b) => a.sortOrder - b.sortOrder).map(item => item.label)).toEqual(['5H', '周'])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('builds the provider limit label from the actual window duration', () => {
|
||||||
|
expect(getCodexQuotaWindowLimitLabel({ code: 'weekly', window_minutes: 10_080 })).toBe('周限额')
|
||||||
|
expect(getCodexQuotaWindowLimitLabel({ code: 'weekly', window_minutes: 43_800 })).toBe('月限额')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('selects a monthly primary window over a zero-minute weekly placeholder', () => {
|
||||||
|
const monthly = { code: 'monthly', label: '月', window_minutes: 43_800, used_ratio: 0.02 }
|
||||||
|
const selected = getCodexPrimaryQuotaWindow([
|
||||||
|
monthly,
|
||||||
|
{ code: 'weekly', label: '周', window_minutes: 0, used_ratio: 1 },
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(selected).toEqual(monthly)
|
||||||
|
expect(getCodexQuotaWindowLimitLabel(selected!)).toBe('月限额')
|
||||||
|
})
|
||||||
|
|
||||||
it('drops zero-minute placeholder windows', () => {
|
it('drops zero-minute placeholder windows', () => {
|
||||||
expect(getCodexQuotaWindowPresentation({
|
expect(getCodexQuotaWindowPresentation({
|
||||||
code: 'weekly',
|
code: 'weekly',
|
||||||
|
|||||||
@@ -60,3 +60,20 @@ export function getCodexQuotaWindowPresentation(
|
|||||||
sortOrder: (isSpark ? 10_000_000 : 0) + (hasExplicitWindowMinutes ? windowMinutes : fallbackOrder),
|
sortOrder: (isSpark ? 10_000_000 : 0) + (hasExplicitWindowMinutes ? windowMinutes : fallbackOrder),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCodexQuotaWindowLimitLabel(window: QuotaWindowSnapshot): string | null {
|
||||||
|
const presentation = getCodexQuotaWindowPresentation(window)
|
||||||
|
return presentation ? `${presentation.label}限额` : null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCodexPrimaryQuotaWindow(
|
||||||
|
windows: QuotaWindowSnapshot[] | null | undefined,
|
||||||
|
): QuotaWindowSnapshot | null {
|
||||||
|
if (!Array.isArray(windows)) return null
|
||||||
|
|
||||||
|
for (const code of ['monthly', 'weekly']) {
|
||||||
|
const window = windows.find(candidate => String(candidate.code || '').trim().toLowerCase() === code)
|
||||||
|
if (window && getCodexQuotaWindowPresentation(window)) return window
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user