+
    –°³j,ä ã                   óä  € ^ RI t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIH	t	 ^ RI
HtHt ^ RIHt ^ RIHt ^ RIHtHtHtHtHtHtHt ^ RIHt ^ RIt^R	IHt ^R
IHtH t H!t!H"t"H#t#H$t$ ^RI%H&t& ^RI'H(t(H)t)H*t* ^RI+H,t,H-t- ^RI.H/t/H0t0 ^RI1H2t2 ]0Pf                  ! ]44      t5Rt6Rt7Rt8Rt9Rt:Rt;Rt<]=! ]7]8];]<04      t>Rt?Rt@RtA^tBRdtCRtD^2tERtFRetGRtHRtIRtJRtKRftL^tMR tNR!tOR" R# ltPR$ R% ltQ] ! R& R'4      4       tR] ! R( R)4      4       tS] ! R* R+4      4       tT]	R, R- l4       tU ! R. R/4      tVR0 R1 ltWR2 R3 ltXR4 R5 ltYR6 R7 ltZ ! R8 R9]P¶                  4      t\ ! R: R;4      t] ! R< R=4      t^ ! R> R?4      t_ ! R@ RA4      t`RB RC ltaRD RE ltbRF RG ltcRH RI ltdRJ RK lteRLRM/RN RO lltfRP RQ ltgRR RS lthRT RU ltiRV RW ltjRRRX]H/RY RZ lltkRR/R[ R\ lltlR] R^ ltmR_ R` ltnRRRa^/Rb Rc lltoR# )gé    N)ÚThreadPoolExecutor)Úcontextmanager)Ú	dataclassÚfield)ÚPath)Ú	token_hex)ÚAnyÚBinaryIOÚCallableÚIteratorÚListÚLiteralÚoverload)Úurlparse)Ú	constants)ÚHOST_TRUST_TTLÚCacheContextÚ
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.12z0.6.0Ú@bd08d60b3bdab4ddd4e81401b6dacc96e01bcee3a4753e258b99d40c07d81ee3Ú24hg      >@ÚownÚ	namespaceÚneverÚ.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-$SBX_SERVER_SHA256" "$d"; fi
if command -v sha256sum >/dev/null 2>&1; then
  actual=$(sha256sum "$d" | cut -d' ' -f1)
elif command -v openssl >/dev/null 2>&1; then
  actual=$(openssl dgst -sha256 -r "$d" | cut -d' ' -f1)
elif [ "${SBX_ALLOW_UNVERIFIED_SERVER:-}" = 1 ]; then
  echo "sbx: SBX_ALLOW_UNVERIFIED_SERVER=1: running the sandbox server unverified" >&2
  actual=$SBX_SERVER_SHA256  # opted out, so there is nothing left to compare against
else
  echo "sbx: cannot verify the sandbox server digest: this image has neither sha256sum nor" >&2
  echo "sbx: openssl, so refusing to run it. Use an image with either hash tool installed." >&2
  echo "sbx: Dedicated jobs may opt out with env={'SBX_ALLOW_UNVERIFIED_SERVER': '1'};" >&2
  echo "sbx: pool hosts require setting it in the image environment instead." >&2
  exit 1
fi
if [ "$actual" != "$SBX_SERVER_SHA256" ]; then
  echo "sbx: sandbox server digest mismatch: got $actual," >&2
  echo "sbx: expected $SBX_SERVER_SHA256." >&2
  echo "sbx: refusing to run it. Upgrade huggingface_hub if this client is pinned to a" >&2
  echo "sbx: digest that is no longer published." >&2
  exit 1
fi
chmod +x "$d"
unset SBX_SERVER_URL SBX_SERVER_MOUNT SBX_SERVER_SHA256 SBX_ALLOW_UNVERIFIED_SERVER
exec "$d"
c                ó<   € V ^8„  d   QhR\         R\         R\         /# )é   Úhf_tokenÚnonceÚreturn©Ústr)Úformats   "ÚY/home/luca/screen-checking/.venv/lib/python3.14/site-packages/huggingface_hub/_sandbox.pyÚ__annotate__r2   ¡   s&   € ÷ cñ c¤Cð c´ð c¼ñ có    c                ó¨   € \         P                  ! V P                  4       RV 2P                  4       \        P                  4      P                  4       # )a  Derive the sandbox auth token from the user's HF token and the job's 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.
Only the derived token is passed to the sandbox server as a job secret; the HF token
itself is not.

Scope: one nonce is minted per *job*, not per sandbox. For a dedicated sandbox those are
the same thing. In a pool this derives the *host* credential, which manages the pool and
can recover per-sandbox tokens -- a leak there is host-wide. Each pooled sandbox also has
its own random capability token, minted by the host server, which is what per-sandbox
operations and `proxy_headers` use.

