Ë
    ãß²jB  ã            	       ó6  — d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
 ddlmZ ddlmZmZ ddlmZ ddlmZmZmZmZmZ ddlmZmZmZmZmZmZ  ej>                  e «      Z!ejD                  d	k7  Z#eZ$dd„Z%dde&de&de&d
efd„Z' G d„ de«      Z(y)zKSSH remote execution environment with ControlMaster connection persistence.é    N)ÚPath)ÚIterable)ÚBaseEnvironmentÚEnvironmentConnectionError)Ú_popen_bash)ÚFileSyncManagerÚiter_sync_filesÚquoted_mkdir_commandÚquoted_rm_commandÚunique_parent_dirs)Ú	bash_argvÚclient_env_withÚload_hermes_env_varsÚprepend_unsetÚresolve_passthrough_envÚrun_captureÚntÚreturnc                  ót   — dD ]3  } t        j                  | «      rŒt        | j                  «       › d�«      ‚ y)z@Fail fast with a clear error when the SSH client is unavailable.)ÚsshÚscpzT is not installed or not in PATH. Install OpenSSH client: apt install openssh-clientN)ÚshutilÚwhichÚRuntimeErrorÚupper)Útools    ú;/home/ubuntu/.hermes/hermes-agent/tools/environments/ssh.pyÚ_ensure_ssh_availabler       sD   € àò UˆÜ�|‰|˜DÕ!Ü $§*¡*£, ð 0Tð  Tó Uð UñUó    ÚreasonÚsubjectÚwhatc                 ó(   — t        | |› d|› d�¬«      S )Nu    failed â€” verify z is healthy, then retry.©Ú
retry_hint)r   )r    r!   r"   s      r   Ú_sync_errorr&   (   s%   € Ü%Ø˜g˜YÐ&9¸$¸Ð?WÐXôZð Zr   c                   ó´  ‡ — e Zd ZdZdZdZ	 	 	 d/dededededed	ed
efˆ fd„Z	de
edf   defd„Zdee   fd„Zdedefd„Zd0dedz  dee   defd„Zdededej(                  fd„Zdededededdf
d„Zd„ Zdefd„Zd1d„Zdededdfd „Zd!ee
eef      ddfd"„Zd#eddfd$„Zd%ee   ddfd&„Zd1d'„Zdd(dd)œd*ed+eded,edz  dej>                  f
d-„Z d.„ Z!ˆ xZ"S )2ÚSSHEnvironmenta  Run commands on a remote machine over SSH.

    Spawn-per-call: every execute() spawns a fresh ``ssh ... bash -c`` process.
    Session snapshot preserves env vars across calls; CWD persists via in-band
    stdout markers. Uses SSH ControlMaster for connection reuse.
    TFÚhostÚuserÚcwdÚtimeoutÚportÚkey_pathÚ
probe_onlyc                 ó&  •‡ — t         ‰
‰ �  ||¬«       ||||f\  ‰ _        ‰ _        ‰ _        ‰ _        t        t        j                  «       «      dz  ‰ _	        ‰ j                  j                  dd¬«       |› d|› d|› �}|r|› d‰ j                  › �}t        j                  |j                  «       «      j                  «       d d }	‰ j                  |	› d	�z  ‰ _        t#        «        ‰ j%                  «        |rd ‰ _        y ‰ j)                  «       ‰ _        ‰ j-                  «        t/        ˆ fd
„‰ j0                  ‰ j2                  ‰ j4                  ‰ j6                  ¬«      ‰ _        ‰ j&                  j9                  d¬«       ‰ j;                  «        y )N)r+   r,   z
hermes-sshT)ÚparentsÚexist_okú@ú:z:probe:é   ú.sockc                  ó4   •— t        ‰ j                  › d�«      S )Nú/.hermes)r	   Ú_remote_home©Úselfs   €r   ú<lambda>z)SSHEnvironment.__init__.<locals>.<lambda>R   s   ø€ ¤°D×4EÑ4EÐ3FÀhÐ1OÓ!P€ r   )Úget_files_fnÚ	upload_fnÚ	delete_fnÚbulk_upload_fnÚbulk_download_fn)Úforce)ÚsuperÚ__init__r)   r*   r-   r.   r   ÚtempfileÚ
gettempdirÚcontrol_dirÚmkdirÚ_session_idÚhashlibÚsha256ÚencodeÚ	hexdigestÚcontrol_socketr   Ú_establish_connectionÚ_sync_managerÚ_detect_remote_homer9   Ú_ensure_remote_dirsr   Ú_scp_uploadÚ_ssh_deleteÚ_ssh_bulk_uploadÚ_ssh_bulk_downloadÚsyncÚinit_session)r;   r)   r*   r+   r,   r-   r.   r/   Ú
socket_keyÚ
_socket_idÚ	__class__s   `         €r   rD   zSSHEnvironment.__init__:   sr  ù€ ô 	‰Ñ˜S¨'ÐÔ2Ø9=¸tÀTÈ8Ð9SÑ6ˆŒ	�4”9˜dœi¨¬Ü¤× 3Ñ 3Ó 5Ó6¸ÑEˆÔØ×Ñ×Ñ t°dÐÔ;ð
 �v˜Q˜t˜f A d VÐ,ˆ
ÙØ&˜< w¨t×/?Ñ/?Ð.@ÐAˆJÜ—^‘^ J×$5Ñ$5Ó$7Ó8×BÑBÓDÀSÀbÐIˆ
Ø"×.Ñ.°J°<¸uÐ1EÑEˆÔÜÔØ×"Ñ"Ô$ÙØ!%ˆDÔØØ ×4Ñ4Ó6ˆÔØ× Ñ Ô"Ü,ÛPØ×&Ñ&°$×2BÑ2BØ×0Ñ0À4×CZÑCZô\ˆÔð 	×Ñ×Ñ dÐÔ+Ø×ÑÕr   Úsend_env.r   c                 ó   — t        | j                  «      }|s|S t        j                  dj	                  |«      j                  «       «      j                  «       dd }|j                  |j                  dd › |› d�«      S )a  One ControlMaster per SendEnv name-set, beside the plain target socket: a mux master only
        relays the env names it was itself started with and silently drops the rest, so a passthrough
        command must ride a master that knows its names. scp/sync/probes keep the plain socket.Ú Né   r6   )	r   rN   rJ   rK   ÚjoinrL   rM   Ú	with_nameÚstem)r;   r\   ÚplainÚdigests       r   Ú_control_socket_forz"SSHEnvironment._control_socket_forX   ss   € ô �T×(Ñ(Ó)ˆÙØˆLô —‘ §¡¨Ó 2× 9Ñ 9Ó ;Ó<×FÑFÓHÈÈ!ÐLˆØ�‰ %§*¡*¨R¨a .Ð!1°&°¸Ð?Ó@Ð@r   c                 óê   ‡— t        | j                  «      Š‰j                  j                  «       r4t	        ‰j                  j                  ‰j                  dd › d�«      «      ng }‰gˆfd„|D «       ¢S )zNThe plain socket plus every SendEnv-set sibling (shared 8-char target prefix).Nr_   z*.sockc              3   ó.   •K  — | ]  }|‰k7  sŒ	|–— Œ y ­w©N© )Ú.0Úsrc   s     €r   ú	<genexpr>z2SSHEnvironment._control_sockets.<locals>.<genexpr>h   s   øè ø€ Ò;˜q°°U³
œÑ;ùs   ƒ
Ž)r   rN   ÚparentÚis_dirÚsortedÚglobrb   )r;   Úsiblingsrc   s     @r   Ú_control_socketszSSHEnvironment._control_socketsd   sd   ø€ ä�T×(Ñ(Ó)ˆØKPÏ<É<×K^ÑK^ÔK`”6˜%Ÿ,™,×+Ñ+¨u¯z©z¸"¸1¨~Ð.>¸fÐ,EÓFÔGÐfhˆØÐ<Ó; HÔ;Ð<Ð<r   Ú	port_flagc                 ó”   — | j                   dk7  r|t        | j                   «      gng }|| j                  rd| j                  gz   S g z   S )z7Port/key flags shared by ssh (``-p``) and scp (``-P``).é   z-i)r-   Ústrr.   )r;   rs   Úflagss      r   Ú_target_flagszSSHEnvironment._target_flagsj   sB   € à/3¯y©y¸Bª�œC §	¡	›NÑ+ÀBˆØ°·²˜˜tŸ}™}Ð-ÑGÐGÀBÑGÐGr   NÚ
extra_argsc                 ó¦  — t        t        |«      «      }dg}t        r)|j                  dd| j	                  |«      › �ddddg«       |j                  g d¢«       |j                  d„ |D «       «       |j                  | j                  d«      «       |j                  |xs g «       |j                  | j                  › d	| j                  › �«       |S )
Nr   ú-oúControlPath=zControlMaster=autozControlPersist=300)r{   zBatchMode=yesr{   z StrictHostKeyChecking=accept-newr{   zConnectTimeout=10c              3   ó8   K  — | ]  }d d|› �fD ]  }|–— Œ Œ y­w)r{   zSendEnv=Nri   )rj   ÚnameÚargs      r   rl   z4SSHEnvironment._build_ssh_command.<locals>.<genexpr>w   s(   è ø€ ÒQ˜4¸ÀÈÈÐ>OÐ7PÒQ°”3ÐQ�3ÑQùs   ‚z-pr3   )	Útuplero   Ú_SSH_MULTIPLEXÚextendre   rx   Úappendr*   r)   )r;   ry   r\   Úcmds       r   Ú_build_ssh_commandz!SSHEnvironment._build_ssh_commando   s»   € Üœ Ó)Ó*ˆØˆgˆÝØ�J‰J˜ ¨T×-EÑ-EÀhÓ-OÐ,PÐQØÐ2°DÐ:NðPô Qà�
‰
ÒoÔpà�
‰
ÑQ 8ÔQÔQØ�
‰
�4×%Ñ% dÓ+Ô,Ø�
‰
�:Ò# Ô$Ø�
‰
�d—i‘i�[  $§)¡) Ð-Ô.Øˆ
r   Ú
remote_cmdc                 ó@   — t        | j                  «       |gz   |¬«      S )zORun one remote shell command over the multiplexed connection, capturing output.©r,   )r   r…   )r;   r†   r,   s      r   Ú_run_sshzSSHEnvironment._run_ssh}   s   € ä˜4×2Ñ2Ó4¸
°|ÑCÈWÔUÐUr   r    r!   c                 óš   — | j                  ||¬«      }|j                  dk7  r)t        |› d|j                  j	                  «       › �|«      ‚y )Nrˆ   r   z: )r‰   Ú
returncoder&   ÚstderrÚstrip)r;   r†   r,   r    r!   Úresults         r   Ú_run_ssh_checkedzSSHEnvironment._run_ssh_checked�   sM   € Ø—‘˜z°7�Ó;ˆØ×Ñ Ò!Ü  ¨¨6¯=©=×+>Ñ+>Ó+@Ð*AÐBÀGÓLÐLð "r   c           
      óÚ  — 	 | j                  dd¬«      }|j                  dk7  rn|j                  j                  «       xs |j                  j                  «       }t        d|› �d| j
                  › d| j                  › d| j                  › d�¬
