§
    ‰eîi&A  ã                   ó¤  — 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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 ddlmZmZmZmZmZ  ej        e¦  «        Z e¦   «         dz  Zd	Zd
efd„Z ded
dfd„Z!de"d
e"fd„Z#de"d
e$e"dz  e%f         fd„Z&de"de"d
dfd„Z'dde"de"dz  d
dfd„Z(ded
efd„Z) G d„ d¦  «        Z* G d„ de¦  «        Z+dS )zäModal cloud execution environment using the native Modal SDK directly.

Uses ``Sandbox.create()`` + ``Sandbox.exec()`` instead of the older runtime
wrapper, while preserving Hermes' persistent snapshot behavior across sessions.
é    N)ÚPath)ÚAnyÚOptional)Úget_hermes_home)ÚBaseEnvironmentÚ_ThreadedProcessHandleÚ_load_json_storeÚ_save_json_store)ÚFileSyncManagerÚiter_sync_filesÚquoted_mkdir_commandÚquoted_rm_commandÚunique_parent_dirszmodal_snapshots.jsonÚdirectÚreturnc                  ó*   — t          t          ¦  «        S ©N)r	   Ú_SNAPSHOT_STORE© ó    ú:/home/div/.hermes/hermes-agent/tools/environments/modal.pyÚ_load_snapshotsr   &   s   € Ý�OÑ,Ô,Ð,r   Údatac                 ó0   — t          t          | ¦  «         d S r   )r
   r   )r   s    r   Ú_save_snapshotsr   *   s   € Ý•_ dÑ+Ô+Ð+Ð+Ð+r   Útask_idc                 ó   — t           › d| › �S )Nú:)Ú_DIRECT_SNAPSHOT_NAMESPACE)r   s    r   Ú_direct_snapshot_keyr    .   s   € Ý(Ð4Ð4¨7Ð4Ð4Ð4r   c                 ó   — t          ¦   «         }t          | ¦  «        }|                     |¦  «        }t          |t          ¦  «        r|r|dfS |                     | ¦  «        }t          |t          ¦  «        r|r|dfS dS )NFT)NF)r   r    ÚgetÚ
isinstanceÚstr)r   Ú	snapshotsÚnamespaced_keyÚsnapshot_idÚlegacy_snapshot_ids        r   Ú_get_snapshot_restore_candidater)   2   sŒ   € ÝÑ!Ô!€IÝ)¨'Ñ2Ô2€NØ—-’- Ñ/Ô/€KÝ�+�sÑ#Ô#ð "¨ð "Ø˜EÐ!Ð!Ø"Ÿš wÑ/Ô/ÐÝÐ$¥cÑ*Ô*ð (Ð/Að (Ø! 4Ð'Ð'Øˆ;r   r'   c                 ó�   — t          ¦   «         }||t          | ¦  «        <   |                     | d ¦  «         t          |¦  «         d S r   )r   r    Úpopr   )r   r'   r%   s      r   Ú_store_direct_snapshotr,   >   sH   € ÝÑ!Ô!€IØ/:€IÕ" 7Ñ+Ô+Ñ,Ø‡M‚M�'˜4Ñ Ô Ð Ý�IÑÔÐÐÐr   c                 óä   — t          ¦   «         }d}t          | ¦  «        | fD ]:}|                     |¦  «        }|€Œ|�||k    r|                     |d ¦  «         d}Œ;|rt	          |¦  «         d S d S )NFT)r   r    r"   r+   r   )r   r'   r%   ÚupdatedÚkeyÚvalues         r   Ú_delete_direct_snapshotr1   E   s—   € ÝÑ!Ô!€IØ€GÝ$ WÑ-Ô-¨wÐ7ð ð ˆØ—’˜cÑ"Ô"ˆØˆ=ØØÐ %¨;Ò"6Ð"6Ø�MŠM˜#˜tÑ$Ô$Ð$ØˆGøØð #Ý˜	Ñ"Ô"Ð"Ð"Ð"ð#ð #r   Ú
image_specc                 ód  ‡— ddl }t          | t          ¦  «        s| S |                      d¦  «        r|j                             | ¦  «        S |                      ¦   «         Št          ˆfd„dD ¦   «         ¦  «        }dg}|r|                     dd¦  «         |j         	                    | |¬¦  «        S )	z�Convert registry references or snapshot ids into Modal image objects.

    Includes add_python support for ubuntu/debian images (absorbed from PR 4511).
    r   Nzim-c              3   ó    •K  — | ]}|‰v V — Œ	d S r   r   )Ú.0ÚbaseÚlowers     €r   ú	<genexpr>z'_resolve_modal_image.<locals>.<genexpr>b   s'   øè è € ÐDÐD t�T˜U�]ÐDÐDÐDÐDÐDÐDr   )ÚubuntuÚdebianz�RUN rm -rf /usr/local/lib/python*/site-packages/pip* 2>/dev/null; python -m ensurepip --upgrade --default-pip 2>/dev/null || truez^RUN apt-get update -qq && apt-get install -y -qq python3 python3-venv > /dev/null 2>&1 || true)Úsetup_dockerfile_commands)
