+
    „WÝj c  ã                   óÚ  € 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 ^ RIHtHtHt ^ RIHt ]'       d   ^ RIt]P&                  ! R4      tR R ltR R	 ltR
 R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR6RRRR/R R llltRt R R  lt!R! R" lt"^Kt#R#t$R$ R% lt%R& R' lt&R( R) lt'R* R+ lt(R7t)R, R- lt*R. R/ lt+R0RR1^R2R3/R4 R5 llt,R# )8z|Serve-process lifecycle: parent death watchdog, port-conflict preflight, READY announcement, browser open, trusted proxies.
N)ÚPath)ÚTYPE_CHECKINGÚAnyÚOptional)Úatomic_json_writezhermes_cli.web_serverc                ó0   € V ^8„  d   QhR\         R\        /# )é   ÚpidÚreturn)ÚintÚstr)Úformats   "ÚSC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\web_server_lifecycle.pyÚ__annotate__r      s   € ÷ ;Nñ ;Nœsð ;N¤sñ ;Nó    c           	     óÐ  a€ \         P                  R8X  d�    \        RV  R24      P                  RR7      pTP                  R^4      ^,          P                  4       P                  4       p\        T4      ^8  g   T^,          P                  4       '       g   \        RT  24      hR	T^,           2# \        P                  R
8X  Ed   ^ RIp^ RIHo RpVP!                  RRR7      pSP"                  SP$                  SP"                  .VP&                  n        SP*                  VP&                  n        SP*                  .VP/                  SP0                  4      .^,          ,           VP2                  n        SP$                  VP2                  n        SP*                  .VP4                  n        SP$                  VP4                  n        VP'                  VRV 4      pV'       g2   VP7                  4       pVR 9   d   \        V 4      h\        VRV  24      hV3R l\9        ^4       4       w  ršr¼ VP3                  WtP;                  V	4      VP;                  V
4      VP;                  V4      VP;                  V4      4      '       g   \        VP7                  4       RV  24      h VP5                  V4       V	P<                  ^ ,          V	P>                  ,          pRVR,            2# \@        PB                  ! RR\E        V 4      RR.RRRRRR7      pVPF                  P                  4       pVPH                  ^ 8X  d   V'       d   RV 2# VPH                  ^8X  d	   V'       d    RVPJ                  PM                  4       9   d   \        V 4      h\        RV  RVPJ                  P                  4        24      h  \         d   p\        T 4      ThRp?ii ; i  TP5                  T4       i ; i)!zÔReturn a cross-runtime marker for the current incarnation of ``pid``.

