+
    lHà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t^ RI	t	^ RI
t
^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIHt ^ RIHt ^ RIHt ^ RIHt ^ RIHt ^ RIHtHtHtHtH t H!t!H"t"H#t#H$t$H%t%H&t&H't'H(t( ^ R	I)H*t*H+t+ ]PX                  ! 4       R
8H  t-]P\                  ! ]/4      t0^t1]Pd                  ! 4       t3Rs4]Pj                  ! R4      t6R R lt7]13R R llt8R R lt9R 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tAR# R$ ltBR%]C! 4       /R& R' lltDR( R) ltER* R+ ltFR|R, R- lltGR. R/ ltHR0RR1R/R2 R3 lltIR4 R5 ltJR|R6R7R8R7R9RR:R/R; R< llltKR|R=RR0R/R> R? llltLR|R@ RA lltMRB RC ltNR|RD RE lltORF RG ltPRH RI ltQRsR] ^ k RJ RK ltSRL RM ltTRN RO ltURP RQ ltV]C! 0 R}m4      tWRR RS ltXRTtY]Z! 4       t[][s\] ^k Rs]RU RV lt^RW RX lt_RY RZ lt`R[ R\ ltaR] R^ ltbR_ R` ltcRa Rb ltdRc Rd lte]! ]f4      PÏ                  4       PÐ                  ^,          ti] ^k ]*! ]i]! ]f4      PÕ                  4       PÐ                  ^,          ]! 4       4      tk] ^k ]l! ]Re]PÚ                  4      ]PÚ                  8g  ;'       g
    ]n! ]Rf4      to] ^k Rtp] ^k Rg Rh ltqRi Rj ltrRk Rl ltsRm Rn lttRo Rp ltuRq Rr ltvRs Rt ltwRu Rv ltxRw Rx lty ! Ry Rz]4      tzR# )~uE   Local execution environment â€” spawn-per-call with session snapshot.N)ÚMapping©ÚPath)Úget_process_hermes_home)ÚBaseEnvironment)Ú_pipe_stdin)Úwindows_hide_flags)Ú_ALWAYS_STRIP_FOLDEDÚ_ALWAYS_STRIP_KEYSÚ_HERMES_PROVIDER_ENV_BLOCKLISTÚ!_HERMES_PROVIDER_ENV_FORCE_PREFIXÚ_is_hermes_internal_secretÚ_is_provider_env_blocklistedÚ_is_terminal_first_party_envÚ_home_adapter_secret_envÚ$_matches_terminal_first_party_prefixÚ_plugin_terminal_env_strip_keysÚ_registered_adapter_secret_envÚ_registry_adapter_secret_envÚstrip_profile_gate_env)Ú_build_hermes_repo_root_aliasesÚ2_strip_hermes_owned_pythonpath_and_runtime_markersÚWindowsFz,^(hermes_bg_[A-Za-z0-9_-]+)\.(log|pid|exit)$c                ó2   € V ^8„  d   QhR\         R,          /# ©é   ÚreturnNr   )Úformats   "Ú=/home/ubuntu/.hermes/hermes-agent/tools/environments/local.pyÚ__annotate__r   3   s   € ÷ ñ ¤D¨4¥Kñ ó    c                 ó^   €  ^ RI Hp  V ! 4       R,          R,          #   \         d     R# i ; i)z;Return HERMES_HOME/cache/terminal, or None if unresolvable.©Úget_hermes_homeÚcacheÚterminalN)Úhermes_constantsr#   Ú	Exceptionr"   s    r   Ú_default_terminal_temp_dirr(   3   s/   € ðÝ4ÙÓ  7Õ*¨ZÕ7Ð7øÜô Úðús   ‚ �,«,c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úmax_age_hoursr   )ÚfloatÚint)r   s   "r   r   r   <   s   € ÷ ;ñ ;¬uð ;ÔX[ñ ;r    c                óV  a
a€ ^ RI Hp \        4       oSf   ^ # \        P                  ! 4       V R,          ,
          o
 \	        SP                  4       4      p/ p/ pT F‡  p TP                  4       P                  ;Y5&   p\        P                  TP                  4      ;p'       g   KK  \        TP                  TP                  ^4      R4      T4      YGP                  ^4      &   K‰  	  R T