Úmodalr#   r$   Ú
startswithÚImageÚfrom_idr7   ÚanyÚinsertÚfrom_registry)r2   Ú_modalÚ
add_pythonÚsetup_commandsr7   s       @r   Ú_resolve_modal_imagerF   S   sæ   ø€ ð
 ÐÐÐå�j¥#Ñ&Ô&ð ØÐà×Ò˜UÑ#Ô#ð 0ØŒ|×#Ò# JÑ/Ô/Ð/ð ×ÒÑÔ€EÝÐDÐDÐDÐDÐ/CÐDÑDÔDÑDÔD€Jð	Jð€Nð ð 
Ø×Ò˜aØlñ	
ô 	
ð 	
ð Œ<×%Ò%ØØ"0ð &ñ ô ð r   c                   ó2   — e Zd ZdZd„ Zd„ Zd„ Zd	d„Zd„ ZdS )
Ú_AsyncWorkerzEBackground thread with its own event loop for async-safe Modal calls.c                 óR   — d | _         d | _        t          j        ¦   «         | _        d S r   )Ú_loopÚ_threadÚ	threadingÚEventÚ_started©Úselfs    r   Ú__init__z_AsyncWorker.__init__v   s#   € Ø:>ˆŒ
Ø37ˆŒÝ!œÑ)Ô)ˆŒˆˆr   c                 ó®   — t          j        | j        d¬¦  «        | _        | j                             ¦   «          | j                             d¬¦  «         d S )NT)ÚtargetÚdaemoné   ©Útimeout)rL   ÚThreadÚ	_run_looprK   ÚstartrN   ÚwaitrO   s    r   rZ   z_AsyncWorker.start{   sN   € Ý Ô'¨t¬~ÀdÐKÑKÔKˆŒØŒ×ÒÑÔÐØŒ×Ò 2ÐÑ&Ô&Ð&Ð&Ð&r   c                 óÌ   — t          j        ¦   «         | _        t          j        | j        ¦  «         | j                             ¦   «          | j                             ¦   «          d S r   )ÚasyncioÚnew_event_looprJ   Úset_event_looprN   ÚsetÚrun_foreverrO   s    r   rY   z_AsyncWorker._run_loop€   sS   € ÝÔ+Ñ-Ô-ˆŒ
ÝÔ˜tœzÑ*Ô*Ð*ØŒ×ÒÑÔÐØŒ
×ÒÑ Ô Ð Ð Ð r   éX  c                 óÀ   — | j         �| j                              ¦   «         rt          d¦  «        ‚t          j        || j         ¦  «        }|                     |¬¦  «        S )NzAsyncWorker loop is not runningrV   )rJ   Ú	is_closedÚRuntimeErrorr]   Úrun_coroutine_threadsafeÚresult)rP   ÚcororW   Úfutures       r   Úrun_coroutinez_AsyncWorker.run_coroutine†   sT   € ØŒ:Ð ¤×!5Ò!5Ñ!7Ô!7ÐÝÐ@ÑAÔAÐAÝÔ1°$¸¼
ÑCÔCˆØ�}Š} Wˆ}Ñ-Ô-Ð-r   c                 óÖ   — | j         r=| j                              ¦   «         r$| j                              | j         j        ¦  «         | j        r| j                             d¬¦  «         d S d S )Né
   rV   )rJ   Ú
is_runningÚcall_soon_threadsafeÚstoprK   ÚjoinrO   s    r   ro   z_AsyncWorker.stopŒ   sn   € ØŒ:ð 	=˜$œ*×/Ò/Ñ1Ô1ð 	=ØŒJ×+Ò+¨D¬J¬OÑ<Ô<Ð<ØŒ<ð 	*ØŒL×Ò bÐÑ)Ô)Ð)Ð)Ð)ð	*ð 	*r   N)rb   )	Ú__name__Ú
__module__Ú__qualname__Ú__doc__rQ   rZ   rY   rj   ro   r   r   r   rH   rH   s   sj   € € € € € ØOÐOð*ð *ð *ð
'ð 'ð 'ð
!ð !ð !ð.ð .ð .ð .ð*ð *ð *ð *ð *r   rH   c                   ó  ‡ — e Zd ZdZdZdZ	 	 	 	 	 d#ded	ed
edee	ee
f                  dedefˆ fd„Zdededdfd„Z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d$d„Zddddœdeded
ed edz  fd!„Zd"„ Zˆ xZS )%ÚModalEnvironmentz¿Modal cloud execution via native Modal sandboxes.

    Spawn-per-call via _ThreadedProcessHandle wrapping async SDK calls.
    cancel_fn wired to sandbox.terminate for interrupt support.
    Úheredocé<   ú/rootNTÚdefaultÚimageÚcwdrW   Úmodal_sandbox_kwargsÚpersistent_filesystemr   c                 ó2  •‡‡‡— t          ¦   «                              ||¬¦  «         || _        || _        d | _        d | _        t          ¦   «         | _        d | _        t          |pi ¦  «        Šd }d}| j        r<t          | j        ¦  «        \  }}|r#t                               d|d d…         ¦  «         dd lŠg Š	 ddlm}	m}