``ProcessLookupError`` means the process is absent; other failures stay
distinct so callers fail safe rather than killing a healthy backend.
Úlinuxz/proc/z/statzutf-8)ÚencodingNÚ)z invalid /proc stat data for PID zlinux:Únt)Úwintypesi   Úkernel32T)Úuse_last_errorFzOpenProcess failed for PID c              3   óD   <"  € T F  pSP                  4       x € K  	  R # 5i©N)ÚFILETIME)Ú.0Ú_r   s   & €r   Ú	<genexpr>Ú(_process_start_marker.<locals>.<genexpr>>   s   øé € Ð,SÉ(ÀQ¨X×->Ñ->×-@Ð-@Ë(ùs   ƒ zGetProcessTimes failed for PID úwin:l     îD\88Úpsz-pz-ozlstart=Úreplace)Úcapture_outputÚtextr   ÚerrorsÚcheckúps:zno such processzps could not inspect PID z: )éW   i�  )'ÚsysÚplatformr   Ú	read_textÚFileNotFoundErrorÚProcessLookupErrorÚrsplitÚstripÚsplitÚlenÚisdigitÚOSErrorÚosÚnameÚctypesr   ÚWinDLLÚDWORDÚBOOLÚOpenProcessÚargtypesÚHANDLEÚrestypeÚPOINTERr   ÚGetProcessTimesÚCloseHandleÚget_last_errorÚrangeÚbyrefÚdwHighDateTimeÚdwLowDateTimeÚ
subprocessÚrunr   ÚstdoutÚ
returncodeÚstderrÚlower)r	   Ú	stat_lineÚexcÚfieldsr6   Ú!process_query_limited_informationr   ÚhandleÚerrorÚcreationÚ	exit_timeÚkernelÚuserÚfiletimeÚresultÚmarkerr   s   &               @r   Ú_process_start_markerrY      se  ø€ ô ‡|�|�wÔð	3Ü˜v c U¨%Ð0Ó1×;Ñ;ÀWÐ;ÓMˆIð ×!Ñ! # qÓ)¨!Õ,×2Ñ2Ó4×:Ñ:Ó<ˆÜˆv‹;˜Ô 6¨"¥:×#5Ñ#5×#7Ò#7ÜÐ<¸S¸EÐBÓCÐCØ˜˜r�
�|Ð$Ð$ä	‡w�w�$…ÛÝ#à,2Ð)Ø—=‘= ¸D�=ÓAˆØ)1¯©¸¿¹ÈÏÉÐ(Wˆ×ÑÔ%Ø'/§¡ˆ×ÑÔ$Ø-5¯_©_Ð,=ÀÇÁÐPX×PaÑPaÓAbÐ@cÐfgÕ@gÕ,gˆ× Ñ Ô)Ø+3¯=©=ˆ× Ñ Ô(Ø)1¯©Ð(9ˆ×ÑÔ%Ø'/§}¡}ˆ×ÑÔ$Ø×%Ñ%Ð&GÈÐPSÓTˆßØ×)Ñ)Ó+ˆEØ˜
Ô"Ü(¨Ó-Ð-Ü˜%Ð#>¸s¸eÐ!DÓEÐEä,SÌ%ÐPQÌ(Ó,SÑ)ˆ˜Vð	)Ø×+Ñ+ØŸ™ XÓ.°·±¸YÓ0GÈÏÉÐV\ÓI]Ð_e×_kÑ_kÐlpÓ_q÷ò ô ˜f×3Ñ3Ó5Ð9XÐY\ÐX]Ð7^Ó_Ð_ðð
 × Ñ  Ô(à×+Ñ+¨rÕ1°X×5KÑ5KÕKˆØ�hÐ!3Õ3Ð4Ð5Ð5ä�^Š^˜T 4¬¨S«°4¸ÐCÐTXÐ_cÐnuØ#,°Eô;€Fà�]‰]× Ñ Ó"€FØ×Ñ˜AÔ§&Ø�V�Hˆ~Ðð 	×Ñ˜QÔ§vÐ2CÀvÇ}Á}×GZÑGZÓG\Ô2\Ü  Ó%Ð%Ü
Ð-¨c¨U°"°V·]±]×5HÑ5HÓ5JÐ4KÐLÓ
MÐMøôe !ô 	3Ü$ SÓ)¨sÐ2ûð	3ûðH × Ñ  Õ(ús$   ˜N3 È0A3O Î3OÎ>O
Ï
OÏO%c                ó0   € V ^8„  d   QhR\         R\        /# )r   rX   r
   ©r   Úbool)r   s   "r   r   r   V   s   € ÷ 6ñ 6¤sð 6¬tñ 6r   c                 óê  € V P                  R 4      w  rpV'       d   V'       d   W3P                  4       8w  d   R# VR9   d   VP                  4       # VR8w  d   R# VP                  4       p\        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      p\        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      p\        V4      ^8¬  ;'       d    T;'       d    T# )Ú:Fr!   c              3   ól   "  € T F*  qP                  4       ;'       d    \        V4      ^8H  x € K,  	  R# 5i)é   N)r2   r1   ©r   Útokens   & r   r   Ú-_valid_parent_start_marker.<locals>.<genexpr>c   s'   é € ÐKÁF¸5—=‘=“?×6Ð6¤s¨5£z°Q¡Ô6ÃFùs   ‚4�4Tc              3   ó,   "  € T F
  pR V9   x € K  	  R# 5i)r^   N© ra   s   & r   r   rc   d   s   é € Ð4©V E�3˜%–<«Vùs   ‚)r   ÚwinÚwinms)Ú	partitionr/   r2   r0   Úanyr1   )rX   ÚprefixÚ	separatorÚvalueÚtokensÚhas_yearÚhas_times   &      r   Ú_valid_parent_start_markerrp   V   sµ   € Ø%×/Ñ/°Ó4Ñ€F�ußŸE U¯k©k«mÔ%;ÙØÐ*Ô*Ø�}‰}‹ÐØ�„~Ùð
 �[‰[‹]€Fß‹sÑKÁFÓK�s�sŠsÑKÁFÓKÓK€Hß‹sÑ4©VÓ4�s�sŠsÑ4©VÓ4Ó4€HÜˆv‹;˜!Ñ×5Ð5 ×5Ð5¨XÐ5r   c                ó<   € V ^8„  d   QhR\         R\         R\        /# ©r   ÚactualÚexpectedr
   r[   )r   s   "r   r   r   h   s&   € ÷ Hñ H¼ð HÄsð HÌtñ Hr   c                ó`   € V P                  R4      ;'       g    VP                  R4      '       * # )a)  Whether a marker mismatch proves the Desktop parent was replaced.

``linux:`` jiffies and ``win:``/``winms:`` FILETIME markers are machine
values; a mismatch there is PID-reuse evidence. The POSIX fallback (macOS
has no ``/proc``) is ``ps -o lstart=`` -- a wall-clock string rendered in
the current TZ/locale. Electron caches it once per app lifetime while the
backend re-renders it per spawn, so a timezone change (or DST, or column
padding) makes the SAME instant differ byte-for-byte. Any ``ps:`` mismatch
is therefore inconclusive (#95693, #93958).
r'   )Ú
startswith)rs   rt   s   &&r   Ú+_parent_start_marker_mismatch_is_conclusiverw   h   s+   € ð ×!Ñ! %Ó(×FÐF¨H×,?Ñ,?ÀÓ,FÔGÐGr   c                ó<   € V ^8„  d   QhR\         R\         R\        /# rr   r[   )r   s   "r   r   r   v   s!   € ÷ .ñ .¬ð .´sð .¼tñ .r   c                ó*  € W8X  d   R# V P                  R4      '       d   VP                  R4      '       g   R#  \        V P                  R4      4      p\        VP                  R4      4      pRpY$,
          R,          pYS8H  #   \         d     R# i ; i)a  Compare parent markers across Desktop generations.

Old Windows Desktop sends .NET ticks (``win:``); new builds send Electron's
creation time in Unix ms (``winms:``) to avoid launching PowerShell. The
backend reads the exact FILETIME and normalizes only for ``winms``.
Tr    zwinms:Fl     ko×ûDi'  )rv   r   ÚremoveprefixÚ
ValueError)rs   rt   Údotnet_ticksÚexpected_unix_msÚdotnet_ticks_at_unix_epochÚactual_unix_mss   &&    r   Ú_parent_start_markers_matchr€   v   s“   € ð ÔÙØ×Ñ˜V×$Ò$¨H×,?Ñ,?À×,IÒ,IÙðÜ˜6×.Ñ.¨vÓ6Ó7ˆÜ˜x×4Ñ4°XÓ>Ó?Ðð "9ÐØ"Õ?ÀFÕJ€NØÑ-Ð-øô ô Úðús   º4B ÂBÂBc                ó   € V ^8„  d   QhRR/# ©r   r
   Nre   )r   s   "r   r   r   �   s   € ÷ ñ ˜dñ r   c                 óT   € R F  p  \        V 4       K  	  R#   \         d     K#  i ; i)ul  Pre-import heavy modules so the event loop is not stalled on first use.