«      ‚y # t        j                  $ rD t        d| j                  › d| j
                  › d�d| j
                  › d| j                  › d	�¬
«      ‚w xY w)Nz!echo 'SSH connection established'é   rˆ   zSSH connection to r3   z
 timed outzCheck that z is up and reachable on port z& and that sshd is running, then retry.r$   r   zSSH connection failed: z  is up, sshd is running on port z, and uc    can log in with the configured key, then retry â€” the connection is re-established automatically.)r‰   Ú
subprocessÚTimeoutExpiredr   r*   r)   r-   r‹   rŒ   r�   Ústdout)r;   rŽ   Ú	error_msgs      r   rO   z$SSHEnvironment._establish_connection†   s	  € ð	FØ—]‘]Ð#FÐPR�]ÓSˆFð ×Ñ Ò!ØŸ™×+Ñ+Ó-ÒF°·±×1DÑ1DÓ1FˆIÜ,Ø)¨)¨Ð5Ø)¨$¯)©)¨Ð4TÐUY×U^ÑU^ÐT_Ð_eØ#Ÿy™y˜kð *NðNôPð Pð "øô ×(Ñ(ò 	FÜ,Ø$ T§Y¡Y K¨q°·±°¸:ÐFØ)¨$¯)©)¨Ð4QÐRV×R[ÑR[ÐQ\ð ]Dð DôFð Fð	Fús   ‚B ÂAC*c                 ó¸  — t        j                  t        «      5  | j                  dd¬«      }|j                  dk(  rk|j
                  j                  «       rQt        j                  d|j
                  j                  «       «       |j
                  j                  «       cddd«       S ddd«       | j                  dk(  rdS d	| j                  › �S # 1 sw Y   Œ)xY w)
z(Detect the remote user's home directory.z
echo $HOMEé
   rˆ   r   zSSH: remote home = %sNÚrootz/rootz/home/)
Ú
contextlibÚsuppressÚ	Exceptionr‰   r‹   r”   r�   ÚloggerÚdebugr*   )r;   rŽ   s     r   rQ   z"SSHEnvironment._detect_remote_home–   s­   € ä× Ñ ¤Ó+ñ 	-Ø—]‘] <¸�]Ó<ˆFØ× Ñ  AÒ%¨&¯-©-×*=Ñ*=Ô*?Ü—‘Ð4°f·m±m×6IÑ6IÓ6KÔLØ—}‘}×*Ñ*Ó,÷		-÷ 	-ñ 	-ð
 Ÿ)™) vÒ-ˆwÐG°V¸D¿I¹I¸;Ð3GÐG÷	-ð 	-ús   šBCÃCc           	      ót   — | j                   › d�}| j                  t        ||› d�|› d�|› d�g«      d¬«       y)z?Create base ~/.hermes directory tree on remote in one SSH call.r8   z/skillsz/credentialsz/cacher—   rˆ   N)r9   r‰   r
   )r;   Úbases     r   rR   z"SSHEnvironment._ensure_remote_dirsŸ   sR   € à×#Ñ#Ð$ HÐ-ˆØ�‰Ô*¨D°T°F¸'Ð2BÀtÀfÈLÐDYÐ^bÐ]cÐciÐ[jÐ+kÓlØ ð 	õ 	"r   Ú	host_pathÚremote_pathc           
      óì  — | j                  dt        j                  t        t	        |«      j
                  «      «      › �d¬«       dgt        rdd| j                  › �gng z   }|| j                  d«      || j                  › d| j                  › d	|› �gz   z  }t        |d
