§
    øžyjDN ã                   óª  — 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ZddlZddlZddlZddlZ ej        ¦   «         dk    ZddlmZmZmZmZmZ ddlmZ ddlmZ  ej        e¦  «        ZdZ  e!g d¢¦  «        Z"d	Z#d
Z$dZ%dZ&	 d]ddœde'de'dee(         dee)ee)ef         f         fd„Z*de)dee)ee)ef         f         fd„Z+dZ,dZ- e!h d£¦  «        Z. e!h d£¦  «        Z/d^d„Z0de1fd„Z2ddddd d!d"dœZ3d_d#e)dee)         fd$„Z4	 d`d&ee)         d'e)de)fd(„Z5d)Z6d*e6z   d+z   Z7d,e6z   d-z   Z8h d.£Z9d/e
j
        d0e)d1e:d2e:d3e(d4e!d5ej;        d6e)fd7„Z<d0e)fd8„Z=d9e)d:e)ddfd;„Z>d<ede)fd=„Z?d>e)d0e)d1e:d2e:d3e(d4e!d5ej;        d6e)fd?„Z@d@e)d0ee)         d&eee)                  de)fdA„ZA	 	 d^d@e)d0ee)         d&eee)                  de)fdB„ZBdadDe1fdE„ZCdeDfdF„ZEdGZFdHZGde)fdI„ZH ejI        dJ¬K¦  «        dLe)de1fdM„¦   «         ZJdNe)de)fdO„ZKdbdNe)dQe)d0e)de)fdR„ZLg dS¢ZM	 	 d^dTeNdNe)deDfdU„ZO eO¦   «         ZPddVlQmRZRmSZS  eRjT        dWdXePdY„ e2dZd[¬\¦  «         dS )caå  
Code Execution Tool -- Programmatic Tool Calling (PTC)

Lets the LLM write a Python script that calls Hermes tools via RPC,
collapsing multi-step tool chains into a single inference turn.

Architecture (two transports):

  **Local backend (UDS):**
  1. Parent generates a `hermes_tools.py` stub module with UDS RPC functions
  2. Parent opens a Unix domain socket and starts an RPC listener thread
  3. Parent spawns a child process that runs the LLM's script
  4. Tool calls travel over the UDS back to the parent for dispatch

  **Remote backends (file-based RPC):**
  1. Parent generates `hermes_tools.py` with file-based RPC stubs
  2. Parent ships both files to the remote environment
  3. Script runs inside the terminal backend (Docker/SSH/Modal/Daytona/etc.)
  4. Tool calls are written as request files; a polling thread on the parent
     reads them via env.execute(), dispatches, and writes response files
  5. The script polls for response files and continues

In both cases, only the script's stdout is returned to the LLM; intermediate
tool results never enter the context window.

Platform: Linux / macOS only (Unix domain sockets for local). Disabled on Windows.
Remote execution additionally requires Python 3 in the terminal backend.
é    NÚWindows)ÚAnyÚDictÚListÚOptionalÚTuple)Úpropagate_context_to_thread)Úthread_scoped_silenceT)Ú
web_searchÚweb_extractÚ	read_fileÚ
write_fileÚsearch_filesÚpatchÚterminalé,  é2   iPÃ  i'  ó    ©Útotal_bytesÚheadÚtailr   Úreturnc                ó¶  — | |z   }|€t          |¦  «        nt          |t          |¦  «        ¦  «        }|t          |¦  «        k    }t          d|t          |¦  «        z
  ¦  «        }|r<|                      dd¬¦  «        d|d›d|d›d	�z   |                     dd¬¦  «        z   }n|                     dd¬¦  «        }|t          |¦  «        ||d
œ}|rd|d<   ||fS )a#  Build display stdout plus explicit truncation metadata.

    The agent receives execute_code results as JSON. A textual truncation
    marker can be missed or later re-truncated by a client layer, so keep the
    marker for humans and also expose byte counts for deterministic handling.
    Nr   úutf-8Úreplace©Úerrorsz

... [OUTPUT TRUNCATED - Ú,z bytes omitted out of z total] ...

)Ústdout_truncatedÚstdout_bytes_capturedÚstdout_bytes_totalÚstdout_bytes_omittedz¬execute_code stdout was truncated; the script did run, but only the captured head/tail output is included. Re-run only with narrower output if the omitted data is required.Úwarning)ÚlenÚmaxÚdecode)	r   r   r   ÚcapturedÚtotalÚ	truncatedÚomittedÚstdout_textÚmetadatas	            ú?/home/ragecks/.hermes/hermes-agent/tools/code_execution_tool.pyÚ_assemble_stdout_resultr/   Q   s#  € ð �d‰{€HØ(Ð0�C�‰MŒMˆMµc¸+ÅsÈ8Á}Ä}Ñ6UÔ6U€EØ�˜H™œÒ%€IÝ�!�U�S ™]œ]Ñ*Ñ+Ô+€Gàð Aà�KŠK˜¨	ˆKÑ2Ô2ð/¨WÐGð /ð /ØÐ.ð/ð /ð /ñ/ð �kŠk˜'¨)ˆkÑ4Ô4ñ5ð 	ˆð —o’o g°i�oÑ@Ô@ˆð &Ý!$ X¡¤Ø#Ø 'ð	 ð  €Hð ð 
ð?ð 	�Ñð
 ˜Ð Ð r   r,   c                 ó   — |                       dd¬¦  «        }t          |¦  «        t          k    rt          |¦  «        S t	          t          dz  ¦  «        }t          |z
  }t          |d|…         || d…         t          |¦  «        ¬¦  «        S )zFCap a complete stdout string by bytes using the same head/tail policy.r   r   r   çš™™™™™Ù?Nr   )Úencoder%   ÚMAX_STDOUT_BYTESr/   Úint)r,   Ústdout_bytesÚ
head_bytesÚ
tail_bytess       r.   Ú_truncate_stdout_textr8   {   s•   € à×%Ò% g°iÐ%Ñ@Ô@€LÝ
ˆ<ÑÔÕ,Ò,Ð,Ý& |Ñ4Ô4Ð4åÕ%¨Ñ+Ñ,Ô,€JÝ! JÑ.€JÝ"Ø�[�j�[Ô!Ø�j�[�\�\Ô"Ý˜Ñ%Ô%ðñ ô ð r   )ÚPATHÚHOMEÚUSERÚLANGÚLC_ÚTERMÚTMPDIRÚTMPÚTEMPÚSHELLÚLOGNAMEÚXDG_Ú
PYTHONPATHÚVIRTUAL_ENVÚCONDA)ÚKEYÚTOKENÚSECRETÚPASSWORDÚ
CREDENTIALÚPASSWDÚAUTHÚDSNÚWEBHOOKÚCREDSÚBEARERÚAPIKEY>   Ú
HERMES_ENVÚHERMES_HOMEÚHERMES_CONFIGÚHERMES_PROFILEÚHERMES_DELEGATED_CHILD_CONTEXT>   úPROGRAMFILES(X86)ÚOSÚPUBLICÚWINDIRÚAPPDATAÚCOMSPECÚPATHEXTÚHOMEPATHÚUSERNAMEÚ	HOMEDRIVEÚ
SYSTEMROOTÚ
USERDOMAINÚPROGRAMDATAÚSYSTEMDRIVEÚUSERPROFILEÚCOMPUTERNAMEÚLOCALAPPDATAÚPROGRAMFILESÚPROGRAMW6432ÚALLUSERSPROFILEÚNUMBER_OF_PROCESSORSÚPROCESSOR_ARCHITECTUREc           	      óR  ‡— d}|€#	 ddl m}m} n# t          $ r	 d„ }d„ }Y nw xY w|}n	 ddl m} n# t          $ r d„ }Y nw xY w|€t          }i }g }|                      ¦   «         D ]Ç\  Š} |‰¦  «        r |‰|¦  «        }|�||‰<   Œ$t          ˆfd„t          D ¦   «         ¦  «        rŒEt          ˆfd	„t          D ¦   «         ¦  «        r||‰<   Œk‰t          v r||‰<   Œz|r!‰ 
                    ¦   «         t          v r||‰<   Œ�‰                     d
¦  «        r|                     ‰¦  «         ŒÈ|rIt                               dt!          |¦  «        d                     t%          |¦  «        ¦  «        ¦  «         	 ddlm}	m}
  |	¦   «         r |
|¦  «        }n# t          $ r Y nw xY w|S )uì  Produce the scrubbed child-process env for execute_code.

    Rules (order matters):
      1. Passthrough vars (skill- or config-declared) pass through the active
         profile secret scope; an absent scoped value is omitted and an
         unscoped multiplex read fails closed.
      2. Secret-substring names (KEY/TOKEN/DSN/WEBHOOK/etc.) are blocked.
      3. Names matching a safe prefix pass.
      4. Operational HERMES_* vars (_HERMES_CHILD_ALLOWED) pass by exact name.
      5. On Windows, a small OS-essential allowlist passes by exact name
         â€” without these the child can't even create a socket or spawn a
         subprocess.

    Extracted into a helper so tests can exercise the logic without
    spawning a subprocess.
    Nr   )Úis_env_passthroughÚresolve_passthrough_valuec                 ó   — dS )NF© )Ú_s    r.   ú<lambda>z"_scrub_child_env.<locals>.<lambda>ê   s   € ˜E€ r   c                 ó   — d S ©Nrs   ©Ú_nameÚ	_fallbacks     r.   ru   z"_scrub_child_env.<locals>.<lambda>ë   ó   € À€ r   )rq   c                 ó   — d S rw   rs   rx   s     r.   ru   z"_scrub_child_env.<locals>.<lambda>ñ   r{   r   c              3   óD   •K  — | ]}|‰                      ¦   «         v V — Œd S rw   )Úupper)Ú.0ÚsÚks     €r.   ú	<genexpr>z#_scrub_child_env.<locals>.<genexpr>  s/   øè è € Ð:Ð: !ˆq�A—G’G‘I”Iˆ~Ð:Ð:Ð:Ð:Ð:Ð:r   c              3   óB   •K  — | ]}‰                      |¦  «        V — Œd S rw   )Ú
startswith)r   Úpr�   s     €r.   r‚   z#_scrub_child_env.<locals>.<genexpr>  s-   øè è € Ð;Ð; 1ˆq�|Š|˜A‰ŒÐ;Ð;Ð;Ð;Ð;Ð;r   ÚHERMES_a  execute_code: dropped %d non-allowlisted HERMES_* var(s) from the sandbox child env (%s). This is intentional hardening (#27303); if a sandbox script legitimately needs one, declare it via env_passthrough in the skill/config so it passes by explicit opt-in.ú, )Ú"is_delegated_child_process_contextÚscrub_kanban_env)Útools.env_passthroughrp   rq   Ú	ExceptionÚ_IS_WINDOWSÚitemsÚanyÚ_SECRET_SUBSTRINGSÚ_SAFE_ENV_PREFIXESÚ_HERMES_CHILD_ALLOWEDr~   Ú_WINDOWS_ESSENTIAL_ENV_VARSr„   ÚappendÚloggerÚdebugr%   ÚjoinÚsortedÚagent.delegation_contextrˆ   r‰   )Ú
source_envÚis_passthroughÚ
is_windowsrq   Ú_epÚscrubbedÚ_dropped_hermesÚvÚresolvedrˆ   r‰   r�   s              @r.   Ú_scrub_child_envr¡   Ñ   s¼  ø€ ð" !%ÐØÐð	Fðð ð ð ð ð ð ð ð øõ ð 	Fð 	Fð 	FØ!�/ˆCØ(EÐ(EÐ%Ð%Ð%ð	Føøøð ˆˆð	FØGÐGÐGÐGÐGÐGÐGøÝð 	Fð 	Fð 	FØ(EÐ(EÐ%Ð%Ð%ð	FøøøàÐÝ ˆ
à€Hð €OØ× Ò Ñ"Ô"ð &ð &‰ˆˆ1Øˆ>˜!ÑÔð 	Ø0Ð0°°AÑ6Ô6ˆHØÐ#Ø&�˜‘ØÝÐ:Ð:Ð:Ð:Õ'9Ð:Ñ:Ô:Ñ:Ô:ð 	ØÝÐ;Ð;Ð;Ð;Õ(:Ð;Ñ;Ô;Ñ;Ô;ð 	ØˆH�Q‰KØØÕ%Ð%Ð%ØˆH�Q‰KØØð 	˜!Ÿ'š'™)œ)Õ'BÐBÐBØˆH�Q‰KØØ�<Š<˜	Ñ"Ô"ð 	&ð ×"Ò" 1Ñ%Ô%Ð%øØð 
Ý�ŠðSõ �Ñ Ô Ø�IŠI•f˜_Ñ-Ô-Ñ.Ô.ñ	
ô 	
ð 	
ð	ð	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð
 .Ð-Ñ/Ô/ð 	2Ø'Ð'¨Ñ1Ô1ˆHøøÝð ð ð Øˆðøøøà€Os-   ‡ �#¢#ª1 ±AÁ AÅ9F Æ
