§
    ‰eîiçf ã                   ó>  — U d Z ddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZ ddlmZmZmZmZ  ej        e¦  «        ZddlmZmZ ddlmZ ddlmZmZmZm Z  de!d	ed
e!fd„Z" e"dde#d¦  «        Z$ e"dde%d¦  «        Z&d„ Z'da(e!e)d<   ddl	Z	 e	j*        ¦   «         Z+d„ Z,d„ Z-d„ Z.d„ Z/ddl0m1Z2 de!de!de3fd„Z4 ej5        d¦  «        Z6de!de!dz  fd „Z7d!e!de!de!fd"„Z8d¿d$e#de!fd%„Z9dÀded'e#de!fd(„Z:d)e!de;fd*„Z<de!d+e#de=e!e#f         fd,„Z>de!de=e!e;f         fd-„Z?de!de!fd.„Z@de!dz  de=e!dz  e!dz  f         fd/„ZAdd0lBmCZD dd1lmEZF dd2lGmHZI dd3lJmKZL dd4lMmNZO dd5lPmQZR dd6lSmTZT d7ZUi ZVee!ef         e)d8<   i ZWee!e%f         e)d9<    e	jX        ¦   «         ZYi ZZee!e	jX        f         e)d:<    e	jX        ¦   «         Z[da\d;a]i Z^ee!ee!ef         f         e)d<<   d=e!d>ee!ef         fd?„Z_d=e!fd@„Z`d=ee!         de!fdA„Zae#dfde!d	e!d
e!fdB„Zbdee!ef         fdC„ZcdDeddz  dee!ef         fdE„Ze	 	 	 	 dÁde!dFe!dGe!dHe#dIe3dJe3dKe3d=e!dLe!fdM„ZfdÂdOe#fdP„ZgdQ„ ZhdR„ ZidS„ Zjd=e!fdT„Zkd=e!de;fdU„ZldV„ Zmd=e!fdW„ZndX„ Zo e
jp        eo¦  «         de!dYe#de!dz  fdZ„Zqde!de;fd[„Zr ej5        d\ejs        ¦  «        Zt ej5        d]¦  «        Zu ej5        d^¦  «        Zv ej5        d_ejs        ¦  «         ej5        d`ejs        ¦  «         ej5        daejs        ¦  «         ej5        dbejs        ¦  «         ej5        dcejs        ¦  «         ej5        ddejs        ¦  «         ej5        deejs        ¦  «         ej5        dfejs        ¦  «        fZwde!de;fdg„Zxde!de!dz  fdh„Zydie;dje;de=fdk„Zz	 	 	 	 	 	 	 	 dÃde!dje;dHee#         d=ee!         dle;dee!         dme;die;dneee!                  de!fdo„Z{de;fdp„Z|edqk    �r\ e}dr¦  «          e}ds¦  «          ec¦   «         Z~ e}dt¦  «          e}due~d         › �¦  «          e}dve~dw         › �¦  «          e}dxe~dy         › �¦  «          e}dze~dG         › �¦  «          e}d{e~dH         › d|�¦  «          e}d}e~dO         › d|�¦  «          e|¦   «         s e}d~¦  «          ed¦  «          e}d€¦  «          e}d�¦  «          e}d‚¦  «          e}dƒ¦  «          e}d„¦  «          e}d…¦  «          e}d†¦  «          e}d‡¦  «          e}dˆ¦  «          e}d‰¦  «         dŠZ€ e}d‹ ej�        dŒd�¦  «        › dŽ�¦  «          e}d� ej�        d�e€¦  «        › �¦  «          e}d‘ ej�        d’d“e€› �¦  «        › �¦  «          e}d” ej�        d•e€¦  «        › �¦  «          e}d– ej�        d—e€¦  «        › �¦  «          e}d˜ ej�        d™ ej‚        ¦   «         ¦  «        › �¦  «         ddšlƒm„Z…  e}d› ej�        dœ e…¦   «         › d��¦  «        › �¦  «          e}dž ej�        dŸd ¦  «        › �¦  «          e}d¡ ej�        d¢d£¦  «        › �¦  «         dd¤l†m‡Z‡ d¥eUd¦d§d¨d©œdªd«d;d¬œdd­e$› d®e$› d¯�dd°œd§d±d©œdªd²d;d¬œdªd³d;d¬œd´dµd§id¶d·œd¸œdgd¹œdºœZˆd»„ Z‰ e‡jp        d¥d¥eˆe‰e|d¼d½¬¾¦  «         dS )Äaf  
Terminal Tool Module

A terminal tool that executes commands in local, Docker, Modal, SSH, Singularity, and Daytona environments.
Supports local execution, containerized backends, and Modal cloud sandboxes, including managed gateway mode.

Environment Selection (via TERMINAL_ENV environment variable):
- "local": Execute directly on the host machine (default, fastest)
- "docker": Execute in Docker containers (isolated, requires Docker)
- "modal": Execute in Modal cloud sandboxes (direct Modal or managed gateway)

Features:
- Multiple execution backends (local, docker, modal)
- Background task support
- VM/container lifecycle management
- Automatic cleanup after inactivity

Cloud sandbox note:
- Persistent filesystems preserve working state across sandbox recreation
- Persistent filesystems do NOT guarantee the same live sandbox or long-running processes survive cleanup, idle reaping, or Hermes exit

Usage:
    from terminal_tool import terminal_tool

    # Execute a simple command
    result = terminal_tool("ls -la")

    # Execute in background
    result = terminal_tool("python server.py", background=True)
é    N)ÚPath)ÚOptionalÚDictÚAnyÚList)Úis_interruptedÚ_interrupt_event)Ú_get_scratch_dir)Úcoerce_modal_modeÚhas_direct_modal_credentialsÚmanaged_nous_tools_enabledÚresolve_modal_backend_stateÚnameÚdefaultÚ
type_labelc                 óÄ   — t          j        | ¦  «        }|�|dk    r|S 	  ||¦  «        S # t          t          f$ r# t                               d| |||¦  «         |cY S w xY w)záParse module-level numeric env vars without breaking import.

    Terminal tool is imported by CLI, ACP, tests, and tool discovery. A single
    malformed env var must not make the whole module unloadable at import time.
    NÚ z;Invalid value for %s: %r (expected %s). Falling back to %r.)ÚosÚgetenvÚ	TypeErrorÚ
ValueErrorÚloggerÚwarning©r   r   Ú	converterr   Úraws        ú5/home/div/.hermes/hermes-agent/tools/terminal_tool.pyÚ_safe_parse_import_envr   K   s†   € õ Œ)�D‰/Œ/€CØ
€{�c˜R’i�iØˆð
Øˆy˜‰~Œ~ÐøÝ•zÐ"ð ð ð Ý�ŠØIØØØØñ	
ô 	
ð 	
ð ˆˆˆðøøøs    
+ «1AÁAÚTERMINAL_MAX_FOREGROUND_TIMEOUTiX  ÚintegerÚTERMINAL_DISK_WARNING_GBg     @@Únumberc                  ód  — 	 t          ¦   «         } d}ddl}|                     t          | dz  ¦  «        ¦  «        D ]Œ}t          |¦  «                             d¦  «        D ]g}|                     ¦   «         rQ	 ||                     ¦   «         j        z  }Œ4# t          $ r&}t           
                    d||¦  «         Y d}~Œ_d}~ww xY wŒhŒ�|dz  }|t          k    r#t                               d|t          ¦  «         dS d	S # t          $ r(}t           
                    d
|d¬¦  «         Y d}~d	S d}~ww xY w)z4Check if total disk usage exceeds warning threshold.r   Núhermes-*Ú*zCould not stat file %s: %si   @z\Disk usage (%.1fGB) exceeds threshold (%.0fGB). Consider running cleanup_all_environments().TFz#Disk usage warning check failed: %s©Úexc_info)r
   ÚglobÚstrr   ÚrglobÚis_fileÚstatÚst_sizeÚOSErrorr   ÚdebugÚDISK_USAGE_WARNING_THRESHOLD_GBr   Ú	Exception)Úscratch_dirÚtotal_bytesr(   ÚpathÚfÚeÚtotal_gbs          r   Ú_check_disk_usage_warningr8   w   s}  € ðÝ&Ñ(Ô(ˆð ˆØˆˆˆØ—I’I�c +°
Ñ":Ñ;Ô;Ñ<Ô<ð 	Ið 	IˆDÝ˜$‘Z”Z×%Ò% cÑ*Ô*ð Ið I�Ø—9’9‘;”;ð IðIØ# q§v¢v¡x¤xÔ'7Ñ7˜˜øÝ"ð Ið Ið IÝŸšÐ%AÀ1ÀaÑHÔHÐHÐHÐHÐHÐHÐHøøøøðIøøøðIðIð  )Ñ,ˆàÕ5Ò5Ð5Ý�NŠNÐyØ#Õ%DñFô Fð Fà�4àˆuøÝð ð ð Ý�ŠÐ:¸AÈˆÑMÔMÐMØˆuˆuˆuˆuˆuøøøøðøøøsB   ‚A3C= Á6BÂC= Â
CÂB>Â9C= Â>CÃ6C= Ã=
D/ÄD*Ä*D/r   Ú_cached_sudo_passwordc                  ó.   — t          t          dd ¦  «        S )NÚsudo_password©ÚgetattrÚ_callback_tls© ó    r   Ú_get_sudo_password_callbackrA   §   s   € Ý•= /°4Ñ8Ô8Ð8r@   c                  ó.   — t          t          dd ¦  «        S )NÚapprovalr<   r?   r@   r   Ú_get_approval_callbackrD   «   s   € Ý•= *¨dÑ3Ô3Ð3r@   c                 ó   — | t           _        dS )u½   Register a callback for sudo password prompts (used by CLI).

    Per-thread scope â€” ACP sessions that run concurrently in a
    ThreadPoolExecutor each have their own callback slot.
    N)r>   r;   ©Úcbs    r   Úset_sudo_password_callbackrH   ¯   s   € ð #%…MÔÐÐr@   c                 ó   — | t           _        dS )uÙ   Register a callback for dangerous command approval prompts.

    Per-thread scope â€” ACP sessions that run concurrently in a
    ThreadPoolExecutor each have their own callback slot. See
    GHSA-qg5c-hvr5-hjgr.
    N)r>   rC   rF   s    r   Úset_approval_callbackrJ   ¸   s   € ð  …MÔÐÐr@   )Úcheck_all_command_guardsÚcommandÚenv_typeÚreturnc                 ó>   — t          | |t          ¦   «         ¬¦  «        S )zJDelegate to consolidated guard (tirith + dangerous cmd) with CLI callback.)Úapproval_callback)Ú_check_all_guards_implrD   )rL   rM   s     r   Ú_check_all_guardsrR   Ë   s*   € å! '¨8Ý4JÑ4LÔ4LðNñ Nô Nð Nr@   z^[A-Za-z0-9/\\:_\-.~ +@=,]+$Úworkdirc                 ó®   — | sdS t                                | ¦  «        s6| D ]1}t                                |¦  «        sdt          |¦  «        › d�c S Œ2dS dS )zÿReject workdir values that don't look like a filesystem path.

    Uses an allowlist of safe characters rather than a deny-list, so novel
    shell metacharacters can't slip through.

    Returns None if safe, or an error message string if dangerous.
    Nz/Blocked: workdir contains disallowed character z<. Use a simple filesystem path without shell metacharacters.z0Blocked: workdir contains disallowed characters.)Ú_WORKDIR_SAFE_REÚmatchÚrepr)rS   Úchs     r   Ú_validate_workdirrY   Ø   s�   € ð ð ØˆtÝ×!Ò! 'Ñ*Ô*ð Bàð 	ð 	ˆBÝ#×)Ò)¨"Ñ-Ô-ð ðQÅdÈ2ÁhÄhð Qð Qð Qðð ð ðð
 BÐAØˆ4r@   Úoutputc                 ó‚   — t          j        d¦  «        }|s| S g d¢}|D ]}|| v rddlm} | d |¦   «         › d�z   c S Œ | S )z¥
    Check for sudo failure and add helpful message for messaging contexts.
    
    Returns enhanced output if sudo failed in messaging context, else original.
    ÚHERMES_GATEWAY_SESSION)zsudo: a password is requiredzsudo: no tty presentzsudo: a terminal is requiredr   ©Údisplay_hermes_homeu@   

ðŸ’¡ Tip: To enable sudo over messaging, add SUDO_PASSWORD to z/.env on the agent machine.)r   r   Úhermes_constantsr^   )rZ   rM   Ú
is_gatewayÚsudo_failuresÚfailureÚ_dhhs         r   Ú_handle_sudo_failurerd   î   s­   € õ ”Ð3Ñ4Ô4€Jàð Øˆðð ð €Mð !ð Eð EˆØ�fÐÐØDÐDÐDÐDÐDÐDØð  EÐaeÐaeÑagÔagð  Eð  Eð  Eñ  Eð  Eð  Eð  Eð ð €Mr@   é-   Útimeout_secondsc                 óF  ‡— ddl }t          ¦   «         }|�	  |¦   «         pdS # t          $ r Y dS w xY wdddœŠˆfd„}	 dt          j        d<   t          j        d	¦  «         t          ¦   «          t          d
¦  «         t          d¦  «         t          d¦  «         t          d¦  «         t          d¦  «         t          d| › d�dz   dz   ¦  «         t          d¦  «         t          ¦   «          t          ddd¬¦  «         t          j	        |d¬¦  «        }| 
                    ¦   «          |                     | ¬¦  «         ‰d         r~‰d         pd}t          ¦   «          |rt          d¦  «         nt          d¦  «         t          ¦   «          |j                             ¦   «          |dt          j        v rt          j        d= S S t          d¦  «         t          d¦  «         t          ¦   «          |j                             ¦   «          	 dt          j        v rt          j        d= dS dS # t          t          f$ re t          ¦   «          t          d¦  «         t          ¦   «          |j                             ¦   «          Y dt          j        v rt          j        d= dS dS t          $ rT}t          d |› d!�¦  «         |j                             ¦   «          Y d}~dt          j        v rt          j        d= dS dS d}~ww xY w# dt          j        v rt          j        d= w xY w)"aà  
    Prompt user for sudo password with timeout.
    
    Returns the password if entered, or empty string if:
    - User presses Enter without input (skip)
    - Timeout expires (45s default)
    - Any error occurs
    
    Only works in interactive mode (HERMES_INTERACTIVE=1).
    If a _sudo_password_callback is registered (by the CLI), delegates to it
    so the prompt integrates with prompt_toolkit's UI.  Otherwise reads
    directly from /dev/tty with echo disabled.
    r   Nr   F)ÚpasswordÚdonec                  óÂ  •— d} d}	 t          j        ¦   «         dk    r\ddl}g }	 |                     ¦   «         }|dv rn#|dk    rt          ‚|                     |¦  «         Œ<d                     |¦  «        ‰
d<   nßddl}t          j	        d	t          j
        ¦  «        } |                     | ¦  «        }|                     | ¦  «        }|d
         |j         z  |d