¬«      }|j                  dk7  rAt        d|j                  j                  «       › �d| j                  › d| j                  › �«      ‚y)z0Upload a single file via scp over ControlMaster.z	mkdir -p r—   rˆ   r   r{   r|   z-Pr3   r4   é   r   zscp failed: zFile sync to N)r‰   ÚshlexÚquoterv   r   rm   r�   rN   rx   r*   r)   r   r‹   r&   rŒ   r�   )r;   r    r¡   Úscp_cmdrŽ   s        r   rS   zSSHEnvironment._scp_upload¥   sò   € à�‰˜	¤%§+¡+¬c´$°{Ó2C×2JÑ2JÓ.KÓ"LÐ!MÐNÐXZˆÔ[Ø�'Í^˜d l°4×3FÑ3FÐ2GÐ$HÑIÐacÑdˆØ�4×%Ñ% dÓ+¨y¸T¿Y¹Y¸KÀqÈÏÉÈÐSTÐU`ÐTaÐ:bÐ.cÑcÑcˆÜ˜W¨bÔ1ˆØ×Ñ Ò!Ü ¨V¯]©]×-@Ñ-@Ó-BÐ,CÐDÈÐVZ×V_ÑV_ÐU`Ð`aÐbf×bkÑbkÐalÐFmÓnÐnð "r   Úfilesc           	      ój  — |sy| j                   › d�}t        |«      }|r*| j                  t        |«      ddd| j                  › �«       t        j                  d¬«      5 }|D ]Õ  \  }}	 t        j                  j                  ||«      }|d
k(  s|j                  d«      rt        d|›d|›�«      ‚t        j                  j                  ||«      }	t        j                  t        j                  j                  |	«      d¬«       	 t        j                   t        j                  j#                  |«      |	«       Œ× | j-                  «       dt/        j0                  |«      › �gz   }t3        j4                  dddd|d
gt2        j6                  t2        j8                  t2        j8                  ¬«      }	 t3        j4                  ||j:                  t2        j8                  t2        j8                  ¬«      }|j:                  jC                  «        	 |jE                  d¬«      \  }}|jG                  «       €|jE                  d¬«      \  }}n(|jH                  r|jH                  jK                  «       nd}|jP                  dk7  r9t        d |jP                  › d!|jS                  d"¬#«      jU                  «       › �«      ‚|jP                  dk7  rItW        d$|jP                  › d!|jS                  d"¬#«      jU                  «       › �d%| j                  › �d&¬'«      ‚	 ddd«       tX        j[                  d(t]        |«      «       y# t        $ r}t        d|›d	|›�«      |‚d}~ww xY w# t$        $ r2}
t'        |
dd«      dk7  r‚ t)        j*                  ||	«       Y d}
~
�Œ+d}
~
ww xY w# t<        $ r" |j?                  «        |jA                  «        ‚ w xY w# t2        jL                  $ rN ||fD ]  }|j?                  «        Œ ||fD ]  }|jA                  «        Œ tO        dd| j                  › d�¬«      ‚w xY w# 1 sw Y   �ŒxY w))z Upload many files in one tar-over-SSH stream: local ``tar c`` piped through one SSH
        connection to remote ``tar x``, after a single batched ``mkdir -p``.Nr8   r£   zremote mkdir failedzRemote directory setup on zhermes-ssh-bulk-)Úprefixzremote path z is not under sync base ú.z../z escapes sync base T)r2   Úwinerrori"  ztar xf - --no-overwrite-dir -C Útarz-chfÚ-z-C)Ústdinr”   rŒ   éx   rˆ   r—   r   zSSH bulk upload timed outzBulk file sync to u.    timed out â€” check the connection and retry.r$   r   ztar create failed (rc=z): Úreplace©Úerrorsz tar extract over SSH failed (rc=zFile sync over SSH to zthe connection)r"   z*SSH: bulk-uploaded %d file(s) via tar pipe)/r9   r   r�   r
   r)   rE   ÚTemporaryDirectoryÚosÚpathÚrelpathÚ
