
    sjH                      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mZ ddl	m
Z
mZmZmZmZ ddlmZmZmZmZmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZ ddl m!Z!m"Z"  ej#        e$          Z%dNdZ&dOdZ'dPdZ(dQdZ)dRdZ*dSd!Z+ e,d"d#h          Z-dTd&Z.dUd)Z/dVd.Z0e0Z1dWd0Z2dXd4Z3dYd<Z4e G d= d>                      Z5	 dZddd?d@d[dMZ6dS )\u?  Per-turn setup for ``run_conversation`` (the turn prologue).

``run_conversation`` opened with ~470 lines of straight-line setup before the
tool-calling loop ever started: stdio guarding, runtime-main wiring, retry-counter
resets, user-message sanitization, todo/nudge-counter hydration, system-prompt
restore-or-build, session-row creation (before compression, whose DB writes
reference the row), preflight context compression, the ``pre_llm_call`` plugin
hook, external-memory prefetch, and crash-resilience persistence (last, so the
user row is written once with its final ``api_content`` sidecar).

All of that is *prologue* — it runs once per turn, has no back-references into the
loop, and produces a fixed set of values the loop then consumes. ``TurnContext``
captures those produced values; ``build_turn_context`` performs the setup work and
returns one. ``run_conversation`` is left to unpack the context and run the loop,
shrinking the orchestrator by the full prologue.

The builder still mutates ``agent`` heavily (counters, thread id, cached prompt,
session DB) exactly as the inline code did — those side effects are the point. The
``TurnContext`` it returns carries only the *locals* the loop reads back.

Behavior is identical to the original inline prologue; this is a pure
move-and-name refactor with no semantic change.
    )annotationsN)	dataclass)AnyDictListMappingOptional)IDLE_COMPACTION_STATUS_TEMPLATE%PREFLIGHT_COMPRESSION_STATUS_TEMPLATEcompression_skipped_due_to_lock&conversation_history_after_compression#recover_rotated_compression_session)#automatic_compaction_status_message)IterationBudget)build_memory_context_block)is_trivial_prompt)append_messagestamp_message_timestamp)estimate_messages_tokens_roughestimate_request_tokens_roughcontentr   ext_prefetch_cachestrplugin_user_contextreturnOptional[str]c                    t          | t                    sdS g }|r&t          |          }|r|                    |           |r|                    |           |sdS | dz   d                    |          z   S )ue  Compose the API-bound content of the current turn's user message.

    Sources: memory-manager prefetch + ``pre_llm_call`` plugin context with
    target="user_message" (the default). Both are appended to the *API copy*
    of the user message only — the stored content stays clean.

    This is the single source of that composition. The prologue stamps the
    result onto the live message as ``api_content`` (persisted alongside the
    clean content) and the ``api_messages`` build in ``conversation_loop``
    sends the same helper's output, so the persisted sidecar can never drift
    from the bytes on the wire — which is the whole prompt-cache invariant:
    what turn N sends must be what turn N+1 replays.

    Returns ``None`` when nothing is injected (multimodal/non-string content,
    or no ephemeral context), meaning the message is sent as-is.
    N

)
isinstancer   r   appendjoin)r   r   r   
injectionsfenceds        6/home/agent/.hermes/hermes-agent/agent/turn_context.pycompose_user_api_contentr%   6   s    * gs## tJ &+,>?? 	&f%%% /-... tVfkk*5555    api_msgDict[str, Any]c                    |                      dd          }t          |t                    r|r|                     d          dv r|| d<   |S )a}  Pop the ``api_content`` sidecar and substitute it into ``content``.

    Used at every API-bound message-build site (the ``api_messages`` build in
    ``conversation_loop``, the max-iterations summary in
    ``chat_completion_helpers``, the chat-completions transport). The sidecar
    carries the exact bytes previously sent to the API for this message when
    they differ from the clean stored content; substituting it here keeps the
    provider prompt-cache prefix byte-stable across turns.

    Returns the popped sidecar string (for callers that need the value for
    current-turn composition logic) or ``None`` when absent.
    api_contentNrole)user	assistantr   )popr   r   get)r'   sidecars     r$   substitute_api_contentr1   Y   sZ     kk-..G7C  %% KK#888$	Nr&   msgNonec                2    |                      dd           dS )u  Drop the ``api_content`` sidecar from a message whose content was rewritten.

    Called from every content-rewrite path (historical image strip,
    merge-summary-into-tail, consecutive-user repair merge, stale-confirmation
    redaction). Replaying the pre-rewrite sidecar would resend exactly what
    the rewrite removed, so it must be dropped — the cost is one cache
    boundary miss, never wrong content.
    r*   N)r.   )r2   s    r$   drop_stale_api_contentr5   p   s     GGM4     r&   Mapping[str, Any]c                ^    |                      d          }t          |t                    r|ndS )zExtract the ``api_content`` sidecar from a message dict for persistence.

    Shared by the gateway/branch forwarding sites that copy the sidecar into a
    new row. Returns the string sidecar or ``None`` when absent/non-string.
    r*   N)r/   r   r   )r2   vs     r$   extract_api_content_sidecarr9   |   s.     	A1c"",11,r&   agentc                    t          | dd          pd}t          | d          r	 d| _        n# t          $ r Y nw xY wt	          |t
                    r|ndS )aM  Pop the gateway's per-turn must-deliver notes off the agent (one-shot).

    The gateway relocates volatile per-turn facts OUT of the ephemeral system
    prompt (auto-reset notes, the first-contact intro, voice-channel changes)
    and delivers them on the current user message via the api_content sidecar
    instead, so the composed system prompt stays byte-stable turn-over-turn.
    It stages the rendered notes on ``agent._gateway_turn_context_notes``
    right before ``run_conversation``; this consumes them so a cached agent
    can never replay a stale note on a later turn.
    _gateway_turn_context_notes )getattrhasattrr<   	Exceptionr   r   )r:   notess     r$   "consume_gateway_turn_context_notesrB      sw     E8"==CEu344 	02E-- 	 	 	D	uc**2552s   - 
