o
    hQ'                     @   sx  U d dl Z d dlZd dl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 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mZmZ ee Z!e j"d
ddZ#e j"eej$  e%d< G dd de&Z'G dd dZ(zd dl)m*Z* e*j+e(_,e(j+e*_+W n e-y   e!.d Y nw ee/e0e1eef Z2e
e2 Z3ee2 Z4ee4e3f Z5G dd deZ6dS )    N)datetimetimezone)	AnyAsyncIterable	AwaitableCallable	CoroutineIteratorMappingOptionalUnion)BackgroundTask)iterate_in_threadpool)MutableHeaders)Response)ReceiveScopeSendMessage)ServerSentEventensure_bytes
exit_event)default_exit_event_contextc                   @   s   e Zd ZdS )SendTimeoutErrorN)__name__
__module____qualname__ r   r   R/var/www/html/openai_agents/venv/lib/python3.10/site-packages/sse_starlette/sse.pyr   "   s    r   c                   @   sF   e Zd ZU dZdZdZee ed< e	dd Z
e	dejfdd	ZdS )
	AppStatusz\Helper to capture a shutdown signal from Uvicorn so we can gracefully terminate SSE streams.FNoriginal_handlerc                  O   sB   dt _td }|d ur|  t jd urt j| i | d S d S )NT)r    should_exitr   getsetr!   )argskwargscurrent_eventr   r   r   handle_exit,   s   

zAppStatus.handle_exitreturnc                  C   s(   t d} | du rt } t |  | S )z4Get or create an exit event for the current context.N)r   r#   anyioEventr$   )eventr   r   r   get_or_create_exit_event9   s
   

z"AppStatus.get_or_create_exit_event)r   r   r   __doc__r"   r!   r   r   __annotations__staticmethodr(   r*   r+   r-   r   r   r   r   r    &   s   
 
r    )ServerzHUvicorn not installed. Graceful shutdown on server termination disabled.c                   @   s^  e Zd ZdZdZdZ										d+deded	ee	e
e
f  d
e
dee dee dee
 deeg ef  deeg ed f  dee deeeged f  ddfddZedeeef fddZejdeeef ddfddZd,deddfddZdeddfdd Zd!eddfd"d#Zed-d$d%Zdeddfd&d'Zd(e d!ededdfd)d*Z!dS ).EventSourceResponsezf
    Streaming response that sends data conforming to the SSE (Server-Sent Events) specification.
       
   Ntext/event-streamcontentstatus_codeheaders
media_type
backgroundpingsepping_message_factorydata_sender_callable)NNNsend_timeoutclient_close_handler_callabler)   c                 C   s   |dvrt d| |p| j| _t|tr|| _nt|| _|| _|d u r)| jn|| _|| _	|	| _
|
| _t }|d urA|| |dd d|d< d|d< | | |d u r[| jn|| _|| _|| _d	| _t | _d S )
N)Nr4   
z'sep must be one of: \r\n, \r, \n, got: zCache-Controlzno-storez
keep-alive
ConnectionnozX-Accel-BufferingT)
ValueErrorDEFAULT_SEPARATORr=   
isinstancer   body_iteratorr   r8   r:   r;   r?   r@   r   update
setdefaultinit_headersDEFAULT_PING_INTERVALping_intervalr>   rA   activer*   Lock
_send_lock)selfr7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   _headersr   r   r   __init__[   s.   



zEventSourceResponse.__init__c                 C   s   | j S N)_ping_interval)rR   r   r   r   rN      s   z!EventSourceResponse.ping_intervalvaluec                 C   s0   t |ttfstd|dk rtd|| _d S )Nzping interval must be intr   z$ping interval must be greater than 0)rH   intfloat	TypeErrorrF   rV   )rR   rW   r   r   r   rN      s
   