ValueErrorr   Ú
startswithr`   ÚmakedirsÚdirnameÚsymlinkÚabspathÚOSErrorÚgetattrr   Úcopy2r…   r¤   r¥   r’   ÚPopenÚDEVNULLÚPIPEr”   r›   ÚkillÚwaitÚcloseÚcommunicateÚpollrŒ   Úreadr“   r   r‹   Údecoder�   r&   rœ   r�   Úlen)r;   r§   rŸ   r1   Ústagingr    r¡   Ú
rel_remoteÚexcÚstagedÚeÚssh_cmdÚtar_procÚssh_procÚ_Ú
ssh_stderrÚtar_stderr_rawÚprocs                     r   rU   zSSHEnvironment._ssh_bulk_upload®   s  € ñ ØØ×#Ñ#Ð$ HÐ-ˆÜ$ UÓ+ˆÙØ×!Ñ!Ô"6°wÓ"?ÀÐEZØ$>¸t¿y¹y¸kÐ"JôLô ×(Ñ(Ð0BÔCð 3	_ÀwØ*/ò 4Ñ&�	˜;ðpÜ!#§¡§¡°¸dÓ!C�Jð  Ò$¨
×(=Ñ(=¸eÔ(DÜ&¨°k°_ÐDWÐX\ÐW_Ð'`ÓaÐaÜŸ™Ÿ™ g¨zÓ:�Ü—‘œBŸG™GŸO™O¨FÓ3¸dÕCð4Ü—J‘JœrŸw™wŸ™¨yÓ9¸6ÕBð4ð$ ×-Ñ-Ó/Ð5TÔUZ×U`ÑU`ÐaeÓUfÐTgÐ3hÐ2iÑiˆGÜ!×'Ñ'¨°¸¸TÀ7ÈCÐ(PÔXb×XjÑXjÜ/9¯©ÄzÇÁôXˆHðÜ%×+Ñ+¨G¸8¿?¹?Ü3=·?±?Ì:Ï?É?ô\�ð �O‰O×!Ñ!Ô#ðoØ (× 4Ñ 4¸SÐ 4Ó A‘��:à—=‘=“?Ð*Ø(0×(<Ñ(<ÀRÐ(<Ó(HÑ%�A‘~à?G¿º X§_¡_×%9Ñ%9Ô%;ÐTW�Nð ×"Ñ" aÒ'Ü"Ð%;¸H×<OÑ<OÐ;PÐPSØ&4×&;Ñ&;À9Ð&;Ó&M×&SÑ&SÓ&UÐ%Vð$Xó Yð Yà×"Ñ" aÒ'Ü!Ð$DÀX×EXÑEXÐDYÐY\Ø%/×%6Ñ%6¸iÐ%6Ó%H×%NÑ%NÓ%PÐ$Qð#Sà$:¸4¿9¹9¸+Ð"FÐM]ô_ð _ð (÷a3	_ôh 	�‰ÐAÄ3ÀuÃ:ÕNøôa "ò pÜ&¨°k°_ÐD\Ð]aÐ\dÐ'eÓfÐloÐoûðpûô ò 4Ü˜q *¨dÓ3°tÒ;ØÜ—L‘L ¨F×3Ò3ûð4ûô ò Ø—‘”Ø—‘”Øðûô ×,Ñ,ò oØ% xÐ0ò  �DØ—I‘I•Kð à% xÐ0ò  �DØ—I‘I•Kð ä0Ø/Ø!3°D·I±I°;Ð>lÐmôoð oðoú÷K3	_ñ 3	_ús�   Á 	P(Á* L5Â
A;P(Ä3MÄ9A5P(Æ/?NÇ.P(È	A#OÉ,B P(Ì5	MÌ>MÍMÍP(Í	NÍ!'NÎP(ÎNÎP(Î+OÏP(ÏA!P%Ð%P(Ð(P2Údestc                 ó¸  — | j                   › d�j                  d«      }| j                  «       dt        j                  |«      › �gz   }t        |d«      5 }t        j                  |t        j                  |t        j                  d¬«      }ddd«       j                  dk7  r§|j                  j                  d	¬
«      j                  «       }|j                  «       D �cg c]  }|j                  «       sŒ|‘Œ }}|j                  dk(  xr t        |«      xr t!        d„ |D «       «      }	|	st#        d|› �d| j$                  › �«      ‚yy# 1 sw Y   ŒÀxY wc c}w )z*Download remote .hermes/ as a tar archive.r8   ú/z!tar cf - --exclude='*.sock' -C / Úwbr¯   )r®   r”   rŒ   r,   Nr   r°   r±   é   c              3   ó>   K  — | ]  }|j                  d «      –— Œ y­w)z: socket ignoredN)Úendswith)rj   Úlines     r   rl   z4SSHEnvironment._ssh_bulk_download.<locals>.<genexpr>  s#   è ø€ ò RPØ6:�—‘Ð0×1ñRPùs   ‚zSSH bulk download failed: zFile sync from )r9   Úlstripr…   r¤   r¥   Úopenr’   ÚrunrÁ   rÂ   r‹   rŒ   rÉ   r�   Ú
splitlinesÚboolÚallr&   r)   )
r;   r×   Úrel_baserÐ   ÚfrŽ   rŒ   rÞ   Údiagnostic_linesÚ	tolerateds
             r   rV   z!SSHEnvironment._ssh_bulk_downloadò   sg  € ð ×'Ñ'Ð(¨Ð1×8Ñ8¸Ó=ˆð ×)Ñ)Ó+Ø/´·±¸HÓ0EÐ/FÐGð/Iñ Iˆä�$˜Óð 	v Ü—^‘^ G´:×3EÑ3EÈaÔXb×XgÑXgÐqtÔuˆF÷	và×Ñ Ò!Ø—]‘]×)Ñ)°Ð)Ó;×AÑAÓCˆFð 28×1BÑ1BÓ1DÖU¨ÈÏ