::rA   boolc                    |rt          | t                    sdS 	 |                     d|d           dS # t          $ r Y dS w xY w)u  Deliver must-deliver notes on a multimodal (list) user message.

    ``compose_user_api_content`` returns ``None`` for non-string content, so
    sidecar-borne facts would silently drop on image/attachment turns.  For
    gateway must-deliver notes we instead append a text part to the content
    list in place — the part becomes durable message content (persisted and
    replayed as-is), which keeps the wire and the transcript byte-identical.

    Returns ``True`` when a part was appended.
    Ftext)typerE   T)r   listr    r@   )r   rA   s     r$   "append_notes_to_multimodal_contentrH      sh      
7D11 u66777t   uus   5 
AAcronsubagentmessages	List[Any]c                   	
 t           dd          }t           dd          }|r|sdS t          t           dd          pd                                          t          v rdS 	 ddlm} ddlm} d}t          |pg           D ]b}t          |t                    rK|                    d	          d
k    r2 ||                    d                                                    } nc|sdS t           dd          s=t           dd          }t          |          r
 |             t           dd          sdS t           dd          	t           dd          
 |||||t           dd          pt           dd          	
t           dd          t           dd          t           dd          dt           dd          	
 fd           dS # t          $ r  t                              dd           Y dS w xY w)a2  Kick off auto-titling for this session's first user message.

    Called from the turn prologue, so every surface a human reads (CLI, gateway,
    TUI/desktop, ACP) gets identical behavior without each one re-implementing
    the call. Fully defensive: titling is cosmetic and must never break a turn.
    _session_dbN
