+
    lHàj%\  ã                   ó:  a € R3 t10 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HtHt ^ RIHt ^ RIHt ]P$                  ! R4      t/ t] ^ k ]	P*                  ! 4       t]! RRR7      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R4tR R ltR5t R R lt!R R lt"R R lt#R R lt$R6RR/R  R! lllt%R" R# lt&]PN                  ! R$]PP                  4      t)R% R& lt*R7R' R( llt+R) R* lt,R+ R, lt-R- R. lt.R/ R0 lt/R8R1 R2 llt0R# )9aµ  Sudo password plumbing and shell-command rewrites for the terminal tool: per-scope
password cache, /dev/tty prompt, the quote-aware shell scanner behind the real-sudo rewrite
(``sudo -S -p ''``) and the compound-background brace-group rewrite, and the NOPASSWD probe.
Split out of ``tools/terminal_tool.py``; every public/patched name is re-imported there so
``tools.terminal_tool.<name>`` keeps resolving (and monkeypatching) as before.N)ÚCallableÚIterator)Ú
ContextVar)Úenv_var_enabledztools.terminal_toolÚsudo_prompt_commandÚ )Údefaultc                ó$   € V ^8„  d   QhR\         /# ©é   Úreturn©Ústr)Úformats   "Ú=/home/ubuntu/.hermes/hermes-agent/tools/terminal_tool_sudo.pyÚ__annotate__r   "   s   € ÷ &ñ &¤ñ &ó    c                 ó*   € \         P                  4       # )zROriginal command for the current sudo password prompt, or '' outside its callback.)Ú_sudo_prompt_commandÚget© r   r   Úget_sudo_prompt_commandr   "   s   € ä×#Ñ#Ó%Ð%r   c                ó$   € V ^8„  d   QhR\         /# r
   r   )r   s   "r   r   r   '   s   € ÷ &ñ &¬ñ &r   c                 ó  € ^ RI Hp Hp V ! 4       pV'       d   RV 2# V! 4       pVf   R\        P                  ! 4        2# \        VRR4      p\        VRR4      pVe   Ve   R\        V4       R\        V4       2# R	\        V4       2# )
z6Return the cache scope for interactive sudo passwords.)Ú_current_session_keyÚ_get_sudo_password_callbackzsession:Nzthread:Ú__self__Ú__func__zcallback-owner:Ú:z	callback:)Útools.terminal_toolr   r   Ú	threadingÚ	get_identÚgetattrÚid)r   r   Úsession_keyÚcallbackÚownerÚfuncs         r   Ú_get_sudo_password_cache_scoper(   '   s•   € çUÙ&Ó(€KßØ˜+˜Ð'Ð'Ù*Ó,€HØÒØœ×,Ò,Ó.Ð/Ð0Ð0Ü�H˜j¨$Ó/€EÜ�8˜Z¨Ó.€DØÒ˜TÒ-Ø ¤ E£ ¨1¬R°«X¨JÐ7Ð7Ø”r˜(“|�nÐ%Ð%r   c                ó$   € V ^8„  d   QhR\         /# r
   r   )r   s   "r   r   r   7   s   € ÷ 3ñ 3¤3ñ 3r   c                 óœ   € \        4       p \        ;_uu_ 4        \        P                  V R4      uuRRR4       #   + '       g   i     R# ; i)z6Return the cached sudo password for the current scope.r   N)r(   Ú_sudo_password_cache_lockÚ_sudo_password_cacher   )Úscopes    r   Ú_get_cached_sudo_passwordr.   7   s/   € ä*Ó,€Eß	"Ö	"Ü#×'Ñ'¨¨rÓ2÷ 
#×	"×	"Ó	"ús	   ™:ºA	c                ó(   € V ^8„  d   QhR\         RR/# )r   Úpasswordr   Nr   )r   s   "r   r   r   >   s   € ÷ 2ñ 2¬ð 2°ñ 2r   c                óÀ   € \        4       p\        ;_uu_ 4        V '       d   V \        V&   M\        P                  VR4       RRR4       R#   + '       g   i     R# ; i)zCPersist a sudo password for the current scope ("" drops the entry).N)r(   r+   r,   Úpop)r0   r-   s   & r   Ú_set_cached_sudo_passwordr3   >   s=   € ä*Ó,€Eß	"Ö	"ßØ*2Ô  Ò'ä ×$Ñ$ U¨DÔ1÷	 
#×	"×	"Ò	"ús   ™)AÁA	c                ó   € V ^8„  d   QhRR/# ©r   r   Nr   )r   s   "r   r   r   H   s   € ÷ %ñ % dñ %r   c                 ó„   € \         ;_uu_ 4        \        P                  4        RRR4       R#   + '       g   i     R# ; i)z;Clear all cached sudo passwords (tests / process teardown).N)r+   r,   Úclearr   r   r   Ú_reset_cached_sudo_passwordsr8   H   s#   € ç	"Ö	"Ü×"Ñ"Ô$÷ 
#×	"×	"Ò	"ús   �.®?	c                ó$   € V ^8„  d   QhR\         /# r
   ©Úbool)r   s   "r   r   r   N   s   € ÷ 