F$Æ#F$c                  óâ   — t           sdS 	 ddlm} m}  |¦   «         }n-# t          $ r  t
                               dd¬¦  «         Y dS w xY w|                     d¦  «        dk    r | |¦  «        S dS )	zCCode execution sandbox requires a POSIX OS for Unix domain sockets.Fr   )Ú"_check_vercel_sandbox_requirementsÚ_get_env_configz?Could not resolve terminal config for execute_code availabilityT©Úexc_infoÚenv_typeÚvercel_sandbox)ÚSANDBOX_AVAILABLEÚtools.terminal_toolr£   r¤   r‹   r”   r•   Úget)r£   r¤   Úconfigs      r.   Úcheck_sandbox_requirementsr­   /  s·   € åð Øˆuð	ð	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð
 !�Ñ"Ô"ˆˆøÝð ð ð Ý�ŠÐVÐaeˆÑfÔfÐfØˆuˆuðøøøð ‡z‚z�*ÑÔÐ!1Ò1Ð1Ø1Ð1°&Ñ9Ô9Ð9àˆ4s   ‹ ž&AÁA)r   zquery: str, limit: int = 5zS"""Search the web. Returns dict with data.web list of {url, title, description}."""z {"query": query, "limit": limit})r   z"urls: list, char_limit: int = Nonea  """Extract content from URLs (no LLM summarization). Returns dict with results list of {url, title, content, error}. Pages over char_limit (default 15000) are head+tail truncated with the full text stored on disk; the content footer gives the path. content is markdown."""z({"urls": urls, "char_limit": char_limit})r   z-path: str, offset: int = 1, limit: int = 2000zS"""Read a file (1-indexed lines). Returns dict with "content" and "total_lines"."""z0{"path": path, "offset": offset, "limit": limit})r   z4path: str, content: str, cross_profile: bool = Falsez�"""Write content to a file (always overwrites). Returns dict with status. cross_profile=True opts out of the cross-Hermes-profile soft guard."""zB{"path": path, "content": content, "cross_profile": cross_profile})r   zŸpattern: str, target: str = "content", path: str = ".", file_glob: str = None, limit: int = 50, offset: int = 0, output_mode: str = "content", context: int = 0zr"""Search file contents (target="content") or find files by name (target="files"). Returns dict with "matches"."""zž{"pattern": pattern, "target": target, "path": path, "file_glob": file_glob, "limit": limit, "offset": offset, "output_mode": output_mode, "context": context})r   z¢path: str = None, old_string: str = None, new_string: str = None, replace_all: bool = False, mode: str = "replace", patch: str = None, cross_profile: bool = Falsez¸"""Targeted find-and-replace (mode="replace") or V4A multi-file patches (mode="patch"). Returns dict with status. cross_profile=True opts out of the cross-Hermes-profile soft guard."""zœ{"path": path, "old_string": old_string, "new_string": new_string, "replace_all": replace_all, "mode": mode, "patch": patch, "cross_profile": cross_profile})r   z6command: str, timeout: int = None, workdir: str = NonezX"""Run a shell command (foreground only). Returns dict with "output" and "exit_code"."""z<{"command": command, "timeout": timeout, "workdir": workdir}Ústderr_textc                 ó<  — | sdS | dd…         }	 t          j        d|¦  «        }|rl|                     d¦  «        }t          t          t          |pt          ¦  «        z  ¦  «        }h d£}||v r|› d|› d�S d|› d	d
                     |¦  «        › d�S t          j        d|¦  «        }|r|                     d¦  «        › d�S t          j        d|¦  «        }|rd|                     d¦  «        › d�S t          j        d|¦  «        r	 dS n# t          $ r Y dS w xY wdS )aâ  Map well-known sandbox script failures to one actionable recovery hint.

    Production mining (state.db): the top execute_code failure classes are
    hermes_tools import misuse (importing tools that aren't in the sandbox,
    23x in one window), calling the built-in helpers via import, treating
    tool results as strings instead of dicts, and importing third-party
    packages that don't exist in the sandbox interpreter. Bounded scan,
    first match wins, never raises.
    Ni   z.cannot import name '(\w+)' from 'hermes_tools'é   >   ÚretryÚ
json_parseÚshell_quoteuc    is a BUILT-IN helper in the sandbox â€” no import needed. Remove it from the import line and call z(...) directly.ú'zK' is not available inside the execute_code sandbox. Importable tools here: r‡   zF. For anything else, use the normal tool call instead of execute_code.z?NameError: name '(json_parse|shell_quote|retry)' is not defineduf    is built into the generated sandbox module â€” call it directly at module scope without importing it.z/ModuleNotFoundError: No module named '([\w.]+)'zœ' is not installed in the sandbox interpreter. Use Python stdlib inside execute_code, or run the code via terminal() with the project venv's python instead.z^TypeError: string indices must be integers|AttributeError: 'str' object has no attribute 'get'u™   Tool functions in the sandbox return DICTS (already parsed) â€” do not json.loads() them or index them like strings. Example: read_file(path)['content'].)ÚreÚsearchÚgroupr—   ÚSANDBOX_ALLOWED_TOOLSÚsetr–   r‹   )r®   Úenabled_toolsÚwindowÚmÚmissingÚ	availableÚbuiltins          r.   Ú_sandbox_failure_hintrÀ   y  sÈ  € ð ð ØˆtØ˜˜$˜Ô€Fð&ÝŒIØ=¸vñ
ô 
ˆð ð 	Ø—g’g˜a‘j”jˆGÝÕ4µs¸=Ð;aÕLaÑ7bÔ7bÑbÑcÔcˆIØ<Ð<Ð<ˆGØ˜'Ð!Ð!àð `ð `ØGNð`ð `ð `ðð
J�Gð Jð JØ*.¯)ª)°IÑ*>Ô*>ðJð Jð Jðõ
 ŒIÐXÐZ`ÑaÔaˆØð 	à—7’7˜1‘:”:ð Ið Ið Iðõ ŒIÐHÈ&ÑQÔQˆØð 	ðE�A—G’G˜A‘J”Jð Eð Eð Eðõ
 Œ9ÐvÐx~ÑÔð 	ð7ðð ð	øõ ð ð ð Øˆtˆtðøøøàˆ4s*   �A&D Á7D Â.D Ã/D Ã2D Ä
DÄDÚudsrº   Ú	transportc                 ób  — t          t          t          | ¦  «        z  ¦  «        }g }g }|D ]X}|t          vrŒt          |         \  }}}}	|                     d|› d|› d|› d|›d|	› d�¦  «         |                     |¦  «         ŒY|dk    rt
          }
nt          }
|
d                     |¦  «        z   S )	ag  
    Build the source code for the hermes_tools.py stub module.

    Only tools in both SANDBOX_ALLOWED_TOOLS and enabled_tools get stubs.

    Args:
        enabled_tools: Tool names enabled in the current session.
        transport: ``"uds"`` for Unix domain socket (local backend) or
                   ``"file"`` for file-based RPC (remote backends).
    zdef ú(z):
    z
    return _call(r‡   z)
ÚfileÚ
)r—   r¸   r¹   Ú_TOOL_STUBSr“   Ú_FILE_TRANSPORT_HEADERÚ_UDS_TRANSPORT_HEADERr–   )rº   rÂ   Útools_to_generateÚstub_functionsÚexport_namesÚ	tool_nameÚ	func_nameÚsigÚdocÚ	args_exprÚheaders              r.   Úgenerate_hermes_tools_modulerÓ   °  s  € õ Õ4µs¸=Ñ7IÔ7IÑIÑJÔJÐà€NØ€LØ&ð 	'ð 	'ˆ	Ø�KÐ'Ð'ØÝ)4°YÔ)?Ñ&ˆ	�3˜˜YØ×Òð>�9ð >ð >˜sð >ð >Øð>ð >à )ð>ð >à/8ð>ð >ð >ñ	
ô 	
ð 	
ð
 	×Ò˜IÑ&Ô&Ð&Ð&à�FÒÐÝ'ˆˆå&ˆà�D—I’I˜nÑ-Ô-Ñ-Ð-r   u²  
# ---------------------------------------------------------------------------
# Convenience helpers (avoid common scripting pitfalls)
# ---------------------------------------------------------------------------

def json_parse(text: str):
    """Parse JSON tolerant of control characters and UTF-8 BOM (strict=False).
    Use this instead of json.loads() when parsing output from terminal()
    or web_extract() that may contain raw tabs/newlines in strings,
    or from tools/files that prepend a UTF-8 BOM (salvage #57870, credit @woxinwuhen713-bit)."""
    if isinstance(text, str) and text.startswith("ï»¿"):
        text = text[1:]
    return json.loads(text, strict=False)


def shell_quote(s: str) -> str:
    """Shell-escape a string for safe interpolation into commands.
    Use this when inserting dynamic content into terminal() commands:
        terminal(f"echo {shell_quote(user_input)}")
    """
    return shlex.quote(s)


def retry(fn, max_attempts=3, delay=2):
    """Retry a function up to max_attempts times with exponential backoff.
    Use for transient failures (network errors, API rate limits):
        result = retry(lambda: terminal("gh issue list ..."))
    """
    last_err = None
    for attempt in range(max_attempts):
        try:
            return fn()
        except Exception as e:
            last_err = e
            if attempt < max_attempts - 1:
                time.sleep(delay * (2 ** attempt))
    raise last_err

a°  """Auto-generated Hermes tools RPC stubs."""
import json, os, socket, shlex, threading, time

_sock = None
# The RPC server handles a single client connection serially and has no
# request-id in the protocol, so concurrent _call() invocations from multiple
# threads (e.g. ThreadPoolExecutor) would race on the shared socket and get
# each other's responses. Serialize the entire send+recv round-trip.
_call_lock = threading.Lock()
uG  
def _connect():
    """Connect to the parent's RPC server via the transport it picked.

    HERMES_RPC_SOCKET can be either:
      - a filesystem path (POSIX Unix domain socket â€” the default on
        Linux and macOS)
      - a string of the form ``tcp://127.0.0.1:<port>`` (Windows, where
        AF_UNIX is unreliable â€” the parent falls back to loopback TCP)
    """
    global _sock
    if _sock is None:
        endpoint = os.environ["HERMES_RPC_SOCKET"]
        if endpoint.startswith("tcp://"):
            # tcp://host:port  (host is always 127.0.0.1 in practice â€” we
            # only bind loopback server-side)
            _host_port = endpoint[len("tcp://"):]
            _host, _, _port = _host_port.rpartition(":")
            _sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            _sock.connect((_host or "127.0.0.1", int(_port)))
        else:
            _sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            _sock.connect(endpoint)
        _sock.settimeout(300)
    return _sock

def _call(tool_name, args):
    """Send a tool call to the parent process and return the parsed result."""
    request = json.dumps({
        "tool": tool_name,
        "args": args,
        "token": os.environ.get("HERMES_RPC_TOKEN", ""),
    }) + "\n"
    with _call_lock:
        conn = _connect()
        conn.sendall(request.encode())
        buf = b""
        while True:
            chunk = conn.recv(65536)
            if not chunk:
                raise RuntimeError("Agent process disconnected")
            buf += chunk
            if buf.endswith(b"\n"):
                break
    raw = buf.decode().strip()
    result = json.loads(raw)
    if isinstance(result, str):
        try:
            return json.loads(result)
        except (json.JSONDecodeError, TypeError):
            return result
    return result

aÝ  """Auto-generated Hermes tools RPC stubs (file-based transport)."""
import json, os, shlex, tempfile, threading, time

_RPC_DIR = os.environ.get("HERMES_RPC_DIR") or os.path.join(tempfile.gettempdir(), "hermes_rpc")
_seq = 0
# `_seq += 1` is not atomic (read-modify-write), so concurrent _call()
# invocations from multiple threads could allocate the same sequence number
# and clobber each other's request files. Guard seq allocation with a lock.
_seq_lock = threading.Lock()
a‘  
def _call(tool_name, args):
    """Send a tool call request via file-based RPC and wait for response."""
    global _seq
    with _seq_lock:
        _seq += 1
        seq = _seq
    seq_str = f"{seq:06d}"
    req_file = os.path.join(_RPC_DIR, f"req_{seq_str}")
    res_file = os.path.join(_RPC_DIR, f"res_{seq_str}")

    # Write request atomically (write to .tmp, then rename).
    # encoding="utf-8" is critical: on Windows-hosted remote backends
    # (or any non-UTF-8 locale) the default open() mode would mangle
    # non-ASCII chars in tool args when encoding them as JSON.
    tmp = req_file + ".tmp"
    with open(tmp, "w", encoding="utf-8") as f:
        json.dump({
            "tool": tool_name,
            "args": args,
            "seq": seq,
            "token": os.environ.get("HERMES_RPC_TOKEN", ""),
        }, f)
    os.rename(tmp, req_file)

    # Wait for response with adaptive polling
    deadline = time.monotonic() + 300  # 5-minute timeout per tool call
    poll_interval = 0.05  # Start at 50ms
    while not os.path.exists(res_file):
        if time.monotonic() > deadline:
            raise RuntimeError(f"RPC timeout: no response for {tool_name} after 300s")
        time.sleep(poll_interval)
        poll_interval = min(poll_interval * 1.2, 0.25)  # Back off to 250ms

    with open(res_file, encoding="utf-8") as f:
        raw = f.read()

    # Clean up response file
    try:
        os.unlink(res_file)
    except OSError:
        pass

    result = json.loads(raw)
    if isinstance(result, str):
        try:
            return json.loads(result)
        except (json.JSONDecodeError, TypeError):
            return result
    return result

>   ÚptyÚ
backgroundÚwatch_patternsÚnotify_on_completeÚserver_sockÚtask_idÚtool_call_logÚtool_call_counterÚmax_tool_callsÚallowed_toolsÚ
stop_eventÚ	rpc_tokenc                 ó.  — ddl m} d}		 |                      d¦  «         |                     ¦   «         s.	 |                      ¦   «         \  }	}
n# t
          j        $ r Y Œ>w xY w|	€O	 |	rJ	 |	                     ¦   «          dS # t          $ r&}t           
                    d|¦  «         Y d}~dS d}~ww xY wdS |	                     d¦  «         d}	 	 |	                     d	¦  «        }n# t
          j        $ r Y �n¨w xY w|s�n ||z  }d
