§
    ‰eîi@  ã                   ó^  — 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	Z	ddl
Z
	 ddlZn# e$ r dZY nw xY wddlmZ ddlmZ ddlmZ ddlmZ  ej        e¦  «        ZdZdZeeegdf         Zeeeeef                  gdf         Zeegdf         Zeee         gdf         Z eg eeeef                  f         Z!dd
edeeeef                  fd„Z"dee         defd„Z#dee         defd„Z$deeeef                  dee         fd„Z%dedefd„Z&dZ'dZ(dZ) G d„ d¦  «        Z*dS )a  Shared file sync manager for remote execution backends.

Tracks local file changes via mtime+size, detects deletions, and
syncs to remote environments transactionally.  Used by SSH, Modal,
and Daytona.  Docker and Singularity use bind mounts (live host FS
view) and don't need this.
é    N)ÚPath)ÚCallable)Úget_hermes_home)Ú_file_mtime_keyg      @ÚHERMES_FORCE_FILE_SYNCú/root/.hermesÚcontainer_baseÚreturnc                 ót  — ddl m}m}m} g } |¦   «         D ]<}|d                              d| d¦  «        }|                     |d         |f¦  «         Œ= || ¬¦  «        D ]%}|                     |d         |d         f¦  «         Œ& || ¬¦  «        D ]%}|                     |d         |d         f¦  «         Œ&|S )a[  Enumerate all files that should be synced to a remote environment.

    Combines credentials, skills, and cache into a single flat list of
    (host_path, remote_path) pairs.  Credential paths are remapped from
    the hardcoded /root/.hermes to *container_base* because the remote
    user's home may differ (e.g. /home/daytona, /home/user).
    r   )Úget_credential_file_mountsÚiter_cache_filesÚiter_skills_filesÚcontainer_pathr   é   Ú	host_path)r	   )Útools.credential_filesr   r   r   ÚreplaceÚappend)r	   r   r   r   ÚfilesÚentryÚremotes          ú>/home/div/.hermes/hermes-agent/tools/environments/file_sync.pyÚiter_sync_filesr   +   s#  € ðð ð ð ð ð ð ð ð ð ð $&€EØ+Ð+Ñ-Ô-ð 3ð 3ˆØÐ'Ô(×0Ò0Ø˜^¨Qñ