m}  |	¦   «         D ]=}‰                     ‰j                             |d         |d         ¬	¦  «        ¦  «         Œ> |
¦   «         D ]=}‰                     ‰j                             |d         |d         ¬	¦  «        ¦  «         Œ> |¦   «         }|D ]=}‰                     ‰j                             |d         |d         ¬	¦  «        ¦  «         Œ>n2# t*          $ r%}t                               d
|¦  «         Y d }~nd }~ww xY w| j                             ¦   «          dt0          fˆˆˆfd„}	 |p|}	 t3          |¦  «        }| j                              ||¦  «        d¬¦  «        \  | _        | _        |r|rt7          | j        |¦  «         n”# t*          $ r‡}|s‚ t                               d|d d…         |¦  «         t;          | j        |¦  «         t3          |¦  «        }| j                              ||¦  «        d¬¦  «        \  | _        | _        Y d }~nd }~ww xY wn(# t*          $ r | j                             ¦   «          ‚ w xY wt                               d| j        ¦  «         t?          d„ | j         | j!        | j"        | j#        ¬¦  «        | _        | j         $                    d¬¦  «         |  %                    ¦   «          d S )N)r|   rW   Fz!Modal: restoring from snapshot %sé   r   )Úget_credential_file_mountsÚiter_skills_filesÚiter_cache_filesÚ	host_pathÚcontainer_path)Úremote_pathz0Modal: could not load credential file mounts: %sr2   c              “   ó€  •K  — ‰j         j                             dd¬¦  «        ƒ d {V —†}t          ‰¦  «        }‰r=t	          |                     dg ¦  «        ¦  «        }|                     ‰¦  «         ||d<    ‰j        j        j        	 d
| |t          |                     dd¦  «        ¦  «        d	œ|¤Žƒ d {V —†}||fS )Nzhermes-agentT)Úcreate_if_missingÚmountsÚsleepÚinfinityrW   i  )r{   ÚapprW   )rŠ   r‹   )
ÚAppÚlookupÚaioÚdictÚlistr+   ÚextendÚSandboxÚcreateÚint)r2   rŒ   Úcreate_kwargsÚexisting_mountsÚsandboxrC   Úcred_mountsÚsandbox_kwargss        €€€r   Ú_create_sandboxz2ModalEnvironment.__init__.<locals>._create_sandboxß   s  øè è € Øœ
Ô)×-Ò-¨nÐPTÐ-ÑUÔUÐUÐUÐUÐUÐUÐUˆCÝ  Ñ0Ô0ˆMØð :Ý"& }×'8Ò'8¸À2Ñ'FÔ'FÑ"GÔ"G�Ø×&Ò& {Ñ3Ô3Ð3Ø*9�˜hÑ'Ø5˜FœNÔ1Ô5Ø#ðà ØÝ˜M×-Ò-¨i¸Ñ>Ô>Ñ?Ô?ð	ð ð
  ðð ð ð ð ð ð ð ˆGð ˜�<Ðr   i,  rV   zBModal: failed to restore snapshot %s, retrying with base image: %sz Modal: sandbox created (task=%s)c                  ó    — t          d¦  «        S )Nz/root/.hermes)r   r   r   r   ú<lambda>z+ModalEnvironment.__init__.<locals>.<lambda>  s   € ¥°Ñ!AÔ!A€ r   )Úget_files_fnÚ	upload_fnÚ	delete_fnÚbulk_upload_fnÚbulk_download_fnT)Úforce)&ÚsuperrQ   Ú_persistentÚ_task_idÚ_sandboxÚ_apprH   Ú_workerÚ_sync_managerr�   r)   ÚloggerÚinfor<   Útools.credential_filesr�   r‚   rƒ   ÚappendÚMountÚfrom_local_fileÚ	ExceptionÚdebugrZ   r   rF   rj   r,   Úwarningr1   ro   r   Ú_modal_uploadÚ_modal_deleteÚ_modal_bulk_uploadÚ_modal_bulk_downloadÚsyncÚinit_session)rP   r{   r|   rW   r}   r~   r   Úrestored_snapshot_idÚrestored_from_legacy_keyr�   r‚   rƒ   Úmount_entryÚentryÚcache_filesÚer›   Útarget_image_specÚeffective_imageÚexcÚ
