+
    „WÝj¶ ã                   óˆ  a € Rë tœ0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIH	t	H
t
Ht ^ RIHtHt ^ RIHt Rs] ^ k ]! 4       t]! R]R7      t] ^k Rìt] ^k Rt] ^k 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 lt]P@                  ! R4      t!R R lt"R R lt#R  R! lt$R" R# lt%/ t&] ^k RíR$ R% llt'R& R' lt(R( R) lt)Rs*] ^k R* R+ lt+R, R- lt,R. R/ lt-].! 0 Rîm4      t/] ^k ]! R1R24      t0Rs1] ^k R3R/R4 R5 llt2R6t3Rït4R7 R8 lt5R9 R: lt6R; R< lt7R= R> lt8R? R@ lt9Rðt:]P@                  ! RA4      t;RB RC lt<RD RE lt=RF RG lt>RH RI lt?RJ RK lt@RL RM ltARN RO ltBRP RQ ltCRíRR RS lltDRíRT RU lltERíRV RW lltFR3R/RX RY lltGRíRZ R[ lltHR\. RñOR]. RòOR0R^R0./tIR_ R` ltJRa Rb ltKRc Rd ltL]! ]M4      P�                  4       Pž                  tPRe Rf ltQRg Rh ltRRíRi Rj lltSRk Rl ltTRíRm Rn lltURo Rp ltVRq Rr ltWRíRs Rt lltXRu Rv ltYRw Rx ltZRy Rz lt[RíR{ R| l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…R†R‡R†RˆR†R‰RŠR‹RŠRŒRŠR�RŠ/taRíRŽ R� lltbR� R‘ ltcRôtdR’te^tfR“tgR”thRsi^2tjR• R– ltkRõtlR—tm].! R˜R™04      tn].! 0 Röm4      toRíRš R› lltpRœ R� ltqRž RŸ ltrR  R¡ ltsR3R/R¢ R£ llttRíR¤R¥/R¦ R§ llltuR]f3R¨ R© lltvRª R« ltwRíR¬ R­ lltxR® R¯ ltyR° R± ltzR÷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Ã 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Ñ llt‹RÒtŒRÓt�RÔtŽ]Ž RÕ2t�].! 0 Rùm4      t�] ^k RÖ R× lt‘RØt’RÙR/RÚ RÛ llt“RÜ RÝ lt”RÞ Rß lt•RÙR/Rà Rá llt–].! 0 Rúm4      t—Râ Rã lt˜Rä Rå lt™RæR/Rç Rè lltšRé Rê lt›R# )ûux   Shared constants for Hermes Agent.

Import-safe, stdlib-only â€” importable from anywhere without circular-import risk.
N)ÚCallableÚMappingÚMutableMapping)Ú
ContextVarÚToken©ÚPathFÚ_HERMES_HOME_OVERRIDE©ÚdefaultÚkaomojic                óT   € V ^8„  d   QhR\         \        ,          R,          R\        /# ©é   ÚpathNÚreturn)Ústrr   r   )Úformats   "ÚDC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_constants.pyÚ__annotate__r      s#   € ÷ ,ñ ,¤3¬¥:°Õ#4ð ,¼ñ ,ó    c                óV   € V f   \         M
\        V 4      p\        P                  V4      # )z›Set a context-local Hermes home override and return its reset token.

Deliberately does not mutate ``os.environ`` (shared by every thread in the process).
)Ú_UNSETr   r	   Úset)r   Úvalues   & r   Úset_hermes_home_overrider      s$   € ð
 %)¢L�&´c¸$³i€EÜ ×$Ñ$ UÓ+Ð+r   c                ó(   € V ^8„  d   QhR\         RR/# )r   Útokenr   N)r   )r   s   "r   r   r   #   s   € ÷ 'ñ '¤eð '°ñ 'r   c                ó0   € \         P                  V 4       R# )z8Restore the previous context-local Hermes home override.N)r	   Úreset)r   s   &r   Úreset_hermes_home_overrider    #   s   € ä×Ñ Ö&r   c                ó2   € V ^8„  d   QhR\         R,          /# ©r   r   N©r   )r   s   "r   r   r   (   s   € ÷ Jñ J¤#¨¥*ñ Jr   c                 óh   € \         P                  4       p V \        Jd   V '       d   \        V 4      # R# )z=Return the active context-local Hermes home override, if any.N)r	   Úgetr   r   ©Úoverrides    r   Úget_hermes_home_overrider(   (   s(   € ä$×(Ñ(Ó*€HØ$¬FÓ2·xŒ3ˆx‹=ÐIÀTÐIr   c                ó0   € V ^8„  d   QhR\         R\        /# ©r   r   r   ©r   r   )r   s   "r   r   r   .   s   € ÷ >ñ >œcð >¤dñ >r   c                óŒ   € \        \        P                  P                  \        P                  P	                  V 4      4      4      # )z>Expand environment and user-home syntax in a Hermes home path.)r   Úosr   Ú
expanduserÚ
expandvars©r   s   &r   Ú_expand_hermes_homer1   .   s+   € ä”—‘×"Ñ"¤2§7¡7×#5Ñ#5°dÓ#;Ó<Ó=Ð=r   c                óx   € V ^8„  d   QhR\         \        \        3,          R\        . \        3,          R\        /# )r   ÚenvironÚ	user_homer   )r   r   r   r   )r   s   "r   r   r   3   s7   € ÷ .ñ .¬7´3¼°8Õ+<ð .ÌÐRTÔVZÐRZÕI[ð .Ô`dñ .r   c                ó*  € V P                  RR4      p\        P                  R8X  dY   V P                  RR4      P                  4       pV'       d   \	        V4      MV! 4       R,          R,          pVRV,           ,          # V! 4       RV,           ,          # )	zRThe platform default that *environ* names, with the literal data-directory suffix.ÚHERMES_DATA_DIR_SUFFIXÚ Úwin32ÚLOCALAPPDATAÚAppDataÚLocalÚhermesú.hermes)r%   ÚsysÚplatformÚstripr   )r3   r4   ÚsuffixÚlocal_appdataÚbases   &&   r   Ú_platform_default_hermes_homerD   3   su   € à�[‰[Ð1°2Ó6€FÜ
‡|�|�wÔØŸ™ N°BÓ7×=Ñ=Ó?ˆß&3Œt�MÔ"¹»ÀyÕ9PÐSZÕ9ZˆØ�x &Õ(Õ)Ð)Ù‹;˜) fÕ,Õ-Ð-r   c                ó$   € V ^8„  d   QhR\         /# ©r   r   r   )r   s   "r   r   r   =   s   € ÷ @ñ @¬4ñ @r   c                 óR   € \        \        P                  \        P                  4      # )zCReturn the platform default with the literal data-directory suffix.)rD   r-   r3   r   Úhome© r   r   Ú!_get_platform_default_hermes_homerJ   =   s   € ä(¬¯©´T·Y±YÓ?Ð?r   c                ó$   € V ^8„  d   QhR\         /# rF   r   )r   s   "r   r   r   B   s   € ÷ %ñ %”tñ %r   c                 óâ   €  ^ RI p \        V P                  \        P                  ! 4       4      P
                  4      #   \        \        \        \        3 d    \        \        4       4      u # i ; i)zøThe OS account's home from the password database, never ``$HOME``: harnesses and profile isolation
repoint HOME (root under ``sudo`` has uid 0 too, which keeps the #108674 remap). Falls back to the
shared real-home resolver where pwd cannot answer.N)Úpwdr   Úgetpwuidr-   ÚgetuidÚpw_dirÚImportErrorÚKeyErrorÚOSErrorÚAttributeErrorÚget_real_home)rM   s    r   Ú_account_homerV   B   sO   € ð%ÛÜ�C—L‘L¤§¢£Ó-×4Ñ4Ó5Ð5øÜœ¤7¬NÐ;ô %Ü”M“OÓ$Ò$ð%ús   ‚:= ½.A.Á-A.c                ó$   € V ^8„  d   QhR\         /# rF   r   )r   s   "r   r   r   M   s   € ÷ wñ w¤Tñ wr   c                 ó  a€ \        4       o \        P                  ! 4       P                  4       SP                  4       8H  p V '       d   \        4       # \        \        P                  V3R l4      #   \        \
        3 d    Rp  LEi ; i)aÙ  The platform default of the OS ACCOUNT, never of a foreign process ``HOME``.

Host service identities (``systemctl --user`` units, LaunchAgents) belong to the account, and their
definitions are found under the account home. A process started with ``HOME=<scratch>`` used to call
``<scratch>/.hermes`` native, name the bare ``hermes-gateway`` unit, and stop the account's real
gateway through it. When the process HOME is the account home the two answers are the same home.
Fc                  ó   <€ S # ©NrI   )Úaccounts   €r   Ú<lambda>Ú-account_default_hermes_home.<locals>.<lambda>Z   s   ø€ Ñnur   )
rV   r   rH   ÚresolverS   ÚRuntimeErrorrJ   rD   r-   r3   )Úsamer[   s    @r   Úaccount_default_hermes_homera   M   so   ø€ ô ‹o€GðÜ�yŠy‹{×"Ñ"Ó$¨¯©Ó(9Ñ9ˆ÷ 37Ô,Ó.ÐvÔ<YÔZ\×ZdÑZdÔfuÓ<vÐvøô ”\Ð"ô ØŠðús   �4A1 Á1BÂBc                óJ   € V ^8„  d   QhR\         R\         R,          R\         /# )r   Únative_homeÚenv_pathNr   r   )r   s   "r   r   r   ]   s%   € ÷ ñ ¤ð ´¸µð Äñ r   c                óú   € Vf   V #  VP                  4       P                  V P                  4       4       V #   \         d9    TP                  P                  R8X  d   TP                  P                  u # Tu # i ; i)zUThe root that holds *env_path*: the native home, a custom root, or *env_path* itself.Úprofiles)r^   Úrelative_toÚ
ValueErrorÚparentÚname)rc   rd   s   &&r   Ú_hermes_root_ofrk   ]   sv   € àÒØÐðZØ×ÑÓ×&Ñ& {×':Ñ':Ó'<Ô=ð Ðøô ô ZØ)1¯©×)=Ñ)=ÀÔ)Kˆx�‰×%Ñ%ÒYÐQYÒYðZús   ˆ-7 ·<A:Á5A:Á9A:z*%([^%]+)%|\$\{([^}]+)\}|\$([A-Za-z0-9_-]+)c                ó`   € V ^8„  d   QhR\         \        \        3,          R\        R,          /# )r   r3   r   N)r   r   r   )r   s   "r   r   r   k   s+   € ÷ Vñ V¬´´c°Õ):ð V¼tÀd½{ñ Vr   c                ó’  aa	€ V P                  4        UUu/ uF  w  rVP                  4       VbK  	  uppoSP                  \        P                  R8X  d   RMRR4      P                  4       o	R V	3R llpSP                  RR4      P                  4       p \        SV4      pV'       g   V# \        P                  V3R lV4      pVR	8X  g   VP                  R4      '       d   \        V! 4       4      VR
,          ,           p\        T4      pTP                  4       '       d   \        YW4      # R# u uppi   \         d     R# i ; i)a²  The Hermes root that a process started with *environ* resolves, or None.

Applies the root rules of ``get_default_hermes_root`` to another process's
environment. ``%NAME%``, ``${NAME}`` and ``$NAME`` references and a leading
``~`` expand from *environ* alone, never from this process. Returns None
when the answer depends on anything outside *environ*: a relative
HERMES_HOME, an undefined variable, or a missing user profile folder.
r8   ÚUSERPROFILEÚHOMEr7   c                ó$   € V ^8„  d   QhR\         /# rF   r   )r   s   "r   r   Ú1hermes_root_for_environment.<locals>.__annotate__w   s   € ÷ ñ ”tñ r   c                  ó@   <€ S '       g   \        R 4      h\        S 4      # )zno user profile folder)ÚLookupErrorr   )Úprofiles   €r   r4   Ú.hermes_root_for_environment.<locals>.user_homew   s   ø€ ßÜÐ6Ó7Ð7Ü�G‹}Ðr   ÚHERMES_HOMEc                 ód   <€ SV P                  V P                  4      P                  4       ,          # rZ   )ÚgroupÚ	lastindexÚupper)ÚmatchÚnamess   &€r   r\   Ú-hermes_root_for_environment.<locals>.<lambda>�   s    ø€ °E¸%¿+¹+ÀeÇoÁoÓ:V×:\Ñ:\Ó:^Ö4_r   Ú~ºé   NNN)ú~/z~\)Úitemsrz   r%   r>   r?   r@   rD   Ú_ENV_REFERENCEÚsubÚ
startswithr   rs   r   Úis_absoluterk   )
r3   Úkeyr   r4   Úrawrc   Úexpandedrd   r|   rt   s
   &       @@r   Úhermes_root_for_environmentrŠ   k   s  ù€ ð 3:·-±-´/ÔB±/¡J CˆS�Y‰Y‹[˜%Ò±/ÒB€EØ�i‰i¬¯©¸Ô)@™ÀfÈbÓQ×WÑWÓY€G÷ð ð
 �)‰)�M 2Ó
&×
,Ñ
,Ó
.€CðÜ3°E¸9ÓEˆßØÐÜ!×%Ñ%Ô&_ÐadÓeˆØ�sŒ?˜h×1Ñ1°-×@Ò@Ü™9›;Ó'¨(°2­,Õ6ˆHô �H‹~€HØ5=×5IÑ5I×5KÒ5KŒ?˜;Ó1ÐUÐQUÐUùó' Cøô  ô Úðús   –D1ÂD7 Â-AD7 Ä7EÅEc                ó2   € V ^8„  d   QhR\         R,          /# r"   r   )r   s   "r   r   r   Š   s   € ÷ ñ ¤4¨$¥;ñ r   c                 óh  € \        \        R4      '       d   \        P                  ! 4       ^ 8w  d   R# \        P                  P	                  RR4      P                  4       p V '       d   V R8X  d   R# ^ RIp \        VP                  V 4      P                  4      R,          #   \         d     R# i ; i)a  The invoking user's native ``~/.hermes`` when this process is root under ``sudo``, else None.

