Ë
    áß²j° ã                  ó   — U d Z ddlmZ ddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddl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 ddlmZ ddlmZmZmZmZmZmZmZ ddlmZ ddlm Z m!Z! dd	l"m#Z# dd
l$m%Z%m&Z& ddl'm(Z(m)Z) ddl*m+Z+ ddl,m-Z.  ej^                  e0«      Z1ejd                  ddœdìd„«       Z3 e4e(jj                  e(jl                  h«      Z7dZ8dZ9de9› d�Z:de9› d�Z;dZ<díd„Z=dîd„Z>dZ?dZ@dZAdZBdZCdZDdZEd ZFe:e;e<e?j�                  d!¬"«      e@j�                  d#d$¬%«      eAj�                  d&d#¬'«      eBj�                  d(d)d*¬+«      eCj�                  d,d-¬.«      eDj�                  d(d#¬.«      eEj�                  d#d(¬/«      f
ZHdïd0„ZIdðd1„ZJd2ZKd3ZLdñd4„ZM ejœ                  «       ZO ej                   d5d¬6«      ZQd7eRd8<   dòd9„ZSdód:„ZTdôd;„ZUdõd<„ZVdöd=„ZWd÷d>„ZXdød?„ZYdùd@„ZZdôdA„Z[	 	 	 	 	 	 	 	 	 	 dúdB„Z\ddddCœ	 	 	 	 	 	 	 	 	 	 	 dûdD„Z]	 	 	 	 	 	 düdE„Z^ G dF„ dG«      Z_dHZ`dIZadJZbdac ejœ                  «       ZddKZedLZfdýdM„ZgdNZh ejœ                  «       ZidajdðdO„ZkdþdÿdP„ZldQ„ Zmdþ�d dR„ZnddSœ	 	 	 	 	 	 	 �ddT„Zo�ddU„Zp	 	 	 	 	 	 	 	 	 	 	 	 �ddV„Zq�ddW„Zr�ddX„Zs�ddY„Zt�ddZ„Zudddddd[œ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dd\„Zv	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �d	d]„Zw	 	 	 	 	 	 	 	 	 	 	 	 �d
d^„Zx	 	 	 	 	 	 	 	 	 	 �dd_„Zy�dd`„Zz	 	 	 	 	 	 	 	 	 	 �dda„Z{ddddddbddddcœ		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �ddd„Z| G de„ dfe}«      Z~dgZ�ddh„Z€�ddi„Z��ddj„Z‚dîdk„Zƒ�ddl„Z„dbdmœ�ddn„Z…�ddo„Z†dddpœ	 	 	 	 	 	 	 	 	 	 	 	 	 �ddq„Z‡�ddr„Zˆ�dds„Z‰�ddt„ZŠ�ddu„Z‹�ddv„ZŒ	 	 	 	 	 	 �ddw„Z��ddx„ZŽdîdy„Z�dîdz„Z��dd{„Z‘dbdmœ�dd|„Z’�dd}„Z“�dd~„Z”�dd„Z•	 	 	 	 	 	 	 	 �dd€„Z–�d d�„Z—�d!d‚„Z˜�ddƒ„Z™dd„œ	 	 	 	 	 	 	 	 	 	 	 	 	 �d"d…„Zš G d†„ d‡«      Z›�d#dˆ„Zœ G d‰„ dŠ«      Z��d$d‹„Zž	 	 	 	 	 	 	 	 	 	 	 	 �d%dŒ„ZŸ�d&d�„Z dîdŽ„Z¡dîd�„Z¢�d'd�„Z£dîd‘„Z¤	 dþ	 	 	 	 	 	 	 �d(d’„Z¥d“Z¦�d)d”„Z§d•Z¨�d*d–„Z©d—Zªd˜Z«�d+d™„Z¬�d*dš„Z­�d,d›„Z®�d-dœ„Z¯�d.d�„Z°�d/dž„Z±�d0dŸ„Z²d Z³�d1d¡„Z´�d2d¢„Zµed£   Z¶�d3d¤„Z·�d4d¥„Z¸�d5d¦„Z¹dd§œ�d6d¨„Zºd©Z»�d7dª„Z¼�d8d«„Z½�d9d¬„Z¾ G d­„ d®«      Z¿ G d¯„ d°«      ZÀ�d:d±„ZÁ	 dþ	 	 	 	 	 	 	 	 	 	 	 	 	 �d;d²„ZÂ�d<d³„ZÃ	 	 	 	 	 	 	 	 	 	 	 	 	 	 �d=d´„ZÄ	 	 	 	 	 	 	 	 	 	 	 	 	 	 �d>dµ„ZÅ	 	 	 	 	 	 	 	 	 	 �d?d¶„ZÆ�d@d·„ZÇ�dAd¸„ZÈ	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dBd¹„ZÉ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dCdº„ZÊ�dDd»„ZË�dd¼„ZÌ	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dEd½„ZÍ�dd¾„ZÎ�dFd¿„ZÏ�dGdÀ„ZÐ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dHdÁ„ZÑdîdÂ„ZÒdÃdbdÄœ�dIdÅ„ZÓ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dJdÆ„ZÔ	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dKdÇ„ZÕe�j¬                   G dÈ„ dÉ«      «       Z×	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dLdË„ZØe�j¬                   G dÌ„ dÍ«      «       ZÙ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dMdÎ„ZÚe�j¬                   G dÏ„ dÊ«      «       ZÛ�dNdÐ„ZÜ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dOdÑ„ZÝ	 	 	 	 	 	 	 	 	 	 	 	 �dPdÒ„ZÞddÓddddddÔœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 �dQdÕ„Zß�dRdÖ„Zà�dSd×„ZáddÓddØœ	 	 	 	 	 	 	 	 	 	 	 	 	 �dTdÙ„ZâdÚZãdÛdÜdÝdÞdÞdßdàœZä�dU�dVdá„Zå�dWdâ„Zæ�dXdã„Zç�dYdä„Zè�dZdå„Zédædçœ�d[dè„Zêg dé¢Zë G dê„ dëe}«      Zìy(\  aÜ  Context compression: feasibility probe, warning replay, compress, image fix.

Thread-safety contract for extension points: with ``compression.context_timeout_seconds > 0`` (default) the
whole pass, context engines and memory providers included, runs on a pooled daemon thread. Calls may arrive
on any pooled thread (never rely on thread-affinity/locals); the message list is a private deep snapshot
(in-place mutation is invisible to the live conversation unless the pass commits); state is published ONLY
on an admitted :class:`CompressionCommitFence` commit (work still running after a host timeout is discarded);
one pass per session at a time (durable lock) but sessions run concurrently, so shared engines must be thread-safe.
é    )ÚannotationsN)Údatetime)ÚPath)ÚAnyÚCallableÚDictÚListÚLiteralÚOptionalÚTuple)ÚAuxiliaryExplicitCancellation)Ú#automatic_compaction_status_messageÚsanitize_memory_context)Ú#PRE_COMPRESS_CHECKPOINT_API_VERSION)Úestimate_messages_tokens_roughÚestimate_request_tokens_rough)ÚActivityProvenanceÚnormalize_activity_provenance)Úset_usage_anchor)Únew_session_idF©Úexc_infoc             #  ó¬   K  — 	 d–— y# t         $ r?}|rt        j                  | d¬«      nt        j                  | |«       Y d}~y Y d}~yd}~ww xY w­w)zLRun a best-effort block; on Exception log ``message`` at DEBUG and continue.NTr   )Ú	ExceptionÚloggerÚdebug)Úmessager   Úexcs      úC/home/ubuntu/.hermes/hermes-agent/agent/conversation_compression.pyÚ_swallowr    *   sF   è ø€ ðYÜøÜò YÙ08Œ�‰�W tˆÔ,¼f¿l¹lÈ7ÐTW×>XÑ>XÕ,ûðYüs6   ‚A„	 ˆA‰	A’/AÁAÁAÁAÁAÁAé<   zCompacting contextu   ðŸ—œï¸� u:    â€” summarizing earlier conversation so I can continue...u@    â€” still summarizing earlier conversation so I can continue...u6   âœ“ Context compaction complete â€” continuing turn...c                óè   — ddl m} t        | t        «      s| S | D ���cg c]>  }t        |t        «      r*|j                  «       D ��ci c]  \  }}||k7  sŒ||“Œ c}}n|‘Œ@ c}}}S c c}}w c c}}}w )a  Copy ``msgs`` with the ``_db_persisted`` marker removed for no-op comparison.
    Live dicts carry the marker while ``compress()`` output is swept, so a raw ``==`` would misclassify an
    identical no-op copy as progress. Non-list inputs and non-dict entries pass through unchanged.r   ©Ú_DB_PERSISTED_MARKER)Úagent.context_compressorr$   Ú
isinstanceÚlistÚdictÚitems)Úmsgsr$   ÚmÚkÚvs        r   Ú_strip_marker_for_comparisonr.   J   sc   € õ >Ü�dœDÔ!ØˆØmq×rÐrÐhiÌÐTUÔW[ÔI\˜aŸg™g›i×E‘d�a˜¨1Ð0DÓ+DˆQ�‰TÔEÐbcÑcÔrÐrùÓEùÔrs   Ÿ(A-ÁA'ÁA'ÁA-Á'A-c                ó‚   — t        | dd«      }|syt        dd¬«      5   |dt        «       ddd«       y# 1 sw Y   yxY w)z;Emit the structured terminal edge for a started compaction.Ústatus_callbackNz.status_callback error in compaction completionTr   Ú	compacted)Úgetattrr    ÚCOMPACTION_DONE_STATUS)Úagentr0   s     r   Ú_emit_compaction_doner5   T   sB   € ä˜eÐ%6¸Ó=€OÙØÜ	ÐBÈTÔ	Rñ =Ù˜Ô%;Ô<÷=÷ =ñ =ús   ž5µ>ur   ðŸ“¦ Pre-API compression: ~{tokens:,} tokens near the context/output limit. Compacting before the next model call.ub   ðŸ“¦ Preflight compression: ~{tokens:,} tokens >= {threshold:,} threshold. This may take a moment.u\   ðŸ’¤ Resumed after {idle_seconds}s idle â€” compacting ~{tokens:,} tokens before continuing.uS   ðŸ—œï¸� Context too large (~{tokens:,} tokens) â€” compressing ({attempt}/{cap})...u=   ðŸ—œï¸� Compressed {before} â†’ {after} messages, retrying...uA   ðŸ—œï¸� Compressed ~{before:,} â†’ ~{after:,} tokens, retrying...uL   ðŸ—œï¸� Context reduced to {new_ctx:,} tokens (was {old_ctx:,}), retrying...uè   âš  Context is over the compression threshold (~{tokens:,} tokens >= {threshold:,}) but compression is currently blocked ({reason}). The model may stop responding. Run /new to start a fresh session or /compress to retry immediately.i@â )ÚtokensiÀÔ i † )r6   Ú	thresholdi  )Úidle_secondsr6   i�Ð é   é   )r6   ÚattemptÚcapé   é   )ÚbeforeÚafter)Únew_ctxÚold_ctxc                óÄ   — t        | t        «      r| j                  «       nd}|syt        |v ry|t        k(  ry|j                  «       }d|v sd|v ryd|v xs
 d|v xs d|v S )	a=  True for in-progress auto-compaction lifecycle lines (not the done edge).
    The gateway re-tags matches as ``kind="compacting"`` for the whole pause; matching only the marker left
    idle/preflight/retry lines looking hung. ``COMPACTION_DONE_STATUS`` is emitted as ``kind="compacted"`` and
    must not match here.Ú FTzcompaction completez compression is currently blockedÚcompactÚcompresszcontext reduced to)r&   ÚstrÚstripÚCOMPACTION_STATUS_MARKERr3   Úlower)ÚtextÚbodyÚlowereds      r   Úis_compaction_progress_statusrN   Œ   sw   € ô
 & d¬CÔ0ˆ4�:‰:Œ<°b€DÙØÜ 4Ñ'ØØÔ%Ò%ØØ�j‰j‹l€Gà Ñ'Ð+MÐQXÑ+XØØ˜ÐÒ[ :°Ð#8Ò[Ð<PÐT[Ð<[Ð[ó    c                óz   — ddl m}  || d¬«      }|rt        j                  dt	        |«      «       t        |«      S )zÌRebuild agent.tools at the compaction commit boundary (the only moment config reaches a forever-session's
    frozen tool schemas; the prompt cache is already invalid). Returns True when tools were added.r   )Úrefresh_agent_mcp_toolsT)Úcontent_awarez'Compaction tool refresh added tools: %s)Útools.mcp_tool_agentrQ   r   ÚinfoÚsortedÚbool)r4   rQ   Úaddeds      r   Ú_refresh_agent_tool_definitionsrX   Ÿ   s3   € õ =Ù# E¸Ô>€EÙÜ�‰Ð=¼vÀe»}ÔMÜ�‹;ÐrO   )Ú_previous_summaryÚ_summary_has_user_turnÚcompression_countÚ_last_compression_savings_pctÚ_ineffective_compression_countÚ_anti_thrash_recovery_deadlineÚ_fallback_compression_streakÚ$_verify_compaction_cleared_thresholdÚ_last_compression_made_progressÚ_summary_failure_cooldown_untilÚ_cooldown_persist_failedÚ_last_summary_errorÚ_consecutive_timeout_failuresÚ _consecutive_truncation_failuresÚ_last_summary_dropped_countÚ_last_summary_fallback_usedÚ_last_compress_abortedÚ_last_summary_auth_failureÚ_last_summary_network_failureÚ#_last_summary_empty_content_failureÚ_last_summary_truncated_failureÚ_last_summary_overload_failureÚ_last_aux_model_failure_errorÚ_last_aux_model_failure_modelÚ_last_aux_resolved_modelÚ_summary_model_fallen_backÚsummary_modelÚ_last_compression_telemetryÚ_active_compression_telemetryÚ_compression_telemetry_seedÚ_proactive_prune_rearm_tokens)rb   rd   rc   c                ó¨   — 	 t        | «      }t        D �ci c]  }||v sŒ|||   “Œ }}t        j                  |«      S # t        $ r i cY S w xY wc c}w )zåCopy only the mutable bookkeeping owned by one compression attempt.
    The allow-list avoids copying clients, DB handles, locks and plugin resources; missing fields are ignored
    so legacy/third-party compressors keep working.)ÚvarsÚ	TypeErrorÚ _COMPRESSOR_ATTEMPT_STATE_FIELDSÚcopyÚdeepcopy)Ú
compressorÚvaluesÚnameÚselecteds       r   Ú"_snapshot_compressor_attempt_stater‚   »   sb   € ðÜ�jÓ!ˆô 0PÖb tÐSWÐ[aÒSa��f˜T‘lÑ"Ðb€HÐbô �=‰=˜Ó"Ð"øô ò ØŠ	ðüâbs   ‚> •	AŸA¾AÁAÚ$hermes_compressor_attempt_generation)Údefaultzcontextvars.ContextVar[Any]Ú_COMPRESSOR_ATTEMPT_GENERATIONc                óì   — t         5  t        | dd«      }|€t        j                  «       }	 || _        |cddd«       S # t
        $ r  t        j                  «       cY cddd«       S w xY w# 1 sw Y   yxY w)aû  Per-compressor lock serializing the durable cooldown rollback against claims. The process-wide
    claim lock must stay cheap (every compressor in a gateway shares it), so the slow SQLite write in
    ``_restore_compressor_attempt_state`` is fenced by THIS lock instead; ``_claim_compressor_attempt``
    takes it first so a claim on that compressor waits for the restore while other compressors proceed.
    A slotted/frozen compressor that cannot hold the attribute gets a no-op (its guard is off anyway).Ú _compression_attempt_serial_lockN)Ú_COMPRESSOR_ATTEMPT_LOCKr2   Ú	threadingÚLockr‡   r   Ú
contextlibÚnullcontext)r~   Úlocks     r   Ú_compressor_attempt_serial_lockrŽ   æ   s}   € ô 
"ñ Ü�zÐ#EÀtÓLˆØˆ<Ü—>‘>Ó#ˆDð0Ø>B�
Ô;ð ÷ñ øô ò 0Ü!×-Ñ-Ó/Ñ/÷ñ ð0ú÷ð ús+   ‡$A*¬>³A*¾A'ÁA*Á&A'Á'A*Á*A3c           	     ó  — t        | «      5  t        5  t        t        | dd«      xs d«      dz   }	 || _        |cddd«       cddd«       S # t
        $ r Y ddd«       ddd«       yw xY w# 1 sw Y   nxY wddd«       y# 1 sw Y   yxY w)zâClaim the compressor for a new attempt; return its monotonic generation id.
    Restores or cancelled-check mutations stamped with an OLDER generation no-op, so a detached late attempt
    cannot clobber its successor's state.Ú_compression_attempt_generationr   r9   N)rŽ   rˆ   Úintr2   r�   r   ©r~   Ú
generations     r   Ú_claim_compressor_attemptr”   ÷   s™   € ô 
)¨Ó	4ñ Ô6Nñ Üœ Ð-NÐPQÓRÒWÐVWÓXÐ[\Ñ\ˆ
ð	Ø9CˆJÔ6ð ÷÷ ò øô ò 	Ø÷÷ ð ð	ú÷	ð ú÷ ÷ ñ úsI   ŒB“A,²A¹A,º	BÁ	A)ÁA,ÁBÁ(A)Á)A,Á,A5	Á1BÂB
c                óz   — |syt         5  t        t        | dd«      xs d«      |k(  cddd«       S # 1 sw Y   yxY w)zETrue when *generation* still owns the compressor (or guard disabled).Tr�   r   N)rˆ   r‘   r2   r’   s     r   Ú_compressor_attempt_is_currentr–     sB   € áØÜ	!ñ aÜ”7˜:Ð'HÈ!ÓLÒQÐPQÓRÐV`Ñ`÷a÷ aò aús   Š1±:c                ó¤   — t         5  t        j                  t        «      5  || _        ddd«       ddd«       y# 1 sw Y   ŒxY w# 1 sw Y   yxY w)aX  Publish the generation of the attempt that is ACTUALLY running summary work.

    The entry claim is taken before the breaker gates and the per-session lock, so no-op
    entries (lock sit-outs, transient gates) bump ``_compression_attempt_generation``
    without doing any work. Candidate supersession must key on this separate marker,
    published only when the summary dispatch begins, or those no-op claims discard a
    completed candidate and compression livelocks. Slotted/frozen compressors that
    cannot hold the attribute keep the entry-generation check as a conservative fallback.
    N)rˆ   r‹   Úsuppressr   Ú'_compression_working_attempt_generationr’   s     r   Ú _mark_compressor_working_attemptrš     sU   € ô 