ô 
ˆð 	�Š�e˜KÔ(¨&Ð1Ñ2Ô2Ð2Ð2Ø"Ð"°.ÐAÑAÔAð Dð DˆØ�Š�e˜KÔ(¨%Ð0@Ô*AÐBÑCÔCÐCÐCØ!Ð!°Ð@Ñ@Ô@ð Dð DˆØ�Š�e˜KÔ(¨%Ð0@Ô*AÐBÑCÔCÐCÐCØ€Ló    Úremote_pathsc                 óF   — dd                      d„ | D ¦   «         ¦  «        z   S )z<Build a shell ``rm -f`` command for a batch of remote paths.zrm -f Ú c              3   ó>   K  — | ]}t          j        |¦  «        V — Œd S ©N©ÚshlexÚquote)Ú.0Úps     r   ú	<genexpr>z$quoted_rm_command.<locals>.<genexpr>J   s*   è è € ÐDÐD°!�uœ{¨1™~œ~ÐDÐDÐDÐDÐDÐDr   ©Újoin)r   s    r   Úquoted_rm_commandr(   H   s(   € à�c—h’hÐDÐD°|ÐDÑDÔDÑDÔDÑDÐDr   Údirsc                 óF   — dd                      d„ | D ¦   «         ¦  «        z   S )z>Build a shell ``mkdir -p`` command for a batch of directories.z	mkdir -p r   c              3   ó>   K  — | ]}t          j        |¦  «        V — Œd S r   r    )r#   Úds     r   r%   z'quoted_mkdir_command.<locals>.<genexpr>O   s*   è è € Ð!?Ð!?°Q¥%¤+¨a¡.¤.Ð!?Ð!?Ð!?Ð!?Ð!?Ð!?r   r&   )r)   s    r   Úquoted_mkdir_commandr-   M   s(   € à˜ŸšÐ!?Ð!?¸$Ð!?Ñ!?Ô!?Ñ?Ô?Ñ?Ð?r   r   c                 ó4   — t          d„ | D ¦   «         ¦  «        S )zCExtract sorted unique parent directories from (host, remote) pairs.c                 óV   — h | ]&\  }}t          t          |¦  «        j        ¦  «        ’Œ'S © )Ústrr   Úparent©r#   Ú_r   s      r   ú	<setcomp>z%unique_parent_dirs.<locals>.<setcomp>T   s-   € ÐCÐCÐC±	°°6•3•t˜F‘|”|Ô*Ñ+Ô+ÐCÐCÐCr   )Úsorted)r   s    r   Úunique_parent_dirsr7   R   s   € åÐCÐC¸UÐCÑCÔCÑDÔDÐDr   Úpathc                 óú   ‡— t          j        ¦   «         }t          | d¦  «        5 Št          ˆfd„d¦  «        D ]}|                     |¦  «         Œ	 ddd¦  «         n# 1 swxY w Y   |                     ¦   «         S )z$Return hex SHA-256 digest of a file.Úrbc                  ó.   •— ‰                       d¦  «        S )Ni   )Úread)Úfs   €r   ú<lambda>z_sha256_file.<locals>.<lambda>[   s   ø€  !§&¢&¨¡-¤-€ r   r   N)ÚhashlibÚsha256ÚopenÚiterÚupdateÚ	hexdigest)r8   ÚhÚchunkr=   s      @r   Ú_sha256_filerG   W   s»   ø€ åŒÑÔ€AÝ	ˆd�DÑ	Ô	ð ˜QÝÐ/Ð/Ð/Ð/°Ñ5Ô5ð 	ð 	ˆEØ�HŠH�U‰OŒOˆOˆOð	ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð �;Š;‰=Œ=Ðs   ¥,AÁA"Á%A"é   )é   é   é   l        c                   ó  — e Zd ZdZeddfdedededede	dz  de
dz  fd	„Zd
dœdeddfd„Zddedz  ddfd„Zdeddfd„Zdeddfd„Zdd„Z	 ddedeeeef                  dz  dedz  fd„Z	 ddedeeeef                  dz  dedz  fd„ZdS )ÚFileSyncManageru–  Tracks local file changes and syncs to a remote environment.

    Backends instantiate this with transport callbacks (upload, delete)
    and a file-source callable.  The manager handles mtime-based change
    detection, deletion tracking, rate limiting, and transactional state.

    Not used by bind-mount backends (Docker, Singularity) â€” those get
    live host FS views and don't need file sync.
    NÚget_files_fnÚ	upload_fnÚ	delete_fnÚsync_intervalÚbulk_upload_fnÚbulk_download_fnc                 ó„   — || _         || _        || _        || _        || _        i | _        i | _        d| _        || _        d S )Ng        )	Ú_get_files_fnÚ
_upload_fnÚ_bulk_upload_fnÚ_bulk_download_fnÚ
_delete_fnÚ_synced_filesÚ_pushed_hashesÚ_last_sync_timeÚ_sync_interval)ÚselfrN   rO   rP   rQ   rR   rS   s          r   Ú__init__zFileSyncManager.__init__p   sP   € ð *ˆÔØ#ˆŒØ-ˆÔØ!1ˆÔØ#ˆŒØ;=ˆÔØ.0ˆÔØ&)ˆÔØ+ˆÔÐÐr   F)Úforcer`   r
   c                ó  ‡— |sLt           j                             t          ¦  «        s(t	          j        ¦   «         }|| j        z
  | j        k     rdS |                      ¦   «         }d„ |D ¦   «         Šg }t          | j
        ¦  «        }|D ]R\  }}t          |¦  «        }|€Œ| j
                             |¦  «        |k    rŒ6|                     ||f¦  «         |||<   ŒSˆfd„| j
        D ¦   «         }	|s|	st	          j        ¦   «         | _        dS t          | j
        ¦  «        }
