+
    iHàj‘"  ã                  ó¼   € R t ^ RIHt ^ RIt^ RIHt Rt^<t^tRt	Rt
^ t^tRtRt^],          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4      tR# )a2  Cheap content-sanity checks for model output, completed or still streaming.

A model in a degenerate repetition loop can spend its ENTIRE output budget echoing one fragment;
the ``finish_reason=length`` continuation would then stitch it into the final response with a
"continue" nudge (one incident: a 60k-char turn delivered as 31 Discord messages). This detects
repetition-dominated fragments BEFORE the nudge so the turn aborts with a clear error. Deliberately
conservative: only LONG verbatim repeats (60+ chars) covering a majority of the fragment trip it.
)ÚannotationsN)ÚCounteri�  g      à?zB[the reply degenerated into a repetition loop and was interrupted]i€>  c               ó    € V ^8„  d   QhRRRR/# ©é   ÚtextÚstrÚreturnÚbool© )Úformats   "Ú;/home/ubuntu/.hermes/hermes-agent/agent/repetition_guard.pyÚ__annotate__r   5   s   € ÷ Pñ P #ð P¨$ñ Pó    c                óÄ   € \        V \        4      '       g   R# \        V 4      pV\        8  d   R# \	        W4      '       d   R# \        W4      ;'       g    \        W4      # )u  True when a contiguous run of at least five exact repetitions covers at least half
of ``text`` â€” the signature of a model repetition loop (issue #86581). Coverage is measured
with the true period, so long multi-line loop units count fully. Fail-open for short input.
FT)Ú
isinstancer   ÚlenÚMIN_FRAGMENT_LENGTHÚ_line_repetition_dominatedÚ_window_count_dominatedÚ_periodic_run_dominated)r   Úns   & r   Úis_repetition_dominatedr   5   sT   € ô
 �dœC× Ò ÙÜˆD‹	€AØÔÔÙô " $×*Ò*Ùô # 4Ó+×OÐOÔ/FÀtÓ/OÐOr   c               ó$   € V ^8„  d   QhRRRRRR/# ©r   r   r   r   Úintr	   r
   r   )r   s   "r   r   r   I   s!   € ÷ ñ  #ð ¨#ð °$ñ r   c                ó   € \         p\        \        \        P                  ! V\
        ,          V,          4      4      p/ p\        W,
          ^,           4       F3  pWWR,            pVP                  V^ 4      ^,           pWs8¼  d    R# WtV&   K5  	  R# )zKTrue when one 60-char window recurs often enough to cover half of ``text``.TF)Ú_REPEAT_WINDOWÚmaxÚ_MIN_REPEAT_COUNTÚmathÚceilÚ_DOMINANCE_RATIOÚrangeÚget)r   r   ÚwindowÚneededÚcountsÚiÚkeyÚcs   &&      r   r   r   I   sw   € ä€FÜÔ"¤D§I¢I¨aÔ2BÕ.BÀVÕ.KÓ$LÓM€FØ€FÜ�1•: •>Ö"ˆØ�q•zÐ"ˆØ�J‰J�s˜AÓ Õ"ˆØŒ;ÚØˆs‹ñ #ñ r   c               ó$   € V ^8„  d   QhRRRRRR/# r   r   )r   s   "r   r   r   W   s!   € ÷ 'ñ ' #ð '¨#ð '°$ñ 'r   c           	     ó  aa€ \         pW,
          pV^8  d   R# \        ^V\        ,           ^,
          \        ^,
          ,          4      p\        \	        ^ V^,           V4      4      pVR,          V8w  d   VP                  V4       . pV Fö  oV SSV,            pS^,           p\	        \        4       FË  p	V P                  Wx4      p
V
^ 8  d    KE  V
S,
          oV
^,           p\        ;QJ d     VV3R lV 4       F  '       g   K   RM	  RM! VV3R lV 4       4      '       d   Kt  \        WSSV4      w  r¼WË,
          \        S,          8¼  d   WË,
          V\        ,          8¼  d     R# VP                  W¼S34       KÍ  	  Kø  	  R# )ad  Detect a dominant exact periodic run from evenly spaced anchors.

