+
    iHàjsx  ã                  óÐ   € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIHtHtH	t	H
t
 ^ RIHt ^ RIHt ^ RIHt ^ RIHtHt ]P(                  ! R4      tR	 tR
 R ltR R lt ! R R4      tR# )a  Micro-compaction mixin for ContextCompressor.

Rolling per-exchange summarization that folds old user/assistant exchanges into a single
summary marker between turns. OFF by default: every pass rewrites the prompt prefix and
breaks the provider prompt cache.
)ÚannotationsN)ÚAnyÚDictÚListÚOptional)Úpublish_micro)Ú	_safe_int)Úrecord_absorbed_message)Úestimate_messages_tokens_roughÚestimate_tokens_roughzagent.context_compressorc                 ó   € ^ RI Hp  V # )z£The origin module, resolved lazily: avoids the import cycle and keeps tests that patch
``agent.context_compressor.X`` effective (attributes are read at call time).©Úcontext_compressor)Úagentr   r   s    Ú;/home/ubuntu/.hermes/hermes-agent/agent/micro_compaction.pyÚ_ccr      s   € õ )ØÐó    c               ó    € V ^8„  d   QhRRRR/# ©é   Úentryr   ÚreturnÚbool© )Úformats   "r   Ú__annotate__r      s   € ÷ ^ñ ^˜cð ^ dñ ^r   c                óŠ   € \        V \        4      ;'       d-    \        V P                  \	        4       P
                  4      4      # ©N)Ú
isinstanceÚdictr   Úgetr   ÚCOMPRESSED_SUMMARY_METADATA_KEY©r   s   &r   Ú_is_summary_markerr#      s-   € Ü�eœTÓ"×]Ð]¤t¨E¯I©I´c³e×6[Ñ6[Ó,\Ó']Ð]r   c               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   r   "   s   € ÷ Yñ Y˜Cð Y Dñ Yr   c                ó€   € \        V 4      ;'       d-    \        V P                  \        4       P                  4      4      # )zXTrue for a summary marker provably absorbed into the rolling summary (micro, not batch).)r#   r   r    r   ÚMICRO_COMPACT_MARKER_KEYr"   s   &r   Ú_is_micro_markerr'   "   s+   € ä˜eÓ$×XÐX¬¨e¯i©i¼»×8VÑ8VÓ.WÓ)XÐXr   c                  ó.  € ] tR t^'tR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/R R lltR R ltR R lt]R R l4       tR R ltRRRRRR/R R lltR  R! ltR"RR#R/R$ R% lltR-R& R' llt]R( R) l4       tR* R+ ltR,tR# ).ÚMicroCompactionMixinz?Rolling micro-compaction; host must be a ``ContextCompressor``.c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Úmessagesúlist[dict[str, Any]]Úhead_endÚintÚ
tail_startr   r   )r   s   "r   r   Ú!MicroCompactionMixin.__annotate__*   s,   € ÷ ñ Ð0Dð ÐPSð Ðadð Ðilñ r   c                ó  a a€ VS P                   u;8  d   V8  d    S P                   #  VV 3R l\        W#4       4       p\        VRR7      pWR8¼  d
   V^,           MTpWR8¼  d–   S P                  P	                  4       '       d   RM&S P                  SV,          P                  R4      4      pV'       dE   VS n        RSV,          \        4       P                  &   \        P                  R\        V4      4       VS n         V# )zŽIndex of the first message not yet absorbed into the rolling summary: the in-memory
cursor when valid, else just past the last summary marker.c              3  óh   <"  € T F'  pSP                  SV,          4      '       g   K#  Vx € K)  	  R # 5ir   )Ú_is_context_summary_message)Ú.0Úir+   Úselfs   & €€r   Ú	<genexpr>Ú?MicroCompactionMixin._resolve_compact_cursor.<locals>.<genexpr>/   s)   øé € ÐmÑ ;˜1¸t×?_Ñ?_Ð`hÐijÕ`k×?l—Q’QÓ ;ùs   ƒ 2¨
2)ÚdefaultÚ ÚcontentTzFMicro-compaction: recovered rolling summary from transcript (%d chars)éÿÿÿÿ)Ú_micro_compact_cursorÚrangeÚmaxÚ_micro_compact_rolling_summaryÚstripÚ_rolling_summary_from_markerr    r   r&   ÚloggerÚinfoÚlen)r6   r+   r-   r/   Ú	summariesÚlastÚcursorÚ	recovereds   ff&&    r   Ú_resolve_compact_cursorÚ,MicroCompactionMixin._resolve_compact_cursor*   sß   ù€ ð �d×0Ñ0Ö=°:Õ=Ø×-Ñ-Ð-ð >åm¤ hÔ ;Ómˆ	Ü�9 bÔ)ˆØ!Ô-�˜–°8ˆØÔð #×AÑA×GÑG×IÒI™Ø×1Ñ1°(¸4µ.×2DÑ2DÀYÓ2OÓPð ÷ Ø6?�Ô3ð BF�˜•œs›u×=Ñ=Ñ>Ü—‘ÐdÔfiÐjsÓftÔuØ%+ˆÔ"Øˆr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r+   r,   Ústartr.   r/   r   úOptional[tuple[int, int]]r   )r   s   "r   r   r0   A   s,   € ÷ %ñ %Ø,ð%Ø58ð%ØFIð%à	"ñ%r   c                ó†  a a€ \        V\        S4      4      pR VV 3R llpTpWd8  d   V! VR4      '       g   V^,          pK   Wd8¼  d   R# TpV^,          pWd8  d   V! VR4      '       d   V^,          pK   V\        S4      8  d
   SV,          MRp\        V\        4      '       d   VP	                  R4      R9   d   R# Wv3# )zýFind the next complete exchange (full agent turn) starting at *start*; returns
