+
    lHàjƒ?  ã                  óÄ  a € 0 t $ R t^ RIHt ^ 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HtHt ^ RIHt ^ RIHt ]P(                  ! ]4      tRtR8tRtR	tR
 R ltR R ltR R ltR R lt/ tR] R&   R R lt!R R lt"R R lt#R R lt$Rt%R R lt&Rt'R  R! lt(R" R# lt)R$ R% lt*R& R' lt+R( R) lt,R*R+R,RR-R/R. R/ llt-R0 R1 lt.R2 R3 lt/R4 R5 lt0R6 R7 lt1R# )9a*  Bot Desktop hosted INSIDE the configured terminal backend (docker / ssh / a plugin backend with streams).

Same launcher, same lease, same pane: only WHERE Xvnc + Xfce run changes. ``runtime`` decides between the
gateway host and this module via ``placement()``; callers keep using ``runtime.start/stop/status/desktop_env``.

Layout inside the sandbox, under ``<sandbox tmp>/hermes-bot-desktop/<profile>/``: ``launcher.sh`` (copied in
at start), ``env`` (published DISPLAY/XAUTHORITY/DBUS), ``rfb.sock`` (Xvnc's unix socket), ``launcher.pid``.
Host-side state under ``<HERMES_HOME>/bot-desktop/``: ``sandbox.json`` = ``{"env_key": ..., "display": ...}``
so status() knows which terminal environment owns the screen without re-deriving it.

The Desktop pane never sees a socket path: ``open_rfb_stream()`` returns a Popen whose stdin/stdout ARE the
RFB byte stream, relayed by a 15-line Python script inside the sandbox (python3 is in every sandbox image;
socat is not). cua-driver runs the same way: ``cua_mcp_argv()`` is the docker/ssh prefix + ``cua-driver mcp``.
)ÚannotationsN)ÚPath)ÚAnyÚDictÚOptional©Úget_hermes_home)ÚstreamsÚpnz#nousresearch/hermes-sandbox:desktopa7  import os,socket,sys,threading
s=socket.socket(socket.AF_UNIX);s.connect(sys.argv[1])
def up():
  while True:
    d=os.read(0,65536)
    if not d: break
    s.sendall(d)
  s.shutdown(socket.SHUT_WR)
threading.Thread(target=up,daemon=True).start()
while True:
  d=s.recv(65536)
  if not d: break
  os.write(1,d)
c               ó    € V ^8„  d   QhRRRR/# )é   ÚbackendúOptional[str]Úreturn© )Úformats   "ÚC/home/ubuntu/.hermes/hermes-agent/tools/bot_desktop/sandbox_host.pyÚ__annotate__r   7   s   € ÷ .ñ . ð .°=ñ .ó    c                óH   € ^ RI Hp V '       d   W9   d   R# RV  R\         R2# )zÈHow to get the desktop stack into a plugin backend's sandbox, or None for a built-in backend: a plugin
picks its image through its own settings, so there is no ``terminal.<plugin>_image`` key to name.)Ú_BUILTIN_BACKENDSNz	give the zL plugin's sandbox the desktop stack through the plugin's own image setting (z has it))Útools.terminal_tool_configr   ÚSANDBOX_IMAGE_HINT)r   r   s   & r   Úplugin_image_advicer   7   s0   € õ =ß�gÔ2ÙØ˜�yð !Ü"Ð# 8ð-ð .r   c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r   r   A   s   € ÷ >ñ >�ñ >r   c                 ó2   € \        4       R ,          R,          # )zbot-desktopzsandbox.jsonr   r   r   r   Ú_markerr   A   s   € ÜÓ˜}Õ,¨~Õ=Ð=r   c               ó   € V ^8„  d   QhRR/# )r   r   údict[str, Any]r   )r   s   "r   r   r   E   s   € ÷ ñ �nñ r   c                 ó’   €  \         P                  ! \        4       P                  R R7      4      #   \        \
        3 d    / u # i ; i)z	utf-8-sig©Úencoding)ÚjsonÚloadsr   Ú	read_textÚOSErrorÚ
