Ë
    áß²jµ*  ã                   ó|   — d Z ddlZddlZddlmZmZmZ ddlmZ dZ	dZ
dZdZd	ed
efd„Zded
efd„Z G d„ d«      Zy)a  Provider API error summarising for ``AIAgent``.

Entitlement-failure detection, xAI subscription decoration, structured-detail coercion, and log-safe
redaction of provider error payloads.
Extracted from ``run_agent.py``; every method resolves through ``AIAgent``'s MRO unchanged.
é    N)ÚAnyÚDictÚOptional)Úredact_sensitive_text)zexpected ident at linezexpected value at line)z$temporary failure in name resolutionzname or service not knownz,nodename nor servname provided, or not knownzgetaddrinfo failedz#no address associated with hostnameznetwork is unreachableuZ   â€” xAI rejected this OAuth account. NOTE: X Premium+ does NOT include xAI API access â€” only standalone SuperGrok subscribers can use this provider. Other possible causes: no Grok subscription, your tier doesn't include this model, or your quota is exhausted. Check https://grok.com/?_s=usage to see which, or run `/model` to switch providers.)ÚmessageÚdetailÚerrorÚcodeÚtypeÚlowerÚreturnc                 ó:   — d| v xs d| v xr d| v xs
 d| v xr d| v S )zYxAI's permission-denied body text for an unsubscribed / under-tiered / exhausted account.z'do not have an active grok subscriptionzout of available resourcesÚgrokzdoes not have permission© ©r   s    ú</home/ubuntu/.hermes/hermes-agent/agent/api_error_summary.pyÚ_is_xai_entitlement_textr   &   s?   € ð 	2°UÐ:ò 	EØ(¨EÐ1ÒE°fÀ°oò	Eà&¨%Ð/ÒC°F¸e°Oðó    r	   c                 ó0   — t        | dd «      }|rd|› d�S dS )NÚstatus_codezHTTP z: Ú )Úgetattr)r	   r   s     r   Ú_http_prefixr   /   s&   € Ü˜% °Ó5€KÙ&1ˆU�;�-˜rÐ"Ð9°rÐ9r   c                   ó¸   — e Zd ZdZedeeeef      dee	   de
fd„«       Zededefd„«       Zededefd	„«       Zed
edefd„«       Zdedee   fd„Zdedefd„Zy)ÚApiErrorSummaryMixinz?Provider error -> user/log-safe summary (see module docstring).Úerror_contextr   r   c                 ó®   ‡ — |dvryt        ‰ t        «      sydj                  ˆ fd„dD «       «      }|j                  «       syd|v sd|v ryt	        |«      S )u¶  Detect subscription/entitlement 401/403s that masquerade as auth failures.

        Refreshing a token cannot fix an unsubscribed account, so callers surface the error instead of looping
        the pool. xAI returns the same permission-denied text for BOTH cases; a ``[WKE=unauthenticated:...]``
        suffix (or "access token could not be validated") means stale token â†’ return False so the refresh path
        runs.

        Disambiguator for xAI (#29344): the same ``code`` text ("The caller does not have permission to
        execute the specified operation") is returned for BOTH an unsubscribed account AND a stale OAuth
        access token.  xAI ships an explicit signal in the ``error`` field that tells the two apart: a
        ``[WKE=unauthenticated:...]`` suffix (and/or the ``OAuth2 access token could not be validated``
        phrasing) means the credentials failed validation â€” that's recoverable by refreshing the token, NOT
        by surfacing an entitlement message. When either signal is present we return False eagerly so the
        credential-pool refresh path runs, letting long-running TUI sessions recover from stale tokens
        without an exit/reopen cycle.
        >   Né‘  é“  FÚ c              3   óv   •K  — | ]0  }t        ‰j                  |«      xs d «      j                  «       –— Œ2 y­w)r   N)ÚstrÚgetr   )Ú.0Úkr   s     €r   ú	<genexpr>z?ApiErrorSummaryMixin._is_entitlement_failure.<locals>.<genexpr>P   s4   øè ø€ ò 