ñ 
¤Tñ 
r   c                 óB   €  ^ RI Hp  V ! 4       #   \         d     R# i ; i)aÀ  True while running inside a delegate_task child. Subagents run on parent-process worker
threads and inherit process-wide ``HERMES_INTERACTIVE=1``, which does NOT mean they can reach
the user: a raw ``/dev/tty`` sudo prompt from a child races the TUI for the tty and blocks the
child for the full timeout, so children are always headless for sudo prompting. The ContextVar
is set by ``delegated_child_context()`` and propagates via ``copy_context``.©Úis_delegated_child_contextF)Úagent.delegation_contextr>   Ú	Exceptionr=   s    r   Ú_in_delegated_child_contextrA   N   s%   € ðÝGÙ)Ó+Ð+øÜô Úðús   ‚ ��c                ó<   € V ^8„  d   QhR\         R\         R\         /# )r   ÚoutputÚenv_typer   r   )r   s   "r   r   r   ^   s&   € ÷ }ñ }¤ð }´ð }¼ñ }r   c                óF  a € \        R4      p\        4       pV'       g	   V'       dI   \        ;QJ d#    V 3R l\         4       F  '       g   K   RM	  RM! V 3R l\         4       4      '       g   S # ^ RIHp V'       d   S RV! 4        R2,           # S RV! 4        R	2,           # )
zžAppend a SUDO_PASSWORD tip when sudo failed in a headless context
(gateway session, delegate_task child or `hermes chat -q`); otherwise return *output* as is.ÚHERMES_GATEWAY_SESSIONc              3   ó,   <"  € T F	  qS9   x € K  	  R # 5i©Nr   )Ú.0ÚfrC   s   & €r   Ú	<genexpr>Ú'_handle_sudo_failure.<locals>.<genexpr>c   s   øé € Ð-[ÑCZ¸a°6®kÓCZùó   ƒTF)Údisplay_hermes_homeuQ   

ðŸ’¡ Tip: This session cannot prompt for a sudo password. Add SUDO_PASSWORD to z</.env on the agent machine, or run the command without sudo.u@   