|v �r”|                     d
d¦  «        \  }}|                     ¦   «         }|sŒ5t          j        ¦   «         }	 t!          j        |                     ¦   «         ¦  «        }n_# t           j        t(          f$ rF}t+          d|› �¦  «        }|	                     |dz                        ¦   «         ¦  «         Y d}~ŒÇd}~ww xY w|r[t1          j        t5          |                     d¦  «        pd¦  «                             ¦   «         |                     ¦   «         ¦  «        s;t+          d¦  «        }|	                     |dz                        ¦   «         ¦  «         �Œg|                     dd¦  «        }|                     di ¦  «        }||vrcd                     t;          |¦  «        ¦  «        }t+          d|› d|› �¦  «        }|	                     |dz                        ¦   «         ¦  «         �Œú|d         |k    r?t+          d|› d�¦  «        }|	                     |dz                        ¦   «         ¦  «         �ŒE|dk    r5t=          |t>          ¦  «        r t@          D ]}| !                    |d¦  «         Œ	 tE          ¦   «         5   ||||¬¦  «        }ddd¦  «         n# 1 swxY w Y   nP# tF          $ rC}t           $                    d|d¬¦  «         t+          t5          |¦  «        ¦  «        }Y d}~nd}~ww xY w|dxx         dz  cc<   t          j        ¦   «         |z
  }t5          |¦  «        dd…         }| %                    ||tM          |d¦  «        dœ¦  «         |	                     |dz                        ¦   «         ¦  «         d
|v �°”�ŒÑn^# t
          j        $ r t           
                    d¦  «         Y n3t          $ r'}t           
                    d |d¬¦  «         Y d}~nd}~ww xY w|	rJ	 |	                     ¦   «          dS # t          $ r&}t           
                    d|¦  «         Y d}~dS d}~ww xY wdS # |	rH	 |	                     ¦   «          w # t          $ r%}t           
                    d|¦  «         Y d}~w d}~ww xY ww xY w)!z…
    Accept one client connection and dispatch tool-call requests until
    the client disconnects or the call limit is reached.
    r   ©Úhandle_function_callNgš™™™™™©?zRPC conn close error: %sr   r   Ti   ó   
r°   zInvalid RPC request: rÆ   ÚtokenÚ zUnauthorized RPC requestÚtoolÚargsr‡   úTool 'ú/' is not available in execute_code. Available: úTool call limit reached (ú0). No more tool calls allowed in this execution.r   ©rÙ   zTool call failed in sandbox: %sr¥   éP   é   ©ræ   Úargs_previewÚdurationzRPC listener socket timeoutzRPC listener socket error: %s)'Úmodel_toolsrâ   Ú
settimeoutÚis_setÚacceptÚsocketÚtimeoutÚcloseÚOSErrorr”   r•   ÚrecvÚsplitÚstripÚtimeÚ	monotonicÚjsonÚloadsr'   ÚJSONDecodeErrorÚUnicodeDecodeErrorÚ
tool_errorÚsendallr2   ÚsecretsÚcompare_digestÚstrr«   r–   r—   Ú
isinstanceÚdictÚ_TERMINAL_BLOCKED_PARAMSÚpopr
   r‹   Úerrorr“   Úround)rØ   rÙ   rÚ   rÛ   rÜ   rÝ   rÞ   rß   râ   Úconnrt   ÚeÚbufÚchunkÚlineÚ
call_startÚrequestÚexcÚresprÍ   Ú	tool_argsr¾   ÚparamÚresultÚcall_durationrð   s                             r.   Ú_rpc_server_loopr  �  sï  € ð 1Ð0Ð0Ð0Ð0Ð0à€Dðl<Ø×Ò˜tÑ$Ô$Ð$Ø×#Ò#Ñ%Ô%ð 	ðØ%×,Ò,Ñ.Ô.‘��aØøÝ”>ð ð ð Ø�ðøøøàˆ<Øð~ ð 	<ð<Ø—
’
‘”���øÝð <ð <ð <Ý—’Ð7¸Ñ;Ô;Ð;Ð;Ð;Ð;Ð;Ð;Ð;øøøøð<øøøð	<ð 	<ð} 	�Š˜ÑÔÐàˆðT	7ðØŸ	š	 %Ñ(Ô(��øÝ”>ð ð ð Ø‘ðøøøàð ÙØ�5‰LˆCð ˜3�,‘,ØŸIšI e¨QÑ/Ô/‘	��cØ—z’z‘|”|�Øð Øå!œ^Ñ-Ô-�
ðÝ"œj¨¯ª©¬Ñ7Ô7�G�GøÝÔ,Õ.@ÐAð ð ð Ý%Ð&C¸cÐ&CÐ&CÑDÔD�DØ—L’L $¨¡+×!5Ò!5Ñ!7Ô!7Ñ8Ô8Ð8Ø�H�H�H�Høøøøðøøøð
 !ð ­Ô(>õ ˜Ÿš GÑ,Ô,Ð2°Ñ3Ô3×:Ò:Ñ<Ô<¸i×>NÒ>NÑ>PÔ>Pñ	)ô )ð õ &Ð&@ÑAÔA�DØ—L’L $¨¡+×!5Ò!5Ñ!7Ô!7Ñ8Ô8Ð8Ùà#ŸKšK¨°Ñ3Ô3�	Ø#ŸKšK¨°Ñ3Ô3�	ð  MÐ1Ð1Ø $§	¢	­&°Ñ*?Ô*?Ñ @Ô @�IÝ%ð2 ð 2ð 2Ø&/ð2ð 2ñô �Dð —L’L $¨¡+×!5Ò!5Ñ!7Ô!7Ñ8Ô8Ð8Ùð % QÔ'¨>Ò9Ð9Ý%ðH°Nð Hð Hð Hñô �Dð —L’L $¨¡+×!5Ò!5Ñ!7Ô!7Ñ8Ô8Ð8Ùð  
Ò*Ð*­z¸)ÅTÑ/JÔ/JÐ*Ý!9ð 3ð 3˜Ø!Ÿš e¨TÑ2Ô2Ð2Ð2ð
2Ý.Ñ0Ô0ð ð Ø!5Ð!5Ø% y¸'ð"ñ "ô "˜ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð øøõ !ð 2ð 2ð 2Ý—L’LÐ!BÀCÐRV�LÑWÔWÐWÝ'­¨C©¬Ñ1Ô1�F�F�F�F�F�Føøøøð2øøøð " !Ð$Ð$Ô$¨Ñ)Ð$Ð$Ñ$Ý $¤Ñ 0Ô 0°:Ñ =�õ  # 9™~œ~¨c¨r¨cÔ2�Ø×$Ò$Ø%Ø$0Ý % m°QÑ 7Ô 7ð&ð &ñ ô ð ð —’˜f t™m×3Ò3Ñ5Ô5Ñ6Ô6Ð6ðU ˜3�,‘,ñT	7øøõl Œ>ð 4ð 4ð 4Ý�ŠÐ2Ñ3Ô3Ð3Ð3Ð3Ýð Hð Hð HÝ�ŠÐ4°aÀ$ˆÑGÔGÐGÐGÐGÐGÐGÐGøøøøðHøøøð ð 	<ð<Ø—
’
‘”���øÝð <ð <ð <Ý—’Ð7¸Ñ;Ô;Ð;Ð;Ð;Ð;Ð;Ð;Ð;øøøøð<øøøð	<ð 	<øˆ4ð 	<ð<Ø—
’
‘”��øÝð <ð <ð <Ý—’Ð7¸Ñ;Ô;Ð;Ð;Ð;Ð;Ð;Ð;øøøøð<øøøð	<øøøs]  Š)R ´A ÁR ÁAÁR ÁAÁR Á'A= Á=
B-ÂB(Â(B-Â2R ÃC! Ã R Ã!C4Ã0R Ã3C4Ã4AR Å	&E0 Å/R Å0GÆ<GÇR ÇGÇF4R ÎN6 ÎN*ÎN6 Î*N.Î.N6 Î1N.Î2N6 Î5R Î6
PÏ 9O>Ï9R Ï>PÐBR ÒU Ò)S7ÓU Ó	S7ÓS2Ó-U Ó2S7Ó7U Ó=T Ô
UÔT>Ô>UÕVÕU!Õ VÕ!
VÕ+VÖVÖVÖVc                 ó  — ddl m}m}m}m}m}m}m}m}m	}	m
}
m}  |
| ¦  «        }|5  ||v r:t          j        ¦   «         ||<   ||          |¦   «         d         fcddd¦  «         S 	 ddd¦  «         n# 1 swxY w Y   |5  ||vrt          j        ¦   «         ||<   ||         }ddd¦  «         n# 1 swxY w Y   |5  |5  ||v rFt          j        ¦   «         ||<   ||          |¦   «         d         fcddd¦  «         cddd¦  «         S 	 ddd¦  «         n# 1 swxY w Y    |¦   «         }|d         }|	                     |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}|dv r«|                     dd¦  «        |                     dd¦  «        |                     dd¦  «        |                     dd¦  «        |                     dd¦  «        |                     dg ¦  «        |                     dd¦  «        |                     dd¦  «        dœ}d}|dk    rl|                     dd¦  «        |                     d d¦  «        |                     d!d"¦  «        |                     d#d¦  «        |                     d$d¦  «        d%œ}d}|d&k    rd'|                     d(d¦  «        i}t                                d)||dd*…         ¦  «          |||||d+         |||| ||| ¦  «        ¬,¦	  «	        }|5  |||<   t          j        ¦   «         ||<   ddd¦  «         n# 1 swxY w Y    |¦   «          t                                d-||dd*…         ¦  «         ||fcddd¦  «         S # 1 swxY w Y   dS ).zòGet or create the terminal environment for *task_id*.

    Reuses the same environment (container/sandbox/SSH session) that the
    terminal and file tools use, creating one if it doesn't exist yet.
    Returns ``(env, env_type)`` tuple.
    r   )Ú_active_environmentsÚ	_env_lockÚ_create_environmentr¤   Ú_last_activityÚ_start_cleanup_threadÚ_creation_locksÚ_creation_locks_lockÚ_task_env_overridesÚ_resolve_container_task_idÚ_resolve_task_host_cwdr§   NÚdockerÚdocker_imageÚsingularityÚsingularity_imageÚmodalÚmodal_imageÚdaytonaÚdaytona_imagerå   Úcwd>   r+  r'  r-  r)  r¨   Úcontainer_cpur°   Úcontainer_memoryi   Úcontainer_diski È  Úcontainer_persistentTÚvercel_runtimeÚdocker_volumesÚdocker_run_as_host_userFÚdocker_network)r0  r1  r2  r3  r4  r5  r6  r7  ÚsshÚssh_hostÚssh_userÚssh_porté   Ússh_keyÚssh_persistent)ÚhostÚuserÚportÚkeyÚ
persistentÚlocalrC  Úlocal_persistentz7Creating new %s environment for execute_code task %s...é   r÷   )	r§   Úimager/  r÷   Ú
ssh_configÚcontainer_configÚlocal_configrÙ   Úhost_cwdz-%s environment ready for execute_code task %s)rª   r  r  r  r¤   r   r!  r"  r#  r$  r%  r&  rý   Ú	threadingÚLockr«   r”   Úinfo)rÙ   r  r  r  r¤   r   r!  r"  r#  r$  r%  r&  Úeffective_task_idÚ	task_lockr¬   r§   Ú	overridesrG  r/  rI  rH  rJ  Úenvs                          r.   Ú_get_or_create_envrS    sá  € ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð 3Ð2°7Ñ;Ô;Ðð 
ð Zð ZØÐ 4Ð4Ð4Ý04´	±´ˆNÐ,Ñ-Ø'Ð(9Ô:¸O¸OÑ<MÔ<MÈjÔ<YÐYðZð Zð Zð Zñ Zô Zð Zð ZØ4ðZð Zð Zñ Zô Zð Zð Zð Zð Zð Zð Zøøøð Zð Zð Zð Zð 
ð 7ð 7Ø OÐ3Ð3Ý1:´Ñ1AÔ1AˆOÐ-Ñ.Ø#Ð$5Ô6ˆ	ð7ð 7ð 7ñ 7ô 7ð 7ð 7ð 7ð 7ð 7ð 7øøøð 7ð 7ð 7ð 7ð
 
ð Ið IØð 	^ð 	^Ø Ð$8Ð8Ð8Ý48´I±K´K�Ð0Ñ1Ø+Ð,=Ô>ÀÀÑ@QÔ@QÐR\Ô@]Ð]ð	^ð 	^ð 	^ð 	^ñ 	^ô 	^ð 	^ðIð Ið Ið Iñ Iô Ið Ið Ià8ð	^ð 	^ð 	^ñ 	^ô 	^ð 	^ð 	^ð 	^ð 	^ð 	^ð 	^øøøð 	^ð 	^ð 	^ð 	^ð
 !�Ñ"Ô"ˆØ˜*Ô%ˆØ'×+Ò+Ð,=¸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ˆàÐØÐVÐVÐVà!'§¢¨O¸QÑ!?Ô!?Ø$*§J¢JÐ/AÀ4Ñ$HÔ$HØ"(§*¢*Ð-=¸uÑ"EÔ"EØ(.¯
ª
Ð3IÈ4Ñ(PÔ(PØ"(§*¢*Ð-=¸rÑ"BÔ"BØ"(§*¢*Ð-=¸rÑ"BÔ"BØ+1¯:ª:Ð6OÐQVÑ+WÔ+WØ"(§*¢*Ð-=¸tÑ"DÔ"Dð	 ð 	 Ðð ˆ
Ø�uÒÐàŸ
š
 :¨rÑ2Ô2ØŸ
š
 :¨rÑ2Ô2ØŸ
š
 :¨rÑ2Ô2Ø—z’z )¨RÑ0Ô0Ø$ŸjšjÐ)9¸5ÑAÔAðð ˆJð ˆØ�wÒÐà˜fŸjšjÐ);¸UÑCÔCðˆLõ 	�ŠÐMØÐ0°°!°Ô4ñ	6ô 	6ð 	6à!Ð!ØØØØ˜9Ô%Ø!Ø-Ø%Ø%Ø+Ð+¨F°GÑ<Ô<ð

ñ 

ô 

