+
    lHàjÕ4  ã                   óR  a € R: t70 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 ^ RIHt ^ RIHtHtHt ^ RIHt ]P*                  ! ]4      tRtR] R2tR	tR
tRt/ t] ^ k ]	P<                  ! 4       t] ! R R4      4       t R R lt!R R lt"R R lt#R R lt$R R lt%Rt&]PN                  ! ^R7      R R l4       t(R R lt)R R lt*R;R  R! llt+R" R# lt,R<R$ R% llt-R& R' lt.R( R) lt/R* R+ lt0R,R-/R. R/ llt1R0 R1 lt2R2 R3 lt3R4 R5 lt4R6 R7 lt5R8 R9 lt6R# )=a‰  Lightpanda local engine for Browser Use mode.

With ``browser.engine: lightpanda``, Browser Use mode spawns one ``lightpanda serve`` per
browser session and points ``browser_exec`` at its CDP endpoint (``BU_CDP_URL``); the
built-in ``browser_*`` tools keep going through ``agent-browser --engine lightpanda``.
``tools.browser_tool`` owns the session cache, inactivity reaper and atexit sweep.
N)Ú	dataclass©ÚPath)ÚDictÚOptionalÚTuple)Úatomic_json_writez=https://lightpanda.io/docs/run-locally/installation/one-linerzInstall Lightpanda from z& and make sure `lightpanda` is on PATHg      $@gš™™™™™¹?iÐ  c                   ó^   a € ] tR t^%t o Rt]V 3R lR l4       tV 3R lR ltV 3R ltRt	V t
R# )ÚLightpandaServerNc                ó    <€ V ^8„  d   QhRS[ /# ©é   Úreturn©Ústr)ÚformatÚ__classdict__s   "€Ú=/home/ubuntu/.hermes/hermes-agent/tools/browser_lightpanda.pyÚ__annotate__ÚLightpandaServer.__annotate__.   s   ø€ ÷ /ñ /™ñ /ó    c                ó    € R V P                    2# )úhttp://127.0.0.1:)Úport©Úselfs   &r   Úcdp_urlÚLightpandaServer.cdp_url-   s   € à" 4§9¡9 +Ð.Ð.r   c                ó    <€ V ^8„  d   QhRS[ /# r   )Úbool)r   r   s   "€r   r   r   1   s   ø€ ÷ (ñ (™$ñ (r   c                ó:   € V P                   P                  4       R J # ©N)ÚprocÚpollr   s   &r   Úis_aliveÚLightpandaServer.is_alive1   s   € Ø�y‰y�~‰~Ó 4Ð'Ð'r   c                óz   <€ V ^8„  d   Qh/ S[ ;R&   S[;R&   S[P                  ;R&   S[ ;R&   S[S[,          ;R&   # )r   Úsession_namer   r"   Úlog_pathÚ
start_time)r   ÚintÚ
subprocessÚPopenr   )r   r   s   "€r   r   r   %   sL   ø‡ ‚ áÑñ ñ �Iñ ñ ×
Ñ
Ññ	 ñ
 �Mñ ñ ™•Ñ$ò r   © )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__r)   Úpropertyr   r$   Ú__annotate_func__Ú__static_attributes__Ú__classdictcell__)r   s   @r   r
   r
   %   s/   ø‡ € ð !%€Jà÷/ó ð/÷(ð (÷ ƒ r   r
   c                ó$   € V ^8„  d   QhR\         /# r   )Úlist)r   s   "r   r   r   5   s   € ÷ ñ œ$ñ r   c                  óD  € \         P                  ! 4       p V R ,          R,          V R,          R,          R,          .p ^ RIHp VP	                  \        V! 4       4      R,          R,          4       V#   \
         d"   p\        P                  RT4        Rp?T# Rp?ii ; i)z.lightpandaÚ
lightpandaz.localÚbin©Úget_hermes_homez1hermes home unavailable for lightpanda lookup: %sN)r   ÚhomeÚhermes_constantsr<   ÚappendÚ	ExceptionÚloggerÚdebug)r=   Ú
candidatesr<   Úes       r   Ú_home_candidatesrE   5   s�   € Ü�9Š9‹;€DØ˜Õ&¨Õ5°t¸hµÈÕ7NÐQ]Õ7]Ð^€JðMÝ4Ø×Ñœ$™Ó0Ó1°EÕ9¸LÕHÔIð Ðøô ô MÜ�‰ÐHÈ!×LÐLØÐûðMús   ¾3A3 Á3BÁ>BÂBc                ó:   € V ^8„  d   QhR\         \        ,          /# r   )r   r   )r   s   "r   r   r   @   s   € ÷ ]ñ ]¤¬¥ñ ]r   c                 óŠ  € \         P                  R8X  d   \        P                  R4       R# \         P                  P                  RR4      p  ^ RIHp V! V 4      p \        P                  ! RV R	7      ;'       g    \        R
 \        4        4       R4      #   \         d!   p\        P                  RT4        Rp?LaRp?ii ; i)zÃReturn the lightpanda executable, or None. Order: PATH (with agent-browser's Homebrew/managed-node
