§
    }Štj9 ã                   óÎ  — 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 d dlmZmZmZmZmZmZmZ d dlZdd	lmZ dd
lmZmZmZmZ ddl m!Z! ddl"m#Z#m$Z$m%Z% ddl&m'Z'm(Z( ddl)m*Z*m+Z+ ddl,m-Z-  e+j.        e/¦  «        Z0dZ1dZ2dZ3dZ4dZ5dZ6dZ7dZ8dZ9dZ:dZ;dZ<dZ=dZ>dZ?dZ@d eAd!eAd"eAfd#„ZBd$eCeDz  eAz  d"eCfd%„ZEe
 G d&„ d'¦  «        ¦   «         ZFe
 G d(„ d)¦  «        ¦   «         ZGe
 G d*„ d+¦  «        ¦   «         ZH G d,„ d-¦  «        ZId.eAeeA         z  d/eJdz  d"eKeAef         fd0„ZLd1ejM        d"eeK         fd2„ZNd1ejM        d"dfd3„ZO G d4„ d5¦  «        ZP G d6„ d7¦  «        ZQ G d8„ d9¦  «        ZR G d:„ d;¦  «        ZSd<e'd"eAfd=„ZTd<e'd eAd>eKeAef         dz  d?eKeAef         dz  d@ee!         dz  dAeCeDz  eAz  dz  dBeJdCeAd"eUeVeA         eKeAef         eKeAef         ee!         f         fdD„ZWd<e'dEe(dFeAdz  d"eKeAef         fdG„ZXddHœd<e'dIeAdFeAdz  d"e(fdJ„ZYddHœd<e'dKeAdFeAdz  d"ePfdL„ZZdMeAdFeAdz  d"eUeAeAdz  f         fdN„Z[dEe(d"eAfdO„Z\ddPdQœd<e'dReAdFeAdz  dSeCd"eAf
dT„Z]dS )Ué    N)ÚThreadPoolExecutor)Úcontextmanager)Ú	dataclassÚfield)ÚPath)Ú	token_hex)ÚAnyÚBinaryIOÚCallableÚIteratorÚListÚLiteralÚoverloadé   )Ú	constants)Ú
CachedHostÚdelete_pool_cacheÚread_pool_cacheÚsave_pool_cache)ÚVolume)ÚHfHubHTTPErrorÚSandboxCommandErrorÚSandboxError)ÚHfApiÚJobInfo)Ú	get_tokenÚlogging)Úparse_durationi?Ã  z
hf-sandboxzhf-sandbox-modeÚ	dedicatedÚpoolzhf-sandbox-poolzhf-sandbox-noncezpython:3.12iX  Ú24hé2   ú.)Ú	COMPLETEDÚERRORÚDELETEDÚCANCELEDé   z/.hf-sbx-servera#  set -e
d=/tmp/.sbx-server
if command -v wget >/dev/null 2>&1; then wget -q -O "$d" "$SBX_SERVER_URL"
elif command -v curl >/dev/null 2>&1; then curl -fsSL -o "$d" "$SBX_SERVER_URL"
else cp "$SBX_SERVER_MOUNT/sbx-server" "$d"; fi
chmod +x "$d"
unset SBX_SERVER_URL SBX_SERVER_MOUNT
exec "$d"
Úhf_tokenÚnonceÚreturnc                 ó´   — t          j        |                      ¦   «         d|› �                     ¦   «         t          j        ¦  «                             ¦   «         S )a5  Derive the per-sandbox auth token from the user's HF token and the sandbox nonce.

    Stateless: any machine holding the same HF token can recompute it from the
    nonce stored in the job's labels, so `Sandbox.connect(job_id)` needs no local state.
    The HF token itself is never sent to the sandbox.
    zhf-sandbox:)ÚhmacÚnewÚencodeÚhashlibÚsha256Ú	hexdigest)r)   r*   s     úV/var/www/html/CA-Chatbot/venv/lib/python3.11/site-packages/huggingface_hub/_sandbox.pyÚ_derive_sandbox_tokenr4   ^   sE   € õ Œ8�H—O’OÑ%Ô%Ð'<°UÐ'<Ð'<×'CÒ'CÑ'EÔ'EÅwÄ~ÑVÔV×`Ò`ÑbÔbÐbó    Údurationc                 óv   — t          | t          t          f¦  «        rt          | ¦  «        S t          | ¦  «        S )zBParse a duration like 300, "300s", "10m", "2h", "1d" into seconds.)Ú
isinstanceÚintÚfloatr   )r6   s    r3   Ú_duration_to_secsr;   h   s2   € å�(�S¥%˜LÑ)Ô)ð Ý�8‰}Œ}ÐÝ˜(Ñ#Ô#Ð#r5   c                   ó�   — e Zd ZU dZedz  ed<   eed<   eed<   dZedz  ed<   dZe	ed<   d	Z
eed
<   ede	fd„¦   «         Zdefd„ZdS )ÚSandboxCommandResultz?Result of a command executed in a sandbox with [`Sandbox.run`].NÚ	exit_codeÚstdoutÚstderrÚsignalFÚ	timed_outr   Úduration_msr+   c                 ó   — | j         dk    S )Nr   )r>   ©Úselfs    r3   ÚokzSandboxCommandResult.okz   s   € àŒ~ Ò"Ð"r5   c                 ó�   — t          | j        ¦  «        dk    r| j        n| j        d d…         dz   }d| j        › d|›d| j        › d�S )NéP   éM   z...zSandboxCommandResult(exit_code=z	, stdout=z, duration_ms=ú))Úlenr?   r>   rC   )rF   Úouts     r3   Ú__repr__zSandboxCommandResult.__repr__~   sX   € Ý  ¤Ñ-Ô-°Ò3Ð3ˆdŒkˆk¸¼ÀSÀbÀSÔ9IÈEÑ9QˆØr°´ÐrÐrÈ#ÐrÐrÐ_cÔ_oÐrÐrÐrÐrr5   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r9   Ú__annotations__ÚstrrA   rB   ÚboolrC   ÚpropertyrG   rN   © r5   r3   r=   r=   o   s¹   € € € € € € àIÐIà�T‰zÐÐÑØ€K€K�KØ€K€K�KØ€FˆC�$‰JÐÐÑØ€IˆtÐÐÑØ€K�ÐÐÑàð#�Dð #ð #ð #ñ „Xð#ðs˜#ð sð sð sð sð sð sr5   r=   c                   ó°   — e Zd ZU dZeed<   eee         z  ed<    edd¬¦  «        Z	ded<   dZ
edz  ed	<   dZedz  ed
<   dZeed<   dZedz  ed<   dd„ZdS )ÚSandboxProcessa�  A background process started in a sandbox with [`Sandbox.run`]`(..., background=True)`.

    List a sandbox's processes with [`Sandbox.processes`] and stop one with [`SandboxProcess.kill`].
    Completed processes stay in the listing until the sandbox is deleted, so `running` and
    `exit_code` tell whether a process is still alive or already exited (as of when it was listed).
    ÚpidÚcmdF)ÚreprÚcompareÚSandboxÚ_sandboxNÚtagÚstarted_at_msTÚrunningr>   r+   c                 óL   — | j                              dd| j        › �¦  «         dS )z:Terminate the background process (idempotent server-side).ÚDELETEz/processes/N)r_   Ú_requestrZ   rE   s    r3   ÚkillzSandboxProcess.kill–   s+   € àŒ×Ò˜xÐ)A°t´xÐ)AÐ)AÑBÔBÐBÐBÐBr5   ©r+   N)rO   rP   rQ   rR   r9   rS   rT   r   r   r_   r`   ra   rb   rU   r>   rf   rW   r5   r3   rY   rY   ƒ   sÆ   € € € € € € ðð ð 
€H€H�HØ	ˆt�CŒy‰ÐÐÑð  ˜% U°EÐ:Ñ:Ô:€HˆiÐ:Ð:Ñ:Ø€Cˆˆt‰ÐÐÑØ $€M�3˜‘:Ð$Ð$Ñ$Ø€GˆTÐÐÑØ €Iˆs�T‰zÐ Ð Ñ ðCð Cð Cð Cð Cð Cr5   rY   c                   ój   — e Zd ZU dZeed<   eed<   ed         ed<   eed<   dZedz  ed<   d	Z	eed
<   dS )Ú	FileEntryz%A file or directory inside a sandbox.ÚnameÚpath)ÚfileÚdirÚsymlinkÚtypeÚsizeNÚmtime_msÚ Úmode)
rO   rP   rQ   rR   rT   rS   r   r9   rq   rs   rW   r5   r3   ri   ri   ›   sd   € € € € € € à/Ð/à
€I€I�IØ
€I€I�IØ
Ð*Ô
+Ð+Ð+Ñ+Ø
€I€I�IØ€Hˆc�D‰jÐÐÑØ€Dˆ#€N€N�N€N€Nr5   ri   c            	       óÂ  — e Zd ZdZdZdZdZd#d	„Zd
ede	fd„Z
d$d
ededefd„Zd%d
edee	z  ez  dedz  ddfd„Zd%deez  d
ededz  ddfd„Zd
edeez  ddfd„Zdedeeeef                  fd„Zdee         deegef         dee         fd„Zd
ededee	         fd„Zd
ede	dedz  ddfd„Zd
edee         fd„Zd
edefd„Zd
edefd„Zd&d
ed eddfd!„Zd
eddfd"„Z dS )'ÚSandboxFilesu=  Filesystem operations inside a sandbox, available as [`Sandbox.files`].

    In shared (pool) mode, paths are rooted at the sandbox's private home â€” the
    only place its code can write â€” so a leading `/` is taken relative to that
    home. In dedicated mode, paths are absolute on the container filesystem.
    i    é   é   Úsandboxr^   r+   Nc                 ó   — || _         d S ©N)r_   ©rF   rx   s     r3   Ú__init__zSandboxFiles.__init__¶   s   € ØˆŒˆˆr5   rk   c                 óê   — |                       |¦  «        j        }|| j        k    r)d                     |                      ||¦  «        ¦  «        S | j                             ddd|i¬¦  «        }|j        S )z=Read a file from the sandbox and return its content as bytes.r5   ÚGETú/files/readrk   ©Úparams)Ústatrp   ÚPARALLEL_THRESHOLDÚjoinÚ_read_rangesr_   re   Úcontent)rF   rk   rp   Úresponses       r3   ÚreadzSandboxFiles.read¹   sn   € à�yŠy˜‰ŒÔ#ˆØ�$Ô)Ò)Ð)Ø—8’8˜D×-Ò-¨d°DÑ9Ô9Ñ:Ô:Ð:Ø”=×)Ò)¨%°ÈÐPTÀ~Ð)ÑVÔVˆØÔÐr5   úutf-8Úencodingc                 óR   — |                       |¦  «                             |¦  «        S )z@Read a file from the sandbox and return its content as a string.)rˆ   Údecode)rF   rk   rŠ   s      r3   Ú	read_textzSandboxFiles.read_textÁ   s    € à�yŠy˜‰Œ×%Ò% hÑ/Ô/Ð/r5   Údatars   c                 ó`  — t          |t          ¦  «        r|                     ¦   «         }n)t          |t          ¦  «        s|                     ¦   «         }t          |¦  «        | j        k    r|                      |||¦  «         dS d|i}|�||d<   | j         	                    dd||¬¦  «         dS )zHWrite content to a file in the sandbox (parent directories are created).Nrk   rs   ÚPUTú/files/write©r�   r†   )
r8   rT   r/   Úbytesrˆ   rL   rƒ   Ú_write_rangesr_   re   )rF   rk   rŽ   rs   r�   s        r3   ÚwritezSandboxFiles.writeÅ   s°   € å�d�CÑ Ô ð 	Ø—;’;‘=”=ˆDˆDÝ˜D¥%Ñ(Ô(ð 	Ø—9’9‘;”;ˆDÝˆt‰9Œ9�tÔ.Ò.Ð.Ø×Ò˜t T¨4Ñ0Ô0Ð0ØˆFØ˜$�ˆØÐØ!ˆF�6‰NØŒ×Ò˜u n¸VÈTÐÑRÔRÐRÐRÐRr5   Ú
local_pathc                 óZ  — t          |¦  «                             ¦   «         j        }|| j        k    r8|                      |t          |¦  «                             ¦   «         |¦  «         dS t          |d¦  «        5 }|                      |||¬¦  «         ddd¦  «         dS # 1 swxY w Y   dS )z#Upload a local file to the sandbox.NÚrb)rs   )r   r‚   Úst_sizerƒ   r”   Ú
read_bytesÚopenr•   )rF   r–   rk   rs   rp   Úfs         r3   ÚuploadzSandboxFiles.uploadÓ   sæ   € å�JÑÔ×$Ò$Ñ&Ô&Ô.ˆØ�$Ô)Ò)Ð)Ø×Ò˜t¥T¨*Ñ%5Ô%5×%@Ò%@Ñ%BÔ%BÀDÑIÔIÐIØˆFÝ�*˜dÑ#Ô#ð 	+ qØ�JŠJ�t˜Q TˆJÑ*Ô*Ð*ð	+ð 	+ð 	+ñ 	+ô 	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+øøøð 	+ð 	+ð 	+ð 	+ð 	+ð 	+s   Á:B Â B$Â'B$c                 ó   — |                       |¦  «        j        }|| j        k    rYt          |d¦  «        5 }|                      ||¦  «        D ]}|                     |¦  «         Œ	 ddd¦  «         n# 1 swxY w Y   dS | j                             ddd|i¬¦  «        5 }t          |d¦  «        5 }|                     d¬¦  «        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 )	z!Download a file from the sandbox.ÚwbNr~   r   rk   r€   rv   )Ú
chunk_size)	r‚   rp   rƒ   r›   r…   r•   r_   Ú_streamÚ
iter_bytes)rF   rk   r–   rp   rœ   Úpartr‡   Úchunks           r3   ÚdownloadzSandboxFiles.downloadÜ   sÛ  € à�yŠy˜‰ŒÔ#ˆØ�$Ô)Ò)Ð)Ý�j $Ñ'Ô'ð "¨1Ø ×-Ò-¨d°DÑ9Ô9ð "ð "�DØ—G’G˜D‘M”M�M�Mð"ð"ð "ð "ñ "ô "ð "ð "ð "ð "ð "ð "øøøð "ð "ð "ð "ð ˆFØŒ]×"Ò" 5¨-ÀÈÀÐ"ÑOÔOð 	#ÐS[Ý�j $Ñ'Ô'ð #¨1Ø%×0Ò0¸KÐ0ÑHÔHð #ð #�EØ—G’G˜E‘N”N�N�Nð#ð#ð #ð #ñ #ô #ð #ð #ð #ð #ð #ð #øøøð #ð #ð #ð #ð	#ð 	#ð 	#ñ 	#ô 	#ð 	#ð 	#ð 	#ð 	#ð 	#ð 	#ð 	#øøøð 	#ð 	#ð 	#ð 	#ð 	#ð 	#sG   ¶/A2Á2A6Á9A6ÂDÂ//C+ÃDÃ+C/	Ã/DÃ2C/	Ã3DÄDÄ
Drp   c                 óP   ‡‡— | j         Šˆˆfd„t          d‰‰¦  «        D ¦   «         S )Nc                 ó:   •— g | ]}|t          ‰‰|z
  ¦  «        f‘ŒS rW   )Úmin)Ú.0Úoffsetr¤   rp   s     €€r3   ú