sudo strips HERMES_HOME and sets HOME=/root, so the process's own default is root's; the profile
store and the system service being operated on belong to SUDO_USER.
ÚgeteuidNÚ	SUDO_USERr7   Úrootr=   )Úhasattrr-   r�   r3   r%   r@   rM   r   ÚgetpwnamrP   rR   )Ú	sudo_userrM   s     r   Úsudo_invoker_default_homer“   Š   s„   € ô ”2�y×!Ò!¤R§Z¢Z£\°QÔ%6ÙÜ—
‘
—‘˜{¨BÓ/×5Ñ5Ó7€Iß˜	 VÔ+ÙÛðÜ�C—L‘L Ó+×2Ñ2Ó3°iÕ?Ð?øÜô Úðús   Á7*B" Â"B1Â0B1c                ó   € V ^8„  d   QhRR/# r"   rI   )r   s   "r   r   r   �   s   € ÷ ñ  Tñ r   c                 ó8  € \         '       d   R# Rs  \        4       p V R,          pVP                  4       '       d!   VP                  RR7      P	                  4       MRpV'       d‰   VR8w  d€   RV: R	X  R
V: R2p\        P                  ! \        4      ;_uu_ 4        \        P                  P                  VR,           4       \        P                  P                  4        RRR4       R# R# R#   \
        \        3 d    Rp L§i ; i  + '       g   i     R# ; i)z`Warn once when HERMES_HOME is unset but a non-default profile is sticky-active (wrong fallback).NTÚactive_profileúutf-8©Úencodingr7   r   zB[HERMES_HOME fallback] HERMES_HOME is unset but active profile is z. Falling back to u'   , which is the DEFAULT profile â€” not zŒ. Any data this process writes will land in the wrong profile. The subprocess spawner should pass HERMES_HOME explicitly (see issue #18594).Ú
)Ú_profile_fallback_warnedrJ   ÚexistsÚ	read_textr@   ÚUnicodeDecodeErrorrS   Ú
contextlibÚsuppressÚ	Exceptionr>   ÚstderrÚwriteÚflush)Úfallback_homeÚactive_pathÚactiveÚmsgs       r   Ú_warn_profile_fallback_oncer©   �   s   € ÷  ÓÙð  $ÐðÜ9Ó;ˆØ#Ð&6Õ6ˆØDO×DVÑDV×DXÒDX�×&Ñ&°Ð&Ó8×>Ñ>Ô@Ð^`ˆ÷ �&˜IÔ%ðØ ™Ð#5°m°_ð E.Ø.4©Zð 8"ð#ð 	ô × Ò ¤×+Õ+Ü�J‰J×Ñ˜S 4�ZÔ(Ü�J‰J×ÑÔ÷ ,Ñ+ñ &�vøô ¤Ð(ô ØŠðú÷ ,×+Ð+ús   ’AC/ ÂADÃ/DÄDÄD	c                ó$   € V ^8„  d   QhR\         /# rF   r   )r   s   "r   r   r   ¼   s   € ÷ %ñ %œñ %r   c                 óÌ   € \        4       p V '       d   \        V 4      # \        P                  P	                  RR4      P                  4       '       g   \        4        \        4       # )uU   Hermes home: context-local override â†’ ``HERMES_HOME`` env var â†’ platform default.rv   r7   )r(   r1   r-   r3   r%   r@   r©   Úget_process_hermes_homer&   s    r   Úget_hermes_homer­   ¼   sE   € ä'Ó)€HßÜ" 8Ó,Ð,Ü�:‰:�>‰>˜-¨Ó,×2Ñ2×4Ò4Ü#Ô%Ü"Ó$Ð$r   c                óT   € V ^8„  d   QhR\         \        ,          R,          R\         /# r   r+   )r   s   "r   r   r   Î   s#   € ÷ ñ œ#¤�* tÕ+ð ´sñ r   c           	     ó¾  € V e   \        V 4      M	\        4       p\        V4      p\        P	                  V4      pVe   V# VP                  4       p VP                  RR7      p\        P                  P                  \        T4      4      pT\        T&   T#   \         d<    \        P                  P                  \        TP                  RR7      4      4      u # i ; i)af  Stable registry key for a Hermes home/profile dir.

``strict=False`` so profiles whose directories don't exist yet still get a key.

The resolved value is remembered per input path. A directory that does
not exist yet is resolved without touching the cache, because the answer
can change once it is created (e.g. part of the path turns out to be a symlink).
T©ÚstrictF)r   r­   r   Ú_HOME_KEY_CACHEr%   r.   r^   rS   r-   r   Únormcase)r   Ú	candidaterˆ   Úcachedr‰   Úresolvedr‡   s   &      r   Úhermes_home_keyr·   Î   sÈ   € ð #Ò.”�T”
´OÓ4E€IÜ
ˆi‹.€CÜ× Ñ  Ó%€FØÒØˆØ×#Ñ#Ó%€HðEØ×#Ñ#¨4Ð#Ó0ˆô
 �'‰'×
Ñ
œ3˜x›=Ó
)€CØ„O�CÑØ€Jøô ô Eô �w‰w×Ñ¤ H×$4Ñ$4¸EÐ$4Ó$BÓ CÓDÒDðEús   ÁB ÂACÃCc                ó   € V ^8„  d   QhRR/# r"   rI   )r   s   "r   r   r   è   s   € ÷ ñ  Tñ r   c                 ó.   € \         P                  4        R# )zJForget every remembered home key (for tests that move a home dir on disk).N)r²   ÚclearrI   r   r   Úreset_hermes_home_key_cacher»   è   s   € ä×ÑÖr   c                ó$   € V ^8„  d   QhR\         /# rF   r   )r   s   "r   r   r   í   s   € ÷ 	Tñ 	T¤ñ 	Tr   c                 ó˜   € \         P                  P                  RR4      P                  4       p V '       d   \	        V 4      # \        4       # )a…  Hermes home of the running process, ignoring task overrides.

For process-level assets (theme YAML, dashboard plugin manifests) that must stay visible while a
request is scoped to another profile (e.g. embedded ``/chat`` under ``--open-profile``). Follows
``HERMES_HOME`` live on purpose: routed-profile DECISIONS compare against
:func:`get_routing_process_hermes_home` instead (#119242).
rv   r7   )r-   r3   r%   r@   r1   rJ   )Úvals    r   r¬   r¬   í   s8   € ô �*‰*�.‰.˜¨Ó
+×
1Ñ
1Ó
3€Cß'*Ô˜sÓ#ÐSÔ0QÓ0SÐSr   c                óL   € V ^8„  d   QhR\         \        ,          R,          RR/# r   r+   )r   s   "r   r   r   ý   s'   € ÷ Fñ F¤#¬¥*¨tÕ"3ð F¸ñ Fr   c                ó,   € V f   RsR# \        V 4      sR# )aþ  Pin the home this process serves as its own profile, for "is this task routed?" decisions.

An embedding host that serves several profiles and mirrors the active turn's profile into
``os.environ["HERMES_HOME"]`` for legacy readers (Hermes WebUI) otherwise makes every turn's own
profile look like the launch profile: ``agent.secret_scope.serves_routed_profile()`` turns
False and that turn's MCP connections fall back to bare, cross-profile names; the sibling
launch-home checks (``secret_scope._is_process_home``, ``tools.environments.local._is_routed_home``,
``hermes_cli.env_loader._process_hermes_home``) misjudge the same way. ``None`` clears the pin.

Process-global on purpose: it names the process's own identity, not a per-task value. It is NOT
folded into :func:`get_process_hermes_home`: :func:`get_hermes_home` falls back to that for
tasks carrying no override, and the host's mirror exists precisely so those readers see the
served profile. Hosts that never mutate ``HERMES_HOME`` need not call this (no-op).
N)r   Ú_PINNED_PROCESS_HERMES_HOMEr0   s   &r   Úpin_process_hermes_homerÂ   ý   s   € ð  +/ª, $Ò¼CÀ»IÒr   c                ó$   € V ^8„  d   QhR\         /# rF   ©Úbool)r   s   "r   r   r     s   € ÷ 3ñ 3¤tñ 3r   c                  ó   € \         R J# rZ   )rÁ   rI   r   r   Úprocess_hermes_home_is_pinnedrÇ     s   € Ü&¨dÐ2Ð2r   c                ó$   € V ^8„  d   QhR\         /# rF   r   )r   s   "r   r   r     s   € ÷ Pñ P¬ñ Pr   c                 óH   € \         p V '       d   \        V 4      # \        4       # )z`Launch home for routed-profile decisions: the pinned home, else :func:`get_process_hermes_home`.)rÁ   r1   r¬   )Úpinneds    r   Úget_routing_process_hermes_homerË     s   € ä(€Fß*0Ô˜vÓ&ÐOÔ6MÓ6OÐOr   ÚnodeÚ	downloadsÚ
connectorsrH   c                óT   € V ^8„  d   QhR\         \        ,          R,          R\        /# ©r   rH   Nr   r+   )r   s   "r   r   r   (  s#   € ÷ ñ ¤S¬4¥Z°$Õ%6ð Ä$ñ r   c                óx  € \        4       pV e   \        V 4      P                  4       M-\        P                  P                  RR4      P                  4       pV'       d   \        V4      MRp\        V4      Ve   \        V4      MR3p\        pVe   VR,          V8X  d
   V^,          # \        W4      p. VOVN5sV# )zDRoot of an explicit home, or the process home when none is supplied.Nrv   r7   :Nr   N)	rJ   r   r@   r-   r3   r%   r1   Ú_default_hermes_root_memork   )rH   rc   Úenv_homerd   Úmemo_keyÚmemoÚresults   $      r   Úget_default_hermes_rootr×   (  s£   € ô 4Ó5€KØ$(Ò$4Œs�4‹y�‰Ô ¼"¿*¹*¿.¹.ÈÐXZÓ:[×:aÑ:aÓ:c€Hß08Ô" 8Ô,¸d€HÜ�KÓ °8Ò3G¤# h¤-ÈRÐP€HÜ$€DØÒ˜D �H¨Ô0Ø�A�wˆÜ˜[Ó3€FØ 3 (Ð 3¨FÑ 3ÐØ€Mr   z.deletedc                ó0   € V ^8„  d   QhR\         R\        /# )r   Úprofiles_dirr   ©r   rÅ   )r   s   "r   r   r   =  s   € ÷ ñ ¬4ð ´Dñ r   c                ó¾  a€ V P                   oSP                  R8X  d   R#  V \        ,          P                  4       '       gI   \        ;QJ d#    V3R l\
         4       F  '       g   K   RM	  RM! V3R l\
         4       4      '       d   R#   SP                  RR7      \        4       P                  RR7      8H  #   \         d     L;i ; i  \         d     R# i ; i)z÷True when *profiles_dir* is provably ``<hermes-home>/profiles``.

Accepts the classic ``~/.hermes`` layout, a root carrying Hermes-home marker files, a
``profiles/.deleted`` tombstone dir (only ``profile delete`` creates it), or the default root.
r=   Tc              3   óR   <"  € T F  pSV,          P                  4       x € K  	  R # 5irZ   )rœ   )Ú.0Úmarkerr�   s   & €r   Ú	<genexpr>Ú+_is_hermes_profiles_root.<locals>.<genexpr>G  s&   øé € ð B
Ù3G¨ˆT�F�]×"Ñ"×$Ð$Ó3Gùs   ƒ$'Fr°   )	ri   rj   Ú_DELETED_PROFILES_DIRÚis_dirÚanyÚ_HERMES_HOME_MARKERSrS   r^   r×   )rÙ   r�   s   &@r   Ú_is_hermes_profiles_rootrå   =  sÊ   ø€ ð ×Ñ€DØ‡y�y�IÔÙðØÔ0Õ0×8Ñ8×:Ò:¿c»cô B
Ý3GóB
¿c¿cºcô B
Ý3GóB
÷ ?
ò ?
ñ ð?
ðØ�|‰| 5ˆ|Ó)Ô-DÓ-F×-NÑ-NÐV[Ð-NÓ-\Ñ\Ð\øô ô Ùðûô ô Úðús5   ¢ B< Á
B< ÁB< Á)!B< Â,C Â<C
Ã	C
ÃCÃCc                óT   € V ^8„  d   QhR\         \        ,          R\        R,          /# ©r   r   r   Nr+   )r   s   "r   r   r   S  s"   € ÷ ñ œS¤4�Zð ¬D°4­Kñ r   c                ó&  € \        V 4      pV.VP                  O Fr  pVP                  P                  R8X  dA   VP                  P	                  R4      '       g    \        VP                  4      '       d   Vu # VP                  R8X  g   Kq   R# 	  R# )a  Return ``<root>/profiles/<name>`` when *path* is that home or under it.

Requires ``<name>`` not to start with ``.`` and the ``profiles`` parent to be a real Hermes home;
a default home whose path merely contains a ``profiles`` segment is not a named profile.
rf   Ú.r=   N)r   Úparentsri   rj   r…   rå   )r   Úcurrentr´   s   &  r   Únamed_profile_homerì   S  sw   € ô �4‹j€GØÐ0 §¡Ó0ˆ	Ø×Ñ×!Ñ! ZÔ/¸	¿¹×8QÑ8QÐRU×8VÒ8VÜ,¨Y×-=Ñ-=×>Ò>ØÒØ�>‰>˜YÖ&Úñ 1ñ r   c                ób   € V ^8„  d   QhR\         \        ,          R,          R\         R,          /# r   r+   )r   s   "r   r   r   c  s'   € ÷ ñ ¤¤d¥
¨TÕ 1ð ´c¸Dµjñ r   c                ó  € V e    \        V 4      P                  4       '       g   R# \        V 4      P                  4       p \	        4       pWP                  RR7      3 F‹  pW28X  g   W2P                  RR7      8X  d    R# \        V4      pVe   VP                  u # VP                  P                  R8X  g   K\  VP                  P                  R4      '       d   K  VP                  u # 	  R#   \        \        \        3 d     R# i ; i)a  Return the canonical profile id owning *path*, or ``None`` when it is not a profile home.

