o
    iq                     @  s&  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	m
Z
 d dlmZ d dlmZ d dlmZ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mZ ddlmZmZ ddlm Z m!Z! ddlm"Z" ddl#m$Z$ erzddl%m&Z& e'e(dd Z)edZ*eG dd dZ+eG dd dZ,eG dd dZ-eG dd dZ.e+e,B e-B e.B Z/G dd dee* Z0G dd dZ1G dd  d Z2G d!d" d"Z3G d#d$ d$Z4G d%d& d&Z5G d'd( d(Z6G d)d* d*Z7ere8e9e& e8e:e	f f Z;ej<d+ d,Z=ed=d3d4Z>dd5d>d;d<Z?dS )?    )annotationsN)Callable	Generator)contextmanager)	dataclass)TYPE_CHECKINGAnyGenericLiteralTypeVaroverload)trace   )llm)function_toolutils)trace_typestracer)	NOT_GIVEN
NotGivenOr)is_given   )SpeechHandle)AgentLIVEKIT_EVALS_VERBOSERun_Tc                   @  "   e Zd ZU ded< dZded< dS )ChatMessageEventzllm.ChatMessageitemmessageLiteral['message']typeN__name__
__module____qualname____annotations__r!    r'   r'   a/var/www/html/livekit_bhavya/venv/lib/python3.10/site-packages/livekit/agents/voice/run_result.pyr   '      
 r   c                   @  r   )FunctionCallEventzllm.FunctionCallr   function_callLiteral['function_call']r!   Nr"   r'   r'   r'   r(   r*   -   r)   r*   c                   @  r   )FunctionCallOutputEventzllm.FunctionCallOutputr   function_call_outputLiteral['function_call_output']r!   Nr"   r'   r'   r'   r(   r-   3   r)   r-   c                   @  s2   e Zd ZU ded< ded< ded< dZded	< d
S )AgentHandoffEventllm.AgentHandoffr   Agent | None	old_agentr   	new_agentagent_handoffLiteral['agent_handoff']r!   Nr"   r'   r'   r'   r(   r0   9   s
   
 r0   c                   @  s   e Zd Zddd5d	d
Zed6ddZejd7ddZed8ddZ	d9ddZ
d:ddZd;d d!Zd<d#d$Zd=d'd(Zd=d)d*Zd>d,d-Zd?d.d/Zd@d3d4ZdS )A	RunResultN)
user_inputr8   
str | Noneoutput_typetype[Run_T] | NonereturnNonec                C  s8   t  | _tjd   | _|| _|| _g | _d | _d | _	d S N)
set_handlesasyncioFuture	_done_fut_user_input_output_type_recorded_items_final_output_RunResult__last_speech_handle)selfr8   r:   r'   r'   r(   __init__E   s   
zRunResult.__init__list[RunEvent]c                 C     | j S )z5List of all recorded events generated during the run.)rF   rI   r'   r'   r(   eventsP   s   zRunResult.events	RunAssertc                 C  s4   t rdt| j}td| j d| d t| S )z
        Provides an assertion helper for verifying the run events.

        Returns:
            RunAssert: Assertion interface for run events.
        z
    z
