+
    „WÝj…·  ã                   óê  a € R[ tU0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIHtHt ^ RIHt ^ RIHt ^ RIHtHt ^ RIHtHtHtHt RsRtRsRsR	 R
 lt]	P@                  R8X  d   ]! 4       '       d   ^ RI!H"t# M^ RIH#t# RtM^ RIH#t# ]
PH                  ! 4       t%Rt&Rt'Rs(R R lt)R t* ! R R4      t+R R lt,R R lt-Rs.]
P^                  ! 4       t0R R lt1R R lt2R\t3R R lt4R  R! lt5R" R# lt6R$ R% lt7]7! 4         ! R& R']Pp                  4      t9R(R]R)R^R*R_R+R`R,RaR-Rb/t:R. R/ lt;R0 R1 lt<R2RR3RR4RR5RR6RR7R/R8 R9 llt=R: R; lt>R< R= lt? ! R> R?]#4      t@R@ RA ltARBtB ! RC RD]P†                  4      tDRsE] ^ k RsF] ^k . tG] ^k RsH]
P^                  ! 4       tI ! RE RF]4      tJRG RH ltKRI RJ ltLRK RL ltMRM RN ltNRcRO RP lltORQ RR ltPRS RT ltQRU RV ltRRWR/RX RY lltSRZ tTR# )da`  Centralized logging setup for Hermes Agent.

Log files: agent.log (INFO+, everything), errors.log (WARNING+), gateway.log (INFO+,
gateway components; ``mode="gateway"``), gui.log (INFO+, dashboard/TUI-gateway;
``mode="gui"``). All are rotating files driven through one async queue and formatted
with ``RedactingFormatter`` so secrets never reach disk.
N)ÚQueueHandlerÚQueueListener)ÚPath)Ú	monotonic)ÚOptionalÚSequence)Úget_config_pathÚget_hermes_homeÚmkdir_under_hermes_homeÚnamed_profile_is_deletedFÚ c                ó$   € V ^8„  d   QhR\         /# ©é   Úreturn)Úbool)Úformats   "ÚBC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_logging.pyÚ__annotate__r   &   s   € ÷ "ñ "œDñ "ó    c                 óÌ  € \         P                  R8w  d   R#  ^ RIp ^ RIpTP                  RR7      w  r4 \        P                  ! TR4      ;_uu_ 4       pT P                  YPP                  4       T P                  T4       RRR4        \        P                  ! T4       R#   \         d   p\        T4      s Rp?R# Rp?ii ; i  + '       g   i     LM; i  \         d@   p\        T4      s Rp? \        P                  ! T4       R#   \         d     R# i ; iRp?ii ; i  \         d     R# i ; i   \        P                  ! T4       i   \         d     i i ; i; i)uŽ  Return True when portalocker can actually take a lock on this box.