ˆð ð 	<ð 	<Ø69Ð Ð!2Ñ3Ý04´	±´ˆNÐ,Ñ-ð	<ð 	<ð 	<ñ 	<ô 	<ð 	<ð 	<ð 	<ð 	<ð 	<ð 	<øøøð 	<ð 	<ð 	<ð 	<ð 	ÐÑÔÐÝ�ŠÐCØÐ0°°!°Ô4ñ	6ô 	6ð 	6à�Hˆ}ðSIð Ið Ið Iñ Iô Ið Ið Ið Ið Ið Ið Iøøøð Ið Ið Ið Ið Ið Is„   ¨2A4Á4A8Á;A8Â#B0Â0B4Â7B4Â=O:Ã 2DÃ2O:ÄO:ÄD	ÄO:ÄD	Ä I)O:Î	N1Î%O:Î1N5	Î5O:Î8N5	Î94O:Ï:O>ÐO>Úremote_pathÚcontentc                 óÞ   — t          j        |                     d¦  «        ¦  «                             d¦  «        }t	          j        |¦  «        }|                      d|› d|› �dd¬¦  «         dS )	u&  Write *content* to *remote_path* on the remote environment.

    Uses ``echo â€¦ | base64 -d`` rather than stdin piping because some
    backends (Modal) don't reliably deliver stdin_data to chained
    commands.  Base64 output is shell-safe ([A-Za-z0-9+/=]) so single
    quotes are fine.
    r   Úasciiúecho 'ú' | base64 -d > ú/é   ©r/  r÷   N)Úbase64Ú	b64encoder2   r'   ÚshlexÚquoteÚexecute)rR  rT  rU  ÚencodedÚquoted_remote_paths        r.   Ú_ship_file_to_remoterd  y  s}   € õ Ô˜wŸ~š~¨gÑ6Ô6Ñ7Ô7×>Ò>¸wÑGÔG€GÝœ [Ñ1Ô1ÐØ‡K‚KØ>�Ð>Ð>Ð*<Ð>Ð>ØØð ñ ô ð ð ð r   rR  c                 óì  — t          | dd¦  «        }t          |¦  «        r	  |¦   «         }t          |t          ¦  «        r,|                     d¦  «        r|                     d¦  «        pdS n2# t          $ r%}t                               d|¦  «         Y d}~nd}~ww xY wt          j
        ¦   «         }t          |t          ¦  «        r,|                     d¦  «        r|                     d¦  «        pdS dS )zAReturn a writable temp dir for env-backed execute_code sandboxes.Úget_temp_dirNrZ  z/Could not resolve execute_code env temp dir: %sú/tmp)ÚgetattrÚcallabler  r  r„   Úrstripr‹   r”   r•   ÚtempfileÚ
gettempdir)rR  rf  Útemp_dirr  Ú	candidates        r.   Ú_env_temp_dirro  Š  s  € å˜3 °Ñ5Ô5€LÝ�ÑÔð Qð	QØ#�|‘~”~ˆHÝ˜(¥CÑ(Ô(ð 3¨X×-@Ò-@ÀÑ-EÔ-Eð 3Ø—’ sÑ+Ô+Ð2¨sÐ2øøÝð 	Qð 	Qð 	QÝ�LŠLÐJÈCÑPÔPÐPÐPÐPÐPÐPÐPøøøøð	QøøøåÔ#Ñ%Ô%€IÝ�)�SÑ!Ô!ð , i×&:Ò&:¸3Ñ&?Ô&?ð ,Ø×Ò Ñ$Ô$Ð+¨Ð+Øˆ6s   ¢A
A. Á.
BÁ8BÂBÚrpc_dirc	                 ó$
  — ddl m}	 d}
t          j        |¦  «        }|                     ¦   «         �sÞ	 |                      d|› d�dd¬¦  «        }|                     d	d
¦  «                             ¦   «         }|s|                     |
¦  «         Œrt          d„ | 
                    d¦  «        D ¦   «         ¦  «        }|D �]È}|                     ¦   «         r �n°t          j        ¦   «         }t          j        |¦  «        }|                      d|› �dd¬¦  «        }	 t          j        |                     d	d
¦  «        ¦  «        }nR# t          j        t           f$ r9 t"                               d|¦  «         |                      d|› �dd¬¦  «         Y ŒÔw xY w|r[t'          j        t+          |                     d¦  «        pd
¦  «                             ¦   «         |                     ¦   «         ¦  «        s8t"                               d|¦  «         |                      d|› �dd¬¦  «         �Œm|                     dd
¦  «        }|                     di ¦  «        }|                     dd¦  «        }|d›}|› d|› �}t          j        |¦  «        }||vr9d                     t          |¦  «        ¦  «        }t1          d|› d|› �¦  «        }�nD|d         |k    rt1          d|› d�¦  «        }�n#|dk    r5t3          |t4          ¦  «        r t6          D ]}|                     |d¦  «         Œ	 t;          ¦   «         5   |	|||¬¦  «        }ddd¦  «         n# 1 swxY w Y   nP# t<          $ rC}t"                               d |d!¬"¦  «         t1          t+          |¦  «        ¦  «        }Y d}~nd}~ww xY w|dxx         d#z  cc<   t          j        ¦   «         |z
  }|                      |t+          |¦  «        dd$…         tC          |d%¦  «        d&œ¦  «         tE          j#        |                     d'¦  «        ¦  «         $                    d(¦  «        }|                      d)|› d*|› d+|› d,|› �dd-¬¦  «         |                      d|› �dd¬¦  «         �ŒÊnH# t<          $ r;} |                     ¦   «         st"                               d.| d!¬"¦  «         Y d} ~ nd} ~ ww xY w|                     ¦   «         s|                     |
¦  «         |                     ¦   «         �¯ÜdS dS )/zñPoll the remote filesystem for tool call requests and dispatch them.

    Runs in a background thread.  Each ``env.execute()`` spawns an
    independent process, so these calls run safely concurrent with the
    script-execution thread.
    r   rá   gš™™™™™¹?zls -1 z/req_* 2>/dev/null || truerZ  é
   r\  Úoutputrå   c                 óØ   — g | ]g}|                      ¦   «         rQ|                      ¦   «                              d ¦  «        s*d|                      ¦   «         v ¯S|                      ¦   «         ‘ŒhS )z.tmpz/req_)rü   Úendswith)r   Úfs     r.   ú
<listcomp>z"_rpc_poll_loop.<locals>.<listcomp>½  sq   € ð  ð  ð  ØØ—7’7‘9”9ð ð Ÿš™	œ	×*Ò*¨6Ñ2Ô2ð ð ˜qŸwšw™yœyÐ(Ð(ð —’‘	”	ð )Ð(Ð(r   rÆ   zcat zMalformed RPC request in %szrm -f é   rä   zUnauthorized RPC request in %sræ   rç   ÚseqÚ06dz/res_r‡   rè   ré   rê   rë   r   Nrì   z&Tool call failed in remote sandbox: %sTr¥   r°   rí   rî   rï   r   rW  rX  rY  z.tmp && mv z.tmp é<   zRPC poll error: %s)%rò   râ   r_  r`  rô   ra  r«   rü   Úwaitr—   rû   rý   rþ   rÿ   r   r  Ú
ValueErrorr”   r•   r  r  r  r2   r–   r  r  r	  r
  r  r
   r‹   r  r“   r  r]  r^  r'   )!rR  rp  rÙ   rÚ   rÛ   rÜ   rÝ   rÞ   rß   râ   Úpoll_intervalÚquoted_rpc_dirÚ	ls_resultrs  Ú	req_filesÚreq_filer  Úquoted_req_fileÚread_resultr  rÍ   r  ry  Úseq_strÚres_fileÚquoted_res_filer¾   Útool_resultr  r  r  Úencoded_resultr  s!                                    r.   Ú_rpc_poll_looprŠ  š  sj  € ð" 1Ð0Ð0Ð0Ð0Ð0à€Må”[ Ñ)Ô)€NØ×ÒÑ!Ô!ñ u+ðq	EàŸšØC˜ÐCÐCÐCØØð $ñ ô ˆIð
 —]’] 8¨RÑ0Ô0×6Ò6Ñ8Ô8ˆFØð Ø—’ Ñ.Ô.Ð.Øåð  ð  Ø#)§<¢<°Ñ#5Ô#5ð ñ  ô  ñ ô ˆIð &ð ZLñ ZL�Ø×$Ò$Ñ&Ô&ð Ø‘Eå!œ^Ñ-Ô-�
å"'¤+¨hÑ"7Ô"7�à!ŸkškØ,˜?Ð,Ð,ØØð *ñ ô �ð
Ý"œj¨¯ª¸À2Ñ)FÔ)FÑGÔG�G�GøÝÔ,­jÐ9ð ð ð Ý—L’LÐ!>ÀÑIÔIÐIà—K’KÐ :¨Ð :Ð :ÀÈQ�KÑOÔOÐOØ�Hð	øøøð !ð ­Ô(>õ ˜Ÿš GÑ,Ô,Ð2°Ñ3Ô3×:Ò:Ñ<Ô<¸i×>NÒ>NÑ>PÔ>Pñ	)ô )ð õ —L’LÐ!AÀ8ÑLÔLÐLØ—K’KÐ :¨Ð :Ð :ÀÈQ�KÑOÔOÐOÙà#ŸKšK¨°Ñ3Ô3�	Ø#ŸKšK¨°Ñ3Ô3�	Ø—k’k %¨Ñ+Ô+�Ø ˜,˜,�Ø%Ð5Ð5¨GÐ5Ð5�Ý"'¤+¨hÑ"7Ô"7�ð  MÐ1Ð1Ø $§	¢	­&°Ñ*?Ô*?Ñ @Ô @�IÝ",ð2 ð 2ð 2Ø&/ð2ð 2ñ#ô #�K‘Kð
 ' qÔ)¨^Ò;Ð;Ý",ðH°Nð Hð Hð Hñ#ô #�K‘Kð ! JÒ.Ð.µ:¸iÍÑ3NÔ3NÐ.Ý%=ð 7ð 7˜EØ%ŸMšM¨%°Ñ6Ô6Ð6Ð6ð;Ý2Ñ4Ô4ð ð Ø*>Ð*>Ø )¨9¸gð+ñ +ô +˜Kðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð øøõ %ð ;ð ;ð ;ÝŸšÐ%MØ%(°4ð %ñ 9ô 9ð 9å&0µ°S±´Ñ&:Ô&:˜˜˜˜˜˜øøøøð;øøøð
 & aÐ(Ð(Ô(¨AÑ-Ð(Ð(Ñ(Ý$(¤NÑ$4Ô$4°zÑ$A�MØ!×(Ò(Ø )Ý(+¨I©¬°s¸°sÔ(;Ý$)¨-¸Ñ$;Ô$;ð*ð *ñ ô ð õ "(Ô!1Ø×&Ò& wÑ/Ô/ñ"ô "ç’&˜‘/”/ð ð —’ðF˜^ð Fð F¸_ð Fð FØ-ðFð FØ4CðFð FàØð	 ñ ô ð ð —’Ð6 _Ð6Ð6¸CÈ�ÑKÔKÐKÑKøøåð 	Eð 	Eð 	EØ×$Ò$Ñ&Ô&ð EÝ—’Ð1°1¸t�ÑDÔDÐDøøøøøøøøøð	Eøøøð × Ò Ñ"Ô"ð 	+Ø�OŠO˜MÑ*Ô*Ð*ðk ×ÒÑ!Ô!ñ u+ð u+ð u+ð u+ð u+s”   ³AR ÂB
R Ä(EÅR ÅAFÆR ÆFÆFR Ì%MÌ3MÍMÍM	ÍMÍM	ÍMÍR Í
N'Í$9N"ÎR Î"N'Î'C R Ò
SÒ1SÓSÚcodec                 ó@  — t          ¦   «         }|                     dt          ¦  «        }|                     dt          ¦  «        }|rt	          |¦  «        nt	          ¦   «         }t          t          |z  ¦  «        }|st          }|pd}t          |¦  «        \  }	}
t          j	        ¦   «         j
        dd…         }t          |	¦  «        }|› d|› �}t          j        |¦  «        }t          j        |› d�¦  «        }g }dg}t          j        ¦   «         }t!          j        ¦   «         }d}	 |	                     d	d
d¬¦  «        }d|                     dd¦  «        vr�t'          j        dd|
› d�dddœ¦  «        |                     ¦   «          |�|                     d¬¦  «         	 |	                     d|› �d
d¬¦  «         S # t,          $ r t.                               d|¦  «         Y S w xY w|	                     d|› �d
d¬¦  «         t3          j        d¦  «        }t7          t9          |¦  «        d¬¦  «        }t;          |	|› d�|¦  «         t;          |	|› d�| ¦  «         t!          j        t?          t@          ¦  «        |	|› d�|||||||f	d¬ ¦  «        }| !                    ¦   «          d!t          j        |› d�¦  «        › d"t          j        |¦  «        › d#�}tE          j#        d$d¦  «         $                    ¦   «         }|r|d%t          j        |¦  «        › �z  }t.           %                    d&|
|dd'…         ¦  «         |	                     d(|› d)|› d*�|¬¦  «        }|                     dd¦  «        pd}|                     d+d,¦  «        }d-}|d.k    rd}n|d/k    rd0}�n# t,          $ �r}tM          t          j        ¦   «         |z
  d1¦  «        }t.           '                    d2||d         tQ          |¦  «        j)        |d¬3¦  «         t'          j        dtU          |¦  «        |d         |dœd4¬5¦  «        cY d}~|                     ¦   «          |�|                     d¬¦  «         	 |	                     d|› �d
