-
-
- {{ formatWindowRequests(grokLocalUsage) }} req
-
-
- {{ formatWindowTokens(grokLocalUsage) }}
-
-
- A ${{ formatWindowCost(grokLocalUsage) }}
-
+
+
+
+
+ {{ grokQuotaUnknownLabel }}
+
+
+
+
+
+
- U ${{ formatWindowUserCost(grokLocalUsage) }}
+ {{ t('admin.accounts.usageWindow.grokPrepaid') }} ${{ grokPrepaidMoneyLine.prepaid }}
+
+
+ {{ t('admin.accounts.usageWindow.grokUsed') }}
+ {{ grokPrepaidMoneyLine.used }}/{{ grokPrepaidMoneyLine.limit }}
+
+ {{ grokQuotaUnknownLabel }}
+
+
+
+ {{ usageErrorLabel }}
-
-
-
-
- {{ t('admin.accounts.usageWindow.grokPrepaid') }} ${{ grokBillingMoneySummary.prepaid }}
-
-
- {{ t('admin.accounts.usageWindow.grokUsed') }}
- {{ grokBillingMoneySummary.used }}/{{ grokBillingMoneySummary.limit }}
-
-
- {{ grokBillingMoneySummary.usedPercent }}%
-
-
- {{ t('admin.accounts.usageWindow.grokOverageShort') }}
- {{ grokBillingMoneySummary.onDemandUsed }}/{{ grokBillingMoneySummary.onDemandCap }}
-
-
-
-
-
{{ t('admin.accounts.usageWindow.grokRetryAfter', { time: grokRetryAfterLabel }) }}
-
- {{ grokQuotaUnknownLabel }}
-
-
- {{ usageErrorLabel }}
-
-
- {{ grokQuotaStatusLine }}
-
-
+
+
+
-
-
@@ -667,11 +617,10 @@
import { ref, computed, onMounted, onBeforeUnmount, onUnmounted, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { adminAPI } from '@/api/admin'
-import type { GrokQuotaProbeResult } from '@/api/admin/grok'
import type { Account, AccountUsageInfo, GeminiCredentials, WindowStats } from '@/types'
import { buildOpenAIUsageRefreshKey } from '@/utils/accountUsageRefresh'
import { enqueueUsageRequest } from '@/utils/usageLoadQueue'
-import { formatCompactNumber, formatRelativeTime } from '@/utils/format'
+import { formatCompactNumber } from '@/utils/format'
import UsageProgressBar from './UsageProgressBar.vue'
import AccountQuotaInfo from './AccountQuotaInfo.vue'
import OpenAIQuotaResetCell from './OpenAIQuotaResetCell.vue'
@@ -1124,17 +1073,6 @@ interface GrokQuotaBarInfo {
resetsAt: string | null
}
-const makeGrokQuotaBar = (quota?: { limit?: number | null; remaining?: number | null; reset_at?: string | null } | null): GrokQuotaBarInfo | null => {
- if (!quota || quota.limit == null || quota.remaining == null || quota.limit <= 0) return null
- const remaining = Math.min(quota.limit, Math.max(0, quota.remaining))
- return {
- utilization: (remaining / quota.limit) * 100,
- resetsAt: quota.reset_at || null
- }
-}
-
-const grokRequestQuotaBar = computed(() => makeGrokQuotaBar(usageInfo.value?.grok_request_quota))
-const grokTokenQuotaBar = computed(() => makeGrokQuotaBar(usageInfo.value?.grok_token_quota))
const grokBilling = computed(() => usageInfo.value?.grok_billing || null)
const grokWeeklyBillingBar = computed((): GrokQuotaBarInfo | null => {
const billing = grokBilling.value
@@ -1177,49 +1115,30 @@ const formatGrokMoney = (value?: number | null) => {
if (value >= 10) return value.toFixed(1)
return value.toFixed(2)
}
-// Absolute money: prefer prepaid/monthly_used fields; fall back to cents/100.
-const grokBillingMoneySummary = computed(() => {
+// Prepaid money line for paid Grok: show when prepaid_balance is present.
+// Monthly used/limit numbers are optional context; primary progress is the 30d bar.
+const grokPrepaidMoneyLine = computed(() => {
const billing = grokBilling.value
if (!billing) return null
- const prepaid =
- billing.prepaid_balance != null
- ? billing.prepaid_balance
- : null
+ const prepaid = billing.prepaid_balance
+ // "只针对预付": only render when prepaid field exists (including $0.00).
+ if (prepaid == null || !Number.isFinite(prepaid)) return null
const used =
billing.monthly_used != null
? billing.monthly_used
: billing.used_cents != null
? billing.used_cents / 100
- : null
+ : 0
const limit =
billing.monthly_limit != null
? billing.monthly_limit
: billing.monthly_limit_cents != null
? billing.monthly_limit_cents / 100
- : null
- const onDemandUsed = billing.on_demand_used ?? null
- const onDemandCap = billing.on_demand_cap ?? null
- const hasAny =
- (prepaid ?? 0) > 0 ||
- (used ?? 0) > 0 ||
- (limit ?? 0) > 0 ||
- (onDemandCap ?? 0) > 0 ||
- (onDemandUsed ?? 0) > 0
- if (!hasAny) return null
- let usedPercent: number | null = null
- if (billing.used_percent != null && Number.isFinite(billing.used_percent)) {
- usedPercent = Math.round(Math.min(100, Math.max(0, billing.used_percent)))
- } else if (limit != null && limit > 0 && used != null) {
- usedPercent = Math.round(Math.min(100, Math.max(0, (used / limit) * 100)))
- }
+ : 0
return {
- prepaid: prepaid != null ? formatGrokMoney(prepaid) : null,
- used: formatGrokMoney(used ?? 0),
- limit: formatGrokMoney(limit ?? 0),
- onDemandUsed: formatGrokMoney(onDemandUsed ?? 0),
- onDemandCap: formatGrokMoney(onDemandCap ?? 0),
- showOverage: (onDemandCap ?? 0) > 0 || (onDemandUsed ?? 0) > 0,
- usedPercent
+ prepaid: formatGrokMoney(prepaid),
+ used: formatGrokMoney(used),
+ limit: formatGrokMoney(limit)
}
})
const grokPlanLabelIsFree = (value: string) => value.includes('free') || value.includes('basic')
@@ -1247,18 +1166,6 @@ const grokIsFree = computed(() => {
return billing != null
})
const grokFreeQuotaUsage = computed(() => usageInfo.value?.grok_local_usage_24h || null)
-const showGrokStandaloneLocalStats = computed(() => {
- // Official 7d/30d bars already embed window_stats — avoid duplicate local row.
- return !usageInfo.value?.seven_day && !usageInfo.value?.thirty_day
-})
-const grokLocalUsage = computed(() => {
- if (grokIsFree.value) return grokFreeQuotaUsage.value
- return props.todayStats ||
- usageInfo.value?.grok_local_usage ||
- usageInfo.value?.grok_local_usage_7d ||
- usageInfo.value?.grok_local_usage_monthly ||
- null
-})
const grokFreeTokenBar = computed(() => {
if (!grokIsFree.value || !grokFreeQuotaUsage.value) return null
const limit = usageInfo.value?.grok_free_token_limit
@@ -1268,14 +1175,10 @@ const grokFreeTokenBar = computed(() => {
})
const grokQuotaUnknown = computed(() => {
if (props.account.platform !== 'grok') return false
- if (
- grokBilling.value ||
- grokBillingMoneySummary.value ||
- grokMonthlyBillingBar.value ||
- grokFreeTokenBar.value ||
- grokRequestQuotaBar.value ||
- grokTokenQuotaBar.value
- ) {
+ if (grokIsFree.value) {
+ return !grokFreeTokenBar.value
+ }
+ if (grokWeeklyBillingBar.value || grokMonthlyBillingBar.value || grokPrepaidMoneyLine.value) {
return false
}
return usageInfo.value?.grok_quota_snapshot_state !== 'observed'
@@ -1285,33 +1188,6 @@ const grokQuotaUnknownLabel = computed(() => {
? t('admin.accounts.usageWindow.grokNoHeaders')
: t('admin.accounts.usageWindow.grokUnknown')
})
-const grokQuotaStatusLine = computed(() => {
- if (props.account.platform !== 'grok') return null
- const parts: string[] = []
- const status = usageInfo.value?.grok_last_status_code
- if (status) {
- parts.push(t('admin.accounts.usageWindow.grokLastStatus', { status }))
- }
- if (usageInfo.value?.grok_last_quota_probe_at) {
- parts.push(
- t('admin.accounts.usageWindow.grokLastProbe', {
- time: formatRelativeTime(usageInfo.value.grok_last_quota_probe_at)
- })
- )
- }
- if (usageInfo.value?.grok_last_headers_seen_at) {
- parts.push(
- t('admin.accounts.usageWindow.grokLastHeadersSeen', {
- time: formatRelativeTime(usageInfo.value.grok_last_headers_seen_at)
- })
- )
- }
- return parts.length > 0 ? parts.join(' | ') : null
-})
-const grokEntitlementLabel = computed(() => {
- const status = (usageInfo.value?.grok_entitlement_status || '').trim()
- return status || null
-})
const grokRetryAfterLabel = computed(() => {
const seconds = usageInfo.value?.grok_retry_after_seconds
if (seconds == null || seconds <= 0) return null
@@ -1320,11 +1196,6 @@ const grokRetryAfterLabel = computed(() => {
return `${minutes}m`
})
-const formatWindowRequests = (stats: WindowStats) => formatCompactNumber(stats.requests, { allowBillions: false })
-const formatWindowTokens = (stats: WindowStats) => formatCompactNumber(stats.tokens)
-const formatWindowCost = (stats: WindowStats) => stats.cost.toFixed(2)
-const formatWindowUserCost = (stats: WindowStats) => (stats.user_cost ?? 0).toFixed(2)
-
// 账户类型显示标签
const antigravityTierLabel = computed(() => {
switch (antigravityTier.value) {
@@ -1447,9 +1318,9 @@ const loadUsage = async (options?: { source?: 'passive' | 'active'; bypassCache?
error.value = null
try {
- const fetchFn = () => options?.source
- ? adminAPI.accounts.getUsage(props.account.id, options.source)
- : adminAPI.accounts.getUsage(props.account.id)
+ const fetchFn = () => options?.source
+ ? adminAPI.accounts.getUsage(props.account.id, options.source, options.bypassCache === true)
+ : adminAPI.accounts.getUsage(props.account.id)
const result = await enqueueUsageRequest(props.account, fetchFn)
if (!unmounted.value) {
usageInfo.value = result
@@ -1526,54 +1397,10 @@ const loadActiveUsage = async () => {
}
}
-const handleGrokProbed = (result: GrokQuotaProbeResult) => {
- const current = usageInfo.value
- if (!current) return
- const snapshot = result.snapshot
- const statusCode = snapshot?.status_code ?? result.status_code
- const hasActiveProbeSnapshot = snapshot != null && (
- result.source === 'active_probe' ||
- result.source === 'hybrid_probe' ||
- snapshot.observation_source === 'active_probe'
- )
- const probeSucceeded = hasActiveProbeSnapshot &&
- statusCode != null && statusCode >= 200 && statusCode < 300
- const snapshotEntitlement = snapshot?.entitlement_status?.trim()
- const currentEntitlement = current.grok_entitlement_status?.trim()
- const entitlementStatus = snapshotEntitlement || (
- probeSucceeded && currentEntitlement?.toLowerCase() === 'forbidden'
- ? undefined
- : current.grok_entitlement_status
- )
- const merged: AccountUsageInfo = {
- ...current,
- grok_billing: result.billing ?? current.grok_billing,
- grok_local_usage_24h: result.local_usage_24h ?? current.grok_local_usage_24h,
- grok_local_usage_7d: result.local_usage_7d ?? current.grok_local_usage_7d,
- grok_local_usage_monthly: result.local_usage_monthly ?? current.grok_local_usage_monthly,
- grok_request_quota: snapshot?.requests ?? current.grok_request_quota,
- grok_token_quota: snapshot?.tokens ?? current.grok_token_quota,
- grok_retry_after_seconds: snapshot?.retry_after_seconds ?? current.grok_retry_after_seconds,
- grok_entitlement_status: entitlementStatus,
- grok_quota_snapshot_state: result.billing
- ? 'billing_observed'
- : snapshot?.headers_observed
- ? 'observed'
- : current.grok_quota_snapshot_state,
- grok_last_quota_probe_at: result.billing?.fetched_at ?? snapshot?.last_probe_at ?? current.grok_last_quota_probe_at,
- grok_last_headers_seen_at: snapshot?.last_headers_seen_at ?? current.grok_last_headers_seen_at,
- grok_last_status_code: result.status_code ?? snapshot?.status_code ?? current.grok_last_status_code,
- is_forbidden: probeSucceeded ? false : current.is_forbidden,
- forbidden_reason: probeSucceeded ? undefined : current.forbidden_reason,
- forbidden_type: probeSucceeded ? undefined : current.forbidden_type,
- validation_url: probeSucceeded ? undefined : current.validation_url,
- needs_verify: probeSucceeded ? false : current.needs_verify,
- is_banned: probeSucceeded ? false : current.is_banned,
- error: result.billing || snapshot ? undefined : current.error,
- error_code: result.billing || snapshot ? undefined : current.error_code
- }
- usageInfo.value = merged
- _usageCache.set(props.account.id, { data: merged, ts: Date.now() })
+// The probe persists upstream quota state; refresh this cell so its compact
+// bars and entitlement status reflect the newly observed snapshot.
+const handleGrokProbed = async () => {
+ await loadUsage({ source: 'active', bypassCache: true })
}
// ===== API Key quota progress bars =====
diff --git a/frontend/src/components/account/GrokQuotaProbeCell.vue b/frontend/src/components/account/GrokQuotaProbeCell.vue
index fa6fe29bec..e5f84077a2 100644
--- a/frontend/src/components/account/GrokQuotaProbeCell.vue
+++ b/frontend/src/components/account/GrokQuotaProbeCell.vue
@@ -24,18 +24,13 @@
{{ t('admin.accounts.usageWindow.grokProbe') }}
-
-
+
+
{{ summary }}
@@ -48,12 +43,17 @@
import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { adminAPI } from '@/api/admin'
-import type { GrokQuotaProbeResult, GrokQuotaWindow } from '@/api/admin/grok'
+import type { GrokQuotaProbeResult } from '@/api/admin/grok'
import type { Account } from '@/types'
-const props = defineProps<{
- account: Account
-}>()
+const props = withDefaults(
+ defineProps<{
+ account: Account
+ /** When true, only show the probe button (+ errors). No duplicate weekly summary. */
+ compact?: boolean
+ }>(),
+ { compact: false }
+)
const emit = defineEmits<{ probed: [result: GrokQuotaProbeResult] }>()
@@ -79,42 +79,16 @@ const extractErrorMessage = (e: unknown): string => {
)
}
-const formatWindow = (label: string, window?: GrokQuotaWindow | null): string | null => {
- if (!window || window.limit == null || window.remaining == null) return null
- return `${label} ${window.remaining}/${window.limit}`
-}
-
-const retryAfterLabel = computed(() => {
- const seconds = data.value?.snapshot?.retry_after_seconds
- if (seconds == null || seconds <= 0) return null
- if (seconds < 60) return `${seconds}s`
- return `${Math.ceil(seconds / 60)}m`
-})
-
const summary = computed(() => {
- const snapshot = data.value?.snapshot
- if (!data.value) return ''
+ if (props.compact || !data.value) return ''
+ // Non-compact fallback (rarely used): brief weekly percent if present.
const billing = data.value.billing
- const parts: Array
= []
if (billing?.period_type?.toLowerCase() === 'weekly' && billing.usage_percent != null) {
- parts.push(t('admin.accounts.usageWindow.grokWeeklyUsage', {
+ return t('admin.accounts.usageWindow.grokWeeklyUsage', {
percent: Math.round(Math.min(100, Math.max(0, billing.usage_percent)))
- }))
+ })
}
- if (snapshot) {
- parts.push(
- formatWindow(t('admin.accounts.usageWindow.grokRequests'), snapshot.requests),
- formatWindow(t('admin.accounts.usageWindow.grokTokens'), snapshot.tokens)
- )
- }
- if (retryAfterLabel.value) {
- parts.push(t('admin.accounts.usageWindow.grokRetryAfter', { time: retryAfterLabel.value }))
- }
- if (snapshot?.entitlement_status) {
- parts.push(snapshot.entitlement_status)
- }
- const visibleParts = parts.filter((part): part is string => Boolean(part))
- return visibleParts.length > 0 ? visibleParts.join(' | ') : t('admin.accounts.usageWindow.grokNoHeaders')
+ return ''
})
const truncatedError = computed(() => {
diff --git a/frontend/src/components/account/__tests__/AccountUsageCell.spec.ts b/frontend/src/components/account/__tests__/AccountUsageCell.spec.ts
index 6fcc963145..46f3908254 100644
--- a/frontend/src/components/account/__tests__/AccountUsageCell.spec.ts
+++ b/frontend/src/components/account/__tests__/AccountUsageCell.spec.ts
@@ -651,7 +651,7 @@ describe('AccountUsageCell', () => {
expect(badges.some(node => node.attributes('title') === 'usage.userBilled')).toBe(true)
})
- it('Grok OAuth 会展示本地 user billed 用量并把耗尽配额显示为 0% 剩余', async () => {
+ it('Grok OAuth compact UI drops local chips and header quota bars', async () => {
getUsage.mockResolvedValue({
grok_local_usage: {
requests: 4,
@@ -670,12 +670,7 @@ describe('AccountUsageCell', () => {
const wrapper = mount(AccountUsageCell, {
props: {
- account: makeAccount({
- id: 3861,
- platform: 'grok',
- type: 'oauth',
- extra: {}
- })
+ account: makeAccount({ id: 3861, platform: 'grok', type: 'oauth', extra: {} })
},
global: {
stubs: {
@@ -683,66 +678,49 @@ describe('AccountUsageCell', () => {
props: ['label', 'utilization', 'resetsAt', 'color'],
template: '{{ label }}|{{ utilization }}|{{ resetsAt }}
'
},
- AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
+ AccountQuotaInfo: true
}
}
})
await flushPromises()
-
expect(getUsage).toHaveBeenCalledWith(3861)
- expect(wrapper.text()).toContain('4 req')
- expect(wrapper.text()).toContain('1.2K')
- expect(wrapper.text()).toContain('A $0.12')
- expect(wrapper.text()).toContain('U $0.34')
- expect(wrapper.text()).toContain('admin.accounts.usageWindow.grokRequests|0|2026-07-09T16:00:00Z')
-
- const badges = wrapper.findAll('span[title]')
- expect(badges.some(node => node.attributes('title') === 'usage.accountBilled')).toBe(true)
- expect(badges.some(node => node.attributes('title') === 'usage.userBilled')).toBe(true)
+ expect(wrapper.text()).not.toContain('4 req')
+ expect(wrapper.text()).not.toContain('admin.accounts.usageWindow.grokRequests|')
})
- it('Grok OAuth 配额条按剩余容量显示 100% 满格和 25% 低量', async () => {
+ it('Grok paid monthly limits show 30d bar without free 24h', async () => {
getUsage.mockResolvedValue({
- grok_request_quota: {
- limit: 100,
- remaining: 100,
- reset_at: '2026-07-09T16:00:00Z'
+ grok_billing: {
+ period_type: 'weekly',
+ usage_percent: null,
+ used_percent: 12,
+ monthly_limit_cents: 25_000,
+ used_cents: 3_000,
+ plan: ''
},
- grok_token_quota: {
- limit: 1000,
- remaining: 250,
- reset_at: '2026-07-09T16:00:00Z'
- },
- grok_quota_snapshot_state: 'observed'
+ grok_entitlement_status: 'free',
+ grok_token_quota: { limit: 1_000, remaining: 250 }
})
const wrapper = mount(AccountUsageCell, {
props: {
- account: makeAccount({
- id: 4073,
- platform: 'grok',
- type: 'oauth',
- extra: {}
- })
+ account: makeAccount({ id: 4402, platform: 'grok', type: 'oauth', extra: {} })
},
global: {
stubs: {
UsageProgressBar: {
- props: ['label', 'utilization', 'resetsAt', 'color', 'remainingCapacity'],
- template: '{{ label }}|{{ utilization }}|{{ remainingCapacity }}
'
+ props: ['label', 'utilization'],
+ template: '{{ label }}|{{ utilization }}
'
},
- AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
+ AccountQuotaInfo: true
}
}
})
await flushPromises()
-
- expect(wrapper.text()).toContain('admin.accounts.usageWindow.grokRequests|100|true')
- expect(wrapper.text()).toContain('admin.accounts.usageWindow.grokTokens|25|true')
+ expect(wrapper.text()).toContain('30d|')
+ expect(wrapper.text()).not.toContain('24h|')
})
it('Grok OAuth uses the official weekly billing percentage when available', async () => {
@@ -775,7 +753,6 @@ describe('AccountUsageCell', () => {
template: '{{ label }}|{{ utilization }}|{{ resetsAt }}|{{ remainingCapacity }}
'
},
AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
}
}
})
@@ -789,11 +766,11 @@ describe('AccountUsageCell', () => {
})
it.each([
- { tokens: 0, expected: 0, compact: '0' },
- { tokens: 500_000, expected: 50, compact: '500.0K' },
- { tokens: 1_000_000, expected: 100, compact: '1.0M' },
- { tokens: 1_100_000, expected: 100, compact: '1.1M' }
- ])('Grok Free derives its 1M quota from local tokens: $tokens -> $expected%', async ({ tokens, expected, compact }) => {
+ { tokens: 0, expected: 0 },
+ { tokens: 500_000, expected: 50 },
+ { tokens: 1_000_000, expected: 100 },
+ { tokens: 1_100_000, expected: 100 }
+ ])('Grok Free derives its 1M quota from local tokens: $tokens -> $expected%', async ({ tokens, expected }) => {
getUsage.mockResolvedValue({
grok_free_token_limit: 1_000_000,
grok_billing: {
@@ -823,7 +800,6 @@ describe('AccountUsageCell', () => {
template: '{{ label }}|{{ utilization }}
'
},
AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
}
}
})
@@ -831,10 +807,10 @@ describe('AccountUsageCell', () => {
await flushPromises()
expect(wrapper.text()).toContain(`24h|${expected}`)
- expect(wrapper.findAll('span').filter((node) => node.text() === compact)).toHaveLength(1)
expect(wrapper.findAll('.usage-bar')).toHaveLength(1)
expect(wrapper.text()).not.toContain('admin.accounts.usageWindow.grokRequests|')
expect(wrapper.text()).not.toContain('admin.accounts.usageWindow.grokTokens|')
+ expect(wrapper.text()).not.toContain('7d|')
})
it('Grok Free uses rolling 24h usage instead of today-only usage', async () => {
@@ -872,7 +848,6 @@ describe('AccountUsageCell', () => {
template: '{{ label }}|{{ utilization }}|{{ title }}
'
},
AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
}
}
})
@@ -880,7 +855,6 @@ describe('AccountUsageCell', () => {
await flushPromises()
expect(wrapper.text()).toContain('24h|75|admin.accounts.usageWindow.grokFreeQuota24hHint')
- expect(wrapper.text()).toContain('750.0K')
expect(wrapper.text()).not.toContain('7d|')
expect(wrapper.text()).not.toContain('200.0K')
expect(wrapper.text()).not.toContain('250.0K')
@@ -917,7 +891,6 @@ describe('AccountUsageCell', () => {
template: '{{ label }}|{{ utilization }}
'
},
AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
}
}
})
@@ -930,85 +903,6 @@ describe('AccountUsageCell', () => {
expect(wrapper.text()).not.toContain('250.0K')
})
- it('Grok paid plans are not mistaken for Free when weekly usage is temporarily missing', async () => {
- getUsage.mockResolvedValue({
- grok_billing: {
- period_type: 'weekly',
- usage_percent: null,
- plan: 'SuperGrok Heavy'
- },
- grok_entitlement_status: 'free',
- grok_local_usage: {
- requests: 2,
- tokens: 2_000_000,
- cost: 1,
- standard_cost: 1
- },
- grok_token_quota: { limit: 1_000, remaining: 250 }
- })
-
- const wrapper = mount(AccountUsageCell, {
- props: {
- account: makeAccount({ id: 4401, platform: 'grok', type: 'oauth', extra: {} })
- },
- global: {
- stubs: {
- UsageProgressBar: {
- props: ['label', 'utilization'],
- template: '{{ label }}|{{ utilization }}
'
- },
- AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
- }
- }
- })
-
- await flushPromises()
-
- expect(wrapper.text()).toContain('admin.accounts.usageWindow.grokTokens|25')
- expect(wrapper.text()).not.toContain('2M|')
- })
-
- it('Grok custom paid monthly limits override stale Free entitlement', async () => {
- getUsage.mockResolvedValue({
- grok_billing: {
- period_type: 'weekly',
- usage_percent: null,
- monthly_limit_cents: 25_000,
- plan: ''
- },
- grok_entitlement_status: 'free',
- grok_local_usage: {
- requests: 2,
- tokens: 2_000_000,
- cost: 1,
- standard_cost: 1
- },
- grok_token_quota: { limit: 1_000, remaining: 250 }
- })
-
- const wrapper = mount(AccountUsageCell, {
- props: {
- account: makeAccount({ id: 4402, platform: 'grok', type: 'oauth', extra: {} })
- },
- global: {
- stubs: {
- UsageProgressBar: {
- props: ['label', 'utilization'],
- template: '{{ label }}|{{ utilization }}
'
- },
- AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
- }
- }
- })
-
- await flushPromises()
-
- expect(wrapper.text()).toContain('admin.accounts.usageWindow.grokTokens|25')
- expect(wrapper.text()).not.toContain('2M|')
- })
-
it('Grok credential Free tier keeps the 1M fallback when billing is unavailable', async () => {
getUsage.mockResolvedValue({
grok_free_token_limit: 1_000_000,
@@ -1032,7 +926,6 @@ describe('AccountUsageCell', () => {
template: '{{ label }}|{{ utilization }}
'
},
AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
}
}
})
@@ -1042,257 +935,6 @@ describe('AccountUsageCell', () => {
expect(wrapper.text()).toContain('24h|100')
})
- it('Grok paid manual probes keep the weekly/local summary when 24h usage is returned', async () => {
- getUsage.mockResolvedValue({
- grok_quota_snapshot_state: 'no_headers',
- error: 'stale error',
- error_code: 'quota_unknown'
- })
-
- const wrapper = mount(AccountUsageCell, {
- props: {
- account: makeAccount({ id: 4501, platform: 'grok', type: 'oauth', extra: {} })
- },
- global: {
- stubs: {
- UsageProgressBar: {
- props: ['label', 'utilization', 'resetsAt'],
- template: '{{ label }}|{{ utilization }}|{{ resetsAt }}
'
- },
- AccountQuotaInfo: true,
- GrokQuotaProbeCell: {
- emits: ['probed'],
- template: ``
- }
- }
- }
- })
-
- await flushPromises()
- await wrapper.get('.probe').trigger('click')
-
- expect(wrapper.text()).toContain('7d|42|2026-07-17T00:00:00Z')
- expect(wrapper.text()).toContain('1.0M')
- expect(wrapper.text()).not.toContain('750.0K')
- expect(wrapper.text()).toContain('ACTIVE')
- expect(wrapper.text()).not.toContain('stale error')
- })
-
- it('Grok successful probes immediately clear stale forbidden state', async () => {
- getUsage.mockResolvedValue({
- is_forbidden: true,
- forbidden_reason: 'stale forbidden response',
- forbidden_type: 'validation',
- validation_url: 'https://example.com/verify',
- needs_verify: true,
- is_banned: true,
- grok_entitlement_status: 'forbidden',
- grok_quota_snapshot_state: 'no_headers',
- error: 'stale forbidden response',
- error_code: 'forbidden'
- })
-
- const wrapper = mount(AccountUsageCell, {
- props: {
- account: makeAccount({ id: 4503, platform: 'grok', type: 'oauth', extra: {} })
- },
- global: {
- stubs: {
- UsageProgressBar: true,
- AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
- }
- }
- })
-
- await flushPromises()
- expect(wrapper.text()).toContain('forbidden')
-
- const setupState = wrapper.vm.$.setupState as {
- handleGrokProbed: (result: Record) => void
- usageInfo: Record | null
- }
- setupState.handleGrokProbed({
- source: 'active_probe',
- snapshot: {
- headers_observed: false,
- updated_at: '2026-07-18T00:00:00Z',
- status_code: 200
- },
- status_code: 200,
- headers_observed: false,
- reset_supported: false,
- fetched_at: 1
- })
- await wrapper.vm.$nextTick()
-
- expect(setupState.usageInfo).toMatchObject({
- is_forbidden: false,
- needs_verify: false,
- is_banned: false,
- grok_last_status_code: 200
- })
- expect(setupState.usageInfo?.forbidden_reason).toBeUndefined()
- expect(setupState.usageInfo?.forbidden_type).toBeUndefined()
- expect(setupState.usageInfo?.validation_url).toBeUndefined()
- expect(setupState.usageInfo?.grok_entitlement_status).toBeUndefined()
- expect(wrapper.text()).not.toContain('admin.accounts.forbidden')
- })
-
- it('Grok successful probes preserve the entitlement reported by the latest snapshot', async () => {
- getUsage.mockResolvedValue({
- is_forbidden: true,
- grok_entitlement_status: 'forbidden'
- })
-
- const wrapper = mount(AccountUsageCell, {
- props: {
- account: makeAccount({ id: 4504, platform: 'grok', type: 'oauth', extra: {} })
- },
- global: {
- stubs: {
- UsageProgressBar: true,
- AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
- }
- }
- })
-
- await flushPromises()
-
- const setupState = wrapper.vm.$.setupState as {
- handleGrokProbed: (result: Record) => void
- usageInfo: Record | null
- }
- setupState.handleGrokProbed({
- source: 'active_probe',
- snapshot: {
- headers_observed: true,
- updated_at: '2026-07-18T00:00:00Z',
- entitlement_status: 'ACTIVE',
- status_code: 200
- },
- status_code: 200,
- headers_observed: true,
- reset_supported: false,
- fetched_at: 1
- })
- await wrapper.vm.$nextTick()
-
- expect(setupState.usageInfo?.grok_entitlement_status).toBe('ACTIVE')
- expect(wrapper.text()).toContain('ACTIVE')
- expect(wrapper.text()).not.toContain('admin.accounts.forbidden')
- })
-
- it('Grok billing-only success does not clear an active-probe forbidden state', async () => {
- getUsage.mockResolvedValue({
- is_forbidden: true,
- forbidden_type: 'forbidden',
- needs_verify: true,
- is_banned: true,
- grok_entitlement_status: 'forbidden'
- })
-
- const wrapper = mount(AccountUsageCell, {
- props: {
- account: makeAccount({ id: 4505, platform: 'grok', type: 'oauth', extra: {} })
- },
- global: {
- stubs: {
- UsageProgressBar: true,
- AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
- }
- }
- })
-
- await flushPromises()
-
- const setupState = wrapper.vm.$.setupState as {
- handleGrokProbed: (result: Record) => void
- usageInfo: Record | null
- }
- setupState.handleGrokProbed({
- source: 'billing_probe',
- billing: {
- period_type: 'weekly',
- usage_percent: 10,
- plan: 'SuperGrok'
- },
- status_code: 200,
- headers_observed: false,
- reset_supported: false,
- fetched_at: 1
- })
- await wrapper.vm.$nextTick()
-
- expect(setupState.usageInfo).toMatchObject({
- is_forbidden: true,
- forbidden_type: 'forbidden',
- needs_verify: true,
- is_banned: true,
- grok_entitlement_status: 'forbidden'
- })
- expect(wrapper.text()).toContain('forbidden')
- })
-
- it('Grok Free manual probes merge rolling 24h usage', async () => {
- getUsage.mockResolvedValue({
- grok_free_token_limit: 1_000_000,
- subscription_tier: 'FREE',
- grok_quota_snapshot_state: 'no_headers'
- })
-
- const wrapper = mount(AccountUsageCell, {
- props: {
- account: makeAccount({ id: 4502, platform: 'grok', type: 'oauth', extra: {} })
- },
- global: {
- stubs: {
- UsageProgressBar: {
- props: ['label', 'utilization'],
- template: '{{ label }}|{{ utilization }}
'
- },
- AccountQuotaInfo: true,
- GrokQuotaProbeCell: {
- emits: ['probed'],
- template: ``
- }
- }
- }
- })
-
- await flushPromises()
- await wrapper.get('.probe').trigger('click')
-
- expect(wrapper.text()).toContain('24h|75')
- expect(wrapper.text()).toContain('750.0K')
- expect(wrapper.text()).not.toContain('7d|')
- })
-
it('Key 账号在 today stats loading 时显示骨架屏', async () => {
const wrapper = mount(AccountUsageCell, {
props: {
@@ -1424,7 +1066,6 @@ describe('AccountUsageCell', () => {
template: '{{ label }}|{{ utilization }}
'
},
AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
}
}
})
@@ -1468,7 +1109,6 @@ describe('AccountUsageCell', () => {
template: '{{ label }}|{{ utilization }}
'
},
AccountQuotaInfo: true,
- GrokQuotaProbeCell: true
}
}
})