É
Í¢ÐUÐÐUØ×)Ñ)¨QÑ.ò P´4Ð8HÓ3Iò PÌcñ RPØ>NôRPó OPˆIáÜ!Ð$>¸v¸hÐ"GØ$3°D·I±I°;Ð"?óAð Að ð "÷	vð 	vüò  Vs   Á7EÃEÃ5EÅEÚremote_pathsc                 óX   — | j                  t        |«      ddd| j                  › �«       y )Nr—   zremote rm failedzRemote file cleanup on )r�   r   r)   )r;   ré   s     r   rT   zSSHEnvironment._ssh_delete
  s,   € Ø×ÑÔ/°Ó=¸rÐCUØ 7¸¿	¹	°{ÐCõ	Er   c                 óR   — | j                   �| j                   j                  «        y y rh   )rP   rW   r:   s    r   Ú_before_executezSSHEnvironment._before_execute  s%   € Ø×ÑÐ)Ø×Ñ×#Ñ#Õ%ð *r   r¯   )Úloginr,   Ú
stdin_dataÚ
cmd_stringrí   rî   c          	      óî   — t        t        ¬«      \  }}| j                  |¬«      t        t	        j
                  t        ||«      «      |«      z   }t        |«      }|�t        |||¬«      S t        ||«      S )aË  Forward the passthrough allowlist (skill ``required_environment_variables`` +
        ``terminal.env_passthrough``) the way docker does: ``SendEnv`` carries the names, the ssh
        client's env carries the values, so secrets never enter the remote ``bash -c`` argv. The
        remote sshd must ``AcceptEnv`` them (#14091). Profile-scoped names missing from the active
        scope are unset remotely so a shared host cannot serve another profile's value.)Úhermes_env_loader)r\   )Úenv)	r   Ú_load_hermes_env_varsr…   r   r¤   r¥   r   r   r   )	r;   rï   rí   r,   rî   ÚvaluesÚunset_namesr„   Ú
client_envs	            r   Ú	_run_bashzSSHEnvironment._run_bash  ss   € ô 6ÔH]Ô^Ñˆ�Ø×%Ñ%¨vÐ%Ó6¼Ä5Ç;Á;Ì}Ð]gÐitÓOuÓCvÐx}Ó9~Ñ~ˆÜ$ VÓ,ˆ
Ø?IÐ?UŒ{˜3 
°
Ô;ÐwÔ[fÐgjÐlvÓ[wÐwr   c           
      óR  — | j                   r/t        j                  d«       | j                   j                  «        | j	                  «       D ]Á  }|j                  «       sŒt        j                  t        t        j                  «      5  ddd|› �dd| j                  › d| j                  › �g}t        j                  |dd	t        j                  ¬
