o
    ưi[                     @   s  U 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mZm	Z	m
Z
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mZmZ d dlmZ d dlZd dlmZ d dlmZmZmZm Z m!Z!m"Z"m#Z# d dl$m%Z% d d	l&T erd d
lm'Z' d dl(m)Z* d dl+m,Z, neZ'eZ*eZ,zd dl-m.Z. W n e/y   dZ.Y nw de0fddZ1e1 Z2ej3dddZ4		d6deee0e5e6f  dedeeee0ef  ef fddZ7i Z8e	eee5 ee5 ee5 f ej9f e:d< dee5 dee5 dee5 dej9fddZ;	d7deee<e5f  dee<e5f fdd Z=	d7dee> dee<e5ej9f fd!d"Z?da@eee<e5ej9f  e:d#< dee<e5ej9f fd$d%ZAd&d' ZBG d(d) d)ejCZDG d*d+ d+ZEG d,d- d-ZF		d6d.ee'eGf d/ee0 d0ed1 deEfd2d3ZHd7d/ee0 deFfd4d5ZIdS )8    N)	TYPE_CHECKINGAnyCallableDictListMappingOptionalTupleUnionClientSessionTCPConnector)USE_CLIENT_DEFAULTAsyncHTTPTransportHTTPTransport)RequestFiles)verbose_logger)_DEFAULT_TTL_FOR_HTTPX_CLIENTSAIOHTTP_CONNECTOR_LIMIT AIOHTTP_CONNECTOR_LIMIT_PER_HOSTAIOHTTP_KEEPALIVE_TIMEOUTAIOHTTP_NEEDS_CLEANUP_CLOSEDAIOHTTP_TTL_DNS_CACHEDEFAULT_SSL_CIPHERS)track_llm_api_timing)*)LlmProviders)LoggingLiteLLMAiohttpTransport)versionz0.0.0returnc                  C   s*   t jd} | durd| iS ddt iS )z
    Get default headers for HTTP requests.

    - Default: `User-Agent: litellm/{version}`
    - Override: set `LITELLM_USER_AGENT` to fully override the header value.
    ZLITELLM_USER_AGENTNz
User-Agentzlitellm/)osenvirongetr    )
user_agent r&   ]/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/custom_httpx/http_handler.pyget_default_headers6   s   r(         @timeoutconnectdatacontentc                 C   s>   d}|}| durt | ttfr|du r| }||fS | }||fS )a  
    Helper function to route data/content parameters correctly for httpx requests

    This prevents httpx DeprecationWarnings that cause memory leaks.

    Background:
    - httpx shows a DeprecationWarning when you pass bytes/str to `data=`
    - It wants you to use `content=` instead for bytes/str
    - The warning itself leaks memory when triggered repeatedly

    Solution:
    - Move bytes/str from `data=` to `content=` before calling build_request
    - Keep dicts in `data=` (that's still the correct parameter for dicts)

    Args:
        data: Request data (can be dict, str, or bytes)
        content: Request content (raw bytes/str)

    Returns:
        Tuple of (request_data, request_content) properly routed for httpx
    N)
isinstancebytesstr)r-   r.   request_datarequest_contentr&   r&   r'   !_prepare_request_data_and_contentJ   s   r4   _ssl_context_cachecafilessl_security_levelssl_ecdh_curvec                 C   s   t j| d}t jj|_|rt|tr|| n|t |rrt|trrz|	| t
d|  W |S  tyS   t
dtj d  dt j d| d Y |S  tyq } zt
d| d	| d
 W Y d}~|S d}~ww |S )z
    Create an SSL context with the given configuration.
    This is separated from get_ssl_configuration to enable caching.
    )r6   zSSL ECDH curve set to: z<SSL ECDH curve configuration not supported. Python version: r   z, OpenSSL version: z. Requested curve: z!. Continuing with default curves.zInvalid SSL ECDH curve name: 'z'. zp. Common valid curves: X25519, prime256v1, secp384r1, secp521r1. Continuing with default curves (including PQC).N)sslcreate_default_context