ValueErrorr   r   r   Ú_read_markerr'   E   s?   € ðÜ�zŠzœ'›)×-Ñ-°{Ð-ÓCÓDÐDøÜ”ZÐ ô ØŠ	ðús   ‚-0 °AÁAc               ó    € V ^8„  d   QhRRRR/# )r   Úenvr   r   r   r   )r   s   "r   r   r   L   s   € ÷ ñ ˜ð  ñ r   c                ó†   € R\        V 4      P                  /p\        V RR4      pV'       d   W!R&   \        V RR4      VR&   V# )zªWhat the marker records about the sandbox hosting the screen, so a restarted gateway (empty terminal
registry) can tell a still-running sandbox from one that was removed.r   Ú_container_idNÚ	containerÚ_docker_exeÚdocker)ÚtypeÚ__name__Úgetattr)r)   Úidentr,   s   &  r   Ú_owner_identityr3   L   sH   € ð '¬¨S«	×(:Ñ(:Ð;€EÜ˜˜_¨dÓ3€IßØ&ˆkÑÜ! # }°hÓ?ˆˆh‰Ø€Lr   zdict[str, tuple[float, bool]]Ú_ALIVE_CACHEc               ó    € V ^8„  d   QhRRRR/# )r   Úmarkerr   r   Úboolr   )r   s   "r   r   r   Z   s   € ÷ ñ  ð °Dñ r   c           	     ó.  € V P                  R4      pV'       g   R# \        P                  ! 4       p\        P                  V4      pV'       d   W#^ ,          ,
          R8  d
   V^,          #  \        P
                  ! V P                  R4      ;'       g    RRRRV.RR^R\        P                  R	7      pVP                  ^ 8H  ;'       d    VP                  P                  4       R
8H  pW%3\        V&   V#   \        \        P                  3 d    Rp L+i ; i)aa  Whether the sandbox a marker names still exists. Docker: ``docker inspect`` on the recorded container
(cached a few seconds; this sits on the browser's per-command path). Other backends (ssh host, apptainer
instance) cannot be probed from here without their environment object: the re-attach's own
``published_env`` probe decides, so they read as alive.r,   Tg      @r.   Úinspectz-fz{{.State.Running}}F)Úcapture_outputÚtextÚtimeoutÚcheckÚstdinÚtrue)ÚgetÚtimeÚ	monotonicr4   Ú
subprocessÚrunÚDEVNULLÚ
returncodeÚstdoutÚstripr%   ÚTimeoutExpired)r6   r,   ÚnowÚcachedÚprocÚalives   &     r   Úmarker_sandbox_aliverN   Z   sñ   € ð
 —