t          | j        ¦  «        }|r(t                               dt!          |¦  «        ¦  «         |	r(t                               dt!          |	¦  «        ¦  «         	 |rE| j        �>|                      |¦  «         t                               dt!          |¦  «        ¦  «         n:|D ]7\  }}|                      ||¦  «         t                               d||¦  «         Œ8|	r0|                      |	¦  «         t                               d|	¦  «         |D ]\  }}t)          |¦  «        | j        |<   Œ|	D ]3}|                     |d¦  «         | j                             |d¦  «         Œ4|| _
        t	          j        ¦   «         | _        dS # t,          $ rL}|
| _
        || _        t	          j        ¦   «         | _        t                               d	|¦  «         Y d}~dS d}~ww xY w)
aT  Run a sync cycle: upload changed files, delete removed files.

        Rate-limited to once per ``sync_interval`` unless *force* is True
        or ``HERMES_FORCE_FILE_SYNC=1`` is set.

        Transactional: state only committed if ALL operations succeed.
        On failure, state rolls back so the next cycle retries everything.
        Nc                 ó   — h | ]\  }}|’ŒS r0   r0   r3   s      r   r5   z'FileSyncManager.sync.<locals>.<setcomp>’   s   € ÐFÐFÐF©9¨1¨f ÐFÐFÐFr   c                 ó   •— g | ]}|‰v¯|‘Œ	S r0   r0   )r#   r$   Úcurrent_remote_pathss     €r   ú
<listcomp>z(FileSyncManager.sync.<locals>.<listcomp>¡   s$   ø€ ÐTÐTÐT˜1°aÐ?SÐ6SÐ6S�QÐ6SÐ6SÐ6Sr   zfile_sync: uploading %d file(s)z+file_sync: deleting %d stale remote file(s)z#file_sync: bulk-uploaded %d file(s)zfile_sync: uploaded %s -> %szfile_sync: deleted %sz-file_sync: sync failed, rolled back state: %s)ÚosÚenvironÚgetÚ_FORCE_SYNC_ENVÚtimeÚ	monotonicr\   r]   rU   ÚdictrZ   r   r   r[   ÚloggerÚdebugÚlenrW   rV   rY   rG   ÚpopÚ	ExceptionÚwarning)r^   r`   ÚnowÚcurrent_filesÚ	to_uploadÚ	new_filesr   Úremote_pathÚfile_keyÚ	to_deleteÚ
prev_filesÚprev_hashesr$   Úexcrd   s                 @r   ÚsynczFileSyncManager.syncƒ   sV  ø€ ð ð 	�RœZŸ^š^­OÑ<Ô<ð 	Ý”.Ñ"Ô"ˆCØ�TÔ)Ñ)¨DÔ,?Ò?Ð?Ø�à×*Ò*Ñ,Ô,ˆØFÐF¸ÐFÑFÔFÐð ,.ˆ	Ý˜Ô+Ñ,Ô,ˆ	Ø&3ð 	.ð 	.Ñ"ˆI�{Ý& yÑ1Ô1ˆHØÐØØÔ!×%Ò% kÑ2Ô2°hÒ>Ð>ØØ×Ò˜i¨Ð5Ñ6Ô6Ð6Ø%-ˆI�kÑ"Ð"ð UÐTÐTÐT Ô 2ÐTÑTÔTˆ	àð 	 ð 	Ý#'¤>Ñ#3Ô#3ˆDÔ ØˆFõ ˜$Ô,Ñ-Ô-ˆ
Ý˜4Ô.Ñ/Ô/ˆàð 	LÝ�LŠLÐ:½CÀ	¹N¼NÑKÔKÐKØð 	XÝ�LŠLÐFÍÈIÉÌÑWÔWÐWð	QØð Y˜TÔ1Ð=Ø×$Ò$ YÑ/Ô/Ð/Ý—’ÐBÅCÈ	ÁNÄNÑSÔSÐSÐSà.7ð Yð YÑ*�I˜{Ø—O’O I¨{Ñ;Ô;Ð;Ý—L’LÐ!?ÀÈKÑXÔXÐXÐXàð AØ—’ 	Ñ*Ô*Ð*Ý—’Ð4°iÑ@Ô@Ð@ð +4ð Kð KÑ&�	˜;Ý3?À	Ñ3JÔ3J�Ô# KÑ0Ð0àð 1ð 1�Ø—’˜a Ñ&Ô&Ð&ØÔ#×'Ò'¨¨4Ñ0Ô0Ð0Ð0à!*ˆDÔÝ#'¤>Ñ#3Ô#3ˆDÔ Ð Ð øåð 	Qð 	Qð 	QØ!+ˆDÔØ"-ˆDÔÝ#'¤>Ñ#3Ô#3ˆDÔ Ý�NŠNÐJÈCÑPÔPÐPÐPÐPÐPÐPÐPÐPøøøøð		Qøøøs   Æ	D'J2 Ê2
LÊ<ALÌLÚhermes_homec                 ó>  — | j         €dS | j        s#| j        st                               d¦  «         dS |pt          ¦   «         dz  }|j                             dd¬¦  «         d}t          t          ¦  «        D ]‚}	 |  
                    |¦  «          dS # t          $ r[}|}|t          dz
  k     rAt          |         }t                               d|dz   ||¦  «         t          j        |¦  «         Y d}~Œ{d}~ww xY wt                               dt          |¦  «         dS )	a‘  Pull remote changes back to the host filesystem.

        Downloads the remote ``.hermes/`` directory as a tar archive,
        unpacks it, and applies only files that differ from what was
        originally pushed (based on SHA-256 content hashes).

        Protected against SIGINT (defers the signal until complete) and
        serialized across concurrent gateway sandboxes via file lock.
        Nu+   sync_back: no prior push state â€” skippingz
