
    9jl                        d Z ddlmZ ddlmZmZmZmZ ddlm	Z	 ddl
mZmZ d&dZd'dZd(dZdddddd)dZdddd*d%ZdS )+aZ  Warn when an in-session model switch will trigger preflight compression on the next turn.

Addresses part of #23767 ("user-facing guardrail when switching from a
high-context provider to a substantially lower-context provider"). The other
proposed fixes from that issue (hard preflight token guard, metadata cache
invalidation on switch, compression safety invariant, oversized tool-output
handling) are tracked separately.

Mirrors the expensive-model guard pattern: merge into ``ModelSwitchResult.warning_message``
so Herm TUI, CLI, and gateway surfaces that already show switch warnings pick it up.
    )annotations)AnyCallableListOptional)MINIMUM_CONTEXT_LENGTH)ModelSwitchResultresolve_display_context_lengthresultr	   textstrreturnNonec                H    | j         r| j          d| | _         d S || _         d S )Nz | )warning_message)r   r   s     E/home/rurouni/.hermes/hermes-agent/hermes_cli/context_switch_guard.py_append_warningr      s:     &$*$:!E!Et!E!E!%    context_lengthintthreshold_percentfloatc                L    t          t          | |z            t                    S )N)maxr   r   )r   r   s     r   _threshold_tokensr      s!    s>$55668NOOOr   agentr   messagesOptional[List[dict]]Optional[int]c                .   t          | dd           }|d S |t          t          |dd                    t          t          |dd                    z   dz   }t          |          |k    rd S 	 ddlm} t          | d	d           pd
}t          | dd           }t           ||||pd                     S # t
          $ r Y nw xY wt          t          |dd          pd          }|dk    r|S t          t          | dd          pd          }|dk    r|nd S )Ncontext_compressorprotect_first_n   protect_last_n      r   )estimate_request_tokens_rough_cached_system_prompt tools)system_promptr*   last_prompt_tokenssession_prompt_tokens)getattrr   lenagent.model_metadatar'   	Exception)	r   r   ccprotectr'   r+   r*   lastsession_prompts	            r   _estimate_tokensr6       sv   	,d	3	3B	ztgb"3Q77883B("--<
 <
 
 x==G##4	JJJJJJ#E+BDIIORME7D11E--"/-4      	 	 	D	 wr/338q99Daxx(?CCHqIIN+a//>>T9s   .AB5 5
CCNr   r   custom_providersconfig_context_lengthr8   list | Noner9   
int | Nonec               (   | j         r|dS t          |dd          sdS t          |dd          }|dS t          t          |dd          pd          }t          | j        | j        | j        pt          |dd          pd| j        pt          |d	d          pd| j        ||
          }|sdS t          ||          }|dS t          t          |dd                    }	t          ||	          }
||
k     rdS t          t          |dd          pd          dk    rdS g }|r$||k     r|                    d|dd|dd           |                    d|dd| j         d|dd|
dd	           t          | d                    |                     dS )zJIf the next user message will likely preflight-compress, append a warning.Ncompression_enabledTr!   r   r   base_urlr)   api_key)r>   r?   
model_infor8   r9   r   g      ?_ineffective_compression_count   zContext window shrinks (,u    → z). zSession is ~z	 tokens; z allows z (auto-compress at ~zM). Your next message will run preflight compression before the model replies.)successr.   r   r
   	new_modeltarget_providerr>   r?   r@   r6   r   r   appendr   join)r   r   r   r8   r9   r2   old_ctxnew_ctxestimatepctnew_thresholdpartss               r   #merge_preflight_compression_warningrO   A   s0    > U]5/66 	,d	3	3B	z'".227a88G,HGE:r$B$BHbE'%B"?"?E2$)3  G  x00H
/55
6
6C%gs33M-
727;;@qAAQFFE 
7W$$EwEEEwEEEE	
 	
 	
 
LL	Vx, 	V 	V	V 	V%,1	V 	V+2	V 	V 	V   FBGGENN+++++r   )r8   load_gateway_configrunnersession_keysourcerP   Callable[[], dict] | Nonec                  t          |dd          }t          |dd          }d}|C|A|5  |                    |          }	|	r|	d         |	d         }ddd           n# 1 swxY w Y   |dS d}
|	  |            }t          |t                    r|                    di           ni }t          |t                    r*|                    d          t	          |d                   }
n# t
          $ r Y nw xY wd}t          |dd          }t          |dd          }|C|A	 |                    |          }	|                    |	j                  }n# t
          $ r Y nw xY wt          | ||||
	           dS )
z3Gateway helper: cached agent + session DB messages._agent_cache_lockN_agent_cacher   modelr   _session_dbsession_storer7   )
r.   get
isinstancedictr   r1   get_or_create_sessionget_messages_as_conversation
session_idrO   )r   rQ   rR   rS   r8   rP   lockcacher   entrycfg_ctxcfg	model_cfgr   dbstores                   r   (enrich_model_switch_warnings_for_gatewayri   z   s    6.55DFND11EEE- 	! 	!IIk**E !q-a	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! }G&	%%''C0:30E0EM,,,2I)T** ;y}}=M/N/N/Zi(89:: 	 	 	D	 H		-	-BFOT22E	~%+	//77E66u7GHHHH 	 	 	D	 ()%     s6   (AA#&A#3A6C* *
C76C7#/E 
E E )r   r	   r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   r   r   )r   r	   r   r   r   r   r8   r:   r9   r;   r   r   )r   r	   rQ   r   rR   r   rS   r   r8   r:   rP   rT   r   r   )__doc__
__future__r   typingr   r   r   r   r0   r   hermes_cli.model_switchr	   r
   r   r   r6   rO   ri    r   r   <module>ro      s  
 
 # " " " " " 0 0 0 0 0 0 0 0 0 0 0 0 7 7 7 7 7 7 U U U U U U U U& & & &P P P P: : : :H %)$((,6, 6, 6, 6, 6, 6,~ %)59/ / / / / / / /r   