‘
˜;Ó'€IßÙÜ
�.Š.Ó
€CÜ×Ñ˜iÓ(€Fß�#˜q�	•/ CÔ'Ø�a�yÐðÜ�~Š~˜vŸz™z¨(Ó3×?Ð?°xÀÈDÐRfÐhqÐrØ-1¸ÀbÐPUÔ]g×]oÑ]oôqˆà—‘ 1Ñ$×FÐF¨¯©×):Ñ):Ó)<ÀÑ)Fˆð  #˜l„L�ÑØ€Løô ”Z×.Ñ.Ð/ô ØŠðús   Á,'C4 Â5C4 Ã
C4 Ã4DÄDc               ó$   € V ^8„  d   QhRRRRRR/# )r   r)   r   ÚprofileÚstrr   r   )r   s   "r   r   r   p   s&   € ÷ Wñ W�Sð W 3ð W¨3ñ Wr   c                óV   € \         P                  ! V 4      P                  R 4       RV 2# )Ú/z/hermes-bot-desktop/)r	   Úsandbox_temp_dirÚrstrip©r)   rP   s   &&r   Ú_remote_dirrW   p   s+   € Ü×&Ò& sÓ+×2Ñ2°3Ó7Ð8Ð8LÈWÈIÐVÐVr   c               ó    € V ^8„  d   QhRRRR/# ©r   r)   r   r   rQ   r   )r   s   "r   r   r   t   s   € ÷ ñ �cð ˜cñ r   c                óz  € \        V RR4      pV'       d   V# \        P                  ! V . R
O\        V 4      ^R7      pVP                  ^ 8X  d+   VP
                  P                  RR4      P                  4       MRpV'       d   VP                  R4      '       g   \        V 4      '       d
   R\         2MR	pW0n
        V# )aa  ``$HOME`` of the user the desktop and the browser run as inside ``env`` (cached on the env). This
is where state that must outlive a container stop goes: ``/tmp`` in the Docker backend is a 512 MB
tmpfs that is emptied on every stop and shared with the sandbox's scratch, so a browser profile
(logins, cookies) there would vanish and grow into that cap.Ú_bd_desktop_homeN©Úuserr<   úutf-8ÚreplaceÚ rS   z/home/z/root)Úbashú-czprintf %s "$HOME")r1   r	   Úrun_inÚ	_user_forrF   rG   ÚdecoderH   Ú
startswithÚDESKTOP_USERr[   )r)   rK   rL   Úhomes   &   r   Údesktop_homeri   t   s–   € ô
 �SÐ,¨dÓ3€FßØˆÜ�>Š>˜#ÒBÌÐSVËÐacÔd€DØ=A¿_¹_ÐPQÔ=Qˆ4�;‰;×Ñ˜g yÓ1×7Ñ7Ô9ÐWY€Dß�t—‘ s×+Ò+Ü*3°C¯.ª.�œ�~Ñ&¸gˆØÔØ€Kr   c               ó    € V ^8„  d   QhRRRR/# rY   r   )r   s   "r   r   r   „   s   € ÷ Rñ R˜Sð R Sñ Rr   c                ó<   € \        V 4      P                  R4       R2# )zÉThe ONE ``--user-data-dir`` the agent's agent-browser and the dock's Browser icon share inside the
sandbox (same rule as the host: two profiles would mean the human logs into a jar the bot never sees).rS   z$/.hermes/bot-desktop/browser-profile)ri   rU   )r)   s   &r   Úbrowser_profile_dirrl   „   s#   € ô ˜3Ó×&Ñ& sÓ+Ð,Ð,PÐQÐQr   a  for d in "${PLAYWRIGHT_BROWSERS_PATH:-}" /opt/playwright "$HOME/.cache/ms-playwright"; do [ -n "$d" ] || continue; for c in "$d"/chromium-*/chrome-linux/chrome "$d"/chromium-*/chrome-linux64/chrome; do [ -x "$c" ] && { printf %s "$c"; exit 0; }; done; done; exit 1c               ó    € V ^8„  d   QhRRRR/# ©r   r)   r   r   r   r   )r   s   "r   r   r   ’   s   € ÷ 	ñ 	˜Sð 	 ]ñ 	r   c                ó6  € \        V RR4      pVR8w  d   V# \        P                  ! V RR\        .\	        V 4      ^R7      pVP
                  ^ 8X  d+   VP                  P                  RR4      P                  4       MRpT;'       g    R	V n	        V P                  # )