«       d d d «       t        j                  t        «      5  |j                  «        d d d «       ŒÃ y # 1 sw Y   Œ>xY w# 1 sw Y   ŒÚxY w)Nz"SSH: syncing files from sandbox...r   r{   r|   z-OÚexitr3   Té   )Úcapture_outputr,   r®   )rP   rœ   ÚinfoÚ	sync_backrr   Úexistsr™   rš   r½   r’   ÚSubprocessErrorr*   r)   rá   rÁ   Úunlink)r;   Úsocketr„   s      r   ÚcleanupzSSHEnvironment.cleanup  sù   € Ø×ÒÜ�K‰KÐ<Ô=Ø×Ñ×(Ñ(Ô*Ø×+Ñ+Ó-ò 	 ˆFØ—=‘=”?ØÜ×$Ñ$¤W¬j×.HÑ.HÓIñ ^Ø˜d l°6°(Ð$;¸TÀ6ÈdÏiÉiÈ[ÐXYÐZ^×ZcÑZcÐYdÐKeÐf�Ü—‘˜s°4ÀÌ*×J\ÑJ\Õ]÷^ô ×$Ñ$¤WÓ-ñ  Ø—‘”÷ ð  ñ	 ÷^ð ^ú÷ ð  ús   ÂADÃ5DÄD	ÄD&	)Ú~é<   ru   Ú F)Nri   ©r   N)#Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú_profile_scoped_passthroughÚ_sudo_nopasswd_probe_supportedrv   Úintrã   rD   r€   r   re   Úlistrr   rx   r   r…   Úfloatr’   ÚCompletedProcessr‰   r�   rO   rQ   rR   rS   rU   rV   rT   rì   rÀ   r÷   r  Ú__classcell__)r[   s   @r   r(   r(   -   só  ø„ ñð #'ÐØ%)Ð"à8;ØDFØ$)ñ˜Sð ¨ð °#ð ØðØ*-ðØ>Aðà!õð<
A¨E°#°s°(©Oð 
AÀó 
Að= $ t¡*ó =ðH sð H¨tó Hñ
¨T°D©[ð È8ÐTWÉ=ð Ðbfó ðV 3ð V°ð V¸:×;VÑ;Vó VðM¨3ð M¸ð MÈð MÐVYð MÐ^bó Mò
Pð H Só Hó"ðo Sð o°sð o¸tó oðBO d¨5°°c°©?Ñ&;ð BOÀó BOðHA tð A°ó Að0E¨¨S©	ð E°dó Eó&ð ;@ÐPSØ+/ò
x Cð 
x°4ð 
xÈ#ð 
xØ! D™jð
xØ4>×4DÑ4Dó
xö r   r(   r  )zthe SSH connection))r
  r™   rJ   Úloggingr´   r¤   r   r’   rE   Úpathlibr   Útypingr   Útools.environments.baser   r   Útools.environments.base_outputr   Útools.environments.file_syncr   r	   r
   r   r   Ú tools.environments.remote_commonr   r   r   r   r   r   Ú	getLoggerr  rœ   r~   r�   ró   r   rv   r&   r(   ri   r   r   ú<module>r     sª   ðÙ Qã Û Û Û 	Û Û Û Û Ý Ý ç OÝ 6÷cõ c÷k÷ kð 
ˆ×	Ñ	˜8Ó	$€ð
 —‘˜D‘€ð -Ð óUñZ˜ð Z cð Z°ð ZÐPjó Zô
| �_õ | r   