concurrent-log-handler locks every write through portalocker, which on
Windows instantiates Win32Locker and imports pywintypes. Bundled payloads
have shipped with that import broken (the venv's .pth files were never
processed), and portalocker 3.x gives no msvcrt fallback â€” every emit then
dies with the ImportError, CLH retries 20x, and the suppressed "Cannot
acquire lock" RuntimeError below hides it completely. Probe a scratch file
once at import so we can fall back to stdlib rotation instead of silently
dropping every record. No-op (True) off Windows, where stdlib is in use.
Úwin32TNFzhermes-portalocker-)Úprefixzr+b)ÚsysÚplatformÚportalockerÚtempfileÚ	ExceptionÚreprÚ_WINDOWS_CLH_FALLBACK_REASONÚmkstempÚosÚfdopenÚlockÚLOCK_EXÚunlockÚunlinkÚOSError)r   r   ÚexcÚfdÚpathÚstreams         r   Ú_portalocker_prober,   &   s)  € ô ‡|�|�wÔÙðÛÛð ×ÑÐ'<ÐÓ=�H€BðÜ�YŠY�r˜5×!Ô! VØ×Ñ˜V×%8Ñ%8Ô9Ø×Ñ˜vÔ&÷ "ð	Ü�IŠI�dŒOñ øô! ô Ü'+¨C£yÐ$Ýûðú÷
 "×!ûô ô Ü'+¨C£yÐ$Ûð	Ü�IŠI�dŽOøÜô 	Úð	þðûô ô 	ØÙð	ûð	Ü�IŠI�d�OøÜô 	Ùð	ýs¬   ™B# ¶C Á-CÂC ÂD' Â#CÂ.B?Â?CÃC	ÃC ÃD9 ÃC ÃD$Ã%DÃ0D9 Ã5D ÄDÄDÄD$Ä$D9 Ä'D6Ä5D6Ä9E#Ä;EÅE#ÅE ÅE#ÅE Å E#r   )ÚConcurrentRotatingFileHandler)ÚRotatingFileHandlerTz>%(asctime)s %(levelname)s%(session_tag)s %(name)s: %(message)szC%(asctime)s - %(name)s - %(levelname)s%(session_tag)s - %(message)sc                ó   € V ^8„  d   QhRR/# ©r   r   N© )r   s   "r   r   r   t   s   € ÷ +ñ + 4ñ +r   c                 ó`  € \         P                  p V e   V \        J d   R# \        V RR4      RJ d   V sR# \        V RR4      pVf   R# \        P
                  ! \        \        4      ;_uu_ 4        V P                  4       '       g   V! RR7       V sRRR4       R#   + '       g   i     R# ; i)u®  Best-effort line buffering for a piped stdout (#92281).

Python block-buffers stdout when it isn't a TTY, so an agent loop
driving ``print()`` into a supervisor's pipe delivers its output in
large delayed bursts â€” a headless run looks stalled for minutes while
the work is actually progressing (only stderr, which we already give
``line_buffering=True`` in ``_safe_stderr()``, shows up on time).
Reconfigure the interpreter's own stdout for line buffering when it is
piped; interactive TTY stdout is already line-buffered. ACP reaches this
too (its AIAgent calls ``setup_logging``) with stdout as its protocol
channel â€” harmless, since line buffering only adds flushes at newlines.
NÚline_bufferingFTÚreconfigure)r3   )	r   ÚstdoutÚ_line_buffered_stdoutÚgetattrÚ
contextlibÚsuppressr'   Ú
ValueErrorÚisatty)r+   r4   s     r   Ú_line_buffer_piped_stdoutr<   t   sŒ   € ô �Z‰Z€FØ‚~˜Ô#8Ó8ÙÜˆvÐ'¨Ó/°4Ó7Ø &ÐÙÜ˜& -°Ó6€KØÒÙô 
×	Ò	œW¤j×	1Õ	1Ø�}‰}�ŠÙ tÕ,Ø$*Ð!÷ 
2×	1×	1Ò	1ús   Á0"BÂB-	c                 ó"  € \         P                  p \        V RR4      ;'       g    RpVP                  4       P	                  RR4      R
9   d   V #  \
        P                  ! V P                  RRRR7      pR	 Vn        V#   \         d    T u # i ; i)z¹Return a stderr stream that tolerates Unicode on all platforms.

Wraps ``sys.stderr`` with ``errors='replace'`` so un-encodable characters become
``?`` instead of crashing the process.
ÚencodingNúutf-8Ú-r   ÚreplaceT)r>   Úerrorsr3   c                  ó   € R # ©Nr1   r1   r   r   Ú<lambda>Ú_safe_stderr.<locals>.<lambda>    s   € ¡r   )Úutf8Úutf8surrogateescape)
r   Ústderrr7   ÚlowerrA   ÚioÚTextIOWrapperÚbufferÚcloser   )r+   r>   Úwrappeds      r   Ú_safe_stderrrP   “   s…   € ô �Z‰Z€FÜ�v˜z¨4Ó0×;Ð;°G€HØ‡~�~Ó×Ñ  RÓ(Ð,KÔKØˆðÜ×"Ò" 6§=¡=¸7È9ÐeiÔjˆá$ˆŒØˆøÜô ØŠðús   Á-A> Á>BÂBc                   ó6   a € ] tR t^¦t o RtR tR tR tRtV t	R# )Ú_RedactingStdiozïText stream proxy that redacts each write: a detached gateway's stdout/stderr IS a
persisted log (``logs/gateway-stdio.log``), and agent status lines (provider error echoes)
reach it through ``print``, never through ``RedactingFormatter``.c                ó   € Wn         R # rD   ©Ú_stream)Úselfr+   s   &&r   Ú__init__Ú_RedactingStdio.__init__«   s   € ØŽr   c                óˆ   € ^ RI Hp V P                  P                  \	        V\
        4      '       d   V! V4      4      # T4      # )é    )Úredact_sensitive_text)Úagent.redactr[   rU   ÚwriteÚ
isinstanceÚstr)rV   Útextr[   s   && r   r]   Ú_RedactingStdio.write®   s6   € Ý6Ø�|‰|×!Ñ!ÄÈDÔRU×AVÒAVÑ"7¸Ó"=ÓaÐaÐ\`ÓaÐar   c                ó.   € \        V P                  V4      # rD   )r7   rU   )rV   Únames   &&r   Ú__getattr__Ú_RedactingStdio.__getattr__²   s   € Ü�t—|‘| TÓ*Ð*r   rT   N)
Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rW   r]   rd   Ú__static_attributes__Ú__classdictcell__©Ú__classdict__s   @r   rR   rR   ¦   s    ø‡ € ñIòòb÷+ð +r   rR   c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r   ¶   s   € ÷ 8ñ 8˜tñ 8r   c                 ó¨   € R FK  p \        \        V 4      pVf   K  \        V\        4      '       d   K1  \	        \        V \        V4      4       KM  	  R# )zORoute a detached process's stdout/stderr through secret redaction (idempotent).N)r5   rI   )r7   r   r^   rR   Úsetattr)rc   r+   s     r   Úredact_detached_stdiorr   ¶   s;   € ã$ˆÜœ˜dÓ#ˆØÔ¤j°¼×&IÔ&IÜ”C˜œ¨vÓ6Ö7ó %r   c                ó>   € V ^8„  d   QhR\         R,          R\        /# ©r   r(   Nr   ©ÚBaseExceptionr   )r   s   "r   r   r   ¾   s   € ÷ ñ ´ÀÕ1Eð Ì$ñ r   c                ó„   € \         P                  R8H  ;'       d'    \        V \        4      ;'       d    R\	        V 4      9   # )a  True for concurrent-log-handler's Windows lock timeout.

Slash-command workers and the gateway share rotating files on Windows Desktop;
when another process holds the rollover lock too long CLH raises this
RuntimeError, which must not escape into Desktop chat output.
r   z%Cannot acquire lock after 20 attempts)r   r   r^   ÚRuntimeErrorr_   ©r(   s   &r   Ú'_is_windows_concurrent_log_lock_timeoutrz   ¾   sC   € ô 	�‰˜Ñ÷ 	@ð 	@Ü�sœLÓ)÷	@ð 	@à3´s¸3³xÑ?ðr   c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r   Ð   s   € ÷ ñ ¨ñ r   c                 óÖ   € \         ;_uu_ 4        \        '       d    RRR4       R# RsRRR4       \        P                  ! R4      P	                  R4       R#   + '       g   i     L7; i)u3  Report a suppressed CLH lock timeout exactly once per process.

Every emit after the first failure raises the same RuntimeError, so the
warning must be one-shot or it would spam errors.log as badly as the
stderr noise it replaces. CLH does not chain the underlying cause (the
RuntimeError is raised outside the except, from the retry loop's else
clause), so the message cannot include it; a constantly repeating timeout
means file logging is degraded â€” the startup portalocker probe in this
module should have caught a dead portalocker and fallen back already.
NTÚhermes_loggingz¸concurrent-log-handler timed out acquiring the cross-process log lock; this and later records were dropped (the Desktop slash-worker surface stays clean, but file logging is degraded).)Ú_windows_lock_timeout_warn_lockÚ_windows_lock_timeout_warnedÚloggingÚ	getLoggerÚwarningr1   r   r   Ú_warn_windows_lock_timeout_oncerƒ   Ð   sR   € ÷ 
)Ö	(ß'Ó'Ø÷ 
)Ñ	(ð (,Ð$÷ 
)ô ×ÒÐ&Ó'×/Ñ/ð	>ö÷	 
)×	(ús   �A§AÁA(	c                ó>   € V ^8„  d   QhR\         R,          R\        /# rt   ru   )r   s   "r   r   r   ç   s   € ÷ ñ ¤M°DÕ$8ð ¼Tñ r   c                óÈ   € \        V \        4      ;'       d    V P                  ^8H  ;'       g5    \        V \        4      ;'       d    R\	        V 4      P                  4       9   # )zHTrue when a file handler lost its backing stream during teardown or I/O.zclosed file)r^   r'   Úerrnor:   r_   rJ   ry   s   &r   Ú_is_unavailable_log_streamr‡   ç   sQ   € ô 
�CœÓ	!×	4Ð	4 c§i¡i°1¡n÷ 	Oð 	OÜ�sœJÓ'×MÐM¨M¼SÀ»X¿^¹^Ó=MÑ,Mðr   c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r   ÷   s   € ÷ :ñ :˜dñ :r   c                 ó†   € \          F6  p \        P                  ! V 4      P                  \        P                  4       K8  	  R# )z)Pin noisy third-party loggers at WARNING.N)Ú_NOISY_LOGGERSr€   r�   ÚsetLevelÚWARNING)rc   s    r   Ú_quiet_noisy_loggersr�   ÷   s)   € çˆÜ×Ò˜$Ó×(Ñ(¬¯©Ö9ó r   c                ó(   € V ^8„  d   QhR\         RR/# )r   Ú
session_idr   N)r_   )r   s   "r   r   r   ý   s   € ÷ -ñ -¤Cð -¨Dñ -r   c                ó   € V \         n        R# )z*Set the session ID for the current thread.N©Ú_session_contextr�   )r�   s   &r   Úset_session_contextr“   ý   s   € à",ÔÖr   c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r     s   € ÷ 'ñ '˜tñ 'r   c                 ó   € R\         n        R# )z,Clear the session ID for the current thread.Nr‘   r1   r   r   Úclear_session_contextr–     s   € à"&ÔÖr   c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r     s   € ÷ 9ñ 9¨ñ 9r   c                 ó¢   a€ \         P                  ! 4       o\        SRR4      '       d   R# V3R lp RV n        \         P                  ! V 4       R# )a  Replace the global LogRecord factory with one that adds ``session_tag``.

Unlike a Filter, the record factory runs for EVERY record in the process (propagated
and third-party-handled ones included), so ``%(session_tag)s`` never KeyErrors.
Idempotent via a marker attribute.
Ú_hermes_session_injectorFNc                  óä   <€ S! V / VB p\        \        R R4      pV'       d   RV R2MRVn         \        \	        4       P                  4       4      Vn        V#   \         d    RTn         T# i ; i)r�   Nz [Ú]r   )r7   r’   Úsession_tagr_   r	   ÚresolveÚhermes_homer   )ÚargsÚkwargsÚrecordÚsidÚcurrent_factorys   *,  €r   Ú_session_record_factoryÚ@_install_session_record_factory.<locals>._session_record_factory  sx   ø€ Ù  $Ð1¨&Ñ1ˆÜÔ&¨°dÓ;ˆß,/˜r #  a™[°RˆÔð	$Ü!$¤_Ó%6×%>Ñ%>Ó%@Ó!AˆFÔð ˆøô ô 	$Ø!#ˆFÕØˆð	$ús   ±&A ÁA/Á.A/T)r€   ÚgetLogRecordFactoryr7   r™   ÚsetLogRecordFactory)r¤   r£   s    @r   Ú_install_session_record_factoryr¨     sE   ø€ ô ×1Ò1Ó3€OÜˆÐ :¸E×BÒBÙõð 8<ÐÔ4Ü×ÒÐ 7Ö8r   c                   óT   a a€ ] tR tRt oRtV3R lV 3R lltV3R lR ltRtVtV ;t	# )Ú_ComponentFilteri&  zBOnly pass records whose logger name starts with one of *prefixes*.c                ó4   <€ V ^8„  d   QhRS[ S[,          RR/# )r   Úprefixesr   N)r   r_   )r   rn   s   "€r   r   Ú_ComponentFilter.__annotate__)  s   ø€ ÷ )ñ )¡©#¥ð )°4ñ )r   c                óD   <€ \         SV `  4        \        V4      V n        R # rD   )ÚsuperrW   ÚtupleÚ	_prefixes)rV   r¬   Ú	__class__s   &&€r   rW   Ú_ComponentFilter.__init__)  s   ø€ Ü‰ÑÔÜ˜x›ˆŽr   c                ó:   <€ V ^8„  d   QhRS[ P                  RS[/# ©r   r¡   r   )r€   Ú	LogRecordr   )r   rn   s   "€r   r   r­   -  s!   ø€ ÷ 6ñ 6™W×.Ñ.ð 6±4ñ 6r   c                óL   € VP                   P                  V P                  4      # rD   )rc   Ú
startswithr±   ©rV   r¡   s   &&r   ÚfilterÚ_ComponentFilter.filter-  s   € Ø�{‰{×%Ñ% d§n¡nÓ5Ð5r   )r±   )
rf   rg   rh   ri   rj   rW   rº   rk   rl   Ú__classcell__©r²   rn   s   @@r   rª   rª   &  s!   ù‡ € ÙL÷)ó )÷6÷ 6ð 6r   rª   ÚgatewayÚagentÚtoolsÚcliÚcronÚguic                ó:   € V ^8„  d   QhR\         \        ,          /# r   )Úsetr   )r   s   "r   r   r   @  s   € ÷ ñ œ#œd�)ñ r   c                 óÈ  € \        4       p \         F°  p\        V\        4      '       d9   V P	                  VP
                  4       V P                  VP                  4       KQ  \        V\        4      '       g   Ki   V P	                  \        VP                  4      P                  4       P                  P                  4       K²  	  V #   \        \        \        3 d     KÏ  i ; i)z²Homes the queued file handlers already serve: static handlers by their file, routers by
