fix(xai-oauth): recover from prelude SSE errors, gate reasoning replay, surface entitlement 403s
Original commit 31ba2b0cb by Teknium targeted run_codex_stream() at
its pre-refactor location in run_agent.py. Re-applied:
- Prelude error retry/fallback → agent/codex_runtime.py (in
run_codex_stream where the body now lives)
- _decorate_xai_entitlement_error helper + _summarize_api_error
wrapping → run_agent.py (these methods remained on AIAgent
as @staticmethod's; cherry-pick applied them cleanly)
The xai-oauth provider gate, encrypted_content drop on replay, etc.
landed in agent/codex_responses_adapter.py via the prior merge from main.
Closes #8133, #14634
Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
This commit is contained in:
43
run_agent.py
43
run_agent.py
@ -1287,6 +1287,45 @@ class AIAgent:
|
||||
trajectory = self._convert_to_trajectory_format(messages, user_query, completed)
|
||||
_save_trajectory_to_file(trajectory, self.model, completed)
|
||||
|
||||
@staticmethod
|
||||
def _decorate_xai_entitlement_error(detail: str) -> str:
|
||||
"""Append a friendly hint when xAI's OAuth surface returns an
|
||||
entitlement-shaped error.
|
||||
|
||||
xAI's ``/v1/responses`` endpoint replies to OAuth tokens that lack a
|
||||
SuperGrok / X Premium subscription with HTTP 403 carrying a body like::
|
||||
|
||||
{"code": "The caller does not have permission to execute the
|
||||
specified operation", "error": "You have either run out of
|
||||
available resources or do not have an active Grok subscription.
|
||||
Manage subscriptions at https://grok.com/..."}
|
||||
|
||||
The raw text is useful but the action the user needs to take (subscribe
|
||||
on grok.com, or switch providers with ``/model``) isn't obvious from
|
||||
the wire format. Detect the entitlement shape and append a hint.
|
||||
|
||||
Matched once per detail string — won't double-decorate if the upstream
|
||||
already concatenated the same text.
|
||||
"""
|
||||
if not detail:
|
||||
return detail
|
||||
lower = detail.lower()
|
||||
is_entitlement = (
|
||||
"do not have an active grok subscription" in lower
|
||||
or ("out of available resources" in lower and "grok" in lower)
|
||||
or ("does not have permission" in lower and "grok" in lower)
|
||||
)
|
||||
if not is_entitlement:
|
||||
return detail
|
||||
hint = (
|
||||
" — xAI OAuth account lacks SuperGrok / X Premium entitlement for "
|
||||
"this model. Subscribe at https://grok.com or run `/model` to "
|
||||
"switch providers."
|
||||
)
|
||||
if hint.strip() in detail:
|
||||
return detail
|
||||
return f"{detail}{hint}"
|
||||
|
||||
@staticmethod
|
||||
def _summarize_api_error(error: Exception) -> str:
|
||||
"""Extract a human-readable one-liner from an API error.
|
||||
@ -1320,12 +1359,12 @@ class AIAgent:
|
||||
if msg:
|
||||
status_code = getattr(error, "status_code", None)
|
||||
prefix = f"HTTP {status_code}: " if status_code else ""
|
||||
return f"{prefix}{msg[:300]}"
|
||||
return AIAgent._decorate_xai_entitlement_error(f"{prefix}{msg[:300]}")
|
||||
|
||||
# Fallback: truncate the raw string but give more room than 200 chars
|
||||
status_code = getattr(error, "status_code", None)
|
||||
prefix = f"HTTP {status_code}: " if status_code else ""
|
||||
return f"{prefix}{raw[:500]}"
|
||||
return AIAgent._decorate_xai_entitlement_error(f"{prefix}{raw[:500]}")
|
||||
|
||||
def _mask_api_key_for_logs(self, key: Optional[str]) -> Optional[str]:
|
||||
if not key:
|
||||
|
||||
Reference in New Issue
Block a user