base_imagerC   r™   rš   Ú	__class__s                        @@@€r   rQ   zModalEnvironment.__init__�   s»  øøøø€ õ 	‰Œ×Ò˜S¨'ÐÑ2Ô2Ð2à0ˆÔØˆŒØˆŒØˆŒ	Ý#‘~”~ˆŒØ59ˆÔåÐ2Ð8°bÑ9Ô9ˆà#ÐØ#(Ð ØÔð 	\Ý=\Ø”ñ>ô >Ñ:Ð Ð":ð $ð \Ý—’Ð?ÐAUÐVYÐWYÐVYÔAZÑ[Ô[Ð[àÐÐÐàˆð	Pðð ð ð ð ð ð ð ð ð ð  :Ð9Ñ;Ô;ð ð �Ø×"Ò"Ø”L×0Ò0Ø# KÔ0Ø$/Ð0@Ô$Að 1ñ ô ñô ð ð ð +Ð*Ñ,Ô,ð ð �Ø×"Ò"Ø”L×0Ò0Ø˜kÔ*Ø$)Ð*:Ô$;ð 1ñ ô ñô ð ð ð +Ð*Ñ,Ô,ˆKØ$ð ð �Ø×"Ò"Ø”L×0Ò0Ø˜kÔ*Ø$)Ð*:Ô$;ð 1ñ ô ñô ð ð ðøõ ð 	Pð 	Pð 	PÝ�LŠLÐKÈQÑOÔOÐOÐOÐOÐOÐOÐOøøøøð	Pøøøð 	Œ×ÒÑÔÐð	 ­cð 	 ð 	 ð 	 ð 	 ð 	 ð 	 ð 	 ð 	 ð 	Ø 4Ð =¸ÐðPÝ"6Ð7HÑ"IÔ"I�Ø+/¬<×+EÒ+EØ#�O OÑ4Ô4¸cð ,Fñ ,ô ,Ñ(�”	˜4œ=ð  (ð PÐ,Dð PÝ*¨4¬=Ð:NÑOÔOÐOøøõ ð ð ð Ø+ð ØÝ—’ØXØ(¨¨"¨Ô-¨sñô ð õ (¨¬Ð7KÑLÔLÐLÝ1°%Ñ8Ô8�
Ø+/¬<×+EÒ+EØ#�O JÑ/Ô/¸ð ,Fñ ,ô ,Ñ(�”	˜4œ=˜=˜=˜=˜=˜=øøøøðøøøøøõ ð 	ð 	ð 	ØŒL×ÒÑÔÐØð	øøøõ 	�ŠÐ6¸¼ÑFÔFÐFå,ØAÐAØÔ(ØÔ(ØÔ2Ø!Ô6ð
ñ 
ô 
ˆÔð 	Ô×Ò dÐÑ+Ô+Ð+Ø×ÒÑÔÐÐÐsQ   Â=C$F" Æ"
GÆ,GÇGÇ=K2 ÈAI ÉK2 É
K.É'A=K)Ë$K2 Ë)K.Ë.K2 Ë2%Lr„   r†   r   c                 óŒ  ‡ ‡‡— t          |¦  «                             ¦   «         }t          j        |¦  «                             d¦  «        Št          t          |¦  «        j        ¦  «        }dt          j        |¦  «        › dt          j        |¦  «        › �Šˆˆˆ fd„}‰ j	         
                     |¦   «         d¬¦  «         dS )z4Upload a single file via base64 piped through stdin.Úasciiz	mkdir -p z && base64 -d > c               “   ó  •K  — ‰j         j                             dd‰¦  «        ƒ d {V —†} d}‰j        }|t	          ‰¦  «        k     ra| j                             ‰|||z   …         ¦  «         | j        j                             ¦   «         ƒ d {V —† ||z  }|t	          ‰¦  «        k     °a| j                             ¦   «          | j        j                             ¦   «         ƒ d {V —† | j	                             ¦   «         ƒ d {V —† d S )NÚbashú-cr   )