TLSVersionTLSv1_2minimum_versionr/   r1   set_ciphersr   set_ecdh_curver   debugAttributeErrorwarningsysr    splitOPENSSL_VERSION
ValueError)r6   r7   r8   Zcustom_ssl_contexter&   r&   r'   _create_ssl_contextz   s:   	


rH   
ssl_verifyc                 C   s   ddl m} | du rtdtj} t| tr(tj	| r| S || }|dur(|} | du r;td}|r;tj	|r;|S | durA| S dS )aM  
    Common utility to resolve the SSL verification setting.
    Prioritizes:
    1. Passed-in ssl_verify
    2. os.environ["SSL_VERIFY"]
    3. litellm.ssl_verify
    4. os.environ["SSL_CERT_FILE"] (if ssl_verify is True)

    Returns:
        Union[bool, str]: The resolved SSL verification setting (bool or path to CA bundle)
    r   str_to_boolNZ
SSL_VERIFYTSSL_CERT_FILE)
litellm.secret_managers.mainrK   r"   getenvlitellmrI   r/   r1   pathexists)rI   rK   Zssl_verify_boolssl_cert_filer&   r&   r'   get_ssl_verify   s   

rS   c                 C   s   t | tjr| S t| d} tdtj}tdtj}d}t | t	r*tj
| r*| }|s@td}|r<tj
|r<|}nt }| durZ|||f}|tvrVt|||dt|< t| S | S )aF  
    Unified SSL configuration function that handles ssl_context and ssl_verify logic.

    SSL Configuration Priority:
    1. If ssl_verify is provided -> is a SSL context use the custom SSL context
    2. If ssl_verify is False -> disable SSL verification (ssl=False)
    3. If ssl_verify is a string -> use it as a path to CA bundle file
    4. If SSL_CERT_FILE environment variable is set and exists -> use it as CA bundle file
    5. Else will use default SSL context with certifi CA bundle

    If ssl_security_level is set, it will apply the security level to the SSL context.

    SSL contexts are cached to avoid creating duplicate contexts with the same configuration,
    which reduces memory allocation and improves performance.

    Args:
        ssl_verify: SSL verification setting. Can be:
            - None: Use default from environment/litellm settings
            - False: Disable SSL verification
            - True: Enable SSL verification
            - str: Path to CA bundle file

    Returns:
        Union[bool, str, ssl.SSLContext]: Appropriate SSL configuration
    )rI   ZSSL_SECURITY_LEVELZSSL_ECDH_CURVENrL   F)r6   r7   r8   )r/   r9   
SSLContextrS   r"   rN   rO   r7   r8   r1   rP   rQ   certifiwherer5   rH   )rI   r7   r8   r6   rR   	cache_keyr&   r&   r'   get_ssl_configuration   s.   



rX   _shared_realtime_ssl_contextc                   C   s   t du rt a t S )z
    Lazily create the SSL context reused by realtime websocket clients so we avoid
    import-order cycles during startup while keeping a single shared configuration.
    N)rY   rX   r&   r&   r&   r'   get_shared_realtime_ssl_context  s   rZ   c                 C   sv   t | tr| d}n| S |dkr9| d|}|dkr'| d |d  d }|S | d |d  d | |d   }|S | S )Nzkey=&   z[REDACTED_API_KEY])r/   r1   find)error_messageZ	key_indexZ
next_paramZmasked_messager&   r&   r'   mask_sensitive_info!  s    
	