The default home is the Hermes root itself, so its basename is an installation detail (``.hermes``
on POSIX and commonly ``hermes`` on Windows), not the profile id ``default``.
NFr°   r   rf   ré   )r   r@   r   r.   r×   r^   rì   rj   ri   r…   rS   r_   rh   )r   rë   Údefault_rootr´   Únameds   &    r   Úprofile_name_for_homerñ   c  sà   € ð ‚|œ3˜t›9Ÿ?™?×,Ò,ÙÜ�4‹j×#Ñ#Ó%€GðÜ.Ó0ˆØ!§?¡?¸% ?Ó#@ÓAˆIØÔ(¨I×9MÑ9MÐUZÐ9MÓ9[Ô,[Ú Ü& yÓ1ˆEØÒ Ø—z‘zÒ!ð ×Ñ×$Ñ$¨
Ö2¸9¿>¹>×;TÑ;TÐUX×;YÔ;YØ —~‘~Ò%ñ Bñ øô ”\¤:Ð.ô Úðús0   Á =C. Á?C. ÂC. Â9C. ÃC. Ã*C. Ã.DÄDc                ó0   € V ^8„  d   QhR\         R\         /# ©r   Úprofile_homer   r   )r   s   "r   r   r   }  s   € ÷ Kñ K¬ð K´$ñ Kr   c                 óR   € V P                   \        ,          V P                  ,          # rZ   )ri   rá   rj   ©rô   s   &r   Úprofile_tombstone_pathr÷   }  s   € Ø×ÑÔ!6Õ6¸×9JÑ9JÕJÐJr   c                óF   € V ^8„  d   QhR\         \        ,          R\        /# ró   ©r   r   rÅ   )r   s   "r   r   r   �  s   € ÷ ?ñ ?¬3´­:ð ?¼$ñ ?r   c                 óF   € \        \        V 4      4      P                  4       # rZ   )r÷   r   rœ   rö   s   &r   Únamed_profile_is_deletedrû   �  s   € Ü!¤$ |Ó"4Ó5×<Ñ<Ó>Ð>r   z^[a-z0-9][a-z0-9_-]{0,63}$c                óF   € V ^8„  d   QhR\         \        ,          R\        /# ró   rù   )r   s   "r   r   r   Ž  s"   € ÷ rñ r¬S´4­Zð r¼Dñ rr   c                 óž   a€ \        V 4      o\        ;QJ d#    V3R  l\         4       F  '       g   K   R# 	  R# ! V3R  l\         4       4      # )c              3   ó�   <"  € T F;  pSV,          P                  4       ;'       g    SV,          P                  4       x € K=  	  R # 5irZ   )Úis_fileÚ
is_symlink)rÝ   rÞ   rH   s   & €r   rß   Ú-named_profile_has_identity.<locals>.<genexpr>’  s8   øé € ÐqÑWpÈV��v•×&Ñ&Ó(×HÐH¨T°F­]×,FÑ,FÓ,HÔHÓWpùs
   ƒ"A¦ ATF)r   rã   Ú_PROFILE_IDENTITY_MARKERS©rô   rH   s   &@r   Únamed_profile_has_identityr  Ž  s:   ø€ ô �Ó€Dß‹3ÔqÕWpÓq�3Œ3ÐqŠ3Ðqˆ3ÔqÕWpÓqÓqÐqr   c                óF   € V ^8„  d   QhR\         \        ,          R\        /# ró   rù   )r   s   "r   r   r   •  s   € ÷ ñ ´c¼Dµjð ÄTñ r   c                ó   € \        V 4      p\         Ff  pW,          pVP                  4       '       d    R#  VP                  4       '       d,   VR8w  g    VP	                  4       P
                  ^ 8”  d    R# Kf  Kh  	  R#   \         d     Kz  i ; i)uÒ  Stricter than :func:`named_profile_has_identity`: is this dir a profile a host should change
its own posture for?

An EMPTY ``.env`` is all a crashed ``hermes profile create`` leaves behind, and it is enough for
``named_profile_has_identity``. Listing such a shell is harmless; counting it as a second tenant
is not â€” it flips the whole host's credential reads fail-closed at the next boot. Every other
marker, and a non-empty or symlinked ``.env``, still counts.
Tú.envF)r   r  r   rÿ   ÚstatÚst_sizerS   )rô   rH   rÞ   r   s   &   r   Ú#named_profile_has_servable_identityr
  •  s}   € ô �Ó€Dß+ˆØ�}ˆØ�?‰?×ÒÚð	Ø�|‰|�~Š~ 6¨VÔ#3°t·y±y³{×7JÑ7JÈQÔ7NÚñ 8O‰~ñ ,ñ øô ô 	Úð	ús   ·A>Á&A>Á>BÂBc                óF   € V ^8„  d   QhR\         \        ,          R\        /# ró   rù   )r   s   "r   r   r   «  s"   € ÷ eñ e¬¬d­
ð e´tñ er   c                óŽ   € \        V 4      pVP                  4       ;'       d$    \        V4      ;'       d    \        V4      '       * # )a  A resolvable named profile: an existing dir with identity that has not been deleted.
``-p``/``--profile`` resolution and ``profile_exists`` share this so a stale ghost shell can
never be started as a backend (whose ``ensure_hermes_home`` would rebuild the full tree).)r   râ   r  rû   r  s   & r   Únamed_profile_is_liver  «  s:   € ô �Ó€DØ�;‰;‹=×dÐdÔ7¸Ó=×dÐdÔF^Ð_cÓFdÔBdÐdr   c                ó>   € V ^8„  d   QhR\         \        ,          RR/# ©r   rô   r   Nr+   )r   s   "r   r   r   ³  s   € ÷ 5ñ 5¬S´4­Zð 5¸Dñ 5r   c                 óŽ   € \        \        V 4      4      pVP                  P                  R R R7       VP	                  RRR7       R# )T©rê   Úexist_okzdeleted
r—   r˜   N)r÷   r   ri   ÚmkdirÚ
write_text)rô   rÞ   s   & r   Úmark_named_profile_deletedr  ³  s;   € Ü#¤D¨Ó$6Ó7€FØ
‡M�M×Ñ ¨tÐÔ4Ø
×Ñ�k¨GÐÖ4r   c                ó>   € V ^8„  d   QhR\         \        ,          RR/# r  r+   )r   s   "r   r   r   ¹  s"   € ÷ Gñ G¬c´D­jð G¸Tñ Gr   c                 óN   € \        \        V 4      4      P                  R R7       R# )T)Ú
missing_okN)r÷   r   Úunlinkrö   s   &r   Úclear_named_profile_deletedr  ¹  s   € Üœ4 Ó-Ó.×5Ñ5ÀÐ5ÖFr   c                ó>   € V ^8„  d   QhR\         \        ,          RR/# rç   r+   )r   s   "r   r   r   ½  s   € ÷ 
ñ 
¬¬t­ð 
¸ñ 
r   c                ó”   € \        V 4      pVe9   \        V4      '       g   VP                  4       '       g   \        RV R24      hR# R# )z1Refuse missing or tombstoned named profile homes.Nz#Named profile home does not exist: z0. Create the profile explicitly before using it.)rì   rû   rœ   ÚFileNotFoundError)r   rH   s   & r   Úassert_named_profile_home_liver  ½  sO   € ä˜dÓ#€DØÒÔ5°d×;Ò;À4Ç;Á;Ç=Â=ÜØ1°$°ð 8=ð =ó
ð 	
ñ DQÑr   c                óF   € V ^8„  d   QhR\         \        ,          R\        /# r*   r+   )r   s   "r   r   r   Ç  s   € ÷ 	ñ 	¤#¬¥*ð 	´ñ 	r   c                óT   € \        V 4      p\        V4       ^ RIHp V! VRRR7       V# )zECreate *path*, but never materialize a deleted/missing named profile.)Úmake_user_dirTr  )r   r  Úhermes_dir_aclr!  )r   Útargetr!  s   &  r   Úmkdir_under_hermes_homer$  Ç  s)   € ä�$‹Z€FÜ" 6Ô*õ -Ù�& $°Õ6Ø€Mr   c                óV   € V ^8„  d   QhR\         R\        R,          R\         R\        /# )r   Úenv_varr   NÚsubdirr   r+   )r   s   "r   r   r   Ó  s2   € ÷ jñ jœ3ð j¬°­ð j¼cð jÄdñ jr   c                ó    € \         P                  ! V R4      P                  4       pV'       d   \        V4      # Ve   V# \	        4       V,          # )u®   Resolve a package-manager-relocatable directory.

Order: *env_var* (Nix wrapper / explicit override) â†’ caller ``default`` (source checkout) â†’
``<HERMES_HOME>/<subdir>``.
r7   )r-   Úgetenvr@   r   r­   )r&  r   r'  r'   s   &&& r   Ú_packaged_dirr*  Ó  sA   € ô �yŠy˜ "Ó%×+Ñ+Ó-€Hß%Œ4�‹>Ði°gÒ6I¨7ÐiÌÓO`ÐciÕOiÐir   c                ó>   € V ^8„  d   QhR\         R,          R\         /# ©r   r   Nr   r   )r   s   "r   r   r   Ý  s"   € ÷ Oñ O¤T¨D¥[ð O¼Dñ Or   c                ó   € \        RV R4      # )zHReturn the optional-skills directory, honoring package-manager wrappers.ÚHERMES_OPTIONAL_SKILLSzoptional-skills©r*  r
   s   &r   Úget_optional_skills_dirr0  Ý  s   € äÐ1°7Ð<MÓNÐNr   c                ó>   € V ^8„  d   QhR\         R,          R\         /# r,  r   )r   s   "r   r   r   â  s"   € ÷ Kñ K¤4¨$¥;ð K¼$ñ Kr   c                ó   € \        RV R4      # )zaReturn the optional-mcps directory, honoring package-manager wrappers (``HERMES_OPTIONAL_MCPS``).ÚHERMES_OPTIONAL_MCPSzoptional-mcpsr/  r
   s   &r   Úget_optional_mcps_dirr4  â  s   € äÐ/°¸/ÓJÐJr   c                ó>   € V ^8„  d   QhR\         R,          R\         /# r,  r   )r   s   "r   r   r   ç  s"   € ÷ Eñ E¤D¨4¥Kð E¼4ñ Er   c                ó   € \        RV R4      # )zcReturn the bundled skills directory, honoring package-manager wrappers (``HERMES_BUNDLED_SKILLS``).ÚHERMES_BUNDLED_SKILLSÚskillsr/  r
   s   &r   Úget_bundled_skills_dirr9  ç  s   € äÐ0°'¸8ÓDÐDr   c                óV   € V ^8„  d   QhR\         R\         R\        R,          R\        /# )r   Únew_subpathÚold_namerH   Nr   r+   )r   s   "r   r   r   ì  s3   € ÷ Rñ R¤ð R¬sð R¼TÀD½[ð RÔTXñ Rr   c               óp   € T;'       g    \        4       pW!,          p\        V4      '       d   V# W ,          # )ua  Resolve a Hermes subdirectory, honouring a populated legacy ``<old_name>/`` (no migration).

An empty legacy dir does NOT count (install scaffolds, manual mkdir) so it cannot shadow the new path.

A bare empty ``<old_name>/`` directory does **not** count as "the legacy install is in use" â€” install
scaffolds, manual ``mkdir`` work, and cleared-then-abandoned locations all create empty stubs that would
otherwise silently shadow real data populated at ``<new_subpath>/``. See #27602 for the pairing-store
regression where a dormant empty ``pairing/`` orphaned approved-user data in ``platforms/pairing/``.
)r­   Ú_legacy_path_has_content)r;  r<  rH   Úold_paths   &&$ r   Úget_hermes_dirr@  ì  s3   € ð ×$Ð$”?Ó$€DØ�€HÜ/°×9Ò9ˆ8ÐQ¸tÕ?QÐQr   c                óT   € V ^8„  d   QhR\         R,          R\        \         ,          /# rÐ   )r   Úlist)r   s   "r   r   r   û  s&   € ÷ eñ e¤ t¥ð e´t¼Dµzñ er   c                óŒ   € T ;'       g    \        4       R,          p\        P                  R8X  d   WR,          .# VR,          V.# )zGHistorical layout for old-updater diagnostics, never runtime selection.rÌ   r8   Úbin)r­   r>   r?   )rH   Únode_dirs   & r   Úiter_hermes_node_dirsrF  û  sA   € à×)Ð)œÓ)¨VÕ3€HÜ+.¯<©<¸7Ô+BˆH Õ&Ð'ÐdÈÐTYÕIYÐ[cÐHdÐdr   ÚnpmÚnpxznode.exec                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r   Úcommandr   ©r   rB  )r   s   "r   r   r     s"   € ÷ Wñ W¬3ð W´4¼µ9ñ Wr   c                 óÄ   € \        V 4      P                  p\        P                  R 8w  g   RV9   d   V.# \        P                  VP                  4       V R2V R2V.4      # )r8   ré   ú.cmdú.exe)r   rj   r>   r?   Ú_WINDOWS_NODE_SHIMSr%   Úlower)rJ  rC   s   & r   Ú_candidate_node_command_namesrQ    sW   € Ü�‹=×Ñ€DÜ
‡|�|�wÔ #¨¤+Øˆvˆä×"Ñ" 4§:¡:£<°T°F¸$°-ÀDÀ6ÈÀÐPTÐ1UÓVÐVr   c                ó:   € V ^8„  d   QhR\         \        ,          /# )r   Úargv)rB  r   )r   s   "r   r   r     s   € ÷ 
ñ 
œT¤#�Yñ 
r   c           
     óš   € ^ RI p ^ RIHp VP                  ! V 3RRR^
RV! 4       /VB #   \        TP
                  \        3 d     R# i ; i)z>Run a hidden ``--version`` probe; ``None`` when it cannot run.N)Úwindows_hide_flagsÚcapture_outputTÚtimeoutÚcreationflags)Ú