fallbacks), then installer/agent-browser locations, then ``$HERMES_HOME/bin``. No Windows build.ÚntzLightpanda has no Windows buildNÚPATHÚ )Ú_merge_browser_pathz"browser PATH merge unavailable: %sr9   ©Úpathc              3   óÀ   "  € T FT  qP                  4       '       g   K  \        P                  ! V\        P                  4      '       g   KG  \	        V4      x € KV  	  R # 5ir!   )Úis_fileÚosÚaccessÚX_OKr   )Ú.0Úcs   & r   Ú	<genexpr>Ú)find_lightpanda_binary.<locals>.<genexpr>M   s3   é € ÐUÑ+�A¯y©y¯{Œ¼r¿yºyÈÌBÏGÉG×?TŒŒˆQ�ˆÓ+ùs   ‚Až(AÁA)rP   ÚnamerA   rB   ÚenvironÚgetÚtools.browser_tool_installrK   r@   ÚshutilÚwhichÚnextrE   )Úpath_envrK   rD   s      r   Úfind_lightpanda_binaryr_   @   s¢   € ô 
‡w�w�$„Ü�‰Ð6Ô7ÙÜ�z‰z�~‰~˜f bÓ)€Hð>ÝBÙ& xÓ0ˆô �<Š<˜¨8Ô4÷ ]ð ]¼ÙUÔ)Ô+ÓUÐW[ó9]ð ]øô ô >Ü�‰Ð9¸1×=Ñ=ûð>ús   ÁB ÂCÂ"B=Â=Cc                ó$   € V ^8„  d   QhR\         /# r   ©r*   )r   s   "r   r   r   P   s   € ÷ *ñ *¤#ñ *r   c                  óv  € \         P                   ! \         P                  \         P                  4      ;_uu_ 4       p V P                  \         P                  \         P
                  ^4       V P                  R4       \        V P                  4       ^,          4      uuRRR4       #   + '       g   i     R# ; i)é   N)ú	127.0.0.1é    )	ÚsocketÚAF_INETÚSOCK_STREAMÚ
setsockoptÚ
SOL_SOCKETÚSO_REUSEADDRÚbindr*   Úgetsockname)Úsocks    r   Ú_pick_free_loopback_portro   P   sm   € Ü	�Š”v—~‘~¤v×'9Ñ'9×	:Ô	:¸dØ�‰œ×)Ñ)¬6×+>Ñ+>ÀÔBØ�	‰	Ð"Ô#Ü�4×#Ñ#Ó% aÕ(Ó)÷ 
;×	:×	:Ó	:ús   ¼A B'Â'B8	c                ó$   € V ^8„  d   QhR\         /# r   r   )r   s   "r   r   r   W   s   € ÷ ñ ”Dñ r   c                  ó‚   € ^ RI Hp  \        V ! 4       4      R,          R,          R,          pVP                  RRR7       V# )re   r;   Úcachezbrowser-user9   T©ÚparentsÚexist_ok)r>   r<   r   Úmkdir)r<   rM   s     r   Ú
_state_dirrw   W   s6   € Ý0Ü‘Ó!Ó" WÕ,¨}Õ<¸|ÕK€DØ‡J�J�t d€JÔ+Ø€Kr   c                ó$   € V ^8„  d   QhR\         /# r   r   )r   s   "r   r   r   ^   s   € ÷ 
ñ 
œñ 
r   c                 óN   € \        4       R,          p V P                  RRR7       V # )aH  Filesystem HTTP cache shared by every Lightpanda this Hermes spawns.