Ø89ŒC�×!Ñ! !Ó$Ò*¨Ó+×1Ñ1×3ñ
ùs   ƒ69)r   Úreasonr
   r	   z[wke=unauthenticated:z*oauth2 access token could not be validated)Ú
isinstanceÚdictÚjoinÚstripr   )r   r   Úhaystacks   `  r   Ú_is_entitlement_failurez,ApiErrorSummaryMixin._is_entitlement_failure7   sg   ø€ ð( Ð.Ñ.ØÜ˜-¬Ô.Øà—8‘8ó 
Ø=cô
ó 
ˆð �~‰~ÔØØ" hÑ.Ð2^ÐbjÑ2jØÜ'¨Ó1Ð1r   r   c                 ó\   — | rt        | j                  «       «      s| S d| v r| S | › t        › �S )uÌ  Append a neutral hint when xAI's OAuth surface returns the permission-denied 403.

        xAI's ``/v1/responses`` uses one body for several causes (no subscription, tier lacks the model, quota
        exhausted). The least obvious: X Premium+ does NOT include API access â€” only SuperGrok does. Lead with
        that, keep the raw text, point at https://grok.com/?_s=usage. Idempotent: a substring unique to the
        hint marks prior decoration.
        zX Premium+ does NOT include)r   r   Ú_XAI_ENTITLEMENT_HINT)r   s    r   Ú_decorate_xai_entitlement_errorz4ApiErrorSummaryMixin._decorate_xai_entitlement_errorY   s8   € ñ Ô5°f·l±l³nÔEØˆMØ(¨FÑ2ØˆMØ�Ô/Ð0Ð1Ð1r   Úvaluec                 óP  — t        | t        «      r| S t        | t        «      rˆt        D ]8  }| j	                  |«      }t        |t        «      sŒ%|j                  «       sŒ6|c S  t        D ]%  }|| v sŒt        j                  | |   «      }|sŒ#|c S  	 t        j                  | dd¬«      S t        | t        t        f«      r:| D �cg c]  }t        j                  |«      ‘Œ }}dj                  d„ |D «       «      S | €yt        | «      S # t        $ r t        | «      cY S w xY wc c}w )zBReturn a display-safe string for structured provider error fields.FT)Úensure_asciiÚ	sort_keysz; c              3   ó&   K  — | ]	  }|sŒ|–— Œ y ­w©Nr   )r$   Úparts     r   r&   z@ApiErrorSummaryMixin._coerce_api_error_detail.<locals>.<genexpr>}   s   è ø€ Ò< d²tœTÑ<ùs   ‚Šr   )r(   r"   r)   Ú_ERROR_DETAIL_KEYSr#   r+   r   Ú_coerce_api_error_detailÚjsonÚdumpsÚ	TypeErrorÚlistÚtupler*   )r1   ÚkeyÚnestedÚnested_detailÚitemÚpartss         r   r9   z-ApiErrorSummaryMixin._coerce_api_error_detailh   s  € ô �eœSÔ!ØˆLÜ�eœTÔ"Ü)ò "�ØŸ™ 3›�Ü˜f¤cÕ*¨v¯|©|­~Ø!’Mð"ô *ò -�Ø˜%’<Ü$8×$QÑ$QÐRWÐX[ÑR\Ó$]�MÚ$Ø,Ò,ð	-ð
"Ü—z‘z %°eÀtÔLÐLô �eœd¤E˜]Ô+ØUZÖ[ÈTÔ)×BÑBÀ4ÕHÐ[ˆEÐ[Ø—9‘9Ñ<¨eÔ<Ó<Ð<Øˆ=ØÜ�5‹zÐøô ò "Ü˜5“zÒ!ð"üò \s   ÂD	 ÃD#Ä	D ÄD r	   c                 ó  ‡‡— t        | «      Š| Št        «       }‰�kt        ‰«      |vr^|j                  t        ‰«      «       t	        ˆfd„t
        D «       «      r	 y‰j                  xs ‰j                  Š‰�t        ‰«      |vrŒ^t        | t        «      r t	        ˆfd„t        D «       «      rd‰dd › �S t        | «      }d‰v sd‰v r½t        j                  d	‰t        j                  «      }|r|j                  d
«      j!                  «       nd}t        j                  d‰«      }|r|dd gng }|j#                  |«       |r1|j#                  d|j                  d
«      j!                  «       › �«       dj%                  |«      S t'        | «      j(                  dk(  rt+        ‰dd «      S t-        | dd«      }t        |t.        «      r„t        |j1                  d«      t.        «      r!|j1                  di «      j1                  d«      n|j1                  d«      }|r1t2        j5                  |«      }t2        j7                  |› |dd › �«      S t-        | dd«      }	|	�Ù	 t-        |	dd«      xs dj!                  «       }
|
r·	 t;        j<                  |
«      }t        |t.        «      r|j1                  d«      }t        |t.        «      r/|j1                  d«      rt+        |› t        |d   «      dd › �«      S |j1                  d«      rt+        |› t        |d   «      dd › �«      S t+        |› |
dd › �«      S t2        j7                  |› ‰dd › �«      S # t8        $ r d}
Y Œâw xY w# t:        j>                  t@        f$ r d}Y Œëw xY w)uË   Extract a human-readable one-liner from an API error.

        Cloudflare HTML pages â†’ ``<title>``; network/DNS failures (even SDK-wrapped) â†’ offline hint; else
        truncated str(error).
        Nc              3   óT   •K  — | ]  }|t        ‰«      j                  «       v –— Œ! y ­wr6   )r"   r   )r$   ÚmarkerÚcurrents     €r   r&   z<ApiErrorSummaryMixin._summarize_api_error.<locals>.<genexpr>�   s#   øè ø€ Ò\°f�6œS ›\×/Ñ/Ó1Ô1Ñ\ùs   ƒ%(zhHermes can't reach the model provider. You may be offline. Check your internet connection and try again.c              3   óB   •K  — | ]  }|‰j                  «       v –— Œ y ­wr6   r   )r$   rF   Úraws     €r   r&   z<ApiErrorSummaryMixin._summarize_api_error.<locals>.<genexpr>–   s   øè ø€ Ò0sÈ6°¸3¿9¹9»;Ô1FÑ0sùs   ƒz'Malformed provider streaming response: i,  z	<!DOCTYPEú<htmlz<title[^>]*>([^<]+)</title>é   z!HTML error page (title not found)z2Cloudflare Ray ID:\s*<strong[^>]*>([^<]+)</strong>éþÿÿÿzRay u    â€” ÚGeminiAPIErroriè  Úbodyr	   r   ÚresponseÚtextr   iô  )!r"   ÚsetÚidÚaddÚanyÚ_NETWORK_RESOLUTION_MARKERSÚ	__cause__Ú__context__r(   Ú
ValueErrorÚPROVIDER_STREAM_PARSE_MARKERSr   ÚreÚsearchÚ
IGNORECASEÚgroupr+   Úappendr*   r   Ú__name__r   r   r)   r#   r   r9   r0   Ú	Exceptionr:   ÚloadsÚJSONDecodeErrorr<   )r	   ÚseenÚprefixÚmÚtitleÚrayrC   rN   ÚmsgrO   ÚsnippetÚpayloadÚerrrG   rI   s                @@r   Ú_summarize_api_errorz)ApiErrorSummaryMixin._summarize_api_error‚   s_  ù€ ô �%‹jˆà+0ˆÜ›ˆØÐ!¤b¨£k¸Ñ&=Ø�H‰H”R˜“[Ô!ÜÓ\Ô@[Ô\Ô\ðDðð ×'Ñ'Ò>¨7×+>Ñ+>ˆGð Ð!¤b¨£k¸Ò&=ô �eœZÔ(¬SÓ0sÔUrÔ0sÔ-sØ<¸SÀÀ#¸Y¸KÐHÐHä˜eÓ$ˆà˜#Ñ ¨C¡Ü—	‘	Ð8¸#¼r¿}¹}ÓMˆAÙ*+�A—G‘G˜A“J×$Ñ$Ô&Ð1TˆEÜ—)‘)ÐQÐSVÓWˆCÙ%+�V˜C˜R�[‘M°ˆEØ�L‰L˜ÔÙØ—‘˜t C§I¡I¨a£L×$6Ñ$6Ó$8Ð#9Ð:Ô;Ø—<‘< Ó&Ð&ô �‹;×ÑÐ#3Ò3Ü(¨¨U¨d¨Ó4Ð4ô �u˜f dÓ+ˆÜ�dœDÔ!Ü:DÀTÇXÁXÈgÓEVÔX\Ô:]�$—(‘(˜7 BÓ'×+Ñ+¨IÔ6Ðcg×ckÑckÐluÓcvˆCÙÜ*×CÑCÀCÓH�Ü+×KÑKÈvÈhÐWZÐ[_Ð\_ÐW`ÐVaÐLbÓcÐcô ˜5 *¨dÓ3ˆØÐðÜ" 8¨V°TÓ:Ò@¸b×GÑGÓI�ñ ð#Ü"Ÿj™j¨Ó1�Gô ˜g¤tÔ,Ø!Ÿ+™+ gÓ.�CÜ! #¤tÔ,°·±¸Ô1CÜ4¸°xÄÀCÈ	ÁNÓ@SÐTXÐUXÐ@YÐ?ZÐ5[Ó\Ð\Ø—{‘{ 9Ô-Ü4¸°xÄÀGÈIÑDVÓ@WÐX\ÐY\Ð@]Ð?^Ð5_Ó`Ð`Ü,°¨x¸ÀÀ¸°Ð-GÓHÐHô $×CÑCÀvÀhÈsÐSWÐTWÈyÈkÐDZÓ[Ð[øô! ò Ø’ðûô
 ×,Ñ,¬iÐ8ò #Ø"’Gð#ús$   ÉM Ê M# ÍM ÍM Í#NÎ Nr?   c                 óx   — t        |«      rt        |t        «      sy|sy t        |«      dk  ry|d d › d|dd  › �S )Nz<entra-id-bearer>é   z***é   ú...éüÿÿÿ)Úcallabler(   r"   Úlen)Úselfr?   s     r   Ú_mask_api_key_for_logsz+ApiErrorSummaryMixin._mask_api_key_for_logsÌ   sH   € ô �CŒ=¤¨C´Ô!5Ø&ÙØÜˆs‹8�rŠ>ØØ�b�q�'�˜#˜c " #˜h˜ZÐ(Ð(r   Ú	error_msgc                 ó¾   — |sy|j                  «       j                  d«      sd|v rydj                  |j                  «       «      }t	        |«      dkD  r|dd dz   }|S )	zOClean up error messages for user display, removing HTML content and truncating.zUnknown errorz<!DOCTYPE htmlrJ   z:Service temporarily unavailable (HTML error page returned)r    é–   Nrp   )r+   Ú