+ RunResult(
   user_input=`z`
   events:
    z
))lk_evals_verbosejoin_format_eventsrN   printrD   rO   )rI   
events_strr'   r'   r(   expectU   s   	zRunResult.expectr   c                 C  s&   | j  s	td| jstd| jS )z
        Returns the final output of the run after completion.

        Raises:
            RuntimeError: If the run is not complete or no output is set.

        Returns:
            Run_T: The final result output.
        z3cannot retrieve final_output, RunResult is not donezno final output)rC   doneRuntimeErrorrG   rM   r'   r'   r(   final_outputi   s
   
zRunResult.final_outputboolc                 C  s
   | j  S )z=Indicates whether the run has finished processing all events.)rC   rV   rM   r'   r'   r(   rV   |   s   
zRunResult.done'Generator[None, None, RunResult[Run_T]]c                   s   d fdd}|   S )Nr<   RunResult[Run_T]c                     s   t  jI d H   S r>   )rA   shieldrC   r'   rM   r'   r(   _await_impl   s   z(RunResult.__await__.<locals>._await_impl)r<   r[   )	__await__)rI   r]   r'   rM   r(   r^      s   
zRunResult.__await__r   r1   r3   r2   r4   r   c                C  s0   t |||d}| j|jjd}| j|| d S )N)r   r3   r4   
created_at)r0   _find_insertion_indexr   r`   rF   insert)rI   r   r3   r4   eventindexr'   r'   r(   _agent_handoff   s   zRunResult._agent_handoffllm.ChatItemc                 C  s   | j  rd S d }|jdkrt|d}n|jdkrt|d}n
|jdkr)t|d}|d ur>| j|jjd}| j	
|| d S d S )Nr   )r   r+   r.   r_   )rC   rV   r!   r   r*   r-   ra   r   r`   rF   rb   )rI   r   rc   rd   r'   r'   r(   _item_added   s   




zRunResult._item_addedhandleSpeechHandle | asyncio.Taskc                 C  s2   | j | t|tr|| j || j d S r>   )r@   add
isinstancer   _add_item_added_callbackrg   add_done_callback_mark_done_if_neededrI   rh   r'   r'   r(   _watch_handle   s   
zRunResult._watch_handlec                 C  s6   | j | || j t|tr|| j d S d S r>   )r@   discardremove_done_callbackrn   rk   r   _remove_item_added_callbackrg   ro   r'   r'   r(   _unwatch_handle   s
   
zRunResult._unwatch_handle"SpeechHandle | asyncio.Task | Nonec                 C  s4   t |tr|| _tdd | jD r|   d S d S )Nc                 s  s    | ]}|  V  qd S r>   )rV   ).0rh   r'   r'   r(   	<genexpr>   s    z1RunResult._mark_done_if_needed.<locals>.<genexpr>)rk   r   rH   allr@   
_mark_donero   r'   r'   r(   rn      s
   
zRunResult._mark_done_if_neededc              	   C  s   t tjd | jd u r| jd  	 W d    d S | jj}t|t	sL| j
rBt|| j
sB| jtd| j
j dt| jj  n || _| jd  n| j| W d    d S W d    d S W d    d S 1 smw   Y  d S )NzExpected output of type , got )
contextlibsuppressrA   InvalidStateErrorrH   rC   
set_result_maybe_run_final_outputrk   BaseExceptionrE   set_exceptionrW   r#   r!   rG   )rI   rX   r'   r'   r(   ry      s.   