T3R llp^ p	T FÎ  p\        P                  TP                  4      pT'       d=   YGP                  ^4      ,          S
8¼  g   T! TP                  ^4      4      '       d   Ke  MT! TS
4      '       d   Kw   TP                  4       '       d   \         P"                  ! TRR7       MTP%                  4         \&        P(                  ! T4       KÐ  	  T	#   \         d     ^ # i ; i  \         d     EKŽ  i ; i  \         d     EK  i ; i  \*         d    T	^,          p	 EK$  \         d     EK2  i ; i)u3  Delete session temp artifacts idle for *max_age_hours* (no write anywhere in a
directory's subtree; the kwarg name is the ``cleanup_*_cache`` signature the gateway
housekeeping loop calls every entry with); return count.
Only the managed default dir is pruned â€” never a user-pointed ``terminal.temp_dir``.)Úsubtree_touched_sincei  g        c                ó0   € V ^8„  d   QhR\         R\        /# )r   Ústemr   ©ÚstrÚbool)r   s   "r   r   Ú1cleanup_terminal_temp_cache.<locals>.__annotate__V   s   € ÷ ñ œCð ¤Dñ r    c                 ó¸   <€ R F2  p SV  RV 2,          P                  4       P                  S8¼  d    R# K4  	  R#   \         d     KF  \         d      R# i ; i)ÚlogÚ.TF)r6   ÚpidÚexit)ÚstatÚst_mtimeÚFileNotFoundErrorÚOSError)r0   ÚsfxÚcutoffÚroots   & €€r   Úgroup_touchedÚ2cleanup_terminal_temp_cache.<locals>.group_touchedV   sg   ø€ ó *ˆCðØ˜d˜V 1 S E˜?Õ*×0Ñ0Ó2×;Ñ;¸vÔEÚñ Fñ *ñ øô	 %ô ÚÜô Ûðús   ˆ+<¼AÁ
AÁAÁAT)Úignore_errors)Úhermes_constants_scratchr.   r(   ÚtimeÚlistÚiterdirr=   r:   r;   Ú_BG_GROUP_REÚmatchÚnameÚmaxÚgetÚgroupÚis_dirÚshutilÚrmtreeÚunlinkÚosÚlstatr<   )r*   r.   ÚentriesÚmtimesÚgroup_newestÚfÚmtÚmrA   Úremovedr?   r@   s   &         @@r   Úcleanup_terminal_temp_cacher[   <   sË  ù€ õ
 ?ä%Ó'€DØ‚|ÙÜ�YŠY‹[˜M¨DÕ0Õ1€FðÜ�t—|‘|“~Ó&ˆð !#€FØ%'€LÛˆð	ØŸV™V›X×.Ñ.Ð.ˆF‰I˜ô ×"Ñ" 1§6¡6Ó*Ð*ˆ1×*Ð*Ü'*¨<×+;Ñ+;¸A¿G¹GÀA»JÈÓ+LÈbÓ'QˆLŸ™ ›Ó$ñ ÷ñ ð €GÛˆÜ×Ñ˜qŸv™vÓ&ˆßØŸG™G A›JÕ'¨6Ô1±]À1Ç7Á7È1Ã:×5NÒ5NÙð 6Oá" 1 f×-Ò-Ùð	Ø45·H±H·J²JŒF�MŠM˜!¨4Ö0ÀAÇHÁHÄJð
	Ü�HŠH�QŽKñ ð& €Nøô] ô Úðûô ô 	Ûð	ûô8 ô 	Ûð	ûô !ô 	Ø�q�LŒGÜô 	Ûð	ús_   ½G	 Á GÅ-G.ÆG.ÆG.Æ-HÇ	GÇGÇG+Ç*G+Ç.G>Ç=G>ÈH(ÈH(È"H(È'H(c                ó   € V ^8„  d   QhRR/# r   © )r   s   "r   r   r   z   s   € ÷ 
<ñ 
< 4ñ 
<r    c                 ó   € \         ;_uu_ 4        \        '       d    RRR4       R# RsRRR4        \        4        R#   + '       g   i     L; i  \         d"   p \        P                  RT 4        Rp ? R# Rp ? ii ; i)z@Best-effort prune, at most once per process (CLI-only installs).NTzTerminal temp prune failed: %s)Ú_terminal_temp_prune_lockÚ_terminal_temp_pruned_oncer[   r'   ÚloggerÚdebug)Úexcs    r   Ú_prune_terminal_temp_oncerd   z   s_   € ÷ 
#Ö	"ß%Ó%Ø÷ 
#Ñ	"ð &*Ð"÷ 
#ð<Ü#Ö%÷ 
#×	"ûô ô <Ü�‰Ð5°s×;Ò;ûð<ús$   �>§>²
A ¾A	ÁA=ÁA8Á8A=c                ó0   € V ^8„  d   QhR\         R\         /# ©r   Úcwdr   ©r2   )r   s   "r   r   r   ˆ   s   € ÷ 5ñ 5œsð 5¤sñ 5r    c                ó8  € \         ;'       d"    T ;'       d    \        P                  ! RV 4      pV'       g   V # VP                  ^4      ;'       g    RP	                  RR4      pVP                  ^4      P                  4        RT;'       g    \        ^\4       2# )zå``/c/Users/x`` / ``/cygdrive/c/..`` / ``/mnt/c/..`` -> native ``C:\Users\x`` so
``isdir``/``Popen(cwd=)`` find it. No-op off Windows, for empty input and for
multi-segment POSIX paths like ``/home/x``; idempotent on native paths.z)^/(?:(?:cygdrive|mnt)/)?([a-zA-Z])(/.*)?$Ú Ú/Ú\Ú:)Ú_IS_WINDOWSÚrerI   rM   ÚreplaceÚupperÚchr©rg   rY   Útails   &  r   Ú_msys_to_windows_pathru   ˆ   s~   € ô 	×[Ð[˜×[Ð[¤§¢Ð)UÐWZÓ [€AßØˆ
Ø�G‰G�A‹J×Ð˜"×%Ñ% c¨4Ó0€DØ�g‰g�a‹j×ÑÓ Ð!  4§? ?¬3¨r«7Ð"3Ð4Ð4r    c                ó0   € V ^8„  d   QhR\         R\         /# rf   rh   )r   s   "r   r   r   “   s   € ÷ ñ ¤Cð ¬Cñ r    c                ó¨  € V '       d    \         P                  P                  V 4      M\         P                  ! 4       p\        '       d*   \        V4      p\        P                  ! V4      '       d   V# \         P                  P                  V4      '       d   V# \         P                  P                  V4      p\         P                  ! 4       p\         P                  P                  V4      '       ga   \        V4      P                  \        V4      P                  rTV'       d0   \        V4      \        V4      8:  d   V\        V4      ) R V8X  d   V# V# )zèResolve the initial cwd to an absolute host path. A relative ``TERMINAL_CWD``
naming the launch directory would otherwise make the wrapper ``cd`` *inside*
the project; anchor it once so ``Popen(cwd=)`` and the in-shell ``cd`` agree.N)rR   ÚpathÚ
expanduserÚgetcwdrn   ru   ÚntpathÚisabsÚabspathÚisdirr   ÚpartsÚlen)rg   ÚexpandedÚ	candidateÚcurrentÚwantedÚhaves   &     r   Ú_resolve_local_initial_cwdr†   “   sÛ   € ÷ +.Œr�w‰w×!Ñ! #Ô&´2·9²9³;€Hßƒ{Ü(¨Ó2ˆô �<Š<˜×!Ò!ØˆOÜ	‡w�w‡}�}�X×ÒØˆÜ—‘—‘ Ó)€IÜ�iŠi‹k€Gä�7‰7�=‰=˜×#Ò#Ü˜H“~×+Ñ+¬T°'«]×-@Ñ-@�ß”c˜&“k¤S¨£YÔ.°4¼¸V»¸¸Ð3FÈ&Ô3PØˆNØÐr    c                ó0   € V ^8„  d   QhR\         R\         /# rf   rh   )r   s   "r   r   r   ª   s   € ÷ +ñ +œsð +¤sñ +r    c                ó2  € \         ;'       d"    T ;'       d    \        P                  ! RV 4      pV'       g   V # VP                  ^4      ;'       g    RP	                  RR4      P                  R4      pRVP                  ^4      P                  4        RV 2# )zxNative ``C:\Users\x`` -> Git Bash ``/c/Users/x`` so ``builtin cd`` resolves
it. No-op off Windows / for non-drive paths.z^([a-zA-Z]):[\\/]*(.*)$rj   rl   rk   )rn   ro   rI   rM   rp   ÚlstripÚlowerrs   s   &  r   Ú_windows_to_msys_pathr‹   ª   s   € ô 	×IÐI˜×IÐI¤§¢Ð)CÀSÓ I€AßØˆ
Ø�G‰G�A‹J×Ð˜"×%Ñ% d¨CÓ0×7Ñ7¸Ó<€DØˆq�w‰w�q‹z×ÑÓ!Ð" ! D 6Ð*Ð*r    c                ó0   € V ^8„  d   QhR\         R\         /# ©r   rx   r   rh   )r   s   "r   r   r   ´   s   € ÷ \ñ \œ#ð \¤#ñ \r    c                ód   € \         '       d$   V '       d   \        V 4      P                  RR4      # T # )zé*path* safe to embed in a Git Bash script: ``C:\Users\x`` / ``C:/Users/x``
become ``/c/Users/x`` (MSYS argument conversion mangles ``C:/`` forms) and
leftover backslashes are normalized so bash does not eat ``\U``. No-op off Windows.rl   rk   )rn   r‹   rp   ©rx   s   &r   Ú_bash_safe_pathr�   ´   s*   € ÷ >I»[ÏTÔ  Ó&×.Ñ.¨t°SÓ9Ð[ÐW[Ð[r    c                ó0   € V ^8„  d   QhR\         R\         /# r�   rh   )r   s   "r   r   r   »   s   € ÷ .ñ .œ3ð .¤3ñ .r    c                ó>   € ^ RI pVP                  \        V 4      4      # )zFQuote *path* for safe interpolation into a Git Bash script on Windows.N)ÚshlexÚquoter�   )rx   r“   s   & r   Ú_quote_bash_pathr•   »   s   € ãØ�;‰;” tÓ,Ó-Ð-r    c                ó0   € V ^8„  d   QhR\         R\        /# r�   r1   )r   s   "r   r   r   Á   s   € ÷ <ñ <”cð <œdñ <r    c                óš   € \         P                  P                  V 4      ;'       d&    \         P                  ! V \         P                  4      # )z—True when *path* is a directory this process can actually chdir into
(``isdir`` alone passes ``/root`` for a non-root user; ``Popen(cwd=)`` then dies).)rR   rx   r~   ÚaccessÚX_OKr�   s   &r   Ú_cwd_usablerš   Á   s.   € ô �7‰7�=‰=˜Ó×;Ð;¤2§9¢9¨T´2·7±7Ó#;Ð;r    c                ó0   € V ^8„  d   QhR\         R\         /# rf   rh   )r   s   "r   r   r   Ç   s   € ÷ +ñ +œ3ð +¤3ñ +r    c           	     ó>  € \        V 4      p V '       d   \        V 4      '       d   V # V '       dR   \        P                  P	                  V 4      '       d-   \
        P                  RV \        \        RR 4      ! 4       4       V '       d    \        P                  P                  V 4      MRpV'       dP   \        V4      '       g?   \        P                  P                  V4      pW!8X  d   \        P                  ! 4       # TpKW  T;'       g    \        P                  ! 4       # )u  ``cwd`` if enterable, else the nearest usable ancestor, else
``tempfile.gettempdir()``. MSYS paths are normalized first on Windows so a valid
``pwd -P`` result is not rejected. Lets ``_run_bash`` recover from a deleted or
inaccessible cwd instead of ``Popen`` raising and wedging every later call.

Used by ``_run_bash`` to recover when the configured cwd is gone â€” most commonly because a previous tool
call deleted its own working directory (issue #17558) â€” or inaccessible to this user, e.g. ``/root``
leaking from a root-launched CLI session into a non-root gateway's cron jobs (issue #65583). Without
this guard, ``subprocess.Popen(..., cwd=...)`` raises ``FileNotFoundError``/``PermissionError`` before
bash starts, wedging every subsequent terminal call until the gateway restarts.
uð   Configured terminal cwd %r exists but is not accessible to this user (uid=%s) â€” falling back to the nearest usable directory. If this is a gateway/cron process, check for root-owned paths leaking into terminal.cwd / TERMINAL_CWD (#65583).Úgetuidc                  ó   € R # )Ú?r]   r]   r    r   Ú<lambda>Ú#_resolve_safe_cwd.<locals>.<lambda>Ý   s   € ©sr    rj   )ru   rš   rR   rx   r~   ra   ÚwarningÚgetattrÚdirnameÚtempfileÚ
gettempdir)rg   ÚparentÚnext_parents   &  r   Ú_resolve_safe_cwdr©   Ç   sÁ   € ô   Ó
$€Cß
Œ{˜3×ÒØˆ
ß
Œr�w‰w�}‰}˜S×!Ò!Ü�‰ðð
 ”œ˜X¡{Ô3Ó5ô	7÷ &)ŒR�W‰W�_‰_˜SÔ!¨b€Fß
œ V×,Ò,Ü—g‘g—o‘o fÓ-ˆØÔ Ü×&Ò&Ó(Ð(ØŠØ×*Ð*”X×(Ò(Ó*Ð*r    c                ó(   € V ^8„  d   QhR\         RR/# ©r   Úenvr   N©Údict)r   s   "r   r   r   è   s   € ÷ #ñ #œTð # dñ #r    c                óp   € ^ RI HpHp  V! 4       ;p'       d   W0R&   T! T 4       R#   \         d     Li ; i)zQBridge the context-local HERMES_HOME override, then the subprocess HOME contract.)Úapply_subprocess_home_envÚget_hermes_home_overrideÚHERMES_HOMEN)r&   r°   r±   r'   )r¬   r°   r±   Úvalues   &   r   Ú_apply_profile_homer´   è   s>   € çTðÙ,Ó.Ð.ˆ5Ö.Ø!&�Ññ ˜cÖ"øô ô Ùðús   Š' ™' §5´5c                ó(   € V ^8„  d   QhR\         RR/# r«   r­   )r   s   "r   r   r   ó   s   € ÷ $ñ $¤Tð $¨dñ $r    c                ó  €  ^ RI HpHpHp T! 4       pTP                  4        FK  w  rVTP                  4       pYqJd   Tf   RM
\        T4      Y&   K/  T'       g   K9  T P                  TR4       KM  	  R#   \         d     R# i ; i)u‰  Bridge gateway session ContextVars (HERMES_SESSION_*) into a child env.
Cross-session leak guard: the vars' last-writer-wins ``os.environ`` mirror may
belong to another turn on a concurrent multi-session host, so once the session
context is engaged ContextVars are authoritative â€” a bound value (incl. "") wins
and an _UNSET var is STRIPPED, not inherited. An unengaged CLI keeps the mirror.)Ú_UNSETÚ_VAR_MAPÚsession_context_engagedNrj   )	Úgateway.session_contextr·   r¸   r¹   r'   ÚitemsrL   r2   Úpop)r¬   r·   r¸   r¹   Ú_engagedÚvar_nameÚvarr³   s   &       r   Ú_inject_session_context_envrÀ   ó   ss   € ðßUÑUñ 'Ó(€HØ!Ÿ™Ö)‰ˆØ—‘“	ˆØÓØ"'¢-™B´S¸³ZˆC‹Mß‰XØ�G‰G�H˜dÖ#ó *øô ô Úðús   ‚
A4 Á4BÂBÚplugin_stripc          
      ón   € V ^8„  d   QhR\         \        \        3,          R\        R\        R\        RR/# )r   r»   ÚoutÚunwrap_forcerÁ   r   N)r   r2   r®   r3   Ú	frozenset)r   s   "r   r   r     s=   € ÷ ñ Ü”3œ�8ÕðÜ#'ðÜ:>ðäðà.2ñr    c               óL  €  ^ RI HpHp \	        R V 4       4      p\        4       pV P                  4        FÓ  w  r‰VP                  \        4      '       d4   V'       g   K*  V\        \        4      R p\        V4      '       g   W‘V&   KS  \        V4      '       g   VP                  4       V9   d   K{  \        V4      p
V! V4      p\        W‡4      '       d   V'       g   V
'       g   K±  V'       d   V
'       g	   V! W‰4      p	V	f   KÏ  W‘V&   KÕ  	  R#   \         d
    R R rT ELi ; i)a{  Copy *items* into *out*, dropping Hermes-managed secrets. ``_HERMES_FORCE_<NAME>``
unwraps to ``NAME`` when ``unwrap_force`` (caller extras / terminal env), else is
dropped. Blocklisted names survive only via env_passthrough registration or as
context-entitled first-party ``BUZZ_*`` vars; the latter are used directly, never
scope-resolved (UnscopedSecretError under multiplex).)Úis_env_passthroughÚresolve_passthrough_valuec                 ó   € R # )Fr]   )Ú_s   &r   r    Ú$_filter_secret_env.<locals>.<lambda>  s   € Á5r    c                 ó   € V# ©Nr]   )Ú_nÚfbs   &&r   r    rË     s   € Ñ[]r    c              3   ó@   "  € T F  qP                  4       x € K  	  R # 5irÍ   ©rq   ©Ú.0Úks   & r   Ú	<genexpr>Ú%_filter_secret_env.<locals>.<genexpr>  s   é € Ð#D±|°!§G¡G§I I³|ùs   ‚N)Útools.env_passthroughrÇ   rÈ   r'   rÅ   r   r»   Ú
startswithr   r€   r   rq   r   r   )r»   rÃ   rÄ   rÁ   rÇ   rÈ   Úplugin_strip_foldedÚ
registeredÚkeyr³   Úfirst_partyÚpassthroughs   &&$$        r   Ú_filter_secret_envrÞ     sñ   € ð_ßWô $Ñ#D±|Ó#DÓDÐÜ/Ó1€JØ—k‘k–m‰
ˆØ�>‰>Ô;×<Ò<ßÙØ”cÔ;Ó<Ð=Ð>ˆCÜ-¨c×2Ò2Ø �C‘ÙÜ% c×*Ò*¨c¯i©i«kÐ=PÔ.PÙÜ2°3Ó7ˆÙ(¨Ó-ˆÜ'¨×8Ò8Ç+×Q\ÙßŸ{Ù-¨cÓ9ˆEØÔØ�‹Hó# $øô	 ô _Ù9HÑL]Ó5ð_ús   ‚D ÄD#Ä"D#c                ó0   € V ^8„  d   QhR\         R\         /# ©r   r¬   r   r­   )r   s   "r   r   r   (  s   € ÷ 	/ñ 	/œTð 	/¤dñ 	/r    c                óv   € \        V 4       \        V 4       \        V 4       \        V 4       ^ RIHp V! V 4      # )zÒGuards shared by every spawn surface: profile-home propagation, session-context
bridging, Hermes-owned PYTHONPATH + venv-marker strip, MSYS defaults, delegate_task
Kanban scrub. Returns the (possibly new) dict.©Údelegated_child_subprocess_env)r´   rÀ   r   Ú%_apply_windows_msys_bash_env_defaultsÚagent.delegation_contextrã   )r¬   rã   s   & r   Ú_finalize_child_envræ   (  s2   € ô ˜ÔÜ Ô$Ü6°sÔ;Ü)¨#Ô.ÝGÙ)¨#Ó.Ð.r    c                ó0   € V ^8„  d   QhR\         R\        /# )r   rÁ   r   )rÅ   r®   )r   s   "r   r   r   4  s   € ÷ $ñ $¤yð $¼tñ $r    c                ó  a€ / pV  F  w  rE\        WCVSR7       K  	  ^ RIHp VP                  V3R lV! V4      P	                  4        4       4       \        V4      pVe$   \        V! VP                  VR4      4      4      W7&   \        V4      # )zðFilter each ``(items, unwrap_force)`` in *parts* into one env, rewrite PATH via
*fix_path* (always prepending the hermes install dir so bare ``hermes`` resolves
for children of a systemd/cron-launched gateway), then apply the shared guards.)rÄ   rÁ   )Úscoped_passthrough_additionsc              3   ó@   <"  € T F  w  rVS9  g   K  W3x € K  	  R # 5irÍ   r]   )rÓ   rÔ   ÚvrÁ   s   &  €r   rÕ   Ú _scrubbed_env.<locals>.<genexpr>@  s!   øé € ÐeÑ"K™$˜!ÈqÐXdÑOdŒv��vÓ"Kùs   ƒ“rj   )	rÞ   r×   ré   Úupdater»   Ú_path_env_keyÚ_prepend_hermes_bin_dirrL   ræ   )r   rÁ   Úfix_pathrÃ   r»   rÄ   ré   Úpath_keys   &f&     r   Ú_scrubbed_envrò   4  sƒ   ø€ ð €CÛ$ÑˆÜ˜5°LÈ|×\ñ  %õ CØ‡J�JÔeÑ">¸sÓ"C×"IÑ"IÔ"KÓeÔeÜ˜SÓ!€Hð ÒÜ/±¸¿¹ÀÈ2Ó9NÓ0OÓPˆ‰Ü˜sÓ#Ð#r    c                óX   € V ^8„  d   QhR\         R,          R\         R,          R\         /# )r   Úbase_envNÚ	extra_envr   r­   )r   s   "r   r   r   J  s/   € ÷ Iñ I¤t¨d¥{ð I¼tÀd½{ð IÔVZñ Ir    c                ób   € \        T ;'       g    / R3T;'       g    / R3.\        4       R 4      # )z’Filter Hermes-managed secrets from a subprocess environment (background/PTY
spawn path, search workers, computer-use driver, user-script runners).FTc                 ó   € V # rÍ   r]   ©Úps   &r   r    Ú*_sanitize_subprocess_env.<locals>.<lambda>N  s   € Áar    )rò   r   )rô   rõ   s   &&r   Ú_sanitize_subprocess_envrû   J  s8   € ô ˜8Ÿ>˜> r¨5Ð1°I·O°OÀÀTÐ3JÐKÜ8Ó:¹KóIð Ir    c                ó0   € V ^8„  d   QhR\         R\         /# rà   r­   )r   s   "r   r   r   Q  s   € ÷ ñ ”tð ¤ñ r    c                óJ   € \        V 4      pVe   \        W,          4      W&   V # )z[*env* with the user's tools first on PATH (``_user_tools_first``), for background commands.)rî   Ú_user_tools_first)r¬   rñ   s   & r   Ú_terminal_envrÿ   Q  s%   € ä˜SÓ!€HØÒÜ)¨#­-Ó8ˆ‰Ø€Jr    Úinherit_credentialsrô   c                óŽ   € V ^8„  d   QhR\         R\        \        \        3,          R,          R\        \        \        3,          /# )r   r   rô   Nr   )r3   r®   r2   )r   s   "r   r   r   Y  s9   € ÷ $ñ $Ü ð$Ü48¼¼c¸µNÀTÕ4Ið$ä	Œ#Œsˆ(…^ñ$r    c                ó®   € Ve   \        V4      M\        P                  P                  4       p\	        W R7      pVP                  RR4       \        V4      # )a±  Sanitize a non-terminal child's environment (no skill passthrough).