their default home plus every profile home they route. Caller holds ``_queue_state_lock``.)rÅ   Ú_queued_file_handlersr^   Ú_ProfileRoutingFileHandlerÚaddÚ_default_homeÚupdateÚ_profile_homesr.   r   ÚbaseFilenamer�   ÚparentÚ	TypeErrorr:   r'   )ÚhomesÚhandlers     r   Ú_known_log_homesrÒ   @  s¨   € ô “u€Eß(ˆÜ�gÔ9×:Ò:Ø�I‰I�g×+Ñ+Ô,Ø�L‰L˜×/Ñ/Ö0Ü˜Ô!4×5Ô5ðØ—	‘	œ$˜w×3Ñ3Ó4×<Ñ<Ó>×EÑE×LÑLÖMñ )ð €Løô œz¬7Ð3ô Úðús   Á;ACÃC!Ã C!c                ó0   € V ^8„  d   QhR\         R\        /# ©r   Úhomer   ©r   r   )r   s   "r   r   r   P  s   € ÷ Bñ B¤ð B¬ñ Br   c                óD  €  \        V 4      P                  4       P                  4       p\        ;_uu_ 4        \        4       pRRR4       X'       d   Y9   d   R# \        . \        T4      OTN4      #   \        \        \
        3 d     R# i ; i  + '       g   i     LU; i)zäRoute *home*'s records to its own files when this process already logs for another home.
Enables profile routing for the union of homes (or widens the live routers); False when
*home* is the first home seen or is already served.FN)
r   Ú
expanduserr�   rÏ   r:   r'   Ú_queue_state_lockrÒ   Úenable_profile_log_routingÚsorted)rÕ   ÚresolvedÚknowns   &  r   Ú_adopt_secondary_homerÞ   P  s~   € ðÜ˜“:×(Ñ(Ó*×2Ñ2Ó4ˆ÷ 
Ö	Ü Ó"ˆ÷ 
ç�HÔ%ÙÜ%Ð&@¬¨u«Ð&@°xÐ&@ÓAÐAøô ”z¤7Ð+ô Úðúç	×	ús   ‚'A2 ·BÁ2BÂBÂB	rž   Ú	log_levelÚmax_size_mbÚbackup_countÚmodeÚforcec                óÚ   € V ^8„  d   QhR\         \        ,          R\         \        ,          R\         \        ,          R\         \        ,          R\         \        ,          R\        R\        /# )r   rž   rß   rà   rá   râ   rã   r   )r   r   r_   Úintr   )r   s   "r   r   r   _  sm   € ÷ Nñ Näœ$•ðNô œ�}ðNô œ#•ð	Nô
 œ3•-ðNô ”3�-ðNô ðNô 
ñNr   c                óv  € T ;'       g    \        4       p\        VR,          4      p\        4        \        V4      '       d   V# \	        4       w  r‰p
T;'       g    T;'       g    RP                  4       p\        \        V\        P                  4      pT;'       g    T	;'       g    ^R,          R,          pT;'       g    T
;'       g    ^p^ RI	H
p \        P                  ! 4       pRWÍVR3R\        P                  R^R3R\        P                  R^R	3R
\        P                  R^R33pV FV  w  pppppVe
   VV8w  d   K  \        VV,          TTTV! \        4      V'       d   \        \         V,          4      MRR7       KX  	  \"        '       dC   \$        '       g7   Rs\        P                  ! R4      P'                  R\(        ;'       g    R4       \*        '       d   V'       g   V# VP,                  \        P.                  8X  g   VP,                  V8”  d   VP1                  V4       \3        4        RsV# )a   Configure the Hermes logging subsystem; returns the ``logs/`` directory.

Safe to call multiple times; the second call is a no-op unless *force*. Level and
rotation defaults come from config.yaml ``logging.*``. ``mode="gateway"`` adds
``gateway.log`` and ``mode="gui"`` adds ``gui.log``.
ÚlogsÚINFOi   ©ÚRedactingFormatterz	agent.logNz
errors.logzgateway.logr¾   zgui.logrÃ   )ÚlevelÚ	max_bytesrá   Ú	formatterÚ
log_filterTr}   z|concurrent-log-handler unavailable on this Windows install (%s); file logging fell back to stdlib rotation without rollover.zportalocker probe failedi    i  P i    )r	   r
   r<   rÞ   Ú_read_logging_configÚupperr7   r€   rè   r\   rê   r�   rŒ   Ú_add_rotating_handlerÚ_LOG_FORMATrª   ÚCOMPONENT_PREFIXESÚ_WINDOWS_CLH_FALLBACKÚ_fallback_warnedr‚   r   Ú_logging_initializedrë   ÚNOTSETr‹   r�   )rž   rß   rà   rá   râ   rã   rÕ   Úlog_dirÚ	cfg_levelÚcfg_max_sizeÚ
cfg_backupÚ
level_namerë   rì   Úbackupsrê   ÚrootÚhandler_specsÚfilenameÚlvlÚsizeÚcountÚ	components   $$$$$$                 r   Úsetup_loggingr  _  sî  € ð" ×+Ð+œ/Ó+€DÜ% d¨V¥mÓ4€Gô Ôô ˜T×"Ò"ØˆÜ*>Ó*@Ñ'€I˜ZØ×2Ð2˜y×2Ð2¨F×9Ñ9Ó;€JÜ”G˜Z¬¯©Ó6€EØ×1Ð1 ×1Ð1°°TÕ9¸DÕ@€IØ×-Ð-˜j×-Ð-¨A€Gå/ä×ÒÓ€Dð
 
�e¨°Ð6Ø	”w—‘¨¸¸DÐAØ	œŸ™ o°q¸)ÐDØ	”G—L‘LÐ"2°A°uÐ=ð	€Mó 2?Ñ-ˆ�#�t˜U IØÒ  T¨YÔ%6ÙÜØ�hÕ c°TÈÙ(¬Ó5ßJSÔ'Ô(:¸9Õ(EÔFÐY]÷	
ñ 2?÷ Ó×%5Ó%5ð  ÐÜ×ÒÐ*Ó+×3Ñ3ðJä(×FÐFÐ,Fô	
÷ Ó§EØˆð ‡z�z”W—^‘^Ô# t§z¡z°EÔ'9Ø�‰�eÔÜÔØÐØ€Nr   c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r   °  s   € ÷ ;ñ ;˜tñ ;r   c                 ó¶  € ^ RI Hp  \        P                  ! 4       p\        ;QJ d&    R VP
                   4       F  '       g   K   RM	  RM! R VP
                   4       4      '       d   R# \        P                  ! \        4       4      pVP                  \        P                  4       VP                  V ! \        RR7      4       RVn        VP                  V4       VP                  \        P                  8”  d    VP                  \        P                  4       \        4        \        P                  ! R4      P                  \        P                   4       R# )	zCEnable DEBUG-level console logging for ``--verbose`` / ``-v`` mode.ré   c              3   ó<   "  € T F  p\        VR R4      x € K  	  R# 5i)Ú_hermes_verboseFN)r7   )Ú.0Úhs   & r   Ú	<genexpr>Ú(setup_verbose_logging.<locals>.<genexpr>¶  s   é € Ð
G¹°AŒ7�1Ð'¨×/Ð/»ùs   ‚TFNz%H:%M:%S)Údatefmtz
rex-deploy)r\   rê   r€   r�   ÚanyÚhandlersÚStreamHandlerrP   r‹   ÚDEBUGÚsetFormatterÚ_LOG_FORMAT_VERBOSEr	  Ú
addHandlerrë   r�   rè   )rê   rþ   rÑ   s      r   Úsetup_verbose_loggingr  °  sÑ   € å/ä×ÒÓ€Dç
ƒsÑ
G¸¿ºÓ
G‡s‡s‚sÑ
G¸¿ºÓ
G×GÒGÙÜ×#Ò#¤L£NÓ3€GØ×Ñ”W—]‘]Ô#Ø×ÑÑ+Ô,?ÈÔTÔUØ"€GÔØ‡O�O�GÔà‡z�z”G—M‘MÔ!Ø�‰”g—m‘mÔ$ÜÔä×Ò�lÓ#×,Ñ,¬W¯\©\Ö:r   c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r   Å  s   € ÷ ñ �Dñ r   c                ó:   €  V ! 4        R#   \          d     R# i ; i)u^   Call *fn* (a ``close``/``stop`` bound method) swallowing errors â€” teardown must never raise.N)r   )Úfns   &r   Ú_quietlyr  Å  s   € ðÙ
ŽøÜô Úðús   ‚ ‹™c                   óÂ   a a€ ] tR tRt oRtV 3R ltR tRV3R lR lltRV3R lR lltV3R	 lR
 lt	V3R lV 3R llt