subprocessÚhermes_cli._subprocess_compatrU  ÚrunrS   ÚTimeoutExpiredrh   )rS  ÚkwargsrY  rU  s   &,  r   Ú_run_version_prober^    se   € ãðÝDØ�~Š~Øñ
Ø!%ð
Ø/1ð
ÙASÓAUð
ØY_ñ
ð 	
øô �Z×.Ñ.´
Ð;ô Úðús   †#* ªA
Á	A
c                ó0   € V ^8„  d   QhR\         R\        /# r*   ©r   rÅ   )r   s   "r   r   r     s   € ÷ 9ñ 9œCð 9¤Dñ 9r   c                óf   € \        V R.\        4       R7      pVRJ;'       d    VP                  ^ 8H  # )zJTrue when ``<path> --version`` exits 0 under the Hermes-managed Node PATH.z	--version)ÚenvN)r^  Úwith_hermes_node_pathÚ
returncode)r   rÖ   s   & r   Ú_version_probe_okre    s5   € ä  {Ð 3Ô9NÓ9PÔQ€FØ˜Ð×8Ð8 &×"3Ñ"3°qÑ"8Ð8r   c                ó0   € V ^8„  d   QhR\         R\        /# r*   r`  )r   s   "r   r   r   &  s   € ÷ =ñ =œcð =¤dñ =r   c                óš   € \         P                  P                  V 4      ;'       d&    \         P                  ! V \         P                  4      # )zG``exists()`` follows symlinks, so a dangling link never spawns a probe.)r-   r   rœ   ÚaccessÚX_OKr0   s   &r   Ú_is_executable_filerj  &  s,   € ä�7‰7�>‰>˜$Ó×<Ð<¤B§I¢I¨d´B·G±GÓ$<Ð<r   c                ó>   € V ^8„  d   QhR\         R,          R\        /# r   r`  )r   s   "r   r   r   +  s   € ÷ /ñ /œS 4�Zð /¬Dñ /r   c                ó²   € V '       g   R# \         P                  R8X  d   \        V 4      P                  4       M
\	        V 4      pT;'       d    \        V 4      # )zXTrue only when *path* is a Node/npm/npx binary that actually runs (``--version`` probe).Fr8   )r>   r?   r   rÿ   rj  re  )r   Úpresents   & r   Únode_tool_runnablern  +  sB   € çÙÜ&)§l¡l°gÔ&=Œd�4‹j× Ñ Ô"ÔCVÐW[ÓC\€GØ×.Ð.Ô(¨Ó.Ð.r   c                ó>   € V ^8„  d   QhR\         R,          R\        /# rÐ   rÚ   )r   s   "r   r   r   3  s"   € ÷ lñ l¬4°$­;ð lÄ$ñ lr   c                óò   a€ R UUu. uF  p\        V4       F  q"NK  	  K  	  uppo\        ;QJ d(    V3R l\        V 4       4       F  '       g   K   R# 	  R# ! V3R l\        V 4       4       4      # u uppi )zERead-only legacy artifact detection for already-running old updaters.c              3   ób   <"  € T F$  pS F  q!V,          P                  4       x € K  	  K&  	  R # 5irZ   )rÿ   )rÝ   Ú	directoryrj   r|   s   &  €r   rß   Ú3hermes_managed_node_tree_present.<locals>.<genexpr>6  s.   øé € ÐkÑ=X°	ÓejÐ]a˜DÕ ×)Ñ)×+Ð+ÑejÑ+Ó=Xùs   ƒ,/TF)rÌ   rG  rH  )rQ  rã   rF  )rH   ÚcÚnr|   s   &  @r   Ú hermes_managed_node_tree_presentrv  3  sf   ø€ á.ÔYÑ.�1Ô8UÐVWÖ8X°1ŠQÑ8X‰QÑ.ÒY€Eß‹3ÔkÔ=RÐSWÔ=XÓk�3Œ3ÐkŠ3Ðkˆ3ÔkÔ=RÐSWÔ=XÓkÓkÐkùó Zs   ‡A3c                ó>   € V ^8„  d   QhR\         R\         R,          /# )r   rJ  r   Nr#   )r   s   "r   r   r   9  s   € ÷ &ñ &¤#ð &¬#°­*ñ &r   c                ó–  a € \        S 4      o \        ;QJ d    V 3R lR 4       F  '       g   K   RM	  RM! V 3R lR 4       4      '       dO   \        P                  R8X  d$   \	        S 4      P                  4       '       d   S # R# \        P                  ! S 4      # S P                  4       pR F  pVP                  V4      pK  	  RRRRRR/P                  V4      pVe“   ^ R	IHp V! V4      pVe   VP                  f   R# VR8w  d   \        VP                  4      # \        R4       FC  pVP                  P                  V,          pVP                  4       '       g   K8  \        V4      u # 	  R# \        P                  R8w  d   \        P                  ! S 4      # \         P"                  P                  R
R4      P%                  \         P&                  4       Uu. uF  qˆ'       g   K  VNK  	  p	p\        S 4       FC  pV	 F:  p
\	        V
4      V,          pVP                  4       '       g   K-  \        V4      u u # 	  KE  	  R# u upi )ab  Read PM's selected Node/npm/npx; ``None`` when PM has not installed it.

Never falls back to the user's PATH copy (callers ``pm.ensure`` on ``None``):
mixing toolchains breaks native-addon ABIs and npm caches. Explicit
executable paths remain caller-owned. Discovery never installs, probes,
repairs, or activates the retired ``HERMES_HOME/node`` layout.
c              3   ó,   <"  € T F	  qS9   x € K  	  R # 5irZ   rI   )rÝ   ÚseprJ  s   & €r   rß   Ú'find_node_executable.<locals>.<genexpr>B  s   øé € Ð
1¡[˜c�'Ž>£[ùó   ƒTFr8   NrÌ   rG  rH  )Úinstalled_packageÚPATHr7   )Ú/Ú\)rM  rN  z.ps1)r   rã   r>   r?   r   rÿ   ÚshutilÚwhichrP  Úremovesuffixr%   Úpmr}  ÚbinaryrQ  ri   r-   r3   ÚsplitÚpathsep)rJ  rC   rA   Úpackage_namer}  Ú	installedrj   r´   ÚdÚdirectoriesrr  s   f          r   Úfind_node_executablerŒ  9  sÉ  ø€ ô �'‹l€Gß
ƒsÔ
1¡[Ó
1‡s‡s‚sÔ
1¡[Ó
1×1Ò1Ü�<‰<˜7Ô"Ü" 7›m×3Ñ3×5Ò5�7Ð?¸4Ð?Ü�|Š|˜GÓ$Ð$Ø�=‰=‹?€DÛ*ˆØ× Ñ  Ó(Šñ +à˜F E¨5°%¸Ð?×CÑCÀDÓI€LØÒÝ(á% lÓ3ˆ	ØÒ 	× 0Ñ 0Ò 8ÙØ�5Œ=Ü�y×'Ñ'Ó(Ð(Ü1°%Ö8ˆDØ!×(Ñ(×/Ñ/°$Õ6ˆIØ× Ñ ×"Ô"Ü˜9“~Ò%ñ 9ñ Ü
‡|�|�wÔÜ�|Š|˜GÓ$Ð$Ü Ÿj™jŸn™n¨V°RÓ8×>Ñ>¼r¿z¹zÔJÓPÑJ˜Ëa—1�1ÑJ€KÐPÜ-¨gÖ6ˆÛ$ˆIÜ˜Y›¨$Õ.ˆIØ× Ñ ×"Ô"Ü˜9“~Ô%ó %ñ 7ñ
 ùò Qs   Ç	IÇ*Ic                ó‚   € V ^8„  d   QhR\         \        \        3,          R,          R\         \        \        3,          /# ©r   rb  Nr   ©Údictr   )r   s   "r   r   r   b  s/   € ÷ (ñ (œt¤C¬ H�~°Õ4ð (ÄÄSÌ#ÀXÅñ (r   c                ó"   € ^ RI Hp V! RV R7      # )zFCompose installed PM npm and its Node dependency without provisioning.)Úenv_forrG  )Úbase_env)r„  r’  )rb  r’  s   & r   rc  rc  b  s   € åá�5 3Ô'Ð'r   c                ó>   € V ^8„  d   QhR\         R,          R\        /# r   r`  )r   s   "r   r   r   i  s"   € ÷ Añ A¤ t¥ð A´ñ Ar   c                óR   € V '       g   R# \        V 4      ;'       d    \        V 4      # )u|  True when *path* is an agent-browser CLI that runs (``--version`` exits 0).

Dead/wrong-arch/hung binaries are rejected so callers try the next candidate.

A bare presence check (``shutil.which`` / ``Path.exists``) is not enough: agent-browser's npm
``postinstall`` re-points a *global* install symlink (e.g. ``/opt/homebrew/bin/agent-browser``) at our
local ``node_modules/agent-browser/bin/...`` binary, which then disappears on the next ``hermes update``
â€” leaving a **dangling symlink** that ``which`` still reports but exec fails on with exit 127 (issue
#48521). Callers that trust such a path silently break every browser tool.
F)rj  re  r0   s   &r   Úagent_browser_runnabler–  i  s#   € ÷ ÙÜ˜tÓ$×@Ð@Ô):¸4Ó)@Ð@r   c                ó0   € V ^8„  d   QhR\         R\        /# r*   rÚ   )r   s   "r   r   r   y  s   € ÷ ñ ¤4ð ¬Dñ r   c                ó”  €  V P                  4       p\        P                  ! VP                  4      '       d   V P                  4       p\        P                  ! TP                  4      '       g   R#  \        T P                  4       4       R#   \         d     R# \
         d     R# i ; i  \         d     R# \
         d     R# i ; i)zÕTrue iff *path* is a non-directory file or a populated directory.

Non-not-found ``OSError`` means "assume occupied" (never orphan legacy data). Symlinks are
judged on their target; a dangling one does NOT count.
FT)
Úlstatr  ÚS_ISLNKÚst_moder  rS   ÚS_ISDIRÚnextÚiterdirÚStopIteration)r   Ústs   & r   r>  r>  y  s    € ðØ�Z‰Z‹\ˆÜ�<Š<˜Ÿ
™
×#Ò#Ø—‘“ˆBô
 �<Š<˜Ÿ
™
×#Ò#ÙðÜˆT�\‰\‹^Ôñ
 øô ô ÚÜô Úðûô ô ÚÜô ØÙðús@   ‚5B ¸B Á1B+ ÂB(ÂB(Â#B(Â'B(Â+CÂ9CÃCÃCc                ó>   € V ^8„  d   QhR\         R,          R\        /# rÐ   )r   r   )r   s   "r   r   r   ’  s   € ÷ ñ œd T�kð ´Sñ r   c                óÊ   € V f   \        4       p  RV P                  \        P                  ! 4       4      P	                  4       ,           #   \
         d    \        T 4      u # i ; i)a  User-facing ``~/`` display string for HERMES_HOME (``~/.hermes/profiles/coder``).

``home`` overrides the lookup for callers that run before the CLI has applied the sticky
``active_profile`` (``get_hermes_home()`` would emit the wrong-profile fallback warning there).
r�   )r­   rg   r   rH   Úas_posixrh   r   ©rH   s   &r   Údisplay_hermes_homer¥  ’  sT   € ð ‚|ÜÓ ˆðØ�d×&Ñ&¤t§y¢y£{Ó3×<Ñ<Ó>Õ>Ð>øÜô Ü�4‹yÒðús   �8A	 Á	A"Á!A"c                ó$   € V ^8„  d   QhR\         /# rF   r#   )r   s   "r   r   r      s   € ÷ ?ñ ?œcñ ?r   c                 óV   € \        \        4       4      p V '       d   V R8w  d   RV  R2# R# )aR  ``-p <name> `` (trailing space) pinning copy-pasteable ``hermes ...`` guidance to the
active NAMED profile, else ``""``: a bare ``hermes`` follows the sticky ``active_profile``
file, which can name a different database than the one that failed (#105887). A custom
home outside the profile tree has no selector (only HERMES_HOME names it).r   z-p Ú r7   )rñ   r­   ©rj   s    r   Úprofile_cli_selectorrª     s-   € ô
 !¤Ó!2Ó3€Dß  T¨YÔ%6ˆS���aˆ=Ð>¸BÐ>r   c                ó(   € V ^8„  d   QhR\         RR/# rç   r   )r   s   "r   r   r   ©  s   € ÷  ñ  œDð   Tñ  r   c                óÞ  € V P                   P                  4       pV\        R4      8X  g   \        VP                  4      ^8  d   R# V\
        8X  g   \
        VP                  9   d1   ^ RIpVP                  \        4      P                  RV\
        4       R# \        P                  ! \        4      ;_uu_ 4        \        P                  ! VR4       RRR4       R#   + '       g   i     R# ; i)z`Chmod ``0o700`` on *path*'s parent, refusing ``/`` and top-level dirs (misresolved HERMES_HOME).r  Nz¦Not restricting permissions on %s: it is inside the hermes-agent install directory (%s). Credential files are normally stored under the hermes home directory instead.éÀ  )ri   r^   r   ÚlenÚpartsÚ_INSTALL_ROOTrê   ÚloggingÚ	getLoggerÚ__name__ÚwarningrŸ   r    rS   r-   Úchmod)r   ri   r±  s   &  r   Úsecure_parent_dirr¶  ©  s£   € à�[‰[× Ñ Ó"€FØ”�c“Ôœc &§,¡,Ó/°!Ô3Ùð ”Ô¤-°6·>±>Ô"AÛà×Ñœ(Ó#×+Ñ+ðGàHNÔP]ô	
ñ
 	Ü	×	Ò	œW×	%Õ	%Ü
�Š�˜Ô÷ 
&×	%×	%Ò	%ús   Â9CÃC,	c                ó>   € V ^8„  d   QhR\         R,          R\         /# r   r#   )r   s   "r   r   r   ¾  s   € ÷ %ñ %œ# �*ð %¬ñ %r   c                ó^  € T ;'       g    RP                  4       pV'       g   R#  \        P                  P                  \        P                  P	                  \        P                  P                  V4      4      4      #   \         d#    \        P                  P                  T4      u # i ; i)zDReturn a comparable absolute path string, or ``""`` for empty input.r7   )r@   r-   r   r³   Úabspathr.   r¡   )r   rˆ   s   & r   Ú_norm_home_pathrº  ¾  sv   € à�:ˆ:�2×
Ñ
Ó
€CßÙð%Ü�w‰w×Ñ¤§¡§¡´·±×0BÑ0BÀ3Ó0GÓ HÓIÐIøÜô %Ü�w‰w×Ñ Ó$Ò$ð%ús   ¦AA? Á?*B,Â+B,c                ón   € V ^8„  d   QhR\         \        \        3,          R,          R\        R,          /# rŽ  r�  )r   s   "r   r   r   É  s/   € ÷ Añ AœD¤¤c �N¨TÕ1ð A¼SÀ4½Zñ Ar   c                ó4  € \        4       ;'       g:    T ;'       g    / P                  R4      ;'       g    \        P                  ! R4      pV'       g   R# \	        \        V4      R,          4      p\        P                  P                  V4      '       d   V# R# )zEReturn ``{HERMES_HOME}/home`` when the profile-home directory exists.rv   NrH   )r(   r%   r-   r)  r   r1   r   Úisdir)rb  Úhermes_homerô   s   &  r   Ú_profile_home_pathr¿  É  sn   € ä*Ó,×jÐj°·°¸·±ÀÓ0N×jÐjÔRT×R[ÒR[Ð\iÓRj€KßÙÜÔ*¨;Ó7¸&Õ@ÓA€LÜŸ7™7Ÿ=™=¨×6Ò6ˆ<Ð@¸DÐ@r   c                óX   € V ^8„  d   QhR\         R,          R\         R,          R\        /# )r   r´   Nrô   r   r`  )r   s   "r   r   r   Ò  s.   € ÷ lñ l¤ d¥
ð l¼#À½*ð lÌñ lr   c                 ój   € \        T ;'       d"    T;'       d    \        V 4      \        V4      8H  4      # rZ   )rÅ   rº  )r´   rô   s   &&r   Ú_is_profile_homerÂ  Ò  s-   € Ü�	×jÐj˜l×jÐj¬¸yÓ/IÌ_Ð]iÓMjÑ/jÓkÐkr   c                ój   € V ^8„  d   QhR\         \        \        3,          R\        R\        R\        /# )r   rb  r‡   r   r   r�  )r   s   "r   r   r   Ö  s6   € ÷ @ñ @”$”sœC�x•.ð @¤sð @´Sð @Ä#ñ @r   c                óŽ   € \        V P                  V4      ;'       g    \        P                  ! W4      4      P	                  4       # )zCStripped *key* from *env*, falling back to the process environment.)r   r%   r-   r)  r@   )rb  r‡   r   s   &&&r   Ú_env_getrÅ  Ö  s/   € äˆs�w‰w�s‹|×6Ð6œrŸyšy¨Ó6Ó7×=Ñ=Ó?Ð?r   c                óv   € V ^8„  d   QhR\         \        \        3,          R,          R\        \        ,          /# rŽ  )r�  r   rB  )r   s   "r   r   r   Û  s+   € ÷ (ñ (¤D¬¬c¨¥N°TÕ$9ð (ÄTÌ#ÅYñ (r   c                ó,  € T ;'       g    / p \        V R4      \        V R4      .p\        P                  ! \        4      ;_uu_ 4        ^ RIpVP                  VP                  \        P                  ! 4       4      P                  P                  4       4       RRR4       VP                  \        V R4      4       \        V R4      \        V R4      rCV'       dT   V'       dL   TP                  VP                  R4      '       d   V V 2M\        P                  P                  W44      4       \        P                  P                  R4      pVR8w  d   VP                  V4       V Uu. uF  qf'       g   K  VNK  	  up#   + '       g   i     Lï; iu upi )	z5Return likely OS-user home candidates in trust order.ÚHERMES_REAL_HOMEro   Nrn   Ú	HOMEDRIVEÚHOMEPATHr~   )r€  r  )rÅ  rŸ   r    r¡   rM   ÚappendrN   r-   rO   rP   r@   r…   r   Újoinr.   )rb  Ú
candidatesrM   Údriver   r‰   rt  s   &      r   Ú_iter_real_home_candidatesrÏ  Û  s%  € à
�)ˆ)�€CÜ˜3Ð 2Ó3´X¸cÀ6Ó5JÐK€JÜ	×	Ò	œY×	'Õ	'ÛØ×Ñ˜#Ÿ,™,¤r§y¢y£{Ó3×:Ñ:×@Ñ@ÓBÔC÷ 
(ð ×Ñ”h˜s MÓ2Ô3Ü˜3 Ó,¬h°s¸JÓ.Gˆ4ß—Ø×Ñ¨d¯o©o¸k×.JÒ.J˜U˜G D 6Ñ*ÔPR×PWÑPW×P\ÑP\Ð]bÓPiÔjÜ�w‰w×!Ñ! #Ó&€HØ�3„Ø×Ñ˜(Ô#Ù!Ó'‘z�!£Q�AˆA‘zÑ'Ð'÷ 
(×	'üò (s   ÁAE>Å'	FÅ5FÅ>F	c                ó`   € V ^8„  d   QhR\         \        \        3,          R,          R\        /# rŽ  r�  )r   s   "r   r   r   ì  s'   € ÷ ñ ”tœC¤˜H•~¨Õ,ð ¼ñ r   c                ó,  € \        V 4      p\        4       p\        V 4       FD  p\        V4      pV'       d   WB9   d   K  VP	                  V4       \        W14      '       d   KB  Vu # 	  ^ RIp VP                  4       #   \        \        3 d     R# i ; i)zìThe OS user's real home, avoiding the Hermes profile HOME.

``HOME`` belongs to the OS account and external CLIs keeping credentials under ``~``; a parent
already running with ``HOME={HERMES_HOME}/home`` is repaired back when possible.
Nú/tmp)
r¿  r   rÏ  rº  ÚaddrÂ  ÚtempfileÚ
gettempdirr_   rS   )rb  rô   Úseenr´   r‡   rÔ  s   &     r   rU   rU   ì  s„   € ô & cÓ*€LÜ“U€DÜ/°Ö4ˆ	Ü˜iÓ(ˆß�c”kÙØ�‰�ŒÜ 	×8Ô8ØÒñ 5ó ðØ×"Ñ"Ó$Ð$øÜœ'Ð"ô âðús   Á.A> Á>BÂBÚisolatedrt   rô   zprofile-homeÚhostÚrealÚuserÚ	real_homez	real-homec                ón   € V ^8„  d   QhR\         \        \        3,          R,          R\        R,          /# rŽ  r�  )r   s   "r   r   r     s+   € ÷ ñ œT¤#¤s (�^¨dÕ2ð ¼cÀD½jñ r   c                óž  € T ;'       g    / p \        V 4      p\        V RR4      P                  4       ;'       g    Rp\        P	                  W"4      pVR8X  d   V# \        V 4      p\        V R4      p\        V4      \        V4      8w  d   TMRpVR8X  d   V# V'       d   \        4       '       d   V# V'       d   \        WA4      '       d   V# R# )z×Subprocess ``HOME`` override, or ``None``.

``auto``: hosts keep real HOME (repairing a profile-home parent), containers use
``{HERMES_HOME}/home``; ``real``: always real HOME; ``profile``: always the profile home.
ÚTERMINAL_HOME_MODEÚautort   ro   NrÙ  )	r¿  rÅ  rP  Ú_HOME_MODE_ALIASESr%   rU   rº  Úis_containerrÂ  )rb  rô   ÚmoderÛ  Úcurrent_homeÚrepaireds   &     r   Úget_subprocess_homerå    s·   € ð �)ˆ)�€CÜ% cÓ*€LÜ�CÐ-¨vÓ6×<Ñ<Ó>×HÐHÀ&€DÜ×!Ñ! $Ó-€DàˆyÔØÐÜ˜cÓ"€IÜ˜C Ó(€LÜ+¨IÓ6¼/È,Ó:WÔW‰yÐ]a€HØˆv„~ØˆçœŸšØÐßÔ+¨L×GÒGØˆÙr   c                óJ   € V ^8„  d   QhR\         \        \        3,          RR/# )r   rb  r   N)r   r   )r   s   "r   r   r   !  s#   € ÷ 	ñ 	¤>´#´s°(Õ#;ð 	Àñ 	r   c                óx   € \        V 4      pV'       d   WR&   \        V 4      pV'       d   W R&   \        V 4       R# )z°Apply Hermes' subprocess HOME contract to *env* in-place: ``HOME``/``HERMES_REAL_HOME``
per the home mode, and the temp vars re-pointed at ``env["HERMES_HOME"]``'s scratch dir.rÈ  ro   N)rU   rå  Úapply_scratch_tmp_env)rb  rÛ  rH   s   &  r   Úapply_subprocess_home_envré  !  s6   € ô ˜cÓ"€IßØ"+ÐÑÜ˜sÓ#€DßØˆF‰Ü˜#Ör   ÚHERMES_SCRATCH_DIRz.last_prunei  c                ó$   € V ^8„  d   QhR\         /# rF   r#   )r   s   "r   r   r   D  s   € ÷ 
ñ 
œCñ 
r   c                 óÒ   € ^ RI p \        P                  R8X  d   R# V P                  4       p\	        V4      \
        8:  g&   \        P                  P                  R4      '       g   V# R# )zíTemp root short enough for AF_UNIX sockets. The scratch dir usually fits; macOS
``TMPDIR`` never does and a deep profile home may not, so those fall back to the OS
default root for sockets only (everything else stays in the scratch dir).NÚdarwinrÒ  )	rÔ  r>   r?   rÕ  r®  ÚSOCKET_TMPDIR_MAX_LENr-   r   r½  )rÔ  r´   s     r   Úsocket_safe_tmpdirrï  D  sL   € ó Ü
‡|�|�xÔÙØ×#Ñ#Ó%€IÜ
ˆ9ƒ~Ô.Ô.´b·g±g·m±mÀF×6KÒ6KØÐÙr   ÚnixosÚbrewÚhomebrewc                ób   € V ^8„  d   QhR\         \        ,          R,          R\         R,          /# rÐ   r+   )r   s   "r   r   r   `  s'   € ÷ ñ œS¤4�Z¨$Õ.ð ¼#À½*ñ r   c                óâ  € \         P                  ! RR4      P                  4       P                  4       ;'       g    RpV e   \	        V 4      M	\        4       R,          pVfG   VP                  4       '       d1    VP                  RRR7      P                  4       P                  4       pVe   V\        9   g   V\        9   d   R# VR8X  g   V\        9   d   \        # V#   \         d    Rp LEi ; i)uù  Return the package manager owning this install, if any.
Signals: HERMES_MANAGED env var (systemd service) or a ``.managed`` marker file in
HERMES_HOME (NixOS activation script â€” interactive shells don't see the service env).
An unreadable or empty marker still counts as managed (the legacy NixOS shape).

``home`` names the home whose marker file is read, for callers that already resolved it
(:func:`get_scratch_dir` at boot, before ``--profile`` re-homes the process).
Defaults to the effective home.ÚHERMES_MANAGEDr7   Nz.managedr—   Úreplace)r™   Úerrors)r-   r)  r@   rP  r   r­   rœ   r�   rS   Ú_IGNORED_MANAGED_VALUESÚ_MANAGED_FALSE_VALUESÚ_MANAGED_TRUE_VALUESÚ_LEGACY_MANAGED_SYSTEM)rH   rÞ   Úmanaged_markers   &  r   Úget_managed_systemrý  `  sÐ   € ô �YŠYÐ'¨Ó,×2Ñ2Ó4×:Ñ:Ó<×DÐDÀ€FØ$(Ò$4”d˜4”j¼/Ó:KÈzÕY€NØ‚~˜.×/Ñ/×1Ò1ð	Ø#×-Ñ-°wÀyÐ-ÓQ×WÑWÓY×_Ñ_ÓaˆFð ‚~˜Ô#:Ô:¸fÔH]Ô>]ÙØ�„|�vÔ!5Ô5Ü%Ð%Ø€Møô ô 	ØŠFð	ús   Á9/C ÃC.Ã-C.c                ó$   € V ^8„  d   QhR\         /# rF   rÄ   )r   s   "r   r   r   w  s   € ÷ 
ñ 
¤Tñ 
r   c                 ó®   € \         P                  P                  R4      '       g&   \         P                  P                  R4      '       d   R# \        4       # )uB  Container/chmod-skip detection: the ``HERMES_CONTAINER``/``HERMES_SKIP_CHMOD`` operator
overrides on top of the canonical :func:`_detect_container` signals (same breadth as
:func:`is_container` â€” Docker/Podman/LXC/Kubernetes, cgroup and root-mountinfo). The cached
:func:`is_container` itself is deliberately avoided: it ignores these env overrides and is
computed only once per process, so tests could not flip it. Volume-mounted config is not
forced to owner-only in containers: gateway and dashboard may run as different UIDs, or
the mount itself needs broader permissions.ÚHERMES_CONTAINERÚHERMES_SKIP_CHMODT)r-   r3   r%   Ú_detect_containerrI   r   r   Ú_container_or_chmod_skippedr  w  s7   € ô 
‡z�z‡~�~Ð(×)Ò)¬R¯Z©Z¯^©^Ð<O×-PÒ-PÙÜÓÐr   c                ób   € V ^8„  d   QhR\         \        R,          \        R,          3,          /# r"   )ÚtupleÚint)r   s   "r   r   r   „  s%   € ÷ :ñ :¤¤s¨T¥z´3¸µ:Ð'=Õ!>ñ :r   c                 ó\   € \         P                  R8X  d   R# R R lp V ! R4      V ! R4      3# )aº  Read HERMES_UID / HERMES_GID (set by Docker deployments); (None, None) if unset/invalid/Windows.
The entrypoint chowns HERMES_HOME once, but subdirs created at runtime (``profiles/<name>/``)
need the same chown or they land root:root and block later uid-mapped workers.

Docker containers running Hermes commonly set these to map the in-container user to a host user so
volume-mounted state files end up with the right ownership. See #34107.
r8   c                ó>   € V ^8„  d   QhR\         R\        R,          /# )r   rj   r   N)r   r  )r   s   "r   r   Ú-_resolve_hermes_uid_gid.<locals>.__annotate__�  s   € ÷ ñ ”sð œs T�zñ r   c                 ó¶   €  \        \        P                  P                  V R 4      P	                  4       ;'       g    R4      #   \
        \        3 d     R# i ; i)r7   N)r  r-   r3   r%   r@   Ú	TypeErrorrh   r©  s   &r   Ú_env_intÚ)_resolve_hermes_uid_gid.<locals>._env_int�  sI   € ð	Ü”r—z‘z—~‘~ d¨BÓ/×5Ñ5Ó7×?Ð?¸4Ó@Ð@øÜœ:Ð&ô 	Úð	ús   ‚9A ¼A ÁAÁAÚ
HERMES_UIDÚ
HERMES_GID)NN)r>   r?   )r  s    r   Ú_resolve_hermes_uid_gidr  „  s2   € ô ‡|�|�wÔØÐõñ �LÓ!¡8¨LÓ#9Ð9Ð9r   c                ó   € V ^8„  d   QhRR/# r"   rI   )r   s   "r   r   r   ˜  s   € ÷ ñ  $ñ r   c                ó´   € \        4       w  rVf   Vf   R#  \        P                  ! Ye   TMRVe   TMR4       R#   \        \        \
        3 d     R# i ; i)a<  Chown ``path`` to ``HERMES_UID:HERMES_GID`` when set; EPERM/ENOENT are non-fatal (the
entrypoint's startup chown -R fixes ownership on the next restart).

Used by :func:`apply_secure_dir_policy` to keep ownership consistent across all directories
created by ``ensure_hermes_home`` on Docker deployments. See #34107.
Néÿÿÿÿ)r  r-   ÚchownrS   rT   ÚNotImplementedError)r   ÚuidÚgids   &  r   Ú_chown_to_hermes_uidr  ˜  sT   € ô 'Ó(�H€CØ
‚{�s’{ÙðÜ
�Š�šo‘s°2¸cºo±sÐSUÖVøÜ”^Ô%8Ð9ô Úðús   ˜#= ½AÁAc                óL   € V ^8„  d   QhR\         \        ,          R,          RR/# rÐ   r+   )r   s   "r   r   r   ¨  s#   € ÷ !ñ !¬3´­:¸Õ+<ð !Èñ !r   c               ó�  € \        V4      e   R# \        P                  P                  RR4      P	                  4       p\        4       '       d   V'       g   \        V 4       R#  \        T;'       g    R^4      p \        P                  ! W4       \        V 4       R#   \         d    Rp L3i ; i  \        \        3 d     L3i ; i)uQ  Apply the canonical Hermes home-directory permission policy to *path*.

Owner-only ``0700`` by default, but the operator's explicit and managed sharing choices
win (#117347): managed installs are left exactly as the package manager / activation
script set them (#77579); in a container only an explicit ``HERMES_HOME_MODE`` is applied
(a bind-mounted data dir is often shared with sibling containers, #10757); elsewhere
``HERMES_HOME_MODE`` (e.g. ``0701``, ``2770``) is passed to the host's ``chmod``. Special
bits may be cleared by the host filesystem (macOS commonly clears setgid on directories
whose group the caller does not belong to). ``HERMES_UID`` / ``HERMES_GID`` ownership is
applied when those env vars are set (#34107).

``home`` (keyword-only: both arguments are path-likes) names the home whose managed-mode
marker is read, for callers that already resolved it; without it the effective home is
consulted.

Import-safe twin of ``hermes_cli.config._secure_dir`` (which delegates here), so callers
outside the CLI package â€” like :func:`get_scratch_dir` â€” share one policy implementation.
NÚHERMES_HOME_MODEr7   Ú700r­  )rý  r-   r3   r%   r@   r  r  r  rh   rµ  rS   r  )r   rH   Úexplicit_moderâ  s   &$  r   Úapply_secure_dir_policyr  ¨  s©   € ô& ˜$ÓÒ+ÙÜ—J‘J—N‘NÐ#5°rÓ:×@Ñ@ÓB€MÜ"×$Ò$¯]Ü˜TÔ"ÙðÜ�=×)Ð) E¨1Ó-ˆðÜ
�Š�Ôô ˜Öøô ô ØŠðûô Ô(Ð)ô Ùðús*   Á$B Á2B Á;B1 ÂB.Â-B.Â1CÃCÚpruneTc                ó`   € V ^8„  d   QhR\         \        ,          R,          R\        R\        /# )r   rH   Nr  r   rù   )r   s   "r   r   r   Ì  s*   € ÷ ñ œ#¤�* tÕ+ð ¼dð Ìdñ r   c               ó
  € V e   \        V 4      M	\        4       pVR,          R,          p VP                  RRR7       \        P                  R8w  d   \        W2R7       T'       d   \        T4       T#   \         d     L"i ; i)ac  ``<home>/cache/scratch`` (created, owner-only); *home* defaults to the active Hermes home.

Every Hermes process and child gets ``TMPDIR``/``TMP``/``TEMP`` pointed here at boot (see
:func:`export_scratch_tmp_env`), so ``tempfile`` defaults land here without call sites
knowing. Entries idle for ``SCRATCH_MAX_IDLE_HOURS`` are pruned at most once per process
and once per hour across processes (stamp file), so a fan-out of children stays cheap.

Permissions follow :func:`apply_secure_dir_policy`, so an explicit ``HERMES_HOME_MODE`` or
a managed/shared home is honored instead of a blanket ``0700`` (#117347).
ÚcacheÚscratchTr  r8   r¤  )r   r­   r  r>   r?   r  rS   Ú_prune_scratch_dir_once)rH   r  rC   r#  s   &$  r   Úget_scratch_dirr%  Ì  sv   € ð Ò)Œ4�Œ:¬Ó/@€DØ�W�n˜yÕ(€GðØ�‰˜d¨TˆÔ2Ü�<‰<˜7Ô"ô $ GÕ7÷ Ü Ô(Ø€Nøô	 ô Ùðús   «4A4 Á4BÂBc                óJ   € V ^8„  d   QhR\         R,          R\        R\        /# )r   r#  NÚmax_idle_hoursr   )r   Úfloatr  )r   s   "r   r   r   æ  s+   € ÷ 
añ 
aœt d�{ð 
aÄ5ð 
aÔfiñ 
ar   c                óª   € ^ RI Hp V e   T M\        RR7      pVP                  P                  R,          R,          pV! W1\	        \
        04      V4      # )aq  Delete top-level scratch entries with no write anywhere in their subtree for
*max_idle_hours*, reaping processes and git worktree registrations rooted in them
first (``hermes_constants_scratch``); return the count removed. Each removal, each
kill and each entry rescued mid-prune is recorded in ``<home>/logs/scratch-prune.log``
(*scratch* is ``<home>/cache/scratch``).)Úprune_idle_entriesF©r  Úlogszscratch-prune.log)Úhermes_constants_scratchr*  r%  ri   Ú	frozensetÚ_SCRATCH_PRUNE_STAMP)r#  r'  r*  r�   Úlog_files   &&   r   Úprune_scratch_dirr1  æ  sK   € õ <àÒ)‰7¬ÀUÔ/K€DØ�{‰{×!Ñ! FÕ*Ð-@Õ@€HÙ˜d´IÔ?SÐ>TÓ4UÐW_Ó`Ð`r   c                ó(   € V ^8„  d   QhR\         RR/# )r   r#  r   Nr   )r   s   "r   r   r   ó  s   € ÷ #ñ #¤Tð #¨dñ #r   c                 ó–  € \         '       d   R # Rs ^ R IpV \        ,          p VP                  4       VP                  4       P                  ,
          \
        8  d   R #  \        P                  ! \        4      ;_uu_ 4        VP                  4        \        V 4       R R R 4       R #   \         d     LUi ; i  + '       g   i     R # ; i)NT)Ú_scratch_pruned_onceÚtimer/  r  Úst_mtimeÚ_SCRATCH_PRUNE_INTERVAL_SECONDSrS   rŸ   r    r¡   Útouchr1  )r#  r5  Ústamps   &  r   r$  r$  ó  s—   € çÓÙØÐÛØÔ*Õ*€EðØ�9‰9‹;˜Ÿ™›×.Ñ.Õ.Ô1PÔPÙð Qô 
×	Ò	œY×	'Õ	'Ø�‰ŒÜ˜'Ô"÷ 
(Ñ	'øô ô Ùðúç	'×	'Ð	'ús   £8B& Â B7Â&B4Â3B4Â7C	c                ó>   € V ^8„  d   QhR\         R,          R\        /# )r   r#  Nr   )r   r  )r   s   "r   r   r     s   € ÷ ñ ¤T¨D¥[ð ¼Cñ r   c                óŒ  € V e   T M\        RR7      p^ p\        P                  ! VR R7       F~  w  r4pV Fr  p\        P                  ! \
        4      ;_uu_ 4        V\        P                  ! \        P                  P                  W64      4      P                  ,          pRRR4       Kt  	  K€  	  V#   + '       g   i     K�  ; i)zMTotal bytes under the scratch dir (for ``hermes doctor``); 0 when unreadable.NFr+  c                 ó   € R # rZ   rI   )Ú_es   &r   r\   Ú)scratch_dir_usage_bytes.<locals>.<lambda>  s   € É$r   )Úonerror)
r%  r-   ÚwalkrŸ   r    rS   r™  r   rÌ  r	  )r#  r�   ÚtotalÚdirpathÚ	_dirnamesÚ	filenamesrj   s   &      r   Úscratch_dir_usage_bytesrE    s�   € àÒ)‰7¬ÀUÔ/K€DØ€EÜ)+¯ª°¹×)OÑ%ˆ˜IÛˆDÜ×$Ò$¤W×-Õ-ØœŸš¤"§'¡'§,¡,¨wÓ"=Ó>×FÑFÕF�÷ .Ñ-ó ñ *Pð €L÷ .×-Ð-ús   ÁAB2	Â2Cc                óR   € V ^8„  d   QhR\         \        \        3,          R\        /# )r   rb  r   )r   r   rÅ   )r   s   "r   r   r     s#   € ÷ ñ œ~¬c´3¨hÕ7ð ¼Dñ r   c                ó´  € V P                  \        R4      p\         F6  pV P                  VR4      P                  4       pV'       g   K-  W18w  g   K5   R# 	  V P                  RR4      P                  4       p \	        \        V'       d   \        V4      M	\        4       4      4      p\         F  pYPT&   K	  	  YP\        &   R#   \        \        3 d     R# i ; i)uÔ  Point ``TMPDIR``/``TMP``/``TEMP`` in *env* at the scratch dir of ``env["HERMES_HOME"]``.

A temp var the user (or the OS: macOS ``/var/folders``, Windows ``%TEMP%``) set is
respected and nothing changes. A value Hermes itself exported earlier â€” recognisable
because it equals ``HERMES_SCRATCH_DIR`` â€” is re-derived, so a child running under another
profile's home gets that home's scratch dir rather than its parent's. Returns True when
the vars were (re)written.
r7   Frv   T)
r%   ÚSCRATCH_DIR_MARKER_ENVÚSCRATCH_TMP_ENV_VARSr@   r   r%  r1   r¬   r_   rS   )rb  Úoursr‡   r   rH   r#  s   &     r   rè  rè    s»   € ð �7‰7Ô)¨2Ó.€Dß#ˆØ—‘˜˜RÓ ×&Ñ&Ó(ˆß‰5�U–]Úñ $ð �7‰7�= "Ó%×+Ñ+Ó-€DðÜ”oÇ4Ô&9¸$Ô&?ÔMdÓMfÓgÓhˆ÷
 $ˆØˆC‹ñ $à")ÔÑÙøô œ'Ð"ô ò ðús   Á8/C ÃCÃCc                ó$   € V ^8„  d   QhR\         /# rF   rÄ   )r   s   "r   r   r   *  s   € ÷ ñ ¤ñ r   c                 ó^   € \        \        P                  4      p V '       d   ^ RIpRVn        V # )a  Boot hook: apply :func:`apply_scratch_tmp_env` to this process and reset ``tempfile``'s
cached default so ``tempfile.gettempdir()`` follows. Call again after anything that
re-homes the process (``--profile`` resolution); a user-set temp var is never overridden.N)rè  r-   r3   rÔ  Útempdir)ÚchangedrÔ  s     r   Úexport_scratch_tmp_envrO  *  s%   € ô $¤B§J¡JÓ/€GßÛØˆÔØ€Nr   c                ó2   € V ^8„  d   QhR\         R,          /# r"   )r�  )r   s   "r   r   r   8  s   € ÷ ñ ¤d¨T¥kñ r   c                óˆ  € V e   V RJ d   R# \        V \        4      '       d]   V P                  RR4      RJ d   RR/# \        V P                  R4      ;'       g    R4      P	                  4       pV'       d   RRRV/# R# \        V 4      P	                  4       P                  4       p V R9   d   RR/# V \        9   d   RRRV /# R# )uT  Parse a reasoning effort level into a config dict.