<   |                     | |j        |¦  «         g }	 t          j        | d¦  «        }|r|dv rn|                     |¦  «         Œ2d                     |¦  «                             dd¬¦  «        ‰
d<   n2# t"          t          t$          f$ r d‰
d<   Y nt&          $ r d‰
d<   Y nw xY w| �V|�T	 ddl}|                     | |j        |¦  «         n2# t&          $ r%}	t(                               d|	¦  «         Y d}	~	nd}	~	ww xY w| �H	 t          j        | ¦  «         n2# t&          $ r%}	t(                               d|	¦  «         Y d}	~	nd}	~	ww xY wd‰
d<   dS # | �V|�T	 ddl}|                     | |j        |¦  «         n2# t&          $ r%}	t(                               d|	¦  «         Y d}	~	nd}	~	ww xY w| �H	 t          j        | ¦  «         n2# t&          $ r%}	t(                               d|	¦  «         Y d}	~	nd}	~	ww xY wd‰
d<   w xY w)zKRead password with echo disabled. Uses msvcrt on Windows, /dev/tty on Unix.NÚWindowsr   T)úÚ
úr   rh   z/dev/ttyé   é   )ó   
ó   r@   zutf-8Úreplace)Úerrorsz)Failed to restore terminal attributes: %szFailed to close tty fd: %sri   )ÚplatformÚsystemÚmsvcrtÚgetwchÚKeyboardInterruptÚappendÚjoinÚtermiosr   ÚopenÚO_RDONLYÚ	tcgetattrÚECHOÚ	tcsetattrÚ	TCSAFLUSHÚreadÚdecodeÚEOFErrorr.   r1   r   r/   Úclose)Útty_fdÚ	old_attrsrw   ÚcharsÚcr|   Ú	new_attrsÚbÚ_termiosr6   Úresults             €r   Úread_password_threadz7_prompt_for_sudo_password.<locals>.read_password_thread"  s¼  ø€ àˆØˆ	ð*	"ÝŒÑ Ô  IÒ-Ð-Ø���Ø�ð$ØŸš™œ�AØ˜LÐ(Ð(ØØ˜F’{�{Ý/Ð/Ø—L’L ‘O”O�Oð$ð &(§W¢W¨U¡^¤^��zÑ"Ð"à���Ýœ ­R¬[Ñ9Ô9�Ø#×-Ò-¨fÑ5Ô5�	Ø#×-Ò-¨fÑ5Ô5�	Ø(¨œ|¨w¬|¨mÑ;�	˜!‘Ø×!Ò! &¨'Ô*;¸YÑGÔGÐGØ�ð$Ýœ ¨Ñ*Ô*�AØð   ^Ð 3Ð 3ØØ—L’L ‘O”O�Oð	$ð
 &)§X¢X¨e¡_¤_×%;Ò%;¸GÈIÐ%;Ñ%VÔ%V��zÑ"øøÝÕ+­WÐ5ð 	$ð 	$ð 	$Ø!#ˆF�:ÑÐÐÝð 	$ð 	$ð 	$Ø!#ˆF�:ÑÐÐð	$øøøð Ð! iÐ&;ðQØ.Ð.Ð.Ð.Ø×&Ò& v¨xÔ/AÀ9ÑMÔMÐMÐMøÝ ð Qð Qð QÝ—L’LÐ!LÈaÑPÔPÐPÐPÐPÐPÐPÐPøøøøðQøøøàÐ!ðBÝ”H˜VÑ$Ô$Ð$Ð$øÝ ð Bð Bð BÝ—L’LÐ!=¸qÑAÔAÐAÐAÐAÐAÐAÐAøøøøðBøøøà!ˆF�6‰NˆNˆNøð Ð! iÐ&;ðQØ.Ð.Ð.Ð.Ø×&Ò& v¨xÔ/AÀ9ÑMÔMÐMÐMøÝ ð Qð Qð QÝ—L’LÐ!LÈaÑPÔPÐPÐPÐPÐPÐPÐPøøøøðQøøøàÐ!ðBÝ”H˜VÑ$Ô$Ð$Ð$øÝ ð Bð Bð BÝ—L’LÐ!=¸qÑAÔAÐAÐAÐAÐAÐAÐAøøøøðBøøøà!ˆF�6‰NÐ!Ð!Ð!Ð!sº   ‡EE ÅH5 ÅF	Å6H5 Å8F	ÆH5 ÆF	Æ	H5 Æ F2 Æ2
G!Æ<GÇG!Ç'G< Ç<
H+ÈH&È&H+È5KÈ; IÉKÉ
JÉ&JÊKÊJÊKÊJ&Ê%KÊ&
KÊ0KËKËKË	KÚ1ÚHERMES_SPINNER_PAUSEgš™™™™™É?u´   â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”�uA   â”‚  ðŸ”� SUDO PASSWORD REQUIRED                              â”‚u´   â”œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”¤u?   â”‚  Enter password below (input is hidden), or:            â”‚uA   â”‚    â€¢ Press Enter to skip (command fails gracefully)     â”‚u   â”‚    â€¢ Wait zs to auto-skipz                           u   â”‚u´   â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜z  Password (hidden): T)ÚendÚflush©ÚtargetÚdaemon©Útimeoutri   rh   u1     âœ“ Password received (cached for this session)u'     â�­ Skipped - continuing without sudou(   
  â�± Timeout - continuing without sudoz    (Press Enter to dismiss)u)     â�­ Cancelled - continuing without sudoz
  [sudo prompt error: z] - continuing without sudo
)ÚsysrA   r1   r   ÚenvironÚtimeÚsleepÚprintÚ	threadingÚThreadÚstartr{   Ústdoutr“   r…   ry   )rf   r™   Ú_sudo_cbr�   Úpassword_threadrh   r6   rŽ   s          @r   Ú_prompt_for_sudo_passwordr¤     s�  ø€ ð €J€J€Jõ +Ñ,Ô,€HØÐð	Ø�8‘:”:Ð# Ð#øÝð 	ð 	ð 	Ø�2�2ð	øøøð ¨Ð.Ð.€Fð."ð ."ð ."ð ."ð ."ð`03Ø-0�Œ
Ð)Ñ*ÝŒ
�3‰Œˆå‰ŒˆÝÐ(Ñ)Ô)Ð)ÝÐCÑDÔDÐDÝÐ(Ñ)Ô)Ð)ÝÐOÑPÔPÐPÝÐQÑRÔRÐRÝÐ@ Ð@Ð@Ð@À8ÑKÈeÑSÑTÔTÐTÝÐ(Ñ)Ô)Ð)Ý‰ŒˆÝÐ%¨2°TÐ:Ñ:Ô:Ð:å#Ô*Ð2FÈtÐTÑTÔTˆØ×ÒÑÔÐØ×Ò _ÐÑ5Ô5Ð5à�&Œ>ð 	Ø˜jÔ)Ð/¨RˆHÝ‰GŒGˆGØð AÝÐIÑJÔJÐJÐJåÐ?Ñ@Ô@Ð@Ý‰GŒGˆGØŒJ×ÒÑÔÐØð& "¥R¤ZÐ/Ð/Ý”
Ð1Ð2Ð2ð 0õ# Ð=Ñ>Ô>Ð>ÝÐ0Ñ1Ô1Ð1Ý‰GŒGˆGØŒJ×ÒÑÔÐØð "¥R¤ZÐ/Ð/Ý”
Ð1Ð2Ð2Ð2ð 0Ð/øõ Õ'Ð(ð ð ð Ý‰ŒˆÝÐ9Ñ:Ô:Ð:Ý‰ŒˆØŒ
×ÒÑÔÐØð "¥R¤ZÐ/Ð/Ý”
Ð1Ð2Ð2Ð2ð 0Ð/õ ð ð ð ÝÐI¨ÐIÐIÐIÑJÔJÐJØŒ
×ÒÑÔÐØˆrˆrˆrà!¥R¤ZÐ/Ð/Ý”
Ð1Ð2Ð2Ð2ð 0Ð/øøøøðøøøøð
 "¥R¤ZÐ/Ð/Ý”
Ð1Ð2Ð2Ð2Ð2Ð2sJ   —# £
1°1¿E-H. Ç	AH. È.AL ÊL Ê#	L Ê,,K;ËL Ë;L Ì L ÌL éÈ   Úlimitc                 óÈ   — | €dS t          | t          ¦  «        r
| d|…         S 	 t          | ¦  «        d|…         S # t          $ r dt	          | ¦  «        j        › d�cY S w xY w)z>Return a log-safe preview for possibly-invalid command values.Nz<None>Ú<Ú>)Ú
isinstancer)   rW   r1   ÚtypeÚ__name__)rL   r¦   s     r   Ú_safe_command_previewr­   „  s�   € à€ØˆxÝ�'�3ÑÔð Ø�v˜�vŒÐð-Ý�G‰}Œ}˜V˜e˜VÔ$Ð$øÝð -ð -ð -Ø,•4˜‘=”=Ô)Ð,Ð,Ð,Ð,Ð,Ð,ð-øøøs   ¥< ¼"A!Á A!Útokenc                 ó®   — d| vs|                       d¦  «        rdS |                      dd¦  «        \  }}t          t          j        d|¦  «        ¦  «        S )zCReturn True when *token* is a leading shell environment assignment.Ú=Frp   z^[A-Za-z_][A-Za-z0-9_]*$)Ú
startswithÚsplitÚboolÚrerV   )r®   r   Ú_values      r   Ú_looks_like_env_assignmentr¶   �  sW   € à
�%ÐÐ˜5×+Ò+¨CÑ0Ô0ÐØˆuØ—;’;˜s AÑ&Ô&�L€Dˆ&Ý•”Ð4°dÑ;Ô;Ñ<Ô<Ð<r@   r    c                 óÖ  — |}t          | ¦  «        }||k     rÇ| |         }|                     ¦   «         s|dv rn¦|dk    r:|dz  }||k     r#| |         dk    r|dz  }||k     r| |         dk    °||k     r|dz  }Œg|dk    r@|dz  }||k     r4| |         }|dk    r|dz   |k     r|dz  }Œ#|dk    r|dz  }n|dz  }||k     °4Œ­|dk    r|dz   |k     r|dz  }ŒÂ|dz  }||k     °Ç| ||…         |fS )zERead one shell token, preserving quotes/escapes, starting at *start*.z;|&()ú'rp   ú"ú\é   )ÚlenÚisspace)rL   r    ÚiÚnrX   Úinners         r   Ú_read_shell_tokenrÁ   —  s]  € à€AÝˆG‰Œ€Aà
ˆaŠ%ˆ%Ø�QŒZˆØ�:Š:‰<Œ<ð 	˜2 ˜=˜=ØØ�Š9ˆ9Ø�‰FˆAØ�a’%�%˜G AœJ¨#Ò-Ð-Ø�Q‘�ð �a’%�%˜G AœJ¨#Ò-Ð-à�1ŠuˆuØ�Q‘�ØØ�Š9ˆ9Ø�‰FˆAØ�a’%�%Ø œ
�Ø˜D’=�= Q¨¡U¨Q¢Y YØ˜‘F�AØØ˜C’<�<Ø˜‘F�AØØ�Q‘�ð �a’%�%ð Ø�Š:ˆ:˜!˜a™% !š)˜)Ø�‰FˆAØØ	ˆQ‰ˆð5 ˆaŠ%ˆ%ð8 �5˜�7Ô˜QÐÐr@   c                 óà  — g }d}t          | ¦  «        }d}d}||k     �rº| |         }|                     ¦   «         r#|                     |¦  «         |dk    rd}|dz  }ŒF|dk    r]|r[|                      d|¦  «        }|dk    r|                     | |d…         ¦  «         �n8|                     | ||…         ¦  «         |}Œ©|                      d	|¦  «        s,|                      d
|¦  «        s|                      d|¦  «        r)|                     | ||dz   …         ¦  «         |dz  }d}�Œ|dv r|                     |¦  «         |dz  }d}�Œ6|dk    r|                     |¦  «         |dz  }d}�ŒZt          | |¦  «        \  }}	|r|dk    r|                     d¦  «         d}n|                     |¦  «         |rt          |¦  «        rd}nd}|	}||k     �°ºd                     |¦  «        |fS )zGRewrite only real unquoted sudo command words, not plain text mentions.r   TFrm   rp   ú#éÿÿÿÿNú&&ú||z;;r»   z;|&(ú)Úsudozsudo -S -p ''r   )r¼   r½   rz   Úfindr±   rÁ   r¶   r{   )
rL   Úoutr¾   r¿   Úcommand_startÚfoundrX   Úcomment_endr®   Únext_is
             r   Ú_rewrite_real_sudo_invocationsrÏ   »  s<  € à€CØ	€AÝˆG‰Œ€AØ€MØ€Eà