Cold Windows installs pay .pyc compilation + Defender scans (15-30s) on
these chains; the first WS RPC burst (setup.status, setup.runtime_check,
gateway.readyâ†’resolve_skin, model.options) pulled them in on the loop
thread (#60800). Warm them all off-loop while the socket is already open.
N)zhermes_cli.gatewayzhermes_cli.authzhermes_cli.copilot_authzhermes_cli.runtime_providerzhermes_cli.skin_enginezhermes_cli.inventoryzhermes_cli.model_switch)Ú
__import__Ú	Exception)Úmods    r   Ú_warm_gateway_moduler‡   �   s.   € óˆð	Ü�sŽOóøô ô 	Úð	ús   ‡˜'¦'c                ó$   € V ^8„  d   QhR\         /# ©r   r
   )Úfloat)r   s   "r   r   r   ¤   s   € ÷ 5ñ 5¬ñ 5r   c                  óP   €  ^ RI Hp  V ! 4       #   \         d    ^ RIHp Tu # i ; i)é    )Ú_get_restart_drain_timeout)Ú%DEFAULT_GATEWAY_RESTART_DRAIN_TIMEOUT)Úhermes_cli.gatewayr�   ÚImportErrorÚgateway.restartrŽ   )r�   rŽ   s     r   Ú_resolve_restart_drain_timeoutr’   ¤   s+   € ð5ÝAÙ)Ó+Ð+øÜô 5ÝIØ4Ò4ð5ús   ‚ �%¤%c                ó   € V ^8„  d   QhRR/# r‚   re   )r   s   "r   r   r   ­   s   € ÷ 
ñ 
¨ñ 
r   c                 óž   €  ^ RI Hp  ^ RIHp V! V ! RRR7      4       R#   \         d"   p\
        P                  RT4        Rp?R# Rp?ii ; i)u²  Bring this process's own state.db schema current at startup â€” read-only first.

The dashboard is a view layer; the gateway owns the writer. A healthy store
must never see a second writable ``SessionDB`` from this process (its
close-time checkpoint and a possible FTS rebuild in ``_init_fts`` are the
two-writer corruption vector, #107688 / #100896). Access-mode semantics
(no bootstrap of a missing store; one additive catch-up of a store that lags
SCHEMA_SQL, only while no gateway owns it, #79531 / #140315) live in the routers' own-store opener,
:func:`hermes_cli.web_server_sessions._open_session_db_at_path`. Never
raises: an unfixable store still gets the per-poll read-probe heal.
)Ú_open_session_db_for_profile)Úrelease_or_closeNT)Ú	read_onlyzvstartup schema reconcile of state.db failed (%s); session reads will report the store unavailable until owner recovery)Úhermes_cli.web_server_sessionsr•   Úhermes_state_registryr–   r…   Ú_logÚwarning)r•   r–   rM   s      r   Ú_eager_reconcile_own_session_dbrœ   ­   sG   € ð	
ÝOÝ:áÑ5°dÀdÔKÖLøÜô 
Ü�‰ðKØLO÷	
ò 	
ûð
ús   ‚   A«AÁAc                ó4   € V ^8„  d   QhRRR\         R\         /# )r   Úserverzuvicorn.ServerÚfallbackr
   ©r   )r   s   "r   r   r   Å   s"   € ÷ ñ Ð-ð ¼ð Äñ r   c                óâ   € V P                   '       d]   V P                   ^ ,          P                  '       d:   V P                   ^ ,          P                  ^ ,          P                  4       ^,          # V# )zTRead the OS-assigned port from the live uvicorn socket (ephemeral port-0 discovery).)ÚserversÚsocketsÚgetsockname)rž   rŸ   s   &&r   Ú_read_bound_portr¥   Å   sL   € à‡~‡~€~˜&Ÿ.™.¨Õ+×3×3Ð3Ø�~‰~˜aÕ ×(Ñ(¨Õ+×7Ñ7Ó9¸!Õ<Ð<Ø€Or   c                ó(   € V ^8„  d   QhR\         RR/# )r   Úactual_portr
   Nr    )r   s   "r   r   r   Ì   s   € ÷ Qñ Q¬Sð Q°Tñ Qr   c                óþ   € \         P                  P                  R4      pV'       g   R#  \        \	        V4      R\        V 4      /RRR7       R#   \         d"   p\        P                  RY4        Rp?R# Rp?ii ; i)zðPublish the port through an atomic ready file when ``HERMES_DESKTOP_READY_FILE`` is set.