r`   c                       s2   e Zd Z	ddee dee f fddZ  ZS )MaskedHTTPStatusErrorNmessagetextc                    sf   t t|jj}t j|jtj|jj	||jj
|jjdtj|jj|jj|jj
dd || _|| _d S )N)methodurlheadersr.   )status_coder.   rf   )rb   requestresponse)r`   r1   rh   re   super__init__rb   httpxRequestrd   rf   r.   Responseri   rg   rc   )selforiginal_errorrb   rc   Z
masked_url	__class__r&   r'   rk   >  s"   
zMaskedHTTPStatusError.__init__NN)__name__
__module____qualname__r   r1   rk   __classcell__r&   r&   rq   r'   ra   =  s    ra   c                   @   s  e Zd Z						d9deeeejf  deee	e
edef  f  dee	 dee ded f
d	d
Z		d:deeeejf  deee	e
edef  f  dee ded dejf
ddZdd Zdd Zdd Z			d;de	dee dee dee fddZe 									d<de	deeee	ef  dee dee dee deeeejf  dedee dee d efd!d"Z							d=de	deeee	ef  dee dee dee deeeejf  ded efd#d$Z							d=de	deeee	ef  dee dee dee deeeejf  ded efd%d&Z							d=de	deeee	ef  dee dee dee deeeejf  ded efd'd(Z						d>de	d)ejdeeee	ef  dee dee dee ded efd*d+Zd?d,d-Z e!			d;d.ee"j# dee ded deee$e%f  fd/d0Z&e!defd1d2Z'e!		d:dee d.ee"j# de(e	ef fd3d4Z)e!			d;dee d.ee"j# ded de$fd5d6Z*e!dee% fd7d8Z+dS )@AsyncHTTPHandlerNr+   event_hooks.client_aliasrI   shared_sessionr   c                 C   s*   || _ || _| j||||d| _|| _d S )N)r+   ry   rI   r{   )r+   ry   create_clientclientrz   )ro   r+   ry   concurrent_limitrz   rI   r{   r&   r&   r'   rk   X  s   	
zAsyncHTTPHandler.__init__r!   c           	   	   C   sn   t |}tdtj}|d u rt}tjt|t	j
r|nd t|tr#|nd |d}t }tj||||||ddS )NSSL_CERTIFICATEssl_contextrI   r{   T)	transportry   r+   verifycertrf   follow_redirects)rX   r"   rN   rO   ssl_certificate_DEFAULT_TIMEOUTrx   _create_async_transportr/   r9   rT   boolr(   rl   AsyncClient)	ro   r+   ry   rI   r{   
ssl_configr   r   default_headersr&   r&   r'   r|   k  s&   zAsyncHTTPHandler.create_clientc                       | j  I d H  d S Nr}   aclosero   r&   r&   r'   close     zAsyncHTTPHandler.closec                    s   | j S r   )r}   r   r&   r&   r'   
__aenter__  s   zAsyncHTTPHandler.__aenter__c                    r   r   r   r   r&   r&   r'   	__aexit__  r   zAsyncHTTPHandler.__aexit__re   paramsrf   r   c                    sH   |d ur|nt }|pi }|t| | jj||||dI d H }|S )N)r   rf   r   )r   updateHTTPHandlerextract_query_paramsr}   r$   ro   re   r   rf   r   Z_follow_redirectsri   r&   r&   r'   r$     s   	zAsyncHTTPHandler.getFr-   jsonstreamlogging_objfilesr.   c                    s  t   }z/|d u r| j}t||
\}}| jjd|||||||	|d	}| jj||dI d H }|  |W S  tjtj	fyi   | j
|| jd}z| j|||||||dI d H W | I d H   Y S | I d H  w  tjy } z8t   }t|| d}i }t|dd }|d ur|j D ]\}}||d|< qtjd	| d
| ddd|dd }~w tjy } z;|du rt|d|j I d H  t|d|j I d H  nt|dt|jj t|dt|jj t|d|jj |d }~w ty } z|d }~ww )NPOSTr-   r   r   rf   r+   r   r.   r   r+   ry   re   r}   r-   r   r   rf   r      ri   response_headers-{}z%Connection timed out. Timeout passed=z, time taken=z secondsdefault-model-namelitellm-httpx-handlerrb   modelllm_providerrf   Trb   rc   rg   )timer+   r4   r}   build_requestsendraise_for_statusrl   RemoteProtocolErrorConnectErrorr|   ry   single_connection_post_requestr   TimeoutExceptionroundgetattrrf   itemsformatrO   TimeoutHTTPStatusErrorsetattrri   areadr`   rc   rg   	Exception)ro   re   r-   r   r   rf   r+   r   r   r   r.   
start_timer2   r3   reqri   
new_clientrG   end_timeZ
time_deltaerror_responsekeyvaluer&   r&   r'   post  s   $
zAsyncHTTPHandler.postc	                      z,|d u r	| j }t||\}	}
| jjd||	|||||
d}| j|I d H }|  |W S  tjtjfyb   | j	|| j
d}z| j|||||||dI d H W | I d H   Y S | I d H  w  tjy } z*i }t|dd }|d ur|j D ]\}}||d|< q{tjd| dd	d
|dd }~w tjy } z$t|d|jj |du rt|d|j I d H  |t|d|jj |d }~w ty } z|d }~ww )NPUTr-   r   r   rf   r+   r.   r   r   ri   r   Connection timed out after 	 seconds.r   r   r   rg   Trb   r+   r4   r}   r   r   r   rl   r   r   r|   ry   r   r   r   r   rf   r   r   rO   r   r   r   ri   rg   r   rc   r   ro   re   r-   r   r   rf   r+   r   r.   r2   r3   r   ri   r   rG   r   r   r   r&   r&   r'   put  j   $

zAsyncHTTPHandler.putc	                    r   )NPATCHr   r   r   ri   r   r   r   r   r   r   rg   Trb   r   r   r&   r&   r'   patchE  r   zAsyncHTTPHandler.patchc	                    sD  z.|d u r	| j }t||\}	}
| jjd||	|||||
d}| jj||dI d H }|  |W S  tjtjfyd   | j	|| j
d}z| j|||||||dI d H W | I d H   Y S | I d H  w  tjy } z$t|d|jj |du rt|d|j I d H  |t|d|jj |d }~w ty } z|d }~ww )	NDELETEr   r   r   r   rg   Trb   )r+   r4   r}   r   r   r   rl   r   r   r|   ry   r   r   r   r   ri   rg   r   rc   r   )ro   re   r-   r   r   rf   r+   r   r.   r2   r3   r   ri   r   rG   r&   r&   r'   delete  sP   $
zAsyncHTTPHandler.deleter}   c	              	      sH   t ||\}	}
|jd||	||||
d}|j||dI dH }|  |S )zz
        Making POST request for a single connection client.

        Used for retrying connection client errors.
        r   r-   r   r   rf   r.   r   N)r4   r   r   r   )ro   re   r}   r-   r   r   rf   r   r.   r2   r3   r   ri   r&   r&   r'   r     s   z/AsyncHTTPHandler.single_connection_post_requestc                 C   s.   zt  |   W d S  ty   Y d S w r   )asyncioget_running_loopcreate_taskr   r   r   r&   r&   r'   __del__  s
   zAsyncHTTPHandler.__del__r   c                 C   s    t  rt j| ||dS t  S )a  
        - Creates a transport for httpx.AsyncClient
            - if litellm.force_ipv4 is True, it will return AsyncHTTPTransport with local_address="0.0.0.0"
            - [Default] It will return AiohttpTransport
            - Users can opt out of using AiohttpTransport by setting litellm.use_aiohttp_transport to False


        Notes on this handler:
        - Why AiohttpTransport?
            - By default, we use AiohttpTransport since it offers much higher throughput and lower latency than httpx.

        - Why force ipv4?
            - Some users have seen httpx ConnectionError when using ipv6 - forcing ipv4 resolves the issue for them
        r   )rx   _should_use_aiohttp_transport_create_aiohttp_transport_create_httpx_transportr   r&   r&   r'   r     s   	z(AsyncHTTPHandler._create_async_transportc                  C   sD   ddl } ddlm} tjdu s|| dddu rdS td dS )	z
        AiohttpTransport is the default transport for litellm.

        Httpx can be used by the following
            - litellm.disable_aiohttp_transport = True
            - os.getenv("DISABLE_AIOHTTP_TRANSPORT") = "True"
        r   NrJ   TZDISABLE_AIOHTTP_TRANSPORTFalseFzUsing AiohttpTransport...)r"   rM   rK   rO   disable_aiohttp_transportrN   r   r@   )r"   rK   r&   r&   r'   r     s   	

z.AsyncHTTPHandler._should_use_aiohttp_transportc                 C   s:   dt jrdndi}|dur||d< |S | du rd|d< |S )aq  
        Helper method to get SSL connector initialization arguments for aiohttp TCPConnector.

        SSL Configuration Priority:
        1. If ssl_context is provided -> use the custom SSL context
        2. If ssl_verify is False -> disable SSL verification (ssl=False)

        Returns:
            Dict with appropriate SSL configuration for TCPConnector
        
local_addr)0.0.0.0r   Nr9   F)rO   
force_ipv4)rI   r   connector_kwargsr&   r&   r'   _get_ssl_connector_kwargs  s   z*AsyncHTTPHandler._get_ssl_connector_kwargsc                    s   ddl m} ddlm} tj| |d}tj|t	dddu r"dd}|dur+|}n| d	u r1d	}t
d
 |durO|jsOt
dt| d |||d	dS t
d ttd| trad d< tdkrit d< tdkrqt d< | fdd|dS )z
        Creates an AiohttpTransport with RequestNotRead error handling

        Note: aiohttp TCPConnector ssl parameter accepts:
        - SSLContext: custom SSL context
        - False: disable SSL verification
        r   r   rJ   )rI   r   ZAIOHTTP_TRUST_ENVr   TNFzCreating AiohttpTransport...z4SHARED SESSION: Reusing existing ClientSession (ID: ))r}   rI   Zowns_sessionzDNEW SESSION: Creating new ClientSession (no shared session provided))Zkeepalive_timeoutZttl_dns_cacheZenable_cleanup_closedlimitZlimit_per_hostc                      s   t tdi  dS )N)Z	connector	trust_envr&   r   r&   Ztransport_connector_kwargsr   r&   r'   <lambda>|  s    z<AsyncHTTPHandler._create_aiohttp_transport.<locals>.<lambda>)r}   rI   )+litellm.llms.custom_httpx.aiohttp_transportr   rM   rK   rx   r   rO   Zaiohttp_trust_envr"   rN   r   r@   closedidr   r   r   r   r   )rI   r   r{   r   rK   r   Zssl_for_transportr&   r   r'   r   7  sX   
z*AsyncHTTPHandler._create_aiohttp_transportc                   C   s   t jrtddS dS )z
        Creates an AsyncHTTPTransport

        - If force_ipv4 is True, it will create an AsyncHTTPTransport with local_address set to "0.0.0.0"
        - [Default] If force_ipv4 is False, it will return None
        r   local_addressN)rO   r   r   r&   r&   r&   r'   r     s   
z(AsyncHTTPHandler._create_httpx_transport)NNNNNNrs   NNN)	NNNNNFNNNNNNNNFN)NNNNFNr!   N),rt   ru   rv   r   r
   floatrl   r   r   r1   r   r   r   VerifyTypesrk   r   r|   r   r   r   dictr   r$   r   r0   LiteLLMLoggingObjectr   r   r   r   r   r   r   staticmethodr9   rT   r   r   r   r   r   r   r   r   r&   r&   r&   r'   rx   W  s   

%
	
V	
E	
E	
9	

"
Krx   c                   @   s  e Zd Z					d&deeeejf  deej deee	e
f  dee	 fddZd	d
 Z			d'de
dee dee dee	 fddZede
dee
e
f fddZ									d(de
deeee
ef  deeee
ef  dee dee de	deeeejf  deeeef  dedee fddZ							d)de
deeee
ef  deeee
f  dee dee de	deeeejf  defddZ							d)de
deeee
ef  deeee
f  dee dee de	deeeejf  defddZ							d*de
deeee
ef  dee dee dee deeeejf  de	defd d!Zd+d"d#Zdee fd$d%ZdS ),r   NFr+   r}   rI   disable_default_headersc           
      C   sf   |d u rt }t|}tdtj}|st nd }|d u r.|  }	tj	|	||||dd| _
d S || _
d S )Nr   T)r   r+   r   r   rf   r   )r   rX   r"   rN   rO   r   r(   _create_sync_transportrl   Clientr}   )
ro   r+   r~   r}   rI   r   r   r   r   r   r&   r&   r'   rk     s    

	zHTTPHandler.__init__c                 C   s   | j   d S r   )r}   r   r   r&   r&   r'   r     s   zHTTPHandler.closere   r   rf   r   c                 C   s>   |d ur|nt }|pi }|| | | jj|||d}|S )N)r   rf   )r   r   r   r}   r$   r   r&   r&   r'   r$     s   	zHTTPHandler.getr!   c                 C   s&   ddl m}m} || }t||jS )u   
        Parse a URL’s query-string into a dict.

        :param url: full URL, e.g. "https://.../path?foo=1&bar=2"
        :return: {"foo": "1", "bar": "2"}
        r   )	parse_qslurlsplit)urllib.parser   r   r   query)re   r   r   partsr&   r&   r'   r     s   z HTTPHandler.extract_query_paramsr-   r   r   r   r.   r   c                 C   s:  z8t ||	\}}|d ur| jjd||||||||d	}n| jjd|||||||d}| jj||d}|  |W S  tjyL   tjd| dddd	 tj	y } z7|d
u rot
|dt|j  t
|dt|j  nt|jj}t
|d| t
|d| t
|d|jj |d }~w ty } z|d }~ww )Nr   r   )r-   r   r   rf   r   r.   r   r   r   r   r   rb   r   r   Trb   rc   rg   r4   r}   r   r   r   rl   r   rO   r   r   r   r`   ri   readrc   rg   r   )ro   re   r-   r   r   rf   r   r+   r   r.   r   r2   r3   r   ri   rG   
error_textr&   r&   r'   r     sT   
zHTTPHandler.postc	              
   C   s6  z6t ||\}	}