``(exchange_start, exchange_end)`` or ``None``. Spans assistant+tool rows up to the next
user message; user turns are never absorbed (alternation safety, verbatim user text).c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úidxr.   ÚrolesÚtupler   r   r   )r   s   "r   r   Ú=MicroCompactionMixin._find_one_exchange.<locals>.__annotate__I   s&   € ÷ 	nñ 	n˜3ð 	n uð 	n°ñ 	nr   c                ó„   <€ SV ,          P                  R 4      V9   ;'       d    SP                  SV ,          4      '       * # )Úrole)r    r3   )rQ   rR   r+   r6   s   &&€€r   Ú	_turn_rowÚ:MicroCompactionMixin._find_one_exchange.<locals>._turn_rowI   s:   ø€ Ø˜C•=×$Ñ$ VÓ,°Ñ5×mÐm¸d×>^Ñ>^Ð_gÐhkÕ_lÓ>mÔ:mÐmr   NrV   )Ú	assistant)rY   Útool)ÚminrE   r   r   r    )	r6   r+   rM   r/   ÚlimitrW   rQ   Úexchange_startÚboundarys	   ff&&     r   Ú_find_one_exchangeÚ'MicroCompactionMixin._find_one_exchangeA   sµ   ù€ ô �J¤ H£Ó.ˆ÷	nñ 	nð
 ˆØŒk¡)¨C°×"@Ò"@Ø�1�HŠCØŒ<ÙØˆØˆq�ˆØŒk™i¨Ð-B×CÒCØ�1�HŠCð %(¬#¨h«-Ô$7�8˜C–=¸TˆÜ˜(¤D×)Ò)¨X¯\©\¸&Ó-AÐEZÔ-ZÙØÐ$Ð$r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úexisting_summaryÚstrÚexchange_textr   zlist[dict[str, str]]r   )r   s   "r   r   r0   _   s#   € ÷ 
ñ 
¸Cð 
ÐPSð 
ÐXlñ 
r   c                ó`   € VP                  4       '       d   TMRpRV RV R2pRRRR/RR	RV/.# )
z>Build the prompt messages for a single-exchange micro-summary.z(No previous summary yet.)uA  You are a summarization agent creating a compact record of an ongoing conversation.  You are given a running summary and the next exchange from the conversation.  Merge the exchange's key decisions, requirements, file paths, and open questions into the summary.  Preserve the summary's structure.  Drop resolved details that are no longer relevant.  Add new decisions, file paths, and open questions.

NEVER include API keys, tokens, passwords, secrets, credentials, or connection strings in the summary â€” replace any that appear with [REDACTED].

## Current Running Summary
z

## Next Exchange to Merge
zy

Return ONLY the updated summary text, no preamble or explanation. Do not include this instruction block in your output.rV   Úsystemr;   z/You are a conversation summarization assistant.Úuser)rA   )r6   rb   rd   Úsummary_blockÚuser_prompts   &&&  r   Ú_build_micro_summary_promptÚ0MicroCompactionMixin._build_micro_summary_prompt_   se   € à,<×,BÑ,B×,DÒ,DÑ(ÐJfˆð
+ð ,9¨/ð :*Ø*7¨ð 9DðDð 	ð" �X˜yÐ*[Ð\Ø�V˜Y¨Ð4ð
ð 	
r   c               ó    € V ^8„  d   QhRRRR/# )r   rd   rc   r   úOptional[str]r   )r   s   "r   r   r0   w   s   € ÷ +ñ +°#ð +¸-ñ +r   c                óü  € ^ RI HpHp RRRV P                  V P                  V4      R\        RV P                  ;'       g    R4      RR/pV P                  V4       V P                  '       dx   TP                  R	R
V P                  RV P                  ;'       g    RRV P                  ;'       g    RRV P                  ;'       g    RR\        V RR4      ;'       g    R/4        V! 4       ;_uu_ 4        V! R/ VB pRRR4       \#        4       P%                  X4      R8X  d   \        P'                  R4       R# TP(                  ^ ,          P*                  p\-        T\.        4      '       d   TP1                  R4      M\        TRT4      p\-        T\2        4      '       d   TMT'       d   \3        T4      MRP5                  4       p^ RIHp	 T	! RT4      P5                  4       pT'       g   \        P!                  R4       R# \#        4       P;                  YX4      '       d   \        P'                  R4       R# T#   + '       g   i     ELF; i  \         d"   p\        P!                  RT4        Rp?R# Rp?ii ; i)zXMicro-summarize one exchange into the rolling summary via the aux LLM (None on failure).)Úaux_interrupt_protectionÚcall_llmÚtaskÚcompressionr+   Ú
max_tokensiÜ  Útemperaturegš™™™™™¹?Úmain_runtimeÚmodelÚproviderr:   Úbase_urlÚapi_keyÚapi_modeNz#micro-summarization call failed: %sÚlengthub   micro-summarization output hit the token cap (finish_reason=length) â€” discarding partial summaryr;   )Ústrip_think_blocksz*micro-summarization returned empty contentuL   micro-summarization returned refusal content â€” discarding unusable summaryr   )Úagent.auxiliary_clientro   rp   rj   r@   r[   Úmax_summary_tokensÚ_apply_summary_routerv   Ú
setdefaultrw   rx   ry   ÚgetattrÚ	ExceptionrC   rD   r   Ú_response_finish_reasonÚwarningÚchoicesÚmessager   r   r    rc   rA   Úagent.agent_runtime_helpersr|   Ú_is_refusal_response)
r6   rd   ro   rp   Úcall_kwargsÚresponseÚexcr†   r;   r|   s
   &&        r   Ú_micro_summarize_oneÚ)MicroCompactionMixin._micro_summarize_onew   sü  € çMð �MØ˜×8Ñ8¸×9\Ñ9\Ð^kÓlØœ#˜d D×$;Ñ$;×$CÐ$C¸tÓDØ˜3ð	
ˆð 	×!Ñ! +Ô.Ø�:�:ˆ:Ø×"Ñ" >Ø˜Ÿ™ Z°·±×1DÐ1DÀ"ÀjÐRV×R_ÑR_×ReÐReÐceØ˜4Ÿ<™<×-Ð-¨2¨z¼7À4ÈÐUWÓ;X×;^Ð;^Ð\^ð4ô ð
	Ù)×+Õ+Ù#Ñ2 kÑ2�÷ ,ô ‹5×(Ñ(¨Ó2°hÔ>Ü�N‰NØtôñ à×"Ñ" 1Õ%×-Ñ-ˆÜ,6°wÄ×,EÒ,E�'—+‘+˜iÔ(Ì7ÐSZÐ\eÐgnÓKoˆÜ(¨´#×6Ò6‘7ÏG¼CÀ¼LÐY[×bÑbÓdˆåBÙ$ T¨7Ó3×9Ñ9Ó;ˆßÜ�K‰KÐDÔEÙÜ‹5×%Ñ% h×8Ò8Ü�N‰NÐiÔjÙØˆ÷3 ,×+Ð+ûäô 	Ü�K‰KÐ=¸sÔCÝûð	ús6   Ã&I Ã5	H;Ã>I È;I	ÉI ÉI ÉI;ÉI6É6I;c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r   r0   ¤   s   € ÷ yñ y˜tñ yr   c                óF   € \        V P                  4      V P                  8¬  # )z?Return True when the rolling summary is large enough to defrag.)r   r@   Ú&_micro_compact_defrag_threshold_tokens©r6   s   &r   Ú_needs_defragÚ"MicroCompactionMixin._needs_defrag¤   s   € ä$ T×%HÑ%HÓIÈT×MxÑMxÑxÐxr   c               ó    € V ^8„  d   QhRRRR/# )r   r+   r,   r   r   r   )r   s   "r   r   r0   ¨   s   € ÷ ñ Ð0Dð Èñ r   c                óÄ  € V P                   pVP                  4       '       g   R# RV n         V P                  V4      pT;'       g    TV n         V'       g   R# \        R \	        V4       4       R4      pVe@   V P                  V4      VR&   VP                  \        4       P                  R4       RV n	        \        P                  R\        V4      \        V4      4       R# )zšRe-summarize the rolling summary text and rewrite the marker in place.
Transcript-shape-neutral (no splice, no cursor move). Returns True when it rewrote.Fr:   c              3  óL   "  € T F  p\        V4      '       g   K  Vx € K  	  R # 5ir   ©r'   ©r4   Úes   & r   r7   Ú?MicroCompactionMixin._defrag_rolling_summary.<locals>.<genexpr>¶   s   é € ÐKÑ!3˜AÔ7GÈ×7J—a’aÓ!3ùó   ‚$š
$Nr;   TzGMicro-compaction defrag: rolling summary re-summarized (%d -> %d chars))r@   rA   rŒ   ÚnextÚreversedÚ_render_micro_marker_contentÚpopr   Ú_DB_PERSISTED_MARKERÚ_flush_scan_cursor_invalidatedrC   rD   rE   )r6   r+   Úold_summaryÚfresh_summaryr   s   &&   r   Ú_defrag_rolling_summaryÚ,MicroCompactionMixin._defrag_rolling_summary¨   sÈ   € ð ×9Ñ9ˆØ× Ñ ×"Ò"Ùà.0ˆÔ+Ø×1Ñ1°+Ó>ˆØ.;×.JÐ.J¸{ˆÔ+ßÙô ÑK¤¨(Ô!3ÓKÈTÓRˆØÒØ#×@Ñ@ÀÓOˆE�)Ñð �I‰I”c“e×0Ñ0°$Ô7ð 37ˆDÔ/Ü�‰ØUÜ�Óœc -Ó0ô	
ñ r   c               ó   € V ^8„  d   QhRR/# )r   r   ÚNoner   )r   s   "r   r   r0   É   s   € ÷ 5ñ 5¨tñ 5r   c                	ó"   € ^ V n         RV n        R# )é    Nr<   )Ú#_micro_compact_consecutive_failuresÚ"_micro_compact_last_failure_cursorr‘   s   &r   Ú_reset_micro_failure_trackingÚ2MicroCompactionMixin._reset_micro_failure_trackingÉ   s   € Ø34ˆÔ0Ø24ˆÖ/r   Úturn_session_idNc               ó$   € V ^8„  d   QhRRRRRR/# )r   r+   r,   r®   rm   r   r   )r   s   "r   r   r0   Í   s)   € ÷ _ñ _Ø,ð_ØBOð_à	ñ_r   c               ó4  a aaaa€ S P                   '       g   V# \        ^\        S P                  ;'       g    ^4      4      pV^8”  d4   S ;P                  ^,          un        S P                  V8  d   V# ^ S n        \        V4      oS^8¼  d   S P                  V4      MRpVf   V# Vw  rV\        P                  ! 4       o\        V4      o\        V4      pS P                  V4      w  r‰R VVVV V3R llp
V'       d   V
! W�SR7       V# S P                  S P                  rËS P                  4       '       dÓ   \        R \!        V4       4       R4      pVe   \#        V4      MRpS P%                  V4      pV'       dS   S P'                  WV	R7      '       g:   VS n        Ve"   VP)                  4        VP+                  V4       V
! RVSR7       V# V'       d   S P-                  4        V'       d   RMR	pV
! VV\        V4      R7       V# \/        S P                  P1                  4       4      pS P3                  WV 4      p\5        V4      pS P7                  V4      pVf    S P9                  WV4      pV
! VVSVR
7       V# VS n        VS n        S P-                  4        S P;                  WVVR7      pS P=                  VV^,           4      S n        S P'                  VWyR7      '       g   W¼uS n        S n        V
! RVSR7       V# V
! RV\        V4      VR
7       V# )ad  Run one round of micro-compaction (entry point from ``finalize_turn()``). Returns the
(possibly modified) list and syncs the session DB via ``archive_and_compact`` (the
append-only flush alone would double-load on resume). ``turn_session_id`` is the session the
caller's turn started in; it parents the pass's Relay mark when this session has no scope yet.Nc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úoutcomerc   Úresultr,   Úextrar   r   r§   r   )r   s   "r   r   Ú9MicroCompactionMixin._micro_compact.<locals>.__annotate__ï   s*   € ÷ 	ñ 	 ð 	Ð-Að 	ÈCð 	ÐTXñ 	r   c                óª   <€ SP                   ! RR V RSR\        V4      RSR\        \        P                  ! 4       S,
          R,          4      RS/VB  R# )	r²   Úmessages_beforeÚmessages_afterÚtokens_beforeÚduration_msiè  r®   Nr   )Ú _emit_micro_compaction_telemetryrE   r.   ÚtimeÚ	monotonic)r²   r³   r´   Ú_started_atÚ_tokens_beforeÚ
n_messagesr6   r®   s   &&,€€€€€r   Ú
_telemetryÚ7MicroCompactionMixin._micro_compact.<locals>._telemetryï   sj   ø€ Ø×1Ò1ñ ØðØ1;ðÜLOÐPVËKðà,ðä:=¼t¿~º~Ó?OÐR]Õ?]ÐaeÕ>eÓ:fðð !0ðð 49ôr   )Útokens_afterc              3  óL   "  € T F  p\        V4      '       g   K  Vx € K  	  R # 5ir   r—   r˜   s   & r   r7   Ú6MicroCompactionMixin._micro_compact.<locals>.<genexpr>ÿ   s   é € ÐQÑ'9 !Ô=MÈa×=PŸAšAÓ'9ùr›   )ÚheldÚstart_watermarkÚstale_generationÚdefragÚdefrag_failed)rÃ   Úexchange_tokens)Ú	supersedeÚabsorbed)Ú_micro_compact_enabledr?   r.   Ú_micro_compact_every_n_turnsÚ_micro_compact_turns_since_passrE   Ú_next_exchanger¼   r½   r
   ÚlistÚ_micro_start_watermarkr=   r@   r’   rœ   r�   r   r¤   Ú_sync_micro_compact_to_dbÚclearÚupdater¬   r   rA   Ú_serialize_for_summaryr   rŒ   Ú_record_micro_failureÚ_splice_micro_compact_resultÚ_cursor_after_splice)r6   r+   r®   Úevery_nÚexchanger]   Úexchange_endÚ_heldÚ_skipÚ_start_watermarkrÁ   Ú_pre_cursorÚ_pre_summaryÚ_markerÚ_pre_markerÚ	defraggedr²   Ú_cumulativerd   Ú_exchange_tokensÚupdated_summaryÚ_outcomer³   r¾   r¿   rÀ   s   f&d                    @@@r   Ú_micro_compactÚ#MicroCompactionMixin._micro_compactÍ   sö  ü€ ð ×*×*Ð*ØˆOô �aœ˜T×>Ñ>×CÐCÀ!ÓDÓEˆØ�QŒ;Ø×0Ò0°AÕ5Õ0Ø×3Ñ3°gÔ=Ø�Ø34ˆDÔ0ä˜“]ˆ
Ø4>À!´O�4×&Ñ& xÔ0ÈˆØÒØˆOØ'/Ñ$ˆô —n’nÓ&ˆÜ7¸ÓAˆô �X“ˆØ"&×"=Ñ"=¸eÓ"DÑˆ÷	ô 	÷ Ù�u°^ÕDØˆOà$(×$>Ñ$>À×@cÑ@c�\ð ×Ñ×ÒÜÑQ¤x°Ô'9ÓQÐSWÓXˆGØ+2Ò+>œ$˜wœ-ÀDˆKØ×4Ñ4°XÓ>ˆIß ×!?Ñ!?ØÐ6Fð "@÷ "ò "ð 7C�Ô3ØÒ&Ø—M‘M”OØ—N‘N ;Ô/ÙÐ-¨xÀnÕUØ�ßØ×2Ñ2Ô4ß"+‘h°ˆGÙ�w Ô7UÐV^Ó7_Õ`ØˆOô ˜4×>Ñ>×DÑDÓFÓGˆà×3Ñ3°HÈLÐ4YÓZˆÜ0°Ó?ÐØ×3Ñ3°MÓBˆØÒ"Ø×1Ñ1°.ÓOˆHÙ�x ¸ÐXhÕiØˆOà.=ˆÔ+Ø%1ˆÔ"Ø×*Ñ*Ô,à×2Ñ2°8È\ÐepÐ2ÓqˆØ%)×%>Ñ%>¸vÀ~ÐXYÕGYÓ%ZˆÔ"Ø×-Ñ-¨f¸5Ð-×cÒcð OZÐKˆDÔ&¨Ô(KÙÐ)¨8À.ÕQØˆOÙØ˜Ô-KÈFÓ-SÐeuõ	
ð ˆr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r]   r.   rÝ   r   rc   r   )r   s   "r   r   r0   .  s!   € ÷ "ñ "°Cð "Àsð "Èsñ "r   c                ó(  € WP                   8H  pV'       d   V P                  ^,           M^V n        Wn         V P                  \        4       P                  8  d   R# \        P                  RWP                  4       W n        V P                  4        R# )zTCount a summarize failure at this cursor; skip the exchange after too many in a row.Úsummarize_failedzNMicro-compaction: skipping exchange at cursor %d after %d consecutive failuresÚexchange_skipped)r«   rª   r   Ú'_MICRO_COMPACT_MAX_CONSECUTIVE_FAILURESrC   rD   r=   r¬   )r6   r]   rÝ   Úsame_cursors   &&& r   rØ   Ú*MicroCompactionMixin._record_micro_failure.  sy   € ð %×(OÑ(OÑOˆßcn°4×3[Ñ3[Ð^_Ö3_ÐtuˆÔ0Ø2@Ô/Ø×3Ñ3´c³e×6cÑ6cÔcÙ%Ü�‰Ø\Ø×DÑDô	
ð
 &2Ô"Ø×*Ñ*Ô,Ù!r   c               ó    € V ^8„  d   QhRRRR/# )r   r+   r,   r   rN   r   )r   s   "r   r   r0   ?  s    € ÷ kñ kÐ';ð kÐ@Yñ kr   c                óÐ   € V P                  WP                  V4      4      pV P                  WRR7      pW#8¼  d   R# V P                  WV4      pWC8¼  d   R# V P	                  WV4      # )zFThe next un-absorbed exchange inside the compressible window, or None.F)Úallow_split_turnN)Ú_align_boundary_forwardÚ_protect_head_sizeÚ_find_tail_cut_by_tokensrJ   r_   )r6   r+   Úcompress_startÚcompress_endrH   s   &&   r   rÑ   Ú#MicroCompactionMixin._next_exchange?  sm   € à×5Ñ5°h×@WÑ@WÐX`Ó@aÓbˆØ×4Ñ4°XÐ`eÐ4ÓfˆØÔ)ÙØ×-Ñ-¨hÈÓUˆØÔ-ˆtÐj°4×3JÑ3JÈ8Ð]iÓ3jÐjr   c               ó    € V ^8„  d   QhRRRR/# )r   r;   r   r   rc   r   )r   s   "r   r   r0   I  s   € ÷ 	;ñ 	;¨cð 	;°cñ 	;r   c                ó€  € \        4       p\        V \        4      '       d   V P                  4       '       g   R# V P	                  VP
                  4      pVR8w  d   W\        VP
                  4      ,           R MT pVP                  VP                  4      pVR8w  d   VRV P                  4       # TP                  4       # )zLRecover the rolling-summary text from a summary marker (resume rehydration).r:   Nr<   )	r   r   rc   rA   ÚrfindÚHISTORICAL_TASK_HEADINGrE   ÚfindÚ_SUMMARY_END_MARKER)r;   ÚccrQ   ÚbodyÚends   &    r   rB   Ú1MicroCompactionMixin._rolling_summary_from_markerH  sš   € ô ‹UˆÜ˜'¤3×'Ò'¨w¯}©}¯ªÙà�m‰m˜B×6Ñ6Ó7ˆØBEÈÄ)ˆwœS ×!;Ñ!;Ó<Õ<Ð=Ñ>ÐQXˆØ�i‰i˜×.Ñ.Ó/ˆØ! Rœi��T�c�
×8Ñ8Ó:Ð:¨T×8Ñ8Ó:Ð:r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r³   r,   Úfallbackr.   r   r   )r   s   "r   r   r0   T  s(   € ÷ vñ vÐ+?ð vÈ3ð vÐSVñ vr   c                óf   a€ \        V3R l\        \        S4      ^,
          RR4       4       V4      # )zöCursor position just past the summary marker in *result*. Must derive from the SPLICED
list: a splice collapses several rows into one marker (and may drop a superseded one), so
pre-splice indices land inside a later exchange and silently skip it.c              3  ój   <"  € T F(  p\        SV,          4      '       g   K  V^,           x € K*  	  R# 5i)é   N)r#   )r4   rQ   r³   s   & €r   r7   Ú<MicroCompactionMixin._cursor_after_splice.<locals>.<genexpr>X  s*   øé € ÐjÑ(F ÔJ\Ð]cÐdgÕ]h×Ji”W�S˜1—W’WÓ(Fùs   ƒ3¢3r<   )rœ   r>   rE   )r6   r³   r  s   &f&r   rÚ   Ú)MicroCompactionMixin._cursor_after_spliceT  s*   ø€ ô Ôj¬¬c°&«k¸A­o¸rÀ2Ô(FÓjÐltÓuÐur   rË   rº   c               ó<   € V ^8„  d   QhRRRRRRRRRRR	RR
RRRRR/	# )r   r²   rc   r·   r.   r¸   r¹   z
int | NonerÃ   rË   rº   r®   z
str | Noner   r§   r   )r   s   "r   r   r0   Z  sc   € ÷ !Oñ !OØð!OØ03ð!OØEHð!OØYcð!Oà ð!Oà3=ð!OàS]ð!Oð $ð!Oð 
ñ	!Or   c          	     óþ  €  Ve   Ve	   WT,
          MRp	T ;P                   T	;'       g    ^ ,          un         V ;P                  ^,          un        V P                  p
T
;'       d    VRJ;'       d    V
^ 8„  pV'       d   \        WZ,          ^d,          ^4      MRp/ RRbR\	        V RR4      ;'       g    RbRVbRVbR	VbR
\        V4      bR\        V4      bR\        V	4      bR\        V4      bR\        V P                  4      bR\        V P                  4      bRV P                  bRV P                   bR\        V4      bR\        V
4      bR\        V P                  4      bRVbRV P                  ;'       g    RRV P                  ;'       g    R/Cp\        P                  R\        P                  ! VRRR7      4       \!        WØR7       R#   \"         d"   p\        P%                  RT4        Rp?R# Rp?ii ; i)zšEmit one content-free JSON log line for a micro-compaction pass.
``tokens_delta`` < 0 means the pass shrank the transcript; ``*_total`` fields accumulate.NÚeventÚmicro_compactionÚ
session_idÚ_session_idr:   r²   r·   r¸   r¹   rÃ   Útokens_deltarË   Úrolling_summary_tokensrH   Úpasses_totalÚtokens_saved_totalrº   Úthreshold_tokensÚcontext_limitÚoccupancy_pctÚ
main_modelÚ	aux_modelzmicro compaction telemetry: %sT)Ú	sort_keysÚ
separators)r®   z-failed to emit micro-compaction telemetry: %s)Ú,Ú:)Ú!_micro_compact_tokens_saved_totalÚ_micro_compact_passesÚ_threshold_tokensÚroundr�   r   r   r@   r=   Ú_resolved_context_lengthrv   Úsummary_modelrC   rD   ÚjsonÚdumpsr   r‚   Údebug)r6   r²   r·   r¸   r¹   rÃ   rË   rº   r®   ÚdeltaÚ	thresholdÚhas_occupancyÚ	occupancyÚpayloadr‹   s   &$$$$$$$$      r   r»   Ú5MicroCompactionMixin._emit_micro_compaction_telemetryZ  s9  € ð	OØ4AÒ4MÐR^ÒRj�LÖ0ÐptˆEØ×2Ò2°e·j°j¸qÕ@Õ2Ø×&Ò&¨!Õ+Õ&ð
 ×.Ñ.ˆIØ%×TÐT¨,¸dÐ*B×TÐTÀyÐSTÁ}ˆMßDQœ˜lÕ6¸Õ<¸aÔ@ÐW[ˆIðØÐ+ðØ-9¼7À4ÈÐXZÓ;[×;aÐ;aÐ_aðØclÐnuðà! ?ðà4DÀnðð  ¤¨=Ó!9ðð <JÌ9ÐUaÓKbðð ¤	¨%Ó 0ð	ð 3DÄYÈÓE_ð	ð
 )Ô*?À×@cÑ@cÓ*dðð œ) D×$>Ñ$>Ó?ðð BPÐQU×QkÑQkðð % d×&LÑ&Lðð O\Ô]fÐgrÓ]sðð #¤I¨iÓ$8ðð ;JÌ9ÐUY×UrÑUrÓKsðð   ðð -9¸$¿*¹*×:JÐ:JÈÈKÐY]×YkÑYk×YqÐYqÐoqñˆGô �K‰KÐ8¼$¿*º*ÀWÐX\ÐisÔ:tÔuÜ˜'×CøÜô 	OÜ�L‰LÐHÈ#×NÒNûð	Oús;   ‚&G ©;G Á%G Á1G Á?3G Â3CG Æ>G ÇG<ÇG7Ç7G<c               ó    € V ^8„  d   QhRRRR/# )r   rÆ   r,   r   z#tuple[Optional[str], Optional[int]]r   )r   s   "r   r   r0   }  s   € ÷ ñ Ð+?ð ÐDgñ r   c                ó¤  € \        V RR4      \        V RR4      r2\        VRR4      pV'       d   \        V4      '       g   R#  V! V4      p\        4       P                  W#W4       RV3#   \        4       P                   d#   p\
        P                  RT4       R	u Rp?# Rp?i\         d#   p\
        P                  RT4       R