z©Path of the Playwright Chromium agent-browser uses inside ``env`` (the dock's Browser icon must run
the same binary), or None when the image has none. Cached on the env.Ú_bd_chromiumÚunsetra   rb   r\   r^   r_   r`   N)
r1   r	   rc   Ú_CHROMIUM_PROBErd   rF   rG   re   rH   rp   )r)   rK   rL   Úexes   &   r   Úchromium_executablert   ’   s†   € ô �S˜.¨'Ó2€FØ�ÔØˆÜ�>Š>˜# ¨¬oÐ>ÄYÈsÃ^Ð]_Ô`€DØ<@¿O¹OÈqÔ<Pˆ$�+‰+×
Ñ
˜W iÓ
0×
6Ñ
6Ô
8ÐVX€CØ—{�{˜d€CÔØ×ÑÐr   a  
import io, sys
from PIL import ImageGrab
img = ImageGrab.grab(xdisplay=sys.argv[1])
img.thumbnail((int(sys.argv[2]), int(sys.argv[3])))
buf = io.BytesIO()
img.convert("RGB").save(buf, "JPEG", quality=int(sys.argv[4]), optimize=True)
sys.stdout.buffer.write(buf.getvalue())
c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r   r)   r   Ú	publishedúdict[str, str]Úmax_sizeztuple[int, int]ÚqualityÚintr   zOptional[bytes]r   )r   s   "r   r   r   ©   s1   € ÷ ñ �3ð  >ð ¸_ð ÐWZð Ð_nñ r   c                ó²  € VP                  R4      pV'       g   R# VP                  4        UUu/ uF  w  rVVR
9   g   K  WVbK  	  ppp \        P                  ! V RR\        V\        V^ ,          4      \        V^,          4      \        V4      .V\        V 4      ^R7      pTP                  ^ 8w  g"   TP                  P                  R4      '       g6   \        P                  RTP                  P!                  RR	4      RR 4       R# TP                  # u uppi   \        \        P                  3 d"   p	\        P                  RT	4        Rp	?	R# Rp	?	ii ; i)zÀOne JPEG of the sandbox screen, grabbed INSIDE the sandbox (the X socket and its cookie live there).
Needs Pillow in the image (the published desktop image ships it); None when the grab fails.ÚDISPLAYNÚpython3rb   ©Ú	child_envr]   r<   zsandbox screen grab failed: %ss   ÿØr^   r_   )r|   Ú
XAUTHORITYiÔþÿÿ)r@   Úitemsr	   rc   Ú_GRAB_SCRIPTrQ   rd   r%   rC   ÚSubprocessErrorÚloggerÚdebugrF   rG   rf   Ústderrre   )
r)   rv   rx   ry   ÚdisplayÚkÚvr   rL   Úexcs
   &&&&      r   Ú	grab_jpegr‹   ©   s%  € ð �m‰m˜IÓ&€GßÙØ"+§/¡/Ô"3ÔVÑ"3™$˜!°qÐ<UÑ7U”�’Ñ"3€IÑVðÜ�~Š~˜c I¨t´\À7ÌCÐPXÐYZÕP[ÓL\Ô^aÐbjÐklÕbmÓ^nÜ$'¨£Lð$2Ø=FÌYÐWZË^Ðegôiˆð
 ‡�˜!Ô 4§;¡;×#9Ñ#9¸+×#FÒ#FÜ�‰Ð5°t·{±{×7IÑ7IÈ'ÐS\Ó7]Ð^bÐ^cÐ7dÔeÙØ�;‰;Ðùó Wøô ”Z×/Ñ/Ð0ô Ü�‰Ð5°sÔ;Ýûðús#   ¯D¿DÁ	AD ÄEÄ5EÅEc               ó    € V ^8„  d   QhRRRR/# rn   r   )r   s   "r   r   r   ¼   s   € ÷ ñ �3ð ˜=ñ r   c                ó°   € \        V RR4      pVR8w  d   V# \        P                  ! V RR\        .^R7      pVP                  ^ 8X  d   \        MRpW0n        V# )zYDESKTOP_USER when the sandbox has it, else None (exec default). Cached on the env object.Ú_bd_desktop_userrq   Úidz-u)r<   N)r1   r	   rc   rg   rF   rŽ   )r)   rK   Úprober]   s   &   r   rd   rd   ¼   sV   € ä�SÐ,¨gÓ6€FØ�ÔØˆÜ�NŠN˜3  t¬\Ð :ÀBÔG€EØ ×+Ñ+¨qÔ0�<°d€DØÔØ€Kr   c               ó    € V ^8„  d   QhRRRR/# )r   r)   r   r   z	list[str]r   )r   s   "r   r   r   Ç   s   € ÷ Lñ L˜#ð L )ñ Lr   c                ó$  € R RP                  \        4      ,           R,           p\        P                  ! V RRV.\	        V 4      ^R7      pVP
                  P                  RR4      P                  4        Uu. uF  q3'       g   K  VNK  	  up# u upi )z	for b in Ú z7; do command -v "$b" >/dev/null 2>&1 || echo "$b"; donera   rb   r\   r^   r_   )ÚjoinÚ	_REQUIREDr	   rc   rd   rG   re   Úsplit)r)   ÚscriptrL   Úbs   &   r   Úmissing_binariesr™   Ç   ss   € Ø˜3Ÿ8™8¤IÓ.Õ.Ð1jÕj€FÜ�>Š>˜# ¨¨fÐ5¼IÀc»NÐTVÔW€DØ—{‘{×)Ñ)¨'°9Ó=×CÑCÔEÓKÑE�!Ë�AˆAÑEÑKÐKùÒKs   Á6	BÂBc               ó$   € V ^8„  d   QhRRRRRR/# )r   r)   r   ÚrdirrQ   r   rw   r   )r   s   "r   r   r   Í   s!   € ÷ ñ �Cð ˜sð  ~ñ r   c                óæ  € \         P                  ! V R RR\        P                  ! V4       R\        P                  ! V4       R\        P                  ! V4       R2.\	        V 4      ^R7      pVP
                  ^ 8w  d   / # / pVP                  P                  RR4      P                  4        FA  pVP                  R	4      w  rVpV'       g   K!  VP                  4       W5P                  4       &   KC  	  V# )
ra   rb   zkill -0 $(cat z2/launcher.pid 2>/dev/null) 2>/dev/null && test -S z/rfb.sock && cat ú/envr\   r^   r_   Ú=)r	   rc   ÚshlexÚquoterd   rF   rG   re   Ú
splitlinesÚ	partitionrH   )r)   r›   rL   ÚoutÚlinerˆ   Úsepr‰   s   &&      r   Ú
_publishedr¦   Í   sÖ   € Ü�>Š>˜# ¨°¼u¿{º{È4Ó?PÐ>Qð R;Ü;@¿;º;ÀtÓ;LÐ:MÐM^Ô_d×_jÒ_jÐkoÓ_pÐ^qÐquð/wð  xä(¨›~°rô;€Dð ‡�˜!ÔØˆ	Ø€CØ—‘×"Ñ" 7¨IÓ6×AÑAÖCˆØ—N‘N 3Ó'‰	ˆ�ß‰3ØŸW™W›YˆC—‘“	‹Nñ Dð €Jr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r)   r   rP   rQ   r   rw   r   )r   s   "r   r   r   Û   s!   € ÷ 6ñ 6�sð 6 Sð 6¨^ñ 6r   c                ó,   € \        V \        W4      4      # )N)r¦   rW   rV   s   &&r   Úpublished_envr©   Û   s   € Ü�cœ; sÓ4Ó5Ð5r   Úwait_secondsg      4@Úbrowser_execÚbrowser_exec_linec               ó4   € V ^8„  d   QhRRRRRRRRRR	R
R	RR/# )r   r)   r   rP   rQ   Úgeometryrª   Úfloatr«   r   r¬   r   rw   r   )r   s   "r   r   r   ß   s@   € ÷ ;=ñ ;=ˆsð ;=˜Sð ;=¨sð ;=À%ð ;=Ø%ð;=ØANð;=ØZhñ;=r   c               ó®  € \        W4      p\        W4      pVP                  R4      '       d   \        WW4      # \	        W4       \        V 4      pV'       dJ   \        \        V RR4      4      ;'       g    R\         R2p	\        RRP                  V4       RV	 R	24      h\        V 4      p
\        \        4      P                  R
4      P                  4       p\        \        4      P                  R4      P                  4       pR\         P"                  ! V4       R\         P"                  ! V4       R\         P"                  ! V4       R\         P"                  ! \$        P&                  ! V4      P)                  4       4       R\         P"                  ! \$        P&                  ! V4      P)                  4       4       R2p\*        P,                  ! V RRV.V
^R7      pVP.                  ^ 8w  d,   \        RVP0                  P)                  RR4      R3R  24      h^pRVR\3        V4      RV R2RV R2RV R2R V R!2R"VR#V R$2/pV'       d   V'       d   VVR%&   VVR&&   R'\         P"                  ! V4       R(2p\*        P,                  ! V RRV.VV
^R)7      pVP.                  ^ 8w  d,   \        R*VP0                  P)                  RR4      R3R  24      h\4        P6                  ! 4       V,           p\4        P6                  ! 4       V8  dy   \        W4      pVP                  R4      '       d?   \8        P;                  R+V\=        V 4      P>                  VR,          4       \        WW4      # \4        P@                  ! R,4       K’  \*        P,                  ! V R-RR.V R/2.V
^
R7      PB                  p\	        W4       \        R0VR1 R2VP)                  RR4       24      h)4zsBring the screen up inside ``env`` (idempotent); returns the published env. Raises RuntimeError naming
the blocker.r|   Ú_hermes_backend_nameNzuse zY (the default sandbox base plus the desktop stack) as terminal.docker_image / modal_imagezBot Desktop needs z, zQ inside the terminal backend's sandbox. The configured image does not have them; z(, or set bot_desktop.placement: gateway.zlauncher.shzwallpaper.pngzset -e; rm -rf z; mkdir -p z; cd z; echo z! | base64 -d > launcher.sh; echo z6 | base64 -d > wallpaper.png; chmod 0700 . launcher.shra   rb   r\   z(could not seed the sandbox desktop dir: r^   r_   ÚHERMES_BD_PROFILEÚHERMES_BD_DISPLAY_NUMÚHERMES_BD_SOCKETú	/rfb.sockÚHERMES_BD_XAUTHz/XauthorityÚHERMES_BD_ENV_FILEr�   ÚHERMES_BD_CONFIG_HOMEz/xdgÚHERMES_BD_GEOMETRYÚHERMES_BD_WALLPAPERz/wallpaper.pngÚHERMES_BD_BROWSER_EXECÚHERMES_BD_BROWSER_EXEC_LINEzcd zË && setsid -f bash -c 'echo $$ > launcher.pid; exec bash launcher.sh' > launcher.log 2>&1 < /dev/null; for _ in 1 2 3 4 5 6 7 8 9 10; do [ -s launcher.pid ] && break; sleep 0.1; done; [ -s launcher.pid ]r~   z(sandbox desktop launcher did not start: z-Bot Desktop for profile %s up inside %s on %sg      Ð?ÚtailÚ2000z/launcher.logz3sandbox desktop did not publish its display within z.0fzs:
iþÿÿ)"rW   r¦   r@   Ú_recordÚstopr™   r   r1   r   ÚRuntimeErrorr”   rd   r   Ú__file__Ú	with_nameÚ
read_bytesrŸ   r    Úbase64Ú	b64encodere   r	   rc   rF   r†   rQ   rA   rB   r„   Úinfor/   r0   ÚsleeprG   )r)   rP   r®   rª   r«   r¬   r›   ÚliveÚmissingÚadvicer]   ÚlauncherÚ	wallpaperÚseedrL   Únumr   ÚspawnÚdeadliner½   s   &&$$$$              r   ÚstartrÒ   ß   sÂ  € ô �sÓ$€DÜ�cÓ €DØ‡x�x�	×Òô �s 'Ó0Ð0ÜˆÔÜ˜sÓ#€GßÜ$¤W¨SÐ2HÈ$Ó%OÓP÷ 4ð 4ØÔ%Ð&ð '2ð 3ð 	ô Ø  §¡¨7Ó!3Ð 4ð 5#Ø#) (Ð*RðTóUð 	Uô �S‹>€DÜ”X“×(Ñ(¨Ó7×BÑBÓD€HÜ”X“×(Ñ(¨Ó9×DÑDÓF€Ià
œ%Ÿ+š+ dÓ+Ð,¨K¼¿ºÀDÓ8IÐ7JÈ%ÔPU×P[ÒP[Ð\`ÓPaÐObð cÜ—’œV×-Ò-¨hÓ7×>Ñ>Ó@ÓAÐBð CÜ—’œV×-Ò-¨iÓ8×?Ñ?ÓAÓBÐCð D$ð	$ð 	ô �>Š>˜# ¨¨dÐ3¸$ÈÔK€DØ‡�˜!ÔÜÐEÀdÇkÁk×FXÑFXÐY`ÐbkÓFlÐmqÐmrÐFsÐEtÐuÓvÐvØ
€Cà˜WÐ&=¼sÀ3»xÐI[Ð`dÐ_eÐenÐ]oØ˜d˜V ;Ð/Ð1EÈ$ÈÈtÀ}Ø D 6¨ Ð0DÀhÐPeÐjnÐioÐo}Ðg~ð€I÷
 ×)Ø.:ˆ	Ð*Ñ+Ø3Dˆ	Ð/Ñ0ð ”5—;’;˜tÓ$Ð%ð &tð u€Eô �>Š>˜# ¨¨eÐ4À	ÐPTÐ^`Ôa€DØ‡�˜!ÔÜÐEÀdÇkÁk×FXÑFXÐY`ÐbkÓFlÐmqÐmrÐFsÐEtÐuÓvÐvÜ�~Š~Ó ,Õ.€HÜ
�.Š.Ó
˜XÔ
%Ü˜#Ó$ˆØ�8‰8�I×ÒÜ�K‰KÐGÈÔRVÐWZÓR[×RdÑRdÐfjÐktÕfuÔvÜ˜3 gÓ4Ð4Ü�
Š
�4ÖÜ�>Š>˜# ¨¨f¸¸¸mÐ6LÐMÐTXÐbdÔe×lÑl€DÜˆÔÜ
ÐLÈ\ÐZ]ÐL^Ð^bØŸ+™+ g¨yÓ9Ð:ð<ó =ð =r   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r)   r   r›   rQ   rP   rÉ   rw   r   r   )r   s   "r   r   r     s/   € ÷ ñ �ð ˜Cð ¨#ð °^ð Èñ r   c           
     óÞ   € \        4       P                  P                  R R R7       \        4       P                  \        P
                  ! RVR,          RVRV/\        V 4      C4      RR7       V# )T)ÚparentsÚexist_okr‡   r|   ÚdirrP   r^   r    )r   ÚparentÚmkdirÚ
write_textr"   Údumpsr3   )r)   r›   rP   rÉ   s   &&&&r   r¿   r¿     si   € ÜƒI×Ñ×Ñ 4°$ÐÔ7ÜƒI×ÑœŸš Y°°YµÀÈÈiÐY`ð %=Ü'6°sÓ';ð%=ó >ØHOð ô Qà€Kr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r)   r   rP   rQ   r   r7   r   )r   s   "r   r   r   $  s!   € ÷  ñ  ˆcð  ˜Cð   Dñ  r   c                óx  € \        W4      p\        P                  ! V4      pRV R\        P                  ! VR,           4       R\        P                  ! VR,           4       RV RV RV R2p\        P                  ! V R	R
V.\        V 4      ^R7      p\        4       P                  RR7       VP                  ^ 8H  # )a8  Kill the launcher's session (Xvnc, dbus, Xfce, anything the desktop spawned) and, as a backstop, every
process still holding this profile's rfb.sock or Xauthority path (a launcher that lost its pid file left
an Xvnc that 'Server is already active for display 20' on the next start). True when something was live.z
live=0
p=$(cat z°/launcher.pid 2>/dev/null)
if [ -n "$p" ] && kill -0 "$p" 2>/dev/null; then live=1; kill -TERM -- -"$p" 2>/dev/null || kill -TERM "$p" 2>/dev/null; fi
for pid in $(pgrep -f -- rS   z| 2>/dev/null); do [ "$pid" != "$$" ] && { live=1; kill -TERM "$pid" 2>/dev/null; }; done
sleep 0.5
for pid in $(pgrep -f -- zR 2>/dev/null); do [ "$pid" != "$$" ] && kill -KILL "$pid" 2>/dev/null; done
rm -f z/env z/launcher.pid z/rfb.sock
[ "$live" = 1 ]
ra   rb   r\   T)Ú
missing_ok)	rW   rŸ   r    r	   rc   rd   r   ÚunlinkrF   )r)   rP   r›   Úqr—   rL   s   &&    r   rÀ   rÀ   $  s¼   € ô �sÓ$€DÜ�Š�DÓ€Að	à	
ˆð äŸ+š+ d¨S¥jÓ1Ð2ð 3äŸ+š+ d¨S¥jÓ1Ð2ð 3Ø€cˆˆqˆc� ˜sð #ð	€Fô �>Š>˜# ¨¨fÐ5¼IÀc»NÐTVÔW€DÜƒI×Ñ ÐÔ%Ø�?‰?˜aÑÐr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r)   r   rP   rQ   r   zsubprocess.Popenr   )r   s   "r   r   r   9  s'   € ÷ hñ h˜ð h sð hÐ/?ñ hr   c                ór   € \        W4      p\        P                  ! V RR\        V R2.\	        V 4      R7      # )zCPopen whose stdin/stdout carry the RFB bytes of the sandbox's Xvnc.r}   rb   rµ   )r]   )rW   r	   Úopen_streamÚ_RELAYrd   )r)   rP   r›   s   && r   Úopen_rfb_streamrå   9  s8   € ä�sÓ$€DÜ×Ò˜s Y°´fÀÀÀiÐ>PÐ$QÔXaÐbeÓXfÔgÐgr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r)   r   rP   rQ   rv   rw   r   ztuple[str, list[str]]r   )r   s   "r   r   r   ?  s)   € ÷ ñ ˜Cð ¨#ð ¸.ð ÐMbñ r   c                ó¼   € \         P                  ! V . ROV\        V 4      RR7      pVf"   \        \	        V 4      P
                   R24      hV^ ,          VR,          3# )z``(command, args)`` for ``StdioServerParameters``: the backend's exec prefix running ``cua-driver mcp`` on