<listcomp>z(SandboxFiles._ranges.<locals>.<listcomp>ë   s,   ø€ ÐXÐXÐX¸��˜U D¨6¡MÑ2Ô2Ð3ÐXÐXÐXr5   r   )ÚPARALLEL_CHUNK_SIZEÚrange)rF   rp   r¤   s    `@r3   Ú_rangeszSandboxFiles._rangesé   s6   øø€ ØÔ(ˆØXÐXÐXÐXÐXÅ%ÈÈ4ÐQVÑBWÔBWÐXÑXÔXÐXr5   ÚitemsÚfnc                 óÞ   — t          | j        t          |¦  «        ¦  «        }t          |¦  «        5 }t	          |                     ||¦  «        ¦  «        cddd¦  «         S # 1 swxY w Y   dS )zÙRun `fn(item)` over items concurrently.

        All workers share the sandbox's `httpx.Client`, which is thread-safe and pools
        connections, so parallel transfers fan out over several streams at once.
        N)r¨   ÚPARALLEL_MAX_WORKERSrL   r   ÚlistÚmap)rF   r¯   r°   ÚworkersÚexecutors        r3   Ú	_parallelzSandboxFiles._parallelí   s¤   € õ �dÔ/µ°U±´Ñ<Ô<ˆÝ Ñ(Ô(ð 	1¨HÝ˜Ÿš R¨Ñ/Ô/Ñ0Ô0ð	1ð 	1ð 	1ð 	1ñ 	1ô 	1ð 	1ð 	1ð 	1ð 	1ð 	1ð 	1øøøð 	1ð 	1ð 	1ð 	1ð 	1ð 	1s   ²#A"Á"A&Á)A&c                 ó¦   ‡ ‡— dt           t          t          f         dt          fˆˆ fd„}‰                      ‰                      |¦  «        |¦  «        S )NÚrngr+   c                 ó^   •— | \  }}‰j                              dd‰||dœ¬¦  «        }|j        S )Nr~   r   )rk   rª   Úlengthr€   )r_   re   r†   )r¹   rª   r»   r‡   rk   rF   s       €€r3   Úfetchz(SandboxFiles._read_ranges.<locals>.fetchø   sE   ø€ Ø ‰NˆF�FØ”}×-Ò-Ø�}°dÀfÐX^Ð-_Ð-_ð .ñ ô ˆHð Ô#Ð#r5   )Útupler9   r“   r·   r®   )rF   rk   rp   r¼   s   ``  r3   r…   zSandboxFiles._read_ranges÷   s_   øø€ ð	$•u�S¥#˜X”ð 	$­5ð 	$ð 	$ð 	$ð 	$ð 	$ð 	$ð 	$ð �~Š~˜dŸlšl¨4Ñ0Ô0°%Ñ8Ô8Ð8r5   c                 óÂ   ‡ ‡‡‡— dt           t          t          f         dd fˆˆˆˆ fd„}‰                      ‰                      t	          ‰¦  «        ¦  «        |¦  «         d S )Nr¹   r+   c           	      ó|   •— | \  }}‰|dœ}‰�‰|d<   ‰j                              dd|‰|||z   …         ¬¦  «         d S )N)rk   rª   rs   r�   r‘   r’   ©r_   re   )r¹   rª   r»   r�   rŽ   rs   rk   rF   s       €€€€r3   Úpushz(SandboxFiles._write_ranges.<locals>.push  s`   ø€ Ø ‰NˆF�FØ.2¸fÐ%EÐ%EˆFØÐØ!%��v‘ØŒM×"Ò" 5¨.ÀÐQUÐV\Ð_eÐhnÑ_nÐVnÔQoÐ"ÑpÔpÐpÐpÐpr5   )r½   r9   r·   r®   rL   )rF   rk   rŽ   rs   rÁ   s   ```` r3   r”   zSandboxFiles._write_ranges  s‚   øøøø€ ð	q•e�C¥˜H”oð 	q¨$ð 	qð 	qð 	qð 	qð 	qð 	qð 	qð 	qð 	qð 	�Š�t—|’|¥C¨¡I¤IÑ.Ô.°Ñ5Ô5Ð5Ð5Ð5r5   c                 óˆ   — | j                              ddd|i¬¦  «        }d„ |                     ¦   «         d         D ¦   «         S )z List a directory in the sandbox.r~   z/files/listrk   r€   c                 ó&   — g | ]}t          d i |¤Ž‘ŒS )rW   )ri   )r©   Úentrys     r3   r«   z%SandboxFiles.list.<locals>.<listcomp>  s&   € ÐKÐKÐK u•	Ð"Ð"˜EÐ"Ð"ÐKÐKÐKr5   Úentries)r_   re   Újson©rF   rk   r‡   s      r3   r³   zSandboxFiles.list  sD   € à”=×)Ò)¨%°ÈÐPTÀ~Ð)ÑVÔVˆØKÐK°·²±´À	Ô0JÐKÑKÔKÐKr5   c                 ó|   — | j                              ddd|i¬¦  «        }t          di |                     ¦   «         ¤ŽS )z3Get metadata of a file or directory in the sandbox.r~   z/files/statrk   r€   rW   )r_   re   ri   rÆ   rÇ   s      r3   r‚   zSandboxFiles.stat  s?   € à”=×)Ò)¨%°ÈÐPTÀ~Ð)ÑVÔVˆÝÐ+Ð+˜8Ÿ=š=™?œ?Ð+Ð+Ð+r5   c                 óz   — 	 |                       |¦  «         dS # t          $ r}|j        dk    rY d}~dS ‚ d}~ww xY w)z+Check whether a path exists in the sandbox.Ti”  NF)r‚   r   Ústatus_code)rF   rk   Úes      r3   ÚexistszSandboxFiles.exists  sW   € ð	Ø�IŠI�d‰OŒOˆOØ�4øÝð 	ð 	ð 	ØŒ} Ò#Ð#Ø�u�u�u�u�uØøøøøð	øøøs   ‚ ™
:£5´5µ:FÚ	recursivec                 óV   — d|i}|rd|d<   | j                              dd|¬¦  «         dS )z*Delete a file or directory in the sandbox.rk   Ú1rÍ   rd   z/files/deleter€   NrÀ   )rF   rk   rÍ   r�   s       r3   ÚdeletezSandboxFiles.delete  s@   € à˜$�ˆØð 	&Ø"%ˆF�;ÑØŒ×Ò˜x¨ÀÐÑHÔHÐHÐHÐHr5   c                 óD   — | j                              ddd|i¬¦  «         dS )z0Create a directory (and parents) in the sandbox.ÚPOSTz/files/mkdirrk   r€   NrÀ   )rF   rk   s     r3   ÚmkdirzSandboxFiles.mkdir&  s)   € àŒ×Ò˜v ~¸vÀt¸nÐÑMÔMÐMÐMÐMr5   )rx   r^   r+   N)r‰   rz   )F)!rO   rP   rQ   rR   rƒ   r¬   r²   r|   rT   r“   rˆ   r�   r
   r•   r   r�   r¥   r9   r   r½   r®   r	   r   r·   r…   r”   ri   r³   r‚   rU   rÌ   rÐ   rÓ   rW   r5   r3   ru   ru   §   sï  € € € € € ðð ð )ÐØ)ÐØÐð ð  ð  ð  ð ˜ð   ð  ð  ð  ð  ð0ð 0˜cð 0¨Sð 0¸sð 0ð 0ð 0ð 0ðSð S˜#ð S S¨5¡[°8Ñ%;ð SÀ3ÈÁ:ð SÐY]ð Sð Sð Sð Sð+ð +  t¡ð +°3ð +¸cÀD¹jð +ÐTXð +ð +ð +ð +ð#˜Sð #¨c°D©jð #¸Tð #ð #ð #ð #ðY˜Cð Y D¨¨s°C¨x¬Ô$9ð Yð Yð Yð Yð1˜t Cœyð 1¨h¸°u¸c°zÔ.Bð 1ÀtÈCÄyð 1ð 1ð 1ð 1ð9 ð 9¨Cð 9°D¸´Kð 9ð 9ð 9ð 9ð6 #ð 6¨Uð 6¸#À¹*ð 6Èð 6ð 6ð 6ð 6ðL˜ð L  i¤ð Lð Lð Lð Lð
,˜ð , ð ,ð ,ð ,ð ,ð
˜3ð  4ð ð ð ð ðIð I˜3ð I¨4ð I¸Dð Ið Ið Ið IðN˜#ð N $ð Nð Nð Nð Nð Nð Nr5   ru   r[   Úshellc                 ó¼   — |du r$t          | t          ¦  «        st          d¦  «        ‚|du r$t          | t          ¦  «        rt          d¦  «        ‚d| i}|�||d<   |S )zQBuild the `cmd`/`shell` part of an `/exec` payload, validating their consistency.TzCshell=True requires `cmd` to be a shell command string, not a list.FzRshell=False requires `cmd` to be an argv list (e.g. ['echo', 'hi']), not a string.r[   NrÔ   )r8   rT   Ú
ValueError)r[   rÔ   Úpayloads      r3   Ú_exec_payloadrØ   +  sl   € à�€}€}�Z¨­SÑ1Ô1€}ÝÐ^Ñ_Ô_Ð_Ø�€~€~�* S­#Ñ.Ô.€~ÝÐmÑnÔnÐnØ$ c˜l€GØÐØ ˆ�ÑØ€Nr5   r‡   c              #   ó    K  — |                       ¦   «         D ]6}|sŒt          j        |¦  «        }|                     d¦  «        dk    r|V — Œ7dS )zJIterate NDJSON events from a streaming response, skipping keepalive pings.ÚeventÚpingN)Ú
iter_linesrÆ   ÚloadsÚget)r‡   ÚlinerÚ   s      r3   Ú_iter_eventsrà   7  sf   è è € à×#Ò#Ñ%Ô%ð ð ˆØð 	ØÝ”
˜4Ñ Ô ˆØ�9Š9�WÑÔ Ò'Ð'ØˆKˆKˆKøðð r5   c                 óâ   — |                       ¦   «          	 |                      ¦   «         d         }n# t          $ r | j        dd…         }Y nw xY wt	          d| j        › d|› �| j        ¬¦  «        ‚)zQRead the error body and raise a SandboxError (works for streaming responses too).ÚerrorNiô  zSandbox API error (z): )rÊ   )rˆ   rÆ   Ú	ExceptionÚtextr   rÊ   )r‡   Úmessages     r3   Ú_raise_for_statusræ   A  s‚   € à‡M‚M�O„O€Oð&Ø—-’-‘/”/ 'Ô*ˆˆøÝð &ð &ð &Ø”-   Ô%ˆˆˆð&øøøå
ÐO¨XÔ-AÐOÐOÀgÐOÐOÐ]eÔ]qÐ
rÑ
rÔ
rÐrs   –1 ±AÁAc                   ó&  — e Zd ZdZdddœdedededz  d	ed
edededededdfd„Zedddœde	d
edededededd fd„¦   «         Z
ededz  fd„¦   «         Zdededej        fd„Zedededeej                 fd„¦   «         Zdd„Zdd„Zdeddfd„ZdS )Ú_SandboxServeruE  HTTP transport to one `sbx-server` instance â€” a dedicated job or a shared host.

    Owns the `httpx.Client`, the base URL and the auth headers.
    In dedicated mode a server is paired 1:1 with its [`Sandbox`
    In pool mode one server (one host job) is shared by many sandboxes, and `live`/`capacity` track packing.
    é
   r   )Úmax_connectionsÚcapacityÚjob_idÚownerÚimageNÚbase_urlr*   Úsandbox_tokenÚapirê   rë   r+   c       	         ó0  — || _         || _        || _        || _        || _        || _        t          |¦  «        | _        || _        |	| _	        d| _
        d| _        t          j        d| j        › �|dœt          j        ||¬¦  «        d¬¦  «        | _        d S )Nr   TúBearer ©ÚAuthorizationzX-Sandbox-Token)rê   Úmax_keepalive_connections)ÚheadersÚlimitsÚfollow_redirects)rì   rí   Ú_imagerï   r*   Ú_apiÚ_effective_tokenÚ_auth_tokenÚ_sandbox_tokenrë   ÚliveÚverifiedÚhttpxÚClientÚLimitsÚ_client)
rF   rì   rí   rî   rï   r*   rð   rñ   rê   rë   s
             r3   r|   z_SandboxServer.__init__S  s°   € ð ˆŒØˆŒ
ØˆŒØ ˆŒð ˆŒ
ØˆŒ	Ý+¨CÑ0Ô0ˆÔØ+ˆÔà ˆŒØˆŒ	ð ˆŒõ ”|à!=¨4Ô+;Ð!=Ð!=Ø#0ðð õ ”<°Ð[jÐkÑkÔkØ!ð
ñ 
ô 
ˆŒˆˆr5   Újobc                óz   —  | |j         |j        j        |j        p|j        t          |¦  «        |||||¬¦	  «	        S )zIBuild a server from a freshly fetched job (reads its exposed server URL).©	rì   rí   rî   rï   r*   rð   rñ   rê   rë   )Úidrí   rj   Údocker_imageÚspace_idÚ_find_server_url)Úclsr  r*   rð   rñ   rê   rë   s          r3   Úfrom_jobz_SandboxServer.from_job{  sP   € ð ˆsØ”6Ø”)”.ØÔ"Ð2 c¤lÝ% cÑ*Ô*ØØ'ØØ+Øð

ñ 

ô 

ð 
	