Matching a 60-character anchor at a later position supplies a candidate
period. Expanding the equality ``text[i] == text[i + period]`` in both
directions recovers the full run, so coverage is measured using the true
repeating unit rather than crediting every occurrence with only 60 chars.
Fc              3  ó|   <"  € T F1  w  rq1Su;8*  ;'       d    V8  Mu ;'       d    SV,          ^ 8H  x € K3  	  R# 5i©é    Nr   )Ú.0ÚloÚhiÚpÚperiodÚstarts   &   €€r   Ú	<genexpr>Ú*_periodic_run_dominated.<locals>.<genexpr>x   s3   øé € ÐRÉ¹I¸BÀA˜×#Ô# Ô#×7Ð7¨°­
°a©Ô7Ëùs   ƒ#<§<Téÿÿÿÿ)r   r   Ú_MAX_ANCHOR_SAMPLESÚlistr#   ÚappendÚ_MAX_ANCHOR_MATCHESÚfindÚanyÚ_expand_runr   r"   )r   r   r%   Ú	max_startÚsample_stepÚsample_startsÚrejectedÚanchorÚsearch_fromÚ_ÚmatchÚleftÚrightr4   r5   s   &&           @@r   r   r   W   sG  ù€ ô €FØ•
€IØ�1„}ÙäØ	Ø	Ô(Õ	(¨1Õ	,Ô2EÈÕ2IÕJó€Kô œ˜q )¨a¥-°Ó=Ó>€MØ�RÕ˜IÔ%Ø×Ñ˜YÔ'ð ,.€HÛˆØ�e˜e f�nÐ-ˆØ˜a•iˆÜÔ*Ö+ˆAØ—I‘I˜fÓ2ˆEØ�qŒyÚØ˜U•]ˆFØ !�)ˆKß‹sÕRÉÓR�s�sŠsÕRÉÓR×RÒRÙÜ% d¨u°f¸fÓE‰KˆDØ�|Ô0°6Õ9Ô9¸e½lÈaÔRbÕNbÔ>bÛØ�O‰O˜T¨&Ð1Ö2ó ,ñ ñ r   c               ó0   € V ^8„  d   QhRRRRRRRRRRRR	/# )
r   r   r   r   r   r5   r4   Úmatchedr	   ztuple[int, int]r   )r   s   "r   r   r   �   s6   € ÷ 	 ñ 	 �cð 	 ˜cð 	 ¨#ð 	 °sð 	 ÀSð 	 È_ñ 	 r   c                ó  € TpV^ 8”  d4   W^,
          ,          W^,
          V,           ,          8X  d   V^,          pK:  W$,           pWc,           V8  d&   W,          WV,           ,          8X  d   V^,          pK2  WVV,           3# )zXExpand one known equal window to the ``[left, right)`` bounds of its exact periodic run.r   )r   r   r5   r4   rK   rH   rI   s   &&&&&  r   r?   r?   �   sg   € à€DØ
�Œ(�t 1�H•~¨°Q­h¸Õ.?Õ)@Ô@Ø��	Šà�O€EØ
�.˜1Ô
 ¥°¸Vµ^Õ0DÔ!DØ��
ŠØ˜•ÐÐr   c               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   r   �   s   € ÷ Hñ H ð H¨ñ Hr   c                óJ  € \        V 4      '       g   R# V P                  4        Uu. uF  qP                  4       NK  	  ppV Uu. uF  q'       g   K  VNK  	  pp\        V4      \        8  d   R# \        \        V4      4      \        V4      \        ,          8*  # u upi u upi )a`  Stricter than :func:`is_repetition_dominated`: also require the runaway shape.

