+
    lHàjù   ã                  ód  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RIH	t	H
t
 ^ RIHt ^ RIHt ]P                  ! ]4      tRtRt^xt]! R	R
7       ! R R4      4       tR R ltR tR R ltR R ltR R ltR R ltR&R R lltR R ltR R ltR R ltR'R  R! llt R(R" R# llt!R'R$ R% llt"R# ))zIGeneric managed-tool gateway helpers for Nous-hosted vendor passthroughs.)ÚannotationsN)Ú	dataclass)ÚCallableÚOptional©Úget_hermes_home)Úmanaged_nous_tools_enabledznousresearch.comÚhttpsT)Úfrozenc                  ó@   € ] tR t^t$ R]R&   R]R&   R]R&   R]R&   RtR# )	ÚManagedToolGatewayConfigÚstrÚvendorÚgateway_originÚnous_user_tokenÚboolÚmanaged_mode© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__annotations__Ú__static_attributes__r   ó    Ú?/home/ubuntu/.hermes/hermes-agent/tools/managed_tool_gateway.pyr   r      s   ‡ àƒKØÓØÓØ×r   r   c               ó    € V ^8„  d   QhRRRR/# )é   ÚvalueÚobjectÚreturnúOptional[str]r   )Úformats   "r   Ú__annotate__r#      s   € ÷ Oñ O�&ð O˜]ñ Or   c                ó~   € \        V \        4      '       d'   V P                  4       '       d   V P                  4       # R# )z:*value* stripped when it is a non-blank string, else None.N)Ú
isinstancer   Ústrip)r   s   &r   Ú_cleanr'      s)   € ä& u¬c×2Ò2°u·{±{·}²}ˆ5�;‰;‹=ÐNÈ$ÐNr   c                 ó$   € \        4       R,          # )zDReturn the Hermes auth store path, respecting HERMES_HOME overrides.z	auth.jsonr   r   r   r   Úauth_json_pathr)   "   s   € äÓ˜{Õ*Ð*r   c               ó   € V ^8„  d   QhRR/# )r   r    zOptional[dict]r   )r"   s   "r   r#   r#   '   s   € ÷ ñ  >ñ r   c                 óÂ   €  ^ RI Hp  V ! R4      p\        V\        4      '       g   R# ^ RIHpHp V! V4      '       d   V! 4       '       g   R# V#   \         d     R# i ; i)a<  The profile's Nous state, or None. A free-tier identity counts only while guests are allowed:
with ``nous.guest: false`` it is invisible here, so no cached or refreshed token of it is ever
attached to a request.