r5   c                 ó   — | j         S rz   )rú   rE   s    r3   rî   z_SandboxServer.image“  s
   € àŒ{Ðr5   Úmethodrk   c                 óÊ   — |                      dt          j        dd¬¦  «        ¦  «        } | j        j        || j        |z   fd|i|¤Ž}|j        dk    rt          |¦  «         |S )z@Request to the in-job server. Raises SandboxError on API errors.Útimeoutg      N@ç      $@©Úconnecté�  )Úpopr  ÚTimeoutr  Úrequestrï   rÊ   ræ   ©rF   r  rk   Úkwargsr  r‡   s         r3   r  z_SandboxServer.request—  sp   € à—*’*˜Y­¬°dÀDÐ(IÑ(IÔ(IÑJÔJˆØ'�4”<Ô'¨°´ÀÑ0DÐ`Ð`ÈgÐ`ÐY_Ð`Ð`ˆØÔ 3Ò&Ð&Ý˜hÑ'Ô'Ð'Øˆr5   c              +   ó  K  — |                      dt          j        dd¬¦  «        ¦  «        } | j        j        || j        |z   fd|i|¤Ž5 }|j        dk    rt          |¦  «         |V — ddd¦  «         dS # 1 swxY w Y   dS )zJStreaming request to the in-job server. Raises SandboxError on API errors.r  g     €Q@r  r  r  N)r  r  r  r  Ústreamrï   rÊ   ræ   r  s         r3   r  z_SandboxServer.streamŸ  sÝ   è è € ð —*’*˜Y­¬°dÀDÐ(IÑ(IÔ(IÑJÔJˆØ ˆTŒ\Ô  ¨¬¸Ñ)=ÐYÐYÀwÐYÐRXÐYÐYð 	Ð]eØÔ# sÒ*Ð*Ý! (Ñ+Ô+Ð+ØˆNˆNˆNð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s   ÁA7Á7A;Á>A;c                 ó8   — | j                              ¦   «          d S rz   )r  ÚcloserE   s    r3   r  z_SandboxServer.close¨  s   € ØŒ×ÒÑÔÐÐÐr5   c                 óR   — | j                              | j        | j        ¬¦  «         d S )N©rì   Ú	namespace)rû   Ú
cancel_jobrì   rí   rE   s    r3   r"  z_SandboxServer.cancel_job«  s'   € ØŒ	×Ò D¤K¸4¼:ÐÑFÔFÐFÐFÐFr5   Ústart_timeoutc           
      ó  — t          j         ¦   «         |z   }d}t          j         ¦   «         |k     �rA	 | j                             | j        dz   t	          j        d¦  «        ¬¦  «        }|j        dk    rdS n# t          j        $ r Y nw xY wt          j         ¦   «         |z
  dk    r¡t          j         ¦   «         }| j         	                    | j
        | j        ¬¦  «        }|j        j        t          v rUt          | j        | j
        | j        ¬	¦  «        }t!          d
| j
        › d|j        j        › d|j        j        › d|› �¦  «        ‚t          j        d¦  «         t          j         ¦   «         |k     �°At!          d
| j
        › d|d›d�¦  «        ‚)zMPoll /health until the server answers; fail fast (with logs) if the job dies.g        z/healthg      @)r  éÈ   Ng       @r   ©r!  zSandbox job z$ terminated during startup (status: z, message: ú).g333333Ã?z did not become ready within z.0fzs.)Útimer  rÞ   rï   r  r  rÊ   ÚRequestErrorrû   Úinspect_jobrì   rí   ÚstatusÚstageÚ_TERMINAL_STAGESÚ_tail_job_logsr   rå   Úsleep)rF   r#  ÚdeadlineÚlast_job_checkr‡   r  Úlogss          r3   Ú
wait_readyz_SandboxServer.wait_ready®  s¬  € å”9‘;”; Ñ.ˆØˆÝŒi‰kŒk˜HÒ$Ñ$ðØœ<×+Ò+¨D¬M¸IÑ,EÍuÌ}Ð]`ÑOaÔOaÐ+ÑbÔb�ØÔ'¨3Ò.Ð.Ø�Fð /øåÔ%ð ð ð Ø�ðøøøåŒy‰{Œ{˜^Ñ+¨cÒ1Ð1Ý!%¤¡¤�Ø”i×+Ò+°4´;È$Ì*Ð+ÑUÔU�Ø”:Ô#Õ'7Ð7Ð7Ý)¨$¬)°T´[ÈDÌJÐWÑWÔW�DÝ&ð^ t¤{ð ^ð ^Ø$'¤JÔ$4ð^ð ^ØADÄÔASð^ð ^ØW[ð^ð ^ñô ð õ ŒJ�tÑÔÐõ! Œi‰kŒk˜HÒ$Ñ$õ" Ði¨$¬+ÐiÐiÐTaÐiÐiÐiÐiÑjÔjÐjs   ²AA6 Á6BÂBrg   )rO   rP   rQ   rR   rT   r   r9   r|   Úclassmethodr   r  rV   rî   r  ÚResponser  r   r   r  r  r"  r:   r3  rW   r5   r3   rè   rè   K  s  € € € € € ðð ð"  "Øð&
ð &
ð &
ð ð&
ð ð	&
ð
 �T‰zð&
ð ð&
ð ð&
ð ð&
ð ð&
ð ð&
ð ð&
ð 
ð&
ð &
ð &
ð &
ðP ð  "Øð
ð 
ð 
ð ð
ð ð	
ð
 ð
ð ð
ð ð
ð ð
ð 
ð
ð 
ð 
ñ „[ð
ð. ð�s˜T‘zð ð ð ñ „Xðð˜cð ¨ð ¸5¼>ð ð ð ð ð ð˜Sð ¨ð ¸(À5Ä>Ô:Rð ð ð ñ „^ððð ð ð ðGð Gð Gð Gðk¨ð k°$ð kð kð kð kð kð kr5   rè   c            	       ó–   — e Zd ZdZedddeded         fd„¦   «         Zedddedeg df         fd	„¦   «         Zdd
deded         fd„ZdS )Ú_KillMethodz>Lets `kill` work both as a classmethod and an instance method.ÚinstanceNrí   r+   ).Nc                 ó   — d S rz   rW   ©rF   r8  rí   s      r3   Ú__get__z_KillMethod.__get__É  s   € ØKNÈ3r5   r^   c                 ó   — d S rz   rW   r:  s      r3   r;  z_KillMethod.__get__Ë  s   € ØORÈsr5   úSandbox | Nonec           	      óh   ‡— |�|j         S d d dœdt          dt          d z  dt          d z  dd fˆfd„}|S )N©r!  ÚtokenÚ
sandbox_idr!  r@  r+   c                ó\   •— ‰                      | ||¬¦  «                             ¦   «          d S )Nr?  )r  rf   )rA  r!  r@  rí   s      €r3   rf   z!_KillMethod.__get__.<locals>.killÑ  s-   ø€ Ø�MŠM˜*°	ÀˆMÑGÔG×LÒLÑNÔNÐNÐNÐNr5   )Ú_killrT   )rF   r8  rí   rf   s     ` r3   r;  z_KillMethod.__get__Í  sx   ø€ ØÐØ”>Ð!à=AÐW[ð 	Oð 	Oð 	O�Sð 	Oµ°d±
ð 	OÍ#ÐPTÉ*ð 	OÐ`dð 	Oð 	Oð 	Oð 	Oð 	Oð 	Oð ˆr5   )rO   rP   rQ   rR   r   ro   r   r;  rW   r5   r3   r7  r7  Æ  s¡   € € € € € ØHÐHàØN ÐN¨TÐN°h¸yÔ6IÐNÐNÐNñ „XØNØØR 	ÐR°$ÐR¸8ÀBÈÀHÔ;MÐRÐRÐRñ „XØRðÐ 0ð ¸ð À(È9ÔBUð ð ð ð ð ð r5   r7  c                   ó„  — e Zd ZdZdedededz  dededdfd	„Zee	fd
e
ddddddddœ	dededeez  ez  dz  deeef         dz  deeef         dz  dee         dz  dedz  dedededz  dd fd„¦   «         Zedddœdededz  dedz  dd fd„¦   «         Z e¦   «         Zd@d„Zd@d„ZdAd„Zd@d„Zed d d d d d d d d d!œ	d"eee         z  d#edz  deeef         dz  d$edz  d%edz  d&edz  d'eegdf         dz  d(eegdf         dz  d)ed*ed         defd+„¦   «         Zed d d d,œd"eee         z  d#edz  deeef         dz  d$edz  d*ed-         defd.„¦   «         Zdddddddd-dd!œ	d"eee         z  d#edz  deeef         dz  d$edz  d%edz  d&edz  d'eegdf         dz  d(eegdf         dz  d)ed*edeez  fd/„Zdee         fd0„Ze dedz  fd1„¦   «         Z!e dedz  fd2„¦   «         Z"dBd4d5œd6eez  d7ed8edefd9„Z#e deeef         fd:„¦   «         Z$defd;„Z%d<ed=ede&j'        fd>„Z(e)d<ed=ede*e&j'                 fd?„¦   «         Z+dS )Cr^   aë  An isolated cloud machine running on Hugging Face Jobs.

    Create a dedicated one with [`Sandbox.create`] (one job per sandbox), or get many cheap shared ones from a [`SandboxPool`].
    Reattach to a running sandbox from anywhere with [`Sandbox.connect`]. Use as a context manager to terminate it on exit:

    ```python
    >>> from huggingface_hub import Sandbox
    >>> with Sandbox.create(image="python:3.12") as sbx:
    ...     print(sbx.run("python --version").stdout)
    ```
    r  ÚserverÚlocal_idNÚowns_sandboxÚowns_serverr+   c                ó¬   — || _         || _        || _        |€dnd|› �| _        || _        || _        d | _        d| _        t          | ¦  «        | _	        d S )Nz/v1ú/v1/sandboxes/F)
r  Ú_serverÚ	_local_idÚ
_base_pathÚ_owns_sandboxÚ_owns_serverÚ_on_killÚ_killedru   Úfiles)rF   r  rE  rF  rG  rH  s         r3   r|   zSandbox.__init__ä  si   € ð ˆŒØˆŒà!ˆŒð $,Ð#3˜%˜%Ð9TÈ(Ð9TÐ9TˆŒð *ˆÔð (ˆÔà<@ˆŒØˆŒÝ! $Ñ'Ô'ˆŒ
ˆ
ˆ
r5   ú	cpu-basicFç      ^@)	ÚflavorÚidle_timeoutÚenvÚsecretsÚvolumesr!  Úforward_hf_tokenr#  r@  rî   rU  rV  rW  rX  rY  r!  rZ  r#  r@  c       	         ó  — t          |
¬¦  «        }t          |¦  «        }t          d¦  «        }t          ||¦  «        }t	          ||||||||¬¦  «        \  }}}}|                     |||||t          t          dt          t          t          |i|pdt          g|¬¦
  «
        }d}	 t                               ||||t          j        dz   ¬¦  «        }|                     |	¦  «         n‰# t"          $ r| 	 |                     |j        |j        j        ¬	¦  «         n<# t"          $ r/}t,                               d
|j        › d|› �¦  «         Y d}~nd}~ww xY w|�|                     ¦   «          ‚ w xY w | |j        |ddd¬¦  «        S )u3  Create a dedicated sandbox (one HF Job) and block until it is ready (~7s on cpu-basic).

        Each sandbox is a full isolated VM, so this is the right choice for GPU
        workloads or untrusted code. To fan out many cheap CPU sandboxes instead, use
        [`SandboxPool`].

        The job runs with a fixed 24h maximum lifetime; `idle_timeout` is the real
        keeper â€” an idle sandbox shuts itself down well before that.

        Args:
            image (`str`, *optional*, defaults to `"python:3.12"`):
                Any Docker image with `/bin/sh` (Docker Hub or `hf.co/spaces/...`).
            flavor (`str`, *optional*, defaults to `"cpu-basic"`):
                Hardware flavor, e.g. `"cpu-basic"`, `"a10g-small"`. See `hf jobs hardware`.
            idle_timeout (`int` or `float` or `str`, *optional*, defaults to `600`):
                Auto-shutdown after this much inactivity (no API calls, no running
                processes). Defaults to 10 minutes; pass `None` to disable.
            env (`dict[str, Any]`, *optional*):
                Environment variables available in the sandbox.
            secrets (`dict[str, Any]`, *optional*):
                Secret environment variables (encrypted server-side).
            volumes (`List[Volume]`, *optional*):
                HF repos/buckets to mount, see [`Volume`].
            namespace (`str`, *optional*):
                User or org namespace to run under (defaults to current user).
            forward_hf_token (`bool`, *optional*, defaults to `False`):
                If True, your HF token is injected as `HF_TOKEN` (opt-in).
            start_timeout (`float`, *optional*, defaults to `120.0`):
                Max seconds to wait for the sandbox to become ready.
            token (`str`, *optional*):
                HF token override.

        The image only needs `/bin/sh`. The sandbox server is downloaded at startup with
        `wget`/`curl` if available, otherwise read off an always-mounted server bucket (which
        adds ~2-3s to cold start, so shipping `wget`/`curl` keeps it fast).
        ©r@  rw   ©rW  rX  rY  rV  rZ  rð   rÏ   N©
rî   ÚcommandrW  rX  rU  r  ÚlabelsrY  Úexposer!  é   ©r  r*   rð   rñ   rê   r   zFailed to cancel sandbox job ú after startup failure: T©r  rE  rF  rG  rH  )r   rü   r   r4   Ú_bootstrap_job_specÚrun_jobÚSANDBOX_MAX_LIFETIMEÚSANDBOX_LABELÚ
MODE_LABELÚMODE_DEDICATEDÚNONCE_LABELÚSANDBOX_SERVER_PORTrè   r  ru   r²   r3  rã   r"  r  rí   rj   ÚloggerÚwarningr  )r  rî   rU  rV  rW  rX  rY  r!  rZ  r#  r@  rñ   r)   r*   rð   r_  Újob_envÚjob_secretsÚjob_volumesr  rE  rË   s                         r3   ÚcreatezSandbox.create  sã  € õf ˜%Ð Ñ Ô ˆÝ# CÑ(Ô(ˆÝ˜"‘”ˆÝ-¨h¸Ñ>Ô>ˆå5HØØØØØØ%Ø-Ø'ð	6
ñ 	6
ô 	6
Ñ2ˆ�˜+ {ð �kŠkØØØØØÝ(Ý! 3­
µNÅKÐQVÐWØÐ' 4Ý'Ð(Øð ñ 
ô 
ˆð +/ˆð	Ý#×,Ò,ØØØ+ØÝ ,Ô AÀAÑ Eð -ñ ô ˆFð ×Ò˜mÑ,Ô,Ð,Ð,øÝð 		ð 		ð 		ðdØ—’ c¤f¸¼	¼�ÑGÔGÐGÐGøÝð dð dð dÝ—’Ðb¸s¼vÐbÐbÐ_`ÐbÐbÑcÔcÐcÐcÐcÐcÐcÐcøøøøðdøøøàÐ!Ø—’‘”�Øð		øøøð ˆs�c”f V°dÈÐ[_Ð`Ñ`Ô`Ð`s7   Â$AC& Ã&
E,Ã1&DÄE,Ä
EÄ"%EÅE,ÅEÅE,r?  rA  c                ó>  — t          |¬¦  «        }t          ||¦  «        \  }}t          |v r±|                     t          d¦  «        \  }}t	          |||¬¦  «        }	 d„ |                     dd¦  «                             ¦   «         D ¦   «         }||vrt          d|› d|› d	�¦  «        ‚n## t          $ r | 	                    ¦   «          ‚ w xY w | |||d
d¬¦  «        S | 
                    ||¬¦  «        }	|	j        pi }
|
                     t          ¦  «        }|
                     t          ¦  «        dk    s|€t          d|› dt          › d�¦  «        ‚|
                     t          ¦  «        t           k    rt          d|› dt          › d�¦  «        ‚|	j        j        dk    r t          d|› d|	j        j        › d�¦  «        ‚t'          t)          |¦  «        |¦  «        }t*                               |	|||t.          j        dz   ¬¦  «        } | |	j        |dd