Windows Desktop launches via ``pythonw.exe`` (no console flash) cannot use
stdout for the port announcement, so Electron waits for this JSON instead.
ÚHERMES_DESKTOP_READY_FILENÚport)ÚindentÚ
separatorsz+Failed to write dashboard ready file %r: %s)Ú,r^   )	r4   ÚenvironÚgetr   r   r   r…   rš   r›   )r§   ÚtargetrM   s   &  r   Ú_write_dashboard_ready_filer±   Ì   sd   € ô �Z‰Z�^‰^Ð7Ó8€FßÙðQÜœ$˜v›,¨´°[Ó1AÐ(BÈ4Ð\f×gøÜô QÜ�‰ÐBÀF×PÒPûðQús   «#A ÁA<ÁA7Á7A<c          
      óL   € V ^8„  d   QhR\         R\        R\        R\         RR/# )r   Úhostr§   Úopen_browserÚinitial_profiler
   N©r   r   r\   )r   s   "r   r   r   Ü   s1   € ÷ "8ñ "8œcð "8´ð "8Ä4ð "8ÔZ]ð "8Ðbfñ "8r   c                ó  a	a
€ V'       g   R# ^ RI o
\        P                  R8g  ;'       gP    \        \        P
                  P                  R4      ;'       g     \        P
                  P                  R4      4      pV'       g   \        P                  R4       R# ^ RI	H
p V R9  d   T MRpRV! V4       R	V 2o	V'       d   ^ R
IHp S	RV! V4       2,          o	V	V
3R lp\        P                  ! VRR7      P                  4        R# )zÊOpen the dashboard URL in the user's browser if appropriate.

Skips headless Linux (no DISPLAY/WAYLAND_DISPLAY) so a TUI browser can't
SIGHUP the server; maps ``0.0.0.0``/``::`` binds to ``127.0.0.1``.
Nr   ÚDISPLAYÚWAYLAND_DISPLAYzzSkipping browser-open: no DISPLAY or WAYLAND_DISPLAY detected (headless Linux). Pass --no-open to suppress this detection.)Úformat_url_hostú	127.0.0.1zhttp://r^   )Úquotez
/?profile=c                  ó|   <€  \         P                  ! R 4       SP                  S 4       R#   \         d     R# i ; i)g      ð?N)ÚtimeÚsleepÚopenr…   )Ú	_open_urlÚ
webbrowsers   €€r   Ú_openÚ"_maybe_open_browser.<locals>._open÷   s1   ø€ ð	Ü�JŠJ�sŒOØ�O‰O˜IÖ&øÜô 	Úð	ús   ƒ', ¬;º;T)r°   Údaemon)z0.0.0.0z::)rÂ   r)   r*   r\   r4   r®   r¯   rš   ÚdebugÚhermes_cli.url_utilsrº   Úurllib.parser¼   Ú	threadingÚThreadÚstart)r³   r§   r´   rµ   Ú_has_displayrº   Ú_display_hostr¼   rÃ   rÁ   rÂ   s   &&&&     @@r   Ú_maybe_open_browserrÎ   Ü   sÒ   ù€ ÷ Ùãä—<‘< 7Ñ*×rÐr¬d´2·:±:·>±>À)Ó3L×3qÐ3qÔPR×PZÑPZ×P^ÑP^Ð_pÓPqÓ.r€LßÜ�
‰
ðKô	
ñ 	å4à Ð(9Ô9‘D¸{€MØ™/¨-Ó8Ð9¸¸;¸-ÐH€IßÝ&Ø�z¡%¨Ó"8Ð!9Ð:Õ:ˆ	öô ×Ò˜E¨$Ô/×5Ñ5Ö7r   Ú
pid_existsÚprocess_start_markerc                óR   € V ^8„  d   QhR\         R\        \        ,          R\        /# )r   Údesktop_pidÚexpected_start_markerr
   )r   r   r   r\   )r   s   "r   r   r     s*   € ÷ %ñ %Üð%ä#¤C�=ð%ô 
ñ%r   c               ó^  €  VeM   T;'       g    \         p V! \        V 4      4      pTe'   \	        YQ4      '       d   R# \        YQ4      '       d   R# Vf	   ^ RIHp Tp\        V! \        V 4      4      4      '       * #   \         d     R# \         d    Rp Lqi ; i  \         d     R# i ; i)ak  True when the exact Desktop process that owns this backend is gone.