V3R lV 3R lltV 3R ltV 3R ltRtVtV ;t# )Ú_ManagedRotatingFileHandleriÍ  aé  RotatingFileHandler with managed-mode perms and external-rotation detection.

In managed mode (NixOS) the setgid stateDir needs group-readable files, but
``_open()``/``doRollover()`` honor the umask (0644), so ``chmod 0660`` follows both.
A rotating handler also holds an fd: if the file is rotated externally (logrotate,
``mv``) writes silently go to the old inode, so each emit compares the path's inode
to the open stream's and reopens on mismatch (the ``WatchedFileHandler`` pattern).
c                ó¤   <€ ^ RI Hp V! 4       V n        RV n        RV n        RV n        RV n        \        SV `   ! V/ VB  V P                  4        R# )rZ   )Ú
is_managedFN)
Úhermes_cli.configr  Ú_managedÚ_unavailable_reportedÚ_skip_write_when_dir_missingÚskipped_missing_dirÚ_never_reopen_after_closer¯   rW   Ú_record_stream_stat)rV   rŸ   r    r  r²   s   &*, €r   rW   Ú$_ManagedRotatingFileHandler.__init__×  sQ   ø€ Ý0Ù"›ˆŒØ%*ˆÔ"ð -2ˆÔ)Ø#(ˆÔ ð */ˆÔ&Ü‰Ò˜$Ð) &Ò)Ø× Ñ Ö"r   c                ó–   € V P                   '       d%    \        P                  ! V P                  R 4       R# R#   \         d     R# i ; i)i°  N)r   r!   ÚchmodrÍ   r'   )rV   s   &r   Ú_chmod_if_managedÚ-_ManagedRotatingFileHandler._chmod_if_managedå  s=   € Ø�=�=ˆ=ðÜ—’˜×*Ñ*¨EÖ2ñ øô ô Úðús   ”!9 ¹AÁAc                óH   <€ V ^8„  d   QhRS[ S[P                  ,          RR/# )r   Ústr   N)r   r!   Ústat_result)r   rn   s   "€r   r   Ú(_ManagedRotatingFileHandler.__annotate__ì  s$   ø€ ÷ 8ñ 8¡h©r¯~©~Õ&>ð 8È$ñ 8r   c                óä   €  T;'       g!    \         P                  ! V P                  4      pVP                  VP                  uV n        V n        R#   \         d    RRuT n        T n         R# i ; i)zLSnapshot dev/ino of ``baseFilename`` so emit() can detect external rotation.N)r!   ÚstatrÍ   Úst_devÚst_inoÚ	_stat_devÚ	_stat_inor'   ©rV   r,  s   &&r   r%  Ú/_ManagedRotatingFileHandler._record_stream_statì  sZ   € ð	8Ø×1Ð1”r—w’w˜t×0Ñ0Ó1ˆBØ-/¯Y©Y¸¿	¹	Ð*ˆDŒN˜DžNøÜô 	8Ø-1°4Ð*ˆDŒN˜DŸNð	8ús   ‚A ‹AA ÁA/Á.A/c                ó   <€ V ^8„  d   QhRR/# r0   r1   )r   rn   s   "€r   r   r.  ô  s   ø€ ÷ .ñ .°$ñ .r   c                óà   € V P                   e    \        V P                   P                  4       RV n          V P                  4       V n         T P                  T4       R#   \         d     R# i ; i)z–Close and reopen ``baseFilename`` (best-effort).

On failure the stream is left ``None`` so the next emit bails rather than
writing to a stale inode.
N)r+   r  rN   Ú_openr   r%  )rV   r-  s   &&r   Ú_reopen_streamÚ*_ManagedRotatingFileHandler._reopen_streamô  s]   € ð �;‰;Ò"Ü�T—[‘[×&Ñ&Ô'ØˆŒð	ØŸ*™*›,ˆDŒKð 	× Ñ  Ö-øô ô 	Úð	ús   ¶A ÁA-Á,A-c                ó   <€ V ^8„  d   QhRR/# r0   r1   )r   rn   s   "€r   r   r.    s   ø€ ÷ $ñ $¨tñ $r   c                ó�  €  \         P                  ! V P                  4      pT P                  e   T P                  f   T P                  T4       R# TP                  TP                  3T P                  T P                  38w  d   T P	                  T4       R# R#   \         d    T P	                  4         R# \
         d     R# i ; i)zãReopen when ``baseFilename`` was renamed, unlinked, or replaced by another inode.

Silent + best-effort: any error falls back to the existing (possibly stale)
stream so logging keeps working instead of dying on a stat failure.
N)r!   r0  rÍ   ÚFileNotFoundErrorr:  r'   r3  r4  r%  r1  r2  r5  s   & r   Ú_reopen_if_externally_rotatedÚ9_ManagedRotatingFileHandler._reopen_if_externally_rotated  sŸ   € ð	Ü—’˜×*Ñ*Ó+ˆBð �>‰>Ò! T§^¡^Ò%;Ø×$Ñ$ RÖ(Ø�i‰i˜Ÿ™Ð#¨¯©¸¿¹Ð'GÔGØ×Ñ Ö#ñ Høô !ô 	Ø×ÑÔ!ÚÜô 	Úð	ús   ‚ B ÂCÂ7CÃ CÃCc                ó8   <€ V ^8„  d   QhRS[ P                  RR/# ©r   r¡   r   N©r€   r¶   )r   rn   s   "€r   r   r.    s!   ø€ ÷ /ñ /™7×,Ñ,ð /°ñ /r   c                ól  <€ R V n         V P                  '       d   \        V RR 4      '       d   R# V P                  RJpT;'       g*    \        P
                  P                  V P                  4      pV'       d   V P                  4        V P                  fx   V'       g	   V'       gh   V P                  '       dV   \        P
                  P                  \        P
                  P                  V P                  4      4      '       g
   RV n         R# \        SV `5  V4       V P                  e
   R V n        R# R# )FÚ_closedNT)r#  r$  r7   r+   r!   r*   ÚexistsrÍ   r?  r"  ÚisdirÚdirnamer¯   Úemitr!  )rV   r¡   Ú
had_streamÚfile_existsr²   s   &&  €r   rI  Ú _ManagedRotatingFileHandler.emit  sØ   ø€ Ø#(ˆÔ ð ×)×)Ð)¬g°d¸IÀu×.MÒ.MÙØ—[‘[¨Ð,ˆ
à ×EÐE¤B§G¡G§N¡N°4×3DÑ3DÓ$EˆßØ×.Ñ.Ô0ð �K‰KÒ§Z·{È×Hi×HiÐHiÜŸ™Ÿ™¤b§g¡g§o¡o°d×6GÑ6GÓ&H×IÒIØ'+ˆDÔ$ÙÜ‰‰�VÔð �;‰;Ò"Ø).ˆDÖ&ñ #r   c                ó8   <€ V ^8„  d   QhRS[ P                  RR/# rB  rC  )r   rn   s   "€r   r   r.  0  s!   ø€ ÷ $ñ $¡'×"3Ñ"3ð $¸ñ $r   c                ó|  <a a€ \         P                  ! 4       ^,          o\        S4      '       d   \        4        R# \	        S4      '       d`   S P
                  '       g   RS n        \        VV 3R l4       S P                  e    \        S P                  P                  4       RS n        R# \        SS `)  V4       R# )ay  Suppress the known Windows ``concurrent-log-handler`` lock timeout.