d¬¦  «        S )z?Reattach to a running sandbox from anywhere, using only its id.r\  r   r&  c                 ó   — h | ]
}|d          ’ŒS ©r  rW   )r©   Úitems     r3   ú	<setcomp>z"Sandbox.connect.<locals>.<setcomp>o  s   € ÐaÐaÐa¨4˜D œJÐaÐaÐar5   r~   ú/v1/sandboxeszSandbox z no longer exists on host r#   FTre  r   rÏ   NúJob z is not a sandbox (missing 'z	' label).z` is a sandbox host, not a single sandbox. Connect to one of its sandboxes with id '<host_job_id>z<local_id>'.ÚRUNNINGú is not running (status: r'  rb  rc  )r   Ú_split_sandbox_idÚSHARED_ID_SEPÚsplitÚ_connect_hostr  rÆ   r   rã   r  r*  r`  rÞ   rl  ri  rj  Ú	MODE_POOLr+  r,  r4   rü   rè   r  ru   r²   r  )r  rA  r!  r@  rñ   Úhost_job_idrF  rE  Úexistingr  r`  r*   rð   s                r3   r  zSandbox.connectf  ss  € õ ˜%Ð Ñ Ô ˆÝ 1°*¸iÑ HÔ HÑˆ
�IÝ˜JÐ&Ð&Ø$.×$4Ò$4µ]ÀAÑ$FÔ$FÑ!ˆK˜Ý" 3¨¸yÐIÑIÔIˆFðØaÐa°6·>²>À%ÈÑ3YÔ3Y×3^Ò3^Ñ3`Ô3`ÐaÑaÔa�Ø 8Ð+Ð+Ý&Ð'f°*Ð'fÐ'fÐXcÐ'fÐ'fÐ'fÑgÔgÐgð ,øåð ð ð Ø—’‘”�Øðøøøð �3˜*¨V¸hÐUZÐhlÐmÑmÔmÐmà�oŠo Z¸9ˆoÑEÔEˆØ”Ð!˜rˆØ—
’
�;Ñ'Ô'ˆØ�:Š:•mÑ$Ô$¨Ò+Ð+¨u¨}ÝÐf jÐfÐfÍmÐfÐfÐfÑgÔgÐgØ�:Š:•jÑ!Ô!¥YÒ.Ð.ÝðO�zð Oð OÝ3@ðOð Oð Oñô ð ð Œ:Ô˜yÒ(Ð(ÝÐc¨*ÐcÐcÈsÌzÔO_ÐcÐcÐcÑdÔdÐdÝ-Õ.>¸sÑ.CÔ.CÀUÑKÔKˆÝ×(Ò(ØØØ'ØÝ(Ô=ÀÑAð )ñ 
ô 
ˆð ˆs�c”f V°dÈÐ\`ÐaÑaÔaÐas   ÁAB+ Â+ Cc                 ó¨  — | j         rdS 	 | j        €| j                             ¦   «          n#| j                             dd| j        › �¦  «         n=# t
          $ r0}t                               d| j        › d|› �¦  «         Y d}~dS d}~ww xY wd| _         | j	        �|  	                    | ¦  «         | j
        r| j                             ¦   «          dS dS )zÉTerminate the sandbox. Idempotent.

        Dedicated sandboxes cancel their underlying job; shared sandboxes are
        removed from their host (freeing a slot) while the host keeps running.
        Nrd   rJ  zFailed to kill sandbox ú: T)rQ  rL  rK  r"  r  rã   rn  ro  r  rP  rO  r  )rF   rË   s     r3   rC  zSandbox._kill‘  sþ   € ð Œ<ð 	ØˆFð	ØŒ~Ð%Ø”×'Ò'Ñ)Ô)Ð)Ð)à”×$Ò$ XÐ/PÀÄÐ/PÐ/PÑQÔQÐQøøÝð 	ð 	ð 	å�NŠNÐC°T´WÐCÐCÀÐCÐCÑDÔDÐDØˆFˆFˆFˆFˆFøøøøð	øøøð ˆŒØŒ=Ð$Ø�MŠM˜$ÑÔÐØÔð 	!ØŒL×ÒÑ Ô Ð Ð Ð ð	!ð 	!s   ‹AA Á
B
Á%BÂB
c                 óJ   — | j         r| j                             ¦   «          dS dS )zžRelease the local HTTP client without terminating the sandbox. Idempotent.

        No-op for pool sandboxes (the client belongs to the pool's host).
        N)rO  rK  r  rE   s    r3   r  zSandbox.close¨  s3   € ð
 Ôð 	!ØŒL×ÒÑ Ô Ð Ð Ð ð	!ð 	!r5   c                 ó   — | S rz   rW   rE   s    r3   Ú	__enter__zSandbox.__enter__°  ó   € Øˆr5   c                 óh   — | j         r|                      ¦   «          d S |                      ¦   «          d S rz   )rN  rf   r  ©rF   Úexc_infos     r3   Ú__exit__zSandbox.__exit__³  s/   € ØÔð 	Ø�IŠI‰KŒKˆKˆKˆKà�JŠJ‰LŒLˆLˆLˆLr5   .)	rÔ   rW  Úcwdr  ÚstdinÚ	on_stdoutÚ	on_stderrÚcheckÚ
backgroundr[   rÔ   rŽ  r  r�  r�  r‘  r’  r“  c       	         ó   — d S rz   rW   )rF   r[   rÔ   rW  rŽ  r  r�  r�  r‘  r’  r“  s              r3   ÚrunzSandbox.run»  s	   € ð  #˜sr5   )rÔ   rW  rŽ  Tc                ó   — d S rz   rW   )rF   r[   rÔ   rW  rŽ  r“  s         r3   r•  zSandbox.runË  s	   € ð ˜r5   c       	         ó  — t          ||¦  «        }|r||d<   |r||d<   |
rV|                      dd|¬¦  «                             ¦   «         }t          |d         ||                     d¦  «        | ¬¦  «        S |�||d
<   |�||d<   g }g }d	}|                      dd|¬¦  «        5 }t          |¦  «        D �]}|d         dk    r/|                     |d         ¦  «         |� ||d         ¦  «         Œ>|d         dk    r/|                     |d         ¦  «         |� ||d         ¦  «         Œy|d         dk    r|t          |d         d 	                    |¦  «        d 	                    |¦  «        |                     d¦  «        |                     dd¦  «        |                     dd¦  «        ¬¦  «        }�Œ	 d	d	d	¦  «         n# 1 swxY w Y   |€t          d¦  «        ‚|	r#|j        dk    s|j        rt          ||¬¦  «        ‚|S )u+	  Run a command in the sandbox and wait for it, streaming output live.

        With `background=True` the command is started detached and `run` returns a
        [`SandboxProcess`] immediately, without waiting for it to finish â€” handy for
        servers and other long-running processes. List them later with [`Sandbox.processes`]
        and stop one with [`SandboxProcess.kill`]. The streaming/wait-only options
        (`timeout`, `stdin`, `on_stdout`, `on_stderr`, `check`) don't apply in that mode.

        Args:
            cmd (`str` or `List[str]`):
                A shell command string (run with `/bin/sh -c`) or an argv list (exec'd directly).
            shell (`bool`, *optional*):
                Force the execution mode instead of inferring it from the type of `cmd`.
                `True` runs through `/bin/sh -c` and requires `cmd` to be a string; `False`
                exec's `cmd` directly and requires it to be an argv list. `None` (default)
                infers from the type. Set it explicitly to avoid the type-driven footgun (e.g.
                `["echo hi"]` being exec'd as a single program named `"echo hi"`).
            env (`dict[str, Any]`, *optional*):
                Extra environment variables for this command.
            cwd (`str`, *optional*):
                Working directory.
            timeout (`float`, *optional*):
                Kill the command (whole process group) after this many seconds.
            stdin (`str`, *optional*):
                Data to write to the command's stdin.
            on_stdout (`Callable[[str], None]`, *optional*):
                Callback invoked with stdout chunks as they arrive.
            on_stderr (`Callable[[str], None]`, *optional*):
                Callback invoked with stderr chunks as they arrive.
            check (`bool`, *optional*, defaults to `True`):
                If True, raise [`SandboxCommandError`] on non-zero exit.
            background (`bool`, *optional*, defaults to `False`):
                If True, start the command detached and return a [`SandboxProcess`] right
                away instead of waiting for it and returning a [`SandboxCommandResult`].

        Returns: a [`SandboxCommandResult`] (with `exit_code`, `stdout`, `stderr`,
        `duration_ms`), or a [`SandboxProcess`] when `background=True`.
        rW  rŽ  rÒ   ú
/processes©rÆ   rZ   r`   )rZ   r[   r`   r_   Nr  r�  z/execrÚ   r?   rŽ   r@   Úexitr>   rr   rA   rB   FrC   r   )r>   r?   r@   rA   rB   rC   z%connection lost while running command)r[   Úresult)rØ   re   rÆ   rY   rÞ   r¡   rà   Úappendr=   r„   r   r>   rB   r   )rF   r[   rÔ   rW  rŽ  r  r�  r�  r‘  r’  r“  r×   rŽ   Ústdout_partsÚstderr_partsr›  r‡   rÚ   s                     r3   r•  zSandbox.runÖ  s‡  € õh    UÑ+Ô+ˆØð 	!Ø ˆG�E‰NØð 	!Ø ˆG�E‰NØð 	`Ø—=’= ¨¸G�=ÑDÔD×IÒIÑKÔKˆDÝ! d¨5¤k°sÀÇÂÈÁÄÐZ^Ð_Ñ_Ô_Ð_ØÐØ!(ˆG�IÑØÐØ$ˆG�GÑà"$ˆØ"$ˆØ.2ˆØ�\Š\˜& '°ˆ\Ñ8Ô8ð 	¸HÝ% hÑ/Ô/ð ñ �Ø˜”> XÒ-Ð-Ø ×'Ò'¨¨f¬Ñ6Ô6Ð6Ø Ð,Ø!˜	 %¨¤-Ñ0Ô0Ð0øØ˜7”^ xÒ/Ð/Ø ×'Ò'¨¨f¬Ñ6Ô6Ð6Ø Ð,Ø!˜	 %¨¤-Ñ0Ô0Ð0øØ˜7”^ vÒ-Ð-Ý1Ø"'¨Ô"4Ø!Ÿwšw |Ñ4Ô4Ø!Ÿwšw |Ñ4Ô4Ø$Ÿyšy¨Ñ2Ô2Ø"'§)¢)¨K¸Ñ"?Ô"?Ø$)§I¢I¨m¸QÑ$?Ô$?ðñ ô �Fùðð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð& ˆ>ÝÐFÑGÔGÐGØð 	>�fÔ&¨!Ò+Ð+¨vÔ/?Ð+Ý%¨#°fÐ=Ñ=Ô=Ð=Øˆs   Â#DGÇGÇ
Gc                 óp   ‡ — ‰                       dd¦  «                             ¦   «         }ˆ fd„|D ¦   «         S )a.  List the background processes of this sandbox.

        Returns the processes started with [`Sandbox.run`]`(..., background=True)`; stop one
        with [`SandboxProcess.kill`]. Completed processes stay listed (with `running=False` and
        their `exit_code`) until the sandbox is deleted.
        r~   r˜  c                 óÒ   •— g | ]c}t          |d          |d         |                     d¦  «        |                     d¦  «        |d         |                     d¦  «        ‰¬¦  «        ‘ŒdS )rZ   r[   r`   ra   rb   r>   )rZ   r[   r`   ra   rb   r>   r_   )rY   rÞ   )r©   ÚprF   s     €r3   r«   z%Sandbox.processes.<locals>.<listcomp>;  s}   ø€ ð 
ð 
ð 
ð õ Ø�e”HØ�e”HØ—E’E˜%‘L”LØŸeše OÑ4Ô4Ø˜)œØŸ%š% Ñ,Ô,Øðñ ô ð
ð 
ð 
r5   )re   rÆ   )rF   rŽ   s   ` r3   Ú	processeszSandbox.processes3  sQ   ø€ ð �}Š}˜U LÑ1Ô1×6Ò6Ñ8Ô8ˆð
ð 
ð 
ð 
ð ð
ñ 
ô 
ð 	
r5   c                 ó   — | j         j        S rz   )rK  rî   rE   s    r3   rî   zSandbox.imageJ  s   € àŒ|Ô!Ð!r5   c                 ó,   — | j         �| j        j        ndS )zIFor a shared/pool sandbox, the job id of the host running it (else None).N)rL  rK  rì   rE   s    r3   Úhost_idzSandbox.host_idN  s   € ð '+¤nÐ&@ˆtŒ|Ô"Ð"ÀdÐJr5   ú/zhttps://)ÚschemeÚportrk   r§  c                óª   — | j         j                             dd¦  «        d         }|                     d¦  «        r|nd|z   }|› |› | j        › d|› |› �S )a4  Public URL that proxies through to a server running *inside* this sandbox.

        Requests to the returned URL are forwarded by the in-job sandbox server to a
        server you started in the sandbox on `port`, including WebSocket (`ws(s)://`)
        upgrades and streamed responses. Pair it with [`proxy_headers`] for auth.

        How the sandbox must listen on `port`:

        - **Pool / shared sandbox**: it cannot bind a TCP port (Landlock), so bind a
          **unix socket** at `$SBX_PROXY_DIR/<port>.sock` (the `SBX_PROXY_DIR` env var
          is set in every sandbox). E.g. `uvicorn app:app --uds $SBX_PROXY_DIR/8000.sock`.
        - **Dedicated sandbox**: bind a normal TCP port on `127.0.0.1:<port>`. (You can
          also expose the port directly via the job proxy without going through here.)

        Args:
            port (`int` or `str`):
                The port (pool: the `<port>` of the unix socket) the inner server listens on.
            path (`str`, *optional*, defaults to `"/"`):
                Path on the inner server to point at, e.g. `"/ws"`.
            scheme (`str`, *optional*, defaults to `"https://"`):
                URL scheme to build the link with. Defaults to `"https://"`; pass
                `"wss://"` for a WebSocket client (the proxy is protocol-agnostic, so only
                the client-side scheme changes).

        Returns:
            `str`: a URL like `https://<job_id>--49983.hf.jobs/v1/.../proxy/8000/ws` (or
            `wss://...` with `scheme="wss://"`).

        Example:
            ```python
            >>> url = sandbox.proxy_url_for(8000, "/ws", scheme="wss://")
            >>> import websockets
            >>> async with websockets.connect(url, additional_headers=sandbox.proxy_headers) as ws:
            ...     await ws.send("hello")
            ```
        z://r   éÿÿÿÿr¦  z/proxy/)rK  rï   r  Ú
