+
    lHàj])  ã                  ó  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIHtH	t	H
t
 RtR#tR$tR R ltR R ltR	 R
 ltR R lt0 R%mt0 R&mtR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltRRRRR R/R! R" lltR# )'z0Shared helpers for direct xAI HTTP integrations.)ÚannotationsN)ÚAnyÚDictÚOptionalzhttps://api.x.ai/v1c               ó$   € V ^8„  d   QhRRRRRR/# )é   Úobjr   ÚkeyÚstrÚreturn© )Úformats   "Ú3/home/ubuntu/.hermes/hermes-agent/tools/xai_http.pyÚ__annotate__r      s!   € ÷ ;ñ ;�3ð ;˜Sð ; Sñ ;ó    c                óT   € \        V \        4      '       d   V P                  V4      # R # ©N)Ú
isinstanceÚdictÚget)r   r	   s   &&r   Ú	_dict_getr      s!   € Ü% c¬4×0Ò0ˆ3�7‰7�3‹<Ð:°dÐ:r   c               ó   € V ^8„  d   QhRR/# )r   r   Úboolr   )r   s   "r   r   r      s   € ÷ ñ ˜Tñ r   c                 ó˜  € ^ RI Hp  V ! RR4      ;'       g    RP                  4       '       d   R#  ^ RIHp V! 4       R,          pVP                  4       '       g   R# \        P                  ! VP                  RR	7      4      p\        \        \        VR
4      R4      R4      p\        \        VR4      ;'       g    R4      P                  4       '       d   R# \        \        VR4      R4      p\        V\        4      ;'       d5    \        ;QJ d    R V 4       F  '       g   K   R# 	  R# ! R V 4       4      #   \         d     R# i ; i)u=  Cheap probe: True when xAI credentials are *likely* usable.

Deliberately avoids :func:`resolve_xai_http_credentials` (disk locks, OAuth network
refresh) â€” hot-paint callers and ``WebSearchProvider.is_available()`` must not do network
I/O. Checks, fast-to-slow: ``XAI_API_KEY``; ``providers.xai-oauth.tokens.access_token`` in
``auth.json``; any ``credential_pool.xai-oauth`` entry with an ``access_token`` (pool-only
multi-account grants never write the providers singleton). Returns False on any exception
so a corrupted auth store can't block other availability scans.
)Ú
get_secretÚXAI_API_KEYÚ T©Úget_hermes_homez	auth.jsonFz	utf-8-sig©ÚencodingÚ	providersú	xai-oauthÚtokensÚaccess_tokenÚcredential_poolc              3  ó¸   "  € T FP  p\        V\        4      ;'       d4    \        VP                  R R4      ;'       g    R4      P	                  4       x € KR  	  R# 5i)r$   r   N)r   r   r
   r   Ústrip)Ú.0Úes   & r   Ú	<genexpr>Ú&has_xai_credentials.<locals>.<genexpr>-   sH   é € ð 1
