Ë
    ÂÓ^j
9 ã                   óT  — 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jš                  d"eeK   fd2„ZNd1ejš                  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]y)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 --header "Authorization: Bearer $SBX_DL_TOKEN" -O "$d" "$SBX_SERVER_URL"
elif command -v curl >/dev/null 2>&1; then curl -fsSL -H "Authorization: Bearer $SBX_DL_TOKEN" -o "$d" "$SBX_SERVER_URL"
else cp "$SBX_SERVER_MOUNT/sbx-server" "$d"; fi
chmod +x "$d"
unset SBX_DL_TOKEN SBX_SERVER_URL SBX_SERVER_MOUNT
exec "$d"
Úhf_tokenÚnonceÚreturnc                 ó¦   — t        j                  | j                  «       d|› �j                  «       t        j                  «      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     úc/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/huggingface_hub/_sandbox.pyÚ_derive_sandbox_tokenr4   ]   s;   € ô �8‰8�H—O‘OÓ%¨°U°GÐ'<×'CÑ'CÓ'EÄwÇ~Á~ÓV×`Ñ`ÓbÐbó    Údurationc                 óZ   — 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;   g   s%   € ä�(œ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y)Ú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.oky   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   )rG   Úouts     r3   Ú__repr__zSandboxCommandResult.__repr__}   sW   € Ü  §¡Ó-°Ò3ˆd�kŠk¸¿¹ÀSÀbÐ9IÈEÑ9QˆØ0°·±Ð0@À	È#ÈÐP^Ð_c×_oÑ_oÐ^pÐpqÐrÐrr5   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r9   Ú__annotations__ÚstrrA   rB   ÚboolrC   ÚpropertyrH   rO   © r5   r3   r=   r=   n   sb   … áIà�T‰zÓØƒKØƒKØ€FˆC�$‰JÓØ€IˆtÓØ€K�Óàð#�Dò #ó ð#ð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y)Ú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>   c                 óV   — | j                   j                  dd| j                  › �«       y)z:Terminate the background process (idempotent server-side).ÚDELETEz/processes/N)r`   Ú_requestr[   rF   s    r3   ÚkillzSandboxProcess.kill•   s!   € à�‰×Ñ˜x¨;°t·x±x°jÐ)AÕBr5   ©r+   N)rP   rQ   rR   rS   r9   rT   rU   r   r   r`   ra   rb   rc   rV   r>   rg   rX   r5   r3   rZ   rZ   ‚   si   … ñð 
ƒHØ	ˆt�C‰y‰Óñ   U°EÔ:€HˆiÓ:Ø€Cˆˆt‰ÓØ $€M�3˜‘:Ó$Ø€GˆTÓØ €Iˆs�T‰zÓ ôCr5   rZ   c                   ób   — 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
<   y)Ú	FileEntryz%A file or directory inside a sandbox.ÚnameÚpath)ÚfileÚdirÚsymlinkÚtypeÚsizeNÚmtime_msÚ Úmode)
rP   rQ   rR   rS   rU   rT   r   r9   rr   rt   rX   r5   r3   rj   rj   š   s7   … á/à
ƒIØ
ƒIØ
Ð*Ñ
+Ó+Ø
ƒIØ€Hˆc�D‰jÓØ€Dˆ#„Nr5   rj   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 y)#Ú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    é   é   r+   Nc                 ó   — || _         y ©N)r`   ©rG   Úsandboxs     r3   Ú__init__zSandboxFiles.__init__µ   s	   € Øˆ�r5   rl   c                 óð   — | j                  |«      j                  }|| j                  kD  r!dj                  | j	                  ||«      «      S | j
                  j                  ddd|i¬«      }|j                  S )z=Read a file from the sandbox and return its content as bytes.r5   ÚGETú/files/readrl   ©Úparams)Ústatrq   ÚPARALLEL_THRESHOLDÚjoinÚ_read_rangesr`   rf   Úcontent)rG   rl   rq   Úresponses       r3   ÚreadzSandboxFiles.read¸   sk   € à�y‰y˜‹×#Ñ#ˆØ�$×)Ñ)Ò)Ø—8‘8˜D×-Ñ-¨d°DÓ9Ó:Ð:Ø—=‘=×)Ñ)¨%°ÈÐPTÀ~Ð)ÓVˆØ×ÑÐr5   Úencodingc                 óB   — | j                  |«      j                  |«      S )z@Read a file from the sandbox and return its content as a string.)r‰   Údecode)rG   rl   rŠ   s      r3   Ú	read_textzSandboxFiles.read_textÀ   s   € à�y‰y˜‹×%Ñ% hÓ/Ð/r5   Údatart   c                 ó2  — t        |t        «      r|j                  «       }n t        |t        «      s|j	                  «       }t        |«      | j                  kD  r| j                  |||«       yd|i}|�||d<   | j                  j                  dd||¬«       y)zHWrite content to a file in the sandbox (parent directories are created).Nrl   rt   ÚPUTú/files/write©r‚   r‡   )
r8   rU   r/   Úbytesr‰   rM   r„   Ú_write_rangesr`   rf   )rG   rl   rŽ   rt   r‚   s        r3   ÚwritezSandboxFiles.writeÄ   s†   € ä�dœCÔ Ø—;‘;“=‰DÜ˜D¤%Ô(Ø—9‘9“;ˆDÜˆt‹9�t×.Ñ.Ò.Ø×Ñ˜t T¨4Ô0ØØ˜$�ˆØÐØ!ˆF�6‰NØ�‰×Ñ˜u n¸VÈTÐÕRr5   Ú
local_pathc                 ó(  — t        |«      j                  «       j                  }|| j                  kD  r+| j	                  |t        |«      j                  «       |«       yt        |d«      5 }| j                  |||¬«       ddd«       y# 1 sw Y   yxY w)z#Upload a local file to the sandbox.NÚrb)rt   )r   rƒ   Úst_sizer„   r”   Ú
read_bytesÚopenr•   )rG   r–   rl   rt   rq   Úfs         r3   ÚuploadzSandboxFiles.uploadÒ   s   € ä�JÓ×$Ñ$Ó&×.Ñ.ˆØ�$×)Ñ)Ò)Ø×Ñ˜t¤T¨*Ó%5×%@Ñ%@Ó%BÀDÔIØÜ�*˜dÓ#ð 	+ qØ�J‰J�t˜Q TˆJÔ*÷	+÷ 	+ñ 	+ús   Á*BÂBc                 óì  — | j                  |«      j                  }|| j                  kD  r?t        |d«      5 }| j	                  ||«      D ]  }|j                  |«       Œ 	 ddd«       y| j                  j                  ddd|i¬«      5 }t        |d«      5 }|j                  d¬«      D ]  }|j                  |«       Œ 	 ddd«       ddd«       y# 1 sw Y   yxY w# 1 sw Y   ŒxY w# 1 sw Y   yxY w)	z!Download a file from the sandbox.ÚwbNr   r€   rl   r�   rw   )Ú
chunk_size)	rƒ   rq   r„   r›   r†   r•   r`   Ú_streamÚ
iter_bytes)rG   rl   r–   rq   rœ   Úpartrˆ   Úchunks           r3   ÚdownloadzSandboxFiles.downloadÛ   só   € à�y‰y˜‹×#Ñ#ˆØ�$×)Ñ)Ò)Ü�j $Ó'ð "¨1Ø ×-Ñ-¨d°DÓ9ò "�DØ—G‘G˜D•Mñ"÷"ð Ø�]‰]×"Ñ" 5¨-ÀÈÀÐ"ÓOð 	#ÐS[Ü�j $Ó'ð #¨1Ø%×0Ñ0¸KÐ0ÓHò #�EØ—G‘G˜E•Nñ#÷#÷	#ð 	#÷	"ð ú÷#ð #ú÷	#ð 	#ús/   ·)CÂ
C*Â)CÃC*ÃCÃC'	Ã#C*Ã*C3rq   c           	      óx   — | j                   }t        d||«      D �cg c]  }|t        |||z
  «      f‘Œ c}S c c}w rE   )ÚPARALLEL_CHUNK_SIZEÚrangeÚmin)rG   rq   r¤   Úoffsets       r3   Ú_rangeszSandboxFiles._rangesè   s;   € Ø×(Ñ(ˆÜBGÈÈ4ÐQVÓBWÖX¸�œ˜U D¨6¡MÓ2Ò3ÒXÐXùÒXs   œ7ÚitemsÚfnc                 ó¸   — t        | j                  t        |«      «      }t        |«      5 }t	        |j                  ||«      «      cddd«       S # 1 sw Y   yxY w)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_WORKERSrM   r   ÚlistÚmap)rG   r¬   r­   ÚworkersÚexecutors        r3   Ú	_parallelzSandboxFiles._parallelì   sL   € ô �d×/Ñ/´°U³Ó<ˆÜ Ó(ð 	1¨HÜ˜Ÿ™ R¨Ó/Ó0÷	1÷ 	1ò 	1ús   «AÁAc                 óˆ   ‡ ‡— dt         t        t        f   dt        fˆˆ fd„}‰ j                  ‰ j	                  |«      |«      S )NÚrngr+   c                 ój   •— | \  }}‰j                   j                  dd‰||dœ¬«      }|j                  S )Nr   r€   )rl   rª   Úlengthr�   )r`   rf   r‡   )r¶   rª   r¸   rˆ   rl   rG   s       €€r3   Úfetchz(SandboxFiles._read_ranges.<locals>.fetch÷   sB   ø€ Ø ‰NˆF�FØ—}‘}×-Ñ-Ø�}°dÀfÐX^Ñ-_ð .ó ˆHð ×#Ñ#Ð#r5   )Útupler9   r“   r´   r«   )rG   rl   rq   r¹   s   ``  r3   r†   zSandboxFiles._read_rangesö   s:   ù€ ð	$”uœS¤#˜X‘ð 	$¬5ö 	$ð �~‰~˜dŸl™l¨4Ó0°%Ó8Ð8r5   c                 óœ   ‡ ‡‡‡— dt         t        t        f   dd fˆˆˆˆ fd„}‰ j                  ‰ j                  t	        ‰«      «      |«       y )Nr¶   r+   c           	      ór   •— | \  }}‰|dœ}‰�‰|d<   ‰j                   j                  dd|‰|||z    ¬«       y )N)rl   rª   rt   r�   r‘   r’   ©r`   rf   )r¶   rª   r¸   r‚   rŽ   rt   rl   rG   s       €€€€r3   Úpushz(SandboxFiles._write_ranges.<locals>.push  sP   ø€ Ø ‰NˆF�FØ.2¸fÑ%EˆFØÐØ!%��v‘Ø�M‰M×"Ñ" 5¨.ÀÐQUÐV\Ð_eÐhnÑ_nÐQoÐ"Õpr5   )rº   r9   r´   r«   rM   )rG   rl   rŽ   rt   r¾   s   ```` r3   r”   zSandboxFiles._write_ranges   sD   û€ ð	q”eœC¤˜H‘oð 	q¨$÷ 	qð 	qð 	�‰�t—|‘|¤C¨£IÓ.°Õ5r5   c                 ó    — | j                   j                  ddd|i¬«      }|j                  «       d   D �cg c]  }t        di |¤Ž‘Œ c}S c c}w )z List a directory in the sandbox.r   z/files/listrl   r�   ÚentriesrX   )r`   rf   Újsonrj   )rG   rl   rˆ   Úentrys       r3   r°   zSandboxFiles.list
  sI   € à—=‘=×)Ñ)¨%°ÈÐPTÀ~Ð)ÓVˆØ08·±³À	Ñ0JÖK u”	Ñ"˜EÓ"ÒKÐKùÒKs   ¶Ac                 ót   — | j                   j                  ddd|i¬«      }t        di |j                  «       ¤ŽS )z3Get metadata of a file or directory in the sandbox.r   z/files/statrl   r�   rX   )r`   rf   rj   rÁ   )rG   rl   rˆ   s      r3   rƒ   zSandboxFiles.stat  s6   € à—=‘=×)Ñ)¨%°ÈÐPTÀ~Ð)ÓVˆÜÑ+˜8Ÿ=™=›?Ñ+Ð+r5   c                 ót   — 	 | j                  |«       y# t        $ r}|j                  dk(  rY d}~y‚ d}~ww xY w)z+Check whether a path exists in the sandbox.Ti”  NF)rƒ   r   Ústatus_code)rG   rl   Úes      r3   ÚexistszSandboxFiles.exists  s7   € ð	Ø�I‰I�dŒOØøÜò 	Ø�}‰} Ò#ÜØûð	ús   ‚ ”	7�2±2²7Ú	recursivec                 óV   — d|i}|rd|d<   | j                   j                  dd|¬«       y)z*Delete a file or directory in the sandbox.rl   Ú1rÈ   re   z/files/deleter�   Nr½   )rG   rl   rÈ   r‚   s       r3   ÚdeletezSandboxFiles.delete  s1   € à˜$�ˆÙØ"%ˆF�;ÑØ�‰×Ñ˜x¨ÀÐÕHr5   c                 óD   — | j                   j                  ddd|i¬«       y)z0Create a directory (and parents) in the sandbox.ÚPOSTz/files/mkdirrl   r�   Nr½   )rG   rl   s     r3   ÚmkdirzSandboxFiles.mkdir%  s   € à�‰×Ñ˜v ~¸vÀt¸nÐÕMr5   )r|   r_   r+   N)zutf-8rz   )F)!rP   rQ   rR   rS   r„   r§   r¯   r}   rU   r“   r‰   r�   r
   r•   r   r�   r¥   r9   r   rº   r«   r	   r   r´   r†   r”   rj   r°   rƒ   rV   rÇ   rË   rÎ   rX   r5   r3   rv   rv   ¦   sÐ  „ ñð )ÐØ)ÐØÐó ð ˜ð   ó  ñ0˜cð 0¨Sð 0¸só 0ñS˜#ð S S¨5¡[°8Ñ%;ð SÀ3ÈÁ:ð SÐY]ó Sñ+  t¡ð +°3ð +¸cÀD¹jð +ÐTXó +ð#˜Sð #¨c°D©jð #¸Tó #ðY˜Cð Y D¨¨s°C¨x©Ñ$9ó Yð1˜t C™yð 1¨h¸°u¸c°zÑ.Bð 1ÀtÈCÁyó 1ð9 ð 9¨Cð 9°D¸±Kó 9ð6 #ð 6¨Uð 6¸#À¹*ð 6Èó 6ðL˜ð L  i¡ó Lð
,˜ð , ó ,ð
˜3ð  4ó ñI˜3ð I¨4ð I¸Dó IðN˜#ð N $ô Nr5   rv   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\   rÏ   )r8   rU   Ú
ValueError)r\   rÏ   Úpayloads      r3   Ú_exec_payloadrÓ   *  sX   € à��}œZ¨¬SÔ1ÜÐ^Ó_Ð_Ø��~œ* S¬#Ô.ÜÐmÓnÐnØ$ c˜l€GØÐØ ˆ�ÑØ€Nr5   rˆ   c              #   ó˜   K  — | j                  «       D ]3  }|sŒt        j                  |«      }|j                  d«      dk7  sŒ0|–— Œ5 y­w)zJIterate NDJSON events from a streaming response, skipping keepalive pings.ÚeventÚpingN)Ú
iter_linesrÁ   ÚloadsÚget)rˆ   ÚlinerÕ   s      r3   Ú_iter_eventsrÛ   6  sH   è ø€ à×#Ñ#Ó%ò ˆÙØÜ—
‘
˜4Ó ˆØ�9‰9�WÓ Ó'Ø‹Kñùs   ‚A A
ÁA
c                 óÔ   — | j                  «        	 | j                  «       d   }t	        d| j
                  › d|› �| j
                  ¬«      ‚# t        $ r | j                  dd }Y ŒAw xY w)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á   @  sl   € à‡M�M„Oð&Ø—-‘-“/ 'Ñ*ˆô Ð,¨X×-AÑ-AÐ,BÀ#ÀgÀYÐOÐ]e×]qÑ]qÔ
rÐrøô ò &Ø—-‘-  Ð%Šð&ús   ’A Á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y)Ú_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       	         ó4  — || _         || _        || _        || _        || _        || _        t        |«      | _        || _        |	| _	        d| _
        d| _        t        j                  d| j                  › �|dœt        j                  ||¬«      d¬«      | _        y )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)
rG   rç   rè   ré   rê   r*   rë   rì   rå   ræ   s
             r3   r}   z_SandboxServer.__init__R  s›   € ð ˆŒØˆŒ
ØˆŒØ ˆŒð ˆŒ
ØˆŒ	Ü+¨CÓ0ˆÔØ+ˆÔà ˆŒØˆŒ	ð ˆŒô —|‘|à#*¨4×+;Ñ+;Ð*<Ð!=Ø#0ñô —<‘<°Ð[jÔkØ!ô
ˆ�r5   Újobc                ó¢   —  | |j                   |j                  j                  |j                  xs |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è   rk   Údocker_imageÚspace_idÚ_find_server_url)Úclsr   r*   rë   rì   rå   ræ   s          r3   Úfrom_jobz_SandboxServer.from_jobz  sL   € ñ Ø—6‘6Ø—)‘)—.‘.Ø×"Ñ"Ò2 c§l¡lÜ% cÓ*ØØ'ØØ+Øô

ð 
	
r5   c                 ó   — | j                   S rz   )rõ   rF   s    r3   ré   z_SandboxServer.image’  s   € à�{‰{Ðr5   Úmethodrl   c                 óâ   — |j                  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á   ©rG   r
  rl   Úkwargsr  rˆ   s         r3   r  z_SandboxServer.request–  sd   € à—*‘*˜Y¬¯©°dÀDÔ(IÓJˆØ'�4—<‘<×'Ñ'¨°·±ÀÑ0DÑ`ÈgÐ`ÐY_Ñ`ˆØ×Ñ 3Ò&Ü˜hÔ'Øˆr5   c              +   ó  K  — |j                  dt        j                  dd¬«      «      } | j                  j                  || j
                  |z   fd|i|¤Ž5 }|j                  dk\  rt        |«       |–— ddd«       y# 1 sw Y   yxY w­w)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ÓJˆØ ˆT�\‰\× Ñ  ¨¯©¸Ñ)=ÑYÀwÐYÐRXÑYð 	Ð]eØ×#Ñ# sÒ*Ü! (Ô+ØŠN÷	÷ 	ñ 	üs   ‚ABÁA?Á6	BÁ?BÂBc                 ó8   — | j                   j                  «        y rz   )rÿ   ÚcloserF   s    r3   r  z_SandboxServer.close§  s   € Ø�‰×ÑÕr5   c                 óf   — | j                   j                  | j                  | j                  ¬«       y )N©rç   Ú	namespace)rö   Ú