ˆaŠ%‰%Ø�QŒZˆà�:Š:‰<Œ<ð 	Ø�JŠJ�r‰NŒNˆNØ�TŠzˆzØ $�Ø�‰FˆAØà�Š9ˆ9˜ˆ9Ø!Ÿ,š, t¨QÑ/Ô/ˆKØ˜bÒ Ð Ø—
’
˜7 1 2 2œ;Ñ'Ô'Ð'ÙØ�JŠJ�w˜q ˜}Ô-Ñ.Ô.Ð.ØˆAØà×Ò˜d AÑ&Ô&ð 	¨'×*<Ò*<¸TÀ1Ñ*EÔ*Eð 	È×I[ÒI[Ð\`ÐbcÑIdÔIdð 	Ø�JŠJ�w˜q  Q¡˜wÔ'Ñ(Ô(Ð(Ø�‰FˆAØ ˆMÙà�ˆ<ˆ<Ø�JŠJ�r‰NŒNˆNØ�‰FˆAØ ˆMÙà�Š9ˆ9Ø�JŠJ�r‰NŒNˆNØ�‰FˆAØ!ˆMÙå)¨'°1Ñ5Ô5‰ˆˆvØð 	˜U fš_˜_Ø�JŠJ�Ñ'Ô'Ð'ØˆEˆEà�JŠJ�uÑÔÐàð 	"Õ7¸Ñ>Ô>ð 	"Ø ˆMˆMà!ˆMØˆða ˆaŠ%‰%ðd �7Š7�3‰<Œ<˜ÐÐr@   c                 óT  — t          | ¦  «        }d}d}d}d}g }||k     �rv| |         }|dk    r|dk    r|dk    rd}|dz  }Œ)|                     ¦   «         r|dz  }ŒC|dk    r!|                      d|¦  «        }|dk    r�n|}Œj|dk    r|dz   |k     r|dz  }Œ|dv r't          | |¦  «        \  }	}
t	          |
|dz   ¦  «        }Œª|d	k    r|dz  }|dz  }Œ»|d
k    rt	          d|dz
  ¦  «        }|dz  }ŒÚ|dk    rA|dz   |k     r8| |dz                                 ¦   «         s| |dz            dk    r|dz  }|dz  }�Œ!|dk    r|dk    r|dz  }d}|dz  }�Œ;|dk    s|dk    r|dz  }�ŒN|                      d|¦  «        s|                      d|¦  «        r|dz   }|dz  }�Œ†|dk    r	d}|dz  }�Œ•|dk    r	d}|dz  }�Œ¤|dk    r¦|dz   |k     r| |dz            dk    r|dz  }�ŒÉ|dz
  }|dk    r?| |                              ¦   «         r%|dz  }|dk    r| |                              ¦   «         °%|dk    r| |         dv r|dz  }�Œ*|dk    r|                     ||f¦  «         d}|dz  }�ŒPt          | |¦  «        \  }	}
t	          |
|dz   ¦  «        }||k     �°v|s| S | }t          |¦  «        D ]{\  }}|}||k     r?||                              ¦   «         r%|dz  }||k     r||                              ¦   «         °%|d|…         }|||…         }||dz   d…         }|dz   |z   dz   |z   }Œ||S )u¸  Wrap `A && B &` (or `A || B &`) to `A && { B & }` at depth 0.

    Bash parses ``A && B &`` with `&&` tighter than `&`, so it forks a
    subshell for the whole `A && B` compound and backgrounds it. Inside
    the subshell, `B` runs foreground, so the subshell waits for `B` to
    finish. When `B` is a long-running process (`python3 -m http.server`,
    `yes > /dev/null`, anything that doesn't naturally exit), the subshell
    never exits. It leaks as a process stuck in ``wait4`` forever â€” and
    on the way, its open stdout pipe can prevent the terminal tool from
    returning promptly.

    Rewriting the tail to `A && { B & }` preserves `&&`'s error semantics
    (skip B if A fails) while replacing the subshell with a brace group.
    The brace group runs in the current shell (no fork), backgrounds B as
    a simple command (bash doesn't wait for it in non-interactive mode),
    and exits immediately. B runs as a normal backgrounded child, orphaned
    when the parent shell exits.

    Handles redirects (``&>``, ``2>&1``) and skips content inside quoted
    strings and parenthesised subshells. Leaves simple ``cmd &`` alone â€”
    that construct doesn't have the subshell-wait bug.
    r   rÄ   rm   rp   rÃ   rº   r»   )r¸   r¹   ú(rÇ   Ú{Ú}rÅ   rÆ   ú;Ú|ú&r©   z<>Nz{ z& })r¼   r½   rÉ   rÁ   Úmaxr±   rz   Úreversed)rL   r¿   r¾   Úparen_depthÚbrace_depthÚlast_chain_op_endÚrewritesrX   ÚnlÚ_rÎ   ÚjrŽ   Ú	chain_endÚamp_posÚ
insert_posÚprefixÚmiddleÚsuffixs                      r   Ú_rewrite_compound_backgroundræ   ø  sg  € õ. 	ˆG‰Œ€AØ	€AØ€KØ€Kð ÐØ&(€Hà
ˆaŠ%‰%Ø�QŒZˆð �Š:ˆ:˜+¨Ò*Ð*¨{¸aÒ/?Ð/?Ø "ÐØ�‰FˆAØà�:Š:‰<Œ<ð 	Ø�‰FˆAØð
 �Š9ˆ9Ø—’˜d AÑ&Ô&ˆBØ�RŠxˆxÙØˆAØà�Š:ˆ:˜!˜a™% !š)˜)Ø�‰FˆAØð �ÐÐÝ)¨'°1Ñ5Ô5‰IˆAˆvÝ�F˜A ™EÑ"Ô"ˆAØà�Š9ˆ9Ø˜1ÑˆKØ�‰FˆAØà�Š9ˆ9Ý˜a ¨q¡Ñ1Ô1ˆKØ�‰FˆAØð �Š9ˆ9˜˜Q™ š˜¨°°A±¬×(>Ò(>Ñ(@Ô(@˜ÀGÈAÐPQÉEÄNÐVZÒDZÐDZØ˜1ÑˆKØ�‰FˆAÙØ�Š9ˆ9˜ qš˜Ø˜1ÑˆKà "ÐØ�‰FˆAÙð
 ˜Š?ˆ?˜k¨Ašo˜oØ�‰FˆAÙð ×Ò˜d AÑ&Ô&ð 	¨'×*<Ò*<¸TÀ1Ñ*EÔ*Eð 	Ø ! A¡ÐØ�‰FˆAÙð �Š9ˆ9Ø "ÐØ�‰FˆAÙð �Š9ˆ9Ø "ÐØ�‰FˆAÙð �Š9ˆ9à�1‰u�qŠyˆy˜W Q¨¡Uœ^¨sÒ2Ð2à�Q‘�Ùà�A‘ˆAØ�q’&�&˜W QœZ×/Ò/Ñ1Ô1�&Ø�Q‘�ð �q’&�&˜W QœZ×/Ò/Ñ1Ô1�&à�AŠvˆv˜' !œ*¨Ð,Ð,Ø�Q‘�Ùà  AÒ%Ð%Ø—’Ð!2°AÐ 6Ñ7Ô7Ð7Ø "ÐØ�‰FˆAÙõ & g¨qÑ1Ô1‰	ˆˆ6Ý�˜˜A™ÑÔˆð] ˆaŠ%‰%ð` ð Øˆð €FÝ& xÑ0Ô0ð 9ð 9Ñˆ	�7ð ˆ
Ø˜7Ò"Ð" v¨jÔ'9×'AÒ'AÑ'CÔ'CÐ"Ø˜!‰OˆJð ˜7Ò"Ð" v¨jÔ'9×'AÒ'AÑ'CÔ'CÐ"à˜˜˜Ô$ˆØ˜
 7Ð*Ô+ˆØ˜ !™˜˜Ô&ˆð ˜$‘ Ñ'¨%Ñ/°&Ñ8ˆˆà€Mr@   c                 ó  — | €dS t          | ¦  «        \  }}|s| dfS dt          j        v }|r t          j                             dd¦  «        nt          }|s*|s(t          j        d¦  «        rt          d¬¦  «        }|r|a|s|r||dz   fS | dfS )	a[  
    Transform sudo commands to use -S flag if SUDO_PASSWORD is available.

    This is a shared helper used by all execution environments to provide
    consistent sudo handling across local, SSH, and container environments.

    Returns:
        (transformed_command, sudo_stdin) where:
        - transformed_command has every bare ``sudo`` replaced with
          ``sudo -S -p ''`` so sudo reads its password from stdin.
        - sudo_stdin is the password string with a trailing newline that the
          caller must prepend to the process's stdin stream.  sudo -S reads
          exactly one line (the password) and passes the rest of stdin to the
          child command, so prepending is safe even when the caller also has
          its own stdin_data to pipe.
        - If no password is available, sudo_stdin is None and the command is
          returned unchanged so it fails gracefully with
          "sudo: a password is required".

    Callers that drive a subprocess directly (local, ssh, docker, singularity)
    should prepend sudo_stdin to their stdin_data and pass the merged bytes to
    Popen's stdin pipe.

    Callers that cannot pipe subprocess stdin (modal, daytona) must embed the
    password in the command string themselves; see their execute() methods for
    how they handle the non-None sudo_stdin case.

    If SUDO_PASSWORD is not set and in interactive mode (HERMES_INTERACTIVE=1):
      Prompts user for password with 45s timeout, caches for session.

    If SUDO_PASSWORD is not set and NOT interactive:
      Command runs as-is (fails gracefully with "sudo: a password is required").
    N)NNÚSUDO_PASSWORDr   ÚHERMES_INTERACTIVEre   )rf   rm   )rÏ   r   rš   Úgetr9   r   r¤   )rL   ÚtransformedÚhas_real_sudoÚhas_configured_passwordr;   s        r   Ú_transform_sudo_commandrî   �  sÈ   € ðH €ØˆzÝ!?ÀÑ!HÔ!HÑ€K�Øð Ø˜ˆ}Ðà-µ´Ð;ÐØ;RÐm•B”J—N’N ?°BÑ7Ô7Ð7ÕXm€Mà"ð 2¨=ð 2½R¼YÐG[Ñ=\Ô=\ð 2Ý1À"ÐEÑEÔEˆØð 	2Ø$1Ð!àð 1 -ð 1à˜M¨DÑ0Ð0Ð0à�Dˆ=Ðr@   )ÚLocalEnvironment)ÚSingularityEnvironment)ÚSSHEnvironment)ÚDockerEnvironment)ÚModalEnvironment)ÚManagedModalEnvironment)Úis_managed_tool_gateway_readyu6  Execute shell commands on a Linux environment. Filesystem usually persists between calls.

Do NOT use cat/head/tail to read files â€” use read_file instead.
Do NOT use grep/rg/find to search â€” use search_files instead.
Do NOT use ls to list directories â€” use search_files(target='files') instead.
Do NOT use sed/awk to edit files â€” use patch instead.
Do NOT use echo/cat heredoc to create files â€” use write_file instead.
Reserve terminal for: builds, installs, git, processes, scripts, network, package managers, and anything that needs a shell.

Foreground (default): Commands return INSTANTLY when done, even if the timeout is high. Set timeout=300 for long builds/scripts â€” you'll still get the result in seconds if it's fast. Prefer foreground for short commands.
Background: Set background=true to get a session_id. Two patterns:
  (1) Long-lived processes that never exit (servers, watchers).
  (2) Long-running tasks with notify_on_complete=true â€” you can keep working on other things and the system auto-notifies you when the task finishes. Great for test suites, builds, deployments, or anything that takes more than a minute.
For servers/watchers, do NOT use shell-level background wrappers (nohup/disown/setsid/trailing '&') in foreground mode. Use background=true so Hermes can track lifecycle and output.
After starting a server, verify readiness with a health check or log signal, then run tests in a separate terminal() call. Avoid blind sleep loops.
Use process(action="poll") for progress checks, process(action="wait") to block until done.
Working directory: Use 'workdir' for per-command cwd.
PTY mode: Set pty=true for interactive CLI tools (Codex, Claude Code, Python REPL).

Do NOT use vim/nano/interactive tools without pty=true â€” they hang without a pseudo-terminal. Pipe git output to cat if it might page.
Ú_active_environmentsÚ_last_activityÚ_creation_locksFÚ_task_env_overridesÚtask_idÚ	overridesc                 ó   — |t           | <   dS )a#  
    Register environment overrides for a specific task/rollout.

    Called by Atropos environments before the agent loop to configure
    per-task sandbox settings (e.g., a custom Dockerfile for the Modal image).

    Supported override keys:
        - modal_image: str -- Path to Dockerfile or Docker Hub image name
        - docker_image: str -- Docker image name
        - cwd: str -- Working directory inside the sandbox

    Args:
        task_id: The rollout's unique task identifier
        overrides: Dict of config keys to override
    N©rù   )rú   rû   s     r   Úregister_task_env_overridesrþ     s   € ð  $-Õ˜Ñ Ð Ð r@   c                 ó<   — t                                | d¦  «         dS )z‰
    Clear environment overrides for a task after rollout completes.

    Called during cleanup to avoid stale entries accumulating.
    N)rù   Úpop©rú   s    r   Úclear_task_env_overridesr    s    € õ ×Ò˜G TÑ*Ô*Ð*Ð*Ð*r@   c                 ó    — | r| t           v r| S dS )a“  
    Map a tool-call ``task_id`` to the container/sandbox key used by
    ``_active_environments``.

    The top-level agent passes ``task_id=None`` and lands on ``"default"``.
    ``delegate_task`` children pass their own subagent ID so that
    file-state tracking, the active-subagents registry, and TUI events stay
    distinct per child -- but we deliberately collapse that ID back to
    ``"default"`` here so subagents share the parent's long-lived container
    (one bash, one /workspace, one set of installed packages).

    Exception: RL / benchmark environments (TerminalBench2, HermesSweEnv, ...)
    call ``register_task_env_overrides(task_id, {...})`` to request a
    per-task Docker/Modal image. When an override is registered for a
    task_id, we honour it by returning the task_id unchanged -- those
    rollouts need their own isolated sandbox, which is the whole point of
    the override.
    r   rý   r  s    r   Ú_resolve_container_task_idr  '  s!   € ð& ð �7Õ1Ð1Ð1ØˆØˆ9r@   c           
      óª   — t          j        | |¦  «        }	  ||¦  «        S # t          t          j        f$ r t          d| › d|›d|› d�¦  «        ‚w xY w)zðParse an environment variable with *converter*, raising a clear error on bad values.

    Without this wrapper, a single malformed env var (e.g. TERMINAL_TIMEOUT=5m)
    causes an unhandled ValueError that kills every terminal command.
    zInvalid value for ú: z (expected z1). Check ~/.hermes/.env or environment variables.)r   r   r   ÚjsonÚJSONDecodeErrorr   s        r   Ú_parse_env_varr	  A  s‹   € õ Œ)�D˜'Ñ
"Ô
"€Cð
Øˆy˜‰~Œ~ÐøÝ�Ô,Ð-ð 
ð 
ð 
Ýð> ð >ð >¨ð >ð >¸:ð >ð >ð >ñ
ô 
ð 	
ð
øøøs	   —
" ¢0Ac                  óŒ  ‡	‡
— d} t          j        dd¦  «        }t          j        dd¦  «                             ¦   «         dv }|dk    rt          j        ¦   «         }n|dk    rd}nd	}t          j        d
|¦  «        Š
d}d}|dk    rØ|rÖt          j        d
¦  «        pt          j        ¦   «         }t           j                             t           j                             |¦  «        ¦  «        Š	t          ˆ	fd„|D ¦   «         ¦  «        sSt           j                             ‰	¦  «        r8t           j         	                    ‰	¦  «        r‰	 
                    d¦  «        s‰	}dŠ
nj|dv rf‰
rdt          ˆ
fd„|D ¦   «         ¦  «        }t           j                             ‰
¦  «         }|s|r%‰
|k    rt                               d‰
||¦  «         |Š
i d|“dt          t          j        dd¦  «        ¦  «        “dt          j        d| ¦  «        “dt          ddt          j        d¦  «        “dt          j        dd | › �¦  «        “d!t          j        d"| ¦  «        “d#t          j        d$| ¦  «        “d%‰
“d&|“d'|“d(t          d)d*¦  «        “d+t          d,d-¦  «        “d.t          j        d/d0¦  «        “d1t          j        d2d0¦  «        “d3t          d4d5¦  «        “d6t          j        d7d0¦  «        “d8t          j        d9t          j        d:d;¦  «        ¦  «                             ¦   «         dv “t          j        d<d¦  «                             ¦   «         dv t          d=d>t"          d?¦  «        t          d@dA¦  «        t          dBdC¦  «        t          j        dDd;¦  «                             ¦   «         dv t          dEdt          j        d¦  «        dFœ¥S )GzBGet terminal environment configuration from environment variables.ú*nikolaik/python-nodejs:python3.11-nodejs20ÚTERMINAL_ENVÚlocalÚ&TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACEÚfalse)Útruer�   ÚyesÚsshÚ~ú/rootÚTERMINAL_CWDN)z/Users/z/home/zC:\zC:/Údockerc              3   óB   •K  — | ]}‰                      |¦  «        V — Œd S ©N©r±   )Ú.0ÚpÚ	candidates     €r   ú	<genexpr>z"_get_env_config.<locals>.<genexpr>n  s1   øè è € Ð?Ð?¨A�	×$Ò$ QÑ'Ô'Ð?Ð?Ð?Ð?Ð?Ð?r@   )ú
/workspacer  r  )Úmodalr  ÚsingularityÚdaytonac              3   óB   •K  — | ]}‰                      |¦  «        V — Œd S r  r  )r  r  Úcwds     €r   r  z"_get_env_config.<locals>.<genexpr>u  s/   øè è € ÐDÐD°˜3Ÿ>š>¨!Ñ,Ô,ÐDÐDÐDÐDÐDÐDr@   zeIgnoring TERMINAL_CWD=%r for %s backend (host/relative path won't work in sandbox). Using %r instead.rM   Ú
modal_modeÚTERMINAL_MODAL_MODEÚautoÚdocker_imageÚTERMINAL_DOCKER_IMAGEÚdocker_forward_envÚTERMINAL_DOCKER_FORWARD_ENVz[]z
valid JSONÚsingularity_imageÚTERMINAL_SINGULARITY_IMAGEú	docker://Úmodal_imageÚTERMINAL_MODAL_IMAGEÚdaytona_imageÚTERMINAL_DAYTONA_IMAGEr#  Úhost_cwdÚdocker_mount_cwd_to_workspacer˜   ÚTERMINAL_TIMEOUTÚ180Úlifetime_secondsÚTERMINAL_LIFETIME_SECONDSÚ300Ússh_hostÚTERMINAL_SSH_HOSTr   Ússh_userÚTERMINAL_SSH_USERÚssh_portÚTERMINAL_SSH_PORTÚ22Ússh_keyÚTERMINAL_SSH_KEYÚssh_persistentÚTERMINAL_SSH_PERSISTENTÚTERMINAL_PERSISTENT_SHELLr  ÚTERMINAL_LOCAL_PERSISTENTÚTERMINAL_CONTAINER_CPUr�   r"   ÚTERMINAL_CONTAINER_MEMORYÚ5120ÚTERMINAL_CONTAINER_DISKÚ51200ÚTERMINAL_CONTAINER_PERSISTENTÚTERMINAL_DOCKER_VOLUMES)Úlocal_persistentÚcontainer_cpuÚcontainer_memoryÚcontainer_diskÚcontainer_persistentÚdocker_volumes)r   r   ÚlowerÚgetcwdr4   ÚabspathÚ
expanduserÚanyÚisabsÚisdirr±   r   Úinfor   r	  r  ÚloadsÚfloat)Údefault_imagerM   Úmount_docker_cwdÚdefault_cwdr2  Úhost_prefixesÚdocker_cwd_sourceÚis_host_pathÚis_relativer  r#  s            @@r   Ú_get_env_configrd  Q  s.  øø€ ð A€MÝŒy˜¨Ñ1Ô1€Hå”yÐ!IÈ7ÑSÔS×YÒYÑ[Ô[Ð_sÐsÐð
 �7ÒÐÝ”i‘k”kˆˆØ	�UÒ	Ð	Øˆˆàˆõ Œ)�N KÑ