``HERMES_PARENT_PID`` is the Electron PID, not necessarily our PPID (the
Windows ``hermes.exe`` launcher adds shims), so never compare getppid().
The start marker (newer Desktops) defeats PID recycling; PID-only probing
stays for older ones. Any inconclusive failure keeps serving (fail-safe).
NTF)Ú_pid_exists)	rY   r   r-   r…   r€   rw   Úgateway.statusrÕ   r\   )rÒ   rÓ   rÏ   rÐ   ÚprobeÚactual_markerrÕ   s   &&$$   r   Ú_is_serve_orphanedrÙ     s¯   € ðØ Ò,Ø(×AÐAÔ,AˆEð%Ù %¤c¨+Ó&6Ó 7�ð Ò(Ü.¨}×TÒTÙ Ü>¸}×dÒdÙð ÒÝ2à$ˆJÜ™
¤3 {Ó#3Ó4Ó5Ô5Ð5øô! &ô ÚÜô %Ø $’ð%ûô ô ÚðúsU   ‚B �B —A= ¨B ¿B Á*B Á=BÂB ÂBÂBÂB ÂBÂB ÂB,Â+B,g      $@c                ó8   € V ^8„  d   QhR\         P                  /# r‰   )rÉ   ÚTimer)r   s   "r   r   r   0  s   € ÷ ñ ¤)§/¡/ñ r   c                 óÒ   € \         P                  ! \        \        P                  RR7      p RV n        V P                  4        \        P                  ! \        P                  4       V # )aí  Ask this backend to shut itself down, with a hard-exit backstop.

``os._exit`` here skipped the flush-on-kill handlers this same process
installs before serving (#96095, ``install_exit_flush_signal_handlers``)
and every ``atexit`` hook, so an unclean desktop exit dropped the in-memory
transcripts that a SIGTERM from a live desktop persists to ``state.db``.
Raise SIGTERM instead, and keep the reap guaranteed the way ``cli.py``'s
``_arm_exit_watchdog`` does: a daemon timer that ``os._exit``\ s if the
unwind stalls (it survives ``Py_FinalizeEx``'s non-daemon thread joins).
``raise_signal`` reaches Python's handler on Windows too, where
``os.kill(pid, SIGTERM)`` would terminate the process without running it.

Returns the armed ceiling timer.
)ÚargsT)rŒ   )
rÉ   rÛ   Ú_ORPHAN_EXIT_CEILING_Sr4   Ú_exitrÅ   rË   ÚsignalÚraise_signalÚSIGTERM)Úceilings    r   Ú_request_orphan_shutdownrä   0  sB   € ô �oŠoÔ4´b·h±hÀTÔJ€GØ€G„NØ‡M�M„OÜ
×ÒœŸ™Ô'Ø€Nr   c                ó   € V ^8„  d   QhRR/# r‚   re   )r   s   "r   r   r   F  s   € ÷ 3Vñ 3V dñ 3Vr   c            	     ó&  aaa€ \         P                  P                  R4      p \         P                  P                  R4      ;'       g    Ro\         P                  P                  R4      ;'       g    Rp \        T ;'       g    R4      oS^ 8:  d   R# SRJpY!RJ8w  d   R# T'       dQ   \        S;'       g    R4      '       d   T'       d   YP                  4       8w  d   \        P                  RSS4       R#  \        R\        \         P                  P                  RR	4      4      4      oR TTT3R llp\        P                  ! TRRR7      P                  4        R#   \        \
        3 d     R# i ; i  \        \
        3 d    R
o Lai ; i)a  Exit when the exact desktop parent that spawned this backend dies.

Desktop passes its PID and, in newer versions, a start marker (defeats PID
reuse) plus a per-spawn nonce (makes mixed-version plumbing fail safe:
marker without nonce or vice versa disables the watchdog).
ÚHERMES_PARENT_PIDÚHERMES_PARENT_START_MARKERNÚHERMES_PARENT_NONCEÚ z†Parent-death watchdog disabled: unusable HERMES_PARENT_START_MARKER=%r / nonce; falling back to no parent tracking for desktop PID %s.g      à?ÚHERMES_SERVE_WATCHDOG_POLL_Sz2.0g       @c                ó   € V ^8„  d   QhRR/# r‚   re   )r   s   "r   r   Ú2_start_parent_death_watchdog.<locals>.__annotate__l  s   € ÷ #ñ #�4ñ #r   c                  óÂ   <€ \        S S4      '       g   \        P                  ! S4       K*   \        P	                  R S S4       \        4        R#   \
         d     Li ; i)zaParent-death watchdog: desktop PID %s appears orphaned (expected_start_marker=%r); shutting down.N)rÙ   r¾   r¿   rš   r›   r…   rä   )rÒ   ÚpollÚstart_markers   €€€r   Ú_loopÚ+_start_parent_death_watchdog.<locals>._loopl  sR   ø€ Ü$ [°,×?Ò?Ü�JŠJ�tÖð	Ü�L‰LØsØØôô 	!Ö"øô ô 	Ùð	ús   ­A ÁAÁATzserve-parent-watchdog)r°   rÅ   r5   )r4   r®   r¯   r   Ú	TypeErrorr{   rp   r/   rš   r›   ÚmaxrŠ   rÉ   rÊ   rË   )Úraw_pidÚnonceÚ
has_markerrñ   rÒ   rï   rð   s       @@@r   Ú_start_parent_death_watchdogrø   F  sQ  ú€ ô �j‰j�n‰nÐ0Ó1€Gä—:‘:—>‘>Ð">Ó?×GÐGÀ4€LÜ�J‰J�N‰NÐ0Ó1×9Ð9°T€EðÜ˜'Ÿ-˜- RÓ(ˆð �aÔÙà TÐ)€JØ 4Ð'Ô(ÙßÔ5°l×6HÐ6HÀb×IÒI×QVÐZ_×cnÑcnÓcpÔZpô 	�‰ðEàØô		
ñ 	ðÜ�3œœbŸj™jŸn™nÐ-KÈUÓSÓTÓUˆ÷#ò #ô ×Ò˜E¨$Ð5LÔM×SÑSÖUøôK ”zÐ"ô Úðûô* ”zÐ"ô ØŠðús*   Á6E" ÂE" Ã;3E: Å"E7Å6E7Å:FÆFzBACKEND_PORT_IN_USE port={port}c                ó0   € V ^8„  d   QhR\         R\        /# )r   rM   r
   )r3   r\   )r   s   "r   r   r   …  s   € ÷ eñ eœwð e¬4ñ er   c                ót   € ^ RI pV P                   VP                  ^b^0R09   ;'       g    \        V RR4      R8H  # )z@True when ``exc`` is the platform's address-in-use bind failure.Ni@'  Úwinerror)ÚerrnoÚ