cancel_jobrç   rè   rF   s    r3   r  z_SandboxServer.cancel_jobª  s!   € Ø�	‰	×Ñ D§K¡K¸4¿:¹:ÐÕFr5   Ústart_timeoutc           
      ó¬  — t        j                   «       |z   }d}t        j                   «       |k  �rm	 | j                  j                  | j                  dz   t	        j
                  d«      ¬«      }|j                  dk(  ry	 t        j                   «       |z
  dkD  rÖt        j                   «       }| 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  r�Œmt!        d
| j                  › d|d›d�«      ‚# t        j                  $ r Y �ŒQw xY w)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)rG   r  ÚdeadlineÚlast_job_checkrˆ   r   Úlogss          r3   Ú
wait_readyz_SandboxServer.wait_ready­  s†  € ä—9‘9“; Ñ.ˆØˆÜ�i‰i‹k˜HÓ$ðØŸ<™<×+Ñ+¨D¯M©M¸IÑ,EÌuÏ}É}Ð]`ÓOaÐ+Ób�Ø×'Ñ'¨3Ò.Øð /ô �y‰y‹{˜^Ñ+¨cÒ1Ü!%§¡£�Ø—i‘i×+Ñ+°4·;±;È$Ï*É*Ð+ÓU�Ø—:‘:×#Ñ#Ô'7Ñ7Ü)¨$¯)©)°T·[±[ÈDÏJÉJÔW�DÜ&Ø& t§{¡{ mð 4$Ø$'§J¡J×$4Ñ$4Ð#5°[ÀÇÁ×ASÑASÐ@TÐTVÐW[ÐV\ð^óð ô �J‰J�tÔô! �i‰i‹k˜HÔ$ô" ˜\¨$¯+©+¨Ð6SÐTaÐbeÐSfÐfhÐiÓjÐjøô ×%Ñ%ò Úðús   ³AF< Æ<GÇGrh   )rP   rQ   rR   rS   rU   r   r9   r}   Úclassmethodr   r  rW   ré   rü   ÚResponser  r   r   r  r  r  r:   r.  rX   r5   r3   rã   rã   J  so  „ ñð"  "Øò&
ð ð&
ð ð	&
ð
 �T‰zð&
ð ð&
ð ð&
ð ð&
ð ð&
ð ð&
ð ð&
ð 
ó&
ðP ð  "Øò
ð ð
ð ð	
ð
 ð
ð ð
ð ð
ð ð
ð 
ò
ó ð
ð. ð�s˜T‘zò ó ðð˜cð ¨ð ¸5¿>¹>ó ð ð˜Sð ¨ð ¸(À5Ç>Á>Ñ:Rò ó ðóóGðk¨ð k°$ô kr5   rã   c            	       óv   — 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y)Ú_KillMethodz>Lets `kill` work both as a classmethod and an instance method.ÚinstanceNrè   r+   ).Nc                  ó   — y rz   rX   ©rG   r3  rè   s      r3   Ú__get__z_KillMethod.__get__È  s   € ØKNr5   r_   c                  ó   — y rz   rX   r5  s      r3   r6  z_KillMethod.__get__Ê  s   € ØORr5   úSandbox | Nonec           	      ól   ‡— |�|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                óJ   •— ‰j                  | ||¬«      j                  «        y )Nr:  )r  rg   )r<  r  r;  rè   s      €r3   rg   z!_KillMethod.__get__.<locals>.killÐ  s   ø€ Ø�M‰M˜*°	ÀˆMÓG×LÑLÕNr5   )Ú_killrU   )rG   r3  rè   rg   s     ` r3   r6  z_KillMethod.__get__Ì  sP   ø€ ØÐØ—>‘>Ð!à=AÐW[ò 	OœSð 	O´°d±
ð 	OÌ#ÐPTÉ*ð 	OÐ`dõ 	Oð ˆr5   )rP   rQ   rR   rS   r   rp   r   r6  rX   r5   r3   r2  r2  Å  sm   „ ÙHàØN ÐN¨TÐN°h¸yÑ6IÒNó ØNØØR 	ÐR°$ÐR¸8ÀBÈÀHÑ;MÒRó ØRðÐ 0ð ¸ð À(È9ÑBUô r5   r2  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d@d„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"dAd3d4œd5eez  d6ed7edefd8„Z#e deeef   fd9„«       Z$defd:„Z%d;ed<ede&jN                  fd=„Z(e)d;ed<ede*e&jN                     fd>„«       Z+y)Br_   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        | «      | _	        y )Nz/v1ú/v1/sandboxes/F)
r  Ú_serverÚ	_local_idÚ
_base_pathÚ_owns_sandboxÚ_owns_serverÚ_on_killÚ_killedrv   Úfiles)rG   r  r@  rA  rB  rC  s         r3   r}   zSandbox.__init__ã  s^   € ð ˆŒØˆŒà!ˆŒð $,Ð#3™%¸>È(ÈÐ9TˆŒð *ˆÔð (ˆÔà<@ˆŒØˆŒÜ! $Ó'ˆ�
r5   ú	cpu-basicFç      ^@)	ÚflavorÚidle_timeoutÚenvÚsecretsÚvolumesr  Úforward_hf_tokenr  r;  ré   rP  rQ  rR  rS  rT  r  rU  r  r;  c       	         óÒ  — t        |
¬«      }t        |«      }t        d«      }t        ||«      }t	        ||||||||¬«      \  }}}}|j                  |||||t        t        dt        t        t        |i|xs dt        g|¬«
      }d}	 t        j                  ||||t        j                  dz   ¬«      }|j!                  |	«        | |j&                  |ddd¬«      S # t"        $ r‚ 	 |j%                  |j&                  |j(                  j*                  ¬	«       n;# t"        $ r/}t,        j/                  d
