o
    hHP                  	   @   s  d dl Z d dlmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
mZmZm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 d dlmZmZmZ d dlmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. ede"e-Z/ede#e.Z0ede!e,Z1ede"e-Z2ededZ3ede!e,Z4e5e6B Z7G dd deZ8G dd dee2e0f Z9G dd dee/e1e0e2e4f Z:dS )    N)Callable)AsyncExitStack)	timedelta)TracebackType)AnyGenericProtocolTypeVar)MemoryObjectReceiveStreamMemoryObjectSendStream)	BaseModel)Self)McpError)MessageMetadataServerMessageMetadataSessionMessage)CONNECTION_CLOSEDINVALID_PARAMSCancelledNotificationClientNotificationClientRequestClientResult	ErrorDataJSONRPCErrorJSONRPCMessageJSONRPCNotificationJSONRPCRequestJSONRPCResponseProgressNotificationRequestParamsServerNotificationServerRequestServerResultSendRequestTSendResultTSendNotificationTReceiveRequestTReceiveResultT)boundReceiveNotificationTc                   @   s2   e Zd ZdZdededB dedB ddfddZdS )	ProgressFnTz-Protocol for progress notification callbacks.progresstotalNmessagereturnc                    s   d S N )selfr+   r,   r-   r0   r0   S/var/www/html/openai_agents/venv/lib/python3.10/site-packages/mcp/shared/session.py__call__1   s    zProgressFnT.__call__)__name__
__module____qualname____doc__floatstrr3   r0   r0   r0   r2   r*   .   s    &r*   c                   @   s   e Zd ZdZ	ddedejdB deddded	ge	f d
e
ddfddZdddZdee dB dedB dedB ddfddZdeeB ddfddZd ddZedefddZedefddZdS )!RequestRespondera  Handles responding to MCP requests and manages request lifecycle.

    This class MUST be used as a context manager to ensure proper cleanup and
    cancellation handling:

    Example:
        with request_responder as resp:
            await resp.respond(result)

    The context manager ensures:
    1. Proper cancellation scope setup and cleanup
    2. Request completion tracking
    3. Cleanup of in-flight requests
    N
request_idrequest_metarequestsessionzBaseSession[
            SendRequestT,
            SendNotificationT,
            SendResultT,
            ReceiveRequestT,
            ReceiveNotificationT
        ]on_complete.RequestResponder[ReceiveRequestT, SendResultT]message_metadatar.   c                 C   s>   || _ || _|| _|| _|| _d| _t | _|| _	d| _
d S )NF)r;   r<   r=   rA   _session
_completedanyioCancelScope_cancel_scope_on_complete_entered)r1   r;   r<   r=   r>   r?   rA   r0   r0   r2   __init__D   s   

zRequestResponder.__init__c                 C   s   d| _ t | _| j  | S )zBEnter the context manager, enabling request cancellation tracking.T)rH   rD   rE   rF   	__enter__r1   r0   r0   r2   rJ   ]   s   

zRequestResponder.__enter__exc_typeexc_valexc_tbc                 C   sb   z| j r	| |  W d| _| jstd| j||| dS d| _| js(td| j||| w )zFExit the context manager, performing cleanup and notifying completion.FNo active cancel scopeN)rC   rG   rH   rF   RuntimeError__exit__r1   rL   rM   rN   r0   r0   r2   rQ   d   s   
zRequestResponder.__exit__responsec                    sJ   | j std| jrJ d| js#d| _| jj| j|dI dH  dS dS )zSend a response for this request.

        Must be called within a context manager block.
        Raises:
            RuntimeError: If not used within a context manager
            AssertionError: If request was already responded to
        2RequestResponder must be used as a context managerzRequest already responded toTr;   rS   N)rH   rP   rC   	cancelledrB   _send_responser;   )r1   rS   r0   r0   r2   respondt   s   zRequestResponder.respondc                    sT   | j std| jstd| j  d| _| jj| jtdddddI dH  dS )	z-Cancel this request and mark it as completed.rT   rO   Tr   zRequest cancelledNcoder-   datarU   )	rH   rP   rF   cancelrC   rB   rW   r;   r   rK   r0   r0   r2   r\      s   
