
    .cj2                        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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     A/home/ice/.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_lengthconfigured_modelconfigured_providerconfigured_base_urlr8   list | Noner9   
int | Noner:   
str | Noner;   r<   c                  | j         r|dS t          |dd          sdS t          |dd          }|dS |t          |dd          }t          t          |dd          pd          }	t          | j        | j        | j        pt          |dd	          pd	| j        pt          |d
d	          pd	| j        ||||nt          |dd          ||nt          |dd          ||nt          |dd          
  
        }
|
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!   _custom_providersr   r   base_urlr)   api_keymodelprovider)rC   rD   
model_infor8   r9   r:   r;   r<   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_providerrC   rD   rG   r6   r   r   appendr   join)r   r   r   r8   r9   r:   r;   r<   r2   old_ctxnew_ctxestimatepctnew_thresholdpartss                  r   #merge_preflight_compression_warningrV   A   s    > U]5/66 	,d	3	3B	z "5*=tDD'".227a88G,HGE:r$B$BHbE'%B"?"?E2$)3  + .. #.  
D11 #.  
D11+  G0  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sourcerW   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}
d}d}d}|	  |            }t          |t                    r|                    di           ni }t          |t                    r~|                    d          it	          |d                   }
|                    d          p|                    d          }|                    d          }|                    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   rE   r   defaultrF   rC   _session_dbsession_storer7   )
r.   get
isinstancedictr   r1   get_or_create_sessionget_messages_as_conversation
session_idrV   )r   rX   rY   rZ   r8   rW   lockcacher   entrycfg_ctxr:   r;   r<   cfg	model_cfgr   dbstores                      r   (enrich_model_switch_warnings_for_gatewayrp      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::#,==#;#;#Uy}}W?U?U &/mmJ&?&?#&/mmJ&?&?# 	 	 	D	 H		-	-BFOT22E	~%+	//77E66u7GHHHH 	 	 	D	 ()%)//	 	 	 	 	 	s6   (AA#&A#9C
E 
EE=/F- -
F:9F:)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?   r<   r?   r   r   )r   r	   rX   r   rY   r   rZ   r   r8   r=   rW   r[   r   r   )__doc__
__future__r   typingr   r   r   r   r0   r   hermes_cli.model_switchr	   r
   r   r   r6   rV   rp    r   r   <module>rv      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 %)$((,#'&*&*O, O, O, O, O, O,p %)598 8 8 8 8 8 8 8r   