0Ô
0€CØ€HØ8€MØ�8ÒÐÐ 0ÐÝœI nÑ5Ô5ÐD½¼¹¼ÐÝ”G—O’O¥B¤G×$6Ò$6Ð7HÑ$IÔ$IÑJÔJˆ	åÐ?Ð?Ð?Ð?°Ð?Ñ?Ô?Ñ?Ô?ð	å”—’˜iÑ(Ô(ð	å-/¬W¯]ª]¸9Ñ-EÔ-Eð	àNW×NbÒNbÐczÑN{ÔN{ð	ð !ˆHØˆCøØ	ÐBÐ	BÐ	BÀsÐ	BåÐDÐDÐDÐD°mÐDÑDÔDÑDÔDˆÝœ'Ÿ-š-¨Ñ,Ô,Ð,ˆØð 	˜Kð 	¨S°KÒ-?Ð-?Ý�KŠKð Xà˜X {ñ4ô 4ð 4ð ˆCð Ø�Hð àÕ'­¬	Ð2GÈÑ(PÔ(PÑQÔQð ð 	�œ	Ð"9¸=ÑIÔIð ð 	�nÐ-JÈDÕRVÔR\Ð^jÑkÔkð	 ð
 	�RœYÐ'CÐE`ÐQ^ÐE`ÐE`ÑaÔað ð 	•r”yÐ!7¸ÑGÔGð ð 	�œÐ#;¸]ÑKÔKð ð 	ˆsð ð 	�Hð ð 	(Ð)9ð ð 	•>Ð"4°eÑ<Ô<ð ð 	�NÐ+FÈÑNÔNð ð 	•B”IÐ1°2Ñ6Ô6ð ð 	•B”IÐ1°2Ñ6Ô6ð ð  	•NÐ#6¸Ñ=Ô=ð! ð" 	•2”9Ð/°Ñ4Ô4ð# ð* 	�"œ)Ø%ÝŒIÐ1°6Ñ:Ô:ñ
ô 
÷ Š%‰'Œ'Ð)ð*ð+ õ2 œIÐ&AÀ7ÑKÔK×QÒQÑSÔSÐWkÐkå'Ð(@À#ÅuÈhÑWÔWÝ*Ð+FÈÑOÔOÝ(Ð)BÀGÑLÔLÝ "¤	Ð*IÈ6Ñ RÔ R× XÒ XÑ ZÔ ZÐ^rÐ rÝ(Ð)BÀDÍ$Ì*ÐVbÑcÔcð? ð  ð  ð  r@   r$  c                 óX   — t          | t          ¦   «         t          d¦  «        ¬¦  «        S )z2Resolve direct vs managed Modal backend selection.r  )Ú
has_directÚmanaged_ready)r   r   rõ   )r$  s    r   Ú_get_modal_backend_staterh     s0   € å&ØÝ/Ñ1Ô1Ý3°GÑ<Ô<ðñ ô ð r@   Úimager#  r˜   Ú
ssh_configÚcontainer_configÚlocal_configr2  c	                 ó  — |pi }	|	                      dd¦  «        }
|	                      dd¦  «        }|	                      dd¦  «        }|	                      dd¦  «        }|	                      d	g ¦  «        }|	                      d
g ¦  «        }|	                      di ¦  «        }| dk    rt          ||¬¦  «        S | dk    r0t          ||||
|||||||	                      dd¦  «        ||¬¦  «        S | dk    rt          ||||
||||¬¦  «        S | dk    �r5i }|
dk    r|
|d<   |dk    r||d<   |dk    rE	 ddl}ddl}d|                     |j        j        ¦  «        j	        v r||d<   n# t          $ r Y nw xY wt          |	                      d¦  «        ¦  «        }|d         dk    rt          ||||||¬¦  «        S |d         dk    rn|d         rt          d ¦  «        ‚|d!         dk    rt          d"¦  «        ‚|d!         dk    rt          d#¦  «        ‚d$}t          ¦   «         rd%}t          |¦  «        ‚t          ||||||¬¦  «        S | d&k    r&dd'lm}  ||||t%          |
¦  «        ||||¬¦  «        S | d(k    r„|r*|                      d)¦  «        r|                      d*¦  «        st          d+¦  «        ‚t'          |d)         |d*         |                      d,d-¦  «        |                      d.d/¦  «        ||¬0¦  «        S t          d1| › d2�¦  «        ‚)3aÓ  
    Create an execution environment for sandboxed command execution.
    
    Args:
        env_type: One of "local", "docker", "singularity", "modal", "daytona", "ssh"
        image: Docker/Singularity/Modal image name (ignored for local/ssh)
        cwd: Working directory
        timeout: Default command timeout
        ssh_config: SSH connection config (for env_type="ssh")
        container_config: Resource config for container backends (cpu, memory, disk, persistent)
        task_id: Task identifier for environment reuse and snapshot keying
        host_cwd: Optional host working directory to bind into Docker when explicitly enabled
        
    Returns:
        Environment instance with execute() method
    rN  rp   rO  é   rP  é È  rQ  TrR  r)  Ú
docker_envr  )r#  r˜   r  r3  F)ri  r#  r˜   ÚcpuÚmemoryÚdiskÚpersistent_filesystemrú   Úvolumesr2  Úauto_mount_cwdÚforward_envÚenvr   )ri  r#  r˜   rq  rr  rs  rt  rú   r  r   rq  rr  NÚephemeral_diskr$  Úselected_backendÚmanaged)ri  r#  r˜   Úmodal_sandbox_kwargsrt  rú   ÚdirectÚmanaged_mode_blockedzäModal backend is configured for managed mode, but a paid Nous subscription is required for the Tool Gateway and no direct Modal credentials/config were found. Log in with `hermes model` or choose TERMINAL_MODAL_MODE=direct/auto.ÚmodezZModal backend is configured for managed mode, but the managed tool gateway is unavailable.z_Modal backend is configured for direct mode, but no direct Modal credentials/config were found.zHModal backend selected but no direct Modal credentials/config was found.z`Modal backend selected but no direct Modal credentials/config or managed tool gateway was found.r!  )ÚDaytonaEnvironmentr  ÚhostÚuserz?SSH environment requires ssh_host and ssh_user to be configuredÚporté   Úkeyr   )r�  r‚  rƒ  Úkey_pathr#  r˜   zUnknown environment type: zD. Use 'local', 'docker', 'singularity', 'modal', 'daytona', or 'ssh')rê   Ú_LocalEnvironmentÚ_DockerEnvironmentÚ_SingularityEnvironmentÚinspectr  Ú	signatureÚSandboxÚcreateÚ
parametersr1   rh  Ú_ManagedModalEnvironmentr   r   Ú_ModalEnvironmentÚtools.environments.daytonar€  ÚintÚ_SSHEnvironment)rM   ri  r#  r˜   rj  rk  rl  rú   r2  Úccrq  rr  rs  Ú
persistentru  r)  rp  Úsandbox_kwargsrŠ  r  Úmodal_stateÚmessageÚ_DaytonaEnvironments                          r   Ú_create_environmentrš  ©  s7  € ð* 
Ð	˜R€BØ
�&Š&� !Ñ
$Ô
$€CØ�VŠVÐ&¨Ñ-Ô-€FØ�6Š6Ð" EÑ*Ô*€DØ—’Ð.°Ñ5Ô5€JØ�fŠfÐ% rÑ*Ô*€GØŸšÐ 4°bÑ9Ô9ÐØ—’˜ bÑ)Ô)€Jà�7ÒÐÝ  S°'Ð:Ñ:Ô:Ð:à	�XÒ	Ð	Ý!Ø˜S¨'Ø˜F¨Ø",°gØØØŸ6š6Ð"AÀ5ÑIÔIØ*Øð	
ñ 	
ô 	
ð 		
ð 
�]Ò	"Ð	"Ý&Ø˜S¨'Ø˜F¨Ø",°gð
ñ 
ô 
ð 	
ð 
�WÒ	Ñ	ØˆØ�Š7ˆ7Ø$'ˆN˜5Ñ!Ø�AŠ:ˆ:Ø'-ˆN˜8Ñ$Ø�!Š8ˆ8ðØ%Ð%Ð%Ð%Ð%Ð%Ð%Ð%Ø# w×'8Ò'8¸¼Ô9MÑ'NÔ'NÔ'YÐYÐYØ7;�NÐ#3Ñ4øøÝð ð ð Ø�ðøøøõ /¨r¯vªv°lÑ/CÔ/CÑDÔDˆàÐ)Ô*¨iÒ7Ð7Ý+Ø ¨gØ%3Ø&0¸'ðñ ô ð ð Ð)Ô*¨hÒ6Ð6ØÐ1Ô2ð Ý ð>ñô ð ð ˜6Ô" iÒ/Ð/Ý Øpñô ð ð ˜6Ô" hÒ.Ð.Ý Øuñô ð ð aˆGÝ)Ñ+Ô+ð àvð õ ˜WÑ%Ô%Ð%å Ø˜S¨'Ø!/Ø",°gð
ñ 
ô 
ð 	
ð 
�YÒ	Ð	àXÐXÐXÐXÐXÐXØ"Ð"Ø˜S¨'Ý�C‘” ¨dØ",°gð
ñ 
ô 
ð 	
ð 
�UÒ	Ð	Øð 	` §¢°Ñ!7Ô!7ð 	`¸z¿~º~ÈfÑ?UÔ?Uð 	`ÝÐ^Ñ_Ô_Ð_ÝØ˜FÔ#Ø˜FÔ#Ø—’ ¨Ñ+Ô+Ø—^’^ E¨2Ñ.Ô.ØØð
ñ 
ô 
ð 	
õ ð  E°hð  Eð  Eð  Eñ  Fô  Fð  	Fs   Ä/3E# Å#
E0Å/E0é,  r6  c                 ó  — t          j         ¦   «         }	 ddlm} t          t                               ¦   «         ¦  «        D ]!}|                     |¦  «        r
|t          |<   Œ"n# t          $ r Y nw xY wg }t          5  t          t           	                    ¦   «         ¦  «        D ]]\  }}||z
  | k    rOt                               |d¦  «        }t                               |d¦  «         |�|                     ||f¦  «         Œ^t          5  |D ] \  }}t                               |d¦  «         Œ!	 ddd¦  «         n# 1 swxY w Y   ddd¦  «         n# 1 swxY w Y   |D �]+\  }}	 ddlm}  ||¦  «         n# t          $ r Y nw xY w	 t#          |d¦  «        r|                     ¦   «          nIt#          |d¦  «        r|                     ¦   «          n$t#          |d¦  «        r|                     ¦   «          t*                               d|¦  «         Œ´# t.          $ rl}	t1          |	¦  «        }
d	|
v sd
|
                     ¦   «         v rt*                               d|¦  «         nt*                               d||	¦  «         Y d}	~	�Œ%d}	~	ww xY wdS )zOClean up environments that have been inactive for longer than lifetime_seconds.r   ©Úprocess_registryN©Úclear_file_ops_cacheÚcleanupÚstopÚ	terminatez,Cleaned up inactive environment for task: %sÚ404ú	not foundú*Environment for task %s already cleaned upú-Error cleaning up environment for task %s: %s)r›   Útools.process_registryrž  Úlistr÷   ÚkeysÚhas_active_processesÚImportErrorÚ	_env_lockÚitemsrö   r   rz   Ú_creation_locks_lockrø   Útools.file_toolsr   Úhasattrr¡  r¢  r£  r   rZ  r1   r)   rS  r   )r6  Úcurrent_timerž  rú   Úenvs_to_stopÚ	last_timerx  rÞ   r   r6   Ú	error_strs              r   Ú_cleanup_inactive_envsr¶  *  sq  € å”9‘;”;€LðØ;Ð;Ð;Ð;Ð;Ð;Ý�N×/Ò/Ñ1Ô1Ñ2Ô2ð 	7ð 	7ˆGØ×4Ò4°WÑ=Ô=ð 7Ø*6•˜wÑ'øð	7øõ ð ð ð Øˆðøøøð €Lå	ð 3ð 3Ý"&¥~×';Ò';Ñ'=Ô'=Ñ">Ô">ð 	8ð 	8ÑˆG�YØ˜iÑ'Ð*:Ò:Ð:Ý*×.Ò.¨w¸Ñ=Ô=�Ý×"Ò" 7¨DÑ1Ô1Ð1Ø�?Ø ×'Ò'¨°#¨Ñ7Ô7Ð7øõ "ð 	3ð 	3Ø*ð 3ð 3‘
�˜Ý×#Ò# G¨TÑ2Ô2Ð2Ð2ð3ð	3ð 	3ð 	3ñ 	3ô 	3ð 	3ð 	3ð 	3ð 	3ð 	3ð 	3øøøð 	3ð 	3ð 	3ð 	3ð3ð 3ð 3ñ 3ô 3ð 3ð 3ð 3ð 3ð 3ð 3øøøð 3ð 3ð 3ð 3ð %ð \ñ \‰ˆ�ð	Ø=Ð=Ð=Ð=Ð=Ð=Ø Ð  Ñ)Ô)Ð)Ð)øÝð 	ð 	ð 	ØˆDð	øøøð	\Ý�s˜IÑ&Ô&ð  Ø—’‘”��Ý˜˜fÑ%Ô%ð  Ø—’‘
”
�
�
Ý˜˜kÑ*Ô*ð  Ø—’‘”�å�KŠKÐFÈÑPÔPÐPÐPøåð 	\ð 	\ð 	\Ý˜A™œˆIØ˜	Ð!Ð! [°I·O²OÑ4EÔ4EÐ%EÐ%EÝ—’ÐHÈ'ÑRÔRÐRÐRå—’ÐNÐPWÐYZÑ[Ô[Ð[øøøøùøøøøð	\øøøð'\ð \su   •AA$ Á$
A1Á0A1Á=BEÄ	$D:Ä.EÄ:D>	Ä>EÅD>	ÅEÅEÅEÅ%E7Å7
FÆFÆB	HÈ
JÈA!JÊJc                  ó6  — t           r‘	 t          ¦   «         } t          | d         ¦  «         n4# t          $ r'}t                               d|d¬¦  «         Y d}~nd}~ww xY wt          d¦  «        D ]}t           s nt          j        d¦  «         Œ t           °�dS dS )zKBackground thread worker that periodically cleans up inactive environments.r6  zError in cleanup thread: %sTr&   Né<   rp   )	Ú_cleanup_runningrd  r¶  r1   r   r   Úranger›   rœ   )Úconfigr6   rÞ   s      r   Ú_cleanup_thread_workerr¼  h  sÎ   € å
ð 
ð	LÝ$Ñ&Ô&ˆFÝ" 6Ð*<Ô#=Ñ>Ô>Ð>Ð>øÝð 	Lð 	Lð 	LÝ�NŠNÐ8¸!ÀdˆNÑKÔKÐKÐKÐKÐKÐKÐKøøøøð	Løøøõ �r‘”ð 	ð 	ˆAÝ#ð Ø�ÝŒJ�q‰MŒMˆMˆMõ ð 
ð 
ð 
ð 
ð 
s   ‰#- ­
A·AÁAc                  óò   — t           5  t          �t                               ¦   «         s6dat	          j        t          d¬¦  «        at                               ¦   «          ddd¦  «         dS # 1 swxY w Y   dS )z;Start the background cleanup thread if not already running.NTr”   )r­  Ú_cleanup_threadÚis_aliver¹  rž   rŸ   r¼  r    r?   r@   r   Ú_start_cleanup_threadrÀ  w  s´   € õ 
ð $ð $ÝÐ"­/×*BÒ*BÑ*DÔ*DÐ"Ø#ÐÝ'Ô.Õ6LÐUYÐZÑZÔZˆOÝ×!Ò!Ñ#Ô#Ð#ð	$ð $ð $ñ $ô $ð $ð $ð $ð $ð $ð $ð $øøøð $ð $ð $ð $ð $ð $s   ˆAA,Á,A0Á3A0c                  ó„   — da t          �6	 t                               d¬¦  «         dS # t          t          f$ r Y dS w xY wdS )z#Stop the background cleanup thread.FNé   r—   )r¹  r¾  r{   Ú
SystemExitry   r?   r@   r   Ú_stop_cleanup_threadrÄ  ‚  sb   € ð ÐÝÐ"ð	Ý× Ò ¨Ð Ñ+Ô+Ð+Ð+Ð+øÝÕ-Ð.ð 	ð 	ð 	ØˆDˆDð	øøøð #Ð"s   ‹( ¨=¼=c                 óÊ   — t          | ¦  «        }t          5  t                               |¦  «        pt                               | ¦  «        cddd¦  «         S # 1 swxY w Y   dS )z9Return the active BaseEnvironment for *task_id*, or None.N)r  r­  rö   rê   )rú   Úlookups     r   Úget_active_envrÇ  �  s²   € å'¨Ñ0Ô0€FÝ	ð Uð UÝ#×'Ò'¨Ñ/Ô/ÐTÕ3G×3KÒ3KÈGÑ3TÔ3TðUð Uð Uð Uñ Uô Uð Uð Uð Uð Uð Uð Uøøøð Uð Uð Uð Uð Uð Us   —4AÁAÁAc                 ód   — t          | ¦  «        }|€dS t          t          |dd¦  «        ¦  «        S )a  Return True if the active environment for task_id is configured for
    cross-turn persistence (``persistent_filesystem=True``).

    Used by the agent loop to skip per-turn teardown for backends whose whole
    point is to survive between turns (docker with ``container_persistent``,
    daytona, modal, etc.). Non-persistent backends (e.g. Morph) still get torn
    down at end-of-turn to prevent leakage. The idle reaper
    (``_cleanup_inactive_envs``) handles persistent envs once they exceed
    ``terminal.lifetime_seconds``.
    NFÚ_persistent)rÇ  r³   r=   )rú   rx  s     r   Úis_persistent_envrÊ  ”  s5   € õ ˜Ñ
!Ô
!€CØ
€{ØˆuÝ•˜˜]¨EÑ2Ô2Ñ3Ô3Ð3r@   c                  ót  — t          t                               ¦   «         ¦  «        } d}| D ]L}	 t          |¦  «         |dz  }Œ# t          $ r(}t
                               d||d¬¦  «         Y d}~ŒEd}~ww xY wt          ¦   «         }ddl}|                     t          |dz  ¦  «        ¦  «        D ]g}	 t          j        |d¬¦  «         t
                               d	|¦  «         Œ5# t          $ r&}t
                               d
||¦  «         Y d}~Œ`d}~ww xY w|dk    rt
                               d|¦  «         |S )z3Clean up ALL active environments. Use with caution.r   rp   zError cleaning %s: %sTr&   Nr$   )Úignore_errorszRemoved orphaned: %sz%Failed to remove orphaned path %s: %szCleaned %d environments)r©  rö   rª  Ú
