Ë
    uPêjQ  ã                   ó’   — d Z ddlmZmZm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 d
dlmZ  G d„ de«      Zy)z�
This file contains the calling OpenAI's `/v1/realtime` endpoint.

This requires websockets, and is currently only supported on LiteLLM Proxy.
é    )ÚAnyÚFinalÚcast)Ú_redact_stringÚverbose_logger)Ú)REALTIME_WEBSOCKET_MAX_MESSAGE_SIZE_BYTES)ÚRealtimeQueryParamsé   )ÚLogging)ÚRealtimeEventNormalizerÚRealTimeStreamingÚ'client_sent_openai_beta_realtime_header)Úget_shared_realtime_ssl_contexté   )ÚOpenAIChatCompletionc                   óÚ   — e Zd ZdZdefd„Zddœdededefd„Zd	ede	fd
„Z
dededefd„Zdedz  fd„Z	 	 	 	 	 	 	 ddede	dededz  dedz  de	dz  dedz  dedz  de	dz  dedz  de	fd„Zy)ÚOpenAIRealtimeaD  
    Base handler for OpenAI-compatible realtime WebSocket connections.

    Subclasses can override template methods to customize:
    - _get_default_api_base(): Default API base URL
    - _get_additional_headers(): Extra headers beyond Authorization
    - _get_ssl_config(): SSL configuration for WebSocket connection
    Úreturnc                  ó   — y)zˆ
        Get the default API base URL for this provider.
        Override this in subclasses to set provider-specific defaults.
        zhttps://api.openai.com/© ©Úselfs    úi/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/llms/openai/realtime/handler.pyÚ_get_default_api_basez$OpenAIRealtime._get_default_api_base!   s   € ð
 )ó    F©Úopenai_beta_realtimeÚapi_keyr   c                ó"   — dd|› �i}|rd|d<   |S )a…  
        Headers for the upstream OpenAI Realtime WebSocket.

        When the client sent ``OpenAI-Beta: realtime=v1`` on the proxy WebSocket,
        ``openai_beta_realtime`` is True and the same header is forwarded upstream
        so the legacy beta API is used. GA clients omit that header on the client
        connection and must send GA-shaped ``session.update`` payloads.
        ÚAuthorizationzBearer zrealtime=v1zOpenAI-Betar   )r   r   r   Úheaderss       r   Ú_get_additional_headersz&OpenAIRealtime._get_additional_headers(   s'   € ð !0°7¸7¸)Ð1DÐEˆÙØ%2ˆG�MÑ"Øˆr   Úurlc                 óH   — |j                  d«      ryt        «       }|du ry|S )a  
        Get SSL configuration for WebSocket connection.
        Override this in subclasses to customize SSL behavior.

        Args:
            url: WebSocket URL (ws:// or wss://)

        Returns:
            SSL configuration (None, True, or SSLContext)
        úws://NFT)Ú
startswithr   )r   r#   Ú
ssl_configs      r   Ú_get_ssl_configzOpenAIRealtime._get_ssl_config;   s0   € ð �>‰>˜'Ô"Øô <Ó=ˆ
ð ˜ÑØàÐr   Úapi_baseÚquery_paramsc                 óÈ   — ddl m} |j                  dd«      }|j                  dd«      } ||«      }|j                  d¬«      }|r|j                  |¬	«      }t	        |«      S )
zd
        Construct the backend websocket URL with all query parameters (including 'model').
        r   )ÚURLzhttps://zwss://zhttp://r%   z/v1/realtime)Úpath)Úparams)Úhttpxr,   ÚreplaceÚ	copy_withÚstr)r   r)   r*   r,   r#   s        r   Ú_construct_urlzOpenAIRealtime._construct_urlS   s`   € õ 	à×#Ñ# J°Ó9ˆØ×#Ñ# I¨wÓ7ˆÙ�(‹mˆà�m‰m ˆmÓ0ˆáØ—-‘- |�-Ó4ˆCÜ�3‹xˆr   Nc                  ó   — y)z»Return a per-session GA event normalizer, or None for passthrough.

        Subclasses (e.g. XAIRealtime) override this to supply a provider-specific
        normalizer instance.
        Nr   r   s    r   Ú_make_event_normalizerz%OpenAIRealtime._make_event_normalizerc   s   € ð r   ÚmodelÚ	websocketÚlogging_objÚclientÚtimeoutÚuser_api_key_dictÚlitellm_metadataÚkwargsc              ‹   ój  K  — dd l }ddlm} |€| j                  «       }|€t	        d«      ‚|€d|i}| j                  ||«      }	 | j                  |«      }t        |«      }|st        j                  d«       | j                  ||¬«      }|j                  d |||d|idœ¬	«       |j                  ||t        |¬