ÙZaÐUVŒJ�qœ$Ó×PÐP¤C¨¯©¨n¸bÓ(A×(GÐ(GÀRÓ$H×$NÑ$NÓ$PÔPÓZaùs   ‚AžA½A)Úagent.secret_scoper   r'   Úhermes_constantsr   ÚexistsÚjsonÚloadsÚ	read_textr   r
   r   ÚlistÚanyÚ	Exception)r   r   Ú	auth_pathÚstorer#   Úentriess         r   Úhas_xai_credentialsr8      s"  € õ .á�= "Ó%×+Ð+¨×2Ñ2×4Ò4ÙðÝ4Ù#Ó%¨Õ3ˆ	Ø×Ñ×!Ò!ÙÜ—
’
˜9×.Ñ.¸Ð.ÓDÓEˆÜœ9¤Y¨u°kÓ%BÀKÓPÐRZÓ[ˆÜŒy˜ Ó0×6Ð6°BÓ7×=Ñ=×?Ò?ÙÜœI eÐ->Ó?ÀÓMˆÜ˜'¤4Ó(÷ 
ð 
¯S«Sñ 1
ÙZaó1
¯S¬Sð 	
ªSð 	
¨Sñ 1
ÙZaó1
ó .
ð 	
øô ô Úðús6   ±)D: ÁA8D: Ã8D: ÄD: Ä%D: Ä(D: Ä,D: Ä:E	ÅE	c               ó   € V ^8„  d   QhRR/# ©r   r   r
   r   )r   s   "r   r   r   4   s   € ÷ &ñ &˜sñ &r   c                 ó\   €  ^ RI Hp  RV ! 4       P                   2#   \         d     R# i ; i)z>Return a stable Hermes-specific User-Agent for xAI HTTP calls.©Úget_version_infozHermes-Agent/zHermes-Agent/unknown)Úhermes_cli.version_infor=   Úbase_versionr4   r<   s    r   Úhermes_xai_user_agentr@   4   s4   € ð&Ý<ØÑ/Ó1×>Ñ>Ð?Ð@Ð@øÜô &Ú%ð&ús   ‚ œ+ª+c               ó   € V ^8„  d   QhRR/# )r   r   údict[str, str]r   )r   s   "r   r   r   =   s   € ÷ 3ñ 3 Nñ 3r   c                 ó   € R\        4       /# )zaDefault headers for OpenAI-SDK and raw HTTP clients talking to xAI (replaces the SDK User-Agent).z
User-Agent)r@   r   r   r   Úhermes_xai_default_headersrD   =   s   € àÔ/Ó1Ð2Ð2r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úvaluer   Údefaultr   r   r   )r   s   "r   r   r   F   s!   € ÷ ñ ˜ð  dð ¨tñ r   c                óÜ   € \        V \        4      '       d   V # \        V \        4      '       d>   V P                  4       P	                  4       ;p\
        \        ,          9   d
   V\
        9   # V# r   )r   r   r
   r'   ÚlowerÚ_TRUE_WORDSÚ_FALSE_WORDS)rF   rG   Ú
normalizeds   && r   Ú_coerce_boolrM   F   sR   € Ü�%œ×ÒØˆÜ�%œ×Ò°·±³×1DÑ1DÓ1FÐ#F :Ì;ÔYeÕKeÔ"eØœ[Ñ(Ð(Ø€Nr   c               ó    € V ^8„  d   QhRRRR/# )r   rF   r   r   zOptional[int]r   )r   s   "r   r   r   N   s   € ÷ _ñ _ ð _¨ñ _r   c                óh  € V f   R# \        V \        4      '       d4   V P                  4       P                  4       p V R9   d   R#  \	        V 4      p \        V \        \        34      '       g   \        # \	        V 4      ^ 8:  d   R# \        \	        V 4      \        4      #   \
         d
    \        u # i ; i)z\Normalize an xAI storage TTL: int seconds, or None for permanent storage (omit on the wire).N>   r   Ú0ÚnoneÚnullÚneverrG   ÚforeverÚ	permanent)
r   r
   r'   rI   ÚintÚ
ValueErrorÚ&SAFE_XAI_STORAGE_EXPIRES_AFTER_SECONDSÚfloatÚminÚ%MAX_XAI_STORAGE_EXPIRES_AFTER_SECONDS)rF   s   &r   Ú_coerce_expires_afterr\   N   s–   € à‚}ÙÜ�%œ×ÒØ—‘“×#Ñ#Ó%ˆØÐYÔYÙð	:Ü˜“JˆEô �eœc¤5˜\×*Ò*Ü5Ð5Ü�u“: ”?ˆ4Ð^¬¬C°«JÔ8]Ó(^Ð^øô	 ô 	:Ü9Ò9ð	:ús   ÁB ÂB1Â0B1c               ó    € V ^8„  d   QhRRRR/# )r   Úsection_namer
   r   zdict[str, Any]r   )r   s   "r   r   r   _   s   € ÷ ñ °#ð ¸.ñ r   c           
     óX  €  ^ RI Hp \        \        \        V! 4       V 4      R4      R4      p\	        V\
        4      '       d   TM/ pR\        VP                  R4      R4      R\        VP                  R4      R4      R\        VP                  R4      4      /#   \         d    Rp L{i ; i)	zÎRead ``<section_name>.xai.storage`` (``image_gen``/``video_gen``) -> {enabled, public_url, expires_after}.