d¬¦  «         S # t,          $ r t.                               d|¦  «         Y S w xY wd}~ww xY w|                     ¦   «          |�|                     d¬¦  «         	 |	                     d|› �d
d¬¦  «         n£# t,          $ r t.                               d|¦  «         Y n|w xY w# |                     ¦   «          |�|                     d¬¦  «         	 |	                     d|› �d
d¬¦  «         w # t,          $ r t.                               d|¦  «         Y w w xY wxY wtM          t          j        ¦   «         |z
  d1¦  «        }tW          |¦  «        \  }} dd6l,m-}!  |!|¦  «        }dd7l.m/}"  |"|d¬8¦  «        }||||d         |d9œ}#|# 0                    | ¦  «         |dk    rEd:|› d;�}$|$|#d<   |r|d<|$› �z   |#d<   nd=|$› �|#d<   t.           1                    d>|||d         ¦  «         n"|d0k    r	|d?z   |#d<   n|dk    rd|#d@<   dA|› �|#d<   t'          j        |#d4¬5¦  «        S )Ba  Run a script on the remote terminal backend via file-based RPC.

    The script and the generated hermes_tools.py module are shipped to
    the remote environment, and tool calls are proxied through a polling
    thread that communicates via request/response files.
    r÷   rÜ   ÚdefaultNé   z/hermes_exec_z/rpcr   z-command -v python3 >/dev/null 2>&1 && echo OKrZ  é   r\  ÚOKrs  rå   r  z!Python 3 is not available in the zO terminal environment. Install Python to use execute_code with remote backends.©Ústatusr  Útool_calls_madeÚduration_secondsrx  ©r÷   zrm -rf z$Failed to clean up remote sandbox %sz	mkdir -p rr  é    rÅ   )rÂ   z/hermes_tools.pyz
/script.pyT©Útargetrç   ÚdaemonzHERMES_RPC_DIR=z HERMES_RPC_TOKEN=z PYTHONDONTWRITEBYTECODE=1ÚHERMES_TIMEZONEz TZ=z)Executing code on %s backend (task %s)...rF  zcd z && z python3 script.pyÚ
returncodeéÿÿÿÿÚsuccessé|   é‚   Úinterruptedrî   z?execute_code remote failed after %ss with %d tool calls: %s: %sr¥   F©Úensure_ascii©Ú
strip_ansi©Úredact_sensitive_text©Ú	code_file©r’  rs  Ú	exit_coder“  r”  úScript timed out after ús and was killed.õ   

â�° õ   â�° zHexecute_code (remote) timed out after %ss (limit %ss) with %d tool callsõ4   
[execution interrupted â€” user sent a new message]r’  úScript exited with code )2Ú_load_configr«   ÚDEFAULT_TIMEOUTÚDEFAULT_MAX_TOOL_CALLSr¹   Ú	frozensetr¸   rS  ÚuuidÚuuid4Úhexro  r_  r`  rý   rþ   rL  ÚEventra  rÿ   Údumpsr–   r‹   r”   r•   r  Útoken_urlsaferÓ   Úlistrd  ÚThreadr	   rŠ  ÚstartÚosÚgetenvrü   rN  r  r  ÚtypeÚ__name__r  r8   Útools.ansi_stripr¤  Úagent.redactr¦  Úupdater$   )%r‹  rÙ   rº   Ú_cfgr÷   rÜ   Úsession_toolsÚsandbox_toolsrO  rR  r§   Ú
sandbox_idrm  Úsandbox_dirÚquoted_sandbox_dirr  rÚ   rÛ   Ú
exec_startrÞ   Ú
rpc_threadÚpy_checkrß   Ú	tools_srcÚ
env_prefixÚtzÚscript_resultr,   rª  r’  r  rñ   Ústdout_metadatar¤  r¦  r  Útimeout_msgs%                                        r.   Ú_execute_remoterÔ  (  s­  € õ ‰>Œ>€DØ�hŠh�y¥/Ñ2Ô2€GØ—X’XÐ.Õ0FÑGÔG€Nà*7ÐB•C˜Ñ&Ô&Ð&½S¹U¼U€MÝÕ3°mÑCÑDÔD€MØð .Ý-ˆàÐ, 9ÐÝ&Ð'8Ñ9Ô9�M€Cˆå”‘”Ô! # 2 #Ô&€JÝ˜SÑ!Ô!€HØÐ8Ð8¨JÐ8Ð8€KÝœ [Ñ1Ô1ÐÝ”[ KÐ!5Ð!5Ð!5Ñ6Ô6€Nà€MØ˜ÐÝ”Ñ!Ô!€JÝ”Ñ"Ô"€JØ€JðdNà—;’;Ø;Ø˜Rð ñ 
ô 
ˆð �x—|’| H¨bÑ1Ô1Ð1Ð1Ý”:Ø!ð'¸ð 'ð 'ð 'ð $%Ø$%ð	ð 	ñ 	ô 	ðf 	�ŠÑÔÐØÐ!Ø�OŠO AˆOÑ&Ô&Ð&ð	NØ�KŠKØ.Ð,Ð.Ð.°CÀð ñ ô ð ð øõ ð 	Nð 	Nð 	NÝ�LŠLÐ?ÀÑMÔMÐMÐMÐMð	Nøøøða 	�ŠØ(˜Ð(Ð(¨c¸2ð 	ñ 	
ô 	
ð 	
õ Ô)¨"Ñ-Ô-ˆ	õ 1Ý�ÑÔ¨6ð
ñ 
ô 
ˆ	õ 	˜S [Ð"BÐ"BÐ"BÀIÑNÔNÐNÝ˜S [Ð"<Ð"<Ð"<¸dÑCÔCÐCõ
 Ô%Ý.­~Ñ>Ô>à˜Ð)Ð)Ð)Ð+<ØÐ0°.Ø˜z¨9ðð
 ð
ñ 
ô 
ˆ
ð 	×ÒÑÔÐð)�eœk¨[Ð*>Ð*>Ð*>Ñ?Ô?ð )ð )Ý %¤¨IÑ 6Ô 6ð)ð )ð )ð 	õ
 ŒYÐ(¨"Ñ-Ô-×3Ò3Ñ5Ô5ˆØð 	3ØÐ2¥¤¨R¡¤Ð2Ð2Ñ2ˆJõ 	�ŠÐ?ØÐ0°°!°Ô4ñ	6ô 	6ð 	6àŸšØHÐ$ÐHÐH¨*ÐHÐHÐHØð $ñ 
ô 
ˆð
 $×'Ò'¨°"Ñ5Ô5Ð;¸ˆØ!×%Ò% l°BÑ7Ô7ˆ	Øˆð ˜ÒÐØˆFˆFØ˜#ÒÐØ"ˆFùøåð ñ ð Ý�œÑ)Ô)¨JÑ6¸Ñ:Ô:ˆÝ�ŠØMØÐ'¨Ô*­D°©I¬IÔ,>ÀØð 	ñ 	
ô 	
ð 	
õ
 ŒzØÝ˜‘X”XØ0°Ô3Ø (ð	
ð 
ð
 ðñ ô ð 	ð 	ð 	ð 	ð 	ð 	�ŠÑÔÐØÐ!Ø�OŠO AˆOÑ&Ô&Ð&ð	NØ�KŠKØ.Ð,Ð.Ð.°CÀð ñ ô ð ð øõ ð 	Nð 	Nð 	NÝ�LŠLÐ?ÀÑMÔMÐMÐMÐMð	Nøøøøøøøð3øøøð  	�ŠÑÔÐØÐ!Ø�OŠO AˆOÑ&Ô&Ð&ð	NØ�KŠKØ.Ð,Ð.Ð.°CÀð ñ ô ð ð øõ ð 	Nð 	Nð 	NÝ�LŠLÐ?ÀÑMÔMÐMÐMÐMð	Nøøøøð 	�ŠÑÔÐØÐ!Ø�OŠO AˆOÑ&Ô&Ð&ð	NØ�KŠKØ.Ð,Ð.Ð.°CÀð ñ ô ð ð øõ ð 	Nð 	Nð 	NÝ�LŠLÐ?ÀÑMÔMÐMÐMÐMð	Nøøøøøøõ •T”^Ñ%Ô%¨
Ñ2°AÑ6Ô6€Hõ $9¸Ñ#EÔ#EÑ €K�ð ,Ð+Ð+Ð+Ð+Ð+Ø�*˜[Ñ)Ô)€Kð
 3Ð2Ð2Ð2Ð2Ð2Ø'Ð'¨¸tÐDÑDÔD€Kð ØØØ,¨QÔ/Ø$ðð €Fð ‡M‚M�/Ñ"Ô"Ð"à�ÒÐØJ°ÐJÐJÐJˆØ%ˆˆw‰ð ð 	4Ø*Ð-E¸Ð-EÐ-EÑEˆF�8ÑÐà3 kÐ3Ð3ˆF�8ÑÝ�ŠØVØ�gÐ0°Ô3ñ	
ô 	
ð 	
ð 	
ð 
�=Ò	 Ð	 àÐQÑQð 	ˆxÑÐð 
�aŠˆØ"ˆˆxÑØ@°YÐ@Ð@ˆˆw‰åŒ:�f¨5Ð1Ñ1Ô1Ð1s™   Ä)AN Æ"F>Æ>%G&Ç%G&Ç)F4N ÎT( ÎR1Î*B	R,Ð3R1Ð4T( Ñ%RÒ%R)Ò(R)Ò,R1Ò1T( Ó!S= Ó=%T%Ô$T%Ô(-VÕU2Õ1VÕ2%VÖVÖVÖVc                 ó‚  — t           st          d¦  «        S | r|                      ¦   «         st          d¦  «        S ddlm}m}  |¦   «         }|d         }ddlm}  || | ||¦  «        ¬¦  «        }|                     dd	¦  «        s0t          j
        d
|                     d¦  «        pddddœd	¬¦  «        S |                     d¦  «        rddlm}	  |	¦   «          |dk    rt          | ||¦  «        S ddlm}
 t          ¦   «         }|                     dt           ¦  «        }|                     dt"          ¦  «        }|rt%          |¦  «        nt%          ¦   «         }t'          t(          |z  ¦  «        }|st(          }t+          j        d¬¦  «        }t.          j        dk    rdnt+          j        ¦   «         }t4          }|rd}d}n<t6          j                             |dt=          j        ¦   «         j         › d�¦  «        }|}g }dg}tC          j"        ¦   «         }d}tG          j$        ¦   «         }	 tK          tM          |¦  «        ¦  «        }tO          t6          j                             |d¦  «        dd¬¦  «        5 }| (                    |¦  «         ddd¦  «         n# 1 swxY w Y   tO          t6          j                             |d ¦  «        dd¬¦  «        5 }| (                    | ¦  «         ddd¦  «         n# 1 swxY w Y   tS          j*        d!¦  «        }|rftW          j+        tV          j,        tV          j-        ¦  «        }| .                    d"¦  «         | /                    ¦   «         dd#…         \  }}d$|› d%|› �}nStW          j+        tV          j0        tV          j-        ¦  «        }| .                    |¦  «         t7          j1        |d&¦  «         | 2                    d'¦  «         tG          j3        ti          tj          ¦  «        ||||||||fd(¬)¦  «        }| 6                    ¦   «          to          t6          j8        ¦  «        } || d*<   || d+<   d,| d-<   d| d.<   d,| d/<   t6          j         9                    t6          j         9                    t6          j         :                    tv          ¦  «        ¦  «        ¦  «        }!|                      d0d1¦  «        }"||!g}#|"r|# <                    |"¦  «         t6          j=                             |#¦  «        | d0<   t7          j>        d2d1¦  «                             ¦   «         }$|$r|$| d3<   |  ?                    d2d¦  «         dd4l@mA}%  |%| ¦  «         t…          ¦   «         }&t‡          |&¦  «        }'t‰          |&||pd1¬5¦  «        }(t6          j                             |d ¦  «        })t‹          jF        |'|)g|(| tŠ          jG        tŠ          jG        tŠ          jH        d(t4          rtŠ          jI        nd¬6¦  «        }*tC          j"        ¦   «         |z   }+g },t•          t–          d7z  ¦  «        }-t–          |-z
  }.d8„ }/dg}0d9„ }1g }2g }3tG          j3        |1|*jL        |2|3|-|.|0fd(¬)¦  «        }4tG          j3        |/|*jM        |,tœ          fd(¬)¦  «        }5|4 6                    ¦   «          |5 6                    ¦   «          d:}6tC          j"        ¦   «         |d;œ}7	 dd<lOmP}8 n# t¢          $ r d}8Y nw xY wd=}9|* R                    ¦   «         €Ü |
¦   «         rt§          |*¦  «         d>}6nÀtC          j"        ¦   «         }:|:|+k    rt§          |*d(¬?¦  «         d}6n“|8�	  |8|7d@¦  «         n# t¢          $ r Y nw xY w	 |* T                    t«          |9t­          dA|+|:z
  ¦  «        ¦  «        ¬B¦  «         n# tŠ          jW        $ r Y nw xY wt«          dC|9dDz  ¦  «        }9|* R                    ¦   «         ®Ü|4                     dE¬B¦  «         |5                     dE¬B¦  «         dF                     |,¦  «         X                    ddG¬H¦  «        };t³          dF                     |2¦  «        dF                     |3¦  «        |0d         ¬I¦  «        \  }<}=|*jZ        �|*jZ        ndJ}>t·          tC          j"        ¦   «         |z
  d#¦  «        }?|                     ¦   «          | \                    ¦   «          d}|                     dE¬B¦  «         ddKl]m^}@  |@|<¦  «        }< |@|;¦  «        };ddLl_m`}A  |A|<d(¬M¦  «        }< |A|;d(¬M¦  «        };|6|<|>|d         |?dNœ}B|B a                    |=¦  «         |6dk    rEdO|› dP�}C|C|Bd