«      4 ƒd {  –—† }t        |t        ||«      |||	d|
xs i i|xs i j!                  d«      dk(  r|nd | j#                  «       ¬«      }|j%                  «       ƒ d {  –—†  d d d «      ƒd {  –—†  y 7 Œx7 Œ7 Œ	# 1 ƒd {  –—†7  sw Y   y xY w# |j&                  j(                  $ rB}|j+                  |j,                  t/        t1        |«      «      ¬«      ƒ d {  –—†7   Y d }~y d }~wt2        $ rx}	 |j+                  dt/        d|› �«      ¬«      ƒ d {  –—†7   nD# t4        $ r3}dt1        |«      v sdt1        |«      v rnt3        d|› �«      ‚Y d }~nd }~ww xY wY d }~y Y d }~y d }~ww xY w­w)Nr   )ÚClientConnectionz-api_key is required for OpenAI realtime callsr6   zÁOpenAI Realtime: connecting with GA protocol (no OpenAI-Beta header). If your client expects beta event names, add 'OpenAI-Beta: realtime=v1' to the WebSocket headers sent to the LiteLLM proxy.r   r*   )r)   r!   Úcomplete_input_dict)Úinputr   Úadditional_args)Úadditional_headersÚmax_sizeÚsslr<   ÚintentÚtranscription)r6   r;   Úrequest_dataÚforce_transcription_modelÚevent_normalizer)ÚcodeÚreasonió  zInternal server error: zalready completedzwebsocket.closez*Unexpected error while closing WebSocket: )Ú
websocketsÚwebsockets.asyncio.clientr?   r   Ú
ValueErrorr3   r(   r   r   Údebugr"   Úpre_callÚconnectr   r   r   Úgetr5   Úbidirectional_forwardÚ
exceptionsÚInvalidStatusCodeÚcloseÚstatus_coder   r2   Ú	ExceptionÚRuntimeError)r   r6   r7   r8   r)   r   r9   r:   r*   r;   r<   r=   rM   r?   r#   r'   r   r!   Ú
backend_wsÚrealtime_streamingÚeÚclose_errors                         r   Úasync_realtimezOpenAIRealtime.async_realtimek   sx  è ø€ ó 	Ý>àÐØ×1Ñ1Ó3ˆHØˆ?ÜÐLÓMÐMð ÐØ# UÐ+ˆLØ×(Ñ(¨°<Ó@ˆð6	`à $× 4Ñ 4°SÓ 9ˆJä*QÐR[Ó*\Ð Ù'Ü×$Ñ$ðJôð
 "×9Ñ9¸'ÐXlÐ9ÓmˆGð × Ñ ØØà #Ø&Ø,:¸LÐ+Iñ!ð !ô ð "×)Ñ)ØØ#*ÜBØð	 *ó ÷ Að Að
 Ü,=ØÜÐ)¨:Ó6ØØØ&7Ø"4Ð6FÒ6LÈ"Ð!Mà".Ò"4°"×!9Ñ!9¸(Ó!CÀÒ!V™Ð\`à%)×%@Ñ%@Ó%Bô-Ð"ð )×>Ñ>Ó@×@Ð@÷%A÷ Añ Aøð$ Aøð%Aø÷ A÷ Añ Aûð( ×$Ñ$×6Ñ6ò 	UØ—/‘/ q§}¡}¼^ÌCÐPQËFÓ=S�/ÓT×TÖTûÜò 		`ð`Ø—o‘o¨4¼ÐI`ÐabÐ`cÐGdÓ8e�oÓf×fÒføÜò `Ø&¬#¨kÓ*:Ñ:Ð>OÔSVÐWbÓScÑ>càô $Ð&PÐQ\ÐP]Ð$^Ó_Ð_ô ûð`úô ô	 gûð		`üsæ   ‚AH3ÁA=E ÃD;ÃE ÃAEÄ%D=Ä&EÄ*E Ä5D?Ä6E Ä:H3Ä;E Ä=EÄ?E ÅEÅE
ÅEÅE ÅH3ÅE ÅH0Å/2F,Æ!F$Æ"F,Æ'H3Æ,H0Æ9"G"ÇGÇG"Ç!H+Ç"	HÇ+)HÈH+ÈHÈH+È!
H3È+H0È0H3)NNNNNNN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r2   r   ÚboolÚdictr"   r   r(   r	   r3   r   r5   ÚLiteLLMLoggingÚfloatr_   r   r   r   r   r      s7  „ ñð) só )ð &+ò	àðð #ð	ð
 
óð& 3ð ¨3ó ð0 sð Ð:Mð ÐRUó ð Ð(?À$Ñ(Fó ð  $Ø"Ø!Ø $Ø37Ø(,Ø(,ñQ`àðQ`ð ðQ`ð $ð	Q`ð
 ˜‘*ðQ`ð �t‘ðQ`ð �d‘
ðQ`ð ˜‘ðQ`ð *¨DÑ0ðQ`ð  ™:ðQ`ð  ™+ðQ`ð ôQ`r   r   N)rc   Útypingr   r   r   Úlitellm._loggingr   r   Úlitellm.constantsr   Úlitellm.types.realtimer	   Ú"litellm_core_utils.litellm_loggingr   rf   Ú%litellm_core_utils.realtime_streamingr   r   r   Úllms.custom_httpx.http_handlerr   Úopenair   r   r   r   r   ú<module>rp      sB   ðñ÷ $Ñ #ç ;Ý GÝ 6å L÷ñ õ
 OÝ )ôe`Ð)õ e`r   