EADDRINUSEÚgetattr)rM   rü   s   & r   Ú_is_addr_in_use_errorrÿ   …  s=   € ãð �9‰9˜×)Ñ)¨2¨r°5Ð9Ñ9×dÐd¼WÀSÈ*ÐVZÓ=[Ð_dÑ=dÐdr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   r³   rª   r
   r¶   )r   s   "r   r   r   �  s!   € ÷ "ñ "œcð "¬ð "´ñ "r   c                ó¤  € V'       g   R# ^ RI pRV 9   d   VP                  MVP                  p VP                  W2P                  4      p \        TRR4      p\        P                  R8X  d#   Te   TP                  TP                  T^4       M'TP                  TP                  TP                  ^4       TP                  Y34        TP                  4        R#   \         d     R# i ; i  \         d&   p\        T4      u Rp?TP                  4        # Rp?i\         d     TP                  4        R# i ; i  TP                  4        i ; i)u  Probe whether binding ``host:port`` would fail with EADDRINUSE.

``port == 0`` (ephemeral) never conflicts, so it is skipped. Any probe
error other than address-in-use returns ``False`` so uvicorn surfaces it
with its normal diagnostics (bad host, EACCES, â€¦).
FNr^   ÚSO_EXCLUSIVEADDRUSEÚwin32)ÚsocketÚAF_INET6ÚAF_INETÚSOCK_STREAMr3   rþ   r)   r*   Ú
setsockoptÚ
SOL_SOCKETÚSO_REUSEADDRÚbindrÿ   Úcloser…   )r³   rª   Ú_socketÚfamilyr×   Ú
_exclusiverM   s   &&     r   Ú_port_bind_conflictr  �  s  € ÷ ÙÛà!$¨¤ˆW×Ò°'·/±/€FðØ—‘˜v×':Ñ':Ó;ˆðÜ˜WÐ&;¸TÓBˆ
Ü�<‰<˜7Ô" zÒ'=ð ×Ñ˜W×/Ñ/°¸QÕ?ð ×Ñ˜W×/Ñ/°×1EÑ1EÀqÔIØ�
‰
�D�<Õ ð 	�‰ŒÙøô) ô Úðûô ô *Ü$ SÓ)Ô)ð 	�‰�ûô ô Øà�‰Žðûð 	�‰�úsT   ¯C ÁA=C- ÃC*Ã)C*Ã-D:Ã8
DÄD:ÄD= ÄD:Ä%D:Ä&D= Ä9D:Ä:D= Ä=Ec                ó(   € V ^8„  d   QhR\         RR/# )r   Úliner
   N)r   )r   s   "r   r   r   ²  s   € ÷ ñ ¤sð ¨tñ r   c                óÆ   €  \         P                  ! ^V R,           P                  4       4       R#   \         d&     \	        T RR7        R#   \
         d      R# i ; ii ; i)uy  Write a machine-parsed sentinel line to the REAL stdout (fd 1).