.sync.lockT)ÚparentsÚexist_okr   z2sync_back: attempt %d failed (%s), retrying in %dsz%sync_back: all %d attempts failed: %s)rX   r[   rZ   rm   rn   r   r2   ÚmkdirÚrangeÚ_SYNC_BACK_MAX_RETRIESÚ_sync_back_oncerq   Ú_SYNC_BACK_BACKOFFrr   rj   Úsleep)r^   r~   Ú	lock_pathÚlast_excÚattemptr|   Údelays          r   Ú	sync_backzFileSyncManager.sync_backÒ   sJ  € ð Ô!Ð)ØˆFð
 Ô"ð 	¨4Ô+=ð 	Ý�LŠLÐFÑGÔGÐGØˆFà Ð5¥OÑ$5Ô$5¸ÑEˆ	ØÔ×Ò t°dÐÑ;Ô;Ð;à%)ˆÝÕ3Ñ4Ô4ð 	&ð 	&ˆGð&Ø×$Ò$ YÑ/Ô/Ð/Ø��øÝð &ð &ð &Ø�ØÕ3°aÑ7Ò7Ð7Ý.¨wÔ7�EÝ—N’NØLØ !™ S¨%ñô ð õ ”J˜uÑ%Ô%Ð%øøøøøøøøøð&øøøõ 	�ŠÐ>Õ@VÐX`ÑaÔaÐaÐaÐas   Á<BÂ
