All patches live under sub2api/ and are baked into image grokpool-sub2api:local.
Files:
backend/internal/service/openai_gateway_scheduling.gobackend/internal/service/openai_account_scheduler.gobackend/internal/service/openai_gateway_grok.gobackend/internal/service/openai_gateway_grok_cache.gobackend/internal/service/grok_token_provider.go
Intent:
- Prefer free accounts with more remaining tokens (~1M windows)
- Soft fit / headroom scoring for Grok OAuth
- Shorter free-account 429 cooldowns
- Avoid queuing when free slots still exist (TopK overflow / free-slot scan / sticky escape)
Details: docs/SCHEDULER.md
Files:
backend/internal/service/grok_quota_service.go—ClassifyGrokAccountLivenessbackend/internal/handler/admin/grok_oauth_handler.go—ProbeDeadAccountsbackend/internal/handler/admin/grok_import_probe.go— import-time hybrid probebackend/internal/server/routes/admin.go—POST /admin/grok/accounts/probe-dead- Frontend bulk actions + i18n (
probeDead)
Rules:
- Dead = real upstream chat ban / permanent credential death (e.g. permission-denied on chat)
- Billing-only 403 is not auto-dead
- Do not
SetAccountErrorfor dead marks in a way that breaks OAuth refresh; use schedulable=false + notes
Files:
backend/internal/pkg/xai/sso_device.go— Authorization Code + PKCEbackend/internal/pkg/xai/oauth.go—referrer=grok-build(notsub2api)backend/internal/service/grok_oauth_service.go— credentialsbase_url=cli-chat-proxy.grok.com/v1
Hard requirements:
- SSO cookie is only an entry ticket
- Final credential is OAuth access/refresh
- JWT must contain
referrer=grok-build base_urlmust behttps://cli-chat-proxy.grok.com/v1- Device-flow tokens without the claim are rejected
Files:
backend/internal/service/openai_gateway_grok.go- detect body
subscription:free-usage-exhausted/ tokens actual/limit - pin remaining≈0, observation_source=
free_usage_exhausted_body - rate_limit_reset_at ≈ +24h (do not clamp to free RPM 2m window)
- detect body
backend/internal/service/openai_account_runtime_block_fastpath.goOpenAIOAuth429FailoverState.freeUsageExhaustedSeen- free-usage keeps multi-account switching (not early stop after 1–2)
- handlers (
openai_gateway_handler, chat/images/media/alpha_search):- pass upstream body into
ShouldStopOpenAIOAuth429Failover - failover exhausted free-usage/429 → clean client 429 (no raw body / no 503 wrap)
- pass upstream body into
- tests:
openai_gateway_grok_free_usage_test.go
Intent: free daily exhaust must cool the account ~24h and rotate pool; clients should see a normal 429, not a gateway 503 storm.
- Groups route allowed in simple mode
- Accounts bulk bar: probe dead / delete dead
- Quick nav links as needed
- Account page size can load all accounts when needed
powershell -ExecutionPolicy Bypass -File scripts\build-sub2api.ps1
powershell -ExecutionPolicy Bypass -File scripts\check-parity.ps1Stock image weishaw/sub2api:latest does not include these patches.