§
    øžyj ã                   ó:  — 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  ej        ¦   «         dk    ZddlmZmZmZ ddlmZ ddlmZmZ ddlmZmZmZmZ dd	lmZ dd
l m!Z!  ej"        e#¦  «        Z$ e¦   «         dz  Z%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.da/ee0         e1d<    e	j2        ¦   «         Z3da4dZ5dZ6dZ7dZ8de9fd„Z:de0fd„Z;de0fd„Z<dee=         de=dee=         fd „Z>d!e=de0fd"„Z?d#e9de=fd$„Z@e G d%„ d&¦  «        ¦   «         ZA G d'„ d(¦  «        ZB eB¦   «         ZCd#eDde=fd)„ZEd*eFde=fd+„ZGd*eFdd,fd-„ZHdd.lImJZJmKZK d/d0d1d2g d3¢d4d5œd2d6d7œd2d8d7œd9d:d;d<œd9d=d7œd9d>d;d<œd?œd@gdAœdBœZLdCeFdeFfdD„ZMdE„ ZN eJjO        d/dFeLeNdG¬H¦  «         dS )Iaø  
Process Registry -- In-memory registry for managed background processes.

Tracks processes spawned via terminal(background=true), providing:
  - Output buffering (rolling 200KB window)
  - Status polling and log retrieval
  - Blocking wait with interrupt support
  - Process killing
  - Crash recovery via JSON checkpoint file
  - Session-scoped tracking for gateway reset protection

Background processes execute THROUGH the environment interface -- nothing
runs on the host machine unless TERMINAL_ENV=local. For Docker, Singularity,
Modal, Daytona, and SSH backends, the command runs inside the sandbox.

Usage:
    from tools.process_registry import process_registry

    # Spawn a background process (called from terminal_tool)
    session = process_registry.spawn(env, "pytest -v", task_id="task_123")

    # Poll for status
    result = process_registry.poll(session.id)

    # Block until done
    result = process_registry.wait(session.id, timeout=300)

    # Kill it
    process_registry.kill(session.id)
é    N)ÚPathÚWindows)Ú_find_shellÚ_resolve_safe_cwdÚ_sanitize_subprocess_env)Úwindows_hide_flags)Ú	dataclassÚfield)ÚAnyÚDictÚListÚOptional)Úget_hermes_home)Úredact_sensitive_textzprocesses.jsoni@ i  é@   i€Q é   é   é
   é   Ú_SYSTEMD_SCOPE_AVAILABLEç        g      N@i   i   @l        Úreturnc                  óÜ  — d} t          j        dd¦  «                             ¦   «         }|r^d}	 t          |¦  «        dz  dz  }|t          k    r|} d}n# t
          $ r Y nw xY w|s$t                               d|t          dz  ¦  «         g }	 t          d	¦  «         	                    d
¬¦  «         
                    ¦   «         D ]Å}|                     d¦  «        r®|                     d¦  «        d                              d¦  «        }t          d¦  «        |z  dz   	                    d
¬¦  «                             ¦   «         }|                     ¦   «         r/t          |¦  «        }|t          k    r|                     |¦  «          nŒÆn# t           t
          f$ r Y nw xY w	 t          t          j        d¦  «        ¦  «        t          t          j        d¦  «        ¦  «        z  }	t%          t&          t)          t          |	dz  ¦  «        ¦  «        }
|                     |
¦  «         n# t           t
          t*          f$ r Y nw xY w|rt%          |¦  «        nt,          }| rt%          | |¦  «        n|S )aU  Return a finite per-worker cgroup limit without widening host risk.

    The proposed local-memory-guard environment override is honored when it
    tightens the safe bound, so this isolation composes with PR #57121 instead
    of inventing a second knob.  An oversized override cannot widen host risk.
    Otherwise retain the tighter of the gateway's current cgroup-v2
    ``memory.max`` and half of physical RAM, capped at 4 GiB.  This keeps the
    sibling worker outside the gateway cgroup while ensuring the worker cannot
    consume memory up to the enclosing user slice or host limit.
    NÚTERMINAL_LOCAL_MEMORY_MAX_MBÚ Fi   TzbIgnoring invalid TERMINAL_LOCAL_MEMORY_MAX_MB=%r; expected an integer representing at least %d MiBi   z/proc/self/cgroupúutf-8©Úencodingz0::z::é   ú/z/sys/fs/cgroupz
memory.maxÚSC_PHYS_PAGESÚSC_PAGE_SIZE)ÚosÚgetenvÚstripÚintÚ_MIN_WORKER_MEMORY_MAX_BYTESÚ
ValueErrorÚloggerÚwarningr   Ú	read_textÚ
splitlinesÚ
startswithÚ	partitionÚlstripÚisdigitÚappendÚOSErrorÚsysconfÚminÚ_WORKER_MEMORY_MAX_CAP_BYTESÚmaxÚ	TypeErrorÚ _DEFAULT_WORKER_MEMORY_MAX_BYTES)Úoverride_boundÚoverrideÚoverride_validÚparsedÚ
candidatesÚlineÚrelativeÚ	raw_limitÚcgroup_limitÚphysical_bytesÚphysical_boundÚ
safe_bounds               ú</home/ragecks/.hermes/hermes-agent/tools/process_registry.pyÚ_worker_memory_max_bytesrF   l   s¤  € ð %)€NÝŒyÐ7¸Ñ<Ô<×BÒBÑDÔD€HØð Øˆð	Ý˜‘]”] TÑ)¨DÑ0ˆFØÕ5Ò5Ð5Ø!'�Ø!%�øøÝð 	ð 	ð 	ØˆDð	øøøàð 	Ý�NŠNðCàÝ,°Ñ=ñ	ô ð ð €JðÝÐ,Ñ-Ô-×7Ò7ÀÐ7ÑIÔI×TÒTÑVÔVð 
	ð 
	ˆDØ�Š˜uÑ%Ô%ð 	ØŸ>š>¨$Ñ/Ô/°Ô2×9Ò9¸#Ñ>Ô>�åÐ)Ñ*Ô*¨XÑ5¸ÑDß’) W�)Ñ-Ô-¯eªe©g¬gð ð ×$Ò$Ñ&Ô&ð 8Ý#& y¡>¤>�LØ#Õ'CÒCÐCØ"×)Ò)¨,Ñ7Ô7Ð7Ø�ð	øøõ •ZÐ ð ð ð Øˆðøøøð
Ý�RœZ¨Ñ8Ô8Ñ9Ô9½CÝŒJ�~Ñ&Ô&ñ=
ô =
ñ 
ˆõ Ý(ÝÕ,¨nÀÑ.AÑBÔBñ
ô 
ˆð 	×Ò˜.Ñ)Ô)Ð)Ð)øÝ•Z¥Ð+ð ð ð Øˆðøøøð %/ÐT•�Z‘”�Õ4T€JØ.<ÐL�3ˆ~˜zÑ*Ô*Ð*À*ÐLs7   ¯$A Á
A!Á A!ÂC;F	 Æ	FÆFÆ!BH% È%H?È>H?c                  óÆ  — t           } t          j        ¦   «         }| du rdS | du r|t          z
  t          k     rdS t
          5  t           } t          j        ¦   «         }| du r	 ddd¦  «         dS | du r!|t          z
  t          k     r	 ddd¦  «         dS d}t          �s	 ddl}|                     d¦  «        }|rÇdt          j
        ¦   «         › dt          j        ¦   «         j        dd…         › �}t          j        |d	d
dd|dddddt!          ¦   «         › �ddddgdd¬¦  «        }|j        dk    }|sNt$                               d|j        |j        pd                     dd¦  «                             ¦   «         ¦  «         n2# t.          $ r%}t$                               d|¦  «         Y d}~nd}~ww xY w|a t          j        ¦   «         a|cddd¦  «         S # 1 swxY w Y   dS )uú  Return True if ``systemd-run --user --scope`` can create a cgroup.

    Cached after the first probe.  ``shutil.which`` alone is insufficient:
    in system-service deployments (and containers) the user D-Bus session
    bus that ``systemd-run --user`` needs may be absent even though the
    binary is on PATH, causing every spawn to fail with
    ``Failed to connect to user bus``.  We do a cheap no-op probe
    (``systemd-run --user --scope --unit=â€¦ -- /bin/true``) and remember the
    outcome.
    TFNr   úsystemd-runzhermes-probe-scope-Ú-é   ú--userú--scopeú--quietú--unitú	--collectú
--propertyúMemoryAccounting=yesú
MemoryMax=úOOMPolicy=killú--z	/bin/truer   ©Úcapture_outputÚtimeoutz3systemd-run --user --scope probe failed (rc=%s): %só    r   Úreplacez*systemd-run --user --scope probe error: %s)r   ÚtimeÚ	monotonicÚ_SYSTEMD_SCOPE_PROBED_ATÚ"_SYSTEMD_SCOPE_FAILURE_TTL_SECONDSÚ_SYSTEMD_SCOPE_PROBE_LOCKÚ_IS_WINDOWSÚshutilÚwhichr#   ÚgetpidÚuuidÚuuid4ÚhexÚ
subprocessÚrunrF   Ú
returncoder)   ÚdebugÚstderrÚdecoder%   Ú	Exception)ÚcachedÚnowÚ	availabler`   ÚbinaryÚ
probe_unitÚresultÚexcs           rE   Ú!_systemd_run_user_scope_availablert   ª   sÌ  € õ &€FÝ
Œ.Ñ
Ô
€CØ�€~€~Øˆtà�%ˆˆØÕ*Ñ*Õ-OÒOÐOàˆuõ
 
#ð 2ð 2Ý)ˆÝŒnÑÔˆØ�Tˆ>ˆ>Øð	2ð 2ð 2ñ 2ô 2ð 2ð 2ð 2ð �eˆOˆOØÕ.Ñ.Ý0ò1ð 1ð ð2ð 2ð 2ñ 2ô 2ð 2ð 2ð 2ð ˆ	Ýñ !	Pð PØ���àŸš mÑ4Ô4�Øð ð "\µr´y±{´{Ð![Ð![ÅTÄZÁ\Ä\ÔEUÐVXÐWXÐVXÔEYÐ![Ð![�JÝ'œ^à" H¨i¸Ø$ jØ'Ø(Ð*@Ø(Ð*SÕ7OÑ7QÔ7QÐ*SÐ*SØ(Ð*:Ø Ø'ð	ð (,Ø !ðñ ô �Fð !'Ô 1°QÒ 6�IØ$ð ÝŸšØQØ"Ô-Ø#œ]Ð1¨c×9Ò9Ø '¨ñô ç#še™gœgñô ð øøõ ð Pð Pð PÝ—’ÐIÈ3ÑOÔOÐOÐOÐOÐOÐOÐOøøøøðPøøøð $-Ð Ý#'¤>Ñ#3Ô#3Ð Øðe2ð 2ð 2ð 2ñ 2ô 2ð 2ð 2ð 2ð 2ð 2ð 2øøøð 2ð 2ð 2ð 2ð 2ð 2sI   Á GÁ.GÂ
GÂC"FÆ GÆ
F0ÆF+Æ&GÆ+F0Æ0GÇGÇGc                  ó"  — t           j                             d¦  «        dk    rdS 	 ddlm}  ddlm}  | ¦   «         o  |d¬¦  «        t          j        ¦   «         k    S # t          $ r&}t           
                    d|¦  «         Y d	}~dS d	}~ww xY w)
aÈ  Return whether this process is in a supervised Hermes gateway runtime.

    Both supervisor markers and ``_HERMES_GATEWAY`` are inherited by every
    descendant, and importing ``gateway.run`` also sets the latter. Require
    this process to own the live gateway PID file as well. That keeps transient
    systemd scopes limited to the gateway itself instead of terminal children
    or unrelated interactive CLIs in the same supervised process tree.
    Ú_HERMES_GATEWAYÚ1Fr   )Úis_gateway_supervisor_process)Úget_running_pid)Úcleanup_stalez8Could not verify supervised gateway process identity: %sN)r#   ÚenvironÚgetÚgateway.restartrx   Úgateway.statusry   rb   rl   r)   ri   )rx   ry   rs   s      rE   Ú_is_supervised_gateway_processr   ø   sÄ   € õ 
„z‡~‚~Ð'Ñ(Ô(¨CÒ/Ð/Øˆuð
ØAÐAÐAÐAÐAÐAØ2Ð2Ð2Ð2Ð2Ð2ð *Ð)Ñ+Ô+ð DØ�¨eÐ4Ñ4Ô4½¼	¹¼ÒCð	
øõ ð ð ð Ý�ŠÐOÐQTÑUÔUÐUØˆuˆuˆuˆuˆuøøøøðøøøs   §6A Á
BÁ(B	Â	BÚ
shell_argvÚunit_suffixc                 óŒ   — ddl }|                     d¦  «        }|€| S d|› �}t          ¦   «         }|dddd|d	d
dd
d|› �d
ddg| ¢S )ad  Wrap *shell_argv* in a ``systemd-run --user --scope`` invocation.

    The resulting cgroup gets its own memory accounting so an OOM in the
    worker does not kill the gateway cgroup (#70716).  ``--collect`` makes
    the transient scope self-clean after exit; ``--unit`` gives it a
    recognisable name for ``systemctl --user status`` / journalctl.
    r   NrH   úhermes-worker-rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   )r`   ra   rF   )r€   r�   r`   rp   Ú	unit_nameÚ
memory_maxs         rE   Ú_build_systemd_scope_argvr†     s‰   € ð €M€M€Mà�\Š\˜-Ñ(Ô(€FØ€~ð ÐØ. Ð.Ð.€IÝ)Ñ+Ô+€JàØØØØØØØØØØ!�ZÐ!Ð!ØØØðð 
ðð rX   r„   c                 ó   ‡— ddl }|                     d¦  «        }|€dS 	 t          j        |dd| gdd¬	¦  «        }|j        dk    r„|j        pd
                     d¬¦  «                             ¦   «         }|                     ¦   «         Št          ˆfd„dD ¦   «         ¦  «        rdS t                               d| |j        |¦  «         dS dS # t          $ r'}t                               d| |¦  «         Y d}~dS d}~ww xY w)u)  Stop a transient systemd user scope by unit name.

    This reaps the *entire* cgroup â€” catching double-forked descendants that
    survive a plain PID signal because they were reparented to init inside the
    scope (issue #70716, reviewer gap #2).  ``systemctl --user stop`` sends
    SIGTERM to every process in the unit's cgroup and escalates to SIGKILL
    after the unit's ``TimeoutStopSec``.

    Returns True if the unit was successfully stopped (or was already gone),
    False if ``systemctl`` is unavailable or the stop command failed.
    r   NÚ	systemctlFrK   ÚstopTr   rU   rX   rY   ©Úerrorsc              3   ó    •K  — | ]}|‰v V — Œ	d S ©N© )Ú.0ÚmarkerÚstderr_lowers     €rE   ú	<genexpr>z%_stop_systemd_unit.<locals>.<genexpr>R  s<   øè è € ð ð àð ˜,Ð&ðð ð ð ð ð rX   )z
not loadedz	not foundzdoes not existz&systemctl --user stop %s exited %d: %sz#systemctl --user stop %s failed: %s)r`   ra   rf   rg   rh   rj   rk   r%   ÚlowerÚanyr)   ri   rl   )r„   r`   rp   rr   rj   rs   r‘   s         @rE   Ú_stop_systemd_unitr•   8  sN  ø€ ð €M€M€Mà�\Š\˜+Ñ&Ô&€FØ€~ØˆuðÝ”Ø�X˜v yÐ1ØØð
ñ 
ô 
ˆð
 Ô Ò!Ð!Ø”mÐ* s×2Ò2¸)Ð2ÑDÔD×JÒJÑLÔLˆFØ!Ÿ<š<™>œ>ˆLÝð ð ð ð àKðñ ô ñ ô ð ð �tÝ�LŠLØ8Ø˜6Ô,Øñô ð ð
 �5ØˆtøÝð ð ð Ý�ŠÐ:¸IÀsÑKÔKÐKØˆuˆuˆuˆuˆuøøøøðøøøs    BC Â&"C Ã
C=ÃC8Ã8C=Úsecondsc                 óÊ   — t          dt          | ¦  «        ¦  «        }|dk     r|› d�S t          |d¦  «        \  }}|dk     r|› d|› d�S t          |d¦  «        \  }}|› d|› d�S )Nr   é<   Úszm zh Úm)r6   r&   Údivmod)r–   r™   ÚminsÚsecsÚhourss        rE   Úformat_uptime_shortrŸ   c  s†   € ÝˆA�s�7‰|Œ|ÑÔ€AØˆ2‚v€vØˆwˆwˆwˆÝ˜˜2‘”�J€Dˆ$Øˆb‚y€yØÐ!Ð!˜$Ð!Ð!Ð!Ð!Ý˜˜rÑ"Ô"�K€Eˆ4ØÐÐ�tÐÐÐÐrX   c                   óÂ  — e Zd ZU dZeed<   eed<   dZeed<   dZeed<   dZe	e
         ed<   dZe	ej                 ed	<   dZeed
<   dZe	e         ed<   dZeed<   dZe	e
         ed<   dZeed<   dZe	e
         ed<   dZeed<   dZeed<   dZeed<   eZe
ed<   dZeed<   dZeed<   dZeed<   dZeed<   dZ eed<   dZ!eed<   dZ"eed<   dZ#eed<   dZ$eed<   d Z%e
ed!<   dZ&eed"<    e'e(¬#¦  «        Z)e*e         ed$<    e'd d¬%¦  «        Z+e
ed&<    e'd d¬%¦  «        Z,e
ed'<    e'dd¬%¦  «        Z-eed(<    e'dd¬%¦  «        Z.eed)<    e'dd¬%¦  «        Z/eed*<    e'dd¬%¦  «        Z0eed+<    e'd d¬%¦  «        Z1e
ed,<    e'e2j3        d¬-¦  «        Z4e2j3        ed.<    e'e2j5        ¬#¦  «        Z6e2j5        ed/<    e'dd¬%¦  «        Z7e	e2j8                 ed0<    e'dd¬%¦  «        Z9eed1<   dS )2ÚProcessSessionz3A tracked background process with output buffering.ÚidÚcommandr   Útask_idÚsession_keyNÚpidÚprocessÚenv_refÚcwdr   Ú
started_atÚhost_start_timeFÚexitedÚ	exit_codeÚcompletion_reasonÚtermination_sourceÚoutput_bufferÚmax_output_charsÚdetachedÚhostÚ	pid_scopeÚsystemd_unitÚwatcher_platformÚwatcher_chat_idÚwatcher_user_idÚwatcher_user_nameÚwatcher_thread_idÚwatcher_message_idr   Úwatcher_intervalÚnotify_on_complete)Údefault_factoryÚwatch_patterns)ÚdefaultÚreprÚ_watch_hitsÚ_watch_suppressedÚ_watch_disabledÚ_watch_last_emit_atÚ_watch_cooldown_untilÚ_watch_strike_candidateÚ_watch_consecutive_strikes)r¾   rÁ   Ú_completion_eventÚ_lockÚ_reader_threadÚ_pty):Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚstrÚ__annotations__r¤   r¥   r¦   r   r&   r§   rf   ÚPopenr¨   r   r©   rª   Úfloatr«   r¬   Úboolr­   r®   r¯   r°   ÚMAX_OUTPUT_CHARSr±   r²   r´   rµ   r¶   r·   r¸   r¹   rº   r»   r¼   r½   r
   Úlistr¿   r   rÂ   rÃ   rÄ   rÅ   rÆ   rÇ   rÈ   Ú	threadingÚEventrÉ   ÚLockrÊ   rË   ÚThreadrÌ   rŽ   rX   rE   r¡   r¡   n  sh  € € € € € € à=Ð=Ø€G€G�GØ€L€L�LØ€GˆSÐÐÑØ€K�ÐÐÑØ€Cˆ�#ŒÐÐÑØ*.€GˆX�jÔ&Ô'Ð.Ð.Ñ.Ø€GˆSÐÐÑØ€Cˆ�#ŒÐÐÑØ€J�ÐÐÑØ%)€O�X˜c”]Ð)Ð)Ñ)Ø€FˆDÐÐÑØ#€Iˆx˜Œ}Ð#Ð#Ñ#Ø%Ð�sÐ%Ð%Ñ%Ø Ð˜Ð Ð Ñ Ø€M�3ÐÐÑØ,Ð�cÐ,Ð,Ñ,Ø€HˆdÐÐÑØ€IˆsÐÐÑØ€L�#ÐÐÑàÐ�cÐÐÑØ€O�SÐÐÑØ€O�SÐÐÑØÐ�sÐÐÑØÐ�sÐÐÑØ Ð˜Ð Ð Ñ ØÐ�cÐÐÑØ$Ð˜Ð$Ð$Ñ$à % °dÐ ;Ñ ;Ô ;€N�D˜”IÐ;Ð;Ñ;Ø�u Q¨UÐ3Ñ3Ô3€K�Ð3Ð3Ñ3Ø"˜U¨1°5Ð9Ñ9Ô9Ð�sÐ9Ð9Ñ9Ø!˜E¨%°eÐ<Ñ<Ô<€O�TÐ<Ð<Ñ<ð "' ¨s¸Ð!?Ñ!?Ô!?Ð˜Ð?Ð?Ñ?Ø#( 5°¸5Ð#AÑ#AÔ#AÐ˜5ÐAÐAÑAØ$) E°%¸eÐ$DÑ$DÔ$DÐ˜TÐDÐDÑDØ&+ e°A¸EÐ&BÑ&BÔ&BÐ ÐBÐBÑBØ).¨¸y¼ÐUZÐ)[Ñ)[Ô)[Ð�y”Ð[Ð[Ñ[Ø!˜E°)´.ÐAÑAÔA€Eˆ9Œ>ÐAÐAÑAØ16°¸tÈ%Ð1PÑ1PÔ1P€N�H˜YÔ-Ô.ÐPÐPÑPØ�˜d¨Ð/Ñ/Ô/€Dˆ#Ð/Ð/Ñ/Ð/Ð/rX   r¡   c                   ó´  — e Zd ZdZdZd„ Zededefd„¦   «         Zde	dedd	fd
„Z
de	dedd	fd„Zdedefd„Zedee         defd„¦   «         Zedee         dee         fd„¦   «         Zedee         dee         defd„¦   «         Zdee	         dee	         fd„Zedefd„¦   «         Zedefd„¦   «         ZedYdedee         dd	fd„¦   «         Zededefd„¦   «         Z	 	 	 	 	 dZdedededed ed!ede	fd"„Z	 	 	 	 d[dededededed$ede	fd%„Zde	fd&„Zde	ded'ed(ed)ef
d*„Zde	fd+„Z de	fd,„Z!d-edefd.„Z"d-edefd/„Z#d0d1œd-ed2edefd3„Z$	 	 d\d0d1œded2edd4fd5„Z%d-edee	         fd6„Z&d]d8„Z'd-edefd9„Z(d^d-ed;ed	z  d<edefd=„Z)dYd-ed$edefd>„Z*d?d0d@œd-edAedBedefdC„Z+d-edDedefdE„Z,d_d-edDedefdF„Z-d-edefdG„Z.d-edefdH„Z/defdI„Z0d`dedede1fdJ„Z2dedefdK„Z3	 dYdedLee         defdM„Z4defdN„Z5dede6e         fdO„Z7dedAedefdP„Z8	 dY e6¦   «         dQddRœdee         dSe6dAedBedef
dT„Z9dU„ Z:	 dYdVee;e<eef                           fdW„Z=defdX„Z>d	S )aÚProcessRegistrya$  
    In-memory registry of running and finished background processes.

    Thread-safe. Accessed from:
      - Executor threads (terminal_tool, process tool handlers)
      - Gateway asyncio loop (watcher tasks, session reset checks)
      - Cleanup thread (sandbox reaping coordination)
    )z'bash: cannot set terminal process groupz"bash: no job control in this shellzno job control in this shellz!cannot set terminal process groupz)tcsetattr: Inappropriate ioctl for devicec                 óþ  — i | _         i | _        t          j        ¦   «         | _        g | _        dd l}|                     ¦   «         | _        	 ddl	m
}  || j        ¦  «         n2# t          $ r%}t                               d|¦  «         Y d }~nd }~ww xY wt          ¦   «         | _        t          ¦   «         | _        t          j        ¦   «         | _        d| _        d| _        d| _        d| _        d | _        d | _        d S )Nr   )Úrestore_undelivered_completionsz2Could not restore async delegation completions: %sr   )Ú_runningÚ	_finishedrØ   rÚ   rÊ   Úpending_watchersÚqueueÚQueueÚcompletion_queueÚtools.async_delegationrß   rl   r)   r*   ÚsetÚ_completion_consumedÚ_poll_observedÚ_global_watch_lockÚ_global_watch_window_startÚ_global_watch_window_hitsÚ_global_watch_tripped_untilÚ$_global_watch_suppressed_during_tripÚ	on_outputÚon_close)ÚselfÚ
_queue_modrß   rs   s       rE   Ú__init__zProcessRegistry.__init__µ  s&  € Ø35ˆŒØ46ˆŒÝ”^Ñ%Ô%ˆŒ
ð 79ˆÔð 	#Ð"Ð"Ð"Ø2<×2BÒ2BÑ2DÔ2DˆÔð	VØNÐNÐNÐNÐNÐNØ+Ð+¨DÔ,AÑBÔBÐBÐBøÝð 	Vð 	Vð 	VÝ�NŠNÐOÐQTÑUÔUÐUÐUÐUÐUÐUÐUøøøøð	Vøøøõ *-©¬ˆÔ!õ $'¡5¤5ˆÔõ
 #,¤.Ñ"2Ô"2ˆÔØ14ˆÔ'Ø./ˆÔ&Ø25ˆÔ(Ø9:ˆÔ1ð ˆŒð
 ˆŒˆˆs   ÁA# Á#