u Rp?# Rp?ii ; i)uä  ``(skip_outcome, watermark)`` taken before a pass's slow step; *skip_outcome* is the telemetry
label of a pass that must not run, or None.

A store with no watermark API runs the pass with ``(None, None)``: the commit keeps today's
archive-everything behaviour. ``watermark_unavailable`` when the read itself raised â€” that must
NOT collapse into the same None, because None means "archive every active row", the very loss
this watermark exists to prevent. ``stale_generation`` when *held* is no longer the session's live
generation (another compaction already committed): this pass holds no compression lease, so
publishing would leave two generations live. The commit re-checks, since a compaction can also
land during the summary call.
Ú_session_dbNr  r:   Úget_active_message_watermarkz(micro-compaction: skipping this pass, %sz?micro-compaction: watermark read failed, skipping this pass: %s)NN)rÈ   N)Úwatermark_unavailableN)r�   Úcallabler   Ú_archive_watermark_forÚStaleHeldHistoryrC   rD   r‚   )r6   rÆ   Ú
session_dbr  Úwatermark_ofÚ	watermarkr‹   s   &&     r   rÓ   Ú+MicroCompactionMixin._micro_start_watermark}  s¼   € ô ")¨¨}¸dÓ!CÄWÈTÐS`ÐbdÓEe�JÜ˜zÐ+IÈ4ÓPˆß¤¨,×!7Ò!7ØÐð	1Ù$ ZÓ0ˆIÜ‹E×(Ñ(¨ÀÔQð �YˆÐøô ‹u×%Ñ%ô 	,Ü�K‰KÐBÀCÔHØ+Õ+ûÜô 	1Ü�K‰KÐYÐ[^Ô_Ø0Õ0ûð	1ús6   Á"A) Á)CÂBÂCÂCÂ,CÂ-C
ÃCÃ
CrÆ   rÇ   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úcompacted_messagesr,   rÆ   zOptional[list[dict[str, Any]]]rÇ   zOptional[int]r   r   r   )r   s   "r   r   r0   ˜  s.   € ÷ 3ñ 3Ø"6ð3ØA_ð3à&ð3ð 
ñ3r   c          
     óò  € \        V RR4      \        V RR4      rTV'       d	   V'       g   R# ^ RIHp  V Uu. uFH  p\        V\        4      '       g   K  VP                  \        4       P                  4      '       g   KF  VNKJ  	  ppRp	R;r«Ve0   Ve,   \        4       P                  WEW#4      p	^ RI	H
