Ë
    áß²j]G  ã                   óü   — d Z ddlZddlZddlZddlZddlZddlmZ  ej                  d«      Z	 G d„ d«      Z
dedefd	„Zd
ededededededdfd„Zdededdfd„Zdd„Zddœd„Zdeddfd„Zdd„Z G d„ d«      Zy)ae  Host-side ``AIAgent._compress_context`` wrapper.

Publishes the commit fence ``hard_interrupt()`` reads, runs the compressor on a snapshot under the progress
timeout, mirrors ``_DB_PERSISTED_MARKER`` stamps back onto the live lists and rebinds the session context.
Extracted from ``run_agent.py``; every method resolves through ``AIAgent``'s MRO unchanged.
é    N)ÚActivityProvenanceÚ	run_agentc                   ó   — e Zd ZdZdZdd„Zy)Ú_CommitFenceRegistrationa³  One ``_compress_context`` attempt's entry on the agent's commit-fence stack.

    The fence slot is a stack, not a save/restore cell: overlapping attempts register in
    order but may complete in any order, so each attempt removes only its own entry and the
    published slot always tracks the newest *live* attempt. The stall-fallback retry swaps
    ``fence`` in place so the slot update stays tied to the owning registration.
    ©ÚfenceNc                 ó   — || _         y ©Nr   )Úselfr   s     ú=/home/ubuntu/.hermes/hermes-agent/agent/compression_facade.pyÚ__init__z!_CommitFenceRegistration.__init__   s	   € Øˆ�
ó    ©ÚreturnN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__r   © r   r   r   r      s   „ ñð €Iôr   r   Úsystem_messager   c                 ó    — t        | dd«      x}r|S 	 | j                  |«      S # t        $ r  t        j	                  dd¬«       |xs dcY S w xY w)zûCached prompt, else a fresh build, else the raw ``system_message`` (never raises).
    Resolved lazily by the timeout wrapper: an eager rebuild would raise before compress_context runs when
    ``_cached_system_prompt`` is unset and the builder fails.Ú_cached_system_promptNzQcompress_context timeout fallback prompt rebuild failed; using raw system_messageT©Úexc_infoÚ )ÚgetattrÚ_build_system_promptÚ	ExceptionÚloggerÚdebug)Úagentr   Úcacheds      r   Ú_timeout_fallback_promptr$   #   s`   € ô ˜Ð 7¸Ó>Ð>€vÐ>Øˆð$Ø×)Ñ)¨.Ó9Ð9øÜò $Ü�‰ÐhÐswˆÔxØÒ# Ò#ð$ús   “$ ¤&AÁAÚidleÚwaitedÚsince_progressÚtotal_ceilingÚtotal_exhaustedÚprogress_observedc                ór  — ddl m}  || «       |rt        j                  d||«       nt        j                  d|||«       t	        | dd«      }t        |«      r	  |dt        j                  ¬«       t	        t	        | dd«      dd«      }	t        |	«      r	 |r |	dd¬«       n
 |	dd¬«       t	        | dd«      }
t        |
«      sy|r|rdnd} |
d|d›d|› d�«       y |
d|d›d�«       y# t        $ r t        j                  d	d
¬«       Y Œ�w xY w# t        $ r t        j                  dd
¬«       Y Œˆw xY w)zRHost-side timeout bookkeeping: log, activity stamp, cooldown ladder, user warning.r   )Ú"mark_context_compression_timed_outzpContext compression reached its total ceiling after %.1fs (progress observed=%s); continuing without compressionzpContext compression made no progress for %.1fs (total wait %.1fs, ceiling %.1fs); continuing without compressionÚ_touch_activityNzcontext compression timed out)Ú
provenancez.compress_context timeout activity touch failedTr   Úcontext_compressorÚrecord_timeout_failurez-host compress_context total ceiling exhaustedÚceiling_exhausted)Úfailure_kindz3host compress_context timeout (no summary progress)Ústalledz2failed to record compress_context timeout cooldownÚ_emit_warningz" after summary output was observedr   u8   âš  Context compression reached its total ceiling after z.1fÚsur   . No messages were dropped â€” continuing without compression. Run /compress to retry or /new for a clean session.u(   âš  Context compression timed out after u·   s with no output from the summary model. No messages were dropped â€” continuing without compression. Run /compress to retry, /new for a clean session, or check auxiliary.compression.)
Úagent.conversation_compressionr,   r    Úwarningr   Úcallabler   ÚAGENT_COMPRESSION_TIMEOUTr   r!   )r"   r%   r&   r'   r(   r)   r*   r,   ÚtouchÚrecordÚemitÚprogresss               r   Ú_report_compression_timeoutr>   0   sl  € õ
 RÙ& uÔ-ÙÜ�‰Ø~ØÐ%õ	