CLH's ``emit()`` routes that RuntimeError here, so this is the single point to
silence it before stdlib prints to stderr (which the Desktop slash-worker
captures into chat output). Silencing is not silent: warn once through the
logging system so a wedged lock is visible in the logs instead of a black hole.
NTc                  óP   <€ \        R SP                   RS  R2\        4       R7      # )zhermes_logging: z unavailable (z(); file logging paused until it recovers)Úfile)ÚprintrÍ   rP   )r(   rV   s   €€r   rE   Ú9_ManagedRotatingFileHandler.handleError.<locals>.<lambda>B  s/   ø€ ¤Ø& t×'8Ñ'8Ð&9¸ÈÀuð M<ð <ÜBNÃ.õ"Rr   )r   Úexc_inforz   rƒ   r‡   r!  r  r+   rN   r¯   ÚhandleError)rV   r¡   r(   r²   s   f&@€r   rT  Ú'_ManagedRotatingFileHandler.handleError0  sŽ   ú€ ô �lŠl‹n˜QÕˆÜ2°3×7Ò7Ü+Ô-ÙÜ% c×*Ò*ð ×-×-Ð-Ø-1�Ô*Üõ Rô Sð �{‰{Ò&Ü˜Ÿ™×*Ñ*Ô+ØˆDŒKÙÜ‰Ñ˜FÖ#r   c                óD   <€ \         SV `  4       pV P                  4        V# rD   )r¯   r9  r)  )rV   r+   r²   s   & €r   r9  Ú!_ManagedRotatingFileHandler._openK  s   ø€ Ü‘‘“ˆØ×ÑÔ Øˆr   c                ó   <€  \         P                  ! V P                  4      p\        SV `  4        Ve†    \        \         RR 4      ! 4       ^ 8X  d7   \         P                  ! V P                  VP                  VP                  4       \         P                  ! V P                  VP                  R,          4       V P                  4        V P                  4        R #   \         d    R p LÈi ; i  \         d     LBi ; i)NÚgeteuidc                  ó   € R# )é   éÿÿÿÿr1   r1   r   r   rE   Ú8_ManagedRotatingFileHandler.doRollover.<locals>.<lambda>\  s   € ±"r   iÿ  )r!   r0  rÍ   r'   r¯   Ú
doRolloverr7   ÚchownÚst_uidÚst_gidr(  Úst_moder)  r%  )rV   Úpreviousr²   s   & €r   r^  Ú&_ManagedRotatingFileHandler.doRolloverP  sÊ   ø€ ð
	Ü—w’w˜t×0Ñ0Ó1ˆHô 	‰ÑÔØÒðÜœ2˜y©*Ô5Ó7¸1Ô<Ü—H’H˜T×.Ñ.°·±ÀÇÁÔQÜ—’˜×*Ñ*¨H×,<Ñ,<¸vÕ,EÔFð 	×ÑÔ ð 	× Ñ Ö"øô ô 	ØŠHð	ûô ô Ùðús#   ƒ C ¶BC/ ÃC,Ã+C,Ã/C=Ã<C=)r   r$  r"  r3  r4  r!  r#  r+   rD   )rf   rg   rh   ri   rj   rW   r)  r%  r:  r?  rI  rT  r9  r^  rk   rl   r¼   r½   s   @@r   r  r  Í  sU   ù‡ € ñõ#ò÷8ò 8÷.ò .÷$ð $÷&/ó /÷4$ó $õ6÷
#õ #r   r  c          
      óT   € V ^8„  d   QhR\         R\        R\        R\        R\        /# )r   r*   rë   rì   rá   r   )r   rå   r  )r   s   "r   r   r   g  s4   € ÷ ñ Ü