"ñ LÜ× Ñ ¤Ó+ñ 	LØAKˆJÔ>÷	L÷Lð L÷	Lð 	Lú÷Lð Lús   ‡A¡:©AºA	¿AÁAc                ó.   — t        | «      s
t        «       ‚y)zäUnwind the CALLING attempt (its generation rides the ContextVar) as a cancellation when a newer
    attempt has since begun summary work on *compressor*, so none of the shared-state writes that
    follow the call site can land.N)Ú_caller_attempt_is_currentr   ©r~   s    r   Ú_raise_if_stale_attemptrž     s   € ô & jÔ1Ü+Ó-Ð-ð 2rO   c                ó>   — t        | t        j                  «       «      S )u`   Working-attempt check for the calling attempt's own generation (ContextVar; None â†’ unguarded).)Ú_working_attempt_is_currentr…   Úgetr�   s    r   rœ   rœ   #  s   € ä& zÔ3Q×3UÑ3UÓ3WÓXÐXrO   c                óØ   — |syt         5  t        | dd«      }|€&t        t        | dd«      xs d«      |k(  cddd«       S t        |«      t        |«      k(  cddd«       S # 1 sw Y   yxY w)zñTrue when *generation* is still the last attempt that began summary work.

    Without a published marker (attribute-less compressor, or the attempt never reached
    dispatch) supersession falls back to the entry-generation ownership check.Tr™   Nr�   r   )rˆ   r2   r‘   )r~   r“   Úmarkers      r   r    r    (  sq   € ñ
 ØÜ	!ñ .Ü˜Ð%NÐPTÓUˆØˆ>Ü”w˜zÐ+LÈaÓPÒUÐTUÓVÐZdÑd÷.ñ .ô �6‹{œc *›oÑ-÷	.÷ .ò .ús   Š,A Á A Á A)c                ó²   — t         5  t        j                  t        «      5  || _        || _        ddd«       ddd«       y# 1 sw Y   ŒxY w# 1 sw Y   yxY w)zDInstall the F4 cancellation consult, stamped with its owner attempt.N)rˆ   r‹   r˜   r   Ú_compression_cancelled_checkÚ"_compression_cancelled_check_owner)r~   Úcheckr“   s      r   Ú$_install_compression_cancelled_checkr¨   6  s[   € ä	!ñ GÜ× Ñ ¤Ó+ñ 	GØ6;ˆJÔ3Ø<FˆJÔ9÷	G÷Gð G÷	Gð 	Gú÷Gð Gús!   ‡A¡A°AÁA
	ÁAÁAc                óô   — t         5  t        | dd«      }|�|r||k7  r
	 ddd«       yt        j                  t        «      5  d| _        d| _        ddd«       	 ddd«       y# 1 sw Y   ŒxY w# 1 sw Y   yxY w)z²Clear the cancellation consult only when *generation* installed it.
    Prevents a detached late primary from tearing down a newer fallback's callback. Returns True when cleared.r¦   NFT)rˆ   r2   r‹   r˜   r   r¥   r¦   )r~   r“   Úowners      r   Ú+_clear_compression_cancelled_check_if_ownerr«   >  sŠ   € ô 
"ñ Ü˜
Ð$HÈ$ÓOˆØÐ¡°¸Ò0CØ÷ð ô × Ñ ¤Ó+ñ 	AØ6:ˆJÔ3Ø<@ˆJÔ9÷	Að ÷ð ÷	Að 	Aú÷	ð ús(   ‡A.¨A.ÁA"Á	A.Á"A+	Á'A.Á.A7c           	     óÀ  — t        | «      j                  d«      }t        | «      j                  d«      }|�|sy|du rLt        t        |«      dd«      }t	        |«      r|€t        d«      ‚ |||t        j                  |«      «       yt        dd¬«      5  t        |d	   xs d
«      }t        d
|t        j                  «       z
  «      }|dkD  rQt        t        |«      dd«      }	t	        |	«      rZ |	||t        j                  «       |z   |j                  d«      «       n*t        t        |«      dd«      }
t	        |
«      r	 |
||«       ddd«       y# 1 sw Y   yxY w)zäRecreate/clear the durable cooldown row from the attempt snapshot.
    Authoritative captures use the exact raw-row restore API (verifies read-back, propagates failure); the
    legacy path re-derives deadline/error best-effort.Ú_session_dbÚ_session_idNTÚ(restore_compression_failure_cooldown_rowz6exact compression cooldown rollback API is unavailablez0compression cooldown persistence rollback failedr   rb   ç        r   Ú#record_compression_failure_cooldownrd   Ú"clear_compression_failure_cooldown)ry   r¡   r2   ÚtypeÚcallableÚRuntimeErrorr|   r}   r    ÚfloatÚmaxÚtimeÚ	monotonic)r~   ÚsnapshotÚauthoritativeÚdurable_stateÚ
session_dbÚ
session_idÚrestorerÚdeadlineÚ	remainingÚrecorderÚclearers              r   Ú_rollback_durable_cooldownrÄ   K  sB  € ô �jÓ!×%Ñ% mÓ4€JÜ�jÓ!×%Ñ% mÓ4€JØÐ¡ØØ˜ÑÜœ4 
Ó+Ð-WÐY]Ó^ˆÜ˜Ô! ]Ð%:ÜÐWÓXÐXÙ�˜Z¬¯©°}Ó)EÔFØÜ	ÐDÈtÔ	Tñ 
0Ü˜Ð"CÑDÒKÈÓLˆÜ˜˜X¬¯©Ó(8Ñ8Ó9ˆ	Ø�qŠ=Üœt JÓ/Ð1VÐX\Ó]ˆHÜ˜Ô!Ù˜ Z´·±³¸yÑ1HÈ(Ï,É,ÐWlÓJmÕnäœd :Ó.Ð0TÐVZÓ[ˆGÜ˜Ô Ù˜
 JÔ/÷
0÷ 
0ñ 
0ús   ÂB4EÅE©Údurable_cooldown_authoritativeÚdurable_cooldown_stateÚattempt_generationc          	     óB  — |�/t        | |«      s#t        j                  d|t        | dd«      «       yt	        j
                  |«      }t        | «      5  t        5  |xr t        t        | dd«      xs d«      |k7  }ddd«       r t        j                  d|«       	 ddd«       yd|v r1|dur-|du st        |j                  d	d«      «      st        | |||«       |j                  «       D ]  \  }}t        | ||«       Œ 	 ddd«       y# 1 sw Y   Œ�xY w# 1 sw Y   yxY w)
an  Restore the per-attempt snapshot after a pre-commit hard cancel.
    A restore stamped with a stale ``attempt_generation`` no-ops so a timed-out primary's late unwind cannot
    roll back state owned by the fallback attempt.

    ``attempt_generation`` (when provided) is the claim the calling attempt took via
    :func:`_claim_compressor_attempt`. See #96634.
    NzªSkipping stale compressor attempt-state restore: attempt generation %s no longer owns the compressor (current: %s). A newer (stall-fallback) attempt's state is preserved.r�   r   zuSkipping stale compressor attempt-state restore at write time: attempt generation %s lost the compressor mid-restore.rb   FTrc   )r–   r   Úwarningr2   r|   r}   rŽ   rˆ   r‘   rV   r¡   rÄ   r)   Úsetattr)	r~   rº   rÆ   rÇ   rÈ   ÚrestoredÚlostr€   Úvalues	            r   Ú!_restore_compressor_attempt_staterÏ   h  sE  € ð Ð%Ô.LÈZÐYkÔ.lÜ�‰ð@à¤¨
Ð4UÐW[Ó \ô	
ð
 	Ü�}‰}˜XÓ&€Hô 
)¨Ó	4ñ -Ü%ñ 	DØ%ò  D¬#¬g°jÐBcÐefÓ.gÒ.lÐklÓ*mð  rDñ  +DˆD÷	DáÜ�N‰NðOØPbôð ÷-ð -ð .°Ñ9Ø.°eÑ;Ø/°4Ñ7¼tÀHÇLÁLÐQkÐmrÓDsÔ?tä& z°8Ð=[Ð]sÔtØ#Ÿ>™>Ó+ò 	-‰KˆD�%Ü�J  eÕ,ñ	-÷%-ð -÷	Dð 	Dú÷-ð -ús+   ÁDÁ"D	Á;!DÂ%ADÄ	D	ÄDÄDc                ó\  — 	 ddl m} t        | |«      syt        | «      }|j	                  d«      }|j	                  d«      }|�|syt        t        |«      dd«      }t        |«      sy |||«      }t        |t        «      st        d	«      ‚|j                  | d
¬«       t        | dd«      }	|	d
ur|	dfS t        | «      }t        D ]"  }
|
|v sŒt        j                   ||
   «      ||
<   Œ$ d
t        j                   |«      fS # t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)a5  Refresh and snapshot built-in durable cooldown state under the lease.
    Third-party compressors are not invoked: plugin code must not run under the lease. Returns ``False`` on
    durable read failure (rollback must not mistake unknown state for an empty row) and ``None`` when the
    legacy API is absent.r   ©ÚContextCompressor©NNr­   r®   NÚ$get_compression_failure_cooldown_row©FNz3raw compression cooldown snapshot must be a mappingT©Úrefreshz5authoritative compression cooldown capture failed: %sÚ(_last_cooldown_refresh_was_authoritative)r%   rÒ   r&   ry   r¡   r2   r³   r´   r(   rz   Ú'get_active_compression_failure_cooldownr   r   r   Ú!_COMPRESSOR_COOLDOWN_STATE_FIELDSr|   r}   )r~   Úattempt_snapshotrÒ   r   r½   r¾   Ú
raw_readerr¼   r   r»   r€   s              r   Ú+_capture_authoritative_cooldown_under_leaserÝ   ˜  s8  € ðÝ>Ü˜*Ð&7Ô8ØÜ�jÓ!ˆØ—Z‘Z Ó.ˆ
Ø—Z‘Z Ó.ˆ
ØÐ¡ZàÜœT *Ó-Ð/UÐW[Ó\ˆ
Ü˜
Ô#Øá" :¨zÓ:ˆÜ˜-¬Ô.ÜÐQÓRÐRØ×AÑAÀ*ÐVZÐAÔ[ô ˜JÐ(RÐTXÓY€MØ˜DÑ Ø˜dÐ"Ð"Ü�*Ó€FÜ1ò AˆØ�6Š>Ü%)§]¡]°6¸$±<Ó%@Ð˜TÒ"ðAð ”—‘˜}Ó-Ð-Ð-øô ò Ü�‰ÐLÈcÔRÜûðús(   ‚D •1D Á!D Á)7D Ä	D+ÄD&Ä&D+c                  ó
  — e Zd ZdZddd„Zdd„Zdd„Zedd„«       Zedd„«       Z	edd„«       Z
d d	„Zdd!d
„Zd"d„Zdd!d„Zdd„Zedd„«       Zedd„«       Zdd„Zdd„Zedd„«       Zdd„Zdd„Zdd„Zdd„Zd#d„Zd$d„Zdd„Zy)%ÚCompressionCommitFencea  Fence timeout cancellation against post-summary session mutation.
    The sync worker thread cannot be killed; the fence makes the commit boundary deterministic: cancellation
    wins before mutation starts, or waits for an already-started commit to finish completely.Nc                ór  — t        j                  «       | _        d| _        d| _        t        j
                  «       | _        d| _        t        j                  «       | _        d | _	        d| _
        t        j                  «       | _        d| _        d | _        d| _        d| _        |�| j%                  |«       y y ©NF)r‰   rŠ   Ú_lockÚ
_cancelledÚ_commit_startedÚEventÚ_commit_phaseÚ_admission_revokedÚ_lock_release_guardÚ_cancelled_lock_releaseÚ!_cancelled_lock_release_requestedr¸   r¹   Ú_last_progressÚ_progress_observedÚ	_deadlineÚ(_retain_cancelled_lock_until_worker_doneÚ_commit_watermark_fencedÚset_total_ceiling_seconds)ÚselfÚtotal_ceiling_secondss     r   Ú__init__zCompressionCommitFence.__init__Ã  s£   € Ü—^‘^Ó%ˆŒ
ØˆŒØ$ˆÔô 'Ÿ_™_Ó.ˆÔð #(ˆÔô $-§>¡>Ó#3ˆÔ ØEIˆÔ$Ø16ˆÔ.ä"Ÿn™nÓ.ˆÔØ"'ˆÔØ'+ˆŒØ8=ˆÔ5à(-ˆÔ%Ø Ð,Ø×*Ñ*Ð+@ÕAð -rO   c                ór   — t        |«      }|dk  rt        d«      ‚t        j                  «       |z   | _        y)z:Arm the wall-clock deadline shared by the host and worker.r   z*total compression ceiling must be positiveN)r¶   Ú
ValueErrorr¸   r¹   rí   )rñ   Úsecondss     r   rð   z0CompressionCommitFence.set_total_ceiling_secondsè  s1   € ä˜“.ˆØ�aŠ<ÜÐIÓJÐJÜŸ™Ó)¨GÑ3ˆ�rO   c                óD   — t        j                  «       | _        d| _        y)zURecord forward progress (a streamed token); a bare float store is atomic, so no lock.TN)r¸   r¹   rë   rì   ©rñ   s    r   Útouch_progressz%CompressionCommitFence.touch_progressï  s   € ä"Ÿn™nÓ.ˆÔØ"&ˆÕrO   c                ó   — | j                   S )zAWhether semantic provider progress was reported for this attempt.)rì   rø   s    r   Úprogress_observedz(CompressionCommitFence.progress_observedô  s   € ð ×&Ñ&Ð&rO   c                óT   — | j                   }|d uxr t        j                  «       |k\  S ©N)rí   r¸   r¹   )rñ   rÀ   s     r   Údeadline_exceededz(CompressionCommitFence.deadline_exceededù  s'   € à—>‘>ˆØ˜tÐ#ÒD¬¯©Ó(8¸HÑ(DÐDrO   c                ó   — | j                   S )uX  Armed deadline (absolute monotonic); the worker's stream consumer stops when the host stops waiting.

        :meth:`set_total_ceiling_seconds` documents this deadline as "shared by the host and worker", but
        until #99692 only the host could read it â€” ``deadline_exceeded`` answers "is it past?" for a caller
        that is already polling, which is useless to a worker blocked inside a provider stream. Publishing
        the instant itself lets the worker's stream consumer stop at exactly the moment the host stops
        waiting (see ``auxiliary_client.aux_stream_deadline``).
        )rí   rø   s    r   Údeadline_monotonicz)CompressionCommitFence.deadline_monotonicþ  s   € ð �~‰~ÐrO   c                óX   — t        dt        j                  «       | j                  z
  «      S )z8Seconds since the worker last reported forward progress.r°   )r·   r¸   r¹   rë   rø   s    r   Úseconds_since_progressz-CompressionCommitFence.seconds_since_progress
  s!   € ä�3œŸ™Ó(¨4×+>Ñ+>Ñ>Ó?Ð?rO   c                óª   — | j                   5  | j                  sd| _        |�|j                  «        | j                   cddd«       S # 1 sw Y   yxY w)zYCancel a pending commit (``True``), or block until an active commit finishes (``False``).TN)râ   rä   rã   Úset©rñ   Úcancel_events     r   Úcancel_before_commitz+CompressionCommitFence.cancel_before_commit  sL   € à�Z‰Zñ 	,Ø×'Ò'Ø"&�”ØÐ'Ø× Ñ Ô"Ø×+Ñ+Ð+÷	,÷ 	,ò 	,ús   �2A	Á	Ac                óð   — | j                   j                  d¬«      sy	 | j                  sd| _        | j                   | j                   j	                  «        S # | j                   j	                  «        w xY w)zZNon-blocking :meth:`cancel_before_commit`; ``None`` while an active commit owns the fence.F©ÚblockingNT)râ   Úacquirerä   rã   Úreleaserø   s    r   Útry_cancel_before_commitz/CompressionCommitFence.try_cancel_before_commit  s\   € à�z‰z×!Ñ!¨5Ð!Ô1Øð	!Ø×'Ò'Ø"&�”Ø×+Ñ+Ð+à�J‰J×ÑÕ øˆD�J‰J×ÑÕ ús   ŸA ÁA5c                ó\  — | j                   j                  «        | j                  s'| j                  s|�Wt	        |j                  «       «      r>d| _        | j                   j                  «        | j                  r| j                  «        yd| _	        | j                  j                  «        y)z?Atomically admit commit unless a hard cancellation already won.TF)râ   r  Úis_cancelledrç   rV   Úis_setrã   r  Ú"release_cancelled_compression_lockrä   ræ   r  r  s     r   Úbegin_commitz#CompressionCommitFence.begin_commit"  s†   € à�
‰
×ÑÔØ×Ò × 7Ò 7¸LÐ<TÔY]Ð^j×^qÑ^qÓ^sÔYtØ"ˆDŒOØ�J‰J×ÑÔ Ø×&Ò&à×7Ñ7Ô9ØØ#ˆÔà×Ñ×ÑÔ ØrO   c                ó¦   — | j                   j                  «        | j                  j                  «        | j                  r| j                  «        yy)z8Leave a commit boundary entered by :meth:`begin_commit`.N)ræ   Úclearrâ   r  rç   r  rø   s    r   Úfinish_commitz$CompressionCommitFence.finish_commit1  s>   € à×Ñ× Ñ Ô"Ø�
‰
×ÑÔØ×"Ò"à×3Ñ3Õ5ð #rO   c                ó6   — | j                   j                  «       S )zbLock-free read: an admitted commit is in progress (hosts reach the overrun loop on a hung commit).)ræ   r  rø   s    r   Úcommit_in_flightz'CompressionCommitFence.commit_in_flight9  s   € ð ×!Ñ!×(Ñ(Ó*Ð*rO   c                óR   — | j                   xs | j                  xs | j                  S )z7True after cancellation won before the commit boundary.)rã   rç   rþ   rø   s    r   r  z#CompressionCommitFence.is_cancelled>  s$   € ð �‰ÒS $×"9Ñ"9ÒS¸T×=SÑ=SÐSrO   c                ó   — d| _         y)z9Prevent a timed-out live worker from overlapping a retry.TN©rî   rø   s    r   Ú)retain_compression_lock_until_worker_donez@CompressionCommitFence.retain_compression_lock_until_worker_doneC  s
   € à8<ˆÕ5rO   c                ó   — d| _         y)u]  Record a watermark-bounded commit (later rows survive as tail); a detached worker may keep admission.

        Called by the compression worker right after it captures ``get_active_message_watermark()`` under
        the durable compression lock (#75316/#87484). A watermark-fenced commit archives ONLY rows at or
        below the watermark; rows appended later â€” e.g. the user turn the host released at the turn-hold
        boundary (#97963) â€” are cloned as live concurrent tail. That is exactly the property a host needs
        before letting a detached worker keep its commit admission.
        TN©rï   rø   s    r   Úmark_commit_watermark_fencedz3CompressionCommitFence.mark_commit_watermark_fencedG  s   € ð )-ˆÕ%rO   c                ó   — | j                   S )z9Lock-free read: the worker's commit is watermark-bounded.r  rø   s    r   Úcommit_watermark_fencedz.CompressionCommitFence.commit_watermark_fencedR  s   € ð ×,Ñ,Ð,rO   c                ó   — d| _         y)zdUndo :meth:`retain_compression_lock_until_worker_done` once a bounded join proved the worker exited.FNr  rø   s    r   Úallow_cancelled_lock_releasez3CompressionCommitFence.allow_cancelled_lock_releaseW  s
   € à8=ˆÕ5rO   c                óà   — d| _         | j                  j                  d¬«      r,	 | j                  «        | j                  j	                  «        yy# | j                  j	                  «        w xY w)aC  Revoke FUTURE commit admission without blocking on the fence lock.
        An in-flight commit is never abandoned (``begin_commit`` re-checks the flag under the lock). The lease
        release must not run mid-commit: released now if the lock is free, else deferred to
        ``finish_commit``/refusal (holder-qualified).TFr	  N)rç   râ   r  r  r  rø   s    r   Úrevoke_commit_admissionz.CompressionCommitFence.revoke_commit_admission[  s[   € ð
 #'ˆÔØ�:‰:×Ñ uÐÔ-ð%Ø×7Ñ7Ô9à—
‘
×"Ñ"Õ$ð	 .øð —
‘
×"Ñ"Õ$ús   ¥A ÁA-c                óž   — | j                   j                  «        | j                  s| j                  r| j                   j	                  «        yy)zbHold the fence across lock acquisition + release-hook publication so a timeout cannot win between.FT)râ   r  r  rç   r  rø   s    r   Úbegin_lock_setupz'CompressionCommitFence.begin_lock_setupo  s9   € à�
‰
×ÑÔØ×Ò × 7Ò 7Ø�J‰J×ÑÔ ØØrO   c                ó8   — | j                   j                  «        y)z@Leave a lock setup boundary entered by :meth:`begin_lock_setup`.N)râ   r  rø   s    r   Úfinish_lock_setupz(CompressionCommitFence.finish_lock_setupw  s   € à�
‰
×ÑÕrO   c                ó€   — | j                   5  || _        | j                  }ddd«       r |«        |S # 1 sw Y   ŒxY w)zhPublish the worker's holder-qualified release; if cleanup was already requested, run it and return True.N)rè   ré   rê   )rñ   r  Ú	requesteds      r   Úregister_cancelled_lock_releasez6CompressionCommitFence.register_cancelled_lock_release{  sC   € à×%Ñ%ñ 	?Ø+2ˆDÔ(Ø×>Ñ>ˆI÷	?ñ ÙŒIØÐ÷	?ð 	?ús   �4´=c                óp   — | j                   5  | j                  |u rd| _        ddd«       y# 1 sw Y   yxY w)z>Forget ``release`` after the worker's normal cleanup finishes.N)rè   ré   ©rñ   r  s     r   Úclear_cancelled_lock_releasez3CompressionCommitFence.clear_cancelled_lock_release„  s6   € à×%Ñ%ñ 	4Ø×+Ñ+¨wÑ6Ø/3�Ô,÷	4÷ 	4ñ 	4ús   �,¬5c                óš   — | j                   ry| j                  5  d| _        | j                  }ddd«       � |«        yy# 1 sw Y   ŒxY w)zdAfter cancellation won: release the worker's lock (a request ahead of hook publication is retained).NT)rî   rè   rê   ré   r-  s     r   r  z9CompressionCommitFence.release_cancelled_compression_lockŠ  sQ   € à×8Ò8ØØ×%Ñ%ñ 	3Ø59ˆDÔ2Ø×2Ñ2ˆG÷	3ð ÐÙ�Ið ÷	3ð 	3ús   šAÁA
rý   )rò   úfloat | NoneÚreturnÚNone)rö   r¶   r1  r2  ©r1  r2  ©r1  rV   )r1  r0  )r1  r¶   )r  r   r1  rV   )r1  úOptional[bool])r  úCallable[[], None]r1  rV   )r  r6  r1  r2  )Ú__name__Ú
__module__Ú__qualname__Ú__doc__ró   rð   rù   Úpropertyrû   rþ   r   r  r  r  r  r  r  r  r  r  r   r"  r$  r&  r(  r+  r.  r  © rO   r   rß   rß   ¾  sÜ   „ ñaô#BóJ4ó'ð
 ò'ó ð'ð òEó ðEð ò	ó ð	ó@ô,ó	!ôó6ð ò+ó ð+ð òTó ðTó=ó	-ð ò-ó ð-ó>ó
%ó(óóó4ôrO   rß   g      ^@g     À‚@Ústall_interruptedg      >@g      @c                ó¢  — d}t        j                  t        t        «      5  t	        t        |«      d«      }ddd«       	 | j                  |¬«       y# 1 sw Y   ŒxY w# t        j                  j                  $ r | j                  «       cY S t        j                  j                  $ r Y yt        $ r t        j                  dd¬«       Y yw xY w)a  Best-effort bounded join of a fence-cancelled compression worker.
    Returns True when the future settled within ``grace_seconds`` (thread provably exited); False for a
    still-running worker, which the caller must treat as an orphan behind the poison fence.r°   N©ÚtimeoutTz5cancelled compression worker exited with an exceptionr   )r‹   r˜   rz   rõ   r·   r¶   ÚresultÚ
concurrentÚfuturesÚTimeoutErrorÚdoneÚCancelledErrorr   r   r   )ÚfutureÚgrace_secondsÚgraces      r   Ú_join_cancelled_workerrJ  ­  s³   € ð €EÜ	×	Ñ	œY¬
Ó	3ñ /Ü”E˜-Ó(¨#Ó.ˆ÷/ðØ�‰˜eˆÔ$Ø÷	/ð /ûô
 ×Ñ×*Ñ*ò ð �{‰{‹}ÒÜ×Ñ×,Ñ,ò áÜò ä�‰ÐLÐW[ˆÔ\Ùðús)   ¡AÁ A ÁAÁ-CÂCÂ,CÃCé   c                 ó|   — t         5  t        t        k\  r
	 ddd«       yt        dz  a	 ddd«       y# 1 sw Y   yxY w)z9Reserve one bounded compression-pool admission slot (F6).NFr9   T)Ú_compress_admission_lockÚ_compress_admitted_countÚ_COMPRESS_EXECUTOR_MAX_WORKERSr<  rO   r   Ú_try_admit_compression_jobrP  Õ  sB   € ô 
"ñ Ü#Ô'EÒEØ÷ð ô 	! AÑ%Ð Ø÷	÷ ñ ús   ‡2Ÿ
2²;c                ó^   — t         5  t        dkD  r	t        dz  addd«       y# 1 sw Y   yxY w)z?Free an admission slot (future done-callback or failed submit).r   r9   N)rM  rN  )Ú_futures    r   Ú_release_compression_admissionrS  ß  s/   € ô 
"ñ *Ü# aÒ'Ü$¨Ñ)Ð$÷*÷ *ñ *ús   ‡#£,c                 óŽ   — t         } | �| S ddlm} t        5  t         € |t        d¬«      a t         cddd«       S # 1 sw Y   yxY w)zBReturn the process-wide compress-timeout DaemonThreadPoolExecutor.Nr   )ÚDaemonThreadPoolExecutorzcompress-ctx-timeout)Úmax_workersÚthread_name_prefix)Ú_compress_timeout_executorÚtools.daemon_poolrU  Ú_compress_timeout_executor_lockrO  )ÚexecutorrU  s     r   Ú_get_compress_timeout_executorr\  ç  sK   € ô *€HØÐØˆÝ:Ü	(ñ *Ü%Ð-á)AÜ:ÐOeô*Ð&ô *÷*÷ *ò *ús	   —;»Ac                ó6  — t         }t        }| }|€ii }t        j                  t        «      5  ddlm}  |«       }t        |t        «      r|j                  di «      ni }t        |t        «      r|ni }ddd«       t        |t        «      r�t        j                  t        t        «      5  |j                  d«      �t        |d   «      }ddd«       t        j                  t        t        «      5  |j                  d«      �t        |d   «      dkD  rt        |d   «      }ddd«       |dkD  rFt        ||«      }ddlm} t         |dd«      «      }|dkD  r||kD  r|}t        |t!        ||«      «      }||fS # 1 sw Y   �ŒxY w# 1 sw Y   Œ¼xY w# 1 sw Y   ŒqxY w)zÙReturn ``(idle_timeout_seconds, total_ceiling_seconds)``.
    ``idle_timeout_seconds <= 0`` disables the progress-aware wrapper. The ceiling is clamped to at least one
    idle window when the idle budget is positive.Nr   )Úload_configÚcompressionÚcontext_timeout_secondsÚcontext_total_ceiling_seconds)Ú_effective_aux_timeout)ÚDEFAULT_CONTEXT_TIMEOUT_SECONDSÚ%DEFAULT_CONTEXT_TOTAL_CEILING_SECONDSr‹   r˜   r   Úhermes_cli.configr^  r&   r(   r¡   rz   rõ   r¶   r·   Úagent.auxiliary_clientrb  Úmin)	Úcompression_cfgÚidleÚceilingÚcfgr^  ÚrawÚmayberb  Ú_aux_budgets	            r   Ú$resolve_context_compression_timeoutsro  ÷  s‚  € ô +€DÜ3€GØ
€CØ
€{ØˆÜ× Ñ ¤Ó+ñ 	;Ý5Ù“-ˆCÜ2<¸SÄ$Ô2G�C—G‘G˜M¨2Ô.ÈRˆEÜ% e¬TÔ2‘%¸ˆC÷		;ô
 �#”tÔä× Ñ ¤¬JÓ7ñ 	=Ø�w‰wÐ0Ó1Ð=Ü˜SÐ!:Ñ;Ó<�÷	=ô × Ñ ¤¬JÓ7ñ 	FØ�w‰wÐ6Ó7ÐCÌÈcÐRqÑNrÓHsÐvwÒHwÜ Ð$CÑ DÓE�÷	Fð ˆa‚xÜ�g˜tÓ$ˆõ
 	BÜÑ2°=À$ÓGÓHˆØ˜Š?Ø˜WÒ$Ø%�Ü�tœS ¨gÓ6Ó7ˆDØ�ˆ=Ð÷3	;ñ 	;ú÷	=ð 	=ú÷	Fð 	Fús$   ¬AE6Â( FÃ.1FÅ6F ÆFÆF)Úidle_timeout_secondsc                ó@  — |}|€t        «       \  }}	 t        |«      }|dk  ry| �	 t        | j	                  «       «      |k\  S 	 t        j                  «       t        |«      z
  |k\  S # t        t        f$ r Y yw xY w# t
        $ r Y yw xY w# t        t        f$ r Y yw xY w)u  Return whether a pre-commit cancel landed after the stall window.
    An early ``/stop`` stays cooldown-neutral; an interrupt after the inactivity budget counts as a stall so
    the next automatic turn does not blindly retry.

    When the fence (or, without a fence, the attempt clock) has already sat idle for the configured
    compression inactivity budget, the interrupt is a stalled attempt â€” the same condition the host timeout
    uses â€” and the next automatic turn must not blindly retry that strategy (#96775).
    Fr   )ro  r¶   rz   rõ   r  r   r¸   r¹   )Úcommit_fenceÚ
started_atrp  ri  Ú_ceilings        r   Úcompression_attempt_stalledru    s½   € ð  €DØ€|Ü=Ó?‰ˆˆhðÜ�T‹{ˆð ˆq‚yØØÐð	Ü˜×<Ñ<Ó>Ó?À4ÑGÐGðÜ—‘Ó ¤5¨Ó#4Ñ4¸Ñ=Ð=øô ”zÐ"ò Ùðûô ò 	Ùð	ûô ”zÐ"ò Ùðús4   “A' §A< Á"B Á'A9Á8A9Á<	BÂBÂBÂBc                ó4  — t        | dd«      }t        |dd«      xs t        | dd«      xs d}t        |t        «      rt        |«      nd}d}t	        j
                  t        t        «      5  t        |xs d«      }ddd«       d|› d|› d	|› �S # 1 sw Y   ŒxY w)
z:Identity of the stalled source context + summary strategy.Úcontext_compressorNrs   ÚmodelrD   r   zmsgs=z:tokens=z:model=)	r2   r&   r'   Úlenr‹   r˜   rz   rõ   r‘   )r4   ÚmessagesÚapprox_tokensr~   rx  Ú
n_messagesr6   s          r   Ú_stall_source_fingerprintr}  ;  sš   € ä˜Ð 4°dÓ;€JÜ�J °Ó6Ò]¼'À%ÈÐRVÓ:WÒ]Ð[]€EÜ",¨X´tÔ"<”�X”À!€JØ€FÜ	×	Ñ	œY¬
Ó	3ñ )Ü�]Ò' aÓ(ˆ÷)à�:�,˜h v h¨g°e°WÐ=Ð=÷)ð )ús   Á+BÂBc               óF  — t        ||¬«      syt        | dd«      }t        |dd«      }t        |«      syt        › dt	        | ||«      › �}	  ||d¬«       t        j                  dt        | dd«      xs d|«       y
# t
        $ r t        j                  d	d
¬«       Y yw xY w)zÌPersist a stall-interrupted cooldown after snapshot restore.
    Must run *after* ``_restore_compressor_attempt_state`` so rollback cannot wipe the new row. Returns True
    when the backoff was recorded.)rr  rs  Frw  NÚrecord_timeout_failureú:r=  )Úfailure_kindz5stall-interrupted compression cooldown persist failedTr   z?Recorded stall-interrupted compression backoff (session=%s, %s)r¾   Únone)	ru  r2   r´   ÚSTALL_INTERRUPTED_FAILURE_CLASSr}  r   r   r   rT   )r4   rr  rs  rz  r{  r~   ÚrecordÚerrors           r   Ú!_record_stall_interrupted_backoffr†  F  s½   € ô '°LÈZÕXØÜ˜Ð 4°dÓ;€Jô �ZÐ!9¸4Ó@€FÜ�FÔØÜ.Ð/¨qÔ1JÈ5ÐRZÐ\iÓ1jÐ0kÐl€EðÙˆuÐ#6Õ7ô ‡K�KØIÌ7ÐSXÐZfÐhlÓKmÒKwÐqwØôð øô ò Ü�‰ÐLÐW[ˆÔ\Ùðús   Á
A= Á= B ÂB c                 ó^  — 	 ddl m} m}  |d«      j                  d«      }t        |t        «      syt        |«      D �]  \  }}t        |t        «      sŒt        |j                  d	«      xs d
«      j                  «       }t        |j                  d«      xs d
«      j                  «       }|r|sŒu	  | |«      }ddl m}  ||j                  d«      «      }	d|› d|› d�||t        |j                  d«      xs d
«      j                  «       xs d|xs dt        |j                  d«      xs |j                  d«      xs d
«      j                  «       xs d|	dœc S  y# t        $ r t
        j                  dd¬«       Y yw xY w# t        $ r t
        j                  d|d¬«       d}Y Œðw xY w)a  Return the first usable ``auxiliary.compression.fallback_chain`` entry.
    The aux client applies the chain only from its exception handler, so a silent stall never reaches it; this
    pins the route onto one bounded retry instead. Only the first complete entry: if it errors, the aux
    client's own exception path walks the rest. ``None`` when none is usable (skip compression).r   )Ú_fallback_entry_api_keyÚ_get_auxiliary_task_configr_  Úfallback_chainz(compression fallback_chain lookup failedTr   NÚproviderrD   rx  z8compression fallback_chain[%d] api key resolution failed)Ú_coerce_positive_timeoutr@  zfallback_chain[z](ú)Úbase_urlÚapi_modeÚ	transport)Úlabelr‹  rx  rŽ  Úapi_keyr�  r@  )rf  rˆ  r‰  r¡   r   r   r   r&   r'   Ú	enumerater(   rG   rH   rŒ  )
rˆ  r‰  ÚchainÚindexÚentryr‹  rx  r’  rŒ  r@  s
             r   Ú"resolve_compression_fallback_router—  b  sŸ  € ð
ß^Ù*¨=Ó9×=Ñ=Ð>NÓOˆô �eœTÔ"ØÜ! %Ó(ó 
‰ˆˆuÜ˜%¤Ô&ØÜ�u—y‘y Ó,Ò2°Ó3×9Ñ9Ó;ˆÜ�E—I‘I˜gÓ&Ò,¨"Ó-×3Ñ3Ó5ˆñ ™uØð	Ù-¨eÓ4ˆGõ 	DÙ*¨5¯9©9°YÓ+?Ó@ˆà& u g¨R°¨z¸Ð;Ø ØÜ˜EŸI™I jÓ1Ò7°RÓ8×>Ñ>Ó@ÒHÀDØ’ $Ü˜EŸI™I jÓ1ÒQ°U·Y±Y¸{Ó5KÒQÈrÓR×XÑXÓZÒbÐ^bØñ
ò 	
ð!
ð2 øô= ò Ü�‰Ð?È$ˆÔOÙðûô  ò 	Ü�L‰LÐSÐUZÐeiˆLÔjØŠGð	ús#   ‚E  Â3FÅ  FÆFÆ#F,Æ+F,c                óŠ   — t        «       fD �cg c]  }|€Œ|‘Œ	 }}| r ddlm} |j                  t	        |«      «       |S c c}w )zÃPinned routes for the stall retry, in order: the configured chain entry, then (only once a
    stall-class backoff has already burned a window in this session) the deterministic fallback summary.r   )ÚDETERMINISTIC_SUMMARY_ROUTE)r—  r%   r™  Úappendr(   )Úescalate_deterministicÚrouteÚroutesr™  s       r   Ú_stall_retry_routesrž  ‹  sF   € ô #EÓ"FÐ!HÖ^˜ÈEÑL]ŠeÐ^€FÐ^ÙÝHØ�‰”dÐ6Ó7Ô8Ø€Mùò	 _s
   ŽA –A c                óz   — t        t        | dd«      dd«      }t        |t        «      rt        |t        «      s|S dS )zZTimeout-class failures this session that no healthy summary has cleared yet (type-pinned).rw  Nre   r   )r2   r&   r‘   rV   )r4   Úcounts     r   Ú_prior_timeout_failuresr¡  •  s:   € ä”G˜EÐ#7¸Ó>Ð@_ÐabÓc€EÜ˜u¤cÔ*´:¸eÄTÔ3Jˆ5ÐQÐPQÐQrO   c                óÊ   — t        t        | dd«      dd«      }t        |t        «      st        |t        «      r|dk  ryt        |t        «      st        |t        «      sy||kD  S )a  Whether a ~``request_tokens`` request cannot be sent at all (above the model's context window).
    ``None`` when either side is unknown (no compressor / unresolvable window / no estimate), so callers
    keep their conservative default instead of treating "unknown" as "fits".rw  NÚcontext_lengthr   )r2   r&   rV   r‘   )r4   Úrequest_tokensÚwindows      r   Úrequest_exceeds_model_windowr¦  ›  s[   € ô ”W˜UÐ$8¸$Ó?ÐAQÐSWÓX€FÜ�&œ$Ô¤z°&¼#Ô'>À&ÈAÂ+ØÜ�.¤$Ô'¬z¸.Ì#Ô/NØØ˜FÑ"Ð"rO   )Úon_commit_overrunÚon_timeout_causeÚtelemetry_agentÚ	new_fencer›  c        
        óÂ   — t        |dd«      }
t        t        |
dd«      «      r|
j                  «       ryt        |	«      D ]  }t	        || ||||||||¬«
      }|€Œ|c S  y)uM  Re-run an aborted compression with the summary route pinned: once on the configured chain entry,
    then â€” when ``escalate_deterministic`` (a stall backoff already burned one idle window this session,
    #112420) â€” once with the summary LLM skipped so compress() commits its deterministic fallback summary.
    Returns ``(messages, system_prompt)`` on real compression, else ``None`` and the caller degrades as
    before. The entry's ``timeout`` sets the idle window. Re-runs the whole worker, so pre-compression
    callbacks must be idempotent.

    The retry is bounded the same way the primary was: silence for one idle window ends it, while a fallback
    that is streaming keeps its ceiling. The entry's own ``timeout`` (when declared) sets that idle window,
    so a fallback tuned for a slower-but-healthy backend is not held to a deadline the stalled primary
    defined (#62452 semantics, applied to the stall path).
    Known limitation (accepted, #96634 review): the retry re-runs the COMPLETE worker, which repeats
    memory/plugin pre-compression callbacks. Built-in callbacks are idempotent (re-reads and overwrites of
    attempt-scoped state); third-party plugin callbacks are advised to be. Splitting the worker to resume
    mid-pipeline would couple this path to every host's callback ordering â€” deliberately out of scope.
    Ú_hard_interrupt_requestedNr  )	Úworkerrz  Úsystem_prompt_fallbackrp  rò   r§  r¨  r©  rª  )r2   r´   r  rž  Ú_run_pinned_compression_retry)r­  rz  r®  rp  rò   r§  r¨  r©  rª  r›  Úhard_cancelrœ  Ú	recovereds                r   Ú$_retry_compression_on_fallback_chainr²  §  s€   € ô2 ˜/Ð+FÈÓM€KÜ”˜ X¨tÓ4Ô5¸+×:LÑ:LÔ:NØÜ$Ð%;Ó<ò ˆÜ1Ø˜&¨8ÐLbØ!5ÐMbØ/ÐBRÐdsØô	
ˆ	ð Ñ ØÒðð rO   c       	        óÜ  — d}
|	�	  |	«       }
t        |
t        «      st        j                  d«       t	        «       }
t        | j                  d«      xs |«      }t        t        |«      |«      }| j                  d«      du }|rt        j                  d| d	   «       nt        j                  d
| d	   | d   «       t        |dd«      }t        |dd«      }	 ddl	m
}  || «      5  t        ||||||||
|d¬«
      \  }}ddd«       |u rt        j                  d| d	   «       yt        |dd«      }|s%t        |t        «      r2t        |t        «      r"||kD  rt        j                  d| d	   «       |fS t        j                  d| d	   «       |fS # t         $ r t        j                  dd¬«       Y �Œ§w xY w# 1 sw Y   Œ¼xY w# t         $ r t        j                  d| d	   d¬«       Y yw xY w)zaOne bounded re-run of ``worker`` with ``route`` pinned; ``None`` when it produced no compression.Nzœcompression stall-fallback fence factory failed; the retry will run on an unpublished fence (a /stop mid-retry cannot serialize against its commit boundary)Tr   z¨compression stall-fallback retry running on an unpublished fence; hard-interrupt admission will read the aborted attempt's fence rather than the retry's commit boundaryr@  Údeterministicu�   Context compression stalled on every summary route â€” committing the %s (no summary model) before continuing without compressionr‘  u~   Context compression stalled on the configured summary route â€” retrying once on %s (%s) before continuing without compressionrx  rw  r_   r   )Úpin_summary_routeF)
r­  rz  r®  rp  rò   r§  r¨  Úfencer©  Ústall_fallbackz1Context compression fallback attempt on %s failedzbContext compression fallback attempt on %s produced no compression; continuing without compressionz�Context compression committed a deterministic fallback summary on %s after the primary summary route stalled (no summary model produced output)zKContext compression recovered on %s after the primary summary route stalled)r   r   rÊ   r&   rß   r¶   r¡   r·   r2   r%   rµ  Ú*run_compress_context_with_progress_timeoutr‘   rT   )rœ  r­  rz  r®  rp  rò   r§  r¨  r©  rª  Úretry_fenceri  rj  r´  r~   Ústreak_beforerµ  Úresult_msgsÚresult_promptÚstreak_afters                       r   r¯  r¯  Ï  s(  € ð €KØÐð	Ù#›+ˆKô �kÔ#9Ô:Ü�‰ðuô	
ô -Ó.ˆÜ�—‘˜9Ó%Ò=Ð)=Ó>€DÜ”%Ð-Ó.°Ó5€GØ—I‘I˜oÓ.°$Ð6€MÙÜ�‰ð4Ø5:¸7±^õ	
ô
 	�‰ðMØNSÐT[ÉnÐ^cÐdkÑ^lô	
ô ˜Ð*>ÀÓE€JÜ˜JÐ(FÈÓJ€MðÝ>Ù˜uÓ%ñ 	Ü)SØ¨ÐI_Ø%)ÀÐ\mØ!1¸ÐVeØ$ô	*Ñ&ˆK˜÷	ð �hÑä�‰ØpØ�'‰Nô	
ð ô ˜:Ð'EÀqÓI€LÙœ L´#Ô6¼:ÀmÔUXÔ;YÐ^jÐmzÒ^zÜ�‰ð9Ø:?À¹.ô	
ð ˜Ð%Ð%ô 	�‰ÐaÐchÐipÑcqÔrØ˜Ð%Ð%øôu ò 	Ü�N‰Nðtàð ÷ ð	ú÷:	ð 	ûô ò ô 	�‰ÐJÈEÐRYÉNÐeiˆÔjÙð	ús;   †F ÃG Ã$F8Ã=G Æ F5Æ4F5Æ8GÆ=G Ç$G+Ç*G+c               óV  — 	 t        j                  «       |z
  }||z
  }|dk  ry|j                  «       }t        t	        ||z
  d«      |«      }	 d| j                  |¬«      fS # t        j                  j                  $ r© | j                  «       r>| j                  «       }	|	€d| j                  «       fcY S t        j                  d|	«       Y yt        j                  «       |z
  }|j                  «       }|j                  s%||k  r ||k  rt        j                  d|||«       Y �Œ$Y yw xY w)zTPoll ``future`` under the idle budget + ceiling; ``(True, result)`` when it settled.Tr   rÕ   g{®Gázt?r?  uC   Context compression worker exited with %r â€” taking the stall pathul   Context compression still streaming after %.0fs (last progress %.1fs ago) â€” extending wait (ceiling %.0fs))r¸   r¹   r  rg  r·   rA  rB  rC  rD  rE  Ú	exceptionr   rT   rþ   )
rG  r¶  ri  rj  Úwait_startedÚwaitedÚremaining_ceilingÚsince_progressÚ
wait_slicer   s
             r   Ú_await_worker_within_budgetrÅ    s%  € ð Ü—‘Ó! LÑ0ˆØ# fÑ,ÐØ Ò!Øà×5Ñ5Ó7ˆÜœ˜T NÑ2°EÓ:Ð<MÓNˆ
ð	Ø˜Ÿ™¨z˜Ó:Ð:Ð:øÜ×!Ñ!×.Ñ.ò 	ð �{‰{Œ}Ø×&Ñ&Ó(�Ø�;Ø §¡£Ð0Ò0Ü—‘ÐaÐcfÔgÙ"Ü—^‘^Ó%¨Ñ4ˆFØ"×9Ñ9Ó;ˆNØ×*Ò*¨~ÀÒ/DÈÐRYÒIYÜ—‘ð CØ˜N¨Gôò Ùð#	ús    ÁA" Á"AD(Â5D(ÃAD(Ä'D(c               ó  — d}d}	 t        j                  «       |z
  }||z
  }|dk  rwt        t        t	        |d«      «      }|dz  }|dk  rt
        j                  nt
        j                  } |d||z
  ||«       |s#|�!d}t        d	d¬
«      5   |||«       ddd«       	 | j                  |¬«      S # 1 sw Y   ŒxY w# t        j                  j                  $ r% | j                  «       r| j                  «       cY S Y Œùw xY w)zîbegin_commit won the race: the SessionDB mutation cannot be fence-cancelled, so wait
    in bounded slices, logging (escalating) + surfacing once via ``on_commit_overrun``
    WHILE the commit hangs. Never silently hung or abandoned.
    Fr   Tçš™™™™™©?r9   é   uÕ   Context compression SessionDB commit still running %.1fs past the total ceiling (waited %.1fs, ceiling %.1fs); commit cannot be abandoned mid-flight â€” continuing to wait (check SessionDB health if this persists)Nz/compress_context commit-overrun callback failedr   r?  )r¸   r¹   rg  Ú"_COMMIT_OVERRUN_WAIT_SLICE_SECONDSr·   r   rÊ   r…  r    rA  rB  rC  rD  rE  )	rG  rj  rÀ  r§  Úoverrun_surfacedÚoverrun_reportsrÁ  rÁ   Úlogs	            r   Ú_await_in_flight_commitrÍ  ;  s  € ð ÐØ€OØ
Ü—‘Ó! LÑ0ˆØ˜fÑ$ˆ	Ø˜Š>äÔ>ÄÀGÈTÓ@RÓSˆIØ˜qÑ ˆOØ$3°qÒ$8”&—.’.¼f¿l¹lˆCÙðOàPVÐY`ÑP`ÐbhØô	ñ $Ð(9Ð(EØ#'Ð ÜÐOÐZ^Ô_ñ 7Ù% f¨gÔ6÷7ð		Ø—=‘=¨�=Ó3Ð3÷7ð 7ûô ×!Ñ!×.Ñ.ò 	ð �{‰{Œ}Ø—}‘}“Ò&ñ ð	ús   Â
B1ÂB= Â1B:Â==C?Ã>C?c                ór   — 	 | j                   ry| j                  «       }|�|S t        j                  d«       Œ7)zSCancel pre-commit; ``False`` when an admitted commit owns the fence (caller waits).Fgš™™™™™™?)r  r  r¸   Úsleep)r¶  Ú	cancelleds     r   Ú_cancel_or_join_workerrÑ  b  s@   € à
ð ×!Ò!ØØ×2Ñ2Ó4ˆ	ØÐ ØÐô 	�
‰
�5Ôð rO   c               ó®   — |rCt        t        |«      }t        | |«      r|j                  «        nt        j                  d|«       |j                  «        y)aQ  Idle-timeout unwind: free the worker's durable lease via the holder-qualified hook.
    Total-ceiling only: bounded grace for the worker to exit (it checks the fence between provider phases; an
    uninterruptible call is orphaned). Idle-stall skips the join: the worker is hung, the fallback needs a
    prompt return, the fence guards.uÛ   Cancelled compression worker did not exit within %.1fs grace â€” orphaning it behind the poison fence (late result will be discarded); retaining the session compression lease until it exits so no new attempt overlaps itN)rg  Ú(_CANCELLED_WORKER_TEARDOWN_GRACE_SECONDSrJ  r"  r   rÊ   r  )rG  r¶  Útotal_exhaustedrj  rI  s        r   Ú_release_cancelled_workerrÕ  q  sO   € ñ ÜÔ<¸gÓFˆÜ! &¨%Ô0ð ×.Ñ.Õ0ä�N‰NðQàRWôð
 
×,Ñ,Õ.rO   T)	Ú
on_timeoutr¨  r§  r¶  r©  r·  rª  Úfallback_workerÚrequest_exceeds_windowc                ó
  ‡ ‡‡— |dk  rt        d«      ‚dˆfd„}t        t        |«      t        |«      «      }t        |«      }|r|}|�|n	t        «       }|j	                  |«       |
xr |xs t        |	«      dk\  }ddlm} t        «       }t        «       sGt        j                  dt        «       |	�"t        |	t        j                  «       ddd	¬
«       ‰ |«       fS dˆˆ fd„}	 |j!                   ||«      |«      }|j'                  t$        «       t        j                  «       }d}	 t)        |||||¬«      \  }}|rd}||s|j+                  «        S S |j-                  «        t        j                  «       |z
  |k\  xs |j.                  }|r|j1                  «        |�)t3        dd¬«      5   |||j4                  «       ddd«       t7        |«      s&t9        ||||¬«      }d}||s|j+                  «        S S d}t;        ||||¬«       t        j                  «       |z
  }|j=                  «       }|
r0t?        |xs ‰ ‰‰|||||	||¬«
      }|�||s|j+                  «        S S |�!t3        dd¬«      5   ||||«       ddd«       nt        j                  d|||«       ‰ |«       f|s|j+                  «        S S # t"        $ r t%        «        ‚ w xY w# 1 sw Y   �ŒxY w# 1 sw Y   ŒJxY w# |s|j+                  «        w w xY w)uÉ  Run ``worker(fence)`` under a sync progress-aware (idle + ceiling) timeout.
    Budgets bound the PRE-commit phase only: an admitted commit always completes (overrun logged, surfaced
    once via ``on_commit_overrun``). A pre-commit cancel returns ``(messages, system_prompt_fallback)`` (lazy
    callable), detaching the worker; a stall first retries the chain once on ``new_fence``, then on_timeout.
    ``request_exceeds_window``: the request this compaction must shrink is above the model's context
    window, so "continue without compression" is not an option â€” a stall escalates to the deterministic
    fallback summary on the FIRST timeout instead of waiting for a prior stall in the session (#114594).r   zwrun_compress_context_with_progress_timeout requires idle_timeout_seconds > 0; call compress_context directly to disablec                 ó,   •— t        ‰ «      r ‰ «       S ‰ S rý   )r´   )r®  s   €r   Ú_resolve_fallback_promptzLrun_compress_context_with_progress_timeout.<locals>._resolve_fallback_promptŸ  s   ø€ Ü+3Ð4JÔ+KÑ%Ó'ÐgÐQgÐgrO   Nr9   )Úpropagate_context_to_threaduþ   Context compression pool saturated (%d workers busy) â€” refusing new compression this cycle and continuing without compression. Wedged workers are fence-cancelled and free their slot when they return; if this persists, check the summary provider health.ÚabortedÚpool_saturated©rs  Úcommit_statusÚsplit_statusÚfailure_classc                ó´   •— | j                   rt        j                  j                  d«      ‚| j                  rt
        j                  d«       ‰dfS  ‰| «      S )Nz0compression deadline expired before worker startz<Skipping stale compression job: fence cancelled before startrD   )rþ   rB  rC  rD  r  r   rT   )Úworker_fencerz  r­  s    €€r   Ú_fence_gated_workerzGrun_compress_context_with_progress_timeout.<locals>._fence_gated_workerÍ  sQ   ø€ ð ×)Ò)Ü×$Ñ$×1Ñ1Ð2dÓeÐeØ×$Ò$Ü�K‰KÐVÔWØ˜R�<ÐÙ�lÓ#Ð#rO   F)ri  rj  rÀ  Tz.compress_context timeout-cause callback failedr   )rj  rÀ  r§  )rÔ  rj  )
r­  rz  r®  rp  rò   r§  r¨  r©  rª  r›  z(compress_context timeout callback failedzpContext compression made no progress for %.1fs (total wait %.1fs, ceiling %.1fs); continuing without compression)r1  rG   )rä  rß   ) rõ   r·   r¶   rß   rð   r¡  Útools.thread_contextrÜ  r\  rP  r   rÊ   rO  Ú#_emit_compression_attempt_telemetryr¸   r¹   ÚsubmitÚBaseExceptionrS  Úadd_done_callbackrÅ  r$  Úcancelrþ   r  r    rû   rÑ  rÍ  rÕ  r  r²  )r­  rz  r®  rp  rò   rÖ  r¨  r§  r¶  r©  r·  rª  r×  rØ  rÛ  rj  ri  r›  rÜ  r[  rå  rG  rÀ  Úhandled_exitÚsettledrA  rÔ  rÁ  rÃ  r±  s   ```                           r   r¸  r¸  ‡  sq  ú€ ð$ ˜qÒ ÜðRó
ð 	
õ
hô ”%Ð-Ó.´Ð6JÓ0KÓL€GÜÐ%Ó&€Dñ ØˆØÐ&‰EÔ,BÓ,D€EØ	×#Ñ# GÔ,ð
 ,ò ØÒOÔ"9¸/Ó"JÈaÑ"Oð õ
 AÜ-Ó/€Hô &Ô'Ü�‰ðZô +ô		