|d ur| jjd||	|||||
d}n| jjd||	||||
d}| jj||d}|  |W S  tjyJ   tjd| dddd	 tj	y } z7|d
u rmt
|dt|j  t
|dt|j  nt|jj}t
|d| t
|d| t
|d|jj |d }~w ty } z|d }~ww )Nr   r   r   r   r   r   r   r   r   Trb   rc   rg   r   )ro   re   r-   r   r   rf   r   r+   r.   r2   r3   r   ri   rG   r   r&   r&   r'   r     D   
zHTTPHandler.patchc	              
   C   s   z2t ||\}	}
|d ur| jjd||	|||||
d}n| jjd||	||||
d}| jj||d}|W S  tjyF   tjd| dddd	 tyS } z|d }~ww )
Nr   r   r   r   r   r   r   r   r   )	r4   r}   r   r   rl   r   rO   r   r   )ro   re   r-   r   r   rf   r   r+   r.   r2   r3   r   ri   rG   r&   r&   r'   r   J  s.   
zHTTPHandler.putc	              
   C   s6  z6t ||\}	}
|d ur| jjd||	|||||
d}n| jjd||	||||
d}| jj||d}|  |W S  tjyJ   tjd| dddd	 tj	y } z7|d
u rmt
|dt|j  t
|dt|j  nt|jj}t
|d| t
|d| t
|d|jj |d }~w ty } z|d }~ww )Nr   r   r   r   r   r   r   r   r   Trb   rc   rg   r   )ro   re   r-   r   r   rf   r+   r   r.   r2   r3   r   ri   rG   r   r&   r&   r'   r   n  r   zHTTPHandler.deletec                 C   s$   z|    W d S  ty   Y d S w r   )r   r   r   r&   r&   r'   r     s
   zHTTPHandler.__del__c                 C   s   t jrtddS tt ddS )z
        Create an HTTP transport with IPv4 only if litellm.force_ipv4 is True.
        Otherwise, return None.

        Some users have seen httpx ConnectionError when using ipv6 - forcing ipv4 resolves the issue for them
        r   r   Zsync_transportN)rO   r   r   r   r   r&   r&   r'   r     s   