r§   Úexecr�   Ú_STDIN_CHUNK_SIZEÚlenÚstdinÚwriteÚdrainÚ	write_eofr[   )ÚprocÚoffsetÚ
chunk_sizeÚb64ÚcmdrP   s      €€€r   Ú_writez.ModalEnvironment._modal_upload.<locals>._write  s%  øè è € ØœÔ+×/Ò/°¸¸cÑBÔBÐBÐBÐBÐBÐBÐBˆDØˆFØÔ/ˆJØ�3˜s™8œ8Ò#Ð#Ø”
× Ò   V¨F°ZÑ,?Ð%?Ô!@ÑAÔAÐAØ”jÔ&×*Ò*Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ø˜*Ñ$�ð �3˜s™8œ8Ò#Ð#ð ŒJ× Ò Ñ"Ô"Ð"Ø”*Ô"×&Ò&Ñ(Ô(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ø”)—-’-‘/”/Ð!Ð!Ð!Ð!Ð!Ð!Ð!Ð!Ð!r   rU   rV   N)r   Ú
read_bytesÚbase64Ú	b64encodeÚdecoder$   ÚparentÚshlexÚquoter©   rj   )rP   r„   r†   ÚcontentÚcontainer_dirrÖ   rÔ   rÕ   s   `     @@r   r´   zModalEnvironment._modal_upload  sÕ   øøø€ å�y‘/”/×,Ò,Ñ.Ô.ˆÝÔ˜wÑ'Ô'×.Ò.¨wÑ7Ô7ˆÝ�D Ñ-Ô-Ô4Ñ5Ô5ˆð6�œ MÑ2Ô2ð 6ð 6Ý œ; {Ñ3Ô3ð6ð 6ð 	ð

	"ð 
	"ð 
	"ð 
	"ð 
	"ð 
	"ð 
	"ð 	Œ×"Ò" 6 6¡8¤8°RÐ"Ñ8Ô8Ð8Ð8Ð8r   i   Úfilesc                 ó
  ‡ ‡	‡
— |sdS t          j        ¦   «         }t          j        |d¬¦  «        5 }|D ]/\  }}|                     ||                     d¦  «        ¬¦  «         Œ0	 ddd¦  «         n# 1 swxY w Y   t          j        |                     ¦   «         ¦  «         	                    d¦  «        Š
t          |¦  «        }t          |¦  «        }|› d�Š	ˆ	ˆ
ˆ fd„}‰ j                              |¦   «         d	¬
¦  «         dS )a  Upload many files via tar archive piped through stdin.

        Builds a gzipped tar archive in memory and streams it into a
        ``base64 -d | tar xzf -`` pipeline via the process's stdin,
        avoiding the Modal SDK's 64 KB ``ARG_MAX_BYTES`` exec-arg limit.
        Nzw:gz)ÚfileobjÚmodeú/)ÚarcnamerÆ   z && base64 -d | tar xzf - -C /c               “   óŠ  •K  — ‰j         j                             dd‰¦  «        ƒ d {V —†} d}‰j        }|t	          ‰¦  «        k     ra| j                             ‰|||z   …         ¦  «         | j        j                             ¦   «         ƒ d {V —† ||z  }|t	          ‰¦  «        k     °a| j                             ¦   «          | j        j                             ¦   «         ƒ d {V —† | j	                             ¦   «         ƒ d {V —†}|dk    r9| j
        j                             ¦   «         ƒ d {V —†}t          d|› d|› �¦  «        ‚d S )NrÈ   rÉ   r   zModal bulk upload failed (exit z): )r§   rÊ   r�   rË   rÌ   rÍ   rÎ   rÏ   rÐ   r[   ÚstderrÚreadre   )rÑ   rÒ   rÓ   Ú	exit_codeÚstderr_textrÕ   ÚpayloadrP   s        €€€r   Ú_bulkz2ModalEnvironment._modal_bulk_upload.<locals>._bulkG  s}  øè è € ØœÔ+×/Ò/°¸¸cÑBÔBÐBÐBÐBÐBÐBÐBˆDð ˆFØÔ/ˆJØ�3˜w™<œ<Ò'Ð'Ø”
× Ò  ¨°¸Ñ0CÐ)CÔ!DÑEÔEÐEØ”jÔ&×*Ò*Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ø˜*Ñ$�ð �3˜w™<œ<Ò'Ð'ð
 ŒJ× Ò Ñ"Ô"Ð"Ø”*Ô"×&Ò&Ñ(Ô(Ð(Ð(Ð(Ð(Ð(Ð(Ð(à"œiŸmšm™oœoÐ-Ð-Ð-Ð-Ð-Ð-ˆIØ˜AŠ~ˆ~Ø$(¤KÔ$4×$8Ò$8Ñ$:Ô$:Ð:Ð:Ð:Ð:Ð:Ð:�Ý"ØQ°iÐQÐQÀKÐQÐQñô ð ð ˆ~r   éx   rV   )ÚioÚBytesIOÚtarfileÚopenÚaddÚlstriprØ   rÙ   ÚgetvaluerÚ   r   r   r©   rj   )rP   rà   ÚbufÚtarr„   r†   ÚparentsÚ
mkdir_partrì   rÕ   rë   s   `        @@r   r¶   z#ModalEnvironment._modal_bulk_upload3  su  øøø€ ð ð 	ØˆFåŒj‰lŒlˆÝŒ\ #¨FÐ3Ñ3Ô3ð 	D°sØ*/ð Dð DÑ&�	˜;Ø—’˜	¨;×+=Ò+=¸cÑ+BÔ+B�ÑCÔCÐCÐCðDð	Dð 	Dð 	Dñ 	Dô 	Dð 	Dð 	Dð 	Dð 	Dð 	Dð 	Døøøð 	Dð 	Dð 	Dð 	Dõ Ô" 3§<¢<¡>¤>Ñ2Ô2×9Ò9¸'ÑBÔBˆå$ UÑ+Ô+ˆÝ)¨'Ñ2Ô2ˆ
ØÐ;Ð;Ð;ˆð	ð 	ð 	ð 	ð 	ð 	ð 	ð, 	Œ×"Ò" 5 5¡7¤7°CÐ"Ñ8Ô8Ð8Ð8Ð8s   ±3A1Á1A5Á8A5Údestc                 óÖ   ‡ — ˆ fd„}‰ j                               |¦   «         d¬¦  «        }t          |t          ¦  «        r|                     ¦   «         }|                     |¦  «         dS )zºDownload remote .hermes/ as a tar archive.

        Modal sandboxes always run as root, so /root/.hermes is hardcoded
        (consistent with iter_sync_files call on line 269).
        c               “   ó  •K  — ‰j         j                             ddd¦  «        ƒ d {V —†} | j        j                             ¦   «         ƒ d {V —†}| j                             ¦   «         ƒ d {V —†}|dk    rt          d|› d�¦  «        ‚|S )NrÈ   rÉ   ztar cf - -C / root/.hermesr   z!Modal bulk download failed (exit ú))r§   rÊ   r�   Ústdoutrè   r[   re   )rÑ   r   ré   rP   s      €r   Ú	_downloadz8ModalEnvironment._modal_bulk_download.<locals>._downloade  sº   øè è € ØœÔ+×/Ò/Ø˜Ð:ñô ð ð ð ð ð ð ˆDð œÔ)×-Ò-Ñ/Ô/Ð/Ð/Ð/Ð/Ð/Ð/ˆDØ"œiŸmšm™oœoÐ-Ð-Ð-Ð-Ð-Ð-ˆIØ˜AŠ~ˆ~Ý"Ð#SÀyÐ#SÐ#SÐ#SÑTÔTÐTØˆKr   rí   rV   N)r©   rj   r#   r$   ÚencodeÚwrite_bytes)rP   rù   rþ   Ú	tar_bytess   `   r   r·   z%ModalEnvironment._modal_bulk_download_  s{   ø€ ð	ð 	ð 	ð 	ð 	ð ”L×.Ò.¨y¨y©{¬{ÀCÐ.ÑHÔHˆ	Ý�i¥Ñ%Ô%ð 	+Ø!×(Ò(Ñ*Ô*ˆIØ×Ò˜Ñ#Ô#Ð#Ð#Ð#r   Úremote_pathsc                 ó|   ‡ ‡— t          |¦  «        Šˆˆ fd„}‰ j                              |¦   «         d¬¦  «         dS )z#Batch-delete remote files via exec.c               “   ó˜   •K  — ‰j         j                             dd‰¦  «        ƒ d {V —†} | j                             ¦   «         ƒ d {V —† d S )NrÈ   rÉ   )r§   rÊ   r�   r[   )rÑ   Úrm_cmdrP   s    €€r   Ú_rmz+ModalEnvironment._modal_delete.<locals>._rmx  s]   øè è € ØœÔ+×/Ò/°¸¸fÑEÔEÐEÐEÐEÐEÐEÐEˆDØ”)—-’-‘/”/Ð!Ð!Ð!Ð!Ð!Ð!Ð!Ð!Ð!r   é   rV   N)r   r©   rj   )rP   r  r  r  s   `  @r   rµ   zModalEnvironment._modal_deletet  sX   øø€ å" <Ñ0Ô0ˆð	"ð 	"ð 	"ð 	"ð 	"ð 	"ð 	Œ×"Ò" 3 3¡5¤5°"Ð"Ñ5Ô5Ð5Ð5Ð5r   c                 ó8   — | j                              ¦   «          dS )zDSync files to sandbox via FileSyncManager (rate-limited internally).N)rª   r¸   rO   s    r   Ú_before_executez ModalEnvironment._before_execute~  s   € àÔ×ÒÑ!Ô!Ð!Ð!Ð!r   Frí   )ÚloginrW   Ú