"zRunResult._mark_doner`   floatintc                C  s:   t tt| jD ]}| j| jj|kr|d   S q	dS )z
        Returns the index to insert an item by creation time.

        Iterates in reverse, assuming items are sorted by `created_at`.
        Finds the position after the last item with `created_at <=` the given timestamp.
        r   r   )reversedrangelenrF   r   r`   )rI   r`   ir'   r'   r(   ra      s
   zRunResult._find_insertion_index)r8   r9   r:   r;   r<   r=   )r<   rK   )r<   rO   )r<   r   )r<   rY   )r<   rZ   )r   r1   r3   r2   r4   r   r<   r=   )r   rf   r<   r=   )rh   ri   r<   r=   )rh   ru   r<   r=   r<   r=   )r`   r   r<   r   )r#   r$   r%   rJ   propertyrN   	functoolscached_propertyrU   rX   rV   r^   re   rg   rp   rt   rn   ry   ra   r'   r'   r'   r(   r7   D   s"    







r7   c                   @  sv  e Zd ZdYddZedZd	d
Zed[dd
Zd\dd
Zd]ddZd^d_ddZeddd`ddZedad"dZedbd%dZedcd(dZeddd+dZddded.dZee	d/dfd3d4Z
ee	e	d5dgd;d4Z
ee	e	d<dhdAd4Z
ee	dBdidFd4Z
e	e	e	e	e	e	dGdjdJd4Z
dkdldMdNZdmdOdPZe	e	d5dndQdRZe	d/dodSdTZe	e	d<dpdUdVZe	dBdqdWdXZdS )rrO   
run_resultr7   c                 C  s   |j | _d| _d S )Nr   )rN   _events_list_current_index)rI   r   r'   r'   r(   rJ      s   
zRunAssert.__init__rd   r   r<   EventAssertc                 C     d S r>   r'   )rI   rd   r'   r'   r(   __getitem__      zRunAssert.__getitem__ssliceEventRangeAssertc                 C  r   r>   r'   )rI   r   r'   r'   r(   r      r   key[int, slice]EventAssert | EventRangeAssertc                 C  s   t |tr| j| }t|| |S t |trH|dk r |t| j7 }d|  kr-t| jk s?n | jd| dt| j d|d t| j| | |S tt	| j
 dt	|j
 )a,  
        Access a specific event or range for assertions.

        Args:
            key (int | slice): Index or slice of events.

        Returns:
            EventAssert: Assertion for a single event when key is int.
            EventRangeAssert: Assertion for a span of events when key is slice.

        Raises:
            TypeError: If key is not an int or slice.
            AssertionError: If index is out of range.

        Examples:
            # Single event access
            >>> result.expect[0].is_message(role="user")
            >>> result.expect[-1].is_message(role="assistant")

            # Full range access
            >>> result.expect[:].contains_function_call(name="foo")

            # Partial range access
            >>> result.expect[0:2].contains_message(role="assistant")
        r   znth(z) out of range (total events: )rd   z# indices must be int or slice, not )rk   r   r   r   r   r   _raise_with_debug_infor   	TypeErrorr!   r#   )rI   r   rN   r'   r'   r(   r      s   


c                 C  s,   d}| j t| jkr| d | | j  }|S )NTz&Expected another event, but none left.)r   r   r   r   rI   __tracebackhide__rc   r'   r'   r(   _current_event  s
   

zRunAssert._current_eventNr   str
int | Noner=   c                 C  s<   d}|d u r	| j n|}dt| j|d}t| d| )NT
selected_indexz
Context around failure:
)r   rQ   rR   r   AssertionError)rI   r   rd   r   marker_indexrT   r'   r'   r(   r     s   z RunAssert._raise_with_debug_info)r!   r!   c                C  r   r>   r'   rI   r!   r'   r'   r(   
next_event  r   zRunAssert.next_eventr    ChatMessageAssertc                C  r   r>   r'   r   r'   r'   r(   r      r   r,   FunctionCallAssertc                C  r   r>   r'   r   r'   r'   r(   r   #  r   r/   FunctionCallOutputAssertc                C  r   r>   r'   r   r'   r'   r(   r   &  r   r6   AgentHandoffAssertc                C  r   r>   r'   r   r'   r'   r(   r   )  r   SLiteral['message', 'function_call', 'function_call_output', 'agent_handoff'] | NonedEventAssert | ChatMessageAssert | FunctionCallAssert | FunctionCallOutputAssert | AgentHandoffAssertc                C  sz   d}	 |   }|  jd7  _|du s| j|krnq|dkr#| S |dkr+| S |dkr3| S |dkr;| S |S )a]  
        Advance to the next event, optionally filtering by type.

        Args:
            type (str, optional): Event type to match.

        Returns:
            EventAssert or subclass: Assertion object for the matched event.

        Example:
            >>> result.expect.next_event(type="function_call").is_function_call(name="foo")
        Tr   Nr   r+   r.   r5   )r   r   rc   r!   