Bot, GitHub and remote-compute secrets never pass through; provider/tool
credentials pass only with ``inherit_credentials=True`` for children that
need them. Callers needing one other secret should add only that key back.
``base_env`` lets an already curated environment use the same policy.
Terminal and execute_code spawns use the skill-aware sanitizer instead.
©r   Ú
PYTHONUTF8Ú1)r®   rR   ÚenvironÚcopyÚ_scrub_credentialsÚ
setdefaultræ   )r   rô   r¬   s   $$ r   Úhermes_subprocess_envr
  Y  sB   € ð %Ò0Œ$ˆxŒ.´b·j±j·o±oÓ6G€CÜ
˜SÔ
J€CØ‡N�N�< Ô%Ü˜sÓ#Ð#r    c                ó<   € V ^8„  d   QhR\         R\        R\         /# )r   r¬   r   r   )r®   r3   )r   s   "r   r   r   j  s!   € ÷ ñ œDð ¼$ð Ä4ñ r    c               óŠ  € \        4       p\        \        4        Uu0 uF  q3P                  4       kK  	  up,          V,          p\	        4       p\        V 4       Fa  pVP                  4       V9   gH   V'       g   \        We4      '       g/   VP                  \        4      '       g   \        V4      '       g   K_  W Kc  	  V # u upi )z`Tier 1 (always) and, unless ``inherit_credentials``, Tier 2 provider/tool credentials, in place.)
r   r	   r   rq   r   rF   r   rØ   r   r   )r¬   r   Úhome_secretsrÔ   Ústrip_foldedrÚ   rÛ   s   &$     r   r  r  j  s”   € ô ,Ó-€LÜ'Ô>]Ô>_Ó*`Ñ>_¸¯7©7®9Ñ>_Ñ*`Õ`ÐcoÕo€LÜ-Ó/€JÜ�CŽyˆØ�I‰I‹K˜<Ô'ß+Ô0LÈS×0]Ò0]Ø—>‘>Ô"C×DÒDÜ-¨c×2Ô2Ø’ñ ð €Jùò +as   œC Úinherit_profile_homeTÚscrub_secretsÚextraÚstrip_launch_profilec                óâ   € V ^8„  d   QhR\         \        \        3,          R,          R\        R\        R\         \        \        3,          R,          R\        R\        \        \        3,          /# )r   ÚbaseNr  r  r  r  r   )r   r2   r3   r®   )r   s   "r   r   r   z  sd   € ÷ !/ñ !/Ü
”#”s�(Õ
˜dÕ
"ð!/ÜDHð!/äð!/ä'.¬s´C¨xÕ'8¸4Õ'?ð!/ô ð!/ô ,0´´S°­>ñ!/r    c               óÊ  € V e   \        V 4      M\        P                  P                  4       pV'       dL   \	        V4       ^ RIHpHp V! 4       '       d,   TP                  V! 4       ;'       g    / 4       \        V4       V'       d#   \        YS'       d   \        V4      4      # R4      # V'       d   \        V4       V'       d   VP                  V4       ^ RIHp V! V4      # )a´  Single factory for child-process envs. ``base=None`` snapshots ``os.environ``.
``scrub_secrets=True`` -> :func:`_sanitize_subprocess_env` (profile home inherent,
``inherit_profile_home`` ignored). ``scrub_secrets=False`` keeps the base
byte-for-byte (git credential flows, ``bws``/``op``); ``inherit_profile_home``
bridges HERMES_HOME + HOME and ``extra`` is applied last so caller overrides win.
``strip_launch_profile`` drops the LAUNCH profile's ``.env`` residue from the base first
(:func:`strip_launch_profile_env`; a no-op unless a routed home is active) so a child that
acts for a routed profile sees only that profile's declared names, never the launch profile's.
Under multiplex semantics it then overlays the bound secret scope (the routed profile's own
``.env`` + source values, which never enter ``os.environ``) and re-applies the managed keys,
all BEFORE the scrub, so those values pass the same scrub / passthrough rules as any other.N)Úcurrent_secret_scopeÚis_multiplex_activerâ   )r®   rR   r  r  Ústrip_launch_profile_envÚagent.secret_scoper  r  rí   Úrestore_managed_envrû   r´   rå   rã   )	r  r  r  r  r  r¬   r  r  rã   s	   &$$$$    r   Úbuild_subprocess_envr  z  s    € ð )-Ò(8œ$˜tœ*¼b¿j¹j¿o¹oÓ>O€CßÜ  Ô%ßPÙ× Ò ð �J‰JÑ+Ó-×3Ð3°Ô4ô   Ô$ßÜ'¨¾E¬T°%«[ÓLÐLÀtÓLÐLßÜ˜CÔ ßØ�
‰
�5ÔÝGÙ)¨#Ó.Ð.r    Útarget_homec          
      ó¾   € V ^8„  d   QhR\         \        \        3,          R,          R\        \        ,          R,          R\        R\        \        \        3,          /# )r   r  Nr  r   r   )r   r2   r   r3   r®   )r   s   "r   r   r   ž  sM   € ÷ )ñ )Ü
”#”s�(Õ
˜dÕ
"ð)Ü;>Ä½:ÈÕ;Lð)äð)ô 
Œ#Œsˆ(…^ñ)r    c               ó  € ^ RI HpHpHpHp ^ RIHpHp V e   \        V 4      M\        VR7      p	\        T;'       g    V! 4       ;'       g    R4      p
V
'       d6   W©R&   V! V	4       \        V
4      '       d   \        Wš4       \        V	RR7       V'       dl   V
'       d   V! \        V
4      4      pM!V! 4       pVf   V! 4       '       d
   V! RR4      hT	P                  R T;'       g    / P!                  4        4       4       V	# )	u{  Child env for a process that acts FOR the active (possibly served) profile: ``hermes -p X``
workers, ``key_cmd`` helpers, browser drivers. The process env is the LAUNCH profile's. When the
target is a ROUTED home (not the launch profile's â€” under multiplex or a Desktop/dashboard backend
serving ``?profile=`` with the flag off) the launch ``.env`` residue and bridged ``TERMINAL_*`` are
dropped (``strip_launch_profile_env``) AND every provider/tool credential is scrubbed from the base
regardless of provenance: a key systemd / Compose / the shell injected into the launch process was
never recorded in ``.env`` or a source snapshot, so a name-based strip cannot see it and the target
overlay cannot remove it. ``inherit_credentials=True`` is for children that legitimately run with
the profile's credentials (they run the agent or mint its token): the target profile's own secrets
(its ``.env`` + hydrated sources, what a standalone ``hermes -p X`` loads itself) are overlaid â€” never
a sibling profile's. Under multiplex with neither a target nor a bound scope the call raises
(``get_secret``'s fail-closed contract): minting with the launch environ would sign in as the wrong
profile. ``False`` keeps the provider scrub; the caller re-adds the few keys the child needs via
``get_secret``. ``target_home`` defaults to the active override; ``base`` replaces the
``hermes_subprocess_env`` snapshot.)ÚUnscopedSecretErrorÚbuild_profile_secret_scoper  r  )Úapply_scratch_tmp_envr±   r  rj   r²   Fa  served_profile_child_env(inherit_credentials=True) called with no target home and no profile secret scope bound while multiplexing is on; the child would inherit the launch profile's credentials. Bind the profile scope (or pass target_home) at the spawn site.c              3   ó8   "  € T F  w  rVf   K  W3x € K  	  R # 5irÍ   r]   )rÓ   rÔ   rë   s   &  r   rÕ   Ú+served_profile_child_env.<locals>.<genexpr>Æ  s   é € ÐOÑ&=™d˜aÀ”6�A•6Ó&=ùs   ‚�)r  r  r   r  r  r&   r!  r±   r®   r
  r2   Ú_is_routed_homer  r  r   rí   r»   )r  r  r   r  r   r  r  r!  r±   r¬   ÚtargetÚsecretss   &$$         r   Úserved_profile_child_envr'  ž  sà   € ÷&dó dçPØÒ(Œ$ˆtŒ*Ô.CÐXkÔ.l€CÜ�×@Ð@Ñ 8Ó :×@Ð@¸bÓA€FßØ#ˆMÑÙ˜cÔ"Ü˜6×"Ò"Ü$ SÔ1Ü˜s¸Õ>ßßÙ0´°f³Ó>‰Gá*Ó,ˆGØŠÑ#6×#8Ò#8Ù)Øð tóuð uð 	�
‰
ÑO w§} }°"×&;Ñ&;Ô&=ÓOÔOØ€Jr    c                ó‚   € V ^8„  d   QhR\         \        \        3,          R,          R\        \        \        3,          /# )r   r  Nr   )r   r2   r®   )r   s   "r   r   r   Ê  s2   € ÷ ñ Ü
”#”s�(Õ
˜dÕ
"ðä	Œ#Œsˆ(…^ñr    c                ó2   € ^ RI Hp \        W! 4       RR7      # )u&  Child env for the host gateway: the default profile's secrets, never the launcher's.