the sandbox display.T)r   r]   Úinteractivez cannot host cua-driver:é   NN)z
cua-driverÚmcpz--no-overlay)r	   Úremote_commandrd   rÁ   r/   r0   )r)   rP   rv   Úargvs   &&& r   Úcua_mcp_invocationrí   ?  s\   € ô ×!Ò! #Ò'LÐXaÜ'0°£~À4ôI€Dà‚|Üœd 3›i×0Ñ0Ð1Ð1HÐIÓJÐJØ��7�D˜•HÐÐr   )	ÚXvncÚxfwm4zxfce4-panelÚ	xfdesktopÚxfsettingsdzdbus-run-sessionÚxauthÚxdpyinfoÚxprop)2Ú__conditional_annotations__Ú__doc__Ú
__future__r   rÅ   r"   ÚloggingrŸ   rC   rA   Úpathlibr   Útypingr   r   r   Úhermes_constantsr   Útools.environmentsr	   Ú	getLoggerr0   r„   rg   r•   r   rä   r   r   r'   r3   r4   Ú__annotations__rN   rW   ri   rl   rr   rt   r‚   r‹   rd   r™   r¦   r©   rÒ   r¿   rÀ   rå   rí   )rõ   s   @r   Ú<module>rÿ      s÷   øðôõ #ã Û Û Û Û Û Ý ß &Ñ &å ,Ý &à	×	Ò	˜8Ó	$€ð
 €Øz€	Ø:Ð ðð õ".õ>õõð /1€Ð+Ó 0õõ,Wõõ RðFð õ	ð€õõ&õLõõ6ð;=È$ð ;=Ø(,ð;=ØQU÷;=õ|õ õ*h÷r   