|j&                  › d|› �«       Y d}~nd}~ww xY w|�|j1                  «        ‚ w xY w)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;  rx   ©rR  rS  rT  rQ  rU  rë   rÊ   N©
ré   ÚcommandrR  rS  rP  r  ÚlabelsrT  Úexposer  é   ©r   r*   rë   rì   rå   r  zFailed to cancel sandbox job ú after startup failure: T©r  r@  rA  rB  rC  )r   r÷   r   r4   Ú_bootstrap_job_specÚrun_jobÚSANDBOX_MAX_LIFETIMEÚSANDBOX_LABELÚ
MODE_LABELÚMODE_DEDICATEDÚNONCE_LABELÚSANDBOX_SERVER_PORTrã   r  rv   r¯   r.  rÞ   r  r  rè   rk   ÚloggerÚwarningr  )r  ré   rP  rQ  rR  rS  rT  r  rU  r  r;  rì   r)   r*   rë   rZ  Újob_envÚjob_secretsÚjob_volumesr   r@  rÆ   s                         r3   ÚcreatezSandbox.create   s‚  € ôf ˜%Ô ˆÜ# CÓ(ˆÜ˜"“ˆÜ-¨h¸Ó>ˆä5HØØØØØØ%Ø-Ø'ô	6
Ñ2ˆ�˜+ {ð �k‰kØØØØØÜ(Ü! 3¬
´NÄKÐQVÐWØÒ' 4Ü'Ð(Øð ó 
ˆð +/ˆð	Ü#×,Ñ,ØØØ+ØÜ ,× AÑ AÀAÑ Eð -ó ˆFð ×Ñ˜mÔ,ñ �c—f‘f V°dÈÐ[_Ô`Ð`øô ò 		ðdØ—‘ c§f¡f¸¿	¹	¿¹�ÕGøÜò dÜ—‘Ð!>¸s¿v¹v¸hÐF^Ð_`Ð^aÐb×cÑcûðdúàÐ!Ø—‘”Øð		ús6   Â<C Ã	E&Ã%1DÄE&Ä	EÄ %E
ÅE&Å
EÅE&r:  r<  c                óæ  — t        |¬«      }t        ||«      \  }}t        |v r||j                  t        d«      \  }}t	        |||¬«      }	 |j                  dd«      j                  «       D �ch c]  }|d   ’Œ	 }	}||	vrt        d|› d|› d	�«      ‚	  | |||d
d¬«      S |j                  ||¬«      }
|
j                  xs i }|j                  t        «      }|j                  t        «      dk7  s|€t        d|› dt        › d�«      ‚|j                  t        «      t         k(  rt        d|› dt        › d�«      ‚|
j"                  j$                  dk7  r&t        d|› d|
j"                  j$                  › d�«      ‚t'        t)        |«      |«      }t*        j-                  |
|||t.        j0                  dz   ¬«      } | |
j2                  |dd
d¬«      S c c}w # t        $ r |j                  «        ‚ w xY w)z?Reattach to a running sandbox from anywhere, using only its id.rW  r   r!  r   ú/v1/sandboxesr  zSandbox z no longer exists on host r#   FTr`  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"  r]  r^  )r   Ú_split_sandbox_idÚSHARED_ID_SEPÚsplitÚ_connect_hostr  rÁ   r   rÞ   r  r%  r[  rÙ   rg  rd  re  Ú	MODE_POOLr&  r'  r4   r÷   rã   r  rv   r¯   r  )r  r<  r  r;  rì   Úhost_job_idrA  r@  ÚitemÚexistingr   r[  r*   rë   s                 r3   r  zSandbox.connecte  s  € ô ˜%Ô ˆÜ 1°*¸iÓ HÑˆ
�IÜ˜JÑ&Ø$.×$4Ñ$4´]ÀAÓ$FÑ!ˆK˜Ü" 3¨¸yÔIˆFðØ39·>±>À%ÈÓ3Y×3^Ñ3^Ó3`Öa¨4˜D ›JÐa�ÐaØ 8Ñ+Ü&¨°*°Ð=WÐXcÐWdÐdeÐ'fÓgÐgð ,ñ
 ˜*¨V¸hÐUZÐhlÔmÐmà�o‰o Z¸9ˆoÓEˆØ—‘Ò!˜rˆØ—
