
    Cjt              	          S SK r S SKrS SKrS SKJrJrJrJr  S SKrS SK	J
r  S SKJrJr  S SKJrJrJr  S SKJrJr  S SKJr  SSKJr  S	rS
 rS%S jrS%S jrS rS r S%S\ S\\    S\4S jjr!   S&S\\    S\\    S\\    4S jjr"   S&S\\    S\\    S\\    S\ 4S jjr#   S&S\\    S\\    S\\    S\4S jjr$S r%S r&S\RN                  4S jr(S\)S\)4S jr*S\RV                  4S jr,S\RV                  4S jr-S  r. S%S!\\R^                     S\\RV                  \RN                  4   4S" jjr0S\\R^                     4S# jr1S\)SS4S$ jr2g)'    N)CallableListOptionalUnion)
get_secretget_secret_str)AzureADCredentialProviderGCPIAMCredentialProvider_generate_gcp_iam_access_token)REDIS_CONNECTION_POOL_TIMEOUTREDIS_SOCKET_TIMEOUT)SensitiveDataMasker   )verbose_loggerz https://redis.azure.com/.defaultc                      [         R                  " [        R                  5      n 1 Skn1 SknU R                   Vs1 s H  o3U;  d  M
  UiM     snU-  nU$ s  snf )N>   selfretryconnection_pool>   urlazure_client_idazure_tenant_idgcp_ssl_ca_certsredis_connect_funcazure_client_secretgcp_service_accountazure_redis_ad_token)inspectgetfullargspecredisRedisargs)arg_specexclude_argsinclude_argsxavailable_argss        `/home/rurouni/.local/share/pipx/venvs/strix-agent/lib/python3.13/site-packages/litellm/_redis.py_get_redis_kwargsr(   "   sT    %%ekk2HL	L "*HA<2GaH<WN Is   	AAc                    U c  [         R                  R                  n [        R                  " [         R                  R                  5      n1 SknS/nUR
                   Vs/ s H  oDU;  d  M
  UPM     snU-   nU$ s  snf )N>   r   r   r   r   )r   r    from_urlr   r   r!   )clientr"   r#   r$   r%   r&   s         r'   _get_redis_url_kwargsr,   <   sn    ~%%%%ekk&:&:;HL 7L!)HA<2GaH<WN Is   !	A<.A<c                     U c  [         R                  R                  n [        R                  " [         R
                  5      n1 SknUR                   Vs1 s H  o3U;  d  M
  UiM     nnU1 Sk-  nU$ s  snf )N>   hostportr   r   startup_nodesr   >   sslpasswordusernamessl_ca_certsssl_cert_reqssocket_timeoutr   r   max_connectionsr   r   ssl_check_hostnamer   r   r   socket_connect_timeout)r   r    r*   r   r   RedisClusterr!   )r+   r"   r#   r%   r&   s        r'   _get_redis_cluster_kwargsr;   O   sn    ~%%%%e&8&89H YL!)HA<2GaNH  N& ) Is   	A2!A2c                  j    Sn [        5        Vs0 s H  o UR                  5        3U_M     sn$ s  snf )NREDIS_)r(   upper)PREFIXr%   s     r'   _get_redis_env_kwarg_mappingr@   n   s6    F/@/BC/B!hqwwyk"A%/BCCCs   0c                  v    [        5       n 0 nU R                  5        H  u  p#[        US S9nUc  M  XAU'   M     U$ )N)default_value)r@   itemsr   )mappingreturn_dictkvvalues        r'   _redis_kwargs_from_environmentrI   t   sB    *,GK1D1"N       service_accountr4   returnc                    ^  U 4S jnU$ )aU  
Creates a custom Redis connection function for GCP IAM authentication.

Args:
    service_account: GCP service account in format 'projects/-/serviceAccounts/name@project.iam.gserviceaccount.com'
    ssl_ca_certs: Path to SSL CA certificate file for secure connections

Returns:
    A connection function that can be used with Redis clients
c                   > SSK JnJn  SSKJn  U R
                  R                  U 5        [        T5      4nU R                  " S/UQ7SS06   U R                  5       nU" U5      S	:w  a  U" S
5      eg! U aQ    [        U S5      (       a>  U R                  (       a-  U R                  SU R                  SS9  U R                  5       n Nje f = f)z8Initialize the connection and authenticate using GCP IAMr   AuthenticationError$AuthenticationWrongNumberOfArgsErrorstr_if_bytesAUTHcheck_healthFr2   rU   OKzGCP IAM authentication failedN)redis.exceptionsrP   rQ   redis.utilsrS   _parser
on_connectr   send_commandread_responsehasattrr2   )r   rP   rQ   rS   	auth_argsauth_responserK   s         r'   iam_connect6create_gcp_iam_redis_connect_func.<locals>.iam_connect   s    	
 	-%3ODF	&A9A5A	 ..0M &$.%&EFF / 4 	tZ((T]]!!&$--e!L $ 2 2 4	s   A3 3AC
C
 )rK   r4   ra   s   `  r'   !create_gcp_iam_redis_connect_funcrd      s    G4 rJ   r   r   r   c                     SSK JnJnJn  U =(       d    [
        R                  R                  S5      nU=(       d    [
        R                  R                  S5      nU=(       d    [
        R                  R                  S5      nU(       a  U(       a  U(       a  U" UUUS9$ U(       a  U" US9$ U" 5       $ ! [         a    [	        S5      ef = f)	z
Build a long-lived Azure credential object.

Azure SDK credentials cache tokens internally and handle expiry/refresh
transparently, so this should be called once and the result reused.
r   )ClientSecretCredentialDefaultAzureCredentialManagedIdentityCredentialziazure-identity is required for Azure AD Redis authentication. Install it with: pip install azure-identityAZURE_CLIENT_IDAZURE_TENANT_IDAZURE_CLIENT_SECRET)	client_id	tenant_idclient_secret)rl   )azure.identityrf   rg   rh   ImportErrorosenvironget)	r   r   r   rf   rg   rh   
_client_id
_tenant_id_client_secrets	            r'   _build_azure_credentialrw      s    

	
 	
 !EBJJNN3D$EJ EBJJNN3D$EJ(QBJJNN;P,QNj^%  (
 	

 
(:>>%'''  
:
 	

s   
B5 5Cc                 Z    [        U UUS9nUR                  [        5      nUR                  $ )u  
One-shot helper that builds a credential and fetches a single Azure AD
access token for Redis. Each call rebuilds the credential and performs a
network round-trip, so it should not be used in steady-state Redis flows
— the sync (``create_azure_ad_redis_connect_func``) and async paths
(``AzureADCredentialProvider``) keep the credential alive across
connections so the Azure SDK's internal cache + silent refresh apply.
r   r   r   )rw   	get_tokenAZURE_REDIS_SCOPEtoken)r   r   r   
credentialr|   s        r'   _generate_azure_ad_redis_tokenr~      s4     )''/J
   !23E;;rJ   c                 8   ^ [        U UUS9mU4S jnTUl        U$ )u2  
Creates a custom Redis connection function for Azure AD authentication.

Used for sync Redis clients. The credential is created once (captured by the
closure) and reused across connections — the Azure SDK handles token caching
and silent renewal internally. Only ``get_token`` is called per connection.
ry   c                   > SSK JnJn  SSKJn  U R
                  R                  U 5        TR                  [        5      R                  n[        R                  R                  SS5      nU(       a  XT4nOU4nU R                  " S/UQ7SS06   U R                  5       nU" U5      S
:w  a  U" S5      eg! U a$    U R                  SUSS	9  U R                  5       n N>f = f)z9Initialize the connection and authenticate using Azure ADr   rO   rR   REDIS_USERNAME rT   rU   FrV   rW   z(Azure AD authentication failed for RedisN)rX   rP   rQ   rY   rS   rZ   r[   rz   r{   r|   rq   rr   rs   r\   r]   )	r   rP   rQ   rS   access_tokenr3   r_   r`   r}   s	           r'   
ad_connect6create_azure_ad_redis_connect_func.<locals>.ad_connect   s    	
 	-%!++,=>DD ::>>"2B7!0I%I&A9A5A	1 ..0M &$.%&PQQ / 4 	1flG ..0M	1s   B4 4'CC)rw   _azure_credential)r   r   r   r   r}   s       @r'   "create_azure_ad_redis_connect_funcr      s/     )''/JRH $.J rJ   c                     S[         R                  ;   a  [         R                  S   $ S[         R                  ;  d  S[         R                  ;  a  [        S5      eS[         R                  ;   a(  [         R                  S   R                  5       S:X  a  Sn OSn S	nS
[         R                  ;   a?  S[         R                  ;   a+  [         R                  S
    S[         R                  S    S3nO*S[         R                  ;   a  [         R                  S    S3nU  SU [         R                  S    S[         R                  S    3$ )N	REDIS_URL
REDIS_HOST
REDIS_PORTzUEither 'REDIS_URL' or both 'REDIS_HOST' and 'REDIS_PORT' must be specified for Redis.	REDIS_SSLtrueredissr   r   r   REDIS_PASSWORD:@z://)rq   rr   
ValueErrorlower)redis_protocol	auth_parts     r'   get_redis_url_from_environmentr   "  s   bjj zz+&&2::%RZZ)Gc
 	
 bjj RZZ%<%B%B%D%N!  I2::%*:bjj*Hzz"234AbjjAQ6R5SSTU		RZZ	'zz"234A6	SBJJ|,D+EQrzzR^G_F`aarJ   c                  |   U R                  5        HU  u  p[        U[        5      (       d  M  UR                  S5      (       d  M4  UR	                  SS5      n[        U5      nX0U'   MW     0 [        5       EU EnUR                  SS5      =(       d    [        S5      nUb/  [        U[        5      (       a  [        R                  " U5      US'   OUc  UR                  SS5        UR                  SS5      =(       d    [        S5      nUb.  [        U[        5      (       a  [        R                  " U5      US'   UR                  SS5      =(       d    [        S	5      nUb  XtS'   UR                  S
S5      =(       d    [        S5      nUb  XS
'   UR                  S5      =(       d    [        S5      n	UR                  S5      =(       d    [        S5      n
U	bq  [        R                  " S5        [        XS9US'   XS   l        UR                  SS5        UR                  SS5        U
(       a  UR                  SS5      (       a  XS'   UR                  S5      =(       d    [        S5      nUSL=(       a    [        U5      R!                  5       S:H  nU(       a  U	b  [        R"                  " S5        U(       a  U	c  UR                  S5      =(       d    [        S5      nUR                  S5      =(       d    [        S5      nUR                  S5      =(       d    [        S5      n[        R                  " S 5        [%        UUUS!9US'   S"US   l        UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS5        S#U;   af  US#   b`  UR                  S5      (       dH  UR                  S$S5        UR                  S%S5        UR                  S&S5        UR                  S'S5        U$ SU;   a	  US   b   U$ SU;   a	  US   b   U$ S$U;  d  US$   c  [)        S(5      eU$ ))zG
Common functionality across sync + async redis client implementations
zos.environ/r   r0   NREDIS_CLUSTER_NODESsentinel_nodesREDIS_SENTINEL_NODESsentinel_passwordREDIS_SENTINEL_PASSWORDservice_nameREDIS_SERVICE_NAMEr   REDIS_GCP_SERVICE_ACCOUNTr   REDIS_GCP_SSL_CA_CERTSzASetting up GCP IAM authentication for Redis with service account.)rK   r4   r   r1   Fr4   r   REDIS_AZURE_AD_TOKENr   zBoth GCP IAM (gcp_service_account) and Azure AD (azure_redis_ad_token) are configured for Redis. Using GCP IAM. Remove one to avoid misconfiguration.r   ri   r   rj   r   rk   z-Setting up Azure AD authentication for Redis.ry   Tr   r.   r/   dbr2   z3Either 'host' or 'url' must be specified for redis.)rC   
isinstancestr
startswithreplacer   rI   rs   jsonloadspopr   r   debugrd   _gcp_service_accountr   warningr   _azure_redis_ad_tokenr   )env_overridesrF   rG   rH   redis_kwargs_startup_nodes_sentinel_nodes_sentinel_password_service_namer   _gcp_ssl_ca_certsr   _azure_ad_enabled_azure_client_id_azure_tenant_id_azure_client_secrets                   r'   _get_redis_client_logicr   :  s   
 ##%a!,,}"="=		-,AqME$!	 &
(
*
L
 2>1A1A/SW1X 2\f]N !j&E&E(,

>(B_%		$/2>2B2BCSUY2Z 3^h_O "z/3'G'G)-O)D%&(4(8(8T) )3	1	2  %,>()#/#3#3ND#I $ZNM  '4^$ (++,AB n#G %(();<  A 'O	
 .O0.
)* CW)*? 	.5+T2 !1!1%!?!?+<( ),,-CD 
I
 	T) 	9%&,,.&8 
 1=C	

 19'++,=> 
.C
 (++,=> 
.C
  ,//! 
  312 	 	LM-O,, 4.
)* DH)*@ +T2&-&-*D1e!4!@ 00VT*VT*T4(Z.  
L	(\/-J-V  	L(\:J-K-W
 	 
|	#|F';'CNOO rJ   c                    [        S5      nUb   [        R                  " U5      U S'   [
        R                  " S5        SSKJn  [        5       n0 nU  H  nXS;   d  M
  X   XE'   M     / nU S    H  nUR                  U" S0 UD65        M     UR                  SS 5        [        R                  " SSU0UD6$ ! [        R                   a    [	        S5      ef = f)Nr   r0   zbREDIS_CLUSTER_NODES environment variable is not valid JSON. Please ensure it's properly formatted.z8init_redis_cluster: startup nodes are being initialized.r   ClusterNoderc   )r   r   r   JSONDecodeErrorr   r   r   redis.clusterr   r;   appendr   r   r:   )r   _redis_cluster_nodes_in_envr   r!   cluster_kwargsargnew_startup_nodesitems           r'   init_redis_clusterr     s    1;<Q1R".	,0JJ7R,SL) ST)$&DN;"."3N  ,._-  !4t!45 . -P,=PPP) ## 	t 	s   B6 6 Cr   c                 J    0 n[        5       nU  H  nX2;   d  M
  X   X'   M     U$ N)r(   )r   connection_kwargsr!   r   s       r'   %_get_redis_sentinel_connection_kwargsr     s3    D;%1%6"  rJ   c                 v   U R                  S5      nU R                  S5      nU R                  S5      n[        U 5      nUR                  S[        5        [	        U5      nX%S'   U(       a  U(       d  [        S5      e[        R                  " S5        [        R                  " UUS9nUR                  " U40 UD6$ 	Nr   r   r   r6   r2   zIBoth 'sentinel_nodes' and 'service_name' are required for Redis Sentinel.z:init_redis_sentinel: sentinel nodes are being initialized.)sentinel_kwargs)rs   r   
setdefaultr   dictr   r   r   r   Sentinel
master_forr   r   r   r   r   r   sentinels          r'   _init_redis_sentinelr     s    !%%&67N$(()<=##N3L=lK  !13GH,-O"3JW
 	
 UV ~~'H |A/@AArJ   c                 v   U R                  S5      nU R                  S5      nU R                  S5      n[        U 5      nUR                  S[        5        [	        U5      nX%S'   U(       a  U(       d  [        S5      e[        R                  " S5        [        R                  " UUS9nUR                  " U40 UD6$ r   )rs   r   r   r   r   r   r   r   async_redisr   r   r   s          r'   _init_async_redis_sentinelr   	  s    !%%&67N$(()<=##N3L=lK  !13GH,-O"3JW
 	
 UV ##'H |A/@AArJ   c                  0   [        S0 U D6nSU;   a  [        U5      $ SU;   aH  US   bB  [        5       n0 nU H  nXB;   d  M
  X   X4'   M     [        R                  R
                  " S0 UD6$ SU;   a  SU;   a  [        U5      $ [        R                  " S0 UD6$ )Nr0   r   r   r   rc   )r   r   r,   r   r    r*   r   )r   r   r!   
url_kwargsr   s        r'   get_redis_clientr   $  s    *;];L,&!,//e!4!@$&
C{"."3
   {{##1j11 <'Nl,J#L11;;&&&rJ   r   c                 4   [        S0 UD6nSU;   Ga  SSKJn  [        5       n0 nU H  nXd;   d  M
  X&   XV'   M     UR	                  SS 5      nU(       a*  [        US5      (       a  [        UR                  5      US'   OUU(       aN  [        US5      (       a=  [        UR                  [        R                  R                  S5      =(       d    S S	9US'   / nUS    H  n	UR                  U" S0 U	D65        M     UR	                  SS 5        [        R                  " SSU0UD6n
U
$ S
U;   a  US
   b  U b  [        R                   " U S9$ [#        [        R                   R$                  S9n0 nU H5  nXd;   a  X&   X'   M  [&        R(                  " SR+                  U5      5        M7     [        R                   R$                  " S0 UD6$ SU;   a  SU;   a  [-        U5      $ UR	                  SS 5      nU(       aO  [        US5      (       a>  [        UR                  [        R                  R                  S5      =(       d    S S	9US'   O0U(       a)  [        US5      (       a  [        UR                  5      US'   [/        US9  U b  XS'   [        R                   " S0 UD6$ )Nr0   r   r   r   r   credential_providerr   r   r3   r   )r   )r+   zLREDIS: ignoring argument: {}. Not an allowed async_redis.Redis.from_url arg.r   r   )r   r   rc   )r   r   r   r;   r   r^   r
   r   r	   r   rq   rr   rs   r   r   r:   r    r,   r*   r   r   formatr   _pretty_print_redis_config)r   r   r   r   r!   r   r   r   r   r   cluster_clientr   s               r'   get_redis_async_clientr   :  s    +;];L,&-(*C{&2&7#  
 ,//0DdK
 '*<>T"U"U4L"775N01  G,>@S$T$T4M"44(89AT5N01
 02 1D$$[%84%89 2?D1 %11 
+
/=
 e!4!@&$$_EE$K,=,=,F,FG
C{"."3
$$bii	     ))7J77 <'Nl,J),77 &))*>Eg&8:MNN.G00ZZ^^$45=/
*+ 
(:<R S S.F33/
*+ L9"*9&' 
 rJ   c                  6   [        S0 U D6n[        R                  " SU5        SU;   a  g SU;   aJ  US   bD  [        US   S.nSU;   a   [	        US   5      US'   [        R                  R                  " S0 UD6$ UR                  SS 5      nU(       aO  [        US5      (       a>  [        UR                  [        R                   R#                  S	5      =(       d    S S
9US'   O0U(       a)  [        US5      (       a  [%        UR&                  5      US'   [        R(                  nSU;   a&  [        R*                  nUR                  SS 5        XAS'   [        R                  " SS[        0UD6$ ! [
        [        4 a    [        R                  " SUS   5         GN=f = f)Nz'get_redis_connection_pool: redis_kwargsr0   r   )timeoutr   r7   z1REDIS: invalid max_connections value %r, ignoringr   r   r   r   r   r   r1   connection_classr   rc   )r   r   r   r   int	TypeErrorr   r   r   BlockingConnectionPoolr*   r   r^   r	   r   rq   rr   rs   r
   r   
ConnectionSSLConnection)r   r   pool_kwargsr   r   s        r'   get_redis_connection_poolr     s    +;];LBLQ,&e!4!@4&
 ,14\BS5T1U-. 11::I[II
 &))*>Eg&8:MNN.G00ZZ^^$45=/
*+ 
(:<R S S.F33/
*+ #--&44%+;'(-- -1= 5 z* &&G !23s   	E* **FFc                     SSK nSSKJn  SSKJn  SSKJn  SSKJn  [        R                  " UR                  5      (       d  gU" 5       n[        5       nUR                  U 5      nU" SSS	9n	U" S
SSSS9n
U
R                  SSSS9  U
R                  SSS	9  UR                  5        H  u  pUc  M
  [!        U["        5      (       aF  US:X  a  U(       a  S[%        U5       S3nO4US:X  a  U(       a  S[%        U5       S3nO['        U5      nO['        U5      nU
R)                  X5        M     SnUR+                  S5      (       a  SnO1UR+                  S5      (       a  SnOUR+                  S5      (       a  SnU" SSSSS9nUR                  S SSS9  UR                  SSS	9  UR)                  S!U5        UR-                  S"5        UR-                  U" U	S#S$95        UR-                  U5        UR-                  U
5        UR-                  S"5        g! [.         a7    [        5       nUR                  U 5      n[        R0                  " S%U 35         g[2         a#  n[        R4                  " S&U 35         SnAgSnAff = f)'zKPretty print the Redis configuration using rich with sensitive data maskingr   N)Console)Panel)Table)TextzRedis Configurationz	bold blue)styleu    🔧 Redis Connection ParametersTzbold magentaleft)titleshow_headerheader_styletitle_justify	Parametercyan)r   no_wrapValueyellowr0   [z cluster nodes]r   z sentinel nodes]zStandard RediszRedis ClusterzRedis Sentinelr   zRedis (URL-based)u   📊 Connection Infoz
bold greenPropertyzConnection Type
blue)border_stylezRedis configuration: z+Error pretty printing Redis configuration: )loggingrich.consoler   
rich.panelr   
rich.tabler   	rich.textr   r   isEnabledForDEBUGr   	mask_dict
add_columnrC   r   listlenr   add_rowrs   printrp   info	Exceptionerror)r   r   r   r   r   r   consolemaskermasked_redis_kwargsr   config_tablekeyrH   	value_strconnection_type
info_tablees                    r'   r   r     sp   SP($$"**7==99) %& %..|< *+> 4' 	
 	64Hx8 .335JC eT**o-%&'E
|?$C	 00U&'E
|3C$D	$'J	 #E
I$$S4 6$ +""?33-O $$%566.O $$U++1O (% 	

 	jEgX6,o> 	deE78j!l#d K$&$..|<34G3HIJ PJ1#NOOPs,   AH A)H 1EH >I;	I;I66I;r   )NNN)3r   r   rq   typingr   r   r   r   r   redis.asyncioasyncior   litellmr   r   "litellm._redis_credential_providerr	   r
   r   litellm.constantsr   r   0litellm.litellm_core_utils.sensitive_data_maskerr   _loggingr   r{   r(   r,   r;   r@   rI   r   rd   rw   r~   r   r   r   r:   r   r   r   r    r   r   r   r   r   r   r   rc   rJ   r'   <module>r!     s     
 2 2  # . 
 R P $6 4&>D #'))3-) )Z &*%))-$(c]$(c]$( "#$(P &*%))-c]c] "# 		. &*%))-7c]7c]7 "#7 	7tb0K\Q(:(: Q8  B%++ B6B0A0A B6'. EIYk@@AY ;k6667Yx-k001-`UPT UPd UPrJ   