BÁ-BÂBÚtextr   c                 ó  ‡— |                       d¦  «        Š‰rat          ˆfd„t          j        D ¦   «         ¦  «        r<‰                     d¦  «         ‰r%t          ˆfd„t          j        D ¦   «         ¦  «        °<d                     ‰¦  «        S )z:Strip shell startup warnings from the beginning of output.Ú
c              3   ó,   •K  — | ]}|‰d          v V — ŒdS )r   NrŽ   )r�   ÚnoiseÚliness     €rE   r’   z5ProcessRegistry._clean_shell_noise.<locals>.<genexpr>ñ  s,   øè è € ÐcÐc°%˜E U¨1¤XÐ-ÐcÐcÐcÐcÐcÐcrX   r   )Úsplitr”   rÝ   Ú_SHELL_NOISE_SUBSTRINGSÚpopÚjoin)rô   rù   s    @rE   Ú_clean_shell_noisez"ProcessRegistry._clean_shell_noiseí  s—   ø€ ð —
’
˜4Ñ Ô ˆØð 	�ÐcÐcÐcÐc½?Ô;bÐcÑcÔcÑcÔcð 	Ø�IŠI�a‰LŒLˆLð ð 	�ÐcÐcÐcÐc½?Ô;bÐcÑcÔcÑcÔcð 	à�yŠy˜ÑÔÐrX   ÚsessionÚchunkNc                 ó\   — | j         }|�|sdS 	  |||¦  «         dS # t          $ r Y dS w xY w)zˆForward a freshly-read chunk to the live-output sink, if one is set.
        Called from reader threads; never raise into the read loop.N)rï   rl   )rñ   rÿ   r   Úsinks       rE   Ú_emit_outputzProcessRegistry._emit_outputõ  sX   € ð Œ~ˆØˆ<˜uˆ<ØˆFð	ØˆD�˜%Ñ Ô Ð Ð Ð øÝð 	ð 	ð 	ØˆDˆDð	øøøs   � �
+ª+Únew_textc                 ó  — |j         r|j        rdS |j        rdS g }d}|                     ¦   «         D ]=}|j         D ]3}||v r-|                     |                     ¦   «         ¦  «         |€|} nŒ4Œ>|sdS t          j        ¦   «         }d}|j        5  |j        ri||j        k     r^|xj	        t          |¦  «        z  c_	        |j        s7d|_        |xj        dz  c_        |j        t          k    rd|_        d|_        d}d}	nR|j        r|j        sd|_        d|_        ||_        |t           z   |_        |xj        dz  c_        |j	        }
d|_	        d}	ddd¦  «         n# 1 swxY w Y   |	rv|rr| j                             |j        |j        |j        d|j	        |j        |j        |j        |j        |j        |j        d|j        › dt          › d	t           › d
�dœ¦  «         dS d                     |dd…         ¦  «        }t          |¦  «        dk    r|dd…         dz   }|                      |¦  «        sdS | j                             |j        |j        |j        d|||
|j        |j        |j        |j        |j        |j        dœ¦  «         dS )uz  Scan new output for watch patterns and queue notifications.

        Called from reader threads with new_text being the freshly-read chunk.

        Per-session rate limit: at most ONE watch-match notification per
        WATCH_MIN_INTERVAL_SECONDS. Any match arriving inside the cooldown
        window is dropped and counts as ONE strike for that window. After
        WATCH_STRIKE_LIMIT consecutive strike windows, watch_patterns is
        disabled for this session and the session is promoted to
        notify_on_complete semantics â€” one notification when the process
        actually exits, no more mid-process spam.
        NFTé   r   Úwatch_disabledz$Watch patterns disabled for process u    â€” z7 consecutive rate-limit windows triggered (min spacing zms). Falling back to notify_on_complete semantics; you'll get exactly one notification when the process exits.)Ú
session_idr¥   r£   ÚtypeÚ
suppressedÚplatformÚchat_idÚuser_idÚ	user_nameÚ	thread_idÚ
message_idÚmessagerö   é   iÐ  z
...(truncated)Úwatch_match)r  r¥   r£   r	  ÚpatternÚoutputr
  r  r  r  r  r  r  )r¿   rÄ   r¬   r,   r1   ÚrstriprZ   rÊ   rÆ   rÃ   ÚlenrÇ   rÈ   ÚWATCH_STRIKE_LIMITr½   rÅ   ÚWATCH_MIN_INTERVAL_SECONDSrÂ   rå   Úputr¢   r¥   r£   r¶   r·   r¸   r¹   rº   r»   rý   Ú_global_watch_admit)rñ   rÿ   r  Úmatched_linesÚmatched_patternr>   Úpatrn   Úshould_disableÚreturn_earlyr
  r  s               rE   Ú_check_watch_patternsz%ProcessRegistry._check_watch_patterns   s™  € ð Ô%ð 	¨Ô)@ð 	ØˆFð
 Œ>ð 	ØˆFð ˆØˆØ×'Ò'Ñ)Ô)ð 	ð 	ˆDØÔ-ð ð �Ø˜$�;�;Ø!×(Ò(¨¯ª©¬Ñ7Ô7Ð7Ø&Ð.Ø*-˜Ø�Eð	 øð ð 	ØˆFåŒi‰kŒkˆØˆØŒ]ð %	%ð %	%ð
 Ô,ð  %°°wÔ7TÒ1TÐ1TØÐ)Ô)­S°Ñ-?Ô-?Ñ?Ð)Ô)ØÔ6ð 	.à6:�GÔ3ØÐ6Ô6¸!Ñ;Ð6Ô6ØÔ9Õ=OÒOÐOØ26˜Ô/ð 6:˜Ô2Ø)-˜Ø#��ð Ô1ð;à#Ô;ð;ð :;�GÔ6Ø27�Ô/ð /2�Ô+Ø03Õ6PÑ0P�Ô-ØÐ#Ô# qÑ(Ð#Ô#Ø$Ô6�
Ø,-�Ô)Ø$�ðK%	%ð %	%ð %	%ñ %	%ô %	%ð %	%ð %	%ð %	%ð %	%ð %	%ð %	%øøøð %	%ð %	%ð %	%ð %	%ðN ð 	Øð ð Ô%×)Ò)Ø")¤*Ø#*Ô#6Ø&œØ,Ø")Ô";Ø 'Ô 8Ø&Ô6Ø&Ô6Ø!(Ô!:Ø!(Ô!:Ø")Ô"<ðL¸w¼zð Lð LÝ-ðLð Lå(BðLð Lð Lð+ð +ñ ô ð ð( ˆFð —’˜=¨¨"¨Ô-Ñ.Ô.ˆÝˆv‰;Œ;˜ÒÐØ˜E˜T˜E”]Ð%7Ñ7ˆFð ×'Ò'¨Ñ,Ô,ð 	ØˆFàÔ×!Ò!Ø!œ*Ø"Ô.Ø”Ø!Ø&ØØ$ØÔ0ØÔ.ØÔ.Ø Ô2Ø Ô2Ø!Ô4ð#
ð #
ñ 	ô 	ð 	ð 	ð 	s   ÂCEÅE#Å&E#rn   c                 óÂ  — | j         5  | j        rJ|| j        k    r?| j        }d| _        d| _        || _        d| _        |dk    rdddd|d|› d�ddddddœ}nd}nd}| j        r || j        k     r| xj        d	z  c_        d
}d}ni|| j        z
  t
          k    r|| _        d| _        | j        t          k    r$|t          z   | _        | xj        d	z  c_        |}d
}n| xj        d	z  c_        d}d}ddd¦  «         n# 1 swxY w Y   |�| j         	                    |¦  «         |�>| j         	                    dddddt          › dt
          › dt          › d�ddddddœ
¦  «         |S )a1  Return True if this watch_match event is allowed through the global breaker.

        Semantics:
        - If we're currently in a cooldown period, drop the event and count it.
        - Otherwise, slide the rolling window and check the global cap.
        - If the cap is exceeded, trip the breaker for WATCH_GLOBAL_COOLDOWN_SECONDS
          and emit ONE summary event so the agent/user sees "N notifications were
          suppressed" instead of getting them individually.
        - When the cooldown ends, emit a release summary and reset counters.
        r   r   r   Úwatch_overflow_releasedz%Watch-pattern notifications resumed. z1 match event(s) were suppressed during the flood.)r  r¥   r£   r	  r
  r  r  r  r  r  r  Nr  FTÚwatch_overflow_trippedzWatch-pattern overflow: >z notifications in zCs across all processes. Suppressing further watch_match events for ús.)
r  r¥   r£   r	  r  r  r  r  r  r  )
rê   rí   rî   rë   rì   ÚWATCH_GLOBAL_WINDOW_SECONDSÚWATCH_GLOBAL_MAX_PER_WINDOWÚWATCH_GLOBAL_COOLDOWN_SECONDSrå   r  )rñ   rn   r
  Úrelease_msgÚadmitÚtrip_nows         rE   r  z#ProcessRegistry._global_watch_admit€  sb  € ð Ô$ð 3	!ð 3	!àÔ/ð #°C¸4Ô;[Ò4[Ð4[Ø!ÔF�
Ø36�Ô0Ø<=�Ô9Ø25�Ô/Ø12�Ô.Ø ’>�>ð ')Ø')Ø#%Ø 9Ø&0ð]Ø)ð]ð ]ð ]ð %'Ø#%Ø#%Ø%'Ø%'ð#ð #�K�Kð" #'�K�Kà"�ð Ô/ð !°C¸$Ô:ZÒ4ZÐ4ZØÐ9Ô9¸QÑ>Ð9Ô9Ø�Ø��ð ˜Ô8Ñ8Õ<WÒWÐWØ69�DÔ3Ø56�DÔ2àÔ1Õ5PÒPÐPà7:Õ=ZÑ7Z�DÔ4ØÐ=Ô=ÀÑBÐ=Ô=Ø"�HØ!�E�EàÐ2Ô2°aÑ7Ð2Ô2Ø#�HØ �Eðg3	!ð 3	!ð 3	!ñ 3	!ô 3	!ð 3	!ð 3	!ð 3	!ð 3	!ð 3	!ð 3	!øøøð 3	!ð 3	!ð 3	!ð 3	!ðl Ð"ØÔ!×%Ò% kÑ2Ô2Ð2ØÐØÔ!×%Ò%Ø Ø!ØØ0ð9Õ0Kð 9ð 9Ý(Cð9ð 9õ 5ð9ð 9ð 9ð
 ØØØØð'ð 'ñ ô ð ð" ˆs   ˆC$C8Ã8C<Ã?C<r¦   c                 ó,   — | sdS ddl m}  || ¦  «        S )z1Best-effort liveness check for host-visible PIDs.Fr   )Ú_pid_exists)r~   r-  )r¦   r-  s     rE   Ú_is_host_pid_alivez"ProcessRegistry._is_host_pid_alive×  s5   € ð ð 	Ø�5ð 	/Ð.Ð.Ð.Ð.Ð.Øˆ{˜3ÑÔÐrX   c                 óP   — | sdS 	 ddl m}  || ¦  «        S # t          $ r Y dS w xY w)z<Kernel start ticks for a host PID, or None when unavailable.Nr   )Úget_process_start_time)r~   r0  rl   )r¦   r0  s     rE   Ú_safe_host_start_timez%ProcessRegistry._safe_host_start_timeá  s[   € ð ð 	Ø�4ð	Ø=Ð=Ð=Ð=Ð=Ð=Ø)Ð)¨#Ñ.Ô.Ð.øÝð 	ð 	ð 	Ø�4�4ð	øøøs   † —
%¤%Úexpected_startc                 ój   — |                       |¦  «        sdS |€dS |                      |¦  «        |k    S )u  True only if ``pid`` is alive AND still the process we spawned.

        The kernel recycles PID/PGID numbers once a process exits and is reaped,
        so a stored PID can later name an *unrelated* process â€” observed in the
        wild as a recycled number landing on a desktop browser's session leader,
        which our tree-kill then SIGTERMs (Firefox dying at irregular intervals).
        We compare the kernel start time captured at spawn against the live one;
        a mismatch means the number was recycled and must never be signalled.

        When no baseline was captured (legacy checkpoints, or platforms without
        ``/proc``) we degrade to a bare liveness check rather than refusing to
        act, preserving prior best-effort behaviour.
        FNT)r.  r1  )Úclsr¦   r2  s      rE   Ú_host_pid_is_oursz!ProcessRegistry._host_pid_is_oursì  sC   € ð ×%Ò% cÑ*Ô*ð 	Ø�5ØÐ!Ø�4Ø×(Ò(¨Ñ-Ô-°Ò?Ð?rX   c                 ó2  — |�|j         s|j        r|j        dk    r|S |                      |j        |j        ¦  «        r|S |j        5  |j         r|cddd¦  «         S d|_         d|_        ddd¦  «         n# 1 swxY w Y   |                      |¦  «         |S )zJUpdate recovered host-PID sessions when the underlying process has exited.Nr³   T)	r¬   r²   r´   r5  r¦   r«   rÊ   r­   Ú_move_to_finished)rñ   rÿ   s     rE   Ú_refresh_detached_sessionz)ProcessRegistry._refresh_detached_session  s  € àˆ?˜gœnˆ?°GÔ4Dˆ?ÈÔHYÐ]cÒHcÐHcØˆNð
 ×!Ò! '¤+¨wÔ/FÑGÔGð 	ØˆNàŒ]ð 	%ð 	%ØŒ~ð Øð	%ð 	%ð 	%ð 	%ñ 	%ô 	%ð 	%ð 	%ð "ˆGŒNð !%ˆGÔð	%ð 	%ð 	%ñ 	%ô 	%ð 	%ð 	%ð 	%ð 	%ð 	%ð 	%øøøð 	%ð 	%ð 	%ð 	%ð 	×Ò˜wÑ'Ô'Ð'Øˆs   Á	A7ÁA7Á7A;Á>A;c                 ó”   — 	 ddl }|                      ¦   «         sdS |                      ¦   «         |j        k    S # t          $ r Y dS w xY w)z�True if a psutil.Process is running and not a zombie.

        A zombie is already dead (just unreaped), so there's nothing to SIGKILL.
        r   NF)ÚpsutilÚ
is_runningÚstatusÚSTATUS_ZOMBIErl   )Úprocr:  s     rE   Ú_proc_alivezProcessRegistry._proc_alive  s_   € ð	ØˆMˆMˆMØ—?’?Ñ$Ô$ð Ø�uØ—;’;‘=”= FÔ$8Ò8Ð8øÝð 	ð 	ð 	Ø�5�5ð	øøøs   ‚9 œ9 ¹
AÁAc                  óÂ   — 	 ddl m} m}m}  | ¦   «         } ||dd¦  «        }|€|d         d         }t	          t          |¦  «        d¦  «        S # t          $ r Y dS w xY w)a%  Grace window (s) between SIGTERM and escalated SIGKILL.

        Read from ``terminal.daemon_term_grace_seconds`` in config.yaml; floored
        at 0 (0 disables escalation). Falls back to the DEFAULT_CONFIG value if
        config is unreadable, so callers always get a sane number.
        r   )Úread_raw_configÚcfg_getÚDEFAULT_CONFIGÚterminalÚdaemon_term_grace_secondsNr   g       @)Úhermes_cli.configrA  rB  rC  r6   rÔ   rl   )rA  rB  rC  ÚcfgÚvals        rE   Ú_daemon_term_grace_secondsz*ProcessRegistry._daemon_term_grace_seconds%  s“   € ð	ØRÐRÐRÐRÐRÐRÐRÐRÐRÐRØ!�/Ñ#Ô#ˆCØ�'˜#˜zÐ+FÑGÔGˆCØˆ{Ø$ ZÔ0Ð1LÔM�Ý•u˜S‘z”z 3Ñ'Ô'Ð'øÝð 	ð 	ð 	Ø�3�3ð	øøøs   ‚AA Á
AÁAc           
      óà  ‡ — |�3‰                       ||¦  «        st                               d|¦  «         dS t          r¨	 t	          j        ddt          |¦  «        ddgdddd	d