This is not a hardened boundary in either direction. An untrusted image can own the
sandbox port, so don't treat it as a guarantee that credentials stay out of the sandbox;
and the token is derived for whichever job carries the matching nonce label, so don't
treat holding it as proof of which job you are talking to.
zhf-sandbox:)ÚhmacÚnewÚencodeÚhashlibÚsha256Ú	hexdigest)r+   r,   s   &&r1   Ú_derive_sandbox_tokenr;   ¡   s;   € ô& �8Š8�H—O‘OÓ%¨°U°GÐ'<×'CÑ'CÓ'EÄwÇ~Á~ÓV×`Ñ`ÓbÐbr3   c                ó\   € V ^8„  d   QhR\         \        ,          \        ,          R\         /# )r*   Údurationr-   )ÚintÚfloatr/   )r0   s   "r1   r2   r2   ·   s#   € ÷ $ñ $¤¤e¥¬cÕ 1ð $´cñ $r3   c                óf   € \        V \        \        34      '       d   \        V 4      # \        V 4      # )zBParse a duration like 300, "300s", "10m", "2h", "1d" into seconds.)Ú
isinstancer>   r?   r    )r=   s   &r1   Ú_duration_to_secsrB   ·   s(   € ä�(œS¤%˜L×)Ò)Ü�8‹}ÐÜ˜(Ó#Ð#r3   c                   ój   a € ] tR t^¾t o RtRtRt^ t]V 3R lR l4       t	V 3R lR lt
V 3R ltR	tV tR# )
ÚSandboxCommandResultz?Result of a command executed in a sandbox with [`Sandbox.run`].NFc                ó    <€ V ^8„  d   QhRS[ /# ©r*   r-   ©Úbool)r0   Ú__classdict__s   "€r1   r2   Ú!SandboxCommandResult.__annotate__Ê   s   ø€ ÷ #ñ #‘Dñ #r3   c                ó    € V P                   ^ 8H  # ©r   )Ú	exit_code©Úselfs   &r1   ÚokÚSandboxCommandResult.okÉ   s   € à�~‰~ Ñ"Ð"r3   c                ó    <€ V ^8„  d   QhRS[ /# rF   r.   )r0   rI   s   "€r1   r2   rJ   Í   s   ø€ ÷ sñ s™#ñ sr3   c                óÄ   € \        V P                  4      ^P8:  d   V P                  MV P                  R,          R,           pRV P                   RV: RV P                   R2# )éP   :NéM   Nz...zSandboxCommandResult(exit_code=z	, stdout=z, duration_ms=Ú))ÚlenÚstdoutrM   Úduration_ms)rO   Úouts   & r1   Ú__repr__ÚSandboxCommandResult.__repr__Í   sU   € Ü  §¡Ó-°Ô3ˆd�kŠk¸¿¹ÀSÕ9IÈEÕ9QˆØ0°·±Ð0@À	È#ÉÐP^Ð_c×_oÑ_oÐ^pÐpqÐrÐrr3   c                ó~   <€ V ^8„  d   Qh/ S[ R,          ;R&   S[;R&   S[;R&   S[ R,          ;R&   S[;R&   S[ ;R&   # )r*   NrM   rX   ÚstderrÚsignalÚ	timed_outrY   )r>   r/   rH   )r0   rI   s   "€r1   r2   rJ   ¾   sY   ø‡ ‚ ñ �T�zÑñ	 ñ
 �Kñ ñ �Kñ ñ �$�JÑñ ñ Ññ ñ Ñò r3   © )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r_   r`   rY   ÚpropertyrP   r[   Ú__annotate_func__Ú__static_attributes__Ú__classdictcell__©rI   s   @r1   rD   rD   ¾   s>   ø‡ € áIð
 €FØ€IØ€Kà÷#ó ð#÷sð s÷ ƒ r3   rD   c                   óf   a € ] tR t^Òt o Rt]! RRR7      tRtRtRt	Rt
V 3R lR ltV 3R ltR	tV tR# )
Ú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`].
Recently completed processes stay in the listing (the server keeps a bounded number of
them), so `running` and `exit_code` tell whether a process is still alive or already
exited (as of when it was listed).
F)ÚreprÚcompareNTc                ó    <€ V ^8„  d   QhRS[ /# rF   rG   )r0   rI   s   "€r1   r2   ÚSandboxProcess.__annotate__ë   s   ø€ ÷ :ñ :‘dñ :r3   c                óØ   € V P                   f   \        R4      hV P                  P                  RRV P                    24      p\	        VP                  4       P                  RR4      4      # )a^  Terminate the background process. Idempotent.

Returns whether this call is what stopped it: `False` means it had already
exited or been terminated, which is not an error.

Note that a descendant which detaches with `setsid()` leaves the signalled
process group and outlives this call. Delete the sandbox to be certain
everything it started is gone.
zßThis process cannot be stopped individually: its sandbox runs a sandbox server that predates opaque process ids, so the server never issued one. Recycle the pool's hosts, or delete the sandbox to stop everything it started.ÚDELETEz/processes/ÚkilledF)Úidr   Ú_sandboxÚ_requestrH   ÚjsonÚget)rO   Úresponses   & r1   ÚkillÚSandboxProcess.killë   sa   € ð �7‰7Š?ÜðUóð ð
 —=‘=×)Ñ)¨(°kÀ$Ç'Á'ÀÐ4KÓLˆÜ�H—M‘M“O×'Ñ'¨°%Ó8Ó9Ð9r3   c                óÐ   <€ V ^8„  d   Qh/ S[ R,          ;R&   S[;R&   S[ S[S[ ,          ,          ;R&   R;R&   S[ R,          ;R&   S[R,          ;R&   S[;R	&   S[R,          ;R
&   # )r*   Nru   ÚpidÚcmdÚSandboxrv   ÚtagÚstarted_at_msÚrunningrM   )r/   r>   r   rH   )r0   rI   s   "€r1   r2   rq   Ò   sƒ   ø‡ ‚ ñ 	ˆd�
�Nñ ñ 
�Hñ ñ  
‰t‘C�y�Ññ! ð& Ñ:ñ' ñ( 
ˆt�Ññ) ñ* ˜•:Ñ$ñ+ ñ, Ññ- ñ. �T�zÑ ò/ r3   ra   )rb   rc   rd   re   rf   r   rv   r�   r‚   rƒ   rM   r{   rh   ri   rj   rk   s   @r1   rm   rm   Ò   s=   ø‡ € ññ"   U°EÔ:€HØ€CØ $€MØ€GØ €I÷:ð :÷3 ƒ r3   rm   c                   ó8   a € ] tR t^ÿt o RtRtRtV 3R ltRtV t	R# )Ú	FileEntryz%A file or directory inside a sandbox.NÚ c                ó~   <€ V ^8„  d   Qh/ S[ ;R&   S[ ;R&   S[R,          ;R&   S[;R&   S[R,          ;R&   S[ ;R&   # )	r*   ÚnameÚpathÚtypeÚsizeNÚmtime_msÚmode)ÚfileÚdirÚsymlink)r/   r   r>   )r0   rI   s   "€r1   r2   ÚFileEntry.__annotate__ÿ   sY   ø‡ ‚ ñ �Iñ	 ñ
 �Iñ ñ Ð*Õ
+Ñ+ñ ñ �Iñ ñ �D�jÑñ ñ �Nò r3   ra   )
rb   rc   rd   re   rf   rŒ   r�   rh   ri   rj   rk   s   @r1   r…   r…   ÿ   s   ø‡ € á/ð  €HØ€D÷ ƒ r3   r…   c                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r*   Ú
local_pathr-   )r   r   r
   )r0   s   "r1   r2   r2     s   € ÷ ñ ¤dð ¬x¼Õ/Añ r3   c              #  óR  "  € V P                   RV P                   R\        ^4       R2,          p\        P                  \        P
                  ,          \        P                  ,          \        \        R^ 4      ,          \        \        R^ 4      ,          p\        P                  ! WR4      p \        P                  ! VR4      ;_uu_ 4       pVx € RRR4       \        P                  ! W4       R#   + '       g   i     L(; i  \         d    TP                  RR	7       h i ; i5i)
aü  Yield a writer whose bytes only appear at `local_path` once the download completes.

Writing straight to the destination has three problems: an interrupted transfer leaves a
truncated file at the final name; `open(path, "wb")` follows a symlink sitting there, so
the sandbox's output can be redirected into any file this process can write; and a
predictable temp name is a race another local process can win.

So the bytes go to a temp file in the destination directory, created `O_EXCL` (nobody
else's file) and `O_NOFOLLOW` (not a symlink) with mode `0600` and an unguessable name,
then `os.replace`d into place. `rename` does not follow symlinks either, so a symlinked
destination is *replaced* rather than written through, and a failure leaves nothing behind.
r(   z.partÚ
O_NOFOLLOWÚO_BINARYi€  ÚwbNT)Ú
missing_ok)Úparentrˆ   r   ÚosÚO_WRONLYÚO_CREATÚO_EXCLÚgetattrÚopenÚfdopenÚreplaceÚBaseExceptionÚunlink)r“   ÚtmpÚflagsÚfdÚfs   &    r1   Ú_open_download_targetr¨     sÑ   é € ð ×
Ñ
  *§/¡/Ð!2°!´I¸a³L°>ÀÐGÕ
G€CÜ�K‰Kœ"Ÿ*™*Õ$¤r§y¡yÕ0´7¼2¸|ÈQÓ3OÕOÔRYÔZ\Ð^hÐjkÓRlÕl€EÜ	�Š�˜UÓ	#€BðÜ�YŠY�r˜4× Ô  AØŠG÷ !ä
�
Š
�3Ö#÷ !× ûô ô Ø�
‰
˜dˆ
Ô#Øðüs6   ‚B+D'Â.D ÃC2ÃD Ã0D'Ã2D	Ã=D ÄD$Ä$D'c                   óˆ  a € ] tR tRt o RtR)tR*t^tR+tV 3R lR lt	V 3R lR lt
R,V 3R lR lltR-V 3R
 lR lltR-V 3R lR lltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R  lR! ltV 3R" lR# ltR.V 3R$ lR% lltV 3R& lR' ltR(tV tR	# )/ÚSandboxFilesi%  u  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.

Paths are normalized lexically, then resolved by the host server relative to an open
home-directory descriptor. The file API refuses symlinks on every component, including
links whose targets are inside the same home.
c                ó"   <€ V ^8„  d   QhRRRR/# )r*   Úsandboxr€   r-   Nra   )r0   rI   s   "€r1   r2   ÚSandboxFiles.__annotate__?  s   ø€ ÷  ñ   	ð  ¨dñ  r3   c                ó   € Wn         R # ©N©rv   ©rO   r¬   s   &&r1   Ú__init__ÚSandboxFiles.__init__?  s   € ØŽr3   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r*   r‰   r-   ©r/   Úbytes)r0   rI   s   "€r1   r2   r­   B  s   ø€ ÷ /ñ /™ð /¡ñ /r3   c                ó`  € V P                  V4      P                  pW P                  8”  d   \        V RV RV P                   R24      hW P                  8”  dD   \        V4      pV P                  W4       F  w  rEWSWD\        V4      ,           % K  	  \        V4      # V P                  V^ V4      # )zÅRead a file from the sandbox and return its content as bytes.

Raises [`SandboxError`] above `MAX_READ_BYTES`; use [`download`] for
anything that large, which streams to disk instead of buffering.
z is z bytes, over the zc-byte limit for reading into memory. Use `files.download(path, local_path)`, which streams to disk.)
Ústatr‹   ÚMAX_READ_BYTESr   ÚPARALLEL_THRESHOLDÚ	bytearrayÚ_read_rangesrW   r·   Ú_read_range)rO   r‰   r‹   ÚbufferÚoffsetÚparts   &&    r1   ÚreadÚSandboxFiles.readB  s¶   € ð �y‰y˜‹×#Ñ#ˆØ×%Ñ%Ô%ÜØ�&˜˜T˜FÐ"3°D×4GÑ4GÐ3Hð IYð Yóð ð ×)Ñ)Ô)ô ˜t“_ˆFØ $× 1Ñ 1°$Ö =‘�Ø6:�v¬¨T«Õ 2Ò3ñ !>ä˜“=Ð Ø×Ñ  a¨Ó.Ð.r3   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[ /# )r*   r‰   Úencodingr-   r.   )r0   rI   s   "€r1   r2   r­   W  s"   ø€ ÷ 0ñ 0™cð 0©Sð 0¹sñ 0r3   c                óB   € V P                  V4      P                  V4      # )z@Read a file from the sandbox and return its content as a string.)rÂ   Údecode)rO   r‰   rÅ   s   &&&r1   Ú	read_textÚSandboxFiles.read_textW  s   € à�y‰y˜‹×%Ñ% hÓ/Ð/r3   Nc                ó^   <€ V ^8„  d   QhRS[ RS[ S[,          S[,          RS[ R,          RR/# ©r*   r‰   Údatar�   Nr-   )r/   r·   r
   )r0   rI   s   "€r1   r2   r­   [  s=   ø€ ÷ Sñ S™#ð S¡S©5¥[±8Õ%;ð SÁ3ÈÅ:ð SÐY]ñ Sr3   c                óP  € \        V\        4      '       d   VP                  4       pM&\        V\        4      '       g   VP	                  4       p\        V4      V P                  8”  d   V P                  WV4       R# RV/pVe   W4R&   V P                  P                  RRWBR7       R# )zHWrite content to a file in the sandbox (parent directories are created).Nr‰   r�   ÚPUTú/files/write©ÚparamsÚcontent)
rA   r/   r7   r·   rÂ   rW   r»   Ú_write_rangesrv   rw   )rO   r‰   rÌ   r�   rÑ   s   &&&& r1   ÚwriteÚSandboxFiles.write[  s†   € ä�dœC× Ò Ø—;‘;“=‰DÜ˜D¤%×(Ò(Ø—9‘9“;ˆDÜˆt‹9�t×.Ñ.Ô.Ø×Ñ˜t¨4Ô0ÙØ˜$�ˆØÒØ!�6‰NØ�‰×Ñ˜u n¸VÐÖRr3   c                óN   <€ V ^8„  d   QhRS[ S[,          RS[ RS[ R,          RR/# )r*   r“   r‰   r�   Nr-   ©r/   r   )r0   rI   s   "€r1   r2   r­   i  s2   ø€ ÷ /ñ /¡¡t¥ð /±3ð /¹cÀD½jð /ÐTXñ /r3   c                ó0  € \        VR4      ;_uu_ 4       p\        P                  ! VP                  4       4      P                  pWPP
                  8”  d   V P                  W$WS4       MV P                  W$VR7       RRR4       R#   + '       g   i     R# ; i)zìUpload a local file to the sandbox.

The file is opened once and both sized (`fstat`) and read through that same
descriptor, so what is uploaded is the file that was measured -- rather than
whatever the path resolves to a moment later.
Úrb)r�   N)rŸ   rš   ÚfstatÚfilenoÚst_sizer»   Ú_write_ranges_from_filerÔ   )rO   r“   r‰   r�   r§   r‹   s   &&&&  r1   ÚuploadÚSandboxFiles.uploadi  sj   € ô �*˜d×#Ô# qÜ—8’8˜AŸH™H›JÓ'×/Ñ/ˆDØ×-Ñ-Ô-ð ×,Ñ,¨T°dÕAà—
‘
˜4¨�
Ô.÷ $×#×#Ò#ús   •A%BÂB	c                ó:   <€ V ^8„  d   QhRS[ RS[ S[,          RR/# )r*   r‰   r“   r-   Nr×   )r0   rI   s   "€r1   r2   r­   z  s&   ø€ ÷ #ñ #™Sð #©c±D­jð #¸Tñ #r3   c           	     ó8  € V P                  V4      P                  p\        \        V4      4      ;_uu_ 4       pW0P                  8”  dH   V P                  W4       F'  w  rVVP                  V4       VP                  V4       K)  	   RRR4       R# V P                  P                  RRRV/R7      ;_uu_ 4       pVP                  RR7       F  pVP                  V4       K  	  RRR4       RRR4       R#   + '       g   i     L; i  + '       g   i     R# ; i)a  Download a file from the sandbox.

The bytes land in a private temp file next to the destination and are renamed
over it at the end, so an interrupted download leaves no truncated file and a
symlink sitting at `local_path` is replaced rather than followed.
NÚGETú/files/readr‰   ©rÑ   ©Ú
chunk_sizeé   )r¹   r‹   r¨   r   r»   r½   ÚseekrÔ   rv   Ú_streamÚ
iter_bytes)	rO   r‰   r“   r‹   r§   rÀ   rÁ   rz   Úchunks	   &&&      r1   ÚdownloadÚSandboxFiles.downloadz  sß   € ð �y‰y˜‹×#Ñ#ˆÜ"¤4¨
Ó#3×4Ô4¸Ø×-Ñ-Ô-ð %)×$5Ñ$5°dÖ$A‘L�FØ—F‘F˜6”NØ—G‘G˜D–Mñ %Bð ÷ 5Ñ4ð —‘×&Ñ& u¨mÀVÈTÀNÐ&×SÔSÐW_Ø%×0Ñ0¸KÐ0ÖH�EØ—G‘G˜E–Nñ I÷ T÷ 5Ñ4÷ T×Sú÷ 5×4Ð4ús*   ¸ADÂ(DÂ8+C5	Ã#DÃ5DÄ DÄD	c                óL   <€ V ^8„  d   QhRS[ RS[S[S[ S[ 3,          ,          /# )r*   r‹   r-   )r>   r   Útuple)r0   rI   s   "€r1   r2   r­   Ž  s,   ø€ ÷ Yñ Y™Cð Y¡D©©s±C¨x­Õ$9ñ Yr3   c           	     ó~   € V P                   p\        ^ W4       Uu. uF  q3\        W!V,
          4      3NK  	  up# u upi rL   )ÚPARALLEL_CHUNK_SIZEÚrangeÚmin)rO   r‹   rë   rÀ   s   &&  r1   Ú_rangesÚSandboxFiles._rangesŽ  s:   € Ø×(Ñ(ˆÜBGÈÈ4ÔBWÓXÑBW¸œ˜U¨6¥MÓ2Ó3ÑBWÑXÐXùÒXs   ›:c                ód   <€ V ^8„  d   QhRS[ S[,          RS[S[.S[3,          RS[ S[,          /# )r*   ÚitemsÚfnr-   )r   r	   r   )r0   rI   s   "€r1   r2   r­   ’  s5   ø€ ÷ 1ñ 1™t¡C�yð 1©h¹°u¹c°zÕ.Bð 1ÁtÉCÅyñ 1r3   c                óØ   € \        V P                  \        V4      4      p\        V4      ;_uu_ 4       p\	        VP                  W!4      4      uuRRR4       #   + '       g   i     R# ; i)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_WORKERSrW   r   ÚlistÚmap)rO   r÷   rø   ÚworkersÚexecutors   &&&  r1   Ú	_parallelÚSandboxFiles._parallel’  sG   € ô �d×/Ñ/´°U³Ó<ˆÜ ×(Ô(¨HÜ˜Ÿ™ RÓ/Ó0÷ )×(×(Ó(ús   ³AÁA)	c                ó2   <€ V ^8„  d   QhRS[ RS[RS[RS[/# )r*   r‰   rÀ   Úlengthr-   ©r/   r>   r·   )r0   rI   s   "€r1   r2   r­   œ  s)   ø€ ÷ ñ ¡ð ©Sð ¹#ð Á%ñ r3   c           
     óœ  € \        4       pV P                  P                  R RRVRVRV/R7      ;_uu_ 4       pVP                  R
R7       F?  p\	        V4      \	        V4      ,           V8”  d   \        R4      hVP                  V4       KA  	  RRR4       \	        V4      V8w  d   \        R	4      h\        V4      #   + '       g   i     L6; i)râ   rã   r‰   rÀ   r  rä   rå   z+File response exceeded the requested range.Nz6File changed size during transfer; retry the download.rç   )r¼   rv   ré   rê   rW   r   Úextendr·   )rO   r‰   rÀ   r  rÌ   rz   rë   s   &&&&   r1   r¾   ÚSandboxFiles._read_rangeœ  s·   € Ü‹{ˆØ�]‰]×"Ñ"Ø�=¨&°$¸À&È(ÐTZÐ)[ð #÷ 
ô 
àØ!×,Ñ,¸Ð,ÖD�Ü�t“9œs 5›zÕ)¨FÔ2Ü&Ð'TÓUÐUØ—‘˜EÖ"ñ E÷
ô ˆt‹9˜ÔÜÐWÓXÐXÜ�T‹{Ð÷
÷ 
ús   ·AB;Â;C	c          	      óR   <€ V ^8„  d   QhRS[ RS[RS[S[S[S[3,          ,          /# )r*   r‰   r‹   r-   )r/   r>   r   rï   r·   )r0   rI   s   "€r1   r2   r­   ©  s5   ø€ ÷ Pñ P¡ð P©Cð P±H¹UÁ3ÉÀ:Õ=NÕ4Oñ Pr3   c           
   #  óh  a a"  € R VV 3R llpS P                  V4      p\        S P                  \        V4      4      p\	        V4      ;_uu_ 4       p\        ^ \        V4      V4       F%  pVP                  W4WwV,            4       Rj  x€L
  K'  	  RRR4       R#  L  + '       g   i     R# ; i5i)zîFetch every range in parallel, yielding `(offset, bytes)` as they land.

Yielding rather than returning a list is the point: the caller places each
chunk and drops it, so peak memory is a few chunks instead of the whole
file plus a copy.
c                ót   € V ^8„  d   QhR\         \        \        3,          R\         \        \        3,          /# )r*   Úrngr-   )rï   r>   r·   )r0   s   "r1   r2   Ú/SandboxFiles._read_ranges.<locals>.__annotate__±  s/   € ÷ 	Bñ 	B”uœS¤#˜X•ð 	B¬5´´e°Õ+<ñ 	Br3   c                 ó4   <€ V w  rVSP                  SW4      3# r¯   )r¾   )r
  rÀ   r  r‰   rO   s   &  €€r1   ÚfetchÚ(SandboxFiles._read_ranges.<locals>.fetch±  s"   ø€ Ø ‰NˆFØ˜4×+Ñ+¨D°&ÓAÐAÐAr3   N)rô   ró   rú   rW   r   rò   rü   )rO   r‰   r‹   r  Úrangesrý   rþ   Ústarts   ff&     r1   r½   ÚSandboxFiles._read_ranges©  s�   ùé € ÷	Bñ 	Bð —‘˜dÓ#ˆÜ�d×/Ñ/´°V³Ó=ˆÜ ×(Ô(¨HÜ˜q¤# f£+¨wÖ7�Ø#Ÿ<™<¨°eÀg½oÐ/NÓO×OÒOñ 8÷ )Ñ(áO÷ )×(Ð(üs0   „AB2Á7BÂ	B
Â
BÂ
B2ÂBÂB/	Â)	B2c                ó>   <€ V ^8„  d   QhRS[ RS[RS[ R,          RR/# rË   r¶   )r0   rI   s   "€r1   r2   r­   »  s-   ø€ ÷ 6ñ 6¡#ð 6©Uð 6¹#À½*ð 6Èñ 6r3   c                óz   a aaa€ R  VVVV 3R llpS P                  S P                  \        S4      4      V4       R# )c                óJ   € V ^8„  d   QhR\         \        \        3,          RR/# ©r*   r
  r-   N©rï   r>   )r0   s   "r1   r2   Ú0SandboxFiles._write_ranges.<locals>.__annotate__¼  s&   € ÷ 	añ 	a”eœC¤˜H•oð 	a¨$ñ 	ar3   c           	      ó`   <€ V w  rSP                  SVSWV,            S\        S4      R 7       R# )©ÚtotalN)Ú
_put_rangerW   )r
  rÀ   r  rÌ   r�   r‰   rO   s   &  €€€€r1   ÚpushÚ(SandboxFiles._write_ranges.<locals>.push¼  s0   ø€ Ø ‰NˆFØ�O‰O˜D &¨$¨vÀ½Ð*HÈ$ÔVYÐZ^ÓV_ˆOÖ`r3   N)rÿ   rô   rW   )rO   r‰   rÌ   r�   r  s   ffff r1   rÓ   ÚSandboxFiles._write_ranges»  s,   û€ ÷	aó 	að 	�‰�t—|‘|¤C¨£IÓ.°Ö5r3   c          
      óD   <€ V ^8„  d   QhRS[ RS[RS[RS[ R,          RR/# )r*   r‰   Úsourcer‹   r�   Nr-   )r/   r
   r>   )r0   rI   s   "€r1   r2   r­   Â  s8   ø€ ÷ 1ñ 1©Cð 1¹ð 1Éð 1ÑTWÐZ^ÕT^ð 1Ðcgñ 1r3   c                óš   a aaaaa€ \         P                  ! 4       oR VVVV VV3R llpS P                  S P                  S4      V4       R# )z�Upload `source` in parallel ranges, reading each range on demand.

Serialize reads from the shared descriptor; network writes still overlap.
c                óJ   € V ^8„  d   QhR\         \        \        3,          RR/# r  r  )r0   s   "r1   r2   Ú:SandboxFiles._write_ranges_from_file.<locals>.__annotate__É  s&   € ÷ 	Cñ 	C”eœC¤˜H•oð 	C¨$ñ 	Cr3   c                 ó   <€ V w  rS;_uu_ 4        S	P                  V4       S	P                  V4      pR R R 4       \        X4      V8w  d   \        R4      hSP	                  SWSSR7       R #   + '       g   i     LB; i)Nz+Upload source changed size during transfer.r  )rè   rÂ   rW   r   r  )
r
  rÀ   r  rë   r�   r‰   Ú	read_lockrO   r‹   r   s
   &   €€€€€€r1   r  Ú2SandboxFiles._write_ranges_from_file.<locals>.pushÉ  sd   ø€ Ø ‰NˆFß’Ø—‘˜FÔ#ØŸ™ FÓ+�÷ ô �5‹z˜VÔ#Ü"Ð#PÓQÐQØ�O‰O˜D &°¸TˆOÖB÷ —ús   �#A-Á-A=	N)Ú	threadingÚLockrÿ   rô   )rO   r‰   r   r‹   r�   r  r%  s   fffff @r1   rÝ   Ú$SandboxFiles._write_ranges_from_fileÂ  s6   ý€ ô
 —N’NÓ$ˆ	÷	Cõ 	Cð 	�‰�t—|‘| DÓ)¨4Ö0r3   c                óJ   <€ V ^8„  d   QhRS[ RS[RS[RS[ R,          RS[RR/# )r*   r‰   rÀ   rë   r�   Nr  r-   r  )r0   rI   s   "€r1   r2   r­   Ô  sE   ø€ ÷ 	Tñ 	T™sð 	T©Cð 	T¹ð 	TÁSÈ4ÅZð 	TÑ[^ð 	TÐcgñ 	Tr3   c               ó”   € R VRV/pVe   WFR&   V\        V4      ,           V8¼  d   WVR&   V P                  P                  RRWcR7       R# )r‰   rÀ   Nr�   Útruncate_torÎ   rÏ   rÐ   )rW   rv   rw   )rO   r‰   rÀ   rë   r�   r  rÑ   s   &&&&&$ r1   r  ÚSandboxFiles._put_rangeÔ  sQ   € Ø"(¨$°¸&Ð!AˆØÒØ!�6‰Nð ”C˜“JÕ %Ô'Ø$)�=Ñ!Ø�‰×Ñ˜u n¸VÐÖSr3   c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# rµ   )r/   r   r…   )r0   rI   s   "€r1   r2   r­   ß  s   ø€ ÷ ñ ™ð ¡¡i¥ñ r3   c                óô   € . pRp RV/pVe   W4R&   V P                   P                  RRVR7      P                  4       pVP                  R VR,           4       4       VP	                  R	4      pV'       d   Ks  V# )
z¼List a directory in the sandbox.

The server paginates, so this follows the cursor and returns everything --
a caller sees one list regardless of how the directory is chunked on the
wire.
Nr‰   Úafterrâ   z/files/listrä   c              3   ó8   "  € T F  p\        R/ VB x € K  	  R # 5i)Nra   )r…   )Ú.0Úentrys   & r1   Ú	<genexpr>Ú$SandboxFiles.list.<locals>.<genexpr>í  s   é € ÐNÑ;M°%œ9Ñ- uÖ-Ó;Mùó   ‚ÚentriesÚnext)rv   rw   rx   r  ry   )rO   r‰   r7  r0  rÑ   Úpayloads   &&    r1   rû   ÚSandboxFiles.listß  sz   € ð $&ˆØ ˆØØ&,¨d ^ˆFØÒ Ø"'�w‘Ø—m‘m×,Ñ,¨U°MÈ&Ð,ÓQ×VÑVÓXˆGØ�N‰NÑN¸7À9Ö;MÓNÔNØ—K‘K Ó'ˆEß‘5Ø�r3   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rµ   )r/   r…   )r0   rI   s   "€r1   r2   r­   ò  s   ø€ ÷ ,ñ ,™ð ,¡ñ ,r3   c                ót   € V P                   P                  RRRV/R7      p\        R/ VP                  4       B # )z3Get metadata of a file or directory in the sandbox.râ   z/files/statr‰   rä   ra   )rv   rw   r…   rx   )rO   r‰   rz   s   && r1   r¹   ÚSandboxFiles.statò  s6   € à—=‘=×)Ñ)¨%°ÈÐPTÀ~Ð)ÓVˆÜÑ+˜8Ÿ=™=›?Ñ+Ð+r3   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rµ   ©r/   rH   )r0   rI   s   "€r1   r2   r­   ÷  s   ø€ ÷ ñ ™3ð ¡4ñ r3   c                ó€   €  V P                  V4       R#   \         d   pTP                  R8X  d    Rp?R# h Rp?ii ; i)z+Check whether a path exists in the sandbox.Té”  NF)r¹   r   Ústatus_code)rO   r‰   Úes   && r1   ÚexistsÚSandboxFiles.exists÷  s7   € ð	Ø�I‰I�dŒOÙøÜô 	Ø�}‰} Ô#ÝØûð	ús   ‚ •= 8·8¸=c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r*   r‰   Ú	recursiver-   Nr?  )r0   rI   s   "€r1   r2   r­     s'   ø€ ÷ Iñ I™3ð I©4ð I¸Dñ Ir3   c                ód   € RV/pV'       d   RVR&   V P                   P                  RRVR7       R# )z*Delete a file or directory in the sandbox.r‰   Ú1rG  rs   z/files/deleterä   N©rv   rw   )rO   r‰   rG  rÑ   s   &&& r1   ÚdeleteÚSandboxFiles.delete  s1   € à˜$�ˆßØ"%ˆF�;ÑØ�‰×Ñ˜x¨ÀÐÖHr3   c                ó$   <€ V ^8„  d   QhRS[ RR/# )r*   r‰   r-   Nr.   )r0   rI   s   "€r1   r2   r­     s   ø€ ÷ Nñ N™#ð N $ñ Nr3   c                óF   € V P                   P                  RRRV/R7       R# )z0Create a directory (and parents) in the sandbox.ÚPOSTz/files/mkdirr‰   rä   NrJ  )rO   r‰   s   &&r1   ÚmkdirÚSandboxFiles.mkdir  s   € à�‰×Ñ˜v ~¸vÀt¸nÐÖMr3   r°   i    rç   i    )zutf-8r¯   )F)rb   rc   rd   re   rf   r»   rñ   rú   rº   r²   rÂ   rÈ   rÔ   rÞ   rì   rô   rÿ   r¾   r½   rÓ   rÝ   r  rû   r¹   rD  rK  rP  ri   rj   rk   s   @r1   rª   rª   %  så   ø‡ € ñ	ð )ÐØ)ÐØÐð '€N÷ ð  ÷/ð /÷*0ò 0÷Sò S÷/ò /÷"#ð #÷(Yð Y÷1ð 1÷ð ÷Pð P÷$6ð 6÷1ð 1÷$	Tð 	T÷ð ÷&,ð ,÷
ð ÷Iò I÷Nö Nr3   rª   c                ó˜   € V ^8„  d   QhR\         \        \         ,          ,          R\        R,          R\        \         \        3,          /# )r*   r   ÚshellNr-   )r/   r   rH   Údictr	   )r0   s   "r1   r2   r2     s5   € ÷ 	ñ 	”sœT¤#�Y•ð 	¬t°d­{ð 	¼tÄCÌÀH½~ñ 	r3   c                óº   € VRJ d"   \        V \        4      '       g   \        R4      hVRJ d"   \        V \        4      '       d   \        R4      hRV /pVe   WR&   V# )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   rS  )rA   r/   Ú
ValueError)r   rS  r9  s   && r1   Ú_exec_payloadrW    s\   € à�ƒ}œZ¨¬S×1Ò1ÜÐ^Ó_Ð_Ø�ƒ~œ* S¬#×.Ò.ÜÐmÓnÐnØ$ c˜l€GØÒØ �ÑØ€Nr3   c                óZ   € V ^8„  d   QhR\         P                  R\        \        ,          /# )r*   rz   r-   )ÚhttpxÚResponser   rT  )r0   s   "r1   r2   r2     s"   € ÷ ñ œ5Ÿ>™>ð ¬h´t­nñ r3   c              #  ó´   "  € V P                  4        F?  pV'       g   K  \        P                  ! V4      pVP                  R4      R8w  g   K;  Vx € KA  	  R# 5i)zJIterate NDJSON events from a streaming response, skipping keepalive pings.ÚeventÚpingN)Ú
iter_linesrx   Úloadsry   )rz   Úliner\  s   &  r1   Ú_iter_eventsra    sB   é € à×#Ñ#Ö%ˆßÙÜ—
’
˜4Ó ˆØ�9‰9�WÓ Ö'ØŒKó &ùs   ‚AAÁ
Ac                ó<   € V ^8„  d   QhR\         P                  RR/# )r*   rz   r-   N)rY  rZ  )r0   s   "r1   r2   r2   #  s"   € ÷ sñ s¤§¡ð s°4ñ sr3   c                óè   € V P                  4         V P                  4       R,          p\	        RV P
                   RV 2V P
                  R7      h  \         d    T P                  R,          p LGi ; i)zQRead the error body and raise a SandboxError (works for streaming responses too).Úerror:Niô  NzSandbox API error (z): )rB  )rÂ   rx   Ú	ExceptionÚtextr   rB  )rz   Úmessages   & r1   Ú_raise_for_statusrh  #  sj   € à‡M�M„Oð&Ø—-‘-“/ 'Õ*ˆô Ð,¨X×-AÑ-AÐ,BÀ#ÀgÀYÐOÐ]e×]qÑ]qÔ
rÐrøô ô &Ø—-‘- Õ%Šð&ús   ’A ÁA1Á0A1c                óH   € V ^8„  d   QhR\         P                  R\        RR/# )r*   rz   Újob_idr-   N)rY  rZ  r/   )r0   s   "r1   r2   r2   -  s%   € ÷ ñ ¤U§^¡^ð ¼Sð ÀTñ r3   c           	     ó  €  V P                  4       P                  R4      p\        V\        4      '       d$   \        V\
        4      '       g   V\        8¼  d   R# Ve   TMRp\        RV RV R\         R24      h  \         d    Rp Lii ; i)aï  Refuse a server whose wire contract this client cannot drive.

Permissive in one direction only. A *newer* server is accepted: it declares its own
backwards compatibility by keeping the protocol integer it still supports. An *older* one
is refused, because the mismatches are things like the per-sandbox capability token, which
surfaces as a 403 on an unrelated route several calls later instead of here.

`version` is no use for this: it moves for a doc fix as readily as for a protocol break.
ÚprotocolNz1 (declares no protocol)úSandbox job z runs sbx-server protocol z5, but this version of huggingface_hub needs protocol z¶ or newer. A pool host keeps the server binary it downloaded at boot for up to 24h, so recycle this pool's hosts (kill them, or let them idle-time-out) to pick up the current server.)rx   ry   re  rA   r>   rH   ÚSANDBOX_SERVER_PROTOCOLr   )rz   rj  rl  Úreporteds   &&  r1   Ú_check_server_protocolrp  -  sš   € ðØ—=‘=“?×&Ñ& zÓ2ˆô �(œC× Ò ¬°H¼d×)CÒ)CÈÔTkÔHkÙà#Ò/‰xÐ5O€HÜ
Ø
�v�hÐ8¸¸
ð C*Ü*AÐ)Bð CDð	Dóð øô ô ØŠðús   ‚A; Á;BÂ
Bc                   ó<   a € ] tR tRt o RtV 3R lR ltR tRtV tR# )Ú_SandboxAuthiG  aÖ  Attach the *current* HF bearer to every request.

The bearer used to be captured once when the transport was built. A sandbox
host lives up to 24h, so an OIDC/OAuth credential can expire or rotate inside
that window, after which every request to the Jobs proxy failed even though
the handle was still perfectly good. Reading it per request fixes that.

The `X-Sandbox-Token` is deliberately *not* re-derived: the server holds the
value derived from the bearer that created the job, so re-deriving from a
rotated bearer would produce a token the server has never seen. The two
credentials answer different gates -- the proxy wants a live bearer, the
server wants the original capability -- and only the first needs refreshing.
c                ó$   <€ V ^8„  d   QhRS[ RR/# )r*   Úapir-   N)r   )r0   rI   s   "€r1   r2   Ú_SandboxAuth.__annotate__V  s   ø€ ÷ ñ ™Eð  dñ r3   c                ó   € Wn         R # r¯   ©Ú_api)rO   rt  s   &&r1   r²   Ú_SandboxAuth.__init__V  s   € ØŽ	r3   c              #  ó`   "  € R \        V P                  4       2VP                  R&   Vx € R# 5i)úBearer ÚAuthorizationN)Ú_effective_tokenrx  Úheaders)rO   Úrequests   &&r1   Ú	auth_flowÚ_SandboxAuth.auth_flowY  s*   é € Ø-4Ô5EÀdÇiÁiÓ5PÐ4QÐ+Rˆ�‰˜Ñ(ØŒùs   ‚,.rw  N)	rb   rc   rd   re   rf   r²   r€  ri   rj   rk   s   @r1   rr  rr  G  s   ø‡ € ñ÷ð ÷ð r3   rr  c                   ó  a € ] tR tRt o RtR^
R^ /V 3R lR llt]R^
R^ /V 3R lR ll4       t]V 3R	 lR
 l4       t	V 3R lR lt
RR/V 3R lR llt]RR/V 3R lR ll4       tV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltRtV tR# )Ú_SandboxServeri^  u5  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.
Úmax_connectionsÚcapacityc                ób   <€ V ^8„  d   QhRS[ RS[ RS[ R,          RS[ RS[ RS[ RS[R	S[R
S[RR/
# )r*   rj  ÚownerÚimageNÚbase_urlr,   Úsandbox_tokenrt  r„  r…  r-   )r/   r   r>   )r0   rI   s   "€r1   r2   Ú_SandboxServer.__annotate__f  su   ø€ ÷ -
ñ -
ñ ð-
ñ ð	-
ñ
 �T�zð-
ñ ð-
ñ ð-
ñ ð-
ñ ð-
ñ ð-
ñ ð-
ð 
ñ-
r3   c       	   	     ó  € Wn         W n        W0n        W@n        WPn        Wpn        W`n        W�n        ^ V n        RV n	        RV n
        \        P                  ! RV/\        V4      \        P                  ! WˆR7      RR7      V n        R# )r   TFúX-Sandbox-Token)r„  Úmax_keepalive_connections)r~  ÚauthÚlimitsÚfollow_redirectsN)rj  r‡  Ú_imager‰  r,   rx  Ú_sandbox_tokenr…  ÚliveÚverifiedÚownedrY  ÚClientrr  ÚLimitsÚ_client)
rO   rj  r‡  rˆ  r‰  r,   rŠ  rt  r„  r…  s
   &$$$$$$$$$r1   r²   Ú_SandboxServer.__init__f  s{   € ð ŒØŒ
ØŒØ Œð Œ
ØŒ	Ø+Ôà ŒØˆŒ	ð ˆŒð ˆŒ
ô —|’|Ø&¨Ð6Ü˜cÓ"Ü—<’<°Ôkð
 #ô	
ˆŽr3   c                óB   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[RS[RR/# )	r*   Újobr,   rŠ  rt  r„  r…  r-   rƒ  )r   r/   r   r>   )r0   rI   s   "€r1   r2   r‹  –  sS   ø€ ÷ 
ñ 
ñ ð
ñ ð	
ñ
 ð
ñ ð
ñ ð
ñ ð
ð 
ñ
r3   c               ó®   € T ! VP                   VP                  P                  VP                  ;'       g    VP                  \        V4      VVVVVR7	      # )zIBuild a server from a freshly fetched job (reads its exposed server URL).©	rj  r‡  rˆ  r‰  r,   rŠ  rt  r„  r…  )ru   r‡  rˆ   Údocker_imageÚspace_idÚ_find_server_url)Úclsrœ  r,   rŠ  rt  r„  r…  s   &$$$$$$r1   Úfrom_jobÚ_SandboxServer.from_job•  sO   € ñ Ø—6‘6Ø—)‘)—.‘.Ø×"Ñ"×2Ð2 c§l¡lÜ% cÓ*ØØ'ØØ+Øô

ð 
	
r3   c                ó.   <€ V ^8„  d   QhRS[ R,          /# ©r*   r-   Nr.   )r0   rI   s   "€r1   r2   r‹  ®  s   ø€ ÷ ñ ‘s˜T•zñ r3   c                ó   € V P                   # r¯   )r’  rN   s   &r1   rˆ  Ú_SandboxServer.image­  s   € à�{‰{Ðr3   c                ó:   <€ V ^8„  d   QhRS[ RS[R,          RS[ /# )r*   ÚkwargsrŠ  Nr-   ©rT  r/   )r0   rI   s   "€r1   r2   r‹  ±  s&   ø€ ÷ 
ñ 
¡$ð 
±s¸Tµzð 
Ádñ 
r3   c                óD   € Ve   / VP                  R/ 4      CRV/CVR&   V# )a  Override `X-Sandbox-Token` for one request.

The client-level header carries the *host* credential, which manages the
pool. A pooled sandbox's own operations should present that sandbox's
capability token instead, so nothing wider than the sandbox is offered on
a per-sandbox call.
r~  r�  )ry   )rO   rª  rŠ  s   &&&r1   Ú_with_tokenÚ_SandboxServer._with_token±  s2   € ð Ò$Ø _ 6§:¡:¨i¸Ó#<Ð _Ð>OÐQ^Ñ _ˆF�9ÑØˆr3   rŠ  Nc                óT   <€ V ^8„  d   QhRS[ RS[ RS[ R,          RS[P                  /# ©r*   Úmethodr‰   rŠ  Nr-   ©r/   rY  rZ  )r0   rI   s   "€r1   r2   r‹  ½  s4   ø€ ÷ ñ ™cð ©ð ÁÀdÅ
ð Ñ`e×`nÑ`nñ r3   c               ó  € VP                  R\        P                  ! RRR7      4      pV P                  WC4      pV P                  P
                  ! WP                  V,           3RV/VB pVP                  R8¼  d   \        V4       V# )z@Request to the in-job server. Raises SandboxError on API errors.Útimeoutg      N@ç      $@©Úconnecté�  )	ÚpoprY  ÚTimeoutr­  r™  r  r‰  rB  rh  ©rO   r±  r‰   rŠ  rª  r´  rz   s   &&&$,  r1   r  Ú_SandboxServer.request½  sp   € à—*‘*˜Y¬¯ª°dÀDÔ(IÓJˆØ×!Ñ! &Ó8ˆØ—<‘<×'Ò'¨·±ÀÕ0DÑ`ÈgÐ`ÐY_Ñ`ˆØ×Ñ 3Ô&Ü˜hÔ'Øˆr3   c          	      ód   <€ V ^8„  d   QhRS[ RS[ RS[ R,          RS[S[P                  ,          /# r°  ©r/   r   rY  rZ  )r0   rI   s   "€r1   r2   r‹  Ç  s:   ø€ ÷ 	ñ 	Ùð	Ù!$ð	Ù8;¸d½
ð	á	‘%—.‘.Õ	!ñ	r3   c             +  ój  "  € VP                  R\        P                  ! RRR7      4      pV P                  WC4      pV P                  P
                  ! WP                  V,           3RV/VB ;_uu_ 4       pVP                  R8¼  d   \        V4       Vx € RRR4       R#   + '       g   i     R# ; i5i)zJStreaming request to the in-job server. Raises SandboxError on API errors.r´  g     €Q@rµ  r¶  r¸  N)	r¹  rY  rº  r­  r™  Ústreamr‰  rB  rh  r»  s   &&&$,  r1   rÀ  Ú_SandboxServer.streamÆ  sˆ   é € ð
 —*‘*˜Y¬¯ª°dÀDÔ(IÓJˆØ×!Ñ! &Ó8ˆØ�\‰\× Ò  ¯©¸Õ)=ÑYÀwÐYÐRX×YÒYÐ]eØ×#Ñ# sÔ*Ü! (Ô+ØŠN÷ Z×Y×YÒYüs   ‚A2B3Á4!BÂ
B3ÂB0	Â*	B3c                ó4   <€ V ^8„  d   QhRS[ RS[ R,          /# )r*   Úlocal_idr-   Nr.   )r0   rI   s   "€r1   r2   r‹  Ò  s   ø€ ÷ ñ ¡cð ©c°D­jñ r3   c                ó°   €  V P                  RRV R24      P                  4       R,          #   \         d   pTP                  R8X  d    Rp?R# h Rp?ii ; i)a)  Recover a pooled sandbox's capability token, using the host credential.

Keeps reconnection stateless: `Sandbox.connect` can reattach to a sandbox
it never created. Returns `None` when the host runs a server that predates
per-sandbox tokens, in which case the caller falls back to the host token.
râ   ú/v1/sandboxes/z/tokenÚtokenrA  N)r  rx   r   rB  )rO   rÃ  rC  s   && r1   rŠ  Ú_SandboxServer.sandbox_tokenÒ  sR   € ð	Ø—<‘< ¨¸°zÀÐ'HÓI×NÑNÓPÐQXÕYÐYøÜô 	Ø�}‰} Ô#ÝØûð	ús   ‚*- ­A¸AÁAÁAc                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r‹  à  s   ø€ ÷ ñ �tñ r3   c                ó:   € V P                   P                  4        R # r¯   )r™  ÚcloserN   s   &r1   rÊ  Ú_SandboxServer.closeà  s   € Ø�‰×ÑÖr3   c                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r‹  ã  s   ø€ ÷ Gñ G˜Dñ Gr3   c                óh   € V P                   P                  V P                  V P                  R 7       R# )©rj  r&   N)rx  Ú
cancel_jobrj  r‡  rN   s   &r1   rÏ  Ú_SandboxServer.cancel_jobã  s!   € Ø�	‰	×Ñ D§K¡K¸4¿:¹:ÐÖFr3   c                ó$   <€ V ^8„  d   QhRS[ RR/# )r*   Ústart_timeoutr-   N)r?   )r0   rI   s   "€r1   r2   r‹  æ  s   ø€ ÷ kñ k©ð k°$ñ kr3   c           
     óæ  € \         P                   ! 4       V,           pRp\         P                   ! 4       V8  Ed�    V P                  P                  V P                  R,           \        P
                  ! R4      R7      pVP                  ^È8X  d   \        W@P                  4       R#  \         P                   ! 4       V,
          R8”  dÛ   \         P                   ! 4       pV P                  P                  V P                  V P                  R7      pVP                  P                  \        9   dv   \!        V P                  V P                  V P                  R7      p\#        R	V P                   R
VP                  P                   RVP                  P$                   RV 24      h\         P&                  ! R4       EK›  \#        R	V P                   RVR R24      h  \        P                   d     ELIi ; i)zMPoll /health until the server answers; fail fast (with logs) if the job dies.g        z/healthg      @©r´  Ng       @rÎ  ©r&   rm  z$ terminated during startup (status: z, message: ú).g333333Ã?z did not become ready within z.0fzs.)Útimer™  ry   r‰  rY  rº  rB  rp  rj  ÚRequestErrorrx  Úinspect_jobr‡  ÚstatusÚstageÚ_TERMINAL_STAGESÚ_tail_job_logsr   rg  Úsleep)rO   rÒ  ÚdeadlineÚlast_job_checkrz   rœ  Úlogss   &&     r1   Ú
wait_readyÚ_SandboxServer.wait_readyæ  s€  € ä—9’9“; Õ.ˆØˆÜ�iŠi‹k˜HÕ$ðØŸ<™<×+Ñ+¨D¯M©M¸IÕ,EÌuÏ}Ê}Ð]`ÓOaÐ+Ób�Ø×'Ñ'¨3Ô.Ü*¨8·[±[ÔAÙð /ô
 �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×Ü˜\¨$¯+©+¨Ð6SÐTaÐbeÐSfÐfhÐiÓjÐjøô ×%Ñ%ô Úðús   »A(G ÇG0Ç/G0)rx  r™  r’  r“  r‰  r…  rj  r”  r,   r–  r‡  r•  )rb   rc   rd   re   rf   r²   Úclassmethodr£  rg   rˆ  r­  r  r   rÀ  rŠ  rÊ  rÏ  râ  ri   rj   rk   s   @r1   rƒ  rƒ  ^  sÒ   ø‡ € ñð-
ð  "ð-
ð ÷-
ò -
ð^ ð
ð  "ð
ð ÷
ñ 
ó ð
ð. ÷ó ð÷
ð 
ðÈT÷ ò ð ð	ØEI÷	ñ 	ó ð	÷ð ÷ð ÷Gð G÷kö kr3   rƒ  c                   ón   a € ] tR tRt o Rt]V 3R lR l4       t]V 3R lR l4       tV 3R lR ltR	tV tR
# )Ú_KillMethodiÿ  z>Lets `kill` work both as a classmethod and an instance method.c                ó8   <€ V ^8„  d   QhRRRS[ RS[R,          /# )r*   ÚinstanceNr‡  r-   ©.N©rŠ   r   )r0   rI   s   "€r1   r2   Ú_KillMethod.__annotate__  s   ø€ ×NÑN ÐN©TÐN±h¸yÕ6IÑNr3   c                ó   € R # r¯   ra   ©rO   rè  r‡  s   &&&r1   Ú__get__Ú_KillMethod.__get__  s   € ÙKNr3   c                ó<   <€ V ^8„  d   QhRRRS[ RS[. R3,          /# )r*   rè  r€   r‡  r-   Nrê  )r0   rI   s   "€r1   r2   rë    s!   ø€ ×RÑR 	ÐR±$ÐR¹8ÀBÈÀHÕ;MÑRr3   c                ó   € R # r¯   ra   rí  s   &&&r1   rî  rï    s   € ÙORr3   c                ó8   <€ V ^8„  d   QhRRRS[ RS[R,          /# )r*   rè  úSandbox | Noner‡  r-   ré  rê  )r0   rI   s   "€r1   r2   rë    s(   ø€ ÷ ñ Ð 0ð ¹ð Á(È9ÕBUñ r3   c                óF   a€ Ve   VP                   # RR RR /R V3R lllpV# )Nr&   rÆ  c                ó\   € V ^8„  d   QhR\         R\         R,          R\         R,          RR/# )r*   Ú
sandbox_idr&   NrÆ  r-   r.   )r0   s   "r1   r2   Ú)_KillMethod.__get__.<locals>.__annotate__
  s8   € ÷ 	Oñ 	OœSð 	O´°dµ
ð 	OÌ#ÐPTÍ*ð 	OÐ`dñ 	Or3   c                óJ   <€ SP                  WVR 7      P                  4        R# ))r&   rÆ  N)r·  r{   )rö  r&   rÆ  r‡  s   &$$€r1   r{   Ú!_KillMethod.__get__.<locals>.kill
  s   ø€ Ø�M‰M˜*ÀˆMÓG×LÑLÖNr3   )Ú_kill)rO   rè  r‡  r{   s   &&f r1   rî  rï    s7   ø€ ØÒØ—>‘>Ð!ð	O¸Tð 	OÐW[÷ 	Oò 	Oð ˆr3   ra   N)	rb   rc   rd   re   rf   r   rî  ri   rj   rk   s   @r1   ræ  ræ  ÿ  s.   ø‡ € ÙHàßNó ØNØßRó ØR÷ö r3   ræ  c                   ó€  a € ] tR tRt o RtRR/V 3R lR llt]]3RRR	]R
RRRRRRRRRRRRRRR/
V 3R lR lll4       t	]RRRR/V 3R lR ll4       t
]! 4       tV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR lt]R R!R
R!R"R!R#R!R$R!R%R!R&R!R'R!R(R!R)R!/
V 3R* lR+ ll4       t]R R!R
R!R"R!/V 3R, lR- ll4       tR RR
RR"RR#RR$RR%RR&RR'R.R(R.R)R/
V 3R/ lR0 lltV 3R1 lR2 lt]V 3R3 lR4 l4       t]V 3R5 lR6 l4       tRDR7R8/V 3R9 lR: lllt]V 3R; lR< l4       tV 3R= lR> ltV 3R? lR@ lt]V 3RA lRB l4       tRCtV tR# )Er€   i  a)  An isolated cloud machine running on Hugging Face Jobs.

> [!NOTE]
> The Sandbox API is experimental. Its API and behavior may change without notice.

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Š  Nc                ó^   <€ V ^8„  d   QhRS[ RS[RS[ R,          RS[RS[RS[ R,          RR/# )	r*   ru   ÚserverrÃ  NÚowns_sandboxÚowns_serverrŠ  r-   )r/   rƒ  rH   )r0   rI   s   "€r1   r2   ÚSandbox.__annotate__   s[   ø€ ÷ !(ñ !(ñ ð!(ñ ð	!(ñ
 ˜•*ð!(ñ ð!(ñ ð!(ñ ˜T•zð!(ð 
ñ!(r3   c               óª   € Wn         W n        W`n        W0n        Vf   RMRV 2V n        W@n        WPn        R V n        RV n        \        V 4      V n
        R # )Nz/v1rÅ  F)ru   Ú_serverr“  Ú	_local_idÚ
_base_pathÚ_owns_sandboxÚ_owns_serverÚ_on_killÚ_killedrª   Úfiles)rO   ru   rý  rÃ  rþ  rÿ  rŠ  s   &$$$$$$r1   r²   ÚSandbox.__init__   s\   € ð ŒØŒð ,Ôà!Œð $,Ò#3™%¸>È(ÈÐ9TˆŒð *Ôð (Ôà<@ˆŒØˆŒÜ! $Ó'ˆŽ
r3   Úflavorú	cpu-basicÚidle_timeoutÚenvÚsecretsÚvolumesr&   Úforward_hf_tokenFÚlabelsrÒ  ç      ^@rÆ  c                ó4  <€ V ^8„  d   QhRS[ RS[ RS[S[,          S[ ,          R,          RS[S[ S[3,          R,          RS[S[ S[3,          R,          RS[S[,          R,          RS[ R,          R	S[R
S[S[ S[ 3,          R,          RS[RS[ R,          RR/# )r*   rˆ  r  r  Nr  r  r  r&   r  r  rÒ  rÆ  r-   r€   )r/   r>   r?   rT  r	   r   r   rH   )r0   rI   s   "€r1   r2   r   F  så   ø€ ÷ rañ raáðrañ ð	rañ
 ™E•k¡CÕ'¨$Õ.ðrañ ‘#‘s�(�^˜dÕ"ðrañ ‘c™3�h• $Õ&ðrañ ‘f• Õ$ðrañ ˜•:ðrañ ðrañ ‘S™#�X• Õ%ðrañ ðrañ �T�zðrað 
ñrar3   c       
        óX  € V	e¢   \        V	\        4      '       g"   \        R\        V	4      P                   24      hV	P                  4        FV  w  rÍ\        V\        4      '       d   \        V\        4      '       g   \        R4      hV\        9   g   KI  \        RV R24      h	  \        VR7      p\        V4      p\        ^4      p\        VV4      p\        VVVVVVVVR7      w  ppppTP                  TTTTT\        / T	;'       g    / C\        R\         \"        \$        V/CT;'       g    R\&        .VR	7
      pRp \(        P+                  VVVV\,        P.                  ^,           R
7      pVP1                  V
4       T ! TP6                  TRRRR7      #   \2         d‡     TP5                  TP6                  TP8                  P:                  R7       M=  \2         d0   p\<        P?                  RTP6                   RT 24        Rp?MRp?ii ; iTe   TPA                  4        h i ; i)u³  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. Note that a
        *foreground* command is not currently counted as activity, so a single
        `run()` that takes longer than this without other API traffic can have its
        sandbox shut down under it â€” raise the timeout (or pass `None`) for long
        single commands.
    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).
    labels (`dict[str, str]`, *optional*):
        Labels to attach to the underlying HF Job.
    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).
Nz'`labels` must be a dict[str, str], got z(`labels` keys and values must be stringszLabel 'zB' is reserved by huggingface_hub Sandbox and cannot be overridden.©rÆ  ©r  r  r  r  r  rŠ  rI  ©
rˆ  Úcommandr  r  r  r´  r  r  Úexposer&   ©rœ  r,   rŠ  rt  r„  rÎ  zFailed to cancel sandbox job ú after startup failure: T©ru   rý  rÃ  rþ  rÿ  )!rA   rT  rV  rŠ   rb   r÷   r/   ÚRESERVED_SANDBOX_LABELSr   r}  r   r;   Ú_bootstrap_job_specÚrun_jobÚSANDBOX_MAX_LIFETIMEÚSANDBOX_LABELÚ
MODE_LABELÚMODE_DEDICATEDÚNONCE_LABELÚSANDBOX_SERVER_PORTrƒ  r£  rª   rú   râ  re  rÏ  ru   r‡  rˆ   ÚloggerÚwarningrÊ  )r¢  rˆ  r  r  r  r  r  r&   r  r  rÒ  rÆ  ÚkeyÚvaluert  r+   r,   rŠ  r  Újob_envÚjob_secretsÚjob_volumesrœ  rý  rC  s   &&$$$$$$$$$$             r1   ÚcreateÚSandbox.createE  s  € ðt ÒÜ˜f¤d×+Ò+Ü Ð#JÌ4ÐPVË<×K`ÑK`ÐJaÐ!bÓcÐcØ$Ÿl™lžn‘
�Ü! #¤s×+Ò+´:¸eÄS×3IÒ3IÜ$Ð%OÓPÐPØÔ1Ö1Ü$ w¨s¨eÐ3uÐ%vÓwÐwñ	 -ô ˜%Ô ˆÜ# CÓ(ˆÜ˜"“ˆÜ-¨h¸Ó>ˆä5HØØØØØØ%Ø-Ø'ô	6
Ñ2ˆ�˜+ {ð �k‰kØØØØØÜ(Øi�v—|�| Ði¤m°S¼*ÄnÔVaÐchÑiØ×'Ð' 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úàÒ!Ø—‘”Øð		ús7   ÅA F ÆH)Æ$1GÇH)ÇHÇ!%HÈH)ÈHÈH)c                óL   <€ V ^8„  d   QhRS[ RS[ R,          RS[ R,          RR/# )r*   rö  r&   NrÆ  r-   r€   r.   )r0   rI   s   "€r1   r2   r   »  s9   ø€ ÷ .bñ .b¡ð .b±C¸$µJð .bÉcÐTXÍjð .bÐdmñ .br3   c          	     ó:  € \        VR7      p\        W4      w  r\        V9   d“   VP                  \        ^4      w  rV\	        WEVR7      p VP                  RR4      P                  4        Uu0 uF  qˆR,          kK  	  p	pWi9  d   \        RV RV R24      hVP                  V4      p
T ! TTTR	R
T
R7      # VP                  WR7      pVP                  ;'       g    / pVP                  \        4      pVP                  \        4      R8w  g   Vf   \        RV R\         R24      hVP                  \         4      \"        8X  d   \        RV R\         R24      hVP$                  P&                  R8w  d'   \        RV RVP$                  P&                   R24      h\)        \+        V4      V4      p
\,        P/                  VVV
V\0        P2                  ^,           R7      pV ! VP4                  VRR	R
R7      # u upi   \         d    TP                  4        h i ; i)z?Reattach to a running sandbox from anywhere, using only its id.r  rÕ  râ   ú/v1/sandboxesru   zSandbox z no longer exists on host r(   FT©ru   rý  rÃ  rþ  rÿ  rŠ  rÎ  rI  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  rx   r   rŠ  re  rÊ  rÙ  r  ry   r%  r"  r#  Ú	MODE_POOLrÚ  rÛ  r;   r}  rƒ  r£  rª   rú   ru   )r¢  rö  r&   rÆ  rt  Úhost_job_idrÃ  rý  ÚitemÚexistingrŠ  rœ  r  r,   s   &&$$          r1   r·  ÚSandbox.connectº  s!  € ô ˜%Ô ˆÜ 1°*Ó HÑˆ
Ü˜JÔ&Ø$.×$4Ñ$4´]ÀAÓ$FÑ!ˆKÜ" 3¸yÔIˆFð	Ø39·>±>À%ÈÓ3Y×3^Ñ3^Ô3`ÓaÑ3`¨4 ŸJ˜JÑ3`�ÐaØÔ+Ü&¨°*°Ð=WÐXcÐWdÐdeÐ'fÓgÐgð !'× 4Ñ 4°XÓ >�ñ ØØØ!Ø"Ø Ø+ôð ð �o‰o Zˆ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ùòM bøô ô Ø—‘”Øðús   Á"G= Á-G8Á>+G= Ç8G= Ç=Hc                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r   ï  s   ø€ ÷ !ñ !�tñ !r3   c                ó  € V P                   '       d   R#  V P                  f   V P                  P                  4        M6V P                  P	                  RRV P                   2V P
                  R7        RV n         V P                  e   V P                  V 4       V P                  '       d   V P                  P                  4        R# R#   \         d1   p\        P                  RT P                   RT 24        Rp?R# Rp?ii ; i)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.
Nrs   rÅ  ©rŠ  zFailed to kill sandbox ú: T)r  r  r  rÏ  r  r“  re  r'  r(  ru   r  r  rÊ  ©rO   rC  s   & r1   rú  ÚSandbox._killï  sÎ   € ð �<�<ˆ<Ùð	Ø�~‰~Ò%Ø—‘×'Ñ'Õ)à—‘×$Ñ$ X°ÀÇÁÐ?OÐ/PÐ`d×`sÑ`sÐ$Õtð
 ˆŒØ�=‰=Ò$Ø�M‰M˜$ÔØ××ÐØ�L‰L×ÑÖ ñ øô ô 	ä�N‰NÐ4°T·W±W°I¸RÀ¸sÐCÔDÝûð	ús   –(C ¿5C ÃDÃ%DÄDc                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r     s   ø€ ÷ !ñ !�tñ !r3   c                ób   € V P                   '       d   V P                  P                  4        R# R# )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)r  r  rÊ  rN   s   &r1   rÊ  ÚSandbox.close  s%   € ð
 ××ÐØ�L‰L×ÑÖ ñ r3   c                ó   <€ V ^8„  d   QhRR/# )r*   r-   r€   ra   )r0   rI   s   "€r1   r2   r     s   ø€ ÷ ñ ˜9ñ r3   c                ó   € V # r¯   ra   rN   s   &r1   Ú	__enter__ÚSandbox.__enter__  ó   € Øˆr3   c                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r     s   ø€ ÷ ñ  Tñ r3   c                ón   € V P                   '       d   V P                  4        R # V P                  4        R # r¯   )r  r{   rÊ  ©rO   Úexc_infos   &*r1   Ú__exit__ÚSandbox.__exit__  s    € Ø××ÐØ�I‰IŽKà�J‰JŽLr3   rS  .Úcwdr´  ÚstdinÚ	on_stdoutÚ	on_stderrÚcheckÚcapture_outputÚ
backgroundc                ó4  <€ V ^8„  d   QhRS[ S[S[ ,          ,          RS[R,          RS[S[ S[3,          R,          RS[ R,          RS[R,          RS[ R,          RS[S[ .R3,          R,          R	S[S[ .R3,          R,          R
S[RS[RS[R,          RS[/# )r*   r   rS  Nr  rT  r´  rU  rV  rW  rX  rY  rZ  Fr-   )	r/   r   rH   rT  r	   r?   r   r   rD   )r0   rI   s   "€r1   r2   r     sÌ   ø€ ÷ #ñ #á‘4™•9�_ð#ñ �d�{ð	#ñ
 ‘#‘s�(�^˜dÕ"ð#ñ �4�Zð#ñ ˜•ð#ñ �T�zð#ñ ™S˜E 4˜KÕ(¨4Õ/ð#ñ ™S˜E 4˜KÕ(¨4Õ/ð#ñ ð#ñ ð#ñ ˜E•Nð#ñ 
ñ#r3   c       
        ó   € R # r¯   ra   )rO   r   rS  r  rT  r´  rU  rV  rW  rX  rY  rZ  s   &&$$$$$$$$$$r1   ÚrunÚSandbox.run  s   € ñ  #r3   c                ó¬   <€ V ^8„  d   QhRS[ S[S[ ,          ,          RS[R,          RS[S[ S[3,          R,          RS[ R,          RS[R,          RS[/# )	r*   r   rS  Nr  rT  rZ  Tr-   )r/   r   rH   rT  r	   r   rm   )r0   rI   s   "€r1   r2   r   +  sh   ø€ ÷ ñ á‘4™•9�_ðñ �d�{ð	ñ
 ‘#‘s�(�^˜dÕ"ðñ �4�Zðñ ˜D•Mðñ 
ñr3   c               ó   € R # r¯   ra   )rO   r   rS  r  rT  rZ  s   &&$$$$r1   r]  r^  *  s   € ñ r3   Tc                ó6  <€ V ^8„  d   QhRS[ S[S[ ,          ,          RS[R,          RS[S[ S[3,          R,          RS[ R,          RS[R,          RS[ R,          RS[S[ .R3,          R,          R	S[S[ .R3,          R,          R
S[RS[RS[RS[S[,          /# )r*   r   rS  Nr  rT  r´  rU  rV  rW  rX  rY  rZ  r-   )	r/   r   rH   rT  r	   r?   r   rD   rm   )r0   rI   s   "€r1   r2   r   5  sÛ   ø€ ÷ }ñ }á‘4™•9�_ð}ñ �d�{ð	}ñ
 ‘#‘s�(�^˜dÕ"ð}ñ �4�Zð}ñ ˜•ð}ñ �T�zð}ñ ™S˜E 4˜KÕ(¨4Õ/ð}ñ ™S˜E 4˜KÕ(¨4Õ/ð}ñ ð}ñ ð}ñ ð}ñ 
¡Õ	.ñ}r3   c       
        ó2  a
a€ \        W4      pV'       d   W<R&   V'       d   WLR&   V'       dX   V P                  RRVR7      P                  4       p\        VP	                  R4      VR,          VVP	                  R4      V R	7      # Ve   W\R&   Ve   WlR&   . p. p^ oR
pR V
V3R llpV P                  RRVR7      ;_uu_ 4       p\        V4       Fâ  pVR,          R8X  d(   V! VVR,          4       Ve   V! VR,          4       K6  K8  VR,          R8X  d(   V! VVR,          4       Ve   V! VR,          4       Kk  Km  VR,          R8X  g   K}  \        VR,          RP                  V4      RP                  V4      VP	                  R4      VP	                  RR4      VP	                  R^ 4      R7      p M	  R
R
R
4       Vf   \        R4      hV	'       d1   VP                  ^ 8w  g   VP                  '       d   \        VVR7      hV#   + '       g   i     LY; i)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.
    capture_output (`bool`, *optional*, defaults to `True`):
        If True, accumulate stdout/stderr into the returned result. Pass `False`
        when you only want `on_stdout`/`on_stderr`: output is then handed to the
        callbacks and dropped, so a command producing gigabytes does not have to fit
        in memory. `result.stdout`/`result.stderr` are empty in that case.
    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`.
r  rT  rO  ú
/processes©rx   ru   r~   r�   )ru   r~   r   r�   rv   Nr´  rU  c                óJ   € V ^8„  d   QhR\         \        ,          R\        RR/# )r*   ÚpartsrÌ   r-   N©rû   r/   )r0   s   "r1   r2   Ú!Sandbox.run.<locals>.__annotate__Œ  s%   € ÷ 	ñ 	œœS�	ð 	¬ð 	°ñ 	r3   c                 ó¾   <€ S'       g   R # S\        V4      ,           \        8”  d   \        R\         R24      hS\        V4      ,          oV P                  V4       R # )Nzcommand produced more than z  characters of output. Pass `capture_output=False` with `on_stdout`/`on_stderr` to stream it instead, or redirect it to a file in the sandbox and download that.)rW   ÚMAX_CAPTURED_OUTPUT_CHARSr   Úappend)rf  rÌ   rY  Úcaptureds   &&€€r1   ÚkeepÚSandbox.run.<locals>.keepŒ  sZ   ø€ ç!ÙØœ#˜d›)Õ#Ô&?Ô?Ü"Ø1Ô2KÐ1Lð MQð Qóð ð
 œ˜D›	Õ!ˆHØ�L‰L˜Ör3   z/execr\  rX   rÌ   r^   ÚexitrM   r†   r_   r`   FrY   )rM   rX   r^   r_   r`   rY   z%connection lost while running command)r   Úresult)rW  rw   rx   rm   ry   ré   ra  rD   Újoinr   rM   r`   r   )rO   r   rS  r  rT  r´  rU  rV  rW  rX  rY  rZ  r9  rÌ   Ústdout_partsÚstderr_partsrp  rm  rz   r\  rl  s   &&$$$$$$$$d$        @r1   r]  r^  5  sï  ù€ ôt   Ó+ˆßØ �E‰NßØ �E‰NßØ—=‘= ¨¸G�=ÓD×IÑIÓKˆDÜ!ð —8‘8˜D“>Ø˜•KØØ—H‘H˜U“OØôð ð ÒØ!(�IÑØÒØ$�GÑð
 #%ˆØ"$ˆØˆØ.2ˆ÷	ñ 	ð �\‰\˜& '°ˆ\×8Ô8¸HÜ% hÖ/�Ø˜•> XÔ-Ù˜ u¨V¥}Ô5Ø Ò,Ù! %¨¥-Ö0ñ -à˜7•^ xÔ/Ù˜ u¨V¥}Ô5Ø Ò,Ù! %¨¥-Ö0ñ -à˜7•^ vÖ-Ü1Ø"'¨Õ"4Ø!Ÿw™w |Ó4Ø!Ÿw™w |Ó4Ø$Ÿy™y¨Ó2Ø"'§)¡)¨K¸Ó"?Ø$)§I¡I¨m¸QÓ$?ô�Fñ ñ' 0÷ 9ð* Š>ÜÐFÓGÐGß�f×&Ñ&¨!Ô+¨v×/?×/?Ð/?Ü%¨#°fÔ=Ð=Øˆ÷3 9×8ús   ÃBHÅA)HÈH	c                ó0   <€ V ^8„  d   QhRS[ S[,          /# rF   )r   rm   )r0   rI   s   "€r1   r2   r   ´  s   ø€ ÷ 
ñ 
™4¡Õ/ñ 
r3   c                ó4  € V P                  RR4      P                  4       pV Uu. uFg  p\        VP                  R4      VR,          VR,          VP                  R4      VP                  R4      VR,          VP                  R	4      V R
7      NKi  	  up# u upi )as  List the background processes of this sandbox.

Returns the processes started with [`Sandbox.run`]`(..., background=True)`; stop one
with [`SandboxProcess.kill`]. Recently completed processes stay listed (with
`running=False` and their `exit_code`); the server keeps a bounded number of them, so a
sandbox that has run thousands of short commands will not list them all.
râ   rc  ru   r~   r   r�   r‚   rƒ   rM   )ru   r~   r   r�   r‚   rƒ   rM   rv   )rw   rx   rm   ry   )rO   rÌ   Úps   &  r1   Ú	processesÚSandbox.processes´  s“   € ð �}‰}˜U LÓ1×6Ñ6Ó8ˆñ ó
ñ �ô Ø—5‘5˜“;Ø�e•HØ�e•HØ—E‘E˜%“LØŸe™e OÓ4Ø˜)�ØŸ%™% Ó,Ø÷	ñ ñ
ð 	
ùò 
s   ¥A-Bc                ó.   <€ V ^8„  d   QhRS[ R,          /# r¦  r.   )r0   rI   s   "€r1   r2   r   Î  s   ø€ ÷ "ñ "‘s˜T•zñ "r3   c                ó.   € V P                   P                  # r¯   )r  rˆ  rN   s   &r1   rˆ  ÚSandbox.imageÍ  s   € à�|‰|×!Ñ!Ð!r3   c                ó.   <€ V ^8„  d   QhRS[ R,          /# r¦  r.   )r0   rI   s   "€r1   r2   r   Ò  s   ø€ ÷ Kñ K™˜t�ñ Kr3   c                óN   € V P                   e   V P                  P                  # R# )zIFor a shared/pool sandbox, the job id of the host running it (else None).N)r  r  rj  rN   s   &r1   Úhost_idÚSandbox.host_idÑ  s"   € ð '+§n¡nÒ&@ˆt�|‰|×"Ñ"ÐJÀdÐJr3   Úschemezhttps://c                óB   <€ V ^8„  d   QhRS[ S[,          RS[RS[RS[/# )r*   Úportr‰   r€  r-   )r>   r/   )r0   rI   s   "€r1   r2   r   Ø  s4   ø€ ÷ (Nñ (N¡#©¥)ð (N±3ð (NÉð (NÑ^añ (Nr3   c               óÎ   € V P                   P                  P                  R^4      R,          pVP                  R4      '       d   TMRV,           pV V V P                   RV V 2# )aL  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://Ú/z/proxy/éÿÿÿÿ)r  r‰  r9  Ú
startswithr  )rO   r‚  r‰   r€  Úhost_and_rests   &&&$ r1   Úproxy_url_forÚSandbox.proxy_url_forØ  sa   € ðL Ÿ™×-Ñ-×3Ñ3°E¸1Ó=¸bÕAˆØ—‘ s×+Ò+‰t°°tµˆØ�˜-˜¨¯©Ð(9¸ÀÀÀtÀfÐMÐMr3   c                ó6   <€ V ^8„  d   QhRS[ S[S[3,          /# rF   r«  )r0   rI   s   "€r1   r2   r     s   ø€ ÷ 
ñ 
™t¡C© H�~ñ 
r3   c                óž   € RR\        V P                  P                  4       2RV P                  ;'       g    V P                  P                  /# )aÝ  Auth headers to send with [`proxy_url_for`] requests (HF token + sandbox token).

Read these at the moment you use them: the HF token is resolved on access,
so a long-lived handle hands out a current bearer rather than one captured
when the sandbox was created.

For a pooled sandbox this is the sandbox's own capability token, not the
pool host's: these headers typically end up in a browser or WebSocket
client, so they should confer access to this sandbox and nothing else.
r|  r{  r�  )r}  r  rx  r“  rN   s   &r1   Úproxy_headersÚSandbox.proxy_headers  sH   € ð ˜wÔ'7¸¿¹×8IÑ8IÓ'JÐ&KÐLØ˜t×2Ñ2×QÐQ°d·l±l×6QÑ6Qð
ð 	
r3   c                ó    <€ V ^8„  d   QhRS[ /# rF   r.   )r0   rI   s   "€r1   r2   r     s   ø€ ÷ @ñ @™#ñ @r3   c                ó@   € R V P                   : RV P                  : R2# )zSandbox(id=z, image=rV   )ru   rˆ  rN   s   &r1   r[   ÚSandbox.__repr__  s   € Ø˜TŸW™W™K x°·
±
©~¸QÐ?Ð?r3   c                ó@   <€ V ^8„  d   QhRS[ RS[ RS[P                  /# ©r*   r±  Úresourcer-   r²  )r0   rI   s   "€r1   r2   r     s+   ø€ ÷ uñ u™sð u©cð uÁÇÁñ ur3   c                óv   € V P                   P                  ! WP                  V,           3R V P                  /VB # rB  )r  r  r  r“  )rO   r±  r“  rª  s   &&&,r1   rw   ÚSandbox._request  s2   € Ø�|‰|×#Ò# F¯O©O¸hÕ,FÑtÐVZ×ViÑViÐtÐmsÑtÐtr3   c                óP   <€ V ^8„  d   QhRS[ RS[ RS[S[P                  ,          /# r’  r¾  )r0   rI   s   "€r1   r2   r     s+   ø€ ÷ ñ ™cð ©Sð ¹xÉÏÉÕ?Wñ r3   c              +  óÔ   "  € V P                   P                  ! WP                  V,           3R V P                  /VB ;_uu_ 4       pVx € RRR4       R#   + '       g   i     R# ; i5i)rŠ  N)r  rÀ  r  r“  )rO   r±  r“  rª  rz   s   &&&, r1   ré   ÚSandbox._stream  sZ   é € à�\‰\× Ò Ø—O‘O hÕ.ñ
Ø>B×>QÑ>Qð
ØU[÷
ò 
àØŠN÷
÷ 
÷ 
ò 
üs   ‚AA(ÁAÁ

A(ÁA%	Á	A()
r  r  r  r  r  r  r“  r  r	  ru   )r„  )rb   rc   rd   re   rf   r²   rä  ÚDEFAULT_IMAGEÚDEFAULT_IDLE_TIMEOUTr.  r·  ræ  r{   rú  rÊ  rK  rR  r   r]  rw  rg   rˆ  r~  rˆ  rŒ  r[   rw   r   ré   ri   rj   rk   s   @r1   r€   r€     sÔ  ø‡ € ñð!(ð %)÷!(ò !(ðJ ð #ñrað "ð	rað
 2Fðrað &*ðrað *.ðrað (,ðrað !%ðrað "'ðrað )-ðrað  %ðrað !÷raò raó ðraðh ð.bÀð .bÐ[_÷ .bñ .bó ð.bñd ‹=€D÷!ð !÷.!ð !÷ð ÷ð ð ð#ð !ð	#ð
 &)ð#ð ð#ð !$ð#ð  ð#ð 36ð#ð 36ð#ð ð#ð  #ð#ð &)÷#ñ #ó ð#ð  ðð !ð	ð
 &)ðð ÷ñ ó ðð}ð "ð	}ð
 &*ð}ð ð}ð !%ð}ð !ð}ð 37ð}ð 37ð}ð ð}ð  $ð}ð !÷}ò }÷~
ð 
ð2 ÷"ó ð"ð ÷Kó ðKñ(NÈz÷ (Nó (NðT ÷
ó ð
÷ @ð @÷
uð uð ÷ó ör3   r€   c                   óª  a € ] tR tRt o Rt]3RRR]R^RRR	RR
]RRRRR]RRRR/V 3R lR lllt	]
RRR]RR/V 3R lR ll4       tRNV 3R lR lltRRR
]RR/V 3R lR lltV 3R lR lt]V 3R lR l4       t]V 3R  lR! l4       t]V 3R" lR# l4       tV 3R$ lR% ltV 3R& lR' ltV 3R( lR) ltV 3R* lR+ ltV 3R, lR- ltV 3R. lR/ ltV 3R0 lR1 ltV 3R2 lR3 ltV 3R4 lR5 ltV 3R6 lR7 ltV 3R8 lR9 ltV 3R: lR; ltR<R/V 3R= lR> lltV 3R? lR@ lt V 3RA lRB lt!V 3RC lRD lt"V 3RE lRF lt#V 3RG lRH lt$V 3RI lRJ lt%ROV 3RK lRL llt&RMt'V t(R# )PÚSandboxPooli#  uÿ  A fleet of shared "host" jobs, each packing many landlock-isolated sandboxes.

> [!WARNING]
> The Sandbox API is experimental. Its API and behavior may change without notice.
>
> **Pooled sandboxes are for workloads inside one trust boundary.** A pooled sandbox is a uid plus a Landlock
> ruleset inside a shared VM â€” not a VM of its own â€” and every sandbox on a host shares that host's auth token
> and its privileged control plane. Use a pool to fan out *your own* code cheaply. For mutually distrusting
> workloads, use [`Sandbox.create`], which gives each one its own VM. The specific gaps are listed under
> "Known limitations" in the sandbox conceptual guide.

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
```
r  r  Úsandboxes_per_hostÚwarm_upÚ	max_hostsNrˆ   r  r&   rÒ  r  Úadopt_hostsrÆ  Ú_connect_modeFc                óÌ   <€ V ^8„  d   QhRS[ RS[ RS[RS[RS[R,          RS[ R,          RS[S[,          S[ ,          R,          R	S[ R,          R
S[RS[ RS[ R,          RS[RR/# )r*   rˆ  r  r�  rž  rŸ  Nrˆ   r  r&   rÒ  r   rÆ  r¡  r-   )r/   r>   r?   rH   )r0   rI   s   "€r1   r2   ÚSandboxPool.__annotate__P  sº   ø€ ÷ D%ñ D%áðD%ñ ð	D%ñ
  ðD%ñ ðD%ñ ˜•:ðD%ñ �D�jðD%ñ ™E•k¡CÕ'¨$Õ.ðD%ñ ˜•:ðD%ñ ðD%ñ ðD%ñ �T�zðD%ñ ðD%ð 
ñD%r3   c               óp  € V
\         \        \        39  d)   \        R\         : R\        : R\        : RV
: R2	4      hV^8  d   \        R4      hV^8  d   \        R4      h\	        VR7      V n        Wn        W n        W0n        W@n	        WPn
        Ve   TMR	\        ^4       2V n        Wpn        W€n        \        V P
                  V4      V n        W�n        W n        RV n        R
V n        . V n        \*        P,                  ! 4       V n        \*        P,                  ! 4       V n        \*        P,                  ! 4       V n        R
V n        R
V n        WÀn        V'       * V n        ^ V n        \*        P>                  ! V P.                  4      V n         \C        4       V n"        V'       g   V PG                  4        R# R# )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. The cap is enforced
        per-process against the hosts this handle knows about, so two processes
        using the same pool concurrently can exceed it. (Per-host density,
        `sandboxes_per_host`, *is* enforced by the host itself.)
    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.
    adopt_hosts (`str`, *optional*, defaults to `"own"`):
        Which already-running hosts `create()` may pack onto. Hosts are found by
        filtering Jobs on labels, and labels are set by whoever creates the Job â€” so a
        label match is a claim, not proof. This decides how much more than the claim is
        required:

        - `"own"` (default): only Jobs this principal started, per the Jobs API's
          `initiator`. Safe in a shared namespace.
        - `"namespace"`: any Job in the namespace carrying the pool's labels, provided
          its image, flavor, command and exposed URL all match. Restores cross-user
          host sharing; only use it in a namespace whose members you trust, since any
          of them can publish a Job your client will then send a token to.
        - `"never"`: no adoption at all â€” this handle only uses hosts it booted itself.
    token (`str`, *optional*):
        HF token override.
zadopt_hosts must be one of z, z; got r(   z sandboxes_per_host must be >= 1.zwarm_up must be >= 1.r  Nzpool-F)$Ú	ADOPT_OWNÚADOPT_NAMESPACEÚADOPT_NEVERrV  r   rx  rˆ  r  r�  Ú_warm_uprŸ  r   rˆ   Ú_idle_timeoutÚ
_namespaceÚ_cache_contextÚ_start_timeoutÚ_adopt_hostsÚ
_principalÚ_principal_resolvedÚ_hostsr'  r(  Ú_lockÚ_warmup_lockÚ
_boot_lockÚ_closedÚ
_warmed_upÚ_require_live_hostÚ_owns_hostsÚ
_in_flightÚ	ConditionÚ_drainedÚsetÚ_dead_host_idsÚ_ensure_warmed_up)rO   rˆ  r  r�  rž  rŸ  rˆ   r  r&   rÒ  r   rÆ  r¡  s   &&$$$$$$$$$$$r1   r²   ÚSandboxPool.__init__P  sƒ  € ðN œy¬/¼;ÐGÔGÜØ-¬i©]¸"¼_Ñ<OÈrÔR]ÑQ`Ð`fÐgrÑfuÐuvÐwóð ð  Ô!ÜÐ?Ó@Ð@Ø�QŒ;ÜÐ4Ó5Ð5Ü Ô&ˆŒ	ØŒ
ØŒØ"4ÔØŒØ"ŒØ Ò,‘D°E¼)ÀA»,¸Ð2HˆŒ	Ø)ÔØ#Œô -¨T¯Y©Y¸	ÓBˆÔØ+ÔØ'Ôð '+ˆŒØ#(ˆÔ Ø,.ˆŒÜ—^’^Ó%ˆŒ
ô &ŸNšNÓ,ˆÔô
 $Ÿ.š.Ó*ˆŒØˆŒàˆŒð #0Ôð  -Ô,ˆÔð ˆŒÜ!×+Ò+¨D¯J©JÓ7ˆŒä(+«ˆÔ÷
 Ø×"Ñ"Ö$ñ r3   c          
      óR   <€ V ^8„  d   QhRS[ RS[ R,          RS[ RS[ R,          RR/# )r*   Úpool_idr&   Nr   rÆ  r-   rœ  r.   )r0   rI   s   "€r1   r2   r£  Ù  sL   ø€ ÷ C
ñ C
áðC
ñ ˜•:ð	C
ñ
 ðC
ñ �T�zðC
ð 
ñC
r3   c               ó„  € \        VR7      p\        V\        WR4      4      pVeE   V ! VP                  VP                  VP
                  VP                  VVP                  VVVRR7
      # \        WQW#R7      p\        WWVR7      pVP                  R4      p	VP                  R4      p
T ! VP                  ;'       g    VP                  ;'       g    \        VP                  e   \        VP                  4      MR	\        VP                  R
\         4      4      V
e   \        V
4      MRTV	e   \        V	4      MRVVVRR7
      # )uà  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).
    adopt_hosts (`str`, *optional*, defaults to `"own"`):
        Which hosts may be attached to. See [`SandboxPool`]. Reattaching to a pool whose
        hosts another member of the namespace started needs `"namespace"`.
    token (`str`, *optional*):
        HF token override.
r  NT)
rˆ  r  r�  rŸ  rˆ   r  r&   r   rÆ  r¡  )r&   ÚpolicyrÕ  ÚSBX_IDLE_TIMEOUTÚSBX_MAX_HOSTSr  ÚSBX_CAPACITY)r   r   r«  rˆ  r  r�  rŸ  r  Ú_find_pool_host_jobÚ	_host_envry   rŸ  r   r™  r/   r>   ÚDEFAULT_SANDBOXES_PER_HOST)r¢  rÀ  r&   r   rÆ  rt  Úcacherœ  r  Úidle_rawÚmax_hosts_raws   &&$$$      r1   r·  ÚSandboxPool.connectØ  s!  € ô< ˜%Ô ˆô   ¬¸Ó)GÓHˆØÒÙØ—k‘kØ—|‘|Ø#(×#;Ñ#;ØŸ/™/ØØ"×/Ñ/Ø#Ø'ØØ"ôð ô " #¸)ÔXˆÜ˜¨IÔ6ˆØ—7‘7Ð-Ó.ˆØŸ™ Ó0ˆÙØ×"Ñ"×CÐC c§l¡l×CÐC´mØ&)§j¡jÒ&<”3�s—z‘z”?À+Ü" 3§7¡7¨>Ô;UÓ#VÓWØ,9Ò,E”c˜-Ô(È4ØØ*2Ò*>œ˜XœÀDØØ#ØØô
ð 	
r3   c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# )r*   Ú	num_hostsr-   )r>   r   r/   )r0   rI   s   "€r1   r2   r£    s   ø€ ÷ ñ ™cð ©$©s­)ñ r3   c                ód  € V P                   '       d   \        R4      hV P                  4        V P                  ;_uu_ 4        V\	        V P
                  4      ,
          pRRR4       X^ 8”  dL   V P                  VRR7      pV P                  ;_uu_ 4        V P
                  P                  V4       RRR4       V P                  ;_uu_ 4        RV n	        RRR4       V P                  4        V P                  #   + '       g   i     L¢; i  + '       g   i     Lc; i  + '       g   i     LR; i)uZ  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.NT©Úallow_partial)r´  r   Ú_discover_hostsr±  rW   r°  Ú_provision_hostsr  r²  rµ  Ú_save_cacheÚhost_ids)rO   rÎ  Ú	shortfallÚbooteds   &&  r1   ÚwarmÚSandboxPool.warm  sÇ   € ð �<�<ˆ<ÜÐ<Ó=Ð=Ø×ÑÔØ�Z�Z‹ZØ!¤C¨¯©Ó$4Õ4ˆI÷ à�qŒ=Ø×*Ñ*¨9ÀDÐ*ÓIˆFØ——“Ø—‘×"Ñ" 6Ô*÷ à××ÓØ"ˆDŒO÷ à×ÑÔØ�}‰}Ð÷ �Zú÷ —úç×ús$   ÁC9ÂDÃDÃ9D		ÄD	ÄD/	r  r  c                ó‚   <€ V ^8„  d   QhRS[ S[S[3,          R,          RS[S[,          S[,          R,          RS[RR/# ©r*   r  Nr  r  r-   r€   ©rT  r/   r	   r>   r?   rH   )r0   rI   s   "€r1   r2   r£  9  sP   ø€ ÷ (+ñ (+ñ ‘#‘s�(�^˜dÕ"ð(+ñ ™E•k¡CÕ'¨$Õ.ð	(+ñ
 ð(+ð 
ñ(+r3   c          	     óŠ  € V P                   ;_uu_ 4        V P                  '       d   \        R4      hV ;P                  ^,          un        RRR4        V P	                  WV4      V P                   ;_uu_ 4        V ;P                  ^,          un        V P
                  P                  4        RRR4       #   + '       g   i     Ls; i  + '       g   i     # ; i  T P                   ;_uu_ 4        T ;P                  ^,          un        T P
                  P                  4        RRR4       i   + '       g   i     i ; i; i)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Ð  N)r±  r´  r   r¸  Ú_create_lockedrº  Ú
notify_all)rO   r  r  r  s   &$$$r1   r.  ÚSandboxPool.create9  s½   € ð: �Z�Z‹ZØ�|�|ˆ|Ü"Ð#@ÓAÐAð �OŠO˜qÕ �O÷ ð	+Ø×&Ñ& sÐ:JÓKà——“Ø—’ 1Õ$•Ø—‘×(Ñ(Ô*÷ �÷ �Zú÷ —û�——“Ø—’ 1Õ$•Ø—‘×(Ñ(Ô*÷ ——�ýs;   •7B7ÁC Á:4C
Â7C	Ã
CÃEÃ24D/	Ä&	EÄ/D?Ä:Ec                ó‚   <€ V ^8„  d   QhRS[ S[S[3,          R,          RS[S[,          S[,          R,          RS[RR/# rÜ  rÝ  )r0   rI   s   "€r1   r2   r£  c  sT   ø€ ÷ Lñ Lá‘#‘s�(�^˜dÕ"ðLñ ™E•k¡CÕ'¨$Õ.ðLñ ð	Lð
 
ñLr3   c                óD  € \        T;'       g    / 4      pV'       d   \        V P                  4      VR &   Ve   \        V4      MRp. pRp^ p V P	                  4         V P                  4       p	V	f+   V'       g#   RpV P                  4        V P                  4       p	V	fw   V P                  '       dT   V'       dL   V P                  '       g:   \        V P                  V P                  4       \        RV P                   R24      hV P                  V4      p	V	eA    V P                  W”V4      p
T
e   T P'                  4        T
# Y–9   d   TP)                  T	4       RpV^,          pV\*        8”  g   EK  \        R4      h  \         dU    T P                   ;_uu_ 4        \#        ^ T	P$                  ^,
          4      T	n        RRR4       h   + '       g   i     h ; ii ; i  \         d´    T P                   ;_uu_ 4        T P                   Uu. uF  q»T9  g   K  TNK  	  Mu upi upT n        RRR4       M  + '       g   i     M; iT FK  p	 T	P-                  4        M  \         d     Mi ; iT	P/                  4        K8    T	P/                  4        i ; i	  h i ; i)ÚHF_TOKENNFTú No running host found for pool 'úX'. The pool has stopped (all its hosts were killed or idle-timed-out); create a new one.zZCould not place sandbox: hosts kept reporting full. Raise max_hosts or sandboxes_per_host.)rT  r}  rx  rB   r½  Ú_reserve_onerÓ  r¶  r°  r   rˆ   r«  r   Ú_boot_one_hostÚ_create_onere  r±  Úmaxr”  rÕ  ÚremoveÚ_MAX_PACK_ROUNDSrÏ  rÊ  )rO   r  r  r  Úsandbox_envÚ	idle_secsÚ	new_hostsÚ
discoveredÚroundsÚhostr¬   Úhs   &&&&        r1   rß  ÚSandboxPool._create_lockedc  sE  € ô ˜3Ÿ9˜9 "“oˆßÜ&6°t·y±yÓ&AˆK˜
Ñ#ð 8DÒ7OÔ% lÔ3ÐUYˆ	à*,ˆ	Øˆ
Øˆð<	ð ×"Ñ"Ô$Øà×(Ñ(Ó*�à’<¯
Ø!%�JØ×(Ñ(Ô*Ø×,Ñ,Ó.�Dà’<Ø×.×.Ð.·:ÀdÇkÇkÀkô *¨$¯)©)°T×5HÑ5HÔIÜ*Ø>¸t¿y¹y¸kð J_ð _óð ð  ×.Ñ.¨yÓ9�Dð Ò#ðØ"&×"2Ñ"2°4ÀiÓ"P˜ð Ò*Ø×(Ñ(Ô*Ø&˜ð
 Ô(Ø!×(Ñ(¨Ô.Ø"�
Ø˜!•�ØÔ,×,Ü&Øtóð øô% %ô ð "ŸZŸZ›ZÜ(+¨A¨t¯y©y¸1­}Ó(=˜DœI÷ (à÷ (žZàúðûô* ô 	à——“Ø*.¯+ª+ÓL©+ QÀ)Ñ9KŸq˜qª+ùÔL�”÷ ——�úã!�ð!Ø—O‘OÕ%øÜ ô Ùðúð —J‘J–Lø�D—J‘J•Lúñ "ð ð	úsÁ   Á,G! Á;7G! Â3G! Â;G! ÃAG! ÄE? Ä.G! Å*G! Å4G! Å?GÆ#G
Ç	GÇ
GÇ	GÇG! Ç!JÈ H9ÈH#
ÈH#
È"H9È0	JÈ9I	ÉJÉI#É"JÉ#I1É.JÉ0I1É1JÉ4JÊJÊJc                ó    <€ V ^8„  d   QhRS[ /# rF   ©r>   )r0   rI   s   "€r1   r2   r£  ²  s   ø€ ÷ $ñ $™3ñ $r3   c                ó’   € V P                   ;_uu_ 4        \        V P                  4      uuRRR4       #   + '       g   i     R# ; i)z*Number of host jobs currently provisioned.N)r±  rW   r°  rN   s   &r1   rÎ  ÚSandboxPool.num_hosts±  s%   € ð �Z�Z‹ZÜ�t—{‘{Ó#÷ �Z�Z‹Zús	   •5µA	c                ó    <€ V ^8„  d   QhRS[ /# rF   rö  )r0   rI   s   "€r1   r2   r£  ¸  s   ø€ ÷ :ñ :™sñ :r3   c                ó    € V P                   ;_uu_ 4        \        R V P                   4       4      uuRRR4       #   + '       g   i     R# ; i)z<Number of sandboxes currently handed out (across all hosts).c              3   ó8   "  € T F  qP                   x € K  	  R # 5ir¯   )r”  )r2  rò  s   & r1   r4  Ú,SandboxPool.num_sandboxes.<locals>.<genexpr>»  s   é € Ð9©[ T—y–y«[ùr6  N)r±  Úsumr°  rN   s   &r1   Únum_sandboxesÚSandboxPool.num_sandboxes·  s+   € ð �Z�Z‹ZÜÑ9¨T¯[ª[Ó9Ó9÷ �Z�Z‹Zús	   •<¼A	c                ó0   <€ V ^8„  d   QhRS[ S[,          /# rF   )r   r/   )r0   rI   s   "€r1   r2   r£  ¾  s   ø€ ÷ 9ñ 9™$™s�)ñ 9r3   c                ó¼   € V P                   ;_uu_ 4        V P                   Uu. uF  qP                  NK  	  upuuRRR4       # u upi   + '       g   i     R# ; i)z!Job ids of the provisioned hosts.N)r±  r°  rj  ©rO   rò  s   & r1   rÖ  ÚSandboxPool.host_ids½  s9   € ð �Z�Z‹ZØ,0¯KªKÓ8©K D—K”K©KÑ8÷ ŠZùÚ8÷ �ZˆZús   •A
¤A¸A
ÁA
Á
A	c                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r£  Ã  s   ø€ ÷ =ñ =�tñ =r3   c                óf  a € S P                   ;_uu_ 4        S P                  '       d    RRR4       R# RS n        S P                  \        ,           pS P                  '       d[   S P
                  P                  V 3R lVR7      '       g4   \        P                  RS P                   RS P                   RV R24       S P                  p. S n
        RRR4       . p. pX F6  p VP                  '       d   VP                  4        TP!                  4        K8  	  V'       d   S P#                  VR7       M2S P$                  '       d!   \'        S P                  S P(                  4       V'       d,   \+        RS P                   RRP-                  V4       R24      hR#   + '       g   i     LÒ; i  \         dc   pTP                  T4       TP                  TP                   R	T R
24       \        P                  RTP                   RT 24        Rp?ELRp?ii ; i  TP!                  4        i ; i)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>`.

Only hosts *this handle started* are cancelled. A host discovered via labels may
be serving another process' sandboxes, so it is released rather than terminated.

Raises [`SandboxError`] if a host job could not be cancelled, naming the jobs that
are still running â€” they keep billing, and their cache entries are kept so they stay
discoverable. When `close()` is reached through `__exit__` with an exception already
in flight, the failure is logged instead, so it cannot mask the original error.
NTc                  ó"   <€ S P                   ^ 8H  # rL   )r¸  rN   s   €r1   Ú<lambda>Ú#SandboxPool.close.<locals>.<lambda>Ý  s   ø€ ÀdÇoÁoÐYZÒFZr3   rÔ  úPool 'ú': z$ operation(s) still in flight after z(s; any host they boot will keep running.ú (rV   úFailed to cancel sandbox host rC  )Úhostsz#' could not terminate host job(s): ú; zM. They are still running and billing; cancel them with `hf jobs cancel <id>`.)r±  r´  r¬  Ú_CLOSE_DRAIN_TIMEOUTr¸  rº  Úwait_forr'  r(  rˆ   r°  r–  rÏ  re  rk  rj  rÊ  rÕ  r·  r   r«  r   rq  )rO   Údrain_timeoutr  Ú	survivorsÚfailuresrò  rC  s   f      r1   rÊ  ÚSandboxPool.closeÃ  sÑ  ø€ ð" �Z�Z‹ZØ�|�|ˆ|Ø÷ ‰Zð  ˆDŒLð
 !×/Ñ/Ô2FÕFˆMØ��ˆ t§}¡}×'=Ñ'=Ô>ZÐdqÐ'=×'rÒ'rÜ—‘Ø˜TŸY™Y˜K s¨4¯?©?Ð*;Ð;_Ø$�oÐ%MðOôð —K‘KˆEØˆDŒK÷ ð" +-ˆ	Ø ˆÛˆDðð —:—:�:Ø—O‘OÔ%ð —
‘
–ñ ÷ à×Ñ 9ÐÕ-Ø××Ðä˜dŸi™i¨×)<Ñ)<Ô=ßÜØ˜Ÿ™˜Ð#FÀtÇyÁyÐQYÓGZÐF[ð \^ð ^óð ñ ÷Q �Zûô2 ô Tð × Ñ  Ô&Ø—‘ 4§;¡; -¨r°!°°AÐ 6Ô7Ü—‘Ð!?ÀÇÁ¸}ÈBÈqÈcÐR×SÒSûðTûð —
‘
•úsH   –F´/FÁ$&FÂAFÃ#"F.ÆF+	Æ.HÆ9AHÈHÈHÈHÈH0c                ó   <€ V ^8„  d   QhRR/# )r*   r-   rœ  ra   )r0   rI   s   "€r1   r2   r£    s   ø€ ÷ ñ ˜=ñ r3   c                ó   € V # r¯   ra   rN   s   &r1   rK  ÚSandboxPool.__enter__  rM  r3   c                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r£    s   ø€ ÷ oñ o Tñ or3   c                ó®   €  V P                  4        R#   \         d6    T^ ,          f   h \        P                  RT P                   R2RR7        R# i ; i)r   Nr	  z/' teardown failed while handling another error.T)rQ  )rÊ  r   r'  r(  rˆ   rP  s   &*r1   rR  ÚSandboxPool.__exit__  sP   € ð	oØ�J‰JŽLøÜô 	oð ˜�{Ò"ØÜ�N‰N˜V D§I¡I ;Ð.]Ð^ÐimˆN×nð	oús   ‚ ”<AÁAc                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r£    s   ø€ ÷ 'ñ ' 4ñ 'r3   c           	     óÖ  € V P                   ;_uu_ 4        V P                  '       d    RRR4       R# V P                  4        V P                  f   V P                  M\        V P                  V P                  4      pV P                  ;_uu_ 4        V\        V P                  4      ,
          pRRR4       X^ 8”  d®   V P                  4        V P                  '       gŒ   V P                  ;_uu_ 4        V\        V P                  4      ,
          pRRR4       V^ 8”  dL   V P                  VRR7      pV P                  ;_uu_ 4        V P                  P                  V4       RRR4       RV n        RRR4       V P                  '       d   V P                  4        R# R#   + '       g   i     Lù; i  + '       g   i     Lª; i  + '       g   i     Lk; i  + '       g   i     Lo; i)uQ  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.
NTrÑ  )r²  rµ  Ú_seed_hosts_from_cacherŸ  r¨  ró   r±  rW   r°  rÓ  r¶  rÔ  r  rÕ  )rO   Útargetr×  rØ  s   &   r1   r½  ÚSandboxPool._ensure_warmed_up  sA  € ð  ××ÓØ��ˆØ÷ Ñð ×'Ñ'Ô)Ø&*§n¡nÒ&<�T—]’]Ä#ÀdÇmÁmÐUY×UcÑUcÓBdˆFØ——“Ø"¤S¨¯©Ó%5Õ5�	÷ à˜1Œ}Ø×$Ñ$Ô&ð ×.×.Ð.ØŸŸ›Ø$*¬S°·±Ó-=Õ$=˜	÷ $à  1”}Ø!%×!6Ñ!6°yÐPTÐ!6Ó!U˜Ø!ŸZŸZ›ZØ ŸK™K×.Ñ.¨vÔ6÷ (à"ˆDŒO÷' ð, �;�;ˆ;Ø×ÑÖñ ÷# —ú÷ $Ÿú÷ (ŸZú÷# ×ús_   •G³AGÂF	Â.0GÃGÃ3F2	Ä6GÅG	Å"GÆF/Æ*GÆ2GÆ=GÇGÇGÇG(	c                ó.   <€ V ^8„  d   QhRS[ R,          /# r¦  r.   )r0   rI   s   "€r1   r2   r£  :  s   ø€ ÷ 	ñ 	™s T�zñ 	r3   c                óT  € V P                   '       gQ    V P                  P                  RR7      P                  R4      V n        V P                  RJV n         V P                  # V P                  #   \
         d.   p\        P                  RT 24        Rp?T P                  # Rp?ii ; i)zGId of the principal this pool authenticates as, for the `"own"` policy.T©rÉ  ru   Nú;Could not resolve the current user to validate pool hosts: )r¯  rx  Úwhoamiry   r®  re  r'  r(  rD  s   & r1   Ú_principal_idÚSandboxPool._principal_id:  s•   € à×'×'Ð'ðbØ"&§)¡)×"2Ñ"2¸Ð"2Ó">×"BÑ"BÀ4Ó"H�”Ø+/¯?©?À$Ð+F�Ô(ð �‰Ðˆt�‰Ðøô ô bä—‘Ð!\Ð]^Ð\_Ð`×aÐaØ�‰Ðûðbús   ”AA/ Á/B'Á:B"Â"B'c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r*   rœ  r-   ©r   rH   )r0   rI   s   "€r1   r2   r£  E  s   ø€ ÷ ñ ™gð ©$ñ r3   c           	     ó4  € \        TV P                  V P                  \        8X  d   V P                  4       MRV P                  V P
                  V P                  R7      pVe6   \        P                  RVP                   RV P                   RV R24       R# R# )	z9Whether `job` may be adopted as one of this pool's hosts.N©rÂ  Úprincipal_idr&   rˆ  r  zNot adopting job ú as a host for pool 'r
  r(   FT©Ú_host_rejectionr­  r¥  r%  rª  rˆ  r  r'  Údebugru   rˆ   ©rO   rœ  Úreasons   && r1   Ú
_adoptableÚSandboxPool._adoptableE  s†   € ä ØØ×$Ñ$Ø15×1BÑ1BÄiÔ1O˜×+Ñ+Ô-ÐUYØ—o‘oØ—*‘*Ø—;‘;ô
ˆð ÒÜ�L‰LÐ,¨S¯V©V¨HÐ4IÈ$Ï)É)ÈÐTWÐX^ÐW_Ð_`ÐaÔbÙÙr3   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r(  r)  )r0   rI   s   "€r1   r2   r£  T  s   ø€ ÷ ñ ¡gð ±$ñ r3   c           
     ó6  € \        TV P                  V P                  \        8X  d   V P                  4       MRV P                  V P
                  V P                  RR7      pVe6   \        P                  RVP                   RV P                   RV R24       R# R# )	zFLike `_adoptable`, minus the checks a not-yet-running job cannot pass.NF)rÂ  r,  r&   rˆ  r  Ú	check_urlzNot waiting for job r-  r
  r(   Tr.  r1  s   && r1   Ú_adoptable_pendingÚSandboxPool._adoptable_pendingT  s‰   € ä ØØ×$Ñ$Ø15×1BÑ1BÄiÔ1O˜×+Ñ+Ô-ÐUYØ—o‘oØ—*‘*Ø—;‘;Øô
ˆð ÒÜ�L‰LÐ/°·±¨xÐ7LÈTÏYÉYÈKÐWZÐ[aÐZbÐbcÐdÔeÙÙr3   c                ó   <€ V ^8„  d   QhRR/# )r*   r-   ú_SandboxServer | Nonera   )r0   rI   s   "€r1   r2   r£  d  s   ø€ ÷ ñ Ð5ñ r3   c                ó   € V P                   ;_uu_ 4        V P                   FL  pVP                  VP                  ,
          ^ 8”  g   K'  V;P                  ^,          un        Vu uuRRR4       # 	  RRR4       R#   + '       g   i     R# ; i)zNReserve one slot on the first host with free capacity (under lock), else None.N)r±  r°  r…  r”  r  s   & r1   rç  ÚSandboxPool._reserve_oned  s\   € à�Z�Z‹ZØŸœ�Ø—=‘= 4§9¡9Õ,¨qÖ0Ø—I’I •N•IØ‘K÷	 ŠZÙ#÷ ñ
 ÷ ŽZñ
 ús   •/A<Á	A<Á0A<Á<B	c                ó2   <€ V ^8„  d   QhRS[ R,          RR/# )r*   rï  rƒ  r-   r;  )r   )r0   rI   s   "€r1   r2   r£  m  s"   ø€ ÷ 'ñ '©Ð-=Õ(>ð 'ÐCZñ 'r3   c           	     ó  € V P                   ;_uu_ 4        V P                  4       pVe   VuuRRR4       # V P                  4       '       d!   V P                  4       pVe   VuuRRR4       # V P                  ^4      pVP	                  V4       V P
                  ;_uu_ 4        V P                  P	                  V4       RRR4       V P                  4       uuRRR4       #   + '       g   i     L*; i  + '       g   i     R# ; i)u0  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.
N)r³  rç  Ú_adopt_pending_hostrÔ  r  r±  r°  )rO   rï  rò  rØ  s   &&  r1   rè  ÚSandboxPool._boot_one_hostm  sÁ   € ð �_�_‹_ð ×$Ñ$Ó&ˆDØÒØ÷ Š_ð ×'Ñ'×)Ò)Ø×(Ñ(Ó*�ØÒ#Ø÷ Š_ð ×*Ñ*¨1Ó-ˆFØ×Ñ˜VÔ$Ø——“Ø—‘×"Ñ" 6Ô*÷ à×$Ñ$Ó&÷! Š_÷ —ú÷ �_ˆ_ús4   •C3¶C3ÁC3Á,6C3Â"C 	Â>C3Ã C0Ã+C3Ã3D	c                ó    <€ V ^8„  d   QhRS[ /# rF   rG   )r0   rI   s   "€r1   r2   r£  ‰  s   ø€ ÷ 'ñ '¡Tñ 'r3   c           
     ó   a aa€ S P                    Uu0 uF  qP                  kK  	  upo\        VV 3R lS P                  P	                  R\
        \        \        S P                  /S P                  R7       4       R4      oSf   R# \        P                  RS P                   RSP                   R24       \        P                  ! 4       S P                  ,           p\        P                  ! 4       V8  dÔ   S P                  P                  SP                  S P                  R	7      P                   P"                  pVR9  d   R# VR
8X  dg   S P%                  4        \&        ;QJ d)    V3R lS P                    4       F  '       g   K   RM	  RM! V3R lS P                    4       4      '       d   R# \        P(                  ! R4       Kí  R# u upi )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   ó€   <"  € T F3  pVP                   S9  g   K  SP                  V4      '       g   K/  Vx € K5  	  R # 5ir¯   )ru   r8  )r2  rœ  ÚknownrO   s   & €€r1   r4  Ú2SandboxPool._adopt_pending_host.<locals>.<genexpr>“  sA   øé € ð ñ�Cð —6‘6 Ñ&ô ð ,0×+BÑ+BÀ3×+G÷ ’óùs   ƒ>›>´
>Ú
SCHEDULING©rÚ  r  r&   NFr	  z' host z: is already SCHEDULING; waiting for it instead of booting.rÎ  r5  c              3   óT   <"  € T F  qP                   SP                  8H  x € K  	  R # 5ir¯   ©rj  ru   )r2  rò  Úpendings   & €r1   r4  rF  ­  s   øé € ÐI¹[°T—{‘{ g§j¡jÖ0»[ùó   ƒ%(Tg      ð?)rG  r5  )r°  rj  r8  rx  Ú	list_jobsr#  r;  Ú
POOL_LABELrˆ   rª  r'  r0  ru   r×  r¬  rÙ  rÚ  rÛ  rÓ  ÚanyrÞ  )rO   rò  rß  rÛ  rE  rK  s   f   @@r1   r@  ÚSandboxPool._adopt_pending_host‰  sI  ú€ ð *.¯ªÓ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ÙØ˜	Ô!ð ×$Ñ$Ô&ß“3ÔI¸T¿[º[ÓI—3—3’3ÔI¸T¿[º[ÓI×IÒIÙÜ�JŠJ�sŽOÙùò? 6s   ’Gc                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r£  ²  s   ø€ ÷ */ñ */ ñ */r3   c                óú  a€ V P                    Uu0 uF  qP                  kK  	  ppV P                  P                  R\        \
        \        V P                  /V P                  R7       Uu. uF1  pVP                  V9  g   K  V P                  V4      '       g   K/  VNK3  	  ppV EFJ  oRp \        V P                  SP                  V P                  R7      p\        V P                  SV P                  R7      p\        VP                  RV P                  4      4      Vn        \#        VP%                  RR4      P'                  4       4      Vn        T P8                  ;_uu_ 4        \:        ;QJ d)    T3R
 lT P                    4       F  '       g   K   RM	  RM! T3R
 lT P                    4       4      '       d   TP7                  4        MT P                   P=                  T4       RRR4       EKM  	  R# u upi u upi   \*        \,        P.                  \0        3 dF   p\2        P5                  RSP                   R	T 24       Te   TP7                  4         Rp?EK»  Rp?ii ; i  + '       g   i     EKÕ  ; i)a  Attach to running host jobs carrying this pool's labels.

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.

Labels select candidates; creator, job specification and proxy URL admission
checks decide which candidates can receive credentials. Adopted hosts are released
by close(), not cancelled, because another handle may still be using them.
r5  rH  NrÕ  rÅ  râ   r2  zSkipping host z during discovery: c              3   óT   <"  € T F  qP                   SP                  8H  x € K  	  R # 5ir¯   rJ  )r2  rò  rœ  s   & €r1   r4  Ú.SandboxPool._discover_hosts.<locals>.<genexpr>Ù  s   øé € ÐE¹°—{‘{ c§f¡fÖ,»ùrL  TF)r°  rj  rx  rM  r#  r;  rN  rˆ   rª  ru   r3  r:  rÇ  r>   ry   r�  r…  rW   r  rx   r”  r   rY  Ú	HTTPErrorr   r'  r0  rÊ  r±  rO  rk  )rO   rò  rE  rœ  Úmatchesrý  r  rC  s   &  `    r1   rÓ  ÚSandboxPool._discover_hosts²  sÔ  ø€ ð *.¯ªÓ5© —”©ˆÐ5ð —y‘y×*Ñ*Ø Ü"¤I¬z¸4¿9¹9ÐEØŸ/™/ð +ô ó
ñ�ð
 �v‰v˜UÑ"ô ð (,§¡°s×';÷ ˆCñð 	ð 
ô ˆ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�”ð ——“ß“3ÔE¸¿ºÓE—3—3’3ÔE¸¿ºÓE×EÒEØ—L‘L•Nà—K‘K×&Ñ& vÔ.÷	 ’ó! ùò 6ùò
øô& !¤%§/¡/´>ÐBô ô —‘˜~¨c¯f©f¨XÐ5HÈÈÐLÔMØÒ%Ø—L‘L”NÞûðú÷ —‘úsH   �G6Á*G;ÂG;ÂG;Â,B&H Å&*I(Æ'I(Æ;,I(È  I%È 9I É I%É(I:c                ó    <€ V ^8„  d   QhRS[ /# rF   rö  )r0   rI   s   "€r1   r2   r£  Þ  s   ø€ ÷ ñ ¡#ñ r3   c                ó  € V P                   ;_uu_ 4        V P                   Uu0 uF  qP                  kK  	  ppRRR4        V P                  P	                  R\
        \        \        V P                  /V P                  R7       F  pXP                  VP                  4       K   	  \        X4      # u upi   + '       g   i     L…; i  \         d0   p\        P                  RT P                   RT 24        Rp?LXRp?ii ; i)ah  How many hosts are running for this pool, not just the ones we track.

`max_hosts` is documented as a cost ceiling, but it was compared against
`len(self._hosts)` -- an in-process count. Two processes using the same
pool each counted only their own hosts, so the number of billed host jobs
could quietly exceed the cap by a factor of however many processes were
involved.

Counting via labels narrows that considerably. It does not close it: two
processes can still list simultaneously and both decide there is room. A
hard cap has to be enforced where the jobs are created, not by the
clients racing to count them.
Nr5  rH  z%Could not count live hosts for pool 'r
  )r±  r°  rj  rx  rM  r#  r;  rN  rˆ   rª  Úaddru   re  r'  r0  rW   )rO   rò  Útrackedrœ  rC  s   &    r1   Ú_live_host_countÚSandboxPool._live_host_countÞ  sÉ   € ð �Z�Z‹ZØ/3¯{ª{Ó;©{ t—{”{©{ˆGÐ;÷ ð		TØ—y‘y×*Ñ*Ø Ü"¤I¬z¸4¿9¹9ÐEØŸ/™/ð +ö �ð
 —‘˜CŸF™FÖ#ñô �7‹|Ðùò <÷ �Zûô ô 	Tä�L‰LÐ@ÀÇÁÀÈ3ÈqÈcÐR×SÑSûð	Tús4   •B7¤B2¸B7ÁA$C
 Â2B7Â7C	Ã
DÃ%C?Ã?DrÒ  c                ó<   <€ V ^8„  d   QhRS[ RS[RS[S[,          /# )r*   Únum_newrÒ  r-   )r>   rH   r   rƒ  )r0   rI   s   "€r1   r2   r£  ú  s)   ø€ ÷ $ñ $©ð $¹tð $ÑPTÑUcÕPdñ $r3   c               ó|  € V P                   e–   V P                  4       pV'       d(   \        V\        ^ V P                   V,
          4      4      pW1,           V P                   8”  d@   V P                   V,
          p\	        RV RV P                    R\        ^ V4       RV R2	4      hV^ 8X  d   . # \        \        V^ 4      R7      ;_uu_ 4       p\        V4       Uu. uF  qeP                  V P                  4      NK  	  ppRRR4       . pRp	X F#  p
 VP                  V
P                  4       4       K%  	  V	e-   V F$  p VP                  4        VP                  4        K&  	  V	hV# u upi   + '       g   i     Lt; i  \         d   pTp	 Rp?K„  Rp?ii ; i  \         d     LXi ; i  TP                  4        i ; i)z=Boot `num_new` host jobs in parallel, respecting `max_hosts`.NzPool needs z more host(s) but max_hosts=z allows only z more (zH already running for this pool). Raise max_hosts or kill some sandboxes.)Úmax_workers)rŸ  r\  ró   rê  r   r   rò   ÚsubmitÚ
_boot_hostrk  rp  re  rÏ  rÊ  )rO   r_  rÒ  ÚcurrentÚallowedrþ   Ú_ÚfuturesrØ  rd  ÚfuturerC  rý  s   &&$          r1   rÔ  ÚSandboxPool._provision_hostsú  sŽ  € à�>‰>Ò%Ø×+Ñ+Ó-ˆGßÜ˜g¤s¨1¨d¯n©n¸wÕ.FÓ'GÓH�ØÕ  4§>¡>Ô1ØŸ.™.¨7Õ2�Ü"Ø! ' Ð*FÀtÇ~Á~ÐFVð W#Ü#& q¨'£?Ð"3°7¸7¸)ð D>ð>óð ð
 �aŒ<ØˆIô  ¬C°¸Ó,<×=Õ=ÀÜAFÀwÄÓPÁ¸A—‘ t§¡Ö7ÁˆGÐP÷ >à')ˆØ"&ˆÛˆFðØ—‘˜fŸm™m›oÖ.ñ ð
 ÒÛ �ð#Ø×%Ñ%Ô'ð —L‘L–Nñ !ð ˆKØˆùò# Q÷ >×=ûô ô Ø–ûðûô !ô Ùðûð —L‘L•NúsZ   ÃE*Ã#E%Ã<E*ÄE=Ä=FÅ%E*Å*E:	Å=FÆFÆFÆF&Æ#F)Æ%F&Æ&F)Æ)F;c                ó    <€ V ^8„  d   QhRS[ /# rF   ©rƒ  )r0   rI   s   "€r1   r2   r£     s   ø€ ÷ @ñ @™Nñ @r3   c                ó`  € \        V P                  4      p\        ^4      p\        W4      p\	        V P                  VRRRV P
                  RVR7      w  rErgRVR&   \        V P                  4      VR&   V P                  e   \        V P                  4      VR&   \        R\        \        \        V P                  \        V/pV P                  P                  V P                   TTTV P"                  \$        TT;'       g    R\&        .V P(                  R7
      p	Rp
 \*        P-                  V	VVV P                  \/        V P                  ^,           R	4      V P                  R
7      p
V
P1                  V P2                  4       T PB                  T
n"        T
#   \4         d‘     T P                  P7                  T	P8                  T	P:                  P                  R7       M=  \4         d0   p\<        P?                  RT	P8                   RT 24        Rp?MRp?ii ; iT
e   T
PA                  4        h i ; i)z6Start one host job and wait until its server is ready.NFr  rI  ÚSBX_HOST_MODErÅ  rÄ  r  é   )rœ  r,   rŠ  rt  r„  r…  rÎ  r  r  )#r}  rx  r   r;   r  r©  r/   r�  rŸ  r"  r#  r;  rN  rˆ   r%  r   rˆ  r  r!  r&  rª  rƒ  r£  ró   râ  r¬  re  rÏ  ru   r‡  r'  r(  rÊ  r·  r–  )rO   r+   r,   rŠ  r  r+  r,  r-  r  rœ  rý  rC  s   &           r1   rc  Ú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%F ÆH-Æ;GÇH-ÇHÇ%%HÈ
H-ÈHÈH-c                óR   <€ V ^8„  d   QhRRRS[ S[S[3,          RS[R,          RR/# )r*   rò  rƒ  r  rî  Nr-   ró  )rT  r/   r	   r>   )r0   rI   s   "€r1   r2   r£  b  s:   ø€ ÷ 'ñ 'Ð 0ð '±t¹CÁ¸Hµ~ð 'ÑRUÐX\ÕR\ð 'Ðaqñ 'r3   c           
     ó6  € R^/pVe   W4R&   V'       d   W$R&    VP                  RRVR7      P                  4       pR
Tn        TP                  R4      ;'       g    . p\        TP                  R^ 4      4      '       g	   T'       g1   T P                  ;_uu_ 4        TP                  Tn        RRR4       R# T^ ,          p\        TP                   \          TR,           2TTR,          R
RTP                  R4      R7      p	T P"                  T	n        T	#   \        \        P                  3 dU   pTP
                  '       d   h \        P                  RTP                   R	T 24       T P                  T4        Rp?R# Rp?ii ; i  + '       g   i     R# ; i)uy  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).
ÚcountNÚidle_timeout_secsr  rO  r2  rd  z!Dropping unreachable cached host rC  TÚ	sandboxesÚrejectedru   FrÆ  r3  )r  rx   r   rY  rU  r•  r'  r0  rj  Ú
_drop_hostry   r>   r±  r…  r”  r€   r8  Ú_on_sandbox_killedr  )
rO   rò  r  rî  ÚbodyrÌ   rC  rt  r=  r¬   s
   &&&&      r1   ré  ÚSandboxPool._create_oneb  sX  € ð !(¨˜|ˆØÒ Ø(1Ð$Ñ%ßØ�‰Kð	Ø—<‘< ¨¸d�<ÓC×HÑHÓJˆDð ˆŒØ—H‘H˜[Ó)×/Ð/¨Rˆ	Üˆt�x‰x˜
 AÓ&×'Ò'¯yØ——“Ø ŸM™M�”	÷ áØ˜�|ˆÜØ—+‘+�œ}˜o¨d°4­j¨\Ð:ØØ˜$•ZØØð Ÿ(™( 7Ó+ô	
ˆð  ×2Ñ2ˆÔØˆøô1 œeŸo™oÐ.ô 	Ø�}�}ˆ}ØÜ�L‰LÐ<¸T¿[¹[¸MÈÈAÈ3ÐOÔPØ�O‰O˜DÔ!Ýûð	ú÷ –áús$   š"D ÂFÄFÄ0A	E?Å?FÆF	c                ó$   <€ V ^8„  d   QhRS[ RR/# )r*   r¬   r-   N)r€   )r0   rI   s   "€r1   r2   r£  ‹  s   ø€ ÷ Dñ D©'ð D°dñ Dr3   c                óÔ   € V P                   ;_uu_ 4        \        ^ VP                  P                  ^,
          4      VP                  n        RRR4       R#   + '       g   i     R# ; i)z:Free the packing slot of a shared sandbox that was killed.N)r±  rê  r  r”  r±   s   &&r1   rw  ÚSandboxPool._on_sandbox_killed‹  s9   € à�Z�Z‹ZÜ#& q¨'¯/©/×*>Ñ*>ÀÕ*BÓ#CˆG�O‰OÔ ÷ �Z�ZŠZús   •7AÁA'	c                ó$   <€ V ^8„  d   QhRS[ RR/# ©r*   rò  r-   Nrk  )r0   rI   s   "€r1   r2   r£  �  s   ø€ ÷ ñ ™~ð °$ñ r3   c                ó*  € V P                   ;_uu_ 4        V P                   Uu. uF  q"VJg   K
  VNK  	  upV n        V P                  P                  VP                  4       RRR4       VP                  4        R# u upi   + '       g   i     L'; i)zFForget a host found dead this session (and mark it for cache pruning).N)r±  r°  r¼  rZ  rj  rÊ  )rO   rò  ró  s   && r1   rv  ÚSandboxPool._drop_host�  sa   € à�Z�Z‹ZØ&*§k¢kÓC¡k ¸d°]Ÿ1˜1¡kÑCˆDŒKØ×Ñ×#Ñ# D§K¡KÔ0÷ ð 	�
‰
Žùò D÷ �Zús    •B¤A=°A=¶-BÁ=BÂB	c                ó   <€ V ^8„  d   QhRR/# r¦  ra   )r0   rI   s   "€r1   r2   r£  ™  s   ø€ ÷ 1/ñ 1/¨ñ 1/r3   c                ó(  a€ \        V P                  V P                  4      pVf   R# \        V P                  4      p\
        P
                  ! 4       pVP                   EFm  oV P                  ;_uu_ 4        V P                   Uu0 uF  qDP                  kK  	  ppRRR4       SP                  X9   g   SP                  SP                  8¼  d   Ks  \        S4      pVex   \        P                  RSP                   RV P                   RV R24       V P                  ;_uu_ 4        V P                  P!                  SP                  4       RRR4       Kù  VSP"                  ,
          \$        8”  d   V P'                  S4      '       g   EK/  \)        SP                  SP*                  V P,                  SP.                  SP0                  \3        VSP0                  4      V P                  \5        V P6                  ^,           R4      SP                  R7	      pSP                  Vn
        RVn        V P                  ;_uu_ 4        \:        ;QJ d)    V3R	 lV P                   4       F  '       g   K   R
M	  RM! V3R	 lV P                   4       4      '       d   VP=                  4        MV P                  P?                  V4       RRR4       EKp  	  R# u upi   + '       g   i     ELE; i  + '       g   i     EL§; i  + '       g   i     EK³  ; i)uE  Adopt the pool's cached hosts without any HTTP (rebuilt from cached URL + nonce).

The first thing that happens to a seeded host is an authenticated `POST`, so what the
file says about *where* it lives is not taken on trust: the URL must be one only this
job can have (`_cached_host_rejection`), and an entry older than `HOST_TRUST_TTL` is
re-checked against the Jobs API first (`_confirm_cached_host`). A fresh entry â€” the
`pool create` â†’ `create --pool` case the cache exists for â€” is used as is.

Liveness stays best-effort: a seeded host is confirmed by its 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.
NzDropping cached host ú
 of pool 'z': it r(   rn  rž  Fc              3   óT   <"  € T F  qP                   SP                   8H  x € K  	  R # 5ir¯   ©rj  )r2  rò  Úchs   & €r1   r4  Ú5SandboxPool._seed_hosts_from_cache.<locals>.<genexpr>Ç  s   øé € ÐH¹K°D—{‘{ b§i¡iÖ/»KùrL  T) r   rˆ   r«  r}  rx  r×  r  r±  r°  rj  r”  r…  Ú_cached_host_rejectionr'  r0  r¼  rZ  Ú
updated_atr   Ú_confirm_cached_hostrƒ  r‡  rˆ  r‰  r,   r;   ró   r�  r•  rO  rÊ  rk  )	rO   rÉ  r+   Únowrò  rE  r2  rý  r†  s	   &       @r1   r  Ú"SandboxPool._seed_hosts_from_cache™  s  ø€ ô   §	¡	¨4×+>Ñ+>Ó?ˆØŠ=ÙÜ# D§I¡IÓ.ˆÜ�iŠi‹kˆØ—+•+ˆBØ——“Ø15·²Ó=±¨Ÿœ±�Ð=÷ à�y‰y˜EÔ! R§W¡W°·±Ô%;ÙÜ+¨BÓ/ˆFØÒ!Ü—‘Ð4°R·Y±Y°K¸zÈ$Ï)É)ÈÐTZÐ[aÐZbÐbcÐdÔeØ—Z—Z“ZØ×'Ñ'×+Ñ+¨B¯I©IÔ6÷  áØ�R—]‘]Õ"¤^Ô3¸D×<UÑ<UÐVX×<YÒ<YÚÜ#Ø—y‘yØ—h‘hØ—j‘jØŸ™Ø—h‘hÜ3°H¸b¿h¹hÓGØ—I‘IÜ # D×$;Ñ$;¸aÕ$?ÀÓ EØŸ™ô
ˆFð Ÿ'™'ˆFŒKØ#ˆFŒOØ——“ß“3ÔH¸D¿KºKÓH—3—3’3ÔH¸D¿KºKÓH×HÒHØ—L‘L•Nà—K‘K×&Ñ& vÔ.÷	 ’ó5 ùâ=÷ —�ú÷  —Z�Zú÷$ —‘úsB   Á6KÂK
ÂKÄ'&K+É*K?É/'K?Ê,K?ËKËK(Ë+K<Ë?Lc                ó&   <€ V ^8„  d   QhRS[ RS[/# )r*   r†  r-   )r   rH   )r0   rI   s   "€r1   r2   r£  Ì  s   ø€ ÷ (ñ (¡zð (±dñ (r3   c           	     óì  € V P                   \        8X  d   V P                  4       f   \        R4      h V P                  P                  VP                  VP                  R7      pVP                  ;'       g    / pVP                  P                  R8w  d   RVP                  P                   R2pM¹VP                  \        4      \        8w  g%   VP                  \        4      V P                  8w  d   RV P                   R2pMfVP                  \         4      VP"                  8w  d   R	pM?V P%                  V4      '       g   R
pM%\'        V4      ;qQP(                  8w  d	   RV: R2pMR# \4        P7                  RVP                   RV P                   RV R24       V P8                  ;_uu_ 4        V P:                  P=                  VP                  4       RRR4       R#   \*        P,                   dB   pTP.                  P0                  R8w  d   \        RTP                   R24      ThRp Rp?LÈRp?i\2         d    p\        RTP                   R24      ThRp?ii ; i  + '       g   i     R# ; i)uß  Confirm an aged-out cache entry against the Jobs API before crediting it.

Freshness is what the no-HTTP path rests on: the entry was written by this same
principal minutes ago, so the job it names is almost certainly still the host it
described. Past `HOST_TRUST_TTL` that argument weakens, and the entry becomes a hint
that has to be checked â€” the job must still be running, still be labelled for *this*
pool with the nonce the entry derives its token from, still pass the pool's adoption
policy, and still expose exactly the cached URL. One round-trip, and only for entries
the fast path would no longer be honest about.

A definitive "no" prunes the entry; a transient failure aborts this attempt
without losing the cached host.
NzOCould not validate cached pool hosts: current user is unavailable; retry later.rÎ  r5  z its job is not running (status: rV   z+its job is not labelled as a host of pool 'Ú'z!its job carries a different noncez&its job is not one this pool may adoptzits job exposes z, not the cached URLTrA  zCould not confirm cached host z; retry later.zits job no longer existszDropping stale cached host rƒ  r
  r(   F)r­  r¥  r%  r   rx  rÙ  rj  r‡  r  rÚ  rÛ  ry   r#  r;  rN  rˆ   r%  r,   r3  r¡  r‰  rY  ÚHTTPStatusErrorrz   rB  re  r'  r0  r±  r¼  rZ  )rO   r†  rœ  r  r2  ÚexposedrC  s   &&     r1   rŠ  Ú SandboxPool._confirm_cached_hostÌ  sô  € ð ×Ñ¤	Ô)¨d×.@Ñ.@Ó.BÒ.JÜÐpÓqÐqð	bØ—)‘)×'Ñ'¨r¯y©yÀBÇHÁHÐ'ÓMˆCØ—Z‘Z×%Ð% 2ˆFØ�z‰z×Ñ 9Ô,Ø;¸C¿J¹J×<LÑ<LÐ;MÈQÐO‘Ø—‘œJÓ'¬9Ô4¸¿
¹
Ä:Ó8NÐRV×R[ÑR[Ô8[ØFÀtÇyÁyÀkÐQRÐS‘Ø—‘œKÓ(¨B¯H©HÔ4Ø<‘Ø—_‘_ S×)Ò)ØA‘Ü-¨cÓ2Ð2�'·{±{ÔBØ+¨G©;Ð6JÐK‘áô 	�‰Ð2°2·9±9°+¸ZÈÏ	É	À{ÐRUÐV\ÐU]Ð]^Ð_Ô`Ø�Z�Z‹ZØ×Ñ×#Ñ# B§I¡IÔ.÷ áøô ×$Ñ$ô 	0Ø�z‰z×%Ñ%¨Ô,Ü"Ð%CÀBÇIÁIÀ;ÈnÐ#]Ó^ÐdeÐeØ/�FûÜô 	bÜÐ!?ÀÇ	Á	¸{È.ÐYÓZÐ`aÐaûð	bú÷ ŽZáús[   ´AG! Á88G! Â1AG! Ä&G! Ä+G! ÅG! Å"G! Æ1&I"Ç!IÇ67H2È2IÈ?IÉ IÉIÉ"I3	c                ó"   <€ V ^8„  d   QhRRRR/# )r*   r  zList[_SandboxServer] | Noner-   Nra   )r0   rI   s   "€r1   r2   r£  ö  s   ø€ ÷  
ñ  
Ð!>ð  
È$ñ  
r3   c                ó„  € V P                   ;_uu_ 4        Vf   V P                  MTpV Uu. uFd  p\        VP                  VP                  VP
                  VP                  VP                  VP                  \        P                  ! 4       R7      NKf  	  pp\        V P                  4      pRRR4       \        V P                  V P                  V P                  V P                   V P"                  V P$                  V P&                  e   \)        V P&                  4      MRXXR7	       R# u upi   + '       g   i     LŠ; i)a  Persist the pool config + hosts (with their live counts) for next time.

`hosts` overrides the tracked list, for the one case where they differ:
`close()` persisting the hosts it could *not* cancel, since that record is
the caller's only handle on a job that is still billing.
N)rj  r‡  r‰  r,   r…  r”  r‰  )Úcontextrˆ  r  r�  rŸ  r  r  Údead_host_ids)r±  r°  r   rj  r‡  r‰  r,   r…  r”  r×  r»  r¼  r   rˆ   r«  rˆ  r  r�  rŸ  r©  rB   )rO   r  r   rò  r7  Údeads   &&    r1   rÕ  ÚSandboxPool._save_cacheö  sù   € ð �Z�Z‹ZØ$)¢M�T—[’[°uˆFñ #óñ #�Dô ØŸ;™;ØŸ*™*Ø!Ÿ]™]ØŸ*™*Ø!Ÿ]™]ØŸ™Ü#Ÿyšy›{÷ñ #ð ð ô �t×*Ñ*Ó+ˆD÷ ô 	Ø�I‰IØ×'Ñ'Ø—*‘*Ø—;‘;Ø#×6Ñ6Ø—n‘nØBF×BTÑBTÒB`Ô*¨4×+=Ñ+=Ô>ÐfjØØ÷
	
ùò÷ �Zús   •D/¬A*D*ÂD/Ä*D/Ä/D?	)r­  rx  r³  r«  r´  r¼  rº  r°  r©  r¸  r±  rª  r·  r®  r¯  r¶  r¬  r¨  rµ  r²  r  rˆ  rŸ  rˆ   r�  )é   r¯   ))rb   rc   rd   re   rf   r™  rÈ  rš  r¥  r²   rä  r·  rÙ  r.  rß  rg   rÎ  rþ  rÖ  rÊ  rK  rR  r½  r%  r3  r8  rç  rè  r@  rÓ  r\  rÔ  rc  ré  rw  rv  r  rŠ  rÕ  ri   rj   rk   s   @r1   rœ  rœ  #  s5  ø‡ € ñ*ð\ #ñD%ð "ð	D%ð
 #=ðD%ð ðD%ð !%ðD%ð  ðD%ð 2FðD%ð !%ðD%ð  %ðD%ð %ðD%ð !ðD%ð $÷D%ó D%ðP ðC
ð !%ð	C
ð
 %ðC
ð !÷C
ñ C
ó ðC
÷Jò ð6(+ð &*ð(+ð 2Fð	(+ð
 "'÷(+ò (+÷TLð Lð\ ÷$ó ð$ð
 ÷:ó ð:ð
 ÷9ó ð9÷
=ð =÷~ð ÷oð o÷'ð '÷R	ð 	÷ð ÷ð ÷ ð ÷'ð '÷8'ð '÷R*/ð */÷Xð ð8$Àe÷ $ò $÷L@ð @÷D'ð '÷RDð D÷
ð ÷1/ð 1/÷f(ð (÷T 
÷  
ð  
r3   rœ  c                óL   € V ^8„  d   QhR\         R,          R\         R,          /# )r*   rˆ  Nr-   r.   )r0   s   "r1   r2   r2   	  s"   € ÷ 	ñ 	œC $�Jð 	¬3°­:ñ 	r3   c                ó®   € V f   R# V P                  4       P                  4       p R F*  pV P                  V4      '       g   K  V \        V4      R p K,  	  V # )zˆCompare Docker images leniently: registries and tags get normalized
server-side, and a mis-parse here must not stop a pool from working.N)z
docker.io/zindex.docker.io/zlibrary/)ÚstripÚlowerr†  rW   )rˆ  Úprefixs   & r1   Ú_normalize_imagerŸ  	  sS   € ð ‚}ÙØ�K‰K‹M×ÑÓ!€EÛ@ˆØ×Ñ˜F×#Ô#Øœ#˜f›+˜-Ð(ŠEñ Að €Lr3   c                óJ   € V ^8„  d   QhR\         R\         R\         R,          /# )r*   Úurlrj  r-   Nr.   )r0   s   "r1   r2   r2   %	  s%   € ÷ ñ ¤ð ´ð ¼¸d½
ñ r3   c               ó   € \        V 4      pVP                  R8w  d   RVP                  : R2# VP                  ;'       g    RP                  V R\         R2P                  4       4      '       g   RV R\         R	2# R
# )a3  Why `url` is not a URL we should send a sandbox job's credentials to.

The hostname must be derived from the job id we already hold, so nothing but the
client's own knowledge of which job it is talking to can decide where the credentials
go. The domain is not hard-coded, so staging endpoints keep working.
Úhttpszuses scheme z, not httpsr†   ú--r(   zis not job z's port-z URLN)r   r€  Úhostnamer†  r&  r�  )r¡  rj  Úparseds   &$ r1   Ú_server_host_rejectionr§  %	  s|   € ô �c‹]€FØ‡}�}˜ÔØ˜fŸm™mÑ.¨kÐ:Ð:à�O‰O×!Ð!˜r×-Ñ-°°¸Ô;NÐ:OÈqÐ.Q×.WÑ.WÓ.Y×ZÒZØ˜V˜H HÔ-@Ð,AÀÐFÐFÙr3   c                ó>   € V ^8„  d   QhR\         R\        R,          /# )r*   rœ  r-   N©r   r/   )r0   s   "r1   r2   r2   5	  s"   € ÷ Rñ Rœwð R¬3°­:ñ Rr3   c                ó&  € V P                   e*   \        V P                   P                  ;'       g    . 4      M. p\        V4      ^8w  d   R\        V4       R\         2# \        V^ ,          V P                  R7      pVe   RV^ ,          : RV 2# R# )zDWhy this Job's exposed URL is not one we should send credentials to.Nzexposes z' URL(s), expected exactly one for port r…  ú, which )rÚ  rû   Úexpose_urlsrW   r&  r§  ru   )rœ  Úurlsr2  s   &  r1   Ú_server_url_rejectionr®  5	  sƒ   € à14·±Ò1GŒ4�—
‘
×&Ñ&×,Ð,¨"Ô-ÈR€DÜ
ˆ4ƒy�A„~Øœ#˜d›)˜Ð$KÔL_ÐK`ÐaÐaÜ# D¨¥G°C·F±FÔ;€FØ5;Ò5GˆX�d˜1•g‘[ ¨¨Ð1ÐQÈTÐQr3   c                ó>   € V ^8„  d   QhR\         R\        R,          /# r~  )r   r/   )r0   s   "r1   r2   r2   >	  s"   € ÷ Vñ V¤ð V´°dµ
ñ Vr3   c                óv   € \        V P                  V P                  R7      pVe   RV P                  : RV 2# R# )aK  Why a cached host entry must not be rebuilt into a credentialed transport.

Same reasoning as `_server_url_rejection`, for a URL that comes off the local disk
instead of the Jobs API. Without this, the cache file gets to choose where the HF bearer
and the derived host token are sent -- `http://127.0.0.1:1234` included -- and it gets to
choose it *before* any API call could have contradicted it. Deriving the expected
hostname from the entry's own `job_id` leaves it able to name only a job this client can
independently identify, which is the same bar a discovered host has to clear.
r…  Nznames r«  )r§  r‰  rj  )rò  r2  s   & r1   rˆ  rˆ  >	  s;   € ô $ D§M¡M¸$¿+¹+ÔF€FØ9?Ò9KˆV�D—M‘MÑ$ H¨V¨HÐ5ÐUÐQUÐUr3   c                óJ   € V ^8„  d   QhR\         R\        R,          R\        /# )r*   rt  r&   Nr-   )r   r/   r   )r0   s   "r1   r2   r2   L	  s*   € ÷ pñ pœð p¬#°­*ð p¼ñ pr3   c                óZ   € \         P                  ! V P                  \        V 4      VR7      # )zOThe local pool cache's security context for this endpoint/credential/namespace.)ÚendpointrÆ  r&   )r   Úfor_credentialr³  r}  )rt  r&   s   &&r1   r«  r«  L	  s#   € ä×&Ò&°·±ÔDTÐUXÓDYÐenÔoÐor3   r7  Tc                ó¾   € V ^8„  d   QhR\         R\        R\        R,          R\        R,          R\        R,          R\        R,          R\        R	\        R,          /# )
r*   rœ  rÂ  r,  Nr&   rˆ  r  r7  r-   )r   r/   rH   )r0   s   "r1   r2   r2   Q	  sn   € ÷ 3=ñ 3=Ü	ð3=ô ð3=ô ˜•*ð	3=ô
 �T�zð3=ô ��:ð3=ô �$�Jð3=ô ð3=ô 	ˆ4…Zñ3=r3   c               ó  € V\         8X  d   R# V\        8X  d\   V P                  pVe   VP                  f   R# Vf   R# VP                  V8w  d%   RVP                  ;'       g    VP                   R2# VeH   V P
                  e:   V P
                  P                  V8w  d   RV P
                  P                  : RV: 2# V P                  ;'       g    V P                  pVe$   \        V4      \        V4      8w  d   R	V: RV: 2# Ve8   \        V P                  4      V8w  d   R
\        V P                  4      : RV: 2# V P                  e#   \        V P                  4      \        4       8w  d   R# V'       d   \        V 4      # R# )aÒ  Why this Job must not be adopted as one of our pool hosts, or `None`.

Hosts are found by filtering Jobs on labels, and labels are set by whoever
creates the Job -- so a label match says "this Job claims to be one of our
hosts", not "this Job is one of our hosts". Anyone who can create a Job in
the namespace can make that claim, copy the public nonce from a real host's
labels, and receive the token derived for that host.

Everything checked here is asserted by the backend rather than by the Job's
creator: the initiator, the owner, the image, the flavor, the command, and
the exposed URL. `initiator` is the load-bearing one -- there is no
client-side way to set it -- and it is what makes `policy="own"` meaningful.
z/host adoption is disabled (adopt_hosts='never')NzJthe Jobs API did not say who started it, so it cannot be confirmed as ourszHcould not resolve the current principal to compare against its initiatorz"started by a different principal (rV   zruns under namespace z, not zruns image zruns flavor z*does not run the sandbox bootstrap command)r§  r¥  Ú	initiatorru   rˆ   r‡  rŸ  r   rŸ  r/   r  r  rû   Ú_bootstrap_commandr®  )	rœ  rÂ  r,  r&   rˆ  r  r7  r·  Ú	job_images	   &$$$$$$  r1   r/  r/  Q	  sN  € ð. ”ÔÙ@à”ÔØ—M‘Mˆ	ØÒ 	§¡Ò 4Ù_ØÒÙ]Ø�<‰<˜<Ô'Ø7¸	¿¹×8VÐ8VÈ)Ï,É,Ð7WÐWXÐYÐYàÒ §¡Ò!6¸3¿9¹9¿>¹>ÈYÔ;VØ& s§y¡y§~¡~Ñ&8¸¸y¹mÐLÐLà× Ñ ×0Ð0 C§L¡L€IØÒÔ-¨iÓ8Ô<LÈUÓ<SÔSØ˜Y™M¨°©yÐ9Ð9àÒœc #§*¡*›o°Ô7Øœc #§*¡*›oÑ0°°v±jÐAÐAð ‡{�{Òœd 3§;¡;Ó/Ô3EÓ3GÔGÙ;÷ *3Ô  Ó%Ð<¸Ð<r3   c                ó0   € V ^8„  d   QhR\         R\        /# )r*   rt  r-   )r   r/   )r0   s   "r1   r2   r2   ‡	  s   € ÷ ñ œ%ð ¤Cñ r3   c                 ó˜   € \        V P                  \        4      '       d   V P                  M	\        4       pV'       g   \	        R 4      hV# )zMA Hugging Face token is required to use sandboxes. Run `hf auth login` first.)rA   rÆ  r/   r   r   )rt  rÆ  s   & r1   r}  r}  ‡	  s3   € Ü# C§I¡I¬s×3Ò3ˆC�IŠI¼»€EßÜÐjÓkÐkØ€Lr3   c                óè  € V ^8„  d   QhR\         R\        R\        \        \        3,          R,          R\        \        \        3,          R,          R\        \
        ,          R,          R\        \        ,          \        ,          R,          R\        R	\        R
\        \        \        ,          \        \        \        3,          \        \        \        3,          \        \
        ,          3,          /	# )r*   rt  r+   r  Nr  r  r  r  rŠ  r-   )r   r/   rT  r	   r   r   r>   r?   rH   rï   rû   )r0   s   "r1   r2   r2   Ž	  sÄ   € ÷ (Cñ (CÜ	ð(Cäð(Cô 
Œc”3ˆh�˜$Õ	ð	(Cô
 ”#”s�(�^˜dÕ"ð(Cô ”&�\˜DÕ ð(Cô œ•+¤Õ# dÕ*ð(Cô ð(Cô ð(Cô Œ4”�9”dœ3¤˜8•n¤d¬3´¨8¥n´d¼6µlÐBÕCñ(Cr3   c          	     óÖ  € / T;'       g    / CR\        \        4      /Cp/ T;'       g    / CRV/Cp	\        T;'       g    . 4      p
Ve   \        \        V4      4      VR&   V'       d   WR&   R\         2pV P
                   R\        P                   RV 2VR&   \        VR	&   \        VR
&   V
P                  \        R\        P                  \        RR7      4       \        4       W‰V
3# )aŸ  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. Either
way the download is pinned to `SANDBOX_SERVER_SHA256` and verified before it runs.
ÚSBX_PORTÚ	SBX_TOKENrÃ  rä  zsbx-server-z	/buckets/z	/resolve/ÚSBX_SERVER_URLÚSBX_SERVER_SHA256ÚSBX_SERVER_MOUNTÚbucketT)rŠ   r   Ú
mount_pathÚ	read_only)r/   r&  rû   rB   ÚSANDBOX_SERVER_SHA256r³  r   ÚSANDBOX_SERVER_BUCKETÚ_SERVER_MOUNT_PATHrk  r   r¸  )rt  r+   r  r  r  r  r  rŠ  r+  r,  r-  Úserver_objects   &&$$$$$$    r1   r  r  Ž	  sø   € ð( T #§) )¨ÐS¨j¼#Ô>QÓ:RÑS€GØ"Q g§m m°Ð"Q°kÀ=Ñ"Q€KÜ�w—}�} "Ó%€KØÒÜ&)Ô*;¸LÓ*IÓ&JˆÐ"Ñ#ßØ"*�JÑð
 "Ô"7Ð!8Ð9€MØ#&§<¡< .°	¼)×:YÑ:YÐ9ZÐZcÐdqÐcrÐ s€GÐÑÜ#8€GÐÑ ô #5€GÐÑØ×ÑÜ�H¤Y×%DÑ%DÔQcÐosÔtôô Ó °{ÐBÐBr3   c                ó:   € V ^8„  d   QhR\         \        ,          /# rF   rg  )r0   s   "r1   r2   r2   ¹	  s   € ÷ 2ñ 2œD¤�Iñ 2r3   c                 ó   € RR\         .# )z>The Job command every sandbox host and dedicated sandbox runs.z/bin/shz-c)Ú_BOOTSTRAP_DOWNLOADra   r3   r1   r¸  r¸  ¹	  s   € à�tÔ0Ð1Ð1r3   c          
      óx   € V ^8„  d   QhR\         R\        R\        R,          R\        \        \        3,          /# )r*   rt  rœ  r&   Nr-   )r   r   r/   rT  r	   )r0   s   "r1   r2   r2   ¾	  s4   € ÷ ñ ”5ð œwð ´c¸Dµjð ÄTÌ#ÌsÈ(Å^ñ r3   c               ó  € \        VP                  \        4      '       d   VP                  M/ pRV9  dL   V P                  VP                  VR7      P                  ;'       g    / p\        V\        4      '       d   TM/ pV# )z6Return a host job's env vars (where pool config lives)rÅ  rÎ  )rA   ÚenvironmentrT  rÙ  ru   )rt  rœ  r&   r  s   &&$ r1   rÇ  rÇ  ¾	  sb   € ä'¨¯©¼×>Ò>ˆ#�/Š/ÀB€CØ˜SÔ Ø�o‰o S§V¡V°yˆoÓA×MÑM×SÐSÐQSˆÜ ¤T×*Ò*‰c°ˆØ€Jr3   rÂ  c          
      ób   € V ^8„  d   QhR\         R\        R\        R,          R\        R\        /# )r*   rt  rÀ  r&   NrÂ  r-   )r   r/   r   )r0   s   "r1   r2   r2   Ç	  s5   € ÷ "ñ "œUð "¬Sð "ÄÀdÅ
ð "Ô[^ð "Ôovñ "r3   c          
     óú  € RpV\         8X  d#    V P                  RR7      P                  R4      p. pV P                  R\        \        \        V/VR7       F;  p\        WsWBRRR7      pVf   Vu # VP                  VP                   R	V R
24       K=  	  V'       d"   \        RV RRP                  V4       R24      h\        RV R24      h  \         d#   p\        P                  RT 24        Rp?LÅRp?ii ; i)aÁ  Return a running host job belonging to `pool_id`, found via the pool label.

This one feeds `SandboxPool.connect`'s cold path, which rebuilds the pool's
whole configuration (image, flavor, density, caps) from the job it returns --
so an unvalidated match would let a Job in the namespace choose the image
that the pool's *next* hosts boot. Image and flavor are unknown here (they
are what we are about to learn), so this checks ownership and shape.
NTr"  ru   r#  r5  rH  r+  r  rV   z%Found host job(s) labelled for pool 'z' but none usable: r  zp. Pass adopt_hosts='namespace' to SandboxPool if you intend to share hosts with other members of this namespace.rå  ræ  )r¥  r$  ry   re  r'  r(  rM  r#  r;  rN  r/  rk  ru   r   rq  )	rt  rÀ  r&   rÂ  Ú	principalrC  ru  rœ  r2  s	   &&$$     r1   rÆ  rÆ  Ç	  s*  € ð €IØ”Ôð	^ØŸ
™
¨˜
Ó.×2Ñ2°4Ó8ˆIð €HØ�}‰}Ø¤*¬i¼ÀWÐ!MÐYbð ö ˆô !Ø¨YÐSWÐ`dô
ˆð Š>ØŠJØ�‰˜3Ÿ6™6˜( " V H¨AÐ.Ö/ñ÷ ÜØ3°G°9Ð<OÐPT×PYÑPYÐZbÓPcÐOdð e)ð )ó
ð 	
ô
 Ø
*¨7¨)ð 4Kð 	Kóð øô% ô 	^Ü�N‰NÐXÐYZÐX[Ð\×]Ñ]ûð	^ús   �!C ÃC:ÃC5Ã5C:c                óV   € V ^8„  d   QhR\         R\        R\        R,          R\        /# )r*   rt  r<  r&   Nr-   )r   r/   rƒ  )r0   s   "r1   r2   r2   ì	  s-   € ÷ ñ ”uð ¬3ð ¼cÀD½jð ÔTbñ r3   c          	     ó:  € V P                  WR7      pVP                  ;'       g    / pVP                  \        4      pVe   VP                  \        4      \
        8w  d   \        RV R24      hVP                  P                  R8w  d'   \        RV RVP                  P                   R24      h\        V\        RVRRR	7      pVe   \        RV R
V R24      h\        P                  VV\        \        V 4      V4      V \        P                   ^,           R7      # )z?Reattach to a running host job and return its server transport.rÎ  Nr4  z is not a sandbox host.r5  zSandbox host r6  rÖ  r+  z+ does not look like a usable sandbox host: r(   r  )rÙ  r  ry   r%  r#  r;  r   rÚ  rÛ  r/  r¦  rƒ  r£  r;   r}  rª   rú   )rt  r<  r&   rœ  r  r,   r2  s   &&$    r1   r:  r:  ì	  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ô Ø”O°$À)ÐSWÐ`dô€Fð ÒÜ˜T + Ð.YÐZ`ÐYaÐabÐcÓdÐdÜ×"Ñ"ØØÜ+Ô,<¸SÓ,AÀ5ÓIØÜ$×9Ñ9¸AÕ=ð #ó ð r3   c          	      óz   € V ^8„  d   QhR\         R\         R,          R\        \         \         R,          3,          /# )r*   rö  r&   Nr-   )r/   rï   )r0   s   "r1   r2   r2   
  s3   € ÷ *ñ *¤#ð *´#¸µ*ð *ÄÄsÌCÐRVÍJÀÕAWñ *r3   c                óÎ   € RV 9  d   W3# V P                  R^4      w  r#V'       d   V'       d   RV9   d   \        RV : R24      hVe   W8w  d   \        RV: RV: R24      hW23# )zPAccept `namespace/sandbox_id` ids (as shown in the Hub UI), like `hf jobs` does.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=)r9  r   )rö  r&   Úextracted_namespaceÚ	parsed_ids   &&  r1   r7  r7  
  s†   € à
�*ÔØÐ$Ð$Ø%/×%5Ñ%5°c¸1Ó%=Ñ"Ðß§i°3¸)Ô3CÜÐ\Ð]gÑ\jÐjkÐlÓmÐmØÒ Ô!AÜØ3°I±=Ð@bÐcvÑbyÐyzÐ{ó
ð 	
ð Ð)Ð)r3   c                ó0   € V ^8„  d   QhR\         R\        /# r(  r©  )r0   s   "r1   r2   r2   
  s   € ÷ gñ gœ'ð g¤cñ gr3   c                 ó¶   € V P                   P                  ;'       g    .  F  pR \         R2V9   g   K  Vu # 	  \        RV P                   R\         R24      h)r¤  r(   r4  z) does not expose the sandbox server port )rÚ  r¬  r&  r   ru   )rœ  r¡  s   & r1   r¡  r¡  
  s]   € Ø�z‰z×%Ñ%×+Ð+¨Ò+ˆØÔ#Ð$ AÐ&¨#Ö-ØŠJñ ,ô ˜˜cŸf™f˜XÐ%NÔObÐNcÐcdÐeÓ
fÐfr3   Úlimitc          
      ób   € V ^8„  d   QhR\         R\        R\        R,          R\        R\        /# )r*   rt  rj  r&   NrÛ  r-   )r   r/   r>   )r0   s   "r1   r2   r2   
  s<   € ÷ Wñ Wœð W¤sð W¼#À½*ð WÔTWð WÔadñ Wr3   c                ó¸   €  \        V P                  WR 7      4      V) R pT'       d    RRP                  R T 4       4      ,           # R#   \         d     R# i ; i)rÎ  Nr†   z Last logs:
Ú
c              3   ó,   "  € T F
  pR V 2x € K  	  R# 5i)z  Nra   )r2  r`  s   & r1   r4  Ú!_tail_job_logs.<locals>.<genexpr> 
  s   é € Ð&E¹u°t¨¨D¨6¥{»uùs   ‚)rû   Úfetch_job_logsre  rq  )rt  rj  r&   rÛ  Úliness   &&$$ r1   rÝ  rÝ  
  sb   € ðÜ�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iX  i   )Ú	COMPLETEDÚERRORÚDELETEDÚCANCELED)pr8   r5   rx   rš   r'  r×  Úconcurrent.futuresr   Ú