``served_profile_child_env`` â€” not ``os.environ.copy()``. A profile-scoped parent
(desktop, fleet restart, detached watcher) must not donate its dotenv to the
multiplexer that owns the primary adapter map.
)Úget_default_hermes_rootT)r  r  r   )r&   r*  r'  )r  r*  s   & r   Úhost_gateway_child_envr+  Ê  s   € õ 9Ü#ØÐ6Ó8Èdôð r    c                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r   r  r   )r2   r   r3   )r   s   "r   r   r   Ù  s   € ÷ 
ñ 
¤¤t¥ð 
´ñ 
r    c                ó’   € ^ RI Hp  \        V 4      P                  4       V! 4       P                  4       8g  #   \         d     R# i ; i)aG  True when ``target_home`` is not the process's own (launch) home.

Same launch-home identity as ``agent.secret_scope.serves_routed_profile()``: under a host that
mirrors the served profile into ``HERMES_HOME``, the live env var names the served home and the
launch residue would never be stripped from that profile's child env.)Úget_routing_process_hermes_homeT)r&   r.  r   Úresolver=   )r  r.  s   & r   r$  r$  Ù  sE   € õ AðÜ�KÓ ×(Ñ(Ó*Ñ.MÓ.O×.WÑ.WÓ.YÑYÐYøÜô Úðús   ˆ.7 ·AÁAc                ó`   € V ^8„  d   QhR\         R\        \        ,          R,          R\         /# )r   r¬   r  Nr   )r®   r2   r   )r   s   "r   r   r   æ  s+   € ÷ )'ñ )'¤$ð )'´S¼4µZÀ$Õ5Fð )'ÔRVñ )'r    c                ó  € ^ RI HpHp ^ RIHpHp T;'       g    V! 4       pV'       d   \        V4      '       g   V # T! 4       p^ RIHp ^ RI	H
p	Hp
Hp V
! 4        Uu0 uF  qÌP                  4       kK  	  pp\        V! VR,          4      4      \        V	! 4       4      ,          \        VP                  4       4      ,          \        V! 4       4      ,           Uu0 uFV  pV! VP                  4       4      '       d(   VP                  4       P!                  R4      '       g   KF  VP                  4       kKX  	  upV,
          pV  Uu. uF  qÿP                  4       V9   g   K  VNK  	  up F  pW K  	  \#        V 4      # u upi u upi u upi )a  Drop the LAUNCH profile's residue from a child env built for another served profile.
``os.environ`` holds the default profile's ``.env`` and its bridged ``TERMINAL_*`` settings;
the secret scrub removes credentials but not settings (``HERMES_MODEL``, ``TERMINAL_ENV``,
``HERMES_LANGUAGE``...), so a standalone ``hermes -p X`` worker and a served one saw different
envs. The child re-loads X's own ``.env`` and bridges X's config itself. ``target_home``
defaults to the active home override; no-op when there is no target or the target IS the
launch profile. The authority test is "does this task serve a routed home", not "is the
gateway-wide multiplex flag on": the Desktop/dashboard backend serves ``?profile=B`` by
installing a HERMES_HOME override without that flag.)Ú_is_global_envÚload_env_file)r±   r.  )ÚTERMINAL_CONFIG_ENV_MAP)Úlaunch_dotenv_keysÚmanaged_dotenv_keysÚsource_supplied_namesz.envÚ	TERMINAL_)r  r2  r3  r&   r±   r.  r$  Úhermes_cli.configr4  Úhermes_cli.env_loaderr5  r6  r7  rq   ÚsetÚvaluesrØ   r   )r¬   r  r2  r3  r±   r.  r%  Úlaunch_homer4  r5  r6  r7  rÛ   Úmanaged_namesÚresidue_namesrÔ   s   &&              r   r  r  æ  sU  € ÷ AßZØ×6Ð6Ñ4Ó6€Fßœ¨×0Ò0Øˆ
Ù1Ó3€KÝ9÷ eÑdÙ,?Ô,AÓBÑ,A S—Y‘Y–[Ñ,A€MÐBô 	‰M˜+¨Õ.Ó/Ó0´3Ñ7IÓ7KÓ3LÕLÜ
Ð%×,Ñ,Ó.Ó
/õ	0Ü25Ñ6KÓ6MÓ2Nö	OóSñ	Oð ñ ˜cŸi™i›k×*Ò*¨c¯i©i«k×.DÑ.DÀ[×.Qô 	ˆ�	‰	Žñ	OñSð Vcõ	c€Mñ
 Ó=™3�a§'¡'£)¨}Ñ"<—�™3Ô=ˆØŠHñ >ô
 " #Ó&Ð&ùò CùòSùò
 >s$   ÁE;Ã F Ã:"F Ä!F ÅFÅFc                ó0   € V ^8„  d   QhR\         R\         /# rà   r­   )r   s   "r   r   r     s   € ÷ 	ñ 	œTð 	¤dñ 	r    c                óŽ   € ^ RI Hp V! 4        F3  pV\        P                  9   g   K  \        P                  V,          W&   K5  	  V # )uu  Re-apply the administrator-managed ``.env`` values over *env* â€” call AFTER a routed profile's scope
has been overlaid. ``_apply_managed_env`` gives those keys precedence over the user's own ``.env`` in
the launch process; a routed child must see the same precedence, or the routed user's value for a
managed key (``ORG_POLICY_FLAG=user-value``) silently wins over policy.)r6  )r:  r6  rR   r  )r¬   r6  rÛ   s   &  r   r  r    s6   € õ
 :Ù"Ö$ˆØ”"—*‘*ÖÜ—z‘z #•ˆC‹Hñ %ð €Jr    c                ó$   € V ^8„  d   QhR\         /# ©r   r   rh   )r   s   "r   r   r     s   € ÷ ñ ”Cñ r    c                 óh   € ^ RI p V P                  P                  4       pV'       d   V# \        R4      h)z²Resolve the shell Hermes runs commands with. Owned by pm (the store
is the authority on bundled bash); this is a thin wrapper over
pm.shell() for callers that need a bash binary.NzpNo shell found. Hermes needs bash (Git for Windows on Windows). Run `hermes pm install` or reinstall the bundle.)Úpm.shellÚshellÚbashÚRuntimeError)ÚpmrG  s     r   Ú
_find_bashrJ    s0   € ó à�8‰8�=‰=‹?€DßØˆÜ
ð	;óð r    c                ó:   € V ^8„  d   QhR\         \        ,          /# rC  ©rF   r2   )r   s   "r   r   r   1  s   € ÷ $ñ $œD¤�Iñ $r    c                 óN   € \         f   \        '       d   \        4       M. s \         # )a(  Git Bash's coreutils dirs in ``/etc/profile`` order (mingw first so coreutils
beat System32 lookalikes); ``[]`` off Windows. A non-login ``bash -c`` (fallback
when ``bash -l`` is broken) never sources ``/etc/profile``, so without these
``cat``/``mktemp``/``mv`` are missing and commands exit 127.)Ú_git_bash_bin_dirs_cachern   Ú_compute_git_bash_bin_dirsr]   r    r   Ú_git_bash_bin_dirsrP  1  s!   € ô  Ò'ßCNÃ;Ô#=Ô#?ÐTVÐ Ü#Ð#r    c                ó:   € V ^8„  d   QhR\         \        ,          /# rC  rL  )r   s   "r   r   r   <  s   € ÷ 	Dñ 	D¤D¬¥Iñ 	Dr    c                  óÄ  a€  \        4       p \        P                  P	                  \        P                  P	                  T 4      4      p\        P                  P                  T4      P                  4       R 8X  d    \        P                  P	                  T4      MToRpT3R lT 4       p\        \        P                  R T 4       4      4      #   \         d    . u # i ; i)Úusrc              3   ó†   <"  € T F6  p\         P                  P                  ! S.VP                  R 4      O5!  x € K8  	  R# 5i)rk   N)rR   rx   ÚjoinÚsplit)rÓ   Úsubr@   s   & €r   rÕ   Ú-_compute_git_bash_bin_dirs.<locals>.<genexpr>D  s.   øé € Ð@¹4°CŒB�G‰G�LŠL˜Ð/ §	¡	¨#£×/Ð/»4ùs   ƒ>Ac              3   ót   "  € T F.  p\         P                  P                  V4      '       g   K*  Vx € K0  	  R # 5irÍ   )rR   rx   r~   )rÓ   Úds   & r   rÕ   rX  E  s!   é € ÐB© A´·±·±¸q×1AŸaša«ùs   ‚'8®
8)zmingw64/binzmingw32/binzusr/local/binzusr/binÚbin)
rJ  r'   rR   rx   r¤   ÚbasenamerŠ   rF   r®   Úfromkeys)rG  r§   ÚsubsÚdirsr@   s       @r   rO  rO  <  s£   ø€ ðÜ‹|ˆô �W‰W�_‰_œRŸW™WŸ_™_¨TÓ2Ó3€FÜ&(§g¡g×&6Ñ&6°vÓ&>×&DÑ&DÓ&FÈ%Ô&OŒ2�7‰7�?‰?˜6Ô"ÐU[€DØL€DÜ@¹4Ó@€DÜ”—‘ÑB©ÓBÓBÓCÐCøô ô ØŠ	ðús   ƒ
C ÃCÃCc                óR   € V ^8„  d   QhR\         R\        \         ,          R\         /# )r   Úexisting_pathr_  r   ©r2   rF   )r   s   "r   r   r   H  s*   € ÷ Oñ O´ð O¼DÄ½Ið OÌ#ñ Or    c                ó  € V P                  \        P                  4       Uu. uF  q"'       g   K  VNK  	  ppV Uu. uF  qDV9  g   K  VNK  	  ppV'       d$   \        P                  P                  . VOVO4      # T # u upi u upi )z�Prepend *dirs* missing from *existing_path* (``os.pathsep``); an already-listed
dir keeps its position; unchanged input when nothing is missing.)rV  rR   ÚpathseprU  )ra  r_  ÚerT   rZ  Úmissings   &&    r   Ú_prepend_missing_path_entriesrg  H  sv   € ð (×-Ñ-¬b¯j©jÔ9Ó?Ñ9�Q»Q�qˆqÑ9€GÐ?ÙÓ3™$�Q¨7Ñ"2�qˆq™$€GÐ3ß4;Œ2�:‰:�?‰?Ð/˜WÐ/ wÐ/Ó0ÐNÀÐNùò @ùÚ3s   ¢	A>°A>¼BÁ	Bc                ó0   € V ^8„  d   QhR\         R\         /# ©r   ra  r   rh   )r   s   "r   r   r   P  s   € ÷ Gñ G¤Sð G¬Sñ Gr    c                ó¶  € ^ RI Hp V! V 4      p\        4       pV Uu0 uF"  p\        P                  P                  V4      kK$  	  ppVP                  \        P                  4       Uu. uF4  qf'       g   K  \        P                  P                  V4      V9  g   K2  VNK6  	  ppV'       d$   \        P                  P                  . VOVO4      # T# u upi u upi )a&  *existing_path* with the user's tools before Hermes's (``pm.user_facing``) and, on
Windows, Git Bash's dirs first. They go first even when already listed: they are store
dirs that now sit behind the user's entries, and a non-login ``bash -c`` needs its
coreutils ahead of System32's lookalikes.)Úuser_facing_path)	Úpm.user_facingrk  rP  rR   rx   ÚnormcaserV  rd  rU  )ra  rk  rx   Ú	bash_dirsrZ  Úkeysrù   Úrests   &       r   rþ   rþ   P  s©   € õ
 0á˜MÓ*€DÜ"Ó$€IÙ)2Ó3© AŒB�G‰G×Ñ˜QÖ©€DÐ3Ø—z‘z¤"§*¡*Ô-ÓWÑ-�!³ŒA´r·w±w×7GÑ7GÈÓ7JÐRVÑ7V�AˆAÑ-€DÐWß3<Œ2�:‰:�?‰?Ð.˜YÐ.¨Ð.Ó/ÐFÀ$ÐFùò 4ùÚWs   �(CÁ(	CÁ6!CÂCc                ó$   € V ^8„  d   QhR\         /# rC  rh   )r   s   "r   r   r   e  s   € ÷ 	ñ 	”Sñ 	r    c                 ó`  € \         '       d   RM\        P                  P                  R4      p V '       dq   \        P                  P                  V 4      '       dL   \        P                  ! V \        P                  4      '       d!   \        V 4      P                  \        9   d   V # \        4       # )u0  User's login shell for background spawning: ``$SHELL`` on POSIX when it is an
executable sh-family shell, else ``_find_bash``. macOS's system bash 3.2 under
``-l`` with stdin ``/dev/null`` sources ``~/.bash_profile``, which often
``exec /bin/zsh -l`` and drops ``-c`` â€” the command silently never runs.rj   ÚSHELL)rn   rR   r  rL   rx   Úisfiler˜   r™   r   rJ   Ú_SPAWN_COMPATIBLE_SHELLSrJ  )Ú
user_shells    r   Ú_find_shellrw  e  sg   € ÷
 #“{‘¬¯
©
¯©°wÓ(?€Jß”r—w‘w—~‘~ j×1Ò1´b·i²iÀ
ÌBÏGÉG×6TÒ6TÜ�ZÓ ×%Ñ%Ô)AÔAØÐÜ‹<Ðr    za/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binc                ó2   € V ^8„  d   QhR\         R,          /# r   rh   )r   s   "r   r   r     s   € ÷ ñ ¤ t¥ñ r    c                 óö  € \         \        Jd   \         # ^ RIHp  V ! \	        \
        4      P                  4       P                  ^,          4      pVe+   VP                  4       '       d   \        V4      Rus s
\         # \        P                  ! R4      p\        P                  '       d   \        P                  ^ ,          MRp\        P                   P#                  V4      P%                  4       p\        P&                  '       d.   \        P                   P)                  \        P&                  4      MRp\*        '       d   RMRpV'       d!   \        P                   P)                  V4      pMÖ\        P                   P-                  V4      '       dd   VR8X  g   VP/                  R4      '       dF   \        P                   P1                  V4      '       d!   \        P                   P)                  V4      pMNV'       dE   \        P                   P1                  \        P                   P3                  WV4      4      '       d   TMRpV'       d(   \        P                   P5                  V4      '       d   TMRs Rs
\         # )	aU  Directory holding the ``hermes`` console-script, or None (cached). A gateway
launched by systemd/cron/a desktop launcher lacks the install dir on PATH and bare
``hermes`` exits 127. Order: a sealed payload's own launcher dir; ``which``; absolute
``sys.argv[0]`` naming a real hermes executable; ``sys.executable``'s dir if it holds
the shim.)Úpayload_command_dirNTÚhermesrj   z
hermes.exezhermes.F)Ú_HERMES_BIN_DIRÚ	_SENTINELÚpm.environmentsrz  r   Ú__file__r/  ÚparentsrN   r2   Ú_HERMES_BIN_DIR_IS_PAYLOADrO   ÚwhichÚsysÚargvrR   rx   r\  rŠ   Ú
executabler¤   rn   r|   rØ   rt  rU  r~   )rz  Úpayload_dirr‚  Úargv0r  Úexe_dirÚshimr‚   s           r   Ú_resolve_hermes_bin_dirrŠ    s„  € ô œiÓ'ÜÐÝ3ñ &¤d¬8£n×&<Ñ&<Ó&>×&FÑ&FÀqÕ&IÓJ€KØÒ ;×#5Ñ#5×#7Ò#7Ü69¸+Ó6FÈÐ3ˆÐ3ÜÐÜ�LŠL˜Ó"€EÜŸ8Ÿ8˜8ŒC�H‰H�QŽK¨€EÜ�7‰7×Ñ˜EÓ"×(Ñ(Ó*€DÜ14··°Œb�g‰g�o‰oœcŸn™nÔ-ÀR€Gß&›;‰<¨H€DßÜ—G‘G—O‘O EÓ*‰	Ü
�'‰'�-‰-˜×
Ò
 D¨HÔ$4¸¿¹È	×8RÒ8RÜ—‘—‘˜u×%Ò%Ü—G‘G—O‘O EÓ*‰	ç&¬2¯7©7¯>©>¼"¿'¹'¿,¹,ÀwÓ:U×+VÒ+V‘GÐ\`ˆ	ß#,´·±·±¸y×1IÒ1I‘iÈt€OØ!&ÐÜÐr    c                ó0   € V ^8„  d   QhR\         R\         /# ri  rh   )r   s   "r   r   r   ¡  s   € ÷ Vñ V¬3ð V´3ñ Vr    c                ó>  € \        4       pV'       dn   \        '       db   V P                  \        P                  4       Uu. uF  q"'       g   K  W!8w  g   K  VNK  	  pp\        P                  P                  V.VO4      # \        Y'       d   V.4      # . 4      # u upi )zÌPrepend the hermes install dir to ``existing_path`` if missing. A sealed payload's