t          ¦   «         t          j        ¬¦  «         n`# t          t          j
        t          f$ rA 	 t          j        |t          j        ¦  «         n# t          t           t"          f$ r Y nw xY wY nw xY wdS ddl}	 |                     |¦  «        }nb# |j        $ r Y dS t          t"          f$ rB 	 t          j        |t          j        ¦  «         n# t          t           t"          f$ r Y nw xY wY dS w xY w	 |                     d¬¦  «        }n# |j        |j        t          f$ r g }Y nw xY w|                     |¦  «         |D ]9}	 |                     ¦   «          Œ# |j        $ r Y Œ$|j        t          f$ r Y Œ6w xY w‰                      ¦   «         }|dk    rdS t5          j        ¦   «         |z   }t5          j        ¦   «         |k     rGt9          ˆ fd„|D ¦   «         ¦  «        sn+t5          j        d¦  «         t5          j        ¦   «         |k     °G|D ]p}	 ‰                      |¦  «        sŒ|                     ¦   «          t                               d|j         |¦  «         ŒO# |j        $ r Y Œ[|j        t          f$ r Y Œmw xY wdS )u¿	  Terminate a host-visible PID and its descendants.

        ``expected_start`` is the kernel start time captured when we spawned the
        process. When provided, it is re-validated against the live PID before
        any signal is sent; a mismatch (or a dead PID) means the number was
        recycled onto an unrelated process and we refuse to touch it, so a stale
        background-session PID can never tree-kill a browser or other stranger.

        POSIX: walks the process tree with ``psutil`` and SIGTERMs
        children before the parent so subprocess trees (e.g. Chromium
        renderers/GPU helpers spawned by an ``agent-browser`` daemon)
        don't get reparented to init and survive cleanup.  After a bounded
        grace window (``terminal.daemon_term_grace_seconds``) any tree member
        that ignored SIGTERM â€” a daemon stalled in its signal handler â€” is
        escalated to SIGKILL so it can't leak indefinitely.  Set the grace to
        0 to disable escalation (SIGTERM only).

        Windows: shells out to ``taskkill /PID <pid> /T /F``. This is
        the documented Microsoft primitive for tree-kill and matches the
        existing convention in ``gateway.status.terminate_pid``.  ``/F`` is
        already a hard kill, so no separate escalation step is needed.  We
        can't reuse the POSIX psutil path on Windows because:

          1. Windows doesn't maintain a Unix-style process tree â€”
             ``psutil.Process.children(recursive=True)`` walks PPID
             links that go stale when intermediate processes exit, so
             enumeration is best-effort and misses orphaned descendants.
          2. ``psutil.Process.terminate()`` on Windows is
             ``TerminateProcess()`` which kills only the target handle
             and is a hard kill â€” there is no Windows equivalent of a
             SIGTERM that cascades through a process group. (See the
             warning in ``gateway/status.py::terminate_pid``: "os.kill
             with SIGTERM is not equivalent to a tree-killing hard stop"
             on Windows.) Headless Chromium has no GUI window, so the
             softer ``taskkill /T`` without ``/F`` won't reach it either.

        ``psutil`` is a hard dependency (see ``pyproject.toml``); the
        bare-``os.kill`` fallback covers OSError / PermissionError on
        POSIX and a missing ``taskkill.exe`` on Windows (effectively
        unreachable on real Windows installs, but cheap insurance).
        Nuf   Refusing to terminate host pid %d: start-time mismatch â€” PID was recycled onto an unrelated process.Útaskkillz/PIDz/Tz/FTr   rY   r   )rV   rô   r   r‹   rW   ÚcreationflagsÚstdinr   )Ú	recursivec              3   óB   •K  — | ]}‰                      |¦  «        V — Œd S r�   )r?  )r�   Ú_pr4  s     €rE   r’   z6ProcessRegistry._terminate_host_pid.<locals>.<genexpr>¦  s/   øè è € Ð=Ð=¨r�s—’ rÑ*Ô*Ð=Ð=Ð=Ð=Ð=Ð=rX   gš™™™™™©?zDEscalated to SIGKILL for pid %d (ignored SIGTERM within %.1fs grace))!r5  r)   r*   r_   rf   rg   rÑ   r   ÚDEVNULLÚFileNotFoundErrorÚTimeoutExpiredr2   r#   ÚkillÚsignalÚSIGTERMÚProcessLookupErrorÚPermissionErrorr:  ÚProcessÚNoSuchProcessÚchildrenÚAccessDeniedr1   Ú	terminaterI  rZ   r[   r”   Úsleepr?  Úinfor¦   )	r4  r¦   r2  r:  ÚparentÚtargetsr>  ÚgraceÚdeadlines	   `        rE   Ú_terminate_host_pidz#ProcessRegistry._terminate_host_pid7  sÉ  ø€ ðV Ð%¨c×.CÒ.CÀCÈÑ.XÔ.XÐ%õ �NŠNð>Ø?Bñô ð ð ˆFÝð 	ðÝ”Ø ­¨S©¬°4¸Ð>Ø#'Ø¨¸	ØÝ"4Ñ"6Ô"6Ý$Ô,ðñ ô ð ð øõ &¥zÔ'@Å'ÐJð ð ð ðÝ”G˜C¥¤Ñ0Ô0Ð0Ð0øÝÕ!3µ_ÐEð ð ð Ø�Dðøøøøøðøøøð
 ˆFàˆˆˆð		Ø—^’^ CÑ(Ô(ˆFˆFøØÔ#ð 	ð 	ð 	ØˆFˆFÝ�Ð)ð 	ð 	ð 	ðÝ”˜�Vœ^Ñ,Ô,Ð,Ð,øÝÕ/µÐAð ð ð Ø�ðøøøàˆFˆFð	øøøð	Ø—o’o°�oÑ5Ô5ˆGˆGøØÔ$ fÔ&9½7ÐCð 	ð 	ð 	ØˆGˆGˆGð	øøøà�Š�vÑÔÐàð 	ð 	ˆDðØ—’Ñ Ô Ð Ð øØÔ'ð ð ð Ø�ØÔ'­Ð1ð ð ð Ø�ðøøøð ×.Ò.Ñ0Ô0ˆØ�AŠ:ˆ:ØˆFõ ”>Ñ#Ô# eÑ+ˆÝŒnÑÔ Ò)Ð)ÝÐ=Ð=Ð=Ð=°WÐ=Ñ=Ô=Ñ=Ô=ð ØÝŒJ�tÑÔÐõ ŒnÑÔ Ò)Ð)ð ð 	ð 	ˆDðØ—’ tÑ,Ô,ð ØØ—	’	‘”�Ý—’ð#Ø$(¤H¨eñô ð ð øð Ô'ð ð ð Ø�ØÔ'­Ð1ð ð ð Ø�ðøøøð	ð 	sº   ¿AB ÂC!Â!CÃ C!ÃCÃC!ÃCÃC!Ã C!Ã+D Ä
E ÄE ÄD?Ä>E Ä?EÅE ÅEÅE ÅE Å$E; Å;FÆFÆ4G	Ç	
G(ÇG(Ç'G(Ê KÊ5KË
K+ËK+Ë*K+Úenvc                 óD  — 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dS )zEReturn the writable sandbox temp dir for env-backed background tasks.Úget_temp_dirNr    z*Could not resolve environment temp dir: %sz/tmp)	ÚgetattrÚcallableÚ
isinstancerÑ   r-   r  rl   r)   ri   )re  rg  Útemp_dirrs   s       rE   Ú_env_temp_dirzProcessRegistry._env_temp_dir¹  sÂ   € õ ˜s N°DÑ9Ô9ˆÝ�LÑ!Ô!ð 	PðPØ'˜<™>œ>�Ý˜h­Ñ,Ô,ð 7°×1DÒ1DÀSÑ1IÔ1Ið 7Ø#Ÿ?š?¨3Ñ/Ô/Ð6°3Ð6øøÝð Pð Pð PÝ—’ÐIÈ3ÑOÔOÐOÐOÐOÐOÐOÐOøøøøðPøøøàˆvs   ¢A
A. Á.
BÁ8BÂBr   Fr£   r©   r¤   r¥   Úenv_varsÚuse_ptyc                 óX  — ddl m}  ||¦  «        }t          dt          j        ¦   «         j        dd…         › �|||t          |pt          j        ¦   «         ¦  «        t          j	        ¦   «         ¬¦  «        }	d}
|�r+	 t          rddlm} nddlm} t          ¦   «         }t          t          j        |¦  «        }d	|d
<   |dd|› �g}t           ot#          ¦   «         }|ot%          ¦   «         }|r)t'          ||	j        ¬¦  «        }d|	j        › d�|	_        d}
n|rt,                               d¦  «         |                     ||	j        |d¬¦  «        }|j        |	_        |                      |	j        ¦  «        |	_        ||	_        t=          j        | j         |	fdd|	j        › �¬¦  «        }||	_!        | "                    ¦   «          | j#        5  |  $                    ¦   «          |	| j%        |	j        <   ddd¦  «         n# 1 swxY w Y   |  &                    ¦   «          |	S # tN          $ r t,           (                    d¦  «         Y netR          $ rY}t,           (                    d|¦  «         |
r2|	j        r+tU          |	j        ¦  «        stW          d¦  «        |‚d|	_        Y d}~nd}~ww xY wt          ¦   «         }t          t          j        |¦  «        }d	|d
<   t          rdtY          ¦   «         ini }|dd|› �g}t           ot#          ¦   «         }|ot%          ¦   «         }|r2|
r
|	j        › d�n|	j        }t'          ||¬¦  «        }d|› d�|	_        d}n.|}d}|r(t,                               d|t%          ¦   «         ¦  «         t[          j.        |fd|	j        |ddtZ          j/        tZ          j0        tZ          j1        |dœ	|¤Ž}||	_2        |j        |	_        |                      |	j        ¦  «        |	_        	 t=          j        | j3        |	fdd |	j        › �¬¦  «        }||	_!        | "                    ¦   «          | j#        5  |  $                    ¦   «          |	| j%        |	j        <   ddd¦  «         n# 1 swxY w Y   |  &                    ¦   «          �n # tR          $ �r 	 |	j        r5tU          |	j        ¦  «         |  4                    |j        |	j        ¦  «         nšt          s	 tk          tl          d!tl          j7        ¦  «        }t          j8        t          j9        |j        ¦  «        |¦  «         nE# tt          tv          tx          f$ r | =                    ¦   «          Y nw xY w| =                    ¦   «          n# tR          $ r Y nw xY w	 | >                    d"¬#¦  «         n# tR          $ r Y nw xY w‚ w xY w|	S )$aw  
        Spawn a background process locally.

        Only for TERMINAL_ENV=local. Other backends use spawn_via_env().

        Args:
            use_pty: If True, use a pseudo-terminal via ptyprocess for interactive
                     CLI tools (Codex, Claude Code, Python REPL). Falls back to
                     subprocess.Popen if ptyprocess is not installed.
        r   )Ú_rewrite_compound_backgroundÚproc_Né   )r¢   r£   r¤   r¥   r©   rª   F)Ú
PtyProcessrw   ÚPYTHONUNBUFFEREDz-liczset +m; )r�   rƒ   z.scopeTz{PTY background executor not isolated in a systemd scope (systemd-run --user unavailable); worker shares the gateway cgroup.)r   éx   )r©   re  Ú
dimensionszproc-pty-reader-©ÚtargetÚargsÚdaemonÚnamez3ptyprocess not installed, falling back to pipe modez0PTY spawn failed (%s), falling back to pipe modezZPTY scope could not be reaped; refusing pipe fallback to avoid duplicate command executionr   rL  z-pipe-fallbackz˜Local background executor not isolated in a systemd scope (in_supervised_gateway=%s, systemd-run --user available=%s); worker shares the gateway cgroup.r   rY   )	rô   r©   re  r   r‹   Ústdoutrj   rM  Ústart_new_sessionzproc-reader-ÚSIGKILLé   ©rW   )?Útools.terminal_toolrp  r¡   rc   rd   re   r   r#   ÚgetcwdrZ   r_   Úwinptyrs  Ú
ptyprocessr   r   r{   r   rt   r†   r¢   rµ   r)   ri   Úspawnr©   r¦   r1  r«   rÌ   rØ   rÛ   Ú_pty_reader_looprË   ÚstartrÊ   Ú_prune_if_neededrà   Ú_write_checkpointÚImportErrorr*   rl   r•   ÚRuntimeErrorr   rf   rÓ   ÚPIPEÚSTDOUTrQ  r§   Ú_reader_looprd  rh  rU  rV  ÚkillpgÚgetpgidrW  rX  r2   rT  Úwait)rñ   r£   r©   r¤   r¥   rm  rn  Ú_rewrite_bgÚsafe_commandrÿ   Úpty_scope_attemptedÚ_PtyProcessClsÚ
user_shellÚpty_envÚpty_argvÚpty_in_supervised_gatewayÚpty_use_systemd_scopeÚpty_procÚreaderÚeÚbg_envÚ_popen_kwargsr€   Úin_supervised_gatewayÚuse_systemd_scoper�   Ú
spawn_argvÚpopen_start_new_sessionr>  Úkill_signals                                 rE   Úspawn_localzProcessRegistry.spawn_localÆ  sK  € ð0 	TÐSÐSÐSÐSÐSà"�{ 7Ñ+Ô+ˆå Ø.•t”z‘|”|Ô'¨¨¨Ô,Ð.Ð.ØØØ#Ý! #Ð"4­¬©¬Ñ5Ô5Ý”y‘{”{ð
ñ 
ô 
ˆð $ÐØñ J	.ðH.Ýð HØCÐCÐCÐCÐCÐCÐCàGÐGÐGÐGÐGÐGÝ(™]œ]�
Ý2µ2´:¸xÑHÔH�Ø.1�Ð*Ñ+Ø&¨Ð0I¸<Ð0IÐ0IÐJ�õ $�OÐHÕ(FÑ(HÔ(Hð *ð .ÐUÕ2SÑ2UÔ2Uð &ð )ð Ý8Ø Ø$+¤Jð ñ  ô  �Hð ,O¸G¼JÐ+NÐ+NÐ+N�GÔ(Ø*.Ð'Ð'Ø.ð Ý—L’Lð<ñô ð ð *×/Ò/ØØœØØ(ð	 0ñ ô �ð 'œl�”Ø*.×*DÒ*DÀWÄ[Ñ*QÔ*Q�Ô'à'�”õ #Ô)ØÔ0Ø!˜ØØ8¨G¬JÐ8Ð8ð	ñ ô �ð *0�Ô&Ø—’‘”�à”Zð 8ð 8Ø×)Ò)Ñ+Ô+Ð+Ø07�D”M '¤*Ñ-ð8ð 8ð 8ñ 8ô 8ð 8ð 8ð 8ð 8ð 8ð 8øøøð 8ð 8ð 8ð 8ð ×&Ò&Ñ(Ô(Ð(Ø�øåð Vð Vð VÝ—’ÐTÑUÔUÐUÐUÐUÝð .ð .ð .Ý—’ÐQÐSTÑUÔUÐUØ&ð .¨7Ô+?ð .Ý-¨gÔ.BÑCÔCð !Ý*ðCñô ð  !ð!ð ,.�GÔ(øøøøøøøøøð.øøøõ !‘]”]ˆ
õ *­"¬*°hÑ?Ô?ˆØ%(ˆÐ!Ñ"ÝCNÐV˜Õ*<Ñ*>Ô*>Ð?Ð?ÐTVˆð ! &Ð*C°\Ð*CÐ*CÐDˆ
Ý$/ Ð TÕ4RÑ4TÔ4TÐà!ÐIÕ&GÑ&IÔ&Ið 	ð ð !	à1DÐT�7”:Ð-Ð-Ð-Ð-È'Ì*ð õ 3ØØ'ðñ ô ˆJð $H°KÐ#GÐ#GÐ#GˆGÔ ð '+Ð#Ð#à#ˆJØ&*Ð#Ø$ð 
õ —’ð8ð *Ý5Ñ7Ô7ñô ð õ ÔØð
àØ”ØØØÝ”?ÝÔ$ÝÔ$Ø5ð
ð 
ð ð
ð 
ˆð ˆŒØ”hˆŒØ"&×"<Ò"<¸W¼[Ñ"IÔ"IˆÔð,	åÔ%ØÔ(Ø�ZØØ0 G¤JÐ0Ð0ð	ñ ô ˆFð &,ˆGÔ"Ø�LŠL‰NŒNˆNà”ð 4ð 4Ø×%Ò%Ñ'Ô'Ð'Ø,3�”˜gœjÑ)ð4ð 4ð 4ñ 4ô 4ð 4ð 4ð 4ð 4ð 4ð 4øøøð 4ð 4ð 4ð 4ð ×"Ò"Ñ$Ô$Ð$Ñ$øÝð 	ñ 	ð 	ðØÔ'ð  õ ' wÔ';Ñ<Ô<Ð<Ø×,Ò,¨T¬X°wÔ7NÑOÔOÐOÐOÝ$ð  ð$Ý&-­f°iÅÄÑ&PÔ&P˜Ýœ	¥"¤*¨T¬XÑ"6Ô"6¸ÑDÔDÐDÐDøÝ.µÅÐIð $ð $ð $ØŸ	š	™œ˜˜˜ð$øøøð —I’I‘K”K�KøøÝð ð ð Ø�ðøøøðØ—	’	 !�	Ñ$Ô$Ð$Ð$øÝð ð ð Ø�ðøøøàð9	øøøð< ˆsã   Á?EH Ç$G=Ç1H Ç=HÈH ÈHÈH È$J&É	J&ÉAJ!Ê!J&Ï1AR
 Ð9$Q)ÑR
 Ñ)Q-Ñ-R
 Ñ0Q-Ñ1R
 Ò
V'ÒAU-ÓAT'Ô&U-Ô'+UÕU-ÕUÕU-Õ,V'Õ-
U:Õ7V'Õ9U:Õ:V'Õ>VÖV'Ö
V"ÖV'Ö!V"Ö"V'r   rW   c                 ó  — t          dt          j        ¦   «         j        dd…         › �||||t	          j        ¦   «         |d¬¦  «        }|                      |¦  «        }|› d|j        › d�}	|› d|j        › d�}
|› d|j        › d	�}t          j        |¦  «        }t          j        |¦  «        }t          j        |	¦  «        }t          j        |
¦  «        }t          j        |¦  «        }d
|› d|› d|› d|› d|› d|› �}	 | 	                    ||d¬¦  «        }| 
                    dd¦  «                             ¦   «         }|                     ¦   «         D ]@}|                     ¦   «         }|                     ¦   «         rt          |¦  «        |_         nŒA|j        €|d|_        t          | 
                    dd¦  «        ¦  «        |_        |j        dk    rd|_        d|_        d|_        | 
                    dd¦  «                             ¦   «         |_        n=# t*          $ r0}d|_        d|_        d|_        d|_        d|› �|_        Y d}~nd}~ww xY w|j        sEt-          j        | j        |||	|
|fdd|j        › �¬¦  «        }||_        |                     ¦   «          | j        5  |                      ¦   «          |j        s|| j        |j        <   ddd¦  «         n# 1 swxY w Y   |j        s|                      ¦   «          |S )a#  
        Spawn a background process through a non-local environment backend.

        For Docker/Singularity/Modal/Daytona/SSH: runs the command inside the sandbox
        using the environment's execute() interface. We wrap the command to
        capture the in-sandbox PID and redirect output to a log file inside
        the sandbox, then poll the log via subsequent execute() calls.

        This is less capable than local spawn (no live stdout pipe, no stdin),
        but it ensures the command runs in the correct sandbox context.
        rq  Nrr  Úsandbox)r¢   r£   r¤   r¥   r©   rª   r¨   r´   z/hermes_bg_z.logz.pidz.exitz	mkdir -p z && ( nohup bash -lc z > z$ 2>&1; rc=$?; printf '%s\n' "$rc" > z ) & echo $! > z && cat F)rW   Úrewrite_compound_backgroundr  r   Trh   éÿÿÿÿr   Úfailed_startzFailed to start: zproc-poller-rw  )r¡   rc   rd   re   rZ   rl  r¢   ÚshlexÚquoteÚexecuter|   r%   r,   r0   r&   r¦   r¬   r­   r®   r¯   r°   rl   rØ   rÛ   Ú_env_poller_looprË   r‡  rÊ   rˆ  rà   r‰  )rñ   re  r£   r©   r¤   r¥   rW   rÿ   rk  Úlog_pathÚpid_pathÚ	exit_pathÚquoted_commandÚquoted_temp_dirÚquoted_log_pathÚquoted_pid_pathÚquoted_exit_pathÚ