is_messageis_function_callis_function_call_outputis_agent_handoff)rI   r!   r   	ev_assertr'   r'   r(   r   ,  s    roler   NotGivenOr[llm.ChatRole]ChatMessageAssert | Nonec                C  r   r>   r'   )rI   r!   r   r'   r'   r(   skip_next_event_ifX     zRunAssert.skip_next_event_ifname	argumentsr   NotGivenOr[str]r   NotGivenOr[dict[str, Any]]FunctionCallAssert | Nonec                C  r   r>   r'   )rI   r!   r   r   r'   r'   r(   r   ]     outputis_errorr   r   NotGivenOr[bool]FunctionCallOutputAssert | Nonec                C  r   r>   r'   )rI   r!   r   r   r'   r'   r(   r   f  r   new_agent_typer   NotGivenOr[type[Agent]]AgentHandoffAssert | Nonec                C  r   r>   r'   )rI   r!   r   r'   r'   r(   r   o  r   )r   r   r   r   r   r   LLiteral['message', 'function_call', 'function_call_output', 'agent_handoff']]ChatMessageAssert | AgentHandoffAssert | FunctionCallAssert | FunctionCallOutputAssert | Nonec          
      C  s   d}zAd}	|dkr|   j|d}	n(|dkr |   j||d}	n|dkr.|   j||d}	n|d	kr:|   j|d
}	|  jd7  _|	W S  tyM   Y dS w )a  
        Conditionally skip the next event if it matches criteria.

        Args:
            type (str): Type of event to check.
            role (ChatRole, optional): Required role for message events.
            name (str, optional): Required function name for calls.
            arguments (dict, optional): Required args for function calls.
            output (str, optional): Required output for function call outputs.
            is_error (bool, optional): Required error flag for call outputs.
            new_agent_type (type, optional): Required agent class for handoffs.

        Returns:
            EventAssert or None: The skipped event assertion if matched.

        Example:
            >>> skipped = result.expect.skip_next_event_if(type="message", role="assistant")
        TNr   r   r+   r   r.   r   r5   r   r   )r   r   r   r   r   r   r   rW   )
rI   r!   r   r   r   r   r   r   r   evr'   r'   r(   r   t  s"   #r   countc                 C  sL   d}t |D ]}| jt| jkr| d| d| d |  jd7  _q| S )a  
        Skip a specified number of upcoming events without assertions.

        Args:
            count (int): Number of events to skip.

        Returns:
            RunAssert: Self for chaining.

        Example:
            >>> result.expect.skip_next(2)
        TzTried to skip z event(s), but only z were available.r   )r   r   r   r   r   )rI   r   r   r   r'   r'   r(   	skip_next  s   zRunAssert.skip_nextc                 C  s>   d}| j t| jk r| j| j  }| dt|j  dS dS )z
        Assert that there are no further events.

        Raises:
            AssertionError: If unexpected events remain.

        Example:
            >>> result.expect.no_more_events()
        Tz$Expected no more events, but found: N)r   r   r   r   r!   r#   r   r'   r'   r(   no_more_events  s   
zRunAssert.no_more_eventsc                C     d}| dd j ||dS )ay  
        Assert existence of a function call event matching criteria.

        Args:
            name (str, optional): Function name to match.
            arguments (dict, optional): Arguments to match.

        Returns:
            FunctionCallAssert: Assertion for the matching call.

        Example:
            >>> result.expect.contains_function_call(name="foo")
        TNr   )contains_function_call)rI   r   r   r   r'   r'   r(   r        z RunAssert.contains_function_callc                C     d}| dd j |dS )a0  
        Assert existence of a message event matching criteria.

        Args:
            role (ChatRole, optional): Role to match.

        Returns:
            ChatMessageAssert: Assertion for the matching message.

        Example:
            >>> result.expect.contains_message(role="user")
        TNr   )contains_messagerI   r   r   r'   r'   r(   r     s   zRunAssert.contains_messagec                C  r   )a  
        Assert existence of a function call output event matching criteria.

        Args:
            output (str, optional): Output string to match.
            is_error (bool, optional): Error flag to match.

        Returns:
            FunctionCallOutputAssert: Assertion for the matching output.

        Example:
            >>> result.expect.contains_function_call_output(is_error=True)
        TNr   )contains_function_call_outputrI   r   r   r   r'   r'   r(   r     r   z'RunAssert.contains_function_call_outputc                C  r   )aZ  
        Assert existence of an agent handoff event matching criteria.

        Args:
            new_agent_type (type, optional): Expected new agent class.

        Returns:
            AgentHandoffAssert: Assertion for the matching handoff.

        Example:
            >>> result.expect.contains_agent_handoff(new_agent_type=MyAgent)
        TNr   )contains_agent_handoffrI   r   r   r'   r'   r(   r     s   z RunAssert.contains_agent_handoff)r   r7   )rd   r   r<   r   )r   r   r<   r   )r   r   r<   r   )r<   r   r>   )r   r   rd   r   r<   r=   )r!   r=   r<   r   )r!   r    r<   r   )r!   r,   r<   r   )r!   r/   r<   r   )r!   r6   r<   r   )r!   r   r<   r   )r!   r    r   r   r<   r   )r!   r,   r   r   r   r   r<   r   )r!   r/   r   r   r   r   r<   r   )r!   r6   r   r   r<   r   )r!   r   r   r   r   r   r   r   r   r   r   r   r   r   r<   r   )r   )r   r   r<   rO   r   r   r   r   r   r<   r   r   r   r<   r   r   r   r   r   r<   r   r   r   r<   r   )r#   r$   r%   rJ   r   r   r   r   r   r   r   r   r   r   r   r   r   r'   r'   r'   r(   rO      sl    