ð Ð&Ü/Ø¬D¯N©NÓ,<ÈIÐdmØ.õð Ñ1Ó3Ð3Ð3ö$ðØ—‘Ñ!<Ð=PÓ!QÐSXÓYˆð ×ÑÔ;Ô<Ü—>‘>Ó#€Lð €LðE,Ü5Ø�E ¨gÀLô
‰ˆ�ñ ØˆLØñx ð ×)Ñ)Õ+ð ðq 	�‰ŒÜŸ.™.Ó*¨\Ñ9¸WÑDÒ_È×H_ÑH_ˆñ ð ×;Ñ;Ô=ØÐ'ÜÐJÐUYÔZñ KÙ  °%×2IÑ2IÔJ÷Kä% eÔ,Ü,Ø °lÐVgôˆFð  ˆLØñD ð ×)Ñ)Õ+ð ð= ˆÜ! &¨%ÀÐZaÕbÜ—‘Ó! LÑ0ˆð ×5Ñ5Ó7ˆñ Ü<Ø&Ò0¨&¸8Ð\rØ%)ÀÐ\mØ!1À?Ð^gØ'=ô	ˆIð Ð$Ø ñ ð ×)Ñ)Õ+ð ð Ð!ÜÐDÈtÔTñ 9Ù˜4 ¨Ô8÷9ð 9ô �N‰NðØ-¨v°wôð Ñ1Ó3Ð3áð ×)Ñ)Õ+ð øôU ò Ü&Ô(Øðú÷BKñ Kú÷<9ð 9ûñ ð ×)Ñ)Õ+ð ús\   Ã%J< Ä)K- ÅAK- Æ.KÇ%K- Ç;AK- É%K- É4K!É?)K- Ê<KËKËK- Ë!K*Ë&K- Ë-Lc                  ó   — e Zd ZdZy)Ú CompressionCheckpointUnavailablezGRaised when required durable pre-compress checkpointing is unavailable.N©r7  r8  r9  r:  r<  rO   r   rï  rï  +  s   „ ÚQrO   rï  zlset compression.checkpoint_required: false, or switch to a memory provider that implements checkpoint API v2c                óR  — t        | dd«      }|€yt        |dd«      }g }|�a	 t        |«      }|D ]P  }t        |dd«      }t        |t        «      sŒ!|j                  «       sŒ2|j                  |j                  «       «       ŒR |rdj                  |«      S dS # t        $ r g }Y Œww xY w)zBHuman-readable active provider name, or an explicit none sentinel.Ú_memory_managerNzno active providerÚ	providersr€   z, )r2   r'   rz   r&   rG   rH   rš  Újoin)r4   Úmemory_managerró  ÚnamesÚiterabler‹  r€   s          r   Ú_active_memory_provider_labelrø  7  s³   € ä˜UÐ$5°tÓ<€NØÐØ#Ü˜¨°TÓ:€IØ€EØÐð	Ü˜I“ˆHð !ò 	+ˆHÜ˜8 V¨TÓ2ˆDÜ˜$¤Õ$¨¯©­Ø—‘˜TŸZ™Z›\Õ*ð	+ñ  %ˆ4�9‰9�UÓÐ>Ð*>Ð>øô ò 	ØŠHð	ús   £B ÂB&Â%B&c                ó   — t        d| › �«      S )NzLBLOCKED_MISSING_PREREQUISITE: required pre-compress checkpoint unavailable: )rï  ©Úreasons    r   Ú_checkpoint_blockedrü  J  s   € Ü+Ø
VÐW]ÐV^Ð_óð rO   c                ó*   — t        | › dt        › �«      S )uï   Capability refusal: the gate can never pass with this provider set, so the
    message carries the config-level way out. Transient checkpoint failures keep
    the plain form â€” there the provider is capable and the right move is a retry.z. Recover by )rü  Ú _CHECKPOINT_REQUIRED_REMEDIATIONrú  s    r   Ú_checkpoint_incapablerÿ  P  s   € ô  & ¨Ô7WÐ6XÐYÓZÐZrO   c                óP  — t        | dd«      duryt        | dd«      }|�0t        |dd«      }t        |«      r	 t         |t        «      «      ry	 t
        j                  d	t        | «      t        t        «       y# t        $ r"}t
        j                  d|d¬«       Y d}~yd}~ww xY w)
u€  Startup warning when fail-closed compress will block (init itself must not refuse).

    Capability-probe exceptions are suppressed so a broken provider cannot crash
    agent construction â€” same fail-open style as the micro-compact warning.
    Probe failures log at DEBUG so a flaky probe can be diagnosed without
    refusing init or emitting the incapable-provider WARNING.
    Úcompression_checkpoint_requiredFTNrò  Ú supports_pre_compress_checkpointz?checkpoint-required capability probe failed; init continues: %sr   zŸcompression.checkpoint_required is enabled but the active memory provider (%s) does not implement checkpoint API v%s. Compress will fail closed. Recover by %s.)
r2   r´   rV   r   r   r   r   rÊ   rø  rþ  )r4   rõ  Úsupports_checkpointr   s       r   Ú2_warn_checkpoint_required_without_capable_providerr  W  s¹   € ô ˆuÐ7¸Ó?ÀtÑKØÜ˜UÐ$5°tÓ<€NØÐ!Ü% nÐ6XÐZ^Ó_ÐÜÐ'Ô(ð	ÜÑ+Ô,OÓPÔQØð Rô ‡N�Nð	&ô 	& eÓ,Ü+Ü(õøô ò Ü—‘ØUØØ!ð ô ô
 ûðús   ¹A: Á:	B%ÂB Â B%c                ó’   — 	 ddl m} t        «       }t        | «      |u xr t	        j
                  |d|«      |u S # t        $ r Y yw xY w)zìWhether the live in-memory SessionDB class structurally predates locks.
    Only the exact old ``hermes_state.SessionDB`` class (hot-reload skew) may fail open; proxies, lookalikes,
    non-callables and descriptor failures fail closed.r   )Ú	SessionDBÚtry_acquire_compression_lockF)Úhermes_stater  Úobjectr³   ÚinspectÚgetattr_staticr   )Úlock_dbr  Úmissings      r   Ú!_lock_api_is_absent_on_session_dbr  y  sV   € ðÝ*Ü“(ˆä�‹M˜YÐ&ò fÜ×&Ñ& yÐ2PÐRYÓZÐ^eÐeð	
øô ò Ùðús   ‚7: º	AÁA©Úinclude_cooldownc               ó
  — di fdi fg}|r|j                  ddddif«       |D ]1  \  }}t        t        | «      |d«      }t        |«      sŒ(	  || fi |¤Ž Œ3 y# t        $ r!}t
        j                  d||«       Y d}~ŒZd}~ww xY w)	zFRefresh durable automatic-compression guards on a built-in compressor.Ú!_load_fallback_compression_streakÚ#_load_ineffective_compression_countr   rÙ   r×   TNz)compression guard refresh failed (%s): %s)Úinsertr2   r³   r´   r   r   r   )r~   r  Úmethod_callsÚmethod_nameÚkwargsÚmethodr   s          r   Ú%_refresh_persisted_compression_guardsr  ˆ  s§   € à8¸"Ð=Ð@eÐgiÐ?jÐk€LÙØ×Ñ˜AÐ IÈIÐW[ÐK\Ð]Ô^Ø+ò XÑˆ�VÜœ˜jÓ)¨;¸Ó=ˆÜ˜ÔØð	XÙ�:Ñ( Ó(ñXøô ò 	XÜ�L‰LÐDÀkÐSV×WÑWûð	Xús   Á	AÁ	BÁ!A=Á=Bc                óÄ   — t        t        | «      dd«      }t        |«      sy || |«      }t        |xr) |j	                  d«      duxr |j	                  d«      dk(  «      S )zDReturn whether another path already rotated this compression parent.Úget_sessionNFÚended_atÚ
end_reasonr_  )r2   r³   r´   rV   r¡   )r½   r¾   ÚgetterÚsessions       r   Ú#_session_was_rotated_by_compressionr   —  s_   € ä”T˜*Ó% }°dÓ;€FÜ�FÔØÙ�Z Ó,€GÜ�Òn˜GŸK™K¨
Ó3¸4Ð?ÒnÀGÇKÁKÐP\ÓD]ÐanÑDnÓoÐorO   )râ  Úcommit_started_atc          	     óŒ  — t        d«      5  | j                  }t        |dd«      }t        |t        «      si }t	        |«      }|j                  dd«       |j                  dt        | dd«      xs t        j                  «       j                  «       |j                  d	t        | d	d«      xs d«       |j                  t        t        j                  «       |z
  d
z  «      ||¬«       |�5t        dt        t        j                  «       |z
  d
z  «      «      x|d<   |d<   |r||d<   |j                  dd«       |j                  dd«       t        |j                  d«      xs t        |dd«      xs t        |dd«      «      |d<   t         j#                  dt%        j&                  |dd¬«      «       ddd«       y# 1 sw Y   yxY w)z>Emit one content-free JSON log line for a compression attempt.z0failed to emit compression attempt telemetry: %srt   NÚeventÚcompression_attemptÚ
attempt_idÚ_compression_attempt_idrD   r¾   éè  )Útotal_duration_msrà  rá  r   Ú	commit_msrâ  ÚchunkingFÚchunk_countÚfallback_usedrh   rp   z)context compression attempt telemetry: %sT)ú,r€  )Ú	sort_keysÚ
separators)r    rw  r2   r&   r(   Ú
setdefaultÚuuidÚuuid4ÚhexÚupdater‘   r¸   r¹   r·   rV   r¡   r   rT   ÚjsonÚdumps)	r4   rs  rà  rá  râ  r!  r~   Ú	telemetryÚpayloads	            r   rç  rç     s®  € ô
 
ÐDÓ	Eñ 
Ø×-Ñ-ˆ
Ü˜JÐ(EÀtÓLˆ	Ü˜)¤TÔ*ØˆIÜ�y“/ˆØ×Ñ˜7Ð$9Ô:Ø×Ñ˜<¬°Ð8QÐSUÓ)VÒ)jÔZ^×ZdÑZdÓZf×ZjÑZjÔkØ×Ñ˜<¬°¸ÀbÓ)IÒ)OÈRÔPØ�‰Ü!¤4§>¡>Ó#3°jÑ#@ÀDÑ"HÓIÐYfØ%ð 	ô 	
ð Ð(Ü<?ÀÄ3ÌÏÉÓHXÐ[lÑHlÐptÑGtÓCuÓ<vÐvˆI�kÑ" W¨[Ñ%9ÙØ'4ˆG�OÑ$Ø×Ñ˜: uÔ-Ø×Ñ˜=¨!Ô,Ü#'Ø�K‰K˜Ó(ò JÜ�zÐ#@À%ÓHòJä�zÐ#BÀDÓIó$
ˆ�Ñ ô
 	�‰Ø7¼¿¹ÀGÐW[ÐhrÔ9sô	
÷1
÷ 
ñ 
ús   ŒF%F:Æ:Gc                óB   — t        | dd«      xs | j                  |«      S )zLCached system prompt, or a fresh build when nothing is cached (abort paths).Ú_cached_system_promptN)r2   Ú_build_system_prompt)r4   Úsystem_messages     r   Ú_existing_system_promptr=  Â  s#   € ä�5Ð1°4Ó8Òf¸E×<VÑ<VÐWeÓ<fÐfrO   c                ó$   — t        | |dd|¬«       y )NrÝ  rß  )rç  )r4   rs  râ  s      r   Ú_emit_aborted_attempt_telemetryr?  Ç  s   € Ü'Ø˜*°IÈIÐerörO   c                óF   — |�| |k7  rt        j                  |«      | dd yyy)zLPut the pre-compression deep snapshot back into the live list if it drifted.N)r|   r}   )rz  rº   s     r   Ú_restore_messages_snapshotrA  Í  s)   € àÐ ¨HÒ 4Ü—m‘m HÓ-ˆ‘‰ð !5ÐrO   c                ó"   — d|v r|d   | _         yy)zöRestore ONLY the prune runway from the attempt snapshot.
    compress() zeroes it in memory while the durable copy only clears on a successful commit; a kept
    transcript keeps its cached prefix, and 0 would let the next prune break that cache.rw   N)rw   )r~   rº   s     r   Ú_restore_prune_rearm_tokensrC  Ó  s   € ð '¨(Ñ2Ø3;Ð<[Ñ3\ˆ
Õ0ð 3rO   c                óH   — t        | dd«      }|du xs t        |t        «      S )a*  Type-pinned read of the per-session lock-skip signal.
    ``agent._compression_skipped_due_to_lock`` is a holder string or ``True`` when a pass no-oped because the
    lock was held, ``None`` otherwise. Pinning avoids MagicMock auto-attributes hijacking mocked agents into
    the lock-skip branch.Ú _compression_skipped_due_to_lockNT)r2   r&   rG   ©r4   Ú_sigs     r   Úcompression_skipped_due_to_lockrH  Û  s)   € ô
 �5Ð<¸dÓC€DØ�4ˆ<Ò0œ: d¬CÓ0Ð0rO   c               ó|  — 	 t        | «      }|j                  dt        j                  «       «      }|5  |j                  d«      }|r3t        |t        j                  «      st        j                  «       }||d<   |t        |t        j                  «      r|ndfcddd«       S # t        $ r Y yw xY w# 1 sw Y   yxY w)zCReturn the stable lock and thread-local timeout state for an agent.NÚ'_context_compression_timeout_state_lockÚ"_context_compression_timeout_state)ry   rz   r0  r‰   rŠ   r¡   r&   Úlocal)r4   ÚcreateÚ
attributesr�   Ústates        r   Ú&_get_context_compression_timeout_staterP  ä  s¯   € ðÜ˜%“[ˆ
ð × Ñ Ð!JÌIÏNÉNÓL\Ó]€DØ	ñ KØ—‘ÐCÓDˆÙœ* U¬I¯O©OÔ<Ü—O‘OÓ%ˆEØ?DˆJÐ;Ñ<Øœj¨´	·±Ô@‘UÀdÐJ÷Kñ Køô ò Ùðú÷Kð Kús   ‚B# ³A&B2Â#	B/Â.B/Â2B;c                óŠ   — t        | d¬«      xs d\  }}|€|| _        y|5  ||_        || _        ddd«       y# 1 sw Y   yxY w)z½Write this thread's owned-compression timeout outcome.
    The ``agent._last_compression_timed_out`` mirror stays authoritative for minimal agent doubles that do not
    support ``vars()``.T©rM  rÓ   N)rP  Ú_last_compression_timed_outÚ	timed_out)r4   rT  r�   rO  s       r   Ú(_set_context_compression_timeout_outcomerU  õ  sQ   € ô 9¸ÀtÔLÒ\ÐP\�K€Dˆ%Ø€}Ø,5ˆÔ)ØØ	ñ 6Ø#ˆŒØ,5ˆÔ)÷6÷ 6ñ 6ús	   ¡9¹Ac                ó   — t        | d«       y)z=Clear the current thread's owned-compression timeout outcome.FN©rU  ©r4   s    r   Ú)reset_context_compression_timeout_outcomerY    s   € ä,¨U°EÕ:rO   c                ó   — t        | d«       y)z5Mark the current owned compression as host-timed-out.TNrW  rX  s    r   Ú"mark_context_compression_timed_outr[    s   € ä,¨U°DÕ9rO   c                óÜ   — t        | d¬«      }|�C|\  }}|5  t        |t        j                  «      rt	        |dd«      du cddd«       S 	 ddd«       t	        | dd«      du S # 1 sw Y   ŒxY w)zâReturn whether this thread's owned compression hit its host timeout.
    Thread-local so overlapping automatic/manual entrypoints cannot hide each other's timeout; attribute
    fallback for minimal doubles; reads type-pinned.FrR  NrT  TrS  )rP  r&   r‰   rL  r2   )r4   Úlocked_stater�   rO  s       r   Úcontext_compression_timed_outr^    s€   € ô :¸%ÈÔN€LØÐØ"‰ˆˆeØñ 	AÜ˜%¤§¡Ô1Ü˜u k°4Ó8¸DÐ@÷	Añ 	AØ1÷	Aô �5Ð7¸Ó>À$ÐFÐF÷	Að 	Aús   —)A"Á"A+c               ó‚  — | j                   }t        ||¬«       t        t        |«      dd«      }t	        |«      syd}|rHt        j                  t        t        «      5  dt        j                  |«      j                  v }ddd«       t        |r
 ||d¬«      n ||«      «      }|rt        | |«       |S # 1 sw Y   Œ6xY w)a:  Refresh durable guards, then evaluate the compressor's automatic breaker gate.
    ``bypass_cooldown`` ignores the cooldown when the gate accepts ``ignore_cooldown`` (engines predating it get the
    legacy no-argument call). When blocked, the transient-block signal is published for automatic-path consumers.
    r  Ú_automatic_compression_blockedNFÚignore_cooldownT)ra  )rw  r  r2   r³   r´   r‹   r˜   rz   rõ   r
  Ú	signatureÚ
parametersrV   Ú#_mark_compression_blocked_transient)r4   Úbypass_cooldownr  r~   ÚblockedÚacceptsrA  s          r   Ú"_automatic_compression_gate_blocksrh    s²   € ð
 ×)Ñ)€JÜ)¨*ÐGWÕXÜ”d˜:Ó&Ð(HÈ$ÓO€GÜ�GÔØØ€GÙÜ× Ñ ¤¬JÓ7ñ 	QØ'¬7×+<Ñ+<¸WÓ+E×+PÑ+PÐPˆG÷	Qä¹w‘'˜*°dÕ;ÉGÐT^ÓL_Ó`€FÙÜ+¨E°:Ô>Ø€M÷	Qð 	Qús   Á"B5Â5B>c                óV   — t        | dd«      }t        |t        «      xr t        |«      S )uo  Type-pinned read of the transient-block signal.
    Set when an automatic pass no-ops on a TRANSIENT guard (summary-failure cooldown or structural backoff).
    Consumers must defer, not count it toward ``compression_exhausted``, or an overflow auto-reset wipes a
    session that was merely cooling down. The permanent ``ineffective`` breaker never sets it.

    See #97488.
    Consumers (the overflow-recovery loops in ``conversation_loop``) must treat such a no-op as a temporary
    defer, NOT as evidence the session is incompressible: counting it toward ``compression_exhausted`` lets
    a real upstream ``context_length_exceeded`` auto-reset (wipe) a session whose compression was merely
    cooling down (#97488). The permanent ``ineffective`` breaker intentionally does NOT set this signal â€” a
    genuinely incompressible session must still be able to exhaust.
    Ú_compression_blocked_transientN)r2   r&   rG   rV   rF  s     r   Úcompression_blocked_transientlyrk  -  s)   € ô �5Ð:¸DÓA€DÜ�dœCÓ Ò/¤T¨$£ZÐ/rO   c           
     óÈ  — t        |dd«      }d}t        |«      rt        dd¬«      5   |«       }ddd«       t        |t        «      rƒ|j                  d«      s|j                  d«      r`t        j                  d|t        | d	d«      xs d
t        |dd«      xs d«       t        j                  t        «      5  || _        ddd«       yyy# 1 sw Y   Œ�xY w# 1 sw Y   yxY w)zâPublish the transient-block signal when the active guard is transient.
    Classification comes from ``_compression_block_reason``: ``cooldown:*`` and ``structural_backoff:*`` are
    transient; ``ineffective`` stays unmarked.Ú_compression_block_reasonNz$compression block-reason read failedTr   ÚcooldownÚstructural_backoffu¯   Skipping automatic compression re-entry: transient guard active (%s, session=%s, last failure: %s) â€” will retry after the backoff lapses; /compress forces an immediate retryr¾   r‚  rd   Úunknown)r2   r´   r    r&   rG   Ú
startswithr   rT   r‹   r˜   r   rj  )r4   r~   Ú	reason_fnrû  s       r   rd  rd  >  sà   € ô ˜
Ð$?ÀÓF€IØ€FÜ�	ÔÜÐ<ÀtÔLñ 	!Ù“[ˆF÷	!ä�&œ#Ô F×$5Ñ$5°jÔ$AÀV×EVÑEVÐWkÔElÜ�‰ðFàGMÜ�E˜<¨Ó.Ò8°&Ü�JÐ 5°tÓ<ÒIÀ	ô	
ô × Ñ ¤Ó+ñ 	:Ø39ˆEÔ0÷	:ð 	:ð FmÐ÷	!ð 	!ú÷	:ð 	:ús   ¨CÂ9CÃCÃC!c                óÞ   — 	 ddl m}  || «       t        j                  t        «      5  ddlm}  || «       ddd«       y# t        $ r | t        j                  d<   Y ŒOw xY w# 1 sw Y   yxY w)zOPoint the worker thread's session ContextVar and log context at ``session_id``.r   )Úset_current_session_idÚHERMES_SESSION_ID)Úset_session_contextN)	Úgateway.session_contextrt  r   ÚosÚenvironr‹   r˜   Úhermes_loggingrv  )r¾   rt  rv  s      r   Ú_rebind_session_contextr{  S  sg   € ð5ÝBÙ˜zÔ*ô 
×	Ñ	œYÓ	'ñ (Ý6Ù˜JÔ'÷(ð (øô ò 5Ø*4Œ�
‰
Ð&Ó'ð5ú÷(ð (ús   ‚A ©A#ÁA ÁA Á#A,c                ó  — t        t        |«      dd«      }t        t        |«      dd«      }t        t        |«      dd«      }t        |«      rt        |«      rt        |«      sy |||«      }|rt        |«      t        |«      k(  ryt        |«      } |||«      }t	        |t
        «      r|j                  d«      �y |||«      }	t	        |	t        «      r|	sy |||«      }
|
rt        |
«      |k7  ry|| _        t        |«       d| _
        |j                  d«      r
|d   | _        t        |	«      | _        || _        |	D �ch c]  }t	        |t
        «      sŒt        |«      ’Œ  c}| _        t        | j"                  dd«      }t        |«      r=t%        d	«      5   ||d
||t        | dd«      xs dt        | dd«      ¬«       ddd«       nNt        | j"                  dd«      }t        |«      r,t'        j(                  t*        «      5   |||¬«       ddd«       t%        d«      5  | j,                  r| j,                  j/                  ||dd
¬«       ddd«       |	S c c}w # 1 sw Y   ŒOxY w# 1 sw Y   Œ[xY w# 1 sw Y   |	S xY w)u  Move a stale compression contender onto the live continuation tip.
    Resolve and load first, then mutate the agent, so ambiguous lineage or an unreadable handoff fails closed.
    Uses the transitive ``get_compression_tip`` walk; a tip is adopted only while its row is still live.

    Resolution uses the canonical transitive walk ``get_compression_tip`` so a lineage with >=2 compression
    hops (root -> mid -> tip) recovers to the live tip â€” the depth-1 ``find_live_compression_child`` lookup
    this used to call finds no live *direct* child in that shape and skipped recovery (#82001). The tip walk
    returns the input id when no continuation exists, and a resolved tip is adopted only while its row is
    still live â€” both cases fail closed exactly as before.
    Úget_compression_tipNr  Úget_messages_as_conversationr  TÚsystem_promptÚon_session_startz4context engine compression-child adoption failed: %sr_  ÚplatformÚcliÚ_gateway_session_key)Úboundary_reasonÚold_session_idr½   r�  Úconversation_idÚbind_session_state)r½   r¾   z4memory manager compression-child adoption failed: %sF©Úparent_session_idÚresetrû  )r2   r³   r´   rG   r&   r(   r¡   r'   r¾   r{  Ú_session_db_createdr:  ry  Ú_last_flushed_db_idxÚ_flushed_db_message_session_idÚidÚ_flushed_db_message_idsrw  r    r‹   r˜   r   rò  Úon_session_switch)r4   r½   r‰  ÚresolverÚ
row_getterÚloaderÚtipÚchild_session_idÚchildr±  Ú	confirmedr   r€  Ú
bind_states                 r   Ú_adopt_live_compression_childr™  _  ss  € ô ”t˜JÓ'Ð)>ÀÓE€HÜœ˜jÓ)¨=¸$Ó?€JÜ”T˜*Ó%Ð'EÀtÓL€FÜ�HÔ¤X¨jÔ%9ÄÈ&ÔAQØÙ
�:Ð0Ó
1€CÙ”#�c“(œcÐ"3Ó4Ò4ØÜ˜3“xÐÙ�zÐ#3Ó4€EÜ�eœTÔ" e§i¡i°
Ó&;Ð&GØÙ�zÐ#3Ó4€IÜ�y¤$Ô'©IØñ ˜Ð%6Ó7€IÙœ˜I›Ð*:Ò:ØØ'€EÔÜÐ,Ô-Ø $€EÔØ‡y�y�Ô!Ø&+¨OÑ&<ˆÔ#Ü!$ Y£€EÔØ+;€EÔ(Ø@IÖ$g°WÌZÐX_ÔaeÕMf¤R¨¥[Ò$g€EÔ!Ü˜u×7Ñ7Ð9KÈTÓRÐÜÐ Ô!ÜÐLÓMñ 	ÙØ °-ÐPaØ%´¸¸zÈ4Ó0PÒ0YÐTYÜ '¨Ð/EÀtÓ Lõ÷	ð 	ô ˜U×5Ñ5Ð7KÈTÓRˆ
Ü�JÔÜ×$Ñ$¤YÓ/ñ OÙ jÐ=MÕN÷Oä	ÐHÓ	Iñ Ø× Ò Ø×!Ñ!×3Ñ3Ø Ð4EÈUÐ[hð 4ô ÷ð
 Ðùò' %h÷	ð 	ú÷Oð Oú÷ð
 Ðús0   ÅIÅIÆ)I!ÈI-È&,I9É!I*É-I6É9Jc                óä   — t        t        | «      dd«      }t        |«      sy	  || |«      rt        j	                  d|«       yy# t
        $ r!}t        j	                  d||«       Y d}~yd}~ww xY w)zOReopen a compression-ended parent that has no continuation and no lease holder.Ú#reopen_orphaned_compression_sessionNzGcompression recovery: reopened orphaned session=%s with no continuationz5orphaned compression session reopen failed for %s: %s)r2   r³   r´   r   rÊ   r   )r½   r¾   Úorphan_reopenerr   s       r   Ú_reopen_orphaned_parentr�  �  so   € äœd :Ó.Ð0UÐW[Ó\€OÜ�OÔ$ØðaÙ˜: zÔ2Ü�N‰NÐdÐfpÕqð 3øäò aÜ�‰ÐNÐPZÐ\_×`Ñ`ûðaús   ¤A Á	A/ÁA*Á*A/c                óÊ  — t        | dd«      }t        | dd«      xs d}|�|sy	 t        ||«      syt        |dd«      }t        d«      D ]V  }t        | ||«      }|�|c S t	        |«      r ||«      nd}|st        ||«        y|dk(  r yt        j                  d«       ŒX y# t        $ r5}t        j                  d	|t        |«      j                  |«       Y d}~yd}~ww xY w)
zFRecover a stale live agent before a new turn writes to its old parent.r­   Nr¾   rD   Úget_compression_lock_holderé   é   rÇ  z;compression session recovery failed for session=%s (%s: %s))r2   r   Úranger™  r´   r�  r¸   rÏ  r   r   rÊ   r³   r7  )r4   r½   r¾   Úholder_getterr;   r±  Úholderr   s           r   Ú#recover_rotated_compression_sessionr¥  ©  sô   € ä˜ ¨tÓ4€JÜ˜ ¨dÓ3Ò9°r€JØÐ¡ØðÜ2°:¸zÔJØô   
Ð,IÈ4ÓPˆÜ˜R“yò 
	ˆGÜ5°e¸ZÈÓTˆIØÐ$Ø Ò Ü2:¸=Ô2I‘] :Ô.ÈtˆFÙÜ'¨