launcher dir moves to the front even when already listed: a login PATH can list
another install's ``hermes`` ahead of it.)rŠ  r�  rV  rR   rd  rU  rg  )ra  Úbin_dirÚentryrp  s   &   r   rï   rï   ¡  s�   € ô &Ó'€Gß×-Ó-Ø#0×#6Ñ#6´r·z±zÔ#BÓaÑ#B˜%Ãe”ÐPUÑP`—�Ñ#BˆÐaÜ�z‰z�‰ Ð/¨$Ð/Ó0Ð0Ü(¨ÆW¸¸	ÓUÐUÐRTÓUÐUùò bs   Á 	BÁBÁBc                ó:   € V ^8„  d   QhR\         \        ,          /# rC  rL  )r   s   "r   r   r   ¬  s   € ÷ ñ ¤t¬C¥yñ r    c                 ó¤  €  ^ RI p ^ RIHp V P                  RRR/R7      pVP	                  RR4      P                  \        P                  4       Uu. uF  q3'       g   K  \        V4      NK  	  pp. VOV! 4       R,          NpV Uu. uF%  q3P                  4       '       g   K  \        V4      NK'  	  up# u upi u upi   \         d    . u # i ; i)uå  Return existing Hermes-managed runtime dirs for the terminal subshell PATH.

The terminal tool spawns a subshell whose PATH is the agent process's PATH
plus ``_SANE_PATH``. Neither carries the runtimes Hermes installs for
itself, so on a machine where Hermes provisioned its own toolchain a
command the agent runs resolves a system copy instead â€” or nothing at all:

- the pm store's node/npm entries â€” installed to satisfy the desktop and
  browser toolchain. ``tools/browser_tool.py`` already does this for its own
  subprocesses; the agent's shell deserves the same.
- ``$HERMES_HOME/bin`` â€” the managed ``uv``. ``install.sh`` writes it there
  and nothing has ever put that directory on PATH, so an install whose only
  uv is the managed one looks uv-less to both the agent and the model.

Resolved per call rather than cached in a module constant because
``get_hermes_home()`` is profile-scoped and a managed runtime can appear
mid-process (a lazy pm install, a first browser install).
Nr"   ÚnpmÚPATHrj   )rô   r[  )rI  r&   r#   Úenv_forrL   rV  rR   rd  r   rN   r2   r'   )rI  r#   r¬   rZ  ÚmanagedÚ
candidatess         r   Ú_managed_runtime_path_entriesr–  ¬  s°   € ð&	ÛÝ4à�j‰j˜¨&°"¨ˆjÓ6ˆØ$'§G¡G¨F°BÓ$7×$=Ñ$=¼b¿j¹jÔ$IÓOÑ$I˜qËQ”7”4˜–7Ñ$IˆÐOØ:�wÐ:¡Ó 1°EÕ 9Ð:ˆ
Ù *Ó9¡
˜1¯h©h¯j””�A–¡
Ñ9Ð9ùò Pùâ9øÜô ØŠ	ðús<   ‚AB? Á	B5Á B5Á/B? ÂB:Â#B:Â2B? Â5
B? Â?CÃCc                ó:   € V ^8„  d   QhR\         \        ,          /# rC  rL  )r   s   "r   r   r   Ë  s   € ÷ ñ ¤¤c¥ñ r    c                 ó¸   € \         P                  ! 4       R,          R,          p  V P                  4       '       d   \        V 4      .# . #   \         d    . u # i ; i)u2  ``~/.local/bin`` when it exists â€” the pip --user / pipx / uv-tool install
target. A backend launched by a non-interactive SSH session, systemd or a GUI
launcher inherits a PATH without it (only the login shell adds it), so CLIs
installed there were ``command not found`` from the terminal tool (#111778).z.localr[  )r   ÚhomerN   r2   r=   )Ú	local_bins    r   Ú_user_local_bin_entriesr›  Ë  sT   € ô
 —	’	“˜hÕ&¨Õ.€IðØ#,×#3Ñ#3×#5Ò#5”�I“ÐÐ=¸2Ð=øÜô ð Š	ð	ús   ¥A	 »A	 ÁA	 Á	AÁAc                ó0   € V ^8„  d   QhR\         R\         /# ri  rh   )r   s   "r   r   r   Ú  s   € ÷ ñ ´Sð ¼Sñ r    c                ó0  € \         '       d   V # \        P                  R V P                  R4       4       4      pVP	                  \        P                  . \
        P                  R4      O\        4       O\        4       O4      4       RP                  V4      # )a;  Normalised POSIX PATH with missing sane entries appended: empty entries
dropped (shells read them as cwd), duplicates collapsed (first wins), then
missing ``_SANE_PATH`` / managed-runtime / ``~/.local/bin`` dirs appended so
user entries keep precedence. Windows is a no-op passthrough (native ``;``
PATH untouched).c              3   ó8   "  € T F  q'       g   K  Vx € K  	  R # 5irÍ   r]   )rÓ   rŽ  s   & r   rÕ   Ú4_append_missing_sane_path_entries.<locals>.<genexpr>ã  s   é € ÐQÑ/G eË5ŸEšEÓ/Gùs   ‚	�
rm   )	rn   r®   r]  rV  rí   Ú
_SANE_PATHr–  r›  rU  )ra  Úordereds   & r   Ú!_append_missing_sane_path_entriesr¢  Ú  s‚   € ÷ ƒ{ØÐä�m‰mÑQ¨}×/BÑ/BÀ3Ô/GÓQÓQ€GØ‡N�N”4—=‘=ð ">¤:×#3Ñ#3°CÓ#8ð ">Ô;XÓ;Zð ">Ü#:Ó#<ð">ó ?ô @à�8‰8�GÓÐr    c                ó(   € V ^8„  d   QhR\         RR/# r«   r­   )r   s   "r   r   r   é  s   € ÷ 3ñ 3¬tð 3¸ñ 3r    c                ój   € \         '       d'   V P                  RR4       V P                  RR4       R# R# )uc  Disable MSYS argument path conversion (``/FO`` -> ``C:/.../git/FO`` breaks
tasklist/schtasks/wmic/``cmd /c``). Git for Windows honors ``MSYS_NO_PATHCONV``;
MSYS2/Cygwin bash honor ``MSYS2_ARG_CONV_EXCL`` â€” set both; users can override.

Git Bash rewrites arguments that look like Unix paths (``/FO``, ``/TN``, ``/Create``) into
``C:/.../git/FO``-style paths, which breaks native Windows commands such as ``tasklist``, ``schtasks``,
and ``wmic``. Hermes runs terminal commands through bash on Windows, so set the standard MSYS opt-out by
default. Refs #56700.
MSYS2-proper and Cygwin bash (which ``_find_bash`` can still return via the final ``shutil.which``
fallback) ignore it and honor ``MSYS2_ARG_CONV_EXCL`` instead, so set both. ``*`` disables all argv
conversion â€” the semantic equivalent of ``MSYS_NO_PATHCONV=1``. Also fixes ``cmd /c`` mangling (#56147).
ÚMSYS_NO_PATHCONVr  ÚMSYS2_ARG_CONV_EXCLÚ*N)rn   r	  )r¬   s   &r   rä   rä   é  s,   € ÷ ƒ{Ø�‰Ð)¨3Ô/Ø�‰Ð,¨cÖ2ñ r    c                ó>   € V ^8„  d   QhR\         R\        R,          /# )r   Úrun_envr   N)r®   r2   )r   s   "r   r   r   û  s"   € ÷ ^ñ ^œ4ð ^¤C¨$¥Jñ ^r    c                óD   € \         '       d   \        R V  4       R4      # R# )z~PATH env key to update without altering Windows casing (``Path`` vs ``PATH``);
None when a Windows env has no PATH key at all.c              3   óR   "  € T F  qP                  4       R 8X  g   K  Vx € K  	  R# 5i)r’  NrÑ   rÒ   s   & r   rÕ   Ú _path_env_key.<locals>.<genexpr>þ  s   é € Ð;™G�q§w¡w£y°FÑ':—’›Gùs   ‚'�
'Nr’  )rn   Únext)r©  s   &r   rî   rî   û  s#   € ÷ GRÃkŒ4Ñ;™GÓ;¸TÓBÐ]ÐW]Ð]r    c                ó0   € V ^8„  d   QhR\         R\         /# rà   r­   )r   s   "r   r   r     s   € ÷ ñ ”tð ¤ñ r    c           
     óR  € ^ RI Hp \        \        V! \	        \
        P                  P                  4       4      4      V ,          4      R3.\        4       R 4      p ^ RI	H
