
    Pmj;)                    D   U d Z ddlmZ ddlZddlmZ ddlmZmZ ddl	m
Z
mZmZmZ  ej        e          ZdZdZd	Zd
ZdZdZeZeZeeeehZded<   e G d d                      Zd3dZd3dZd4dZd5dZd6dZ d5d Z!d7d#Z"d8d$Z#d7d%Z$d9d(Z%d:d*Z&d;d,Z'd<d0Z(d=d2Z)dS )>a  Hermes middleware contract helpers.

Observer hooks report what happened. Middleware can change what happens by
rewriting a request or wrapping the actual execution callback. Keep the small
contract helpers here so agent-loop call sites and plugins share one vocabulary.
    )annotationsN)deepcopy)	dataclassfield)AnyCallableDictListzhermes.observer.v1zhermes.middleware.v1tool_requesttool_executionllm_requestllm_executionzset[str]VALID_MIDDLEWAREc                  X    e Zd ZU dZded<   ded<   dZded<    ee          Zd	ed
<   dS )RequestMiddlewareResultz;Result of applying request middleware to a mutable payload.r   payloadoriginal_payloadFboolchanged)default_factoryzList[Dict[str, Any]]traceN)	__name__
__module____qualname____doc____annotations__r   r   listr        ;/home/thesage/.hermes/hermes-agent/hermes_cli/middleware.pyr   r   %   s\         EELLLG"'%"="="=E======r   r   kwargsr   returnDict[str, Any]c                 <    |                      dt                     | S )Ntelemetry_schema_version)
setdefaultOBSERVER_SCHEMA_VERSIONr!   s    r    observer_payloadr)   /   s    
02IJJJMr   c                 r    |                      dt                     |                      dt                     | S )Nr%   middleware_schema_version)r&   r'   MIDDLEWARE_SCHEMA_VERSIONr(   s    r    middleware_payloadr-   4   s7    
02IJJJ
13LMMMMr   r   c                    	 t          |           S # t          $ rP}t                              d|           t	          | t
                    rt          |           cY d}~S | cY d}~S d}~ww xY w)a  Deep-copy a request payload, tolerating non-deepcopyable members.

    Request payloads are normally plain JSON-shaped dicts, but an LLM request
    can occasionally carry non-deepcopyable objects (clients, callbacks, file
    handles). A hard ``deepcopy`` failure there would otherwise abort the whole
    request-middleware pass. Fall back to a shallow ``dict`` copy so middleware
    still runs and the original nested objects are shared by reference rather
    than corrupting the live payload.
    z<deepcopy failed for request payload (%s); using shallow copyN)r   	Exceptionloggerdebug
isinstancedict)r   excs     r    
_safe_copyr5   :   s          SUXYYYgt$$ 	!==      	s&    
A+>A&A+A& A+&A+requestcontextc                   t          t                    st          | | dg           S t          |           }t          |          }g }t	          t          f||d|D ]t}t          |t                    s|                    d          }t          |t                    sCt          |          }|                    t          |                     ut          ||t          |          |          S )zApply registered LLM request middleware.

    Middleware may return ``{"request": {...}}`` to replace the effective
    provider kwargs before Hermes sends them.
    Fr   r   r   r   r6   original_requestr6   )_has_middlewareLLM_REQUEST_MIDDLEWAREr   r5   _invoke_middlewarer2   r3   getappend_trace_entryr   )r6   r7   r;   current_requestr   resultnext_requests          r    apply_llm_request_middlewarerE   M   s!    122 
&$	
 
 
 	
 "'** !122O"$E$)  	  + + &$'' 	zz),,,-- 	$\22\&))****")U	   r   	tool_namestrargsc                2   t          |          }t          |          }g }t          |                    d          pd          }t          |                    dd                    }|rL|sJddlm} |                    || |          }	|	|k    r&t          |	          }|                    dd	i           t          t                    s$t          |s|n||t          |          |
          S t          t          f| ||d|D ]t}
t          |
t                    s|
                    d          }t          |t                    sCt          |          }|                    t          |
                     ut          ||t          |          |
          S )zApply registered tool request middleware.

    Middleware may return ``{"args": {...}}`` to replace the effective tool
    arguments before hooks, guardrails, approvals, and execution see them.
    