startswithr*   Úsplitrs   )rt   rv   Úcleaneds      r   Ú_clean_error_messagez)ApiErrorSummaryMixin._clean_error_message×   s^   € áØ"à�?‰?Ó×'Ñ'Ð(8Ô9¸WÈ	Ñ=QØOØ—(‘(˜9Ÿ?™?Ó,Ó-ˆÜˆw‹<˜#ÒØ˜d˜s�m eÑ+ˆGØˆr   N)r_   Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodr   r   r"   r   ÚintÚboolr-   r0   r9   r`   rl   ru   r|   r   r   r   r   r   4   sÚ   „ ÙIàð2Ø  S¨# X¡Ñ/ð2Ø>FÀs¹mð2à	ò2ó ð2ðB ð2°ð 2¸ò 2ó ð2ð ð¨ð °ò ó ðð2 ðG\ Ið G\°#ò G\ó ðG\ðR	)¨#ð 	)°(¸3±-ó 	)ð
¨cð 
°cô 
r   r   )r   r:   rZ   Útypingr   r   r   Úagent.redactr   rY   rU   r/   r8   r"   r‚   r   r`   r   r   r   r   r   ú<module>r…      sq   ðñó Û 	ß &Ñ &å .ð !UÐ ðÐ ð2ð ð DÐ ð Cð ¨Dó ð:˜	ð : có :÷
mò mr   