‘
œ;Ó'ˆØ�:‰:”mÓ$¨Ò+¨u¨}Ü  j \Ð1MÌmÈ_Ð\eÐfÓgÐgØ�:‰:”jÓ!¤YÒ.ÜØ�z�lð #3Ü3@°/ÀðOóð ð �:‰:×Ñ˜yÒ(Ü ¨*¨Ð5NÈsÏzÉz×O_ÑO_ÐN`Ð`bÐcÓdÐdÜ-Ô.>¸sÓ.CÀUÓKˆÜ×(Ñ(ØØØ'ØÜ(×=Ñ=ÀÑAð )ó 
ˆñ �c—f‘f V°dÈÐ\`ÔaÐaùò9 bøô ò Ø—‘”Øðús   Á"G Á.GÁ:G ÇG ÇG0c                 óÌ  — | j                   ry	 | j                  €| j                  j                  «        n)| j                  j	                  dd| j                  › �«       d| _         | j                  �| j                  | «       | j                  r| j                  j                  «        yy# t
        $ r/}t        j                  d| j                  › d|› �«       Y d}~yd}~ww xY w)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.
        Nre   rE  zFailed to kill sandbox ú: T)rL  rG  rF  r  r  rÞ   ri  rj  r  rK  rJ  r  )rG   rÆ   s     r3   r>  zSandbox._kill�  s½   € ð �<Š<Øð	Ø�~‰~Ð%Ø—‘×'Ñ'Õ)à—‘×$Ñ$ X°ÀÇÁÐ?OÐ/PÔQð
 ˆŒØ�=‰=Ð$Ø�M‰M˜$ÔØ×ÒØ�L‰L×ÑÕ ð øô ò 	ä�N‰NÐ4°T·W±W°I¸RÀ¸sÐCÔDÜûð	ús   �AB+ Â+	C#Â4%CÃC#c                 óR   — | j                   r| j                  j                  «        yy)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)rJ  rF  r  rF   s    r3   r  zSandbox.close§  s"   € ð
 ×ÒØ�L‰L×ÑÕ ð r5   c                 ó   — | S rz   rX   rF   s    r3   Ú	__enter__zSandbox.__enter__¯  ó   € Øˆr5   c                 ó^   — | j                   r| j                  «        y | j                  «        y rz   )rI  rg   r  ©rG   Úexc_infos     r3   Ú__exit__zSandbox.__exit__²  s   € Ø×ÒØ�I‰I�Kà�J‰J�Lr5   .)	rÏ   rR  Úcwdr  ÚstdinÚ	on_stdoutÚ	on_stderrÚcheckÚ
backgroundr\   rÏ   r†  r  r‡  rˆ  r‰  rŠ  r‹  c       	          ó   — y rz   rX   )rG   r\   rÏ   rR  r†  r  r‡  rˆ  r‰  rŠ  r‹  s              r3   ÚrunzSandbox.runº  s   € ð  #r5   )rÏ   rR  r†  Tc                 ó   — y rz   rX   )rG   r\   rÏ   rR  r†  r‹  s         r3   r�  zSandbox.runÊ  s   € ð r5   c       	         óN  — t        ||«      }|r||d<   |r||d<   |
rC| j                  dd|¬«      j                  «       }t        |d   ||j	                  d«      | ¬«      S |�||d
<   |�||d<   g }g }d	}| j                  dd|¬«      5 }t        |«      D ]Â  }|d   dk(  r#|j                  |d   «       |€Œ" ||d   «       Œ.|d   dk(  r#|j                  |d   «       |€ŒM ||d   «       ŒY|d   dk(  sŒbt        |d   dj                  |«      dj                  |«      |j	                  d«      |j	                  dd«      |j	                  dd«      ¬«      }ŒÄ 	 d	d	d	«       |€t        d«      ‚|	r(|j                  dk7  s|j                  rt        ||¬«      ‚|S # 1 sw Y   ŒBxY w)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`.
        rR  r†  rÍ   ú
/processes©rÁ   r[   ra   )r[   r\   ra   r`   Nr  r‡  z/execrÕ   r?   rŽ   r@   Úexitr>   rs   rA   rB   FrC   r   )r>   r?   r@   rA   rB   rC   z%connection lost while running command)r\   Úresult)rÓ   rf   rÁ   rZ   rÙ   r¡   rÛ   Úappendr=   r…   r   r>   rB   r   )rG   r\   rÏ   rR  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×IÑIÓKˆDÜ! d¨5¡k°sÀÇÁÈÃÐZ^Ô_Ð_ØÐØ!(ˆG�IÑØÐØ$ˆG�GÑà"$ˆØ"$ˆØ.2ˆØ�\‰\˜& '°ˆ\Ó8ð 	¸HÜ% hÓ/ò �Ø˜‘> XÒ-Ø ×'Ñ'¨¨f©Ô6Ø Ñ,Ù! %¨¡-Õ0Ø˜7‘^ xÒ/Ø ×'Ñ'¨¨f©Ô6Ø Ñ,Ù! %¨¡-Õ0Ø˜7‘^ vÓ-Ü1Ø"'¨Ñ"4Ø!Ÿw™w |Ó4Ø!Ÿw™w |Ó4Ø$Ÿy™y¨Ó2Ø"'§)¡)¨K¸Ó"?Ø$)§I¡I¨m¸QÓ$?ô‘Fñ÷	ð& ˆ>ÜÐFÓGÐGÙ�f×&Ñ&¨!Ò+¨v×/?Ò/?Ü%¨#°fÔ=Ð=Øˆ÷/	ð 	ús   Â-FÂ6*FÃ!FÃ6A#FÆF$c                 óø   — | j                  dd«      j                  «       }|D �cg c]J  }t        |d   |d   |j                  d«      |j                  d«      |d   |j                  d«      | ¬	«      ‘ŒL c}S c c}w )
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�  r[   r\   ra   rb   rc   r>   )r[   r\   ra   rb   rc   r>   r`   )rf   rÁ   rZ   rÙ   )rG   rŽ   Úps      r3   Ú	processeszSandbox.processes2  s�   € ð �}‰}˜U LÓ1×6Ñ6Ó8ˆð ö
ð ô Ø�e‘HØ�e‘HØ—E‘E˜%“LØŸe™e OÓ4Ø˜)™ØŸ%™% Ó,Øöò
ð 	
ùò 
s   ¥AA7c                 ó.   — | j                   j                  S rz   )rF  ré   rF   s    r3   ré   zSandbox.imageI  s   € à�|‰|×!Ñ!Ð!r5   c                 óJ   — | j                   �| j                  j                  S dS )zIFor a shared/pool sandbox, the job id of the host running it (else None).N)rG  rF  rç   rF   s    r3   Úhost_idzSandbox.host_idM  s"   € ð '+§n¡nÐ&@ˆt�|‰|×"Ñ"ÐJÀdÐJr5   zhttps://)ÚschemeÚportrl   r�  c                ó²   — | j                   j                  j                  dd«      d   }|j                  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   éÿÿÿÿú/z/proxy/)rF  rê   rv  Ú
startswithrH  )rG   rž  rl   r�  Úhost_and_rests        r3   Úproxy_url_forzSandbox.proxy_url_forT  s^   € ðL Ÿ™×-Ñ-×3Ñ3°E¸1Ó=¸bÑAˆØ—‘ sÔ+‰t°°t±ˆØ�˜-˜¨¯©Ð(9¸ÀÀÀtÀfÐMÐMr5   c                 ób   — d| j                   j                  › �| j                   j                  dœS )zPAuth headers to send with [`proxy_url_for`] requests (HF token + sandbox token).rî   rï   )rF  rø   rù   rF   s    r3   Úproxy_headerszSandbox.proxy_headers~  s0   € ð  ' t§|¡|×'?Ñ'?Ð&@ÐAØ#Ÿ|™|×:Ñ:ñ
ð 	
r5   c                 ó<   — d| j                   ›d| j                  ›d�S )NzSandbox(id=z, image=rL   )r  ré   rF   s    r3   rO   zSandbox.__repr__†  s   € Ø˜TŸW™W˜K x°·
±
¨~¸QÐ?Ð?r5   r
  Úresourcec                 óX   —  | j                   j                  || j                  |z   fi |¤ŽS rz   )rF  r  rH  )rG   r
  r¨  r  s       r3   rf   zSandbox._request‹  s)   € Ø#ˆt�|‰|×#Ñ# F¨D¯O©O¸hÑ,FÑQÈ&ÑQÐQr5   c              +   ó”   K  —  | j                   j                  || j                  |z   fi |¤Ž5 }|–— d d d «       y # 1 sw Y   y xY w­wrz   )rF  r  rH  )rG   r
  r¨  r  rˆ   s        r3   r¡   zSandbox._streamŽ  sF   è ø€ à ˆT�\‰\× Ñ  ¨¯©¸8Ñ)CÑNÀvÑNð 	ÐRZØŠN÷	÷ 	ñ 	üs   ‚,A®<³	A¼AÁArh   )r+   r_   )r¡  ),rP   rQ   rR   rS   rU   rã   rV   r}   r/  ÚDEFAULT_IMAGEÚDEFAULT_IDLE_TIMEOUTr9   r:   Údictr	   r   r   rn  r  r2  rg   r>  r  r€  r…  r   r   r   r=   r�  rZ   r™  rW   ré   rœ  r¤  r¦  rO   rü   r0  rf   r   r   r¡   rX   r5   r3   r_   r_   Ö  sý  „ ñ