``None`` for empty/unrecognized input (caller uses the default); ``{"enabled": False}`` for
"none"/"false"/"disabled"/YAML False â€” ``reasoning_effort: false`` must mean disabled.

The dict form ``{"enabled": true, "effort": "<level>"}`` passes ``effort`` through verbatim so
providers with bespoke thinking tiers (``fast``/``thinking`` relays) can be asked for their real
level; bare strings stay strict so a typo like ``hgih`` never reaches the wire. The wire layer
already tolerates unknown names (``agent.reasoning_effort.clamp_effort``).
NTÚenabledFÚeffortr7   >   ÚnoneÚfalseÚdisabled)Ú
isinstancer�  r%   r   r@   rP  ÚVALID_REASONING_EFFORTS)rS  Úlevels   & r   Úparse_reasoning_effortrZ  8  sÁ   € ð ‚~˜ 4›ÙÜ�&œ$×ÒØ�:‰:�i Ó&¨%Ó/Ø˜uÐ%Ð%ä�F—J‘J˜xÓ(×.Ð.¨BÓ/×5Ñ5Ó7ˆß5:�	˜4 ¨5Ð1ÐDÀÐDÜ�‹[×ÑÓ ×&Ñ&Ó(€FØÐ.Ô.Ø˜5Ð!Ð!ØÔ(Ô(Ø˜4 ¨6Ð2Ð2Ùr   c                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r   Úmodelr   rK  )r   s   "r   r   r   S  s   € ÷ "ñ "¤Sð "¬T´#­Yñ "r   c                ó   aaaaa	a
€ R oR o\        4       o	. o
V	V
3R loVVV3R lpV! V 4       V P                  R4      p\        V4      ^8¼  d   V! VR	,          4       \        V4      ^8¼  d   V! RP                  VR,          4      4       R
pS
 Uu. uF  pRV9  g   K  VNK  	  up F  oS! V3R lV 4       !   K  	  RpS
 Uu. uF  qDP	                  R4      ^8X  g   K  VNK  	  up F  oS! V3R lV 4       !   K  	  S
# u upi u upi )z¸Spelling variants for tolerant override matching, exact first, deduped in order.

Dot/dash recovery runs on EACH base form so ``x-4.5``, ``x-4-5`` and ``x.4.5`` share one variant set.
c                 ó2   € \         P                  ! R RV 4      # )z	(\d)-(\d)z\1.\2©Úrer„   ©Úss   &r   r\   Ú+_canonical_model_variants.<locals>.<lambda>X  s   € œRŸVšV L°(¸AÔ>r   c                 ó2   € \         P                  ! R RV 4      # )z
(\d)\.(\d)z\1-\2r_  ra  s   &r   r\   rc  Y  s   € œRŸVšV M°8¸QÔ?r   c                  ó„   <€ V  F8  pV'       g   K  VS9  g   K  SP                  V4       SP                  V4       K:  	  R # rZ   )rÓ  rË  )ÚvaluesÚvrÖ  Úvariantss   * €€r   Ú_addÚ'_canonical_model_variants.<locals>._add]  s/   ø€ ÛˆAß‰q�Q˜d–]Ø—‘˜”Ø—‘ Ö"ó r   c                 ó˜   <€ V P                  R R4      V P                  RR 4      r!S! WVS! V 4      S! V 4      S! V4      S! V4      4       R# )ré   Ú-N)rö  )rb  ÚdashedÚdottedri  Ú_dash_to_dotÚ_dot_to_dashs   &  €€€r   Ú_add_with_derivativesÚ8_canonical_model_variants.<locals>._add_with_derivativesc  sF   ø€ ØŸ™ 3¨Ó,¨a¯i©i¸¸SÓ.A�ÙˆQ˜¡¨Q£±¸a³Á,ÈvÓBVÑXdÐekÓXlÖmr   r  r   c              3   ó0   <"  € T F  q R S 2x € K  	  R# 5i©r  NrI   )rÝ   Úproviderrg  s   & €r   rß   Ú,_canonical_model_variants.<locals>.<genexpr>q  s   øé € ÐA± X�˜1˜Q˜CÕ ³ùó   ƒc              3   ó0   <"  € T F  q R S 2x € K  	  R# 5irt  rI   )rÝ   Úaggrg  s   & €r   rß   rv  t  s   øé € Ð9Ñ'8 ��a˜�s�|Ó'8ùrw  r  )Ú	anthropicÚopenaiÚgoogleÚ
openrouterÚgroqÚmistralÚxaiÚcohereÚ
perplexityÚtogetherÚ	fireworksÚdeepseek)r}  Úopencoder„  r~  rƒ  )r   r†  r®  rÌ  Úcount)r\  rq  r¯  Úknown_providersrg  Úknown_aggregatorsri  ro  rp  rÖ  rh  s   &   ` @@@@@r   Ú_canonical_model_variantsrŠ  S  sù   ý€ ñ
 ?€LÙ?€LÜ“U€DØ€Hö#÷nñ ˜%Ô Ø�K‰K˜Ó€EÜ
ˆ5ƒz�Q„Ù˜e B�iÔ(Ü
ˆ5ƒz�Q„Ù˜cŸh™h u¨R¥yÓ1Ô2ð€Oñ "Ó2™�A S°¡\�aˆa™Ô2ˆÙÔA±ÓAÔBñ 3àSÐÙ!Ó7™�A§W¡W¨S£\°QÑ%6�aˆa™Ô7ˆÙÔ9Ñ'8Ó9Ô:ñ 8à€Oùò 3ùò 8s   Â	DÂ"DÃDÃ$Dc                óX   € V ^8„  d   QhR\         R\        R,          R\        R,          /# )r   r\  Ú	overridesNr   ©r   r�  )r   s   "r   r   r   x  s*   € ÷  ñ  ¬cð  ¼dÀT½kð  ÌdÐUYÍkñ  r   c                ó¨  a	€ V'       d   \        V\        4      '       d	   V '       g   R# \        V 4      pV F$  pW19   g   K  \        W,          4      pVf   K"  Vu # 	  \	        V4      o	VP                  4        FÔ  w  rV\        V\        4      '       d   RV9  d   K$  VP                  R4      p\        VR,          4      p\        V4      ^8¼  d)   V\        RP                  VR,          4      4      ,          p\        ;QJ d    V	3R lV 4       F  '       g   K   RM	  RM! V	3R lV 4       4      '       g   KÁ  \        V4      pVf   KÒ  Vu # 	  R# )u¾  Per-model reasoning_effort override with spelling tolerance; first non-None parse wins.

Order: exact â†’ dotsâ†”dashes â†’ provider stripped â†’ aggregator stripped â†’ known prefixes added â†’
reverse lookup of prefixed keys whose stripped forms match (custom provider slugs are not
enumerable, so a key like ``ollama-local/qwen3.6:27b`` must still match the bare
``qwen3.6:27b`` model string a fallback swap feeds after stripping the prefix).
Nr  r   c              3   ó,   <"  € T F	  qS9   x € K  	  R # 5irZ   rI   )rÝ   ÚformÚvariant_sets   & €r   rß   Ú5resolve_per_model_reasoning_effort.<locals>.<genexpr>”  s   øé € Ð9©y t�{Ö"«yùr|  TFr  )rW  r�  rŠ  rZ  r   r‚   r   r†  r®  rÌ  rã   )
r\  rŒ  rh  ÚvariantrÖ   r‡   rˆ   r¯  Ú	key_formsr‘  s
   &&       @r   Ú"resolve_per_model_reasoning_effortr•  x  sý   ø€ ÷ œJ y´$×7Ò7¿uÙÜ(¨Ó/€HÛˆØÖÜ+¨IÕ,>Ó?ˆFØÔ!Ø’ñ	 ô �h“-€KØ—O‘OÖ%‰ˆÜ˜#œs×#Ò# s°#¤~ÙØ—	‘	˜#“ˆÜ-¨e°B­iÓ8ˆ	Üˆu‹:˜Œ?ØÔ2°3·8±8¸EÀ"½IÓ3FÓGÕGˆIß‹3Ô9©yÓ9�3�3Š3Ô9©yÓ9×9Ô9Ü+¨CÓ0ˆFØÔ!Ø’ñ &ñ r   c                óJ   € V ^8„  d   QhR\         R\        R,          R\        /# )r   r\  ÚmodelsNr   r�  )r   s   "r   r   r   ›  s%   € ÷ 
ñ 
¬cð 
¼4À$½;ð 
Ì4ñ 
r   c                óÀ   € V '       d   \        V\        4      '       g   / # \        V 4       F.  pVP                  V4      p\        V\        4      '       g   K,  Vu # 	  / # )zò``provider_routing.models.<id>`` entry for *model*, spelling-tolerant like
``reasoning_overrides``; ``{}`` when none matches. Only the keys a user sets per model
are returned so unset ones fall through to the flat ``provider_routing`` values.)rW  r�  rŠ  r%   )r\  r—  r“  Úentrys   &&  r   Ú"resolve_per_model_provider_routingrš  ›  sN   € ÷ œ
 6¬4×0Ò0Øˆ	Ü,¨UÖ3ˆØ—
‘
˜7Ó#ˆÜ�eœT×"Ô"ØŠLñ 4ð €Ir   c                óX   € V ^8„  d   QhR\         R,          R\        R\         R,          /# )r   ÚcfgNr\  r   r�  )r   s   "r   r   r   ¨  s)   € ÷ ñ ¤$¨¥+ð ´cð Ä4È$Å;ñ r   c                óö  € \        V \        4      '       d   T M/ p \        V P                  R4      \        4      '       d   V P                  R4      M/ pV'       g„   V P                  R4      p\        V\        4      '       d5   VP                  R4      ;'       g    VP                  R4      ;'       g    Rp\        V\        4      '       d   VP	                  4       MRp\        YP                  R4      ;'       g    / 4      pVe   V# VP                  RR4      p\        V4      pV'       dM   \        V4      P	                  4       '       d.   Vf*   ^ RIpVP                  \        4      P                  RV4       V# )	zÅEffective reasoning config for *model*: per-model override, then global ``agent.reasoning_effort``.

Single chokepoint for every surface (CLI, gateway, TUI, cron, ``/model``, fallback activation).
Úagentr\  r   r7   Úreasoning_overridesNÚreasoning_effortz5Unknown reasoning_effort '%s', using default (medium))rW  r�  r%   r   r@   r•  rZ  r±  r²  r³  r´  )rœ  r\  Ú	agent_cfgÚ	model_cfgÚ	per_modelrS  rÖ   r±  s   &&      r   Úresolve_reasoning_configr¤  ¨  s  € ô
 ˜C¤×&Ò&‰#¨B€CÜ$.¨s¯w©w°wÓ/?Ä×$FÒ$F�—‘˜Ô ÈB€IçØ—G‘G˜GÓ$ˆ	Ü�i¤×&Ò&Ø!Ÿ™ iÓ0×PÐP°I·M±MÀ'Ó4J×PÐPÈbˆIÜ%/°	¼3×%?Ò%?�	—‘Ô!ÀRˆÜ2°5¿-¹-ÐH]Ó:^×:dÐ:dÐbdÓe€IØÒØÐð �]‰]Ð-¨rÓ2€FÜ# FÓ+€Fß”#�f“+×#Ñ#×%Ò%¨&ª.ÛØ×Ñœ(Ó#×+Ñ+Ð,cÐekÔlØ€Mr   c                ó$   € V ^8„  d   QhR\         /# rF   rÄ   )r   s   "r   r   r   Â  s   € ÷ ñ ”4ñ r   c                 ó   € ^ RI Hp  V ! 4       # )zcDelegate Termux detection without making the bootstrap constants module depend on the full package.)Ú	is_termux)Úhermes_platform.host.runtimer§  ©Údetects    r   r§  r§  Â  s   € å@á‹8€Or   c                ó$   € V ^8„  d   QhR\         /# rF   rÄ   )r   s   "r   r   r   É  s   € ÷ ñ ”ñ r   c                 ó   € ^ RI Hp  V ! 4       # )z`Delegate WSL detection without making the bootstrap constants module depend on the full package.)Úis_wsl)r¨  r­  r©  s    r   r­  r­  É  s   € å=á‹8€Or   c                ó$   € V ^8„  d   QhR\         /# rF   rÄ   )r   s   "r   r   r   Ð  s   € ÷ ñ ”dñ r   c                 ó   € ^ RI Hp  V ! 4       # )zfDelegate container detection without making the bootstrap constants module depend on the full package.)rá  )r¨  rá  r©  s    r   rá  rá  Ð  s   € åCá‹8€Or   c                ó$   € V ^8„  d   QhR\         /# rF   rÄ   )r   s   "r   r   r   ×  s   € ÷ ñ œ4ñ r   c                 ó   € ^ RI Hp  V ! 4       # )zCKeep the historical test seam while delegating canonical detection.)r  )r¨  r  r©  s    r   r  r  ×  s   € åHá‹8€Or   c                ó>   € V ^8„  d   QhR\         R\         R,          /# rç   r#   )r   s   "r   r   r   Þ  s"   € ÷ fñ fœcð f¤c¨D¥jñ fr   c                ó   € \         P                  ! R\        T ;'       g    R4      P                  4       4      pV'       dN   RVP	                  ^4      P                  4        RVP	                  ^4      P                  \        ^\4      R4       2# R# )zKConvert a Windows drive path (``C:\...``) to its ``/mnt/<drive>/...`` form.z^([A-Za-z]):[\\/](.*)$r7   z/mnt/r  N)r`  r{   r   r@   rx   rP  rö  Úchr)r   r{   s   & r   Úwindows_path_to_wslrµ  Þ  sm   € ä�HŠHÐ.´°D·J°J¸B³×0EÑ0EÓ0GÓH€EßV[ˆU�5—;‘;˜q“>×'Ñ'Ó)Ð*¨!¨E¯K©K¸«N×,BÑ,BÄ3ÀrÃ7ÈCÓ,PÐ+QÐRÐeÐaeÐer   c                ó>   € V ^8„  d   QhR\         R\         R,          /# rç   r#   )r   s   "r   r   r   ä  s"   € ÷ Fñ F¤ð F¬¨d­
