mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-21 03:39:54 +00:00
fix(run-agent): treat any 403 on xai-oauth as entitlement to stop refresh-loop
The existing ``_is_entitlement_failure`` heuristic only fires when
the response body contains specific substrings ("do not have an
active Grok subscription", etc.). xAI has been seen to 403 standard
SuperGrok subscribers with a terser body that doesn't match those
keywords (#26847), and the recovery path would then mint a fresh
token, get a fresh 403, and loop until Ctrl+C.
Add a defense-in-depth check at the recovery call site: any 403 on
``provider == "xai-oauth"`` short-circuits ``try_refresh_current``
so the error surfaces immediately with the friendly hint from
``_summarize_api_error``. Keeps the existing keyword path for all
other providers untouched.
This commit is contained in:
@@ -606,7 +606,22 @@ def recover_with_credential_pool(
|
||||
return False, True
|
||||
|
||||
if effective_reason == FailoverReason.auth:
|
||||
if agent._is_entitlement_failure(error_context, status_code):
|
||||
# Subscription/entitlement 403s look like auth failures on the wire
|
||||
# but refresh cannot fix them — the OAuth token is already valid,
|
||||
# the account simply lacks the entitlement. Without this guard,
|
||||
# ``try_refresh_current()`` keeps minting fresh tokens against the
|
||||
# same unsubscribed account and the main agent loop spins re-issuing
|
||||
# the same 403 until the user Ctrl+C's.
|
||||
#
|
||||
# Defense-in-depth for #26847: xAI's backend has been seen to 403
|
||||
# standard SuperGrok subscribers with bodies that don't match the
|
||||
# existing entitlement keyword set in ``_is_entitlement_failure``.
|
||||
# Any 403 against ``xai-oauth`` is treated as entitlement here so
|
||||
# the refresh loop can't spin in those cases either.
|
||||
is_entitlement = agent._is_entitlement_failure(error_context, status_code)
|
||||
if not is_entitlement and status_code == 403 and (agent.provider or "") == "xai-oauth":
|
||||
is_entitlement = True
|
||||
if is_entitlement:
|
||||
_ra().logger.info(
|
||||
"Credential %s — entitlement-shaped 403 from %s; "
|
||||
"skipping pool refresh (account lacks subscription, "
|
||||
|
||||
Reference in New Issue
Block a user