fix(grok): serve current free quota policy

This commit is contained in:
superman2003
2026-07-19 12:17:52 +08:00
parent c99e479bcc
commit d2753dc2e2
12 changed files with 65 additions and 23 deletions
+12
View File
@@ -7,6 +7,18 @@ import (
"time"
)
const GrokFreeRolling24hTokenLimit int64 = 1_000_000
var grokFreeRolling24hTokenLimits = map[int64]struct{}{
GrokFreeRolling24hTokenLimit: {},
2_000_000: {}, // Legacy Free limit observed before July 2026.
}
func IsGrokFreeRolling24hTokenLimit(limit int64) bool {
_, ok := grokFreeRolling24hTokenLimits[limit]
return ok
}
type QuotaWindow struct {
Limit *int64 `json:"limit,omitempty"`
Remaining *int64 `json:"remaining,omitempty"`
+8
View File
@@ -61,3 +61,11 @@ func TestObserveQuotaHeadersRecordsNoHeaderProbe(t *testing.T) {
require.Nil(t, snapshot.Requests)
require.Nil(t, snapshot.Tokens)
}
func TestIsGrokFreeRolling24hTokenLimit(t *testing.T) {
t.Parallel()
require.True(t, IsGrokFreeRolling24hTokenLimit(GrokFreeRolling24hTokenLimit))
require.True(t, IsGrokFreeRolling24hTokenLimit(2_000_000), "legacy snapshots remain classifiable")
require.False(t, IsGrokFreeRolling24hTokenLimit(3_000_000))
}
@@ -207,6 +207,7 @@ type UsageInfo struct {
GrokLastQuotaProbeAt string `json:"grok_last_quota_probe_at,omitempty"`
GrokLastHeadersSeenAt string `json:"grok_last_headers_seen_at,omitempty"`
GrokLastStatusCode int `json:"grok_last_status_code,omitempty"`
GrokFreeTokenLimit int64 `json:"grok_free_token_limit,omitempty"`
GrokLocalUsage *WindowStats `json:"grok_local_usage,omitempty"`
GrokLocalUsage24h *WindowStats `json:"grok_local_usage_24h,omitempty"`
GrokLocalUsage7d *WindowStats `json:"grok_local_usage_7d,omitempty"`
@@ -21,8 +21,9 @@ func NewGrokQuotaFetcher() *GrokQuotaFetcher {
func (f *GrokQuotaFetcher) BuildUsageInfo(account *Account) *UsageInfo {
now := time.Now()
usage := &UsageInfo{
Source: "passive",
UpdatedAt: &now,
Source: "passive",
UpdatedAt: &now,
GrokFreeTokenLimit: xai.GrokFreeRolling24hTokenLimit,
}
if account == nil {
usage.ErrorCode = "quota_unknown"
@@ -19,6 +19,7 @@ func TestGrokQuotaFetcherBuildUsageInfoUnknownUntilFirstSnapshot(t *testing.T) {
usage := NewGrokQuotaFetcher().BuildUsageInfo(&Account{Platform: PlatformGrok, Type: AccountTypeOAuth})
require.Equal(t, "passive", usage.Source)
require.Equal(t, xai.GrokFreeRolling24hTokenLimit, usage.GrokFreeTokenLimit)
require.Equal(t, "quota_unknown", usage.ErrorCode)
require.Contains(t, usage.Error, "unknown until billing is probed")
}
@@ -6,6 +6,7 @@ import (
"net/http"
"strings"
"github.com/Wei-Shaw/sub2api/internal/pkg/xai"
"github.com/gin-gonic/gin"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
@@ -15,7 +16,6 @@ const (
grokConversationIDHeader = "X-Grok-Conv-Id"
grokFreeCacheNativeToolsJSON = `[{"type":"web_search"},{"type":"x_search"}]`
grokFreeCacheDisabledToolChoice = "none"
grokFreeRolling24hTokenLimit = int64(2_000_000)
)
// resolveGrokCacheIdentity derives one stable, tenant-isolated routing identity
@@ -187,7 +187,7 @@ func isKnownGrokFreeAccount(account *Account) bool {
}
}
if snapshot.Tokens != nil && snapshot.Tokens.Limit != nil &&
*snapshot.Tokens.Limit == grokFreeRolling24hTokenLimit {
xai.IsGrokFreeRolling24hTokenLimit(*snapshot.Tokens.Limit) {
inferredFreeSignal = true
}
}
@@ -8,6 +8,7 @@ import (
"sync"
"testing"
"github.com/Wei-Shaw/sub2api/internal/pkg/xai"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"
@@ -325,7 +326,19 @@ func TestGrokFreeMessagesFunctionToolCacheRouteRequiresKnownFreeTier(t *testing.
a := healthyGrokOAuthGatewayTestAccount(9112, "access-token")
a.Extra = map[string]any{grokQuotaSnapshotExtraKey: map[string]any{
"headers_observed": true,
"tokens": map[string]any{"limit": grokFreeRolling24hTokenLimit},
"tokens": map[string]any{"limit": xai.GrokFreeRolling24hTokenLimit},
}}
return a
}(),
wantMix: true,
},
{
name: "legacy free rolling token quota",
account: func() *Account {
a := healthyGrokOAuthGatewayTestAccount(9113, "access-token")
a.Extra = map[string]any{grokQuotaSnapshotExtraKey: map[string]any{
"headers_observed": true,
"tokens": map[string]any{"limit": int64(2_000_000)},
}}
return a
}(),
@@ -347,7 +360,7 @@ func TestGrokFreeMessagesFunctionToolCacheRouteRequiresKnownFreeTier(t *testing.
grokBillingExtraKey: map[string]any{"plan": "SuperGrok", "status_code": http.StatusOK},
grokQuotaSnapshotExtraKey: map[string]any{
"headers_observed": true,
"tokens": map[string]any{"limit": grokFreeRolling24hTokenLimit},
"tokens": map[string]any{"limit": int64(2_000_000)},
},
}
return a