ñ Fr   c                ó  € \        T ;'       g    R4      P                  4       P                  RR4      p\        P                  ! RV\        P
                  4      pV'       d)   RVP                  ^4      P                  RR4      ,           # R# )zTConvert a ``\\wsl.localhost\<distro>\...`` (or legacy ``\\wsl$``) UNC path to POSIX.r7   r  r€  z)^\\\\wsl(?:\.localhost|\$)\\[^\\]+\\(.*)$N)r   r@   rö  r`  r{   Ú
IGNORECASErx   )r   Ú
normalizedr{   s   &  r   Úwsl_unc_path_to_posixrº  ä  se   € ä�T—Z�Z˜R“×&Ñ&Ó(×0Ñ0°°dÓ;€JÜ�HŠHÐAÀ:ÌrÏ}É}Ó]€Eß6;ˆ3�—‘˜Q“×'Ñ'¨¨cÓ2Õ2ÐEÀÐEr   c                ó0   € V ^8„  d   QhR\         R\         /# )r   Úcwdr   r#   )r   s   "r   r   r   ë  s   € ÷ ñ ¤sð ¬sñ r   c                óp   € \        4       '       g   V # \        \        3 F  pV! V 4      pVf   K  Vu # 	  V # )zŽMap a Windows-host cwd (drive path or ``\\wsl.localhost\`` UNC) to POSIX when Hermes runs in WSL.