ð(ð ð(ð ð	(ð
 ˜‘*ð(ð ð(ð ð(ð 
ó(ð: ð #ðbað "Ø1EØ%)Ø)-Ø'+Ø $Ø!&Ø$Ø ò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ðH ØAEÐ[_ò $b ð $b°C¸$±Jð $bÈcÐTXÉjð $bÐdmò $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ð#ð 
ò#ó ð#ð ð
 !Ø%(Øòà�4˜‘9‰_ðð �d‰{ð	ð
 �#�s�(‰^˜dÑ"ðð �4‰Zðð ˜D‘Mðð 
òó ðð "Ø%)ØØ $Ø Ø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ò "ó ð"ð ðK˜˜t™ò Kó ðKð(NÈzò (N #¨¡)ð (N°3ð (NÈð (NÐ^aó (NðT ð
˜t C¨ H™~ò 
ó ð
ð@˜#ó @ð
R˜sð R¨cð RÀÇÁó Rð ð˜cð ¨Sð ¸xÈÏÉÑ?Wò ó ñr5   r_   c                   ó4  — 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'y)=Ú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
    ```
    rN  r   NrO  F)
rP  Úsandboxes_per_hostÚwarm_upÚ	max_hostsrk   rQ  r  r  r;  Ú_connect_moderé   rP  r°  r±  r²  rk   rQ  r  r  r;  r³  r+   c       
         ó&  — |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| j3                  «        yy)	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.rW  Nzpool-é   F)rÑ   r   rö   ré   rP  r°  Ú_warm_upr²  r   rk   Ú_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)rG   ré   rP  r°  r±  r²  rk   rQ  r  r  r;  r³  s               r3   r}   zSandboxPool.__init__¸  s  € ðl  Ò!ÜÐ?Ó@Ð@Ø�QŠ;ÜÐ4Ó5Ð5Ü Ô&ˆŒ	ØˆŒ
ØˆŒØ"4ˆÔØˆŒØ"ˆŒØ Ð,‘D°E¼)ÀA»,¸Ð2HˆŒ	Ø)ˆÔØ#ˆŒØ+ˆÔØ,.ˆŒÜ—^‘^Ó%ˆŒ
ô &ŸN™NÓ,ˆÔô
 $Ÿ.™.Ó*ˆŒØˆŒàˆŒð #0ˆÔð  -Ð,ˆÔä(+«ˆÔñ
 Ø×"Ñ"Õ$ð r5   r:  Úpool_idc                ód  — t        |«      }|�Q | |j                  |j                  |j                  |j                  ||j
                  |€|j                  n||d¬«	      S t        |¬«      }t        |||¬«      }t        |||¬«      }|j                  d«      }|j                  d«      }	 | |j                  xs |j                  xs t        |j                  �t        |j                  «      ndt        |j                  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é   rP  r°  r²  rk   rQ  r  r;  r³  rW  r!  ÚSBX_IDLE_TIMEOUTÚSBX_MAX_HOSTSrN  ÚSBX_CAPACITY)r   ré   rP  r°  r²  rQ  r  r   Ú_find_pool_host_jobÚ	_host_envrÙ   r  r  r«  rU   r9   ÚDEFAULT_SANDBOXES_PER_HOST)
r  rÇ  r  r;  Úcacherì   r   rR  Úidle_rawÚmax_hosts_raws
             r3   r  zSandboxPool.connect  s  € ô.   Ó(ˆØÐÙØ—k‘kØ—|‘|Ø#(×#;Ñ#;ØŸ/™/ØØ"×/Ñ/Ø-6Ð->˜%Ÿ/š/ÀIØØ"ô
ð 
ô ˜%Ô ˆÜ! # w¸)ÔDˆÜ˜˜S¨IÔ6ˆØ—7‘7Ð-Ó.ˆØŸ™ Ó0ˆÙØ×"Ñ"ÒC c§l¡lÒC´mØ&)§j¡jÐ&<”3�s—z‘z”?À+Ü" 3§7¡7¨>Ô;UÓ#VÓWØ,9Ð,E”c˜-Ô(È4ØØ*2Ð*>œ˜XœÀDØØØô

ð 
	
r5   Ú	num_hostsc                 óî  — | j                   rt        d«      ‚| j                  «        | j                  5  |t	        | j
                  «      z
  }ddd«       dkD  rA| j                  |«      }| j                  5  | j
                  j                  |«       ddd«       | j                  5  d| _	        ddd«       | j                  «        | j                  S # 1 sw Y   Œ‡xY w# 1 sw Y   ŒMxY w# 1 sw Y   Œ=xY w)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½  rM   rº  Ú_provision_hostsÚextendr¾  rÁ  Ú_save_cacheÚhost_ids)rG   rÒ  Ú	shortfallÚbooteds       r3   ÚwarmzSandboxPool.warmS  sÒ   € ð �<Š<ÜÐ<Ó=Ð=Ø×ÑÔØ�Z‰Zñ 	5Ø!¤C¨¯©Ó$4Ñ4ˆI÷	5à�qŠ=Ø×*Ñ*¨9Ó5ˆFØ—‘ñ +Ø—‘×"Ñ" 6Ô*÷+à×Ññ 	#Ø"ˆDŒO÷	#à×ÑÔØ�}‰}Ð÷	5ð 	5ú÷+ð +ú÷	#ð 	#ús#   ´CÁ7CÂ'C+ÃCÃC(Ã+C4)rR  rQ  rU  rR  rU  r_   c                ó�  — | j                   rt        d«      ‚t        |xs i «      }|rt        | j                  «      |d<   |�t        |«      nd}g }d}d}	 | j                  «        	 | j                  «       }	|	€$|s"d}| j                  «        | j                  «       }	|	€Y| j                  r<|r:| j                  s.t        | j                  «       t        d| j                  › d�«      ‚| j                  |«      }	|	�=	 | j                  |	||«      }
|
�| j'                  «        |
S |	|v r|j)                  |	«       d}|d	z  }|t*        kD  rt        d
«      ‚Œì# t        $ rA | j                   5  t#        d|	j$                  d	z
  «      |	_        ddd«       ‚ # 1 sw Y   ‚ xY ww xY w# t        $ r› | j                   5  | j                  D �cg c]	  }||vsŒ|‘Œ nc c}w c}| _
        ddd«       n# 1 sw Y   nxY w|D ]H  }		 |	j-                  «        n# t        $ r Y nw xY w|	j/                  «        Œ5# |	j/                  «        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.)rÀ  r   r­  r÷   rö   r;   rÆ  Ú_reserve_onerÕ  rÂ  rº  r   rk   Ú_boot_one_hostÚ_create_onerÞ   r½  Úmaxrú   rØ  ÚremoveÚ_MAX_PACK_ROUNDSr  r  )rG   rR  rQ  rU  Úsandbox_envÚ	idle_secsÚ	new_hostsÚ
discoveredÚroundsÚhostr|   Úhs               r3   rn  zSandboxPool.createn  sc  € ð: �<Š<ÜÐ<Ó=Ð=Ü˜3š9 "“oˆÙÜ&6°t·y±yÓ&AˆK˜
Ñ#ð 8DÐ7OÔ% lÔ3ÐUYˆ	à*,ˆ	Øˆ
Øˆð<	ð ×"Ñ"Ô$Øà×(Ñ(Ó*�à�<©
Ø!%�JØ×(Ñ(Ô*Ø×,Ñ,Ó.�Dà�<Ø×.Ò.±:ÀdÇkÂkô *¨$¯)©)Ô4Ü*Ø>¸t¿y¹y¸kð J_ð _óð ð  ×.Ñ.¨yÓ9�Dð Ð#ðØ"&×"2Ñ"2°4¸ÀiÓ"P˜ð Ð*Ø×(Ñ(Ô*Ø&˜ð
 ˜yÑ(Ø!×(Ñ(¨Ô.Ø"�
Ø˜!‘�ØÔ,Ò,Ü&Øtóð ðU øô0 %ò ð "ŸZ™Zñ >Ü(+¨A¨t¯y©y¸1©}Ó(=˜DœI÷>à÷>àúðûô* ò 	à—‘ñ MØ*.¯+©+ÖL Q¸À)Ò9KšqÑLùÔL�”÷M÷ Mñ Múà!ò !�ð!Ø—O‘OÕ%øÜ ò Ùðúð —J‘J•Lø�D—J‘J•Lúð!ð ð	ús£   ÁB$F! Ã<E ÄF! Ä#1F! ÅFÅ)FÆ	FÆF	ÆFÆF! Æ!IÆ6G*Ç	GÇGÇG*Ç!	IÇ*G3	Ç/IÇ<HÈH-È	HÈH-ÈHÈH-ÈIÈ-H?È?Ic                 óp   — | j                   5  t        | j                  «      cddd«       S # 1 sw Y   yxY w)z*Number of host jobs currently provisioned.N)r½  rM   rº  rF   s    r3   rÒ  zSandboxPool.num_hostsÕ  s,   € ð �Z‰Zñ 	$Ü�t—{‘{Ó#÷	$÷ 	$ò 	$ús   �,¬5c                 ó~   — | j                   5  t        d„ | j                  D «       «      cddd«       S # 1 sw Y   yxY w)z<Number of sandboxes currently handed out (across all hosts).c              3   ó4   K  — | ]  }|j                   –— Œ y ­wrz   )rú   )Ú.0rì  s     r3   ú	<genexpr>z,SandboxPool.num_sandboxes.<locals>.<genexpr>ß  s   è ø€ Ò9 T�t—y•yÑ9ùs   ‚N)r½  Úsumrº  rF   s    r3   Únum_sandboxeszSandboxPool.num_sandboxesÛ  s2   € ð �Z‰Zñ 	:ÜÑ9¨T¯[©[Ô9Ó9÷	:÷ 	:ò 	:ús   �3³<c                 ó˜   — | j                   5  | j                  D �cg c]  }|j                  ‘Œ c}cddd«       S c c}w # 1 sw Y   yxY w)z!Job ids of the provisioned hosts.N)r½  rº  rç   ©rG   rì  s     r3   rÙ  zSandboxPool.host_idsá  s>   € ð �Z‰Zñ 	9Ø,0¯K©KÖ8 D�D—K“KÒ8÷	9ñ 	9ùÚ8÷	9ð 	9ús   �A œ;¯A »A Á A	c                 óÆ  — | j                   5  | j                  }g | _        d| _        ddd«       D ]/  }	 | j                  r|j	                  «        |j                  «        Œ1 | j                  rt        | j                  «       yy# 1 sw Y   Œ`xY w# t
        $ r/}t        j                  d|j                  › d|› �«       Y d}~Œtd}~ww xY w# |j                  «        w xY w)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Þ   ri  rj  rç   r  r   rk   )rG   Úhostsrì  rÆ   s       r3   r  zSandboxPool.closeç  sÇ   € ð �Z‰Zñ 	 Ø—K‘KˆEØˆDŒKØˆDŒL÷	 ð ò 	ˆDðØ×#Ò#Ø—O‘OÔ%ð —
‘
•ð	ð ×ÒÜ˜dŸi™iÕ(ð ÷	 ð 	 ûô ò TÜ—‘Ð!?ÀÇÁ¸}ÈBÈqÈcÐR×SÑSûðTûð —
‘
•ús4   �B¶BÂBÂ	CÂ%CÃCÃCÃCÃC c                 ó   — | S rz   rX   rF   s    r3   r€  zSandboxPool.__enter__ÿ  r�  r5   c                 ó$   — | j                  «        y rz   )r  rƒ  s     r3   r…  zSandboxPool.__exit__  s   € Ø�
‰
�r5   c                 ó  — | j                   5  | j                  r
	 ddd«       y| j                  «        | j                  €| j                  nt        | j                  | j                  «      }| j                  5  |t        | j                  «      z
  }ddd«       dkD  r�| j                  «        | j                  ss| j                  5  |t        | j                  «      z
  }ddd«       |dkD  rA| j                  |«      }| j                  5  | j                  j                  |«       ddd«       d| _        ddd«       | j                  r| j                  «        yy# 1 sw Y   ŒÊxY w# 1 sw Y   ŒˆxY w# 1 sw Y   ŒNxY w# 1 sw Y   ŒKxY w)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½  rM   rº  rÕ  rÂ  rÖ  r×  rØ  )rG   ÚtargetrÚ  rÛ  s       r3   rÆ  zSandboxPool._ensure_warmed_up  sL  € ð  ×Ññ 	#Ø�ŠØ÷	#ð 	#ð ×'Ñ'Ô)Ø&*§n¡nÐ&<�T—]’]Ä#ÀdÇmÁmÐUY×UcÑUcÓBdˆFØ—‘ñ 6Ø"¤S¨¯©Ó%5Ñ5�	÷6à˜1Š}Ø×$Ñ$Ô&ð ×.Ò.ØŸ™ñ >Ø$*¬S°·±Ó-=Ñ$=˜	÷>à  1’}Ø!%×!6Ñ!6°yÓ!A˜Ø!ŸZ™Zñ 7Ø ŸK™K×.Ñ.¨vÔ6÷7à"ˆDŒO÷'	#ð, �;Š;Ø×ÑÕð ÷#6ð 6ú÷>ð >ú÷7ð 7ú÷#	#ð 	#úsY   �E>¤AE>Á8EÂ5E>ÃE&Ã*E>Ä	E2Ä%E>ÅE#	ÅE>Å&E/	Å+E>Å2E;	Å7E>Å>Fú_SandboxServer | Nonec                 óæ   — | j                   5  | j                  D ]@  }|j                  |j                  z
  dkD  sŒ |xj                  dz  c_        |c cddd«       S  	 ddd«       y# 1 sw Y   yxY w)zNReserve one slot on the first host with free capacity (under lock), else None.r   r   N)r½  rº  ræ   rú   rö  s     r3   rá  zSandboxPool._reserve_one0  sg   € à�Z‰Zñ 	 ØŸ™ò  �Ø—=‘= 4§9¡9Ñ,¨qÓ0Ø—I’I ‘N•IØ‘K÷		 ñ 	 ñ ÷	 ð
 ÷	 ð
 ús   �,A'ºA'ÁA'Á'A0ré  rã   c                 ó¶  — | j                   5  | j                  «       }|�|cddd«       S | j                  «       r| j                  «       }|�|cddd«       S | j                  d«      }|j	                  |«       | j
                  5  | j                  j	                  |«       ddd«       | j                  «       cddd«       S # 1 sw Y   Œ"xY w# 1 sw Y   yxY w)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º  )rG   ré  rì  rÛ  s       r3   râ  zSandboxPool._boot_one_host9  sÑ   € ð �_‰_ñ 	'ð ×$Ñ$Ó&ˆDØÐØ÷	'ñ 	'ð ×'Ñ'Ô)Ø×(Ñ(Ó*�ØÐ#Ø÷	'ñ 	'ð ×*Ñ*¨1Ó-ˆFØ×Ñ˜VÔ$Ø—‘ñ +Ø—‘×"Ñ" 6Ô*÷+à×$Ñ$Ó&÷!	'ñ 	'÷+ð +ú÷	'ð 	'ús.   �C«#CÁ.CÂCÂ"CÃC	ÃCÃCc           
      ó0  ‡‡— | j                   D �ch c]  }|j                  ’Œ c}Št        ˆfd„| j                  j	                  dt
        t        t        | j                  i| j                  ¬«      D «       d«      Š‰€yt        j                  d| j                  › d‰j                  › d�«       t        j                  «       | j                  z   }t        j                  «       |k  r«| j                  j                  ‰j                  | j                  ¬	«      j                   j"                  }|d
