+
    lHàj$  ã                  ó�  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIHtH	t	 ]P                  ! 4       P                  tRt^@tR#tR$t]P"                  ! 4       t]! 4       tR]R&   / tR]R&   / tR]R	&   ^ s/ tR]R
&   ]! 4       tR]R&   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$R! R" lt%R# )%ae  Per-session event sequencing + bounded replay for WS reconnects.

Every event frame through :func:`server.write_json` (hence ``_emit``) gets a per-session monotonic
``seq`` and lands in a small ring per session; a reconnecting client calls ``session.events.since``
with its last seen seq and gets everything newer. Invariants: stdio TUI unaffected (``seq`` only on
event frames; Ink ignores unknown keys); one lock guards counters + buffers, and write_json already
serializes per-transport writes so stamping cannot reorder frames; memory bound =
_REPLAY_BUFFER_MAX events AND _REPLAY_BUFFER_BYTES_MAX frozen UTF-8 payload bytes per session,
_REPLAY_PROCESS_BYTES_MAX frozen UTF-8 payload bytes across at most _REPLAY_SESSIONS_MAX sessions,
oldest evicted FIFO (their seq/truncation counters are retained so a revisited session stays
monotonic within the epoch, #100122). Evicted or never-retained (oversized) frames leave a truncation watermark so a
reconnecting client refetches instead of trusting a replay with holes. A torn-down session's ring is freed at
teardown (``forget_session``) and never rebuilt by late frames.
)ÚannotationsN)ÚOrderedDictÚdequei   zOrderedDict[str, deque]Ú_replay_bufferszdict[str, int]Ú_replay_buffer_bytesÚ_replay_evicted_throughÚ_replay_next_seqzset[str]Ú_replay_forgottenc               ó   € V ^8„  d   QhRR/# )é   ÚreturnÚstr© )Úformats   "Ú=/home/ubuntu/.hermes/hermes-agent/tui_gateway/event_replay.pyÚ__annotate__r   5   s   € ÷ ñ �cñ ó    c                 ó   € \         # )z=Opaque token identifying this server process's seq numbering.)Ú_REPLAY_EPOCHr   r   r   Úreplay_epochr   5   s   € äÐr   c               ó    € V ^8„  d   QhRRRR/# )r   ÚparamsÚdictr   Úbytesr   )r   s   "r   r   r   :   s   € ÷ ñ ˜4ð  Eñ r   c                óV   € \         P                  ! V RRR7      P                  RRR7      # )zLSerialize one replay snapshot before the caller can mutate its object graph.F)Úensure_asciiÚ
separatorsúutf-8Úsurrogatepass©Úerrors)Ú,Ú:)ÚjsonÚdumpsÚencode)r   s   &r   Ú_freeze_paramsr&   :   s-   € ä�:Š:�f¨5¸ZÔH×OÑOØ˜ð Pó ð r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úpayloadr   ÚseqÚintr   r   r   )r   s   "r   r   r   A   s!   € ÷ ñ ˜%ð  cð ¨dñ r   c                ó\   € \         P                  ! V P                  RRR7      4      pWR&   V# )zKRebuild a client event object and restore the server-owned sequence number.r   r   r   r)   )r#   ÚloadsÚdecode)r(   r)   Úevents   && r   Ú_thaw_paramsr/   A   s)   € ä�JŠJ�w—~‘~ g°o�~ÓFÓG€EØˆ%�LØ€Lr   c               ó    € V ^8„  d   QhRRRR/# )r   Úobjr   r   ÚNoner   )r   s   "r   r   r   H   s   € ÷ 2ñ 2�dð 2˜tñ 2r   c           	     óØ  € V P                  R4      R8w  d   R# V P                  R4      p\        V\        4      '       g   R# VP                  R4      ;'       g    RpV'       g   R# \        V4      p\	        V4      p\
        ;_uu_ 4        \        P                  V^ 4      ^,           pV\        V&   WQR&   V\        9   d   V\        V&    RRR4       R# \        P                  V4      pVfX   \        4       ;p\        V&   ^ \        V&   \	        \        4      \        8”  d$   \        \        \        \        4      4      4       K;  V\         8”  g   V\"        8”  d   V\        V&    RRR4       R# VP%                  WSV34       \        V;;,          V,          uu&   \&        V,          s\	        V4      \(        8”  g   \        V,          \         8”  dc   VP+                  4       w  rxp	\        V;;,          V	,          uu&   \&        V	,          s\-        \        P                  V^ 4      V4      \        V&   KŒ  \&        \"        8”  d‹   \        P/                  4        Fp  w  r«V'       g   K  VP+                  4       w  rxp	\        V