zRequestResponder.cancelc                 C   s   | j  o| j S r/   )rC   rV   rK   r0   r0   r2   	in_flight   s   zRequestResponder.in_flightc                 C   s   | j jS r/   )rF   cancel_calledrK   r0   r0   r2   rV      s   zRequestResponder.cancelledr/   )r.   r@   r.   N)r4   r5   r6   r7   	RequestIdr   Metar&   r   r   r   rI   rJ   typeBaseExceptionr   rQ   r$   r   rX   r\   propertyboolr]   rV   r0   r0   r0   r2   r:   4   sD    




r:   c                   @   s  e Zd ZU dZeeeeeB  f e	d< e
e	d< eeeeef f e	d< eeef e	d< 	d5deeeB  dee d	ee d
ee dedB ddfddZdefddZdee dB dedB dedB dedB fddZ			d6dedee dedB dededB defddZ	d5de dedB ddfdd Z!d!ed"ee"B ddfd#d$Z#d7d%d&Z$d'eeef ddfd(d)Z%deddfd*d+Z&		d8d,e'e
B d-e(d.e(dB d/e'dB ddf
d0d1Z)d2eeef eB eB ddfd3d4Z*dS )9BaseSessiona  
    Implements an MCP "session" on top of read/write streams, including features
    like request/response linking, notifications, and progress.

    This class is an async context manager that automatically starts processing
    messages when entered.
    _response_streams_request_id
_in_flight_progress_callbacksNread_streamwrite_streamreceive_request_typereceive_notification_typeread_timeout_secondsr.   c                 C   sB   || _ || _i | _d| _|| _|| _|| _i | _i | _t	 | _
d S )Nr   )_read_stream_write_streamrg   rh   _receive_request_type_receive_notification_type_session_read_timeout_secondsri   rj   r   _exit_stack)r1   rk   rl   rm   rn   ro   r0   r0   r2   rI      s   	zBaseSession.__init__c                    s.   t  | _| j I d H  | j| j | S r/   )rD   create_task_group_task_group
__aenter__
start_soon_receive_looprK   r0   r0   r2   rx      s
   
zBaseSession.__aenter__rL   rM   rN   c                    s4   | j  I d H  | jj  | j|||I d H S r/   )ru   acloserw   cancel_scoper\   	__aexit__rR   r0   r0   r2   r}      s   zBaseSession.__aexit__r=   result_typerequest_read_timeout_secondsmetadataprogress_callbackc                    s  | j }|d | _ tjttB  d\}}|| j|< |jdddd}	|durFd|	vr-i |	d< d|	d vr9i |	d d< ||	d d d< || j|< ztdd	|d
|	}
| j	
tt|
|dI dH  d}|durk| }n
| jduru| j }zt| | I dH }W d   n1 sw   Y  W n ty   tttjjd|jj d| ddw t|trt|j||jW | j|d | j|d | I dH  | I dH  S | j|d | j|d | I dH  | I dH  w )a>  
        Sends a request and wait for a response. Raises an McpError if the
        response contains an error. If a request read timeout is provided, it
        will take precedence over the session read timeout.

        Do not use this method to emit notifications! Use send_notification()
        instead.
           Tjsonby_aliasmodeexclude_noneNparams_metaprogressToken2.0)jsonrpcidr-   r   z(Timed out while waiting for response to z	. Waited z	 seconds.rZ   r-   r0   )rh   rD   create_memory_object_streamr   r   rg   
model_dumprj   r   rq   sendr   r   total_secondsrt   
fail_afterreceiveTimeoutErrorr   r   httpxcodesREQUEST_TIMEOUT	__class__r4   
isinstanceerrormodel_validateresultpopr{   )r1   r=   r~   r   r   r   r;   response_streamresponse_stream_readerrequest_datajsonrpc_requesttimeoutresponse_or_errorr0   r0   r2   send_request   sl   







zBaseSession.send_requestnotificationrelated_request_idc                    sT   t d	ddi|jdddd}tt||rt|dndd}| j|I dH  dS )
zk
        Emits a notification, which is a one-way message that does not expect
        a response.
        r   r   Tr   r   )r   Nr   r0   )r   r   r   r   r   rq   r   )r1   r   r   jsonrpc_notificationsession_messager0   r0   r2   send_notification(  s   zBaseSession.send_notificationr;   rS   c                    s|   t |trtd||d}tt|d}| j|I d H  d S td||jddddd}tt|d}| j|I d H  d S )Nr   r   r   r   r-   Tr   r   )r   r   r   )	r   r   r   r   r   rq   r   r   r   )r1   r;   rS   jsonrpc_errorr   jsonrpc_responser0   r0   r2   rW   =  s   