vry|dk(  r/| j%                  «        t'        ˆfd„| j                   D «       «      ryt        j(                  d«       t        j                  «       |k  rŒ«yc c}w )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              3   ó>   •K  — | ]  }|j                   ‰vr|–— Œ y ­wrz   )r  )rñ  r   Úknowns     €r3   rò  z2SandboxPool._adopt_pending_host.<locals>.<genexpr>_  s'   øè ø€ ò àð
 —6‘6 Ñ&ô ñùs   ƒÚ
SCHEDULING©r&  r[  r  NFzPool 'z' host z: is already SCHEDULING; waiting for it instead of booting.r  )r  rr  rr  c              3   óP   •K  — | ]  }|j                   ‰j                  k(  –— Œ y ­wrz   ©rç   r  )rñ  rì  Úpendings     €r3   rò  z2SandboxPool._adopt_pending_host.<locals>.<genexpr>v  s   øè ø€ ÒI°T�t—{‘{ g§j¡jÕ0ÑIùó   ƒ#&Tg      ð?)rº  rç   Únextrö   Ú	list_jobsre  rx  Ú
POOL_LABELrk   r¸  ri  Údebugr  r#  r¹  r%  r&  r'  rÕ  Úanyr*  )rG   rì  r+  r'  r  r
  s       @@r3   r  zSandboxPool._adopt_pending_hostU  sB  ù€ ð *.¯©Ö5 �—“Ò5ˆÜóàŸ9™9×.Ñ.Ø'Ü&¬	´:¸t¿y¹yÐIØ"Ÿo™oð /ó ôð ó
ˆð ˆ?ØÜ�‰�v˜dŸi™i˜[¨°·
±
¨|Ð;uÐvÔwÜ—9‘9“; ×!4Ñ!4Ñ4ˆÜ�i‰i‹k˜HÒ$Ø—I‘I×)Ñ)°·±ÀtÇÁÐ)ÓW×^Ñ^×dÑdˆEØÐ5Ñ5ØØ˜	Ò!ð ×$Ñ$Ô&ÜÓI¸T¿[¹[ÔIÔIØÜ�J‰J�sŒOô �i‰i‹k˜HÓ$ð ùò9 6s   ‘Fc                 ó  ‡— | j                   D �ch c]  }|j                  ’Œ }}| j                  j                  dt        t
        t        | j                  i| j                  ¬«      D �cg c]  }|j                  |vr|‘Œ }}|D �]  Šd}	 t        | j                  ‰j                  | j                  ¬«      }t        | j                  ‰| j                  ¬«      }t        |j                  d| j                  «      «      |_        t!        |j#                  dd«      j%                  «       «      |_        | j6                  5  t9        ˆfd