ô
 	�‰Ø~Ø˜F Mô	
ô �EÐ,¨dÓ3€EÜ�„ð	ZÙÐ1Ô>P×>jÑ>jÕkô ”W˜UÐ$8¸$Ó?ÐAYÐ[_Ó`€FÜ�Ôð	^ÙÙÐFÐUhÖiáÐLÐ[dÕeô �5˜/¨4Ó0€DÜ�DŒ>ØÙÙ;LÑ7ÐRTˆÙðØ˜C�L  ( ð ,nðnõ	
ñ 	Ø6°t¸C°jð ACð Cõ	
øô/ ò 	ZÜ�L‰LÐIÐTXˆLÖYð	Zûô ò 	^Ü�L‰LÐMÐX\ˆLÖ]ð	^ús$   ÁC- ÂD Ã- DÄDÄ D6Ä5D6Úceilingc                 óX   — t        | dd«      }t        |«      r |d|d›d|d›d�«       yy)zVCommit-phase ceiling breach: the SessionDB mutation must complete, so only surface it.r4   Nu9   âš  Context compression commit is taking unusually long (z.0fzs, ceiling uj   s). Waiting for it to finish safely â€” if this persists, check SessionDB health (disk / lock contention).)r   r8   )r"   r&   r?   r<   s       r   Ú_warn_commit_overrunrA   c   sF   € ä�5˜/¨4Ó0€DÜ�„~ÙØGÈÈsÀ|ÐS^Ð_fÐgjÐ^kð luð uõ	
ð r   c                 óÄ   — ddl m} ddlm} t	        | t
        «      rt	        |t
        «      sy|D ].  }t	        |t        «      sŒ|j                  |«      sŒ& || |«       Œ0 y)aR  Mirror ``_DB_PERSISTED_MARKER`` stamps from the worker's snapshot onto a live list.
    Matched by scoped identity; timestamp-less repeated content is ambiguous, so every scoped match is
    stamped. Imported UNCONDITIONALLY: a silent fallback literal would split the stamping key from the flush's
    and resurrect the duplicate-row bug.r   )Ú_DB_PERSISTED_MARKER)Ú_stamp_scoped_twinsN)Úagent.context_compressorrC   r6   rD   Ú
isinstanceÚlistÚdictÚget)Útarget_messagesÚsource_messagesrC   rD   Úsource_messages        r   Ú_sync_persisted_markersrM   m   sT   € õ
 >ÝBÜ�o¤tÔ,´J¸ÔPTÔ4UØØ)ò AˆÜ�n¤dÕ+°×0BÑ0BÐCWÕ0XÙ °Õ@ñAr   )Úapprox_tokensc                óæ   ‡ ‡‡‡‡‡‡‡‡— ddl mŠm}
m} dddœˆˆfd„}t	        j
                  |d¬«      }dddœŠˆfd„}ˆ ˆˆfd	„}ˆˆ ˆˆfd
„} ||‰ˆ ˆfd„|‰||ˆ fd„|‰ || |
‰ |	«      du ¬«      S )u˜  Run ``run(fence, target_messages=snapshot)`` on the pool under the progress-aware timeout.
    The pooled worker must NEVER share the caller's live transcript â€” a late engine after a host timeout could
    rewrite it. It deep-snapshots on the worker and publishes only via an ADMITTED commit; a no-op/abort
    returns the snapshot unchanged, so the ORIGINAL list is handed back to keep identity semantics.r   )ÚCompressionCommitFenceÚrequest_exceeds_model_windowÚ*run_compress_context_with_progress_timeoutF)Úsame_turn_fallback_recoveryc                ób   •— t        j                  ‰«      } ‰| ||¬«      \  }}||u r‰|fS ||fS )N)rJ   rS   )ÚcopyÚdeepcopy)r   rS   ÚsnapshotÚresult_msgsÚresult_promptÚmessagesÚruns        €€r   Ú_snapshot_workerz5_run_under_progress_timeout.<locals>._snapshot_worker‡   sH   ø€ ô —=‘= Ó*ˆÙ%(Ø 8ÐIdô&
Ñ"ˆ�]ð (¨8Ñ3�À}ÐTÐT¸À}ÐTÐTr   T©r)   r*   c                 ó,   •— ‰j                  | |¬«       y )Nr]   )Úupdate)r)   r*   Útimeout_causes     €r   Ú_on_timeout_causez6_run_under_progress_timeout.<locals>._on_timeout_causež   s   ø€ Ø×Ñ¨_ÐPaÐÕbr   c                 ó(   •— t        ‰f| ||‰dœ‰¤Ž y )N)r%   r&   r'   r(   )r>   )r%   r&   r'   r"   r`   r(   s      €€€r   Ú_on_timeoutz0_run_under_progress_timeout.<locals>._on_timeout¡   s%   ø€ Ü#Øð	
Ø V¸NÐZgñ	
Økxó	
r   c                  ó°   •—  ‰«       } ‰5  | ‰_         t        ‰«      j                  d«      xs d}|r|d   ‰u r| ‰_        d d d «       | S # 1 sw Y   | S xY w)NÚ_compression_commit_fence_stackr   éÿÿÿÿ)r   ÚvarsrI   Ú _active_compression_commit_fence)Úretry_fenceÚstackrP   r"   Úfence_registration_lockÚregistrations     €€€€r   Ú_publish_new_fencez7_run_under_progress_timeout.<locals>._publish_new_fence¦   si   ø€ ñ -Ó.ˆØ$ñ 	EØ!,ˆLÔÜ˜“K—O‘OÐ$EÓFÒLÈ"ˆEÙ˜˜r™ lÑ2Ø9D�Ô6÷		Eð
 Ð÷	Eð
 Ðús   ‹6AÁAc                  ó   •— t        ‰ ‰«      S r
   )r$   )r"   r   s   €€r   ú<lambda>z-_run_under_progress_timeout.<locals>.<lambda>´   s   ø€ Ô'?ÀÀ~Ó'V€ r   c                 ó   •— t        ‰| |«      S r
   )rA   )r&   r?   r"   s     €r   ro   z-_run_under_progress_timeout.<locals>.<lambda>·   s   ø€ Ô2FÀuÈfÐV]Ó2^€ r   )ÚworkerrZ   Úsystem_prompt_fallbackÚidle_timeout_secondsÚtotal_ceiling_secondsÚ