°JÔ?ÙØ˜"Š}ÙÜ�J‰J�tÕð
	ð øÜò Ü�‰ØIÈ:ÔW[Ð\_ÓW`×WiÑWiÐknô	
ô ûð	ús.   ¥B$ ²-B$ Á $B$ ÂB$ ÂB$ Â$	C"Â-+CÃC"c           
     ó¸   — dt        j                  «       › dt        j                  «       › dt	        | «      d›dt        j                  «       j                  dd › �S )záBuild a unique lock holder id: ``pid:tid:agent-instance:uuid``.
    pid+tid tell crashed holders apart in diagnostics; instance id and per-acquire uuid disambiguate
    co-resident agents on one thread or pooled compressions.zpid=z:tid=z:agent=Úxz:nonce=Né   )rx  Úgetpidr‰   Ú	get_identrŽ  r1  r2  r3  rX  s    r   Ú_compression_lock_holderr«  È  sS   € ð ”"—)‘)“+�˜e¤I×$7Ñ$7Ó$9Ð#:¸'Ä"ÀUÃ)ÈAÀÈgÔVZ×V`ÑV`ÓVb×VfÑVfÐgiÐhiÐVjÐUkÐlÐlrO   )re  c               ó>  — |||dœ}|rd|d<   |r||d<   	 t        j                  | «      j                  }t        d„ |j                  «       D «       «      r|S |j                  «       D ��	ci c]  \  }}	||v sŒ||	“Œ c}	}S # t        t        f$ r d|icY S w xY wc c}	}w )zÈReturn only compression kwargs accepted by an engine callable.
    Inspecting first keeps older plugin signatures compatible without catching ``TypeError`` and running a
    stateful compressor twice.)Úcurrent_tokensÚfocus_topicÚforceTre  Úmemory_contextr­  c              3  óh   K  — | ]*  }|j                   t        j                  j                  u –— Œ, y ­wrý   )Úkindr
  Ú	ParameterÚVAR_KEYWORD)Ú.0Ú	parameters     r   ú	<genexpr>z0_supported_compression_kwargs.<locals>.<genexpr>á  s%   è ø€ Ò
`¸yˆ9�>‰>œW×.Ñ.×:Ñ:Ô:Ñ
`ùs   ‚02)r
  rb  rc  rz   rõ   Úanyr   r)   )
Úcompress_fnr­  r®  r¯  r°  re  Ú
candidatesrc  r€   rÎ   s
             r   Ú_supported_compression_kwargsr»  Ï  s¸   € ð %3À;ÐY^Ñ_€JÙØ(,ˆ
Ð$Ñ%ÙØ'5ˆ
Ð#Ñ$ð2Ü×&Ñ& {Ó3×>Ñ>ˆ
ô
 Ñ
`ÈJ×L]ÑL]ÓL_Ô
`Ô`ØÐØ+5×+;Ñ+;Ó+=×T™K˜D %ÀÈÒASˆD�%‰KÓTÐTøô ”zÐ"ò 2ð ! .Ð1Ò1ð2üó Us   –B  Á*BÁ7BÂ BÂBc                  óp   — e Zd ZdZ	 ddddœ	 	 	 	 	 	 	 	 	 dd„Zdd„Zddd„Zdd„Zddd	œdd
„Zdd„Z	dd„Z
y)Ú_CompressionActivityHeartbeatzMRefresh the agent inactivity tracker while compression blocks in an aux call.NF)Úemit_client_statusrr  c               óx  — || _         || _        d| _        |€t        |dd«      }	 t	        |xs d«      }t        j                  |«      sd}t        d|«      | _
        || _        t        j                  «       | _        t        j                  | j                   dd¬«      | _        y # t        t        f$ r d}Y Œlw xY w)NFÚ(_compression_activity_heartbeat_intervalç      N@çš™™™™™¹?zcompression-activity-heartbeatT©Útargetr€   Údaemon)Ú_agentÚ_commit_fenceÚ_suppressedr2   r¶   ÚmathÚisfiniterz   rõ   r·   Ú_interval_secondsÚ_emit_client_statusr‰   rå   Ú_stopÚThreadÚ_runÚ_thread)rñ   r4   Úinterval_secondsr¾  rr  s        r   ró   z&_CompressionActivityHeartbeat.__init__é  s¿   € ð ˆŒØ)ˆÔð !ˆÔØÐ#Ü& uÐ.XÐZ^Ó_Ðð	$Ü$Ð%5Ò%=¸Ó>ÐÜ—=‘=Ð!1Ô2Ø#'Ð ô "% SÐ*:Ó!;ˆÔð $6ˆÔ Ü—_‘_Ó&ˆŒ
Ü ×'Ñ'¨t¯y©yÐ?_ÐhlÔmˆ�øô œ:Ð&ò 	$Ø#Òð	$ús   ¦&B% Â%B9Â8B9c                ón   — d| _         | j                  dd¬«       | j                  j                  «        | S )NFzcontext compression startedT)Úallow_terminal_overwrite)rÈ  Ú_touchrÐ  Ústartrø   s    r   rÕ  z#_CompressionActivityHeartbeat.start  s2   € ð !ˆÔØ�‰Ð1ÈDˆÔQØ�‰×ÑÔØˆrO   c                ó,  — | j                   j                  «        | j                  j                  «       r<t	        j
                  «       | j                  ur| j                  j                  d¬«       | j                  «       ry | j                  |d¬«       y )Nç      ð?r?  T)Úforce_persist)	rÍ  r  rÐ  Úis_aliver‰   Úcurrent_threadrô  Ú_should_suppressrÔ  )rñ   Údescs     r   Ústopz"_CompressionActivityHeartbeat.stop
  sl   € Ø�
‰
�‰ÔØ�<‰<× Ñ Ô"¤y×'?Ñ'?Ó'AÈÏÉÑ'UØ�L‰L×Ñ cÐÔ*ð × Ñ Ô"Øð 	�‰�D¨ˆÕ-rO   c                ó„   — | j                   s)| j                  �| j                  j                  rd| _         | j                   S ©NT)rÈ  rÇ  r  rø   s    r   rÛ  z._CompressionActivityHeartbeat._should_suppress  s8   € Ø×Ò D×$6Ñ$6Ð$BÀt×GYÑGY×GfÒGfØ#ˆDÔØ×ÑÐrO   )rÓ  rØ  c               ó   — t        dd¬«      5  |sS| j                  «       r
	 d d d «       y t        t        | j                  dd «      «      }|t
        v rd| _        	 d d d «       y t        | j                  dd «      }t        |«      r5|s| j                  «       r
	 d d d «       y  ||t        j                  |¬«       d d d «       y # 1 sw Y   y xY w)Nz+compression activity heartbeat touch failedTr   Ú_last_activity_provenanceÚ_touch_activity)Ú
provenancerØ  )
r    rÛ  r   r2   rÆ  Ú!_TERMINAL_COMPRESSION_PROVENANCESrÈ  r´   r   ÚAGENT_COMPRESSION)rñ   rÜ  rÓ  rØ  ÚcurrentÚtouchs         r   rÔ  z$_CompressionActivityHeartbeat._touch  sÐ   € ÜÐCÈdÔSñ 	jÙ+Ø×(Ñ(Ô*Ø÷	jð 	jô 8¼ÀÇÁÐMhÐjnÓ8oÓp�ØÔ?Ñ?Ø'+�DÔ$Ø÷	jð 	jô ˜DŸK™KÐ):¸DÓAˆEÜ˜Œñ 0°D×4IÑ4IÔ4KØ÷	jð 	jñ �dÔ'9×'KÑ'KÐ[hÕi÷	j÷ 	jñ 	jús   ŽC«0CÁ$5CÂ"CÃCc                óÊ   — | j                   syt        | j                  dd«      }t        |«      sy	  |t        «       y# t
        $ r t        j                  dd¬«       Y yw xY w)u<  Re-publish the compacting status so remote transports see progress.

        Compression can stream for minutes with no deltas, tool events, or
        status lines reaching remote transports. Idle-progress watchdogs on
        those clients (e.g. the Android relay app's 180s turn watchdog)
        treat the silence as a dead turn and fire ``session.interrupt`` â€”
        killing a healthy compression mid-flight and rolling back its work,
        which retriggers on the next prompt and loops forever on sessions
        near the context ceiling (#98371).

        Routed through ``agent._emit_status`` like every other compaction
        status: same "lifecycle" key (the TUI gateway re-tags it to
        ``compacting``; Telegram edits one bubble per key), same chat-platform
        filter, same CLI print path.
        NÚ_emit_statusz*status emit error in compression heartbeatTr   )rÌ  r2   rÆ  r´   ÚCOMPACTION_HEARTBEAT_STATUSr   r   r   )rñ   Úemits     r   Ú_emit_progress_statusz3_CompressionActivityHeartbeat._emit_progress_status,  s_   € ð  ×'Ò'ØÜ�t—{‘{ N°DÓ9ˆÜ˜Œ~Øð	ÙÔ,Õ-øÜò 	Ü�L‰LØ<Àtð ö ð	ús   ²? ¿ A"Á!A"c                ó   — | j                   j                  | j                  «      sY| j                  «       ry | j	                  d«       | j                  «        | j                   j                  | j                  «      sŒXy y )Nzcontext compression in progress)rÍ  ÚwaitrË  rÛ  rÔ  rì  rø   s    r   rÏ  z"_CompressionActivityHeartbeat._runH  sX   € Ø—*‘*—/‘/ $×"8Ñ"8Ô9Ø×$Ñ$Ô&ØØ�K‰KÐ9Ô:Ø×&Ñ&Ô(ð	 —*‘*—/‘/ $×"8Ñ"8×9rO   rý   )
r4   r   rÑ  r0  r¾  rV   rr  ú Optional[CompressionCommitFence]r1  r2  )r1  z'_CompressionActivityHeartbeat')úcontext compression completed©rÜ  rG   r1  r2  r4  )rÜ  rG   rÓ  rV   rØ  rV   r1  r2  r3  )r7  r8  r9  r:  ró   rÕ  rÝ  rÛ  rÔ  rì  rÏ  r<  rO   r   r½  r½  æ  su   „ ÙWð <@ðnØ_dØ9=ñnØðnØ,8ðnØX\ðnà6ðnð 
ónó2ô
.ó ð
 EJÐafõ jó"ô8)rO   r½  c                óÆ  — ddl m} g }| xs g D ]É  }t        |t        «      sŒ|j	                  d«      }|dvs|j	                  |«      rŒ;|dk(  ry|j	                  d«      rh|j	                  d«      }t        t        |t        «      r|j                  «       n|«      }|sŒ�|j                  «       D ��ci c]  \  }}|dk7  sŒ||“Œ }}}|j                  |«       ŒË |S c c}}w )záReturn direct user/assistant evidence safe for memory checkpointing.
    Summaries, tool rows and system messages are omitted; assistant prose is kept with ``tool_calls``
    stripped, and pure tool-call wrappers are dropped.r   )ÚCOMPRESSED_SUMMARY_METADATA_KEYÚrole>   ÚuserÚ	assistantrö  Ú
tool_callsÚcontent)
r%   ró  r&   r(   r¡   rV   rG   rH   r)   rš  )	rz  ró  Údirect_messagesr   rô  rø  Ú	has_proser,   r-   s	            r   Ú(_direct_messages_for_pre_compress_memoryrû  P  sÙ   € õ
 IØ,.€OØ’>˜rò (ˆÜ˜'¤4Ô(ØØ�{‰{˜6Ó"ˆØÐ,Ñ,°·±Ð<[Ô0\ØØ�;Ò 7§;¡;¨|Ô#<Ø—k‘k )Ó,ˆGÜ´
¸7ÄCÔ0H˜WŸ]™]œ_ÈgÓVˆIÙØØ(/¯©«×M¡  1¸1ÀÓ;L�q˜!‘tÐMˆGÑMØ×Ñ˜wÕ'ð(ð Ðùó Ns   Â2CÃ Cc                  óF   — e Zd Z	 d	 	 	 	 	 	 	 	 	 	 	 dd„Zdd„Zd	d„Zd	d„Zy)
Ú_CompressionLockLeaseRefresherNc                óˆ  — || _         || _        || _        || _        |€t	        dt        d|dz  «      «      }t	        dt        |«      «      | _        t	        dt        | j                  | j                  z  «      «      | _	        t        j                  «       | _        t        j                  | j                  dd¬«      | _        y )	Nr×  rÁ  g       @rÂ  r9   zcompression-lock-refreshTrÃ  )Ú_dbr®   Ú_holderÚ_ttl_secondsr·   rg  r¶   Ú_refresh_interval_secondsr‘   Ú_max_consecutive_failuresr‰   rå   rÍ  rÎ  rÏ  rÐ  )rñ   Údbr¾   r¤  Úttl_secondsÚrefresh_interval_secondss         r   ró   z'_CompressionLockLeaseRefresher.__init__h  s§   € ð ˆŒØ%ˆÔØˆŒØ'ˆÔØ#Ð+Ü'*¨3´°D¸+ÈÑ:KÓ0LÓ'MÐ$Ü),¨S´%Ð8PÓ2QÓ)RˆÔ&ô *-¨Q´°D×4EÑ4EÈ×HfÑHfÑ4fÓ0gÓ)hˆÔ&Ü—_‘_Ó&ˆŒ
Ü ×'Ñ'¨t¯y©yÐ?YÐbfÔgˆ�rO   c                ó:   — | j                   j                  «        | S rý   )rÐ  rÕ  rø   s    r   rÕ  z$_CompressionLockLeaseRefresher.startx  s   € Ø�‰×ÑÔØˆrO   c                óè   — | j                   j                  «        | j                  j                  «       r>t	        j
                  «       | j                  ur| j                  j                  d¬«       y y y )Nr×  r?  )rÍ  r  rÐ  rÙ  r‰   rÚ  rô  rø   s    r   rÝ  z#_CompressionLockLeaseRefresher.stop|  sT   € Ø�
‰
�‰Ôð �<‰<× Ñ Ô"¤y×'?Ñ'?Ó'AÈÏÉÑ'UØ�L‰L×Ñ cÐÕ*ð (VÐ"rO   c                ó  — d}d}|s%| j                   j                  | j                  «      sÖ|rd}| j                   j                  «       ry d}t	        d«      5  | j
                  j                  | j                  | j                  | j                  ¬«      }d d d «       |rd}Œ�|dz  }|| j                  k\  r"t        j                  d|| j                  «       y |rŒ¯| j                   j                  | j                  «      sŒÕy y # 1 sw Y   ŒoxY w)Nr   TFz#compression lock refresh raised: %s©r  r9   zZcompression lock refresh failed %d times in a row; stopping lease refresher for session %s)rÍ  rî  r  r  r    rÿ  Úrefresh_compression_lockr®   r   r  r  r   r   )rñ   Úconsecutive_failuresÚfirstÚ	refresheds       r   rÏ  z#_CompressionLockLeaseRefresher._runƒ  sø   € ð  !Ðð ˆÙ˜4Ÿ:™:Ÿ?™?¨4×+IÑ+IÔJÙØ�Ø—:‘:×$Ñ$Ô&ØØˆIÜÐ?Ó@ñ }Ø ŸH™H×=Ñ=¸d×>NÑ>NÐPT×P\ÑP\Ðjn×j{Ñj{Ð=Ó|�	÷}áØ'(Ð$ØØ  AÑ%Ð Ø# t×'EÑ'EÒEÜ—‘ØpØ(¨$×*:Ñ*:ôð ò# ˜4Ÿ:™:Ÿ?™?¨4×+IÑ+I×J÷}ð }ús   Á=DÄDrý   )r  r   r¾   rG   r¤  rG   r  r¶   r  r0  r1  r2  )r1  z '_CompressionLockLeaseRefresher'r3  )r7  r8  r9  ró   rÕ  rÝ  rÏ  r<  rO   r   rý  rý  g  sP   „ àrvðhØðhØ#&ðhØ03ðhØBGðhØcoðhà	óhó ó+ôrO   rý  c                ód   — t        | dd«      |k(  ry|| _        || _        | j                  |«       y)zÊStore + emit a feasibility verdict once per distinct text: every main-runtime change re-probes, and an
    unchanged verdict must not re-warn on each `/model --once` restore or fallback cycle (#114707).Ú_last_feasibility_noticeN)r2   r  Ú_compression_warningÚ_emit_diagnostic_status)r4   Úmsgs     r   Ú_emit_feasibility_noticer  ž  s7   € ô ˆuÐ0°$Ó7¸3Ò>ØØ%(€EÔ"Ø!$€EÔØ	×!Ñ! #Õ&rO   c               óž  — | j                   }|j                  }|x}|_        ||_        t        |dd«      }t        |dd«      dk(  rd|_        n)t        |t        t        f«      rt        ||z  «      |_        |j                  }	|	r
||	z  |_
        |	rt        ||	z  dz  «      nd}
ddlm} d}|	r=t        ||«      r1|j                  |	|j                  |	|
dz  «      t        |d	d«      «      }|du xs ||k  }t        | d
d«      xs d}t        | dd«      xs d}|r|dk7  r|nd}|s	 ddlm}  ||«      j"                  xs |}|r|› d|› d�n|}|› d|› d�}d|› d|d›d|› d|d›d|d›d�}|r|d|d›d|
d›�z  }n|d|d›d|› d|	d›d|d›d |d›d!�z  }t'        | |«       t(        j+                  d"||||«       y# t$        $ r	 |xs d}Y Œ‰w xY w)#a;  Lower the live threshold to the aux model's window and tell the user how to fix config.
    The summariser sends one user prompt (no system/tools), so threshold == aux_context is safe.
    Retention is recalibrated through its selected policy: lean is window-relative;
    only legacy follows the lowered threshold.Úsummary_target_ratioNÚ	tail_modeÚleanéd   é2   r   rÑ   Ú
max_tokensrx  rD   ú?r‹  Úauto)Úurlparsez (r�  u   âš  Compression model z context is r-  z tokens, but the main model z's compression threshold was z2 tokens. Auto-lowered this session's threshold to z  tokens so compression can run.
u¢     To make this permanent, edit config.yaml â€” either:
  1. Use a larger compression model:
       auxiliary:
         compression:
           model: <model-with-z[+-context>
  2. Lower the compression threshold:
       compression:
         threshold: 0.Ú02dz�  To make this permanent, use a larger compression model in config.yaml:
       auxiliary:
         compression:
           model: <model-with-uG   +-context>
  (Lowering compression.threshold cannot help here â€” with z's zb-token window, Hermes's small-context floor and output reservation would recompute the trigger to z- tokens, still above the compression model's z.)u´   Auxiliary compression model %s has %d token context, below the main model's compression threshold of %d tokens â€” auto-lowered session threshold to %d to keep compression working.)rw  Úthreshold_tokensÚ_aux_context_ceilingr2   Ú_tail_token_budgetr&   r‘   r¶   Útail_token_budgetr£  Úthreshold_percentr%   rÒ   Ú_compute_threshold_tokensÚ_effective_threshold_percentÚurllib.parser  Úhostnamer   r  r   rÊ   )r4   Ú	aux_modelÚaux_contextÚaux_providerÚaux_base_urlr~   Úold_thresholdÚnew_thresholdr  Úmain_ctxÚsafe_pctÚ_CCÚrecomputed_thresholdÚthreshold_suggestion_viableÚ_main_modelÚ_main_providerÚ_aux_provider_labelr  Ú_main_labelÚ
_aux_labelr  s                        r   Ú_lower_threshold_to_aux_contextr9  ¨  s§  € ð ×)Ñ)€JØ×/Ñ/€MØ2=Ð=€M�JÔ/ð '2€JÔ#Ü" :Ð/EÀtÓLÐÜˆz˜;¨Ó-°Ò7à(,ˆ
Õ%Ü	Ð(¬3´¨,Ô	7Ü'*¨=Ð;OÑ+OÓ'Pˆ
Ô$Ø×(Ñ(€HÙØ'4°xÑ'?ˆ
Ô$Ù6>Œs�K (Ñ*¨cÑ1Ô2ÀB€Hõ BØÐÙ”J˜z¨3Ô/Ø"×<Ñ<Ø�c×6Ñ6°xÀÈCÁÓPÜ�J ¨dÓ3ó 
Ðð #7¸$Ð">Ò"eÐBVÐZeÑBeÐä˜% ¨"Ó-Ò4°€KÜ˜U J°Ó3Ò9°r€NÙ*6¸<È6Ò;Q™,ÐWYÐÙð	9Ý-Ù"*¨<Ó"8×"AÑ"AÒ"QÀ\Ðñ :H�[�M  NÐ#3°1Ñ5È[€KØ�;˜bÐ!4Ð 5°QÐ7€Jà
   ¨L¸ÀQ¸ÐGcØˆ-Ð4°]À1Ð4Eð F4Ø4AÀ!Ð3DÐDeð	gð ñ
 #ØðWØWdÐefÐVgð haØaiÐjmÐ`nðpñ	
‰ð 	ðDØDQÐRSÐCTð UKØKVÈ-ÐWZÐ[cÐdeÐZfð gbà# AÐ&Ð&SÐT_Ð`aÐSbÐbdð	fñ	
ˆô ˜U CÔ(Ü
‡N�Nð	WØXaÐcnØ�}õøô1 ò 	9Ø".Ò"8°&Òð	9ús   Ä&F: Æ:GÇGc           	     ó4  — ddl m} t        |xs d«      j                  «       j	                  «       t        t        | dd«      xs d«      j                  «       j	                  «       k7  ry |t        t        | dd«      xs d«      «      }| xs  ||«      |k(  S )zRTrue when the auxiliary compression client is the main model on the main endpoint.r   )Únormalize_route_base_urlrD   rx  FrŽ  )Úhermes_cli.route_identityr;  rG   rH   rJ   r2   )r4   r)  r,  r;  Ú	main_bases        r   Ú_aux_inherits_main_router>  ö  s†   € åBÜ
ˆ9Š?˜Ó×!Ñ!Ó#×)Ñ)Ó+¬s´7¸5À'È2Ó3NÒ3TÐRTÓ/U×/[Ñ/[Ó/]×/cÑ/cÓ/eÒeØÙ(¬¬W°U¸JÈÓ-KÒ-QÈrÓ)RÓS€IØˆ=ÒOÑ4°\ÓBÀiÑOÐOrO   c                ód  — | j                   sy	 ddlm}m}m} ddlm}m} 	  |d«      \  }}}}} |d| j                  «       ¬«      \  }}	|�|	sB |d|«      \  }
}}|
�3|r1|
|}	}d|v r)|j                  d	«      r|j                  dd
«      d
   dd }|�|	s2|r|dk7  rd|› d�}nd}t        | |«       t        j                  d«       yt        t!        |dd«      «      }t!        |dd«      }t#        |«      rt%        |t        «      sdnt        |xs d«      }|r|dk7  r|nt!        | dd«      }t!        | dd«      }|€-t'        | |	|«      r t)        | j*                  j,                  «      }n ||	||||| j.                  ¬«      }|r"||k  rt1        d|	› d|d›d|d›d|dz  › d�	«      ‚|| j*                  j2                  k  rt5        | |	|||¬«       yt!        | dd«      �d| _        d| _        yy# t        $ r d}Y �ŒÉw xY w# t0        $ r ‚ t        $ r }t        j;                  d|«       Y d}~yd}~ww xY w) zïWarn at session start if the aux compression context is below the threshold.
    Called from ``AIAgent.__init__`` (CLI sees it via ``_vprint``); the gateway wires ``status_callback``
    later, so ``replay_compression_warning`` resends it.Nr   )Ú_resolve_task_provider_modelÚ/_try_configured_fallback_for_unavailable_clientÚget_text_auxiliary_client)ÚMINIMUM_CONTEXT_LENGTHÚget_model_context_lengthr_  rD   )Úmain_runtimeú(r�  r9   éÿÿÿÿr  u/   âš  Configured auxiliary compression provider 'z ' is unavailable, so older messages in long chats will be cut without a summary. Sign in to that provider again, or change auxiliary.compression in your config.u°   âš  No auxiliary LLM provider configured: Hermes has no helper model for summarising long chats, so older messages will be cut without a summary. Run `hermes setup` to add one.uL   No auxiliary LLM provider for compression â€” summaries will be unavailable.rŽ  r’  r‹  Ú&_aux_compression_context_length_config)rŽ  r’  Úconfig_context_lengthr‹  Úcustom_providerszAuxiliary compression model z has a context window of r-  z$ tokens, which is below the minimum zE required by Hermes Agent.  Choose a compression model with at least r'  z–K context (set auxiliary.compression.model in config.yaml), or set auxiliary.compression.context_length to override the detected value if it is wrong.)r)  r*  r+  r,  r  z4Compression feasibility check failed (non-fatal): %s)Úcompression_enabledrf  r@  rA  rB  Úagent.model_metadatarC  rD  r   Ú_current_main_runtimeÚendswithÚrsplitr  r   rÊ   rG   r2   r´   r&   r>  r‘   rw  r£  Ú_custom_providersrõ   r   r9  r  r  r   )r4   r@  rA  rB  rC  rD  Ú_aux_cfg_providerÚ_Úclientr)  Ú	fb_clientÚfb_modelÚfb_labelr  r,  Ú_raw_aux_keyÚaux_api_keyÚ_aux_providerÚ_aux_cfg_ctxr*  r   s                        r   Ú#check_compression_model_feasibilityr[  ÿ  sÏ  € ð ×$Ò$ØðSR÷	
ñ 	
÷ 	Zð	#Ù,HÈÓ,WÑ)Ð˜q ! Q¨ñ 6°mÐRW×RmÑRmÓRoÔpÑˆ�	Øˆ>¡Ù,[ØÐ0ó-Ñ)ˆI�x ð Ð$©Ø$-¨x˜	�Ø˜(‘? x×'8Ñ'8¸Ô'=Ø(0¯©¸¸QÓ(?ÀÑ(BÀ3ÀBÐ(GÐ%Øˆ>¡Ù Ð%6¸&Ò%@àEÐFWÐEXð YVð Vñ ðrð ô % U¨CÔ0Ü�N‰NÐiÔjØÜœ7 6¨:°rÓ:Ó;ˆô ˜v y°"Ó5ˆÜ% lÔ3¼JÀ|ÔUXÔ<Y‘bÔ`cÐdpÒdvÐtvÓ`wˆñ "3Ð7HÈFÒ7RÑÔX_Ð`eÐgqÐsuÓXvð 	ô ˜uÐ&NÐPTÓUˆØÐÔ$<¸UÀIÈ|Ô$\ô ˜e×6Ñ6×EÑEÓF‰Ká2Ø L¸+Ð]iØ&¸×9PÑ9PôˆKñ
 ˜;Ð)?Ò?ÜØ.¨y¨kð :Ø(¨˜Oð ,Ø1°!Ð4ð 5Dà)¨TÑ1Ð2ð 31ð	2ó	ð 	ð ˜×1Ñ1×BÑBÒBÜ+Ø ¸ÐRcØ)öô �UÐ6¸Ó=ÐIð .2ˆEÔ*Ø)-ˆEÕ&ð	 JøôA ò 	#Ø "Óð	#ûôJ ò àÜò RÜ�‰ÐKÈS×QÑQûðRúsG   �G= ¢G+ °BG= ÃDG= ÇG= Ç+G:Ç6G= Ç9G:Ç:G= Ç=H/ÈH*È*H/c                ó¬   — d| _         t        | dd«      sy	 t        | «       d| _         y# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)a‘  Re-run the aux feasibility probe after the main runtime changed (model switch, fallback activation,
    primary restore). ``update_model()`` already voided the previous ceiling; probing now clamps the trigger
    before the first compaction on the new window rather than after it (#114707). A probe failure leaves the
    latch unset so the lazy probe at the next compaction re-raises hard rejections.Frw  NzDCompression feasibility re-check deferred to the next compaction: %sT)Ú _compression_feasibility_checkedr2   r[  r   r   r   )r4   r   s     r   Ú"revalidate_compression_feasibilityr^  [  sX   € ð
 .3€EÔ*Ü�5Ð.°Ô5ØðÜ+¨EÔ2ð .2€EÕ*øô ò Ü�‰Ð[Ð]`ÔaÜûðús   —* ª	A³AÁAc                óê   — t        | dd«      st        | dd«      syddlm} t        |xs d«      |k  ry	 t	        | «       d| _        y# t
        $ r }t        j                  d|«       Y d}~yd}~ww xY w)	uð  Run the deferred aux feasibility probe once a request first reaches ``MINIMUM_CONTEXT_LENGTH`` â€” the
    smallest window any summariser may have â€” so an aux clamp lands before the first compaction fires on the
    main-window threshold instead of after it (#114707). Below that size no summariser can be too small, so
    short sessions keep the probe-free cold start (#28957). A probe failure leaves the latch unset for the
    lazy probe in ``compress_context`` to re-raise hard rejections.r]  Frw  Nr   )rC  zBCompression feasibility probe deferred to the first compaction: %sT)	r2   rL  rC  r‘   r[  r   r   r   r]  )r4   Úestimated_tokensrC  r   s       r   Ú&ensure_compression_feasibility_checkedra  k  sx   € ô ˆuÐ8¸%Ô@ÌÐPUÐWkÐmqÔHrØÝ;Ü
ÐÒ ˜qÓ!Ð$:Ò:ØðÜ+¨EÔ2ð .2€EÕ*øô ò Ü�‰ÐYÐ[^Ô_Üûðús   ¶A	 Á		A2ÁA-Á-A2c                óÖ   — t        | dd«      }|rN| j                  rAddlm} t	        j
                  t        «      5  | j                  d ||«      «       ddd«       yyy# 1 sw Y   yxY w)zÒRe-send the stored compression warning through ``status_callback``.
    Called once at the start of the first ``run_conversation()``, when the gateway callback (absent during
    ``__init__``) is finally wired.r  Nr   )ÚDiagnosticTextÚ	lifecycle)r2   r0   Úgateway.warning_notificationsrc  r‹   r˜   r   )r4   r  rc  s      r   Úreplay_compression_warningrf  ~  sj   € ô �%Ð/°Ó
6€CÙ
ˆu×$Ò$å@Ü× Ñ ¤Ó+ñ 	DØ×!Ñ! +©~¸cÓ/BÔC÷	Dð 	Dð %€s÷	Dð 	Dús   »AÁA(c                ó¸   — t        t        | dd«      «      r#t        | dd«      }|du rt        |«      S |du ry|S t        t        | dd«      «      rt        |«      S y)a}  Return the correct flush baseline after a compression boundary.
    Session rotation returns ``None`` so the child gets the full compacted list. In-place compaction returns a
    shallow copy of the already-persisted rows (else the identity flush re-appends them). Aborted/no-op
    attempts keep the baseline: marking all persisted drops unflushed turns; clearing re-appends rows.Ú"_last_compression_attempt_recordedFÚ"_last_compression_attempt_in_placeNTÚ_last_compaction_in_place)rV   r2   r'   )r4   rz  Úprevious_historyÚattempt_in_places       r   Ú&conversation_history_after_compressionrm  Š  si   € ô ŒG�EÐ?ÀÓGÔHÜ" 5Ð*NÐPTÓUÐØ˜tÑ#Ü˜“>Ð!Ø˜uÑ$ØØÐÜŒG�EÐ6¸Ó>Ô?Ü�H‹~ÐØrO   )z-[System: Your previous response was truncatedz*[System: The previous response was cut offz [System: Your previous tool callz@[Your active task list was preserved across context compression]z[IMPORTANT: Background process c                ó¾   — t        | t        «      r| j                  d«      nd }t        |t        «      r|S t        |t        «      rdj                  d„ |D «       «      S y)Nrø  ú
c              3  ó    K  — | ]F  }t        |t        «      sŒt        |j                  d «      xs |j                  d«      xs d«      –— ŒH y­w)rK   rø  rD   N)r&   r(   rG   r¡   )rµ  Úparts     r   r·  z _message_text.<locals>.<genexpr>©  sB   è ø€ ò 
ØCGÔV`ÐaeÔgkÕVlŒC�—‘˜Ó Ò= D§H¡H¨YÓ$7Ò=¸2×>ñ
ùs
   ‚A˜6ArD   )r&   r(   r¡   rG   r'   rô  )r   rø  s     r   Ú_message_textrr  ¤  sW   € Ü(2°7¼DÔ(Aˆg�k‰k˜)Ô$Àt€GÜ�'œ3ÔØˆÜ�'œ4Ô Ø�y‰yñ 
ØKRô
ó 
ð 	
ð rO   )Ú_todo_snapshot_syntheticÚ_empty_recovery_syntheticÚ_verification_stop_syntheticÚ_pre_verify_syntheticÚ_dropped_toolcall_nudgec                ó  ‡ — t        ‰ t        «      r‰ j                  d«      dk7  ryt        ˆ fd„t        D «       «      ryt        ‰ «      j                  «       }|r|j                  t        «      ryddl	m
} |j                  ‰ «       S )zÂDistinguish human intent from user-role runtime scaffolding.
    A compaction summary flipped to ``role="user"`` for alternation is scaffolding and must not short-circuit
    anchor restoration.rô  rõ  Fc              3  ó@   •K  — | ]  }‰j                  |«      –— Œ y ­wrý   )r¡   )rµ  Úflagr   s     €r   r·  z(_is_real_user_message.<locals>.<genexpr>»  s   øè ø€ Ò
? ˆ7�;‰;�t×Ñ
?ùs   ƒr   rÑ   )r&   r(   r¡   r¸  Ú_SYNTHETIC_USER_FLAGSrr  rH   rq  Ú_SYNTHETIC_USER_PREFIXESr%   rÒ   Ú#_is_synthetic_compression_user_turn)r   rK   rÒ   s   `  r   Ú_is_real_user_messager~  µ  sp   ø€ ô �gœtÔ$¨¯©°FÓ(;¸vÒ(EØÜ
Ó
?Ô)>Ô
?Ô?ØÜ˜Ó!×'Ñ'Ó)€DÙ�4—?‘?Ô#;Ô<ØÝ:Ø ×DÑDÀWÓMÐMÐMrO   z[OUT-OF-BAND USER MESSAGEz[/OUT-OF-BAND USER MESSAGE]c                 óR   — 	 ddl m} m} || fS # t        $ r t        t
        fcY S w xY w)zU``(open, close)`` steer markers from prompt_builder, or the stable fallback literals.r   ©ÚSTEER_MARKER_CLOSEÚSTEER_MARKER_OPEN)Úagent.prompt_builderr�  r‚  r   Ú_STEER_FALLBACK_OPENÚ_STEER_FALLBACK_CLOSEr€  s     r   Ú_steer_markersr†  È  s1   € ð;ßNØ Ð"4Ð4Ð4øÜò ;Ü#Ô%:Ð:Ò:ð;ús   ‚ Ž&¥&c                óL   — t        | «      }|syt        «       \  }}||v xr ||v S )zýReturn whether *message* carries a busy-steer marker.
    Steer follow-ups are now their own ``role=user`` rows (caught by ``_is_real_user_message``); in
    transcripts persisted before that they ride inside ``role=tool`` results, so those still count.F)rr  r†  )r   rK   Úopen_markerÚclose_markers       r   Ú_message_contains_busy_steerrŠ  Ñ  s6   € ô ˜Ó!€DÙØÜ .Ó 0Ñ€K�Ø˜$ÐÒ7 <°4Ð#7Ð7rO   c                ó¨  — t        | «      }|syt        «       \  }}|j                  |«      }|dk(  rJ|j                  t        «      }|dk(  ry|j                  d|«      }|dk7  r|dz   n|t	        t        «      z   }n|t	        |«      z  }|j                  ||«      }|dk(  r|j                  t
        |«      }|dk(  ry||| j                  «       xs dS )z9Extract the inner user text from a steer marker, or None.NrG  ro  r9   )rr  r†  Úfindr„  ry  r…  rH   )r   rK   rˆ  r‰  rÕ  ÚnlÚends          r   Ú _extract_steer_text_from_messager�  Ü  sÔ   € ä˜Ó!€DÙØÜ .Ó 0Ñ€K�Ø�I‰I�kÓ"€EØ�‚{à—	‘	Ô.Ó/ˆØ�BŠ;ØØ�Y‰Y�t˜UÓ#ˆØ š(��Q’¨´Ô4HÓ0IÑ(I‰à”�[Ó!Ñ!ˆØ