<   |<r|<dQ|C› �z   |BdR<   ndS|C› �|BdR<   tÄ           c                    dT|?||d         ¦  «         nI|6d>k    r	|<dUz   |BdR<   n:|>dk    r4d
|BdV<   |;pdW|>› �|Bd
<   |;r|<dXz   |;z   |BdR<   tÉ          |;|¬Y¦  «        }D|Dr|D|BdZ<   t          j
        |Bd	¬¦  «        |�H	 | \                    ¦   «          n2# tÊ          $ r%}EtÄ           f                    d[|E¦  «         Y d}E~End}E~Eww xY wddlg}F|F h                    |d(¬\¦  «         	 |rt7          ji        |¦  «         S S # tÊ          $ r Y S w xY w# t¢          $ �r!}Gt·          tC          j"        ¦   «         |z
  d#¦  «        }?tÄ           j                    d]|?|d         t×          |G¦  «        jl        |Gd(¬^¦  «         t          j
        d
tÛ          |G¦  «        |d         |?dœd	¬¦  «        cY d}G~G|�H	 | \                    ¦   «          n2# tÊ          $ r%}EtÄ           f                    d[|E¦  «         Y d}E~End}E~Eww xY wddlg}F|F h                    |d(¬\¦  «         	 |rt7          ji        |¦  «         S S # tÊ          $ r Y S w xY wd}G~Gww xY w# |�H	 | \                    ¦   «          n2# tÊ          $ r%}EtÄ           f                    d[|E¦  «         Y d}E~End}E~Eww xY wddlg}F|F h                    |d(¬\¦  «         	 |rt7          ji        |¦  «         w w # tÊ          $ r Y w w xY wxY w)_aB  
    Run a Python script in a sandboxed child process with RPC access
    to a subset of Hermes tools.

    Dispatches to the local (UDS) or remote (file-based RPC) path
    depending on the configured terminal backend.

    Args:
        code:          Python source code to execute.
        task_id:       Session task ID for tool isolation (terminal env, etc.).
        enabled_tools: Tool names enabled in the current session. The sandbox
                       gets the intersection with SANDBOX_ALLOWED_TOOLS.

    Returns:
        JSON string with execution results.
    z~execute_code sandbox is unavailable in this environment. Use normal tool calls (terminal, read_file, write_file, ...) instead.zNo code provided.r   )r¤   Ú_docker_has_host_accessr§   )Úcheck_execute_code_guard)Úhas_host_accessÚapprovedFr  Úmessagez'execute_code blocked by approval guard.r‘  r¡  Úuser_approved)Úclear_current_thread_interruptrD  )Úis_interruptedr÷   rÜ   Úhermes_sandbox_)ÚprefixÚdarwinrg  NÚhermes_rpc_z.sockzhermes_tools.pyÚwr   )Úencodingz	script.pyr–  )z	127.0.0.1r   rî   ztcp://ú:i€  r°   Tr—  ÚHERMES_RPC_SOCKETÚHERMES_RPC_TOKENÚ1ÚPYTHONDONTWRITEBYTECODEÚPYTHONIOENCODINGÚ
PYTHONUTF8rE   rå   rš  ÚTZ)Úapply_subprocess_home_envrì   )r/  rR  ÚstdoutÚstderrÚstdinÚstart_new_sessionÚcreationflagsr1   c                 ó*  — d}	 	 |                       d¦  «        }|sdS ||k     r"||z
  }|                     |d|…         ¦  «         |t          |¦  «        z  }ŒT# t          t          f$ r(}t
                               d|d¬¦  «         Y d}~dS d}~ww xY w)z)Simple head-only drain (used for stderr).r   Té   Nz Error reading process output: %sr¥   )Úreadr“   r%   r}  rù   r”   r•   )ÚpipeÚchunksÚ	max_bytesr)   ÚdataÚkeepr  s          r.   Ú_drainzexecute_code.<locals>._drainä  sÇ   € àˆEð
Sð'ØŸ9š9 T™?œ?�DØð Ø˜Ø˜yÒ(Ð(Ø(¨5Ñ0˜ØŸš d¨5¨D¨5¤kÑ2Ô2Ð2Ø�S ™YœYÑ&�Eð'øõ ¥Ð(ð Sð Sð SÝ—’Ð?ÀÈT�ÑRÔRÐRÐRÐRÐRÐRÐRÐRøøøøðSøøøs   „A ž;A ÁBÁ*BÂBc                 ó\  — d}ddl m}  |¦   «         }d}		 	 |                      d¦  «        }
|
snÐ|dxx         t          |
¦  «        z  cc<   ||k     rOt	          t          |
¦  «        ||z
  ¦  «        }|                     |
d|…         ¦  «         ||z  }|
|d…         }
|
sŒ‹|                     |
¦  «         |	t          |
¦  «        z  }	|	|k    r0|r.|                     ¦   «         }|	t          |¦  «        z  }	|	|k    r|°.Œèn# t          t          f$ r Y nw xY w| 	                    |¦  «         dS )z-Drain stdout keeping both head and tail data.r   )ÚdequeTró  N)
Úcollectionsrü  rô  r%   Úminr“   Úpopleftr}  rù   Úextend)rõ  Úhead_chunksÚtail_chunksr6   r7   Ú	total_refÚhead_collectedrü  Útail_bufÚtail_collectedrø  rù  Úoldests                r.   Ú_drain_head_tailz&execute_code.<locals>._drain_head_tailõ  s~  € àˆNØ)Ð)Ð)Ð)Ð)Ð)Ø�u‘w”wˆHØˆNðð6ØŸ9š9 T™?œ?�DØð ØØ˜a�L�L”L¥C¨¡I¤IÑ-�L�L‘Là%¨
Ò2Ð2Ý"¥3 t¡9¤9¨j¸>Ñ.IÑJÔJ˜Ø#×*Ò*¨4°°°¬;Ñ7Ô7Ð7Ø&¨$Ñ.˜Ø# D E Eœ{˜Ø#ð %Ø$à—O’O DÑ)Ô)Ð)Ø"¥c¨$¡i¤iÑ/�Nà(¨:Ò5Ð5¸(Ð5Ø!)×!1Ò!1Ñ!3Ô!3˜Ø&­#¨f©+¬+Ñ5˜ð )¨:Ò5Ð5¸(Ð5ð#6ð øõ" ¥Ð(ð ð ð Ø�ðøøøð ×Ò˜xÑ(Ô(Ð(Ð(Ð(s   –C)D  Ä DÄDr�  )Ú
last_touchr½  )Útouch_activity_if_dueg{®Gázt?r   )Úescalatezexecute_code runningg        r•  gš™™™™™É?g      ø?é   r   r   r   r   rœ  r£  r¥  r§  r©  r«  r¬  r­  rs  r®  z?execute_code timed out after %ss (limit %ss) with %d tool callsr¯  r’  r°  z
--- stderr ---
)rº   ÚhintzServer socket close error: %s)Úignore_errorsz8execute_code failed after %ss with %d tool calls: %s: %sr¥   )nr©   r  rü   rª   r¤   rÖ  Útools.approvalr×  r«   rÿ   r¹  Útools.interruptrÜ  rÔ  rÝ  r±  r²  r³  r¹   r´  r¸   rk  ÚmkdtempÚsysÚplatformrl  rŒ   r¾  Úpathr–   rµ  r¶  r·  rý   rþ   rL  r¸  rÓ   r»  ÚopenÚwriter  rº  rö   ÚAF_INETÚSOCK_STREAMÚbindÚgetsocknameÚAF_UNIXÚchmodÚlistenr¼  r	   r  r½  r¡   ÚenvironÚdirnameÚabspathÚ__file__r“   Úpathsepr¿  r  Úhermes_constantsrì  Ú_get_execution_modeÚ_resolve_child_pythonÚ_resolve_child_cwdÚ
subprocessÚPopenÚPIPEÚDEVNULLÚCREATE_NO_WINDOWr4   r3   rí  rî  ÚMAX_STDERR_BYTESÚtools.environments.baser
  r‹   ÚpollÚ_kill_process_groupr|  rþ  r&   ÚTimeoutExpiredr'   r/   r›  r  rø   rÂ  r¤  rÃ  r¦  rÄ  r”   r$   rÀ   rù   r•   ÚshutilÚrmtreeÚunlinkr  rÀ  rÁ  r  )Hr‹  rÙ   rº   r¤   rÖ  Ú_env_configr§   r×  Ú_guardrÜ  Ú_is_interruptedrÅ  r÷   rÜ   rÆ  rÇ  ÚtmpdirÚ_sock_tmpdirÚ_use_tcp_rpcÚ	sock_pathÚrpc_endpointrÚ   rÛ   rË  rØ   rÞ   rÎ  rv  rß   Ú_hostÚ_portrÌ  Ú	child_envÚ_hermes_rootÚ_existing_ppÚ	_pp_partsÚ_tz_namerì  Ú_modeÚ_child_pythonÚ
_child_cwdÚ_script_pathÚprocÚdeadlineÚstderr_chunksÚ_STDOUT_HEAD_BYTESÚ_STDOUT_TAIL_BYTESrú  Ústdout_total_bytesr  Ústdout_head_chunksÚstdout_tail_chunksÚstdout_readerÚstderr_readerr’  Ú_activity_stater
  r~  Únowr®   r,   rÒ  rª  rñ   r¤  r¦  r  rÓ  r  r  r1  r  sH                                                                           r.   Úexecute_coderS  è  sE  € õ* ð 
ÝðTñ
ô 
ð 	
ð
 ð /�t—z’z‘|”|ð /ÝÐ-Ñ.Ô.Ð.ð MÐLÐLÐLÐLÐLÐLÐLØ!�/Ñ#Ô#€KØ˜:Ô&€Hð 8Ð7Ð7Ð7Ð7Ð7Ø%Ð%ØˆhØ/Ð/°Ñ<Ô<ðñ ô €Fð �:Š:�j %Ñ(Ô(ð ÝŒzØØ—Z’Z 	Ñ*Ô*ÐWÐ.WØ Ø !ð	
ð 
ð
 ðñ ô ð 	ð ‡z‚z�/Ñ"Ô"ð )ØBÐBÐBÐBÐBÐBØ&Ð&Ñ(Ô(Ð(à�7ÒÐÝ˜t W¨mÑ<Ô<Ð<ð
 BÐAÐAÐAÐAÐAõ ‰>Œ>€DØ�hŠh�y¥/Ñ2Ô2€GØ—X’XÐ.Õ0FÑGÔG€Nð +8ÐB•C˜Ñ&Ô&Ð&½S¹U¼U€MÝÕ3°mÑCÑDÔD€Màð .Ý-ˆõ ÔÐ%6Ð7Ñ7Ô7€Fõ !œ\¨XÒ5Ð5�6�6½8Ô;NÑ;PÔ;P€LÝ€LØð !Øˆ	Øˆˆå”G—L’L Ð/T½T¼Z¹\¼\Ô=MÐ/TÐ/TÐ/TÑUÔUˆ	Ø ˆà€MØ˜ÐÝ”Ñ!Ô!€JØ€KÝ”Ñ"Ô"€Jð\õ 1µ°mÑ1DÔ1DÑEÔEˆ	Ý•"”'—,’,˜vÐ'8Ñ9Ô9¸3ÈÐQÑQÔQð 	ÐUVØ�GŠG�IÑÔÐð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	õ •"”'—,’,˜v {Ñ3Ô3°SÀ7ÐKÑKÔKð 	ÈqØ�GŠG�D‰MŒMˆMð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	õ Ô)¨"Ñ-Ô-ˆ	ð ð 	'Ý œ-­¬½Ô8JÑKÔKˆKØ×ÒÐ-Ñ.Ô.Ð.Ø&×2Ò2Ñ4Ô4°R°a°RÔ8‰LˆE�5Ø3 EÐ3Ð3¨EÐ3Ð3ˆLˆLå œ-­¬½Ô8JÑKÔKˆKØ×Ò˜YÑ'Ô'Ð'ÝŒH�Y Ñ&Ô&Ð&Ø×Ò˜1ÑÔÐõ
 Ô%Ý.Õ/?Ñ@Ô@à˜W mØ! >°=À*Èiðð ð
ñ 
ô 
ˆ
ð 	×ÒÑÔÐõ %¥R¤ZÑ0Ô0ˆ	Ø)5ˆ	Ð%Ñ&Ø(1ˆ	Ð$Ñ%Ø/2ˆ	Ð+Ñ,ð$ )0ˆ	Ð$Ñ%Ø"%ˆ	�,Ñõ
 ”w—’¥r¤w§¢µr´w·²ÅxÑ7PÔ7PÑ'QÔ'QÑRÔRˆØ —}’} \°2Ñ6Ô6ˆØ˜\Ð*ˆ	Øð 	+Ø×Ò˜\Ñ*Ô*Ð*Ý"$¤*§/¢/°)Ñ"<Ô"<ˆ	�,Ñõ
 ”9Ð.°Ñ3Ô3×9Ò9Ñ;Ô;ˆØð 	'Ø&ˆI�d‰OØ�ŠÐ'¨Ñ.Ô.Ð.à>Ð>Ð>Ð>Ð>Ð>Ø!Ð! )Ñ,Ô,Ð,õ $Ñ%Ô%ˆÝ-¨eÑ4Ô4ˆÝ'¨¨v¸w¸}È"ÐMÑMÔMˆ