,	,<
rO   c                   @  sp   e Zd Zd.d/dd	Zd0ddZd1ddZeedd2ddZeedd3dd Zed!d4d%d&Z	ed'd5d+d,Z
d-S )6r   rc   RunEventparentrO   rd   r   c                 C     || _ || _|| _d S r>   _event_parent_indexrI   rc   r   rd   r'   r'   r(   rJ   .     
zEventAssert.__init__r   r   r<   r=   c                 C     d}| j j|| jd d S NTr   r   r   r   rI   r   r   r'   r'   r(   _raise3     zEventAssert._raisec                 C  rL   r>   r   rM   r'   r'   r(   rc   7     zEventAssert.eventr   r   r   r   r   r   c                C  s   d}t | jts| d t | jtsJ t|r/| jjj|kr/| d| d| jjj d t|r_t| jjj	}|
 D ]\}}||vsM|| |kr^| d| d| d||  q?t| j| j| jS )	a  
        Verify this event is a function call with matching details.

        Args:
            name (str, optional): Expected function name.
            arguments (dict, optional): Expected call arguments.

        Returns:
            FunctionCallAssert: Assertion for the function call.

        Raises:
            AssertionError: If the event is not a function call or details mismatch.

        Example:
            >>> ev_assert.is_function_call(name="foo", arguments={"x": 1})
        TzExpected FunctionCallEventzExpected call name '', got ''z	For key 'z', expected rz   )rk   r   r*   r   r   r   r   jsonloadsr   itemsgetr   r   r   )rI   r   r   r   actualr   valuer'   r'   r(   r   :  s   
"zEventAssert.is_function_callr   r   r   r   r   c                C  s   d}t | jts| d t | jtsJ t|r/| jjj|kr/| d| d| jjj d t|rH| jjj|krH| d| d| jjj  t| j| j	| j
S )a  
        Verify this event is a function call output with matching details.

        Args:
            output (str, optional): Expected output text.
            is_error (bool, optional): Expected error flag.

        Returns:
            FunctionCallOutputAssert: Assertion for the output.

        Raises:
            AssertionError: If the event is not function output or details mismatch.

        Example:
            >>> ev_assert.is_function_call_output(output="OK", is_error=False)
        Tz Expected FunctionCallOutputEventzExpected output 'r   r   zExpected is_error=rz   )rk   r   r-   r   r   r   r   r   r   r   r   r   r'   r'   r(   r   a  s   
z#EventAssert.is_function_call_outputr   r   r   r   c                C  sp   d}t | jts| d t | jtsJ t|r/| jjj|kr/| d| d| jjj d t| j| j| j	S )a  
        Verify this event is a message from the given role.

        Args:
            role (ChatRole, optional): Expected sender role.

        Returns:
            ChatMessageAssert: Assertion for the message.

        Raises:
            AssertionError: If the event is not a message or role mismatch.

        Example:
            >>> ev_assert.is_message(role="assistant")
        TzExpected ChatMessageEventzExpected role 'r   r   )