;;,          V	,          uu&   \&        V	,          s\-        \        P                  V
^ 4      V4      \        V
&    K•  	  K™   RRR4       R#   + '       g   i     R# ; i)zSStamp one outgoing event frame (mutates obj in place) and record a frozen snapshot.Úmethodr.   Nr   Ú
session_idÚ r)   )ÚgetÚ
isinstancer   r&   ÚlenÚ_replay_lockr   r	   r   r   r   r   Ú_REPLAY_SESSIONS_MAXÚ_drop_ring_lockedÚnextÚiterÚ_REPLAY_BUFFER_BYTES_MAXÚ_REPLAY_PROCESS_BYTES_MAXÚappendÚ_replay_total_bytesÚ_REPLAY_BUFFER_MAXÚpopleftÚmaxÚitems)r1   r   Úsidr(   Úsizer)   ÚbufÚevicted_seqÚ_eventÚevicted_sizeÚ	evict_sidÚ	evict_bufs   &           r   Ú_stamp_eventrO   H   sK  € à
‡w�wˆxÓ˜GÔ#ÙØ�W‰W�XÓ€FÜ�fœd×#Ò#ÙØ
�*‰*�\Ó
"×
(Ð
( b€Cßáô ˜VÓ$€GÜˆw‹<€Dß	Žä×"Ñ" 3¨Ó*¨QÕ.ˆØ #Ô˜ÑØˆu‰ØÔ#Ô#Ø+.Ô# CÑ(Ø÷ 
‰ô ×!Ñ! #Ó&ˆØŠ;Ü).«Ð0ˆC”/ #Ñ&Ø()Ô  Ñ%Ü”oÓ&Ô)=Ô=Ü!¤$¤t¬OÓ'<Ó"=Ö>ØÔ*Ô*¨dÔ5NÔ.NØ+.Ô# CÑ(Ø÷! 
‰ð" 	�
‰
�C $Ð'Ô(Ü˜S×! TÕ)Ó!Ü˜tÕ#ÐÜ�#‹hÔ+Ô+Ô/CÀCÕ/HÔKcÔ/cØ03·±³Ñ-ˆK Ü  ×%¨Õ5Ó%Ü <Õ/ÐÜ+.Ô/F×/JÑ/JÈ3ÐPQÓ/RÐT_Ó+`Ô# CÓ(Ü!Ô$=Ô=Ü(7×(=Ñ(=Ö(?Ñ$�	ß‘9Ø8A×8IÑ8IÓ8KÑ5�K¨Ü(¨×3°|ÕCÓ3Ü'¨<Õ7Ð'Ü9<Ü/×3Ñ3°I¸qÓAÀ;ó:Ô+¨IÑ6ò ó )@ð >÷3 
��Šús"   ÂA KÃBKÅ/C2KÉ&A'KËK)	c               ó    € V ^8„  d   QhRRRR/# ©r   rG   r   r   r2   r   )r   s   "r   r   r   }   s   € ÷ jñ j˜3ð j 4ñ jr   c                óò   € \         P                  V R4      f   R# \        \        P                  V ^ 4      ,          s\	        \
        P                  V ^ 4      \        P                  V ^ 4      4      \
        V &   R# )aN  Free one session's retained frames (FIFO cap eviction and teardown). Caller holds ``_replay_lock``.

The ring goes, the session's seq numbering stays (#100122): a revisited session continues from its high
seq instead of restarting at 1 under clients' still-held watermarks (a reset seq is invisible to
dispatchIfNewer, so replay AND live frames silently vanish). The truncation watermark is raised to the
latest stamped seq: a client holding any older watermark has a gap and must refetch history instead of
trusting the new tail. Both counters are one int per session id seen this process.N)r   ÚpoprB   r   rE   r   r7   r   ©rG   s   &r   r<   r<   }   sc   € ô ×Ñ˜3 Ó%Ò-ÙÜÔ/×3Ñ3°C¸Ó;Õ;ÐÜ#&Ô'>×'BÑ'BÀ3ÈÓ'JÔL\×L`ÑL`ÐadÐfgÓLhÓ#iÔ˜CÓ r   c               ó    € V ^8„  d   QhRRRR/# rQ   r   )r   s   "r   r   r   Œ   s   € ÷ ñ ˜ð  ñ r   c                ó°   € V '       g   R# \         ;_uu_ 4        \        P                  V 4       \        V 4       RRR4       R#   + '       g   i     R# ; i)z£Release a torn-down session's replay ring. A runtime sid is never reattached after teardown
(resume mints a new one), so its frames can only be replayed to nobody.N)r:   r	   Úaddr<   rT   s   &r   Úforget_sessionrX   Œ   s1   € ÷ Ùß	ŽÜ×Ñ˜cÔ"Ü˜#Ô÷ 
��Šús   ™!AÁA	c               ó$   € V ^8„  d   QhRRRRRR/# )r   rG   r   Ú	last_seenr*   r   z
list[dict]r   )r   s   "r   r   r   –   s&   € ÷ 
Fñ 
F�cð 
F cð 
F¨jñ 
Fr   c           
     óD  € \         ;_uu_ 4        \        P                  T ;'       g    R4      pV'       d#   V UUUu. uF  w  r4qSV8”  g   K  W43NK  	  upppM. pRRR4       X UUu. uF  w  r4\        WC4      NK  	  upp# u upppi   + '       g   i     L6; iu uppi )a:  Recorded EVENT OBJECTS (each frame's ``params`` dict) with seq > last_seen for *sid*.