Resolves through the same profile-then-global-root fallback every other credential reader
uses: a profile created with ``share_auth`` has no ``auth.json`` of its own and signs in with
the root identity. Reading only ``HERMES_HOME/auth.json`` made that profile look signed out to
the connector gate alone, so ``manage_connections`` vanished from its tool list.)Úget_provider_auth_stateÚnousN)Úguest_allowedÚis_guest_state)Úhermes_cli.authr,   r%   ÚdictÚhermes_cli.anon_authr.   r/   Ú	Exception)r,   Únous_providerr.   r/   s       r   Ú_read_nous_provider_stater5   '   sS   € ðÝ;á/°Ó7ˆÜ˜-¬×.Ò.ÙßFá˜-×(Ò(±·²ÙØÐøÜô Úðús!   ‚$A ¨A ¾A ÁA ÁAÁAc               ó   € V ^8„  d   QhRR/# ©r   r    r!   r   )r"   s   "r   r#   r#   ?   s   € ÷ ñ  =ñ r   c                 ó€   € ^ RI Hp Hp  V! R4      p\        V4      #   T  d    \        P                  ! R4      p L*i ; i)aH  Read the TOOL_GATEWAY_USER_TOKEN override through the secret scope. Scope verdict is authoritative
when installed (a scoped miss must NOT borrow the process env under multiplex); ``os.environ`` only
when unscoped. Any non-UnscopedSecretError failure propagates -- a failed scoped read must never
silently borrow the ambient env.)ÚUnscopedSecretErrorÚ
get_secretÚTOOL_GATEWAY_USER_TOKEN)Úagent.secret_scoper9   r:   ÚosÚgetenvr'   )r9   r:   Úexplicits      r   Ú_read_user_token_overrider@   ?   sE   € ÷
 Cð8ÙÐ7Ó8ˆô �(ÓÐøð ô 8Ü—9’9Ð6Ó7Šð8ús   Š �=¼=c               ó   € V ^8„  d   QhRR/# r7   r   )r"   s   "r   r#   r#   M   s   € ÷ eñ e ñ er   c                 ód   € ^ RI Hp  \        4       ;'       g    \        V ! \	        4       4      4      # )uÄ   Cheap token probe: env override or cached auth-store token, no expiry check and no network â€”
availability scans must stay off the synchronous OAuth refresh path (:func:`read_nous_access_token`).©Úheld_connectors_token)r2   rD   r@   r'   r5   rC   s    r   Úpeek_nous_access_tokenrE   M   s'   € õ ;ä$Ó&×dÐd¬&Ñ1FÔG`ÓGbÓ1cÓ*dÐdr   c               ó   € V ^8„  d   QhRR/# r7   r   )r"   s   "r   r#   r#   U   s   € ÷ ñ  ñ r   c                 ó  € \        4       ;p '       d   V # \        4       ;'       g    / pV'       g   R# ^ RIHp \	        V! V\
        R7      4      ;p'       d   V# \        4       p ^ RIHp \	        V! \
        R7      4      ;p'       d   V#  V#   \         dg   p^ RIH
p \        Yx4      '       d/   \        T\        TP                  ;'       g    R4      4      u Rp?# \        P!                  RT4        Rp?T# Rp?ii ; i)	a–  Read a Nous Subscriber OAuth access token from auth store or env override.

A read: with no Nous identity there is no bearer and the answer is None. The free-tier identity
is created by the boot bootstrap or the first hosted connector action, never on a token-read
path (NS-845 Q1.2). A retired free-tier credential IS replaced here, once: that is the explicit
dead-credential rule, shared with inference.
NrC   )Úskew_seconds©Úresolve_nous_access_token©Úrefresh_skew_seconds)ÚAnonCredentialDeadÚanon_credential_deadz$Nous access token refresh failed: %s)r@   r5   r2   rD   r'   Ú'_NOUS_ACCESS_TOKEN_REFRESH_SKEW_SECONDSrE   r0   rJ   r3   rM   r%   Ú_replace_dead_guest_tokenr   ÚcodeÚloggerÚdebug)	r?   r4   rD   Úfresh_tokenÚcached_tokenrJ   Úrefreshed_tokenÚexcrM   s	            r   Úread_nous_access_tokenrX   U   sæ   € ô -Ó.Ð.€xÖ.ØˆÜ-Ó/×5Ð5°2€MßÙÝ:äÑ2°=ÔOvÔwÓxÐx€{ÖxØÐÜ)Ó+€LðBÝ=ä$Ñ%>ÔT{Ô%|Ó}Ð}ˆ?Ö}Ø"Ð"ð ~ð Ðøô ô Bõ 	<ä�c×.Ò.Ü,¨]¼CÀÇÁ×@bÐ@bÐLbÓ<cÓdÕdÜ�‰Ð;¸S×AÐAØÐûðBús*   Á%%B ÂC?Â4C:Ã
C:ÃC?ÃC:Ã:C?c               ó$   € V ^8„  d   QhRRRRRR/# )r   Ú
dead_stater1   rQ   r   r    r!   r   )r"   s   "r   r#   r#   w   s"   € ÷ ñ ¨$ð °cð ÐWdñ r   c                ó  € ^ RI HpHpHp ^ RIHp V! WP                  R4      R7       W8X  d   R#  V! RR7      f   R# \        V! \        R7      4      #   \         d"   p\        P                  R	T4        Rp?R# Rp?ii ; i)
é    )ÚANON_ACCOUNT_LOCKEDÚclear_dead_guestÚensure_portal_identityrI   Ú
anon_token)Ú
dead_tokenNT)r?   rK   z@Nous free tier replacement after a retired credential failed: %s)r2   r]   r^   r_   r0   rJ   Úgetr'   rO   r3   rR   rS   )rZ   rQ   r]   r^   r_   rJ   rW   s   &&     r   rP   rP   w   sm   € ßbÑbÝ9á�T§n¡n°\Ó&BÕCàÔ"ÙðÙ!¨4Ô0Ò8ÙÜÑ/ÔElÔmÓnÐnøÜô Ü�‰ÐWÐY\Ô]Ýûðús   ²A ¿A ÁBÁ A<Á<Bc               ó   € V ^8„  d   QhRR/# )r   r    r   r   )r"   s   "r   r#   r#   ˆ   s   € ÷ ñ  ñ r   c                 ó¬   € \         P                  ! RR4      P                  4       P                  4       ;'       g    \        p V R9  d   \        R4      hV # )z,Return configured shared gateway URL scheme.ÚTOOL_GATEWAY_SCHEMEÚ z-TOOL_GATEWAY_SCHEME must be 'http' or 'https'>   Úhttpr	   )r=   r>   r&   ÚlowerÚ_DEFAULT_TOOL_GATEWAY_SCHEMEÚ
ValueError)Úschemes    r   Úget_tool_gateway_schemerl   ˆ   sH   € ä�YŠYÐ,¨bÓ1×7Ñ7Ó9×?Ñ?ÓA×aÐaÔEa€FØÐ&Ô&ÜÐHÓIÐIØ€Mr   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r    r   )r"   s   "r   r#   r#   �   s   € ÷ Mñ M Sð M¨Sñ Mr   c                óh  € \         P                  ! V P                  4       P                  RR4       R2R4      P	                  4       P                  R4      ;p'       d   V# \         P                  ! RR4      P	                  4       P	                  R4      ;'       g    \        p\        4        RV  RV 2# )	z0Return the gateway origin for a specific vendor.Ú-Ú_Ú_GATEWAY_URLrf   Ú/ÚTOOL_GATEWAY_DOMAINz://z	-gateway.)r=   r>   ÚupperÚreplacer&   ÚrstripÚ_DEFAULT_TOOL_GATEWAY_DOMAINrl   )r   Úexplicit_vendor_urlÚshared_domains   &  r   Úbuild_vendor_gateway_urlrz   �   s™   € ä Ÿiši¨6¯<©<«>×+AÑ+AÀ#ÀsÓ+KÐ*LÈLÐ(YÐ[]Ó^×dÑdÓf×mÑmÐnqÓrÐrÐÖrØ"Ð"Ü—I’IÐ3°RÓ8×>Ñ>Ó@×FÑFÀsÓK×kÐkÔOk€MÜ%Ó'Ð(¨¨F¨8°9¸]¸OÐLÐLr   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r    ú"Optional[ManagedToolGatewayConfig]r   )r"   s   "r   r#   r#   ˜   s   € ÷ Fñ F˜Cð FÐCeñ Fr   c                ó˜   € T;'       g    \         ! V 4      pT;'       g    \        ! 4       pV'       d	   V'       g   R # \        WVRR7      # )NT)r   r   r   r   )rz   rX   r   )r   Úgateway_builderÚtoken_readerr   r   s   &&&  r   Ú_vendor_gatewayr€   ˜   sO   € Ø%×AÐAÔ)AÐAÀ6ÓJ€NØ#×=Ð=Ô'=Ð=Ó@€Oß§ÙÜ#¨6Ðbqð  AEô  Fð  Fr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r   r   r~   úOptional[Callable[[str], str]]r   ú%Optional[Callable[[], Optional[str]]]r    r|   r   )r"   s   "r   r#   r#       s2   € ÷ Bñ BØðBØ"@ðBà7ðBàCeñBr   c                ó>   € \        4       '       g   R# \        WV4      # )zQResolve shared managed-tool gateway config for a vendor (entitled accounts only).N)r   r€   ©r   r~   r   s   &&&r   Úresolve_managed_tool_gatewayr†       s   € ô &×'Ò'ÙÜ˜6°LÓAÐAr   c               ó    € V ^8„  d   QhRRRR/# )r   r   rƒ   r    r|   r   )r"   s   "r   r#   r#   ©   s    € ÷ =ñ =Ð.Sð =ð  `Bñ =r   c                ó   € \        RRV 4      # )ad  Perplexity ``search_type: "fast"`` is served to every Nous identity with no funding check, the
anonymous guest tier included, so it needs a token this profile may use (guest-disabled and refresh
rules live in the reader), not paid entitlement or a registered account. Search only: every other
vendor route goes through :func:`resolve_managed_tool_gateway`.Ú
perplexityN)r€   )r   s   &r   Úresolve_free_search_gatewayrŠ   ©   s   € ô
 ˜<¨¨|Ó<Ð<r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r   r   r~   r‚   r   rƒ   r    r   r   )r"   s   "r   r#   r#   ±   s2   € ÷ Rñ RØðRØ"@ðRà7ðRàCGñRr   c                ó<   € \        YT;'       g    \        R7      RJ# )zÙTrue when a gateway URL and a likely-usable Nous token are present. Defaults to
:func:`peek_nous_access_token` (no OAuth refresh); callers about to make a real request use
:func:`resolve_managed_tool_gateway` instead.)r~   r   N)r†   rE   r…   s   &&&r   Úis_managed_tool_gateway_readyr�   ±   s:   € ô (¨Ð^j÷  _Eð  _Eô  oEô  Fð  NRð  Rð  Rr   )rN   )NN)N)#Ú__doc__Ú
__future__r   ÚjsonÚloggingr=   Údataclassesr   Útypingr   r   Úhermes_constantsr   Útools.tool_backend_helpersr   Ú	getLoggerr   rR   rw   ri   rO   r   r'   r)   r5   r@   rE   rX   rP   rl   rz   r€   r†   rŠ   r�   r   r   r   Ú<module>r—      s®   ðÙ Oå "ã Û Û 	Ý !ß %å ,Ý Aà	×	Ò	˜8Ó	$€à1Ð Ø&Ð Ø*-Ð 'ñ �$Ô÷ð ó ðõOò
+õ
õ0õeõ÷Dõ"õMõF÷B÷=÷Rñ Rr   