cleanup_vmr1   r   Úerrorr
   r(   r)   ÚshutilÚrmtreerZ  r.   r/   )Útask_idsÚcleanedrú   r6   r2   r(   r4   s          r   Úcleanup_all_environmentsrÓ  §  s  € åÕ(×-Ò-Ñ/Ô/Ñ0Ô0€HØ€Gàð Mð Mˆð	MÝ�wÑÔÐØ�q‰LˆGˆGøÝð 	Mð 	Mð 	MÝ�LŠLÐ0°'¸1ÀtˆLÑLÔLÐLÐLÐLÐLÐLÐLøøøøð	Møøøõ #Ñ$Ô$€KØ€K€K€KØ—	’	�#˜k¨JÑ6Ñ7Ô7Ñ8Ô8ð Kð Kˆð	KÝŒM˜$¨dÐ3Ñ3Ô3Ð3Ý�KŠKÐ.°Ñ5Ô5Ð5Ð5øÝð 	Kð 	Kð 	KÝ�LŠLÐ@À$ÈÑJÔJÐJÐJÐJÐJÐJÐJøøøøð	Køøøð �‚{€{Ý�ŠÐ-¨wÑ7Ô7Ð7Ø€Ns/   ®AÁ
A5ÁA0Á0A5Â21C$Ã$
DÃ.DÄDc                 óˆ  — d}t           5  t                               | d¦  «        }t                               | d¦  «         ddd¦  «         n# 1 swxY w Y   t          5  t
                               | d¦  «         ddd¦  «         n# 1 swxY w Y   	 ddlm}  || ¦  «         n# t          $ r Y nw xY w|€dS 	 t          |d¦  «        r| 
                    ¦   «          nIt          |d¦  «        r|                     ¦   «          n$t          |d¦  «        r|                     ¦   «          t                               d| ¦  «         dS # t          $ rr}t!          |¦  «        }d|v sd	|                     ¦   «         v rt                               d
| ¦  «         n"t                               d| |¦  «         Y d}~dS Y d}~dS d}~ww xY w)z4Manually clean up a specific environment by task_id.Nr   rŸ  r¡  r¢  r£  z,Manually cleaned up environment for task: %sr¤  r¥  r¦  r§  )r­  rö   r   r÷   r¯  rø   r°  r   r¬  r±  r¡  r¢  r£  r   rZ  r1   r)   rS  r   )rú   rx  r   r6   rµ  s        r   rÍ  rÍ  Â  s  € ð
 €CÝ	ð *ð *Ý"×&Ò& w°Ñ5Ô5ˆÝ×Ò˜7 DÑ)Ô)Ð)ð*ð *ð *ñ *ô *ð *ð *ð *ð *ð *ð *øøøð *ð *ð *ð *õ
 
ð +ð +Ý×Ò˜G TÑ*Ô*Ð*ð+ð +ð +ñ +ô +ð +ð +ð +ð +ð +ð +øøøð +ð +ð +ð +ðØ9Ð9Ð9Ð9Ð9Ð9ØÐ˜WÑ%Ô%Ð%Ð%øÝð ð ð Øˆðøøøð €{ØˆðXÝ�3˜	Ñ"Ô"ð 	Ø�KŠK‰MŒMˆMˆMÝ�S˜&Ñ!Ô!ð 	Ø�HŠH‰JŒJˆJˆJÝ�S˜+Ñ&Ô&ð 	Ø�MŠM‰OŒOˆOå�ŠÐBÀGÑLÔLÐLÐLÐLøåð Xð Xð XÝ˜‘F”Fˆ	Ø�IÐÐ °	·²Ñ0AÔ0AÐ!AÐ!AÝ�KŠKÐDÀgÑNÔNÐNÐNå�NŠNÐJÈGÐUVÑWÔWÐWÐWÐWÐWÐWÐWÐWð OÐNÐNÐNÐNÐNøøøøðXøøøsO   Š7AÁAÁAÁBÂBÂBÂB% Â%
B2Â1B2Â:B	E Å
GÅA!F<Æ<Gc                  ó®   — t          ¦   «          t          r?t          t          ¦  «        } t                               d| ¦  «         t          ¦   «          dS dS )zBStop cleanup thread and shut down all remaining sandboxes on exit.z)Shutting down %d remaining sandbox(es)...N)rÄ  rö   r¼   r   rZ  rÓ  )Úcounts    r   Ú_atexit_cleanupr×  ì  sU   € åÑÔÐÝð #ÝÕ(Ñ)Ô)ˆÝ�ŠÐ?ÀÑGÔGÐGÝ Ñ"Ô"Ð"Ð"Ð"ð#ð #r@   Ú	exit_codec                 óÄ  — |dk    rdS t          j        d| ¦  «        }|r|d         n|                      ¦   «         }|                     ¦   «         }d}|D ]7}d|v r|                     d¦  «        sŒ|                     d¦  «        d         } |sdS d	d
id	d
id	d
id	d
id	d
id	d
id	did	did	did	did	didddddœd	didœ}|                     |¦  «        }|r||v r||         S dS )a
  Return a human-readable note when a non-zero exit code is non-erroneous.

    Returns None when the exit code is 0 or genuinely signals an error.
    The note is appended to the tool result so the model doesn't waste
    turns investigating expected exit codes.
    r   Nz\s*(?:\|\||&&|[|;])\s*rÄ   r   r°   Ú-ú/rp   zNo matches found (not an error)z%Files differ (expected, not an error)zGSome directories were inaccessible (partial results may still be valid)z5Condition evaluated to false (expected, not an error)zCould not resolve hostzFailed to connect to hostz2HTTP response code indicated error (e.g. 404, 500)zOperation timed out)é   é   r„  é   uL   Non-zero exit (often normal â€” e.g. 'git diff' returns 1 when files differ))ÚgrepÚegrepÚfgrepÚrgÚagÚackÚdiffÚ	colordiffrÉ   ÚtestÚ[ÚcurlÚgit)r´   r²   Ústripr±   rê   )	rL   rØ  ÚsegmentsÚlast_segmentÚwordsÚbase_cmdÚwÚ	semanticsÚcmd_semanticss	            r   Ú_interpret_exit_coderó  ÿ  st  € ð �A‚~€~Øˆtõ
 ŒxÐ1°7Ñ;Ô;€HØ$,Ð9�H˜R”L�L°'×@Ò@ÑBÔB€Lð ×ÒÑ Ô €EØ€HØð ð ˆØ�!ˆ8ˆ8˜AŸLšL¨Ñ-Ô-ˆ8ØØ—7’7˜3‘<”< Ô#ˆØàð Øˆtð
 Ð6Ð7ØÐ6Ð7ØÐ6Ð7ØÐ6Ð7ØÐ6Ð7ØÐ6Ð7àÐ<Ð=ØÐ@ÐAàÐ^Ð_àÐLÐMØÐLÐMð (Ø*ØDØ%ð	
ð 
ð ÐcÐdð1,ð ,€Ið6 —M’M (Ñ+Ô+€MØð (˜ mÐ3Ð3Ø˜YÔ'Ð'àˆ4r@   c                 ó¦   — d                      |                      ¦   «                              ¦   «         ¦  «        }|                     d¦  «        od|v S )au  Return True when PTY mode would break stdin-driven commands.

    Some CLIs change behavior when stdin is a TTY. In particular,
    `gh auth login --with-token` expects the token to arrive via piped stdin and
    waits for EOF; when we launch it under a PTY, `process.submit()` only sends a
    newline, so the command appears to hang forever with no visible progress.
    Ú zgh auth loginz--with-token)r{   rS  r²   r±   ©rL   Ú
normalizeds     r   Ú_command_requires_pipe_stdinrø  ?  sL   € ð —’˜'Ÿ-š-™/œ/×/Ò/Ñ1Ô1Ñ2Ô2€Jà×Ò˜oÑ.Ô.ð 	)Ø˜jÐ(ðr@   z\b(?:nohup|disown|setsid)\bz\s&\sz\s&\s*(?:#.*)?$z@\b(?:npm|pnpm|yarn|bun)\s+(?:run\s+)?(?:dev|start|serve|watch)\bz\bdocker\s+compose\s+up\bz\bnext\s+dev\bz\bvite(?:\s|$)z\bnodemon\bz\buvicorn\bz\bgunicorn\bz$\bpython(?:3)?\s+-m\s+http\.server\bc                 óØ   — d                      |                      ¦   «                              ¦   «         ¦  «        }d|v p-|                     d¦  «        pd|v p|                     d¦  «        S )zGReturn True for informational invocations that should never be blocked.rõ  z --helpz -hz
 --versionz -v)r{   rS  r²   Úendswithrö  s     r   Ú#_looks_like_help_or_version_commandrû  ]  so   € à—’˜'Ÿ-š-™/œ/×/Ò/Ñ1Ô1Ñ2Ô2€Jà�ZÐð 	&Ø×Ò˜uÑ%Ô%ð	&à˜:Ð%ð	&ð ×Ò˜uÑ%Ô%ð	r@   c                 ó  — t          | ¦  «        rdS t                               | ¦  «        r	 dS t                               | ¦  «        st                               | ¦  «        r	 dS t
          D ]}|                     | ¦  «        r	  dS ŒdS )zÃSuggest background mode when a foreground command looks long-lived.

    Prevents workflows that start a server/watch process and then stall before
    follow-up checks or test commands run.
    NzÇForeground command uses shell-level background wrappers (nohup/disown/setsid). Use terminal(background=true) so Hermes can track the process, then run readiness checks and tests in separate commands.z Foreground command uses '&' backgrounding. Use terminal(background=true) for long-lived processes, then run health checks and tests in follow-up terminal calls.zÁThis foreground command appears to start a long-lived server/watch process. Run it with background=true, verify readiness (health endpoint/log signal), then execute tests in a separate command.)rû  Ú_SHELL_LEVEL_BACKGROUND_REÚsearchÚ_INLINE_BACKGROUND_AMP_REÚ_TRAILING_BACKGROUND_AMP_REÚ_LONG_LIVED_FOREGROUND_PATTERNS)rL   Úpatterns     r   Ú_foreground_background_guidancer  h  sÂ   € õ +¨7Ñ3Ô3ð Øˆtå!×(Ò(¨Ñ1Ô1ð 
ð?ð	
ð 	
õ !×'Ò'¨Ñ0Ô0ð 
Õ4O×4VÒ4VÐW^Ñ4_Ô4_ð 
ðWð	
ð 	
õ
 3ð ð ˆØ�>Š>˜'Ñ"Ô"ð 	ð<ðð ð ð	ð ˆ4r@   Únotify_on_completeÚ
backgroundc                 ó"   — |r
| r|rd}d|fS |dfS )uK  Decide what to do when both notify_on_complete and watch_patterns are set.

    These flags produce duplicate, delayed notifications when combined â€” one
    notification per watch-pattern match AND one on process exit, with async
    delivery that can spam the user long after the process ends. When both are
    set, we drop watch_patterns in favor of notify_on_complete (the more useful
    "let me know when it's done" signal) and return a human-readable note.

    Returns:
        (watch_patterns_to_use, conflict_note). conflict_note is "" when there
        is no conflict.
    zuwatch_patterns ignored because notify_on_complete=True; these two flags produce duplicate notifications when combinedNr   r?   )r  Úwatch_patternsr  Únotes       r   Ú#_resolve_notification_flag_conflictr	  ‰  s=   € ð$ ð Ð(ð ¨^ð ðLð 	ð �TˆzÐØ˜2ÐÐr@   ÚforceÚptyr  c	                 ón  — 	 t          | t          ¦  «        s]t                               dt	          | ¦  «        j        ¦  «         t          j        dddt	          | ¦  «        j        › �ddœd¬¦  «        S t          ¦   «         }	|	d	         }