z"HTTPHandler._create_sync_transport)NNNNFr   )	NNNNFNNNN)NNNNFNNr   r   )rt   ru   rv   r   r
   r   rl   r   r   r   r1   rk   r   r   r$   r   r   r   r0   r   r   r   r   r   r   r   r   r   r   r   r&   r&   r&   r'   r     s   
&
	

=	
4	
'	

1r   r   r   r{   r   c              	   C   s   d}|dur#|  D ]\}}z|| d| 7 }W q
 ty"   Y q
w d| |  }ttdd}|du rBddlm} | }ttd| ||}	|	rK|	S |durddd	 |  D }
||
d
< tdi |
}ntt	j
ddd|d}|j||td |S )z
    Retrieves the async HTTP client from the cache
    If not present, creates a new client

    Caches the new client and returns it.
     N_Zasync_httpx_clientin_memory_llm_clients_cacher   LLMClientCachec                 S      i | ]\}}|d kr||qS r   r&   .0kvr&   r&   r'   
<dictcomp>      z*get_async_httpx_client.<locals>.<dictcomp>r{        @r)   r*   )r+   r{   r   r   ttlr&   )r   r   r   rO   #litellm.caching.llm_caching_handlerr  r   	get_cacherx   rl   r   	set_cacher   )r   r   r{   _params_key_namer   r   _cache_key_namecacher  _cached_clienthandler_params_new_clientr&   r&   r'   get_async_httpx_client  s>   
r  c           
   	   C   s   d}| dur#|   D ]\}}z|| d| 7 }W q
 ty"   Y q