�)‰)�L %Ó
(€CØ
ˆb‚yØ�i‰iÔ-¨uÓ5ˆØ�"Š9ØØ��cˆ?× Ñ Ó"Ò* dÐ*rO   c                ó&   — t        d„ | D «       «      S )z°Whether *messages* already carries a steer marker in a ``role=tool`` row.
    Only tool rows count, so a summary merely quoting the marker text is not mistaken for live intent.c              3  ó‚   K  — | ]7  }t        |t        «      xr! |j                  d «      dk(  xr t        |«      –— Œ9 y­w)rô  ÚtoolN)r&   r(   r¡   rŠ  )rµ  r  s     r   r·  z-_compressed_has_busy_steer.<locals>.<genexpr>÷  s=   è ø€ ò ØfiŒ
�3œÓÒa #§'¡'¨&£/°VÑ";ÒaÔ@\Ð]`Ó@aÓañùs   ‚=?)r¸  ©rz  s    r   Ú_compressed_has_busy_steerr”  ô  s   € ô ñ Ømuôó ð rO   c                óø  — ddl m} t        | t        «      r+| j	                  |«      }|dk(  r| S | d| j                  «       S t        | t        «      r¨g }| D ]Ÿ  }t        |t        «      r2|j                  d«      dk(  rt        |j                  d«      xs d«      nd}|r|j	                  |«      nd}|dk(  r|j                  |«       Œs|d| j                  «       x}sŒ‰|j                  i |¥d|i¥«       Œ¡ |S | S )zåRemove a previously merged todo-snapshot block from message content.
    Snapshots are appended to the trailing user turn, so a surviving header is stale; stripping before
    re-injection prevents accumulation across boundaries.r   )ÚTODO_INJECTION_HEADERrG  Nr³   rK   rD   )
Útools.todo_toolr–  r&   rG   rŒ  Úrstripr'   r(   r¡   rš  )rø  r–  ÚidxÚcleanedrq  rK   Ústrippeds          r   Ú_strip_stale_todo_snapshotrœ  ü  sú   € õ 6Ü�'œ3ÔØ�l‰lÐ0Ó1ˆØ�"Š9ØˆNØ�t˜ˆ}×#Ñ#Ó%Ð%Ü�'œ4Ô ØˆØò 	;ˆDÜ2<¸TÄ4Ô2HÈTÏXÉXÐV\ÓM]ÐagÒMg”3�t—x‘x Ó'Ò-¨2Ô.ÐmoˆDÙ6:�$—)‘)Ð1Ô2ÀˆCØ�bŠyØ—‘˜tÕ$Ø! $ 3˜Z×.Ñ.Ó0Ð0�Ñ0Ø—‘Ð9 $Ð9¨°Ñ9Õ:ð	;ð ˆØ€NrO   c                ó¬   — t        | t        «      r!t        |t        «      r|j                  «        S t        | t        «      rt        |t        «      r| S y)a9  Return whether stripping the snapshot leaves no structured content.
    Text snapshots trail a string; structured ones occupy their own text part, so only an empty remainder
    proves the row was scaffolding alone. Text extraction is deliberately not used: image, audio and other
    non-text parts must survive.F)r&   rG   rH   r'   )rø  r›  s     r   Ú_todo_snapshot_is_only_contentrž  	  sE   € ô
 �'œ3Ô¤J¨x¼Ô$=Ø—>‘>Ó#Ð#Ð#Ü�'œ4Ô ¤Z°¼$Ô%?Øˆ|ÐØrO   c                ó*   — ddl m} || d<    || «       y)zFRewrite message content without allowing an old API sidecar to replay.r   )Údrop_stale_api_contentrø  N)Úagent.turn_contextr   )r   rø  r   s      r   Ú_replace_message_contentr¢  	  s   € å9Ø €GˆIÑÙ˜7Õ#rO   uJ   [Skills pruned during compression â€” reload before acting on these tasks]c                óö   — ddl m}m} g }| D ]?  }t        |t        «      sŒ |t        |«      «      D ]  }||vsŒ|j                  |«       Œ ŒA ||d…= |sydj                  d„ |D «       «      }t        › d|› d�S )	zØReload notice for skills whose bodies were pruned, or ``""``.
    Scans ``[SKILL_PRUNED: ...]`` markers in the post-compression transcript; first-seen order, deduplicated,
    capped at ``_MAX_PRUNED_SKILL_MARKERS``.r   )Ú_MAX_PRUNED_SKILL_MARKERSÚ_extract_pruned_skill_namesNrD   z; c              3  ó(   K  — | ]
  }d |› d�–— Œ y­w)zskill_view(name='z')Nr<  )rµ  r€   s     r   r·  z._pruned_skill_reload_notice.<locals>.<genexpr>;	  s   è ø€ ÒE°tÐ)¨$¨¨rÔ2ÑEùs   ‚zÎ
The task list above crossed the compression boundary verbatim, but the skill instructions that governed it were pruned. Before executing any preserved task that depends on these skills, reload them first: uˆ   . After reloading, re-check that each pending task is still justified â€” findings recorded before the boundary may have invalidated it.)	r%   r¤  r¥  r&   r(   rr  rš  rô  Ú"_PRUNED_SKILL_RELOAD_NOTICE_HEADER)Ú
compressedr¤  r¥  rö  r   r€   Úcallss          r   Ú_pruned_skill_reload_noticerª  ,	  s¡   € ÷ `Ø€EØò #ˆÜ˜'¤4Ô(ØÙ/´¸gÓ0FÓGò 	#ˆDØ˜5Ò Ø—‘˜TÕ"ñ	#ð#ð 	Ð'Ñ(Ð)ÙØØ�I‰IÑE¸uÔEÓE€Eä-Ð
.ð /ð �gð eð		eðrO   c                óT  — |j                  d«      }| j                  d«      }t        |t        «      st        |t        «      r dd„}t        |  ||«       ||«      z   «       n)|xs d› d|xs d› �j	                  «       }t        | |«       t
        D ]  }| j                  |d«       Œ y)zÕFold the human anchor into an existing user-role scaffolding turn.
    Used only when any insertion would create consecutive user turns. Anchor text leads, scaffolding follows,
    and synthetic flags are cleared.rø  c                ó^   — t        | t        «      rt        | «      S dt        | xs d«      dœgS )NrK   rD   )r³   rK   )r&   r'   rG   )rø  s    r   Ú_partsz/_merge_anchor_into_user_message.<locals>._partsN	  s/   € Ü$.¨w¼Ô$=”4˜“=ÐqÈVÔ]`ÐahÒanÐlnÓ]oÑDpÐCqÐqrO   rD   ú

N)rø  r   r1  r'   )r¡   r&   r'   r¢  rH   r{  Úpop)rÄ  ÚanchorÚanchor_contentÚtarget_contentr­  Úmergedrz  s          r   Ú_merge_anchor_into_user_messager´  F	  s    € ð —Z‘Z 	Ó*€NØ—Z‘Z 	Ó*€NÜ�.¤$Ô'¬:°nÄdÔ+Kó	rô 	! ©°Ó)?Á&ÈÓBXÑ)XÕYà"Ò( bÐ)¨¨nÒ.BÀÐ-CÐD×JÑJÓLˆÜ  ¨Ô0Ü%ò ˆØ�
‰
�4˜ÕñrO   )Úinsertedr³  Úalready_presentÚplaceholder_appendedc                óZ  ‡ ‡‡— ddl mŠm} dd„}dˆˆˆ fd„}t        ‰ «      D ]1  \  }} ||«      dk(  sŒ|dk(  s |‰ |dz
     «      dk7  sŒ) ||«      c S  ‰ r+ |‰ d   «      dk7  s|j	                  t        ‰ d   «      «      r |t        ‰ «      «      S t        ‰ d   ‰«       d	‰ d   ‰<   y
)z?Insert the latest human turn without breaking role alternation.r   )r$   rÒ   c                óH   — t        | t        «      r| j                  d«      S d S )Nrô  ©r&   r(   r¡   )r  s    r   Ú_rolez'_insert_real_user_anchor.<locals>._role`	  s   € Ü",¨S´$Ô"7ˆs�w‰w�v‹ÐA¸TÐArO   c                ó4   •— d‰‰<   ‰j                  | ‰«       y)NTrµ  )r  )r•  r$   r°  rz  s    €€€r   Ú_placez(_insert_real_user_anchor.<locals>._placec	  s   ø€ Ø'+ˆÐ#Ñ$Ø�‰˜˜vÔ&ØrO   rö  r9   rõ  rG  Tr³  )r  r   r1  úOptional[str])r•  r‘   r1  ÚCompressedUserTurnOutcome)r%   r$   rÒ   r“  Ú_is_context_summary_contentrr  ry  r´  )rz  r°  rÒ   r»  r½  r•  r   r$   s   ``     @r   Ú_insert_real_user_anchorrÁ  \	  s½   ú€ çPóB÷ô $ HÓ-ò !‰ˆˆwÙ�‹>˜[Ó(¨e°qªj¹EÀ(È5ÐSTÉ9ÑBUÓ<VÐZ`Ó<`Ù˜%“=Ò ð!ñ Ù�˜"‘Ó &Ò(Ø×8Ñ8¼ÀxÐPRÁ|Ó9TÔUá”c˜(“mÓ$Ð$ô $ H¨R¡L°&Ô9Ø)-€HˆR�LÐ%Ñ&ØrO   c                óˆ  ‡— t        d„ |D «       «      st        |«      ryddlmŠm}m} t        ˆfd„|D «       «      ryt        | «      D ]d  }t        |«      rt        | ||«      «      c S t        |t        «      r|j                  d«      dk7  rŒGt        |«      }|sŒUt        |d|d	œ«      c S  dd
lm}  ||d|d	œ«       y)zDPreserve human intent, not merely a synthetic user-role placeholder.c              3  ó2   K  — | ]  }t        |«      –— Œ y ­wrý   ©r~  )rµ  r   s     r   r·  z3_ensure_compressed_has_user_turn.<locals>.<genexpr>	  s   è ø€ Ò
D¨gÔ  ×)Ñ
Dùs   ‚r¶  r   )Ú_INFLIGHT_REPLAY_MERGED_KEYÚ%COMPRESSION_CONTINUATION_USER_CONTENTÚ_fresh_compaction_message_copyc              3  ód   •K  — | ]'  }t        |t        «      xr |j                  ‰«      –— Œ) y ­wrý   rº  )rµ  r   rÅ  s     €r   r·  z3_ensure_compressed_has_user_turn.<locals>.<genexpr>Š	  s+   øè ø€ Ò
lÐV]Œ:�gœtÓ$ÒQ¨¯©Ð5PÓ)QÓQÑ
lùs   ƒ-0rô  r’  rõ  ©rô  rø  )Úappend_messager·  )r¸  r”  r%   rÅ  rÆ  rÇ  Úreversedr~  rÁ  r&   r(   r¡   r�  Úagent.message_metadatarÊ  )Úoriginal_messagesr¨  rÆ  rÇ  r   Ú
steer_textrÊ  rÅ  s          @r   Ú _ensure_compressed_has_user_turnrÏ  }	  sÅ   ø€ ä
Ñ
D¸Ô
DÔDÔHbÐcmÔHnØ ÷ñ ô Ó
lÐakÔ
lÔlà ô Ð-Ó.ò aˆÜ  Ô)Ü+¨JÑ8VÐW^Ó8_Ó`Ò`Ü˜'¤4Ô(¨G¯K©K¸Ó,?À6Ò,IØÜ5°gÓ>ˆ
ÚÜ+¨JÀÐT^Ñ8_Ó`Ò`ðaõ 6Ù�:¨Ð;`ÑaÔbØ!rO   c                ó(  — t        | t        «      rVt        |t        «      rF| j                  d«      |j                  d«      k7  s#| j                  d«      |j                  d«      k7  ry| j                  d«      }|j                  d«      }|�|�||k(  S y)zCCompare the live turn identity we care about for rotation stamping.rô  rø  FÚ	timestampTrº  )ÚleftÚrightÚleft_timestampÚright_timestamps       r   Ú_messages_match_scoped_identityrÖ  Ÿ	  s„   € ô �tœTÔ"Ü˜%¤Ô&Ø�8‰8�FÓ˜uŸy™y¨Ó0Ò0Ø�8‰8�IÓ %§)¡)¨IÓ"6Ò6àØ—X‘X˜kÓ*€NØ—i‘i Ó,€OØÐ! oÐ&AØ Ñ0Ð0ØrO   ©Úexact_counts_stampedc               óf  — ddl m} |j                  d«      }d}|�Z| D ]R  }t        |t        «      r |j                  d«      |k7  st        ||«      sŒ4|j                  |«      r|xs |}ŒLd||<   d}ŒT |ry| D ]7  }t        |t        «      sŒ|j                  |«      rŒ&t        ||«      sŒ3d||<   Œ9 y)aM  Stamp ``_db_persisted`` on every unstamped scoped twin of ``source`` in ``targets``.
    Exact-timestamp twins are preferred: when the source carries a timestamp and any exact twin was stamped
    (or, with ``exact_counts_stamped``, merely exists), the broad scoped pass is skipped so a content-equal
    old duplicate is left alone.r   r#   rÑ  FNT)r%   r$   r¡   r&   r(   rÖ  )ÚtargetsÚsourcerØ  r$   Úsource_timestampÚ	exact_hitrÄ  s          r   Ú_stamp_scoped_twinsrÞ  ¯	  sÇ   € õ
 >Ø—z‘z +Ó.ÐØ€IØÐ#Øò 	ˆFä˜v¤tÔ,Ø—:‘:˜kÓ*Ð.>Ò>Ü6°v¸vÔFàØ�z‰zÐ.Ô/Ø%Ò=Ð)=�	ØØ+/ˆFÐ'Ñ(Ø‰Ið	ñ ØØò 0ˆä�vœtÕ$Ø—J‘JÐ3Õ4Ü/°¸Õ?à+/ˆFÐ'Ò(ñ0rO   Ú0_pending_context_engine_compression_notificationc               óŽ  — t        dd¬«      5  ddlm} |j                  j	                  |j                  «       ||¬«       ddd«       t        | j                  dd«      }t        |«      sy		  ||d
|t        | dd«      xs dt        | dd«      ¬«       y# 1 sw Y   ŒUxY w# t        $ r t        j                  dd¬«       Y y	w xY w)zDNotify the active context engine after a durable compression commit.z*relay segment rotation notification failedTr   r   )Úrelay_runtime)Úprofile_keyr¾   r…  Nr€  Fr_  r�  r‚  rƒ  )r„  r…  r�  r†  z4context engine on_session_start (compression) failed)r    r4   rá  ÚSESSION_COORDINATORÚnotify_session_compactedÚcurrent_profile_keyr2   rw  r´   r   r   r   )r4   r   r…  rá  Úcallbacks        r   Ú+_notify_context_engine_compression_completerç  Ò	  sÒ   € ô 
Ð>ÈÔ	Nñ 
Ý'Ø×)Ñ)×BÑBØ%×9Ñ9Ó;ÈÐguð 	Cô 	
÷
ô
 �u×/Ñ/Ð1CÀTÓJ€HÜ�HÔØðÙØ¨MÈ.Ü˜U J°Ó5Ò>¸Ü# EÐ+AÀ4ÓHõ	
ð
 ÷
ð 
ûô ò ô 	�‰ÐKÐVZˆÔ[Ùð	ús   Ž3BÁ-'B! ÂBÂ! CÃCc               ó†   ‡ ‡‡— t        t        ‰ t        d«      «      rt        d«      ‚dˆ ˆˆfd„}t	        ‰ t        |«       y)zCStage exactly one existing hook call for an outer host transaction.Nú-a compression notification is already pendingc                 ó    •— t        ‰ ‰‰¬«      S )N©r   r…  )rç  )r4   r   r…  s   €€€r   Ú_notifyz?_queue_context_engine_compression_notification.<locals>._notifyñ	  s   ø€ Ü:Ø .Àô
ð 	
rO   r4  )r´   r2   Ú$_PENDING_CONTEXT_ENGINE_NOTIFICATIONrµ   rË   )r4   r   r…  rì  s   ``` r   Ú._queue_context_engine_compression_notificationrî  ì	  s5   ú€ ä”˜ÔCÀTÓJÔKÜÐJÓKÐK÷
ô
 ˆEÔ7¸ÕArO   c               ó‚   — t        | t        d«      }t        | t        d«       |rt        |«      syt	         |«       «      S )zCEmit or discard a deferred notification; repeated calls are no-ops.NF)r2   rí  rË   r´   rV   )r4   Ú	committedÚpendings      r   Ú0finalize_context_engine_compression_notificationrò  ù	  s7   € ä�eÔAÀ4ÓH€GÜˆEÔ7¸Ô>ÙœH WÔ-ØÜ‘“	‹?ÐrO   c                  ó&   — e Zd ZdZdd„Zddœdd„Zy)	Ú_CompactionLifecyclezÚOwns the one-shot terminal edge of the compaction status lifecycle.
    ``commit_status`` is rebound to "committed" only on success and read at ``complete()`` time, so abort
    paths keep the terminal edge suppressed.c                ó<   — || _         || _        d| _        d| _        y )NFrÝ  )rÆ  Ústatus_emittedÚ_done_emittedrà  )rñ   r4   rö  s      r   ró   z_CompactionLifecycle.__init__
  s!   € ØˆŒØ,ˆÔØ"ˆÔØ&ˆÕrO   F©Úforce_terminalc               ó”   — | j                   ry d| _         | j                  r(| j                  dk(  s|rt        | j                  «       y y y )NTrð  )r÷  rö  rà  r5   rÆ  )rñ   rù  s     r   Úcompletez_CompactionLifecycle.complete
  sF   € Ø×ÒØØ!ˆÔð ×Ò D×$6Ñ$6¸+Ò$EÉÜ! $§+¡+Õ.ð JXÐrO   N)r4   r   rö  rV   r1  r2  )rù  rV   r1  r2  )r7  r8  r9  r:  ró   rû  r<  rO   r   rô  rô  
  s   „ ñ0ó'ð 27ö /rO   rô  c                  ór   — e Zd ZdZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d
d„Zedd„«       Zdd„Zdd„Zdd„Z	dd„Z
dd„Zy	)Ú_CompressionLeasea  The per-attempt durable compression lock plus its lifecycle plumbing.
    ``holder`` is None when no durable lock is owned (legacy DB, no session db); ``watermark`` is MAX(id) of
    active rows at lease start (None = archive everything, no concurrent-tail preservation this cycle).c               óÞ   — || _         || _        || _        || _        || _        || _        || _        d | _        d | _        d | _	        d| _
        t        j                  «       | _        d| _        y rá   )rÆ  r  ÚsidÚttlÚ_refresh_intervalrÇ  Ú
_lifecycler¤  Ú	watermarkÚ
_refresherÚ	_releasedr‰   rŠ   Ú_release_guardÚ_lock_setup_entered)rñ   r4   r  rÿ  r   Úrefresh_intervalrr  rd  s           r   ró   z_CompressionLease.__init__
  sl   € ð ˆŒØˆŒØˆŒØˆŒØ!1ˆÔØ)ˆÔØ#ˆŒØ%)ˆŒØ(,ˆŒØDHˆŒØˆŒÜ'Ÿn™nÓ.ˆÔð $)ˆÕ rO   c                ó.   — | j                   j                  S )zSTrue when the routine compaction start status was shown (heartbeats may follow it).)r  rö  rø   s    r   rö  z _CompressionLease.status_emitted1
  s   € ð �‰×-Ñ-Ð-rO   c                ór   — | j                   €y| j                   j                  «       | _        | j                  S rß  )rÇ  r&  r  rø   s    r   r&  z"_CompressionLease.begin_lock_setup6
  s4   € Ø×ÑÐ%ØØ#'×#5Ñ#5×#FÑ#FÓ#HˆÔ Ø×'Ñ'Ð'rO   c                óx   — | j                   r| j                  €y d| _         | j                  j                  «        y rá   )r  rÇ  r(  rø   s    r   r(  z#_CompressionLease.finish_lock_setup<
  s3   € Ø×'Ò'¨4×+=Ñ+=Ð+EØØ#(ˆÔ Ø×Ñ×,Ñ,Õ.rO   c                ó$  — | j                   €y t        | j                  | j                  | j                   | j                  | j
                  «      }| j                  5  | j                  s|j                  «       | _	        d d d «       y # 1 sw Y   y xY wrý   )
r¤  rý  r  rÿ  r   r  r  r  rÕ  r  )rñ   Ú	candidates     r   Ústart_refresherz!_CompressionLease.start_refresherB
  sp   € Ø�;‰;ÐØÜ2°4·7±7¸D¿H¹HÀdÇkÁkÐSW×S[ÑS[Ð]a×]sÑ]sÓtˆ	ð × Ñ ñ 	4Ø—>’>Ø"+§/¡/Ó"3�”÷	4÷ 	4ñ 	4ús   Á"BÂBc                ó^  — | j                   5  | j                  r
	 ddd«       yd| _        t        | j                  dd«      | j                  k(  rd| j                  _        | j                  �.t        d«      5  | j                  j                  «        ddd«       | j                  �\| j                  rP| j                  rDt        d«      5  | j                  j                  | j                  | j                  «       ddd«       ddd«       y# 1 sw Y   ŒzxY w# 1 sw Y   ŒxY w# 1 sw Y   yxY w)zÝStop this holder's refresher and release only its durable lock.
        Holder-qualified and idempotent: safe for the host after a timeout because a newer holder's lease can
        never be deleted by this stale release.NTÚ_active_compression_lock_holderz*compression lock refresher stop failed: %sz#compression lock release failed: %s)r  r  r2   rÆ  r¤  r  r  r    rÝ  r  rÿ  Úrelease_compression_lockrø   s    r   Úrelease_holder_onlyz%_CompressionLease.release_holder_onlyL
  s   € ð × Ñ ñ 	LØ�~Š~Ø÷	Lð 	Lð "ˆDŒNÜ�t—{‘{Ð$EÀtÓLÐPT×P[ÑP[Ò[Ø>B�—‘Ô;Ø�‰Ð*ÜÐJÓKñ +Ø—O‘O×(Ñ(Ô*÷+à�w‰wÐ" t§x¢x°D·K²KÜÐCÓDñ LØ—G‘G×4Ñ4°T·X±X¸t¿{¹{ÔK÷L÷	Lð 	L÷+ð +ú÷Lð Lú÷	Lð 	LúsA   �D#¤AD#Á7DÂ7D#Ã	1DÃ:D#ÄD	ÄD#ÄD 	ÄD#Ä#D,c                óT  — 	 | j                   j                  «        	 | j                  «        	 | j                  �%| j                  j	                  | j                  «       | j                  «        y# | j                  «        w xY w# 	 | j                  �%| j                  j	                  | j                  «       | j                  «        w # | j                  «        w xY wxY w# 	 | j                  «        	 | j                  �%| j                  j	                  | j                  «       | j                  «        w # | j                  «        w xY w# 	 | j                  �%| j                  j	                  | j                  «       | j                  «        w # | j                  «        w xY wxY wxY w)z?Finish lifecycle cleanup and release the OLD session lock once.N)r  rû  r  rÇ  r.  r(  rø   s    r   r  z_CompressionLease.release]
  sJ  € ð
	-Ø�O‰O×$Ñ$Ô&ð-Ø×(Ñ(Ô*ð-Ø×)Ñ)Ð5Ø×*Ñ*×GÑGÈ×H`ÑH`Ôaà×*Ñ*Õ,ø�D×*Ñ*Õ,ûð	-Ø×)Ñ)Ð5Ø×*Ñ*×GÑGÈ×H`ÑH`Ôaà×*Ñ*Õ,ø�D×*Ñ*Õ,þð-Ø×(Ñ(Ô*ð-Ø×)Ñ)Ð5Ø×*Ñ*×GÑGÈ×H`ÑH`Ôaà×*Ñ*Õ,ø�D×*Ñ*Õ,ûð	-Ø×)Ñ)Ð5Ø×*Ñ*×GÑGÈ×H`ÑH`Ôaà×*Ñ*Õ,ø�D×*Ñ*Õ,ÿøs{   ‚C! �B ®1A0 Á0BÂCÂ1C	Â8CÃ	CÃCÃ!F'Ã#EÃ41D6Ä%F'Ä6EÅF'ÅF$Å1FÅ>F$ÆF!Æ!F$Æ$F'N)r4   r   r  r   rÿ  rG   r   r¶   r  r   rr  rï  rd  rô  r1  r2  r4  r3  )r7  r8  r9  r:  ró   r;  rö  r&  r(  r  r  r  r<  rO   r   rý  rý  
  s}   „ ñkð)Øð)Ø!$ð)Ø+.ð)Ø5:ð)ØNQð)à6ð)àCWð)ð 
ó)ð( ò.ó ð.ó(ó/ó4óLô"-rO   rý  c                ó¦   — | €y	 t        | «      ry| j                  }t        |«      sdt	        d«      fS |dfS # t        $ r}d|fcY d}~S d}~ww xY w)zÝReturn ``(try_acquire_compression_lock, lookup_error)`` for ``lock_db``.
    ``(None, None)`` = no db or legacy SessionDB without the lock API (fail open); ``(None, exc)`` = lookup
    itself failed (caller fails closed).NrÓ   z0compression lock API is present but not callable)r  r  r   r´   rz   )r  Útry_acquirer   s      r   Ú_resolve_lock_apir  l
  si   € ð €ØðÜ,¨WÔ5ØØ×:Ñ:ˆô �KÔ Ø”YÐQÓRÐRÐRØ˜ÐÐøô	 ò Ø�SˆyÕûðús   …9 ‘9 ¹	AÁAÁAÁAc                ód   — |€t        | |«      }t        | ||«       |j                  d¬«       d|fS )zVSit-out return for lease acquisition: prompt, aborted telemetry, terminal status edge.NTrø  )r=  r?  rû  )r4   rd  r<  Úattempt_started_atrâ  Úprompts         r   Ú_abort_leaser  }
  s=   € ð
 €~Ü(¨°Ó?ˆÜ# EÐ+=¸}ÔMØ×Ñ dÐÔ+Ø�ˆ<ÐrO   c                ó  — 	  || j                   | j                  | j                  ¬«      }|rd	 | j                  j	                  | j                   «      | _        |�4t        j                  t        «      5  |j                  «        ddd«       |S 	 |S |S # 1 sw Y   |S xY w# t        $ r3}t        j                  d| j                   |«       d| _        Y d}~|S d}~ww xY w# t        $ r—}t        d«      5  | j                  j                  | j                   | j                  «       ddd«       n# 1 sw Y   nxY wd| _        t        j                  d| j                   t        |«      j                   |«       Y d}~yd}~ww xY w)aË  Acquire the durable lock for ``lease.holder`` and capture the start watermark.
    Watermark = MAX(id) of active rows at START: appends aren't blocked during summary; later rows are
    concurrent tail that archive_and_compact re-sequences. Capture is safety-additive (fallback archives
    everything), so its failure never aborts. An acquire that raises is not version skew: fail closed and
    release holder-qualified best-effort (safe if never acquired).r
  Nu}   compression watermark capture failed for session=%s (%s) â€” concurrent appends this cycle will be archived with the snapshotz8compression lock cleanup after failed acquire failed: %sul   compression lock acquisition raised unexpectedly for session=%s (%s: %s) â€” skipping compression this cycleF)rÿ  r¤  r   r  Úget_active_message_watermarkr  r‹   r˜   ÚAttributeErrorr  r   r   rÊ   r    r  r³   r7  )Úleaser  rr  ÚacquiredÚ_wm_errÚ	_lock_errs         r   Ú_try_acquire_durable_lockr"  ‰
  sP  € ðÙ˜uŸy™y¨%¯,©,ÀEÇIÁIÔNˆÙð'Ø"'§(¡(×"GÑ"GÈÏ	É	Ó"R�”ð  Ð+Ü#×,Ñ,¬^Ó<ñ DØ$×AÑAÔC÷Dð ˆð ,ð ˆˆxˆ÷Dð ˆûô ò 'Ü—‘ð9Ø:?¿)¹)ÀWôð #'�—�Øˆûð'ûô ò ÜÐPÓQñ 	GØ�H‰H×-Ñ-¨e¯i©i¸¿¹ÔF÷	G÷ 	Gñ 	GúàˆŒÜ�‰ØzØ�I‰I”t˜I“×/Ñ/°ô	
ô ûðúsŠ   ‚+C ®AB  Á3BÂB  ÂC ÂC ÂC ÂBÂB  ÂC ÂB  Â 	CÂ)(CÃC ÃCÃC Ã	E?Ã(E:Ã31D-Ä$	E:Ä-D6	Ä2AE:Å:E?c                óà  — d}t        j                  t        «      5  |j                  j	                  |j
                  «      }ddd«       t        j                  d|j
                  |«       d|_        |xs d| _	        t        | dd«      |j
                  k7  rD|j
                  | _        t        j                  t        «      5  | j                  d«       ddd«       t        | |«      }t        j                  t        «      5  t        | j                  d«      r| j                  j!                  |¬«       ddd«       t#        | |||d|«      S # 1 sw Y   �ŒxY w# 1 sw Y   Œ†xY w# 1 sw Y   Œ2xY w)	zNAnother path holds the lock: publish the lock-skip signal, warn once, sit out.Nu~   compression skipped: another path is compressing session=%s (holder=%s) â€” returning messages unchanged to avoid session forkTÚ"_last_compression_lock_warning_siduw   âš  Skipping concurrent compression â€” another path is already compressing this session. Will retry after it finishes.Ú_begin_compression_telemetry)r­  Úlock_contended)r‹   r˜   r   r  rŸ  rÿ  r   rÊ   r¤  rE  r2   r$  Ú_emit_warningr=  Úhasattrrw  r%  r  )r4   r  rd  r<  r{  r  ÚexistingÚ_existing_sps           r   Ú_sit_out_lock_contentionr+  «
  sL  € ð
 €HÜ	×	Ñ	œYÓ	'ñ CØ—8‘8×7Ñ7¸¿	¹	ÓBˆ÷Cä
‡N�Nð	MØNSÏiÉiÐYaôð €E„Lð .6Ò-=¸€EÔ*äˆuÐ:¸DÓAÀUÇYÁYÒNØ38·9±9ˆÔ0Ü× Ñ ¤Ó+ñ 	Ø×Ñð%ô÷	ô
 +¨5°.ÓA€LÜ	×	Ñ	œYÓ	'ñ `Ü�5×+Ñ+Ð-KÔLØ×$Ñ$×AÑAÐQ^ÐAÔ_÷`ô ˜˜y¨.Ð:LÐN^Ð`lÓmÐm÷-Cñ Cú÷	ð 	ú÷`ð `ús#   œ&EÃEÄ 3E$ÅEÅE!Å$E-c               óf  — t        | dd«      }| j                  xs d}d| _        t        |«      \  }}	d}
t	        j
                  t        t        «      5  t        t        | dd«      xs d«      }
ddd«       t        | |||
t        | dd«      ||¬«      }|�û|rùt        | «      |_        |	�5d|_        t        j                  d|t        |	«      j                  |	«       d	}n�|€7d|_        t        | d
d«      |k7  r|| _        t        j                  d|«       d}nW|j#                  «       s:t        j%                  d| j                  xs d«       d	| _        t)        | |||d«      S t+        |||«      }|s |j-                  «        t/        | |||||«      S |j                  �†|j                  | _        |�s|j3                  |j4                  «      rXt        j%                  d| j                  xs d«       d	| _        t7        | |«      }t9        | |d«       |j;                  «        d|fS |dfS # 1 sw Y   �ŒºxY w)aÂ  Take the per-session compression lock; ``(None, prompt)`` means sit out.
    Two AIAgents sharing a session_id (e.g. background review fork) would both rotate and orphan a child.
    Keyed on the OLD id (what rivals read from SessionEntry). Loser sits out: messages unchanged, caller sees
    no-op. Only structural absence of the lock API (version skew) fails open; once resolved, any exception
    fails closed since unlocked runs can fork lineage.r­   NrD   g     Àr@Ú_compression_lock_ttl_secondsÚ"_compression_lock_refresh_interval)r  rÿ  r   r  rr  rd  ug   compression lock lookup raised unexpectedly for session=%s (%s: %s) â€” skipping compression this cycleFÚ _last_compression_lock_error_siduÃ   compression lock subsystem unavailable for session=%s â€” proceeding without lock. This usually means a stale in-memory module after an update; restart the process (or `hermes update`) to resync.TzBCompression commit cancelled before lock acquisition (session=%s).r‚  Úcommit_fence_cancelledzBCompression commit cancelled before summary dispatch (session=%s).)r2   r¾   rE  r  r‹   r˜   rz   rõ   r¶   rý  r«  r¤  r   rÊ   r³   r7  r/  r&  rT   rj  r  r"  r(  r+  r  r+  r  r=  r?  r  )r4   rr  rd  r<  r{  r  Ú_lock_dbÚ	_lock_sidÚ_try_acquire_lockÚ_lock_lookup_errorÚ	_lock_ttlr  Ú_lock_acquiredr*  s                 r   Ú_acquire_compression_leaser7  Ê
  sU  € ô �u˜m¨TÓ2€HØ× Ñ Ò& B€Ið .2€EÔ*Ü,=¸hÓ,GÑ)ÐÐ)Ø€IÜ	×	Ñ	œY¬