``tui_gateway.server`` redirects ``sys.stdout`` to stderr at import (#94724),
so a ``print()`` sentinel never reaches the Desktop's stdout pipe; fd 1 is
untouched. If fd 1 is unwritable (pythonw.exe) fall back to ``print()`` for
humans only â€” pythonw spawns discover the port via the ready file. Never
raises.
Ú
T©ÚflushN)r4   ÚwriteÚencoder3   Úprintr…   )r  s   &r   Ú_write_machine_sentinel_liner  ²  sU   € ðÜ
�Š��T˜D•[×(Ñ(Ó*Ö+øÜô ð	Ü�$˜d×#Ð#øÜô 	Ûð	úðús&   ‚,0 °A ¼AÁAÁA ÁAÁA c                ó4   € V ^8„  d   QhR\         R\        RR/# )r   r³   rª   r
   N)r   r   )r   s   "r   r   r   Ä  s!   € ÷ 	ñ 	œcð 	¬ð 	°ñ 	r   c                ól   € \        \        P                  VR7      4       \        RV RV  R2RR7       R# )z@Print the machine sentinel + a human hint naming likely holders.)rª   z  Port z on u¿    is already in use â€” likely another 'hermes serve' / 'hermes dashboard' backend or the Hermes gateway. Stop the other process, or pass --port <other> (--port 0 picks a free ephemeral port).Tr  N)r  Ú_PORT_IN_USE_SENTINELr   r  )r³   rª   s   &&r   Ú_report_port_in_user  Ä  s=   € ä Ô!6×!=Ñ!=À4Ð!=Ó!HÔIÜ	Ø
�$��t˜D˜6ð "2ð 	2ð ÷r   c                óh   € V ^8„  d   QhR\         \        \        3,          R\        \        ,          /# )r   Údashboard_configr
   )Údictr   r   Úlist)r   s   "r   r   r   Ó  s&   € ÷ 4ñ 4´T¼#¼s¸(µ^ð 4ÌÌSÍ	ñ 4r   c                óx  € V P                  R. 4      pVR9   d   . pMN\        V\        4      '       d   V.pM4\        V\        \        34      '       g   \
        P                  RV4       . p\        \        4      pV FØ  p\        V\        4      '       d   VP                  4       '       g   \
        P                  RV4       KG  VP                  4       p RV9   dA   \        P                  ! VRR7      pVP                  ^ 8X  d   \        R4      h\        V4      pM \        \        P                  ! V4      4      p Wb9  g   KÇ  VP                  V4       KÚ  	  V\        \        4      8w  d&   \
        P                  R	R
P!                  V4      4       V#   \         d    \
        P                  RT4        EK<  i ; i)zñReturn the bounded proxy addresses uvicorn may trust: loopback plus valid config entries.

Invalid or unbounded (/0, '*') ``dashboard.trusted_proxies`` entries fail
closed so client-supplied forwarding headers never become request metadata.
Útrusted_proxieszVdashboard.trusted_proxies must be a list of IP addresses or CIDR networks; ignoring %rz[Ignoring invalid dashboard.trusted_proxies entry %r; expected an IP address or CIDR networkÚ/F)Ústrictzunbounded networkzwIgnoring unsafe dashboard.trusted_proxies entry %r; use a bounded IP address or CIDR network, never '*' or a /0 networkzDashboard trusted proxies: %sz, )Nrê   )r¯   Ú
isinstancer   r"  Útuplerš   r›   Ú&_DEFAULT_DASHBOARD_FORWARDED_ALLOW_IPSr/   Ú	ipaddressÚ
ip_networkÚ	prefixlenr{   Ú
ip_addressÚappendÚinfoÚjoin)r   Ú
configuredÚtrustedÚ	raw_entryÚentryÚnetworkÚ
normalizeds   &      r   Ú_dashboard_forwarded_allow_ipsr7  Ó  sy  € ð "×%Ñ%Ð&7¸Ó<€JØ�ZÔØ‰
Ü	�J¤×	$Ò	$Ø �\‰
Ü˜
¤T¬5 M×2Ò2Ü�‰ðàô	
ð
 ˆ
äÔ9Ó:€GÛˆ	Ü˜)¤S×)Ò)°·±×1BÒ1BÜ�L‰Lð*àôñ
 à—‘Ó!ˆð	Ø�eŒ|Ü#×.Ò.¨u¸UÔC�Ø×$Ñ$¨Ô)Ü$Ð%8Ó9Ð9Ü  ›\‘
ä ¤×!5Ò!5°eÓ!<Ó=‘
ð Ö$Ø�N‰N˜:Ö&ñ7  ð: ”$Ô=Ó>Ô>Ü�	‰	Ð1°4·9±9¸WÓ3EÔFà€Nøô ô 	Ü�L‰LðEàôó
 ð	ús   ÃAFÄFÆ!F9Æ8F9c                ó   € V ^8„  d   QhRR/# r‚   re   )r   s   "r   r   r   
  s   € ÷ 8ñ 8 $ñ 8r   c                 ó  € ^ RI Hp  ^ RIHpHp V R,          pR\
        P                  V! VR,          R,          4      3R\
        P                  V! VR,          R,          4      33 Fo  w  rEp\        P                  ! V4      pR	Vn
        VP                  '       d   K7  \        P                  ! V4      pVP                  V4       VP                  V4       Kq  	  \        P                  ! R4      P                  \        P                   4       R
# )aï  uvicorn's default console logging, without its ``dictConfig``.