rk   r   r   r   r   r   r   r   r   r   r   r'   r'   r(   r     s   
zEventAssert.is_messager   r   r   r   c                C  sv   d}t | jts| d t | jtsJ t|r2t | jj|s2| d|j dt| jjj d t| j| j	| j
S )a  
        Verify this event is an agent handoff.

        Args:
            new_agent_type (type, optional): Expected new agent class.

        Returns:
            AgentHandoffAssert: Assertion for the handoff.

        Raises:
            AssertionError: If the event is not an agent handoff or type mismatch.

        Example:
            >>> ev_assert.is_agent_handoff(new_agent_type=MyAgent)
        TzExpected AgentHandoffEventzExpected new_agent 'r   r   )rk   r   r0   r   r   r4   r#   r!   r   r   r   r   r'   r'   r(   r     s   
zEventAssert.is_agent_handoffN)r   )rc   r   r   rO   rd   r   r   r   r<   r=   )r<   r   r   r   r   r   )r#   r$   r%   rJ   r   rc   r   r   r   r   r   r'   r'   r'   r(   r   -  s    

( r   c                   @  sZ   e Zd Zd&ddZeed	d'ddZedd(ddZeedd)ddZedd*d#d$Zd%S )+r   rN   rK   r   rO   rngr   c                 C  r   r>   )_eventsr   _rng)rI   rN   r   r   r'   r'   r(   rJ     r   zEventRangeAssert.__init__r   r   r   r   r   r<   r   c             	   C     d}t | jD ]/\}}t|| j| jjpd| }tt |j	||dW  d     S 1 s1w   Y  q| j
d| j td)a  
        Assert that a function call matching criteria exists in the event range.

        Args:
            name (str, optional): Expected function name.
            arguments (dict, optional): Expected call arguments.

        Returns:
            FunctionCallAssert: Assertion for the matched function call.

        Raises:
            AssertionError: If no matching function call is found in range.

        Example:
            >>> result.expect[0:3].contains_function_call(name="foo")
        Tr   r   Nz8No FunctionCallEvent satisfying criteria found in range unreachable)	enumerater   r   r   r   startr{   r|   r   r   r   rW   )rI   r   r   r   idxr   	candidater'   r'   r(   r        &
z'EventRangeAssert.contains_function_callr   r   r   r   c             	   C     d}t | jD ].\}}t|| j| jjpd| }tt |j	|dW  d     S 1 s0w   Y  q| j
d| j td)a  
        Assert that a message matching criteria exists in the event range.

        Args:
            role (ChatRole, optional): Expected sender role.

        Returns:
            ChatMessageAssert: Assertion for the matched message.

        Raises:
            AssertionError: If no matching message is found in range.

        Example:
            >>> result.expect[:2].contains_message(role="assistant")
        Tr   r   Nz5No ChatMessageEvent matching criteria found in range r   )r   r   r   r   r   r   r{   r|   r   r   r   rW   )rI   r   r   r   r   r  r'   r'   r(   r     s   
&
z!EventRangeAssert.contains_messager   r   r   r   r   c             	   C  r   )a  
        Assert that a function call output matching criteria exists in the event range.

        Args:
            output (str, optional): Expected output text.
            is_error (bool, optional): Expected error flag.

        Returns:
            FunctionCallOutputAssert: Assertion for the matched output.

        Raises:
            AssertionError: If no matching output is found in range.

        Example:
            >>> result.expect[1:4].contains_function_call_output(is_error=True)
        Tr   r   Nz<No FunctionCallOutputEvent matching criteria found in range r   )r   r   r   r   r   r   r{   r|   r   r   r   rW   )rI   r   r   r   r   r   r  r'   r'   r(   r     r  z.EventRangeAssert.contains_function_call_outputr   r   r   r   c             	   C  r  )a  
        Assert that an agent handoff matching criteria exists in the event range.

        Args:
            new_agent_type (type, optional): Expected new agent class.

        Returns:
            AgentHandoffAssert: Assertion for the matched handoff.

        Raises:
            AssertionError: If no matching handoff is found in range.

        Example:
            >>> result.expect[0:3].contains_agent_handoff(new_agent_type=MyAgent)
        Tr   r   Nz6No AgentHandoffEvent matching criteria found in range r   )r   r   r   r   r   r   r{   r|   r   r   r   rW   )rI   r   r   r   r   r  r'   r'   r(   r   &  s   
&
z'EventRangeAssert.contains_agent_handoffN)rN   rK   r   rO   r   r   r   r   r   r   )	r#   r$   r%   rJ   r   r   r   r   r   r'   r'   r'   r(   r     s    
%##r   c                   @  s>   e Zd ZdddZdddZdddZeddddZdS )r   rc   r   r   rO   rd   r   c                 C  r   r>   r   r   r'   r'   r(   rJ   F  r   zChatMessageAssert.__init__r   r   r<   r=   c                 C  r   r   r   r   r'   r'   r(   r   K  r   zChatMessageAssert._raisec                 C  rL   r>   r   rM   r'   r'   r(   rc   O  r   zChatMessageAssert.eventjudge_evaluationllm_vllm.LLMintentc                  sN  d}t  }| jjj}|tjd |tj j	 |tj
d |tjt||d |s:| d td|sE| d tdtd.dd}t }|jddd |jdd| d| d d}d}	i }
dg}t fdd|D s|d|
d<  j||gdddid|
d 2 z3 dH W }|jdur|j}	|jsq|jjr|jjd! }|j}q6 |s| d" t|tsJ tj||d#\}}||i |I dH \}}|tj|  |tj| |	r| tj!|	j"tj#|	j$tj%|	j"tj&|	j$tj'|	j(i |s| d$|  | S t)r%d!d%l*m+} ||,d&d'd(d)d*}t-d+| d,| d- | S )/a  
        Evaluate whether the message fulfills the given intent.

        Args:
            llm_v (llm.LLM): LLM instance for judgment.
            intent (str): Description of the expected intent.

        Returns:
            ChatMessageAssert: Self for chaining further assertions.

        Example:
            >>> await msg_assert.judge(llm, intent="should ask for size")
        Tjudger  )r  r   zThe chat message is empty.r   z(Intent is required to judge the message.successrY   reasonr   r<   tuple[bool, str]c                   s
   | |fS )z
            Determines whether the message correctly fulfills the given intent.

            Args:
                success: Whether the message satisfies the intent.
                reason: A concise explanation justifying the result.
            r'   )r	  r
  r'   r'   r(   check_intentv  s   	z-ChatMessageAssert.judge.<locals>.check_intentsysteman  You are a test evaluator for conversational agents.
You will be shown a message and a target intent. Determine whether the message accomplishes the intent.
Only respond by calling the `check_intent(success: bool, reason: str)` function with your final judgment.
Be strict: if the message does not clearly fulfill the intent, return `success = False` and explain why.)r   contentuserzCCheck if the following message fulfills the given intent.