No-op off WSL and for paths already POSIX.
)r­  rº  rµ  )r¼  Ú
translatorÚ
translateds   &  r   Útranslate_cwd_for_wsl_backendrÀ  ë  s=   € ô
 �8Š8Øˆ
Ü,Ô.AÓBˆ
Ù “_ˆ
ØÔ!ØÒñ Cð €Jr   c                ó$   € V ^8„  d   QhR\         /# rF   r   )r   s   "r   r   r   ù  s   € ÷ -ñ -œñ -r   c                 ó$   € \        4       R,          # )z5Return the path to ``config.yaml`` under HERMES_HOME.úconfig.yaml©r­   rI   r   r   Úget_config_pathrÅ  ù  s   € äÓ˜}Õ,Ð,r   c                ó$   € V ^8„  d   QhR\         /# rF   r   )r   s   "r   r   r   þ  s   € ÷ (ñ (œñ (r   c                 ó$   € \        4       R,          # )z:Return the path to the skills directory under HERMES_HOME.r8  rÄ  rI   r   r   Úget_skills_dirrÈ  þ  s   € äÓ˜xÕ'Ð'r   c                ó$   € V ^8„  d   QhR\         /# rF   r   )r   s   "r   r   r     s   € ÷ &ñ &”dñ &r   c                 ó$   € \        4       R,          # )z7Return the path to the ``.env`` file under HERMES_HOME.r  rÄ  rI   r   r   Úget_env_pathrË    s   € äÓ˜vÕ%Ð%r   c                ó(   € V ^8„  d   QhR\         RR/# )r   Úforcer   NrÄ   )r   s   "r   r   r     s   € ÷ +ñ +¤ð +°$ñ +r   c                óª   aa€ V '       g   R# ^ RI o\        SP                  RR4      '       d   R# SP                  oRVV3R llpRVn        VSn        R# )a   Monkey-patch ``socket.getaddrinfo`` to prefer IPv4 when *force* is True.

Broken-IPv6 hosts hang on AAAA for the full TCP timeout; ``AF_UNSPEC`` resolves as ``AF_INET``,
falling back to full resolution when no A record exists (pure-IPv6 hosts still work).
NÚ_hermes_ipv4_patchedFc           	      ó”   <€ V^ 8X  d    S! WSP                   W4V4      # S! WW#WE4      #   SP                   d    S! YY#YE4      u # i ; i)é    )ÚAF_INETÚgaierror)rØ  ÚportÚfamilyÚtypeÚprotoÚflagsÚ_original_getaddrinfoÚsockets   &&&&&&€€r   Ú_ipv4_getaddrinfoÚ0apply_ipv4_preference.<locals>._ipv4_getaddrinfo  s]   ø€ Ø�QŒ;ðUÙ,¨T¸¿¹ÈÐV[Ó\Ð\ñ % T°¸uÓLÐLøð —?‘?ô UÙ,¨T¸ÀuÓTÒTðUús   Š) ©AÁAT)rÑ  rÑ  rÑ  rÑ  )rÚ  ÚgetattrÚgetaddrinforÏ  )rÍ  rÛ  rÙ  rÚ  s   & @@r   Úapply_ipv4_preferencerß    sR   ù€ ÷ Ùãäˆv×!Ñ!Ð#9¸5×AÒAÙØ"×.Ñ.Ð÷Mð Mð .2ÐÔ*Ø*€FÖr   zpartial-stream-stubÚlengthzhttps://openrouter.ai/api/v1z/modelsc                ó>   € V ^8„  d   QhR\         R\         R,          /# )r   Úmodel_idr   Nr#   )r   s   "r   r   r   7  s   € ÷ ñ ¤cð ¬c°D­jñ r   c                óœ   € T ;'       g    RP                  R4      w  rpV'       d	   V'       g   R# VP                  4       \        9   d   V# R# )u  Return the base model id when ``model_id`` carries a recognized
OpenRouter routing-variant suffix (e.g. ``x-ai/grok-4:nitro`` â†’
``x-ai/grok-4``), else ``None``.

Lives here rather than in ``hermes_cli.models`` so the metadata layer
(``agent.model_metadata``) can share one definition without importing the
CLI â€” this module is dependency-free by contract.