An interrupt checkpoint DROPS the partial when this fires, so a legitimately repetitive but
correct reply (distinct batch rows) must not qualify: repeated windows have to dominate AND,
when the text has line structure, at most half of its non-empty lines may be distinct.
FT)r   Ú
splitlinesÚstripr   r   ÚsetÚ_RUNAWAY_DISTINCT_LINE_RATIO)r   ÚlineÚliness   &  r   Úis_runaway_repetitionrU   �   s€   € ô # 4×(Ò(ÙØ&*§o¡oÔ&7Ó8Ñ&7˜d�Z‰ZŽ\Ñ&7€EÐ8Ù#Ó,™e�d£t�TˆT™e€EÐ,Ü
ˆ5ƒzÔ%Ô%ÙÜŒs�5‹z‹?œc %›jÔ+GÕGÑGÐGùò	 9ùÚ,s   ¦BÁ	B ÁB c               ó$   € V ^8„  d   QhRRRRRR/# r   r   )r   s   "r   r   r   �   s&   € ÷ oñ o Sð o¨Sð o°Tñ or   c                óþ   a€ \        R R V P                  4        4        4       4      p\        ;QJ d-    V3R lVP                  4        4       F  '       g   K   R# 	  R# ! V3R lVP                  4        4       4      # )zHTrue when a single normalized line covers half the fragment via repeats.c              3  ó8   "  € T F  q'       g   K  Vx € K  	  R # 5i©Nr   )r0   Únorms   & r   r6   Ú-_line_repetition_dominated.<locals>.<genexpr>Ÿ   s   é € Ð[Ñ&R˜dÓVZ—T’TÓ&Rùs   ‚	�
c              3  ó@   "  € T F  qP                  4       x € K  	  R # 5irY   )rP   )r0   rS   s   & r   r6   r[   Ÿ   s   é € Ð&RÑ@Q¸§z¡z§| |Ó@Qùs   ‚c              3  óŠ   <"  € T F8  w  rV\         8¬  ;'       d!    V\        V4      ,          S\        ,          8¬  x € K:  	  R # 5irY   )r   r   r"   )r0   rS   r*   r   s   &  €r   r6   r[       s;   øé € ÐnÑ_mÑT[ÐTXˆqÔ%Ñ%×OÐO¨!¬c°$«i­-¸1Ô?OÕ;OÑ*OÔOÓ_mùs
   ƒAš)ATF)r   rO   r>   Úitems)r   r   r'   s   &f r   r   r   �   s]   ø€ äÑ[Ñ&RÀÇÁÔ@QÔ&RÓ[Ó[€Fß‹3ÔnÐ_e×_kÑ_kÔ_mÓn�3Œ3ÐnŠ3Ðnˆ3ÔnÐ_e×_kÑ_kÔ_mÓnÓnÐnr   c                  ó6   € ] tR t^£tRtRtR R ltR R ltRtR# )ÚRunawayStreamWatcha,  The stop-path criterion applied WHILE one channel (visible text or reasoning) streams.

A stream that keeps producing never reaches a completion check, and endpoints without an
output cap (#127234) keep a looping model going for as long as the turn lives. The first
check runs at ``STOP_PATH_MIN_CHARS`` (asked-for repeats stay below it, as on the stop path)
and the gap doubles until it reaches one tail window, then stays there. A fixed stride keeps a
loop that starts late in a long reply from streaming as long as the reply already was before
a check sees it; each check reads only the tail, so the total work stays linear in the output.
Each check also trims the held text to the tail, and checks are at most one tail window apart,
so the watch never holds more than two tail windows plus the latest delta.
c               ó   € V ^8„  d   QhRR/# )r   r	   ÚNoner   )r   s   "r   r   ÚRunawayStreamWatch.__annotate__²   s   € ÷ /ñ /˜$ñ /r   c                	ó8   € . V n         ^ V n        \        V n        R# r.   )Ú_partsÚ_charsÚSTOP_PATH_MIN_CHARSÚ_next_check)Úselfs   &r   Ú__init__ÚRunawayStreamWatch.__init__²   s   € Ø!#ˆŒØˆŒÜ.ˆÖr   c               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   rc   ·   s   € ÷ +ñ +˜ð + ñ +r   c                ó–  € V'       g   R# V P                   P                  V4       V ;P                  \        V4      ,          un        V P                  V P                  8  d   R# V P                  \        V P                  \        4      ,           V n        RP                  V P                   4      \        ) R pV.V n         \        V4      # )z?Add one delta; True once the channel has become a runaway loop.FÚ N)	re   r;   rf   r   rh   ÚminÚ_STREAM_TAIL_CHARSÚjoinrU   )ri   r   Útails   && r   ÚfeedÚRunawayStreamWatch.feed·   s�   € çÙØ�‰×Ñ˜4Ô Ø�Š”s˜4“yÕ �Ø�;‰;˜×)Ñ)Ô)ÙØŸ;™;¬¨T¯[©[Ô:LÓ)MÕMˆÔØ�w‰w�t—{‘{Ó#Ô%7Ð$7Ð$8Ð9ˆØ�fˆŒÜ$ TÓ*Ð*r   )rf   rh   re   N)	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú	__slots__rj   rs   Ú__static_attributes__r   r   r   r`   r`   £   s   † ñ
ð 4€Iõ/÷
+ñ +r   r`   )ry   Ú
__future__r   r    Úcollectionsr   r   r   r   r"   ÚREPETITION_LOOP_INTERRUPTEDr9   r<   rR   rg   rp   r   r   r   r?   rU   r   r`   r   r   r   Ú<module>r      s�   ðñõ #ã Ý ð Ð à€àÐ àÐ ð cÐ ð
 Ð ØÐ ð  #Ð ð
 Ð ð Ð,Õ,Ð õPõ(õ'õT	 õHõ o÷+ó +r   