session_id 
skip_relayFr   )relay_runtime)rJ   rF   rH   source
nemo_relayr9   rF   rH   original_argsrH   )r5   rG   r?   r   popagentrM   apply_tool_request_interceptsr@   r<   TOOL_REQUEST_MIDDLEWAREr   r>   r2   r3   rA   )rF   rH   r7   rQ   current_argsr   rJ   rL   rM   
relay_argsrC   	next_argss               r    apply_tool_request_middlewarerY   x   s    t$$Mm,,L"$EW[[..4"55Jgkk,6677J 
3* 
3''''''"@@! A 
 


 %%%j11LLL(L1222233 
& %7DD<!KK	
 
 
 	
 %#	 
   + + &$'' 	JJv&&	)T** 	!),,\&))****"&U	   r   c                    t          | fi |S )z7Compatibility wrapper for older ``api_request`` naming.)rE   )r6   r7   s     r    apply_api_request_middlewarer[      s    
 (;;7;;;r   	next_callCallable[[Dict[str, Any]], Any]c                    t          t                    }|s ||           S t          t          ||f| |                    d|           d|S )zCRun provider execution through registered LLM execution middleware.r;   r:   )_get_middleware_callbacksLLM_EXECUTION_MIDDLEWARE_run_execution_chainrR   )r6   r\   r7   	callbackss       r    run_llm_execution_middlewarerc      sp     **BCCI "y!!!   %7AA    r   c           	         t          t                    }|s ||          S t          t          ||f| ||                    d|          d|S )z@Run tool execution through registered tool execution middleware.rQ   rP   )r_   TOOL_EXECUTION_MIDDLEWAREra   rR   )rF   rH   r\   r7   rb   s        r    run_tool_execution_middlewarerf      sp     **CDDI y! kk/488    r   c                    t          | |fi |S )z9Compatibility wrapper for older ``api_execution`` naming.)rc   )r6   r\   r7   s      r    run_api_execution_middlewarerh      s     (FFgFFFr   kind	List[Any]c           	     4    ddl m}  || fi t          di |S )Nr   )invoke_middlewarer   )hermes_cli.pluginsrl   r-   )ri   r!   rl   s      r    r>   r>      s<    444444TBB%7%A%A&%A%ABBBr   r   c                $    ddl m}  ||           S )Nr   )has_middleware)rm   ro   )ri   ro   s     r    r<   r<      s$    111111>$r   List[Callable]c                n    ddl m} t           |            j                            | g                     S )Nr   )get_plugin_manager)rm   rr   r   _middlewarer?   )ri   rr   s     r    r_   r_      s?    555555""$$044T2>>???r   rb   terminal_callCallable[[Any], Any]c                     dv rdnd G d dt                     d fd
 d                   S )Nr6   rH   c                        e Zd Zd fdZ xZS )7_run_execution_chain.<locals>._DownstreamExecutionErrororiginalBaseExceptionr"   Nonec                r    t                                          t          |                     || _        d S N)super__init__rG   ry   )selfry   	__class__s     r    r   z@_run_execution_chain.<locals>._DownstreamExecutionError.__init__  s,    GGS]]+++$DMMMr   )ry   rz   r"   r{   )r   r   r   r   __classcell__)r   s   @r    _DownstreamExecutionErrorrx     s=        	% 	% 	% 	% 	% 	% 	% 	% 	% 	%r   r   indexintr   r   r"   c                     t                    k    r           S           ddd d
d	
 f	d}t          di }|<   ||d<   	  di |S # 	$ r}|j        d }~wt          $ r^}t                              dt          dt                              |           rcY d }~S r  
 d	z             cY d }~S d }~ww xY w)NFnext_payloadr   r"   c                   	 r2t          d dt          dt                               d          d	  dz   | 
n|           d	S # t          $ r} |          |d }~ww xY w)NzMiddleware 'z' callback r   zF called next_call() more than once; downstream execution is single-useT   )RuntimeErrorgetattrreprr/   )r   r4   r   call_atcallbackr   ri   next_callednext_resultnext_succeededr   s     r    r\   z8_run_execution_chain.<locals>.call_at.<locals>.next_call  s      "U4 U UxT(^^DDU U U  
 K>%geaiL<PVbcc!%"" > > >//44#=>s   A 
A+A&&A+r\   z&Middleware '%s' callback %s raised: %sr   r   r}   )r   r   r"   r   r   )lenr-   ry   r/   r0   warningr   r   )r   r   r\   call_kwargsr4   r   r   r   r   r   r   rb   ri   r!   payload_keyrt   s   ``   @@@@r    r   z%_run_execution_chain.<locals>.call_at  s   C	NN"" =)))U#	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	>( )22622#*K #,K 	/8**k***( 	 	 	, 	/ 	/ 	/NN8*d8nn==	    #""""""" 7519g........	/s6   A" "C'A..C;<C7C=CCCr   )r   r   r   r   r"   r   )r/   )ri   rb   rt   r!   r   r   r   s   ````@@@r    ra   ra      s      )F22))K% % % % %I % % %
// // // // // // // // // // // //b 71f[)***r   rC   c                    i }dD ]3}|                      |          }t          |t                    r|r|||<   4|sd|d<   |S )N)rN   reasonnamepluginrN   )r?   r2   rG   )rC   entrykeyvalues       r    rA   rA   ?  s^    E+  

3eS!! 	e 	E#J #"hLr   )r!   r   r"   r#   )r   r   r"   r   )r6   r#   r7   r   r"   r   )rF   rG   rH   r#   r7   r   r"   r   )r6   r#   r\   r]   r7   r   r"   r   )
rF   rG   rH   r#   r\   r]   r7   r   r"   r   )ri   rG   r!   r   r"   rj   )ri   rG   r"   r   )ri   rG   r"   rp   )
ri   rG   rb   rp   rt   ru   r!   r   r"   r   )rC   r#   r"   r#   )*r   
__future__r   loggingcopyr   dataclassesr   r   typingr   r   r	   r
   	getLoggerr   r0   r'   r,   rU   re   r=   r`   API_REQUEST_MIDDLEWAREAPI_EXECUTION_MIDDLEWAREr   r   r   r)   r-   r5   rE   rY   r[   rc   rf   rh   r>   r<   r_   ra   rA   r   r   r    <module>r      sR     # " " " " "        ( ( ( ( ( ( ( ( , , , , , , , , , , , ,		8	$	$. 2 ( , & *  0 3  	      > > > > > > > >   
      &( ( ( (V8 8 8 8v< < < <   &   *G G G GC C C C       @ @ @ @>+ >+ >+ >+B     r   