t          |¦  «        }t                               |i ¦  «        }|
d
k    r|                     d¦  «        p|	d         }nn|
dk    r|                     d¦  «        p|	d         }nJ|
dk    r|                     d¦  «        p|	d         }n&|
dk    r|                     d¦  «        p|	d         }nd}|                     d¦  «        p|	d         }|	d         }|p|}|s1|r/|t          k    r$t          j        dd|› dt          › d�id¬¦  «        S |s,t          | ¦  «        }|rt          j        dd|ddœd¬¦  «        S t          ¦   «          t          5  |t           v r+t#          j        ¦   «         t$          |<   t           |         }d}nd}ddd¦  «         n# 1 swxY w Y   |�r*t&          5  |t(          vrt+          j        ¦   «         t(          |<   t(          |         }ddd¦  «         n# 1 swxY w Y   |5  t          5  |t           v r*t#          j        ¦   «         t$          |<   t           |         }d}ddd¦  «         n# 1 swxY w Y   |�rk|
dk    rt/          ¦   «          t                               d|
|dd…         ¦  «         	 d}|
dk    rl|	                     dd¦  «        |	                     dd¦  «        |	                     dd¦  «        |	                     d d¦  «        |	                     d!d¦  «        d"œ}d}|
d#v rÀ|	                     d$d%¦  «        |	                     d&d'¦  «        |	                     d(d)¦  «        |	                     d*d¦  «        |	                     d+d,¦  «        |	                     d-g ¦  «        |	                     d.d¦  «        |	                     d/g ¦  «        |	                     d0i ¦  «        d1œ	}d}|
d2k    rd3|	                     d4d¦  «        i}t3          |
||||||||	                     d5¦  «        ¬6¦	  «	        }nB# t4          $ r5}t          j        ddd7|› d8�d9dœd¬¦  «        cY d}~cddd¦  «         S d}~ww xY wt          5  |t           |<   t#          j        ¦   «         t$          |<   |}ddd¦  «         n# 1 swxY w Y   t                               d:|
|dd…         ¦  «         ddd¦  «         n# 1 swxY w Y   d}|�sMt7          | |
¦  «        }|d;         sÒ|                     d<¦  «        d=k    rnt          j        dd|                     d>d?¦  «        d=|                     d@| ¦  «        |                     dAdB¦  «        |                     dCd¦  «        dDœd¬¦  «        S |                     dAdB¦  «        }dE|› dF�}t          j        dd|                     d>|¦  «        dGdœd¬¦  «        S |                     dH¦  «        r|                     dAdI¦  «        }dJ|› dK�}n1|                     dL¦  «        r|                     dAdI¦  «        }dM|› dN�}|r]t9          |¦  «        }|rLt                               dO|ddP…         t;          | ¦  «        ¦  «         t          j        dd|dGdœd¬¦  «        S d}|} |rt=          | ¦  «        rd} dQ}|�r-dRdSlm }! dRdTl!m"}"  |!d¬U¦  «        }#|p|}$	 |
d2k    r3|" #                    | |$||#tI          |dV¦  «        r|j%        nd| ¬W¦  «        }%n|" &                    || |$||#¬X¦  «        }%dY|%j'        |%j(        dRddZœ}&|r||&d[<   |r||&d\<   |rk|s|rgdRd]l)m*}'  |'d^d¦  «        }(|(rS |'d_d¦  «        }) |'d`d¦  «        }* |'dad¦  «        }+ |'dbd¦  «        },|(|%_+        |)|%_,        |+|%_-        |,|%_.        |*|%_/        ta          tc          |¦  «        |tc          |¦  «        ¬c¦  «        \  }}-|-r&t                               dd|%j'        |-¦  «         |-|&de<   |r^|r\d|%_2        d|&df<   |%j+        rIdg|%_3        |"j4         5                    |%j'        dg|#|%j+        |%j,        |%j-        |%j.        |%j/        ddhœ	¦  «         |r |rtm          |¦  «        |%_7        |%j7        |&di<   t          j        |&d¬¦  «        S # tp          $ r4}t          j        dddjt          |¦  «        › �dkœd¬¦  «        cY d}~S d}~ww xY wdl}.dR}/d}0|/|.k    �re	 d|i}1|r||1d<    |j9        | fi |1¤Ž}0�nH# tp          $ �r:}t          |¦  «         :                    ¦   «         }2d|2v r#t          j        ddmdn|› do�dkœd¬¦  «        cY d}~S |/|.k     rd|/d%z  }/dp|/z  }3t                               dq|3|/|.t;          | ¦  «        t	          |¦  «        j        |||
¦	  «	         t#          j;        |3¦  «         Y d}~Œàt           <                    dr|.t;          | ¦  «        t	          |¦  «        j        |||
¦  «         t          j        dddst	          |¦  «        j        › dtt          |¦  «        › �dkœd¬¦  «        cY d}~S d}~ww xY w	 |0                     dud¦  «        }4|0                     dvdR¦  «        }5t{          |4|
¦  «        }4	 dRdwl>m?}6  |6dx| |4|5|pd|
¬y¦  «        }7|7D ]}8t          |8t          ¦  «        r|8}4 nŒn# tp          $ r Y nw xY wdRdzl@mA}9  |9¦   «         }:t…          |4¦  «        |:k    r[t‡          |:d{z  ¦  «        };|:|;z
  }<t…          |4¦  «        |;z
  |<z
  }=d||=› d}t…          |4¦  «        › d~�}>|4d|;…         |>z   |4|< d…         z   }4dRdlDmE}?  |?|4¦  «        }4dRd€lFmG}@ |4r |@|4 H                    ¦   «         ¦  «        nd}4t“          | |5¦  «        }A|4|5ddkœ}B|r||Bd[<   |Ar|A|Bd�<   t          j        |Bd¬¦  «        S # tp          $ ri}dRdlJ}C|C K                    ¦   «         }Dt           <                    d‚|D¦  «         t          j        dddƒt          |¦  «        › �|Ddd„œd¬¦  «        cY d}~S d}~ww xY w)…u.  
    Execute a command in the configured terminal environment.

    Args:
        command: The command to execute
        background: Whether to run in background (default: False)
        timeout: Command timeout in seconds (default: from config)
        task_id: Unique identifier for environment isolation (optional)
        force: If True, skip dangerous command check (use after user confirms)
        workdir: Working directory for this command (optional, uses session cwd if not set)
        pty: If True, use pseudo-terminal for interactive CLI tools (local backend only)
        notify_on_complete: If True and background=True, you'll be notified exactly once when the process exits. The right choice for almost every long task. MUTUALLY EXCLUSIVE with watch_patterns.
        watch_patterns: List of strings to watch for in background output. HARD rate limit: 1 notification per 15s per process. After 3 strike windows in a row, watch_patterns is disabled and the session is auto-promoted to notify_on_complete. Use ONLY for rare, one-shot mid-process signals on long-lived processes (server readiness, migration-done markers). NEVER use in loops/batch jobs â€” error patterns there will hit the strike limit and get disabled. MUTUALLY EXCLUSIVE with notify_on_complete â€” set one, not both.

    Returns:
        str: JSON string with output, exit_code, and error fields

    Examples:
        # Execute a simple command
        >>> result = terminal_tool(command="ls -la /tmp")

        # Run a background task
        >>> result = terminal_tool(command="python server.py", background=True)

        # With custom timeout
        >>> result = terminal_tool(command="long_task.sh", timeout=300)
        
        # Force run after user confirmation
        # Note: force parameter is internal only, not exposed to model API
    z+Rejected invalid terminal command value: %sr   rÄ   z&Invalid command: expected string, got rÎ  )rZ   rØ  rÎ  ÚstatusF)Úensure_asciirM   r  r'  r   r+  r  r.  r!  r0  r#  r˜   zForeground timeout zs exceeds the maximum of zNs. Use background=true with notify_on_complete=true for long-running commands.TNz*Creating new %s environment for task %s...é   r  r9  r;  r=  r„  r@  rB  )r�  r‚  rƒ  r…  r•  )r  r   r  r!  rN  rp   rO  rn  rP  ro  rQ  r$  r&  rR  r3  r)  rp  )	rN  rO  rP  rQ  r$  rR  r3  r)  rp  r  r•  rM  r2  )	rM   ri  r#  r˜   rj  rk  rl  rú   r2  z5Terminal tool disabled: environment creation failed (rÇ   Údisabledz %s environment ready for task %sÚapprovedr  Úapproval_requiredr˜  zWaiting for user approvalrL   Údescriptionzcommand flaggedÚpattern_key)rZ   rØ  rÎ  r  rL   r  r  zCommand denied: z?. Use the approval prompt to allow it, or rephrase the command.ÚblockedÚuser_approvedzflagged as dangerouszCommand required approval (z) and was approved by the user.Úsmart_approvedzCommand was flagged (z&) and auto-approved by smart approval.z+Blocked dangerous workdir: %s (command: %s)r¥   zÉPTY disabled for this command because it expects piped stdin/EOF (for example gh auth login --with-token). For local background processes, call process(action='close') after writing so it receives EOF.r   )Úget_current_session_keyr�  )r   rx  )rL   r#  rú   Úsession_keyÚenv_varsÚuse_pty)rx  rL   r#  rú   r  zBackground process started)rZ   Ú
session_idÚpidrØ  rÎ  rC   Úpty_note)Úget_session_envÚHERMES_SESSION_PLATFORMÚHERMES_SESSION_CHAT_IDÚHERMES_SESSION_THREAD_IDÚHERMES_SESSION_USER_IDÚHERMES_SESSION_USER_NAME)r  r  r  zbackground proc %s: %sÚwatch_patterns_ignoredr  rÂ  )	r  Úcheck_intervalr  ru   Úchat_idÚuser_idÚ	user_nameÚ	thread_idr  r  z$Failed to start background process: )rZ   rØ  rÎ  ro   é|   zCommand timed out after z secondsr»   zfExecution error, retrying in %ds (attempt %d/%d) - Command: %s - Error: %s: %s - Task: %s, Backend: %szWExecution failed after %d retries - Command: %s - Error: %s: %s - Task: %s, Backend: %szCommand execution failed: r  rZ   Ú
returncode)Úinvoke_hookÚtransform_terminal_output)rL   rZ   r,  rú   rM   )Úget_max_bytesgš™™™™™Ù?z

... [OUTPUT TRUNCATED - z chars omitted out of z total] ...

)Ú
strip_ansi)Úredact_sensitive_textÚexit_code_meaningzterminal_tool exception:
%szFailed to execute command: )rZ   rØ  rÎ  Ú	tracebackr  )Lrª   r)   r   r   r«   r¬   r  Údumpsrd  r  rù   rê   ÚFOREGROUND_MAX_TIMEOUTr  rÀ  r­  rö   r›   r÷   r¯  rø   rž   ÚLockr8   rZ  rš  r¬  rR   rY   r­   rø  Útools.approvalr  r¨  rž  Úspawn_localr±  rx  Úspawn_via_envÚidr  Úgateway.session_contextr  Úwatcher_platformÚwatcher_chat_idÚwatcher_user_idÚwatcher_user_nameÚwatcher_thread_idr	  r³   r  Úwatcher_intervalÚpending_watchersrz   r©  r  r1   ÚexecuterS  rœ   rÎ  rd   Úhermes_cli.pluginsr-  Útools.tool_output_limitsr/  r¼   r’  Útools.ansi_stripr0  Úagent.redactr1  rë  ró  r3  Ú
format_exc)ErL   r  r˜   rú   r
  rS   r  r  r  r»  rM   Úeffective_task_idrû   ri  r#  Údefault_timeoutÚeffective_timeoutÚguidancerx  Úneeds_creationÚ	task_lockrj  rk  rl  Únew_envr6   Úapproval_noterC   ÚdescÚfallback_msgÚworkdir_errorÚpty_disabled_reasonÚeffective_ptyr  rž  r  Úeffective_cwdÚproc_sessionÚresult_dataÚ_gseÚ_gw_platformÚ_gw_chat_idÚ_gw_thread_idÚ_gw_user_idÚ_gw_user_nameÚconflict_noteÚmax_retriesÚretry_countrŽ   Úexecute_kwargsrµ  Ú	wait_timerZ   r,  r-  Úhook_resultsÚhook_resultr/  ÚMAX_OUTPUT_CHARSÚ