On by default so xAI returns permanent public URLs, not short-lived CDN ones; null TTL = permanent.)Úload_configÚxaiÚstorageNÚenabledTÚ
public_urlÚexpires_after)	Úhermes_cli.configr`   r   r4   r   r   rM   r   r\   )r^   r`   rb   s   &  r   Úread_xai_imagine_storage_configrg   _   sš   € ðÝ1ÜœI¤i±³¸|Ó&LÈeÓTÐV_Ó`ˆô $ G¬T×2Ò2‰g¸€Gà”< §¡¨IÓ 6¸Ó=Ø”l 7§;¡;¨|Ó#<¸dÓCØÔ.¨w¯{©{¸?Ó/KÓLðð øô ô ØŠðús   ‚+B ÂB)Â(B)c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r^   r
   Úfilename_prefixÚ	extensionr   zOptional[dict[str, Any]]r   )r   s   "r   r   r   o   s,   € ÷ ñ ØðØ+.ðØ;>ðàñr   c          	     ó¤  € \        V 4      pVR,          '       g   R# \        P                  P                  \        P                  4      P	                  R4      pT RT R\
        P                  ! 4       P                  R,           RVP                  R4      ;'       g    R 2pRVR	\        VR	,          4      /pVR
,          e   VR
,          VR
&   V# )zAReturn an xAI ``storage_options`` payload, or None when disabled.rc   Nz%Y%m%d-%H%M%SÚ-:Né   NÚ.ÚbinÚfilenamerd   re   )
rg   ÚdatetimeÚnowÚUTCÚstrftimeÚuuidÚuuid4ÚhexÚlstripr   )r^   ri   rj   ÚcfgÚtsrp   Úpayloads   &$$    r   Úbuild_xai_storage_optionsr|   o   s»   € ô *¨,Ó
7€CØˆy�>Œ>ÙÜ	×	Ñ	×	Ñ	œxŸ|™|Ó	,×	5Ñ	5°oÓ	F€BØ!Ð" ! B 4 q¬¯ª«×)9Ñ)9¸"Õ)=Ð(>¸aÀ	×@PÑ@PÐQTÓ@U×@^Ð@^ÐY^Ð?_Ð`€HØ)¨8°\Ä4ÈÈLÕHYÓCZÐ[€GØ
ˆ?ÕÒ'Ø#& Õ#7ˆ�Ñ Ø€Nr   c               ó    € V ^8„  d   QhRRRR/# )r   r^   r
   r   r   )r   s   "r   r   r   ~   s   € ÷ ñ ¨#ð °#ñ r   c                óª   € \        V 4      pVR,          '       g   R# RpVR,          e#   VR,          R,          pRVR RV^8w  d   RMR 2pR	V R
V  R2# )z5User-facing notice for first xAI Imagine storage use.rc   r   zwithout an automatic expiryre   z
for about Úgz dayÚszMxAI Imagine storage is enabled so generated media gets a reusable public URL zK. xAI may bill for stored files and public URL hosting. Disable this with `zL.xai.storage.enabled: false` or set `expires_after` to change the retention.i€Q )rg   )r^   ry   Ú	retentionÚdayss   &   r   Úxai_storage_notice_textrƒ   ~   sw   € ä
)¨,Ó
7€CØˆy�>Œ>ÙØ-€IØ
ˆ?ÕÒ'Ø�?Õ# |Õ4ˆØ   a ¨°D¸A´I©SÀ2Ð,FÐGˆ	ð	Ø�[ð !'Ø'3 nð 5:ð	:ðr   c               ó    € V ^8„  d   QhRRRR/# )r   r^   r
   r   úOptional[str]r   )r   s   "r   r   r   �   s   € ÷ ñ °Sð ¸]ñ r   c                ó’  € \        V 4      pV'       g   R#  ^ RIHp V! 4       R,          pVP                  RRR7       W0 R2,          pVP	                  4       '       d   R# VP                  \        P                  P                  \        P                  4      P                  4       R,           RR	7       V#   \         d    Tu # i ; i)