bg_commandrr   r  r>   r�  rœ  s                          rE   Úspawn_via_envzProcessRegistry.spawn_via_env´  sÕ  € õ( !Ø.•t”z‘|”|Ô'¨¨¨Ô,Ð.Ð.ØØØ#ØÝ”y‘{”{ØØð	
ñ 	
ô 	
ˆð ×%Ò% cÑ*Ô*ˆØÐ;Ð;¨7¬:Ð;Ð;Ð;ˆØÐ;Ð;¨7¬:Ð;Ð;Ð;ˆØÐ=Ð=¨G¬JÐ=Ð=Ð=ˆ	Ýœ WÑ-Ô-ˆÝœ+ hÑ/Ô/ˆÝœ+ hÑ/Ô/ˆÝœ+ hÑ/Ô/ˆÝ œ; yÑ1Ô1ÐðD˜ð Dð DØ .ðDð DØ3BðDð Dà/?ðDð Dð )ðDð Dð 3BðDð Dð 	ð	<Ø—[’[ØØØ,1ð !ñ ô ˆFð
 —Z’Z ¨"Ñ-Ô-×3Ò3Ñ5Ô5ˆFà×)Ò)Ñ+Ô+ð ð �Ø—z’z‘|”|�Ø—<’<‘>”>ð Ý"% d¡)¤)�G”KØ�Eðð Œ{Ð"Ø!%�”Ý$'¨¯
ª
°<ÀÑ(DÔ(DÑ$EÔ$E�Ô!ØÔ$¨Ò)Ð)Ø(*�GÔ%Ø,:�Ô)Ø-;�Ô*Ø(.¯
ª
°8¸RÑ(@Ô(@×(FÒ(FÑ(HÔ(H�Ô%øøÝð 	<ð 	<ð 	<Ø!ˆGŒNØ "ˆGÔØ(6ˆGÔ%Ø)7ˆGÔ&Ø$;¸Ð$;Ð$;ˆGÔ!Ð!Ð!Ð!Ð!Ð!øøøøð	<øøøð Œ~ð 		åÔ%ØÔ,Ø˜s H¨h¸	ÐBØØ0 G¤JÐ0Ð0ð	ñ ô ˆFð &,ˆGÔ"Ø�LŠL‰NŒNˆNàŒZð 	4ð 	4Ø×!Ò!Ñ#Ô#Ð#Ø”>ð 4Ø,3�”˜gœjÑ)ð	4ð 	4ð 	4ñ 	4ô 	4ð 	4ð 	4ð 	4ð 	4ð 	4ð 	4øøøð 	4ð 	4ð 	4ð 	4ð
 Œ~ð 	%Ø×"Ò"Ñ$Ô$Ð$àˆs+   Ã?DH È
IÈ"&IÉIÊ(+KËK#Ë&K#c                 ó€  ‡ ‡‡— dŠ t          j        d¦  «        d¬¦  «        }dt          fˆˆ ˆfd„}	 ‰j        }|�|j        €Ç	 	 |                     dd¬	¦  «        }|r ||¦  «         n# t          $ r Y nw xY w	 ‰j                             d
¬¦  «         n2# t          $ r%}t           	                    d|¦  «         Y d}~nd}~ww xY wd‰_
        ‰j        dk    r‰j        j        ‰_        d‰_        ‰                      ‰¦  «         dS |j        }t          t          |dd¦  «        dd¦  «        }d}	|�dt           s]t          |dd¦  «        }
	 t#          |
¦  «        r
 |
¦   «         nd}n# t          $ r d}Y nw xY wt%          |t&          ¦  «        r|dk    r|}	|	�”ddl}d}	 	 |                     |	gg g d¦  «        \  }}}n# t*          t,          f$ r Y nZw xY w|r3 |d¦  «        }|snF|                     |¦  «        }|r ||¦  «         d}n |                     ¦   «         �|dz  }|dk    rnŒŒnN	 |�' |d¦  «        }|sn=|                     |¦  «        }|sŒ)n|                     d¦  «        }|sn ||¦  «         ŒMn2# t          $ r%}t           	                    d|¦  «         Y d}~nd}~ww xY w	 |                     dd¬	¦  «        }|r ||¦  «         n# t          $ r Y nw xY w	 ‰j                             d
¬¦  «         n2# t          $ r%}t           	                    d|¦  «         Y d}~nd}~ww xY wd‰_
        ‰j        dk    r‰j        j        ‰_        d‰_        ‰                      ‰¦  «         dS # 	 |                     dd¬	¦  «        }|r ||¦  «         n# t          $ r Y nw xY w	 ‰j                             d
¬¦  «         n2# t          $ r%}t           	                    d|¦  «         Y d}~nd}~ww xY wd‰_
        ‰j        dk    r‰j        j        ‰_        d‰_        ‰                      ‰¦  «         w xY w)u’  Background thread: read stdout from a local Popen process.

        IMPORTANT: avoid ``TextIOWrapper.read(4096)`` here. On pipes that call can
        block until EOF (or a large buffer fills), which makes "live" output land
        in one burst at process exit. ``buffer.read1(4096)`` yields incremental
        chunks as bytes become available, then we decode to text.

        Orphaned-pipe guard (issue #68915): when the user's command backgrounds
        a long-lived process (``node server.js &``, ``sleep 300 &``), that
        grandchild inherits the write end of our stdout pipe via ``fork()``.
        The direct ``bash`` child exits promptly, but the pipe never reaches
        EOF while the grandchild lives â€” so a blocking read would park this
        thread forever, ``session.exited`` would never flip, and
        ``notify_on_complete`` would never fire (``_reconcile_local_exit``
        only runs lazily from poll()/wait(), which an autonomous notification
        can't rely on). On POSIX we therefore ``select()`` with a short poll
        interval and stop draining shortly after the direct child exits, even
        if the pipe hasn't EOF'd â€” mirroring the foreground fix in
        ``tools/environments/base.py::_wait_for_process`` (#8340). Windows
        pipes don't support select(); the blocking path is kept there and the
        lazy reconcile in poll()/wait() remains the safety net.
        Tr   rY   rŠ   r   c                 ó^  •— ‰r‰                      | ¦  «        } dŠ‰j        5  ‰xj        | z  c_        t          ‰j        ¦  «        ‰j        k    r‰j        ‰j         d …         ‰_        d d d ¦  «         n# 1 swxY w Y   ‰                     ‰| ¦  «         ‰                     ‰| ¦  «         d S )NF)rþ   rÊ   r°   r  r±   r!  r  )r   Úfirst_chunkrñ   rÿ   s    €€€rE   Ú_append_chunkz3ProcessRegistry._reader_loop.<locals>._append_chunk;  s  ø€ àð $Ø×/Ò/°Ñ6Ô6�Ø#�Ø”ð ^ð ^ØÐ%Ô%¨Ñ.Ð%Ô%Ý�wÔ,Ñ-Ô-°Ô0HÒHÐHØ,3Ô,AÀ7ÔC[ÐB[ÐB\ÐB\Ô,]�GÔ)ð^ð ^ð ^ñ ^ô ^ð ^ð ^ð ^ð ^ð ^ð ^øøøð ^ð ^ð ^ð ^ð ×&Ò& w°Ñ6Ô6Ð6Ø×Ò˜g uÑ-Ô-Ð-Ð-Ð-s   ¢AA6Á6A:Á=A:NrX   ©Úfinalr  r€  z$Process wait timed out or failed: %sÚkilledr¬   ÚbufferÚread1Úfilenor   gš™™™™™É?é   r  r   zProcess stdout reader ended: %s)ÚcodecsÚgetincrementaldecoderrÑ   r§   r|  rk   rl   r‘  r)   ri   r¬   r®   rh   r­   r7  rh  r_   ri  rj  r&   Úselectr(   r2   ÚpollÚread)rñ   rÿ   Údecoderr¼  r>  Útailr�  r|  Úraw_readÚfdrÂ  Ú	candidateÚ_selectÚidle_after_exitÚreadyÚ_Úrawr   r»  s   ``                @rE   rŽ  zProcessRegistry._reader_loop  sÉ  øøø€ ð. ˆð 8•&Ô.¨wÑ7Ô7¸yÐIÑIÔIˆð
	.¥ð 
	.ð 
	.ð 
	.ð 
	.ð 
	.ð 
	.ð 
	.ð 
	.ðU	,Ø”?ˆDØˆ|˜tœ{Ð2ØðFØ—~’~ c°�~Ñ6Ô6�Øð (Ø!�M $Ñ'Ô'Ð'øøÝð ð ð Ø�ðøøøðHØ”×$Ò$¨QÐ$Ñ/Ô/Ð/Ð/øÝð Hð Hð HÝ—’ÐCÀQÑGÔGÐGÐGÐGÐGÐGÐGøøøøðHøøøà!ˆGŒNØÔ(¨HÒ4Ð4Ø$+¤OÔ$>�Ô!Ø,4�Ô)Ø×"Ò" 7Ñ+Ô+Ð+Ð+Ð+ðc ”[ˆFå�w v¨x¸Ñ>Ô>ÀÈÑNÔNˆHð
 ˆBØÐ#­KÐ#Ý  ¨°4Ñ8Ô8�ð%Ý,4°VÑ,<Ô,<Ð F  ¡¤ À$�I�IøÝ ð %ð %ð %Ø $�I�I�Ið%øøøå˜i­Ñ-Ô-ð #°)¸q².°.Ø"�Bàˆ~Ø(Ð(Ð(Ð(à"#�ð"ðØ&-§n¢n°b°T¸2¸rÀ3Ñ&GÔ&G™˜˜q ! !øÝ&­Ð0ð ð ð Ø˜ðøøøàð "Ø&˜h t™nœn˜Ø"ð "Ø!Ø '§¢¨sÑ 3Ô 3˜Ø ð 1Ø)˜M¨%Ñ0Ô0Ð0Ø*+˜˜ØŸš™œÐ0ð (¨1Ñ,˜Ø*¨aÒ/Ð/Ø!ð+"øð.)ØÐ+Ø&˜h t™nœn˜Ø"ð "Ø!Ø '§¢¨sÑ 3Ô 3˜Ø$ð %Ø$ð%ð
 !'§¢¨DÑ 1Ô 1˜Ø$ð "Ø!à!�M %Ñ(Ô(Ð(ð)øøõ  ð 	?ð 	?ð 	?Ý�LŠLÐ:¸AÑ>Ô>Ð>Ð>Ð>Ð>Ð>Ð>øøøøð	?øøøðØ—~’~ c°�~Ñ6Ô6�Øð (Ø!�M $Ñ'Ô'Ð'øøÝð ð ð Ø�ðøøøðHØ”×$Ò$¨QÐ$Ñ/Ô/Ð/Ð/øÝð Hð Hð HÝ—’ÐCÀQÑGÔGÐGÐGÐGÐGÐGÐGøøøøðHøøøà!ˆGŒNØÔ(¨HÒ4Ð4Ø$+¤OÔ$>�Ô!Ø,4�Ô)Ø×"Ò" 7Ñ+Ô+Ð+Ð+Ð+øðØ—~’~ c°�~Ñ6Ô6�Øð (Ø!�M $Ñ'Ô'Ð'øøÝð ð ð Ø�ðøøøðHØ”×$Ò$¨QÐ$Ñ/Ô/Ð/Ð/øÝð Hð Hð HÝ—’ÐCÀQÑGÔGÐGÐGÐGÐGÐGÐGøøøøðHøøøà!ˆGŒNØÔ(¨HÒ4Ð4Ø$+¤OÔ$>�Ô!Ø,4�Ô)Ø×"Ò" 7Ñ+Ô+Ð+Ð+øøøs"  ´I? Á$A+ Á+
A8Á7A8Á<B Â
CÂ"CÃCÄAI? ÅE+ Å*I? Å+E:Å7I? Å9E:Å:)I? Æ$G ÇI? ÇGÇI? ÇGÇB(I? É>M7 É?
J.Ê	J)Ê$M7 Ê)J.Ê.M7 Ê2$K Ë
K$Ë#K$Ë(L Ì
L3ÌL.Ì.L3Í7P=Í9$NÎP=Î
N+Î(P=Î*N+Î+P=Î/OÏ
P=Ï
O:ÏO5Ï0P=Ï5O:Ï:AP=r¯  r°  r±  c                 ó¼  — t          j        |¦  «        }t          j        |¦  «        }t          j        |¦  «        }d}	|j        �s•t          j        d¦  «         	 |                     d|› d�d¬¦  «        }
|
                     dd¦  «        }|r¹t          |¦  «        |	k    r
||	d	…         nd}t          |¦  «        }	|j        5  ||_	        t          |j	        ¦  «        |j
        k    r|j	        |j
         d	…         |_	        d	d	d	¦  «         n# 1 swxY w Y   |r,|                      ||¦  «         |                      ||¦  «         |                     d
|› d�d¬¦  «        }|                     dd¦  «                             ¦   «         }|�r|                     ¦   «         d                              ¦   «         dk    rÑ|                     d|› d�d¬¦  «        }|                     dd¦  «                             ¦   «         }	 t          |                     ¦   «         d                              ¦   «         ¦  «        |_        n# t"          t$          f$ r
 d|_        Y nw xY wd|_        |j        dk    rd|_        |                      |¦  «         d	S nB# t*          $ r5 d|_        d|_        d|_        d|_        |                      |¦  «         Y d	S w xY w|j        �¯“d	S d	S )zBBackground thread: poll a sandbox log file for non-local backends.r   r   zcat ú 2>/dev/nullr   r€  r  r   Nzkill -0 "$(cat z# 2>/dev/null)" 2>/dev/null; echo $?r  r©  Ú0Tr¿  r¬   ÚlostÚbackend_lost)r«  r¬  r¬   rZ   r^  r­  r|   r  rÊ   r°   r±   r!  r  r%   r,   r&   r­   r(   Ú
IndexErrorr®   r7  rl   r¯   )rñ   rÿ   re  r¯  r°  r±  r´  rµ  r¶  Úprev_output_lenrr   Ú
new_outputÚdeltaÚcheckÚcheck_outputÚexit_resultÚexit_strs                    rE   r®  z ProcessRegistry._env_poller_loopž  sx  € õ  œ+ hÑ/Ô/ˆÝœ+ hÑ/Ô/ˆÝ œ; yÑ1Ô1ÐØˆØ”.ñ 0	ÝŒJ�q‰MŒMˆMð.àŸšÐ%I¨OÐ%IÐ%IÐ%IÐSU˜ÑVÔV�Ø#ŸZšZ¨°"Ñ5Ô5�
Øð 
:å<?À
¹O¼OÈoÒ<]Ð<]˜J Ð'7Ð'7Ô8Ð8Ðce�EÝ&)¨*¡o¤o�OØ œð fð fØ0:˜Ô-Ý˜wÔ4Ñ5Ô5¸Ô8PÒPÐPØ4;Ô4IÈ7ÔKcÐJcÐJdÐJdÔ4e˜GÔ1ðfð fð fñ fô fð fð fð fð fð fð føøøð fð fð fð fð ð :Ø×2Ò2°7¸EÑBÔBÐBØ×)Ò)¨'°5Ñ9Ô9Ð9ð ŸšØ\ Ð\Ð\Ð\Øð $ñ ô �ð  %Ÿyšy¨°2Ñ6Ô6×<Ò<Ñ>Ô>�Øñ  L×$;Ò$;Ñ$=Ô$=¸bÔ$A×$GÒ$GÑ$IÔ$IÈSÒ$PÐ$Pà"%§+¢+Ø=Ð/Ð=Ð=Ð=Ø !ð #.ñ #ô #�Kð  +Ÿš¨x¸Ñ<Ô<×BÒBÑDÔD�Hð/Ý,/°×0CÒ0CÑ0EÔ0EÀbÔ0I×0OÒ0OÑ0QÔ0QÑ,RÔ,R˜Ô)Ð)øÝ&­
Ð3ð /ð /ð /Ø,.˜Ô)Ð)Ð)ð/øøøà%)�G”NØÔ0°HÒ<Ð<Ø4<˜Ô1Ø×*Ò*¨7Ñ3Ô3Ð3Ø�Føøåð ð ð à!%�”Ø$&�Ô!Ø,2�Ô)Ø-;�Ô*Ø×&Ò& wÑ/Ô/Ð/Ø��ðøøøðS ”.ñ 0	ð 0	ð 0	ð 0	ð 0	s\   ÁA(J Ã?DÄJ ÄDÄJ ÄDÄC*J È>I É J ÉIÉJ ÉIÉ1J Ê;KËKc                 ó–  ‡ ‡— ‰j         } t          j        d¦  «        d¬¦  «        }dt          fˆ ˆfd„}	 |                     ¦   «         r�	 |                     d¦  «        }|r9t          |t          ¦  «        r|n|                     |¦  «        }|r ||¦  «         n# t          $ r Y n#t          $ r Y nw xY w|                     ¦   «         °�n2# t          $ r%}t                               d|¦  «         Y d}~nd}~ww xY w	 |                     d	d
¬¦  «        }|r ||¦  «         n# t          $ r Y nw xY w	 |                     ¦   «          n2# t          $ r%}t                               d|¦  «         Y d}~nd}~ww xY wd
‰_        ‰j        dk    r%t          |d¦  «        r|j        nd‰_        d‰_        ‰                      ‰¦  «         dS )z2Background thread: read output from a PTY process.r   rY   rŠ   rô   c                 ó,  •— ‰j         5  ‰xj        | z  c_        t          ‰j        ¦  «        ‰j        k    r‰j        ‰j         d …         ‰_        d d d ¦  «         n# 1 swxY w Y   ‰                     ‰| ¦  «         ‰                     ‰| ¦  «         d S r�   )rÊ   r°   r  r±   r!  r  )rô   rñ   rÿ   s    €€rE   Ú_append_textz6ProcessRegistry._pty_reader_loop.<locals>._append_textà  sî   ø€ Ø”ð ^ð ^ØÐ%Ô%¨Ñ-Ð%Ô%Ý�wÔ,Ñ-Ô-°Ô0HÒHÐHØ,3Ô,AÀ7ÔC[ÐB[ÐB\ÐB\Ô,]�GÔ)ð^ð ^ð ^ñ ^ô ^ð ^ð ^ð ^ð ^ð ^ð ^øøøð ^ð ^ð ^ð ^ð ×&Ò& w°Ñ5Ô5Ð5Ø×Ò˜g tÑ,Ô,Ð,Ð,Ð,s   ‰AAÁA!Á$A!rÃ  zPTY stdout reader ended: %sNrX   Tr½  z PTY wait timed out or failed: %sr¿  Ú
exitstatusr©  r¬   )rÌ   rÄ  rÅ  rÑ   ÚisaliverÈ  rj  rk   ÚEOFErrorrl   r)   ri   r‘  r¬   r®   Úhasattrrã  r­   r7  )	rñ   rÿ   ÚptyrÉ  râ  r   rô   r�  rÊ  s	   ``       rE   r†  z ProcessRegistry._pty_reader_loopØ  sV  øø€ àŒlˆð 8•&Ô.¨wÑ7Ô7¸yÐIÑIÔIˆð	-�sð 	-ð 	-ð 	-ð 	-ð 	-ð 	-ð 	-ð	;Ø—+’+‘-”-ð ð
ØŸHšH T™NœN�EØð /å(2°5½#Ñ(>Ô(>ÐY˜u˜uÀGÇNÂNÐSXÑDYÔDY˜Øð /Ø(˜L¨Ñ.Ô.Ð.øøÝð ð ð Ø�EÝ ð ð ð Ø�Eðøøøð —+’+‘-”-ð øøõ ð 	;ð 	;ð 	;Ý�LŠLÐ6¸Ñ:Ô:Ð:Ð:Ð:Ð:Ð:Ð:øøøøð	;øøøð	Ø—>’> #¨T�>Ñ2Ô2ˆDØð #Ø�˜TÑ"Ô"Ð"øøÝð 	ð 	ð 	ØˆDð	øøøð	@Ø�HŠH‰JŒJˆJˆJøÝð 	@ð 	@ð 	@Ý�LŠLÐ;¸QÑ?Ô?Ð?Ð?Ð?Ð?Ð?Ð?øøøøð	@øøøàˆŒØÔ$¨Ò0Ð0Ý29¸#¸|Ñ2LÔ2LÐ T ¤ ÐRTˆGÔØ(0ˆGÔ%Ø×Ò˜wÑ'Ô'Ð'Ð'Ð'sr   ·C ÁAB ÂC Â
B5Â'C Â)	B5Â2C Â4B5Â5C Ã
C<ÃC7Ã7C<Ä $D% Ä%
D2Ä1D2Ä6E Å
E:ÅE5Å5E:c                 óö  — | j         5  | j                             |j        d¦  «        du}|| j        |j        <   ddd¦  «         n# 1 swxY w Y   |j                             ¦   «          |                      ¦   «          |rw|j        rrddl	m
} |j        r ||j        dd…         ¦  «        nd}| j                             d|j        |j        |j        |j        |j        |j        ||j        dœ	¦  «         dS dS dS )uú   Move a session from running to finished.

        Idempotent: if the session was already moved (e.g. kill_process raced
        with the reader thread), the second call is a no-op â€” no duplicate
        completion notification is enqueued.
        Nr   ©Ú
strip_ansié0øÿÿr   Ú
completion)	r	  r  r¥   r£   r­   r®   r¯   r  rª   )rÊ   rà   rü   r¢   rá   rÉ   rç   r‰  r½   Útools.ansi_striprê  r°   rå   r  r¥   r£   r­   r®   r¯   rª   )rñ   rÿ   Úwas_runningrê  Úoutput_tails        rE   r7  z!ProcessRegistry._move_to_finished  sx  € ð ŒZð 	1ð 	1Øœ-×+Ò+¨G¬J¸Ñ=Ô=ÀTÐIˆKØ)0ˆDŒN˜7œ:Ñ&ð	1ð 	1ð 	1ñ 	1ô 	1ð 	1ð 	1ð 	1ð 	1ð 	1ð 	1øøøð 	1ð 	1ð 	1ð 	1ð 	Ô!×%Ò%Ñ'Ô'Ð'Ø×ÒÑ Ô Ð ð
 ð 	˜7Ô5ð 	Ø3Ð3Ð3Ð3Ð3Ð3ØGNÔG\Ðd˜*˜* WÔ%:¸5¸6¸6Ô%BÑCÔCÐCÐbdˆKØÔ!×%Ò%Ø$Ø%œjØ&Ô2Ø"œ?Ø$Ô.Ø%,Ô%>Ø&-Ô&@Ø%ð &Ô0ð'ð 'ñ ô ð ð ð ð	ð 	ð 	ð 	s   ˆ2AÁA
ÁA
r  c                 ó   — || j         v S )zECheck if a completion notification was already consumed via wait/log.)rè   )rñ   r  s     rE   Úis_completion_consumedz&ProcessRegistry.is_completion_consumed/  s   € à˜TÔ6Ð6Ð6rX   c                 óR  — |sdS | j         5  | j                             |¦  «        p| j                             |¦  «        }ddd¦  «         n# 1 swxY w Y   |€dS 	 |                      |¦  «         n# t
          $ r Y nw xY w|j        rdS |j        r|j        s|j	        dk    rdS dS )uÚ  Whether a goal loop parked on this session should still be parked.

        Used by the goal-loop wait barrier (``hermes_cli.goals``) to support
        waiting on a process's OWN trigger, not just its exit. A session is
        "still waiting" when:
          - it is still running, AND
          - if it has ``watch_patterns``, none has matched yet (so a
            long-lived watcher that fires a trigger mid-run â€” and may never
            exit â€” unblocks the moment its pattern hits, not on exit).

        Returns False (don't wait) when the session has exited, its watch
        pattern has already fired, or the session is unknown â€” so a stale or
        already-triggered barrier can never wedge the loop.
        FNr   T)
rÊ   rà   r|   rá   r8  rl   r¬   r¿   rÄ   rÂ   ©rñ   r  rÿ   s      rE   Úis_session_waitingz"ProcessRegistry.is_session_waiting3  s-  € ð ð 	Ø�5ØŒZð 	Vð 	VØ”m×'Ò'¨
Ñ3Ô3ÐU°t´~×7IÒ7IÈ*Ñ7UÔ7UˆGð	Vð 	Vð 	Vñ 	Vô 	Vð 	Vð 	Vð 	Vð 	Vð 	Vð 	Vøøøð 	Vð 	Vð 	Vð 	Vàˆ?Ø�5ð	Ø×*Ò*¨7Ñ3Ô3Ð3Ð3øÝð 	ð 	ð 	ØˆDð	øøøàŒ>ð 	Ø�5ð Ô!ð 	¨'Ô*Að 	ØÔ" QÒ&Ð&Ø�uØˆts#   Œ5AÁAÁAÁA3 Á3
B Á?B T©Úskip_poll_observedrö  c                ó*   — || j         v p
|o|| j        v S )uP  Whether this drain should skip a completion event for this session.

        Skips when the agent has either truly consumed the output (wait/log â†’
        ``_completion_consumed``) or observed the exit inline via poll()
        (``_poll_observed``).  In both cases the CLI agent already has the
        result this turn, so injecting a [SYSTEM: ...] completion would be a
        duplicate (#8228).  The gateway/tui watchers do NOT use this â€” they
        check only ``is_completion_consumed`` so a read-only poll never
        suppresses their autonomous delivery turn (#10156).
        )rè   ré   )rñ   r  rö  s      rE   Ú_drain_should_skipz"ProcessRegistry._drain_should_skipW  s)   € ð ˜TÔ6Ð6ð 