p V! 4       pV'       d$   VP                  V4       VP                  RR4       V#   \         d    / p L<i ; i)añ  Build a run environment with a sane PATH and provider-var stripping. The process env is
the LAUNCH profile's; under a routed home override its ``.env`` residue is dropped first
(``strip_launch_profile_env``, a no-op for the launch profile) so the backend's own ``env``
and the served profile's declared passthrough names are what the child sees. A local session's
client toolchain (PATH, venv, nvm/pyenv/conda: ``agent.session_client_env``) replaces the daemon's
beneath the backend's own ``env``.)Útoolchain_environTc                 ó*   € \        \        V 4      4      # rÍ   )rþ   r¢  rø   s   &r   r    Ú_make_run_env.<locals>.<lambda>  s   € Ô#Ô$EÀaÓ$HÔIr    )Úpublished_envÚWAYLAND_DISPLAYN)Úagent.session_client_envr°  rò   r®   r  rR   r  r  rÅ   Útools.bot_desktop.runtimer³  r'   rí   r¼   )r¬   r°  r©  r³  Ú	publisheds   &    r   Ú_make_run_envr¸    s‘   € õ ;ÜÜ
Ñ Ô!9¼"¿*¹*¿/¹/Ó:KÓ!LÓMÐPSÕSÓ
TÐVZÐ	[Ð\Ü‹ÙIó€GðÝ;Ù!“Oˆ	÷ Ø�‰�yÔ!Ø�‰Ð% tÔ,Ø€Nøô ô ØŠ	ðús   ÁB ÂB&Â%B&Úbase_prefixÚreal_prefixc                ó\   € V ^8„  d   QhR\         \        \        ,          \        3,          /# rC  )ÚtuplerF   r2   r3   )r   s   "r   r   r   /  s    € ÷ ñ ¬%´´Sµ	¼4°Õ*@ñ r    c                 ó|  €  ^ RI Hp  V ! 4       ;'       g    / P                  R4      ;'       g    / pVP                  R4      ;'       g    . p\        V\        4      '       g   . pV Uu. uF  q3'       g   K  \        V4      NK  	  up\        VP                  RR4      4      3# u upi   \         d    . R3u # i ; i)zt(shell_init_files, auto_source_bashrc) from config.yaml; defaults on any
failure so terminal execution never breaks.)Úload_configr%   Úshell_init_filesÚauto_source_bashrcT)r9  r¾  rL   Ú
isinstancerF   r2   r3   r'   )r¾  Úterminal_cfgÚfilesrW   s       r   Ú _read_terminal_shell_init_configrÄ  /  s¨   € ðÝ1Ù#›×+Ð+¨×0Ñ0°Ó<×BÐBÀˆØ× Ñ Ð!3Ó4×:Ð:¸ˆÜ˜%¤×&Ò&ØˆEÙ %Ó+¡˜1«””�A–¡Ñ+¬T°,×2BÑ2BÐCWÐY]Ó2^Ó-_Ð_Ð_ùÒ+øÜô Ø�4ˆxŠðús9   ‚B) –B) ¯B) Á
B) Á)	B$Á7B$ÂB) Â$B) Â)B;Â:B;c                ó:   € V ^8„  d   QhR\         \        ,          /# rC  rL  )r   s   "r   r   r   =  s   € ÷ ñ ¤4¬¥9ñ r    c                 óž  € \        4       w  rT ;'       g    V'       d   \        '       g   . ROM. p. pV F‚  p \        P                  P	                  \        P                  P                  V4      4      pV'       d;   \        P                  P                  V4      '       d   VP                  V4       K€  K‚  K„  	  V#   \         d     K–  i ; i)a^  Files to source before the login-shell snapshot (``~``/``${VAR}`` expanded,
missing dropped). ``auto_source_bashrc`` applies only without an explicit list:
~/.profile and ~/.bash_profile first (no interactivity guard; where
n/nvm/asdf/pyenv add PATH), ~/.bashrc last (Debian's returns early when
non-interactive, but guard-less bashrcs keep working).)z
~/.profilez~/.bash_profilez	~/.bashrc)	rÄ  rn   rR   rx   Ú
expandvarsry   rt  Úappendr'   )ÚexplicitÚauto_bashrcr•  ÚresolvedÚrawrx   s         r   Ú_resolve_shell_init_filesrÍ  =  s­   € ô =Ó>Ñ€HØ÷ Jð Jß!,·[³[ó MØFHð à€HÛˆð	Ü—7‘7×%Ñ%¤b§g¡g×&8Ñ&8¸Ó&=Ó>ˆDßœŸ™Ÿ™ t×,Ò,Ø—‘ Ö%ñ -‰tñ ð €Oøô ô 	Úð	ús   ¹A(B=Â"B=Â=CÃCc                óR   € V ^8„  d   QhR\         R\        \         ,          R\         /# )r   Ú
cmd_stringrÃ  r   rb  )r   s   "r   r   r   Q  s%   € ÷ 2ñ 2¤Cð 2´´Sµ	ð 2¼cñ 2r    c                ó¶   € V'       g   V # V Uu. uF  q"P                  RR4      NK  	  ppR.R V 4       OpRP                  V4      R,           V ,           # u upi )z›Prepend guarded, silent ``source <file>`` lines: ``set +e`` keeps going on
errors, ``2>/dev/null`` hides noisy prompts, ``|| true`` neutralises the status.Ú'z'\''zset +ec              3   ó4   "  € T F  pR V RV R2x € K  	  R# 5i)z[ -r 'z
' ] && . 'z' 2>/dev/null || trueNr]   )rÓ   rù   s   & r   rÕ   Ú&_prepend_shell_init.<locals>.<genexpr>W  s"   é € ÐXÑSWÈa˜V A 3 j°°Ð3HÕIÓSWùs   ‚Ú
)rp   rU  )rÏ  rÃ  rù   ÚsafeÚpreludes   &&   r   Ú_prepend_shell_initr×  Q  s\   € ÷ ØÐÙ-2Ó3©U¨�I‰I�c˜7Ö#©U€DÐ3ØÐYÑXÑSWÓXÐY€GØ�9‰9�WÓ Õ$ zÕ1Ð1ùò 4s   �Ac                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   ÚpgidÚtimeoutr   )r,   r+   r3   )r   s   "r   r   r   \  s!   € ÷ ñ ¤Sð ´5ð ¼Tñ r    c                óT  € \         P                  ! 4       V,           p  V P                  4         \        P
                  ! V^ 4       \         P                  ! 4       T8¼  d   R# \         P                  ! R4       K^    \         d     LYi ; i  \         d     R# \         d     L_i ; i)zÃWait until the process group is gone, reaping the wrapper as we go (a dead
but unreaped group leader still makes ``killpg(pgid, 0)`` succeed).
POSIX-only; callers are behind the _IS_WINDOWS gate.TFgš™™™™™©?)	rE   Ú	monotonicÚpollr'   rR   ÚkillpgÚProcessLookupErrorÚPermissionErrorÚsleep)ÚprocrÙ  rÚ  Údeadlines   &&& r   Ú_wait_for_group_exiträ  \  s‹   € ô �~Š~Ó 'Õ)€HØ
ð	Ø�I‰IŒKð	Ü�IŠI�d˜AÔô
 �>Š>Ó˜xÔ'ÙÜ�
Š
�4Öøô ô 	Ùð	ûô "ô 	ÚÜô 	Ùð	ús.   ŸA; °B Á;B	ÂB	ÂB'ÂB'Â#B'Â&B'c                ó4   € V ^8„  d   QhR\         R\        RR/# )r   ÚdescendantsrÙ  r   N)rF   r,   )r   s   "r   r   r   q  s!   € ÷ ñ ¬Dð ¼ð Àñ r    c                ó  € V  FU  p VP                  4       '       g   K   \        P                  ! VP                  4      V8X  d   KD   VP                  4        KW  	  R#   \         d     L#i ; i  \         d     Kz  i ; i)ué   SIGKILL snapshotted survivors that escaped the process group via ``setsid``
â€” after TERMâ†’KILL so in-group members keep their grace; psutil's identity-aware
Process skips recycled PIDs. POSIX-only (see _IS_WINDOWS gate in caller).N)Ú
is_runningrR   Úgetpgidr8   r=   Úkillr'   )ræ  rÙ  Úchilds   && r   Ú_sweep_escaped_descendantsrì  q  sy   € ó ˆð
	Ø×#Ñ#×%Ò%ÙðÜ—:’:˜eŸi™iÓ(¨DÔ0Ùð 1ð �J‰JŽLó øô ô Ùðûô ô 	Úð	ús4   ‡A/ %AÁA/ÁA,Á)A/Á+A,Á,A/Á/A>Á=A>c                ó$   € V ^8„  d   QhR\         /# rC  )r3   )r   s   "r   r   r   ƒ  s   € ÷ ñ ¬Tñ r    c                ó®   € V f   R# Vf   R# ^ RI HpHp  V! V 4      pTf   R#  T! Y4      #   \         d     R# i ; i  \        \
        3 d     R# i ; i)uª  The setsid group leader's PID == its PGID.  Confirm it is still the process we