session_idplatformr=   r   )flatten_message_text)maybe_auto_titler+   r,   r   _session_db_createdF_ensure_db_sessionmodelprovider_title_failure_callback_emit_auxiliary_failurebase_urlapi_keyapi_mode)rU   rV   rY   rZ   r[   _on_session_titlec                 X    t          dd            k    ot          dd           k    S )NrU   rV   )r>   )_model	_providerr:   s   r$   <lambda>z4_maybe_title_session_at_turn_start.<locals>.<lambda>   s6    w--7 BE:t44	A r&   )conversation_historyfailure_callbackmain_runtimetitle_callbackruntime_validatorz%Turn-start auto-title dispatch failedTexc_info)r>   r   lower_UNTITLED_PLATFORMSagent.message_contentrQ   agent.title_generatorrR   reversedr   dictr/   stripcallabler@   loggerdebug)r:   rK   
session_dbrO   rQ   rR   	user_textr2   ensurer^   r_   s   `        @@r$   "_maybe_title_session_at_turn_startru      s    t44Jd33J Z 
75*b))/R006688<OOO6M>>>>>>::::::
 	HN++ 	 	C#t$$ F)B)B001C1CDDJJLL	 	F
 u3U;; 	U$8$??F 5"7?? 
 ..E:t44	!)8$?? C5";TBB  %#E:t<<"5)T::#E:t<<  #5*=tDD     #	
 	
 	
 	
 	
 	
,  M M M<tLLLLLLMs!   (BG .AG <BG &HHuser_messageintc                ,   ddl m} d}t          t          |           dz
  dd          D ]i}| |         }t	          |t
                    r|                    d          dk    s9|                    d          |k    r|c S |dk     r ||          r|}j|S )u  Locate this turn's user message after compaction rebuilt ``messages``.

    Compression replaces list entries with fresh copies (and may append a
    todo-snapshot user message or a restored user turn AFTER the surviving
    copy of the current turn's message), so a pre-compression index is
    meaningless. Prefer the LAST user message whose content exactly matches
    this turn's text — the surviving copy in the common case — so the
    injection stamp and the #48677 persist override can't land on a
    todo-snapshot or historical row. Fall back to the last *user-originated*
    turn when no exact match survives (merge-summary-into-tail rewrites the
    content but the trackers still need a live anchor). Compaction handoffs
    must never become the fallback anchor (#80622) — they are reference-only
    scaffolding, not the active ask. Returns -1 when the list has no
    user-originated message at all.
    r   )is_user_originated_turn   r+   r,   r   )agent.context_compressorry   rangelenr   rm   r/   )rK   rv   ry   fallbackir2   s         r$   reanchor_current_turn_user_idxr     s      A@@@@@H3x==1$b"-- 	 	qk3%% 	#''&//V*C*C779--HHH a<<33C88<HOr&   orig_lennew_lenorig_tokens
new_tokensc                0    || k     rdS |dk    o||dz  k     S )uF  Return ``True`` if a compression pass materially reduced the request.

    Compression can succeed by summarising message contents — reducing the
    estimated request token count — without reducing the message row
    count.  Treating row count as the sole progress signal false-positives
    on size-only wins and surfaces a misleading "Cannot compress further"
    failure even when post-compression tokens are well below the model
    context window.  See issue #39548 for an observed case: 220 → 220
    messages, ~288k → ~183k tokens on a 1M-context model still triggered
    auto-reset.

    The token reduction must be *material* (>5%) to count as progress — the
    same floor the overflow-handler retry path uses (conversation_loop.py,
    #39550) — so a sub-5% wobble doesn't keep the multi-pass loop spinning.
    Tr   ffffff? )r   r   r   r   s       r$   compression_made_progressr   %  s-    $ t?>zK$,>>>r&   threshold_tokensc                ,    ||k    o| dk    o|| dz  k     S )aw  Whether an over-threshold request merits another immediate summary.

    Row-count progress is enough to prove that a compression boundary was real,
    but not enough to justify another expensive pass before trying the provider.
    Continue only when the request remains over threshold *and* the previous pass
    materially reduced its estimated token pressure (>5%).
    r   r   r   )r   r   r   s      r$   ,_compression_warrants_another_preflight_passr   C  s0     	&& 	,!O	,t++r&   List[Dict[str, Any]]protect_first_nprotect_last_nc                ^    t          |           ||z   dz   k    rdS t          |           |k    S )u  Cheap gate for the (expensive) full preflight token estimate.

    Returns ``True`` when either:
      (a) message count exceeds the protected ranges (the historical gate), or
      (b) a cheap char-based estimate already crosses the configured threshold
          — the few-but-huge case from issue #27405 that the count-only gate
          would silently skip (a handful of very large messages never trips
          the count condition, so compression was never attempted and the
          turn hit a hard context-overflow error).

    Branch (b) uses ``estimate_messages_tokens_rough`` (the shared char-based
    estimator) so a single large base64 image isn't mistaken for ~250K tokens.
    It intentionally undercounts vs. the full request estimate — it omits the
    system prompt and tool schemas — because it is only a *hint* deciding
    whether to pay for the authoritative ``estimate_request_tokens_rough``,
    which (together with ``should_compress``) makes the real decision.
    r{   T)r~   r   )rK   r   r   r   s       r$   _should_run_preflight_estimater   T  s8    . 8}}7!;;;t)(337GGGr&   enabledidle_after_secondsidle_gap_secondsfloattokensfloor_tokenscooldown_activec                :    | r|dk    rdS ||k     rdS |rdS ||k    S )ah  Decide whether an idle-triggered compaction should run this turn.

    Idle compaction is opt-in (``idle_after_seconds <= 0`` disables it). It
    fires when a session resumes after a wall-clock gap of at least
    ``idle_after_seconds`` since its last activity, so a long-lived thread
    that is paused and later resumed compacts its accumulated history up
    front instead of re-reading it on every subsequent turn.

    It is orthogonal to the token-threshold trigger: it does NOT require the
    context to exceed ``threshold_tokens``. It still skips work when the
    context is at or below ``floor_tokens`` (the size compaction would reduce
    *to*), so a small idle thread never pays for a summarisation that saves
    nothing, and it defers to an active compression-failure cooldown.

    Pure predicate so the policy is unit-testable without a live agent.
    r   Fr   r   r   r   r   r   r   s         r$   _should_idle_compactr   p  sE    2  (A--u,,,u uL  r&   c                      e Zd ZU dZded<   ded<   ded<   ded	<   d
ed<   ded<   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S )TurnContextzCValues produced by the turn prologue and consumed by the turn loop.r   rv   r   original_user_messager   rK   Optional[List[Dict[str, Any]]]ra   r   active_system_prompteffective_task_idturn_idrw   current_turn_user_idxFrC   should_review_memoryr=   r   r   preflight_compression_blockedN)	__name__
__module____qualname____doc____annotations__r   r   r   r   r   r&   r$   r   r     s         MM """"8888''''LLL!&&&&&!!!!!     */!//////r&   r   F)persist_user_display_kindpersist_user_display_metadata
moa_activesystem_messagera   r   task_idpersist_user_messageOptional[Any]persist_user_timestampOptional[float]r   r   Optional[Dict[str, Any]]r   c       
        .   i  |             t                     }|| | j                    |t           dd                                                       	 ddlm} ddlm}  |           pd} |t           dd          pdt           d	d          pdt           d
d          pdt           dd          pdt           dd          pdt           dd          pdt           dd          pdt           dd          pd|	  	         n# t          $ r Y nw xY w	 t           dd          s,ddl	}d|j
        v rddlm}m}  |            r | d           n,# t          $ r t                              dd           Y nw xY wt!          |t"                    r ||          }t!          |t"                    r ||          }| _        d _        | _        | _        |pt#          t-          j                              }| _        t#          t           dd          pd          }|s/ j        pd d| dt-          j                    j        dd          }d _        | _        d _        ddlm}  | |           d _        d _         d _!        d _"        d _#        d _$        d _%        d _&        d _'        d _(        d _)         j*        +                                 d _,        t           j-        dd          }t]          |          r
 |             d _/         j0        dk    r;	  1                                r 2                    d            n# t          $ r Y nw xY w j3        r 4                                 d _3        tk           j6                   _7        t           d!d          rtq          j8                     _9        nd _9        d _:         ||          }tw          |          d"k    r|dd"         d#z   n|}|<                    d$d%          }t          =                    d& j        pd' j>         j?        pd( j@        pd(tw          pg           |           rt                    ng it           d)d          }||n|} t!          |t                    r!|C                    d*          | k    r|}!||!d*<   n0t          d+|d,|-          }!t!          |t                    rd _E        t          |!|-           r. jF        G                                s H                               rV jI        dk    rKt          d. D                       }"|"dk    r,|" _I         jK        dk    r jL        dk    r|" jK        z   _L        |r||!d/<   |	r|	|!d0<   t          i|!           tw          i          d1z
  }#|# _         xjI        d1z  c_I        d _N        t           d2d          }$|$|$O                                 t           d3d          }%|%|%O                                 ||n|}&d}' jK        dk    r9d4 jP        v r0 j-        r) xjL        d1z  c_L         jL         jK        k    r	d}'d _L        t           d5d          }(|(0	 dd6lQmR})  |)|&          }*|*r |(|*           n# t          $ r Y nw xY w jS        sC ||          }+ T                    d7|+dd8          tw          |+          d8k    rd#nd d9            jU         |
 |            jU        },t           d:d          }-	 |- V                                 n.|-5   V                                 ddd           n# 1 swxY w Y   n4# t          $ r' t          W                    d; j        pd'd           Y nw xY wt!          |t                    r|C                    d<          rd _E        n6# t!          |t                    r|C                    d<          rd _E        w xY wt           d=d          }. jX        r|.dk    rirtq          j8                    t           d>tq          j8                              z
  }/|/|.k    r_ jY        }0t          i|,pd j[        pd?          }1t          |0j]        |0j^        z            }2 t          |0d@dA                       }3t           jX        |.|/|1|2t          |3          B          rt          =                    dCt          |/          |.|1dD|2dD j        pd'           t          |0dEt          jc        t          |/          |1F          |1t          |/           j>        G          }4|4r 2                    |4           i}5 d                    i||1|H          \  i},i|5ur(t           i          t          i|          }#|# _        d}6d}7d _g        d _h         jX        rt          i jY        jj         jY        jk         jY        j]                  rt          i|,pd j[        pd?          }8 jY        }0t          |0dId          }9t]          |9          r; |9            }:t!          |:t                    rt!          |:t                    s|: _h        t          |0dJdK           }; |;|8          }<t           dd          dLk    o3t#          t           dMdN          pdN          l                                dOv }=|<s|0jm        }>|>dk    r|8|>k    r|8|0_m         t          |0d@dP                       }?d}@d}A|<r.t          =                    dQ|8dD|0j]        dD|0jn        dD           n|?rlt          =                    dRt          |?C                    dSdT                     j        pd'           |8|0j]        k    r|?C                    dSdT          }BdU|BdV}An|=r+t          =                    dWt           dMdN                     n\|0o                    |8          }@|@sEt          |0dXd          }Ct]          |C          r%	  |C|8          d1         }An# t          $ r d}AY nw xY w|@r!d}6t           dYd          }Dt]          |D          r
 |D             t          =                    dZ|8dD|0j]        dD j>        |0jp        dD           t          |0d[t          jc        |8|0j]        \          |8|0j]        |0jp         j>        ]          }E|Er 2                    |E           t          d1t          t           d^d_          pd_                    }Ft          |F          D ],}Gtw          i          }H|8}Ii}J d                    i||8|H          \  i},i|Ju r3t                     r$t          =                    d` j        pd'            nt          i|,pd j[        pd?          }8t          |Htw          i          |I|8          sd}7 nt           i          d _!        d _$        d _&        d _'        d _(        |0o                    |8          s n<t          |I|8|0j]                  s$d}7t          W                    da|IdD|8dD            n.n|Ar w                    |A|8|0j]                   nqt           dYd          }Dt]          |D          r
 |D             |?s|<s|=rd}Knt          |0dbd          }Kd}Lt]          |K          rN	 t           |Ki                    }Ln4# t          $ r'}Mt                              dc|M           d}LY d}M~Mnd}M~Mww xY w|Lrt          =                    ddt          |0det          |0          jy                  |8dDt          |0dfd          dD           i}N d                    i||8|H          \  i},i|Nur5d}6t           i          d _!        d _$        d _&        d _'        d _(        n" jX        st          t           dgd          dhd          }Ot!          |Ot                    r|Odk    rd}PiD ]^}Qt!          |Qt                    s|QC                    d*          }Rt!          |Rt"                    r|Ptw          |R          z  }PU|Rr|Od1z   }P n_|P|Ok    r+t           dYd          }Dt]          |D          r
 |D             nKt          i|,pd j[        pd?          }S|S|Ok    r*t           dYd          }Dt]          |D          r
 |D             |6rt          i|          }#|# _        d}T	 ddilzm{}U  |Udj j        |||&t          i          t                      j>        t           dkd          pdt           dld          pdt           dmd          pdn          }Vg }W	 ddol|m}}Xm~}Y  |X            }Zn# t          $ r d}Yd}ZY nw xY w|VD ]}[d}\t!          |[t                    r+|[C                    dp          rt#          |[dp                   }\n-t!          |[t"                    r|[                                r|[}\nq|YH	  |Y|\ j        dq|Zr          }\n2# t          $ r%}]t          W                    ds|]           Y d}]~]nd}]~]ww xY w|W                    |\           |Wrdt                    |W          }Tn2# t          $ r%}^t          W                    du|^           Y d}^~^nd}^~^ww xY wt                     }_|_rd|#cxk    rtw          i          k     r9n n6t!          i|#         t                    ri|#         C                    d*          nd}`t!          |`t                    rt          |`|_           n|Tr|Tdtz   |_z   n|_}Ti  _        t                       _        d _        d _        t          j                    j         _         |                                d j                    j        r+ |                                d j                   d _        nd _        d _         j        rK	 t!          |&t"                    r|&nd}a j                             jI        |a           n# t          $ r Y nw xY wd}b j        r	 t!          |&t"                    r|&nd}ct'          |c          s j                            |c          pd}bn# t          $ r Y nw xY w|brB	  j                                        }d|dr 2                    |d           n# t          $ r Y nw xY w|s:t           dd          dLk    r$d|#cxk    rtw          i          k     r	n ni|#         C                    dv          d+k    ri|#         }et-          |eC                    d*d          |b|T          }f|f|f|eC                    d*          k    r|f|edw<   |6rt          t           dxd                    rxt           dyd          }g|ge	 |g                     j        |eC                    d*          |f           n4# t          $ r' t          W                    dz j        pd'd           Y nw xY wd ifd}}h	 |- |h             n$|-5   |h             ddd           n# 1 swxY w Y   n4# t          $ r' t          W                    d~ j        pd'd           Y nw xY wt!          |t                    r|C                    d<          rd _E        n6# t!          |t                    r|C                    d<          rd _E        w xY wt1           i           t3          ||&i|,|||#|'|T|b|7          S )a  Run the once-per-turn setup and return the loop's input context.

    The callables/helpers the original prologue referenced from the
    ``conversation_loop`` module are passed in explicitly to keep this module
    free of an import cycle with ``agent.conversation_loop``.
    N_memory_write_originassistant_toolr   )set_runtime_main)resolve_prompt_cache_scope_safer=   rV   rU   requested_providerrY   rZ   r[   	auth_moderO   )r   rY   rZ   r[   r   rO   cache_scope_skip_mcp_refreshFztools.mcp_tool)has_registered_mcp_toolsrefresh_agent_mcp_toolsT)