on_timeoutÚon_timeout_causeÚon_commit_overrunr   Útelemetry_agentÚ	new_fenceÚfallback_workerÚrequest_exceeds_windowr
   )r6   rP   rQ   rR   Ú	functoolsÚpartial)r"   r[   rZ   r   Úactive_fencerl   rk   Úidle_timeoutr(   rN   rQ   rR   r\   Ú_same_turn_fallback_workerra   rc   rm   rP   r`   s   ```` `` `        @@r   Ú_run_under_progress_timeoutr�   {   sŽ   ÿø€ ÷ñ ðUÀE÷ Uô& "+×!2Ñ!2Ð3CÐaeÔ!fÐà(-ÀEÑJ€Môcö
÷

ñ 6Ø¨(ÜVØ)ÀÐ[fØ*Û^ÐfrØÐ);ÐMgÙ;¸EÀ=ÓQÐUYÐYôð r   Údirect_pathc                óÜ   — t        |t        «      r|rt        |d   t        «      sy|d   }|s||urt        ||«       t	        | dd«      }t        |t        «      r||urt        ||«       yyy)zJMirror persisted-marker stamps from the result list onto the live list(s).r   NÚ_session_messages)rF   ÚtuplerG   rM   r   )r"   ÚresultrZ   r‚   Úresult_messagesÚsession_messagess         r   Ú_mirror_result_onto_live_listsr‰   ½   sr   € ä�vœuÔ%©&´ZÀÀqÁ	Ì4Ô5PØØ˜Q‘i€Oá�o¨XÑ5Ü ¨/Ô:Ü˜uÐ&9¸4Ó@ÐÜÐ"¤DÔ)Ð.>ÀhÑ.NäÐ 0°/ÕBð /OÐ)r   c                 ó(  — t        j                  t        «      5  ddlm}  || j
                  «       ddd«       	 ddlm} | j
                  r || j
                  «       yy# 1 sw Y   Œ0xY w# t        $ r t        j                  dd¬«       Y yw xY w)zãPropagate a rotated session id to the CALLER's thread/ContextVar (idempotent otherwise).
    The worker thread rotated hermes_logging's thread-local id; post-compression tools must resolve
    HERMES_SESSION_ID to the child id.r   )Úset_session_contextN)Úset_current_session_idz1post-compression session ContextVar rebind failedTr   )