zBReturn the storage notice once per Hermes home, then mark it seen.Nr   ÚstateT)ÚparentsÚexist_okÚ_xai_storage_notice_seenÚ
zutf-8r   )rƒ   r-   r   Úmkdirr.   Ú
write_textrq   rr   rs   Ú	isoformatr4   )r^   Únoticer   Ú
marker_dirÚmarkers   &    r   Ú"maybe_mark_xai_storage_notice_seenr’   �   s¨   € ä$ \Ó2€FßÙð
Ý4Ù$Ó&¨Õ0ˆ
Ø×Ñ °ÐÔ5Ø Ð.FÐGÕGˆØ�=‰=�?Š?ÙØ×Ñœ(×+Ñ+×/Ñ/´·±Ó=×GÑGÓIÈDÕPÐ[bÐÔcØˆøÜô ØŠðús   —AB6 Á!AB6 Â6CÃCc               ó   € V ^8„  d   QhRR/# r:   r   )r   s   "r   r   r   ¡   s   € ÷ 9ñ 9 sñ 9r   c                 ó    € ^ RI Hp  V ! RR4      # )u  Read ``XAI_API_KEY`` via ``resolve_provider_secret`` (config â†’ profile scope â†’ env/.env â†’ pool).

Both the preferred-key and the no-OAuth fallback paths go through here so scope policy
(incl. failing closed in a multiplexed gateway turn) is never re-implemented per caller.
©Úresolve_provider_secretr   ra   )Útools.tool_backend_helpersr–   r•   s    r   Ú_resolve_explicit_xai_api_keyr˜   ¡   s   € õ CÙ" =°%Ó8Ð8r   c               ó   € V ^8„  d   QhRR/# r:   r   )r   s   "r   r   r   «   s   € ÷ pñ p ñ pr   c                 óž   € ^ RI Hp  \        V ! R4      ;'       g    V ! R4      ;'       g    R4      P                  4       P	                  R4      # )zG``HERMES_XAI_BASE_URL`` then ``XAI_BASE_URL``, stripped; '' when unset.©Úget_env_valueÚHERMES_XAI_BASE_URLÚXAI_BASE_URLr   Ú/)rf   rœ   r
   r'   Úrstripr›   s    r   Ú_xai_base_url_overrider¡   «   sA   € å/Ü‰}Ð2Ó3×ZÐZ±}À^Ó7T×ZÐZÐXZÓ[×aÑaÓc×jÑjÐknÓoÐor   Úforce_refreshFÚapi_key_hintÚprefer_api_keyc               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r¢   r   r£   r…   r¤   r   rB   r   )r   s   "r   r   r   ±   s2   € ÷ 4Iñ 4IØð4IØ2?ð4IØX\ð4Iàñ4Ir   c                óø  € ^ RI Hp V'       d]   \        \        4       ;'       g    R4      P	                  4       ;p'       d*   \        4       pVP                  V\        R7      pRRRVRV/#  ^ RIH	p V! R	4      pV '       d   VP                  V4      MVP                  4       p	V '       d   V	f   VP                  4       p	\        V	R
R4      ;'       g    \        V	RR4      p
\        \        V	RR4      ;'       g"    \        V	RR4      ;'       g    VP                  4      P	                  4       P                  R4      pVP                  \        4       VR7      p\        V
4      P	                  4       '       d    RR	R\        V
4      P	                  4       RV/#  ^ RIHp \        4       p\        V! R4      ;'       g    \        4      P	                  4       P                  R4      pRRRVRV/#   \         d     Lai ; i)ug  Resolve bearer credentials for direct xAI HTTP endpoints.