Intent:
z

Message:
Nzgpt-5c                 3  s    | ]}| j v V  qd S r>   )model)rv   excluded_modelr  r'   r(   rw     s    z*ChatMessageAssert.judge.<locals>.<genexpr>g        temperaturefunctionr   r  )r!   r  )chat_ctxtoolstool_choiceextra_kwargsr   z0LLM did not return any arguments for evaluation.)fncjson_argumentszJudgement failed: )shortenr   z\n   z...)widthplaceholderz- Judgment succeeded for `z`: ``)r	  rY   r
  r   r<   r  ).r   get_current_spanr   r   text_contentset_attributer   ATTR_GEN_AI_OPERATION_NAMEATTR_GEN_AI_REQUEST_MODELr  ATTR_FUNCTION_TOOL_NAMEATTR_FUNCTION_TOOL_ARGSr   dumpsr   rW   r   r   ChatContextadd_messageanychatusagedelta
tool_callsr   rk   r   	llm_utilsprepare_function_argumentsATTR_FUNCTION_TOOL_IS_ERRORATTR_FUNCTION_TOOL_OUTPUTset_attributesATTR_GEN_AI_USAGE_INPUT_TOKENSprompt_tokensATTR_GEN_AI_USAGE_OUTPUT_TOKENScompletion_tokens#ATTR_GEN_AI_USAGE_INPUT_TEXT_TOKENS$ATTR_GEN_AI_USAGE_OUTPUT_TEXT_TOKENS%ATTR_GEN_AI_USAGE_INPUT_CACHED_TOKENSprompt_cached_tokensrP   textwrapr  replacerS   )rI   r  r  r   current_spanmsg_contentr  r  r   r,  r  excluded_models_temperaturechunktoolfnc_args
fnc_kwargsr	  r
  r  	print_msgr'   r  r(   r  R  s   



		