Ú
contextlibÚsuppressr   Úhermes_loggingr‹   Ú
session_idÚgateway.session_contextrŒ   r    r!   )r"   r‹   rŒ   s      r   Ú_rebind_caller_session_contextr’   Ë   s�   € ô 
×	Ñ	œYÓ	'ñ .Ý6Ù˜E×,Ñ,Ô-÷.ðYÝBØ×ÒÙ" 5×#3Ñ#3Õ4ð ÷.ð .ûô ò YÜ�‰ÐHÐSWˆÖXðYús   šA"¼$A. Á"A+Á. BÂBc                   óN   — e Zd ZdZddddddddœdededed	ed
ededededefd„Z	y)ÚCompressionFacadeMixinz-``_compress_context`` (see module docstring).NÚdefaultF©rN   Útask_idÚfocus_topicÚforceÚbypass_cooldownÚ!defer_context_engine_notificationÚcommit_fencerZ   r   rN   r—   r˜   r™   rš   r›   r   c                óh  ‡ ‡‡‡‡‡‡‡‡‡"— ddl m}
mŠ"m}m}  |‰ «       ddlm}m}m}m	}m
}m} ddlm} d} |«       €‰ j                  «       }|r ||«      }d} |«       € |‰ «      }|r ||«      }|	xs  |
«       }t        ‰ «      j!                  dt#        j$                  «       «      }t'        |«      }	 |5  t        ‰ «      j!                  dg «      }|j)                  |«       |‰ _        ddd«       dˆˆˆ"ˆˆˆˆˆ ˆˆf
d„	}|	du}|s |«       \  }}|dk  }|r	 ||«      } nt-        ‰ |‰‰|||‰¬	«
      } t/        ‰ | ‰|¬
«       t1        ‰ «       | |5  t        ‰ «      j3                  d«      xs d}t5        t7        |«      dz
  dd«      D ]  }!||!   |u sŒ||!=  n |r|d   j8                  ‰ _        nt        ‰ «      j;                  dd«       ddd«       |� ||«       |�	 ||«       S S # 1 sw Y   �ŒxY w# 1 sw Y   Œ,xY w# |5  t        ‰ «      j3                  d«      xs d}t5        t7        |«      dz
  dd«      D ]  }!||!   |u sŒ||!=  n |r|d   j8                  ‰ _        nt        ‰ «      j;                  dd«       ddd«       n# 1 sw Y   nxY w|� ||«       |�	 ||«       w w xY w)u
  Forwarder â€” see ``agent.conversation_compression.compress_context``.
        ``force=True`` (manual /compress) bypasses the summary-failure cooldown; ``bypass_cooldown=True``
        (provider-proven overflow recovery) runs one real attempt while the cooldown stays armed.

        ``force=True`` is passed by the manual ``/compress`` slash command so users can bypass the
        summary-failure cooldown after an auto-compress abort. Auto-compress callers use the default
        ``force=False``. See #100661.
        r   )rP   Úcompress_contextÚ)reset_context_compression_timeout_outcomeÚ$resolve_context_compression_timeouts)Úget_affinity_scopeÚget_conversation_contextÚreset_affinity_scopeÚreset_conversation_contextÚset_affinity_scopeÚset_conversation_context)Ú declared_conversation_scope_safeNÚ_compression_commit_fence_lockre   c                 ó8   •
—  ‰‰
|�|n‰	‰‰‰‰‰‰xs |‰| ¬«
      S )Nr–   r   )r   rJ   rS   rN   rš   rž   r›   r˜   r™   rZ   r   r   r—   s      €€€€€€€€€€r   Ú_runz6CompressionFacadeMixin._compress_context.<locals>._run  s8   ø€ Ù'Ø¨_Ð-H™/ÈhÐXfØ"/¸ÈkÐafØ$3Ò$RÐ7RØ7XÐhmô	ð r   )r~   rl   rk   r   r(   rN   )r‚   r   é   rf   rh   )NNF)r6   rP   rž   rŸ   r    Úagent.portal_tagsr¡   r¢   r£   r¤   r¥   r¦   Úagent.prompt_cache_scoper§   Ú_conversation_root_idrg   Ú