Default order: Hermes-managed xAI OAuth, then ``XAI_API_KEY`` (via ``get_env_value`` so
``~/.hermes/.env`` keys count). ``prefer_api_key=True`` inverts that for API-metered
endpoints where the subscription OAuth bearer authorizes but misbehaves (x_search answers
without citations, TTS 403s). Both branches honor ``HERMES_XAI_BASE_URL``/``XAI_BASE_URL``
behind the same origin-pinning validation. ``force_refresh=True`` forces an OAuth refresh;
pass the rejected bearer as ``api_key_hint`` so a multi-account pool refreshes the issuing
entry, not whichever its strategy selects first.

Prefers Hermes-managed xAI OAuth credentials when available, then falls back to ``XAI_API_KEY`` resolved
via ``hermes_cli.config.get_env_value`` so keys stored in ``~/.hermes/.env`` (the standard Hermes
location) are honored â€” not just ones already exported into ``os.environ``. This keeps direct xAI
endpoints (images, TTS, STT, etc.) aligned with the main runtime auth model and preserves the regression
contract from PR #17140 / #17163.
The key is read through :func:`tools.tool_backend_helpers.resolve_provider_secret` so profile secret
scoping is identical to the fallback branch, and the base URL honors ``HERMES_XAI_BASE_URL`` /
``XAI_BASE_URL`` behind the same origin-pinning validation as the OAuth branch. See #87045, #88040.
Nr   )ÚfallbackÚproviderra   Úapi_keyÚbase_url)Ú	load_poolr"   Úruntime_api_keyr$   Úruntime_base_urlrŸ   r›   rž   )Úhermes_cli.authÚauthr
   r˜   r'   r¡   Ú _xai_validate_inference_base_urlÚDEFAULT_XAI_BASE_URLÚagent.credential_poolr«   Útry_refresh_matchingÚselectÚgetattrÚDEFAULT_XAI_OAUTH_BASE_URLr    r4   rf   rœ   )r¢   r£   r¤   Úauth_modÚexplicit_keyÚoverriderª   r«   ÚpoolÚentryr$   Úfallback_base_urlrœ   r©   s   $$$           r   Úresolve_xai_http_credentialsr½   ±   sÏ  € õ, 'ß¬3Ô/LÓ/N×/TÐ/TÐRTÓ+U×+[Ñ+[Ó+]Ð]˜<Ö]ä)Ó+ˆØ×<Ñ<¸XÔPdÐ<ÓeˆØ˜E 9¨l¸JÈÐQÐQðÝ3Ù˜Ó%ˆß;H�×)Ñ)¨,Ô7ÈdÏkÉkËmˆß˜Uš]ð —K‘K“MˆEÜ˜uÐ&7¸Ó>×dÐdÄ'È%ÐQ_ÐacÓBdˆÜÜ�EÐ-¨tÓ4÷ 3ð 3Ü�u˜j¨"Ó-÷3ð 3à×2Ñ2ó
÷ ‰%‹'—&‘&˜“+ð	 	ð
 ×<Ñ<Ô=SÓ=UÐ`qÐ<ÓrˆÜˆ|Ó×"Ñ"×$Ò$Ø ¨Y¼¸LÓ8I×8OÑ8OÓ8QÐS]Ð_gÐhÐhð %õ
 0Ü+Ó-€GÜ‘= Ó0×HÐHÔ4HÓI×OÑOÓQ×XÑXÐY\Ó]€HØ˜˜y¨'°:¸xÐHÐHøô ô Ùðús1   Á,G+ Â(G+ Â+'G+ Ã&G+ Ã:G+ ÄBG+ Ç+G9Ç8G9i �' i £ >   Ú1ÚonÚyesÚtruerc   >   rP   ÚnoÚoffÚfalseÚdisabled)Ú__doc__Ú
__future__r   rq   r/   Úosru   Útypingr   r   r   r±   r[   rX   r   r8   r@   rD   rJ   rK   rM   r\   rg   r|   rƒ   r’   r˜   r¡   r½   r   r   r   Ú<module>rÊ      s¢   ðÙ 6å "ã Û Û 	Û ß &Ñ &ð -Ð Ø(9Ð %Ø)9Ð &õ;õõ>&õ3ò
 4€Ú6€õõ_õ"õ õõ"õ$9õpð4IØ"ð4IØBFð4IØ_d÷4Iñ 4Ir   