Shared rather than per-session so a cached asset survives session churn.
Lightpanda holds it in sqlite (WAL) with a best-effort write path, and
``--http-cache-entry-limit`` (upstream default 1000, not passed here)
bounds it without Hermes managing eviction.
z
http-cacheTrs   )rw   rv   rL   s    r   Ú_http_cache_dirrz   ^   s%   € ô ‹<˜,Õ&€DØ‡J�J�t d€JÔ+Ø€Kr   z--http-cache-dir)Úmaxsizec                ó0   € V ^8„  d   QhR\         R\        /# )r   Úbinaryr   )r   r   )r   s   "r   r   r   o   s   € ÷ ñ ¬ð ´ñ r   c                ó.  €  \         P                  ! V R.RRRRR\         P                  RR7      p\        VP                  ;'       g    RVP
                  ;'       g    R,           9   #   \         d"   p\        P                  R	T4        R
p?R# R
p?ii ; i)aK  True if ``lightpanda serve`` accepts ``--http-cache-dir``.

The flag landed upstream in 0.3.x; older binaries fatally reject it
("unknown argument"), which would break every launch. Probing ``help``
output keeps working across future flag additions without parsing
versions, and the lru_cache keeps it once per binary per process.
ÚhelpTúutf-8Úreplaceg      @F)Úcapture_outputÚtextÚencodingÚerrorsÚtimeoutÚstdinÚcheckrJ   z4lightpanda http-cache probe failed (%s); assuming noN)	r+   ÚrunÚDEVNULLÚ_HTTP_CACHE_FLAGÚstdoutÚstderrr@   rA   rB   )r}   r"   rD   s   &  r   Ú_binary_supports_http_cacherŽ   n   s�   € ð
Ü�~Š~Ø�VÐØ d°WÀYÐX[Ü×$Ñ$Øô	
ˆô   T§[¡[×%6Ð%6°B¸4¿;¹;×;LÐ;LÈ"Õ$MÑNÐNøÜô Ü�‰ÐKÈQÔOÝûðús$   ‚AA( ÁA( Á
A( Á(BÁ3BÂBc                ó0   € V ^8„  d   QhR\         R\        /# ©r   r'   r   )r   r   )r   s   "r   r   r   „   s   € ÷ 1ñ 1œsð 1¤tñ 1r   c                 ó*   € \        4       V  R 2,          # )ú.json)rw   ©r'   s   &r   Ú_record_pathr”   „   s   € Ü‹<˜\˜N¨%Ð0Õ0Ð0r   c                ó$   € V ^8„  d   QhR\         /# r   )Údict)r   s   "r   r   r   ˆ   s   € ÷ !ñ !”dñ !r   c                  ó¶   €  ^ RI Hp  V ! 4       #   \         d?   p\        P	                  RT4       \
        P                  P                  4       u Rp?# Rp?ii ; i)re   )Ú_build_browser_envz/credential-scrubbed browser env unavailable: %sN)Útools.browser_toolr˜   r@   rA   rB   rP   rX   Úcopy)r˜   rD   s     r   Ú_browser_envr›   ˆ   sC   € ð!Ý9Ù!Ó#Ð#øÜô !Ü�‰ÐFÈÔJÜ�z‰z�‰Ó Õ ûð!ús   ‚ �Aš3AÁAÁAc                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   Úurlr†   r   )r   Úfloatr   )r   s   "r   r   r   ‘   s!   € ÷ ñ ”Cð ¤%ð ´$ñ r   c                 ó€   €  ^ RI Hp V! WR7      #   \         d"   p\        P	                  RY4        Rp?R# Rp?ii ; i)re   )Úis_browser_debug_ready©r†   z%CDP readiness probe failed for %s: %sNF)Úhermes_cli.browser_connectr    r@   rA   rB   )r�   r†   r    rD   s   &&  r   Ú
_cdp_readyr£   ‘   s7   € ðÝEÙ% cÔ;Ð;øÜô Ü�‰Ð<¸cÔEÝûðús   ‚ ‘=œ8¸=c                ó0   € V ^8„  d   QhR\         R\         /# )r   rM   r   r   )r   s   "r   r   r   š   s   € ÷ Vñ Vœð V¤ñ Vr   c                óü   €  \        V 4      P                  4       \        ) R P                  RRR7      p\        R \        TP                  4       P                  4       4       4       R4      #   \         d     R# i ; i)zCLast non-empty line of the child's stderr log ('' when unreadable).Nr€   r�   )r…   rJ   c              3   óT   "  € T F  qP                  4       '       g   K  Vx € K   	  R # 5ir!   )Ústrip)rS   Úlns   & r   rU   Ú!_read_log_tail.<locals>.<genexpr>    s   é € ÐPÑA˜ÇXÁXÇZ—’ÓAùs   ‚(ž
()	r   Ú
read_bytesÚ_STDERR_TAIL_LIMITÚdecodeÚOSErrorr]   Úreversedr§   Ú
splitlines)rM   rƒ   s   & r   Ú_read_log_tailr°   š   st   € ðÜ�D‹z×$Ñ$Ó&Ô(:Ð':Ð';Ð<×CÑCÀGÐT]ÐCÓ^ˆô ÑPœh t§z¡z£|×'>Ñ'>Ó'@ÔAÓPÐRTÓUÐUøô ô Úðús   ‚2A, Á,A;Á:A;c                óH   € V ^8„  d   QhR\         P                  R\        RR/# )r   r"   Úwhatr   N)r+   r,   r   )r   s   "r   r   r   £   s'   € ÷ 
9ñ 
9”Z×%Ñ%ð 
9¬Sð 
9ÀDñ 
9r   c                ó  €  V P                  4       f&   V P                  4         V P                  ^R7       R# R#   \         d    T P	                  4         R# i ; i  \         d"   p\
        P                  RY4        Rp?R# Rp?ii ; i)zRpoll -> terminate -> wait(5) -> kill; shared with the real-profile Chrome cleanup.Nr¡   z%s terminate failed: %s)r#   Ú	terminateÚwaitr@   ÚkillrA   rB   )r"   r²   rD   s   && r   Ú
_terminater·   £   sp   € ð9Ø�9‰9‹;ÒØ�N‰NÔðØ—	‘	 !�	Ö$ñ øô ô Ø—	‘	—ðûäô 9Ü�‰Ð.°×8Ò8ûð9ús2   ‚"A ¥; »AÁA ÁAÁA ÁB	Á(BÂB	c                óF   € V ^8„  d   QhR\         R\        \         ,          /# ©r   Úpidr   )r*   r   )r   s   "r   r   r   °   s   € ÷ ñ œ#ð ¤(¬3¥-ñ r   c                 óV   €  ^ RI Hp VP                  V 4      #   \         d     R# i ; i)re   ©ÚProcessRegistryN)Útools.process_registryr½   Ú_safe_host_start_timer@   )rº   r½   s   & r   Ú_safe_start_timerÀ   °   s-   € ðÝ:Ø×4Ñ4°SÓ9Ð9øÜô Úðús   ‚ ™(§(c                ó(   € V ^8„  d   QhR\         RR/# )r   rº   r   Nra   )r   s   "r   r   r   ¸   s   € ÷ Lñ L”Cð L¨Dñ Lr   c                ó6   € ^ RI Hp VP                  WR7       R# )zFTree-kill ``pid`` via ProcessRegistry, verifying its start time first.r¼   )Úexpected_startN)r¾   r½   Ú_terminate_host_pid)rº   rÃ   r½   s   && r   Ú
_tree_killrÅ   ¸   s   € å6Ø×'Ñ'¨Ð'ÖKr   c                ó(   € V ^8„  d   QhR\         RR/# )r   Úserverr   N)r
   )r   s   "r   r   r   ¾   s   € ÷ ]ñ ]Ô*ð ]¨tñ ]r   c                 ó„  € R V P                   P                  RV P                  R\        P                  ! 4       RV P
                  R\        P                  ! 4       /p \        \        4       V P                   R2,          VRR7       R#   \         d-   p\        P                  RT P                  T4        Rp?R# Rp?ii ; i)	rº   r   Ú	owner_pidr)   Ú
started_atr’   N)Úindentz,could not write lightpanda record for %s: %s)r"   rº   r   rP   Úgetpidr)   Útimer   rw   r'   r­   rA   rB   )rÇ   ÚrecordrD   s   &  r   Ú_write_recordrÏ   ¾   s•   € Ø�V—[‘[—_‘_ f¨f¯k©k¸;ÌÏ	Ê	ËØ˜F×-Ñ-¨|¼T¿YºY»[ðJ€Fð]ô 	œ*›,¨F×,?Ñ,?Ð+@ÀÐ)FÕFÈÐW[×\øÜô ]Ü�‰ÐCÀV×EXÑEXÐZ[×\Ò\ûð]ús   Á*B ÂB?Â!B:Â:B?Úblock_private_networksFc          	      óŠ   € V ^8„  d   QhR\         R\        R\        \        \        ,          \        \         ,          3,          /# )r   r'   rÐ   r   )r   r   Útupler   r
   )r   s   "r   r   r   É   sJ   € ÷ .ñ .¤Cð .ÄDð .ÔUZÔ[cÔdtÕ[uÔwô  ADõ  xEð  \Eõ  VFñ .r   c               ó’  € \        4       pV'       g$   \        P                  R8X  d   R# RR\         R23# \	        4       pVRRRR\        V4      .p\        V4      '       d!   V\        \        \        4       4      .,          pV'       d   VP                  R	4       \        \        4       V  R