startswithrM  )rF   r¨  rk   r§  Úhost_and_rests        r3   Úproxy_url_forzSandbox.proxy_url_forU  sg   € ðL œÔ-×3Ò3°E¸1Ñ=Ô=¸bÔAˆØ—’ sÑ+Ô+Ð;ˆtˆt°°t±ˆØÐM˜-ÐM¨¬ÐMÐMÀÐMÀtÐMÐMÐMr5   c                 ó:   — d| j         j        › �| j         j        dœS )zPAuth headers to send with [`proxy_url_for`] requests (HF token + sandbox token).ró   rô   )rK  rý   rþ   rE   s    r3   Úproxy_headerszSandbox.proxy_headers  s,   € ð B t¤|Ô'?ÐAÐAØ#œ|Ô:ð
ð 
ð 	
r5   c                 ó(   — d| j         ›d| j        ›d�S )NzSandbox(id=z, image=rK   )r  rî   rE   s    r3   rN   zSandbox.__repr__‡  s   € Ø?˜TœWÐ?Ð?°´
Ð?Ð?Ð?Ð?r5   r  Úresourcec                 ó:   —  | j         j        || j        |z   fi |¤ŽS rz   )rK  r  rM  )rF   r  r±  r  s       r3   re   zSandbox._requestŒ  s(   € Ø#ˆtŒ|Ô# F¨D¬O¸hÑ,FÐQÐQÈ&ÐQÐQÐQr5   c              +   ó|   K  —  | j         j        || j        |z   fi |¤Ž5 }|V — d d d ¦  «         d S # 1 swxY w Y   d S rz   )rK  r  rM  )rF   r  r±  r  r‡   s        r3   r¡   zSandbox._stream�  s—   è è € à ˆTŒ\Ô  ¨¬¸8Ñ)CÐNÐNÀvÐNÐNð 	ÐRZØˆNˆNˆNð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s   Ÿ1±5¸5rg   )r+   r^   )r¦  ),rO   rP   rQ   rR   rT   rè   rU   r|   r4  ÚDEFAULT_IMAGEÚDEFAULT_IDLE_TIMEOUTr9   r:   Údictr	   r   r   rs  r  r7  rf   rC  r  rˆ  r�  r   r   r   r=   r•  rY   r¢  rV   rî   r¥  r­  r¯  rN   r  r5  re   r   r   r¡   rW   r5   r3   r^   r^   ×  sd  € € € € € ð
ð 
ð(ð ð(ð ð	(ð
 ˜‘*ð(ð ð(ð ð(ð 
ð(ð (ð (ð (ð: ð #ðbað "Ø1EØ%)Ø)-Ø'+Ø $Ø!&Ø$Ø ðbað bað baàðbað ð	bað
 ˜E‘k CÑ'¨$Ñ.ðbað �#�s�(Œ^˜dÑ"ðbað �c˜3�h” $Ñ&ðbað �f” Ñ$ðbað ˜‘:ðbað ðbað ðbað �T‰zðbað 
ðbað bað bañ „[ðbaðH ØAEÐ[_ð $bð $bð $b ð $b°C¸$±Jð $bÈcÐTXÉjð $bÐdmð $bð $bð $bñ „[ð$bðP ˆ;‰=Œ=€Dð!ð !ð !ð !ð.!ð !ð !ð !ðð ð ð ðð ð ð ð ð
 !Ø%(ØØ #ØØ25Ø25ØØ%(ð#ð #ð #à�4˜”9‰_ð#ð �d‰{ð	#ð
 �#�s�(Œ^˜dÑ"ð#ð �4‰Zð#ð ˜‘ð#ð �T‰zð#ð ˜S˜E 4˜KÔ(¨4Ñ/ð#ð ˜S˜E 4˜KÔ(¨4Ñ/ð#ð ð#ð ˜E”Nð#ð 
ð#ð #ð #ñ „Xð#ð ð
 !Ø%(Øðð ð à�4˜”9‰_ðð �d‰{ð	ð
 �#�s�(Œ^˜dÑ"ðð �4‰Zðð ˜D”Mðð 
ðð ð ñ „Xðð "Ø%)ØØ $Ø Ø26Ø26ØØ ð[ð [ð [à�4˜”9‰_ð[ð �d‰{ð	[ð
 �#�s�(Œ^˜dÑ"ð[ð �4‰Zð[ð ˜‘ð[ð �T‰zð[ð ˜S˜E 4˜KÔ(¨4Ñ/ð[ð ˜S˜E 4˜KÔ(¨4Ñ/ð[ð ð[ð ð[ð 
 Ñ	.ð[ð [ð [ð [ðz
˜4 Ô/ð 
ð 
ð 
ð 
ð. ð"�s˜T‘zð "ð "ð "ñ „Xð"ð ðK˜˜t™ð Kð Kð Kñ „XðKð(NÈzð (Nð (Nð (N #¨¡)ð (N°3ð (NÈð (NÐ^að (Nð (Nð (Nð (NðT ð
˜t C¨ Hœ~ð 
ð 
ð 
ñ „Xð
ð@˜#ð @ð @ð @ð @ð
R˜sð R¨cð RÀÄð Rð Rð Rð Rð ð˜cð ¨Sð ¸xÈÌÔ?Wð ð ð ñ „^ðð ð r5   r^   c                   ór  — e Zd ZdZefdedddedddddœ
ded	ed
edededz  dedz  dee	z  ez  dz  dedz  de	dedz  de
ddfd„Zedddœdededz  dedz  dd fd„¦   «         Zd9dedee         fd„Zdeddœdeeef         dz  dee	z  ez  dz  de
ddfd„Zedefd„¦   «         Zedefd „¦   «         Zedee         fd!„¦   «         Zd:d"„Zd;d#„Zd:d$„Zd:d%„Zd<d'„Zd(ed)         dd&fd*„Zde
fd+„Zd:d,„Zd-edee         fd.„Z defd/„Z!d0d)deeef         d1edz  dd2fd3„Z"d4e#ddfd5„Z$d0eddfd6„Z%d:d7„Z&d:d8„Z'dS )=ÚSandboxPoola  A fleet of shared "host" jobs, each packing many landlock-isolated sandboxes.

    One host is one billed HF Job (a VM); it runs the sandbox server and multiplexes
    up to `sandboxes_per_host` lightweight sandboxes, isolated from each other by
    uid + the Landlock LSM. This makes large fan-outs cheap (the VM cost is shared
    across all its sandboxes) and fast (creating a sandbox is ~one proxy round-trip
    once a host is warm). Best for many parallel CPU sandboxes such as RL rollouts;
    for GPU or strong VM-level isolation between mutually-distrusting workloads, use
    [`Sandbox.create`] instead.

    The constructor pre-provisions `warm_up` hosts (default 1) and blocks until they are
    ready; further hosts are then provisioned on demand as sandboxes are requested, and all
    are torn down on `close()` (or when idle, via `idle_timeout`). The user never manages jobs:

    ```python
    >>> from huggingface_hub import SandboxPool
    >>> with SandboxPool(image="python:3.12", flavor="cpu-basic", warm_up=2) as pool:
    ...     boxes = [pool.create() for _ in range(100)]   # packed across the warm hosts
    ...     print(boxes[0].run("echo hi").stdout)
    hi
    ```

    `create()` makes **one** sandbox at a time: it reuses a host that still has free
    capacity before booting a new one, so you grow on demand as work arrives. To avoid
    a cold start on the first few calls, pre-provision hosts with `warm_up` (or
    [`warm`]). Warm hosts are discovered via job labels, so reuse works **across
    processes** too (a fresh pool with the same `image`/`flavor`/`name` attaches to
    hosts an earlier run left behind):

    ```python
    >>> pool = SandboxPool(image="python:3.12")
    >>> sbx = pool.create()    # finds a warm host (here or in another process), else boots one
    ```
    rS  r   NrT  F)
rU  Úsandboxes_per_hostÚwarm_upÚ	max_hostsrj   rV  r!  r#  r@  Ú_connect_moderî   rU  r¹  rº  r»  rj   rV  r!  r#  r@  r¼  r+   c       
         óX  — |dk     rt          d¦  «        ‚|dk     rt          d¦  «        ‚t          |
¬¦  «        | _        || _        || _        || _        || _        || _        |�|ndt          d¦  «        › �| _	        || _
        || _        |	| _        g | _        t          j        ¦   «         | _        t          j        ¦   «         | _        t          j        ¦   «         | _        d| _        d| _        || _        | | _        t/          ¦   «         | _        |s|                      ¦   «          dS dS )	u´	  Configure a pool and pre-provision `warm_up` hosts (blocks until they are ready).

        Env/secrets are *not* set here: they belong to each sandbox and are passed to
        `create(env=...)`, so sandboxes in the same pool can have different environments.

        Args:
            image (`str`, *optional*, defaults to `"python:3.12"`):
                Docker image for the hosts (needs `/bin/sh`). All sandboxes in the
                pool share this image.
            flavor (`str`, *optional*, defaults to `"cpu-basic"`):
                Hardware flavor for the host jobs (e.g. `"cpu-basic"`).
            sandboxes_per_host (`int`, *optional*, defaults to `50`):
                How many sandboxes to pack per host (per VM density).
            warm_up (`int`, *optional*, defaults to `1`):
                How many hosts to pre-provision in the constructor (which blocks
                until they are ready), so an initial burst of `create()` calls doesn't pay
                a host cold start each. Existing warm hosts (from the cache / other processes)
                count towards it, so only the shortfall is booted; capped by `max_hosts`.
                Defaults to 1 (a single host).
            max_hosts (`int`, *optional*):
                Optional cap on the number of host jobs (a cost ceiling). When
                reached and all hosts are full, `create()` raises.
            name (`str`, *optional*):
                Pool name, used as the `hf-sandbox-pool` job label so the pool is
                discoverable (e.g. `hf sandbox pool ls`, `connect()`). `create()` reuses
                running hosts carrying this label (including from other processes) before
                booting new ones, so distinct names keep separate pools from sharing hosts.
                A random name is generated when omitted.
            idle_timeout (`int` or `float` or `str`, *optional*, defaults to `600`):
                Host idle timeout â€” a host shuts down once it has had no
                sandboxes for this long (a billing backstop). Each sandbox also has its
                own idle timeout, set at `create()`. Pass `None` to disable.
            namespace (`str`, *optional*):
                User or org namespace to run hosts under.
            start_timeout (`float`, *optional*, defaults to `120.0`):
                Max seconds to wait for a host to become ready.
            token (`str`, *optional*):
                HF token override.
        r   z sandboxes_per_host must be >= 1.zwarm_up must be >= 1.r\  Nzpool-é   F)rÖ   r   rû   rî   rU  r¹  Ú_warm_upr»  r   rj   Ú_idle_timeoutÚ
_namespaceÚ_start_timeoutÚ_hostsÚ	threadingÚLockÚ_lockÚ_warmup_lockÚ
_boot_lockÚ_closedÚ
_warmed_upÚ_require_live_hostÚ_owns_hostsÚsetÚ_dead_host_idsÚ_ensure_warmed_up)rF   rî   rU  r¹  rº  r»  rj   rV  r!  r#  r@  r¼  s               r3   r|   zSandboxPool.__init__¹  s9  € ðl  Ò!Ð!ÝÐ?Ñ@Ô@Ð@Ø�QŠ;ˆ;ÝÐ4Ñ5Ô5Ð5Ý Ð&Ñ&Ô&ˆŒ	ØˆŒ
ØˆŒØ"4ˆÔØˆŒØ"ˆŒØ Ð,�D�DÐ2H½)ÀA¹,¼,Ð2HÐ2HˆŒ	Ø)ˆÔØ#ˆŒØ+ˆÔØ,.ˆŒÝ”^Ñ%Ô%ˆŒ
õ &œNÑ,Ô,ˆÔõ
 $œ.Ñ*Ô*ˆŒØˆŒàˆŒð #0ˆÔð  -Ð,ˆÔå(+©¬ˆÔð
 ð 	%Ø×"Ò"Ñ$Ô$Ð$Ð$Ð$ð	%ð 	%r5   r?  Úpool_idc                ó`  — t          |¦  «        }|�6 | |j        |j        |j        |j        ||j        |€|j        n||d¬¦	  «	        S t          |¬¦  «        }t          |||¬¦  «        }t          |||¬¦  «        }| 
                    d¦  «        }| 
                    d¦  «        }	 | |j        p|j        pt          |j        �t          |j        ¦  «        ndt          | 
                    d	t           ¦  «        ¦  «        |	�t          |	¦  «        nd||�t          |¦  «        nd||d¬¦	  «	        S )
ur  Reattach to a running pool by id, from any machine â€” no local state needed.

        Finds a running host labelled with `pool_id` and rebuilds the pool's config
        (image/flavor/density/host-idle) from that host job's spec and env vars, returning
        a [`SandboxPool`] ready to `create()` more sandboxes â€” packing onto the running
        hosts, or booting a duplicate (same config) when they are full.

        Raises [`SandboxError`] if no running host is found (a pool stops existing once
        all of its hosts are gone â€” idle-timed-out or killed).

        Args:
            pool_id (`str`):
                The id returned when the pool was first created.
            namespace (`str`, *optional*):
                Namespace to search for the pool's hosts (defaults to yours).
            token (`str`, *optional*):
                HF token override.
        NT)	rî   rU  r¹  r»  rj   rV  r!  r@  r¼  r\  r&  ÚSBX_IDLE_TIMEOUTÚSBX_MAX_HOSTSrS  ÚSBX_CAPACITY)r   rî   rU  r¹  r»  rV  r!  r   Ú_find_pool_host_jobÚ	_host_envrÞ   r	  r
  r´  rT   r9   ÚDEFAULT_SANDBOXES_PER_HOST)
r  rÐ  r!  r@  Úcacherñ   r  rW  Úidle_rawÚmax_hosts_raws
             r3   r  zSandboxPool.connect  sM  € õ.   Ñ(Ô(ˆØÐØ�3Ø”kØ”|Ø#(Ô#;Øœ/ØØ"Ô/Ø-6Ð->˜%œ/˜/ÀIØØ"ð
ñ 
ô 
ð 
õ ˜%Ð Ñ Ô ˆÝ! # w¸)ÐDÑDÔDˆÝ˜˜S¨IÐ6Ñ6Ô6ˆØ—7’7Ð-Ñ.Ô.ˆØŸš Ñ0Ô0ˆØˆsØÔ"ÐC c¤lÐCµmØ&)¤jÐ&<•3�s”z‘?”?�?À+Ý" 3§7¢7¨>Õ;UÑ#VÔ#VÑWÔWØ,9Ð,E•c˜-Ñ(Ô(Ð(È4ØØ*2Ð*>�˜X™œ˜ÀDØØØð

ñ 

ô 

ð 
	
r5   Ú	num_hostsc                 óì  — | j         rt          d¦  «        ‚|                      ¦   «          | j        5  |t	          | j        ¦  «        z
  }ddd¦  «         n# 1 swxY w Y   |dk    rN|                      |¦  «        }| j        5  | j                             |¦  «         ddd¦  «         n# 1 swxY w Y   | j        5  d| _	        ddd¦  «         n# 1 swxY w Y   |  
                    ¦   «          | j        S )u¢  Ensure `num_hosts` empty host(s) are running and leave them running. Returns the
        pool's host job ids.

        Used to "create" a pool up front: the hosts carry the pool label and config (in
        their env vars), so a later `SandboxPool.connect(pool_id)` (even from another
        machine) finds them and spawns sandboxes without a cold start. The hosts keep
        billing until killed or idle.

        Adopts hosts already running for this pool (found via job labels) before booting,
        so a `warm()` after `connect()` â€” or a repeated `warm()` â€” tops up to `num_hosts`
        instead of duplicating live hosts and blowing past `max_hosts`.
        úThis SandboxPool is closed.Nr   T)rÉ  r   Ú_discover_hostsrÆ  rL   rÃ  Ú_provision_hostsÚextendrÇ  rÊ  Ú_save_cacheÚhost_ids)rF   rÛ  Ú	shortfallÚbooteds       r3   ÚwarmzSandboxPool.warmT  s®  € ð Œ<ð 	>ÝÐ<Ñ=Ô=Ð=Ø×ÒÑÔÐØŒZð 	5ð 	5Ø!¥C¨¬Ñ$4Ô$4Ñ4ˆIð	5ð 	5ð 	5ñ 	5ô 	5ð 	5ð 	5ð 	5ð 	5ð 	5ð 	5øøøð 	5ð 	5ð 	5ð 	5à�qŠ=ˆ=Ø×*Ò*¨9Ñ5Ô5ˆFØ”ð +ð +Ø”×"Ò" 6Ñ*Ô*Ð*ð+ð +ð +ñ +ô +ð +ð +ð +ð +ð +ð +øøøð +ð +ð +ð +àÔð 	#ð 	#Ø"ˆDŒOð	#ð 	#ð 	#ñ 	#ô 	#ð 	#ð 	#ð 	#ð 	#ð 	#ð 	#øøøð 	#ð 	#ð 	#ð 	#à×ÒÑÔÐØŒ}Ðs5   ²AÁAÁAÂB*Â*B.Â1B.Â<CÃCÃC)rW  rV  rZ  rW  rZ  r^   c                ó¼  ‡
— | j         rt          d¦  «        ‚t          |pi ¦  «        }|rt          | j        ¦  «        |d<   |�t          |¦  «        nd}g Š
d}d}	 |                      ¦   «          	 |                      ¦   «         }|€,|s*d}|                      ¦   «          |                      ¦   «         }|€Q| j	        r5|r3| j
        s,t          | j        ¦  «         t          d| j        › d�¦  «        ‚|                      ‰
¦  «        }|�•	 |                      |||¦  «        }	nK# t          $ r> | j        5  t#          d|j        d	z
  ¦  «        |_        ddd¦  «         n# 1 swxY w Y   ‚ w xY w|	�|                      ¦   «          |	S |‰
v r‰
                     |¦  «         d}|d	z  }|t*          k    rt          d
¦  «        ‚�ŒO# t          $ r‘ | j        5  ˆ
fd„| j
        D ¦   «         | _
        ddd¦  «         n# 1 swxY w Y   ‰
D ]U}	 |                     ¦   «          n# t          $ r Y nw xY w|                     ¦   «          Œ=# |                     ¦   «          w xY w‚ w xY w)u‰  Create one sandbox, provisioning a host if needed.

        Reuses a host with free capacity (this pool's, or a warm host found via job labels
        / the local cache) before booting a new one, so a `create()` against a warm host
        costs ~one round-trip. Call it repeatedly to fan out; use `warm_up` (or [`warm`])
        to pre-provision hosts and avoid a cold start on the first calls. If a host fills
        up under us (another process packed it) or a cached host is gone, the sandbox is
        re-placed on another host (or a fresh one).

        Args:
            env (`dict[str, Any]`, *optional*):
                Environment variables for this sandbox (each sandbox gets its own).
            idle_timeout (`int` or `float` or `str`, *optional*, defaults to `600`):
                Per-sandbox idle timeout â€” a sandbox is evicted from its host
                after this much inactivity (no API calls, no running process). Distinct
                from the host idle timeout. Pass `None` to disable.
            forward_hf_token (`bool`, *optional*, defaults to `False`):
                If True, inject your HF token as `HF_TOKEN` in the sandbox
                (opt-in). Unlike a dedicated sandbox's `secrets`, a pooled sandbox's env is
                delivered to the host server at creation (never stored in the host job), so
                it doesn't appear in any job's metadata.
        rÝ  ÚHF_TOKENNFr   Tú No running host found for pool 'úX'. The pool has stopped (all its hosts were killed or idle-timed-out); create a new one.r   zZCould not place sandbox: hosts kept reporting full. Raise max_hosts or sandboxes_per_host.c                 ó   •— g | ]}|‰v¯|‘Œ	S rW   rW   )r©   ÚhÚ	new_hostss     €r3   r«   z&SandboxPool.create.<locals>.<listcomp>Ì  s#   ø€ ÐLÐLÐL Q¸À)Ð9KÐ9K˜qÐ9KÐ9KÐ9Kr5   )rÉ  r   r¶  rü   rû   r;   rÏ  Ú_reserve_onerÞ  rË  rÃ  r   rj   Ú_boot_one_hostÚ_create_onerã   rÆ  Úmaxrÿ   rá  ÚremoveÚ_MAX_PACK_ROUNDSr"  r  )rF   rW  rV  rZ  Úsandbox_envÚ	idle_secsÚ
discoveredÚroundsÚhostrx   rì  s             @r3   rs  zSandboxPool.createo  s�  ø€ ð: Œ<ð 	>ÝÐ<Ñ=Ô=Ð=Ý˜3˜9 "‘o”oˆØð 	BÝ&6°t´yÑ&AÔ&AˆK˜
Ñ#ð 8DÐ7OÕ% lÑ3Ô3Ð3ÐUYˆ	à*,ˆ	Øˆ
Øˆð<	ð ×"Ò"Ñ$Ô$Ð$ð,à×(Ò(Ñ*Ô*�à�<¨
�<Ø!%�JØ×(Ò(Ñ*Ô*Ð*Ø×,Ò,Ñ.Ô.�Dà�<ØÔ.ð °:ð ÀdÄkð õ *¨$¬)Ñ4Ô4Ð4Ý*ð_¸t¼yð _ð _ð _ñô ð ð  ×.Ò.¨yÑ9Ô9�Dð Ð#ðØ"&×"2Ò"2°4¸ÀiÑ"PÔ"P˜˜øÝ$ð ð ð ð "œZð >ð >Ý(+¨A¨t¬y¸1©}Ñ(=Ô(=˜DœIð>ð >ð >ñ >ô >ð >ð >ð >ð >ð >ð >øøøð >ð >ð >ð >àðøøøð Ð*Ø×(Ò(Ñ*Ô*Ð*Ø&˜ð
 ˜yÐ(Ð(Ø!×(Ò(¨Ñ.Ô.Ð.Ø"�
Ø˜!‘�ØÕ,Ò,Ð,Ý&Øtñô ð ñU,øõZ ð 	ð 	ð 	à”ð Mð MØLÐLÐLÐL¨$¬+ÐLÑLÔL�”ðMð Mð Mñ Mô Mð Mð Mð Mð Mð Mð Møøøð Mð Mð Mð Mà!ð !ð !�ð!Ø—O’OÑ%Ô%Ð%Ð%øÝ ð ð ð Ø�Dðøøøð —J’J‘L”L�L�Lø�D—J’J‘L”L�L�LøøøØð	øøøs©   ÁB,G  Ä	D! Ä G  Ä!E)Ä2EÅE)ÅE 	Å E)Å#E 	Å$E)Å)G  Æ<G  Ç IÇG6Ç*IÇ6G:	Ç:IÇ=G:	Ç>IÈHÈI È
H(È%I È'H(È(I È+IÉ IÉIc                 ól   — | j         5  t          | j        ¦  «        cddd¦  «         S # 1 swxY w Y   dS )z*Number of host jobs currently provisioned.N)rÆ  rL   rÃ  rE   s    r3   rÛ  zSandboxPool.num_hostsÖ  s}   € ð ŒZð 	$ð 	$Ý�t”{Ñ#Ô#ð	$ð 	$ð 	$ð 	$ñ 	$ô 	$ð 	$ð 	$ð 	$ð 	$ð 	$ð 	$øøøð 	$ð 	$ð 	$ð 	$ð 	$ð 	$s   ˆ)©-°-c                 ó€   — | j         5  t          d„ | j        D ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS )z<Number of sandboxes currently handed out (across all hosts).c              3   ó$   K  — | ]}|j         V — Œd S rz   )rÿ   ©r©   r÷  s     r3   ú	<genexpr>z,SandboxPool.num_sandboxes.<locals>.<genexpr>à  s$   è è € Ð9Ð9 T�t”yÐ9Ð9Ð9Ð9Ð9Ð9r5   N)rÆ  ÚsumrÃ  rE   s    r3   Únum_sandboxeszSandboxPool.num_sandboxesÜ  sŒ   € ð ŒZð 	:ð 	:ÝÐ9Ð9¨T¬[Ð9Ñ9Ô9Ñ9Ô9ð	:ð 	:ð 	:ð 	:ñ 	:ô 	:ð 	:ð 	:ð 	:ð 	:ð 	:ð 	:øøøð 	:ð 	:ð 	:ð 	:ð 	:ð 	:s   ˆ3³7º7c                 óf   — | j         5  d„ | j        D ¦   «         cddd¦  «         S # 1 swxY w Y   dS )z!Job ids of the provisioned hosts.c                 ó   — g | ]	}|j         ‘Œ
S rW   ©rì   rû  s     r3   r«   z(SandboxPool.host_ids.<locals>.<listcomp>æ  s   € Ð8Ð8Ð8 D�D”KÐ8Ð8Ð8r5   N)rÆ  rÃ  rE   s    r3   râ  zSandboxPool.host_idsâ  sƒ   € ð ŒZð 	9ð 	9Ø8Ð8¨D¬KÐ8Ñ8Ô8ð	9ð 	9ð 	9ð 	9ñ 	9ô 	9ð 	9ð 	9ð 	9ð 	9ð 	9ð 	9øøøð 	9ð 	9ð 	9ð 	9ð 	9ð 	9s   ˆ&¦*­*c                 ó¾  — | j         5  | j        }g | _        d| _        ddd¦  «         n# 1 swxY w Y   |D ]ˆ}	 | j        r|                     ¦   «          n<# t
          $ r/}t                               d|j        › d|› �¦  «         Y d}~nd}~ww xY w| 	                    ¦   «          Œp# | 	                    ¦   «          w xY w| j        rt          | j        ¦  «         dS dS )uÂ  Release the pool. Idempotent.

        For a pool we created, this terminates all host jobs (and therefore all their
        sandboxes). For a `connect()`'d handle it only releases the local HTTP clients: the
        shared hosts may be serving other clients, so â€” like [`Sandbox.connect`] â€” leaving a
        `with` block must not tear them down. Terminate a connected pool's hosts explicitly
        with `hf sandbox pool delete <id>`.
        TNúFailed to cancel sandbox host r…  )rÆ  rÃ  rÉ  rÌ  r"  rã   rn  ro  rì   r  r   rj   )rF   Úhostsr÷  rË   s       r3   r  zSandboxPool.closeè  sM  € ð ŒZð 	 ð 	 Ø”KˆEØˆDŒKØˆDŒLð	 ð 	 ð 	 ñ 	 ô 	 ð 	 ð 	 ð 	 ð 	 ð 	 ð 	 øøøð 	 ð 	 ð 	 ð 	 ð ð 	ð 	ˆDðØÔ#ð &Ø—O’OÑ%Ô%Ð%øøÝð Tð Tð TÝ—’ÐRÀÄÐRÐRÈqÐRÐRÑSÔSÐSÐSÐSÐSÐSÐSøøøøðTøøøð —
’
‘”��ø�—
’
‘”��øøøØÔð 	)Ý˜dœiÑ(Ô(Ð(Ð(Ð(ð	)ð 	)s;   ˆ*ª.±.ºAÁB'Á
BÁ %B
ÂB'Â
BÂB'Â'B=c                 ó   — | S rz   rW   rE   s    r3   rˆ  zSandboxPool.__enter__   r‰  r5   c                 ó.   — |                       ¦   «          d S rz   )r  r‹  s     r3   r�  zSandboxPool.__exit__  s   € Ø�
Š
‰Œˆˆˆr5   c                 óð  — | j         5  | j        r	 ddd¦  «         dS |                      ¦   «          | j        €| j        nt          | j        | j        ¦  «        }| j        5  |t          | j        ¦  «        z
  }ddd¦  «         n# 1 swxY w Y   |dk    r¥|  	                    ¦   «          | j
        sŠ| j        5  |t          | j        ¦  «        z
  }ddd¦  «         n# 1 swxY w Y   |dk    rN|                      |¦  «        }| j        5  | j                             |¦  «         ddd¦  «         n# 1 swxY w Y   d| _        ddd¦  «         n# 1 swxY w Y   | j        r|                      ¦   «          dS dS )u©  One-time: seed from the cache and pre-provision up to `warm_up` hosts.

        Cheap by default: seeding is local (no HTTP), and if the cache already gives at
        least `warm_up` hosts we trust them and skip discovery/booting (dead ones are
        pruned lazily by `create()`). Only when short do we list_jobs and boot the
        shortfall in parallel, capped by `max_hosts`.

        Runs at most once per pool, under `_warmup_lock`: concurrent first `create()` calls
        block here until the warm-up completes â€” and see its hosts â€” rather than racing past
        a half-set flag and each booting their own. `_warmed_up` is only set once the work
        succeeds, so a failed warm-up is retried (seeding/discovery dedupe by job id).

        Warm-up hosts are pool-level (like [`warm`]): they are not torn down if the
        triggering `create()` later fails â€” `close()` (or the `with` block) reclaims them.
        Nr   T)rÇ  rÊ  Ú_seed_hosts_from_cacher»  r¿  r¨   rÆ  rL   rÃ  rÞ  rË  rß  rà  rá  )rF   Útargetrã  rä  s       r3   rÏ  zSandboxPool._ensure_warmed_up  s›  € ð  Ôð 	#ð 	#ØŒð Øð	#ð 	#ð 	#ñ 	#ô 	#ð 	#ð 	#ð 	#ð ×'Ò'Ñ)Ô)Ð)Ø&*¤nÐ&<�T”]�]Å#ÀdÄmÐUYÔUcÑBdÔBdˆFØ”ð 6ð 6Ø"¥S¨¬Ñ%5Ô%5Ñ5�	ð6ð 6ð 6ñ 6ô 6ð 6ð 6ð 6ð 6ð 6ð 6øøøð 6ð 6ð 6ð 6à˜1Š}ˆ}Ø×$Ò$Ñ&Ô&Ð&ð Ô.ð 7Øœð >ð >Ø$*­S°´Ñ-=Ô-=Ñ$=˜	ð>ð >ð >ñ >ô >ð >ð >ð >ð >ð >ð >øøøð >ð >ð >ð >à  1’}�}Ø!%×!6Ò!6°yÑ!AÔ!A˜Ø!œZð 7ð 7Ø œK×.Ò.¨vÑ6Ô6Ð6ð7ð 7ð 7ñ 7ô 7ð 7ð 7ð 7ð 7ð 7ð 7øøøð 7ð 7ð 7ð 7à"ˆDŒOð'	#ð 	#ð 	#ñ 	#ô 	#ð 	#ð 	#ð 	#ð 	#ð 	#ð 	#øøøð 	#ð 	#ð 	#ð 	#ð, Œ;ð 	Ø×ÒÑÔÐÐÐð	ð 	sƒ   ˆ	EžAEÁ!BÁ9EÂB		Â	EÂB		Â+EÂ8CÃEÃC 	Ã EÃ#C 	Ã$%EÄ	D0Ä$EÄ0D4	Ä4EÄ7D4	Ä8
EÅEÅEú_SandboxServer | Nonec                 óÀ   — | j         5  | j        D ]5}|j        |j        z
  dk    r |xj        dz  c_        |c cddd¦  «         S Œ6	 ddd¦  «         n# 1 swxY w Y   dS )zNReserve one slot on the first host with free capacity (under lock), else None.r   r   N)rÆ  rÃ  rë   rÿ   ©rF   r÷  s     r3   rí  zSandboxPool._reserve_one1  sÑ   € àŒZð 	 ð 	 Øœð  ð  �Ø”= 4¤9Ñ,¨qÒ0Ð0Ø�I”I ‘N�I”IØ�K�Kð		 ð 	 ð 	 ð 	 ñ 	 ô 	 ð 	 ð 	 à0ð ð	 ð 	 ð 	 ñ 	 ô 	 ð 	 ð 	 ð 	 ð 	 ð 	 ð 	 øøøð 	 ð 	 ð 	 ð 	 ð
 ˆts   ˆ0AÁAÁAÁArì  rè   c                 óê  — | j         5  |                      ¦   «         }|�|cddd¦  «         S |                      ¦   «         r$|                      ¦   «         }|�|cddd¦  «         S |                      d¦  «        }|                     |¦  «         | j        5  | j                             |¦  «         ddd¦  «         n# 1 swxY w Y   |                      ¦   «         cddd¦  «         S # 1 swxY w Y   dS )uh  Provision (or adopt) one host and reserve a slot on it. Returns None to retry.

        Held under `_boot_lock` so that, within a process, only one host is booted at a time:
        a burst of create() calls that all found every host full queue here, and each new host
        frees `sandboxes_per_host` slots for the threads still waiting â€” so they reuse it instead
        of each booting their own. Before booting, we reuse a slot freed by a concurrent boot and,
        failing that, adopt a host already SCHEDULING for this pool (here or in another process)
        rather than piling on a duplicate.
        Nr   )rÈ  rí  Ú_adopt_pending_hostrß  rà  rÆ  rÃ  )rF   rì  r÷  rä  s       r3   rî  zSandboxPool._boot_one_host:  s·  € ð Œ_ð 	'ð 	'ð ×$Ò$Ñ&Ô&ˆDØÐØð	'ð 	'ð 	'ð 	'ñ 	'ô 	'ð 	'ð 	'ð ×'Ò'Ñ)Ô)ð  Ø×(Ò(Ñ*Ô*�ØÐ#Øð	'ð 	'ð 	'ð 	'ñ 	'ô 	'ð 	'ð 	'ð ×*Ò*¨1Ñ-Ô-ˆFØ×Ò˜VÑ$Ô$Ð$Ø”ð +ð +Ø”×"Ò" 6Ñ*Ô*Ð*ð+ð +ð +ñ +ô +ð +ð +ð +ð +ð +ð +øøøð +ð +ð +ð +à×$Ò$Ñ&Ô&ð!	'ð 	'ð 	'ð 	'ñ 	'ô 	'ð 	'ð 	'ð 	'ð 	'ð 	'ð 	'øøøð 	'ð 	'ð 	'ð 	'ð 	'ð 	's@   ˆC(­+C(Á%1C(ÂB=Â1C(Â=C	ÃC(ÃC	ÃC(Ã(C,Ã/C,c           
      óÐ  ‡‡— d„ | j         D ¦   «         Št          ˆfd„| j                             dt          t
          t          | j        i| j        ¬¦  «        D ¦   «         d¦  «        Š‰€dS t           
                    d| j        › d‰j        › d	�¦  «         t          j        ¦   «         | j        z   }t          j        ¦   «         |k     r�| j                             ‰j        | j        ¬
¦  «        j        j        }|dvrdS |dk    r6|                      ¦   «          t%          ˆfd„| j         D ¦   «         ¦  «        rdS t          j        d¦  «         t          j        ¦   «         |k     °�dS )aÃ  Wait for and adopt a host already SCHEDULING for this pool, if any.

        Avoids over-provisioning when a host is already on its way up for this pool (started by
        another process, or an earlier create() in this one): rather than booting a duplicate,
        wait for it to reach RUNNING and adopt it via discovery. Returns True if a pending host
        was found (whether or not it eventually came up), False if none is scheduling.
        c                 ó   — h | ]	}|j         ’Œ
S rW   r  rû  s     r3   rx  z2SandboxPool._adopt_pending_host.<locals>.<setcomp>^  ó   € Ð5Ð5Ð5 �”Ð5Ð5Ð5r5   c              3   ó.   •K  — | ]}|j         ‰v¯|V — Œd S rz   rv  ©r©   r  Úknowns     €r3   rü  z2SandboxPool._adopt_pending_host.<locals>.<genexpr>`  s@   øè è € ð ð àð
 ”6 Ð&Ð&ð ð 'Ð&Ð&Ð&ðð r5   Ú
SCHEDULING©r+  r`  r!  NFzPool 'z' host z: is already SCHEDULING; waiting for it instead of booting.r   )r  r{  r{  c              3   ó8   •K  — | ]}|j         ‰j        k    V — Œd S rz   ©rì   r  )r©   r÷  Úpendings     €r3   rü  z2SandboxPool._adopt_pending_host.<locals>.<genexpr>w  s,   øè è € ÐIÐI°T�t”{ g¤jÒ0ÐIÐIÐIÐIÐIÐIr5   Tg      ð?)rÃ  Únextrû   Ú	list_jobsrj  r�  Ú
POOL_LABELrj   rÁ  rn  Údebugr  r(  rÂ  r*  r+  r,  rÞ  Úanyr/  )rF   r0  r,  r  r  s      @@r3   r  zSandboxPool._adopt_pending_hostV  sƒ  øø€ ð 6Ð5¨¬Ð5Ñ5Ô5ˆÝðð ð ð àœ9×.Ò.Ø'Ý&­	µ:¸t¼yÐIØ"œoð /ñ ô ðñ ô ð ñ
ô 
ˆð ˆ?Ø�5Ý�ŠÐv˜dœiÐvÐv°´
ÐvÐvÐvÑwÔwÐwÝ”9‘;”; Ô!4Ñ4ˆÝŒi‰kŒk˜HÒ$Ð$Ø”I×)Ò)°´ÀtÄÐ)ÑWÔWÔ^ÔdˆEØÐ5Ð5Ð5Ø�uØ˜	Ò!Ð!ð ×$Ò$Ñ&Ô&Ð&ÝÐIÐIÐIÐI¸T¼[ÐIÑIÔIÑIÔIð  Ø˜4ÝŒJ�s‰OŒOˆOõ Œi‰kŒk˜HÒ$Ð$ð ˆur5   c                 ó¼  ‡‡— d„ | j         D ¦   «         Šˆfd„| j                             dt          t          t
          | j        i| j        ¬¦  «        D ¦   «         }|D �]~Šd}	 t          | j        ‰j	        | j        ¬¦  «        }t          | j        ‰| j        ¬¦  «        }t          |                     d| j        ¦  «        ¦  «        |_        t          |                     dd	¦  «                             ¦   «         ¦  «        |_        ne# t&          t(          j        t,          f$ rF}t.                               d
‰j	        › d|› �¦  «         |�|                     ¦   «          Y d}~�Œd}~ww xY w| j        5  t7          ˆfd„| j         D ¦   «         ¦  «        r|                     ¦   «          n| j                              |¦  «         ddd¦  «         n# 1 swxY w Y   �Œ€dS )aE  Attach to running host jobs that match this pool (image/flavor/name).

        Lets `create()` reuse a host warmed by an earlier call or another process
        instead of booting a new one. Hosts are found via job labels; each adopted
        host's free capacity is read from the server, so packing stays accurate.
        c                 ó   — h | ]	}|j         ’Œ
S rW   r  rû  s     r3   rx  z.SandboxPool._discover_hosts.<locals>.<setcomp>ƒ  r  r5   c                 ó&   •— g | ]}|j         ‰v¯|‘ŒS rW   rv  r  s     €r3   r«   z/SandboxPool._discover_hosts.<locals>.<listcomp>„  s4   ø€ ð 
ð 
ð 
àð
 Œv˜UÐ"Ð"ð ð #Ð"Ð"r5   r{  r  Nr&  rÔ  r~   ry  zSkipping host z during discovery: c              3   ó8   •K  — | ]}|j         ‰j        k    V — Œd S rz   r  )r©   r÷  r  s     €r3   rü  z.SandboxPool._discover_hosts.<locals>.<genexpr>Ÿ  s,   øè è € ÐEÐE°�t”{ c¤fÒ,ÐEÐEÐEÐEÐEÐEr5   )rÃ  rû   r  rj  r�  r  rj   rÁ  r€  r  rÖ  r9   rÞ   r¹  rë   rL   r  rÆ   rÿ   r   r  Ú	HTTPErrorr   rn  r  r  rÆ  r  rœ  )rF   ÚmatchesrE  rW  rË   r  r  s        @@r3   rÞ  zSandboxPool._discover_hosts|  s-  øø€ ð 6Ð5¨¬Ð5Ñ5Ô5ˆð
ð 
ð 
ð 
à”y×*Ò*Ø Ý"¥I­z¸4¼9ÐEØœ/ð +ñ ô ð
ñ 
ô 
ˆð ð 	/ñ 	/ˆCØˆFðÝ& t¤y°#´&ÀDÄOÐTÑTÔT�õ   ¤	¨3¸$¼/ÐJÑJÔJ�Ý"% c§g¢g¨n¸dÔ>UÑ&VÔ&VÑ"WÔ"W�”Ý! &§.¢.°¸Ñ"HÔ"H×"MÒ"MÑ"OÔ"OÑPÔP�”�øÝ ¥%¤/µ>ÐBð ð ð õ —’ÐL¨c¬fÐLÐLÈÐLÐLÑMÔMÐMØÐ%Ø—L’L‘N”N�NØ���‘øøøøðøøøð ”ð /ð /ÝÐEÐEÐEÐE¸¼ÐEÑEÔEÑEÔEð /Ø—L’L‘N”N�N�Nà”K×&Ò& vÑ.Ô.Ð.ð	/ð /ð /ñ /ô /ð /ð /ð /ð /ð /ð /øøøð /ð /ð /ð /ùð!	/ð 	/s,   Á"B$DÄE)Ä#;E$Å$E)Å3AGÇG	ÇG	Únum_newc                 óö  ‡ ‡
— ‰ j         5  t          ‰ j        ¦  «        }ddd¦  «         n# 1 swxY w Y   ‰ j        �D||z   ‰ j        k    r6‰ j        |z
  }t	          d|› d‰ j        › dt          d|¦  «        › d�¦  «        ‚t          t          |d¦  «        ¬¦  «        5 Š
ˆ
ˆ fd	„t          |¦  «        D ¦   «         }ddd¦  «         n# 1 swxY w Y   g }d}|D ]C}	 | 	                    | 
                    ¦   «         ¦  «         Œ+# t          $ r}|}Y d}~Œ<d}~ww xY w|�Z|D ]U}		 |	                     ¦   «          n# t          $ r Y nw xY w|	                     ¦   «          Œ=# |	                     ¦   «          w xY w|‚|S )
z=Boot `num_new` host jobs in parallel, respecting `max_hosts`.NzPool needs z more host(s) but max_hosts=z allows only r   z. more. Raise max_hosts or kill some sandboxes.é    )Úmax_workersc                 óD   •— g | ]}‰                      ‰j        ¦  «        ‘ŒS rW   )ÚsubmitÚ
_boot_host)r©   Ú_r¶   rF   s     €€r3   r«   z0SandboxPool._provision_hosts.<locals>.<listcomp>²  s'   ø€ ÐPÐPÐP¸A�x—’ t¤Ñ7Ô7ÐPÐPÐPr5   )rÆ  rL   rÃ  r»  r   rð  r   r¨   r­   rœ  r›  rã   r"  r  )rF   r%  ÚcurrentÚallowedÚfuturesrä  râ   ÚfuturerË   rE  r¶   s   `         @r3   rß  zSandboxPool._provision_hosts¤  sn  øø€ àŒZð 	'ð 	'Ý˜$œ+Ñ&Ô&ˆGð	'ð 	'ð 	'ñ 	'ô 	'ð 	'ð 	'ð 	'ð 	'ð 	'ð 	'øøøð 	'ð 	'ð 	'ð 	'àŒ>Ð%¨'°GÑ*;¸d¼nÒ*LÐ*LØ”n wÑ.ˆGÝð_˜gð _ð _À4Ä>ð _ð _Ý" 1 g™œð_ð _ð _ñô ð õ  ­C°¸Ñ,<Ô,<Ð=Ñ=Ô=ð 	QÀØPÐPÐPÐPÐPÅÀwÁÄÐPÑPÔPˆGð	Qð 	Qð 	Qñ 	Qô 	Qð 	Qð 	Qð 	Qð 	Qð 	Qð 	Qøøøð 	Qð 	Qð 	Qð 	Qà')ˆØ"&ˆØð 	ð 	ˆFðØ—’˜fŸmšm™oœoÑ.Ô.Ð.Ð.øÝð ð ð Ø������øøøøðøøøàÐØ ð #ð #�ð#Ø×%Ò%Ñ'Ô'Ð'Ð'øÝ ð ð ð Ø�Dðøøøð —L’L‘N”N�N�Nø�F—L’L‘N”N�N�NøøøØˆKØˆs`   Š+«/²/ÂCÃCÃCÃ'DÄ
DÄDÄDÄ$D9Ä8EÄ9
EÅEÅEÅEÅE4c                 óÔ  — t          | j        ¦  «        }t          d¦  «        }t          ||¦  «        }t	          | j        |ddd| j        d|¬¦  «        \  }}}}d|d<   t          | j        ¦  «        |d<   | j        �t          | j        ¦  «        |d<   t          dt          t          t          | j        t          |i}| j                             | j        |||| j        t$          ||pdt&          g| j        ¬	¦
  «
        }	d}
	 t*                               |	||| j        t/          | j        d
z   d¦  «        | j        ¬¦  «        }
|
                     | j        ¦  «         nŽ# t4          $ r� 	 | j                             |	j        |	j        j        ¬¦  «         n<# t4          $ r/}t<                               d|	j        › d|› �¦  «         Y d}~nd}~ww xY w|
�|
                      ¦   «          ‚ w xY w|
S )z6Start one host job and wait until its server is ready.rw   NFr]  rÏ   ÚSBX_HOST_MODErÔ  rÓ  r^  r(   é   )r  r*   rð   rñ   rê   rë   r   r  rd  )!rü   rû   r   r4   rf  rÀ  rT   r¹  r»  ri  rj  r�  r  rj   rl  rg  rî   rU  rh  rm  rÁ  rè   r  r¨   r3  rÂ  rã   r"  r  rí   rn  ro  r  )rF   r)   r*   rð   r_  rp  rq  rr  r`  r  rE  rË   s               r3   r+  zSandboxPool._boot_hostÅ  s/  € å# D¤IÑ.Ô.ˆÝ˜"‘”ˆÝ-¨h¸Ñ>Ô>ˆÝ5HØŒIØØØØØÔ+Ø"Ø'ð	6
ñ 	6
ô 	6
Ñ2ˆ�˜+ {ð $'ˆ�Ñ õ
 #& dÔ&=Ñ">Ô">ˆ�Ñð Œ>Ð%Ý'*¨4¬>Ñ':Ô':ˆG�OÑ$Ý ¥jµ)½ZÈÌÕT_ÐafÐgˆØŒi×ÒØ”*ØØØØ”;Ý(ØØÐ' 4Ý'Ð(Ø”oð  ñ 
ô 
ˆð +/ˆð	õ $×,Ò,ØØØ+Ø”IÝ # DÔ$;¸aÑ$?ÀÑ EÔ EØÔ0ð -ñ ô ˆFð ×Ò˜dÔ1Ñ2Ô2Ð2Ð2øÝð 	ð 	ð 	ðeØ”	×$Ò$¨C¬F¸c¼i¼nÐ$ÑMÔMÐMÐMøÝð eð eð eÝ—’ÐcÀÄÐcÐcÐ`aÐcÐcÑdÔdÐdÐdÐdÐdÐdÐdøøøøðeøøøàÐ!Ø—’‘”�Øð	øøøð ˆs7   Ã?AE Å
G%Å%+FÆG%Æ
G
Æ%GÇ G%ÇG
Ç
G%r÷  rô  r=  c                 ó¶  — ddi}|�||d<   |r||d<   	 |                      dd|¬¦  «                             ¦   «         }nf# t          t          j        f$ rM}|j        r‚ t                               d	|j        › d
|› �¦  «         |  	                    |¦  «         Y d}~dS d}~ww xY wd|_        | 
                    d¦  «        pg }t          | 
                    dd¦  «        ¦  «        s|s-| j        5  |j        |_        ddd¦  «         n# 1 swxY w Y   dS |d         }t          |j        › t           › |d         › �||d         dd¬¦  «        }	| j        |	_        |	S )u¡  Create one sandbox on a reserved `host`. Returns the sandbox, or None to retry.

        None means either the host filled up between our reservation and the create
        (server-authoritative capacity â€” another client packed it, so we mark it full and
        place the sandbox elsewhere) or a host rebuilt from the cache is gone/unreachable
        (dropped and re-placed via discovery / a fresh boot).
        Úcountr   NÚidle_timeout_secsrW  rÒ   ry  r™  z!Dropping unreachable cached host r…  TÚ	sandboxesÚrejectedr   r  Fre  )r  rÆ   r   r  r#  r   rn  r  rì   Ú