>>> openrouter_variant_base("x-ai/grok-4:nitro")
'x-ai/grok-4'
>>> openrouter_variant_base("x-ai/grok-4:free") is None
True
>>> openrouter_variant_base("x-ai/grok-4") is None
True
r7   Ú:N)Ú
rpartitionrP  ÚOPENROUTER_VARIANT_SUFFIXES)râ  rC   rz  rA   s   &   r   Úopenrouter_variant_baserç  7  s>   € ð  "Ÿ˜ R×3Ñ3°CÓ8Ñ€Dˆvß—dÙØ‡|�|ƒ~Ô4Ô4ØˆÙr   zhttps://ai-gateway.vercel.sh/v1Úwindowsc                ó>   € V ^8„  d   QhR\         R,          R\        /# ©r   rè  Nr   ©rÅ   r   )r   s   "r   r   r   R  s   € ÷ .ñ .¤t¨d¥{ð .¼dñ .r   c               ó    € ^ RI Hp V! WR7      # )úRFrozen updater surface: pre-PM updaters import this name; pm.environments owns it.)Úvenv_bin_dir©rè  )Úpm.environmentsrî  )Úvenv_dirrè  r^   s   &$ r   rî  rî  R  s   € å7á�8Ô-Ð-r   c                ó2   € V ^8„  d   QhR\         R,          /# r"   r   )r   s   "r   r   r   Y  s   € ÷ ñ ¤d¨T¥kñ r   c                ó¨  a€ \        V 4      o\        V3R lR 4       R4      pVe   V# \        \        P                  4      p\        \        4      P                  4       P                  SP                  4       8X  dW   \        P                  \        P                  8w  d4   \        V4      P                  4       '       d   \        VS4      '       d   V# R# )u  The project's ``venv`` or ``.venv`` dir when one exists (``uv venv`` defaults to ``.venv``);
for an install whose interpreter lives outside the checkout, the running interpreter's venv.

``uv venv`` defaults to ``.venv`` while our installers create ``venv``, so both layouts are in the wild.
Call sites that only knew about ``venv`` silently no-oped on a ``.venv`` install â€” that is how the
Windows shim-lock preflight skipped itself entirely (#79542). ``venv`` wins when both exist, matching
what the installers write.

Installers that keep the interpreter out of the checkout (``$HERMES_HOME/venvs/<name>``, the layout the
shipped Windows launchers assume) have neither, and the ``project_venv_dir(root) or root / "venv"``
idiom those call sites share then handed ``uv`` a ``VIRTUAL_ENV`` that does not exist: that one invented
path skipped the import probe, reclassified every ``hermes tools`` dependency as missing and failed the
reinstall with interpreter errors (#116148). The interpreter running this module is the only truthful
answer to "which venv is live", so fall back to it â€” but only for the checkout it was loaded from. A
foreign root (test temp dir, another clone) still resolves to ``None``: handing it someone else's venv
would point the callers' writes at the wrong environment.
c              3   ót   <"  € T F-  pSV,          P                  4       '       g   K"  SV,          x € K/  	  R # 5irZ   )râ   )rÝ   ru  r�   s   & €r   rß   Ú#project_venv_dir.<locals>.<genexpr>l  s*   øé € ÐOÑ&7 ¸DÀ1½H×;LÑ;L×;N”H�D˜1—H’HÓ&7ùs   ƒ8§8N)Úvenvz.venv)r   r�  r>   ÚprefixÚ__file__r^   ri   Úbase_prefixÚvenv_python_pathrÿ   Ú_venv_installs_checkout)Úproject_rootÚin_treeÚrunningr�   s   &  @r   Úproject_venv_dirrÿ  Y  s˜   ø€ ô$ �Ó€DÜÔOÑ&7ÓOÐQUÓV€GØÒØˆô ”3—:‘:Ó€GÜŒX‹×ÑÓ ×'Ñ'¨4¯<©<«>Ô9Ü—
‘
œcŸo™oÔ-Ü  Ó)×1Ñ1×3Ò3Ü'¨°×6Ò6ØˆÙr   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   rö  r�   r   rÚ   )r   s   "r   r   r   z  s!   € ÷ ñ ¤$ð ¬dð ´tñ r   c                óÚ  € ^ RI p^ RIHp ^ RIHp ^ RIHp ^ RIHp V! R\        V! V 4      4      .R7       Fž  p VP                  R4      pTP                  T;'       g    R	4      P                  R
R4      p	T	P                  R4      '       g   KY  \        T! T! T	4      P                   4      4      P#                  4       TP#                  4       8X  g   K�   R# 	  R#   \         d     K²  i ; i)aÔ  Is *venv*'s own ``hermes-agent`` installed from *root*?

Where this module was loaded from does not answer that: ``PYTHONPATH=<checkout>
<other install>/bin/python`` runs one checkout's code on another install's interpreter,
and adopting that venv made a dev checkout's update rewrite the Desktop install's venv
into an editable install of the dev tree. Every install of a checkout into a venv
(installers, ``uv sync``) records the source tree in ``direct_url.json``.
N)Údistributions)Úurlparse)Úurl2pathname)Úsite_packageszhermes-agent)rj   r   zdirect_url.jsonz{}Úurlr7   zfile:TF)ÚjsonÚimportlib.metadatar  Úurllib.parser  Úurllib.requestr  rð  r  r   r�   Úloadsr%   rh   r…   r   r   r^   )
rö  r�   r  r  r  r  r  Údistrˆ   r  s
   &&        r   rû  rû  z  sÂ   € ó Ý0Ý%Ý+å-á >¼¹]È4Ó=PÓ9QÐ8R×Sˆð	Ø—.‘.Ð!2Ó3ˆCØ—*‘*˜SŸ[˜[ DÓ)×-Ñ-¨e°RÓ8ˆCð �>‰>˜'×"Ô"¤t©L¹À#»×9KÑ9KÓ,LÓ'M×'UÑ'UÓ'WÐ[_×[gÑ[gÓ[iÖ'iÚñ Tñ øô	 ô 	Úð	ús   »$CÁ CÃC*Ã)C*c                ó>   € V ^8„  d   QhR\         R,          R\        /# rê  rë  )r   s   "r   r   r   •  s   € ÷ 2ñ 2¬4°$­;ð 2Ä$ñ 2r   c               ó    € ^ RI Hp V! WR7      # )rí  )Úvenv_pythonrï  )rð  r  )rñ  rè  r  s   &$ r   rú  rú  •  s   € å+á�xÔ1Ð1r   c                ó>   € V ^8„  d   QhR\         R,          R\        /# )r   rj   Nr   r`  )r   s   "r   r   r   ¤  s"   € ÷ [ñ [¤ d¥
ð [¬tñ [r   c                óÂ   € V '       d"   \        V 4      P                  R4      ^ ,          MRp\        V4      ;'       d#    V\        9   ;'       g    VP	                  R4      # )zbTrue when *name* ships with Hermes (exact first segment; ``startswith`` would claim ``agentops``).ré   r7   Úhermes_)r   r†  rÅ   ÚFIRST_PARTY_MODULE_ROOTSr…   )rj   r�   s   & r   Úis_first_party_moduler  ¤  sF   € ç&*Œ3ˆt‹9�?‰?˜3Ó Ö"°€DÜ�‹:×ZÐZ˜4Ô#;Ñ;×YÐY¸t¿¹ÈyÓ?YÐZr   c                óF   € V ^8„  d   QhR\         R\        \        ,          /# ©r   Úexcr   )ÚBaseExceptionrB  r   )r   s   "r   r   r   ª  s   € ÷ ñ œ]ð ¬t´C­yñ r   c                óž   € \        V \        4      '       d3   \        V \        4      '       g   \        \	        V RR4      4      '       g   . # . RO# )zORecovery guidance lines when *exc* looks like a half-updated tree, else ``[]``.rj   N)r7   z`This looks like a partially-updated install: one module was refreshed and a related one was not.z>Re-run the update to bring the whole tree to the same version:z    hermes updatezDIf that also fails, reinstall: https://hermes-agent.nousresearch.com)rW  rQ   ÚModuleNotFoundErrorr  rÝ  )r  s   &r   Úpartial_update_hintr  ª  sA   € ô �sœK×(Ò(¬J°sÔ<O×,PÒ,PÜ(¬°°f¸dÓ)C×DÒDØˆ	òð r   Úfilec                ó0   € V ^8„  d   QhR\         R\        /# r  )r  rÅ   )r   s   "r   r   r   º  s   € ÷ ñ ¤-ð Ä$ñ r   c               óŽ   € \        V 4      pV'       g   R# RV  2.VO F#  p\        Y1f   \        P                  MTR7       K%  	  R# )z0Print recovery guidance for a half-updated tree.FzError: )r  T)r  Úprintr>   r¢   )r  r  ÚlinesÚlines   &$  r   Úemit_partial_update_hintr"  º  s?   € ä Ó$€EßÙØ˜3˜%�Ð) 5Ó)ˆÜˆd¢|œŸš¸×>ñ *ár   c                ób   € V ^8„  d   QhR\         \        ,          R,          R\         R,          /# )r   ÚscopeNr   r+   )r   s   "r   r   r   Ä  s+   € ÷ Añ Aœ3¤�:¨Õ,ð A´°tµñ Ar   c                ó$   € V e   \        V 4      # R# )u  Normalize a WRITE-side registry scope key, preserving ``None``.

Two different contracts live on the same registries â€” do not unify them:

* **Write / slot paths** (``register_*``, ``snapshot_registration``,
  ``restore_registration``, tool-registry slot lookup): ``None`` means
  the process-global layer and must stay ``None``. Use this function.
* **Read paths** (``list_providers``, ``get_provider``): ``None`` means
  "the active home's scope" and must go through :func:`hermes_home_key`
  (falsy input resolves to the active default home). Using this
  function there hides every scoped registration â€” the exact bug
  fixed after e66a627aa5.

Both normalize non-None values identically (resolved absolute path,
normcase on Windows) so writes and reads agree on the key.
N)r·   )r$  s   &r   Únormalize_scoper&  Ä  s   € ð" &+Ò%6Œ?˜5Ó!Ð@¸DÐ@r   c                ó\  € V ^8„  d   Qh/ ^ \         9   d
   \        ;R&   ^\         9   d    \        \        \        ,          ,          ;R&   ^\         9   d   \
        \        R3,          ;R&   ^\         9   d
   \        ;R&   ^\         9   d   \        \        \        3,          ;R&   ^\         9   d   \        R,          ;R&   ^\         9   d   \        \        ,          ;R	&   ^\         9   d'   \
        \        \        \        3,          R,          ;R
&   ^\         9   d   \        \        ,          ;R&   # )r   r›   r	   .ÚINDICATOR_STYLESÚDEFAULT_INDICATOR_STYLEr²   NrÁ   ÚLOCAL_RUNTIME_ROOT_DIRSrÒ   ræ  )	Ú__conditional_annotations__rÅ   r   r   Úobjectr  r�  r.  r   )r   s   "r   r   r      sô   € ÷ ñ ÷ 'Ò &œ$Ñ &ñ÷" fÒ e”z¤#¬¥,Õ/Ñ eñ#÷* MÒ L”%œ˜S˜•/Ñ Lñ+÷, )Ò (œÑ (ñ-÷T %Ò $””cœ3�h•Ñ $ñU÷r /Ò .œS 4�ZÑ .ñs÷z TÒ Sœ¤3�Ñ Sñ{÷H	 ?Ò >œ5¤¤c¬4 Õ0°4Õ7Ñ >ñI	÷b)ò œY¤s�^ñ òc)r   )ÚasciiÚemojir   ÚunicoderZ   >   rÌ   r—  Úruntimes)rÃ  r  ústate.db)rÃ  r  zSOUL.mdzprofile.yamlz	auth.jsonr1  )znpm.cmdznpm.exerG  )znpx.cmdznpx.exerH  )r7   )ÚTMPDIRÚTMPÚTEMP)ÚtrueÚ1Úyes>   Ú0ÚnoÚoffrU  )ÚminimalÚlowÚmediumÚhighÚxhighÚmaxÚultra)F>   ÚfloorÚnitroÚexactoÚonline>   ÚcliÚcronrž  ÚtoolsÚutilsÚgatewayÚpluginsÚtoolsetsÚ	providersÚ	run_agentÚacp_adapterÚmodel_toolsÚtui_gateway)�r+  Ú__doc__rŸ   r-   r`  r�  r  r>   Úcollections.abcr   r   r   Úcontextvarsr   r   Úpathlibr   r›   r,  r   r	   r(  r)  r   r    r(   r1   rD   rJ   rV   ra   rk   Úcompilerƒ   rŠ   r“   r©   r­   r²   r·   r»   r¬   rÁ   rÂ   rÇ   rË   r.  r*  ÚCONNECTOR_DOWNLOADS_SUBDIRrÒ   r×   rá   rä   rå   rì   rñ   r÷   rû   r  ÚPROFILE_ID_REr  r
  r  r  r  r  r$  r*  r0  r4  r9  r@  rF  rO  rQ  r^  re  rø  r^   ri   r°  rj  rn  rv  rŒ  rc  r–  r>  r¥  rª  r¶  rº  r¿  rÂ  rÅ  rÏ  rU   rà  rå  ré  rI  rH  ÚSCRATCH_MAX_IDLE_HOURSr/  r7  r4  rî  rï  rú  rû  rø  rù  rý  r  r  r  r  r%  r1  r$  rE  rè  rO  rX  rZ  rŠ  r•  rš  r¤  r§  r­  rá  r  rµ  rº  rÀ  rÅ  rÈ  rË  rß  ÚPARTIAL_STREAM_STUB_IDÚFINISH_REASON_LENGTHÚOPENROUTER_BASE_URLÚOPENROUTER_MODELS_URLræ  rç  ÚAI_GATEWAY_BASE_URLrî  rÿ  rû  rú  r  r  r  r"  r&  r   )r+  s   @r   Ú<module>r_     s5  øðöó
 Û 	Û 	Û Û Û 
ß =Ñ =ß )Ý à!&Ð Ó &Ù	‹€Ù2<Ð=TÐ^dÔ2eÐ Ó eð %MÐ Ó LØ(Ð Ó (õ,õ'õ
Jõ>õ
.õ@õ
%õwõ ð —’ÐIÓJ€õVõ>õ&õ>%ð #%€Ó $÷õ4õ
	Tð +/Ð Ó .õFõ&3õPñ +4Ò4RÓ*SÐ Ó Sñ " +¨|Ó<Ð ð ;?Ð Ó >ð¸÷ ð  #Ð à:Ð õõ,õ õ4Kõ?ð hÐ à—
’
Ð8Ó9€õrõõ,eõ5õGõ
õ	õj÷O÷
K÷
Eð
RÈ4÷ R÷eð 
Ò(¨%Ò1NÐPVÐYcÐekÐXlðÐ õ
Wõ
õ9ñ �X“×&Ñ&Ó(×/Ñ/€õ=õ
/÷lõ&÷R(õAõ ÷2õ?õ õ*%÷Aõl÷@÷
(÷"ð. ! )¨^¸YÈÐXaØ˜f f¨f°kÀ6È;ÐX^ð`Ð ÷õ4	ð* 1Ð Ø-Ð ØÐ Ø$Ð Ø"&Ð ØÐ ð Ð õ
ð" ,Ð à Ð ñ $ V¨ZÐ$8Ó9Ð ñ "Ò"=Ó>Ð ÷õ.
õ:õ(ð !¸t÷ !ñHÀT÷ ð ð4 .2ÐKa÷ 
aõ#÷"õõ6ð XÐ õõ6"õJ õF
÷õ4õõõõfõFõõ-õ
(õ
&÷
+ð4 /Ð ØÐ Ø4Ð Ø.Ð/¨wÐ7Ð ñ /8Ú*ó/Ð ó õ
ð0 8Ð ð.°T÷ .õõBð62¸÷ 2ñ %ò &ó Ð õ[õð ¸÷ ÷Ar   