head_charsÚ
tail_charsÚomittedÚtruncated_noticer0  r1  Ú	exit_noteÚresult_dictr3  Útb_strsE                                                                        r   Úterminal_toolrn  ¤  sÙ  € ðRzÝ˜'¥3Ñ'Ô'ð 
	#Ý�NŠNØ=Ý�W‘”Ô&ñô ð õ ”:ØØØZÅ$ÀwÁ-Ä-ÔBXÐZÐZØ!ð	ð ð
 "ð#ñ #ô #ð #õ !Ñ"Ô"ˆØ˜*Ô%ˆõ 7°wÑ?Ô?Ðõ (×+Ò+Ð,=¸rÑBÔBˆ	ð �xÒÐØ—M’M .Ñ1Ô1ÐK°V¸NÔ5KˆEˆEØ˜Ò&Ð&Ø—M’MÐ"5Ñ6Ô6ÐU¸&ÐATÔ:UˆEˆEØ˜Ò Ð Ø—M’M -Ñ0Ô0ÐI°F¸=Ô4IˆEˆEØ˜Ò"Ð"Ø—M’M /Ñ2Ô2ÐM°f¸_Ô6MˆEˆEàˆEà�mŠm˜EÑ"Ô"Ð3 f¨U¤mˆØ  Ô+ˆØ#Ð6 Ðð ð 	#˜gð 	#¨'Õ4JÒ*JÐ*JÝ”:ØðJ¨'ð Jð JÝ-ðJð Jð Jðð "ð#ñ #ô #ð #ð ð 	'Ý6°wÑ?Ô?ˆHØð 'Ý”zØ Ø!#Ø%Ø%ð	#ð #ð
 !&ð'ñ 'ô 'ð 'õ 	ÑÔÐõ ð 	&ð 	&Ø Õ$8Ð8Ð8Ý48´I±K´K•Ð0Ñ1Ý*Ð+<Ô=�Ø!&��à!%�ð	&ð 	&ð 	&ñ 	&ô 	&ð 	&ð 	&ð 	&ð 	&ð 	&ð 	&øøøð 	&ð 	&ð 	&ð 	&ð ñ I	eå%ð ?ð ?Ø$­OÐ;Ð;Ý9B¼Ñ9IÔ9I•OÐ$5Ñ6Ý+Ð,=Ô>�	ð?ð ?ð ?ñ ?ô ?ð ?ð ?ð ?ð ?ð ?ð ?øøøð ?ð ?ð ?ð ?ð
 ð Beð Beåð /ð /Ø(Õ,@Ð@Ð@Ý<@¼I¹K¼K�Ð'8Ñ9Ý2Ð3DÔE˜Ø).˜ð	/ð /ð /ñ /ô /ð /ð /ð /ð /ð /ð /øøøð /ð /ð /ð /ð "ñ :eØ =Ò0Ð0Ý1Ñ3Ô3Ð3Ý—K’KÐ LÈhÐXiÐjlÐklÐjlÔXmÑnÔnÐnð0/Ø%)˜
Ø# uÒ,Ð,à(.¯
ª
°:¸rÑ(BÔ(BØ(.¯
ª
°:¸rÑ(BÔ(BØ(.¯
ª
°:¸rÑ(BÔ(BØ'-§z¢z°)¸RÑ'@Ô'@Ø.4¯jªjÐ9IÈ5Ñ.QÔ.Qð*ð *˜Jð ,0Ð(Ø#Ð'TÐTÐTà17·²¸OÈQÑ1OÔ1OØ4:·J²JÐ?QÐSWÑ4XÔ4XØ28·*²*Ð=MÈuÑ2UÔ2UØ8>¿
º
ÐCYÐ[_Ñ8`Ô8`Ø.4¯jªj¸ÀvÑ.NÔ.NØ28·*²*Ð=MÈrÑ2RÔ2RØAGÇÂÐLkÐmrÑAsÔAsØ6<·j²jÐAUÐWYÑ6ZÔ6ZØ.4¯jªj¸ÀrÑ.JÔ.Jð
0ð 
0Ð,ð (,˜Ø# wÒ.Ð.à ,¨f¯jªjÐ9KÈUÑ.SÔ.Sð,˜Lõ #6Ø%-Ø"'Ø #Ø$5Ø'1Ø-=Ø)5Ø$5Ø%+§Z¢Z°
Ñ%;Ô%;ð
#ñ 
#ô 
#˜˜øõ 'ð /ð /ð /Ý#œzØ&(Ø)+Ø%aÐ]^Ð%aÐ%aÐ%aØ&0ð	+ð +ð
 ).ð /ñ  /ô  /ð /ð /ð /ð /ð /ðoBeð Beð Beð Beñ Beô Beð Beð Beøøøøðl/øøøõ #ð &ð &ØBIÕ,Ð->Ñ?Ý<@¼I¹K¼K�Ð'8Ñ9Ø%˜ð&ð &ð &ñ &ô &ð &ð &ð &ð &ð &ð &øøøð &ð &ð &ð &õ —K’KÐ BÀHÐN_Ð`bÐabÐ`bÔNcÑdÔdÐdðEBeð Beð Beñ Beô Beð Beð Beð Beð Beð Beð Beøøøð Beð Beð Beð BeðL ˆØñ  	eÝ(¨°(Ñ;Ô;ˆHØ˜JÔ'ð 'à—<’< Ñ)Ô)Ð-@Ò@Ð@Ýœ:Ø"$Ø%'Ø!)§¢¨iÐ9TÑ!UÔ!UØ"5Ø#+§<¢<°	¸7Ñ#CÔ#CØ'/§|¢|°MÐCTÑ'UÔ'UØ'/§|¢|°MÀ2Ñ'FÔ'Fð'ð 'ð %*ð+ñ +ô +ð +ð  —|’| MÐ3DÑEÔE�ðT tð Tð Tð Tð õ ”zØ Ø!#Ø%Ÿ\š\¨)°\ÑBÔBØ'ð	#ð #ð
 !&ð'ñ 'ô 'ð 'ð �|Š|˜OÑ,Ô,ð eØ—|’| MÐ3IÑJÔJ�Ø c¸dÐ cÐ cÐ c��Ø—’Ð.Ñ/Ô/ð eØ—|’| MÐ3IÑJÔJ�Ø d¸Ð dÐ dÐ d�ð ð 
	'Ý-¨gÑ6Ô6ˆMØð 'Ý—’ÐLØ& t¨ tœ}Õ.CÀGÑ.LÔ.LñNô Nð Nå”zØ Ø!#Ø*Ø'ð	#ð #ð
 !&ð'ñ 'ô 'ð 'ð #ÐØˆØð 	Õ/°Ñ8Ô8ð 	Ø!ˆMðð  ð ñ T	?ð ?Ð>Ð>Ð>Ð>Ð>Ø?Ð?Ð?Ð?Ð?Ð?à1Ð1¸"Ð=Ñ=Ô=ˆKØ#˜N sˆMða'Ø˜wÒ&Ð&Ø#3×#?Ò#?Ø 'Ø)Ø 1Ø$/Ý,3°C¸Ñ,?Ô,?Ð!I ¤ ÀTØ -ð $@ñ $ô $�L�Lð $4×#AÒ#AØØ 'Ø)Ø 1Ø$/ð $Bñ $ô $�Lð ;Ø".¤/Ø'Ô+Ø!"Ø!ðð �ð !ð <Ø.;�K 
Ñ+Ø&ð BØ.A�K 
Ñ+ð
 ð GÐ#5ð G¸ð GØOÐOÐOÐOÐOÐOØ#' 4Ð(AÀ2Ñ#FÔ#F�LØ#ð 	GØ&* dÐ+CÀRÑ&HÔ&H˜Ø(,¨Ð-GÈÑ(LÔ(L˜Ø&* dÐ+CÀRÑ&HÔ&H˜Ø(,¨Ð-GÈÑ(LÔ(L˜Ø8D˜Ô5Ø7B˜Ô4Ø7B˜Ô4Ø9F˜Ô6Ø9F˜Ô6õ 1TÝ'+Ð,>Ñ'?Ô'?Ø#1Ý# JÑ/Ô/ð1ñ 1ô 1Ñ-� ð
 !ð JÝ—N’NÐ#;¸\¼_ÈmÑ\Ô\Ð\Ø<I�KÐ 8Ñ9ð &ð ¨*ð Ø6:�LÔ3Ø8<�KÐ 4Ñ5ð
 $Ô4ð Ø89˜Ô5Ø(Ô9×@Ò@Ø*6¬/Ø./Ø+6Ø(4Ô(EØ'3Ô'CØ'3Ô'CØ)5Ô)GØ)5Ô)GØ26ð
Bð 
Bñ 
ô 
ð 
ð "ð P jð PÝ26°~Ñ2FÔ2F�LÔ/Ø4@Ô4O�KÐ 0Ñ1å”z +¸EÐBÑBÔBÐBøÝð 'ð 'ð 'Ý”zØ Ø!#ØLÅCÈÁFÄFÐLÐLð#ð #ð !&ð	'ñ 'ô 'ð 'ð 'ð 'ð 'ð 'ð 'øøøøð'øøøð ˆKØˆKØˆFà Ò,Ñ,ð+Ø&/Ð1BÐ%C�NØð 8Ø07˜ uÑ-Ø(˜Sœ[¨ÐCÐC°NÐCÐC�F‘FøÝ ð +ñ +ð +Ý # A¡¤§¢¡¤�IØ  IÐ-Ð-Ý#œzØ&(Ø),Ø%[Ð@QÐ%[Ð%[Ð%[ð+ð +ð ).ð	 /ñ  /ô  /ð /ð /ð /ð /ð /ð /ð # [Ò0Ð0Ø# qÑ(˜Ø$%¨Ñ$4˜	ÝŸšð  (PØ'0°+¸{ÕLaÐbiÑLjÔLjÕlpÐqrÑlsÔlsÔl|Ð~ð  BSð  U]ñ^ô ^ð ^åœ
 9Ñ-Ô-Ð-Ø ˜˜˜˜å—L’LÐ!zØ!,Õ.CÀGÑ.LÔ.LÍdÐSTÉgÌgÔN^Ð`aÐctÐv~ñ@ô @ð @åœ:Ø"$Ø%'Ø!Z½dÀ1¹g¼gÔ>NÐ!ZÐ!ZÕRUÐVWÑRXÔRXÐ!ZÐ!Zð'ð 'ð %*ð	+ñ +ô +ð +ð +ð +ð +ð +ð +øøøøð)+øøøð6 ð —Z’Z ¨"Ñ-Ô-ˆFØŸš L°!Ñ4Ô4ˆJõ *¨&°(Ñ;Ô;ˆFðØ:Ð:Ð:Ð:Ð:Ð:Ø*˜{Ø/Ø#Ø!Ø)Ø-Ð3°Ø%ð ñ  ô  �ð $0ð ð �KÝ! +­sÑ3Ô3ð Ø!,˜Ø˜ðøøõ ð ð ð Ø�ðøøøð ?Ð>Ð>Ð>Ð>Ð>Ø,˜}™œÐÝ�6‰{Œ{Ð-Ò-Ð-Ý Ð!1°CÑ!7Ñ8Ô8�
Ø-°
Ñ:�
Ý˜f™+œ+¨
Ñ2°ZÑ?�ð;°7ð ;ð ;Ý! &™kœkð;ð ;ð ;ð !ð     Ô,Ð/?Ñ?À&È*ÈÈÈÔBVÑV�ð 4Ð3Ð3Ð3Ð3Ð3Ø�Z Ñ'Ô'ˆFð ;Ð:Ð:Ð:Ð:Ð:Ø>DÐLÐ*Ð*¨6¯<ª<©>¬>Ñ:Ô:Ð:È"ˆFõ -¨W°jÑAÔAˆIð !Ø'Øðð ˆKð
 ð 8Ø*7�˜JÑ'Øð =Ø3<�Ð/Ñ0å”:˜k¸Ð>Ñ>Ô>Ð>øåð 
ð 
ð 
ØÐÐÐØ×%Ò%Ñ'Ô'ˆÝ�ŠÐ3°VÑ<Ô<Ð<ÝŒzØØØ;µ3°q±6´6Ð;Ð;ØØð
ð 
ð ðñ ô ð 	ð 	ð 	ð 	ð 	ð 	øøøøð	
øøøsÔ  ‚A1q Á4D-q Æ"-q Çq Ç%7H(Èq È(H,È,q È/H,È0q È=2I;É/q É;I?É?q ÊI?Êq ÊUÊ4KËUËK	ËUËK	Ë>UÌFRÒUÒ
SÒ'SÓSÓUÓ
q ÓSÓ
UÓ&(TÔUÔT	ÔUÔ!T	Ô"'UÕ	q ÕUÕq ÕUÕB&q ØA
q ÙCq Ü8q Ý
Gd ä
eä#)eåeåq åeåq å(f æq ækæAkçkçq çA%kè;q é A=kê=kê>q ëkëA q ì	7m í q í
míq ímíC2q ñ
r4ñAr/ò)r4ò/r4c                  óä  — t          ¦   «         } | d         }	 |dk    rdS |dk    rRddlm}  |¦   «         }|st                               d¦  «         dS t          j        |d	gdd
¬¦  «        }|j        dk    S |dk    rPt          j	        d¦  «        pt          j	        d¦  «        }|r$t          j        |dgdd
¬¦  «        }|j        dk    S dS |dk    rH|  
                    d¦  «        r|  
                    d¦  «        st                               d¦  «         dS dS |dk    �r[t          |  
                    d¦  «        ¦  «        }|d         dk    rdS |d         dk    râ|d         rt                               d¦  «         dS |d         dk    rt                               d¦  «         dS |d         dk    rEt          ¦   «         rt                               d¦  «         nt                               d¦  «         dS t          ¦   «         rt                               d¦  «         nt                               d¦  «         dS t          j                             d¦  «        €t                               d!¦  «         dS dS |d"k    rdd#lm} t%          j        d$¦  «        d uS t                               d%|¦  «         dS # t(          $ r(}t                               d&|d¬'¦  «         Y d }~dS d }~ww xY w)(z8Check if all requirements for the terminal tool are met.rM   r  Tr  r   )Úfind_dockerz?Docker executable not found in PATH or common install locationsFÚversionrÂ  )Úcapture_outputr˜   r   Ú	apptainerz	--versionr  r9  r;  z„SSH backend selected but TERMINAL_SSH_HOST and TERMINAL_SSH_USER are not both set. Configure both or switch TERMINAL_ENV to 'local'.r  r$  rz  r{  r}  r~  zïModal backend selected with TERMINAL_MODAL_MODE=managed, but a paid Nous subscription is required for the Tool Gateway and no direct Modal credentials/config were found. Log in with `hermes model` or choose TERMINAL_MODAL_MODE=direct/auto.r  z®Modal backend selected with TERMINAL_MODAL_MODE=managed, but the managed tool gateway is unavailable. Configure the managed gateway or choose TERMINAL_MODAL_MODE=direct/auto.z¦Modal backend selected with TERMINAL_MODAL_MODE=direct, but no direct Modal credentials/config were found. Configure Modal or choose TERMINAL_MODAL_MODE=managed/auto.zžModal backend selected with TERMINAL_MODAL_MODE=direct, but no direct Modal credentials/config were found. Configure Modal or choose TERMINAL_MODAL_MODE=auto.z±Modal backend selected but no direct Modal credentials/config or managed tool gateway was found. Configure Modal, set up the managed gateway, or choose a different TERMINAL_ENV.z|Modal backend selected but no direct Modal credentials/config was found. Configure Modal or choose a different TERMINAL_ENV.NzFmodal is required for direct modal terminal backend: pip install modalr!  )ÚDaytonaÚDAYTONA_API_KEYzWUnknown TERMINAL_ENV '%s'. Use one of: local, docker, singularity, modal, daytona, ssh.z&Terminal requirements check failed: %sr&   )rd  Útools.environments.dockerrp  r   rÎ  Ú
subprocessÚrunr,  rÏ  Úwhichrê   rh  r   Ú	importlibÚutilÚ	find_specr!  rt  r   r   r1   )	r»  rM   rp  r  rŽ   Ú
executabler—  rt  r6   s	            r   Úcheck_terminal_requirementsr~  Š  s‘  € åÑÔ€FØ�jÔ!€HðaØ�wÒÐØ�4à˜Ò!Ð!Ø=Ð=Ð=Ð=Ð=Ð=Ø �[‘]”]ˆFØð Ý—’Ð^Ñ_Ô_Ð_Ø�uÝ”^ V¨YÐ$7ÈÐVWÐXÑXÔXˆFØÔ$¨Ò)Ð)à˜Ò&Ð&Ýœ kÑ2Ô2ÐQµf´lÀ=Ñ6QÔ6QˆJØð .Ý#œ¨°[Ð(AÐRVÐ`aÐbÑbÔb�ØÔ(¨AÒ-Ð-Ø�5à˜ÒÐØ—:’:˜jÑ)Ô)ð °·²¸JÑ1GÔ1Gð Ý—’ðZñô ð ð �uØ�4à˜Ò Ñ Ý2°6·:²:¸lÑ3KÔ3KÑLÔLˆKØÐ-Ô.°)Ò;Ð;Ø�tàÐ-Ô.°(Ò:Ð:ØÐ5Ô6ð !Ý—L’LðEñô ð ð !˜5Ø˜vÔ&¨)Ò3Ð3Ý—L’Lð;ñô ð ð
 !˜5Ø  Ô(¨HÒ4Ð4Ý1Ñ3Ô3ð ÝŸšð@ñô ð ð õ Ÿšð8ñô ð ð
 !˜5å1Ñ3Ô3ð 
ÝŸšðBñô ð ð õ ŸšðRñô ð ð !˜5åŒ~×'Ò'¨Ñ0Ô0Ð8Ý—’ÐeÑfÔfÐfØ�uà�4à˜Ò"Ð"Ø'Ð'Ð'Ð'Ð'Ð'Ý”9Ð.Ñ/Ô/°tÐ;Ð;õ �LŠLð'àñô ð ð
 �5øÝð ð ð Ý�ŠÐ=¸qÈ4ˆÑPÔPÐPØˆuˆuˆuˆuˆuøøøøðøøøsb   ˜J=  2J= Á#J= Á8AJ= ÃA
J= Ä5J= Å.J= Æ&J= Æ+AJ= Ç<AJ= É9J= É>!J= Ê J= Ê=
K/ËK*Ë*K/Ú__main__zTerminal Tool Modulez2==================================================z
Current Configuration:z  Environment type: z  Docker image: r'  z  Modal image: r.  z  Working directory: z  Default timeout: Úsz  Lifetime: u;   
â�Œ Requirements not met. Please check the messages above.rp   u   
âœ… All requirements met!z
Available Tool:z=  - terminal_tool: Execute commands in sandboxed environmentsz
Usage Examples:z  # Execute a commandz*  result = terminal_tool(command='ls -la')z  z  # Run a background taskzE  result = terminal_tool(command='python server.py', background=True)z
Environment Variables:r  z  TERMINAL_ENV: r  r  z- (local/docker/singularity/modal/daytona/ssh)z  TERMINAL_DOCKER_IMAGE: r(  z  TERMINAL_SINGULARITY_IMAGE: r,  r-  z  TERMINAL_MODAL_IMAGE: r/  z  TERMINAL_DAYTONA_IMAGE: r1  z  TERMINAL_CWD: r  r]   z  TERMINAL_SANDBOX_DIR: ÚTERMINAL_SANDBOX_DIRz
/sandboxesz  TERMINAL_TIMEOUT: r4  Ú60z  TERMINAL_LIFETIME_SECONDS: r7  r8  )ÚregistryÚterminalÚobjectÚstringz The command to execute on the VM)r«   r  Úbooleanu2  Run the command in the background. Two patterns: (1) Long-lived processes that never exit (servers, watchers). (2) Long-running tasks paired with notify_on_complete=true â€” you can keep working and get notified when the task finishes. For short commands, prefer foreground with a generous timeout instead.)r«   r  r   z3Max seconds to wait (default: 180, foreground max: u   ). Returns INSTANTLY when command finishes â€” set high for long tasks, you won't wait unnecessarily. Foreground timeout above z7s is rejected; use background=true for longer commands.)r«   r  Úminimumz^Working directory for this command (absolute path). Defaults to the session working directory.zœRun in pseudo-terminal (PTY) mode for interactive CLI tools like Codex, Claude Code, or Python REPL. Only works with local and SSH backends. Default: false.u¾  When true (and background=true), you'll be automatically notified exactly once when the process finishes. **This is the right choice for almost every long-running task** â€” tests, builds, deployments, multi-item batch jobs, anything that takes over a minute and has a defined end. Use this and keep working on other things; the system notifies you on exit. MUTUALLY EXCLUSIVE with watch_patterns â€” when both are set, watch_patterns is dropped.Úarrayr«   u
  Strings to watch for in background process output. HARD RATE LIMIT: at most 1 notification per 15 seconds per process â€” matches arriving inside the cooldown are dropped. After 3 consecutive 15-second windows with dropped matches, watch_patterns is automatically disabled for that process and promoted to notify_on_complete behavior (one notification on exit, no more mid-process spam). USE ONLY for truly rare, one-shot mid-process signals on LONG-LIVED processes that will never exit on their own â€” e.g. ['Application startup complete'] on a server so you know when to hit its endpoint, or ['migration done'] on a daemon. DO NOT use for: (1) end-of-run markers like 'DONE'/'PASS' â€” use notify_on_complete instead; (2) error patterns like 'ERROR'/'Traceback' in loops or multi-item batch jobs â€” they fire on every iteration and you'll hit the strike limit fast; (3) anything you'd ever combine with notify_on_complete. When in doubt, choose notify_on_complete. MUTUALLY EXCLUSIVE with notify_on_complete â€” set one, not both.)r«   r®  r  )rL   r  r˜   rS   r  r  r  )r«   Ú
propertiesÚrequired)r   r  rŽ  c                 óf  — t          |                      d¦  «        |                      dd¦  «        |                      d¦  «        |                     d¦  «        |                      d¦  «        |                      dd¦  «        |                      dd¦  «        |                      d	¦  «        ¬
¦  «        S )NrL   r  Fr˜   rú   rS   r  r  r  )rL   r  r˜   rú   rS   r  r  r  )rn  rê   )ÚargsÚkws     r   Ú_handle_terminalr�  P  s™   € ÝØ—’˜Ñ#Ô#Ø—8’8˜L¨%Ñ0Ô0Ø—’˜Ñ#Ô#Ø—’�yÑ!Ô!Ø—’˜Ñ#Ô#Ø�HŠH�U˜EÑ"Ô"ØŸ8š8Ð$8¸%Ñ@Ô@Ø—x’xÐ 0Ñ1Ô1ð	ñ 	ô 	ð 	r@   u   ðŸ’»i † )r   ÚtoolsetÚschemaÚhandlerÚcheck_fnÚemojiÚmax_result_size_chars)re   )r¥   )NNNr   N)r›  )FNNFNFFN)ŠÚ__doc__Úimportlib.utilrz  r  Úloggingr   ru   r´   r›   rž   ÚatexitrÏ  rw  Úpathlibr   Útypingr   r   r   r   Ú	getLoggerr¬   r   Útools.interruptr   r	   Útools.environments.singularityr
   Útools.tool_backend_helpersr   r   r   r   r)   r   r’  r5  r\  r0   r8   r9   Ú__annotations__r  r>   rA   rD   rH   rJ   r7  rK   rQ   ÚdictrR   ÚcompilerU   rY   rd   r¤   r­   r³   r¶   ÚtuplerÁ   rÏ   ræ   rî   Útools.environments.localrï   r‡  rð   r‰  Útools.environments.sshrñ   r“  rv  rò   rˆ  Útools.environments.modalró   r�  Ú tools.environments.managed_modalrô   r�  Útools.managed_tool_gatewayrõ   ÚTERMINAL_TOOL_DESCRIPTIONrö   r÷   r6  r­  rø   r¯  r¾  r¹  rù   rþ   r  r  r	  rd  r…  rh  rš  r¶  r¼  rÀ  rÄ  rÇ  rÊ  rÓ  rÍ  r×  Úregisterró  rø  Ú