stdin_dataÚ
cmd_stringr
  r  c                óœ   ‡‡‡‡‡— | j         Š| j        Šˆˆfd„}dt          t          t          f         fˆˆˆˆˆfd„}t          ||¬¦  «        S )zEReturn a _ThreadedProcessHandle wrapping an async Modal sandbox exec.c                  ód   •— ‰                      ‰ j                             ¦   «         d¬¦  «         d S )Nr  rV   )rj   Ú	terminater�   )r˜   Úworkers   €€r   Úcancelz*ModalEnvironment._run_bash.<locals>.cancel�  s1   ø€ Ø× Ò  Ô!2×!6Ò!6Ñ!8Ô!8À"Ð ÑEÔEÐEÐEÐEr   r   c                  óX   •— ˆˆˆˆfd„} ‰                       | ¦   «         ‰dz   ¬¦  «        S )Nc               “   óF  •K  — dg} ‰r|                       dd‰g¦  «         n|                       d‰g¦  «          ‰j        j        | d‰	iŽƒ d {V —†}|j        j                             ¦   «         ƒ d {V —†}|j        j                             ¦   «         ƒ d {V —†}|j                             ¦   «         ƒ d {V —†}t          |t          ¦  «        r| 	                    dd¬¦  «        }t          |t          ¦  «        r| 	                    dd¬¦  «        }|}|r|r|› d|› �n|}||fS )	NrÈ   z-lrÉ   rW   zutf-8Úreplace)ÚerrorsÚ
)
r’   rÊ   r�   rý   rè   rç   r[   r#   ÚbytesrÚ   )
ÚargsÚprocessrý   rç   ré   Úoutputr  r
  r˜   rW   s
         €€€€r   Ú_doz8ModalEnvironment._run_bash.<locals>.exec_fn.<locals>._do‘  so  øè è € Ø�x�Øð 4Ø—K’K  t¨ZÐ 8Ñ9Ô9Ð9Ð9à—K’K  zÐ 2Ñ3Ô3Ð3Ø 0 ¤Ô 0°$Ð HÀÐ HÐ HÐHÐHÐHÐHÐHÐH�Ø&œ~Ô2×6Ò6Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ð8�Ø&œ~Ô2×6Ò6Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ð8�Ø")¤,×"2Ò"2Ñ"4Ô"4Ð4Ð4Ð4Ð4Ð4Ð4�	Ý˜f¥eÑ,Ô,ð FØ#Ÿ]š]¨7¸9˜]ÑEÔE�FÝ˜f¥eÑ,Ô,ð FØ#Ÿ]š]¨7¸9˜]ÑEÔE�FØ�Øð IØ6<ÐH Ð2Ð2¨&Ð2Ð2Ð2À&�FØ˜yÐ(Ð(r   rU   rV   )rj   )r  r  r
  r˜   rW   r  s    €€€€€r   Úexec_fnz+ModalEnvironment._run_bash.<locals>.exec_fn�  sP   ø€ ð)ð )ð )ð )ð )ð )ð )ð )ð& ×'Ò'¨¨©¬°wÀ±|Ð'ÑDÔDÐDr   )Ú	cancel_fn)r§   r©   Útupler$   r•   r   )	rP   r  r
  rW   r  r  r  r˜   r  s	    ```   @@r   Ú	_run_bashzModalEnvironment._run_bash†  sœ   øøøøø€ ð ”-ˆØ”ˆð	Fð 	Fð 	Fð 	Fð 	Fð 	Fð	E��s¥C˜xœð 	Eð 	Eð 	Eð 	Eð 	Eð 	Eð 	Eð 	Eð 	Eð 	Eõ, & g¸Ð@Ñ@Ô@Ð@r   c                 ó8  ‡ — ‰ j         €dS ‰ j        r3t                               d¦  «         ‰ j                             ¦   «          ‰ j        r±	 ˆ fd„}	 ‰ j                              |¦   «         d¬¦  «        }n# t          $ r d}Y nw xY w|r>t          ‰ j
        |¦  «         t                               d|dd…         ‰ j
        ¦  «         n2# t          $ r%}t                               d|¦  «         Y d}~nd}~ww xY w	 ‰ j                             ‰ j         j                             ¦   «         d	¬¦  «         n# t          $ r Y nw xY w‰ j                             ¦   «          d‰ _         d‰ _        dS # ‰ j                             ¦   «          d‰ _         d‰ _        w xY w)
z>Snapshot the filesystem (if persistent) then stop the sandbox.Nz$Modal: syncing files from sandbox...c               “   ó^   •K  — ‰j         j                             ¦   «         ƒ d {V —†} | j        S r   )r§   Úsnapshot_filesystemr�   Ú	object_id)ÚimgrP   s    €r   Ú	_snapshotz+ModalEnvironment.cleanup.<locals>._snapshot³  s7   øè è € Ø $¤Ô A× EÒ EÑ GÔ GÐGÐGÐGÐGÐGÐG�CØœ=Ð(r   rx   rV   z/Modal: saved filesystem snapshot %s for task %sr€   z%Modal: filesystem snapshot failed: %sr  )r§   rª   r«   r¬   Ú	sync_backr¥   r©   rj   r±   r,   r¦   r³   r  r�   ro   r¨   )rP   r%  r'   r¿   s   `   r   ÚcleanupzModalEnvironment.cleanup¨  sö  ø€ àŒ=Ð ØˆFàÔð 	+Ý�KŠKÐ>Ñ?Ô?Ð?ØÔ×(Ò(Ñ*Ô*Ð*àÔð 	KðKð)ð )ð )ð )ð )ð'Ø"&¤,×"<Ò"<¸Y¸Y¹[¼[ÐRTÐ"<Ñ"UÔ"U�K�KøÝ ð 'ð 'ð 'Ø"&�K�K�Kð'øøøð ð Ý*¨4¬=¸+ÑFÔFÐFÝ—K’KØIØ# C R CÔ(¨$¬-ñô ð øøõ ð Kð Kð KÝ—’ÐFÈÑJÔJÐJÐJÐJÐJÐJÐJøøøøðKøøøð	ØŒL×&Ò& t¤}Ô'>×'BÒ'BÑ'DÔ'DÈbÐ&ÑQÔQÐQÐQøÝð 	ð 	ð 	ØˆDð	øøøð ŒL×ÒÑÔÐØ ˆDŒMØˆDŒIˆIˆIøð ŒL×ÒÑÔÐØ ˆDŒMØˆDŒIÐÐÐÐsg   ÁC Á$A8 Á7C Á8BÂC ÂBÂAC Ã
C:ÃC5Ã5C:Ã>8D7 Ä6E0 Ä7
EÅE0 ÅEÅE0 Å0)F)ry   rx   NTrz   )r   N)rq   rr   rs   rt   Ú_stdin_modeÚ_snapshot_timeoutr$   r•   r   r�   r   ÚboolrQ   r´   rË   r‘   r  r¶   r   r·   rµ   r	  r  r'  Ú__classcell__)rÄ   s   @r   rv   rv   “   sâ  ø€ € € € € ðð ð €KØÐð
 ØØ9=Ø&*Ø ðvð vàðvð ðvð ð	vð
 ' t¨C°¨H¤~Ô6ðvð  $ðvð ðvð vð vð vð vð vðp9 sð 9¸ð 9Àð 9ð 9ð 9ð 9ð8 (Ðð*9¨¨U°3¸°8¬_Ô(=ð *9À$ð *9ð *9ð *9ð *9ðX$¨ð $°$ð $ð $ð $ð $ð*6¨$¨s¬)ð 6¸ð 6ð 6ð 6ð 6ð"ð "ð "ð "ð ;@Ø!$Ø+/ð Að  Að  A Cð  A°4ð  AØð Aà! D™jð Að  Að  Að  AðD$ð $ð $ð $ð $ð $ð $r   rv   r   ),rt   r]   rØ   rî   ÚloggingrÜ   rð   rL   Úpathlibr   Útypingr   r   Úhermes_constantsr   Útools.environments.baser   r   r	   r
   Útools.environments.file_syncr   r   r   r   r   Ú	getLoggerrq   r«   r   r   r�   r   r   r$   r    r  r*  r)   r,   r1   rF   rH   rv   r   r   r   ú<module>r3     s²  ððð ð €€€Ø €€€Ø 	€	€	€	Ø €€€Ø €€€Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø  Ð  Ð  Ð  Ð  Ð  Ð  Ð  à ,Ð ,Ð ,Ð ,Ð ,Ð ,ðð ð ð ð ð ð ð ð ð ð ð ðð ð ð ð ð ð ð ð ð ð ð ð ð ð 
ˆÔ	˜8Ñ	$Ô	$€à!�/Ñ#Ô#Ð&<Ñ<€Ø%Ð ð-˜ð -ð -ð -ð -ð,˜$ð , 4ð ,ð ,ð ,ð ,ð5 #ð 5¨#ð 5ð 5ð 5ð 5ð	¨Sð 	°U¸3À¹:ÀtÐ;KÔ5Lð 	ð 	ð 	ð 	ð Cð °cð ¸dð ð ð ð ð#ð # Sð #°s¸T±zð #ÈTð #ð #ð #ð #ð Sð ¨Sð ð ð ð ð@*ð *ð *ð *ð *ñ *ô *ð *ð@yð yð yð yð y�ñ yô yð yð yð yr   