Ý”w—|’| F¨KÑ8Ô8ˆåÔØ˜LÐ)ØØÝ”?Ý”?ÝÔ$Ø"Ý9DÐK�*Ô5Ð5È!ð	
ñ 	
ô 	
ˆõ ”>Ñ#Ô# gÑ-ˆØ ˆõ !Õ!1°CÑ!7Ñ8Ô8ÐÝ-Ð0BÑBÐð	Sð 	Sð 	Sð  ˜SÐð	)ð 	)ð 	)ð@ $&ÐØ#%Ðå!Ô(Ø#Ø”+Ð1Ð3EØ$Ð&8Ð:LðNàð	
ñ 
ô 
ˆõ "Ô(Ø ¤¨mÕ=MÐ NÐW[ð
ñ 
ô 
ˆð 	×ÒÑÔÐØ×ÒÑÔÐàˆåœ.Ñ*Ô*Øð
ð 
ˆð	)ØEÐEÐEÐEÐEÐEÐEøÝð 	)ð 	)ð 	)Ø$(Ð!Ð!Ð!ð	)øøøàˆØ�iŠi‰kŒkÐ!ØˆÑ Ô ð Ý# DÑ)Ô)Ð)Ø&�ØÝ”.Ñ"Ô"ˆCØ�XŠ~ˆ~Ý# D°4Ð8Ñ8Ô8Ð8Ø"�Øð %Ð0ðØ)Ð)¨/Ð;QÑRÔRÐRÐRøÝ ð ð ð Ø�DðøøøðØ—	’	¥# mµS¸¸hÈ¹nÑ5MÔ5MÑ"NÔ"N�	ÑOÔOÐOÐOøÝÔ,ð ð ð Ø�ðøøøå  ]°SÑ%8Ñ9Ô9ˆMð+ �iŠi‰kŒkÐ!ð0 	×Ò 1ÐÑ%Ô%Ð%Ø×Ò 1ÐÑ%Ô%Ð%à—h’h˜}Ñ-Ô-×4Ò4°WÀYÐ4ÑOÔOˆå'>Ø�HŠHÐ'Ñ(Ô(Ø�HŠHÐ'Ñ(Ô(Ø*¨1Ô-ð(
ñ (
ô (
Ñ$ˆ�_ð (,¤Ð'B�D”O�OÈˆ	Ý�œÑ)Ô)¨JÑ6¸Ñ:Ô:ˆð 	�ŠÑÔÐØ×ÒÑÔÐØˆØ�Š ˆÑ"Ô"Ð"ð 	0Ð/Ð/Ð/Ð/Ð/Ø �j Ñ-Ô-ˆØ �j Ñ-Ô-ˆð 	7Ð6Ð6Ð6Ð6Ð6Ø+Ð+¨KÀ4ÐHÑHÔHˆØ+Ð+¨KÀ4ÐHÑHÔHˆð Ø!Ø"Ø0°Ô3Ø (ð"
ð "
ˆð 	�Š�oÑ&Ô&Ð&à�YÒÐØN°GÐNÐNÐNˆKØ)ˆF�7‰Oð
 ð 8Ø#.Ð1I¸KÐ1IÐ1IÑ#I��xÑ Ð à#7¨+Ð#7Ð#7��xÑ Ý�NŠNØQØ˜'Ð#4°QÔ#7ñô ð ð ð �}Ò$Ð$Ø*Ð-dÑdˆF�8ÑÐØ˜!Š^ˆ^Ø&ˆF�8ÑØ)ÐSÐ-SÈ	Ð-SÐ-SˆF�7‰Oàð TØ#.Ð1EÑ#EÈÑ#S��xÑ õ )¨ÀMÐRÑRÔRˆDØð &Ø!%��v‘åŒz˜&¨uÐ5Ñ5Ô5ð* Ð"ðAØ×!Ò!Ñ#Ô#Ð#Ð#øÝð Að Að AÝ—’Ð<¸aÑ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@øøøøðAøøøàˆˆˆØ�Š�f¨DˆÑ1Ô1Ð1ð	ð ð %Ý”	˜)Ñ$Ô$Ð$Ð$ð%øåð 	ð 	ð 	ØˆDð	øøøøõ? ð ñ ð Ý�œÑ)Ô)¨JÑ6¸Ñ:Ô:ˆÝ�ŠØFØØ˜aÔ Ý�‰IŒIÔØØð 	ñ 	
ô 	
ð 	
õ ŒzØÝ˜‘X”XØ0°Ô3Ø (ð	
ð 
ð
 ðñ ô ð 	ð 	ð 	ð 	ð 	ð Ð"ðAØ×!Ò!Ñ#Ô#Ð#Ð#øÝð Að Að AÝ—’Ð<¸aÑ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@øøøøðAøøøàˆˆˆØ�Š�f¨DˆÑ1Ô1Ð1ð	ð ð %Ý”	˜)Ñ$Ô$Ð$Ð$ð%øåð 	ð 	ð 	ØˆDð	øøøøøøøð?øøøøð& Ð"ðAØ×!Ò!Ñ#Ô#Ð#Ð#øÝð Að Að AÝ—’Ð<¸aÑ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@øøøøðAøøøàˆˆˆØ�Š�f¨DˆÑ1Ô1Ð1ð	ð ð %Ý”	˜)Ñ$Ô$Ð$Ð$ð%øåð 	ð 	ð 	ØˆDð	øøøøøøs‹  È0Aj  É<JÊj  ÊJ"Ê"j  Ê%J"Ê&3j  ËK;Ë/j  Ë;K?Ë?j  ÌK?ÌOj  Û[ Ûj  Û[*Û'j  Û)[*Û*A$j  Ý] Ýj  Ý
])Ý&j  Ý(])Ý)j  Ý-5^# Þ"j  Þ#^5Þ2j  Þ4^5Þ5H=j  ç5h
è

h9èh4è4h9éi0é0
i=é<i=ê n,êB	n'ìn,ìn/ ìl1ì1
m ì;mím í?nî
n$î#n$î'n,î,n/ î/p>î3oïp>ï
o7ïo2ï-p>ï2o7ï7p>ðp.ð,p>ð.
p;ð8p>ð:p;ð;p>Fr  c                 óÒ  — ddl }	 |                     | j        ¦  «        }|                     d¬¦  «        }|D ]'}	 |                     ¦   «          Œ# |j        $ r Y Œ$w xY w	 |                     ¦   «          n# |j        $ r Y nw xY wn�# |j        $ r Y n„t          t          f$ rq}t           	                    d|d¬¦  «         	 |  
                    ¦   «          n4# t          $ r'}t           	                    d|d¬¦  «         Y d}~nd}~ww xY wY d}~nd}~ww xY w|�rM	 |                      d¬	¦  «         dS # t          j        $ �r! 	 |                     | j        ¦  «        }|                     d¬¦  «        D ]'}	 | 
                    ¦   «          Œ# |j        $ r Y Œ$w xY w	 | 
                    ¦   «          n# |j        $ r Y nw xY wY dS Y dS # |j        $ r Y Y dS t          t          f$ rz}t           	                    d
|d¬¦  «         	 |  
                    ¦   «          n4# t          $ r'}t           	                    d|d¬¦  «         Y d}~nd}~ww xY wY d}~Y dS Y d}~Y dS d}~ww xY ww xY wdS )zGKill the child and its entire process tree (cross-platform via psutil).r   NT)Ú	recursivez$Could not terminate process tree: %sr¥   zCould not kill process: %srx  r•  zCould not kill process tree: %s)ÚpsutilÚProcessÚpidÚchildrenÚ	terminateÚNoSuchProcessÚPermissionErrorrù   r”   r•   Úkillr‹   r|  r'  r0  )rG  r  rV  ÚparentrY  Úchildr  Úe2s           r.   r/  r/  ·  sq  € à€M€M€MðJØ—’ ¤Ñ)Ô)ˆØ—?’?¨T�?Ñ2Ô2ˆØð 	ð 	ˆEðØ—’Ñ!Ô!Ð!Ð!øØÔ'ð ð ð Ø�ðøøøð	Ø×ÒÑÔÐÐøØÔ#ð 	ð 	ð 	ØˆDð	øøøøøàÔð ð ð ØˆÝ�WÐ%ð Jð Jð JÝ�ŠÐ;¸QÈˆÑNÔNÐNð	JØ�IŠI‰KŒKˆKˆKøÝð 	Jð 	Jð 	JÝ�LŠLÐ5°rÀDˆLÑIÔIÐIÐIÐIÐIÐIÐIøøøøð	Jøøøøøøøøøøøøð	Jøøøð ñ Rð	RØ�IŠI˜aˆIÑ Ô Ð Ð Ð øÝÔ(ð 	Rñ 	Rð 	RðRØŸš¨¬Ñ1Ô1�Ø#Ÿ_š_°t˜_Ñ<Ô<ð ð �EðØŸ
š
™œ˜˜øØ!Ô/ð ð ð Ø˜ðøøøðØ—K’K‘M”M�M�MøØÔ+ð ð ð Ø�Dðøøøð "�M�Mà�D�DøØÔ'ð ð ð Ø���Ý#¥WÐ-ð Rð Rð RÝ—’Ð>ÀÈD�ÑQÔQÐQðRØ—I’I‘K”K�K�KøÝ ð Rð Rð RÝ—L’LÐ!=¸rÈD�LÑQÔQÐQÐQÐQÐQÐQÐQøøøøðRøøøð  �K�K�K�K�K�KàQÐQÐQÐQÐQÐQÐQøøøøðRøøøð	Røøøð	Rð RsB  †4B »AÁB Á
AÁB ÁAÁB Á!A6 Á5B Á6
BÂ B ÂBÂB Â
DÂDÂ#DÃCÃDÃ
DÃ DÃ=DÄDÄDÄDÄD3 Ä3I$Å2GÅ7FÆGÆ
FÆGÆFÆGÆF2Æ1GÆ2
F?Æ<GÆ>F?Æ?GÇ
I ÇI$ÇI Ç&IÈHÈIÈ
I
È#IÉ IÉI
É
IÉI$ÉI$ÉI É I$c                  ó¢   — 	 ddl m}   | ¦   «                              di ¦  «        }t          |t          ¦  «        r|ni S # t
          $ r i cY S w xY w)a  Load code_execution config without importing the interactive CLI.

    This helper is called while building the module-level execute_code schema
    during tool discovery.  Importing ``cli`` here pulls prompt_toolkit/Rich and
    a large chunk of the classic REPL onto every agent startup path, including
    ``hermes --tui`` where it is never used.  Read the lightweight raw config
    instead; the config layer already caches by (mtime, size), and an absent
    key cleanly falls back to DEFAULT_EXECUTION_MODE.
    r   )Úread_raw_configÚcode_execution)Úhermes_cli.configrb  r«   r  r	  r‹   )rb  Úcfgs     r.   r±  r±  é  st   € ðØ5Ð5Ð5Ð5Ð5Ð5àˆoÑÔ×#Ò#Ð$4°bÑ9Ô9ˆÝ  ¥dÑ+Ô+Ð3ˆsˆs°Ð3øÝð ð ð Øˆ	ˆ	ˆ	ðøøøs   ‚<? ¿AÁA)ÚprojectÚstrictrf  c                  ó$  — t          t          ¦   «                              dt          ¦  «        ¦  «                             ¦   «                              ¦   «         } | t          v r| S t                               d| t          t          ¦  «         t          S )u  Return the active execute_code mode â€” 'project' or 'strict'.

    Reads ``code_execution.mode`` from config.yaml; invalid values fall back
    to ``DEFAULT_EXECUTION_MODE`` ('project') with a log warning.

    Mode semantics:
      - ``project`` (default): scripts run in the session's working directory
        with the active virtual environment's python, so project dependencies
        (pandas, torch, project packages) and files resolve naturally.
      - ``strict``: scripts run in an isolated temp directory with
        ``sys.executable`` (hermes-agent's python). Reproducible and the
        interpreter is guaranteed to work, but project deps and relative paths
        won't resolve.

    Env scrubbing and tool whitelist apply identically in both modes.
    ÚmodezHIgnoring code_execution.mode=%r (expected one of %s), falling back to %r)	r  r±  r«   ÚDEFAULT_EXECUTION_MODErü   ÚlowerÚEXECUTION_MODESr”   r$   )Ú	cfg_values    r.   r$  r$    sx   € õ" •L‘N”N×&Ò& vÕ/EÑFÔFÑGÔG×MÒMÑOÔO×UÒUÑWÔW€IØ•OÐ#Ð#ØÐÝ
‡N‚NØRØ•?Õ$:ñô ð õ "Ð!r   r–  )ÚmaxsizeÚpython_pathc           	      óú   — 	 ddl m} t          j        | ddgddt          rt          j        ndt          j         |¦   «         ¬¦  «        }|j        dk    S # t          t          j	        t          j
        f$ r Y dS w xY w)	zßCheck whether a candidate Python interpreter is usable for execute_code.

    Requires Python 3.8+ (f-strings and stdlib modules the RPC stubs need).
    Cached so we don't fork a subprocess on every execute_code call.
    r   )Údelegated_child_subprocess_envz-cz<import sys; sys.exit(0 if sys.version_info >= (3, 8) else 1)rx  T)r÷   Úcapture_outputrñ  rï  rR  F)r˜   rq  r'  ÚrunrŒ   r+  r*  r›  rù   r0  ÚSubprocessError)ro  rq  r  s      r.   Ú_is_usable_pythonru  !  s¤   € ðØKÐKÐKÐKÐKÐKå”Ø˜$ØKðMàØÝ9DÐK�*Ô5Ð5È!ÝÔ$Ø.Ð.Ñ0Ô0ð
ñ 
ô 
ˆð Ô  AÒ%Ð%øÝ•ZÔ.µ
Ô0JÐKð ð ð Øˆuˆuðøøøs   ‚AA Á!A:Á9A:ri  c                 ó.  — | dk    rt           j        S t          rd}d}nd}d}dD ]å}t          j                             |d¦  «                             ¦   «         }|sŒ7|D ]«}|D ]¦}t          j                             |||¦  «        }t          j         	                    |¦  «        rt          j
        |t          j        ¦  «        sŒbt          |¦  «        r|c c c S t                               d||¦  «         t           j        c c c S Œ¬Œæt           j        S )	uÕ  Pick the Python interpreter for the execute_code subprocess.

    In ``strict`` mode, always ``sys.executable`` â€” guaranteed to work and
    keeps behavior fully reproducible across sessions.

    In ``project`` mode, prefer the user's active virtualenv/conda env's
    python so ``import pandas`` etc. work. Falls back to ``sys.executable``
    if no venv is detected, the candidate binary is missing/not executable,
    or it fails a Python 3.8+ version check.
    rf  )z