Ó	3ñ [Üœ' %Ð)HÈ%ÓPÒYÐTYÓZˆ	÷[äØ�( 	¨yÜ  Ð(LÈdÓSÐbnØô€Eð
 Ð¡	Ü/°Ó6ˆŒØÐ)ð  ˆEŒLÜ�N‰NØyØœ4Ð 2Ó3×<Ñ<Ð>Pôð #‰NØÐ&ð  ˆEŒLÜ�uÐ@À$ÓGÈ9ÒTØ9B�Ô6Ü—‘ðlàôð
 "‰Nà×)Ñ)Ô+Ü—‘ØXÐZ_×ZjÑZjÒZtÐntôð 38�Ô/Ü# E¨9°nÐFXÐZrÓsÐsÜ6°uÐ>OÐQ]Ó^ˆNÙØ×#Ñ#Ô%Ü+Ø�u˜i¨¸ÐHZóð ð ‡|�|ÐØ05·±ˆÔ-ØÐ#¨×(TÑ(TÐUZ×UnÑUnÔ(oä�K‰KØTÐV[×VfÑVfÒVpÐjpôð /4ˆEÔ+Ü2°5¸.ÓIˆLÜ+¨EÐ3EÐG_Ô`Ø�M‰MŒOØ˜Ð%Ð%Ø�$ˆ;Ð÷o[ñ [ús   ÁH&È&H0c                ór  — |j                   �|j                  sy	 t        |j                   |j                  «      }|syt        | |j                   |j                  «      }|j                  «        t        | |«      }|�/t        j                  d|j                  | j                  «       ||fS t        j                  d|j                  «       ||fS # t        $ r]}t        j                  d|j                  t        |«      j                  |«       |j                  «        |t        | |«      fcY d}~S d}~ww xY w)a5  Sit out (or adopt the live child) when the parent was already rotated.
    A late contender can take the parent lock after the winner released it and rotated; holding the lock does
    not prove this agent still owns a live parent. Returns the ``compress_context`` result to hand back, or
    None to proceed.Nzecompression session ownership lookup failed for session=%s (%s: %s) - skipping compression this cyclez<compression recovery: stale session=%s adopted live child=%szzcompression skipped: session=%s was already rotated by another compression path, but no unique live child could be adopted)r  rÿ  r   r   r   rÊ   r³   r7  r  r=  r™  r¾   )r4   r  rz  r<  Ú_parent_already_rotatedÚ_session_errÚrecovered_messagesr*  s           r   Ú_adopt_if_parent_rotatedr<    s  € ð ‡x�xÐ˜uŸyšyØðHÜ"EÀeÇhÁhÐPU×PYÑPYÓ"ZÐñ #ØÜ6°u¸e¿h¹hÈÏ	É	ÓRÐØ	‡M�M„OÜ*¨5°.ÓA€LØÐ%Ü�‰ÐUÐW\×W`ÑW`Ðbg×brÑbrÔsØ! <Ð/Ð/Ü
‡N�Nð	NØOTÏyÉyôð �\Ð!Ð!øô' ò HÜ�‰ØsØ�I‰I”t˜LÓ)×2Ñ2°Lô	
ð 	�‰ŒØÔ0°¸ÓGÐGÕGûðHús   › C Ã	D6ÃAD1Ä+D6Ä1D6c                ór  — |j                   �|j                  syt        t        |j                   «      dd«      }t	        |«      sy ||j                   |j                  «      }t        |t        «      rt        |«      t        |«      kD  syt        | dd«      }d}t        |t        «      rQd|cxk  rt        |«      k  r=n n:d}t        j                  t        «      5  | j                  ||d| ¬«      }ddd«       |s5t        j                  d|j                  t        |«      t        |«      «       y ||j                   |j                  «      }t        |t        «      rt        |«      t        |«      kD  syt        j                  d	|j                  t        |«      t        |«      «       |S # 1 sw Y   Œ»xY w)
uA  Return the durable parent transcript when it outgrew the in-memory snapshot.
    Rotation only (in-place never loses rows). The snapshot predates the lease: if durable grew, a writer
    committed a turn â€” ADOPT it (aborting wedged busy sessions forever). Length check only: in-memory edits of
    past turns are legal.Nr~  Ú_persist_user_message_idxTr   F©Úconversation_historyu´   compression: session=%s grew before lease (%d â†’ %d msgs) but the pre-adoption flush of the live tail failed; skipping durable-snapshot adoption so un-persisted user input is keptuU   compression: session=%s grew before lease (%d â†’ %d msgs); adopting durable snapshot)r  rÿ  r2   r³   r´   r&   r'   ry  r‘   r‹   r˜   r   Ú_flush_messages_to_session_dbr   rÊ   rT   )r4   r  rz  Údurable_loaderÚdurable_parentÚ_preflush_idxÚ_preflush_oks          r   Ú_adopt_grown_durable_parentrF  5  su  € ð
 ‡x�xÐ˜uŸyšyØÜœT %§(¡(›^Ð-KÈTÓR€NÜ�NÔ#ØÙ# E§H¡H¨e¯i©iÓ8€NÜ�~¤tÔ,´°^Ó1DÄsÈ8Ã}Ò1TØô ˜EÐ#>ÀÓE€Mà€LÜ�-¤Ô%¨!¨}Ô*L¼sÀ8»}Õ*LØˆÜ× Ñ ¤Ó+ñ 	xØ ×>Ñ>¸xÐ^fÐguÐhuÐ^vÐ>ÓwˆL÷	xáÜ�‰ðfà�I‰I”s˜8“}¤c¨.Ó&9ô	
ð
 á# E§H¡H¨e¯i©iÓ8€NÜ�~¤tÔ,´°^Ó1DÄsÈ8Ã}Ò1TØÜ
‡K�KØ_Ðaf×ajÑajÔloÐpxÓlyÜˆNÓôð Ð÷#	xð 	xús   ÃF-Æ-F6c                óð  — d}t        | dd«      }t        |«      }|r�t        |dd«      }|�t        |«      st        dt        › �«      ‚	 t         |t        «      «      }|st        dt        › �«      ‚	 |j                  ||dt        ¬	«      }	t        |	t        «      rt        |	«      }|S |rRt!        j"                  t        «      5  |j                  ||¬«      }	t        |	t        «      rt        |	«      }ddd«       |S |S # t        $ r}t        d«      |‚d}~ww xY w# t        $ rB}t        j                  d
t        |«      j                  «       t        dt        › d�«      |‚d}~ww xY w# 1 sw Y   |S xY w)aN  Provider ``on_pre_compress()`` insights to surface in the summary ("" if none).
    Raw messages stay the API v1 provider contract; normalized evidence goes only to API v2+ checkpoint
    providers inside MemoryManager.on_pre_compress(). Raises :class:`CompressionCheckpointUnavailable` when a
    required checkpoint cannot be taken.rD   rò  Nr  z.no active provider implements checkpoint API vz provider capability probe failedz3active provider does not implement checkpoint API vT)Úevidence_messagesÚrequire_checkpointÚcheckpoint_api_versionz,Required pre-compress checkpoint failed (%s)zprovider checkpoint API vz failed)rH  )r2   rû  r´   rÿ  r   rV   r   rü  Úon_pre_compressr   rÊ   r³   r7  r&   rG   r   r‹   r˜   )
r4   rz  Úcheckpoint_requiredr°  rõ  rH  r  Ú
compatibler   Ú
_maybe_ctxs
             r   Ú_pre_compress_memory_contextrO  d  s§  € ð
 €NÜ˜UÐ$5°tÓ<€NÜ@ÀÓJÐÙÜ% nÐ6XÐZ^Ó_ÐØÐ!¬Ð2EÔ)FÜ'Ø@ÔAdÐ@eÐfóð ð	SÜÑ1Ô2UÓVÓWˆJñ Ü'ØEÔFiÐEjÐkóð ð	yØ'×7Ñ7ØÐ,=ÐRVÜ'Jð 8ó ˆJô �j¤#Ô&Ü4°ZÓ@ˆNð Ðñ 
Ü× Ñ ¤Ó+ñ 	EØ'×7Ñ7¸ÐTeÐ7ÓfˆJÜ˜*¤cÔ*Ü!8¸Ó!D�÷	Eð Ðˆ>Ðøô+ ò 	SÜ%Ð&HÓIÈsÐRûð	Sûô ò 	yÜ�N‰NÐIÌ4ÐPSË9×K]ÑK]Ô^Ü%Ð(AÔBeÐAfÐfmÐ&nÓoÐuxÐxûð	yú÷	Eð Ðús<   Á
D  Á4D Ã/E+Ä 	DÄ	DÄDÄ	E(Ä&=E#Å#E(Å+E5c               óB  — | j                   j                  }t        ||||||¬«      }|j                  «       red|vrat	        | j                   dt        | j                   «      j                  «      }t	        | dd«      |k7  r|| _        t        j                  d|«       ||fS )z>Bind ``compress()`` and only the kwargs its signature accepts.)r­  r®  r¯  r°  re  r°  r€   Ú'_last_memory_context_unsupported_engineNzfcontext engine %s does not accept memory_context; continuing without provider-supplied summary context)
rw  rF   r»  rH   r2   r³   r7  rQ  r   rÊ   )	r4   r{  r®  r¯  r°  re  r¹  Úcompress_kwargsÚengine_names	            r   Ú_resolve_compress_callrT  Œ  s£   € ð
 ×*Ñ*×3Ñ3€KÜ3Ø M¸{ÐRWÐhvØ'ô€Oð ×ÑÔÐ"2¸/Ñ"IÜ˜e×6Ñ6¸ÄÀU×E]ÑE]Ó@^×@gÑ@gÓhˆÜ�5ÐCÀTÓJÈkÒYØ<GˆEÔ9Ü�N‰NØxØôð ˜Ð'Ð'rO   c               ó"  ‡‡— ddl m}m}m}	 ‰�‰j                  nd„ }
‰�‰j
                  nd}‰�t        | j                  ˆfd„|«       d
ˆˆfd„}t        j                  |«      }	 ‰�3‰j                  r't        j                  d| j                  xs d«       |}no ||
«      5   |	|«      5   ||¬	«      5  t        | j                  |«        ||fi |¤Ž}‰�‰j                  «       r
t!        «       ‚ddd«       ddd«       ddd«       t        j#                  |«       ‰�t%        | j                  |«       S # 1 sw Y   ŒHxY w# 1 sw Y   ŒLxY w# 1 sw Y   ŒPxY w# t        j#                  |«       ‰�t%        | j                  |«       w w xY w)zQRun the compressor under the fence's progress hook, deadline and interrupt guard.r   )Úaux_interrupt_protectionÚaux_progress_hookÚaux_stream_deadlineNc                  ó   — y rý   r<  r<  rO   r   ú<lambda>z'_run_summary_dispatch.<locals>.<lambda>ª  s   � rO   c                 ó   •— ‰ j                   S rý   )r  )rr  s   €r   rZ  z'_run_summary_dispatch.<locals>.<lambda>µ  s   ø€ ¨l×.GÑ.G€ rO   c                 ój   •— t        ‰d uxr ‰j                  «       xs ‰ d uxr ‰ j                  «      S rý   )rV   r  r  )rr  Úhard_cancel_events   €€r   Ú_compression_cancel_requestedz<_run_summary_dispatch.<locals>._compression_cancel_requested¸  s@   ø€ ÜØ dÐ*ÒIÐ/@×/GÑ/GÓ/Iò HØ DÐ(ÒF¨\×-FÑ-Fó
ð 	
rO   uU   Compression cancelled before summary dispatch (session=%s) â€” skipping summary work.r‚  )Úcancel_checkr4  )rf  rV  rW  rX  rù   r   r¨   rw  r…   r  r  r   rT   r¾   rš   r  r   rŠ  r«   )r4   rz  r¹  rR  rr  rÈ   r]  rV  rW  rX  Ú_progress_hookÚ_host_stream_deadliner^  Ú_attempt_ctx_tokenr¨  s       ` `        r   Ú_run_summary_dispatchrc  ¡  sŸ  ù€ ÷ hÑgØ4@Ð4L�\×0Ò0ÑS_€Nð @LÐ?W˜L×;Ò;Ð]aÐð Ðô 	-Ø×$Ñ$Ó&GÐI[ô	
ö
ô 8×;Ñ;Ð<NÓOÐðfð Ð#¨×(AÒ(AÜ�K‰KØgØ× Ñ Ò* Fôð "‰Jñ " .Ó1ñ:Ù3FÐG\Ó3]ñ:á(Ð6SÔTñ:ô 1°×1IÑ1IÐK]Ô^Ù(¨ÑE°_ÑE�
à$Ð0Ð5F×5MÑ5MÔ5OÜ7Ó9Ð9÷:÷ :÷ :ô 	'×,Ñ,Ð-?Ô@ØÐ#Ü7¸×8PÑ8PÐRdÔeØÐ÷!:ð :ú÷ :ð :ú÷ :ð :ûô 	'×,Ñ,Ð-?Ô@ØÐ#Ü7¸×8PÑ8PÐRdÕeð $úsT   Á'=E Â$	EÂ-
EÂ7<D:Ã3EÃ;EÄE Ä:EÄ?EÅE	ÅEÅEÅE Å0Fc                ó  — | j                   j                  «       }t        | j                   dd«      }d}t        j                  t
        «      5  t        |«      rt         |«       «      nd}ddd«       |r×t        t        |«      dz
  dd«      D ]»  }||   }t        |t        «      r|j                  d«      dk7  rŒ-|j                  d«      }t        |«      }||k(  rŒO|j                  d	«      r=t        ||«      r1|j                  |«       |t        |«      k  r0| j!                  |«       nt#        ||«       |j                  d	d«        n |�r,t%        |«      }	|	r|› d
|	› �}ddlm}
 d}|rt        |d   t        «      r|d   nd}|�Ù|j                  d«      dk(  rÅt        |j                  d«      «      }|j+                  «       D ��ci c]  \  }}|dk7  sŒ||“Œ }}}||d<   t-        |«      r/t        |t.        «      r|rd
|› �n|}t#        | |
||«      «       d}nC||j                  d«      k7  r/t1        d|dœ«      j3                  «       st#        ||«       d|d	<   d}|s|j5                  d|ddœ«       yyy# 1 sw Y   �ŒxY wc c}}w )zSStrip stale todo snapshots from ``compressed`` and fold the live one in (in place).Ú	has_itemsNFr9   rG  rô  rõ  rø  rs  r®  r   )Ú_append_text_to_contentTrÉ  )rô  rø  rs  )Ú_todo_storeÚformat_for_injectionr2   r‹   r˜   r   r´   rV   r¢  ry  r&   r(   r¡   rœ  rž  r¯  Ú_repair_message_sequencer¢  rª  r%   rf  r)   r~  rG   rr  rH   rš  )r4   r¨  Útodo_snapshotÚ_todo_has_itemsÚ_todo_store_is_authoritativeÚ	_todo_idxÚ_todo_messageÚ_todo_contentÚ_todo_strippedÚ_reload_noticerf  r³  Ú_tailÚ	_strippedÚkeyrÎ   Ú_probeÚ_snapshot_texts                     r   Ú_fold_todo_snapshotrw  Ü  s�  € à×%Ñ%×:Ñ:Ó<€Mô ˜e×/Ñ/°¸dÓC€Oð $)Ð Ü	×	Ñ	œYÓ	'ñ gÜBJÈ?ÔB[¤t©OÓ,=Ô'>ÐafÐ$÷gá#Üœs :›°Ñ2°B¸Ó;ò 	ˆIØ& yÑ1ˆMÜ˜m¬TÔ2°m×6GÑ6GÈÓ6OÐSYÒ6YØØ)×-Ñ-¨iÓ8ˆMÜ7¸ÓFˆNØ Ò.ØØ× Ñ Ð!;Ô<ÔA_Ø˜~ôBð —‘˜yÔ)Øœs :›Ò.ð ×2Ñ2°:Õ>ä(¨¸ÔGð ×!Ñ!Ð"<¸dÔCÙð+	ò, ô 5°ZÓ@ˆÙØ,˜o¨T°.Ð1AÐBˆMõ 	EØˆÙ",´¸JÀr¹NÌDÔ1Q�
˜2’ÐW[ˆØÐ §¡¨6Ó!2°fÒ!<Ü2°5·9±9¸YÓ3GÓHˆIØ38·;±;³=×U¡Z S¨%ÀCÈ9ÓDT�c˜5‘jÐUˆFÑUØ )ˆF�9ÑÜ$ VÔ,Ü;EÀiÔQTÔ;UÑZc 4¨ Ñ!7Ðiv�Ü(¨Ñ0GÈ	ÐSaÓ0bÔcØ‘à˜UŸY™Y yÓ1Ò1¼-ÐQWÐdmÑHnÓ:o×:uÑ:uÔ:wô )¨°Ô>Ø48�Ð0Ñ1Ø�ÙØ×Ñ v¸-ÐeiÑjÕkð ðI ÷3gñ güó^ Vs   ÁI<Ç
J	ÇJ	É<Jc                óâ  — | j                   }| j                  «        	 t        | «       | j                  |«      }|�!||k(  r|x}| _         ddlm}  || |d¬«       |S |x}| _         |�at        | dd	«      du rt        j                  nt        j                  } |d
| j                  xs dt        |«      t        |«      «       d| _        |S # t        $ r t        j                  dd¬«       Y ŒÄw xY w)zJRefresh tool schemas and rebuild the system prompt at the commit boundary.zWcompaction tool-definition refresh failed; keeping the session's existing tool snapshotTr   r   )Úreconstruct_static_prefixzcompression keep-prompt)r<  Ú	log_labelÚ_compaction_prompt_drift_loggedFzªCompaction rebuilt a drifted system prompt (session=%s, %d -> %d chars): builder output changed since the stored snapshot (update, config change, or memory/skills growth)r‚  )r:  Ú_invalidate_system_promptrX   r   r   rÊ   r;  Úagent.system_promptry  r2   r   rT   r¾   ry  r{  )r4   r<  Úcached_system_promptÚrebuilt_system_promptÚnew_system_promptry  rÌ  s          r   Ú"_rebuild_system_prompt_at_boundaryr�  &  s  € à ×6Ñ6ÐØ	×#Ñ#Ô%ð
Ü'¨Ô.ð "×6Ñ6°~ÓFÐØÐ'Ð,AÐEYÒ,YØ:NÐNÐ˜EÔ7ÝAÙ! %¸ÐRkÕlð Ðð ;PÐOÐ˜EÔ7ØÐ+ô #*¨%Ð1RÐTYÓ"ZÐ^bÑ"b”&—,’,Ôhn×hsÑhsˆCÙð]à× Ñ Ò* F¬CÐ0DÓ,EÄsÐK\ÓG]ôð
 59ˆEÔ1ØÐøô? ò 
Ü�‰ØeÐptð 	ö 	
ð
ús   žC Ã C.Ã-C.c               ó  — t        |«      }t        |«      }||kD  rQddlm}  ||||¬«      }	|	�>t        |	«      }
|
|k  r.t        j	                  d| j
                  xs d|d›|
d›«       |	}|
}||kD  rót        j                  d| j
                  xs d|d›|d›«       t        j                  t        «      5  d	| j                  _        ddd«       t        j                  t        «      5  | j                  d
«       ddd«       t        | |«      }t        | |d«       t        dd	¬«      5  | j                  j!                  «        ddd«       t#        | j                  |«       d|fS |dfS # 1 sw Y   Œ£xY w# 1 sw Y   Œ|xY w# 1 sw Y   Œ?xY w)aN  Anti-growth guard at the COMMIT SITE (in-place commits before the gateway can inspect).
    Compares like-for-like rough estimates; on growth tries one mechanical salvage pass, else treats the
    attempt as a refused no-op. Returns ``(compressed, None)`` to proceed or ``(None, prompt)`` when refused
    (caller releases the lease).r   )Úsalvage_grown_transcript)ÚbudgetNzTCompression salvage recovered a shrinking transcript (session=%s, ~%s -> ~%s tokens)r‚  r-  z—Compression refused: compressed transcript would be larger than the original (session=%s, ~%s -> ~%s tokens); keeping the original transcript unchangedTu«   âš ï¸� Compression refused: the generated summary would have GROWN the conversation instead of shrinking it. No messages were dropped â€” conversation continues unchanged.Ú
would_growz+could not record rejected-compaction striker   )r   r%   rƒ  r   rT   r¾   rÊ   r‹   r˜   r   rw  Ú!_last_compress_refused_would_growr'  r=  r?  r    Úrecord_rejected_compactionrC  )r4   rz  r¨  r<  r  rÛ   Ú	_rough_inÚ
_rough_outrƒ  Ú	_salvagedÚ	_salv_estr*  s               r   Ú#_salvage_or_refuse_grown_transcriptrŒ  U  s¤  € ô /¨xÓ8€IÜ/°
Ó;€JØ�IÒõ 	FÙ,¨X°zÈ)ÔTˆ	ØÐ Ü6°yÓAˆIØ˜9Ò$Ü—‘ØjØ×$Ñ$Ò.¨°9¸Q°-ÀYÈqÀMôð '�
Ø&�
Ø�IÒÜ�‰ðAØBG×BRÑBRÒB\ÐV\Ø˜ˆmØ˜!ˆnô		
ô × Ñ ¤Ó+ñ 	NØIMˆE×$Ñ$ÔF÷	Nä× Ñ ¤Ó+ñ 	Ø×Ñð_ô÷	ô
 /¨u°nÓEˆÜ'¨Ð/AÀ<ÔPô ÐCÈdÔSñ 	Bð ×$Ñ$×?Ñ?ÔA÷		Bô
 	$ E×$<Ñ$<Ð>NÔOØ�\Ð!Ð!Ø�tÐÐ÷%	Nð 	Nú÷	ð 	ú÷	Bð 	Bús$   Â5E)Ã(E5Ä(FÅ)E2Å5E>ÆF
c                óÒ   — t        | dd«      }t        |«      sy	 ddlm}  ||«      xs i }|j	                  d«      duxr  ||j	                  d«      «       S # t
        $ r Y yw xY w)zŸTrue when the parent row was ended by a non-automatic reason. Fails OPEN: an
    unreadable row must not turn a cheap guard into a new way to lose compression.r  NFr   )Úis_automatic_end_reasonr  r  )r2   r´   Úhermes_state_commonrŽ  r¡   r   )r½   r¾   ÚreaderrŽ  Úrows        r   Ú_parent_deliberately_endedr’  ’  sr   € ô �Z °Ó5€FÜ�FÔØðÝ?Ù�ZÓ Ò& BˆØ�w‰w�zÓ"¨$Ð.ÒeÑ7NÈsÏwÉwÐWcÓOdÓ7eÐ3eÐeøÜò Ùðús   ›>A Á	A&Á%A&c                ó  — t        d«      5  ddlm}  ||| j                  d¬«       ddd«       t        d«      5  ddlm}  ||| j                  «       ddd«       t        d	«      5  dd
lm}  ||| j                  d¬«       ddd«       |syd}t        d«      5  | j                  j                  |«      }ddd«       	 | j                  j                  | j                  |«       |�;t        d«      5  | j                  j                  | j                  |«       ddd«       yy# 1 sw Y   ŒþxY w# 1 sw Y   ŒÝxY w# 1 sw Y   ŒºxY w# 1 sw Y   Œ’xY w# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w# 1 sw Y   yxY w)a©  Migrate /goal, /heartbeat, /loop state and the title from the parent to the child.
    Each lookup is a flat per-session read with no parent walk, so state would silently die at the boundary. The title
    is carried unchanged (renumbering per rotation made one session look like many); its provenance is read BEFORE the
    transfer clears the ancestor's row, then restored so an inherited auto-title stays upgradeable.
    z)Could not migrate goal on compression: %sr   )Úmigrate_goal_to_sessionr_  rú  Nz.Could not migrate heartbeat on compression: %s)Úmigrate_heartbeat_to_sessionz)Could not migrate loop on compression: %s)Úmigrate_loop_to_sessionz#Could not read title provenance: %sz,Could not propagate title on compression: %sz(Could not propagate title provenance: %s)r    Úhermes_cli.goalsr”  r¾   Úhermes_cli.heartbeatr•  Úhermes_cli.loopsr–  r­   Úget_session_title_sourceÚset_session_titler   r   r   Úset_session_title_source)r4   r…  Ú	old_titler”  r•  r–  Ú_srcÚes           r   Ú_carry_session_state_to_childr      s‡  € ô 
Ð=Ó	>ñ Xõ 	=Ù °×0@Ñ0@ÈÕW÷Xô 
ÐBÓ	Cñ GÝEÙ$ ^°U×5EÑ5EÔF÷Gô 
Ð=Ó	>ñ XÝ<Ù °×0@Ñ0@ÈÕW÷Xñ ØØ€DÜ	Ð7Ó	8ñ JØ× Ñ ×9Ñ9¸.ÓIˆ÷JðØ×Ñ×+Ñ+¨E×,<Ñ,<¸iÔHð
 ÐÜÐ@ÓAñ 	OØ×Ñ×6Ñ6°u×7GÑ7GÈÔN÷	Oð 	Oð ÷/Xð Xú÷Gð Gú÷Xð Xú÷Jð Jûô ò Ü�‰ÐCÀQÔGÜûðú÷
	Oð 	OúsR   ŒD%»D1Á(D=ÂE	Ã&E Ã4'FÄ%D.Ä1D:Ä=EÅ	EÅ	E>ÅE9Å9E>ÆF
c                óú   — d}t        j                  t        «      5  | j                  j	                  |«      }ddd«       |r|j                  d«      r|d   S ddlm}  |t        | dd«      «      S # 1 sw Y   Œ:xY w)zÑThe parent row's persisted source: a compression child is the same conversation, so a ``--source tool``,
    ``oneshot`` or inherited ``kanban`` label must not degrade to the bare ``agent.platform`` (#112550).NrÛ  r   )Ú_session_source_for_agentr�  )	r‹   r˜   r   r­   r  r¡   Ú	run_agentr¢  r2   )r4   r‰  Úparentr¢  s       r   Ú_compression_child_sourcer¥  Â  sw   € ð €FÜ	×	Ñ	œYÓ	'ñ BØ×"Ñ"×.Ñ.Ð/@ÓAˆ÷Bá�&—*‘*˜XÔ&Ø�hÑÐÝ3Ù$¤W¨U°JÀÓ%EÓFÐF÷Bð Bús   œA1Á1A:c               óp  — t        | dd«      }t        |t        «      rd|cxk  rt        |«      k  rn n|d| nd}t	        | j
                  |«      rt        d|› �«      ‚d}	t        j                  t        «      5  | j
                  j                  | j                  «      }	ddd«       t        j                  t        «      5  | j                  ||¬«       ddd«       d}
t        j                  t        «      5  ddlm}  |«       }
ddd«       |
dk(  rd}
| j
                  j                  | j                  «      }t!        «       }ddlm} | j
                  j'                  ||t)        | |«      | j*                  | j,                  ||t        | d	d«      |
|j.                  |j.                  du|j.                  du|j0                  |	�|j2                  nd|	¬
«       |dv r`t5        d„ t7        |«      D «       d«      }t        |t8        «      r4d||<   t        | dd«      }t        |t:        «      r||urt=        ||d¬«       |D ]  }t        |t8        «      sŒd||<   Œ || _        d| _        tA        | j                  «       d| _!        tE        | ||«       y# 1 sw Y   �ŒòxY w# 1 sw Y   �ŒÊxY w# 1 sw Y   �Œ¦xY w)a  Rotate the session: flush the parent, publish the child, re-point the agent.
    Flushes current-turn msgs to the OLD session, passing the durable prefix (messages[:persist idx]) so
    preflight, which runs before rows are marker-stamped, can't re-append them.r>  Nr   z"Compression parent already ended: r?  )Úget_active_profile_namer„   r#   Úworking_directory)r‰  r•  rÛ  rx  Úmodel_configr  rz  ÚcwdÚprofile_nameÚcompression_lock_holderÚrequire_compression_leaseÚrequire_lease_refreshÚlease_ttl_secondsr  Úwatermark_ceiling>   r³  rµ  c              3  ó8   K  — | ]  }t        |«      sŒ|–— Œ y ­wrý   rÄ  )rµ  r+   s     r   r·  z._publish_rotated_compaction.<locals>.<genexpr>  s   è ø€ Ò)d°ÔK`ÐabÕKc¬!Ñ)dùs   ‚“TÚ_session_messagesr×  )#r2   r&   r‘   ry  r’  r­   rµ   r‹   r˜   r   r  r¾   rA  Úhermes_cli.profilesr§  Úget_session_titleÚmint_session_idr%   r$   Úpublish_compression_childr¥  rx  Ú_session_init_model_configr¤  r   r  ÚnextrË  r(   r'   rÞ  Ú_db_flush_scan_prefixr{  r‹  r   )r4   rz  r¨  r€  r  r…  Úcompressed_user_turn_outcomeÚcurrent_idxÚpersisted_historyÚ_foreign_tail_ceilingÚ_profile_for_childr§  r�  r   r$   Ú_compressed_anchor_sourcer²  Ú_handoff_messages                     r   Ú_publish_rotated_compactionrÁ  Î  s­  € ô ˜%Ð!<¸dÓC€Kä",¨[¼#Ô">À1ÈÔCdÔWZÐ[cÓWdÕCdˆ��+ÑÐjnð ô " %×"3Ñ"3°^ÔDÜÐ?ÀÐ?OÐPÓQÐQð !ÐÜ	×	Ñ	œYÓ	'ñ aØ %× 1Ñ 1× NÑ NÈu×O_ÑO_Ó `Ð÷aä	×	Ñ	œYÓ	'ñ ^Ø×+Ñ+¨HÐK\Ð+Ô]÷^ð
 ÐÜ	×	Ñ	œYÓ	'ñ 7Ý?Ù4Ó6Ð÷7ð ˜YÒ&Ø!ÐØ×!Ñ!×3Ñ3°E×4DÑ4DÓE€IÜ$Ó&€NÝ=Ø	×Ñ×/Ñ/Ø(¸>Ü(¨°Ó?ÀuÇ{Á{Ø×5Ñ5ÐEVÐakÜ�EÐ.°Ó5ÐDVØ %§¡ÈÏÉÐ\`ÐH`Ø#Ÿl™l°$Ð6È%Ï)É)Ø&;Ð&G�5—?’?ÈTØ/ð 0ô 	ð $Ð'=Ñ=ô %)Ñ)d´X¸hÓ5GÔ)dÐfjÓ$kÐ!ÜÐ/´Ô6Ø>BÐ%Ð&:Ñ;Ü '¨Ð/BÀDÓ IÐÜÐ+¬TÔ2Ð7HÐPXÑ7Xô $Ð$5Ð7PÐgkÕlØ&ò :ÐÜÐ&¬Õ-Ø59ÐÐ1Ò2ð:ð &€EÔØ"&€EÔÜ˜E×,Ñ,Ô-Ø $€EÔÜ! %¨¸ÕC÷_añ aú÷^ñ ^ú÷7ñ 7ús$   Á;&JÃJÃ9J+ÊJÊJ(Ê+J5c                óŒ  — t        | j                  dd«      }|r.t        | dd«      |k7  r|| _        | j                  d|› d�«       yyt        | j                  dd«      }t        | j                  dd«      }||f}|rIt        | dd«      |k7  r8|| _        t
        j                  d	||xs d
«       | j                  d|› d�«       yyy)zPSurface a failed summary, or a recovered-but-broken aux compression model, once.rd   NÚ!_last_compression_summary_warningu    âš  Compression summary failed: z%. Inserted a fallback context marker.rp   ro   Ú_last_aux_fallback_warning_keyzLConfigured compression model %r failed (%s); recovered using the main model.úunknown erroru"   â„¹ Configured compression model 'zn' failed, so Hermes summarised with your main model instead. Check auxiliary.compression.model in your config.)r2   rw  rÃ  r'  rÄ  r   rÊ   )r4   Úsummary_errorÚ_aux_fail_modelÚ_aux_fail_errÚ_aux_keys        r   Ú_warn_summary_or_aux_fallbackrÊ    sï   € ä˜E×4Ñ4Ð6KÈTÓR€MÙÜ�5Ð=¸tÓDÈÒUØ6CˆEÔ3Ø×ÑÐ"BÀ=À/ÐQvÐ wÕxð Vô " %×":Ñ":Ð<[Ð]aÓbˆÜ × 8Ñ 8Ð:YÐ[_Ó`ˆà# ]Ð3ˆÙœw uÐ.NÐPTÓUÐYaÒaØ3;ˆEÔ0Ü�N‰NØ^Ø Ò!A°/ôð ×ÑØ4°_Ð4Eð Fbð bõð  bˆ?rO   rD   ©r¾   Úskillsc               óv  — t        j                  t        «      5  ddlm}  || «       ddd«       |r0t        j                  t        «      5  ddlm}  ||«       ddd«       |syt        j                  t        «      5  ddlm}  || «       ddd«       y# 1 sw Y   ŒoxY w# 1 sw Y   ŒIxY w# 1 sw Y   yxY w)a™  Advance the file-read (and skill_view) repeat-read dedup to a fresh generation after a boundary.
    The mtime map is kept: the first read of each unchanged key returns full content compaction may have
    omitted; later reads return stubs, and stub-hit counters restart at the same boundary (#84857).
    The computer_use screenshot dedup is session-keyed and forgets its last frame for the same reason.
    r   )Úreset_file_dedupN)Úreset_screenshot_dedup)Úreset_skill_view_dedup)	r‹   r˜   r   Útools.file_tools_read_trackingrÎ  Útools.computer_use.toolrÏ  Útools.skills_toolrÐ  )Útask_idr¾   rÌ  rÎ  rÏ  rÐ  s         r   Ú_reset_read_dedup_cachesrÕ  .  s    € ô 
×	Ñ	œYÓ	'ñ "ÝCÙ˜Ô!÷"ñ Ü× Ñ ¤Ó+ñ 	/ÝFÙ" :Ô.÷	/ñ ØÜ	×	Ñ	œYÓ	'ñ (Ý<Ù˜wÔ'÷(ð (÷"ð "ú÷	/ð 	/ú÷
(ð (ús#   šBÁB#Á?B/ÂB Â#B,Â/B8c       
   
     óÚ  — |}|xs | j                   xs d}|rO|rMt        dd¬«      5  t        | dd«      }t        t        t	        |«      dd«      x}«      r	 |||«       ddd«       |r4t        |«      s|r'|rt        nt        } || | j                   xs d|¬«       t        d	«      5  t        |«      s|r9| j                  r-| j                  j                  | j                   xs d|d
d¬«       ddd«       | j                  }|j                  }|dk\  r*| j                  › d|› d�}|| _        | j                  |«       t        | dd«      rRt        d«      5  | j                  d| j                   xs d| j                   |xs d||j                  dœ«       ddd«       || _        || _        t'        ||xs d| j(                  xs d¬«      }||_        d|_        d|_        d|_        t3        | d«       |r4t        t	        |«      dd«      }t        |«      r |||	|
¬«       nd|_        t7        || j                   xs d¬«       |S # 1 sw Y   �ŒéxY w# 1 sw Y   �ŒfxY w# 1 sw Y   ŒÌxY w)z™Post-commit bookkeeping: notify engines/providers/hooks, re-arm usage tracking.
    Returns the rough post-compression token estimate (diagnostics only).rD   zGfailed to clear archived compression parent's activity labels (ignored)Tr   r­   NÚclear_session_activity_labelsrë  z2memory manager on_session_switch (compression): %sFr_  rˆ  rÈ  u   âš ï¸�  Session compressed u>    times â€” accuracy may degrade. Consider /new to start fresh.Úevent_callbackz,event_callback error on session:compress: %szsession:compress)r�  r¾   r…  Úin_placer[   )r  ÚtoolsrG  r   Úrecord_completed_compaction)Úused_fallbackÚfeasibility_skip)r¾   )r¾   r    r2   r´   r³   rV   rî  rç  rò  r�  rw  r[   Ú