Fforcec                 C   s   t d)Nz-Compression is not supported for SSE streams.)NotImplementedError)rR   r[   r   r   r   enable_compression   s   z&EventSourceResponse.enable_compressionsendc              	      s  |d| j | jdI dH  | j2 zI3 dH W }t|| j}td| t| j	}|d|ddI dH  W d   n1 s?w   Y  |rZ|j
rZt| jdrW| j I dH  t q6 | j4 I dH  d	| _|dd
d	dI dH  W d  I dH  dS 1 I dH sw   Y  dS )zHSend out SSE data to the client as it becomes available in the iterator.zhttp.response.start)typestatusr9   Nz	chunk: %shttp.response.bodyTr_   body	more_bodyacloseF    )r8   raw_headersrI   r   r=   loggerdebugr*   move_on_afterr@   cancel_calledhasattrre   r   rQ   rO   )rR   r^   datachunkcancel_scoper   r   r   _stream_response   s2   


.z$EventSourceResponse._stream_responsereceivec                    sX   | j r*| I dH }|d dkr%d| _ td | jr#| |I dH  dS | j sdS dS )z/Watch for a disconnect message from the client.Nr_   zhttp.disconnectFz+Got event: http.disconnect. Stop streaming.)rO   rh   ri   rA   )rR   rq   messager   r   r   _listen_for_disconnect   s   
z*EventSourceResponse._listen_for_disconnectc                     s0   t jrdS t  } t jrdS |  I dH  dS )zQWatch for shutdown signals (e.g. SIGINT, SIGTERM) so we can break the event loop.N)r    r"   r-   wait)r   r   r   r   _listen_for_exit_signal   s   z+EventSourceResponse._listen_for_exit_signalc              	      s   | j r^t| jI dH  | jr|  ntdttj	 | j
d}t|| j
}td| | j4 I dH  | j rD|d|ddI dH  W d  I dH  n1 I dH sTw   Y  | j sdS dS )zPeriodically send ping messages to keep the connection alive on proxies.
        - frequenccy ca every 15 seconds.
        - Alternatively one can send periodically a comment line (one starting with a ':' character)
        Nzping - )commentr=   zping: %sra   Trb   )rO   r*   sleeprV   r>   r   r   nowr   utcr=   r   rh   ri   rQ   )rR   r^   sse_ping
ping_bytesr   r   r   _ping   s,   

(zEventSourceResponse._pingscopec              	      s   t  4 I dH Kdtg td f ffdd}|fdd |fdd |j jr?j | fdd W d  I dH  n1 I dH sZw   Y  jdurm I dH  dS dS )	a  Entrypoint for Starlette's ASGI contract. We spin up tasks:
        - _stream_response to push events
        - _ping to keep the connection alive
        - _listen_for_exit_signal to respond to server shutdown
        - _listen_for_disconnect to respond to client disconnect
        Ncoroc                    s   |  I d H   j   d S rU   )ro   cancel)r~   )
task_groupr   r   cancel_on_finish  s   z6EventSourceResponse.__call__.<locals>.cancel_on_finishc                      
     S rU   )rp   r   rR   r^   r   r   <lambda>     
 z.EventSourceResponse.__call__.<locals>.<lambda>c                      r   rU   )r|   r   r   r   r   r     r   c                      s
     S rU   )rs   r   )rq   rR   r   r   r     r   )r*   create_task_groupr   r   
start_soonru   r?   r;   )rR   r}   rq   r^   r   r   )rq   rR   r^   r   r   __call__   s   (
zEventSourceResponse.__call__)
r5   Nr6   NNNNNNN)F)r)   N)"r   r   r   r.   rM   rG   ContentStreamrX   r   r
   strr   r   r   r   rY   r   r   rT   propertyr   rN   setterboolr]   r   rp   r   rs   r0   ru   r|   r   r   r   r   r   r   r2   S   sl    	

=r2   )7contextvarsloggingr   r   typingr   r   r   r   r   r	   r
   r   r   r*   starlette.backgroundr   starlette.concurrencyr   starlette.datastructuresr   starlette.responsesr   starlette.typesr   r   r   r   sse_starlette.eventr   r   	getLoggerr   rh   
ContextVarr   r+   r/   TimeoutErrorr   r    uvicorn.mainr1   r(   r!   ImportErrorri   r   bytesdictContentSyncContentStreamAsyncContentStreamr   r2   r   r   r   r   <module>   s<   
 ,