p V! WEV4      w  r«VP                  WQW‰W«VR7       \        4       P                  V4       R# u upi   \        4       P                   d"   p\        P                  R	T4        Rp?R
# Rp?iT d"   p\        P                  R	T4        Rp?R
# Rp?i\          d    \        P                  R4        R# i ; i)af  Persist the micro-compacted set to the session DB atomically and stamp rows persisted.
Without this the old exchange rows stay ``active=1`` and a resume double-loads both the
summary and the originals. Returns False only when *held* turned out to be a stale generation
(nothing written); the caller must then discard the pass. Any other outcome returns True.r1  Nr  r:   T)ÚHeldRowRewrittenError)Úcoverage_for_commit)Úcarried_messagesr9  Úcovered_idsÚunresolved_heldÚheld_for_casz#Micro-compaction commit skipped, %sFuo   Micro-compaction DB sync failed â€” resume will double-load compacted messages until the next batch compression)r�   Úhermes_state_errorsr>  r   r   r    r   r    r5  Ú&agent.conversation_compression_archiver?  Úarchive_and_compactÚstamp_db_persisted_markersr6  rC   rD   r‚   )r6   r<  rÆ   rÇ   r7  r  r>  r†   r@  r9  rA  rB  r?  r‹   s   &&$$          r   rÔ   Ú.MicroCompactionMixin._sync_micro_compact_to_db˜  s_  € ô ")¨¨}¸dÓ!CÄWÈTÐS`ÐbdÓEe�Jß§ÙÝ=ð&	ñ (:ó Ù'9˜GÜ˜g¤t×,ô Ø18·±¼S»U×=WÑ=W×1X÷ �Ñ'9ð ð  ð ˆIØ,0Ð0ˆKØÒ OÒ$?Ü›E×8Ñ8¸ÐQUÓg�	ÝVÙ/BÀ:Ð[_Ó/`Ñ,�Ø×*Ñ*ØÐAQØ'Ø!ð +ô #ô ‹E×,Ñ,Ð-?Ô@ñ" ùòC øô" ‹u×%Ñ%ô 	ô �K‰KÐ=¸sÔCÝûØ$ô 	ô �K‰KÐ=¸sÔCÝûÜô 	Ü�K‰KðFõñ ð	úsS   ³C4 ·C/Á&C/Á?C/ÂA(C4 Ã/C4 Ã4E6ÄD)Ä)E6Ä2E6Ä3EÅE6ÅE6Å5E6c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r+   r,   Úsplice_startr.   Ú
splice_endrÌ   r   r   r   )r   s   "r   r   r0   Í  s4   € ÷ ñ Ø,ðØ<?ðØMPðØ]aðà	ñr   c           
     ó  € \        4       pV P                  pVP                  4       '       g   V# RRRV P                  V4      VP                  RVP
                  RVP                  R/pVRV V.,           WR ,           pV'       d6   \        V4       U	U