zChatMessageAssert.judgeN)rc   r   r   rO   rd   r   r   )r<   r   )r  r  r  r   r<   r   )	r#   r$   r%   rJ   r   rc   r   start_as_current_spanr  r'   r'   r'   r(   r   E  s    


r   c                   @      e Zd ZdddZdd
dZdS )r   rc   r*   r   rO   rd   r   c                 C  r   r>   r   r   r'   r'   r(   rJ     r   zFunctionCallAssert.__init__r<   c                 C  rL   r>   r   rM   r'   r'   r(   rc     r   zFunctionCallAssert.eventN)rc   r*   r   rO   rd   r   )r<   r*   r#   r$   r%   rJ   rc   r'   r'   r'   r(   r         
r   c                   @  rG  )r   rc   r-   r   rO   rd   r   c                 C  r   r>   r   r   r'   r'   r(   rJ     r   z!FunctionCallOutputAssert.__init__r<   c                 C  rL   r>   r   rM   r'   r'   r(   rc     r   zFunctionCallOutputAssert.eventN)rc   r-   r   rO   rd   r   )r<   r-   rH  r'   r'   r'   r(   r     rI  r   c                   @  rG  )r   rc   r0   r   rO   rd   r   c                 C  r   r>   r   r   r'   r'   r(   rJ     r   zAgentHandoffAssert.__init__r<   c                 C  rL   r>   r   rM   r'   r'   r(   rc     r   zAgentHandoffAssert.eventN)rc   r0   r   rO   rd   r   )r<   r0   rH  r'   r'   r'   r(   r     rI  r   	MockToolsagents_mock_toolsagenttype[Agent]mocksdict[str, Callable]r<   Generator[None, None, None]c              	   c  sJ    t i }i || |i}t |}zdV  W t | dS t | w )a   
    Temporarily assign a set of mock tool callables to a specific Agent type within the current context.

    Usage:
        with mock_tools(MyAgentClass, {"tool_name": mock_fn}):
            # inside this block, MyAgentClass will see the given mocks
    N)_MockToolsContextVarr   r?   reset)rL  rN  currentupdatedtokenr'   r'   r(   
mock_tools  s   
	
rV  r   rN   rK   r   r   	list[str]c             	   C  s   g }t | D ][\}}d}|d ur||krdnd}t|tttfr<|jjddh dd}| d| d|jj d	| d
}n t|t	rR| d| d|j
 d|j d
}n
| d| d| }|| q|S )N z>>>z   T>   idr!   call_idr`   )exclude_noneexclude_defaultsexcludez [z] z(item=r   z] AgentHandoffEvent(old_agent=z, new_agent=)r   rk   r   r*   r-   r   
model_dump	__class__r#   r0   r3   r4   append)rN   r   linesr   rc   prefix	item_reprliner'   r'   r(   rR     s,   "
rR   )rL  rM  rN  rO  r<   rP  )rN   rK   r   r   r<   rW  )@
__future__r   rA   r{   contextvarsr   r   oscollections.abcr   r   r   dataclassesr   typingr   r   r	   r
   r   r   opentelemetryr   rX  r   r   r   r/  	telemetryr   r   typesr   r   r   speech_handler   rL  r   r   getenvrP   r   r   r*   r-   r0   r   r7   rO   r   r   r   r   r   r   dictr!   r   rJ  
ContextVarrQ  rV  rR   r'   r'   r'   r(   <module>   sf     	   X  
 