spawned before signalling the whole group, so a recycled PID/PGID can never take
down an unrelated process group (#43044).  The baseline and the current reading
come from the same host at different times, so they go through the drift-tolerant
fingerprint comparator â€” same-host readings drift ~1 s on macOS (#117505), and
exact equality made the guard refuse to kill live, legitimately-owned groups.
When no baseline was captured, or the current reading is unreadable, keep the
legacy best-effort behaviour rather than refusing to kill: only a LIVE leader with
a different start time proves recycling.FT)Úget_process_start_timeÚstart_time_fingerprints_match)Úgateway.statusrï  rð  r'   Ú	TypeErrorÚ
ValueError)rÙ  Úexpected_startrï  rð  rƒ   s   &&   r   Ú_leader_is_oursrõ  ƒ  so   € ð ‚|ÙØÒÙßTðÙ(¨Ó.ˆð ‚ñ ðÙ,¨^ÓEÐEøô ô Úðûô ”zÐ"ô Úðús   –- ¥? ­<»<¿AÁAc                ó   € V ^8„  d   QhRR/# r   r]   )r   s   "r   r   r   ¡  s   € ÷ 92ñ 92 tñ 92r    c                ób  € \        V RR4      p \        P                  ! V P                  4      p\        W!4      '       g@   . p ^ RIpVP                  V P                  4      P                  RR7      p\        W24       R#  ^ RIpVP                  V P                  4      P                  RR7      pV\        P                  ! 4       8X  d   \        W4       MÊ \        P                  ! V\        P                  4       \!        WR4      '       g’   \        W!4      '       g   R# \        P                  ! V\        P"                  4       \!        WR4       \$        P&                  ! \(        P*                  \,        4      ;_uu_ 4        V P/                  RR	7       RRR4       M \        W24       R#   \         d    \        T RR4      ;pf   h  EL�i ; i  \         d     ELli ; i  \         d    . p ELCi ; i  + '       g   i     Lg; i  \         d     Lw\0         d    \        Y4        LŽi ; i)
uÉ  TERM the group, wait, KILL, then sweep setsid escapees. Descendants are
snapshotted BEFORE the first signal â€” once the wrapper dies they reparent to
init â€” and we wait on the group, not the wrapper, which can exit before
grandchildren under load. POSIX-only (_IS_WINDOWS handled by the caller).
PID-reuse guard (#43044): the group is only signalled while its leader's start
time still matches the spawn-time baseline â€” a recycled PGID is never killed.Ú_hermes_pgid_startNÚ_hermes_pgidT)Ú	recursiveg      ð?ç       @gš™™™™™É?©rÚ  )r£   rR   ré  r8   rß  rõ  ÚpsutilÚProcessÚchildrenr'   rì  ÚgetpgrpÚ_kill_known_pidsrÞ  ÚsignalÚSIGTERMrä  ÚSIGKILLÚ
contextlibÚsuppressÚ
subprocessÚTimeoutExpiredr=   Úwaitrà  )râ  rô  rÙ  ræ  rý  s   &    r   Ú_kill_process_group_posixr
  ¡  sÈ  € ô ˜TÐ#7¸Ó>€NðÜ�zŠz˜$Ÿ(™(Ó#ˆô ˜4×0Ò0ð ˆð	ÛØ Ÿ.™.¨¯©Ó2×;Ñ;ÀdÐ;ÓKˆKô 	# ;Ô5ÙðÛØ—n‘n T§X¡XÓ.×7Ñ7À$Ð7ÓGˆð Œr�zŠz‹|Ôô 	˜Õ+ð	0Ü�IŠI�dœFŸN™NÔ+Ü'¨°C×8Ò8Ü& t×<Ò<ñ Ü—	’	˜$¤§¡Ô/Ü$ T°Ô5Ü×(Ò(¬×)BÑ)BÄG×LÕLØ—I‘I c�IÔ*÷ MÐLð 9ô$ ˜{Ö1øô_ ô Ü˜D .°$Ó7Ð7ˆDÒ@Øò Aðûô ô 	Úð	ûô ô Ø‹ðú÷  M×Lûä!ô 	ÙÜô 	0ô ˜TÖ/ð	0úsy   � F, Á/G Â /G" ÃAH	 Ä A"H	 ÆG6ÆH	 Æ,GÇGÇGÇGÇ"G3Ç2G3Ç6H	ÈH	 ÈH	 È	H.ÈH.ÈH.È-H.c                ó   € V ^8„  d   QhRR/# r   r]   )r   s   "r   r   r   Ý  s   € ÷ ñ ¨4ñ r    c                ó¼   € V .VO F>  p\         P                  ! \        4      ;_uu_ 4        VP                  4        RRR4       K@  	  R#   + '       g   i     KU  ; i)zPKILL the wrapper and its snapshotted descendants by PID (idempotent on zombies).N)r  r  r'   rê  )râ  ræ  r%  s   && r   r  r  Ý  s@   € àÐ&˜+Ó&ˆÜ× Ò ¤×+Õ+Ø�K‰KŒM÷ ,Ñ+ó 'ß+×+Ð+ús   «A
Á
Ac                ó   € V ^8„  d   QhRR/# r   r]   )r   s   "r   r   r   ä  s   € ÷ ñ  4ñ r    c                ód  €  ^ RI HpHp V! V P                  RV! V P                  4      R7       \        P                  ! \        P                  \        4      ;_uu_ 4        V P                  RR7       RRR4       R#   \         d    T P                  4         Lki ; i  + '       g   i     R# ; i)zLIdentity-checked terminate (start time guards against PID reuse), else kill.)rï  Úterminate_pidT)ÚforceÚexpected_start_timerû  rü  N)rñ  rï  r  r8   r'   rê  r  r  r  r  r=   r	  )râ  rï  r  s   &  r   Ú_kill_process_windowsr  ä  s}   € ðßHÙ�d—h‘h dÑ@VÐW[×W_ÑW_Ó@`Õaô 
×	Ò	œZ×6Ñ6¼×	@Õ	@Ø�	‰	˜#ˆ	Ô÷ 
AÑ	@øô ô Ø�	‰	Žðúç	@×	@Ð	@ús   ‚-A= Á BÁ=BÂBÂB/	c                   ó  a a€ ] tR tRt oRtRtRtRtV3R lR ltRV3R lV 3R lllt	V3R	 lR
 lt
]V3R lR l4       tV3R lR ltV3R lR ltRRR^xRR/V3R lR lltR tR tV3R lV 3R lltR tRtVtV ;t# )ÚLocalEnvironmentiï  zÈRun commands directly on the host: every execute() spawns a fresh bash;
the session snapshot preserves exported env vars across calls (unless
``persistent=False``); CWD persists via the stdout marker.Tc                ó4   <€ V ^8„  d   QhRS[ S[R3,          /# )r   r   .)r¼  r2   )r   Ú__classdict__s   "€r   r   ÚLocalEnvironment.__annotate__ú  s   ø€ ÷ 	Vñ 	V¹eÁCÈÀH½oñ 	Vr    c                óŒ   € \        \        P                  V P                  ,          4      p\	        \        R V 4       4      4      # )ay  First-party ``BUZZ_*`` names present in the env, excluded from the shared
session snapshot. env_passthrough can never list them (it refuses blocklisted
names), so under a multiplexed gateway profile A's BUZZ_PRIVATE_KEY would land
in the snapshot and be sourced by profile B. Prefix-only and monotonic on
purpose: conservative even when the context-gated carve-out is inactive.c              3   ó|   "  € T F2  p\        V\        4      '       g   K  \        V4      '       g   K.  Vx € K4  	  R # 5irÍ   )rÁ  r2   r   )rÓ   rJ   s   & r   rÕ   ÚPLocalEnvironment._additional_profile_scoped_passthrough_names.<locals>.<genexpr>  s0   é € ð UÙ#�TÜ˜$¤×$ô Ü)MÈd×)S÷ ŠD›Vùs   ‚<Ÿ<²
<)r®   rR   r  r¬   r¼  Úsorted)ÚselfÚmergeds   & r   Ú,_additional_profile_scoped_passthrough_namesÚ=LocalEnvironment._additional_profile_scoped_passthrough_namesú  sA   € ô ”b—j‘j 4§8¡8Õ+Ó,ˆÜ”Vñ UÙ#óUó Uó Vð 	Vr    Nc                ó@   <€ V ^8„  d   QhRS[ RS[RS[R,          RS[/# )r   rg   rÚ  r¬   NÚ
persistent)r2   r,   r®   r3   )r   r  s   "€r   r   r    s.   ø€ ÷ ñ ™Cð ©sð ¹dÀT½kð Ñ^bñ r    c                ó^   <€ \         SV `  \        V4      W#VR 7       V P                  4        R# ))rg   rÚ  r¬   Úpersist_envN)ÚsuperÚ__init__r†   Úinit_session)r  rg   rÚ  r¬   r!  Ú	__class__s   &&&&&€r   r%  ÚLocalEnvironment.__init__  s*   ø€ Ü‰ÑÔ7¸Ó<ÀgÐdnÐÔoØ×ÑÖr    c                ó    <€ V ^8„  d   QhRS[ /# rC  rh   )r   r  s   "€r   r   r  	  s   ø€ ÷ #[ñ #[™cñ #[r    c                óº  € \         '       Ed,   R	 F¶  pV P                  P                  V4      ;'       g     \        P                  P                  V4      pV'       g   KO  \        P
                  P                  V4      '       g   Kv  \        P
                  P                  V4      '       g   K�  \        V4      P                  4       u # 	  \        4       ;'       g&    \        \        P                  ! 4       4      R,          pVP                  RRR7       \        4        \        V4      P!                  RR4      # R R lpR
 Fž  pV P                  P                  V4      ;'       g     \        P                  P                  V4      pV'       g   KO  VP#                  R4      '       g   Kh  VR8w  g(   \        P
                  P                  V4      '       g   K–  V! V4      u # 	   \        4       pVP                  RRR7       \        V4      pVP#                  R4      '       dS   \        P$                  ! V\        P&                  \        P(                  ,          4      '       d   \        4        V! V4      # \        P                  ! 4       pT! TP#                  R4      '       d   T4      # \        P
                  P-                  T4      4      #   \*         d     Ldi ; i)aè  Shell-safe writable temp dir. Precedence: ``TERMINAL_TEMP_DIR``, TMPDIR/TMP/TEMP
(Termux has no system temp dir), ``HERMES_HOME/cache/terminal`` (real storage: a
tmpfs system temp dir fills under Hermes load; pruned by ``cleanup_terminal_temp_cache``),
``tempfile.gettempdir()``; backend env before process env so terminal.env
overrides work. Windows: ``%TEMP%`` often has spaces that break unquoted bash,
so always the HERMES_HOME cache dir with forward slashes (bash- and Python-valid).ÚTERMINAL_TEMP_DIRÚhermes_terminalT)r€  Úexist_okrl   rk   c                ó0   € V ^8„  d   QhR\         R\         /# )r   rù   r   rh   )r   s   "r   r   Ú3LocalEnvironment.get_temp_dir.<locals>.__annotate__  s   € ÷ 	(ñ 	(”cð 	(œcñ 	(r    c                 ó8   € V P                  R 4      ;'       g    R # )rk   )Úrstriprø   s   &r   Ú_posixÚ-LocalEnvironment.get_temp_dir.<locals>._posix  s   € Ø—8‘8˜C“=×'Ð' CÐ'r    )r+  ÚTMPDIR)r+  r4  ÚTMPÚTEMP)rn   r¬   rL   rR   r  rx   r|   r~   r   Úas_posixr(   r¥   r¦   Úmkdirrd   r2   rp   rØ   r˜   ÚW_OKr™   r'   r}   )r  rÛ   r‚   Ú	cache_dirr2  Úenv_varrË  Úfallbacks   &       r   Úget_temp_dirÚLocalEnvironment.get_temp_dir	  sÿ  € ÷ Œ;Û6�Ø ŸH™HŸL™L¨Ó-×DÐD´·±·±ÀÓ1D�	ß‘9¤§¡§¡¨y×!9Ô!9¼b¿g¹g¿m¹mÈI×>VÔ>VÜ 	›?×3Ñ3Ó5Ò5ñ 7ô 4Ó5÷ Lð LÜ ¤×!4Ò!4Ó!6Ó7Ð:KÕKð à�O‰O D°4ˆOÔ8Ü%Ô'Ü�y“>×)Ñ)¨$°Ó4Ð4õ	(ãEˆGØŸ™Ÿ™ WÓ-×HÐH´·±·±ÀÓ1HˆIß‰y˜Y×1Ñ1°#×6Ô6ØÐ2Ô2´b·g±g·m±mÀI×6NÔ6NÙ˜iÓ(Ò(ñ	 Fð
	Ü2Ó4ˆIØ�O‰O D°4ˆOÔ8Ü˜9“~ˆHØ×"Ñ" 3×'Ò'¬B¯IªI°hÄÇÁÌ"Ï'É'Õ@Q×,RÒ,RÜ)Ô+Ù˜hÓ'Ð'ô ×&Ò&Ó(ˆÙ (×"5Ñ"5°c×":Ò":�hÓZÐZÄÇÁÇÁÐPXÓ@YÓZÐZøô	 ô 	Ùð	ús   Ç$A>K É#K ËKËKc                ó&   <€ V ^8„  d   QhRS[ RS[ /# rf   rh   )r   r  s   "€r   r   r  /  s   ø€ ÷ Mñ M™sð M¡sñ Mr    c                ó@   € \         P                  ! \        V 4      4      # )z@Use native paths for Python, but Git Bash-friendly paths for cd.)r   Ú_quote_cwd_for_cdr‹   ©rg   s   &r   rA  Ú"LocalEnvironment._quote_cwd_for_cd.  s   € ô ×0Ò0Ô1FÀsÓ1KÓLÐLr    c                ó&   <€ V ^8„  d   QhRS[ RS[ /# r�   rh   )r   r  s   "€r   r   r  3  s   ø€ ÷ &ñ &¡cð &©cñ &r    c                ó   € \        V4      # )z?Rewrite native/mixed Windows paths before quoting for Git Bash.)r•   )r  rx   s   &&r   Ú_quote_shell_pathÚ"LocalEnvironment._quote_shell_path3  s   € ä Ó%Ð%r    c                ó   <€ V ^8„  d   QhRR/# r   r]   )r   r  s   "€r   r   r  7  s   ø€ ÷ ñ ˜dñ r    c                óÖ   € \        V P                  4      pWP                  8X  d   R# V\        V P                  4      8w  d"   \        P	                  RV P                  V4       Wn        R# )uþ   Swap ``self.cwd`` for a usable directory if it vanished or is inaccessible