ØÐD :°Ô1DÐ#Dð	
rX   zlist[tuple[dict, str]]c                ó  — g }g }| j                              ¦   «         �sÄ	 | j                              ¦   «         }n# t          $ r Y �nœw xY w|                     d¦  «        dk    }t          |                     d¦  «        pd¦  «        }t          |                     d¦  «        pd¦  «        }	|pt          |p|	¦  «        }
|�H|
rF	 t           ||¦  «        ¦  «        }n# t          $ r d}Y nw xY w|s|                     |¦  «         �ŒnP|r |
r||k    r|                     |¦  «         �Œ%n.|r,|                     d¦  «        r|                     |¦  «         �ŒT|                     d	d¦  «        }|                     d¦  «        d
k    r|                      ||¬¦  «        r�Œœt          |¦  «        }|r|                     ||f¦  «         | j                              ¦   «         �¯Ä|D ]}| j          
                    |¦  «         Œ|S )au  Pop all pending notification events and return formatted pairs.

        Returns a list of (raw_event, formatted_text) tuples.
        Skips completion events the agent already consumed via wait/log or
        observed inline via poll() (see ``_drain_should_skip``). Gateway/TUI
        callers pass ``skip_poll_observed=False`` because read-only polling must
        not suppress autonomous delivery there.

        When a routing filter is supplied, addressed notifications must not be
        drained into the wrong session. Async-delegation events always require
        conversation payload; ordinary notifications require routing when they
        carry ``session_key`` or ``origin_ui_session_id`` metadata. Two filter
        modes are supported, strongest first:

        - ``owns_event(evt) -> bool``: positive-proof ownership callback.
          When provided, a routed event is consumed ONLY if the callback
          returns True; everything else is re-queued for its owner.
          The TUI passes its compression-chain-aware ownership check here so
          a post-compression session still claims its own pre-compression
          dispatches.
        - ``session_key``: plain key equality (CLI and other single-session
          callers). Non-matching addressed events are re-queued.

        With neither set, all events are consumed (legacy single-session
        behavior, backward compatible). Ownerless ordinary notifications also
        retain that legacy behavior even when a filter is provided. When a
        filter is provided, ownerless async-delegation events remain
        fail-closed and require positive proof.
        r	  Úasync_delegationr¥   r   Úorigin_ui_session_idNFÚrestoredr  rì  rõ  )rå   ÚemptyÚ
get_nowaitrl   r|   rÑ   rÕ   r1   rø  Úformat_process_notificationr  )rñ   r¥   Ú
owns_eventrö  ÚresultsÚrequeueÚevtÚis_async_delegationÚevt_session_keyÚevt_origin_sidÚrequires_positive_proofÚownedÚ_evt_sidrô   s                 rE   Údrain_notificationsz#ProcessRegistry.drain_notificationsh  sv  € ðH -/ˆØ "ˆØÔ'×-Ò-Ñ/Ô/ñ ,	,ðØÔ+×6Ò6Ñ8Ô8��øÝð ð ð Ø‘ðøøøð #&§'¢'¨&¡/¤/Ð5GÒ"GÐÝ! #§'¢'¨-Ñ"8Ô"8Ð">¸BÑ?Ô?ˆOÝ  §¢Ð)?Ñ!@Ô!@Ð!FÀBÑGÔGˆNØ&9ð '½TØÐ1 >ñ>ô >Ð#ð Ð%Ð*AÐ%ð"Ý   ¨C¡¤Ñ1Ô1�E�EøÝ ð "ð "ð "Ø!�E�E�Eð"øøøàð Ø—N’N 3Ñ'Ô'Ð'Ùðð ð 	Ð!8ð 	Ø" kÒ1Ð1Ø—N’N 3Ñ'Ô'Ð'Ùð 2ð %ð ¨¯ª°Ñ)<Ô)<ð ð —’˜sÑ#Ô#Ð#Ùð —w’w˜|¨RÑ0Ô0ˆHØ�wŠw�v‰Œ ,Ò.Ð.°4×3JÒ3JØÐ-?ð 4Kñ 4ô 4Ð.ñ å.¨sÑ3Ô3ˆDØð ,Ø—’  T˜{Ñ+Ô+Ð+ðY Ô'×-Ò-Ñ/Ô/ñ ,	,ðZ ð 	+ð 	+ˆCØÔ!×%Ò% cÑ*Ô*Ð*Ð*Øˆs!    : º
AÁAÃC ÃC,Ã+C,c                 óÒ   — | j         5  | j                             |¦  «        p| j                             |¦  «        }ddd¦  «         n# 1 swxY w Y   |                      |¦  «        S )z*Get a session by ID (running or finished).N)rÊ   rà   r|   rá   r8  ró  s      rE   r|   zProcessRegistry.get¿  s®   € àŒZð 	Vð 	VØ”m×'Ò'¨
Ñ3Ô3ÐU°t´~×7IÒ7IÈ*Ñ7UÔ7UˆGð	Vð 	Vð 	Vñ 	Vô 	Vð 	Vð 	Vð 	Vð 	Vð 	Vð 	Vøøøð 	Vð 	Vð 	Vð 	Và×-Ò-¨gÑ6Ô6Ð6s   ˆ5A	Á	AÁAr¡   c                 ó  — |�|j         rdS t          |dd¦  «        }|€dS 	 |                     ¦   «         }n# t          $ r Y dS w xY w|€dS d}t          |dd¦  «        }|��at          �sY	 ddl}|                     ¦   «         }|                     ||j        ¦  «        }|                     ||j        |t          j
        z  ¦  «         	 |                     ¦   «         }	|	r.t          |	t          ¦  «        r|	n|	                     dd¬¦  «        }n# t          t           t"          f$ r Y nw xY w	 |                     ||j        |¦  «         nB# t          $ r Y n6w xY w# 	 |                     ||j        |¦  «         w # t          $ r Y w w xY wxY wn8# t          $ r+}
t$                               d	|j        |
¦  «         Y d}
~
nd}
~
ww xY w|j        5  |rG|xj        |z  c_        t/          |j        ¦  «        |j        k    r|j        |j         d…         |_        d
|_         |j        dk    r||_        d|_        ddd¦  «         n# 1 swxY w Y   t$                               d|j        |¦  «         |                      |¦  «         dS )u$  Reconcile session.exited against the real child process state.

        The reader thread (`_reader_loop`) sets `session.exited = True` only
        in its `finally` block, which runs when `stdout.read()` returns EOF.
        If the direct `Popen` child has exited but a descendant process (e.g.
        a daemon spawned by `hermes update` restarting the gateway) is still
        holding the stdout pipe open, the reader blocks forever and poll()
        keeps returning "running" indefinitely (issue #17327 â€” 74 polls over
        7 minutes on Feishu).

        This helper closes that window: when `session.exited` is still False
        but the direct child's `Popen.poll()` reports an exit code, drain any
        readable bytes non-blocking and flip `session.exited`. The orphaned
        reader thread remains stuck on its blocking `read()` but is a daemon
        thread and will be reaped with the process.

        Safe no-op on sessions without a local `Popen` (env/PTY), already-
        exited sessions, and detached-recovered sessions.
        Nr§   r   r|  r   r   rY   rŠ   z$Non-blocking drain failed for %s: %sTr¿  r¬   zxReconciled session %s: direct child exited with code %s but reader was still blocked (orphaned pipe). Flipped to exited.)r¬   rh  rÇ  rl   r_   ÚfcntlrÂ  ÚF_GETFLÚF_SETFLr#   Ú
O_NONBLOCKrÈ  rj  rÑ   rk   ÚBlockingIOErrorr2   r(   r)   ri   r¢   rÊ   r°   r  r±   r®   r­   r_  r7  )rñ   rÿ   r>  ÚrcÚdrainedr|  r  rÌ  Úflagsr   r�  s              rE   Ú_reconcile_local_exitz%ProcessRegistry._reconcile_local_exitÅ  s7  € ð( ˆ?˜gœnˆ?ØˆFÝ�w 	¨4Ñ0Ô0ˆØˆ<ØˆFð	Ø—’‘”ˆBˆBøÝð 	ð 	ð 	ØˆFˆFð	øøøàˆ:ØˆFð ˆÝ˜˜x¨Ñ.Ô.ˆØÑ¥kÑðTØ���Ø—]’]‘_”_�ØŸš B¨¬Ñ6Ô6�Ø—’˜B ¤¨uµr´}Ñ/DÑEÔEÐEð
Ø"ŸKšK™MœM�EØð oÝ+5°e½SÑ+AÔ+AÐ"n % %ÀuÇ|Â|ÐT[ÐdmÀ|ÑGnÔGn˜øøÝ'­µ*Ð=ð ð ð Ø�DðøøøðØŸš B¨¬°uÑ=Ô=Ð=Ð=øÝ$ð ð ð Ø˜ðøøøøðØŸš B¨¬°uÑ=Ô=Ð=Ð=øÝ$ð ð ð Ø˜ðøøøøøøøøåð Tð Tð TÝ—’ÐCÀWÄZÐQRÑSÔSÐSÐSÐSÐSÐSÐSøøøøðTøøøð Œ]ð 	5ð 	5Øð ^ØÐ%Ô%¨Ñ0Ð%Ô%Ý�wÔ,Ñ-Ô-°Ô0HÒHÐHØ,3Ô,AÀ7ÔC[ÐB[ÐB\ÐB\Ô,]�GÔ)Ø!ˆGŒNØÔ(¨HÒ4Ð4Ø$&�Ô!Ø,4�Ô)ð	5ð 	5ð 	5ñ 	5ô 	5ð 	5ð 	5ð 	5ð 	5ð 	5ð 	5øøøð 	5ð 	5ð 	5ð 	5õ 	�ŠðDàŒJ˜ñ	
ô 	
ð 	
ð
 	×Ò˜wÑ'Ô'Ð'Ð'Ð's´   ¢7 ·
AÁAÁ+AF ÃAD ÄE ÄD'Ä$E Ä&D'Ä'E Ä+E ÅF Å
EÅF ÅEÅF ÅFÅE7Å6FÅ7
FÆFÆFÆFÆF Æ
G Æ!F;Æ;G Ç
A*I É IÉIc                 ó(  — ddl m} |                      |¦  «        }|€dd|› �dœS |                      |¦  «         |j        5  |j        r ||j        dd…         ¦  «        nd}ddd¦  «         n# 1 swxY w Y   |j        |j        |j        rd	nd
|j	        t          t          j        ¦   «         |j        z
  ¦  «        |dœ}|j        r8|j        |d<   |j        |d<   |j        |d<   | j                             |¦  «         |j        r
d|d<   d|d<   |S )z9Check status and get new output for a background process.r   ré  NÚ	not_foundúNo process with ID ©r<  Úerroréüÿÿr   r¬   Úrunning)r  r£   r<  r¦   Úuptime_secondsÚoutput_previewr­   r®   r¯   Tr²   z=Process recovered after restart -- output history unavailableÚnote)rí  rê  r|   r  rÊ   r°   r¢   r£   r¬   r¦   r&   rZ   rª   r­   r®   r¯   ré   Úaddr²   )rñ   r  rê  rÿ   r  rr   s         rE   rÇ  zProcessRegistry.poll  s§  € à/Ð/Ð/Ð/Ð/Ð/à—(’(˜:Ñ&Ô&ˆØˆ?Ø)Ð4VÈ*Ð4VÐ4VÐWÐWÐWð 	×"Ò" 7Ñ+Ô+Ð+àŒ]ð 	hð 	hØJQÔJ_Ðg˜Z˜Z¨Ô(=¸e¸f¸fÔ(EÑFÔFÐFÐegˆNð	hð 	hð 	hñ 	hô 	hð 	hð 	hð 	hð 	hð 	hð 	høøøð 	hð 	hð 	hð 	hð "œ*Ø”Ø")¤.Ð?�h�h°iØ”;Ý!¥$¤)¡+¤+°Ô0BÑ"BÑCÔCØ,ð
ð 
ˆð Œ>ð 	0Ø")Ô"3ˆF�;ÑØ*1Ô*CˆFÐ&Ñ'Ø+2Ô+EˆFÐ'Ñ(ð Ô×#Ò# JÑ/Ô/Ð/ØÔð 	]Ø!%ˆF�:ÑØ\ˆF�6‰NØˆs   Á"A0Á0A4Á7A4éÈ   ÚoffsetÚlimitc                 óº  — ddl m} |                      |¦  «        }|€dd|› �dœS |j        5   ||j        ¦  «        }ddd¦  «         n# 1 swxY w Y   |                     ¦   «         }t          |¦  «        }|€'|dk    r!|| d…         }	t          |	¦  «        p|dk    }
nX|pd}||||z   …         }	t          |||z   ¦  «         	                    |¦  «        d         }|dk    pt          |	¦  «        o||k    }
|j
        |j        |j        rdnd	d
                     |	¦  «        |t          |	¦  «        › d�dœ}|j        r|
r| j                             |¦  «         |S )z;Read the full output log with optional pagination by lines.r   ré  Nr  r  r  r  r¬   r  rö   z lines)r  r£   r<  r  Útotal_linesÚshowing)rí  rê  r|   rÊ   r°   r,   r  rÕ   ÚsliceÚindicesr¢   r£   r¬   rý   rè   r   )rñ   r  r"  r#  rê  rÿ   Úfull_outputrù   r%  ÚselectedÚobserved_completion_outputr‰   rr   s                rE   Úread_logzProcessRegistry.read_log:  sã  € à/Ð/Ð/Ð/Ð/Ð/à—(’(˜:Ñ&Ô&ˆØˆ?Ø)Ð4VÈ*Ð4VÐ4VÐWÐWÐWàŒ]ð 	<ð 	<Ø$˜* WÔ%:Ñ;Ô;ˆKð	<ð 	<ð 	<ñ 	<ô 	<ð 	<ð 	<ð 	<ð 	<ð 	<ð 	<øøøð 	<ð 	<ð 	<ð 	<ð ×&Ò&Ñ(Ô(ˆÝ˜%‘j”jˆð ˆ>˜e aši˜iØ˜e˜V˜W˜W”~ˆHÝ)-¨h©¬Ð)K¸;È!Ò;KÐ&Ð&à�[˜qˆFØ˜V F¨U¡NÐ2Ô3ˆHÝ˜ ¨%¡Ñ0Ô0×8Ò8¸ÑEÔEÀaÔHˆDà˜qÒ ÐL¥T¨(¡^¤^Ð%K¸ÀÒ8Kð 'ð
 "œ*Ø”Ø")¤.Ð?�h�h°iØ—i’i Ñ)Ô)Ø&Ý˜h™-œ-Ð/Ð/Ð/ð
ð 
ˆð Œ>ð 	6Ð8ð 	6ØÔ%×)Ò)¨*Ñ5Ô5Ð5Øˆs   ­A
Á
AÁAc           
      óè  — ddl m} ddlm} 	 t	          t          j        dd¦  «        ¦  «        }n# t          t          f$ r d}Y nw xY w|}|}d}|�|dk    r	dd	|› d
�dœS |r||k    r|}	d|› d|› d�}n|p|}	|  	                    |¦  «        }
|
€dd|› �dœS t          j        ¦   «         |	z   }t          j        ¦   «         |k     �r$|                      |
¦  «        }
|
€dd|› �dœS |                      |
¦  «         |
j        rV| j                             |¦  «         d|
j        |
j        |
j        |
j         ||
j        dd…         ¦  «        dœ}|r||d<   |S  |¦   «         r+d|
j         ||
j        dd…         ¦  «        ddœ}|r||d<   |S |t          j        ¦   «         z
  }|dk    rnA|
j                             t1          d|¦  «        ¬¦  «         t          j        ¦   «         |k     �°$d|
j         ||
j        dd…         ¦  «        ddœ}|
j        rt          j
        ¦   «         |
j        z
  nd}d|	› d�}|�|d t	          |¦  «        › d!�z  }|