_drop_hostrÞ   r9   rÆ  rë   rÿ   r^   r~  Ú_on_sandbox_killedrP  )
rF   r÷  rW  rô  ÚbodyrŽ   rË   r7  rw  rx   s
             r3   rï  zSandboxPool._create_one  s×  € ð !(¨˜|ˆØÐ Ø(1ˆDÐ$Ñ%Øð 	ØˆD�‰Kð	Ø—<’< ¨¸d�<ÑCÔC×HÒHÑJÔJˆDˆDøÝ�eœoÐ.ð 	ð 	ð 	ØŒ}ð ØÝ�LŠLÐO¸T¼[ÐOÐOÈAÐOÐOÑPÔPÐPØ�OŠO˜DÑ!Ô!Ð!Ø�4�4�4�4�4øøøøð	øøøð ˆŒØ—H’H˜[Ñ)Ô)Ð/¨Rˆ	Ýˆt�xŠx˜
 AÑ&Ô&Ñ'Ô'ð 	¨yð 	Ø”ð *ð *Ø œM�”	ð*ð *ð *ñ *ô *ð *ð *ð *ð *ð *ð *øøøð *ð *ð *ð *à�4Ø˜Œ|ˆÝØ”+Ð:�}Ð:¨d°4¬jÐ:Ð:ØØ˜$”ZØØð