C9ÂAC4Ã4C9rˆ   c                 ó€  ‡— t          j        ¦   «         t          j        ¦   «         u }g Šd}|rBt          j        t          j        ¦  «        }ˆfd„}t          j        t          j        |¦  «         	 |                      |¦  «         |rU|�Ut          j        t          j        |¦  «         ‰r6t          j        t          j	        ¦   «         t          j        ¦  «         dS dS dS dS # |rT|�St          j        t          j        |¦  «         ‰r3t          j        t          j	        ¦   «         t          j        ¦  «         w w w w xY w)z>Single sync-back attempt with SIGINT protection and file lock.Nc                 ój   •— ‰                      | |f¦  «         t                               d¦  «         d S )Nz/sync_back: SIGINT deferred until sync completes)r   rm   rn   )ÚsignumÚframeÚdeferred_sigints     €r   Ú_defer_sigintz6FileSyncManager._sync_back_once.<locals>._defer_sigint  s4   ø€ Ø×&Ò&¨° Ñ7Ô7Ð7Ý—’ÐNÑOÔOÐOÐOÐOr   )
Ú	threadingÚcurrent_threadÚmain_threadÚsignalÚ	getsignalÚSIGINTÚ_sync_back_lockedrf   ÚkillÚgetpid)r^   rˆ   Úon_main_threadÚoriginal_handlerr’   r‘   s        @r   r…   zFileSyncManager._sync_back_onceú   sT  ø€ õ
 #Ô1Ñ3Ô3µyÔ7LÑ7NÔ7NÐNˆà(*ˆØÐØð 	8Ý%Ô/µ´Ñ>Ô>ÐðPð Pð Pð Pð Põ ŒM�&œ-¨Ñ7Ô7Ð7ð	8Ø×"Ò" 9Ñ-Ô-Ð-àð 8Ð"2Ð">Ý”�fœmÐ-=Ñ>Ô>Ð>Ø"ð 8Ý”G�BœI™KœK­¬Ñ7Ô7Ð7Ð7Ð7ð8ð 8Ð">Ð">ð8ð 8øð ð 8Ð"2Ð">Ý”�fœmÐ-=Ñ>Ô>Ð>Ø"ð 8Ý”G�BœI™KœK­¬Ñ7Ô7Ð7Ð7ð8Ð">ð8øøøs   Á1C# Ã#AD=c                 óž  — t           €|                      ¦   «          dS t          |d¦  «        }	 t          j        |t           j        ¦  «         |                      ¦   «          t          j        |t           j        ¦  «         |                     ¦   «          dS # t          j        |t           j        ¦  «         |                     ¦   «          w xY w)z;Sync-back under file lock (serializes concurrent gateways).NÚw)ÚfcntlÚ_sync_back_implrA   ÚflockÚLOCK_EXÚLOCK_UNÚclose)r^   rˆ   Úlock_fds      r   r™   z!FileSyncManager._sync_back_locked  s¦   € åˆ=à× Ò Ñ"Ô"Ð"ØˆFÝ�y #Ñ&Ô&ˆð	ÝŒK˜¥¤Ñ/Ô/Ð/Ø× Ò Ñ"Ô"Ð"åŒK˜¥¤Ñ/Ô/Ð/Ø�MŠM‰OŒOˆOˆOˆOøõ ŒK˜¥¤Ñ/Ô/Ð/Ø�MŠM‰OŒOˆOˆOøøøs   ¯3B Â5Cc           	      ó˜  — | j         €t          d¦  «        ‚	 t          |                      ¦   «         ¦  «        }n# t          $ r g }Y nw xY wt          j        d¬¦  «        5 }|                       t          |j        ¦  «        ¦  «         	 t          j
                             |j        ¦  «        }n# t          $ r d}Y nw xY w|t          k    r/t                               d|t          ¦  «         	 ddd¦  «         dS t          j        d¬¦  «        5 }t#          j        |j        ¦  «        5 }|                     |d	¬
¦  «         ddd¦  «         n# 1 swxY w Y   d}t          j        |¦  «        D �]r\  }}}	|	D �]g}
t          j
                             ||
¦  «        }t          j
                             ||¦  «        }d|z   }| j                             |¦  «        }|�t3          |¦  «        }||k    rŒznd}|                      ||¦  «        }|€4|                      ||¦  «        }|€t                               d|¦  «         ŒÉt          j
                             |¦  «        r2|�0t3          |¦  «        }||k    rt                               d|¦  «         t          j        t          j
                             |¦  «        d¬¦  «         tA          j!        ||¦  «         |dz  }�Œi�Œt|rt           "                    d|¦  «         nt                               d¦  «         ddd¦  «         n# 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )z1Download, diff, and apply remote changes to host.Nz/_sync_back_impl called without bulk_download_fnz.tar)Úsuffixr   uB   sync_back: remote tar is %d bytes (cap %d) â€” skipping extractionzhermes-sync-back-)ÚprefixÚdata)Úfilterú/z(sync_back: skipping %s (no host mapping)uw   sync_back: conflict on %s â€” host modified since push, remote also changed. Applying remote version (last-write-wins).T)r�   r   z%sync_back: applied %d changed file(s)z%sync_back: no remote changes detected)#rX   ÚRuntimeErrorÚlistrU   rq   ÚtempfileÚNamedTemporaryFiler   Únamerf   r8   ÚgetsizeÚOSErrorÚ_SYNC_BACK_MAX_BYTESrm   rr   ÚTemporaryDirectoryÚtarfilerA   Ú