setdefaultÚ	threadingÚRLockr   Úappendrh   r�   r‰   r’   rI   ÚrangeÚlenr   Úpop)#r   rZ   r   rN   r—   r˜   r™   rš   r›   rœ   rP   rŸ   r    r¡   r¢   r£   r¤   r¥   r¦   r§   ÚtokenÚrootÚaffinity_tokenÚdeclaredr~   rk   rl   Úfence_stackrª   r‚   r   r(   r†   Úidxrž   s#   `````````                         @r   Ú_compress_contextz(CompressionFacadeMixin._compress_contextÝ   s  ÿù€ ÷&	
ó 	
ñ 	2°$Ô7÷	
÷ 	
õ 	Nð ˆÙ#Ó%Ð-Ø×-Ñ-Ó/ˆDÙÙ0°Ó6�ð ˆÙÓÐ'Ù7¸Ó=ˆHÙÙ!3°HÓ!=�ð $Ò?Ñ'=Ó'?ˆÜ"& t£*×"7Ñ"7Ð8XÔZc×ZiÑZiÓZkÓ"lÐÜ/°Ó=ˆð5	5Ø(ñ EÜ" 4›j×3Ñ3Ð4UÐWYÓZ�Ø×"Ñ" <Ô0Ø8D�Ô5÷E÷
ö ð '¨dÐ2ˆKÙÙ.RÓ.TÑ+�˜mØ*¨aÑ/�ÙÙ˜lÓ+‘ä4Ø˜$ ¨.Ø!-¸LØ,CØ!-¸]ÐZgô	�ô +¨4°¸È{Õ[Ü*¨4Ô0Øð )ñ Mô # 4›jŸn™nÐ-NÓOÒUÐSU�Ü ¤ [Ó!1°AÑ!5°r¸2Ó>ò �CØ" 3Ñ'¨<Ò7Ø'¨Ð,Ùðñ Ø<GÈ¹O×<QÑ<Q�DÕ9ä˜“J—N‘NÐ#EÀtÔL÷Mð Ð Ù*¨5Ô1ØÐ)Ù$ ^Õ4ð *÷gEñ Eú÷HMð MûÐ(ñ Mô # 4›jŸn™nÐ-NÓOÒUÐSU�Ü ¤ [Ó!1°AÑ!5°r¸2Ó>ò �CØ" 3Ñ'¨<Ò7Ø'¨Ð,Ùðñ Ø<GÈ¹O×<QÑ<Q�DÕ9ä˜“J—N‘NÐ#EÀtÔL÷M÷ Mñ Múð Ð Ù*¨5Ô1ØÐ)Ù$ ^Õ4ð *úsW   Â7H Â94G/Ã-A'H ÅAG<Æ8G<Ç/G9Ç4H Ç<H	ÈJ1ÈAJÉ8JÊ	J1ÊJÊJ1)
r   r   r   r   rG   ÚstrÚintÚboolr…   r¼   r   r   r   r”   r”   Ú   sv   „ Ù7ð LPÐ`iØ¨uÈeØ27Àdòh5Øðh5Ø.1ðh5ØEHðh5ØZ]ðh5àðh5à(,ðh5àGKðh5ð ,0ðh5ð 
ô	h5r   r”   r   )r   r�   rU   r|   Úloggingr°   Úagent.session_activityr   Ú	getLoggerr    r   r½   r$   Úfloatr¿   r>   rA   rM   r�   r‰   r’   r”   r   r   r   ú<module>rÄ      sã   ðñó Û Û Û Û å 5ð 
ˆ×	Ñ	˜;Ó	'€÷ñ ð
$°Cð 
$¸Có 
$ð0
Øð0
Ø#(ð0
Ø:?ð0
ØPUð0
Øhlð0
àð0
ð 
ó0
ðf
¨ð 
¸ð 
À$ó 
óAð  04ô?ðDCÈDð CÐUYó CóY÷k5ò k5r   