mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-29 08:11:32 +00:00
fix: SuperGrokPro 用 4.5 窗口区分 Heavy,容量抖动只封单模型
JWT 的 SuperGrokPro 同时覆盖 SuperGrok 与 Heavy,账单月额度又滞后, 账号会误升/误降。multi-agent 容量抖动还会把整号提出调度。 - CanonicalGrokPlan:明确 JWT 优先;模糊档仅采新鲜的 grok-4.5 Responses 窗口 - 配额快照写入 plan_from_45_responses 时间戳,过期信号不用 - engine_overloaded 对 multi-agent 只封当前模型 0.5s–5min
This commit is contained in:
@@ -1481,15 +1481,79 @@ const { pause: pauseAutoRefresh, resume: resumeAutoRefresh } = useIntervalFn(
|
||||
{ immediate: false }
|
||||
)
|
||||
|
||||
// Persisted credentials.subscription_tier outranks lagging billing/quota snapshots.
|
||||
const GROK_QUOTA_SIGNAL_MAX_AGE_MS = 24 * 60 * 60 * 1000
|
||||
const GROK_QUOTA_SIGNAL_MAX_FUTURE_SKEW_MS = 5 * 60 * 1000
|
||||
|
||||
function normalizeGrokPlanKey(value: unknown): string {
|
||||
return String(value ?? '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/[\s_-]+/g, '')
|
||||
}
|
||||
|
||||
function isGrokQuotaTimestampFresh(raw: unknown): boolean {
|
||||
const value = String(raw || '').trim()
|
||||
if (!value) return false
|
||||
const observedAt = Date.parse(value)
|
||||
if (!Number.isFinite(observedAt)) return false
|
||||
const age = Date.now() - observedAt
|
||||
return age <= GROK_QUOTA_SIGNAL_MAX_AGE_MS && age >= -GROK_QUOTA_SIGNAL_MAX_FUTURE_SKEW_MS
|
||||
}
|
||||
|
||||
function isGrok45ResponsesQuotaModel(model: unknown): boolean {
|
||||
const value = String(model || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/^(x-ai|xai)\//, '')
|
||||
return value === 'grok-4.5' || value.startsWith('grok-4.5-')
|
||||
}
|
||||
|
||||
function grokQuotaLooksHeavy(snapshot: Record<string, any> | undefined): boolean {
|
||||
const req = Number(snapshot?.requests?.limit ?? 0)
|
||||
const tok = Number(snapshot?.tokens?.limit ?? 0)
|
||||
return req >= 8300 || tok >= 53_000_000
|
||||
}
|
||||
|
||||
function grok45ResponsesPlanIsHeavy(snapshot: Record<string, any> | undefined): boolean {
|
||||
if (!snapshot) return false
|
||||
const hint = normalizeGrokPlanKey(snapshot.plan_from_45_responses)
|
||||
if (hint === 'supergrokheavy' && isGrokQuotaTimestampFresh(snapshot.plan_from_45_responses_at)) {
|
||||
return true
|
||||
}
|
||||
const observedAt = snapshot.last_headers_seen_at || snapshot.updated_at
|
||||
return (
|
||||
isGrok45ResponsesQuotaModel(snapshot.model) &&
|
||||
isGrokQuotaTimestampFresh(observedAt) &&
|
||||
grokQuotaLooksHeavy(snapshot)
|
||||
)
|
||||
}
|
||||
|
||||
// JWT / unambiguous credentials outrank snapshots. SuperGrokPro is ambiguous
|
||||
// (covers SuperGrok and Heavy). 8300/53M only upgrades when the window came
|
||||
// from grok-4.5 Responses (or a carried 4.5 hint).
|
||||
function getAccountPlanType(row: any): string | undefined {
|
||||
if (!row) return undefined
|
||||
if (row.platform === 'grok') {
|
||||
const extra = (row.extra || {}) as Record<string, any>
|
||||
const billing = extra.grok_billing_snapshot as Record<string, any> | undefined
|
||||
const quota = extra.grok_quota_snapshot as Record<string, any> | undefined
|
||||
const quota = (extra.grok_quota_snapshot || extra.grok_usage_snapshot) as Record<string, any> | undefined
|
||||
const cred = row.credentials?.subscription_tier
|
||||
const credKey = normalizeGrokPlanKey(cred)
|
||||
if (credKey && credKey !== 'supergrokpro') {
|
||||
return cred
|
||||
}
|
||||
if (
|
||||
grok45ResponsesPlanIsHeavy(quota) &&
|
||||
(credKey === 'supergrokpro' ||
|
||||
normalizeGrokPlanKey(billing?.plan) === 'supergrok' ||
|
||||
normalizeGrokPlanKey(billing?.plan) === 'supergrokpro')
|
||||
) {
|
||||
return 'SuperGrok Heavy'
|
||||
}
|
||||
if (credKey === 'supergrokpro') {
|
||||
return billing?.plan || 'SuperGrok'
|
||||
}
|
||||
return (
|
||||
row.credentials?.subscription_tier ||
|
||||
billing?.plan ||
|
||||
quota?.subscription_tier ||
|
||||
extra.subscription_tier ||
|
||||
|
||||
@@ -396,6 +396,38 @@ describe('admin AccountsView — 账号行展示', () => {
|
||||
type: 'oauth',
|
||||
credentials: { plan_type: 'SuperGrok' },
|
||||
},
|
||||
{
|
||||
id: 206,
|
||||
name: 'supergrokpro-responses-quota',
|
||||
platform: 'grok',
|
||||
type: 'oauth',
|
||||
credentials: { subscription_tier: 'SuperGrokPro' },
|
||||
extra: {
|
||||
grok_billing_snapshot: { plan: 'SuperGrok' },
|
||||
grok_quota_snapshot: {
|
||||
model: 'grok-4.5',
|
||||
last_headers_seen_at: new Date().toISOString(),
|
||||
requests: { limit: 8300 },
|
||||
tokens: { limit: 53_000_000 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 207,
|
||||
name: 'supergrokpro-other-model-quota',
|
||||
platform: 'grok',
|
||||
type: 'oauth',
|
||||
credentials: { subscription_tier: 'SuperGrokPro' },
|
||||
extra: {
|
||||
grok_billing_snapshot: { plan: 'SuperGrok' },
|
||||
grok_quota_snapshot: {
|
||||
model: 'grok-4.6',
|
||||
last_headers_seen_at: new Date().toISOString(),
|
||||
requests: { limit: 8300 },
|
||||
tokens: { limit: 53_000_000 },
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
listAccounts.mockResolvedValue({
|
||||
@@ -416,6 +448,8 @@ describe('admin AccountsView — 账号行展示', () => {
|
||||
'FREE',
|
||||
'BASIC',
|
||||
'SuperGrok',
|
||||
'SuperGrok Heavy',
|
||||
'SuperGrok',
|
||||
])
|
||||
|
||||
wrapper.unmount()
|
||||
|
||||
Reference in New Issue
Block a user