extractallÚwalkr'   Úrelpathr[   rh   rG   Ú_resolve_host_pathÚ_infer_host_pathrn   ÚexistsÚmakedirsÚdirnameÚshutilÚcopy2Úinfo)r^   Úfile_mappingÚtfÚtar_sizeÚstagingÚtarÚappliedÚdirpathÚ	_dirnamesÚ	filenamesÚfnameÚstaged_fileÚrelrw   Úpushed_hashÚremote_hashr   Ú	host_hashs                     r   r¡   zFileSyncManager._sync_back_impl!  s�  € àÔ!Ð)ÝÐPÑQÔQÐQð	Ý × 2Ò 2Ñ 4Ô 4Ñ5Ô5ˆLˆLøÝð 	ð 	ð 	ØˆLˆLˆLð	øøøõ Ô(°Ð7Ñ7Ô7ð A	J¸2Ø×"Ò"¥4¨¬¡=¤=Ñ1Ô1Ð1ðÝœ7Ÿ?š?¨2¬7Ñ3Ô3��øÝð ð ð Ø���ðøøøàÕ.Ò.Ð.Ý—’ØXØÕ2ñô ð ð ðA	Jð A	Jð A	Jñ A	Jô A	Jð A	Jð A	Jð A	Jõ  Ô,Ð4GÐHÑHÔHð 1JÈGÝ”\ "¤'Ñ*Ô*ð ;¨cØ—N’N 7°6�NÑ:Ô:Ð:ð;ð ;ð ;ñ ;ô ;ð ;ð ;ð ;ð ;ð ;ð ;øøøð ;ð ;ð ;ð ;ð �Ý57´W¸WÑ5EÔ5Eð '%ñ '%Ñ1�G˜Y¨	Ø!*ð &%ñ &%˜Ý&(¤g§l¢l°7¸EÑ&BÔ&B˜Ý œgŸošo¨k¸7ÑCÔC˜Ø&)¨C¡i˜à&*Ô&9×&=Ò&=¸kÑ&JÔ&J˜ð 'Ð2Ý*6°{Ñ*CÔ*C˜KØ*¨kÒ9Ð9Ø (ð  :ð +/˜Kð %)×$;Ò$;¸KÈÑ$VÔ$V˜	Ø$Ð,Ø(,×(=Ò(=¸kÈ<Ñ(XÔ(X˜IØ(Ð0Ý &§¢Ø$NØ$/ñ!"ô !"ð !"ð !)åœ7Ÿ>š>¨)Ñ4Ô4ð "¸Ð9PÝ(4°YÑ(?Ô(?˜IØ(¨KÒ7Ð7Ý &§¢ð%Hð %0ñ	!"ô !"ð !"õ œ¥B¤G§O¢O°IÑ$>Ô$>ÈÐNÑNÔNÐNÝœ [°)Ñ<Ô<Ð<Ø 1™˜™ñM&%ðP ð JÝ—K’KÐ GÈÑQÔQÐQÐQå—L’LÐ!HÑIÔIÐIðc1Jð 1Jð 1Jñ 1Jô 1Jð 1Jð 1Jð 1Jð 1Jð 1Jð 1Jøøøð 1Jð 1Jð 1Jð 1Jð!A	Jð A	Jð A	Jñ A	Jô A	Jð A	Jð A	Jð A	Jð A	Jð A	Jð A	Jð A	Jøøøð A	Jð A	Jð A	Jð A	Jð A	Jð A	Js”   ˜!: ºA	ÁA	Á!(L?Â
$B/Â.L?Â/B>Â;L?Â=B>Â>0L?Ã;L?ÄL'Ä*EÅL'ÅEÅL'ÅEÅGL'ÌL?Ì'L+	Ì+L?Ì.L+	Ì/L?Ì?MÍMrw   rÂ   c                 ó6   — |�|ng }|D ]\  }}||k    r|c S ŒdS )zAFind the host path for a known remote path from the file mapping.Nr0   )r^   rw   rÂ   ÚmappingÚhostr   s         r   rº   z"FileSyncManager._resolve_host_patho  sC   € ð #/Ð":�,�,ÀˆØ#ð 	ð 	‰LˆD�&Ø˜Ò$Ð$Ø���ð %àˆtr   c                 ó  — |�|ng }|D ]}\  }}t          t          |¦  «        j        ¦  «        }|                     |dz   ¦  «        r?t          t          |¦  «        j        ¦  «        }|t	          |¦  «        d…         }||z   c S Œ~dS )u¨  Infer a host path for a new remote file by matching path prefixes.

        Uses the existing file mapping to find a remote->host directory
        pair, then applies the same prefix substitution to the new file.
        For example, if the mapping has ``/root/.hermes/skills/a.md`` â†’
        ``~/.hermes/skills/a.md``, a new remote file at
        ``/root/.hermes/skills/b.md`` maps to ``~/.hermes/skills/b.md``.
        Nr¬   )r1   r   r2   Ú