2,          4      p \        VR4      ;_uu_ 4       p\        P                  ! V\        P                  \        P                  V\        4       RR7      pRRR4       RT 2p	\$        P&                  ! 4       \(        ,           p
 XP+                  4       pTe)   \-        T4      pRRT RT	 RT'       d	   RT 2 23# R 23# \/        T	4      '       d   Mv\$        P&                  ! 4       T
8¼  dA   \1        T4       \-        T4      pT'       d   RT R2MRpRRT	 R\3        \(        4       RT 23# \$        P4                  ! \6        4       KÅ  \9        YYu\;        TP<                  4      4      p\?        T4       \@        ;_uu_ 4        T\B        T &   RRR4       \D        PG                  RTP<                  Y04       TR3#   + '       g   i     ELk; i  \         \        P"                  3 d   pRRT RT 23u Rp?# Rp?ii ; i  + '       g   i     L{; i)zÕStart ``lightpanda serve`` on a free loopback port; ``(server, None)`` once ``/json/version`` answers,
else ``(None, error)``. stderr goes to ``<state_dir>/<session>.log`` so a chatty child never blocks on a pipe.rH   Nzjbrowser.engine is 'lightpanda' but no lightpanda binary was found on PATH, ~/.lightpanda or ~/.local/bin. z , or set browser.engine to auto.Úservez--hostrd   z--portz--block-private-networksz.logÚwbT)r‡   rŒ   r�   ÚenvÚstart_new_sessionz#Failed to launch lightpanda serve (z): r   z"lightpanda serve exited with code z before z/json/version answeredz: rJ   z (last stderr line: Ú)z lightpanda serve did not expose z/json/version within Úsz9Started lightpanda serve (pid %s, port %s) for session %s)Nzzbrowser.engine is 'lightpanda' but Lightpanda has no Windows build. Set browser.engine to auto (or run Hermes under WSL2).)$r_   rP   rW   ÚLIGHTPANDA_INSTALL_HINTro   r   rŽ   r‹   rz   r?   rw   Úopenr+   r,   rŠ   r›   r­   ÚSubprocessErrorrÍ   Ú	monotonicÚ_READY_TIMEOUT_Sr#   r°   r£   r·   r*   ÚsleepÚ_POLL_INTERVAL_Sr
   rÀ   rº   rÏ   Ú_servers_lockÚ_serversrA   Úinfo)r'   rÐ   r}   r   Úargvr(   Úlog_filer"   rD   r�   ÚdeadlineÚrcÚtailÚdetailrÇ   s   &$             r   Úlaunch_lightpandarê   É   s­  € ô $Ó%€FßÜ�7‰7�dŒ?ð[ð [àð *Ü*AÐ)BÐBbðdð eð 	eô $Ó%€DØ�G˜X {°H¼cÀ$»iÐH€DÜ" 6×*Ò*ØÔ!¤3¤Ó'8Ó#9Ð:Õ:ˆßØ�‰Ð.Ô/Ü”:“< \ N°$Ð"7Õ7Ó8€HðJÜ�(˜D×!Ô! XÜ×#Ò# D´