log_prefixr  r  rØ  r�  ri  rj  r   rÚ  Úlast_compression_rough_tokensÚlast_prompt_tokensÚlast_completion_tokensÚ%awaiting_real_usage_after_compressionr   r`   rÕ  )r4   r¨  r€  r…  rÙ  Úcompacted_in_placeÚsession_commit_succeededÚ!defer_context_engine_notificationÚcompression_made_progressÚcompression_used_fallbackÚcompression_feasibility_skiprÔ  Ú_old_sidÚ_boundary_parentÚ
_labels_dbÚ_clear_labelsÚnotifyr~   Ú_ccÚ_cc_msgÚ_compressed_estÚrecord_boundarys                         r   Ú_finish_compaction_boundaryrò  B  s”  € ð €HØÒ9 5×#3Ñ#3Ò9°rÐñ Ñ,ÜÐ_ÐjnÔoñ 	4Ü  ¨°tÓ<ˆJÜ¬´°jÓ1AÐCbÐdhÓ)iÐi˜ÔjÙ˜j¨(Ô3÷	4ñ  ¤T¨(¤^Ñ7Iñ 1õ ;ä<ð 	ñ
 	ˆu U×%5Ñ%5Ò%;¸ÐL\Õ]ô 
ÐFÓ	Gñ Ü�ŒN™h¨E×,AÒ,AØ×!Ñ!×3Ñ3Ø× Ñ Ò& BÐ:JÐRWÐ`mð 4ô ÷ð ×)Ñ)€JØ
×
&Ñ
&€CØ
ˆa‚xà×ÑÐ Ð ;¸C¸5Ð@~Ðð 	ð &-ˆÔ"Ø×%Ñ% gÔ.ô ˆuÐ&¨Ô-ÜÐDÓEñ 	Ø× Ñ Ø"à %§¡Ò 4°"ÀE×DTÑDTØ&.¢n°"À(Ø)3×)EÑ)Eñô÷	ð 0B€EÔ,Ø&8€EÔ#ô 4ØÐ"3Ò"9°rÀÇÁÒATÐPTô€Oð 0?€JÔ,Ø$&€JÔ!Ø()€JÔ%Ø7;€JÔ4ô �U˜DÔ!ñ !Ü!¤$ zÓ"2Ð4QÐSWÓXˆÜ�OÔ$ÙØÐ*CÐVröð ?CˆJÔ;Ü˜W°×1AÑ1AÒ1GÀRÕHØÐ÷W	4ñ 	4ú÷"ñ ú÷(	ð 	ús$   ¨8IÂ)AIÅ?I!ÉIÉIÉ!I*c               ó
  — t        | j                  dd«      r[t        | j                  dd«      }|xs d}t        | dd«      |k7  r|| _        | j                  d|› d�«       t	        | ||xr d	«       y
||k(  st        |«      t        |«      k(  r�||k7  rt        j                  |«      |dd t        j                  d| j                  xs d«       t        dd
¬«      5  t        t        | j                  dd«      x}«      r |d«       ddd«       t	        | |d«       y
|sXt        j                  d| j                  xs d«       t        j                  t         «      5  | j                  d«       ddd«       y
t#        | j                  |«      s^t        | j                  dd«      }	t        j%                  d||	| j                  xs d«       t'        ||«       d| _        t	        | |d«       y
y# 1 sw Y   ŒæxY w# 1 sw Y   y
xY w)a(  Reject an unusable compression candidate before any session mutation.
    Order matters: compressor-reported abort, no progress, empty transcript, superseded attempt. Each branch surfaces
    its own warning/telemetry; the caller releases the lease and returns the input unchanged when True.
    ri   Frd   NrÅ  rÃ  u   âš  Compression aborted: uz   . No messages were dropped â€” conversation continues unchanged. Run /compress to retry, or /new to start a fresh session.Úsummary_generation_abortedTuH   Compression made no progress (session=%s) â€” skipping boundary rewrite.r‚  zno-progress backoff arm failedr   Ú_record_structural_no_opz:compaction returned the transcript unchanged (no_progress)Úno_progresszocontext compression returned an empty transcript; refusing to rotate session=%s so the parent remains resumableuo   âš  Compression returned an empty transcript. No session split was performed; conversation continues unchanged.r™   zŠDiscarding late compression candidate: attempt generation %s was superseded by a newer working attempt (current working: %s) (session=%s).Úattempt_superseded)r2   rw  rÃ  r'  r?  r.   r|   r}   r   rT   r¾   r    r´   r…  r‹   r˜   r   r    rÊ   rA  rj  )
r4   r¨  rz  Úmessages_before_compressionrÈ   r  Ú_summary_errorÚ_errÚ	_recorderÚ_working_gens
             r   Ú_candidate_rejectedrý     s#  € ô ˆu×'Ñ'Ð)AÀ5ÔIÜ  ×!9Ñ!9Ð;PÐRVÓWˆØÒ0 ˆÜ�5Ð=¸tÓDÈÒLØ6:ˆEÔ3Ø×ÑØ+¨D¨6ð 2Lð Lôô
 	(ØÐ% ~Ò'VÐ:Vô	
ð ð Ð0Ò0Ü$ ZÓ0Ô4PÐQlÓ4mÒmàÐ2Ò2ÜŸ-™-Ð(CÓDˆH‘QˆKÜ�‰ØVÐX]×XhÑXhÒXrÐlrô	
ô
 Ð6ÀÔFñ 	XÜ¤W¨U×-EÑ-EÐGaÐcgÓ%hÐh˜	ÔiÙÐVÔW÷	Xô 	(¨Ð/AÀ=ÔQØÙÜ�‰Ø}Ø×ÑÒ& ô	
ô × Ñ ¤Ó+ñ 	Ø×Ñð Bô÷	ð ô ' u×'?Ñ'?ÐASÔTÜØ×$Ñ$Ð&OÐQUó
ˆô 	�‰ð_àØØ×ÑÒ& ô	
ô 	# 8Ð-HÔIØ*/ˆÔ'Ü'¨Ð/AÐCWÔXØØ÷I	Xð 	Xú÷	ð ús   Ã+G-ÅG9Ç-G6Ç9Hc                  óz   — e Zd ZU dZded<   ded<   dZded<   dZded	<   d
Zded<   dZded<   dZ	ded<   dZ
ded<   y)Ú_CommitOutcomez<Result of the SessionDB commit phase (in-place or rotation).r'   r¨  r¶   r!  Nr¾  Úrefused_promptr…  Únot_applicablerG   rá  FrV   rä  rã  Úmade_progress)r7  r8  r9  r:  Ú__annotations__r   r…  rá  rä  rã  r  r<  rO   r   rÿ  rÿ  ð  sO   … áFàÓØÓØ$(€N�MÓ(Ø$(€N�MÓ(Ø(€L�#Ó(Ø%*Ð˜dÓ*Ø$Ð˜Ó$Ø€M�4ÔrO   rÿ  Ú_Attemptc               óx  ‡— d}d}t        j                  «       }d}d}| j                  �rrd}	 | j                  |«       |D �ch c]1  }t	        |t
        «      sŒ|j                  dd«      sŒ't        |«      ’Œ3 c}Št        | ||||
j                  |
j                  ¬«      \  }}|€t        |||¬«      S |r¤dd	lm}m} | j                  j                  | j                   ||di|j"                  |j$                  t'        ˆfd
„|D «       «      ¬«       d} ||«       t)        «       | _        d}| j                  j-                  | j                   |«       d| _        nA| j                   }t1        | ||||||¬«       d}t3        |«      | _        | j                   | _        d}t        |||||||	¬«      S c c}w # t6        $ rü}| xr |xr | j                   |k(  }|s	|rG|dk7  rB|�@|rd}t9        j:                  |«      |dd |}d}	t=        | j>                  |
j                  «       |€|sdnd}|€(|s&t@        jC                  d| j                   xs d|«       nt@        jC                  d|«       tE        dd¬«      5  | j>                  jG                  tH        d|› �«       ddd«       n# 1 sw Y   nxY wY d}~�Œd}~ww xY w)aA  Persist the compacted transcript: memory extraction, anti-growth guard, then the
    in-place archive or the parent->child rotation.

    Failures roll the live list back and arm the split-failure cooldown; a refused (would-grow) candidate returns
    ``refused_prompt`` so the caller hands back the input unchanged.
    Fr  Nrñ  Ú_compaction_tail)r<  r  rÛ   )r¨  r   r!  r   )Ú&PROACTIVE_PRUNE_REARM_MODEL_CONFIG_KEYÚstamp_db_persisted_markersc              3  ó>   •K  — | ]  }t        |«      ‰v sŒd –— Œ y­w)r9   N)rŽ  )rµ  r+   Ú_tail_tagged_idss     €r   r·  z%_commit_compaction.<locals>.<genexpr>)  s   øè ø€ Ò"V¨¼B¸q»EÐEUÒ<U¤1Ñ"Vùs   ƒ–)Úmodel_config_patchr  Úlock_holderÚ
tail_countÚin_place_committedT)r€  r  r…  rº  Úrotated_committedrÝ  Úfailed_not_indexedzKCompression rotation aborted and rolled back to the parent session (%s): %sr  uK   Session DB compression split failed â€” new session will NOT be indexed: %sz'could not record split-failure cooldownr   zsession_split_failed: )r¨  r!  r…  rá  rä  rã  r  )%r¸   r¹   r­   Úcommit_memory_sessionr&   r(   r¯  rŽ  rŒ  rs  rº   rÿ  r%   r  r  Úarchive_and_compactr¾   r  r¤  Úsumr  r�  Úupdate_system_promptrŒ  rÁ  ry  r�  r   r|   r}   rC  rw  r   rÊ   r    Ú$_record_compression_failure_cooldownÚ_SPLIT_FAILURE_COOLDOWN_SECONDS)r4   rz  r¨  rÙ  r  r€  r<  rº  rø  r  r;   rä  rã  r!  rá  r…  r+   Ú_refused_spr  r  rŸ  Úrotation_rollbackr
  s                         @r   Ú_commit_compactionr  þ  sî  ø€ ð  %ÐØÐÜŸ™Ó(ÐØ#€LØ$(€NØ×ÓØ ˆðq	ð ×'Ñ'¨Ô1ð 0:Öu¨!¼ZÈÌ4Õ=PÐUV×UZÑUZÐ[mÐosÕUt¤ 1¥ÒuÐÜ&IØ�x ¸NÐ_f×_qÑ_qØ!(×!1Ñ!1ô'Ñ#ˆJ˜ð Ð!Ü%Ø'¸ÐWhôð ñ ÷ xð ×!Ñ!×5Ñ5Ø×$Ñ$ jÐFlÐnrÐEsØ#Ÿo™o¸5¿<¹<Ü"Ó"V¨jÔ"VÓVð 6ô ð
  4�ñ +¨:Ô6Ü03³�Ô-ð &*Ð"à×!Ñ!×6Ñ6°u×7GÑ7GÐIZÔ[Ø-.�Õ*ð  "'×!1Ñ!1�Ü+Ø˜8 ZÐCTÐ\aØ#1ÐPlõð  3�Ü-0°«_�Ô*Ø7<×7GÑ7G�Ô4Ø'+Ð$ôh ØÐ1BÐSaØ!Ð<TØ-¸]ôð ùòW  vøôp ò 2	ð %- Ò f°Ò fÀE×DTÑDTÐXfÑDfÐÙ Ù˜\Ð-AÒAÐFaÐFmá$Ø%)�Nô$ #Ÿm™mÐ,GÓH�™�Ø%�
Ø %�Ü+¨E×,DÑ,DÀg×FVÑFVÔWØ(6Ð(>Áx™9ÐUiˆLð Ð%©hÜ—‘ØaØ×$Ñ$Ò+¨¨Qõô
 —‘ÐlÐnoÔpô ÐCÈdÔSñ à×(Ñ(×MÑMÜ3Ð7MÈaÈSÐ5Qô÷÷ ñ ÿüð]2	úsU   ®F4 ÁF/ÁF/Á,F/Á9:F4 Â4C)F4 Æ/F4 Æ4	J9Æ=B8J4É5$J"Ê	J4Ê"J+	Ê'J4Ê4J9c                  ób   — e Zd ZU dZded<   dZded<   dZded<   dZd	ed
<   dZded<   dZ	ded<   y)Ú_SummaryPhasezPOutcome of the summary phase; ``abort_prompt`` set means hand ``messages`` back.r'   rz  Nr   r¨  úOptional[list]rø  úOptional[int]r{  r   r‘   Úpre_msg_countr¾  Úabort_prompt)
r7  r8  r9  r:  r  r¨  rø  r{  r  r  r<  rO   r   r  r  ‰  s=   … áZàƒNØ€J�ÓØ26Ð Ó6Ø#'€M�=Ó'Ø€M�3ÓØ"&€L�-Ô&rO   r  c          
     ó¦  ‡— t        |«      }dŠd}dˆfd„}	 |j                  «        |s.t        | ||«      }|�|}t        |«      }d}t        |«      | _        t	        | ||«      }t        | |||||¬«      \  }}t        j                  |«      }t        | |	|j                  ¬«      j                  «       Št        | ||||	|j                  |
¬«      }	  |d«       t3        |||||¬«      S # t        $ rÿ 	 |j                  | j                  «       nc# t         $ rW}t#        ||«        |d«       |j%                  «        t'        | |j(                  dt+        |«      j,                  › �«       ‚ d}~ww xY wt#        ||«       t/        | |	|j(                  ||¬	«      } |d
«       |j%                  «        t'        | |j(                  |rt0        nd«       t3        |t5        | |«      ¬«      cY  |d«       S t         $ rK} |d«       |j%                  «        t'        | |j(                  dt+        |«      j,                  › �«       ‚ d}~ww xY w#  |d«       w xY w)a  Adopt a grown durable parent, gather memory context and run the summarizer.
    A hard cancel restores the compressor snapshot + live list, records a stall backoff while the lease is
    still held, and aborts; any other failure releases the lease and re-raises.Nc                ó2   •— ‰�‰j                  | «       d Šy y rý   )rÝ  )rÜ  Ú_activity_heartbeats    €r   Ú_stop_heartbeatz+_run_summary_phase.<locals>._stop_heartbeat¢  s"   ø€ àÐ*Ø×$Ñ$ TÔ*Ø"&Ñð +rO   r   )r{  r®  r¯  r°  re  )rr  r¾  )rr  rÈ   r]  z#context compression rollback failedz	rollback:©rr  rs  rz  r{  zcontext compression cancelledÚexplicit_interrupt)rz  r  rð  úcontext compression failedz
exception:)rz  r¨  rø  r{  r  rñ  )ry  r  rF  r>  rO  rT  r|   r}   r½  rö  rÕ  rc  r“   r   Úrestore_compressorrw  ré  rA  r  r?  rs  r³   r7  r†  rƒ  r  r=  )r4   rz  r  rÙ  rL  r{  r®  r¯  re  rr  r]  r<  r;   r  rø  r#  Ú_adopted_parentr°  r¹  rR  r¨  Ú_rollback_excÚ_stall_backoffÚ_compress_excr"  s                           @r   Ú_run_summary_phaser,  •  sg  ø€ ô ˜“M€MØCGÐØ"&Ðõ'ð89Ø×ÑÔÙÜ9¸%ÀÈÓQˆOØÐ*Ø*�Ü # H£�à !�ô 36°h³-�Ô/Ü5°e¸XÐGZÓ[ˆÜ'=Ø ¸KÈuÐesØ+ô(
Ñ$ˆ�_ô '+§m¡m°HÓ&=Ð#Ü;Ø À×AUÑAUô
ç
‰%‹'ð 	ô +Ø�8˜[¨/ÈØ&×1Ñ1ÐEVô
‰
ñF 	Ð7Ô8ÜØ jÐNiØ#°=ôð øôA )ò mð		Ø×&Ñ& u×'?Ñ'?Õ@øÜò 	ô ' xÐ1LÔMÙÐAÔBØ�M‰MŒOÜ+¨E°7×3EÑ3EÈÔSWÐXeÓSf×SoÑSoÐRpÐGqÔrØûð	úô 	# 8Ð-HÔIô ;Ø ¸×9KÑ9KÐV^Ø'ô
ˆñ 	Ð7Ô8Ø�‰ŒÜ'Ø�7×%Ñ%É>Õ(GÐ_sô	
ô  hÔ=TÐUZÐ\jÓ=kÔlÑlñ 	Ð7Õ8ô ò áÐ4Ô5Ø�‰ŒÜ'¨¨w×/AÑ/AÀZÔPTÐUbÓPc×PlÑPlÐOmÐCnÔoØûðûñ 	Ð7Õ8úsW   ˜B8C) Ã)	IÃ3DÄIÄ	E/ÄAE*Å*E/Å/A7IÇ&I Ç0IÇ8AH>È>IÉI É
Ic                  óT   — e Zd ZU dZded<   ded<   ded<   dZd	ed
<   dZded<   dd„Zy)r  zIPer-attempt ownership state threaded through the compress_context phases.r(   rº   r‘   r“   r¶   rs  Nr5  rÆ   úOptional[dict[str, Any]]rÇ   c                ót   — t        || j                  | j                  | j                  | j                  ¬«       y)zPRoll the compressor back to this attempt's snapshot (durable cooldown included).rÅ   N)rÏ   rº   rÆ   rÇ   r“   )rñ   r~   s     r   r'  z_Attempt.restore_compressorñ  s-   € ä)Ø˜Ÿ™Àd×FiÑFiØ#'×#>Ñ#>ÐSW×SbÑSbö	
rO   ©r~   r   r1  r2  )r7  r8  r9  r:  r  rÆ   rÇ   r'  r<  rO   r   r  r  ç  s1   … áSàƒNØƒOØÓØ59Ð" NÓ9Ø7;ÐÐ4Ó;ô
rO   c               ó  — t        | j                  «      }t        | j                  «      }|r%t        t	        | t
        d«      «      rt        d«      ‚d| _        d| _        d| _	        d| _
        t        j                  «       }t        j                  «       j                  }t!        j"                  t$        «      5  || _        || j(                  xs d|rdnddœ| j                  _        ddd«       t-        |||«      S # 1 sw Y   ŒxY w)aú  Snapshot + claim the compressor, reset per-attempt agent signals, seed telemetry.
    The claim stops a late-unwinding sibling (stall-fallback overlap) from restoring its snapshot over ours or
    clearing our cancellation consult. Signals are cleared at the VERY TOP, before codex/breaker
    early-returns, so a stale value cannot make a later no-op look like lock contention;
    ``_last_compression_attempt_in_place=None`` means aborted/no boundary for
    ``conversation_history_after_compression()``.Nré  TrD   Úmanualr  )r%  r¾   Útrigger_source)r‚   rw  r”   r´   r2   rí  rµ   rh  ri  rE  rj  r¸   r¹   r1  r2  r3  r‹   r˜   r   r&  r¾   rv   r  )r4   r¯  Údefer_notificationrº   r“   rs  r%  s          r   Ú_begin_compression_attemptr5  ù  sè   € ô 2°%×2JÑ2JÓK€HÜ*¨5×+CÑ+CÓD€JÙœh¤w¨uÔ6ZÐ\`Ó'aÔbÜÐJÓKÐKØ/3€EÔ,Ø/3€EÔ,Ø-1€EÔ*ð ,0€EÔ(Ü—‘Ó!€JÜ—‘“×!Ñ!€JÜ	×	Ñ	œYÓ	'ñ 
Ø(2ˆÔ%à$°E×4DÑ4DÒ4JÈÙ*/™h°Vñ@
ˆ× Ñ Ô<÷
ô �H˜j¨*Ó5Ð5÷
ð 
ús   Â9/C=Ã=Dc               ó
  — |�E|j                  t        | dd«      «      s)|j                  | j                  «       |t	        | |«      fS 	 t        | |||||¬«      |�|j                  «        S S # |�|j                  «        w w xY w)zOCodex owns the real thread: run its own compact under the commit fence bracket.Nr¬  ©r{  rÔ  r¯  )r  r2   r'  rw  r=  Ú&_compress_context_via_codex_app_serverr  )r4   rz  r<  rr  r;   r{  rÔ  r¯  s           r   Ú_route_codex_compactionr9    s–   € ð
 Ð¨×(AÑ(AÄ'È%ÐQlÐnrÓBsÔ(tØ×"Ñ" 5×#;Ñ#;Ô<ØÔ0°¸ÓGÐGÐGð)Ü5Ø�8˜^¸=ÐRYÐafô
ð Ð#Ø×&Ñ&Õ(ð $øˆ<Ð#Ø×&Ñ&Õ(ð $ús   Á	A- Á-Bc          	     ó  — t         j                  d| j                  xs d||r|d›nd| j                  |«       t        }|s&t        | j                  d|||| j                  |¬«      }|r| j                  |«       t        | t        |«      «      S )zXLog the attempt, emit the (engine-customisable) compacting status, return the lifecycle.zPcontext compression started: session=%s messages=%d tokens=~%s model=%s focus=%rr‚  r-  rp  rF   )ÚphaseÚdefault_messager{  Úmessage_countrx  r®  )
r   rT   r¾   rx  ÚCOMPACTION_STATUSr   rw  ré  rô  rV   )r4   r=  r{  r®  r¯  Ústatuss         r   Ú_announce_compression_startr@  +  sŒ   € ô ‡K�KØZÐ\a×\lÑ\lÒ\vÐpvØ©}˜-¨Ñ*À)ÈUÏ[É[ÐZeôô €FÙÜ4Ø×$Ñ$¨JÈÐ^kØ'¨u¯{©{Èô
ˆñ Ø×Ñ˜6Ô"Ü ¤t¨F£|Ó4Ð4rO   r„   )r{  rÔ  r®  r¯  re  rå  rr  c               ó  ‡ — t        ‰ ||¬«      }
t        ‰ dd«      du }t        ‰ dd«      dk(  r |rt        d«      ‚t        ‰ |||	|
|||¬	«      S |st	        ‰ |«      r|t        ‰ |«      fS t        |«      }t        t        ‰ d
d«      «      }t        ‰ ||||¬«      }t        ‰ dd«      s	 t        ‰ «       d‰ _        t        ‰ |	||||
j                  ¬«      \  }}|€||fS |j                  «        t!        ‰ |||«      }|�|S t#        ‰ j$                  |
j&                  «      \  |
_        |
_        |
j(                  du r|j-                  «        |t        ‰ |«      fS |s,t	        ‰ |d¬«      r|j-                  «        |t        ‰ |«      fS t        ‰ dd«      }t/        ‰ |||||||||	|||
¬«      }|j0                  �|j2                  |j0                  fS |j2                  |j4                  }}|j6                  }|j8                  |j:                  }}d}	 ˆ fd„dD «       \  }}}t=        ‰ ||||
j>                  |
j                  ¬«      r2|t        ‰ |«      f	 |j-                  «        |r|	jA                  «        S S |	�Ò|	jC                  |«      }|s¿|
jE                  ‰ j$                  «       tG        ||«       tH        jK                  d‰ jL                  xs d«       d‰ _'        tQ        ‰ |	|
j                  ||¬«      }t        ‰ |«      }tS        ‰ |
j                  |rtT        nd«       ||f	 |j-                  «        |r|	jA                  «        S S tW        ‰ «       tY        ‰ |«       t[        ||«      }t]        ‰ |«      }t_        ‰ ||||||||||
¬«      }|j`                  �2||j`                  f	 |j-                  «        |r|	jA                  «        S S |j4                  }|jb                  }te        ‰ |||jf                  ||jh                  |jj                  ||jl                  |||¬«      } tH        jK                  d‰ jL                  xs d|t        |«      | d›«       |dv rdnd|_7        tq        ‰ |
j                  |jn                  ||d v rd!nd|jr                  ¬"«       ||f	 |j-                  «        |r|	jA                  «        S S # t        $ r |j                  d¬«       ‚ w xY w# |r|	jA                  «        w w xY w# |r|	jA                  «        w w xY w# |r|	jA                  «        w w xY w# |r|	jA                  «        w w xY w# 	 |j-                  «        |r|	jA                  «        w w # |r|	jA                  «        w w xY wxY w)#u\  Compress conversation context and split the session in SQLite.
    ``force`` (manual /compress) clears the summary-failure cooldown; ``bypass_cooldown`` (provider-proven
    overflow) skips it once, breakers still apply. ``commit_fence`` stops a timed-out worker mutating session
    state. Returns ``(messages, system_prompt)``; on abort input is unchanged, NOT split.

    Args: agent: The owning :class:`AIAgent`. messages: Current message history (will be summarised).
    system_message: Current system prompt; used when compression needs a rebuilt cached prompt.
    approx_tokens: Pre-compression token estimate, logged for ops. task_id: Tool task scope (used for
    clearing file-read dedup state). focus_topic: Optional focus string for guided compression â€” the
    summariser will prioritise preserving information related to this topic. Inspired by Claude Code's
    ``/compact <focus>``. force: If True, bypass any active summary-failure cooldown. Set by the manual
    ``/compress`` slash command so users can retry immediately after an auto-compress abort. Auto-compress
    callers use the default ``False``. bypass_cooldown: If True, the automatic breaker gates ignore ONLY the
    summary-failure cooldown for this attempt (#100661). Set by the provider-proven overflow recovery path:
    the provider already rejected the request, so deferring until the cooldown lapses wedges the session.
    Unlike ``force`` it does not clear the cooldown, and the ineffective/structural breakers still apply; a
    failed attempt records its cooldown normally. defer_context_engine_notification: Delay the existing
    context-engine hook until a manual host commits its outer history transaction. commit_fence: Optional
    cooperative fence for executor callers that may time out. It prevents a late worker from mutating
    session state after its caller has moved on.
    )r¯  r4  r  FTr�  NÚcodex_app_serverzpcodex_app_server owns the authoritative thread and does not expose a truthful pre-compaction transcript boundary)rr  r;   r{  rÔ  r¯  Úcompression_in_place)r=  r{  r®  r¯  r]  rø  )rr  rd  r<  r{  r  r  r¬  )r  rÙ  rL  r{  r®  r¯  re  rr  r]  r<  r;   c              3  ó^   •K  — | ]$  }t        t        ‰j                  |d «      «      –— Œ& y­wrÕ   )rV   r2   rw  )rµ  r€   r4   s     €r   r·  z#compress_context.<locals>.<genexpr>¸  s/   øè ø€ ò a
àô ”˜×1Ñ1°4¸Ó?×@ña
ùs   ƒ*-)ra   rh   Ú_last_feasibility_skip)rÈ   r  zBCompression commit cancelled before session mutation (session=%s).r‚  r$  r0  )rÙ  r  r€  r<  rº  rø  r  r;   )
r€  r…  rÙ  rã  rä  rå  ræ  rç  rè  rÔ  z^context compression done: session=%s messages=%d->%d rough_tokens=~%s awaiting_real_usage=truer-  >   r  r  r  rð  rÝ  >   rÝ  r  Úsession_split_failed)rs  rà  rá  râ  r!  ):r5  r2   rü  r9  rh  r=  ry  rV   r@  r[  r   rû  r]  r7  rs  r(  r<  rÝ   rw  rº   rÆ   rÇ   r  r,  r  rz  r¨  rø  r{  r  rý  r“   r  r  r'  rA  r   rT   r¾   rj  r†  r?  rƒ  rÊ  rw  rÏ  r�  r  r   rá  rò  r…  rã  rä  r  rà  rç  r!  )!r4   rz  r<  r{  rÔ  r®  r¯  re  rå  rr  r;   rL  Ú_pre_msg_countrÙ  rd  r  Ú_abort_promptÚ_adoptedÚ_hard_cancel_eventr;  r¨  rø  Ú_commit_fence_enteredÚ_compression_made_progressÚ_compression_used_fallbackÚ_compression_feasibility_skipr*  r*  rº  r€  Úcommitrá  rð  s!   `                                r   Úcompress_contextrP  >  s  ø€ ô6 )¨°eÐPqÔr€Gô
 " %Ð)JÈEÓRÐVZÐZÐÜˆu�j $Ó'Ð+=Ò=ÙÜ%ð Cóð ô 'Ø�8˜^¸,ÐPWÐgtØ 5ô
ð 	
ñ Ô7¸¸ÔOØÔ0°¸ÓGÐGÐGä˜“]€Nô ”G˜EÐ#9¸4Ó@ÓA€Hô ,Ø˜^¸=ÐVaÐinô€Iô �5Ð<¸eÔDð	Ü/°Ô6ð 26ˆÔ.Ü5Ø˜L°IÈnØ#¸×8JÑ8JôÑ€Eˆ=ð €}Ø˜Ð&Ð&ð 
×ÑÔÜ'¨¨u°hÀÓO€HØÐØˆô
 	4°E×4LÑ4LÈg×N^ÑN^Ó_ñ K€GÔ*¨GÔ,Jð ×-Ñ-°Ñ6ð 	�‰ŒØÔ0°¸ÓGÐGÐGñ Ô7¸¸ÐafÕgØ�‰ŒØÔ0°¸ÓGÐGÐGô ! Ð(CÀTÓJÐÜØˆx˜u¨xÐM`Ø#°ÀEÐ[jØ!Ð5GÐXfÐpwô€Eð
 ×ÑÐ%Ø�~‰~˜u×1Ñ1Ð1Ð1Ø Ÿ>™>¨5×+;Ñ+;ˆj€HØ"'×"CÑ"CÐØ$)×$7Ñ$7¸×9LÑ9L�>€MØ!ÐðI-óa
àtôa
Ñ]Ð"Ð$>Ð@]ô Ø�:˜xÐ)DÐY`×YkÑYkØ&×1Ñ1õ
ð Ô4°U¸NÓKÐKðt	-Ø�M‰MŒOá$Ø×*Ñ*Õ,ð %ðy Ð#Ø$0×$=Ñ$=Ð>PÓ$QÐ!Ù(Ø×*Ñ*¨5×+CÑ+CÔDÜ*¨8Ð5PÔQÜ—‘ØXÐZ_×ZjÑZjÒZtÐntôð 38�Ô/Ü!BØ¨À×ASÑASÐ^fØ"/ô"�ô  7°u¸nÓM�Ü/Ø˜7×-Ñ-Ù7EÕ3ÐKcôð   Ð-ðN	-Ø�M‰MŒOá$Ø×*Ñ*Õ,ð %ôS 	& eÔ,Ü˜E :Ô.Ü'GÈÐR\Ó']Ð$Ü>¸uÀnÓUÐÜ#Ø�8˜Z°(À%Ð[lØ)ÐHdØ(CÐSmØô	
ˆð × Ñ Ð,Ø˜V×2Ñ2Ð2ð6	-Ø�M‰MŒOá$Ø×*Ñ*Õ,ð %ð; ×&Ñ&ˆ
Ø×*Ñ*ˆÜ5Ø�:Ð1BÐSY×ShÑShØ°&×2KÑ2KØ%+×%DÑ%DØ.OØ&,×&:Ñ&:ÐVpØ)FÐPWô
ˆô 	�‰ØlØ×ÑÒ& ¨¼¸J»ÈOÐ\]ÐK^ô	
ð
 (Ð+hÑh‰KÐnwð 	Ôô 	,Ø˜g×0Ñ0À	×@WÑ@WÐfrØ5AÐEfÑ5fÑ1ÐlpØ$×6Ñ6õ	
ð
 Ð,Ð,ð	-Ø�M‰MŒOá$Ø×*Ñ*Õ,ð %øô} ò 	Ø×Ñ¨dÐÔ3Øð	ûñ| %Ø×*Ñ*Õ,ð %ûÑ$Ø×*Ñ*Õ,ð %ûÑ$Ø×*Ñ*Õ,ð %ûÑ$Ø×*Ñ*Õ,ð %ûð	-Ø�M‰MŒOá$Ø×*Ñ*Õ,ð %øÑ$Ø×*Ñ*Õ,ð %ýsv   Â*S ÈAU ÉS!É7B/U Ì'S9ÍAU Î*TÏCU ÒT)ÓSÓ!S6Ó9TÔT&Ô)T>ÕU?ÕU'ÕU?Õ'U<Õ<U?c                ó2  — t        | dd«      }t        |dd«      }t        |«      sy	  |d¬«      }	 |r(t        dt        |j                  d	«      xs d«      «      S dS # t        $ r t        j	                  dd¬«       Y yw xY w# t        t        f$ r Y yw xY w)
zGSeconds left on this session's compaction-failure cooldown (0 = clear).rw  NrÙ   r°   TrÖ   z'codex compaction cooldown lookup failedr   Úremaining_seconds)
r2   r´   r   r   r   r·   r¶   r¡   rz   rõ   )r4   r~   r  rO  s       r   Ú$_codex_compaction_cooldown_remainingrS    s¥   € ä˜Ð 4°dÓ;€JÜ�ZÐ!JÈDÓQ€FÜ�FÔØðÙ˜tÔ$ˆðÙINŒs�3œ˜eŸi™iÐ(;Ó<ÒCÀÓDÓEÐWÐTWÐWøô	 ò Ü�‰Ð>ÈˆÔNÙðûô
 ”zÐ"ò Ùðús(   ¨	A ²)B ÁB Á BÂ BÂBÂBc                ó²   — ddl m} t        | dd«      }t        |dd«      }t        |«      syt	        dd¬«      5   |||«       ddd«       y# 1 sw Y   yxY w)	zÔArm the shared compression-failure cooldown after a failed codex compaction.
    The codex path returns the transcript unchanged, so without a cooldown the still-over-threshold session
    would retry every turn.r   )Ú!_SUMMARY_FAILURE_COOLDOWN_SECONDSrw  Nr  z(codex compaction cooldown persist failedTr   )r%   rU  r2   r´   r    )r4   r…  rU  r~   rÂ   s        r   Ú _record_codex_compaction_failurerV    s\   € õ KÜ˜Ð 4°dÓ;€JÜ�zÐ#IÈ4ÓP€HÜ�HÔØÜ	Ð<ÀtÔ	Lñ ;ÙÐ2°EÔ:÷;÷ ;ñ ;ús   º