ðÜðÜ*-ðÜ=@ðä ñr   c               óÀ   € \        V P                  4       \        '       d   ^ ^ r2\        \	        V 4      W#RR7      pVP                  V4       VP                  V4       V# )zPCreate the ``logs/`` directory and a configured ``_ManagedRotatingFileHandler``.r?   )ÚmaxBytesÚbackupCountr>   )r
   rÎ   rô   r  r_   r‹   r  )r*   rë   rì   rá   rí   rÑ   s   &$$$$ r   Ú_new_file_handlerri  g  sW   € ô ˜DŸK™KÔ(ßÓð #$ Q�<Ü)ÜˆD‹	˜IÈ'ô€Gð ×Ñ�UÔØ×Ñ˜Ô#Ø€Nr   g       @c                   óÆ   a a€ ] tR tRt oRtV3R lV 3R lltV3R lR ltV3R lR ltV3R	 lR
 ltV3R lR lt	V3R lR lt
V3R lV 3R lltV3R lR ltRtVtV ;t# )rÈ   i€  zèRoute queued records to the log file for their Hermes home.

Used only behind the QueueListener, so its small routing lock never blocks an agent
or dashboard event loop. Per-home handlers keep rotation, redaction and managed perms.
c                ó:   <€ V ^8„  d   QhRS[ RS[S[,          RR/# )r   ÚexistingÚprofile_homesr   N)r.   r   r   )r   rn   s   "€r   r   Ú'_ProfileRoutingFileHandler.__annotate__‡  s(   ø€ ÷ 'ñ 'Ñ!4ð 'ÁXÉdÅ^ð 'ÐX\ñ 'r   c                óÈ  <€ \         SV `  VP                  R7       \        VP                  4      P                  4       p\        V4      V n        W0n        VP                  P                  P                  4       V n	        V Uu0 uF*  p\        V4      P                  4       P                  4       kK,  	  upV n        VP                  V n        \        VR^ 4      V n        \        VR^ 4      V n        / V n        \$        P&                  ! 4       V n        RV n        / V n        V P/                  VP0                  4       VP2                   F  pV P5                  V4       K  	  R# u upi )zDTake over *existing*'s path, level, rotation, formatter and filters.)rë   rg  rh  FN)r¯   rW   rë   r   rÍ   r�   r_   Ú_hermes_routed_log_pathrÎ   rÊ   rØ   rÌ   rc   Ú	_filenamer7   Ú
_max_bytesÚ_backup_countÚ_profile_handlersÚ	threadingÚRLockÚ_profile_handlers_lockÚ_router_closedÚ_liveness_checked_atr  rí   ÚfiltersÚ	addFilter)rV   rl  rm  rÜ   rÕ   rî   r²   s   &&&   €r   rW   Ú#_ProfileRoutingFileHandler.__init__‡  s  ø€ ä‰Ñ˜xŸ~™~ÐÔ.Ü˜×-Ñ-Ó.×6Ñ6Ó8ˆÜ ›MˆÔØ'/Ô$Ø%Ÿ_™_×3Ñ3×;Ñ;Ó=ˆÔÙMZÓ[É]ÀTœt D›z×4Ñ4Ó6×>Ñ>Ö@É]Ñ[ˆÔØ!Ÿ™ˆŒÜ! (¨J¸Ó:ˆŒÜ$ X¨}¸aÓ@ˆÔØJLˆÔÜ&/§o¢oÓ&7ˆÔ#Ø#ˆÔà79ˆÔ!Ø×Ñ˜(×,Ñ,Ô-Ø"×*Ô*ˆJØ�N‰N˜:Ö&ó +ùò \s   Â0Ec                ó:   <€ V ^8„  d   QhRS[ P                  RS[/# rµ   )r€   r¶   r   )r   rn   s   "€r   r   rn  ›  s!   ø€ ÷ ñ ¡w×'8Ñ'8ð ¹Tñ r   c                óÐ  € \        VR R4      p \        V4      P                  4       P                  4       pW0P                  8X  g   W0P                  9  d   V P                  # V P                  P                  V4      pVe   \        4       V,
          \        8¼  d$   V P                  V4      '       d   V P                  # V#   \        \
        \        3 d    T P                  p L®i ; i)rž   r   )r7   r   rØ   r�   rÏ   r:   r'   rÊ   rÌ   ry  ÚgetÚ
_monotonicÚ_PROFILE_LIVENESS_RECHECK_SÚ_release_if_deleted)rV   r¡   Úraw_homeÚ	candidateÚlasts   &&   r   Ú_home_for_recordÚ+_ProfileRoutingFileHandler._home_for_record›  sÇ   € Ü˜6 =°"Ó5ˆð	+Ü˜X›×1Ñ1Ó3×;Ñ;Ó=ˆIð ×*Ñ*Ô*¨i×?RÑ?RÔ.RØ×%Ñ%Ð%Ø×(Ñ(×,Ñ,¨YÓ7ˆØŠ<œ:›<¨$Õ.Ô2MÔMð ×'Ñ'¨	×2Ò2Ø×)Ñ)Ð)ØÐøô œ:¤wÐ/ô 	+Ø×*Ñ*ŠIð	+ús   �'C  Ã "C%Ã$C%c                ó&   <€ V ^8„  d   QhRS[ RS[/# rÔ   rÖ   )r   rn   s   "€r   r   rn  ¬  s   ø€ ÷ ñ ©ð ±ñ r   c                ó¨   € \        4       V P                  V&   VP                  4       '       d   \        V4      '       g   R# V P	                  V4       R# )z?Release *home* if it was deleted out of band; True when it was.FT)r€  ry  Úis_dirr   Úrelease_profile)rV   rÕ   s   &&r   r‚  Ú._ProfileRoutingFileHandler._release_if_deleted¬  s@   € ä*4«,ˆ×!Ñ! $Ñ'Ø�;‰;�=Š=Ô!9¸$×!?Ò!?Ùð 	×Ñ˜TÔ"Ùr   c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# rÔ   )r   r   r  )r   rn   s   "€r   r   rn  »  s!   ø€ ÷ ñ ¡dð ©xÑ8SÕ/Tñ r   c                óÌ  € V P                   ;_uu_ 4        V P                  P                  V4      pRRR4       Xe   V# \        VR,          V P                  ,          V P
                  V P                  V P                  V P                  R7      pWP                  8g  Vn
        RVn        V P                   ;_uu_ 4        V P                  ;'       g%    WP                  8g  ;'       d    WP                  9  pV'       d   RMV P                  P                  W4      pRRR4       W#Jd   \        VP                   4       V#   + '       g   i     EL; i  + '       g   i     L@; i)zNThe open handler for *home*; ``None`` once the router or that home is retired.Nrç   ©rë   rì   rá   rí   T)rw  rt  r  ri  rq  rë   rr  rs  rí   rÊ   r"  r$  rx  rÌ   Ú
setdefaultr  rN   )rV   rÕ   rÑ   ÚbuiltÚretireds   &&   r   Ú_handler_for_homeÚ,_ProfileRoutingFileHandler._handler_for_home»  s  € à×(×(Ó(Ø×,Ñ,×0Ñ0°Ó6ˆG÷ )àÒØˆNô
 "Ø�6�M˜DŸN™NÕ*°$·*±*ÈÏÉØ×+Ñ+°t·~±~ô
ˆð .2×5GÑ5GÑ-GˆÔ*Ø*.ˆÔ'Ø×(×(Ó(ð ×)Ñ)×mÐm¨d×6HÑ6HÑ.H×.lÐ.lÈT×YlÑYlÑMlˆGß%‘d¨4×+AÑ+A×+LÑ+LÈTÓ+YˆG÷	 )ð
 ÓÜ�U—[‘[Ô!Øˆ÷+ )×(Ð(ú÷ )×(ús#   •D?Â=)EÃ'EÃ>EÄ?E	ÅE#	c                ó4   <€ V ^8„  d   QhRS[ P                  /# )r   r¡   rC  )r   rn   s   "€r   r   rn  Ô  s   ø€ ÷ 
ñ 
™W×.Ñ.ñ 
r   c                óž   € V P                  V4      p\        V\        P                  4      '       d   TpV'       d   V P	                  V4       V# )aK  ``Handler.handle`` without this router's own I/O lock: each per-home handler takes its
own lock to write, and routing state has ``_profile_handlers_lock``. Holding ``self.lock``
across ``emit`` (which can open a handler, taking ``logging._lock``) inverted the order
``logging.shutdown`` uses (module lock, then handler lock) (T23).)rº   r^   r€   r¶   rI  )rV   r¡   Úrvs   && r   ÚhandleÚ!_ProfileRoutingFileHandler.handleÔ  s>   € ð
 �[‰[˜Ó ˆÜ�bœ'×+Ñ+×,Ò,ØˆFßØ�I‰I�fÔØˆ	r   c                ó8   <€ V ^8„  d   QhRS[ P                  RR/# rB  rC  )r   rn   s   "€r   r   rn  à  s!   ø€ ÷ %ñ %™7×,Ñ,ð %°ñ %r   c                ó†  €  V P                  V4      pV P                  V4      pVf7   W P                  8w  d'   V P                  V P                  V P                  4      r2Vf   R # W P                  8X  d   VP                  V4       R # ^ RIHpHp V! \        V4      4      p VP                  V4       V! V4       VP                  '       dF   V P                  V4       V P                  V P                  4      ;pe   VP                  V4       R # R # R #   T! T4       i ; i  \         d    T P                  T4        R # i ; i)N)Úreset_hermes_home_overrideÚset_hermes_home_override)r†  r“  rÊ   r˜  Úhermes_constantsrœ  r�  r_   r#  r‚  r   rT  )rV   r¡   rÕ   rÑ   rœ  r�  ÚtokenÚfallbacks   &&      r   rI  Ú_ProfileRoutingFileHandler.emità  s  € ð	%Ø×(Ñ(¨Ó0ˆDØ×,Ñ,¨TÓ2ˆGØŠ 4×+=Ñ+=Ô#=Ø $× 2Ñ 2°D×4JÑ4JÈ4×K]ÑK]Ó4^�gØŠÙØ×)Ñ)Ô)Ø—‘˜vÔ&Ù÷ ^Ù,¬S°«YÓ7ˆEð2Ø—‘˜vÔ&á*¨5Ô1ð ×*×*Ð*Ø×(Ñ(¨Ô.Ø $× 6Ñ 6°t×7IÑ7IÓ JÐJ�HÒWØ—O‘O FÖ+ñ Xñ +øñ	 +¨5Õ1ûô ô 	%Ø×Ñ˜V×$ð	%ús=   ‚A D  Á$!D  ÂD  Â!D Â2D  ÃAD  Ä
DÄD  Ä E Ä?E c                ó   <€ V ^8„  d   QhRR/# r0   r1   )r   rn   s   "€r   r   rn  ý  s   ø€ ÷ ñ �tñ r   c                óH  <€ V P                   ;_uu_ 4        R V n        \        V P                  P	                  4       4      pV P                  P                  4        RRR4       X F  p\        VP                  4       K  	  \        SV `  4        R#   + '       g   i     L>; i)TN)	rw  rx  Úlistrt  ÚvaluesÚclearr  rN   r¯   )rV   r  rÑ   r²   s   &  €r   rN   Ú _ProfileRoutingFileHandler.closeý  sq   ø€ Ø×(×(Ó(Ø"&ˆDÔÜ˜D×2Ñ2×9Ñ9Ó;Ó<ˆHØ×"Ñ"×(Ñ(Ô*÷ )ó  ˆGÜ�W—]‘]Ö#ñ  ä‰‰Ž÷ )×(ús   –ABÂB!	c                ó&   <€ V ^8„  d   QhRS[ RS[/# rÔ   rÖ   )r   rn   s   "€r   r   rn    s   ø€ ÷ 	ñ 	¡Dð 	©Tñ 	r   c                óB  € V P                   ;_uu_ 4        V P                  P                  VR4      pV P                  P	                  V4       V P
                  P                  VR4       RRR4       Xf   R# \        VP                  4       R#   + '       g   i     L-; i)zAClose and forget the routed files belonging to a deleted profile.NFT)rw  rt  ÚpoprÌ   Údiscardry  r  rN   )rV   rÕ   rÑ   s   && r   r‹  Ú*_ProfileRoutingFileHandler.release_profile  sw   € à×(×(Ó(Ø×,Ñ,×0Ñ0°°tÓ<ˆGØ×Ñ×'Ñ'¨Ô-Ø×%Ñ%×)Ñ)¨$°Ô5÷ )ð Š?ÙÜ�—‘ÔÙ÷ )×(ús   •ABÂB	)rs  rÊ   rq  rp  ry  rr  rt  rw  rÌ   rx  rÍ   )rf   rg   rh   ri   rj   rW   r†  r‚  r“  r˜  rI  rN   r‹  rk   rl   r¼   r½   s   @@r   rÈ   rÈ   €  s_   ù‡ € ñ÷'ó '÷(ð ÷"ð ÷ð ÷2
ð 
÷%ð %÷:ó ÷	÷ 	ð 	r   rÈ   c                   ó6   a € ] tR tRt o RtV 3R lR ltRtV tR# )Ú_NonFormattingQueueHandleri#  ay  ``QueueHandler`` for an in-process queue.

Stdlib ``prepare()`` formats and strips ``args``/``exc_info`` for cross-process
pickling; ours is in-process, so targets get the unformatted record and apply their
own ``RedactingFormatter`` on the listener thread. A shallow copy is returned because
the emitting thread's synchronous handlers may mutate ``record.message`` meanwhile.
c                óN   <€ V ^8„  d   QhRS[ P                  RS[ P                  /# rµ   rC  )r   rn   s   "€r   r   Ú'_NonFormattingQueueHandler.__annotate__,  s'   ø€ ÷ !ñ !™g×/Ñ/ð !±G×4EÑ4Eñ !r   c                ó.   € \         P                   ! V4      # rD   )Úcopyr¹   s   &&r   ÚprepareÚ"_NonFormattingQueueHandler.prepare,  s   € Ü�yŠy˜Ó Ð r   r1   N)rf   rg   rh   ri   rj   r³  rk   rl   rm   s   @r   r®  r®  #  s   ø‡ € ñ÷!ö !r   r®  c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r   0  s   € ÷ $ñ $˜dñ $r   c                 ó    € \         ;_uu_ 4        \        Rup sV e   \        V P                  4       RRR4       R#   + '       g   i     R# ; i)z[Flush and stop the background log listener (idempotent; atexit hook, so it takes the lock).N)rÙ   Ú_queue_listenerr  Ústop©Úlisteners    r   Ú_stop_queue_listenerr»  0  s7   € ÷ 
Ö	Ü$3°TÐ!ˆ�/ØÒÜ�X—]‘]Ô#÷ 
×	×	Ò	ús	   �#<¼A	c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r   9  s   € ÷ 
ñ 
 dñ 
r   c                 ó”   € \         e   \         P                  4        \        \        .\        O5RR/ s \         P                  4        R# )zá(Re)build + start a listener over the current handler set (``_queue_state_lock`` held).

A running listener is stopped first; this only happens while handlers are being
added (queue empty), so ``stop()`` returns immediately.
NÚrespect_handler_levelT)r·  r¸  r   Ú
_log_queuerÇ   Ústartr1   r   r   Ú_start_queue_listener_lockedrÁ  9  s8   € ô Ò"Ü×ÑÔÜ#¤JÐcÔ1FÒcÐ^bÑc€OÜ×ÑÖr   c                ó<   € V ^8„  d   QhR\         P                  RR/# )r   rÑ   r   N)r€   ÚHandler)r   s   "r   r   r   F  s   € ÷ ,ñ ,¤g§o¡oð ,¸$ñ ,r   c                ó˜  € \         ;_uu_ 4        \        fP   \        P                  ! 4       s\	        \        4      pRVn        \        P                  ! 4       P                  V4       \        P                  V 4       \        4        \        '       g   \        P                  ! \        4       RsRRR4       R#   + '       g   i     R# ; i)zéRoute *handler* through the shared async queue instead of attaching it to root.

Emitting threads never block on file I/O or the rotation lock; the ``QueueListener``
applies each handler's own level and filters on its worker thread.
NT)rÙ   r¿  ÚqueueÚSimpleQueuer®  Ú_hermes_queuer€   r�   r  rÇ   ÚappendrÁ  Ú_queue_atexit_registeredÚatexitÚregisterr»  )rÑ   Úqhs   & r   Ú_register_queued_handlerrÍ  F  s…   € ÷ 
Ö	ÜÒÜ×*Ò*Ó,ˆJÜ+¬JÓ7ˆBØ#ˆBÔä×ÒÓ×*Ñ*¨2Ô.Ü×$Ñ$ WÔ-Ü$Ô&ß'Ó'ô �OŠOÔ0Ô1Ø'+Ð$÷ 
×	×	Ò	ús   �BB8Â8C		c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r   ]  s   € ÷ ñ ˜ñ r   c                 ó°   € \         ;_uu_ 4        \        p V e!   V P                  4        V P                  4        RRR4       R#   + '       g   i     R# ; i)uU  Block until all queued records have been written, then resume.

Stops the listener (which processes every pending record before joining) and
restarts it. ``stop()`` joins the worker thread â€” do NOT call this on a hard-exit
path where the listener may be wedged on the rotation lock; use
``drain_log_queue()`` there, which bounds the wait.
N)rÙ   r·  r¸  rÀ  r¹  s    r   Úflush_log_queuerÐ  ]  s7   € ÷ 
Ö	Ü"ˆØÒØ�M‰MŒOØ�N‰NÔ÷	 
×	×	Ò	ús   �+AÁA	c                ó(   € V ^8„  d   QhR\         RR/# )r   Útimeoutr   N)Úfloat)r   s   "r   r   r   l  s   € ÷ ñ œUð ¨Tñ r   c                óœ   a€ \         oSf   R# \        P                  ! V3R lRRR7      pVP                  4        VP	                  V 4       R# )uî   Best-effort, time-bounded drain for hard-exit paths (no restart).

If the listener's worker is wedged on the cross-process rotation lock â€” the very
failure async logging exists to survive â€” an unbounded join would re-freeze shutdown.
Nc                  ó.   <€ \        S P                  4      # rD   )r  r¸  r¹  s   €r   rE   Ú!drain_log_queue.<locals>.<lambda>u  s   ø€ ¬°·±Ô(?r   zhermes-log-drainT)Útargetrc   Údaemon)r·  ru  ÚThreadrÀ  Újoin)rÒ  Útrº  s   & @r   Údrain_log_queuerÜ  l  s>   ø€ ô €HØÒÙÜ×ÒÔ ?ÐFXÐaeÔf€AØ‡G�G„IØ‡F�Fˆ7†Or   c                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r   Úprofile_homer   )r_   r   rå   )r   s   "r   r   r   z  s   € ÷ ñ ¬s´T­zð ¼cñ r   c                ón  a€  \        V 4      P                  4       P                  4       o\        ;_uu_ 4        \        pTe   TP                  4        Rs\        T3R l\         4       4      pTe   \        4        RRR4       T#   \        \        \
        3 d     ^ # i ; i  + '       g   i     X# ; i)az  Release this process's routed log files below a profile before it is removed.

The Desktop serve process can route records for several profiles through one
``QueueListener``. On Windows, each routed concurrent log handler keeps its
lock file open, so closing only external profile resources still leaves
``logs/.__agent.lock`` and ``logs/.__errors.lock`` unavailable to rmtree.
Nc              3   óv   <"  € T F.  p\        V\        4      '       g   K  VP                  S4      x € K0  	  R # 5irD   )r^   rÈ   r‹  )r
  rÑ   rÕ   s   & €r   r  Ú/release_profile_log_handlers.<locals>.<genexpr>�  s3   øé € ð 
á0�Ü˜'Ô#=×>ô *ˆG×#Ñ# D×)Ð)Û0ùs   ƒ9 9)r   rØ   r�   rÏ   r:   r'   rÙ   r·  r¸  ÚsumrÇ   rÁ  )rÞ  rº  ÚreleasedrÕ   s   &  @r   Úrelease_profile_log_handlersrä  z  s¡   ø€ ðÜ�LÓ!×,Ñ,Ó.×6Ñ6Ó8ˆ÷ 
Ö	Ü"ˆØÒØ�M‰MŒOØ"ˆOÜô 
å0ó
ó 
ˆð
 ÒÜ(Ô*÷ 
ð €Oøô ”z¤7Ð+ô Úðú÷ 
Ö	ð €Oús   ƒ'B ¸AB#ÂB ÂB Â#B4	c                ó\   € V ^8„  d   QhR\         \        \        ,          ,          R\        /# )r   rm  r   )r   r_   r   r   )r   s   "r   r   r   —  s#   € ÷ +ñ +¬h´s¼TµzÕ.Bð +Ätñ +r   c           
     ó6  € . pV  Fc  p \        \        V\        4      '       d
   V^,          MT4      P                  4       P	                  4       pY19  g   KR  TP                  T4       Ke  	  \        V4      ^8  d   R# \        ;_uu_ 4        \        '       g    RRR4       R# \         Uu. uF  p\        V\        4      '       g   K  VNK  	  ppV'       dR   V F@  pVP                  ;_uu_ 4        VP                  P                  V4      Vn        RRR4       KB  	   RRR4       R# \         pVe   VP#                  4        Rs. p\         F[  p	\        V	\$        4      '       d2   VP                  \        W‘4      4       \'        V	P(                  4       KJ  VP                  V	4       K]  	  V\        R&   Ve   \+        4         RRR4       R#   \
        \        \        3 d     EKä  i ; iu upi   + '       g   i     EK)  ; i  + '       g   i     R# ; i)a„  Make the queued file logs follow a desktop profile context.

``setup_logging`` binds handlers to one process home; the desktop dashboard's
embedded cron ticker may run jobs for every profile, so its static file handlers
are replaced with profile routers once the profile list is known. Returns ``True``
when routing is (or already was) enabled; a single-profile caller is left untouched.
FNT:NNN)r   r^   r°   rØ   r�   rÏ   r:   r'   rÈ  ÚlenrÙ   rÇ   rÈ   rw  rÌ   Úunionr·  r¸  r.   r  rN   rÁ  )
rm  rÐ   ÚentryrÜ   r  ÚroutersrÑ   rº  Úreplacementrl  s
   &         r   rÚ   rÚ   —  s®  € ð €EÛˆð	Ü¬
°5¼%×(@Ò(@˜E !žHÀeÓL×WÑWÓY×aÑaÓcˆHð Ö Ø�L‰L˜Ö"ñ ô ˆ5ƒz�A„~Ùç	Ö	ß$Ó$Ø÷ 
Ñ	õ 4ÓaÑ3˜´zÀ!ÔE_×7`—1�1Ñ3ˆÐaßÛ"�Ø×3×3Ó3Ø-4×-CÑ-C×-IÑ-IÈ%Ó-P�GÔ*÷ 4Ñ3ñ #ð ÷ 
Ñ	ô #ˆØÒØ�M‰MŒOØ"ˆOØˆß-ˆHÜ˜(Ô$7×8Ò8Ø×"Ñ"Ô#=¸hÓ#NÔOÜ˜Ÿ™Ö(à×"Ñ" 8Ö,ñ .ð $/Ô˜aÑ ØÒÜ(Ô*Ø÷/ 
Ñ	øô œ:¤wÐ/ô 	Ûð	üò b÷ 4×3Ñ3ú÷ 
×	Ð	ús[   ‰AGÂHÂ$HÂ,G-Ã	G-Ã#HÃ2!G2ÄHÄ*BHÇG*Ç)G*Ç-HÇ2HÇ=
HÈH	c                ó   € V ^8„  d   QhRR/# r0   r1   )r   s   "r   r   r   Å  s   € ÷ ñ  ñ r   c                 óŽ  € \        4        \        ;_uu_ 4        \        P                  ! 4       p \	        V P
                  4       F)  p\        VRR4      '       g   K  V P                  V4       K+  	  \         F  p\        VP                  4       K  	  \        P                  4        RsRRR4       R#   + '       g   i     R# ; i)zETear down the async logging queue + listener (test-isolation helper).rÇ  FN)r»  rÙ   r€   r�   r¤  r  r7   ÚremoveHandlerrÇ   r  rN   r¦  r¿  )rþ   r  s     r   Ú_reset_queued_handlersrï  Å  s†   € ô Ôß	Ö	Ü× Ò Ó"ˆÜ�d—m‘mÖ$ˆAÜ�q˜/¨5×1Ô1Ø×"Ñ" 1Ö%ñ %÷ 'ˆAÜ�Q—W‘WÖñ 'ä×#Ñ#Ô%Øˆ
÷ 
×	×	Ò	ús   ™>B3ÁAB3Â3C	rî   c                ó¢   € V ^8„  d   QhR\         R\        R\        R\        R\        P                  R\        \        P
                  ,          RR/# )	r   r*   rë   rì   rá   rí   rî   r   N)r   rå   r€   Ú	Formatterr   ÚFilter)r   s   "r   r   r   Ô  s_   € ÷ (&ñ (&Ü
ð(&ô ð(&ô ð	(&ô
 ð(&ô × Ñ ð(&ô œŸ™Õ(ð(&ð 
ñ(&r   c               ó¦  € V P                  4       p\         FÙ  p\        VRR4      V8X  g@   \        V\        4      '       d-   \        \        VRR4      4      P                  4       V8X  d    R# \        V\        4      '       g   Ko  VP                  VP                  8X  g   KŒ  VP                  P                  VP                  8X  g(   VP                  P                  VP                  9   g   KØ   R# 	  \        WW#VR7      pVe   VP                  V4       \         U	u. uF  p	\        V	\        4      '       g   K  V	NK  	  p
p	V
'       dv   \        4       pV
 F9  pVP                  VP                  4       VP!                  VP                  4       K;  	  \        V\#        V4      4      p\%        VP&                  4       Tp\)        V4       R# u up	i )zSRegister a queued ``RotatingFileHandler`` for *path*; idempotent per resolved path.rp  NrÍ   r   r�  )r�   rÇ   r7   r^   r.   r   rÈ   rq  rc   rÎ   rÊ   rÌ   ri  r{  rÅ   rÉ   rË   rÛ   r  rN   rÍ  )r*   rë   rì   rá   rí   rî   rÜ   rl  rÑ   r  rê  rÐ   ÚrouterÚrouteds   &$$$$$        r   rñ   rñ   Ô  si  € ð �|‰|‹~€Hß)ˆô �8Ð6¸Ó=ÀÔIÜ�xÔ!4×5Ò5Ü”W˜X ~°rÓ:Ó;×CÑCÓEÈÔQâÜ�hÔ :×;Ô;À×@RÑ@RÐV^×VcÑVcÖ@cØ�O‰O×"Ñ" h×&<Ñ&<Ô<ÀÇÁ×@VÑ@VÐZb×ZqÑZqÖ@qâñ *ô  Ø YÐU^ô€Gð ÒØ×Ñ˜*Ô%õ 0Ó]Ñ/�Q´:¸aÔA[×3\�qˆqÑ/€GÐ]ßÜ›5ˆÛˆFØ�I‰I�f×*Ñ*Ô+Ø�L‰L˜×.Ñ.Ö/ñ ô ,¨G´V¸E³]ÓCˆÜ�—‘ÔØˆä˜WÖ%ùò ^s   ÄGÄ<Gc                 ó$  €   ^ RI Hp  V ! \        4       4      pV'       g   R# VP                  R/ 4      p\        V\        4      '       d3   VP                  R4      VP                  R	4      VP                  R
4      3#  R#   \         dt    ^ RIHp \        4       p/ pTP                  4       '       dI   \        TRRR7      ;_uu_ 4       pT! T4      ;'       g    / pRRR4        KÎ    + '       g   i      Lß; i Läi ; i  \         d     L�i ; i)z3Best-effort read of ``logging.*`` from config.yaml.)Úload_user_config_effective)Úfast_safe_loadÚrz	utf-8-sig)r>   Nr€   rë   rà   rá   )NNN)Úhermes_cli.config_effectiver÷  r   r   Úutilsrø  rF  Úopenr  r^   Údict)r÷  Úcfgrø  Úconfig_pathÚfÚlog_cfgs         r   rï   rï   ÿ  sõ   € ðð		2ÝNÙ,¬_Ó->Ó?ˆC÷ Ø%Ð%Ø—'‘'˜) RÓ(ˆÜ�gœt×$Ò$Ø—K‘K Ó(¨'¯+©+°mÓ*DÀgÇkÁkÐR`ÓFaÐbÐbð %ð Ðøô ô 	2Ý,Ü)Ó+ˆKØˆCØ×!Ñ!×#Ò#Ü˜+ s°[×AÕAÀQÙ(¨Ó+×1Ð1¨r�C÷ B×A×AÓAúñ $ð		2ûô ô Ùðúsd   ƒB  ™D ¡D £AD Â A	C>Ã	C'ÃC>Ã$D Ã'C8Ã2C>Ã6D Ã8C>Ã;D Ã=C>Ã>D ÄDÄDc                óÐ   € V ^8„  d   Qh/ ^ \         9   d   \        \        P                  ,          ;R&   ^\         9   d   \        \        ,          ;R&   ^\         9   d
   \
        ;R&   # )r   r¿  r·  rÇ   )Ú__conditional_annotations__r   rÅ  rÆ  r   r¤  )r   s   "r   r   r      sX   € ÷ ñ ÷l /Ò .ŒH”U×&Ñ&Õ'Ñ .ñm÷n 0Ò /”œ-Õ(Ñ /ño÷p !Ò  ”tÑ  òqr   )Úopenaizopenai._base_clientÚhttpxÚhttpcoreÚasyncioÚhpackzhpack.hpackÚgrpcÚmodalÚurllib3zurllib3.connectionpoolÚ
websocketsÚcharset_normalizerÚmarkdown_it)r¾   Úhermes_pluginszplugins.platformszagent.memory_caller_scope)r¿   Ú	run_agentÚmodel_toolsÚbatch_runner)rÀ   )Ú
hermes_clirÁ   )rÂ   )zhermes_cli.web_serverzhermes_cli.pty_bridgezhermes_cli.desktopÚtui_gatewayÚuvicorn)g      ð?)Vr  rj   rÊ  r8   r²  rK   r€   r!   rÅ  r   ru  Úlogging.handlersr   r   Úpathlibr   Útimer   r€  Útypingr   r   rž  r   r	   r
   r   rö   rô   r   rõ   r,   r   Úconcurrent_log_handlerr-   r.   Úlocalr’   rò   r  r6   r<   rP   rR   rr   rz   r   ÚLockr~   rƒ   r‡   rŠ   r�   r“   r–   r¨   rò  rª   ró   rÒ   rÞ   r  r  r  r  ri  r�  rÃ  rÈ   r¿  r·  rÇ   rÉ  rÙ   r®  r»  rÁ  rÍ  rÐ  rÜ  rä  rÚ   rï  rñ   rï   r   )r  s   @r   Ú<module>r     sQ  øðöó Û Û Û 	Û Û 	Û Û 
Û ß 8Ý Ý (ß %÷ó ð
 Ð ð
 Ð Ø!Ð ØÐ õ"ð\ ‡<�<�7ÔÙ×Òö	
õ 	9à $Ñå4ð —?’?Ó$Ð ð O€Ø[Ð ð
 Ð õ+ò>÷&+ñ +õ 8õð  %Ð Ø"+§.¢.Ó"2Ð õõ.ð€õ:õ-õ
'õ
9ñ8  Ô !ô6�w—~‘~ô 6ð" Ð^ØÐBØˆZØ	Ð Ø
ˆIØ	ÐmðÐ õõ BðNà"&ðNð  $ðNð "&ð	Nð
 #'ðNð ðNð ÷Nõb;õ*ôW#Ð"5ô W#õtð, "Ð ôO §¡ô Oðn +/€
Ó .Ø+/€Ó /Ø Ð Ó  Ø Ð ð —N’NÓ$Ð ô
! ô 
!õ$õ
õ,õ.÷õõ:+õ\ð(&ð ,0÷(&ôVr   