
    `gj$'                       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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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Z%d%dZ&d&dZ'd'dZ(	 	 	 	 	 	 	 	 	 	 d(dZ)d)dZ*y)*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ListOptionalzhermes.observer.v1zhermes.middleware.v1tool_requesttool_executionllm_requestllm_executionzset[str]VALID_MIDDLEWAREc                  P    e Zd ZU dZded<   ded<   dZded<    ee      Zd	ed
<   y)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        H/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/middleware.pyr   r   %   s*    ELGT"'"=E=r    r   c                 2    | j                  dt               | S )Ntelemetry_schema_version)
setdefaultOBSERVER_SCHEMA_VERSIONkwargss    r!   observer_payloadr(   /   s    
02IJMr    c                 ^    | j                  dt               | j                  dt               | S )Nr#   middleware_schema_version)r$   r%   MIDDLEWARE_SCHEMA_VERSIONr&   s    r!   middleware_payloadr,   4   s+    
02IJ
13LMMr    c                    	 t        |       S # t        $ rB}t        j                  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_copyr4   :   sK       SUXYgt$= 	s&   
 	A0AAAAAc                ~   t        t              st        | | dg       S t        |       }t        |      }g }t	        t        f||d|D ]Z  }t        |t              s|j                  d      }t        |t              s6t        |      }|j                  t        |             \ t        ||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   requestoriginal_requestr8   )_has_middlewareLLM_REQUEST_MIDDLEWAREr   r4   _invoke_middlewarer1   r2   getappend_trace_entryr   )r8   contextr9   current_requestr   resultnext_requests          r!   apply_llm_request_middlewarerD   M   s     12&$	
 	
 "'* !12O"$E$) 	 + &$'zz),,-$\2\&)*+ #)U	 r    c                   t        t              st        ||dg       S t        |      }t        |      }g }t	        t        f| ||d|D ]Z  }t        |t              s|j                  d      }t        |t              s6t        |      }|j                  t        |             \ t        ||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.
    Fr6   	tool_nameargsoriginal_argsrH   )r:   TOOL_REQUEST_MIDDLEWAREr   r4   r<   r1   r2   r=   r>   r?   r   )rG   rH   r@   rI   current_argsr   rB   	next_argss           r!   apply_tool_request_middlewarerM   x   s     23&!	
 	
 t$Mm,L"$E$#	
  + &$'JJv&	)T*!),\&)*+ #&U	 r    c                    t        | fi |S )z7Compatibility wrapper for older ``api_request`` naming.)rD   )r8   r@   s     r!   apply_api_request_middlewarerO      s    
 (;7;;r    c                ~    t        t              }|s ||       S t        t        ||f| |j                  d|       d|S )zCRun provider execution through registered LLM execution middleware.r9   r7   )_get_middleware_callbacksLLM_EXECUTION_MIDDLEWARE_run_execution_chainpop)r8   	next_callr@   	callbackss       r!   run_llm_execution_middlewarerW      sV     **BCI!!   %7A  r    c           	         t        t              }|s ||      S t        t        ||f| ||j                  d|      d|S )z@Run tool execution through registered tool execution middleware.rI   rF   )rQ   TOOL_EXECUTION_MIDDLEWARErS   rT   )rG   rH   rU   r@   rV   s        r!   run_tool_execution_middlewarerZ      sW     **CDI! kk/48  r    c                    t        | |fi |S )z9Compatibility wrapper for older ``api_execution`` naming.)rW   )r8   rU   r@   s      r!   run_api_execution_middlewarer\      s     (FgFFr    c           	     2    ddl m}  || fi t        di |S )Nr   )invoke_middlewarer   )hermes_cli.pluginsr^   r,   )kindr'   r^   s      r!   r<   r<      s    4TB%7%A&%ABBr    c                    ddl m}  ||       S )Nr   )has_middleware)r_   rb   )r`   rb   s     r!   r:   r:      s    1$r    c                b    ddl m} t         |       j                  j	                  | g             S )Nr   )get_plugin_manager)r_   rd   r   _middlewarer=   )r`   rd   s     r!   rQ   rQ      s'    5"$0044T2>??r    c                n     dv rdnd G d dt               d fd d         S )Nr8   rH   c                        e Zd Zd fdZ xZS )7_run_execution_chain.<locals>._DownstreamExecutionErrorc                D    t         |   t        |             || _        y N)super__init__stroriginal)selfrn   	__class__s     r!   rl   z@_run_execution_chain.<locals>._DownstreamExecutionError.__init__   s    GS]+$DMr    )rn   BaseExceptionreturnNone)r   r   r   rl   __classcell__)rp   s   @r!   _DownstreamExecutionErrorrh      s    	% 	%r    ru   c                     t              k\  r       S     ddd dd	
 f	d}t        d	i }|<   ||d<   	  d	i |S # 	$ r}|j                  d }~wt        $ rN}t        j                  dt        dt                    |       rcY d }~S r  
 dz         cY d }~S d }~ww xY w)
NFc                   	 r&t        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.   )next_payloadr3   ru   call_atcallbackindexr`   next_callednext_resultnext_succeededr   s     r!   rU   z8_run_execution_chain.<locals>.call_at.<locals>.next_call  s     ""4&xT(^DE FUU 
 K>%eaiL<PVbc!%"" >/4#=>s   A 	A
	AArU   z&Middleware '%s' callback %s raised: %sr   rx   rj   )r|   r   rr   r   r   )lenr,   rn   r.   r/   warningrz   r{   )r   r   rU   call_kwargsr3   r~   r   r   r   ru   r}   rV   r`   r'   payload_keyterminal_calls   ``   @@@@r!   r}   z%_run_execution_chain.<locals>.call_at   s    C	N" ))U#	> 	>( )262#*K #,K 	/*k**( 	,, 	/NN8*d8n=	 ""519g..	/s6   A CA''C3/B<"C(B<6C<Cr   )r   intr   r   rr   r   )r.   )r`   rV   r   r'   ru   r}   r   s   ````@@@r!   rS   rS      s>      )F2)K%I %
// //b 1f[)**r    c                z    i }dD ],  }| j                  |      }t        |t              s%|s(|||<   . |sd|d<   |S )N)sourcereasonnamepluginr   )r=   r1   rm   )rB   entrykeyvalues       r!   r?   r?   1  sK    E+ 

3eS!eE#J "hLr    )r'   r   rr   Dict[str, Any])r   r   rr   r   )r8   r   r@   r   rr   r   )rG   rm   rH   r   r@   r   rr   r   )r8   r   rU   Callable[[Dict[str, Any]], Any]r@   r   rr   r   )
rG   rm   rH   r   rU   r   r@   r   rr   r   )r`   rm   r'   r   rr   z	List[Any])r`   rm   rr   r   )r`   rm   rr   List[Callable])
r`   rm   rV   r   r   zCallable[[Any], Any]r'   r   rr   r   )rB   r   rr   r   )+r   
__future__r   loggingcopyr   dataclassesr   r   typingr   r   r	   r
   r   	getLoggerr   r/   r%   r+   rJ   rY   r;   rR   API_REQUEST_MIDDLEWAREAPI_EXECUTION_MIDDLEWAREr   r   r   r(   r,   r4   rD   rM   rO   rW   rZ   r\   r<   r:   rQ   rS   r?   r   r    r!   <module>r      s   #   ( 6 6			8	$. 2 ( , & *  0 3  	 (  > > >
&((( (V**
* * 	*Z<<< <.  		&
 / 	
 	*GG.G G 		GC @>+
>+>+ (>+ 	>+
 	>+Br    