AÁAr7  c          
     óp  — t        | dd«      xs d}|r|d›nd}t        t        | dd«      xs d«      j                  «       }|dvrd}d}	|s|d	k7  rd
|› d�}	n|st        | «      }
|
dkD  rd|
d›d�}	t        | dd«      }|	€|€d}	|	�0t        j                  d|	|t        |«      |«       |t        | |«      fS t        j                  d|t        |«      |«       t        j                  t        «      5  | j                  t        «       ddd«       t        | d¬«      j                  «       }	 |j                  «       }t%        t        |dd«      xs t        |dd«      «      }|j#                  |rdnd«       t        |dd«      r9t        j                  t        «      5  |j'                  «        ddd«       d| _        |rrt        j                  t        «      5  | j+                  d|j,                  › �«       ddd«       t/        | t        t        |dd«      xs d«      «       |t        | |«      fS t1        dd¬«      5  dd lm}m}  || ||d¬!«       t9        | j:                  d"«      r || ||¬#«       ddd«       t=        || j>                  xs d$d¬%«       t        j                  d&|t        |d'd«      xs d$t        |d(d«      xs d$«       t        | |«      }tA        | «       ||fS # 1 sw Y   �ŒâxY w# t         $ r |j#                  d«       ‚ w xY w# 1 sw Y   �ŒixY w# 1 sw Y   �Œ-xY w# 1 sw Y   Œ¼xY w))zÒRoute compaction to Codex app-server for Codex-owned threads.
    Rewriting the local transcript would not shrink the Codex thread, so Codex compacts its own thread and
    Hermes' transcript is left unchanged.r¾   Nr‚  r-  rp  Ú codex_app_server_auto_compactionÚnative>   ÚoffÚhermesrY  r[  zmode=z force=falser   zfailure cooldown active for z.0fÚsÚ_codex_sessionzno active codex threadzKcodex app-server compaction skipped: %s (session=%s messages=%d tokens=~%s)zFcodex app-server compaction started: session=%s messages=%d tokens=~%sT)r¾  r&  ÚinterruptedFr…  rð  Úshould_retireu(   âš  Codex app-server compaction failed: zcompaction interruptedz#codex compaction bookkeeping failedr   )Ú#_record_codex_app_server_compactionÚ_record_codex_app_server_usage)r{  r¯  Úupdate_from_responser“  rD   rË  z>codex app-server compaction done: session=%s thread=%s turn=%sÚ	thread_idÚturn_id)!r2   rG   rJ   rS  r   rT   ry  r=  r‹   r˜   r   ré  r>  r½  rÕ  Úcompact_threadré  rÝ  rV   Úcloser]  r'  r…  rV  r    Úagent.codex_runtimer`  ra  r(  rw  rÕ  r¾   r5   )r4   rz  r<  r{  rÔ  r¯  Ú_sidÚ_tokensÚ	auto_modeÚskip_reasonÚ_cooldown_remainingÚcodex_sessionr"  rA  Úfailedr`  ra  Úexisting_prompts                     r   r8  r8    sI  € ô �5˜,¨Ó-Ò7°€DÙ&3�˜qÑ!¸€GÜ”G˜EÐ#EÀxÓPÒ\ÐT\Ó]×cÑcÓe€IØÐ3Ñ3Øˆ	Ø€KÙ�Y (Ò*Ø˜i˜[¨Ð5‰Ùô CÀ5ÓIÐØ Ò"Ø8Ð9LÈSÐ8QÐQRÐSˆKÜ˜EÐ#3°TÓ:€MØÐ˜}Ð4Ø.ˆØÐÜ�‰ØYÐ[fÐhlÜ�‹M˜7ô	
ð Ô0°¸ÓGÐGÐGÜ
‡K�KÐXÐZ^Ô`cÐdlÓ`mÐovÔwÜ	×	Ñ	œYÓ	'ñ .Ø×ÑÔ,Ô-÷.ä7¸ÐRVÔW×]Ñ]Ó_ÐðØ×-Ñ-Ó/ˆô ”'˜& -°Ó7ÒY¼7À6È7ÐTXÓ;YÓZ€FØ×Ñ¹VÑ9ÐIhÔiÜˆv�¨Ô.Ü× Ñ ¤Ó+ñ 	"Ø×ÑÔ!÷	"à#ˆÔÙÜ× Ñ ¤Ó+ñ 	[Ø×ÑÐ"JÈ6Ï<É<È.Ð YÔZ÷	[ô 	)¨´´G¸FÀGÈTÓ4RÒ4nÐVnÓ0oÔpØÔ0°¸ÓGÐGÐGÜ	Ð7À$Ô	Gñ MßkÙ+¨E°6ÈÐ^bÕcô �5×+Ñ+Ð-CÔDÙ*¨5°&À8ÕL÷Mô ˜W°×1AÑ1AÒ1GÀRÐPUÕVÜ
‡K�KØHÈ$Ü�˜ TÓ*Ò0¨b´'¸&À)ÈTÓ2RÒ2XÐVXôô .¨e°^ÓD€Oô ˜%Ô Ø�_Ð$Ð$÷K.ñ .ûô
 ò Ø× Ñ Ð!=Ô>Øðú÷	"ñ 	"ú÷	[ñ 	[ú÷Mð Mús<   Ã0K&Ä*K3 ÆLÇLÈ;6L,Ë&K0Ë3LÌLÌL)Ì,L5i  @ z.pngz.gifz.webpú.jpgz.bmp)z	image/pngz	image/gifz
image/webpú
image/jpegz	image/jpgz	image/bmpc                ó¬   — | j                  d«      rB| t        d«      d j                  dd«      d   j                  «       }|j                  d«      r|S |S )z?``image/*`` mime from a ``data:`` URL header, else ``default``.údata:Nú;r9   r   úimage/)rq  ry  ÚsplitrH   )Úheaderr„   r  s      r   Ú_data_url_mimerx  o  sT   € à×Ñ˜Ô!Øœ3˜w›<˜>Ð*×0Ñ0°°aÓ8¸Ñ;×AÑAÓCˆ	Ø×Ñ Ô)ØÐØ€NrO   c                ó2  — 	 ddl }ddl}| j                  d«      \  }}}|r| j                  d«      syddlm} |j                  |j                  |j                  |«      «      «      5 }|j                  cddd«       S # 1 sw Y   yxY w# t        $ r Y yw xY w)z```(width, height)`` of a base64 data URL; None when Pillow is missing or the payload is corrupt.r   Nr-  rs  )ÚImage)Úbase64ÚioÚ	partitionrq  ÚPILrz  ÚopenÚBytesIOÚ	b64decodeÚsizer   )Údata_urlr{  r|  rR  Údata_drz  Ú_imgs          r   Ú_decode_pixelsr†  x  s…   € ð	ßØ×)Ñ)¨#Ó.‰ˆˆ1ˆfÙ˜X×0Ñ0°Ô9ØÝØ�Z‰Z˜Ÿ
™
 6×#3Ñ#3°FÓ#;Ó<Ó=ð 	ÀØ—9‘9÷	÷ 	ò 	ûäò Ùðús4   ‚0B
 ³5B
 Á(A>Á4	B
 Á>BÂB
 ÂB
 Â
	BÂBc               ó˜  — t         }t        | t        «      r| j                  d«      syt	        | «      |kD  rdnd}|€t        | «      }|�t        |«      |k  ryd}	 | j                  d«      \  }}}t        |«      }	ddl	}
|
j                  |«      }t        j                  dt        j                  |	d	«      d
¬«      }	 |j                  |«       |j!                  «         |t#        |j$                  «      |	||¬«      }t'        j(                  t*        «      5  t#        |j$                  «      j-                  d¬«       ddd«       |syt        |«      }|dk(  r.t	        |«      t	        | «      k  xr |du xs t        |«      |k  }n(|�t        |«      |k  }nt	        |«      t	        | «      k  }|r|d
fS dS # 1 sw Y   ŒzxY w# t'        j(                  t*        «      5  t#        |j$                  «      j-                  d¬«       ddd«       w # 1 sw Y   w xY wxY w# t*        $ r&}t.        j1                  d|«       d|dufcY d}~S d}~ww xY w)a´  Return ``(resized_url, unshrinkable)`` for a data URL.
    ``resized_url`` is None when no rewrite applied. ``unshrinkable`` is True only when the image violated a
    constraint and resizing failed to satisfy that same constraint, so the caller knows a retry is pointless.
    The accept gate MUST use the axis that triggered the shrink: a pixel downscale can re-encode to MORE bytes
    (PNG non-monotonic); a byte-only reject wedges.rs  rá   ÚbytesNÚ	dimensionr-  r   Úhermes_shrink_rp  F)ÚprefixÚsuffixÚdelete)Ú	mime_typeÚmax_base64_bytesÚmax_dimensionT)Ú
missing_okrß  u.   image-shrink recovery: re-encode failed â€” %s)Ú_IMAGE_SHRINK_TARGET_BYTESr&   rG   rq  ry  r†  r·   r}  rx  r{  r�  ÚtempfileÚNamedTemporaryFileÚ_IMAGE_SUFFIX_BY_MIMEr¡   Úwriterf  r   r€   r‹   r˜   r   Úunlinkr   rÊ   )Úurlr�  Ú	resize_fnÚtarget_bytesÚtriggered_byÚdimsrw  rR  ÚdataÚmimeÚ_b64rl  ÚtmpÚresizedÚnew_dimsÚokr   s                    r   Ú_shrink_data_urlr¤  †  s  € ô .€LÜ�cœ3Ô s§~¡~°gÔ'>ØÜ! #›h¨Ò5‘7¸4€LØÐä˜cÓ"ˆØˆ<œ3˜t›9¨Ò5ØØ"ˆð".ØŸ-™-¨Ó,‰ˆ��4Ü˜fÓ%ˆÛØ�n‰n˜TÓ"ˆÜ×)Ñ)Ø#Ô,A×,EÑ,EÀdÈFÓ,SÐ\aô
ˆð	7Ø�I‰I�cŒNØ�I‰IŒKÙÜ�S—X‘X“¨$ÀÐ]jôˆGô ×$Ñ$¤YÓ/ñ 7Ü�S—X‘X“×%Ñ%°Ð%Ô6÷7áØÜ! 'Ó*ˆØ˜7Ò"ô �W“¤ C£Ñ(Òa¨h¸$Ð.>Ò.`Ä#ÀhÃ-ÐS`ÑB`‰BØÐ!ä�X“ -Ñ/‰Bô �W“¤ C£Ñ(ˆBÙ#%�˜ÐÐ7¨<Ð7÷!7ð 7û”×$Ñ$¤YÓ/ñ 7Ü�S—X‘X“×%Ñ%°Ð%Ô6÷7÷ 7ñ 7þô" ò .Ü�‰ÐGÈÔMØ�\¨Ð-Ð-Õ-ûð.úsu   ÁA!H Â>A G Ã>H Ä&F6Ä=
H ÅA+H Æ4H Æ6F?Æ;H ÇHÇ&HÈ	HÈHÈHÈH È	I	È#IÈ>I	ÉI	c                ó"  — t        | t        «      r| j                  d«      dk7  ry| j                  d«      }t        |t        «      r|syt        | j                  d«      xs d«      j	                  «       }d|j                  d«      r|nd› d	|› �S )
uK   Anthropic ``{"type": "base64", ...}`` image source â†’ data URL, else None.r³   r{  Nr�  Ú
media_typerq  rs  ru  z;base64,)r&   r(   r¡   rG   rH   rq  )rÛ  r�  r¦  s      r   Ú_source_to_data_urlr§  »  sƒ   € ä�fœdÔ# v§z¡z°&Ó'9¸XÒ'EØØ�:‰:�fÓ€DÜ�dœCÔ ©ØÜ�V—Z‘Z Ó-Ò=°Ó>×DÑDÓF€JØ ×!6Ñ!6°xÔ!@‘:ÀlÐSÐS[Ð\`Ð[aÐbÐbrO   c                óR   — |j                  d«      \  }}}i | ¥dt        |«      |dœ¥S )zÔReturn a NEW source dict carrying the re-encoded payload.
    Copy-on-write: parts may be shared with the persistent history, so mutating in place would store the
    degraded image; the caller replaces the part.r-  r{  )r³   r¦  r�  )r}  rx  )rÛ  rƒ  rw  rR  r�  s        r   Ú_write_data_url_to_sourcer©  Æ  s4   € ð ×(Ñ(¨Ó-�O€FˆAˆtØ[ˆfÐ[˜h´nÀVÓ6LÐVZÒ[Ð[rO   i@  )r�  c               óê  ‡‡— | sy	 ddl mŠ d}d}dˆˆfd„}| D �]j  }t        |t        «      sŒ|j                  d«      }t        |t        «      sŒ7d}t        |«      D �]  \  }	}
t        |
t        «      sŒ|
j                  d	«      }d}|d
k(  rN|
j                  d«      } |t        |«      xs d«      \  }}|rœt        |t        «      rŒi |
¥dt        ||«      i¥}ny|dv rt|
j                  d«      }t        |t        «      r, ||j                  dd«      «      \  }}|r7i |
¥di |¥d|i¥i¥}n(t        |t        «      r ||«      \  }}|ri |
¥d|i¥}nŒöŒ÷|�|€t        |«      }|||	<   |dz  }�Œ|s�Œ|dz  }�Œ |€�Œf||d<   �Œm t        dz  }|rt        j                  d||«       |rt        j	                  d||«       y|dkD  S # t        $ r }t        j	                  d|«       Y d}~yd}~ww xY w)a�  Re-encode oversized native image parts to recover from image-too-large errors.
    Mutates ``api_messages`` in place. Returns True if any part was replaced, False if nothing to shrink or
    Pillow could not help. Targets data-URL parts over 4 MB or ``max_dimension`` (Anthropic's per-side pixel
    cap, parsed from the rejection by the caller); http(s) image URLs are left untouched.Fr   )Ú_resize_image_for_visionu6   image-shrink recovery: vision_tools unavailable â€” %sNr˜  c                ó    •— t        | ‰‰¬«      S )N)r�  r™  )r¤  )r˜  r«  r�  s    €€r   Ú_shrinkz3try_shrink_image_parts_in_messages.<locals>._shrinkß  s   ø€ Ü °=ÐLdÔeÐerO   rø  r³   ÚimagerÛ  rD   >   Ú	image_urlÚinput_imager¯  r9   i   zGimage-shrink recovery: re-encoded %d image part(s) to fit under %.0f MBu…   image-shrink recovery: %d oversized image part(s) could not be shrunk under %.0f MB â€” not retrying (would re-send rejected payload))r˜  r   r1  Útuple)Útools.vision_toolsr«  r   r   rÊ   r&   r(   r¡   r'   r“  r§  r©  rG   r’  rT   )Úapi_messagesr�  r   Úchanged_countÚunshrinkable_oversizedr­  r  rø  Únew_contentÚpart_idxrq  ÚptypeÚreplacementrÛ  r¡  ÚunshrinkableÚimage_valueÚ	target_mbr«  s    `                @r   Ú"try_shrink_image_parts_in_messagesr½  Î  sI  ù€ ñ
 ØðÝ?ð €Mð Ðöfð ó +)ˆÜ˜#œtÔ$ØØ—'‘'˜)Ó$ˆÜ˜'¤4Ô(Øð $(ˆÜ'¨Ó0ó  	,‰NˆH�dÜ˜d¤DÔ)ØØ—H‘H˜VÓ$ˆEØˆKØ˜ÒØŸ™ (Ó+�Ù(/Ô0CÀFÓ0KÒ0QÈrÓ(RÑ%�˜Ùœz¨&´$Ô7Ø"` TÐ"`¨8Ô5NÈvÐW^Ó5_Ñ"`‘KØÐ6Ñ6Ø"Ÿh™h {Ó3�ô ˜k¬4Ô0Ù,3°K·O±OÀEÈ2Ó4NÓ,OÑ)�G˜\ÙØ&\¨Ð&\¨{Ð<[¸{Ð<[ÈEÐSZÑ<[Ñ&\™Ü ¬SÔ1Ù,3°KÓ,@Ñ)�G˜\ÙØ&D¨Ð&D¨{¸GÑ&D™ààØÐ&ØÐ&Ü"& w£-�KØ(3�˜HÑ%Ø Ñ"’ÛØ&¨!Ñ+Ò&ðA 	,ðB Ò"Ø(ˆC�	‹NðW+)ôX +¨kÑ:€IÙÜ�‰Ð]Ð_lÐnwÔxÙô 	�‰ðUØVlØô	
ð
 Ø˜1ÑÐøôG ò Ü�‰ÐOÐQTÔUÜûðús   ‡G	 Ç		G2ÇG-Ç-G2)r>  r3   rê  rI   rN   r[  ra  r^  rf  rP  r½  c                  ó   — e Zd ZdZy)Ú!CompressionExecutorSaturatedErrorz@All compression pool slots are occupied; submission was refused.Nrð  r<  rO   r   r¿  r¿  +  s   „ ÚJrO   r¿  )r   rG   r   rV   )r*   r   r1  r   )r4   r   r1  r2  )rK   ú
str | Noner1  rV   r4  )r~   r   r1  údict[str, Any])r~   r   r1  r   )r~   r   r1  r‘   )r~   r   r“   r‘   r1  rV   )r~   r   r“   r‘   r1  r2  r0  )r~   r   r1  rV   )r~   r   r“   r   r1  rV   )r~   r   r§   r   r“   r‘   r1  r2  )
r~   r   rº   rÁ  r»   r5  r¼   r.  r1  r2  )r~   r   rº   rÁ  rÆ   r5  rÇ   r.  rÈ   r  r1  r2  )r~   r   rÛ   rÁ  r1  z/tuple[Optional[bool], Optional[dict[str, Any]]])rG  r   rH  r¶   r1  rV   rý   r3  )rh  úOptional[dict]r1  zTuple[float, float])rr  rï  rs  r¶   rp  zOptional[float]r1  rV   )r4   r   rz  r   r{  r  r1  rG   )r4   r   rr  rï  rs  r¶   rz  r   r{  r  r1  rV   )r1  rÂ  )r›  rV   r1  r'   )r4   r   r1  r‘   )r4   r   r¤  r   r1  r5  )r­  ú4Callable[[CompressionCommitFence], Tuple[list, str]]rz  r'   r®  r   rp  r¶   rò   r¶   r§  ú(Optional[Callable[[float, float], None]]r¨  ú&Optional[Callable[[bool, bool], None]]r©  r   rª  ú.Optional[Callable[[], CompressionCommitFence]]r›  rV   r1  úOptional[Tuple[list, str]])rœ  r(   r­  rÃ  rz  r'   r®  r   rp  r¶   rò   r¶   r§  rÄ  r¨  rÅ  r©  r   rª  rÆ  r1  rÇ  )rG  r   r¶  rß   ri  r¶   rj  r¶   rÀ  r¶   r1  zTuple[bool, Any])
rG  r   rj  r¶   rÀ  r¶   r§  rÄ  r1  r   )r¶  rß   r1  rV   )
rG  r   r¶  rß   rÔ  rV   rj  r¶   r1  r2  )r­  rÃ  rz  r'   r®  r   rp  r¶   rò   r¶   rÖ  z/Optional[Callable[[float, float, float], None]]r¨  rÅ  r§  rÄ  r¶  rï  r©  r   r·  rV   rª  rÆ  r×  z>Optional[Callable[[CompressionCommitFence], Tuple[list, str]]]rØ  rV   r1  úTuple[list, str])r4   r   r1  rG   )rû  rG   r1  rï  )r  r   r1  rV   )r~   r   r  rV   r1  r2  )r½   r   r¾   rG   r1  rV   )r4   r   rs  r¶   rà  rG   rá  rG   râ  rÀ  r!  r0  r1  r2  )r4   r   r<  rG   r1  rG   )r4   r   rs  r¶   râ  rÀ  r1  r2  )rz  r'   rº   r  r1  r2  )r~   r   rº   r(   r1  r2  )r4   r   r1  rV   )r4   r   rM  rV   r1  z/Optional[Tuple[Any, Optional[threading.local]]])r4   r   rT  rV   r1  r2  )r4   r   re  rV   r  rV   r1  rV   )r4   r   r~   r   r1  r2  )r¾   rG   r1  r2  )r4   r   r½   r   r‰  rG   r1  úOptional[List[Dict[str, Any]]])r½   r   r¾   rG   r1  r2  )r4   r   r1  rÉ  )r¹  r   r­  r  r®  r¾  r¯  rV   r°  rG   re  rV   r1  r(   )rz  r   r1  zlist[dict[str, Any]])r4   r   r  rG   r1  r2  )r4   r   r)  rG   r*  r‘   r+  rG   r,  rG   r1  r2  )r4   r   r)  rG   r,  rG   r1  rV   )r4   r   r`  r‘   r1  r2  )r4   r   rz  r'   rk  r  r1  r  )r   r   r1  rG   )r   r   r1  rV   )r1  zTuple[str, str])r   r   r1  r¾  )rz  r'   r1  rV   )rø  r   r1  r   )rø  r   r›  r   r1  rV   )r   r(   rø  r   r1  r2  )r¨  r'   r1  rG   )rÄ  r(   r°  r(   r1  r2  )rz  r'   r°  r(   r1  r¿  )rÍ  r'   r¨  r'   r1  r¿  )rÒ  r   rÓ  r   r1  rV   )rÚ  r'   rÛ  r(   rØ  rV   r1  r2  )r4   r   r   rG   r…  rG   r1  rV   )r4   r   r   rG   r…  rG   r1  r2  )r4   r   rð  rV   r1  rV   )r  r   r1  zTuple[Any, Optional[Exception]])r4   r   rd  rô  r<  rG   r  r¶   râ  rG   r  r¾  r1  úTuple[None, str])r  rý  r  r   rr  r   r1  rV   )r4   r   r  rý  rd  rô  r<  rG   r{  r  r  r¶   r1  rÊ  )r4   r   rr  rï  rd  rô  r<  rG   r{  r  r  r¶   r1  z1Tuple[Optional[_CompressionLease], Optional[str]])
r4   r   r  rý  rz  r'   r<  rG   r1  rÇ  )r4   r   r  rý  rz  r'   r1  r  )r4   r   rz  r'   rL  rV   r1  rG   )r4   r   r{  r  r®  r¾  r¯  rV   r°  rG   re  rV   r1  z)Tuple[Callable[..., Any], dict[str, Any]])r4   r   rz  r'   r¹  zCallable[..., Any]rR  rÁ  rr  rï  rÈ   r   r]  r   r1  r'   )r4   r   r¨  r'   r1  r2  )r4   r   rz  r'   r¨  r'   r<  rG   r  r¶   rÛ   r(   r1  z$Tuple[Optional[list], Optional[str]])r4   r   r…  rG   r�  r   r1  r2  )r4   r   r‰  rG   r1  rG   )r4   r   rz  r'   r¨  r'   r€  rG   r  rý  r…  rG   rº  rG   r1  r2  )rÔ  rG   r¾   rG   rÌ  rV   r1  r2  )r4   r   r¨  r'   r€  rG   r…  r¾  rÙ  rV   rã  rV   rä  rV   rå  rV   ræ  rV   rç  rV   rè  rV   rÔ  rG   r1  r‘   )r4   r   r¨  r   rz  r'   rø  r'   rÈ   r   r  r¶   r1  rV   )r4   r   rz  r'   r¨  r'   rÙ  rV   r  rý  r€  rG   r<  rG   rº  rG   rø  r  r  rV   r;   r  r1  rÿ  )r4   r   rz  r'   r  rý  rÙ  rV   rL  rV   r{  r  r®  r¾  r¯  rV   re  rV   rr  rï  r]  r   r<  rG   r;   r  r1  r  )r4   r   r¯  rV   r4  rV   r1  r  )r4   r   rz  r'   r<  rG   rr  rï  r;   r  r{  r  rÔ  rG   r¯  rV   r1  rÈ  )r4   r   r=  r‘   r{  r  r®  r¾  r¯  rV   r1  rô  )r4   r   rz  r'   r<  rG   r{  r  rÔ  rG   r®  r¾  r¯  rV   re  rV   rå  rV   rr  rï  r1  rÈ  )r4   r   r1  r¶   )r4   r   r…  rG   r1  r2  )r4   r   rz  r'   r<  r¾  r{  r  rÔ  rG   r¯  rV   r1  rÈ  )rq  )rw  rG   r„   rG   r1  rG   )rƒ  rG   r1  zOptional[tuple])r˜  rG   r�  r‘   r™  r   r1  r±  )rÛ  r   r1  r¾  )rÛ  r(   rƒ  rG   r1  r(   )r³  r'   r�  r‘   r1  rV   )ír:  Ú
__future__r   Úconcurrent.futuresrB  r‹   Úcontextvarsr|   Údataclassesr
  r5  ÚloggingrÉ  rx  r“  r¸   r1  r‰   r   Úpathlibr   Útypingr   r   r   r	   r
   r   r   rf  r   Úagent.context_enginer   r   Úagent.memory_providerr   rL  r   r   Úagent.session_activityr   r   Úagent.usage_anchorr   Úhermes_state_idsr   rµ  Ú	getLoggerr7  r   Úcontextmanagerr    Ú	frozensetÚAGENT_COMPRESSION_TIMEOUTÚAGENT_COMPRESSION_COOLDOWNrä  r  rI   r>  rê  r3   r.   r5   Ú#PRE_API_COMPRESSION_STATUS_TEMPLATEÚ%PREFLIGHT_COMPRESSION_STATUS_TEMPLATEÚIDLE_COMPACTION_STATUS_TEMPLATEÚ+COMPRESSION_RETRY_TOO_LARGE_STATUS_TEMPLATEÚ*COMPRESSION_RETRY_MESSAGES_STATUS_TEMPLATEÚ(COMPRESSION_RETRY_TOKENS_STATUS_TEMPLATEÚ1COMPRESSION_RETRY_CONTEXT_REDUCED_STATUS_TEMPLATEÚ)CONTEXT_OVERFLOW_BLOCKED_WARNING_TEMPLATEÚformatÚ"ROUTINE_COMPRESSION_STATUS_SAMPLESrN   rX   r{   rÚ   r‚   rŠ   rˆ   Ú
ContextVarr…   r  rŽ   r”   r–   rš   rž   rœ   r    r¨   r«   rÄ   rÏ   rÝ   rß   rc  rd  rƒ  rX  rZ  rÉ  rÓ  rJ  rO  rM  rN  rP  rS  r\  ro  ru  r}  r†  r—  rž  r¡  r¦  r²  r¯  rÅ  rÍ  rÑ  rÕ  r¸  rµ   rï  rþ  rø  rü  rÿ  r  r  r  r   rç  r=  r?  rA  rC  rH  rP  rU  rY  r[  r^  rh  rk  rd  r{  r™  r�  r¥  r«  r»  r½  rû  rý  r  r9  r>  r[  r^  ra  rf  rm  r|  rr  r{  r~  r„  r…  r†  rŠ  r�  r”  rœ  rž  r¢  r§  rª  r´  r¿  rÁ  rÏ  rÖ  rÞ  rí  rç  rî  rò  rô  rý  r  r  r"  r+  r7  r<  rF  rO  rT  rc  rw  r�  rŒ  r’  r   r¥  rÁ  rÊ  rÕ  rò  rý  Ú	dataclassrÿ  r  r  r,  r  r5  r9  r@  rP  rS  rV  r8  r’  r•  rx  r†  r¤  r§  r©  r½  Ú__all__r¿  r<  rO   r   ú<module>ré     s´  ðòõ #ã Û Û Û Û Û Û Û Û Û 	Û Û Û Û Ý Ý ß F× FÑ Få @ß ]Ý Eß ^ß TÝ /Ý >à	ˆ×	Ñ	˜8Ó	$€ð ×ÑØ/4ô Yó ðYñ %.Ø×1Ñ1Ð3E×3`Ñ3`Ðaó%Ð !ð #%Ð ð 0Ð ØÐ7Ð8Ð8rÐsÐ ð !)Ð)AÐ(Bð  CCð  DÐ àQÐ ósó=ð yð $ð ið &ð cð  ð Zð ,ð .mÐ *Ø+nÐ (àRð 2ð1ð *ð Ð2Ð4JØ'×.Ñ.°fÐ.Ó=Ø)×0Ñ0¸È&Ð0ÓQØ#×*Ñ*¸ÀVÐ*ÓLØ/×6Ñ6¸fÈaÐUVÐ6ÓWØ.×5Ñ5¸RÀrÐ5ÓJØ,×3Ñ3¸6ÈÐ3ÓPØ5×<Ñ<ÀVÐU[Ð<Ó\ð	&Ð "ó\ó&ð$Ð  ð %{Ð !ó#ð< *˜9Ÿ>™>Ó+Ð ð ?U¸k×>TÑ>TØ*°Dô?Ð Ð ;ó ó
ó"
óaóLó.óYó
.óGó
ð0Øð0Ø-ð0Ø>Lð0Ø]uð0à	ó0ð< dhØ7;Ðaeñ--Øð--Ø-ð--ØR`ð--à4ð--àQ^ð--ð 
ó--ð`#.Øð#.Ø'5ð#.à4ó#.÷LTñ Tðp #(Ð Ø(-Ð %ð #6Ð ð "Ð Ø"0 )§.¡.Ó"2Ð ð &*Ð "ð ,/Ð (óðF "#Ð Ø)˜9Ÿ>™>Ó+Ð ØÐ óô*ò*õ "ðL swñØ5ðØCHðØ`oðà	ôô>>ðØðØ!AðØOTðØ`cðà ðð 
ôô8&ôRôRô	#ð CGØ?CÐ\`Ø@DÐejñ%ØCð%ØOSð%àð%à7<ð%àUZð%ð @ð%ð =ð	%ð WZð	%ð
 >ð%ð
 _cð%ð  ô%ðPG&ØðG&ØPðG&Ø\`ðG&àðG&à7<ðG&àUZðG&ð @ðG&ð TzðG&ð ð	G&ð &Tð	G&ð
  ôG&ðTØðØ.ðØ9>ðØINðØ^cðàôðD$Øð$Ø"ð$Ø27ð$ØLtð$àô$ôNð/Øð/Ø.ð/ØDHð/ØSXð/à	ô/ð2 CGØ?CØBFØ.2È4ÐhlØ@DØVZØ#(ña,ØCða,ØOSða,àða,à7<ða,àUZða,ð @ða,ð =ð	a,ð
 @ða,ð ,ða,ð FIða,ð bfða,ð >ða,ð Tða,ð !ða,ð ôa,ôHR |ô Rð1ð !ô?ô&ô[óôDð X\ö Xôpð jnØ&*ñ
Øð
Ø$ð
Ø58ð
ØHKð
Ø\fð
à#ð
ð 
ô
ôDgô
ô.ô]ô1ðKØðKØðKà4ôKô"
6ó;ó
:ô

Gð gkö ô(0ô":ô*	(ð;Øð;Øð;Ø47ð;à#ô;ô|	aôô>mð 27ñUØðUØ)6ðUØERðUØ[_ðUàðUà*.ðUð 
ôU÷.g)ñ g)ôT÷.4ñ 4ôn'ðKØðKØ!ðKØ03ðKØCFðKØVYðKà	ôKô\PóYRóx2ô 2ó&	Dð DHðØðØðØ2@ðàôð&Ð ôðÐ ôNð 3Ð Ø5Ð ô;ô8ô+ô0ôô.	ô$ð &rÐ "ôô4ð& $Ð$cÑdÐ ôôB"ôDð  V[ö 0ð@ (ZÐ $ôô4
Bô÷/ñ /÷,Q-ñ Q-ôhð& 15ð	Øð	Ø/ð	ØADð	ØZ_ð	àð	à -ð	ð ô	ôðDnØðnØ(ðnØ5IðnØ[^ðnà ðnà6;ðnð ônð>GØðGØ!AðGØNbðGàðGà(5ðGàKPðGð 7ôGðT"Øð"Ø(ð"Ø48ð"ØJMð"àô"ôB,ô^%ðP(Øð(Ø"/ð(Ø>Kð(ØTXð(Øjmð(àð(ð /ô(ð*8Øð8Øð8Ø-?ð8ØR`ð8à2ð8àHKð8à`cð8ð 
ô8ôvGlôT,ð^:Øð:Øð:Ø,0ð:ØEHð:Ø^cð:àð:ð *ô:ôzôOôD	GðCDØðCDØðCDØ,0ðCDØHKðCDØTeðCDàðCDà7:ðCDð 
ôCDóLð4 ACÐSWö (ð([Øð[Ø ð[Ø8;ð[ØMZð[Øfjð[àð[à8<ð[àaeð[ð  $ð[ð AEð[ð eið[ð ð	[ð
 	ô[ð|MØðMØðMØ+/ðMØNRðMàðMà16ðMð 
ôMð` ×Ò÷
 ð 
 ó ð
 ðHØðHØðHØ,0ðHØ?CðHØL]ðHàðHà,/ðHàORðHð "0ðHð AEðHð PXðHð ô	HðV ×Ò÷'ð 'ó ð'ðOØðOØðOØ*;ðOØGKðOØbfðOà ðOà/<ðOàEIðOà\`ðOð 3ðOð HKðOð ]`ðOð ð	Oð
 ôOðd ×Ò÷
ð 
ó ð
ô"6ðB)Øð)Øð)Ø03ð)ØFfð)àð)à&3ð)à>Að)àJNð)ð ô)ð"5Øð5Ø"%ð5Ø6Cð5ØR_ð5Øhlð5àô5ð( X\Ø¸4ÈuØ!ÈUØ59ñ	@-Øð@-Øð@-Ø03ð@-ØGTð@-àð@-à+8ð@-àHLð@-ð ð@-ð GKð@-ð 3ð	@-ð
 ô@-ôFô"
;ð bfØ¨EñD%ØðD%ØðD%Ø0=ðD%ØQ^ðD%àðD%à%)ðD%ð ôD%ðR -Ð à f¸GÐSYÐhnØñÐ öôô2.ôjcô\ð TXö Lò^€ôK¨õ KrO   