ñ 
ô 
ˆð  Ô2ˆÔØˆs(   ”*? ¿B"ÁABÂB"Ã/DÄDÄDrx   c                 ó”   — | j         5  t          d|j        j        dz
  ¦  «        |j        _        ddd¦  «         dS # 1 swxY w Y   dS )z:Free the packing slot of a shared sandbox that was killed.r   r   N)rÆ  rð  rK  rÿ   r{   s     r3   r:  zSandboxPool._on_sandbox_killed+  s    € àŒZð 	Dð 	DÝ#& q¨'¬/Ô*>ÀÑ*BÑ#CÔ#CˆGŒOÔ ð	Dð 	Dð 	Dñ 	Dô 	Dð 	Dð 	Dð 	Dð 	Dð 	Dð 	Dð 	Døøøð 	Dð 	Dð 	Dð 	Dð 	Dð 	Ds   ˆ(=½AÁAc                 óÜ   ‡— | j         5  ˆfd„| j        D ¦   «         | _        | j                             ‰j        ¦  «         ddd¦  «         n# 1 swxY w Y   ‰                     ¦   «          dS )zFForget a host found dead this session (and mark it for cache pruning).c                 ó   •— g | ]}|‰u¯|‘Œ	S rW   rW   )r©   rë  r÷  s     €r3   r«   z*SandboxPool._drop_host.<locals>.<listcomp>3  s   ø€ ÐCÐCÐC °Q¸d°]°]˜1°]°]°]r5   N)rÆ  rÃ  rÎ  Úaddrì   r  r  s    `r3   r9  zSandboxPool._drop_host0  s©   ø€ àŒZð 	1ð 	1ØCÐCÐCÐC d¤kÐCÑCÔCˆDŒKØÔ×#Ò# D¤KÑ0Ô0Ð0ð	1ð 	1ð 	1ñ 	1ô 	1ð 	1ð 	1ð 	1ð 	1ð 	1ð 	1øøøð 	1ð 	1ð 	1ð 	1ð 	�
Š
‰Œˆˆˆs   ‰8AÁAÁAc                 ó,  — t          | j        ¦  «        }|€dS t          | j        ¦  «        }| j        5  d„ | j        D ¦   «         }|j        D ]­}|j        |v s|j        |j	        k    rŒt          |j        |j        | j        |j        |j        t          ||j        ¦  «        | j        t!          | j        dz   d¦  «        |j	        ¬¦	  «	        }|j        |_        d|_        | j                             |¦  «         Œ®	 ddd¦  «         dS # 1 swxY w Y   dS )uË  Adopt the pool's cached hosts without any HTTP (rebuilt from cached URL + nonce).

        Best-effort and unverified: each adopted host is confirmed on the first successful
        request (and dropped on the first failure, see `_create_one`). Hosts the cache
        believes are full are skipped â€” label discovery re-checks them with fresh counts if
        the seeded ones don't satisfy the request, so a stale-full entry never blocks a create.
        Nc                 ó   — h | ]	}|j         ’Œ
S rW   r  rû  s     r3   rx  z5SandboxPool._seed_hosts_from_cache.<locals>.<setcomp>F  s   € Ð9Ð9Ð9 T�T”[Ð9Ð9Ð9r5   r(   r3  r  F)r   rj   rü   rû   rÆ  rÃ  r  rì   rÿ   rë   rè   rí   rî   rï   r*   r4   r¨   r¹  r   rœ  )rF   rØ  r)   r  ÚchrE  s         r3   r  z"SandboxPool._seed_hosts_from_cache9  sg  € õ   ¤	Ñ*Ô*ˆØˆ=ØˆFÝ# D¤IÑ.Ô.ˆØŒZð 	+ð 	+Ø9Ð9¨T¬[Ð9Ñ9Ô9ˆEØ”kð +ð +�Ø”9 Ð%Ð%¨¬°B´KÒ)?Ð)?ØÝ'Øœ9Øœ(Øœ*Øœ[Øœ(Ý"7¸À"Ä(Ñ"KÔ"KØœ	Ý$'¨Ô(?À!Ñ(CÀSÑ$IÔ$IØœ[ð
ñ 
ô 
�ð !œg�”Ø"'�”Ø”×"Ò" 6Ñ*Ô*Ð*Ð*ð!+ð	+ð 	+ð 	+ñ 	+ô 	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+øøøð 	+ð 	+ð 	+ð 	+ð 	+ð 	+s   ´CD	Ä	DÄDc                 ó0  — | j         5  d„ | j        D ¦   «         }t          | j        ¦  «        }ddd¦  «         n# 1 swxY w Y   t	          | j        | j        | j        | j        | j	        | j
        �t          | j
        ¦  «        nd| j        ||¬¦	  «	         dS )zOPersist the pool config + current hosts (with their live counts) for next time.c                 ó˜   — g | ]G}t          |j        |j        |j        |j        |j        |j        t          j        ¦   «         ¬ ¦  «        ‘ŒHS ))rì   rí   rï   r*   rë   rÿ   Ú