j        r|d"z  }n|d#z  }|r|› d$|› �|d<   n||d<   |S )%aY  
        Block until a process exits, timeout, or interrupt.

        Args:
            session_id: The process to wait for.
            timeout: Max seconds to block. Falls back to TERMINAL_TIMEOUT config.

        Returns:
            dict with status ("exited", "timeout", "interrupted", "not_found")
            and output snapshot.
        r   ré  )Úis_interruptedÚTERMINAL_TIMEOUTÚ180é´   Nr  ztimeout must be positive (got ú)r  zRequested wait of z%s was clamped to configured limit of r™   r  r  r¬   rë  ©r<  r£   r­   r®   r¯   r  Útimeout_noteÚinterruptedr  z+User sent a new message -- wait interrupted)r<  r£   r  r  g      ð?r€  rW   T)r<  r£   r  Úprocess_runningzWait window of uA   s elapsed â€” the process is still running. This is not an error.z	 Uptime: r%  uc    notify_on_complete is set: you will be notified on exit â€” do more work instead of waiting again.zq Poll again later or use terminal(background=true, notify_on_complete=true) next time for automatic notification.z. )rí  rê  Útools.interruptr.  r&   r#   r$   r(   r7   r|   rZ   r[   r8  r  r¬   rè   r   r£   r­   r®   r¯   r°   rÉ   r‘  r4   rª   r½   )rñ   r  rW   rê  Ú_is_interruptedÚdefault_timeoutÚmax_timeoutÚrequested_timeoutr4  Úeffective_timeoutrÿ   rc  rr   Ú	remainingÚuptimeÚ	base_notes                   rE   r‘  zProcessRegistry.waitd  sÅ  € ð 	0Ð/Ð/Ð/Ð/Ð/ØEÐEÐEÐEÐEÐEð	"Ý!¥"¤)Ð,>ÀÑ"FÔ"FÑGÔGˆOˆOøÝ�IÐ&ð 	"ð 	"ð 	"Ø!ˆOˆOˆOð	"øøøà%ˆØ#ÐØˆð Ð(Ð->À!Ò-CÐ-Cà!ØNÐ:KÐNÐNÐNðð ð ð
 ð 	AÐ!2°[Ò!@Ð!@Ø +Ðð9Ð%6ð 9ð 9Ø*5ð9ð 9ð 9ð ˆLð
 !2Ð @°[Ðà—(’(˜:Ñ&Ô&ˆØˆ?Ø)Ð4VÈ*Ð4VÐ4VÐWÐWÐWå”>Ñ#Ô#Ð&7Ñ7ˆåŒnÑÔ Ò)Ñ)Ø×4Ò4°WÑ=Ô=ˆGØˆØ"-Ð8ZÈjÐ8ZÐ8ZÐ[Ð[Ð[ð ×&Ò& wÑ/Ô/Ð/ØŒ~ð ØÔ)×-Ò-¨jÑ9Ô9Ð9à&Ø&œØ!(Ô!2Ø)0Ô)BØ*1Ô*DØ(˜j¨Ô)>¸u¸v¸vÔ)FÑGÔGðð �ð  ð :Ø-9�F˜>Ñ*Ø�àˆÑ Ô ð 	à+Ø&œØ(˜j¨Ô)>¸u¸v¸vÔ)FÑGÔGØIð	ð �ð  ð :Ø-9�F˜>Ñ*Ø�à ¥4¤>Ñ#3Ô#3Ñ3ˆIØ˜AŠ~ˆ~ØØÔ%×*Ò*µ3°s¸IÑ3FÔ3FÐ*ÑGÔGÐGõI ŒnÑÔ Ò)Ñ)ðN  Ø”Ø �j Ô!6°u°v°vÔ!>Ñ?Ô?ð  $ð
ð 
ˆð 6=Ô5GÐQ•”‘”˜wÔ1Ñ1Ð1ÈTˆð3Ð/ð 3ð 3ð 3ð 	ð ÐØÐ4¥S¨¡[¤[Ð4Ð4Ð4Ñ4ˆIØÔ%ð 		Øð9ñˆIˆIð
 ðQñˆIð ð 	/Ø(4Ð%CÐ%C¸	Ð%CÐ%CˆF�>Ñ"Ð"à%.ˆF�>Ñ"Øˆs   Ž"1 ±AÁAzprocess.kill©ÚsourceÚconsume_outputrA  rB  c                óÔ  — ddl m} |                      |¦  «        }|€dd|› �dœS |j        r‹|j        rt          |j        ¦  «         |j        5  d|j        |j        |j	        |j
         ||j        dd…         ¦  «        d	œ}ddd¦  «         n# 1 swxY w Y   |r| j                             |¦  «         |S 	 |j        rZ	 |j                             d
¬¦  «         �n™# t           $ r/ |j        r$t%          j        |j        t(          j        ¦  «         Y �naw xY w|j        r'|                      |j        j        |j        ¦  «         �n/|j        r-|j        r&|j                             d|j        › d�d¬¦  «         nû|j        rï|j        dk    rä|j        rÝ|                      |j        |j        ¦  «        sœ|j        rt          |j        ¦  «         |j        5  d
|_        d|_         ||j        dd…         ¦  «        }ddd¦  «         n# 1 swxY w Y   |r| j                             |¦  «         |                      |¦  «         d|j        |dœS |                      |j        |j        ¦  «         ndddœS |j        rt          |j        ¦  «         |j        5   ||j        dd…         ¦  «        }|r| j                             |¦  «         d
|_        d|_        d|_	        ||_
        ddd¦  «         n# 1 swxY w Y   |                      |¦  «         |                      ¦   «          d|j         |j	        |j
        |dœS # t           $ r}dtC          |¦  «        dœcY d}~S d}~ww xY w)uN  Kill a background process and return its output snapshot.

        ``consume_output`` is true for explicit tool/RPC kills because their
        caller observes the returned output. Bulk cleanup passes false: it
        discards each result and therefore must not suppress an autonomous
        output-bearing completion notification. Exception: abandoned-turn
        reaping (``kill_started_since``) is bulk cleanup that deliberately
        passes true â€” a killed abandoned process must not enqueue a synthetic
        follow-up that revives work the timeout/interrupt stopped.
        r   ré  Nr  r  r  Úalready_exitedrë  r3  T)Úforcezkill rÔ  r  r€  r³   )r<  r­   r  r  zkRecovered process cannot be killed after restart because its original runtime handle is no longer availableéñÿÿÿr¿  )r<  r  r®   r¯   r  )"rí  rê  r|   r¬   rµ   r•   rÊ   r£   r­   r®   r¯   r°   rè   r   rÌ   r]  rl   r¦   r#   rT  rU  rV  r§   rd  r«   r¨   r­  r²   r´   r5  r7  r‰  r¢   rÑ   )	rñ   r  rA  rB  rê  rÿ   rr   r  r�  s	            rE   Úkill_processzProcessRegistry.kill_processÛ  sð  € ð" 	0Ð/Ð/Ð/Ð/Ð/à—(’(˜:Ñ&Ô&ˆØˆ?Ø)Ð4VÈ*Ð4VÐ4VÐWÐWÐWàŒ>ð 	ð
 Ô#ð 9Ý" 7Ô#7Ñ8Ô8Ð8Ø”ð ð à.Ø&œØ!(Ô!2Ø)0Ô)BØ*1Ô*DØ(˜j¨Ô)>¸u¸v¸vÔ)FÑGÔGðð �ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð ð :ØÔ)×-Ò-¨jÑ9Ô9Ð9ØˆMðO	8ØŒ|ð .ð=Ø”L×*Ò*°Ð*Ñ6Ô6Ð6Ñ6øÝ ð =ð =ð =Ø”{ð =Ýœ ¤­V¬^Ñ<Ô<Ð<øùð=øøøð ”ð 'ð ×(Ò(¨¬Ô)<¸gÔ>UÑVÔVÐVÑVØ”ð " W¤[ð "à”×'Ò'Ð(I°´Ð(IÐ(IÐ(IÐSTÐ'ÑUÔUÐUÐUØÔ!ð  gÔ&7¸6Ò&AÐ&AÀgÄkÐ&Að ×-Ò-¨g¬k¸7Ô;RÑSÔSð ØÔ+ð AÝ*¨7Ô+?Ñ@Ô@Ð@Ø œð Kð KØ)-˜œØ,0˜Ô)Ø!+ ¨GÔ,AÀ%À&À&Ô,IÑ!JÔ!J˜ðKð Kð Kñ Kô Kð Kð Kð Kð Kð Kð Køøøð Kð Kð Kð Kð &ð BØÔ1×5Ò5°jÑAÔAÐAØ×*Ò*¨7Ñ3Ô3Ð3à"2Ø%,Ô%6Ø"(ðð ð ð
 ×(Ò(¨¬°gÔ6MÑNÔNÐNÐNð &ðMðð ð ð Ô#ð 9Ý" 7Ô#7Ñ8Ô8Ð8ð ”ð 4ð 4Ø#˜ GÔ$9¸%¸&¸&Ô$AÑBÔB�Ø!ð >ØÔ-×1Ò1°*Ñ=Ô=Ð=Ø!%�”Ø$'�Ô!Ø,4�Ô)Ø-3�Ô*ð4ð 4ð 4ñ 4ô 4ð 4ð 4ð 4ð 4ð 4ð 4øøøð 4ð 4ð 4ð 4ð ×"Ò" 7Ñ+Ô+Ð+Ø×"Ò"Ñ$Ô$Ð$à"Ø%œjØ%,Ô%>Ø&-Ô&@Ø ðð ð øõ ð 	8ð 	8ð 	8Ø%µ°A±´Ð7Ð7Ð7Ð7Ð7Ð7Ð7Ð7øøøøð	8øøøs«   Á4BÂBÂBÂ9M ÃC ÃM Ã5DÄM ÄDÄC M Ç'H
Ç>M È
HÈM ÈHÈ>M É%M É7"M ÊAK6Ë*M Ë6K:Ë:M Ë=K:Ë>AM Í
M'ÍM"ÍM'Í"M'Údatac                 ó0  — |                       |¦  «        }|€dd|› �dœS |j        rdddœS t          |d¦  «        rË|j        rÄ	 t          r:t          |t          ¦  «        r|                     d¦  «        nt          |¦  «        }n-t          |t          ¦  «        r| 	                    dd	¦  «        n|}|j         
                    |¦  «         d
t          |¦  «        dœS # t          $ r}dt          |¦  «        dœcY d}~S d}~ww xY w|j        r|j        j        sdddœS 	 |j        j         
                    |¦  «         |j        j                             ¦   «          d
t          |¦  «        dœS # t          $ r}dt          |¦  «        dœcY d}~S d}~ww xY w)zASend raw data to a running process's stdin (no newline appended).Nr  r  r  rD  úProcess has already finishedrÌ   r   ÚsurrogateescapeÚok)r<  Úbytes_writtenr  ú?Process stdin not available (non-local backend or stdin closed))r|   r¬   ræ  rÌ   r_   rj  Úbytesrk   rÑ   ÚencodeÚwriter  rl   r§   rM  Úflush)rñ   r  rH  rÿ   Úpty_datar�  s         rE   Úwrite_stdinzProcessRegistry.write_stdinZ  sô  € à—(’(˜:Ñ&Ô&ˆØˆ?Ø)Ð4VÈ*Ð4VÐ4VÐWÐWÐWØŒ>ð 	YØ.Ð9WÐXÐXÐXõ �7˜FÑ#Ô#ð 	<¨¬ð 	<ð<åð jÝ7AÀ$ÍÑ7NÔ7NÐ]˜tŸ{š{¨7Ñ3Ô3Ð3ÕTWÐX\ÑT]ÔT]�H�Hõ KUÐUYÕ[^ÑJ_ÔJ_Ði˜tŸ{š{¨7Ð4EÑFÔFÐFÐei�HØ”×"Ò" 8Ñ,Ô,Ð,Ø"&½¸T¹¼ÐCÐCÐCøÝð <ð <ð <Ø")µC¸±F´FÐ;Ð;Ð;Ð;Ð;Ð;Ð;Ð;øøøøð<øøøð Œð 	s g¤oÔ&;ð 	sØ%Ð0qÐrÐrÐrð	8ØŒOÔ!×'Ò'¨Ñ-Ô-Ð-ØŒOÔ!×'Ò'Ñ)Ô)Ð)Ø"µS¸±Y´YÐ?Ð?Ð?øÝð 	8ð 	8ð 	8Ø%µ°A±´Ð7Ð7Ð7Ð7Ð7Ð7Ð7Ð7øøøøð	8øøøs>   ÁBC Ã
DÃ(C?Ã9DÃ?DÄ AE/ Å/
FÅ9FÆ
FÆFc                 ó4   — |                       ||dz   ¦  «        S )zGSend data + newline to a running process's stdin (like pressing Enter).rö   )rT  )rñ   r  rH  s      rE   Úsubmit_stdinzProcessRegistry.submit_stdin{  s   € à×Ò 
¨D°4©KÑ8Ô8Ð8rX   c                 óÂ   — | j         }|€dddœS |                      |¦  «        }	  |||¦  «         n)# t          $ r}dt          |¦  «        dœcY d}~S d}~ww xY wd|ddœS )uy  Ask the desktop GUI to close the read-only terminal tab mirroring this
        background process.

        This does NOT kill the process â€” it only drops the view. Output keeps
        streaming into the (capped) buffer and the user can reopen the tab from
        the status stack. Desktop-only: returns an error if no UI close sink is
        wired (e.g. CLI / messaging).Nr  z;close_terminal is only available in the Hermes desktop app.r  rL  z’Closed the read-only terminal tab. The process was not killed; its output remains available and the user can reopen the tab from the status stack.)r<  Úclosedr  )rð   r|   rl   rÑ   )rñ   r  r  rÿ   r�  s        rE   Úrequest_close_terminalz&ProcessRegistry.request_close_terminal  s°   € ð Œ}ˆØˆ<à!ØVðð ð ð —(’(˜:Ñ&Ô&ˆð	8ØˆD�˜*Ñ%Ô%Ð%Ð%øÝð 	8ð 	8ð 	8Ø%µ°A±´Ð7Ð7Ð7Ð7Ð7Ð7Ð7Ð7øøøøð	8øøøð Ø ð)ð	
ð 
ð 	
s   ¥2 ²
A¼AÁAÁAc                 óà  — |                       |¦  «        }|€dd|› �dœS |j        rdddœS t          |d¦  «        rO|j        rH	 |j                             ¦   «          dd	d
œS # t
          $ r}dt          |¦  «        dœcY d}~S d}~ww xY w|j        r|j        j        sdddœS 	 |j        j         	                    ¦   «          ddd
œS # t
          $ r}dt          |¦  «        dœcY d}~S d}~ww xY w)zGClose a running process's stdin / send EOF without killing the process.Nr  r  r  rD  rJ  rÌ   rL  zEOF sent)r<  r  r  rN  zstdin closed)
r|   r¬   ræ  rÌ   Úsendeofrl   rÑ   r§   rM  Úclose)rñ   r  rÿ   r�  s       rE   Úclose_stdinzProcessRegistry.close_stdinž  sb  € à—(’(˜:Ñ&Ô&ˆØˆ?Ø)Ð4VÈ*Ð4VÐ4VÐWÐWÐWØŒ>ð 	YØ.Ð9WÐXÐXÐXå�7˜FÑ#Ô#ð 	<¨¬ð 	<ð<Ø”×$Ò$Ñ&Ô&Ð&Ø"&°:Ð>Ð>Ð>øÝð <ð <ð <Ø")µC¸±F´FÐ;Ð;Ð;Ð;Ð;Ð;Ð;Ð;øøøøð<øøøð Œð 	s g¤oÔ&;ð 	sØ%Ð0qÐrÐrÐrð	8ØŒOÔ!×'Ò'Ñ)Ô)Ð)Ø"¨~Ð>Ð>Ð>øÝð 	8ð 	8ð 	8Ø%µ°A±´Ð7Ð7Ð7Ð7Ð7Ð7Ð7Ð7øøøøð	8øøøs<   ÁA" Á"
BÁ,BÁ=BÂBÂ$"C Ã
C-ÃC(Ã"C-Ã(C-c                 óN   — 	 t          | j        ¦  «        S # t          $ r Y dS w xY w)ak  Return the count of currently-running background processes.

        Cheap O(1) read of the running dict, suitable for status-bar polling
        on every render tick. CPython dict ``len()`` is atomic; callers do not
        need to hold ``self._lock``. Reflects ``_running`` only: sessions are
        moved to ``_finished`` when their subprocess exits.
        r   )r  rà   rl   )rñ   s    rE   Úcount_runningzProcessRegistry.count_runningµ  s9   € ð	Ý�t”}Ñ%Ô%Ð%øÝð 	ð 	ð 	Ø�1�1ð	øøøs   ‚ –
$£$c                 ó„  ‡ ‡‡— ‰ j         5  t          ‰ j                             ¦   «         ¦  «        t          ‰ j                             ¦   «         ¦  «        z   }ddd¦  «         n# 1 swxY w Y   ˆ fd„|D ¦   «         }‰s‰rˆˆfd„|D ¦   «         }g }|D �])}|j        |j        dd…         |j        |j        t          j
        dt          j        |j        ¦  «        ¦  «        t          t          j	        ¦   «         |j        z
  ¦  «        |j        rdnd|j        r|j        dd…         nd	d
œ}‰r‰r|j        ‰k    r|j        ‰k    rd|d<   |j        r,|j        s%t          |j        ¦  «        |d<   |j        dk    |d<   |j        rd|d<   |j        r
|j        |d<   |j        rd|d<   |                     |¦  «         �Œ+|S )u  List all running and recently-finished processes.

        When ``task_id`` is given, processes for that task are included. When
        ``session_key`` is also given, session-scoped background processes
        (``background: true``) registered under that gateway session are
        surfaced too, even if they belong to a different task â€” so the agent
        can discover a forgotten preview server that is blocking session
        reset (#29177). Such cross-task entries are flagged with
        ``"session_scoped": true``.
        Nc                 ó:   •— g | ]}‰                      |¦  «        ‘ŒS rŽ   )r8  )r�   r™   rñ   s     €rE   ú
<listcomp>z1ProcessRegistry.list_sessions.<locals>.<listcomp>Ð  s'   ø€ ÐPÐPÐP¸a˜×6Ò6°qÑ9Ô9ÐPÐPÐPrX   c                 óH   •— g | ]}‰r|j         ‰k    s‰r|j        ‰k    ¯|‘ŒS rŽ   ©r¤   r¥   )r�   r™   r¥   r¤   s     €€rE   rb  z1ProcessRegistry.list_sessions.<locals>.<listcomp>Ó  sM   ø€ ð ð ð ØØðà !¤	¨WÒ 4Ð 4Øð !5Ø$%¤M°[Ò$@Ð$@ð à$@Ð$@Ð$@rX   r!  z%Y-%m-%dT%H:%M:%Sr¬   r  i8ÿÿÿr   )r  r£   r©   r¦   rª   r  r<  r  TÚsession_scopedr¿   r   Ú	watch_hitr½   r­   r²   )rÊ   r×   rà   Úvaluesrá   r¢   r£   r©   r¦   rZ   ÚstrftimeÚ	localtimerª   r&   r¬   r°   r¤   r¥   r¿   rÄ   rÂ   r½   r­   r²   r1   )rñ   r¤   r¥   Úall_sessionsrr   r™   Úentrys   ```    rE   Úlist_sessionszProcessRegistry.list_sessionsÂ  sm  øøø€ ð ŒZð 	Xð 	XÝ ¤× 4Ò 4Ñ 6Ô 6Ñ7Ô7½$¸t¼~×?TÒ?TÑ?VÔ?VÑ:WÔ:WÑWˆLð	Xð 	Xð 	Xñ 	Xô 	Xð 	Xð 	Xð 	Xð 	Xð 	Xð 	Xøøøð 	Xð 	Xð 	Xð 	Xð QÐPÐPÐPÀ<ÐPÑPÔPˆàð 	�kð 	ðð ð ð ð Ø'ðñ ô ˆLð ˆØð 	!ñ 	!ˆAàœdØœ9 T c Tœ?Ø”uØ”uÝ"œmÐ,?ÅÄÐPQÔP\ÑA]ÔA]Ñ^Ô^Ý"%¥d¤i¡k¤k°A´LÑ&@Ñ"AÔ"AØ&'¤hÐ=˜(˜(°IØ<=¼OÐ"S !¤/°$°%°%Ô"8Ð"8ÐQSð	ð 	ˆEð ð /˜;ð /¨1¬9¸Ò+?Ð+?ÀAÄMÐU`ÒD`ÐD`Ø*.�Ð&Ñ'ð Ôð 7¨Ô(9ð 7Ý*.¨qÔ/?Ñ*@Ô*@�Ð&Ñ'Ø%&¤]°QÒ%6��kÑ"ØÔ#ð 3Ø.2�Ð*Ñ+ØŒxð 1Ø%&¤[��kÑ"ØŒzð )Ø$(��jÑ!Ø�MŠM˜%Ñ Ô Ð Ñ Øˆs   ‹AA%Á%A)Á,A)c                 óh  ‡— | j         5  t          | j                             ¦   «         ¦  «        }ddd¦  «         n# 1 swxY w Y   |D ]}|                      |¦  «         Œ| j         5  t          ˆfd„| j                             ¦   «         D ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS )z<Check if there are active (running) processes for a task_id.Nc              3   ó>   •K  — | ]}|j         ‰k    o|j         V — Œd S r�   )r¤   r¬   ©r�   r™   r¤   s     €rE   r’   z7ProcessRegistry.has_active_processes.<locals>.<genexpr>	  sG   øè è € ð ð àð ”	˜WÒ$Ð5¨Q¬X¨ðð ð ð ð ð rX   ©rÊ   r×   rà   rg  r8  r”   )rñ   r¤   Úsessionsrÿ   s    `  rE   Úhas_active_processesz$ProcessRegistry.has_active_processesû  sP  ø€ àŒZð 	4ð 	4Ý˜DœM×0Ò0Ñ2Ô2Ñ3Ô3ˆHð	4ð 	4ð 	4ñ 	4ô 	4ð 	4ð 	4ð 	4ð 	4ð 	4ð 	4øøøð 	4ð 	4ð 	4ð 	4ð  ð 	4ð 	4ˆGØ×*Ò*¨7Ñ3Ô3Ð3Ð3àŒZð 	ð 	Ýð ð ð ð àœ×-Ò-Ñ/Ô/ðñ ô ñ ô ð	ð 	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s!   ‰'<¼A ÁA Á(2B'Â'B+Â.B+Úmax_active_agec                 ó–  ‡‡‡— | j         5  t          | j                             ¦   «         ¦  «        }ddd¦  «         n# 1 swxY w Y   |D ]}|                      |¦  «         Œt          j        ¦   «         Š| j         5  t          ˆˆˆfd„| j                             ¦   «         D ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS )uÀ  Check if there are active processes for a gateway session key.

        When *max_active_age* is set (seconds), processes that started more
        than that many seconds ago are **ignored** â€” they are still running
        but are considered stale and must not block session idle / daily
        reset.  This prevents a forgotten ``http.server`` (or any long-lived
        preview process) from permanently freezing the session lifecycle.

        Args:
            session_key: Gateway session key to check.
            max_active_age: If set, ignore processes older than this many
                seconds.  ``None`` retains the legacy behaviour (any running
                process blocks).
        Nc              3   ób   •K  — | ])}|j         ‰k    o|j         o‰d u p‰|j        z
  ‰k     V — Œ*d S r�   )r¥   r¬   rª   )r�   r™   rs  rn   r¥   s     €€€rE   r’   z9ProcessRegistry.has_active_for_session.<locals>.<genexpr>"	  sl   øè è € ð ð ð ð ” Ò,ð VØœ�LðVà# tÐ+ÐT°°a´lÑ0BÀnÒ/Tðð ð ð ð ð rX   )rÊ   r×   rà   rg  r8  rZ   r”   )rñ   r¥   rs  rq  rÿ   rn   s    ``  @rE   Úhas_active_for_sessionz&ProcessRegistry.has_active_for_session		  sk  øøø€ ð" ŒZð 	4ð 	4Ý˜DœM×0Ò0Ñ2Ô2Ñ3Ô3ˆHð	4ð 	4ð 	4ñ 	4ô 	4ð 	4ð 	4ð 	4ð 	4ð 	4ð 	4øøøð 	4ð 	4ð 	4ð 	4ð  ð 	4ð 	4ˆGØ×*Ò*¨7Ñ3Ô3Ð3Ð3åŒi‰kŒkˆØŒZð 	ð 	Ýð ð ð ð ð ð ð œ×-Ò-Ñ/Ô/ð	ñ ô ñ ô ð	ð 	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s!   ‹'>¾AÁAÁ=4B>Â>CÃCc                 ób  — | j         5  t          | j                             ¦   «         ¦  «        }ddd¦  «         n# 1 swxY w Y   |D ]}|                      |¦  «         Œ| j         5  t          d„ | j                             ¦   «         D ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS )a‰  Whether ANY background process is still running (across all sessions).

        Used by scale-to-zero idle detection (gateway/scale_to_zero): a gateway
        with a live background process (terminal background=true) is NOT idle and
        must not be suspended, or the process is lost. Refreshes detached
        sessions first so a finished-but-unreaped process reads as inactive.
        Nc              3   ó&   K  — | ]}|j          V — Œd S r�   )r¬   )r�   r™   s     rE   r’   z1ProcessRegistry.has_any_active.<locals>.<genexpr>8	  s&   è è € ÐDÐD¨˜1œ8�|ÐDÐDÐDÐDÐDÐDrX   rp  )rñ   rq  rÿ   s      rE   Úhas_any_activezProcessRegistry.has_any_active)	  sL  € ð ŒZð 	4ð 	4Ý˜DœM×0Ò0Ñ2Ô2Ñ3Ô3ˆHð	4ð 	4ð 	4ñ 	4ô 	4ð 	4ð 	4ð 	4ð 	4ð 	4ð 	4øøøð 	4ð 	4ð 	4ð 	4ð  ð 	4ð 	4ˆGØ×*Ò*¨7Ñ3Ô3Ð3Ð3àŒZð 	Eð 	EÝÐDÐD¨T¬]×-AÒ-AÑ-CÔ-CÐDÑDÔDÑDÔDð	Eð 	Eð 	Eð 	Eñ 	Eô 	Eð 	Eð 	Eð 	Eð 	Eð 	Eð 	Eøøøð 	Eð 	Eð 	Eð 	Eð 	Eð 	Es   ˆ';»?Á?Á'0B$Â$B(Â+B(c                 óª   ‡— | j         5  t          ˆfd„| j                             ¦   «         D ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS )aO  Capture running process IDs owned by ``task_id``.

        Gateway turns use this as a boundary marker: if a turn times out, only
        processes absent from its starting snapshot belong to the abandoned
        turn. Older session processes must survive because background tasks
        intentionally span successful turns.
        c              3   óJ   •K  — | ]}|j         ‰k    ¯|j        °|j        V — Œd S r�   )r¤   r¬   r¢   ro  s     €rE   r’   z7ProcessRegistry.snapshot_running_ids.<locals>.<genexpr>C	  sE   øè è € ð ð àØ”9 Ò'Ð'°´Ð'ð ”à'Ð'Ð'Ð'ðð rX   N)rÊ   Ú	frozensetrà   rg  )rñ   r¤   s    `rE   Úsnapshot_running_idsz$ProcessRegistry.snapshot_running_ids:	  s²   ø€ ð ŒZð 	ð 	Ýð ð ð ð àœ×-Ò-Ñ/Ô/ðñ ô ñ ô ð	ð 	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s   ‰2AÁAÁAc                óR   — |                       |t          |pd¦  «        |d¬¦  «        S )zòKill processes created for ``task_id`` after a prior snapshot.

        ``consume_output`` is forced on: abandoned-turn output must not
        enqueue a synthetic follow-up that revives work the timeout
        deliberately stopped.
        rŽ   T©Úexclude_idsrA  rB  )Úkill_allr|  )rñ   r¤   Úbaseline_idsrA  s       rE   Úkill_started_sincez"ProcessRegistry.kill_started_sinceI	  s8   € ð �}Š}ØÝ! ,Ð"4°"Ñ5Ô5ØØð	 ñ 
