+
    lHàjj  ã                  ó
  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIHt ^RIH	t	 Rt
]P                  ! 4       t/ tR]R&   / tR]R	&   / tR
]R&   R R ltR R ltR R ltR R ltR R ltRtRsR R ltR R ltR R ltR R ltR# ) uî  Cross-process lease watcher: ``display.lease`` for transitions made OUTSIDE ``hermes serve``.

The lease (``tools.bot_desktop.lease``) lives on disk and is changed by whatever process hosts the
agent â€” a ``hermes computer-use screen`` takeover from the CLI, a cron worker's release.
``lease.on_change`` only fires in the writing process, so ``methods_display``'s in-process
listener never sees those; the Desktop's hero tone and pane state stayed stale until the
pane was reopened. One daemon thread stats every served home's ``bot-desktop/lease.json`` (launch
home + ``_served_profile_homes``) every 0.5s and broadcasts the SAME ``display.lease`` payload when
the epoch moves. Bodies are rebound onto server.py's globals (method_ctx.bind_module).
)ÚannotationsN)ÚPath)Úbind_moduleg      à?zdict[str, int]Ú_lease_epochszdict[str, int | None]Ú_lease_mtimeszdict[str, tuple]Ú_runtime_marksc               ó    € V ^8„  d   QhRRRR/# )é   Úprofile_keyÚstrÚreturnÚdict© )Úformats   "ÚF/home/ubuntu/.hermes/hermes-agent/tui_gateway/methods_display_watch.pyÚ__annotate__r       s   € ÷ Eñ E cð E°Tñ Eó    c                ó&   € ^ RI Hp RV RV! V4      /# )é    )Úpublic_viewr
   Úlease)Útools.bot_desktop.leaser   )r
   r   r   s   && r   Ú_lease_event_payloadr       s   € å3Ø˜;¨±¸UÓ1CÐDÐDr   c               ó   € V ^8„  d   QhRR/# )r	   r   z
list[Path]r   )r   s   "r   r   r   &   s   € ÷ 8ñ 8˜jñ 8r   c                 ó.   € \        \        4      .\        O# ©N)r   Ú_hermes_homeÚ_served_profile_homesr   r   r   Ú_watched_lease_homesr   &   s   € Ü”ÓÐ7Ô!6Ð7Ð7r   c               ó   € V ^8„  d   QhRR/# )r	   Úpathr   r   )r   s   "r   r   r   *   s   € ÷ ñ �ñ r   c                ó\   €  V P                  4       P                  #   \         d     R # i ; ir   )ÚstatÚst_mtime_nsÚOSError)r    s   &r   Ú_mtimer%   *   s+   € ðØ�y‰y‹{×&Ñ&Ð&øÜô Úðús   ‚ œ+ª+c               ó$   € V ^8„  d   QhRRRRRR/# )r	   r
   r   Úpayloadr   r   ÚNoner   )r   s   "r   r   r   1   s&   € ÷ ^ñ ^°ð ^¸tð ^Èñ ^r   c                óÀ  € ^ RI Hp  ^ RIHp \	        VP                  R4      \        4      '       d   VP                  R4      M/ pT! \        VP                  R4      4      VP                  R4      \        VP                  R4      ;'       g    R4      4      pT'       g   R# \        ;_uu_ 4        \        P                  4        UUu. uFd  w  rg\	        T\        4      '       g   K  TP                  R	4      f   K2  T! TP                  R
4      ;'       g    \        4       4      T 8X  g   Kb  TNKf  	  pppRRR4       X FE  p\        T,          R	,          p	 \        T	RR4      ;'       g    Rp
T
'       d   T
 RT 2MTT	n        KG  	  R#   \         d     R# i ; iu uppi   + '       g   i     Lu; i  \         d    \         P#                  RTRR7        Kœ  i ; i)aª  Stage the Bot Screen line as a per-turn note on that profile's live agents (#125830).

The system prompt is byte-stable and only rebuilt at compaction, so a screen started or
stopped mid-session would otherwise stay unknown to the model until then. The note rides
the one-shot user-message channel (``_gateway_turn_context_notes``, consumed by
``agent/turn_context.py``), landing behind the cached prefix. Sessions may hold a fresh
agent per turn, so the note is staged on every live session of the profile, not just one.
``payload`` is the just-broadcast display.status snapshot (``running``/``display`` and the
lease's public view), already read under the profile's home override.©Úhermes_home_key)Úbot_screen_noter   ÚrunningÚdisplayÚholderÚ NÚagentÚprofile_homeÚ_gateway_turn_context_notesz

z-could not stage Bot Screen note on session %sT©Úexc_info)Úhermes_constantsr+   Úagent.prompt_builderr,   Ú
isinstanceÚgetr   Úboolr   Ú	ExceptionÚ_sessions_lockÚ	_sessionsÚitemsÚget_process_hermes_homeÚgetattrr3   ÚloggerÚdebug)r
   r'   r+   r,   Ú