u. uF  w  rš\        V
4      '       g   K  V	NK  	  up
p	RR M. pV'       d7   T P                  \        V4       U	U
u. uF  w  ršW›9  g   K  V
NK  	  up
p	4      pV# u up
p	i u up
p	i )z­Replace *messages[splice_start:splice_end]* with an assistant-role summary marker.
Merges user turns left adjacent by a superseded marker so the result is alternation-valid.rV   rY   r;   TFNr<   )
r   r@   rA   rž   r!   r&   Ú$COMPRESSED_SUMMARY_HAS_USER_TURN_KEYÚ	enumerater'   Ú_merge_adjacent_user_turns)r6   r+   rJ  rK  rÌ   r  Úsummary_textÚsummary_msgr³   r5   ÚmÚstales   &&&&&       r   rÙ   Ú1MicroCompactionMixin._splice_micro_compact_resultÍ  s  € ô
 ‹UˆØ×:Ñ:ˆØ×!Ñ!×#Ò#ØˆOð �K ¨D×,MÑ,MÈlÓ,[Ø×.Ñ.°à×'Ñ'¨à×3Ñ3°Uð
ˆð ˜-˜<Ð(¨K¨=Õ8¸8ÀKÐ;PÕPˆ÷ R[œy¨Ô0ÔHÑ0‘t�qÔ4DÀQ×4G—�Ñ0ÒHÈÈ"ÑMÐ`bˆßØ×4Ñ4ÄIÈfÔDUÔ5hÑDU¹D¸AÐYZÑYg·a°aÑDUÒ5hÓiˆFð ˆùó Iùã5hs   ÂC=Â.C=Ã
D
Ã-D
c               ó    € V ^8„  d   QhRRRR/# )r   rP  rc   r   r   )r   s   "r   r   r0   ì  s   € ÷ zñ z°3ð z¸3ñ zr   c                óˆ   € \        4       pVP                   RVP                   RV P                  4        RVP                   2# )z:Assemble the marker content wrapper around *summary_text*.ú

Ú
)r   ÚSUMMARY_PREFIXrÿ   rA   r  )rP  r  s   & r   rž   Ú1MicroCompactionMixin._render_micro_marker_contentë  sI   € ô ‹UˆØ×#Ñ#Ð$ D¨×)CÑ)CÐ(DÀBÀ|×GYÑGYÓG[ÐF\Ð\`Ðac×awÑawÐ`xÐyÐyr   c               ó    € V ^8„  d   QhRRRR/# )r   r³   r,   r   r   )r   s   "r   r   r0   ñ  s   € ÷ ñ Ð1Eð ÐJ^ñ r   c                óö  € ^ RI Hp R R lp. pV Fä  pV'       d
   VR