quiet_modez&between-turns MCP tool refresh skippedrf   _relay_pending_turn_idsession:   )note_turn_startreset_consolidation_failuresanthropic_messagesu~   🔌 Detected stale connections from a previous provider issue — cleaned up automatically. Proceeding with fresh connection.run_budget_secondsP   z...
 zPconversation turn: session=%s model=%s provider=%s platform=%s history=%d msg=%rnoneunknown_pending_cli_user_messager   r,   )r+   r   )	timestampc              3  L   K   | ]}|                     d           dk    dV   dS )r+   r,   r{   N)r/   ).0ms     r$   	<genexpr>z%build_turn_context.<locals>.<genexpr>  s?       
 
quuV}}/F/FA/F/F/F/F
 
r&   display_kinddisplay_metadatar{   _stream_context_scrubber_stream_think_scrubbermemoryreaction_callback)detect_reactionu   💬 Starting conversation: '<   '_session_persist_lockz5Turn-start session row creation failed for session=%s_db_persisted&compression_idle_compact_after_seconds_last_activity_ts)system_prompttools'get_active_compression_failure_cooldownc                     d S Nr   r   r&   r$   r`   z$build_turn_context.<locals>.<lambda>'  s    PT r&   r   zDIdle compaction: %ss idle >= %ss, ~%s tokens > %s floor (session %s),idle)idle_secondsr   )phasedefault_messageapprox_tokensr   rU   )r   r   !snapshot_preflight_display_tokens$should_defer_preflight_to_real_usagec                    dS )NFr   )_tokenss    r$   r`   z$build_turn_context.<locals>.<lambda>  s    E r&   codex_app_server codex_app_server_auto_compactionnative>   offr   c                     d S r   r   r   r&   r$   r`   z$build_turn_context.<locals>.<lambda>  s    D r&   zpSkipping preflight compression: rough estimate ~%s >= %s, but last real provider prompt was %s after compressionz`Skipping preflight compression: same-session cooldown active (~%s seconds remaining, session %s)remaining_secondsg        z	cooldown:z.0fzsSkipping Hermes preflight compression for codex app-server (mode=%s); Hermes will not start thread compaction here.should_compress_info_clear_context_overflow_warnzDPreflight compression: ~%s tokens >= %s threshold (model %s, ctx %s)	preflight)r   	threshold)r   r   r   r   context_lengthrU   max_compression_attempts   zRPreflight compression deferred: compression lock held by another path (session %s)zgPreflight compression made insufficient progress: ~%s -> ~%s request tokens; skipping additional passesshould_compress_preflightzQshould_compress_preflight raised %s; skipping engine-driven preflight maintenancez_Engine-driven preflight maintenance: %s requested compress() at ~%s tokens (below %s threshold)namer   context_compressorr   )invoke_hookpre_llm_callrP   _parent_session_id_user_id)
rO   r   r   rv   ra   is_first_turnrU   rP   parent_session_id	sender_id)get_spill_configspill_if_oversizedcontextzplugin hook)rO   sourceconfigzhook context spill failed: %sr   zpre_llm_call hook failed: %sr+   r*   _last_compaction_in_placerN   z>in-place compaction api_content backfill failed for session=%sr   r3   c                 \                                                                       d S r   )rT   _persist_session)r:   ra   rK   s   r$   _ensure_and_persistz/build_turn_context.<locals>._ensure_and_persist  s2      """x)=>>>>>r&   z:Early turn-start session persistence failed for session=%s)rv   r   rK   ra   r   r   r   r   r   r   r   r   )r   r3   )r   rO   r>   _restore_primary_runtimeagent.auxiliary_clientr   agent.prompt_cache_scoper   r@   sysmodulestools.mcp_toolr   r   rp   rq   r   r   _stream_callback_persist_user_message_idx_persist_user_message_override_persist_user_message_timestampuuiduuid4_current_task_idhexr   _current_turn_id_current_api_request_idagent.agent_runtime_helpersr   _invalid_tool_retries_invalid_json_retries_empty_content_retries_incomplete_scratchpad_retries_codex_incomplete_retries_thinking_prefill_retries_post_tool_empty_retried_last_content_with_tools$_last_content_tools_all_housekeeping_mute_post_response_unicode_sanitization_passes_tool_guardrailsreset_for_turn_tool_guardrail_halt_decision_memory_storero   _vision_supportedr[   _cleanup_dead_connections_emit_status_compression_warning_replay_compression_warningr   max_iterationsiteration_budgettime_run_budget_started_at_run_budget_wrapup_injectedr~   replaceinforU   rV   rP   rG   rm   r/   r   r   _todo_store	has_items_hydrate_todo_store_user_turn_countsum_memory_nudge_interval_turns_since_memoryr   _is_user_initiated_turnresetvalid_tool_namesagent.reactionsr   r   _safe_print_cached_system_promptrT   warningcompression_enabledr   r   r   rw   r   summary_target_ratior   rC   r   r
   format_compress_contextr   r    _turn_received_provider_response _turn_preflight_display_snapshotr   r   r   rh   last_prompt_tokenslast_real_prompt_tokensshould_compressr   r   maxr}   r   _compression_made_progressr   _warn_context_overflow_blockedrF   r   hermes_cli.lifecycler   tools.hook_output_spillr  r  rn   r    r!   rB   rH   _turn_failed_file_mutationsset_turn_file_mutation_paths_verification_stop_nudges_pre_verify_nudges	threadingcurrent_threadident_execution_thread_id_set_interrupt_interrupt_requested _interrupt_thread_signal_pending_interrupt_message_memory_manageron_turn_startr   prefetch_alldescribe_recallr%   set_latest_user_api_contentru   r   )jr:   rv   r   ra   r   stream_callbackr   r   r   r   restore_or_build_system_promptinstall_safe_stdiosanitize_surrogatessummarize_user_message_for_logset_session_contextset_current_write_originrar   recovered_historyr   r   _cache_scope_sysr   r   r   r   r   _reset_consol_preview_text_msg_previewpending_cli_messageexpected_persist_contentuser_msgprior_user_turnsr   scrubberthink_scrubberr   r   r   r   kind_print_previewr   persist_lock_idle_after	_idle_gap_compressor_idle_tokens_idle_floor_idle_cooldown_idle_status_idle_input_preflight_compressed_preflight_compression_blocked_preflight_tokens_snapshot_fn_snapshot_val_defer_preflight_preflight_deferred_codex_native_auto_last_compression_cooldown_should_compress_now_compress_block_reason_cooldown_secs_info_clear_warn_preflight_status_max_preflight_passes_pass	_orig_len_orig_tokens_preflight_input_engine_preflight_wants_engine_preflight_preflight_exc_engine_input_ctx_len
_raw_chars_m_c_uncompressed_tokensr   _invoke_hook_pre_results
_ctx_parts
_spill_cfg_spill_if_oversized_spill_config_cachedr_piece
_spill_excexc_gateway_notes_gw_turn_content	_turn_msgr   _query_recall_indicator_turn_user_msg_api_content_dbr  rK   sj   `  `                                                                                                     @r$   build_turn_contextr    s   8 
 <EBB$0 ())) WU,BDTUUVVV 
""$$$;;;;;;LLLLLL 76u==CE:r**0bE7B''-2&u.BBGGM2UJ339rE9b117RUJ339re["55;ulB77=2$
	
 
	
 
	
 
	
 
	
    Nu1599 	D 4<//\\\\\\\\++-- D++EdCCCC N N N=MMMMMN ,$$ 9**<88&,, I223GHH -E&*E#+?E(,BE)43tz||#4#4.E'%!92>>D"EEG 
,9YY/@YY4:<<CSTVUVTVCWYY 	 $(E $E$&E! <;;;;;OE7### #$E"#E#$E +,E(&'E#&'E#%*E"%)E"16E. %E)*E&	))+++*.E'E/1OQUVVM "E ~---	..00 """  
  	 	 	D	 ! *))+++%)" -U-ABBE
 u*D11 ,'+y{{$$'+$(-E% 32<@@M36}3E3E3J3JM#2#&..P]L''c22L
KKZ"FEK1L9#)S)=)C%D%D	   .BIt()))rH "%)DdKK 4 @l  	&--3##I..2JJJ& +*55,
 
 
 )400 	3.2E+ H0FGGGG  8E$5$?$?$A$A 8!!"6777  \ 6! ; ; 
 
+
 
 
 
 
 a%5E"+a//E4MQR4R4R,<u?[,[) ! I#< ( 	I+HH'(8X&&&MMA-&;E# 
a %)E! u8$??HU$<dCCN! 5I4T00Zf !$q((E222# 3!!Q&!!$(DDD#' ()E%
  ':DAA$	777777"?#899D (!!$''' 	 	 	D	  
77EE<N3B3,? <N++b00uub< < <	
 	
 	
 "*&&un>RSSS 6 5"94@@L3$$&&&& + +((***+ + + + + + + + + + + + + + + 
 
 
C& 	 	
 	
 	
 	
 	

 -t44 	38K8O8OP_8`8` 	3.2E+ -t44 	38K8O8OP_8`8` 	3.2E+2222 %!I1MMK  CL[1___IKK'%1Ddikk"R"RR	##2K828bk)T  L ,{/OO KWF   N $1#.!*#( $^ 4 4   2L #	NN#''"&&$.    C $C$J%(^^L% % % #/!$Y+	  	  	    5&&|444&161H1HnL- 2I 2 2.. ;..+Qx)=, ,( -K ,- -) 7LE3 "%*"-2E*-1E*  [&%C 0 / 1	& & [& :.4"+%
 
 

 .
 <d
 
 L!! 	G(LNNM --- Gjt7 7 G :G6"2!!
 

 /./@AA E:t,,0BB 	!6  
   egg ! 	 # 	C2Ezz/%771B.!
5L!
 !
 ! !  %!% (	6KKI$((/336::    #  	6KK6)--.A3GGHH *F	   !K$@@@ "7!:!:;NPS!T!T)I^)I)I)I& 	6KKKA8LL    $/#>#>?P#Q#Q ' 6  -CTJJE?? 66167H1I1I!1L..$ 6 6 615...6 A	6$(! "%)GNNK$$ KKV$((/33-11   !D! E L,):! ! ! 0!,!=*9k! ! ! ! 6""#4555 %(3wu&@!DDIJJ% %! 455 > >MM	0#+ 161H1Hn<M- 2I 2 2..
  0007>> 1 KK<(2F  
 E
 %B"6"<"+-% % %!
 2s8}}l<M   6:2E'M8%9( ($ 01,23/15.=B:,1)"223DEE EC %0  
 6:2NNP'++,00	   E $ ]	6 00&!,    "%)GNNK$$ 
 % (; ?Q $(!!$+!<d% %!2 ',#)** 4
4.23D3DX3N3N.O.O++  4 4 4 LL>&  
 /4++++++4 ' 6DKk1B1B1KLL(,,{,>BBFF   !)161H1Hn<M- 2I 2 2.. =00,0)+Qx, ,( 45E067E359E2AFE>05E-& 2& E/668H$
 
 h$$ $	&AJ  !"d++ VVI&&b#&& #b'')JJ 
 "*AJE X%%%94  K(( "KMMM'D"6"<"+-( ( ($
 (833")=t# #K  ,, &# @ !?l!
 !
 +@' 2<DDDDDD#|'%.!%h#$8999+UJ55;%e-A4HHNBeZ66<"
 
 
 !#
	(        $.:<<   	( 	( 	("&#'   	(  	& 	&AF!T"" quuY'7'7 Qy\**As## 		 ".P00#(#3,3	  FF ! P P PNN#BJOOOOOOOOPf%%%% 	:"(++j"9"9 < < <5s;;;;;;;;< 8>>N  )9999CMM999998$9:DAA : *+//	::: 	 	 &-- 	./?PPPP '$#f,~==#   )+E%&)eeE#&'E# E "+!9!;!;!AE BDDu9:::! 7
D%"<===16..#' 16.  	1;<QSV1W1W_--]_I!//0F	RRRR 	 	 	D	  	.89NPS.T.T\**Z\F$V,, V%*%:%G%G%O%O%USU" 	 	 	D	  	$)$9$I$I$K$K!$ :&&'8999   * %E:t,,0BBB&6666X66666*+//776AA!"78/y"--/ACV
 
 #8J8J98U8U(U(U,8N=) % :EBB* *  e]D99?77!,*..y99(   
 %   -!,6%)	 '     ? ? ? ? ? ? ? ?3!!!! & &##%%%& & & & & & & & & & & & & & & 
 
 
H& 	 	
 	
 	
 	
 	

 -t44 	38K8O8OP_8`8` 	3.2E+ -t44 	38K8O8OP_8`8` 	3.2E+2222 'uh777!311+31/-&D   s   B5D 
D#"D#'=E% %&FF=)M' '
M43M4Z: :
[[^ ];/^ ;]??^ ]?^ _- .^85_- 7^88_- -3` q q.-q.|$ $
}.}}EA6AK F9AG GAK GAGGAK GAGGA8AK IAI+I*AK I+
AJI5AJJAK JAJJ0AK K
AK:KAK5K5AK:Q	9AR R
ARRARRAAS# S#
AS0S/AS0S60AT' T'
AT4T3AT4X/AY  Y .AY1Y0AY1Y=AZ/ ZAZ#ZAZ/ Z#AZ'Z'AZ/ Z*AZ'Z+AZ/ Z.A\ Z/.A[ [A\ [A[ [ A\ \3A])r   r   r   r   r   r   r   r   )r'   r(   r   r   )r2   r(   r   r3   )r2   r6   r   r   )r:   r   r   r   )r   r   rA   r   r   rC   )r:   r   rK   rL   r   r3   )rK   rL   rv   r   r   rw   )
r   rw   r   rw   r   rw   r   rw   r   rC   )r   rw   r   rw   r   rw   r   rC   )
rK   r   r   rw   r   rw   r   rw   r   rC   )r   rC   r   rw   r   r   r   rw   r   rw   r   rC   r   rC   r   )rv   r   r   r   ra   r   r   r   r   r   r   r   r   r   r   r   r   rC   r   r   )7r   
__future__r   loggingr]  r7  r  dataclassesr   typingr   r   r   r   r	   agent.conversation_compressionr
   r   r   r   r   agent.context_enginer   agent.iteration_budgetr   agent.memory_managerr   agent.memory_providerr   agent.message_metadatar   r   agent.model_metadatar   r   	getLoggerr   rp   r%   r1   r5   r9   rB   rH   	frozensetri   ru   r   r   rT  r   r   r   r   r  r   r&   r$   <module>r     s   0 # " " " " "        ! ! ! ! ! ! 5 5 5 5 5 5 5 5 5 5 5 5 5 5              E D D D D D 2 2 2 2 2 2 ; ; ; ; ; ; 3 3 3 3 3 3 J J J J J J J J       
 
	8	$	$ 6  6  6  6F   .	! 	! 	! 	!- - - -3 3 3 3(   @  i 455 EM EM EM EMP   @? ? ? ?6 7    "H H H H8! ! ! !D 0 0 0 0 0 0 0 0H /3M 04>B 'M M M M M M M Mr&   