×0BÑ0BÌ:×K]ÑK]Ø+3¼»Ð[_ôaˆD÷ "ð ˜d˜VÐ
$€CÜ�~Š~ÓÔ"2Õ2€HØ
Ø�Y‰Y‹[ˆØŠ>Ü! (Ó+ˆDØÐ=¸b¸TÀÈ#ÈÐNd×txÐgiÐjnÐioÐepð  eBð  Cð  Cð  Cð  Að  eBð  Cð  Cð  CÜ�c�?Š?ØÜ�>Š>Ó˜xÔ'Ü�tÔÜ! (Ó+ˆDß7;Ð+¨D¨6°Ñ3ÀˆFØÐ;¸C¸5Ð@UÔVYÔZjÓVkÐUlÐlmÐntÐmuÐvÐvÐvÜ�
Š
Ô#Ö$ä˜l°$ÔBRÐSW×S[ÑS[ÓB\Ó]€FÜ�&Ôß	ŽØ!'Œ�Ñ÷ 
ä
‡K�KÐKÈTÏXÉXÐW[ÔjØ�4ˆ<Ð÷7 "×!Ð!ûô ”Z×/Ñ/Ð0ô JØÐ:¸6¸(À#ÀaÀSÐIÐIÕIûðJú÷* 
�úsI   Â9J ÃAI0ÄJ È9
J6É0J	É;J ÊJ ÊJ3Ê	J.Ê(J3Ê.J3Ê6K	c                óF   € V ^8„  d   QhR\         R\        \        ,          /# r�   )r   r   r
   )r   s   "r   r   r   ú   s    € ÷ *ñ *œSð *¤XÔ.>Õ%?ñ *r   c                 ó†   € \         ;_uu_ 4        \        P                  V 4      uuR R R 4       #   + '       g   i     R # ; ir!   )rá   râ   rY   r“   s   &r   Ú
get_serverrí   ú   s   € ß	ŽÜ�|‰|˜LÓ)÷ 
��‹ús	   �/¯A 	c                ó(   € V ^8„  d   QhR\         RR/# )r   r'   r   Nr   )r   s   "r   r   r   ÿ   s   € ÷ Nñ N¤#ð N¨$ñ Nr   c                ó  € \         ;_uu_ 4        \        P                  V R4      pRRR4       Xe_   VP                  4       '       dI    \	        VP
                  P                  VP                  4        VP
                  P                  ^R7        \        4       V  R2,          P                  RR7       Ve   \        P                  RV 4       R# R#   + '       g   i     Lµ; i  \         dA   p\        P                  RTP                  T4       \        TP
                  4        Rp?L¹Rp?ii ; i  \         d    \        TP
                  4        LÆi ; i  \          d!   p\        P                  RY4        Rp?LËRp?ii ; i)	zaStop the server for ``session_name`` (tree-kill, plain terminate on failure) and drop its record.Nz&lightpanda tree-kill failed for %s: %sr¡   r’   T©Ú
missing_okz-could not remove lightpanda record for %s: %sz'Stopped lightpanda serve for session %s)rá   râ   Úpopr$   rÅ   r"   rº   r)   r@   rA   rB   r'   r·   rµ   rw   Úunlinkr­   )r'   rÇ   rD   s   &  r   Ústop_lightpandarô   ÿ   s'  € ç	ŽÜ—‘˜l¨DÓ1ˆ÷ 
àÒ˜fŸo™o×/Ò/ð	$Ü�v—{‘{—‘¨×(9Ñ(9Ô:ð	$Ø�K‰K×Ñ QÐÔ'ðWÜ	‹˜<˜.¨Ð.Õ	.×6Ñ6À$Ð6ÔGð ÒÜ�‰Ð>ÀÖMñ ÷! 
�ûô
 ô 	$Ü�L‰LÐAÀ6×CVÑCVÐXYÔZÜ�v—{‘{×#Ñ#ûð	$ûô
 ô 	$Ü�v—{‘{Ö#ð	$ûô ô WÜ�‰ÐDÀl×VÑVûðWúsM   �CÁ	*C& Á4D4 Â$E ÃC#	Ã&D1Ã16D,Ä,D1Ä4 EÅEÅFÅ%F Æ Fc                ó   € V ^8„  d   QhRR/# )r   r   Nr-   )r   s   "r   r   r     s   € ÷ Gñ G˜Tñ Gr   c                 ó   € \         ;_uu_ 4        \        \        4      p RRR4       X  F  p \        V4       K  	  R#   + '       g   i     L'; i  \         d"   p\
        P                  RY4        Rp?KO  Rp?ii ; i)zEStop every server this process started. Idempotent; safe from atexit.Nz!lightpanda stop failed for %s: %s)rá   r7   râ   rô   r@   rA   rB   )ÚnamesrW   rD   s      r   Ústop_all_lightpandarø     sZ   € ç	ŽÜ”X“ˆ÷ 
ãˆð	GÜ˜DÖ!ó ÷ 
�ûô
 ô 	GÜ�L‰LÐ<¸d×FÒFûð	Gús    �>­A¾A	ÁA=ÁA8Á8A=c                ó0   € V ^8„  d   QhR\         R\        /# r¹   )r*   r   )r   s   "r   r   r      s   € ÷ ñ ¤ð ¼$ñ r   c                ó&  €  ^ RI pVP                  V 4      pRVP                  4       P                  4       9  d   R# VP	                  4       pRV9  g   \        V4      V9  d   R# V'       d   ^ RIHp V! V 4      V8H  #  R#   \         d     R# i ; i)zJTrue only when ``pid`` is verifiably the ``lightpanda serve`` we recorded.Nr9   FrÔ   )Úget_process_start_timeT)	ÚpsutilÚProcessrW   ÚlowerÚcmdliner   Úgateway.statusrû   r@   )rº   r   r)   rü   r"   rÿ   rû   s   &&&    r   Ú_is_lightpanda_processr     s‡   € ðÛØ�~‰~˜cÓ"ˆØ˜tŸy™y›{×0Ñ0Ó2Ô2ÙØ—,‘,“.ˆØ˜'Ô!¤S¨£Y°gÔ%=ÙßÝ=Ù)¨#Ó.°*Ñ<Ð<ð ñ
 øô ô Úðús"   ‚8B ¼'B Á%B Á-B ÂBÂBc                ó$   € V ^8„  d   QhR\         /# r   ra   )r   s   "r   r   r   2  s   € ÷ 'ñ '¤#ñ 'r   c                 óî  €  \        4       p  ^ RIHp ^ p\        T P                  R4      4       EF“  pTP                  p \        P                  ! TP                  RR7      4      p\        T\        4      '       g"   \        R\        T4      P                    24      h TP'                  R
4      pT\(        P*                  ! 4       8X  d0   \,        ;_uu_ 4        T\.        9   d    RRR4       K¿   RRR4       M!T'       d   T! \1        T4      4      '       d   Kê  TP'                  R4      pT'       d   \3        \1        T4      TP'                  R4      TP'                  R4      4      '       dE    \5        \1        T4      TP'                  R4      4       T^,          p\        P7                  RY…4       TP%                  RR	7       EK–  	  T#   \         d"   p\        P                  RT4        Rp?^ # Rp?ii ; i  \         d     ^ # i ; i  \"        \        3 d    TP%                  RR	7        EK  i ; i  + '       g   i     EL-; i  \         d!   p\        P                  RY�4        Rp?L¿Rp?ii ; i)zÖKill ``lightpanda serve`` processes whose owning Hermes is gone; return the count. A live owner is
never touched; a PID is only signalled after psutil confirms it is still ``lightpanda serve`` on the recorded port.z$lightpanda state dir unavailable: %sN)Ú_pid_existsz*.jsonz	utf-8-sig)r„   zexpected a JSON object, got Trð   rÉ   rº   r   r)   z4Reaped orphaned lightpanda serve pid %s (session %s)z,orphan lightpanda kill failed for pid %s: %s)rw   r@   rA   rB   r   r  ÚsortedÚglobÚstemÚjsonÚloadsÚ	read_textÚ
isinstancer–   Ú
ValueErrorÚtyper.   r­   ró   rY   rP   rÌ   rá   râ   r*   r  rÅ   rã   )	Ú	state_dirrD   r  ÚreapedÚrecord_pathr'   rÎ   rÉ   rº   s	            r   Úreap_orphaned_lightpandar  2  sý  € ðÜ“Lˆ	ðÝ.ð €FÜ˜iŸn™n¨XÓ6×7ˆØ"×'Ñ'ˆð	Ü—Z’Z × 5Ñ 5¸{Ð 5Ó KÓLˆFÜ˜f¤d×+Ò+Ü Ð#?ÄÀVÃ×@UÑ@UÐ?VÐ!WÓXÐXð ,ð
 —J‘J˜{Ó+ˆ	ØœŸ	š	›Ô#ß–Ø¤8Ô+Ø÷ ‘Ø+÷ �÷ ™;¤s¨9£~×6Ò6ÙØ�j‰j˜ÓˆßÔ)¬#¨c«(°F·J±J¸vÓ4FÈÏ
É
ÐS_ÓH`×aÒaðUÜœ3˜s›8 V§Z¡Z°Ó%=Ô>Ø˜!•�Ü—‘ÐRÐTWÔfð 	×Ñ dÐ×+ñ1 8ð2 €MøôE ô Ü�‰Ð;¸QÔ?Ýûðûô
 ô Úðûô œÐ$ô 	Ø×Ñ¨$ÐÔ/Ûð	ú÷
 —�ûô ô UÜ—‘ÐKÈS×TÑTûðUús`   ‚
G	 �G8 Á AH
ÃH5Å-AI	Ç	G5ÇG0Ç0G5Ç8HÈHÈ
#H2È1H2È5IÉ	I4ÉI/É/I4c                ó8   € V ^8„  d   Qh/ ^ \         9   d   R;R&   # )r   zdict[str, LightpandaServer]râ   ©Ú__conditional_annotations__)r   s   "r   r   r      s!   € ÷ ñ ÷@ -Ò ,Ð
'Ñ ,òAr   )gš™™™™™É?)r9   )8r  Ú__doc__Ú	functoolsr  ÚloggingrP   r[   rf   r+   Ú	threadingrÍ   Údataclassesr   Úpathlibr   Útypingr   r   r   Úutilsr   Ú	getLoggerr.   rA   ÚLIGHTPANDA_INSTALL_URLrÚ   rÞ   rà   r«   râ   ÚLockrá   r
   rE   r_   ro   rw   rz   r‹   Ú	lru_cacherŽ   r”   r›   r£   r°   r·   rÀ   rÅ   rÏ   rê   rí   rô   rø   r  r  r   r  s   @r   Ú<module>r!     s2  øðöó Û Û Û 	Û Û Û Û Û Ý !Ý ß (Ñ (å #à	×	Ò	˜8Ó	$€àXÐ Ø4Ð5KÐ4LÐLvÐvÐ àÐ ØÐ ØÐ à*,€Ó ,Ø—’Ó €ð ÷(ð (ó ð(õõ]õ *õõ
ð &Ð ð ×Ò˜QÔôó  ðõ*1õ!÷õV÷
9õõLõ]ð.È5÷ .õb*õ
Nõ,Gõ÷$'r   