IGNORECASErý  rÿ  r   r  rû  r  r	  rn  r~  r�   r»  ÚexitÚdefault_imgr   rT  r_   r^   rc   Útools.registryrƒ  ÚTERMINAL_SCHEMAr�  r?   r@   r   ú<module>r°     s  ððð ð ð> Ð Ð Ð Ø €€€Ø €€€Ø 	€	€	€	Ø €€€Ø 	€	€	€	Ø €€€Ø Ð Ð Ð Ø €€€Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,à	ˆÔ	˜8Ñ	$Ô	$€ð =Ð <Ð <Ð <Ð <Ð <Ð <Ð <ð <Ð ;Ð ;Ð ;Ð ;Ð ;ðð ð ð ð ð ð ð ð ð ð ð ðØ
ðàðð ð	ð ð ð ð8 0Ð/Ø%ØØØñ	ô Ð ð #9Ð"8ØØ	Ø	Øñ	#ô #Ð ðð ð ð<  Ð �sÐ Ð Ñ ð Ð Ð Ð Ø�	”Ñ!Ô!€ð9ð 9ð 9ð4ð 4ð 4ð%ð %ð %ð ð  ð  ðð ð ð ð ð ð
N˜sð N¨cð N°dð Nð Nð Nð Nð �2”:Ð=Ñ>Ô>Ð ð˜sð  s¨T¡zð ð ð ð ð, ð °ð ¸ð ð ð ð ð4z3ð z3¨sð z3¸Cð z3ð z3ð z3ð z3ðx	-ð 	- 3ð 	-¨sð 	-¸Sð 	-ð 	-ð 	-ð 	-ð= cð =¨dð =ð =ð =ð =ð!˜sð !¨3ð !°5¸¸c¸´?ð !ð !ð !ð !ðH:¨Cð :°E¸#¸t¸)Ô4Dð :ð :ð :ð :ðzb¨#ð b°#ð bð bð bð bðJ6 S¨4¡Zð 6°E¸#À¹*ÀcÈDÁjÐ:PÔ4Qð 6ð 6ð 6ð 6ðt KÐ JÐ JÐ JÐ JÐ JØ \Ð \Ð \Ð \Ð \Ð \Ø DÐ DÐ DÐ DÐ DÐ DØ MÐ MÐ MÐ MÐ MÐ MØ JÐ JÐ JÐ JÐ JÐ JØ `Ð `Ð `Ð `Ð `Ð `Ø DÐ DÐ DÐ DÐ DÐ DðÐ ð. (*Ð �d˜3 ˜8”nÐ )Ð )Ñ )Ø#%€��S˜%�ZÔ Ð %Ð %Ñ %ØˆIŒNÑÔ€	Ø-/€��c˜9œ>Ð)Ô*Ð /Ð /Ñ /Ø%�y”~Ñ'Ô'Ð Ø€ØÐ ð 24Ð �T˜#˜t C¨ Hœ~Ð-Ô.Ð 3Ð 3Ñ 3ð-¨ð -¸¸cÀ3¸h¼ð -ð -ð -ð -ð&+ cð +ð +ð +ð +ð¨°¬ð ¸#ð ð ð ð ð4 7:ÈYð 
ð 
˜ð 
 sð 
Àsð 
ð 
ð 
ð 
ð L˜˜c 3˜hœð Lð Lð Lð Lð^¨°$©ð ¸4ÀÀSÀ¼>ð ð ð ð ð KOØ-1Ø'0Ø(,ð	~Fð ~F #ð ~F¨cð ~F¸ð ~FÀcð ~FØ$(ð~FØCGð~Fà&*ð~Fð "%ð~Fð #&ð	~Fð ~Fð ~Fð ~FðB;\ð ;\¨Sð ;\ð ;\ð ;\ð ;\ð|ð ð ð$ð $ð $ðð ð ðU˜Cð Uð Uð Uð Uð4˜sð 4 tð 4ð 4ð 4ð 4ð&ð ð ð6'X˜ð 'Xð 'Xð 'Xð 'XðT#ð #ð #ð €„�Ñ  Ô  Ð  ð= #ð =°#ð =¸#À¹*ð =ð =ð =ð =ð@¨#ð °$ð ð ð ð ð (˜RœZÐ(FÈÌÑVÔVÐ Ø&˜BœJ xÑ0Ô0Ð Ø(˜bœjÐ);Ñ<Ô<Ð à€B„JÐRÐTVÔTaÑbÔbØ€B„JÐ+¨R¬]Ñ;Ô;Ø€B„JÐ  "¤-Ñ0Ô0Ø€B„JÐ  "¤-Ñ0Ô0Ø€B„Jˆ~˜rœ}Ñ-Ô-Ø€B„Jˆ~˜rœ}Ñ-Ô-Ø€B„Jˆ ¤Ñ.Ô.Ø€B„JÐ6¸¼ÑFÔFð	#Ð ð°ð ¸ð ð ð ð ð¨Sð °S¸4±Zð ð ð ð ðBàðð ð	ð
 ðð ð ð ð: Ø!Ø!ØØ!ØØ$Ø*.ðcð cØðcàðcð �cŒ]ðcð �cŒ]ð	cð
 ðcð �cŒ]ðcð 
ðcð ðcð ˜T #œYÔ'ðcð 	ðcð cð cð cðLf Tð fð fð fð fðR ˆzÒÑà	€EÐ
 Ñ!Ô!Ð!Ø	€Eˆ(�O„O€Oàˆ_ÑÔ€FØ	€EÐ
$Ñ%Ô%Ð%Ø	€EÐ
5 ¨
Ô!3Ð
5Ð
5Ñ6Ô6Ð6Ø	€EÐ
5˜V NÔ3Ð
5Ð
5Ñ6Ô6Ð6Ø	€EÐ
3˜F =Ô1Ð
3Ð
3Ñ4Ô4Ð4Ø	€EÐ
1 &¨¤-Ð
1Ð
1Ñ2Ô2Ð2Ø	€EÐ
4  yÔ 1Ð
4Ð
4Ð
4Ñ5Ô5Ð5Ø	€EÐ
6˜Ð 2Ô3Ð
6Ð
6Ð
6Ñ7Ô7Ð7à&Ð&Ñ(Ô(ð ØˆÐLÑMÔMÐMØˆˆQ‰Œˆà	€EÐ
'Ñ(Ô(Ð(Ø	€EÐ
ÑÔÐØ	€EÐ
IÑJÔJÐJà	€EÐ
ÑÔÐØ	€EÐ
!Ñ"Ô"Ð"Ø	€EÐ
6Ñ7Ô7Ð7Ø	€Eˆ$�K„K€KØ	€EÐ
%Ñ&Ô&Ð&Ø	€EÐ
QÑRÔRÐRà	€EÐ
$Ñ%Ô%Ð%Ø>€KØ	€EÐ
n˜Y˜RœY ~°wÑ?Ô?Ð
nÐ
nÐ
nÑoÔoÐoØ	€EÐ
W i b¤iÐ0GÈÑ&UÔ&UÐ
WÐ
WÑXÔXÐXØ	€EÐ
o¨9¨2¬9Ð5QÐSlÐ_jÐSlÐSlÑ+mÔ+mÐ
oÐ
oÑpÔpÐpØ	€EÐ
U Y R¤YÐ/EÀ{Ñ%SÔ%SÐ
UÐ
UÑVÔVÐVØ	€EÐ
Y y r¤yÐ1IÈ;Ñ'WÔ'WÐ
YÐ
YÑZÔZÐZØ	€EÐ
E˜Y˜RœY ~°y°r´y±{´{ÑCÔCÐ
EÐ
EÑFÔFÐFØ<Ð<Ð<Ð<Ð<Ð<Ø	€EÐ
_ Y R¤YÐ/EÈ$È$É&Ì&ÐG\ÐG\ÐG\Ñ%]Ô%]Ð
_Ð
_Ñ`Ô`Ð`Ø	€EÐ
F  ¤Ð+=¸tÑ!DÔ!DÐ
FÐ
FÑGÔGÐGØ	€EÐ
Y¨)¨"¬)Ð4OÐQVÑ*WÔ*WÐ
YÐ
YÑZÔZÐZð $Ð #Ð #Ð #Ð #Ð #ð Ø,àð !ØAðð ð
 "ð  TØ ðð ð "ð  |ÐUkð   |ð   |ð  mCð   |ð   |ð   |Øðð ð !Øðð ð
 "ð  ~Ø ðð ð "ð  `Ø ð#ð #ð  Ø  (Ð+ð  lðð ð;"
ð "
ðF �KðK&ð &ð*ð *€ðZ
ð 
ð 
ð €Ô Ø	ØØØØ(Ø
Ø!ðñ ô ð ð ð r@   