Returning the full JSON-RPC envelope would make every replayed event fail the
client's ``event.type`` gate and be silently dropped. Decode after releasing the ring lock so a
large replay cannot block concurrent event stamping.
r6   N)r:   r   r7   r/   )rG   rZ   rI   r)   r(   Ú_sizeÚ	snapshotss   &&     r   Úevents_sincer^   –   s|   € ÷ 
ŽÜ×!Ñ! #§) )¨Ó,ˆßZ]¹sÕV¹sÑ(;¨°eÈIÁo”^�c“^¹sÔVÐceˆ	÷ 
ñ <EÔE¹9©<¨3ŒL˜Ö&¹9ÒEÐEùô W÷ 
�üó Fs-   �'B	·B	½BÁBÁB	Á(BÂB	Â	B	c               ó$   € V ^8„  d   QhRRRRRR/# )r   rG   r   rZ   r*   r   Úboolr   )r   s   "r   r   r   £   s&   € ÷ Eñ E�cð E cð E¨dñ Er   c                ó¢   € \         ;_uu_ 4        T\        P                  T ;'       g    R^ 4      8  uuRRR4       #   + '       g   i     R# ; i)u˜   True when events between *last_seen* and the ring's oldest retained seq were
evicted â€” the client must refetch history instead of trusting the replay.r6   N)r:   r   r7   )rG   rZ   s   &&r   Úis_truncatedrb   £   s1   € ÷ 
ŽØÔ2×6Ñ6°s·y°y¸bÀ!ÓDÑD÷ 
��‹ús	   �#=½A	c               ó    € V ^8„  d   QhRRRR/# )r   rG   r   r   r*   r   )r   s   "r   r   r   ª   s   € ÷ 2ñ 2�Cð 2˜Cñ 2r   c                óœ   € \         ;_uu_ 4        \        P                  T ;'       g    R^ 4      uuRRR4       #   + '       g   i     R# ; i)z7Current highest stamped seq for *sid* (0 when unknown).r6   N)r:   r   r7   rT   s   &r   Ú
latest_seqre   ª   s)   € ç	ŽÜ×#Ñ# C§I I¨2¨qÓ1÷ 
��‹ús	   � :ºA	c               ó   € V ^8„  d   QhRR/# )r   r   r2   r   )r   s   "r   r   r   °   s   € ÷ 	 ñ 	 ˜Dñ 	 r   c                 ó(  € \         ;_uu_ 4        \        P                  4        \        P                  4        \        P                  4        \
        P                  4        \        P                  4        ^ sRRR4       R#   + '       g   i     R# ; i)z
Test hook.N)r:   r   Úclearr   r   r   r	   rB   r   r   r   Úreset_replay_stateri   °   sU   € ç	Žä×ÑÔÜ×"Ñ"Ô$Ü×%Ñ%Ô'Ü×ÑÔ Ü×ÑÔ!ØÐ÷ 
��Šús   �A'B Â B	c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r   r   ¼   s   € ÷ 

ñ 

�dñ 

r   c                 óö   € \         ;_uu_ 4        R\        \        4      R\        R \        P	                  4        4       4      R\
        R\        R\        R\        /uuRRR4       #   + '       g   i     R# ; i)	z6Telemetry: buffer occupancy for the ops/debug surface.ÚsessionsÚeventsc              3  ó8   "  € T F  p\        V4      x € K  	  R # 5i)N)r9   )Ú.0Úbuffers   & r   Ú	<genexpr>Úreplay_stats.<locals>.<genexpr>Á   s   é € ÐMÑ4L¨&œ#˜fŸ+˜+Ó4Lùs   ‚r   Úmax_per_sessionÚmax_bytes_per_sessionÚmax_bytes_processN)	r:   r9   r   ÚsumÚvaluesrB   rC   r?   r@   r   r   r   Úreplay_statsrx   ¼   sS   € ç	ŽàœœOÓ,Ø”cÑM´O×4JÑ4JÔ4LÓMÓMØÔ(ØÔ1Ø#Ô%=ØÔ!:ð
÷ 
��‹ús   �AA'Á'A8	i  @ i   )&Ú__conditional_annotations__Ú__doc__Ú
__future__r   r#   Ú	threadingÚuuidÚcollectionsr   r   Úuuid4Úhexr   rC   r;   r?   r@   ÚLockr:   r   Ú__annotations__r   r   rB   r   Úsetr	   r   r&   r/   rO   r<   rX   r^   rb   re   ri   rx   )ry   s   @r   Ú<module>r„      s×   øðôõ #ã Û Û ß *ð
 —
’
“× Ñ €ð Ð ØÐ ð +Ð Ø,Ð à�~Š~Ó€ñ ,7«=€Ð(Ó 8Ø')Ð �nÓ )Ø*,Ð ˜Ó ,ØÐ Ø#%Ð �.Ó %ñ "›eÐ �8Ó #õõ
õõ2õjjõõ
FõEõ2õ	 ÷

r   