ô 
ð 	
rX   r�  r  r€  c                ó  ‡‡— | j         5  ˆˆfd„| j                             ¦   «         D ¦   «         }ddd¦  «         n# 1 swxY w Y   d}|D ];}|                      |j        ||¬¦  «        }|                     d¦  «        dv r|dz  }Œ<|S )zQKill all running processes, optionally filtered by task_id. Returns count killed.c                 óN   •— g | ]!}‰�|j         ‰k    r|j        ‰v¯|j        °|‘Œ"S r�   )r¤   r¢   r¬   )r�   r™   r€  r¤   s     €€rE   rb  z,ProcessRegistry.kill_all.<locals>.<listcomp>g	  sK   ø€ ð ð ð ØØ�O q¤y°GÒ';Ð';Ø”D Ð+Ð+Øœð ,ð à+Ð+Ð+rX   Nr   r@  r<  >   r¿  rD  r  )rÊ   rà   rg  rG  r¢   r|   )	rñ   r¤   r€  rA  rB  ra  r¿  rÿ   rr   s	    ``      rE   r�  zProcessRegistry.kill_all]	  s  øø€ ð ŒZð 	ð 	ðð ð ð ð Øœ=×/Ò/Ñ1Ô1ðñ ô ˆGð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð ˆØð 	ð 	ˆGØ×&Ò&Ø”
ØØ-ð 'ñ ô ˆFð
 �zŠz˜(Ñ#Ô#Ð'CÐCÐCØ˜!‘�øØˆs   Š'=½AÁAc                 óö  ‡ ‡— t          j         ¦   «         Šˆfd„‰ j                             ¦   «         D ¦   «         }|D ]>}‰ j        |= ‰ j                             |¦  «         ‰ j                             |¦  «         Œ?t          ‰ j        ¦  «        t          ‰ j        ¦  «        z   }|t          k    r\‰ j        rUt          ‰ j        ˆ fd„¬¦  «        }‰ j        |= ‰ j                             |¦  «         ‰ j                             |¦  «         ‰ j         
                    ¦   «         ‰ j         
                    ¦   «         z  }‰ j        |z
  }|r‰ xj        |z  c_        ‰ j        |z
  }|r‰ xj        |z  c_        dS dS )zGRemove oldest finished sessions if over MAX_PROCESSES. Must hold _lock.c                 ó@   •— g | ]\  }}‰|j         z
  t          k    ¯|‘ŒS rŽ   )rª   ÚFINISHED_TTL_SECONDS)r�   Úsidr™   rn   s      €rE   rb  z4ProcessRegistry._prune_if_needed.<locals>.<listcomp>	  s:   ø€ ð 
ð 
ð 
Ù�C˜Ø�a”lÑ"Õ&:Ò:Ð:ð Ø:Ð:Ð:rX   c                 ó(   •— ‰j         |          j        S r�   )rá   rª   )r‰  rñ   s    €rE   ú<lambda>z2ProcessRegistry._prune_if_needed.<locals>.<lambda>‹	  s   ø€ ¸D¼NÈ3Ô<OÔ<Z€ rX   ©ÚkeyN)rZ   rá   Úitemsrè   Údiscardré   r  rà   ÚMAX_PROCESSESr4   Úkeys)	rñ   Úexpiredr‰  ÚtotalÚ	oldest_idÚtrackedÚstaleÚstale_pollsrn   s	   `       @rE   rˆ  z ProcessRegistry._prune_if_needed{	  s¥  øø€ õ Œi‰kŒkˆð
ð 
ð 
ð 
Ø"œn×2Ò2Ñ4Ô4ð
ñ 
ô 
ˆð ð 	-ð 	-ˆCØ”˜sÐ#ØÔ%×-Ò-¨cÑ2Ô2Ð2ØÔ×'Ò'¨Ñ,Ô,Ð,Ð,õ �D”MÑ"Ô"¥S¨¬Ñ%8Ô%8Ñ8ˆØ•MÒ!Ð! d¤nÐ!Ý˜DœNÐ0ZÐ0ZÐ0ZÐ0ZÐ[Ñ[Ô[ˆIØ”˜yÐ)ØÔ%×-Ò-¨iÑ8Ô8Ð8ØÔ×'Ò'¨	Ñ2Ô2Ð2ð ”-×$Ò$Ñ&Ô&¨¬×)<Ò)<Ñ)>Ô)>Ñ>ˆØÔ)¨GÑ3ˆØð 	/ØÐ%Ô%¨Ñ.Ð%Ô%ØÔ)¨GÑ3ˆØð 	/ØÐÔ ;Ñ.ÐÔÐÐð	/ð 	/rX   Úextra_entriesc           
      ón  ‡— 	 | j         5  g }| j                             ¦   «         D ]ü}|j        só|j        €1|j        dk    r&|j        r|                      |j        ¦  «        |_        |                     i d|j	        “dt          |j        d¬¦  «        “d|j        “d|j        “d	|j        “d
|j        “d|j        “d|j        “d|j        “d|j        “d|j        “d|j        “d|j        “d|j        “d|j        “d|j        “d|j        “|j        |j        dœ¥¦  «         Œý|r-d„ |D ¦   «         Š|                     ˆfd„|D ¦   «         ¦  «         ddd¦  «         n# 1 swxY w Y   ddlm}  |t:          |¦  «         dS # t<          $ r(}t>                                d|d¬¦  «         Y d}~dS d}~ww xY w)z=Write running process metadata to checkpoint file atomically.Nr³   r  r£   T©Ú	code_filer¦   r´   r«   rµ   r©   rª   r¤   r¥   r¶   r·   r¸   r¹   rº   r»   r¼   )r½   r¿   c                 ó8   — h | ]}|                      d ¦  «        ’ŒS )r  ©r|   )r�   Úitems     rE   ú	<setcomp>z4ProcessRegistry._write_checkpoint.<locals>.<setcomp>Ê	  s$   € Ð"NÐ"NÐ"N¸d 4§8¢8¨LÑ#9Ô#9Ð"NÐ"NÐ"NrX   c              3   óJ   •K  — | ]}|                      d ¦  «        ‰v¯|V — ŒdS )r  Nr�  )r�   rž  Útracked_idss     €rE   r’   z4ProcessRegistry._write_checkpoint.<locals>.<genexpr>Ë	  sF   øè è € ð #ð #à ØŸ8š8 LÑ1Ô1¸ÐDÐDð àDÐDÐDÐDð#ð #rX   r   )Úatomic_json_writez#Failed to write checkpoint file: %s)Úexc_info)!rÊ   rà   rg  r¬   r«   r´   r¦   r1  r1   r¢   r   r£   rµ   r©   rª   r¤   r¥   r¶   r·   r¸   r¹   rº   r»   r¼   r½   r¿   ÚextendÚutilsr¢  ÚCHECKPOINT_PATHrl   r)   ri   )rñ   r˜  Úentriesr™   r¢  r�  r¡  s         @rE   r‰  z!ProcessRegistry._write_checkpointž	  sÜ  ø€ ð
2	RØ”ð +ð +Ø�Øœ×-Ò-Ñ/Ô/ð "ð "�AØœ8ð !ð Ô,Ð4¸¼ÈÒ9NÐ9NÐSTÔSXÐ9NØ04×0JÒ0JÈ1Ì5Ñ0QÔ0Q˜AÔ-ØŸšð (Ø(¨!¬$ð(ð &Õ'<¸Q¼YÐRVÐ'WÑ'WÔ'Wð(ð " 1¤5ð(ð (¨¬ð(ð .¨qÔ/@ð(ð +¨A¬Nð(ð " 1¤5ð(ð )¨!¬,ð(ð  & q¤yð!(ð" *¨1¬=ð#(ð$ /°Ô0Bð%(ð& .¨qÔ/@ð'(ð( .¨qÔ/@ð)(ð* 0°Ô1Dð+(ð, 0°Ô1Dð-(ð. 1°!Ô2Fð/(ð0 /°Ô0Bð1(ð2 34Ô2FØ./Ô.>ð5(ð (ð (ñ ô ð øð8 !ð Ø"NÐ"NÀgÐ"NÑ"NÔ"N�KØ—N’Nð #ð #ð #ð #à$1ð#ñ #ô #ñ ô ð ðO+ð +ð +ñ +ô +ð +ð +ð +ð +ð +ð +øøøð +ð +ð +ð +ð\ 0Ð/Ð/Ð/Ð/Ð/ØÐ�o¨wÑ7Ô7Ð7Ð7Ð7øÝð 	Rð 	Rð 	RÝ�LŠLÐ>ÀÈDˆLÑQÔQÐQÐQÐQÐQÐQÐQÐQøøøøð	Røøøs;   ƒF ŠEEÅF ÅE"Å"F Å%E"Å&F Æ
F4ÆF/Æ/F4c                 óú  — t                                ¦   «         sdS 	 t          j        t                                d¬¦  «        ¦  «        }n# t
          $ r Y dS w xY wd}g }|D �]�}|                     d¦  «        }|sŒ|                     dd¦  «        }|dk    r:t                               d|                     dd	¦  «        d
d…         ||¦  «         Œq|                     d¦  «        }|  	                    ||¦  «        sŸ|  
                    |¦  «        r0t                               d|                     dd¦  «        |¦  «         |                     dd¦  «        }|r@t          |¦  «        s1t                               d||¦  «         |                     |¦  «         �Œ;t          d(i d|d         “d|                     dd	¦  «        “d|                     dd¦  «        “d|                     dd¦  «        “d|“d|“d|“d|                     dd¦  «        “d|                     d¦  «        “d|                     dt          j        ¦   «         ¦  «        “dd“d|                     dd¦  «        “d|                     dd¦  «        “d|                     dd¦  «        “d|                     dd¦  «        “d|                     dd¦  «        “d|                     dd¦  «        “d |                     d d¦  «        “d!|                     d!d"¦  «        “d#|                     d#g ¦  «        “Ž}	| j        5  |	| j        |	j        <   d
d
d
¦  «         n# 1 swxY w Y   |d$z  }t                               d%|	j        d
d…         |¦  «         |	j        dk    rW| j                             |	j        |	j        |	j        |	j        |	j        |	j        |	j        |	j        |	j        |	j        d&œ
¦  «         �Œƒ|                      |¬'¦  «         |S ))z†
        On gateway startup, probe PIDs from checkpoint file.

        Returns the number of processes recovered as detached.
        r   r   r   r¦   r´   r³   z=Skipping recovery for non-host process: %s (pid=%s, scope=%s)r£   ÚunknownNr˜   r«   u•   Not recovering session %s: pid %d is alive but its start time no longer matches â€” PID was recycled onto an unrelated process; refusing to adopt it.r  ú?rµ   r   zjCould not reap persisted scope %s for dead wrapper pid %s; retaining checkpoint entry for the next startupr¢   r¤   r¥   r©   rª   r²   Tr¶   r·   r¸   r¹   rº   r»   r¼   r½   Fr¿   r  z'Recovered detached process: %s (pid=%d))
r  Úcheck_intervalr¥   r  r  r  r  r  r  r½   )r˜  rŽ   )r¦  ÚexistsÚjsonÚloadsr+   rl   r|   r)   r_  r5  r.  r•   r*   r1   r¡   rZ   rÊ   rà   r¢   r£   r¼   râ   r¥   r¶   r·   r¸   r¹   rº   r»   r½   r‰  )
rñ   r§  Ú	recoveredÚunresolved_scope_entriesrk  r¦   r´   Úrecorded_startrµ   rÿ   s
             rE   Úrecover_from_checkpointz'ProcessRegistry.recover_from_checkpoint×	  sú  € õ ×%Ò%Ñ'Ô'ð 	Ø�1ð	Ý”j¥×!:Ò!:ÀGÐ!:Ñ!LÔ!LÑMÔMˆGˆGøÝð 	ð 	ð 	Ø�1�1ð	øøøð ˆ	Ø9;Ð Øð T	ñ T	ˆEØ—)’)˜EÑ"Ô"ˆCØð ØàŸ	š	 +¨vÑ6Ô6ˆIØ˜FÒ"Ð"õ —’ØSØ—I’I˜i¨Ñ3Ô3°C°R°CÔ8ØØñ	ô ð ð ð #ŸYšYÐ'8Ñ9Ô9ˆNØ×)Ò)¨#¨~Ñ>Ô>ð Ø×*Ò*¨3Ñ/Ô/ð Ý—K’KðFð Ÿ	š	 ,°Ñ4Ô4°cñ	ô ð ð  %Ÿyšy¨¸Ñ<Ô<�Øð ;Õ(:¸<Ñ(HÔ(Hð ;Ý—N’NðJà$Øñ	ô ð ð -×3Ò3°EÑ:Ô:Ð:Ùå$ð ð ð Ø˜Ô&Ð&ðàŸ	š	 )¨YÑ7Ô7Ð7ðð Ÿ	š	 )¨RÑ0Ô0Ð0ðð "ŸIšI m°RÑ8Ô8Ð8ð	ð
 �Cðð !/ ðð $˜)ðð #ŸYšY ~°rÑ:Ô:Ð:ðð —I’I˜eÑ$Ô$Ð$ðð !Ÿ9š9 \µ4´9±;´;Ñ?Ô?Ð?ðð ˜ðð "'§¢Ð+=¸rÑ!BÔ!BÐ!Bðð !&§	¢	Ð*;¸RÑ @Ô @Ð @ðð !&§	¢	Ð*;¸RÑ @Ô @Ð @ðð #(§)¢)Ð,?ÀÑ"DÔ"DÐ"Dðð  #(§)¢)Ð,?ÀÑ"DÔ"DÐ"Dð!ð" $)§9¢9Ð-AÀ2Ñ#FÔ#FÐ#Fð#ð$ "'§¢Ð+=¸qÑ!AÔ!AÐ!Að%ð& $)§9¢9Ð-AÀ5Ñ#IÔ#IÐ#Ið'ð(  %ŸyšyÐ)9¸2Ñ>Ô>Ð>ð)ˆGð, ”ð 4ð 4Ø,3�”˜gœjÑ)ð4ð 4ð 4ñ 4ô 4ð 4ð 4ð 4ð 4ð 4ð 4øøøð 4ð 4ð 4ð 4à˜‰NˆIÝ�KŠKÐAÀ7Ä?ÐSVÐTVÐSVÔCWÐY\Ñ]Ô]Ð]ð Ô'¨!Ò+Ð+ØÔ%×,Ò,Ø")¤*Ø&-Ô&>Ø#*Ô#6Ø 'Ô 8Ø&Ô6Ø&Ô6Ø!(Ô!:Ø!(Ô!:Ø")Ô"<Ø*1Ô*Dð.ð .ñ ô ð ùð 	×ÒÐ-EÐÑFÔFÐFàÐs#   �-A Á
AÁAÌ,MÍM	ÍM	r�   )Nr   r   NF)Nr   r   r   )r   N)rÿ   r¡   r   N)Nr!  )r   )NN)?rÍ   rÎ   rÏ   rÐ   rû   ró   ÚstaticmethodrÑ   rþ   r¡   r  r!  rÔ   rÕ   r  r   r&   r.  r1  Úclassmethodr5  r8  r?  rI  rd  r   rl  Údictr¥  r¸  rŽ  r®  r†  r7  rñ  rô  rø  r
  r|   r  rÇ  r,  r‘  rG  rT  rV  rY  r]  r_  r×   rl  rr  rv  ry  r|  r}  rƒ  r�  rˆ  r   r   r‰  r²  rŽ   rX   rE   rÝ   rÝ   £  s«  € € € € € ðð ðÐð6ð 6ð 6ðp ð  ð  ¨ð  ð  ð  ñ „\ð ð	 Nð 	¸3ð 	À4ð 	ð 	ð 	ð 	ð~¨^ð ~Àsð ~Ètð ~ð ~ð ~ð ~ð@U uð U°ð Uð Uð Uð Uðn ð  ¨¤ð  °$ð  ð  ð  ñ „\ð ð ð 8¨C¤=ð °X¸c´]ð ð ð ñ „\ðð ð@ H¨S¤Mð @À8ÈCÄ=ð @ÐUYð @ð @ð @ñ „[ð@ð(°¸.Ô1Ið ÈhÐWeÔNfð ð ð ð ð, ð˜Tð ð ð ñ „\ðð ð¨ð ð ð ñ „\ðð" ð}ð } cð }¸8ÀC¼=ð }ÐTXð }ð }ð }ñ „[ð}ðB ð
˜3ð 
 3ð 
ð 
ð 
ñ „\ð
ð ØØØØðlð làðlð ðlð ð	lð
 ðlð ðlð ðlð 
ðlð lð lð lðd ØØØðbð bàðbð ðbð ð	bð
 ðbð ðbð ðbð 
ðbð bð bð bðLB, Nð B,ð B,ð B,ð B,ðH8Ø%ð8Ø,/ð8Ø;>ð8ØJMð8ØZ]ð8ð 8ð 8ð 8ðt1(¨ð 1(ð 1(ð 1(ð 1(ðf ¨ð  ð  ð  ð  ðH7°ð 7¸ð 7ð 7ð 7ð 7ð"¨Sð "°Tð "ð "ð "ð "ðJ >Bð
ð 
ð 
Øð
Ø6:ð
à	ð
ð 
ð 
ð 
ð& ØðUð
 $(ðUð Uð UàðUð
 !ðUð 
"ðUð Uð Uð Uðn7˜cð 7 h¨~Ô&>ð 7ð 7ð 7ð 7ðH(ð H(ð H(ð H(ðT)˜sð ) tð )ð )ð )ð )ðV(ð ( 3ð (°°d±
ð (È#ð (ÐX\ð (ð (ð (ð (ðTuð u˜sð u¨Sð u¸Dð uð uð uð uðv %Ø#ð}8ð }8ð }8àð}8ð ð	}8ð
 ð}8ð 
ð}8ð }8ð }8ð }8ð~8 cð 8°ð 8¸ð 8ð 8ð 8ð 8ðB9ð 9 sð 9°#ð 9¸tð 9ð 9ð 9ð 9ð
°ð 
¸ð 
ð 
ð 
ð 
ð>8 cð 8¨dð 8ð 8ð 8ð 8ð.˜sð ð ð ð ð5ð 5 Sð 5¸cð 5ÈTð 5ð 5ð 5ð 5ðr¨Cð °Dð ð ð ð ð CGðð ØðØ08¸´ðà	ðð ð ð ð@E ð Eð Eð Eð Eð"¨Cð °I¸c´Nð ð ð ð ð
àð
ð
 ð
ð 
ð
ð 
ð 
ð 
ð, "&ðð "+ ¡¤Ø Ø$ðð ð à˜#”ðð ð	ð
 ðð ðð 
ðð ð ð ð</ð /ð /ðJ 9=ð7Rð 7Rà  T¨#¨s¨(¤^Ô 4Ô5ð7Rð 7Rð 7Rð 7Rðrh¨ð hð hð hð hð hð hrX   rÝ   c                 ó*  — 	 t          t          d| ¦  «        ¦  «        }n# t          t          f$ r Y dS w xY w|dk     r|› d�S t	          |d¦  «        \  }}|dk     r|dk    r|› d�n|› d|› d�S t	          |d¦  «        \  }}|dk    r|› d�n|› d|› d�S )z5Human-friendly elapsed string ('18m', '2h3m', '45s').r   rª  r˜   r™   rš   Úh)r&   r6   r7   r(   r›   )r–   r™   rš   r·  s       rE   Ú_format_ager¸  F
  sÌ   € ðÝ•�A�w‘”Ñ Ô ˆˆøÝ•zÐ"ð ð ð Øˆsˆsðøøøàˆ2‚v€vØˆwˆwˆwˆÝ�!�R‰=Œ=�D€A€qØˆ2‚v€vØ˜qš&˜&�!ˆwˆwˆwˆw¨ k k¨Q k k kÐ1Ý�!�R‰=Œ=�D€A€qØ˜1’f�fˆaˆ7ˆ7ˆ7ˆ7 Q + +¨ + + +Ð-s   ‚   5´5r  c           	      ó:  — ddl }|                      dd¦  «        }|                      dd¦  «        pd}|                      d¦  «        }|                      d¦  «        }|                      d	¦  «        pd
}|                      d¦  «        pd}|                      d¦  «        pd}|                      d¦  «        }	|                      d¦  «        }
|                      dd¦  «        }|                      dd¦  «        }|                      d¦  «        }|                      d¦  «        p|                      ¦   «         }|                      d¦  «        }|                      d¦  «        st          |t          ¦  «        �r‹|pg }|                      d¦  «        pg }|rt	          |¦  «        nt	          |¦  «        }|                      d|¦  «        }d|› d�d|› d�dg}t          |t
          t          f¦  «        rY|                     d|                     |¦  «        ¦  «        }dt          ||z
  ¦  «        › d�}| 
                    d |› |› �¦  «         |r| 
                    d!|› �¦  «         |r+| 
                    d"d#                     |¦  «        › �¦  «         | 
                    d$|› d%|› d&|› d'�¦  «         |
rD|sB| 
                    d(¦  «         | 
                    d)|
› �¦  «         d*                     |¦  «        S t          |d+„ ¬,¦  «        D �]ã}|                     d-d¦  «        }|                     dd¦  «        }|                     d¦  «        }|                     d¦  «        }|t	          |¦  «        k     r||         n|                     dd¦  «        }|d.v rd/nd0}| 
                    d¦  «         d1|› d2|d3z   › d4|› �}|r|d5|› �z  }|d6|› �z  }|                     d¦  «        r|d7|d         › �z  }|                     d¦  «        �|d#|d         › d'�z  }|d8z  }| 
                    |¦  «         |d.v r|r| 
                    |¦  «         np|rI|r| 
                    d9|› d5|› d:�¦  «         | 
                    d;¦  «         | 
                    |¦  «         n%| 
                    d<|› �|rd5|› �ndz   d:z   ¦  «         |                     d=¦  «        }|r| 
                    d>|› �¦  «         �Œåd*                     |¦  «        S d}t          |t
          t          f¦  «        rdt          ||z
  ¦  «        › d�}d?|› d�d@dg}t          |t
          t          f¦  «        rC|                     d|                     |¦  «        ¦  «        }| 
                    d |› |› �¦  «         | 
                    dA|› �¦  «         |r| 
                    d!|› �¦  «         |r+| 
                    d"d#                     |¦  «        › �¦  «         | 
                    d$|› d%|› �¦  «         | 
                    dB|› dC|› dD|› d'�¦  «         | 
                    dE¦  «         |d.v r|	r| 
                    |	¦  «         n¡|dFk    rL| 
                    dG|
