From 98b6e68617b3ad0750b089fac8a9e5563f632f25 Mon Sep 17 00:00:00 2001 From: Hermes Team Date: Mon, 24 Aug 2026 20:06:21 +0700 Subject: [PATCH] =?UTF-8?q?fix(grok):=20=D1=83=D0=B1=D1=80=D0=B0=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BD=D0=B5=D0=B2=D0=B5=D1=80=D0=BD=D0=BE=D0=B5=20?= =?UTF-8?q?=D1=83=D1=82=D0=B2=D0=B5=D1=80=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D1=80=D0=BE=20=C2=AB=D1=80=D0=B0=D0=B7=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=BA=D0=BE=D1=88=D0=B5=D0=BB=D1=8C=D0=BA=D0=B8?= =?UTF-8?q?=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Владелец прислал анонс x.ai/news/grok-hermes: доступ к Grok даётся по подписке SuperGrok через OAuth, покупать кредиты API не требуется. Моя формулировка в интерфейсе утверждала обратное — что подписка кредиты не пополняет и это отдельный кошелёк. Это неверно, и оно уже попадало пользователю на экран. Установлено проверками: - cli-chat-proxy.grok.com/v1/models принимает наш OAuth-токен -> 200, отдаёт grok-4.6; - тот же прокси /chat/completions -> 426, требует версию Grok CLI не ниже 0.1.202, и она читается не из заголовков, которые я перебрал; - api.x.ai/v1/responses (путь из документации Hermes) -> 402 personal-team-blocked:spending-limit. При этом подключён ochenstarik@gmail.com, а подписка SuperGrok — на victor.trushenko@gmail.com. То есть отказ объясняется аккаунтом, а не природой подписки, и утверждать иное я не мог. Сообщение переписано на проверяемое: у аккаунта нет ни баланса, ни лимита трат, а доступ даёт подписка на ЭТОМ же аккаунте либо купленные кредиты. Само чтение биллинга остаётся — оно работает и показывает настоящие числа. Тесты: 422 passed, ruff чисто. Co-Authored-By: Claude Opus 5 --- src/antigravity_provider/router/quota_collector.py | 14 +++++++++----- tests/test_grok_quota.py | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/antigravity_provider/router/quota_collector.py b/src/antigravity_provider/router/quota_collector.py index 96bf0b4..f3805e4 100644 --- a/src/antigravity_provider/router/quota_collector.py +++ b/src/antigravity_provider/router/quota_collector.py @@ -754,8 +754,11 @@ class AccountQuotaService: биллинговым эндпоинтом grok.com. Именно оттуда берут данные и Grok Build, и /usage. - Важно: подписка SuperGrok и кредиты API — РАЗНЫЕ кошельки. Вызовы - через Hub списываются со второго, и именно его показывает этот ответ. + Что показывает ответ: предоплаченный баланс и лимит трат по мере + использования. Доступ к Grok даёт либо подписка SuperGrok на этом же + аккаунте (см. анонс x.ai/news/grok-hermes — OAuth без покупки кредитов), + либо купленные кредиты. Нули в обоих полях означают, что ни того, ни + другого на аккаунте нет. """ now = _utc_now() token = None @@ -831,9 +834,10 @@ class AccountQuotaService: reason = None if not prepaid and not cap: reason = ( - "Кредиты API исчерпаны: предоплаченный баланс и лимит по мере " - "использования равны нулю. Подписка SuperGrok их не пополняет — " - "это отдельный кошелёк." + "У этого аккаунта нет ни предоплаченного баланса, ни лимита по " + "мере использования. Доступ даёт либо подписка SuperGrok на ЭТОМ " + "же аккаунте, либо купленные кредиты — проверьте, что подключён " + "тот аккаунт, на котором оформлена подписка." ) return QuotaSnapshot( diff --git a/tests/test_grok_quota.py b/tests/test_grok_quota.py index b116ccd..9eb4d4f 100644 --- a/tests/test_grok_quota.py +++ b/tests/test_grok_quota.py @@ -45,7 +45,7 @@ def test_exhausted_account_explains_two_wallets(): snap = AccountQuotaService()._collect_grok_quota("grok-orch", _auth()) assert snap.source == "provider_api" - assert "SuperGrok" in (snap.unavailable_reason or ""), "не объяснено, что это разные кошельки" + assert "SuperGrok" in (snap.unavailable_reason or ""), "не объяснено, откуда берётся доступ" assert all(b.status == "exhausted" for b in snap.buckets)