w d| }ttdd}|du r@ddlm} | }ttd| ||}|rI|S | dur^dd	 |   D }tdi |}	n
tt	j
d
ddd}	|j||	td |	S )z
    Retrieves the HTTP client from the cache
    If not present, creates a new client

    Caches the new client and returns it.
    r   Nr   Zhttpx_clientr  r   r  c                 S   r  r  r&   r  r&   r&   r'   r
    r  z%_get_httpx_client.<locals>.<dictcomp>r  r)   r*   )r+   r  r&   )r   r   r   rO   r  r  r   r  r   rl   r   r  r   )
r   r  r   r   r  r  r  r  r  r  r&   r&   r'   _get_httpx_client  s6   
r  rs   r   )Jr   r"   r9   rC   r   typingr   r   r   r   r   r   r   r	   r
   rU   rl   Zaiohttpr   r   r   r   r   Zhttpx._typesr   rO   Zlitellm._loggingr   Zlitellm.constantsr   r   r   r   r   r   r   Z(litellm.litellm_core_utils.logging_utilsr   Zlitellm.types.llms.custom_httpr   Z*litellm.litellm_core_utils.litellm_loggingr   r   r   r   Zlitellm._versionr    r   r   r(   rf   r   r   r1   r0   r4   r5   rT   __annotations__rH   r   rS   r   rX   rY   rZ   r`   r   ra   rx   r   ZhttpxSpecialProviderr  r  r&   r&   r&   r'   <module>   s   
 ,$	
-
1

(
B    >  %

5