``uvicorn.Config``'s default ``log_config`` runs ``dictConfig``, which calls
``logging.shutdown()`` on every live handler: a multiplexed gateway's profile log routers are
already installed when its listener is built, and a closed router stays closed. The listeners
pass ``log_config=None`` and get uvicorn's handlers here instead: ``uvicorn`` to stderr,
``uvicorn.access`` to stdout, neither propagating into the Hermes log files.
)ÚLOGGING_CONFIG)ÚAccessFormatterÚDefaultFormatterÚ
formattersÚuvicornÚdefaultÚfmtzuvicorn.accessÚaccessFN)Úuvicorn.configr:  Úuvicorn.loggingr;  r<  r)   rJ   rH   ÚloggingÚ	getLoggerÚ	propagateÚhandlersÚStreamHandlerÚsetFormatterÚ
addHandlerÚsetLevelÚINFO)	r:  r;  r<  Úformatsr5   ÚstreamÚ	formatterÚloggerÚhandlers	            r   Ú_uvicorn_console_loggingrR  
  sÎ   € õ .ßAà˜\Õ*€Gà	”C—J‘JÑ 0°¸Õ1CÀEÕ1JÓ KÐLØ	œ3Ÿ:™:¡°w¸xÕ7HÈÕ7OÓ'PÐQó$Ñˆ�iô ×"Ò" 4Ó(ˆØ ˆÔØ��ŠÜ×+Ò+¨FÓ3ˆGØ× Ñ  Ô+Ø×Ñ˜gÖ&ñ$ô ×Ò�iÓ ×)Ñ)¬'¯,©,Ö7r   Úws_pingÚtimeout_graceful_shutdownÚlifespanÚautoc                ó®   € V ^8„  d   QhR\         R\        R\        R\        \        \
        \
        3,          ,          R\        \
        ,          R\         /# )r   r³   rª   Úauth_requiredrS  rT  rU  )r   r   r\   r   r(  rŠ   )r   s   "r   r   r   %  sK   € ÷ 4*ñ 4*¬Cð 4*´sð 4*Ìdð 4*Ü#+¬E´%¼°,Õ,?Õ#@ð4*ä5=¼eµ_ð4*äTWñ4*r   c               ó€  a€ ^ RI p^ RIHp ^ RIHp	Hp
  V! 4       P                  R4      ;'       g    / oRR V3R lllpVf   W9   d   RMV! R4      V! R4      3p\        4        VP                  ! WVR	RV\        S4      V^ ,          V^,          V	VVR
7      pWÇP                  ! V4      3#   \         d    / o L‡i ; i)aý  uvicorn ``Config`` + ``Server`` for a dashboard or gateway-session listener (FastAPI-free, so
the gateway can build its session listener without importing the dashboard app).

WS keepalive ping runs ON the agent event loop; a GIL-holding worker call can starve it for
minutes, so uvicorn misses the pong and drops a healthy local socket (#53773/#48445/#50005).
The ping only detects half-open connections (proxy 524, dropped tunnels), impossible on
loopback where a dead client sends a real FIN/RST -> WebSocketDisconnect. So: no ping on
loopback; non-loopback sits behind a Cloudflare Tunnel (~100s idle) and keeps a config-driven
cadence (dashboard.ws_ping_interval/_timeout, #79635) defaulting to 20/20. *ws_ping* overrides
both (SSH-isolated Desktop backends).
N)Úload_config)Ú _DESKTOP_ATTACHMENT_WS_MAX_BYTESÚ_LOOPBACK_HOST_VALUESÚ	dashboardc                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   Úkeyr?  r
   )r   rŠ   )r   s   "r   r   Ú+build_listener_server.<locals>.__annotate__<  s!   € ÷ ñ œcð ¬Eð ¼Uñ r   c                 ól   <€  \        SP                  W4      4      #   \        \        3 d    Tu # i ; ir   )rŠ   r¯   ró   r{   )r_  r?  Údash_cfgs   &&€r   Ú_ws_ping_settingÚ/build_listener_server.<locals>._ws_ping_setting<  s5   ø€ ð	Ü˜Ÿ™ cÓ3Ó4Ð4øÜœ:Ð&ô 	ØŠNð	ús   ƒ �3²3Úws_ping_intervalÚws_ping_timeoutr›   )r³   rª   Ú	log_levelÚ
log_configÚproxy_headersÚforwarded_allow_ipsre  rf  Úws_max_sizerT  rU  )g      4@)NN)r>  Úhermes_cli.configrZ  Úhermes_cli.web_server_boundaryr[  r\  r¯   r…   rR  ÚConfigr7  ÚServer)Ú
served_appr³   rª   rX  rS  rT  rU  r>  rZ  r[  r\  rc  Úconfigrb  s   &&&$$$$      @r   Úbuild_listener_serverrr  %  sÑ   ø€ ó Ý-ßfðÙ“=×$Ñ$ [Ó1×7Ð7°Rˆ÷ò ð ‚Ø"&Ô"?‘,ÙÐ/Ó0Ñ2BÐCTÓ2UðFWˆäÔØ�^Š^Ø D°IÈ$ð $ô ;¸8ÓDØ  �Ø �
Ø4ð
 #<Øô#€Fð& —>’> &Ó)Ð)Ð)øôA ô ØŠðús   •B- ²B- Â-B=Â<B=r   )r»   z::1)-Ú__doc__ÚasynciorD  r*  r4   rà   rF   r)   rÉ   r¾   Úpathlibr   Útypingr   r   r   Úutilsr   r>  rE  rš   rY   rp   rw   r€   r‡   r’   rœ   r¥   r±   rÎ   rÙ   rÞ   rä   rø   ÚPORT_IN_USE_EXIT_CODEr  rÿ   r  r  r  r)  r7  rR  rr  re   r   r   Ú<module>ry     s  ðñó Û Û Û 	Û Û Û 
Û Û Ý ß /Ñ /Ý #çÛð ×ÒÐ0Ó1€õ;Nõ|6õ$Hõ.õ.õ.5õ
õ0õQõ "8ñJ%ð ð	%ð
 ÷%ð %ðX Ð õõ,3Vðv Ð Ø9Ð õeõ"õJõ$	ð *>Ð &õ4õn8ð64*ØCGð4*àGHð4*àZ`÷4*ñ 4*r   