„| j                   D «       «      r|j5                  «        n| j                   j;                  |«       ddd«       �Œ yc c}w c c}w # t(        t*        j,                  t.        f$ rB}t0        j3                  d‰j                  › d	|› �«       |�|j5                  «        Y d}~�Œud}~ww xY w# 1 sw Y   �Œ‡xY w)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.
        rr  r  Nr!  rË  r   rp  zSkipping host z during discovery: c              3   óP   •K  — | ]  }|j                   ‰j                  k(  –— Œ y ­wrz   r	  )rñ  rì  r   s     €r3   rò  z.SandboxPool._discover_hosts.<locals>.<genexpr>ž  s   øè ø€ ÒE°�t—{‘{ c§f¡fÕ,ÑEùr  )rº  rç   rö   r  re  rx  r  rk   r¸  r  rw  rÍ  r9   rÙ   r°  ræ   rM   r  rÁ   rú   r   rü   Ú	HTTPErrorr   ri  r  r  r½  r  r”  )rG   rì  r  r   Úmatchesr@  rR  rÆ   s      `    r3   rÕ  zSandboxPool._discover_hosts{  s®  ø€ ð *.¯©Ö5 �—“Ð5ˆÐ5ð —y‘y×*Ñ*Ø Ü"¤I¬z¸4¿9¹9ÐEØŸ/™/ð +ó ö
àð
 �v‰v˜UÑ"ò ð
ˆð 
ð ó 	/ˆCØˆFðÜ& t§y¡y°#·&±&ÀDÇOÁOÔT�ô   §	¡	¨3¸$¿/¹/ÔJ�Ü"% c§g¡g¨n¸d×>UÑ>UÓ&VÓ"W�”Ü! &§.¡.°¸Ó"H×"MÑ"MÓ"OÓP�”ð —‘ñ /ÜÓE¸¿¹ÔEÔEØ—L‘L•Nà—K‘K×&Ñ& vÔ.÷	/ñ /ñ!	/ùò 6ùò
øô& !¤%§/¡/´>ÐBò ô —‘˜~¨c¯f©f¨XÐ5HÈÈÐLÔMØÐ%Ø—L‘L”NÝûðú÷/ñ /ús1   �FÁ)FÂB&FÄ=AHÆG>Æ<7G9Ç9G>ÈH	Únum_newc                 ó  — | j                   5  t        | j                  «      }ddd«       | j                  �J|z   | j                  kD  r8| j                  |z
  }t	        d|› d| j                  › dt        d|«      › d�«      ‚t        t        |d«      ¬«      5 }t        |«      D �cg c]  }|j                  | j                  «      ‘Œ }}ddd«       g }d}D ]"  }		 |j                  |	j                  «       «       Œ$ |�*|D ]#  }	 |j                  «        |j                  «        Œ% |‚|S # 1 sw Y   �Œ	xY wc c}w # 1 sw Y   ŒtxY w# t        $ r}
|
}Y d}
~
Œ�d}
~
ww xY w# t        $ r Y ŒWw xY w# |j                  «        w xY w)	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_workers)r½  rM   rº  r²  r   rä  r   r©   r¨   ÚsubmitÚ
_boot_hostr”  r“  rÞ   r  r  )rG   r  ÚcurrentÚallowedr³   Ú_ÚfuturesrÛ  rÝ   ÚfuturerÆ   r@  s               r3   rÖ  zSandboxPool._provision_hosts£  sˆ  € à�Z‰Zñ 	'Ü˜$Ÿ+™+Ó&ˆG÷	'à�>‰>Ð%¨'°GÑ*;¸d¿n¹nÒ*LØ—n‘n wÑ.ˆGÜØ˜g˜YÐ&BÀ4Ç>Á>ÐBRð SÜ" 1 g›Ð/Ð/]ð_óð ô  ¬C°¸Ó,<Ô=ð 	QÀÜAFÀwÃÖP¸A�x—‘ t§¡Õ7ÐPˆGÐP÷	Qà')ˆØ"&ˆØò 	ˆFðØ—‘˜fŸm™m›oÕ.ð	ð
 ÐØ ò #�ð#Ø×%Ñ%Ô'ð —L‘L•Nð#ð ˆKØˆ÷;	'ñ 	'üò Q÷	Qð 	Qûô ò Ø•ûðûô !ò Ùðûð —L‘L•Núse   �D*ÂD<Â%"D7ÃD<ÃEÄE Ä*D4Ä7D<Ä<EÅ	EÅEÅEÅ 	E,Å)E/Å+E,Å,E/Å/F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                   |||| j"                  t$        ||xs dt&        g| j(                  ¬	«
      }	d}
	 t*        j-                  |	||| j                  t/        | j                  d
z   d«      | j                  ¬«      }
|
j1                  | j2                  «       |
S # t4        $ rŒ 	 | j                  j7                  |	j8                  |	j:                  j                  ¬«       n;# t4        $ r/}t<        j?                  d|	j8                  › d|› �«       Y d}~nd}~ww xY w|
�|
jA                  «        ‚ w xY w)z6Start one host job and wait until its server is ready.rx   NFrX  rÊ   ÚSBX_HOST_MODErË  rÊ  rY  r(   é   )r   r*   rë   rì   rå   ræ   r  rø  r_  )!r÷   rö   r   r4   ra  r·  rU   r°  r²  rd  re  rx  r  rk   rg  rb  ré   rP  rc  rh  r¸  rã   r  r©   r.  r¹  rÞ   r  r  rè   ri  rj  r  )rG   r)   r*   rë   rZ  rk  rl  rm  r[  r   r@  rÆ   s               r3   r  zSandboxPool._boot_hostÄ  só  € ä# D§I¡IÓ.ˆÜ˜"“ˆÜ-¨h¸Ó>ˆÜ5HØ�I‰IØØØØØ×+Ñ+Ø"Ø'ô	6
Ñ2ˆ�˜+ {ð $'ˆ�Ñ ô
 #& d×&=Ñ&=Ó">ˆ�Ñð �>‰>Ð%Ü'*¨4¯>©>Ó':ˆG�OÑ$Ü ¤j´)¼ZÈÏÉÔT_ÐafÐgˆØ�i‰i×ÑØ—*‘*ØØØØ—;‘;Ü(ØØÒ' 4Ü'Ð(Ø—o‘oð  ó 
ˆð +/ˆð	ô $×,Ñ,ØØØ+Ø—I‘IÜ # D×$;Ñ$;¸aÑ$?ÀÓ EØ×0Ñ0ð -ó ˆFð ×Ñ˜d×1Ñ1Ô2ð ˆøô ò 	ðeØ—	‘	×$Ñ$¨C¯F©F¸c¿i¹i¿n¹nÐ$ÕMøÜò eÜ—‘Ð!?ÀÇÁ¸xÐG_Ð`aÐ_bÐc×dÑdûðeúàÐ!Ø—‘”Øð	ús7   ÄA!E8 Å8	HÆ;F>Æ=HÆ>	G6Ç%G1Ç,HÇ1G6Ç6Hrì  rè  r8  c                 óš  — ddi}|�||d<   |r||d<   	 |j                  dd|¬«      j                  «       }d|_        |j                  d«      xs g }t        |j                  dd«      «      s|s'| j                  5  |j                  |_        ddd«       y|d   }t        |j                  › t         › |d   › �||d   dd¬«      }	| j"                  |	_        |	S # t        t        j                  f$ rM}|j
                  r‚ t        j                  d	|j                  › d
|› �«       | j                  |«       Y d}~yd}~ww xY w# 1 sw Y   yxY w)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_secsrR  rÍ   rp  r‘  z!Dropping unreachable cached host r}  TÚ	sandboxesÚrejectedr   r  Fr`  )r  rÁ   r   rü   r  rû   ri  r  rç   Ú
_drop_hostrÙ   r9   r½  ræ   rú   r_   ru  Ú_on_sandbox_killedrK  )
rG   rì  rR  rè  ÚbodyrŽ   rÆ   r&  rz  r|   s
             r3   rã  zSandboxPool._create_one  sG  € ð !(¨˜|ˆØÐ Ø(1ˆDÐ$Ñ%ÙØˆD�‰Kð	Ø—<‘< ¨¸d�<ÓC×HÑHÓJˆDð ˆŒØ—H‘H˜[Ó)Ò/¨Rˆ	Üˆt�x‰x˜
 AÓ&Ô'©yØ—‘ñ *Ø ŸM™M�”	÷*àØ˜‰|ˆÜØ—+‘+�œ}˜o¨d°4©j¨\Ð:ØØ˜$‘ZØØô
ˆð  ×2Ñ2ˆÔØˆøô+ œeŸo™oÐ.ò 	Ø�}Š}ØÜ�L‰LÐ<¸T¿[¹[¸MÈÈAÈ3ÐOÔPØ�O‰O˜DÔ!Üûð	ú÷*àús$   ”"C Á;EÃD>Ã1AD9Ä9D>ÅE
r|   c                 óª   — | j                   5  t        d|j                  j                  dz
  «      |j                  _        ddd«       y# 1 sw Y   yxY w)z:Free the packing slot of a shared sandbox that was killed.r   r   N)r½  rä  rF  rú   r{   s     r3   r)  zSandboxPool._on_sandbox_killed*  sD   € à�Z‰Zñ 	DÜ#& q¨'¯/©/×*>Ñ*>ÀÑ*BÓ#CˆG�O‰OÔ ÷	D÷ 	Dñ 	Dús   �3A	Á	Ac                 ó  — | j                   5  | j                  D �cg c]	  }||usŒ|‘Œ c}| _        | j                  j                  |j                  «       ddd«       |j                  «        yc c}w # 1 sw Y   ŒxY w)zFForget a host found dead this session (and mark it for cache pruning).N)r½  rº  rÅ  Úaddrç   r  )rG   rì  rí  s      r3   r(  zSandboxPool._drop_host/  sc   € à�Z‰Zñ 	1Ø&*§k¡kÖC °Q¸d²]š1ÒCˆDŒKØ×Ñ×#Ñ# D§K¡KÔ0÷	1ð 	�
‰
�ùò D÷	1ð 	1ús    �A5œ	A0¦A0ª-A5Á0A5Á5A>c                 óÔ  — t        | j                  «      }|€yt        | j                  «      }| j                  5  | j
                  D �ch c]  }|j                  ’Œ }}|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
                  j'                  |«       Œä 	 ddd«       yc c}w # 1 sw Y   yxY w)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.
        Nr(   r"  r  F)r   rk   r÷   rö   r½  rº  rç   rù  rú   ræ   rã   rè   ré   rê   r*   r4   r©   r°  rû   r”  )rG   rÏ  r)   rì  r  Úchr@  s          r3   rý  z"SandboxPool._seed_hosts_from_cache8  s  € ô   §	¡	Ó*ˆØˆ=ØÜ# D§I¡IÓ.ˆØ�Z‰Zñ 	+Ø-1¯[©[Ö9 T�T—[“[Ð9ˆEÐ9Ø—k‘kò +�Ø—9‘9 Ñ%¨¯©°B·K±KÒ)?ØÜ'ØŸ9™9ØŸ(™(ØŸ*™*ØŸ[™[ØŸ(™(Ü"7¸À"Ç(Á(Ó"KØŸ	™	Ü$'¨×(?Ñ(?À!Ñ(CÀSÓ$IØŸ[™[ô
�ð !Ÿg™g�”Ø"'�”Ø—‘×"Ñ" 6Õ*ñ!+÷	+ð 	+ùÚ9÷	+ð 	+ús   ºEÁ	EÁC3EÅEÅE'c                 óJ  — | j                   5  | j                  D �cg c]b  }t        |j                  |j                  |j
                  |j                  |j                  |j                  t        j                  «       ¬«      ‘Œd }}t        | j                  «      }ddd«       t        | j                  | j                  | j                  | j                   | j"                  | j$                  �t'        | j$                  «      nd| j(                  ¬«	       yc c}w # 1 sw Y   Œ€xY w)zOPersist the pool config + current hosts (with their live counts) for next time.)rç   rè   rê   r*   ræ   rú   Ú
updated_atN)ré   rP  r°  r²  rQ  r  rù  Údead_host_ids)r½  rº  r   rç   rè   rê   r*   ræ   rú   r#  rÄ  rÅ  r   rk   ré   rP  r°  r²  r·  r;   r¸  )rG   rì  rù  Údeads       r3   rØ  zSandboxPool._save_cacheX  së   € à�Z‰Zñ 	,ð !ŸK™Köð ô ØŸ;™;ØŸ*™*Ø!Ÿ]™]ØŸ*™*Ø!Ÿ]™]ØŸ™Ü#Ÿy™y›{öðˆEð ô �t×*Ñ*Ó+ˆD÷	,ô 	Ø�I‰IØ—*‘*Ø—;‘;Ø#×6Ñ6Ø—n‘nØBF×BTÑBTÐB`Ô*¨4×+=Ñ+=Ô>ÐfjØ—o‘oØØö
	