python.exezpython3.exe)ÚScripts)ÚpythonÚpython3)Úbin)rF   ÚCONDA_PREFIXrå   z\execute_code: skipping %s=%s (Python version < 3.8 or broken). Using sys.executable instead.)r  Ú
executablerŒ   r¾  r  r«   rü   r  r–   ÚisfileÚaccessÚX_OKru  r”   rN  )ri  Ú	exe_namesÚsubdirsÚvarÚrootÚsubdirÚexern  s           r.   r%  r%  9  sM  € ð ˆyÒÐÝŒ~Ðåð Ø1ˆ	Øˆˆà)ˆ	Øˆà.ð &ð &ˆÝŒz�~Š~˜c 2Ñ&Ô&×,Ò,Ñ.Ô.ˆØð 	ØØð 	&ð 	&ˆFØ ð &ð &�ÝœGŸLšL¨¨v°sÑ;Ô;�	ÝœŸš yÑ1Ô1ð µb´iÀ	Í2Ì7Ñ6SÔ6Sð ØÝ$ YÑ/Ô/ð %Ø$Ð$Ð$Ð$Ð$Ð$Ð$Ð$õ —’ð4Ø58¸)ñô ð õ ”~Ð%Ð%Ð%Ð%Ð%Ð%Ð%ð&ð	&õ Œ>Ðr   rå   Ústaging_dirc                 óŠ  — | dk    r|S |r�	 ddl m}  ||¦  «        }n# t          $ r d}Y nw xY w|r!t          j                             |¦  «        r|S 	 ddlm}  ||¦  «        }n# t          $ r d}Y nw xY w|r!t          j                             |¦  «        r|S t          j         	                    dd¦  «         
                    ¦   «         }|r@t          j                             |¦  «        }t          j                             |¦  «        r|S t          j        ¦   «         }	t          j                             |	¦  «        r|	S |S )u/  Resolve the working directory for the execute_code subprocess.

    - ``strict``: the staging tmpdir (today's behavior).
    - ``project``: the session's own cwd â€” its per-session cwd record
      (written after every completed terminal command), then the raw
      per-session cwd override registered via ``session.cwd.set`` /
      ``register_task_env_overrides``, then the session's TERMINAL_CWD
      (same as the terminal tool), or ``os.getcwd()`` if none points at a
      real dir. Falls back to the staging tmpdir as a last resort so we
      never invoke Popen with a nonexistent cwd.

    This mirrors the resolution ladder file tools and the terminal use
    (record â†’ registered override â†’ TERMINAL_CWD), so all file-writing
    paths within a session agree on the working directory. (#56047)
    rf  r   )Úget_session_cwdN)Ú_registered_task_cwd_overrideÚTERMINAL_CWDrå   )rª   rˆ  r‹   r¾  r  ÚisdirÚtools.file_toolsr‰  r  r«   rü   Ú
expanduserÚgetcwd)
ri  r†  rÙ   rˆ  Úrecordedr‰  Úsession_cwdÚrawÚexpandedÚheres
             r.   r&  r&  d  s€  € ð  ˆyÒÐØÐØð ð	Ø;Ð;Ð;Ð;Ð;Ð;à&� wÑ/Ô/ˆHˆHøÝð 	ð 	ð 	ØˆHˆHˆHð	øøøàð 	�œŸš hÑ/Ô/ð 	ØˆOð	ØFÐFÐFÐFÐFÐFà7Ð7¸Ñ@Ô@ˆKˆKøÝð 	ð 	ð 	ØˆKˆKˆKð	øøøàð 	�2œ7Ÿ=š=¨Ñ5Ô5ð 	ØÐÝ
Œ*�.Š.˜¨Ñ
,Ô
,×
2Ò
2Ñ
4Ô
4€CØ
ð Ý”7×%Ò% cÑ*Ô*ˆÝŒ7�=Š=˜Ñ"Ô"ð 	ØˆOÝŒ9‰;Œ;€DÝ	„w‡}‚}�TÑÔð ØˆØÐs   Œ ž-¬-ÁA& Á&A5Á4A5))r   zv  web_search(query: str, limit: int = 5) -> dict
    Returns {"data": {"web": [{"url", "title", "description"}, ...]}})r   a.    web_extract(urls: list[str], char_limit: int = None) -> dict
    Returns {"results": [{"url", "title", "content", "error"}, ...]} where content is markdown.
    No LLM summarization. Pages over char_limit (default 15000) are head+tail truncated; full text stored on disk (path in the content footer).)r   zˆ  read_file(path: str, offset: int = 1, limit: int = 2000) -> dict
    Lines are 1-indexed. Returns {"content": "...", "total_lines": N})r   zT  write_file(path: str, content: str) -> dict
    Always overwrites the entire file.)r   zÂ  search_files(pattern: str, target="content", path=".", file_glob=None, limit=50) -> dict
    target: "content" (search inside files) or "files" (find files by name). Returns {"matches": [...]})r   zŒ  patch(path: str, old_string: str, new_string: str, replace_all: bool = False) -> dict
    Replaces old_string with new_string in the file.)r   z�  terminal(command: str, timeout=None, workdir=None) -> dict
    Foreground only (no background/pty). Returns {"output": "...", "exit_code": N}Úenabled_sandbox_toolsc                 óZ  ‡ — ‰ €t           Š |€t          ¦   «         }d                     ˆ fd„t          D ¦   «         ¦  «        }ˆ fd„dD ¦   «         }|st	          ‰ ¦  «        dd…         }|rd                     |¦  «        dz   }nd	}|d
k    rd}nd}d|› d|› d�}d|dddd|› d�dœidgdœdœS )u}  Build the execute_code schema with description listing only enabled tools.

    When tools are disabled via ``hermes tools`` (e.g. web is turned off),
    the schema description should NOT mention web_search / web_extract â€”
    otherwise the model thinks they are available and keeps trying to use them.

    ``mode`` controls the working-directory sentence in the description:
      - ``'strict'``: scripts run in a temp dir (not the session's CWD)
      - ``'project'`` (default): scripts run in the session's CWD with the
        active venv's python
    If ``mode`` is None, the current ``code_execution.mode`` config is read.
    NrÆ   c              3   ó*   •K  — | ]\  }}|‰v ¯	|V — Œd S rw   rs   )r   ÚnamerÐ   r”  s      €r.   r‚   z,build_execute_code_schema.<locals>.<genexpr>È  s;   øè è € ð ð Ù��c°Ð8MÐ0MÐ0MˆÐ0MÐ0MÐ0MÐ0Mðð r   c                 ó   •— g | ]}|‰v ¯|‘Œ	S rs   rs   )r   Únr”  s     €r.   rw  z-build_execute_code_schema.<locals>.<listcomp>Í  s$   ø€ Ð[Ð[Ð[˜QÀÐEZÐ@ZÐ@Z�qÐ@ZÐ@ZÐ@Zr   )r   r   rî   r‡   z, ...z...rg  u    Scripts run in their own temp dir, not the session's CWD â€” use absolute paths (os.path.expanduser('~/.hermes/.env')) or terminal()/read_file() for user files.z˜Scripts run in the session's working directory with the active venv's python, so project deps (pandas, etc.) and relative paths work like in terminal().aš  Run a Python script that calls Hermes tools programmatically. Use when you need 3+ tool calls with logic between them: filtering/reducing large outputs before they enter context, conditional branching, or loops (N pages/files, retry on failure). Use normal tool calls for single calls, results you must reason over in full, or anything needing user interaction.

Available via `from hermes_tools import ...`:

z‚

Limits: 5-minute timeout, 50KB stdout cap, max 50 tool calls per script. terminal() is foreground-only (no background or pty).

uP  

Print your final result to stdout; stdlib (json, re, csv, datetime, ...) is available for processing.

Built-in helpers (no import): json_parse(text) â€” tolerant json.loads for terminal() output; shell_quote(s) â€” shlex.quote for dynamic shell args; retry(fn, max_attempts=3, delay=2) â€” exponential backoff for transient failures.rS  Úobjectr‹  ÚstringzDPython code to execute. Import tools with `from hermes_tools import z(` and print your final result to stdout.)rÀ  Údescription)rÀ  Ú
propertiesÚrequired)r—  rœ  Ú
parameters)r¸   r$  r–   Ú_TOOL_DOC_LINESr—   )r”  ri  Ú
tool_linesÚimport_examplesÚ
import_strÚcwd_noterœ  s   `      r.   Úbuild_execute_code_schemar¥  ´  sp  ø€ ð Ð$Ý 5ÐØ€|Ý"Ñ$Ô$ˆð —’ð ð ð ð Ý,ðñ ô ñ ô €Jð
 \Ð[Ð[Ð[Ð"<Ð[Ñ[Ô[€OØð <Ý Ð!6Ñ7Ô7¸¸¸Ô;ˆØð Ø—Y’Y˜Ñ/Ô/°'Ñ9ˆ
ˆ
àˆ
ð
 ˆxÒÐð_ð 	ˆðYð 	ð	]ð ð	]ð 	]ð ð	]ð 	]ð 	]ð ð( Ø"ààØ$ðAØ5?ðAð Að Aðð ð	ð  ˜ð
ð 
ðð ð r   )Úregistryr  rS  rc  c                 óš   — t          |                      dd¦  «        |                     d¦  «        |                     d¦  «        ¬¦  «        S )Nr‹  rå   rÙ   rº   )r‹  rÙ   rº   )rS  r«   )rç   Úkws     r.   ru   ru     sD   € �|Ø�XŠX�f˜bÑ!Ô!Ø—’�yÑ!Ô!Ø—f’f˜_Ñ-Ô-ð /ñ  /ô  /€ r   u   ðŸ��i † )r—  ÚtoolsetÚschemaÚhandlerÚcheck_fnÚemojiÚmax_result_size_chars)r   )NNrw   )rÁ   )F)rå   )UÚ__doc__r]  Ú	functoolsrÿ   Úloggingr¾  r  rµ   r  r_  rö   r'  r  rk  rL  rý   rµ  ÚsystemrŒ   Útypingr   r   r   r   r   Útools.thread_contextr	   Úagent.thread_scoped_outputr
   Ú	getLoggerrÁ  r”   r©   r´  r¸   r²  r³  r3   r,  Úbytesr4   r  r/   r8   r�   r�   r‘   r’   r¡   Úboolr­   rÇ   rÀ   rÓ   Ú_COMMON_HELPERSrÉ   rÈ   r
  r»  r¸  r  rS  rd  ro  rŠ  rÔ  rS  r/  r	  r±  rl  rj  r$  Ú	lru_cacheru  r%  r&  r   r¹   r¥  ÚEXECUTE_CODE_SCHEMAÚtools.registryr¦  r  Úregisterrs   r   r.   ú<module>r¾     s.  ððð ð: €€€Ø Ð Ð Ð Ø €€€Ø €€€Ø 	€	€	€	Ø €€€Ø 	€	€	€	Ø €€€Ø €€€Ø €€€Ø Ð Ð Ð Ø 
€
€
€
Ø €€€Ø Ð Ð Ð Ø €€€Ø €€€àˆhŒoÑÔ 9Ò,€Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3à <Ð <Ð <Ð <Ð <Ð <Ø <Ð <Ð <Ð <Ð <Ð <ð 
ˆÔ	˜8Ñ	$Ô	$€àÐ ð "˜	ð #ð #ð #ñ ô Ð ð €ØÐ ØÐ ØÐ ð
 ð'!ð "&ð	'!ð '!ð '!Ø
ð'!à
ð'!ð ˜#”ð	'!ð
 ˆ3��S˜#�X”ÐÔð'!ð '!ð '!ð '!ðT sð ¨u°S¸$¸sÀC¸x¼.Ð5HÔ/Ið ð ð ð ð6DÐ ð
3Ð ð  "˜	ð #ð #ð #ñ ô Ð ð (˜ið )ð )ð )ñ ô Ð ð4[ð [ð [ð [ð| Dð ð ð ð ð:ðððððððK+ð +€ð\4ð 4 sð 4À8ÈCÄ=ð 4ð 4ð 4ð 4ðp 38ð .ð  .°°S´	ð  .Ø,/ð .Ø<?ð .ð  .ð  .ð  .ðJ'€ðV
ð ñ
ð6ñ@Ð ðH
ð ñ
ð4ñ>Ð ðL YÐXÐXÐ ð}<Ø”ð}<àð}<ð ð}<ð ð	}<ð
 ð}<ð ð}<ð ”ð}<ð ð}<ð }<ð }<ð }<ðHe ð eð eð eð eðP¨3ð ¸ð Àð ð ð ð ð"�sð ˜sð ð ð ð ð K+àðK+ð ðK+ð ð	K+ð
 ðK+ð ðK+ð ðK+ð ”ðK+ð ðK+ð K+ð K+ð K+ð\y2Ø
ðy2à�cŒ]ðy2ð ˜D œIÔ&ðy2ð 	ð	y2ð y2ð y2ð y2ðD "Ø)-ðLð LØ
ðLà�cŒ]ðLð ˜D œIÔ&ðLð 	ð	Lð Lð Lð Lð^/Rð /R¨ð /Rð /Rð /Rð /Rðd�dð ð ð ð ð2 (€Ø"Ð ð"˜Sð "ð "ð "ð "ð6 €Ô˜RÐ Ñ Ô ð 3ð ¨4ð ð ð ñ !Ô ðð.( ð (¨ð (ð (ð (ð (ðV-ð -˜Sð -¨sð -¸Sð -È#ð -ð -ð -ð -ðlð ð €ð4 <@Ø*.ðSð S°Sð SØ$'ðSØ37ðSð Sð Sð Sðp 0Ð/Ñ1Ô1Ð ð 0Ð /Ð /Ð /Ð /Ð /Ð /Ð /à €Ô Ø	ØØð/ð /ð (Ø
Ø!ðñ ô ð ð ð r   