fix(grok): keep inconclusive billing accounts eligible

This commit is contained in:
aofee
2026-09-02 11:09:21 +08:00
parent 3510aa22b5
commit a774230661
3 changed files with 17 additions and 7 deletions
+1 -1
View File
@@ -827,7 +827,7 @@ xAI quota is passive. Sub2API does not invent subscription quota values; it reco
`401` responses temporarily remove accounts with invalid credentials from scheduling. `403` responses are treated as access or entitlement failures instead of token-refresh loops. `429` responses use `Retry-After` or a short cooldown to temporarily remove the account from scheduling.
New Grok image and video generation requests use a media-specific eligibility check. API-key accounts remain eligible. OAuth accounts require positive paid-entitlement evidence from the xAI billing probe; Free, forbidden, missing, malformed, and inconclusive billing observations are excluded from new media generation. Unobserved OAuth accounts are probed before the first media request is forwarded, and imports run the billing-first quota probe proactively. Chat requests and video status lookups are not affected by this media-only quarantine. If no eligible account remains, the media endpoint returns HTTP `503` with error type `grok_media_no_eligible_account`.
New Grok image and video generation requests use a media-specific eligibility check. API-key accounts remain eligible. OAuth accounts with explicit Free or forbidden billing evidence are excluded from new media generation. Missing or malformed observations are probed before dispatch; a successful but incomplete billing response is treated as `billing_inconclusive` and remains eligible for backwards compatibility, because an unknown billing schema is not proof that the account lacks media entitlement. Operators can quarantine a known-bad account with `extra.grok_media_eligible=false` or force-enable a verified account with `true`. Imports run the billing-first quota probe proactively. Chat requests and video status lookups are not affected by this media-only quarantine. If no eligible account remains, the media endpoint returns HTTP `503` with error type `grok_media_no_eligible_account`.
Administrators can override automatic media eligibility through the account create/update API by setting `extra.grok_media_eligible` to `false` (exclude) or `true` (force eligible). On update, set it to `null` to remove the override and return to automatic probe-based behavior; omitting the field preserves the current override. A weekly allowance period alone is not treated as a paid tier signal. Successful image responses must contain at least one actual image output; empty HTTP `200` responses trigger account failover instead of being counted and returned as successful generations.
+10 -4
View File
@@ -1840,9 +1840,10 @@ func (a *Account) SupportsOpenAIEndpointCapability(capability OpenAIEndpointCapa
}
// GrokMediaGenerationEligibility reports whether a Grok account may receive
// new image/video generation requests. OAuth media fails closed unless billing
// observations provide positive paid-entitlement evidence. An explicit
// operator override takes precedence over probe data.
// new image/video generation requests. Explicit evidence of a forbidden or
// free account blocks media, while an incomplete successful billing response
// remains eligible for backwards compatibility. An explicit operator
// override takes precedence over probe data.
func (a *Account) GrokMediaGenerationEligibility() (bool, string) {
if a == nil || !a.IsGrok() {
return false, "not_grok"
@@ -1868,7 +1869,12 @@ func (a *Account) GrokMediaGenerationEligibility() (bool, string) {
return false, "billing_free_tier"
}
if !grokBillingHasAuthoritativeQuota(billing) {
return false, "billing_inconclusive"
// Billing endpoints can return 200 with an account-specific schema that
// omits plan/quota fields (for example, some SuperGrok accounts). An
// incomplete observation is not proof of ineligibility; keep the account
// routable and expose the reason for diagnostics. Operators can still
// quarantine a known-bad account with grok_media_eligible=false.
return true, "billing_inconclusive"
}
return true, "eligible"
}
@@ -46,6 +46,7 @@ func TestGrokMediaGenerationEligibility(t *testing.T) {
{name: "non grok account", account: &Account{Platform: PlatformOpenAI}, want: false, wantReason: "not_grok"},
{name: "non oauth grok account stays eligible", account: &Account{Platform: PlatformGrok, Type: AccountTypeAPIKey}, want: true, wantReason: "non_oauth"},
{name: "unobserved oauth fails closed", account: &Account{Platform: PlatformGrok, Type: AccountTypeOAuth}, want: false, wantReason: "billing_unobserved"},
{name: "inconclusive successful billing remains eligible", account: &Account{Platform: PlatformGrok, Type: AccountTypeOAuth, Extra: map[string]any{grokBillingExtraKey: &xai.BillingSummary{StatusCode: http.StatusOK, Partial: true}}}, want: true, wantReason: "billing_inconclusive"},
{name: "weekly paid usage is eligible without inferring from period type", account: &Account{Platform: PlatformGrok, Type: AccountTypeOAuth, Extra: map[string]any{grokBillingExtraKey: weeklyAllowance}}, want: true, wantReason: "eligible"},
{name: "billing forbidden is rejected", account: &Account{Platform: PlatformGrok, Type: AccountTypeOAuth, Extra: map[string]any{grokBillingExtraKey: forbiddenBilling}}, want: false, wantReason: "billing_forbidden"},
{name: "weekly billing forbidden is rejected after partial success", account: &Account{Platform: PlatformGrok, Type: AccountTypeOAuth, Extra: map[string]any{grokBillingExtraKey: weeklyForbidden}}, want: false, wantReason: "billing_forbidden"},
@@ -65,7 +66,7 @@ func TestGrokMediaGenerationEligibility(t *testing.T) {
}
}
func TestGrokMediaCapabilityKeepsOnlyUnobservedOAuthAsProbeCandidate(t *testing.T) {
func TestGrokMediaCapabilityKeepsUnobservedAndInconclusiveOAuthAsCandidates(t *testing.T) {
unobserved := &Account{Platform: PlatformGrok, Type: AccountTypeOAuth}
eligible, reason := unobserved.GrokMediaGenerationEligibility()
require.False(t, eligible)
@@ -80,7 +81,10 @@ func TestGrokMediaCapabilityKeepsOnlyUnobservedOAuthAsProbeCandidate(t *testing.
Partial: true,
}},
}
require.False(t, inconclusive.SupportsOpenAIEndpointCapability(OpenAIEndpointCapabilityGrokMediaGeneration))
eligible, reason = inconclusive.GrokMediaGenerationEligibility()
require.True(t, eligible)
require.Equal(t, "billing_inconclusive", reason)
require.True(t, inconclusive.SupportsOpenAIEndpointCapability(OpenAIEndpointCapabilityGrokMediaGeneration))
}
func TestGrokMediaCapabilityFiltersOnlyGeneration(t *testing.T) {