,          MRpV! V4      '       d°   V! V4      '       d¢   RP                  R VR,          VR,          3 4       4      VR&   V! V4       / VP                  R4      ;'       g    / C\	        4       P
                  R	/CVR&   VP                  \	        4       P                  R4       R	V n        \        We4       KÓ  VP                  V4       Kæ  	  V# )zåMerge consecutive plain-text real user turns left by a supersede. Same ``\n\n`` join as
``repair_message_sequence`` pass 2, done here so the marker and cursor are never collateral
damage of the downstream repair. Lists untouched.)Údrop_stale_api_contentc               ó    € V ^8„  d   QhRRRR/# )r   rR  r   r   r   r   )r   s   "r   r   ÚEMicroCompactionMixin._merge_adjacent_user_turns.<locals>.__annotate__÷  s   € ÷ 	ñ 	˜3ð 	 4ñ 	r   c                óØ   € \        V \        4      ;'       dT    V P                  R 4      R8H  ;'       d8    \        V 4      '       * ;'       d     \        V P                  R4      \        4      # )rV   rg   r;   )r   r   r    r#   rc   )rR  s   &r   Ú_plain_userÚDMicroCompactionMixin._merge_adjacent_user_turns.<locals>._plain_user÷  s]   € ä˜1œdÓ#÷ 6ð 6¨¯©¨f«¸Ñ(?÷ 6ð 6ÔHZÐ[\ÓH]ÔD]÷ 6ð 6Ü˜qŸu™u YÓ/´Ó5ðr   NrW  c              3  ó8   "  € T F  q'       g   K  Vx € K  	  R # 5ir   r   )r4   Úcs   & r   r7   ÚBMicroCompactionMixin._merge_adjacent_user_turns.<locals>.<genexpr>  s   é € Ð-`Ñ9Z°AÓ^_¯aªaÓ9Zùs   ‚	�
r;   Údisplay_metadataTr<   )Úagent.turn_contextr]  Újoinr    r   ÚMODEL_ONLY_DISPLAY_METADATA_KEYrŸ   r    r¡   r	   Úappend)r6   r³   r]  ra  ÚmergedÚmsgÚprevs   &&     r   rO  Ú/MicroCompactionMixin._merge_adjacent_user_turnsñ  sã   € õ 	>õ	ð (*ˆÛˆCß!'�6˜"–:¨TˆDÙ˜3×Ò¡K°×$5Ò$5Ø"(§+¡+Ñ-`¸$¸y½/È3ÈyÍ>Ñ9ZÓ-`Ó"`��Y‘Ù& tÔ,ð,Y¨t¯x©xÐ8JÓ/K×/QÐ/QÈrð ,YÜ,/«E×,QÑ,QÐSWñ,Y�Ð'Ñ(ð —‘œ›×3Ñ3°TÔ:Ø6:�Ô3Ü'¨Ö2à—‘˜cÖ"ñ# ð$ ˆr   )r¡   rª   r=   r«   r@   rÐ   )T)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rJ   r_   rj   rŒ   r’   r¤   r¬   rê   rØ   rÑ   ÚstaticmethodrB   rÚ   r»   rÓ   rÔ   rÙ   rž   rO  Ú__static_attributes__r   r   r   r)   r)   '   sÄ   † ÙIõõ.%õ<
õ0+õZyõõB5ð_ØRV÷_õB"õ"kð ô	;ó ð	;õvð!Oà@Dð!Oà`dð!Oð '+÷!OõFð63Øbfð3à)-÷3÷jð< ôzó ðz÷
ñ r   r)   )rs  Ú
__future__r   r&  Úloggingr¼   Útypingr   r   r   r   Úagent.compaction_eventsr   Ú"agent.context_compressor_telemetryr   Úagent.message_metadatar	   Úagent.model_metadatar
   r   Ú	getLoggerrC   r   r#   r'   r)   r   r   r   Ú<module>r~     sZ   ðñõ #ã Û Û ß ,Ó ,å 1Ý 8Ý :ß Vð 
×	Ò	Ð5Ó	6€òõ^õY÷
ió ir   