ùò÷	,ð 	,ús   �DœA'DÂDÄDÄD")r   rh   )r+   r¯  )r+   rÿ  )(rP   rQ   rR   rS   r«  rÎ  r¬  rU   r9   r:   rV   r}   r/  r  r   rÜ  r­  r	   rn  rW   rÒ  rô  rÙ  r  r€  r…  rÆ  rá  râ  r  rÕ  rã   rÖ  r  rã  r_   r)  r(  rý  rØ  rX   r5   r3   r¯  r¯  ”  s´  „ ñ!ðJ #ð`%ð "Ø"<ØØ $ØØ1EØ $Ø$Ø Ø#ò`%àð`%ð ð	`%ð
  ð`%ð ð`%ð ˜‘:ð`%ð �D‰jð`%ð ˜E‘k CÑ'¨$Ñ.ð`%ð ˜‘:ð`%ð ð`%ð �T‰zð`%ð ð`%ð 
ó`%ðH Ø>BÐX\ò 4
˜cð 4
°°t±ð 4
È3ÐQUÉ:ð 4
Ðanò 4
ó ð4
ñl˜cð ¨$¨s©)ó ð< &*Ø1EØ!&òeð �#�s�(‰^˜dÑ"ðeð ˜E‘k CÑ'¨$Ñ.ð	eð
 ðeð 
óeðN ð$˜3ò $ó ð$ð
 ð:˜sò :ó ð:ð
 ð9˜$˜s™)ò 9ó ð9ó
)ó0óó
'óRð'¨Ð-=Ñ(>ð 'ÐCZó 'ð8$ Tó $óL&/ðP¨ð °°^Ñ0Dó ðB>˜Nó >ð@$Ð 0ð $°t¸CÀ¸H±~ð $ÐRUÐX\ÑR\ð $Ðaqó $ðL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;  rU   r   r   )rì   r;  s     r3   r÷   r÷   u  s0   € Ü# C§I¡I¬sÔ3ˆC�IŠI¼»€EÙÜÐjÓkÐkØ€Lr5   rR  rS  rT  rQ  rU  rë   c                óŠ  — i |xs i ¥dt        t        «      i¥}i |xs i ¥d|i¥}	t        |xs g «      }
|�t        t        |«      «      |d<   |r||	d<   | j                  › dt
        j                  › d�|d<   ||	d<   t        |d	<   |
j                  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_TOKENrÉ  rÞ  z	/buckets/z/resolve/sbx-serverÚSBX_SERVER_URLÚSBX_DL_TOKENÚSBX_SERVER_MOUNTÚbucketT)rp   ÚsourceÚ
mount_pathÚ	read_onlyz/bin/shz-c)rU   rh  r°   r;   Úendpointr   ÚSANDBOX_SERVER_BUCKETÚ_SERVER_MOUNT_PATHr”  r   Ú_BOOTSTRAP_DOWNLOAD)rì   r)   rR  rS  rT  rQ  rU  rë   rk  rl  rm  rZ  s               r3   ra  ra  |  sé   € ð& T #¢)¨ÐS¨j¼#Ô>QÓ:RÑS€GØ"Q g¢m°Ð"Q°kÀ=Ñ"Q€KÜ�w’} "Ó%€KØÐÜ&)Ô*;¸LÓ*IÓ&JˆÐ"Ñ#ÙØ"*ˆ�JÑà#&§<¡< .°	¼)×:YÑ:YÐ9ZÐZmÐ n€GÐÑØ"*€K�Ñô #5€GÐÑØ×ÑÜ�H¤Y×%DÑ%DÔQcÐosÔtôð ˜$Ô 3Ð4€GØ�G˜[¨+Ð5Ð5r5   r   r  c                óÜ   — t        |j                  t        «      r|j                  ni }d|vr?| j                  |j                  |¬«      j                  xs 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  rR  s       r3   rÍ  rÍ  £  sY   € ä'¨¯©¼Ô>ˆ#�/Š/ÀB€CØ˜SÑ Ø�o‰o S§V¡V°yˆoÓA×MÑMÒSÐQSˆÜ ¤TÔ*‰c°ˆØ€Jr5   r!  rÇ  c                óx   — | j                  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).rr  r  rß  rà  )r  re  rx  r  r   )rì   rÇ  r  r   s       r3   rÌ  rÌ  ¬  sY   € à�}‰}Ø¤*¬i¼ÀWÐ!MÐYbð ó ò ˆð Š
ðô Ø
*¨7¨)ð 4Kð 	Kóð r5   ry  c          	      óÆ  — | j                  ||¬«      }|j                  xs i }|j                  t        «      }|�|j                  t        «      t
        k7  rt        d|› d�«      ‚|j                  j                  dk7  r&t        d|› d|j                  j                  › d�«      ‚t        j                  ||t        t        | «      |«      | t        j                  dz   ¬	«      S )
z?Reattach to a running host job and return its server transport.r  rq  z is not a sandbox host.rr  zSandbox host rs  r"  r]  r^  )r%  r[  rÙ   rg  re  rx  r   r&  r'  rã   r  r4   r÷   rv   r¯   )rì   ry  r  r   r[  r*   s         r3   rw  rw  ¸  sÕ   € à
�/‰/ ¸	ˆ/Ó
B€CØ�Z‰ZÒ˜2€FØ�J‰J”{Ó#€EØ€}˜Ÿ
™
¤:Ó.´)Ò;Ü˜T + Ð.EÐFÓGÐGØ
‡z�z×Ñ˜9Ò$Ü˜]¨;¨-Ð7PÐQT×Q[ÑQ[×QaÑQaÐPbÐbdÐeÓfÐfÜ×"Ñ"ØØÜ+Ô,<¸SÓ,AÀ5ÓIØÜ$×9Ñ9¸AÑ=ð #ó ð r5   r<  c                 ó¤   — d| vr| |fS | j                  dd«      \  }}|r|rd|v rt        d| ›d�«      ‚|�||k7  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#   z%Conflicting namespace: got namespace=z" but sandbox id implies namespace=)rv  r   )r<  r  Úextracted_namespaceÚ	parsed_ids       r3   rt  rt  Ê  s�   € à
�*ÑØ˜9Ð$Ð$Ø%/×%5Ñ%5°c¸1Ó%=Ñ"Ð˜Ù¡i°3¸)Ñ3CÜÐ\Ð]gÐ\jÐjkÐlÓmÐmØÐ Ð.AÒ!AÜØ3°I°=Ð@bÐcvÐbyÐyzÐ{ó
ð 	
ð Ð)Ð)Ð)r5   c                 ó    — | j                   j                  xs g D ]  }dt        › d�|v sŒ|c S  t        d| j                  › dt        › d�«      ‚)Nz--r#   rq  z) does not expose the sandbox server port )r&  Úexpose_urlsrh  r   r  )r   Úurls     r3   r  r  Ø  s\   € Ø�z‰z×%Ñ%Ò+¨ò ˆØÔ#Ð$ AÐ&¨#Ò-ØŠJðô ˜˜cŸf™f˜XÐ%NÔObÐNcÐcdÐeÓ
fÐfr5   é   )r  Úlimitrç   rN  c                ó    — 	 t        | j                  ||¬«      «      | d  }|rddj                  d„ |D «       «      z   S dS # t        $ r Y yw xY w)Nr  rs   z Last logs:
ú
c              3   ó&   K  — | ]	  }d |› �–— Œ y­w)z  NrX   )rñ  rÚ   s     r3   rò  z!_tail_job_logs.<locals>.<genexpr>ä  s   è ø€ Ò&E°t¨¨D¨6¤{Ñ&Eùs   ‚)r°   Úfetch_job_logsrÞ   r…   )rì   rç   r  rN  Úliness        r3   r)  r)  ß  sd   € ðÜ�S×'Ñ'¨vÀÐ'ÓKÓLÈeÈVÈWÐUˆñ JOˆ?˜TŸY™YÑ&E¸uÔ&EÓEÑEÐVÐTVÐVøô ò Ùðús   ‚ A Á	AÁA)^r0   r-   rÁ   r»  r#  Úconcurrent.futuresr   Ú
contextlibr   Údataclassesr   r   Úpathlibr   rS  r   Útypingr	   r
   r   r   r   r   r   rü   rs   r   Ú_sandbox_cacher   r   r   r   Ú
_space_apir   Úerrorsr   r   r   Úhf_apir   r   Úutilsr   r   Úutils._parsingr   Ú
get_loggerrP   ri  rh  rd  re  rf  rx  r  rg  r«  r¬  rc  rÎ  ru  r(  ræ  rA  rB  rU   r4   r9   r:   r;   r=   rZ   rj   rv   rV   r­  rÓ   r0  rÛ   rá   rã   r2  r_   r¯  r÷   rº   r°   ra  rÍ  rÌ  rw  rt  r  r)  rX   r5   r3   ú<module>r`     sÌ  ðó Û Û Û Û Ý 1Ý %ß (Ý Ý ß M× MÑ Mã å ÷ó õ ß EÑ Eß "ß %Ý *ð 
ˆ×	Ñ	˜HÓ	%€ð Ð ð €à€
Ø€Ø€	ð €
ð !€à€àÐ ØÐ àÐ à€ð AÐ ð Ð ð 'Ð ð	Ð ðc Cð c°ð c¸ó cð$  e¡¨cÑ 1ð $°có $ð ÷sð só ðsð& ÷Cð Có ðCð. ÷ð ó ð÷ANñ ANðH	�s˜T #™Y‘ð 	¨t°d©{ð 	¸tÀCÈÀH¹~ó 	ð˜5Ÿ>™>ð ¨h°t©nó ðs §¡ð s°4ó s÷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ðN�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ð HLÐZ\ò W˜ð W sð W¸#À¹*ð WÐTWð WÐadô Wr5   