startswithro   )	r^   rw   rÂ   rÒ   rÓ   r   Ú
remote_dirÚhost_dirr¨   s	            r   r»   z FileSyncManager._infer_host_pathx  sŸ   € ð #/Ð":�,�,ÀˆØ#ð 	)ð 	)‰LˆD�&Ý�T &™\œ\Ô0Ñ1Ô1ˆJØ×%Ò% j°3Ñ&6Ñ7Ô7ð )Ý�t D™zœzÔ0Ñ1Ô1�Ø$¥S¨¡_¤_Ð%5Ð%5Ô6�Ø &Ñ(Ð(Ð(Ð(ð)ð ˆtr   r   )r
   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú_SYNC_INTERVAL_SECONDSÚ
GetFilesFnÚUploadFnÚDeleteFnÚfloatÚBulkUploadFnÚBulkDownloadFnr_   Úboolr}   r   rŒ   r…   r™   r¡   r1   r®   Útuplerº   r»   r0   r   r   rM   rM   e   sù  € € € € € ðð ð  6Ø.2Ø26ð,ð ,à ð,ð ð,ð ð	,ð
 ð,ð % tÑ+ð,ð )¨4Ñ/ð,ð ,ð ,ð ,ð& %*ð IQð IQð IQ˜Tð IQ¨dð IQð IQð IQð IQð^&bð &b T¨D¡[ð &b¸Dð &bð &bð &bð &bðP8¨ð 8°$ð 8ð 8ð 8ð 8ð2¨4ð °Dð ð ð ð ðLJð LJð LJð LJð^ IMðð ¨cð Ø)-¨e°C¸°H¬oÔ)>ÀÑ)EðØQTÐW[ÑQ[ðð ð ð ð GKðð ¨Cð Ø'+¨E°#°s°(¬OÔ'<¸tÑ'CðØORÐUYÉzðð ð ð ð ð r   rM   )r   )+rÛ   r?   Úloggingrf   r!   r¿   r–   r¶   r¯   r“   rj   r    ÚImportErrorÚpathlibr   Útypingr   Úhermes_constantsr   Útools.environments.baser   Ú	getLoggerrØ   rm   rÜ   ri   r1   rÞ   r®   rä   rá   râ   rß   rÝ   r   r(   r-   r7   rG   r„   r†   r´   rM   r0   r   r   ú<module>rì      s³  ððð ð €€€Ø €€€Ø 	€	€	€	Ø €€€Ø €€€Ø €€€Ø €€€Ø €€€Ø Ð Ð Ð Ø €€€ðØ€L€L€L€LøØð ð ð Ø€E€E€Eðøøøà Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð à ,Ð ,Ð ,Ð ,Ð ,Ð ,Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3à	ˆÔ	˜8Ñ	$Ô	$€àÐ Ø*€ð �S˜#�J Ð$Ô%€Ø˜˜e C¨ HœoÔ.Ð/°Ð5Ô6€Ø˜4˜& $˜,Ô'€Ø�T˜#”Y�K Ð%Ô&€Ø�b˜$˜u S¨# XœÔ/Ð/Ô0€
ðð  Cð ¸dÀ5ÈÈcÈÄ?Ô>Sð ð ð ð ð:E D¨¤Ið E°#ð Eð Eð Eð Eð
@˜t Cœyð @¨Sð @ð @ð @ð @ð
E˜d 5¨¨c¨¤?Ô3ð E¸¸S¼	ð Eð Eð Eð Eð
�sð ˜sð ð ð ð ð Ð ØÐ Ø-Ð ðdð dð dð dð dñ dô dð dð dð ds   ¬1 ±;º;