zBaseSession._send_responsec                    s   j 4 I d H C  j4 I d H # zސzy j 2 zq3 d H W }t|tr/ |I d H  qt|jjtrzD j	|jjj
dddd}t|jjj|jjrS|jjjnd |  fdd|jd}| j|j<  |I d H  |jsy |I d H  W q ty } z7td|  td|jj  td	|jjjttd
ddd}tt|d} j|I d H  W Y d }~qd }~ww t|jjtrgz j	|jjj
dddd}t|jtr|jjj }| jv r j| ! I d H  nUt|jt"r5|jjj#}	|	 j$v r5 j$|	 }
z|
|jjj%|jjj&|jjjI d H  W n ty4 } zt'd| W Y d }~nd }~ww  (|I d H   |I d H  W q tyf } ztd| d|jj  W Y d }~qd }~ww  j)*|jjjd }|r||jjI d H  q t+d| I d H  q6 W n* t,j-y   td Y n ty } zt.d|  W Y d }~nd }~ww W  j)/ D ],\}}tt0dd}z|td	||dI d H  |1 I d H  W q ty   Y qw  j)2  n8 j)/ D ],\}}tt0dd}z|td	||dI d H  |1 I d H  W q ty$   Y qw  j)2  w W d   I d H  n1 I d H s<w   Y  W d   I d H  d S 1 I d H sSw   Y  d S )NTr   r   c                    s    j | jd S r/   )ri   r   r;   )rrK   r0   r2   <lambda>`  s    z+BaseSession._receive_loop.<locals>.<lambda>)r;   r<   r=   r>   r?   rA   zFailed to validate request: z Message that failed validation: r   zInvalid request parameters rY   r   r   z)Progress callback raised an exception: %sz!Failed to validate notification: z. Message was: z.Received response with an unknown request ID: zRead stream closed by clientz%Unhandled exception in receive loop: zConnection closedr   )3rp   rq   r   	Exception_handle_incomingr-   rootr   rr   r   r   r:   r   r   metar   ri   r;   _received_requestrC   loggingwarningdebugr   r   r   r   r   r   r   rs   r   	requestIdr\   r   r   rj   r+   r,   r   _received_notificationrg   r   rP   rD   ClosedResourceError	exceptionitemsr   r{   clear)r1   r-   validated_request	respondereerror_responser   r   cancelled_idprogress_tokencallbackstreamr   r   r0   rK   r2   rz   K  s   


	



U\zBaseSession._receive_loopr   c                       dS )z
        Can be overridden by subclasses to handle a request without needing to
        listen on the message stream.

        If the request is responded to within this method, it will not be
        forwarded on to the message stream.
        Nr0   )r1   r   r0   r0   r2   r         zBaseSession._received_requestc                    r   )z
        Can be overridden by subclasses to handle a notification without needing
        to listen on the message stream.
        Nr0   )r1   r   r0   r0   r2   r     r   z"BaseSession._received_notificationr   r+   r,   r-   c                    r   )zh
        Sends a progress notification for a request that is currently being
        processed.
        Nr0   )r1   r   r+   r,   r-   r0   r0   r2   send_progress_notification  r   z&BaseSession.send_progress_notificationreqc                    r   )zCA generic handler for incoming messages. Overwritten by subclasses.Nr0   )r1   r   r0   r0   r2   r     s   zBaseSession._handle_incomingr/   )NNNr_   )NN)+r4   r5   r6   r7   dictr`   r   r   r   __annotations__intr:   r&   r$   r*   r
   r   r   rb   r)   r   rI   r   rx   rc   r   re   r}   r#   r'   r   r   r%   r   r   rW   rz   r   r   r9   r8   r   r   r0   r0   r0   r2   rf      s   
 		




O

q	

rf   );r   collections.abcr   
contextlibr   datetimer   typesr   typingr   r   r   r	   rD   r   anyio.streams.memoryr
   r   pydanticr   typing_extensionsr   mcp.shared.exceptionsr   mcp.shared.messager   r   r   	mcp.typesr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r)   r9   r   r`   r*   r:   rf   r0   r0   r0   r2   <module>   sB    L
k