lease_viewÚlineÚsidÚsessÚsidsr1   Úpriors   &&         r   Ú_notify_agents_of_screen_changerI   1   s…  € õ 1ðÝ8Ü-7¸¿¹ÀGÓ8LÌd×-SÒ-S�W—[‘[ Ô)ÐY[ˆ
Ùœt G§K¡K°	Ó$:Ó;¸W¿[¹[ÈÓ=SÜ" :§>¡>°(Ó#;×#AÐ#A¸rÓBóDˆ÷ Ùß	ŽÜ%.§_¡_Ô%6ô kÑ%6™	˜¼*ÀTÌ4×:P”ÐUY×U]ÑU]Ð^eÓUf”Ù# D§H¡H¨^Ó$<×$YÐ$YÔ@WÓ@YÓZÐ^iÑi÷ �Ñ%6ˆñ k÷ 
ó ˆÜ˜#•˜wÕ'ˆð	^Ü˜EÐ#@À"ÓE×KÐKÈˆEßHM°5°'¸¸d¸VÑ0DÐSWˆEÖ-ó	 øô ô Úðüó
k÷ 
�ûô ô 	^Ü�L‰LÐHÈ#ÐX\ˆL×]ð	^úsl   ˆBF ÂF Â1F#Ã	F
Ã(F
Ã=F
ÄF
Ä-F
Ä3F#ÅF6Å,
F6Å7F6ÆFÆFÆF#Æ#F3	Æ6#GÇGc               ó   € V ^8„  d   QhRR/# ©r	   r   r(   r   )r   s   "r   r   r   Q   s   € ÷ 6ñ 6˜Tñ 6r   c                 óæ  € ^ RI Hp HpHp ^ RIHp \        4        FÅ  pV ! V4      pVR,          pV! V4      p \        VR,          4      \        VR,          4      VP                  4       RJ3pV\        9  p	\        P                  V4      V8X  d    V! V4       K€  V\        V&   V	'       d    V! V4       Kœ  \        4       p
V! V4       \        RV
4       \        WZ4       KÇ  	  R#   T! T4       i ; i)u  Broadcast ``display.status`` when a home's screen started/stopped outside this process â€” a
file move (start/stop by the CLI or gateway) or the launcher dying without touching its files
(Xvnc crash: env and launcher.pid stay put, only the pid stops being live).)r+   Úreset_hermes_home_overrideÚset_hermes_home_override©Úruntimeúbot-desktopÚenvzlauncher.pidNzdisplay.status)r6   r+   rM   rN   Útools.bot_desktoprP   r   r%   Ú_launcher_pidr   r9   Ú_display_snapshotÚ_broadcast_global_eventrI   )r+   rM   rN   Ú_bd_runtimeÚhomeÚkeyÚsdÚtokenÚmarkÚfirstr'   s              r   Ú_poll_runtime_filesr^   Q   sã   € ÷ gÑfÝ8Ü$Ö&ˆÙ˜dÓ#ˆØ�MÕ!ˆÙ(¨Ó.ˆð
	.Ü˜2 �:Ó&¬¨r°NÕ/BÓ(CÀ[×E^ÑE^ÓE`ÐhlÐElÐmˆDØœ~Ñ-ˆEÜ×!Ñ! #Ó&¨$Ô.Øñ ' uÖ-ð #'ŒN˜3ÑßØñ ' uÖ-ô (Ó)ˆGá& uÔ-ÜÐ 0°'Ô:Ü'¨Ö5ó! 'øñ ' uÕ-ús   ¸AC&ÂC&Â7
C&Ã&
C0g      >@g        c               ó   € V ^8„  d   QhRR/# rK   r   )r   s   "r   r   r   n   s   € ÷ .ñ .˜Dñ .r   c                 ó   € \         P                  ! 4       \        ,
          \        8  d   R# \         P                  ! 4       s^ RIHp Hp ^ RIHp \        4        F$  pV! V4      p VP                  4        V ! V4       K&  	  R#   T ! T4       i ; i)zÉEvery _IDLE_CHECK_S: stop screens idle past ``bot_desktop.idle_stop_minutes`` (runtime.stop_if_idle
holds the rules). The stop moves the runtime files, so _poll_runtime_files broadcasts display.status.N)rM   rN   rO   )ÚtimeÚ	monotonicÚ_last_idle_checkÚ_IDLE_CHECK_Sr6   rM   rN   rS   rP   r   Ústop_if_idle)rM   rN   rW   rX   r[   s        r   Ú_poll_idle_screensrf   n   sk   € ô ‡~‚~ÓÔ*Õ*¬]Ô:ÙÜ—~’~Ó'ÐßUÝ8Ü$Ö&ˆÙ(¨Ó.ˆð	.Ø×$Ñ$Ô&á& uÖ-ó 'øñ
 ' uÕ-ús   Á%BÂ
Bc               ó   € V ^8„  d   QhRR/# rK   r   )r   s   "r   r   r      s   € ÷ Sñ S˜4ñ Sr   c                 ó  € ^ RI Hp  ^ RIHp \	        4        FÚ  pV ! V4      p VR,          R,          P                  4       P                  pV\        P                  V^ 4      8X  d   KQ  V\        V&   VP                  \        V4      4      pV\        9  d   VP                  \        V&   K”  VP                  \        V,          8X  d   K²  VP                  \        V&   \        R\        W54      4       KÜ  	  R#   \         d    Rp L»i ; i)z[One pass: read a home's lease only when its file mtime moved; broadcast when the epoch did.r*   ©r   rQ   z
lease.jsonNzdisplay.lease)r6   r+   rS   r   r   r"   r#   r$   r   r9   r   r   ÚepochrV   r   )r+   Ú	_bd_leaserX   rY   Úmtimer   s         r   Ú_poll_lease_filesrm      sÙ   € å0Ý4Ü$Ö&ˆÙ˜dÓ#ˆð	Ø˜MÕ)¨LÕ8×>Ñ>Ó@×LÑLˆEð ”M×%Ñ% c¨1Ó-Ô-ÙØ"Œ�cÑØ—‘œc $›iÓ(ˆØ”mÔ#Ø!&§¡ŒM˜#ÑÙØ�;‰;œ-¨Õ,Ô,ÙØ"Ÿ[™[Œ�cÑÜ Ô1EÀcÓ1QÖRó! 'øô ô 	ØŠEð	ús   £(C7Ã7DÄDc               ó   € V ^8„  d   QhRR/# rK   r   )r   s   "r   r   r   –   s   € ÷ Uñ U˜tñ Ur   c                 óú   € \         P                  4       '       d   R# \         P                  4        ^ RIHp  R R lpV P                  V4       R R lp\        P                  ! VRRR	7      P                  4        R# )
z·Once per process, from the first display.* call: start the lease-file poll thread and mark
in-process transitions as seen so they broadcast exactly once (via the in-process listener).Nri   c               ó    € V ^8„  d   QhRRRR/# )r	   r
   r   r   r(   r   )r   s   "r   r   Ú+_ensure_lease_watcher.<locals>.__annotate__ž   s   € ÷ 5ñ 5 3ð 5°$ñ 5r   c                ód   € \         P                  4       '       d   VP                  \        V &   R # R # r   )Ú_lease_listener_installedÚis_setrj   r   )r
   r   s   &&r   Ú_seen_locallyÚ,_ensure_lease_watcher.<locals>._seen_locallyž   s&   € ô %×+Ñ+×-Ò-Ø).¯©ŒM˜+Ó&ñ .r   c               ó   € V ^8„  d   QhRR/# rK   r   )r   s   "r   r   rq   ¥   s   € ÷ &ñ &�4ñ &r   c                 óÊ   €   \        4        \        4        \        4        \        P                  ! \        4       K<    \         d    \        P                  RR R7        L@i ; i)Tzlease watcher poll failedr4   )	rm   rf   r^   r;   rA   rB   ra   ÚsleepÚ_LEASE_POLL_Sr   r   r   Ú_loopÚ$_ensure_lease_watcher.<locals>._loop¥   sO   € ØðIÜ!Ô#Ü"Ô$Ü#Ô%ô �JŠJ”}Ö%øô ô IÜ—‘Ð8À4�ÖHðIús   ƒ= ½"A"Á!A"zhermes-lease-watcherT)ÚtargetÚnameÚdaemon)	Ú_lease_watcher_startedrt   ÚsetrS   r   Ú	on_changeÚ	threadingÚThreadÚstart)rk   ru   r{   s      r   Ú_ensure_lease_watcherr†   –   s]   € ô ×$Ñ$×&Ò&ÙÜ×ÑÔ Ý4õ5ð
 ×Ñ˜Ô&õ&ô ×Ò˜EÐ(>ÀtÔL×RÑRÖTr   c               ó   € V ^8„  d   QhRR/# rK   r   )r   s   "r   r   r   ±   s   € ÷ 0ñ 0˜ñ 0r   c                ó2   € \        \        4       V RR7       R# )Ú_)ÚskipN)r‰   )r   Úglobals)Úservers   &r   Úregisterr�   ±   s   € Ü”“	˜6¨×/r   )Ú__conditional_annotations__Ú__doc__Ú
__future__r   rƒ   ra   Úpathlibr   Ú
method_ctxr   rz   ÚEventr€   r   Ú__annotations__r   r   r   r   r%   rI   r^   rd   rc   rf   rm   r†   r�   )rŽ   s   @r   Ú<module>r•      s‘   øðô	õ #ã Û Ý å #à€Ø"ŸšÓ*Ð ð !#€ˆ~Ó "Ø')€Ð$Ó )ð $&€Ð Ó %õEõ8õõ^õ@6ð2 €ØÐ õ.õ"Sõ.U÷60r   