updated_at)r   rì   rí   rï   r*   rë   rÿ   r(  rû  s     r3   r«   z+SandboxPool._save_cache.<locals>.<listcomp>\  s`   € ð ð ð ð õ Øœ;Øœ*Ø!œ]Øœ*Ø!œ]ØœÝ#œy™{œ{ðñ ô ðð ð r5   N)rî   rU  r¹  r»  rV  r!  r  Údead_host_ids)rÆ  rÃ  rÍ  rÎ  r   rj   rî   rU  r¹  r»  rÀ  r;   rÁ  )rF   r  Údeads      r3   rá  zSandboxPool._save_cacheY  sø   € àŒZð 	,ð 	,ðð ð !œKðñ ô ˆEõ �tÔ*Ñ+Ô+ˆDð	,ð 	,ð 	,ñ 	,ô 	,ð 	,ð 	,ð 	,ð 	,ð 	,ð 	,øøøð 	,ð 	,ð 	,ð 	,õ 	ØŒIØ”*Ø”;Ø#Ô6Ø”nØBFÔBTÐB`Õ*¨4Ô+=Ñ>Ô>Ð>ÐfjØ”oØØð
	
ñ 
	
ô 
	
ð 
	
ð 
	
ð 
	
s   ˆ&:º>Á>)r   rg   )r+   r¸  )r+   r
  )(rO   rP   rQ   rR   r´  r×  rµ  rT   r9   r:   rU   r|   r4  r  r   rå  r¶  r	   rs  rV   rÛ  rþ  râ  r  rˆ  r�  rÏ  rí  rî  r  rÞ  rè   rß  r+  rï  r^   r:  r9  r  rá  rW   r5   r3   r¸  r¸  •  s9  € € € € € ð!ð !ðJ #ð`%ð "Ø"<ØØ $ØØ1EØ $Ø$Ø Ø#ð`%ð `%ð `%àð`%ð ð	`%ð
  ð`%ð ð`%ð ˜‘:ð`%ð �D‰jð`%ð ˜E‘k CÑ'¨$Ñ.ð`%ð ˜‘:ð`%ð ð`%ð �T‰zð`%ð ð`%ð 
ð`%ð `%ð `%ð `%ðH Ø>BÐX\ð 4
ð 4
ð 4
˜cð 4
°°t±ð 4
È3ÐQUÉ:ð 4
Ðanð 4
ð 4
ð 4
ñ „[ð4
ðlð ˜cð ¨$¨s¬)ð ð ð ð ð< &*Ø1EØ!&ðeð eð eð �#�s�(Œ^˜dÑ"ðeð ˜E‘k CÑ'¨$Ñ.ð	eð
 ðeð 
ðeð eð eð eðN ð$˜3ð $ð $ð $ñ „Xð$ð
 ð:˜sð :ð :ð :ñ „Xð:ð
 ð9˜$˜sœ)ð 9ð 9ð 9ñ „Xð9ð
)ð )ð )ð )ð0ð ð ð ðð ð ð ð
'ð 'ð 'ð 'ðRð ð ð ð'¨Ð-=Ô(>ð 'ÐCZð 'ð 'ð 'ð 'ð8$ Tð $ð $ð $ð $ðL&/ð &/ð &/ð &/ðP¨ð °°^Ô0Dð ð ð ð ðB>˜Nð >ð >ð >ð >ð@$Ð 0ð $°t¸CÀ¸H´~ð $ÐRUÐX\ÑR\ð $Ðaqð $ð $ð $ð $ðLD¨'ð D°dð Dð Dð Dð Dð
˜~ð °$ð ð ð ð ð+ð +ð +ð +ð@
ð 
ð 
ð 
ð 
ð 
r5   r¸  rñ   c                 ó†   — t          | j        t          ¦  «        r| j        nt          ¦   «         }|st	          d¦  «        ‚|S )NzMA Hugging Face token is required to use sandboxes. Run `hf auth login` first.)r8   r@  rT   r   r   )rñ   r@  s     r3   rü   rü   v  s?   € Ý# C¤I­sÑ3Ô3ÐDˆCŒIˆI½¹¼€EØð lÝÐjÑkÔkÐkØ€Lr5   rW  rX  rY  rV  rZ  rð   c                ó’  — i |pi ¥dt          t          ¦  «        i¥}i |pi ¥d|i¥}	t          |pg ¦  «        }
|�t          t          |¦  «        ¦  «        |d<   |r||	d<   | j        › dt
          j        › d�|d<   t          |d	<   |
                     t          d
t
          j        t          d¬¦  «        ¦  «         ddt          g}|||	|
fS )aU  Build the (command, env, secrets, volumes) to launch a job running sbx-server.

    Shared by dedicated sandboxes and shared hosts: both fetch and exec the same unified
    `sbx-server` binary at startup (via `/bin/sh`), downloading it with wget/curl, or
    reading it off the always-mounted server bucket when the image ships neither.
    ÚSBX_PORTÚ	SBX_TOKENNrÒ  rç  z	/buckets/z/resolve/sbx-serverÚSBX_SERVER_URLÚSBX_SERVER_MOUNTÚbucketT)ro   ÚsourceÚ
mount_pathÚ	read_onlyz/bin/shz-c)rT   rm  r³   r;   Úendpointr   ÚSANDBOX_SERVER_BUCKETÚ_SERVER_MOUNT_PATHrœ  r   Ú_BOOTSTRAP_DOWNLOAD)rñ   r)   rW  rX  rY  rV  rZ  rð   rp  rq  rr  r_  s               r3   rf  rf  }  s   € ð& T # )¨ÐS¨j½#Õ>QÑ:RÔ:RÐSÐS€GØ"Q g m°Ð"Q°kÀ=Ð"QÐ"Q€KÝ�w�} "Ñ%Ô%€KØÐÝ&)Õ*;¸LÑ*IÔ*IÑ&JÔ&JˆÐ"Ñ#Øð +Ø"*ˆ�JÑà#&¤<Ð nÐ n½)Ô:YÐ nÐ nÐ n€GÐÑõ #5€GÐÑØ×ÒÝ�H¥YÔ%DÕQcÐosÐtÑtÔtñô ð ð ˜$Õ 3Ð4€GØ�G˜[¨+Ð5Ð5r5   r  r!  c                óÌ   — t          |j        t          ¦  «        r|j        ni }d|vr<|                      |j        |¬¦  «        j        pi }t          |t          ¦  «        r|ni }|S )z6Return a host job's env vars (where pool config lives)rÔ  r   )r8   Úenvironmentr¶  r*  r  )rñ   r  r!  rW  s       r3   rÖ  rÖ  £  sf   € å'¨¬½Ñ>Ô>Ð
Fˆ#Œ/ˆ/ÀB€CØ˜SÐ Ð Ø�oŠo S¤V°yˆoÑAÔAÔMÐSÐQSˆÝ ¥TÑ*Ô*Ð2ˆcˆc°ˆØ€Jr5   r&  rÐ  c                óŠ   — |                       dt          t          t          |i|¬¦  «        D ]}|c S t	          d|› d�¦  «        ‚)zNReturn any running host job belonging to `pool_id` (found via the pool label).r{  r  rè  ré  )r  rj  r�  r  r   )rñ   rÐ  r!  r  s       r3   rÕ  rÕ  ¬  sl   € à�}Š}Ø¥*­i½ÀWÐ!MÐYbð ñ ô ð ð ˆð ˆ
ˆ
ˆ
Ý
ð	K¨7ð 	Kð 	Kð 	Kñô ð r5   r‚  c          	      óÔ  — |                       ||¬¦  «        }|j        pi }|                     t          ¦  «        }|�#|                     t          ¦  «        t
          k    rt          d|› d�¦  «        ‚|j        j        dk    r t          d|› d|j        j        › d�¦  «        ‚t           
                    ||t          t          | ¦  «        |¦  «        | t          j        d	z   ¬
¦  «        S )z?Reattach to a running host job and return its server transport.r   Nrz  z is not a sandbox host.r{  zSandbox host r|  r'  rb  rc  )r*  r`  rÞ   rl  rj  r�  r   r+  r,  rè   r  r4   rü   ru   r²   )rñ   r‚  r!  r  r`  r*   s         r3   r€  r€  ¸  sé   € à
�/Š/ ¸	ˆ/Ñ
BÔ
B€CØŒZÐ˜2€FØ�JŠJ•{Ñ#Ô#€EØ€}˜Ÿ
š
¥:Ñ.Ô.µ)Ò;Ð;ÝÐF +ÐFÐFÐFÑGÔGÐGØ
„zÔ˜9Ò$Ð$ÝÐe¨;ÐeÐeÐQTÔQ[ÔQaÐeÐeÐeÑfÔfÐfÝ×"Ò"ØØÝ+Õ,<¸SÑ,AÔ,AÀ5ÑIÔIØÝ$Ô9¸AÑ=ð #ñ ô ð r5   rA  c                 ó¾   — d| vr| |fS |                       dd¦  «        \  }}|r|rd|v rt          d| ›d�¦  «        ‚|�||k    rt          d|›d|›d�¦  «        ‚||fS )zPAccept `namespace/sandbox_id` ids (as shown in the Hub UI), like `hf jobs` does.r¦  r   z?Sandbox id must be 'sandbox_id' or 'namespace/sandbox_id', got r#   Nz%Conflicting namespace: got namespace=z" but sandbox id implies namespace=)r  r   )rA  r!  Úextracted_namespaceÚ	parsed_ids       r3   r}  r}  Ê  s±   € à
�*ÐÐØ˜9Ð$Ð$Ø%/×%5Ò%5°c¸1Ñ%=Ô%=Ñ"Ð˜Øð n ið n°3¸)Ð3CÐ3CÝÐlÐ]gÐlÐlÐlÑmÔmÐmØÐ Ð.AÒ!AÐ!AÝØ{°IÐ{Ð{ÐcvÐ{Ð{Ð{ñ
ô 
ð 	
ð Ð)Ð)Ð)r5   c                 ó†   — | j         j        pg D ]}dt          › d�|v r|c S Œt          d| j        › dt          › d�¦  «        ‚)Nz--r#   rz  z) does not expose the sandbox server port )r+  Úexpose_urlsrm  r   r  )r  Úurls     r3   r  r  Ø  se   € ØŒzÔ%Ð+¨ð ð ˆØ&Õ#Ð&Ð&Ð&¨#Ð-Ð-ØˆJˆJˆJð .å
Ðe˜cœfÐeÐeÕObÐeÐeÐeÑ
fÔ
fÐfr5   é   )r!  Úlimitrì   ra  c                óÎ   — 	 t          |                      ||¬¦  «        ¦  «        | d …         }n# t          $ r Y dS w xY w|r"dd                     d„ |D ¦   «         ¦  «        z   ndS )Nr   rr   z Last logs:
ú
c              3   ó    K  — | ]	}d |› �V — Œ
dS )z  NrW   )r©   rß   s     r3   rü  z!_tail_job_logs.<locals>.<genexpr>ä  s(   è è € Ð&EÐ&E°t {¨D { {Ð&EÐ&EÐ&EÐ&EÐ&EÐ&Er5   )r³   Úfetch_job_logsrã   r„   )rñ   rì   r!  ra  Úliness        r3   r.  r.  ß  s‡   € ðÝ�S×'Ò'¨vÀÐ'ÑKÔKÑLÔLÈeÈVÈWÈWÔUˆˆøÝð ð ð ØˆrˆrðøøøàINÐVˆ?˜TŸYšYÐ&EÐ&E¸uÐ&EÑ&EÔ&EÑEÔEÑEÐEÐTVÐVs   ‚-0 °
>½>)^r0   r-   rÆ   rÄ  r(  Úconcurrent.futuresr   Ú
contextlibr   Údataclassesr   r   Úpathlibr   rX  r   Útypingr	   r
   r   r   r   r   r   r  rr   r   Ú_sandbox_cacher   r   r   r   Ú
_space_apir   Úerrorsr   r   r   Úhf_apir   r   Úutilsr   r   Úutils._parsingr   Ú
get_loggerrO   rn  rm  ri  rj  rk  r�  r  rl  r´  rµ  rh  r×  r~  r-  rò  rT  rU  rT   r4   r9   r:   r;   r=   rY   ri   ru   rU   r¶  rØ   r5  rà   ræ   rè   r7  r^   r¸  rü   r½   r³   rf  rÖ  rÕ  r€  r}  r  r.  rW   r5   r3   ú<module>rs     s  ðð €€€Ø €€€Ø €€€Ø Ð Ð Ð Ø €€€Ø 1Ð 1Ð 1Ð 1Ð 1Ð 1Ø %Ð %Ð %Ð %Ð %Ð %Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ MÐ Mà €€€à Ð Ð Ð Ð Ð ðð ð ð ð ð ð ð ð ð ð ð ð Ð Ð Ð Ð Ð Ø EÐ EÐ EÐ EÐ EÐ EÐ EÐ EÐ EÐ EØ "Ð "Ð "Ð "Ð "Ð "Ð "Ð "Ø %Ð %Ð %Ð %Ð %Ð %Ð %Ð %Ø *Ð *Ð *Ð *Ð *Ð *ð 
ˆÔ	˜HÑ	%Ô	%€ð Ð ð €à€
Ø€Ø€	ð €
ð !€à€àÐ ØÐ àÐ à€ð AÐ ð Ð ð 'Ð ð	Ð ðc Cð c°ð c¸ð cð cð cð cð$  e¡¨cÑ 1ð $°cð $ð $ð $ð $ð ðsð sð sð sð sñ sô sñ „ðsð& ðCð Cð Cð Cð Cñ Cô Cñ „ðCð. ðð ð ð ð ñ ô ñ „ððANð ANð ANð ANð ANñ ANô ANð ANðH	�s˜T #œY‘ð 	¨t°d©{ð 	¸tÀCÈÀH¼~ð 	ð 	ð 	ð 	ð˜5œ>ð ¨h°t¬nð ð ð ð ðs ¤ð s°4ð sð sð sð sðxkð xkð xkð xkð xkñ xkô xkð xkðvð ð ð ð ñ ô ð ð"{ð {ð {ð {ð {ñ {ô {ð {ð|^
ð ^
ð ^
ð ^
ð ^
ñ ^
ô ^
ð ^
ðB˜%ð  Cð ð ð ð ð#6Ø	ð#6àð#6ð 
ˆc�3ˆhŒ˜$Ñ	ð	#6ð
 �#�s�(Œ^˜dÑ"ð#6ð �&Œ\˜DÑ ð#6ð ˜‘+ Ñ# dÑ*ð#6ð ð#6ð ð#6ð ˆ4�Œ9�d˜3 ˜8”n d¨3°¨8¤n°d¸6´lÐBÔCð#6ð #6ð #6ð #6ðL�5ð ˜wð °c¸D±jð ÀTÈ#ÈsÈ(Ä^ð ð ð ð ð NRð 	ð 	ð 	˜Uð 	¨Sð 	ÀÀdÁ
ð 	ÐV]ð 	ð 	ð 	ð 	ð LPð ð ð �uð ¨3ð ¸cÀD¹jð ÐTbð ð ð ð ð$* #ð *°#¸±*ð *ÀÀsÈCÐRVÉJÀÔAWð *ð *ð *ð *ðg˜'ð g cð gð gð gð gð HLÐZ\ð Wð Wð W˜ð W sð W¸#À¹*ð WÐTWð WÐadð Wð Wð Wð Wð Wð Wr5   