rd5|
› �ndHz   ¦  «         |	r*| 
                    d;¦  «         | 
                    |	¦  «         nO| 
                    dI|› dJ�|
rd*|
› �ndz   ¦  «         |	r*| 
                    d;¦  «         | 
                    |	¦  «         d*                     |¦  «        S )Ku  Format an async-delegation completion into a self-contained re-injection.

    Carries the FULL original task source (goal, the context the parent
    supplied, toolsets, role, model) plus dispatch time, status, and the
    complete result summary. When this re-enters the conversation the agent
    may be deep in unrelated context and won't remember why the subagent
    existed, so the block is written to stand entirely on its own â€” enough to
    use the result OR re-dispatch if the world has moved on.
    r   NÚdelegation_idr©  Úgoalr   ÚcontextÚtoolsetsÚroleÚleafÚmodelrª  r<  Ú	completedÚsummaryr  Ú	api_callsÚduration_secondsÚdispatched_atÚcompleted_atr  Úis_batchÚgoalsÚtotal_duration_secondsu%   [ASYNC DELEGATION BATCH COMPLETE â€” Ú]zA background fan-out of uå    subagent(s) you dispatched earlier has finished. All ran in parallel and waited on each other; their consolidated results are below. You may have moved on since dispatching â€” act on these or re-dispatch if things have changed.z%Y-%m-%d %H:%M:%Sz (z ago)zDispatched: zContext you provided: z
Toolsets: z, zRole: z
   Model: z   Total duration: r™   z--- ERROR ---z)The batch did not complete successfully: rö   c                 ó.   — |                       dd¦  «        S )NÚ
task_indexr   r�  )Úxs    rE   r‹  z*_format_async_delegation.<locals>.<lambda>Ž
  s   € ¨q¯uªu°\À1Ñ/EÔ/E€ rX   rŒ  rÌ  )rÁ  Úsuccessu   âœ“u   âœ—z--- z TASK r  r    z: z
  (status=z, api_calls=z) ---ú(r2  zPartial output:u   (no summary â€” status=Úlive_transcriptz6Full live transcript (complete tool/assistant trace): u   [ASYNC DELEGATION COMPLETE â€” zÈA background subagent you dispatched earlier has finished. You may have moved on since dispatching it; the full task source is below so you can act on the result or re-dispatch if things have changed.zOriginal goal: zStatus: z   API calls: z   Duration: z--- RESULT ---r5  z.The subagent was interrupted before completingú.z3The subagent did not complete successfully (status=z).)rZ   r|   rj  r×   r  r&   rÔ   rh  ri  r¸  r1   rý   Úsorted) r  Ú_timeÚdeleg_idr»  r¼  r½  r¾  rÀ  r<  rÂ  r  rÃ  ÚdurationrÅ  rÆ  Úbatch_resultsr  rÈ  ÚnÚ	total_durrù   ÚtsÚageÚrÚidxÚr_statusÚ	r_summaryÚr_errorÚr_goalÚiconÚheaderÚr_lives                                    rE   Ú_format_async_delegationrä  U
  s4  € ð ÐÐÐà�wŠw�¨	Ñ2Ô2€HØ�7Š7�6˜2ÑÔÐ$ "€DØ�gŠg�iÑ Ô €GØ�wŠw�zÑ"Ô"€HØ�7Š7�6‰?Œ?Ð$˜f€DØ�GŠG�GÑÔÐ# €EØ�WŠW�XÑÔÐ- +€FØ�gŠg�iÑ Ô €GØ�GŠG�GÑÔ€EØ—’˜ QÑ'Ô'€IØ�wŠwÐ)¨3Ñ/Ô/€HØ—G’G˜OÑ,Ô,€MØ—7’7˜>Ñ*Ô*Ð:¨e¯jªj©l¬l€Lð —G’G˜IÑ&Ô&€MØ
‡w‚wˆzÑÔð > �j¨½Ñ=Ô=ñ > ØÐ% 2ˆØ—’˜Ñ Ô Ð& BˆØ#Ð3�C�‰LŒLˆL­¨U©¬ˆØ—G’GÐ4°hÑ?Ô?ˆ	à?°HÐ?Ð?Ð?ðR qð Rð Rð Rð ð
ˆõ �m¥c­5 \Ñ2Ô2ð 	3Ø—’Ð 3°U·_²_À]Ñ5SÔ5SÑTÔTˆBØG•{ <°-Ñ#?Ñ@Ô@ÐGÐGÐGˆCØ�LŠLÐ1¨Ð1¨CÐ1Ð1Ñ2Ô2Ð2Øð 	=Ø�LŠLÐ;°'Ð;Ð;Ñ<Ô<Ð<Øð 	=Ø�LŠLÐ; d§i¢i°Ñ&9Ô&9Ð;Ð;Ñ<Ô<Ð<Ø�ŠÐT˜dÐTÐT¨eÐTÐTÈ	ÐTÐTÐTÑUÔUÐUØð 	$˜ð 	$Ø�LŠL˜Ñ)Ô)Ð)Ø�LŠLÐLÀUÐLÐLÑMÔMÐMØ—9’9˜UÑ#Ô#Ð#Ý˜Ð%EÐ%EÐFÑFÔFð #	ñ #	ˆAØ—%’%˜ aÑ(Ô(ˆCØ—u’u˜X sÑ+Ô+ˆHØŸš˜iÑ(Ô(ˆIØ—e’e˜G‘n”nˆGØ#&­¨U©¬Ò#3Ð#3�U˜3”Z�Z¸¿º¸vÀrÑ9JÔ9JˆFØ$Ð(@Ð@Ð@�5�5ÀeˆDØ�LŠL˜ÑÔÐØ5˜DÐ5Ð5¨¨a©Ð5Ð5°!Ð5Ð5ˆFØð (Ø˜-˜v˜-˜-Ñ'�ØÐ- 8Ð-Ð-Ñ-ˆFØ�uŠu�[Ñ!Ô!ð :ØÐ9¨¨;¬Ð9Ð9Ñ9�Ø�uŠuÐ'Ñ(Ô(Ð4ØÐ7˜qÐ!3Ô4Ð7Ð7Ð7Ñ7�Ø�gÑˆFØ�LŠL˜Ñ Ô Ð ØÐ3Ð3Ð3¸	Ð3Ø—’˜YÑ'Ô'Ð'Ð'Øð 
Øð =Ø—L’LÐ!; XÐ!;Ð!;°Ð!;Ð!;Ð!;Ñ<Ô<Ð<Ø—’Ð.Ñ/Ô/Ð/Ø—’˜YÑ'Ô'Ð'Ð'à—’Ø8¨hÐ8Ð8Ø)0Ð8�~˜G�~�~�~°bñ:àññô ð ð
 —U’UÐ,Ñ-Ô-ˆFØð Ø—’ØUÈVÐUÐUñô ð ùð �yŠy˜ÑÔÐà
€CÝ�-¥#¥u Ñ.Ô.ð DØC•;˜|¨mÑ;Ñ<Ô<ÐCÐCÐCˆð 	6¨(Ð5Ð5Ð5ð	Kð 	ð€Eõ �-¥#¥u Ñ.Ô.ð /Ø�^Š^Ð/°·²ÀÑ1OÔ1OÑPÔPˆØ�ŠÐ- BÐ-¨Ð-Ð-Ñ.Ô.Ð.Ø	‡L‚LÐ) 4Ð)Ð)Ñ*Ô*Ð*Øð 9Ø�ŠÐ7¨gÐ7Ð7Ñ8Ô8Ð8Øð 9Ø�ŠÐ7 $§)¢)¨HÑ"5Ô"5Ð7Ð7Ñ8Ô8Ð8Ø	‡L‚LÐ1˜$Ð1Ð1¨%Ð1Ð1Ñ2Ô2Ð2Ø	‡L‚LÐU˜FÐUÐU°)ÐUÐUÈ(ÐUÐUÐUÑVÔVÐVØ	‡L‚LÐ!Ñ"Ô"Ð"ØÐ)Ð)Ð)¨gÐ)Ø�Š�WÑÔÐÐØ	�=Ò	 Ð	 Ø�ŠØ<Ø$Ð-ˆ|�Eˆ|ˆ|ˆ|¨#ñ/ñ	
ô 	
ð 	
ð ð 	"Ø�LŠLÐ*Ñ+Ô+Ð+Ø�LŠL˜Ñ!Ô!Ð!øð 	�ŠØLÀ&ÐLÐLÐLØ$Ð,ˆ|�Eˆ|ˆ|ˆ|¨"ñ.ñ	
ô 	
ð 	
ð ð 	"Ø�LŠLÐ*Ñ+Ô+Ð+Ø�LŠL˜Ñ!Ô!Ð!Ø�9Š9�UÑÔÐrX   z
str | Nonec                 ó  — |                       dd¦  «        }|                       dd¦  «        }|                       dd¦  «        }|dk    rd|                       dd	¦  «        › d
�S |dk    rb|                       dd¦  «        }|                       dd	¦  «        }|                       dd¦  «        }d|› d|› d|› d|› �}|r	|d|› d�z  }|d
z  }|S |dk    rt          | ¦  «        S |                       dd¦  «        }|                       dd	¦  «        }|                       d¦  «        pd}	|                       d¦  «        pd	}
d	}|dv rd}|	dk    rd|
pd › �}n|	d!k    rd"}n|	d#k    rd$}n|dk    rd%}nd}d|› d&|› d'|› |› d(|› d)|› d
�S )*zÖFormat a process notification event into a [IMPORTANT: ...] message.

    Handles completion events (notify_on_complete), watch pattern matches,
    and watch disabled events from the unified completion_queue.
    r	  rì  r  r©  r£   r  z[IMPORTANT: r  r   rÊ  r  r  rª  r  r
  r   z[IMPORTANT: Background process z matched watch pattern "z".
Command: z
Matched output:
z
(z/ earlier matches were suppressed by rate limit)rú  r­   r®   r¬   r¯   >   ú-15Ú143é�   rF  z	, SIGTERMr¿  zterminated by ÚHermesrÖ  z3marked lost because the process backend disappearedrª  zfailed to startzcompleted normallyÚ z (exit code z).
Command: z	
Output:
)r|   rä  )r  Úevt_typeÚ_sidÚ_cmdÚ_patÚ_outÚ_suprô   Ú_exitÚ_reasonÚ_sourceÚ_signalÚ_statuss                rE   rÿ  rÿ  à
  sN  € ð �wŠw�v˜|Ñ,Ô,€HØ�7Š7�< Ñ+Ô+€DØ�7Š7�9˜iÑ(Ô(€DàÐ#Ò#Ð#Ø7˜cŸgšg i°Ñ4Ô4Ð7Ð7Ð7Ð7à�=Ò Ð Ø�wŠw�y #Ñ&Ô&ˆØ�wŠw�x Ñ$Ô$ˆØ�wŠw�| QÑ'Ô'ˆð'¨dð 'ð 'Ø#ð'ð 'àð'ð 'ð !%ð'ð 'ð 	ð ð 	PØÐO˜$ÐOÐOÐOÑOˆDØ�‰ˆØˆàÐ%Ò%Ð%Ý'¨Ñ,Ô,Ð,à�GŠG�K Ñ%Ô%€EØ�7Š7�8˜RÑ Ô €DØ�gŠgÐ)Ñ*Ô*Ð6¨h€GØ�gŠgÐ*Ñ+Ô+Ð1¨r€GØ€GØÐ(Ð(Ð(ØˆØ�(ÒÐØ8 7Ð#6¨hÐ8Ð8ˆˆØ	�FÒ	Ð	ØGˆˆØ	�NÒ	"Ð	"Ø#ˆˆØ	�!ŠˆØ&ˆˆàˆð	¨$ð 	ð 	°ð 	ð 	Øð	Ø$ð	ð 	àð	ð 	ð ð	ð 	ð 	ðrX   )ÚregistryÚ
tool_errorr§   af  Manage background processes started with terminal(background=true). Actions: 'list' (show all), 'poll' (check status + new output), 'log' (full output with pagination), 'wait' (block until done or timeout), 'kill' (terminate), 'write' (send raw stdin data without newline), 'submit' (send data + Enter, for answering prompts), 'close' (close stdin/send EOF).ÚobjectÚstring)r×   rÇ  Úlogr‘  rT  rQ  Úsubmitr\  z)Action to perform on background processes)r	  ÚenumÚdescriptionz]Process session ID (from terminal background output). Required for all actions except 'list'.)r	  rý  z@Text to send to process stdin (for 'write' and 'submit' actions)ÚintegerzJMax seconds to block for 'wait' action. Returns partial output on timeout.r  )r	  rý  Úminimumz6Line offset for 'log' action (default: last 200 lines)z$Max lines to return for 'log' action)Úactionr  rH  rW   r"  r#  r   )r	  Ú
propertiesÚrequired)r{  rý  Ú
parametersrr   c                 ó~  — t          | t          ¦  «        s| S ddlm}m} |                      d¦  «        pd}dD ]=}|                      |¦  «        }t          |t          ¦  «        r|r |||¦  «        | |<   Œ>t          |                      d¦  «        t          ¦  «        r| d         r || d         d¬¦  «        | d<   | S )uD  Redact secrets from background-process output before it reaches the
    model, session.db, and CLI display.

    Mirrors the foreground ``terminal`` redaction (terminal_tool.py) so the
    two surfaces can't diverge â€” issue #43025 (background output was returned
    verbatim). Respects ``security.redact_secrets`` (no force): output fields
    pass through ``redact_terminal_output`` which picks ``code_file`` based on
    the recorded command (env dumps get the ENV-assignment pass). The command
    string itself is also redacted in case it carried an inline credential.
    r   )r   Úredact_terminal_outputr£   r   )r  r  Trš  )rj  rµ  Úagent.redactr   r  r|   rÑ   )rr   r   r  r£   r
   Úvalues         rE   Ú_redact_process_resultr  J  sí   € õ �f�dÑ#Ô#ð ØˆØJÐJÐJÐJÐJÐJÐJÐJà�jŠj˜Ñ#Ô#Ð) r€GØ-ð Cð CˆØ—
’
˜5Ñ!Ô!ˆÝ�e�SÑ!Ô!ð 	C eð 	CØ2Ð2°5¸'ÑBÔBˆF�5‰MøÝ�&—*’*˜YÑ'Ô'­Ñ-Ô-ð U°&¸Ô2Cð UØ1Ð1°&¸Ô2CÈtÐTÑTÔTˆˆyÑØ€MrX   c                 óB  — |                      d¦  «        }|                       dd¦  «        }|                       d¦  «        �#t          |                       dd¦  «        ¦  «        nd}|dk    rf	 ddlm}  |d¬¦  «        pd}n# t          $ r d}Y nw xY wt          j        d	d
„ t                               ||pd ¬¦  «        D ¦   «         id¬¦  «        S |dv �r7|st          d|› �¦  «        S |dk    r;t          j        t          t                               |¦  «        ¦  «        d¬¦  «        S |dk    ret          j        t          t                               ||                       d¦  «        |                       dd¦  «        ¬¦  «        ¦  «        d¬¦  «        S |dk    rPt          j        t          t                               ||                       d¦  «        ¬¦  «        ¦  «        d¬¦  «        S |dk    r;t          j        t          t                               |¦  «        ¦  «        d¬¦  «        S |dk    rPt          j        t                               |t          |                       dd¦  «        ¦  «        ¦  «        d¬¦  «        S |dk    rPt          j        t                               |t          |                       dd¦  «        ¦  «        ¦  «        d¬¦  «        S |dk    r.t          j        t                               |¦  «        d¬¦  «        S t          d|› d�¦  «        S ) Nr¤   r   r   r  r×   r   )Úget_current_session_key)rÀ   Ú	processesc                 ó,   — g | ]}t          |¦  «        ‘ŒS rŽ   )r  )r�   Úps     rE   rb  z#_handle_process.<locals>.<listcomp>t  s0   € ð ð ð àõ +¨1Ñ-Ô-ðð ð rX   rd  F)Úensure_ascii>   rú  rT  rÇ  r‘  r\  rQ  rû  zsession_id is required for rÇ  rú  r"  r#  r!  )r"  r#  r‘  rW   r€  rT  rQ  rH  rû  r\  zUnknown process action: z8. Use: list, poll, log, wait, kill, write, submit, close)r|   rÑ   Útools.approvalr
  rl   r­  ÚdumpsÚprocess_registryrl  r÷  r  rÇ  r,  r‘  rG  rT  rV  r]  )ry  Úkwr¤   r   r  r
  r¥   s          rE   Ú_handle_processr  c  sn  € Ø�fŠf�YÑÔ€GØ�XŠX�h Ñ#Ô#€Fà48·H²H¸\Ñ4JÔ4JÐ4V•�T—X’X˜l¨BÑ/Ô/Ñ0Ô0Ð0Ð\^€Jà�ÒÐð	Ø>Ð>Ð>Ð>Ð>Ð>Ø1Ð1¸"Ð=Ñ=Ô=ÐCÀˆKˆKøÝð 	ð 	ð 	ØˆKˆKˆKð	øøøåŒzàð ð å-×;Ò;ÀGÐYdÐYlÐhlÐ;ÑmÔmðñ ô ðð ð
ñ 
ô 
ð 	
ð 
ÐNÐ	NÑ	NØð 	FÝÐD¸FÐDÐDÑEÔEÐEØ�VÒÐÝ”:Õ4Õ5E×5JÒ5JÈ:Ñ5VÔ5VÑWÔWÐfkÐlÑlÔlÐlØ�uŠ_ˆ_Ý”:Õ4Õ5E×5NÒ5NØ 4§8¢8¨HÑ#5Ô#5¸T¿XºXÀgÈsÑ=SÔ=Sð 6Oñ 6Uô 6Uñ Vô VØdiðkñ kô kð kà�vÒÐÝ”:Õ4Õ5E×5JÒ5JÈ:Ð_c×_gÒ_gÐhqÑ_rÔ_rÐ5JÑ5sÔ5sÑtÔtð  DIð  Jñ  Jô  Jð  JØ�vÒÐÝ”:Ý&Õ'7×'DÒ'DÀZÑ'PÔ'PÑQÔQØ"ðñ ô ð ð �wÒÐÝ”:Õ.×:Ò:¸:ÅsÈ4Ï8Ê8ÐTZÐ\^ÑK_ÔK_ÑG`ÔG`ÑaÔaÐpuÐvÑvÔvÐvØ�xÒÐÝ”:Õ.×;Ò;¸JÍÈDÏHÊHÐU[Ð]_ÑL`ÔL`ÑHaÔHaÑbÔbÐqvÐwÑwÔwÐwØ�wÒÐÝ”:Õ.×:Ò:¸:ÑFÔFÐUZÐ[Ñ[Ô[Ð[ÝÐq°ÐqÐqÐqÑrÔrÐrs   Á-B ÂBÂBrD  u   âš™ï¸�)r{  ÚtoolsetÚschemaÚhandlerÚemoji)PrÐ   rÄ  r­  Úloggingr#   r  r«  rU  rf   rØ   rZ   rc   Úpathlibr   Úsystemr_   Útools.environments.localr   r   r   Úhermes_cli._subprocess_compatr   Údataclassesr	   r
   Útypingr   r   r   r   rF  r   r  r   Ú	getLoggerrÍ   r)   r¦  rÖ   rˆ  r�  ÚMAX_ACTIVE_PROCESS_AGEr  r  r'  r&  r(  r   rÕ   rÒ   rÚ   r^   r\   r]   r'   r8   r5   r&   rF   rt   r   rÑ   r†   r•   rŸ   r¡   rÝ   r  rÔ   r¸  rµ  rä  rÿ  Útools.registryrö  r÷  ÚPROCESS_SCHEMAr  r  ÚregisterrŽ   rX   rE   ú<module>r$     sÓ  ððð ð ð> €€€Ø €€€Ø €€€Ø 	€	€	€	Ø €€€Ø €€€Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ø €€€Ø €€€Ø Ð Ð Ð Ð Ð àˆhŒoÑÔ 9Ò,€Ø ]Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]Ø <Ð <Ð <Ð <Ð <Ð <Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ø ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,à -Ð -Ð -Ð -Ð -Ð -à .Ð .Ð .Ð .Ð .Ð .à	ˆÔ	˜8Ñ	$Ô	$€ð "�/Ñ#Ô#Ð&6Ñ6€ð Ð ØÐ Ø€ØÐ ð  Ð ØÐ ð !Ð Ø Ð Ø "Ð ð& ,0Ð ˜( 4œ.Ð /Ð /Ñ /Ø*˜IœNÑ,Ô,Ð ØÐ Ø%)Ð "Ø/Ð Ø#5Ð  Ø5Ð ð;M #ð ;Mð ;Mð ;Mð ;Mð|K¨4ð Kð Kð Kð Kð\¨ð ð ð ð ð2$Ø�S”	ð$àð$ð 
ˆ#„Yð$ð $ð $ð $ðN( #ð (¨$ð (ð (ð (ð (ðV ð ¨ð ð ð ð ð ð10ð 10ð 10ð 10ð 10ñ 10ô 10ñ „ð10ðh\"ð \"ð \"ð \"ð \"ñ \"ô \"ð \"ð@E #�?Ñ$Ô$Ð ð.˜ð . 3ð .ð .ð .ð .ðH $ð H¨3ð Hð Hð Hð HðV5 Tð 5¨lð 5ð 5ð 5ð 5ðv 0Ð /Ð /Ð /Ð /Ð /Ð /Ð /ð ð	_ð ð !Ø[Ð[Ð[ØJðð ð !Ø~ðð ð
 !Øaðð ð
 "ØkØðð ð "ØWðð ð
 "ØEØðð ð/
ð 
ð: �Jð? ð  ð*ð *€ðZ 4ð ¨Dð ð ð ð ð2-sð -sð -sð` €Ô Ø	ØØØØ
ðñ ô ð ð ð rX   