(e.g. a command ``rm -rf``'d its own cwd) â€” otherwise Popen raises before bash
starts and every subsequent call fails. A benign MSYSâ†’Windows normalization
is not warned about.NzaLocalEnvironment cwd %r is missing on disk; falling back to %r so terminal commands keep working.)r©   rg   ru   ra   r¢   )r  Úsafe_cwds   & r   Ú_recover_cwdÚLocalEnvironment._recover_cwd7  sS   € ô % T§X¡XÓ.ˆØ—x‘xÔÙØÔ,¨T¯X©XÓ6Ô6Ü�N‰NðHà—‘˜(ô$ð Žr    ÚloginFrÚ  Ú
stdin_datac          
      óZ   <€ V ^8„  d   QhRS[ RS[RS[RS[ R,          RS[P                  /# )r   rÏ  rM  rÚ  rN  Nr   )r2   r3   r,   r  ÚPopen)r   r  s   "€r   r   r  K  s<   ø€ ÷ ñ ¡Cð ±4ð É#ð Ù! D�jðÙ4>×4DÑ4Dñr    c               ó  € \        4       pV'       d   \        V\        4       4      pV.V'       d   R .M. ORNVNpV P                  4        \        P
                  ! V3RRR\        V P                  4      RRRRR	\        P                  R
\        P                  RVe   \        P                  M\        P                  RRRV P                  /	\        '       d   R\        4       /M/ B p\        '       gn   \        P                  ! \         4      ;_uu_ 4        \"        P$                  ! VP&                  4      Vn        ^ RIHp V! VP&                  4      Vn        RRR4       Ve   \1        Wt4       V#   + '       g   i     L!; i)z-lz-cÚtextTr¬   Úencodingzutf-8Úerrorsrp   ÚstdoutÚstderrÚstdinNÚstart_new_sessionrg   Úcreationflags)rï  )rJ  r×  rÍ  rK  r  rP  r¸  r¬   ÚPIPEÚSTDOUTÚDEVNULLrg   rn   r   r  r  rß  rR   ré  r8   rù  rñ  rï  rø  r   )	r  rÏ  rM  rÚ  rN  rG  Úargsrâ  rï  s	   &&$$$    r   Ú	_run_bashÚLocalEnvironment._run_bashK  s]  € ä‹|ˆ÷ Ü,¨ZÔ9RÓ9TÓUˆJØÐC§%˜™¨RÐC°$ÐC¸
ÐCˆØ×ÑÔÜ×ÒØñPØðPÜ!.¨t¯x©xÓ!8ðPØCJðPØS\ðPä—?‘?ðPä+5×+<Ñ+<ðPð &0Ò%;”*—/’/Ä×ASÑASðPð #ð	Pð )-¯©ð	P÷
 ;F»+�Ô!3Ó!5Ñ6È2ñPˆ÷ ‹{Ü×$Ò$Ô%7×8Õ8Ü$&§J¢J¨t¯x©xÓ$8�Ô!õ
 BÙ*@ÀÇÁÓ*J�Ô'÷ 9ð Ò!Ü˜Ô)Øˆ÷ 9×8ús   ÄAE1Å1F	c                ó  €  \         '       d   \        M\        ! V4       R#   \         dU    \        P
                  ! \        4      ;_uu_ 4        TP                  4        RRR4        R#   + '       g   i      R# ; ii ; i)z-Kill the entire process group (all children).N)rn   r  r
  r=   r  r  r'   rê  )r  râ  s   &&r   Ú_kill_processÚLocalEnvironment._kill_processg  sS   € ð	ß&1£kÕ"Ô7PÐPÐRVÖWøÜô 	Ü×$Ò$¤Y×/Õ/Ø—	‘	”÷ 0×/×/Ô/úð	ús+   ‚" Ž" ¢-BÁA+Á BÁ+A=Á6BÁ=Bc           
     ó|  € \         '       d   V P                  V4      # \        P                  ! \        4      ;_uu_ 4        \        VRR4      ;'       g!    \        P                  ! VP                  4      pV\        P                  ! 4       8w  dC   \        V\        VRR4      4      '       d&   \        P                  ! V\        P                  4       RRR4       \        P                  ! \        4      ;_uu_ 4        VP                  4        RRR4       R#   + '       g   i     LM; i  + '       g   i     R# ; i)zPSIGKILL the whole group with no TERM grace or wait: the caller os._exit()s next.rù  Nrø  )rn   ra  r  r  r=   r£   rR   ré  r8   r   rõ  rÞ  r  r  rê  )r  râ  rÙ  s   && r   Ú_force_kill_processÚ$LocalEnvironment._force_kill_processo  sÃ   € ç‹;Ø×%Ñ% dÓ+Ð+Ü× Ò ¤×)Õ)Ü˜4 °Ó6×NÐN¼"¿*º*ÀTÇXÁXÓ:NˆDð
 ”r—z’z“|Ô#¬¸¼gÀdÐL`ÐbfÓ>g×(hÒ(hÜ—	’	˜$¤§¡Ô/÷ *ô × Ò ¤×)Õ)Ø�I‰IŒK÷ *Ñ)÷ *×)ú÷ *×)Ð)ús   Á BDÃ<D*ÄD'	Ä*D;	c                ó    <€ V ^8„  d   QhRS[ /# )r   Úresultr­   )r   r  s   "€r   r   r  ~  s   ø€ ÷ (ñ (©tñ (r    c                óT  <€ V P                   p\        SV `	  V4       V P                   V8w  d{   \        V P                   4      pV'       d2   \        P
                  P                  V4      '       d   W0n         W1R&   R# W n         VP                  RR4       VP                  RR4       R# R# )u  Base semantics plus: Git Bash ``pwd -P`` emits MSYS form on Windows â€”
normalize to native and require the dir to exist, else ``_run_bash`` would
warn every command. A stale path rolls back to the previous cwd, which this
command did not observe, so ``cwd_observed`` is dropped.rg   Úcwd_observedN)rg   r$  Ú_extract_cwd_from_outputru   rR   rx   r~   r¼   )r  rg  Úprev_cwdÚ
normalizedr'  s   &&  €r   rj  Ú)LocalEnvironment._extract_cwd_from_output~  s|   ø€ ð
 —8‘8ˆÜ‰Ñ(¨Ô0Ø�8‰8�xÔÜ.¨t¯x©xÓ8ˆJßœbŸg™gŸm™m¨J×7Ò7Ø%”Ø *�u“à#”Ø—
‘
˜>¨4Ô0Ø—
‘
˜5 $Ö'ñ  r    c                ó^  € ^ RI p VP                  V P                   R24      pV P                  V P                  .VO FD  p\        P
                  ! \        4      ;_uu_ 4        \        P                  ! V4       RRR4       KF  	  R#   \         d    . p Lsi ; i  + '       g   i     Kn  ; i)zƒClean up temp files, including orphaned atomic-write snapshots
(``snap.tmp.<bashpid>``) a failed/interrupted mv could leave behind.Nz.tmp.*)	ÚglobÚ_snapshot_pathr'   Ú	_cwd_filer  r  r=   rR   rQ   )r  ro  ÚstalerW   s   &   r   ÚcleanupÚLocalEnvironment.cleanup�  sŽ   € ó 	ð	Ø—I‘I ×!4Ñ!4Ð 5°VÐ<Ó=ˆEð ×%Ñ% t§~¡~Ð>¸Ó>ˆAÜ×$Ò$¤W×-Õ-Ü—	’	˜!”÷ .Ñ-ó ?øô ô 	ØŠEð	ú÷ .×-Ð-ús   †B Á#BÂBÂBÂB,rB  )rj   é<   NT)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú"_passwordless_sudo_probe_supportedÚ_profile_scoped_passthroughÚis_localr  r%  r=  ÚstaticmethodrA  rF  rK  r^  ra  rd  rj  rs  Ú__static_attributes__Ú__classdictcell__Ú__classcell__)r'  r  s   @@r   r  r  ï  s¬   ù‡ € ñBð *.Ð&Ø"&Ðð €H÷	Vð 	V÷õ ÷#[ð #[ðJ ÷Mó ðM÷&ð &÷ð ð(¸%ð ÐPSð Ø+/÷ò ò8ò÷(ó (÷"ò r    r  c                óŽ  € V ^8„  d   Qh/ ^ \         9   d   \        \        ,          R,          ;R&   ^\         9   d   \        R,          \        ,          ;R&   ^\         9   d
   \        ;R&   ^\         9   d   \
        \        R3,          ;R&   ^\         9   d
   \        ;R&   ^\         9   d   \        \        ,          R,          ;R&   # )	r   NrN  r|  Ú_hermes_repo_root.Ú_hermes_repo_root_aliasesÚ_in_venvÚ_hermes_site_packages)Ú__conditional_annotations__rF   r2   Úobjectr   r¼  r3   )r   s   "r   r   r      sµ   € × KÑ K÷Z 2Ò 1œ$œs�) dÕ*Ñ 1ñ[ L÷r 1Ò 0”�t•œfÕ$Ñ 0ñs L÷J >Ò =”4Ñ =ñK L÷LXò Xœ5¤ s Õ+ñ XñM L÷P2ò 2Œ$ñ 2ñQ L÷T 0Ò /”tœD•z DÕ(Ñ /òU Lr    rÍ   >   ÚshÚkshÚzshrG  ÚdashÚmksh)|r‡  rz  r  Úloggingr{   rR   Úplatformro   rO   r  r  rƒ  r¥   Ú	threadingrE   Úcollections.abcr   Úpathlibr   r&   r   Útools.environments.baser   Útools.environments.base_outputr   Úhermes_cli._subprocess_compatr   Ú#tools.environments.local_env_policyr	   r
   r   r   r   r   r   r   r   r   r   r   r   Ú#tools.environments.local_pythonpathr   r   Úsystemrn   Ú	getLoggerrv  ra   ÚTERMINAL_TEMP_MAX_IDLE_HOURSÚLockr_   r`   ÚcompilerH   r(   r[   rd   ru   r†   r‹   r�   r•   rš   r©   r´   rÀ   rÅ   rÞ   ræ   rò   rû   rÿ   r
  r  r  r'  r+  r$  r  r  rJ  rN  rP  rO  rg  rþ   ru  rw  r   rˆ  r}  r|  r�  rŠ  rï   r–  r›  r¢  rä   rî   r¸  r  r/  r€  rƒ  Úabsoluter„  r£   ÚprefixÚhasattrr…  r†  rÄ  rÍ  r×  rä  rì  rõ  r
  r  r  r  r   )r‡  s   @r   Ú<module>r      så  øðÞ Kã Û Û Û 	Û Û 	Û Û Û Û 
Û Û Û Ý #Ý å 4Ý 3Ý 6Ý <÷÷ ÷ õ ÷Yð �oŠoÓ 9Ñ,€à	×	Ò	˜8Ó	$€ð  "Ð Ø%ŸNšNÓ,Ð Ø"Ð ð �zŠzÐIÓJ€õð 8T÷ ;õ|
<õ5õõ.+õ\õ.õ<õ+õB#õ$ð&á'›k÷õD	/õ$÷,Iõð$Ø#(ð$ØLP÷$õ"ñ !/ØKOð!/àð!/àBFð!/ð "'÷!/ð !/ñH)ØOSð)à %÷)ð )÷Xõ
÷)'õX	õð .2Ð Ó 1õ$õ	DõOõGñ$ %Ò%QÓRÐ õ	ðM€
ñ
 ‹H€	Ø'0€Ó 0à"Ð õõDVõõ>õõ3õ$^õñJ ˜x›.×0Ñ0Ó2×:Ñ:¸1Õ=Ð Ó =Ù.MØ‘t˜H“~×.Ñ.Ó0×8Ñ8¸Õ;Ñ=TÓ=Vó/XÐ ó Xá˜#˜}¨c¯j©jÓ9¸S¿Z¹ZÑG÷ 1ð 1Ù˜S -Ó0ð 	ó 2à+/Ð Ó /õõõ(2õõ*õ$õ<92õxõôk�ö kr    