contextlibr   Údataclassesr   r   Úpathlibr   r  r   Útypingr	   r
   r   r   r   r   r   Úurllib.parser   rY  r†   r   Ú_sandbox_cacher   r   r   r   r   r   Ú
_space_apir   Úerrorsr   r   r   Úhf_apir   r   Úutilsr   r   Úutils._parsingr    Ú
get_loggerrb   r'  r&  r"  r#  r$  r;  rN  r%  Ú	frozensetr  r™  ÚSANDBOX_SERVER_VERSIONrÆ  rn  rš  r!  rÈ  r  rj  r¥  r¦  r§  r8  rÜ  rì  rÈ  rÌ  r;   rB   rD   rm   r…   r¨   rª   rW  ra  rh  rp  ÚAuthrr  rƒ  ræ  r€   rœ  rŸ  r§  r®  rˆ  r«  r/  r}  r  r¸  rÇ  rÆ  r:  r7  r¡  rÝ  ra   r3   r1   Ú<module>r÷     s  ðó Û Û Û 	Û Û Ý 1Ý %ß (Ý Ý ß M× MÑ MÝ !ã å ÷÷ õ ß EÑ Eß "ß %Ý *ð 
×	Ò	˜HÓ	%€ð Ð ð €à€
Ø€Ø€	ð €
ð !€á# ]°JÀ
ÈKÐ$XÓYÐ à€ð !Ð ØZÐ ð
 Ð àÐ ØÐ àÐ ð
 Ð ð -Ð ð
 €	Ø€Ø€à€ð AÐ ð Ð ð 'Ð ðÐ õBcõ,$ð ÷sð só ðsð& ÷):ð ):ó ð):ðX ÷ð ó ðð ôó ð÷2eNñ eNõP	õõsõô4�5—:‘:ô ÷.^kñ ^k÷Bñ ÷"Pñ P÷fs
ñ s
õl	õõ RõVõpð
3=ð ÷3=õlõ(CõV2õ
ð"ÈTð "Ðaj÷ "ðJÈ4÷ õ4*õgðWÀtð WÐZ\÷ Wñ Wr3   