ðŸ’¡ Tip: To enable sudo over messaging, add SUDO_PASSWORD to z/.env on the agent machine.)r   Ú_no_sudo_userÚanyÚ_SUDO_HEADLESS_FAILURESÚhermes_constantsrN   )rC   rD   Ú
is_gatewayÚno_userÚ_dhhs   f&   r   Ú_handle_sudo_failurerV   ^   s‰   ø€ ô !Ð!9Ó:€JÜ‹o€GßŸ'¯#«#Ô-[ÕCZÓ-[¯#¯#ª#Ô-[ÕCZÓ-[×*[Ò*[ØˆÝ<ßØð$Ù$(£F 8ð ,/ð/õ
ð 	
ð
 ÐXÑY]ÓY_ÐX`Ð`{Ð|Õ|Ð|r   c                ó0   € V ^8„  d   QhR\         R\        /# )r   rC   r   ©r   r;   )r   s   "r   r   r   x   s   € ÷ Mñ M¬ð M´ñ Mr   c                ó¼   a€ T ;'       g    RP                  4       o\        ;QJ d#    V3R l\         4       F  '       g   K   R# 	  R# ! V3R l\         4       4      # )z0Return True when sudo rejected a piped password.r   c              3   ó,   <"  € T F	  qS9   x € K  	  R # 5irH   r   )rI   ÚmarkerÚlowereds   & €r   rK   Ú/_sudo_wrong_password_failure.<locals>.<genexpr>{   s   øé € ÐLÑ/K V˜Ö Ó/KùrM   TF)ÚlowerrP   Ú_SUDO_WRONG_PASSWORD_MARKERS)rC   r\   s   &@r   Ú_sudo_wrong_password_failurer`   x   sB   ø€ à�|ˆ|˜×"Ñ"Ó$€Gß‹3ÔLÕ/KÓL�3Œ3ÐLŠ3ÐLˆ3ÔLÕ/KÓLÓLÐLr   c                óJ   € V ^8„  d   QhR\         R,          R\         R\        /# )r   ÚcommandNrC   r   rX   )r   s   "r   r   r   ~   s&   € ÷ ñ ´S¸4µZð Ìð ÔQUñ r   c                óÀ   € R\         P                  9   g<   \        V4      '       d+   \        T ;'       g    R4      ^ 8X  g   \	        4       '       g   R# \        R4       R# )u�   Drop a session-cached sudo password after sudo rejects it. Env-configured
``SUDO_PASSWORD`` is left alone â€” an explicit operator choice, not a cache entry.ÚSUDO_PASSWORDr   FT)ÚosÚenvironr`   Ú_count_real_sudo_invocationsr.   r3   )rb   rC   s   &&r   Ú'_invalidate_cached_sudo_on_auth_failurerh   ~   sE   € ð 	œ2Ÿ:™:Ô%Ü+¨F×3Ò3Ü'¨¯¨°2Ó6¸!Ô;Ü(×*Ò*áÜ˜bÔ!Ùr   c                ó   € V ^8„  d   QhRR/# r5   r   )r   s   "r   r   r   Œ   s   € ÷ 6ñ 6 tñ 6r   c                óD  € V f   R# Ve"    ^ RI pVP                  WP                  V4        \        P                  ! V 4       R#   \         d!   p\        P                  RT4        Rp?L?Rp?ii ; i  \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)zSRestore echo and close the /dev/tty fd opened by the password reader (best effort).Nz)Failed to restore terminal attributes: %szFailed to close tty fd: %s)ÚtermiosÚ	tcsetattrÚ	TCSAFLUSHr@   ÚloggerÚdebugre   Úclose)Útty_fdÚ	old_attrsÚ_termiosÚes   &&  r   Ú_release_ttyru   Œ   s‰   € à‚~ÙØÒð	IÛ&Ø×Ñ˜v×'9Ñ'9¸9ÔEð6Ü
�Š�Öøô ô 	IÜ�L‰LÐDÀa×HÑHûð	Iûô ô 6Ü�‰Ð1°1×5Ò5ûð6ús.   Œ A ­A3 ÁA0ÁA+Á+A0Á3BÁ>BÂBc                ó(   € V ^8„  d   QhR\         RR/# )r   Úresultr   N)Údict)r   s   "r   r   r   œ   s   € ÷ ñ ¤$ð ¨4ñ r   c                ó0  € R;r . p\         P                  ! 4       R8X  dQ   ^ RIpVP                  4       ;pR9  d!   VR8X  d   \        hVP                  V4       K7  RP                  V4      V R&   Mä^ RIp\        P                  ! R\        P                  4      pVP                  V4      pVP                  V4      pV^,          VP                  ( ,          V^&   VP                  WP                  V4       \        P                  ! V^4      ;p'       d   VR9  d   VP                  V4       K9  RP                  V4      P!                  RR	R
7      V R&    \%        W4       RV R&   R#   \        \"        3 d	    RT R&    L*i ; i  \%        Y4       RT R&   i ; i)z[Read one line with echo disabled into ``result``. Uses msvcrt on Windows, /dev/tty on Unix.NÚWindowsÚr   r0   z/dev/ttyr   zutf-8Úreplace)ÚerrorsTÚdone>   Ú
Ú>   ó   
ó   )ÚplatformÚsystemÚmsvcrtÚgetwchÚKeyboardInterruptÚappendÚjoinrk   re   ÚopenÚO_RDONLYÚ	tcgetattrÚECHOrl   rm   ÚreadÚdecoder@   ru   )	rw   rq   rr   Úcharsr…   Úcrk   Ú	new_attrsÚbs	   &        r   Ú_read_hidden_passwordr”   œ   sY  € àÐ€FðØˆÜ�?Š?Ó 	Ô)ÛØŸ™›Ð'�1°Ô<Ø˜”;Ü+Ð+Ø—‘˜Q–Ø!#§¡¨£ˆF�:ÒãÜ—W’W˜Z¬¯©Ó5ˆFØ×)Ñ)¨&Ó1ˆIØ×)Ñ)¨&Ó1ˆIØ$ Q�<¨7¯<©<¨-Õ7ˆI�a‰LØ×Ñ˜f×&7Ñ&7¸ÔCÜŸš ¨Ó*Ð*�1Ö*°¸Ô0GØ—‘˜Q–Ø!$§¡¨%£×!7Ñ!7¸È	Ð!7Ó!RˆF�:Òô 	�VÔ'Øˆˆv‹øô	 œyÐ)ô  ØˆˆzÓð ûô 	�VÔ'ØˆˆvŠús=   …A+E' Á0F Á1B#E' Ä?E' ÅF Å'F Å=F Å?F Æ F ÆFrb   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   Útimeout_secondsrb   r   )Úintr   )r   s   "r   r   r   ¹   s'   € ÷ E9ñ E9¬sð E9ÄSð E9ÔRUñ E9r   c               óö  € ^ RI Hp V! RVR7      ;_uu_ 4       p^ RIHp V! 4       pVex   \        P                  V4      p ^ RIHp V! 4       ;_uu_ 4        V! 4       ;'       g    RpRRR4       X'       d   RMR	Vn        V\        P                  V4       uuRRR4       # RRRR/p	 R\        P                  R&   \        P                  ! R4       \        RP!                  RR$R%R&RRRV  R2R',           R,           R(R3	4      4       \        RRRR7       \"        P$                  ! \&        V	3RR7      p
V
P)                  4        ^ RIHp V! 4       ;_uu_ 4        V
P!                  V R7       RRR4       V	R,          '       g\   \        R4       \*        P,                  P/                  4        RVn         \        P                  P1                  RR4       RRR4       R# V	R,          ;'       g    RpV'       d   RMR	Vn        V'       d   \        R4       M\        R4       \*        P,                  P/                  4        V\        P                  P1                  RR4       uuRRR4       #   + '       g   i     EL; i  \         d)    R
Tn         \        P                  T4       RRR4       R# i ; i  \        P                  T4       i ; i  + '       g   i     ELl; i  \2        \4        3 d]    \        R 4       \*        P,                  P/                  4        R!Tn         \        P                  P1                  RR4       RRR4       R# \         dh   p\        R"T R#24       \*        P,                  P/                  4        R
Tn         Rp?\        P                  P1                  RR4       RRR4       R# Rp?ii ; i  \        P                  P1                  RR4       i ; i  + '       g   i     R# ; i))a  Prompt for a sudo password; "" on skip (empty Enter), timeout, or error. Prefers the
CLI-registered callback (prompt_toolkit-integrated); otherwise reads /dev/tty (msvcrt on
Windows) with echo disabled. Human wait time is excluded from tool deadlines (``human_wait_window``).)Úhuman_input_requestÚsudo)Úprompt©r   N)Úhuman_wait_windowr   ÚprovidedÚskippedÚerrorr0   r~   FÚ1ÚHERMES_SPINNER_PAUSEgš™™™™™É?r   u   â”‚u?   â”‚  Enter password below (input is hidden), or:            â”‚uA   â”‚    â€¢ Press Enter to skip (command fails gracefully)     â”‚u   â”‚    â€¢ Wait zs to auto-skipz  Password (hidden): T)ÚendÚflush)ÚtargetÚargsÚdaemon)ÚtimeoutuF   
  â�± Timeout - continuing without sudo
    (Press Enter to dismiss)
r¨   u3   
  âœ“ Password received (cached for this session)
u)   
  â�­ Skipped - continuing without sudo
u+   
  â�­ Cancelled - continuing without sudo
Ú	cancelledz
  [sudo prompt error: z] - continuing without sudo
u´   â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”�uA   â”‚  ðŸ”� SUDO PASSWORD REQUIRED                              â”‚u´   â”œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”¤z                           u´   â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜)Útools.human_input_hooksr™   r   r   r   ÚsetÚtools.approval_human_waitr�   ÚoutcomeÚresetr@   re   rf   ÚtimeÚsleepÚprintr‰   r    ÚThreadr”   ÚstartÚsysÚstdoutr¤   r2   ÚEOFErrorr‡   )r–   rb   r™   Úhumanr   Ú_sudo_cbÚtokenr�   r0   rw   Úpassword_threadrt   s   &$          r   Ú_prompt_for_sudo_passwordr»   ¹   s)  € õ <á	˜V¨G×	4Õ	4¸ÝCÙ.Ó0ˆØÒÜ(×,Ñ,¨WÓ5ˆEð
2ÝGÙ&×(Õ(Ù'›z×/Ð/¨R�H÷ )ç.6¡
¸I�”Øô
 %×*Ñ*¨5Ô1÷ 
5Ò	4ð" ˜d F¨EÐ2ˆð-	9Ø14ŒB�J‰JÐ-Ñ.Ü�JŠJ�sŒOÜ�$—)‘)ØØ*ØEØ*ØQØSØ" ?Ð"3°>ÐBÀXÕMÐPUÕUØ*Øð
ó 
ô 
ô Ð)¨r¸Õ>Ü'×.Ò.Ô6KÐSYÐR[ÐdhÔiˆOØ×!Ñ!Ô#ÝCÙ"×$Õ$Ø×$Ñ$¨_Ð$Ô=÷ %à˜&—>”>ÜÐaÔbÜ—
‘
× Ñ Ô"Ø )�”Øô* �J‰J�N‰NÐ1°4Ô8÷ 
5Ñ	4ðV ˜jÕ)×/Ð/¨RˆHß*2™J¸	ˆEŒMçÜÐMÕNäÐCÔDÜ�J‰J×ÑÔØô �J‰J�N‰NÐ1°4Ô8÷ 
5Ò	4÷ )×(Ð(ûô ô Ø '�”Øä$×*Ñ*¨5Ô1÷ 
5Ñ	4ðûô %×*Ñ*¨5Õ1ú÷* %×$Ð$ûô  Ô+Ð,ô 	ÜÐAÔBÜ�J‰J×ÑÔØ'ˆEŒMØô �J‰J�N‰NÐ1°4Ô8÷ 
5Ñ	4ôr ô 	ÜÐ,¨Q¨CÐ/LÐMÔNÜ�J‰J×ÑÔØ#ˆEŒMÛä�J‰J�N‰NÐ1°4Ô8÷ 
5Ñ	4ûðr	ûô �J‰J�N‰NÐ1°4Õ8ú÷ 
5×	4Ð	4ús÷   ™'O'ÁI>ÁI*	Á(I>Á8
I>ÂO'Â"O'Â)B/K"ÅK	Å+K"Æ0K"Æ3 O'ÇK"Ç-
K"Ç8K"È	6K"È? O'É*I;É5	I>É>J1ÊJ4ÊO'Ê0J1Ê1J4Ê4KËO'ËKË	K"Ë"AN?Ì#OÌ$ O'ÍN?ÍN?Í4N:ÎOÎ O'Î:N?Î?OÏ"O$Ï$O'Ï'O8	c                ó0   € V ^8„  d   QhR\         R\        /# )r   r¹   r   rX   )r   s   "r   r   r     s   € ÷ =ñ =¤cð =¬dñ =r   c                óª   € RV 9  g   V P                  R4      '       d   R# V P                  R^4      w  r\        \        P                  ! RV4      4      # )zCReturn True when *token* is a leading shell environment assignment.Ú=Fz^[A-Za-z_][A-Za-z0-9_]*$)Ú
startswithÚsplitr;   ÚreÚmatch)r¹   ÚnameÚ_values   &  r   Ú_looks_like_env_assignmentrÅ     sF   € à
�%Ô˜5×+Ñ+¨C×0Ò0ÙØ—;‘;˜s AÓ&�L€DÜ”—’Ð4°dÓ;Ó<Ð<r   z-(?:'[^']*'?|"(?:\\.|[^"])*"?|\\.|[^\s;|&()])*c                ó^   € V ^8„  d   QhR\         R\        R\        \         \        3,          /# )r   rb   r³   r   )r   r—   Útuple)r   s   "r   r   r     s)   € ÷ #ñ #œsð #¬3ð #´5¼¼c¸µ?ñ #r   c                óT   € \         P                  W4      P                  4       pWV V3# )zERead one shell token, preserving quotes/escapes, starting at *start*.)Ú_SHELL_WORD_RErÂ   r£   )rb   r³   r£   s   && r   Ú_read_shell_tokenrÊ     s+   € ä
×
Ñ
˜wÓ
.×
2Ñ
2Ó
4€CØ˜Ð˜sÐ"Ð"r   c                óˆ   € V ^8„  d   QhR\         R\        R\        \        \         \        \        \        3,          ,          /# )r   rb   Ú
backgroundr   )r   r;   r   rÇ   r—   )r   s   "r   r   r     s6   € ÷ ,ñ ,œð ,¬$ð ,¼8ÄEÌ#ÌsÔTWÔY]ÐJ]ÕD^Õ;_ñ ,r   c              #  ó$  "  € ^ \        V 4      r2Rp^ ;rVV'       d   RMRpW#8  Edè   W,          pT;'       g    Tp	Tp
VP                  4       '       d&   V	'       d   RMRV^,           rËT;'       g    VR8H  pEM‹VR8X  d!   V P                  RV4      pRVR8X  d   TMTrËEMdV'       d"   VR8X  d   V^,           V8  d   RV^,           rËEM;V'       d   VR	9   d   R
\        W4      ^,          rËEMV'       dŽ   VR9   gH   VR8X  d2   V^,           V8  d$   W^,           ,          P                  4       '       g   VR8X  dH   V'       d@   \	        ^ WXR8H  ,           VR8H  ,
          4      pWhR8H  VR8H  ,
          ,          pRV^,           rËM‚V'       d   V	'       d   RV^,           rËMgV P                  Wr4      '       d   RV^,           RrLpMCVR9   d   RV^,           VR8g  rLpM,\        W4      w  rÜR
\        T;'       d    \        V4      4      rKW²WÊ3x € TpEKî  R# 5i)a™  Quote-aware shell scanner shared by the sudo and compound-background rewriters.

Yields ``(kind, start, end, at_command_start)`` events that tile *command* exactly:
``ws`` (one whitespace char), ``comment`` (``#`` up to, not including, the newline),
``op`` (``&& || ;; ; | & ( )``), ``word`` (one ``_read_shell_token`` token). Comments open at word boundaries.
Background mode (compound-background semantics) additionally emits ``escape`` for a bare ``\x``, ops ``&>``, ``{ `` and a closing
``}``, and tracks ``(...)``/``{ ... }`` depth: inside a group nothing is an operator, so
every non-structural char (whitespace included) surfaces as a single ``skip`` event.
TÚskipÚwsr   Ú#ÚcommentÚ\Úescapez'"Úwordz()Ú{Ú}Ú(Ú)Úopz;|&()N)ú&&ú||ú&>)rÚ   rÛ   z;;éÿÿÿÿ)ÚlenÚisspaceÚfindrÊ   Úmaxr¿   r;   rÅ   )rb   rÌ   ÚiÚnÚat_startÚparensÚbracesÚtwo_char_opsÚchÚgroupedÚ	was_startÚkindr£   r¹   s   &&            r   Ú_scan_shellrì     sÒ  é € ð Œc�'‹l€qØ€HØÐ€Fß)3Ñ%Ð9K€LØ
�%Ø�ZˆØ×"Ð"˜FˆØˆ	Ø�:‰:�<Š<ß#*™°°q¸1µu�#Ø×-Ð- 2¨¡:ŠHØ�3ŒYØ—,‘,˜t QÓ'ˆCØ!¨°¬¡A¸’#ß˜B $œJ¨1¨q­5°1¬9Ø  ! a¥%’#ß˜B %œKØÔ 1°'Ó =¸aÕ @’#ßØ�$ŒJ˜2 œ9¨¨Q­°¬°wÀ1½uµ~×7MÑ7M×7OÒ7OÐUWÐ[^ÔU^×ciä˜˜F¨C¡iÕ0°B¸#±IÕ>Ó?ˆFØ˜S‘y R¨3¡YÕ/Õ/ˆFØ˜a !�e‘#ßŸGØ  A¥‘#Ø×Ñ ×0Ò0Ø"&¨¨A­¨t�xˆD�xØ�7Œ]Ø"&¨¨A­¨r°S©y�xˆD�xä*¨7Ó6‰JˆEØ#¤T¨(×*XÐ*XÔ7QÐRWÓ7XÓ%Y�(Ø�sÐ%Ò%Ø‹ñ= ùs>   ‚5H¸HÁHÁAHÂ'(HÃ#HÃ4AHÅAHÆ	HÆA?Hc                óR   € V ^8„  d   QhR\         R\        \         \        3,          /# ©r   rb   r   )r   rÇ   r—   )r   s   "r   r   r   C  s"   € ÷ 8$ñ 8$¬Cð 8$´E¼#¼s¸(µOñ 8$r   c                óæ  aa€ . p^ pR;p;rE0 Rmp0 Rmp\        V 4       EF'  w  r‰r«W	V
 oVP                  S4       VR8X  g   VR8X  d   SR8X  d   R;p;rEVR8w  g   V'       g   V'       g   KO   \        P                  ! S4      p\        T4      ^8w  gA   \        ;QJ d    T3R lR 4       F  '       g   K   RM	  RM! T3R lR 4       4      '       d   RpKº  T^ ,          oT'       Ed    T'       d   RpKØ  T'       d   SR9   d   RpKë  T'       d   ST9   d   RpKþ  T'       d‹   ST9   g�   \        ;QJ d    T3R
 lT 4       F  '       g   K   RM	  RM! T3R
 lT 4       4      '       gA   \        ;QJ d    T3R lR 4       F  '       g   K   RM	  RM! T3R lR 4       4      '       d   EK�  T'       d   SP                  R	4      '       d   RpEK´  \        S4      '       d   RpEKÊ  M\        S4      '       d   EKß  SP                  R^4      R,          pTR8H  pTpTR8X  g   EK	  TR;;,          R,          uu&   T^,          pEK*  	  RP                  V4      V3#   \         d    Rp EKP  i ; i)zûRewrite literal sudo executable words, preserving their spelling and arguments.

Follow ordinary env options/assignments, not shell payloads or env split strings:
interpreting those requires a second parser and rewriting inside another quoting layer.
FrÙ   rÏ   r   rÔ   c              3   ó,   <"  € T F	  qS9   x € K  	  R # 5irH   r   )rI   ÚcharÚtexts   & €r   rK   Ú1_rewrite_real_sudo_invocations.<locals>.<genexpr>[  s   øé € Ð!I¹=°4¨$¦,»=ùrM   z$`*?[]~<>{}TÚ-c              3   ó„   <"  € T F5  qP                  R 4      '       g   K  SP                  VR,           4      x € K7  	  R# 5i)ú--r¾   N)r¿   ©rI   ÚoptrÔ   s   & €r   rK   ró   j  s.   øé € Ðd¹m°sÏ~É~Ð^b×OcÔ2˜Ÿ™¨¨c­	×2Ð2»mùs
   ƒA   A c              3   ór   <"  € T F,  pSP                  V4      ;'       d    \        S4      ^8„  x € K.  	  R# 5i)r   N)r¿   rÞ   r÷   s   & €r   rK   ró   k  s/   øé € Ð]ÑJ\À3˜Ÿ™¨Ó,×>Ð>´°T³¸Q±Ô>ÓJ\ùs   ƒ7 7Ú/Úenvrš   z	 -S -p ''r   >   ú-Cú-aú-uú--argv0ú--chdirú--unset>   ú-0ú-iú-vú--nullú--debugú--ignore-environment>   rô   rö   )rþ   rü   rý   rÝ   )rì   rˆ   ÚshlexrÀ   Ú
ValueErrorrÞ   rP   r¿   rÅ   Úrsplitr‰   )rb   ÚoutÚ
sudo_countÚin_envÚenv_operandÚenv_optionsÚvalue_optionsÚflag_optionsrë   r³   r£   rä   ÚwordsÚ
executablerò   rÔ   s   &             @@r   Ú_rewrite_real_sudo_invocationsr  C  s	  ù€ ð €CØ€JØ).Ð.€FÐ.ˆ[ÚG€MÚR€LÜ&1°'×&:Ñ"ˆ�SØ˜SÐ!ˆØ�
‰
�4ÔØ�4Œ<˜D DœL¨T°T¬\Ø16Ð6ˆFÐ6�[Ø�6Œ>§(¯fÙð	Ü—K’K Ó%ˆEô
 ˆu‹:˜Œ?Ÿc›cÔ!I¹=Ó!IŸcŸcšcÔ!I¹=Ó!I×IÒIØˆFÙØ�Q�xˆßˆ6ßØ#�Ùß˜t {Ô2Ø#�Ùß˜t }Ô4Ø"�Ùß ¨Ô 4ß“CÔd¹mÓd—C—C’CÔd¹mÓd×dÒdß“CÔ]ÑJ\Ó]—C—C’CÔ]ÑJ\Ó]×]Ò]Úß˜tŸ™¨s×3Ò3Ø�ÚÜ)¨$×/Ò/Ø#�Úð 0ô (¨×-Ò-ÚØ—[‘[  aÓ(¨Õ,ˆ
Ø˜uÑ$ˆØˆØ˜×Ø��G�{Õ"‹GØ˜!�O‹JñY ';ðZ �7‰7�3‹<˜Ð#Ð#øôI ô 	ØˆFÛð	ús   Á/IÉI0É/I0c                ó0   € V ^8„  d   QhR\         R\        /# rî   )r   r—   )r   s   "r   r   r   ~  s   € ÷ 6ñ 6¬#ð 6´#ñ 6r   c                ó&   € \        V 4      ^,          # )z<Return how many real sudo command words appear in *command*.)r  )rb   s   &r   rg   rg   ~  s   € ä)¨'Ó2°1Õ5Ð5r   c                ó0   € V ^8„  d   QhR\         R\         /# rî   r   )r   s   "r   r   r   ƒ  s   € ÷ 4ñ 4¬#ð 4´#ñ 4r   c                ó:  € Rp. p\        V RR7       F¶  w  r4rVWV pVR8X  d   VR9   d   TpK  VR8X  d   VR8X  g   VR8X  d   VR9   d   RpK<  VR8X  g   KE  VR8X  g   KN  V^,
          pV^ 8¼  d(   W,          P                  4       '       d   V^,          pK.  V^ 8¼  d   W,          R9   d   K›  V^ 8¼  d   VP                  W34       RpK¸  	  T p	\        V4       F¾  w  rTpWº8  d(   W›,          P                  4       '       d   V^,          pK-  Wš^,           R pVP	                  R	4      p\        V4      ;'       d&    V^ ,          R
9  ;'       g    VP                  R4      pV'       d   RMRpV	RV R,           W›V
 ,           R,           V,           V,           p	KÀ  	  V	# )uU  Wrap `A && B &` (or `A || B &`) to `A && { B & }` at depth 0. Bash binds `&&` tighter
than `&`, so `A && B &` backgrounds a subshell that runs B in the foreground and waits for
it; a long-running B leaves that subshell stuck in ``wait4`` forever, and its open stdout
pipe can keep the terminal tool from returning. The brace group keeps `&&`'s
skip-B-on-failure semantics without a fork: bash backgrounds B as a simple command and
exits immediately, orphaning B normally. Redirects (``&>``, ``2>&1``), quoted strings,
comments and ``(...)``/``{ ... }`` bodies never count as the backgrounding ``&`` (see
``_scan_shell``); tracking brace depth also makes the rewrite idempotent. `(...)` subshells
have the same bug class but are not the common agent pattern; left for a follow-up.
Simple ``cmd &`` is left alone â€” it doesn't have the subshell-wait bug.T)rÌ   rÙ   rÏ   r   Ú&z<>Nz 	z;
&|)}rÜ   z ;r   z{ z& }rÝ   )rÚ   rÛ   )Ú;Ú|rÖ   )rì   rß   rˆ   ÚreversedÚlstripr;   r¿   )rb   Ú	chain_endÚrewritesrë   r³   r£   Ú_rò   Újrw   Úamp_posÚ
insert_posÚsuffixÚtailÚneeds_separatorÚ	separators   &               r   Ú_rewrite_compound_backgroundr(  ƒ  s�  € ð €IØ&(€HÜ*¨7¸t×DÑˆ�SØ˜SÐ!ˆØ�4Œ<˜D LÔ0ØŠIØ�TŒ\˜d dœl¨d°d¬l¸tÀÔ?VàŠIØ�TŽ\˜d cžkð ˜•	ˆAØ�q”&˜W�Z×/Ñ/×1Ò1Ø�Q•’Ø�AŒv˜'�*¨Ô,ÙØ˜AŒ~Ø—‘ Ð 2Ô3ØŠIñ#  Eð( €FÜ& xÖ0Ñˆ	ð ˆ
ØÔ" vÕ'9×'AÑ'A×'CÒ'CØ˜!�OŠJð  !�˜Ð&ˆØ�}‰}˜UÓ#ˆÜ˜t›*×\Ð\¨$¨q­'¸Ñ*B×*[Ð*[ÀdÇoÁoÐVZÓF[ˆß+‘D°ˆ	Ø˜˜Ð$ tÕ+¨fÀÐ.HÕHÈ5ÕPÐS\Õ\Ð_eÕeŠñ# 1ð$ €Mr   c                ó$   € V ^8„  d   QhR\         /# r
   r:   )r   s   "r   r   r   º  s   € ÷ Pñ P”tñ Pr   c                 ó@   € ^ RI Hp  \        4       ;'       g    V ! 4       # )zÍA delegated child or a `hermes chat -q` run: nobody can answer a sudo prompt. Single-query only
(not _no_user_can_answer): cron strips HERMES_INTERACTIVE and unattended platforms register no sudo callback.©Ú!_is_single_query_approval_context)Útools.approval_contextr,  rA   r+  s    r   rO   rO   º  s   € õ IÜ&Ó(×OÐOÑ,MÓ,OÐOr   c          	      ó°   € V ^8„  d   QhR\         R,          R\        . \        3,          R,          R\        \         R,          \         R,          3,          /# )r   rb   NÚsudo_nopasswd_checkr   )r   r   r;   rÇ   )r   s   "r   r   r   Á  sJ   € ÷ 4ñ 4Ü�4�Zð4ä! "¤d (Õ+¨dÕ2ð4ô Œ3��:”s˜T•zÐ!Õ"ñ4r   c                óB  € ^ RI Hp V f   R# \        V 4      w  r4V^ 8X  d   V R3#  ^ RIHp V! R4      pVRJpV'       d   TM	\        4       p\        R4      ;'       g    V! 4       RJ;'       d    \        4       '       * p	V'       gF   V'       g>   V	'       d6   Ve   V! 4       '       d   V R3# \        ^-V R7      pV'       d   \        V4       V'       g	   V'       d   W8R,           V,          3# V R3#   \
         d#    \        P                  P                  R4      p Léi ; i)	aÓ  Rewrite command-position ``sudo`` executables to ``sudo -S -p ''`` when a password is available (shared by every
execution environment). Returns ``(command, sudo_stdin)``: ``sudo_stdin`` is one password
line per sudo invocation that the caller must PREPEND to the process stdin (sudo -S consumes
exactly one line and passes the rest through, so it's safe alongside the caller's own
stdin_data). Backends transport that merged stream according to their execution API
(pipe, SDK stdin, or staged file). With no password available the command is
returned unchanged and ``sudo_stdin`` is None, so it fails gracefully with "sudo: a password
is required". Password sources, in order: configured SUDO_PASSWORD, the session cache, then
an interactive prompt (45s timeout, cached on success) when a UI is reachable.
``sudo_nopasswd_check`` (supplied by ``BaseEnvironment``) runs ``sudo -n true`` inside the
selected backend; a True result skips the prompt and the ``-S`` rewrite entirely.rœ   N)Ú
get_secretrd   ÚHERMES_INTERACTIVE)r–   rb   r   )NN)r   r   r  Úagent.secret_scoper1  r@   re   rf   r   r.   r   rO   r»   r3   )
rb   r/  r   Útransformedr  r1  Ú_configured_passwordÚhas_configured_passwordÚsudo_passwordÚshould_prompt_for_sudos
   &&        r   Ú_transform_sudo_commandr9  Á  s  € õ @Ø‚ØÐÜ<¸WÓEÑ€KØ�Q„Ø˜ˆ}Ðð?Ý1Ù)¨/Ó:Ðð 3¸$Ð>Ðß,CÑ(ÔIbÓId€Mô 	Ð,Ó-×ZÐZÑ1LÓ1NÐVZÐ1Z÷ð ä‹oÔ
ð ÷ #¯=×=Sð
 Ò*Ñ/B×/DÒ/DØ˜D�=Ð Ü1À"ÈgÔVˆßÜ% mÔ4ç§-à¨TÕ1°ZÕ?Ð?Ð?Ø�Dˆ=Ðøô3 ô ?Ü!Ÿz™zŸ~™~¨oÓ>Òð?ús   ¦C1 Ã1*DÄDc                ó    € V ^8„  d   Qh/ ^ \         9   d   \        \        \        3,          ;R&   ^\         9   d   \        \        ,          ;R&   # )r   r,   r   )Ú__conditional_annotations__rx   r   r   )r   s   "r   r   r      sA   € ÷ Rñ R÷4 *Ò )”dœ3¤˜8•nÑ )ñ5R÷< VÒ U”j¤•oÑ Uò=Rr   )zsudo: a password is requiredzsudo: no tty presentzsudo: a terminal is required)zsudo: authentication failedz sudo: incorrect password attemptz1sudo: maximum 3 incorrect authentication attemptsz#sudo: 3 incorrect password attempts)é-   )FrH   )2r;  Ú__doc__Úloggingre   rƒ   rÁ   r  Ú
subprocessr´   r    r¯   Úcollections.abcr   r   Úcontextvarsr   Úutilsr   Ú	getLoggerrn   r,   ÚLockr+   r   r   r(   r.   r3   r8   rA   rQ   rV   r_   r`   rh   ru   r”   r»   rÅ   ÚcompileÚDOTALLrÉ   rÊ   rì   r  rg   r(  rO   r9  r   )r;  s   @r   Ú<module>rG     s  øðöRó Û 	Û Û 	Û Û Û 
Û Û ß .Ý "å !ð 
×	Ò	Ð0Ó	1€ð
 (*Ð Ó )Ø%ŸNšNÓ,Ð ñ )3Ð3HÐRTÔ(UÐ Ó Uõ&õ
&õ 3õ2õ%õ
ð sÐ õ}ð$ Ð õMõõ6õ ñ:E9È2÷ E9ð E9õP=ð —’ÐPÐRT×R[ÑR[Ó\€õ#÷,õ^8$õv6õ
4õnP÷4ñ 4r   