o
    ưi                     @   s  d dl Z d dlZd dl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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mZmZ d dlmZ d d	lmZm Z  erkd d
l!m"Z" d dl#m$Z$ neZ$eZ"G dd deZ%G dd de&Z'G dd dZ(dS )    N)datetime)
TYPE_CHECKINGAnyDictListLiteralOptionalTupleUnioncastget_args)	BaseModel)verbose_logger)	DualCache)#BEDROCK_EMBEDDING_PROVIDERS_LITERAL BEDROCK_INVOKE_PROVIDERS_LITERALBEDROCK_MAX_POLICY_SIZE)tracer)
get_secretget_secret_str)AWSPreparedRequestCredentialsc                   @   s*   e Zd ZU eed< eed< ee ed< dS )Boto3CredentialsInfocredentialsaws_region_nameaws_bedrock_runtime_endpointN)__name__
__module____qualname__r   __annotations__strr    r"   r"   X/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/bedrock/base_aws_llm.pyr   (   s   
 r   c                       s   e Zd Z fddZ  ZS )AwsAuthErrorc                    s@   || _ || _tjddd| _tj|| jd| _t | j d S )NPOSTz0https://us-west-2.console.aws.amazon.com/bedrock)methodurl)status_coderequest)	r(   messagehttpxRequestr)   Responseresponsesuper__init__)selfr(   r*   	__class__r"   r#   r0   /   s   zAwsAuthError.__init__)r   r   r   r0   __classcell__r"   r"   r2   r#   r$   .   s    r$   c                       s  e Zd Zdh fddZdideeeef  fddZde	eee f defd	d
Z
e 											djdee dee dee dee dee dee dee dee dee dee deeeef  fddZdee dee fddZededee fddZededee fddZeded ee dedefd!d"Zeded#edefd$d%Zed&edefd'd(Zededee fd)d*Z		dkdedee d&ee defd+d,Z	didee fd-d.Zed/edeeeeef  fd0d1Z	didedeeeef  defd2d3Ze 		dkdedededee dee dee deeeef  deeee f fd4d5Z 			dld6ededed7ed8edee dee deeeef  defd9d:Z!			dldeded7edee dee deeeef  defd;d<Z"d=edeeee f fd>d?Z#e 				dmdee dee dee dededee dee dee deeeef  deeee f fd@dAZ$e dedeeee f fdBdCZ%e dedededeeee f fdDdEZ&e dededee deeee f fdFdGZ'e deeee f fdHdIZ(e defdJdKZ)	LdndMee dNee dedOee*dP  deeef f
dQdRZ+dOee*dP  dedefdSdTZ,	didedee de-fdUdVZ.e 	didWededXee dYedZeee/f d[ed\ee de0fd]d^Z1d[edefd_d`Z2				dmdae*db d[ededcedMedee ddee deee d\ee deeee/ f fdfdgZ3  Z4S )o
BaseAWSLLMreturnNc                    s    t  | _t   g d| _d S )N)aws_access_key_idaws_secret_access_keyaws_session_tokenr   aws_session_nameaws_profile_nameaws_role_nameaws_web_identity_tokenaws_sts_endpointr   aws_external_id)r   	iam_cacher/   r0   aws_authentication_paramsr1   r2   r"   r#   r0   <   s   
zBaseAWSLLM.__init__
ssl_verifyc                 C   s   ddl m} ||dS )av  
        Get SSL verification setting for boto3 clients.

        This ensures that custom CA certificates are properly used for all AWS API calls,
        including STS and Bedrock services.

        Returns:
            Union[bool, str]: SSL verification setting - False to disable, True to enable,
                            or a string path to a CA bundle file
        r   )get_ssl_verifyrC   )Z&litellm.llms.custom_httpx.http_handlerrD   )r1   rC   rD   r"   r"   r#   _get_ssl_verifyM   s   
zBaseAWSLLM._get_ssl_verifycredential_argsc                 C   s    t j|dd}t|  S )zP
        Generate a unique cache key based on the credential arguments.
        T)	sort_keys)jsondumpshashlibsha256encode	hexdigest)r1   rG   Zcredential_strr"   r"   r#   get_cache_key\   s   zBaseAWSLLM.get_cache_keyr7   r8   r9   r   r:   r;   r<   r=   r>   r?   c                 C   s@  |||||||||	|
g
}t |D ]6\}}|r-|dr-t|}|dur,t|tr,|||< q|du rF| j| }| tjv rFt	| ||< q|\
}}}}}}}}}	}
t
d|||||||||	|
 dd t  D }| |}| j|}|r{|S |dur|dur|dur| j|||||	|
d\}}n|dur| j||drt
d| |  \}}nht
d	 |du rd
tt   }| j|||||||	|
|d	\}}nC|dur| |\}}n7|dur|dur|dur| j|||d\}}n |dur|dur|dur| j|||d\}}n|  \}}| jj|||d |S )z3
        Return a boto3.Credentials object
        zos.environ/Nzin get credentials
aws_access_key_id=%s
aws_secret_access_key=%s
aws_session_token=%s
aws_region_name=%s
aws_session_name=%s
aws_profile_name=%s
aws_role_name=%s
aws_web_identity_token=%s
aws_sts_endpoint=%s
aws_external_id=%sc                 S   s(   i | ]\}}| d s|dkr||qS )Zaws_rC   )
startswith).0kvr"   r"   r#   
<dictcomp>   s    z.BaseAWSLLM.get_credentials.<locals>.<dictcomp>)r=   r<   r:   r   r>   r?   rE   z<Already running as target role %s, using ambient credentialsz2Using role assumption: calling _auth_with_aws_rolezlitellm-session-)	r7   r8   r9   r<   r:   r   r>   r?   rC   r7   r8   r9   )r7   r8   r   )ttl)	enumeraterP   r   
isinstancer!   rA   upperosenvirongetenvr   debuglocalsitemsrO   r@   Z	get_cache_auth_with_web_identity_token_is_already_running_as_role_auth_with_env_varsintr   now	timestamp_auth_with_aws_role_auth_with_aws_profile_auth_with_aws_session_token$_auth_with_access_key_and_secret_keyZ	set_cache)r1   r7   r8   r9   r   r:   r;   r<   r=   r>   r?   rC   Zparams_to_checkiparam_vkeyargs	cache_keyZ_cached_credentialsr   Z
_cache_ttlr"   r"   r#   get_credentialsd   s   





zBaseAWSLLM.get_credentialsmodelc                 C   sb   z&t |tr
d|vrW d S |d}t|dk rW d S |d }|s$W d S |W S  ty0   Y d S w )Nzarn:aws:bedrock:      )rX   r!   splitlen	Exception)r1   rq   partsregionr"   r"   r#   _get_aws_region_from_model_arn  s   
z)BaseAWSLLM._get_aws_region_from_model_arn
model_pathc                 C   s8   |  d}t|dkr|d }|ttv rtt|S dS )at  
        Helper function to get the provider from a model path with format: provider/model-name

        Args:
            model_path (str): The model path (e.g., 'llama/arn:aws:bedrock:us-east-1:086734376398:imported-model/r4c4kewx2s0n' or 'anthropic/model-name')

        Returns:
            Optional[str]: The provider name, or None if no valid provider found
        /   r   N)ru   rv   r   r   r   )r{   rx   providerr"   r"   r#   _get_provider_from_model_path$  s   

z(BaseAWSLLM._get_provider_from_model_pathc                 C   s   |  dr| ddd} d|  v rdttv rttdS | dd }|ttv r/tt|S t| }|dur:|S ttD ]
}|| v rH|  S q>dS )a  
        Helper function to get the bedrock provider from the model

        handles 3 scenarions:
        1. model=invoke/anthropic.claude-3-5-sonnet-20240620-v1:0 -> Returns `anthropic`
        2. model=anthropic.claude-3-5-sonnet-20240620-v1:0 -> Returns `anthropic`
        3. model=llama/arn:aws:bedrock:us-east-1:086734376398:imported-model/r4c4kewx2s0n -> Returns `llama`
        4. model=us.amazon.nova-pro-v1:0 -> Returns `nova`
        invoke/ r}   nova.r   N)	rP   replacelowerr   r   r   ru   r5   r   )rq   Z_split_modelr~   r"   r"   r#   get_bedrock_invoke_provider8  s    



z&BaseAWSLLM.get_bedrock_invoke_provideroptional_paramsr~   c                 C   sV  |  dd }|d urtj|d}n|}|ddd}|dkr+d|v r+tj|dd}|S |d	kr<d
|v r<tj|d	d}|S |dkrMd|v rMtj|dd}|S |dkr^d|v r^tj|dd}|S |dkrod|v rotj|dd}|S |dkrd|v rtj|dd}|S |dkrd|v rtj|dd}|S d|v rtj|dd}|S d|v rtj|dd}|S )Nmodel_idr   r   r   r}   llamazllama/)specZdeepseek_r1zdeepseek_r1/Zopenaizopenai/Zqwen2zqwen2/Zqwen3zqwen3/Z	stabilityz
stability/Zmoonshotz	moonshot/znova-2/znova-2znova/r   )popr5   encode_model_idr   "_get_model_id_from_model_with_spec)r   r~   rq   r   r"   r"   r#   get_bedrock_model_id\  sd   #zBaseAWSLLM.get_bedrock_model_idr   c                 C   s   |  |d d}tj|dS )zp
        Remove `llama` from modelID since `llama` is simply a spec to follow for custom bedrock models
        r|   r   r   )r   r5   r   )rq   r   r   r"   r"   r#   r     s   z-BaseAWSLLM._get_model_id_from_model_with_specr   c                 C   s   t jj| ddS )z
        Double encode the model ID to ensure it matches the expected double-encoded format.
        Args:
            model_id (str): The model ID to encode.
        Returns:
            str: The double-encoded model ID.
        r   )safe)urllibparsequoter   r"   r"   r#   r     s   	zBaseAWSLLM.encode_model_idc                 C   s   d|   v rdttv rttdS d| v r>| d}t|dkr/|d }|ttv r/tt|S |d }|ttv r>tt|S ttD ]}|| v rOtt|  S qBdS )a  
        Helper function to get the bedrock embedding provider from the model

        Handles scenarios like:
        1. model=cohere.embed-english-v3:0 -> Returns `cohere`
        2. model=amazon.titan-embed-text-v1 -> Returns `amazon`
        3. model=amazon.nova-2-multimodal-embeddings-v1:0 -> Returns `nova`
        4. model=us.twelvelabs.marengo-embed-2-7-v1:0 -> Returns `twelvelabs`
        5. model=twelvelabs.marengo-embed-2-7-v1:0 -> Returns `twelvelabs`
        r   r      r}   r   N)r   r   r   r   ru   rv   )rq   rx   Zpotential_providerr~   r"   r"   r#   get_bedrock_embedding_provider  s*   



z)BaseAWSLLM.get_bedrock_embedding_providerc           
      C   s   | dd}|du rA|dur| |}n| |}tdd}|du r-|dur-t|tr-|}tdd}|du rA|durAt|trA|}|du r~z,ddl}td | }W d   n1 s^w   Y  |j	}	|	rm|	}W |S d}W |S  t
y}   d}Y |S w |S )ar  
        Get the AWS region name from the environment variables.

        Parameters:
            optional_params (dict): Optional parameters for the model call
            model (str): The model name
            model_id (str): The model ID. This is the ARN of the model, if passed in as a separate param.

        Returns:
            str: The AWS region name
        r   NAWS_REGION_NAME
AWS_REGIONr   boto3.Session()	us-west-2)getrz   r   rX   r!   boto3r   traceSessionregion_namerw   )
r1   r   rq   r   r   litellm_aws_region_namestandard_aws_region_namer   sessionZconfigured_regionr"   r"   r#   _get_aws_region_name  sD   



zBaseAWSLLM._get_aws_region_namec                 C   sX   |du r*t dd}|durt|tr|}t dd}|dur$t|tr$|}|du r*d}|S )a  
        Get the AWS region name for non-llm api calls.

        LLM API calls check the model arn and end up using that as the region name.

        For non-llm api calls eg. Guardrails, Vector Stores we just need to check the dynamic param or env vars.
        Nr   r   r   )r   rX   r!   )r1   r   r   r   r"   r"   r#   )get_aws_region_name_for_non_llm_api_calls  s   



z4BaseAWSLLM.get_aws_region_name_for_non_llm_api_callsarnc                 C   s   |  d}t|dk s|d dkrdS |d }|d }d|dd }|d	r1| d
d }n|drH| d
}t|dkrF|d }ndS dS |||fS )a?  
        Parse an ARN and return (partition, account_id, role_name).

        Handles:
        - arn:aws:iam::123456789012:role/MyRole
        - arn:aws:iam::123456789012:role/path/to/MyRole
        - arn:aws:sts::123456789012:assumed-role/MyRole/session-name

        Returns None if the ARN cannot be parsed.
        rr      r   r   Nr}   rs      zrole/r|   zassumed-role/r   )ru   rv   joinrP   )r   rx   	partitionZ
account_idresourceZ	role_nameZ
role_partsr"   r"   r#    _parse_arn_account_and_role_name*  s   





z+BaseAWSLLM._parse_arn_account_and_role_namec              
   C   s4  |  |}|du rdS |\}}}td}td}|r"|r"||kS z\ddl}	td |	jd| |d}
|
 }|	d	d
}W d   n1 sKw   Y  |  |}|durs|\}}}||krv||kry||kr|t
d| W dS W dS W dS W dS W dS  ty } zt
dt| W Y d}~dS d}~ww )ay  
        Check if the current environment is already running as the target IAM role.

        This handles multiple AWS environments:
        - IRSA (EKS): AWS_ROLE_ARN + AWS_WEB_IDENTITY_TOKEN_FILE are set
        - ECS task roles: Uses sts:GetCallerIdentity to check current role ARN
        - EC2 instance profiles: Uses sts:GetCallerIdentity to check current role ARN

        Compares partition, account ID, and role name to avoid cross-account
        false matches.

        Returns True if the current identity matches the target role, meaning
        we can skip sts:AssumeRole and use ambient credentials directly.
        NFAWS_ROLE_ARNAWS_WEB_IDENTITY_TOKEN_FILEr   z%boto3.client(sts).get_caller_identitysts)verifyArnr   z0Current identity already matches target role: %sTz-Could not determine current role identity: %s)r   rZ   r\   r   r   r   clientrF   get_caller_identityr   r   r]   rw   r!   )r1   r<   rC   Ztarget_parsedZtarget_partitionZtarget_accountZtarget_roleZcurrent_role_arnweb_identity_token_filer   
sts_clientidentityZ
caller_arnZcaller_parsedZcaller_partitionZcaller_accountZcaller_roleer"   r"   r#   ra   P  sV   






z&BaseAWSLLM._is_already_running_as_rolec                 C   s`  ddl }td| d| d|  |du rd| d}	n|}	t|}
|
du r-tdd	d
td |jd||	| |d}W d   n1 sIw   Y  |||
ddd}|dur^||d< |j	di |}|d d |d d |d d |d}|d t
krtd|d   td |jdi |}W d   n1 sw   Y  | }||  fS )z:
        Authenticate with AWS Web Identity Token
        r   NzIN Web Identity Token: z | Role Name: z | Session Name: zhttps://sts..amazonaws.comz6OIDC token could not be retrieved from secret manager.i  )r*   r(   boto3.client(sts)r   )r   endpoint_urlr   i  a  {"Version":"2012-10-17","Statement":[{"Sid":"BedrockLiteLLM","Effect":"Allow","Action":["bedrock:InvokeModel","bedrock:InvokeModelWithResponseStream"],"Resource":"*","Condition":{"Bool":{"aws:SecureTransport":"true"},"StringLike":{"aws:UserAgent":"litellm/*"}}}]})RoleArnRoleSessionNameWebIdentityTokenZDurationSecondsPolicy
ExternalIdr   AccessKeyIdSecretAccessKeySessionToken)r7   r8   r9   r   ZPackedPolicySizezKThe policy size is greater than 75% of the allowed size, PackedPolicySize: zboto3.Session(**iam_creds_dict)r"   )r   r   r]   r   r$   r   r   r   rF   assume_role_with_web_identityr   warningr   rp   &_get_default_ttl_for_boto3_credentials)r1   r=   r<   r:   r   r>   r?   rC   r   Zsts_endpointZ
oidc_tokenr   assume_role_paramssts_responseZiam_creds_dictr   Z	iam_credsr"   r"   r#   r`     sX   	


z(BaseAWSLLM._auth_with_web_identity_tokenirsa_role_arnry   r   c	              
   C   s  ddl }	td t|d}
|
  }W d   n1 sw   Y  || |d}|dur4||d< td |	j	di |}W d   n1 sLw   Y  td	| d
|  |j
|||d}|d }td |	j		d|d |d |d d|}W d   n1 sw   Y  z| }td|dd  W n ty } ztd|  W Y d}~nd}~ww td| d|  ||d}|dur||d< |jdi |S )z.Handle cross-account role assumption for IRSA.r   Nz&Cross-account role assumption detectedrr   r   r   z!boto3.client(sts) for manual IRSAr   zManually assuming IRSA role z with session )r   r   r   r   z.boto3.client(sts) with manual IRSA credentialsr   r   r   rU   z/Current identity after manual IRSA assumption: r   unknownFailed to get caller identity: z"Attempting to assume target role:  with session: r   r   r   r   r"   )r   r   r]   openreadstriprF   r   r   r   r   r   r   rw   assume_role)r1   r   r<   r:   ry   r   r?   r>   rC   r   fZweb_identity_tokenirsa_sts_kwargsr   Zirsa_responseZ
irsa_credsZsts_client_with_credscaller_identityr   r   r"   r"   r#   _handle_irsa_cross_account  sb   

z%BaseAWSLLM._handle_irsa_cross_accountc              
   C   s  ddl }|| |d}|dur||d< td td |jdi |}	W d   n1 s1w   Y  z|	 }
td|
d	d
  W n t	yb } ztd|  W Y d}~nd}~ww td| d|  ||d}|dur{||d< |	j
di |S )z-Handle same-account role assumption for IRSA.r   Nr   r   z2Same account role assumption, using automatic IRSAz%boto3.client(sts) with automatic IRSAr   zCurrent IRSA identity: r   r   r   zAttempting to assume role: r   r   r   r   r"   )r   rF   r   r]   r   r   r   r   r   rw   r   )r1   r<   r:   ry   r?   r>   rC   r   r   r   r   r   r   r"   r"   r#   _handle_irsa_same_account%  s4   

z$BaseAWSLLM._handle_irsa_same_accountr   c                 C   sV   ddl m} |d }||d |d |d d}|d }t|t|j  }||fS )	z.Extract credentials and TTL from STS response.r   r   r   r   r   r   Z
access_keyZ
secret_keytoken
Expiration)botocore.credentialsr   rc   r   rd   tzinfototal_seconds)r1   r   r   sts_credentialsr   Zexpiration_timerV   r"   r"   r#   _extract_credentials_and_ttlQ  s   z'BaseAWSLLM._extract_credentials_and_ttlc
              
   C   s  ddl }
ddlm} td}td}|ptdptd}|r|r|du r|du rtd|  z'|p8d	}||krK| j||||||||	d
}n| j||||||	d
}| 	|W S  t
y } z!td|  dt|v rdt|v rtd| d| d  d}~ww d| |	i}|dur||d< |dur||d< |du r|du rtd |
jd#i |}W d   n1 sw   Y  n"td |
j	d#|||d|}W d   n1 sw   Y  ||d}|dur||d< z
|jd$i |}W n7 t
y6 } z*t|}d|v r1| j||	dr*td|| |  W  Y d}~S td||  d}~ww |d }||d |d |d d }|d! }t|j}||  d" }||fS )%z,
        Authenticate with AWS Role
        r   Nr   r   r   r   ZAWS_DEFAULT_REGIONz-IRSA detected: using web identity token from z	us-east-1)r>   rC   z Failed to assume role via IRSA: ZAccessDeniedz,is not authorized to perform: sts:AssumeRolez)Access denied when trying to assume role z$. Please ensure the trust policy of zV allows the current role to assume it. Current identity: check logs with verbose mode.r   r   r   r   r   rU   r   r   rE   zkAssumeRole failed for %s (%s). Caller is already running as this role; falling back to ambient credentials.zUAssumeRole AccessDenied for %s and caller is NOT the same role. Re-raising. Error: %sr   r   r   r   r   r   <   r   r"   )r   r   r   rZ   r\   r   r]   r   r   r   rw   r!   errorrF   r   r   r   r   ra   r   rb   r   rd   r   r   )r1   r7   r8   r9   r<   r:   r   r>   r?   rC   r   r   r   r   ry   r   r   Zsts_client_kwargsr   r   Z	error_strr   r   Z
sts_expirycurrent_timeZsts_ttlr"   r"   r#   rf   e  s   

	

zBaseAWSLLM._auth_with_aws_rolec                 C   sN   ddl }td |j|d}| dfW  d   S 1 s w   Y  dS )z/
        Authenticate with AWS profile
        r   Nz,boto3.Session(profile_name=aws_profile_name))Zprofile_namer   r   r   r   rp   )r1   r;   r   r   r"   r"   r#   rg     s
   
$z!BaseAWSLLM._auth_with_aws_profilec                 C   s"   ddl m} ||||d}|dfS )z5
        Authenticate with AWS Session Token
        r   r   r   N)r   r   )r1   r7   r8   r9   r   r   r"   r"   r#   rh     s   z'BaseAWSLLM._auth_with_aws_session_tokenc                 C   sV   ddl }td |j|||d}W d   n1 sw   Y  | }||  fS )zA
        Authenticate with AWS Access Key and Secret Key
        r   Nz|boto3.Session(aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, region_name=aws_region_name))r7   r8   r   )r   r   r   r   rp   r   )r1   r7   r8   r   r   r   r   r"   r"   r#   ri   "  s   
	z/BaseAWSLLM._auth_with_access_key_and_secret_keyc                 C   sN   ddl }td | }| }|dfW  d   S 1 s w   Y  dS )z=
        Authenticate with AWS Environment Variables
        r   Nr   r   )r1   r   r   r   r"   r"   r#   rb   ;  s   $zBaseAWSLLM._auth_with_env_varsc                 C   s   dS )zj
        Get the default TTL for boto3 credentials

        Returns `3600-60` which is 59 minutes
        i  r"   rB   r"   r"   r#   r   G  s   z1BaseAWSLLM._get_default_ttl_for_boto3_credentialsruntimeapi_baser   endpoint_type)r   agent	agentcorec                 C   s   t d}|d ur|}n|d urt|tr|}n|r!t|tr!|}n| j||d}|d ur7t|tr7|}||fS |rDt|trD|}||fS |}||fS )NZAWS_BEDROCK_RUNTIME_ENDPOINT)r   r   )r   rX   r!   _select_default_endpoint_url)r1   r   r   r   r   Z env_aws_bedrock_runtime_endpointr   Zproxy_endpoint_urlr"   r"   r#   get_runtime_endpointP  s6   

zBaseAWSLLM.get_runtime_endpointc                 C   s4   |dkr
d| dS |dkrd| dS d| dS )z
        Select the default endpoint url based on the endpoint type

        Default endpoint url is https://bedrock-runtime.{aws_region_name}.amazonaws.com
        r   zhttps://bedrock-agent-runtime.r   r   zhttps://bedrock-agentcore.zhttps://bedrock-runtime.r"   )r1   r   r   r"   r"   r#   r   v  s
   
z'BaseAWSLLM._select_default_endpoint_urlc                 C   s   zddl m} W n ty   tdw |dd}|dd}|dd}| ||}|dd |d	d}|d
d}	|dd}
|dd}|dd}|dd}|dd}| j|||||	|
||||d
}t|||dS )z
        Get boto3 credentials from optional params

        Args:
            optional_params (dict): Optional parameters for the model call

        Returns:
            Credentials: Boto3 credentials object
        r   r   7Missing boto3 to call bedrock. Run 'pip install boto3'.r8   Nr7   r9   r   r<   r:   r;   r=   r>   r   r?   
r7   r8   r9   r   r:   r;   r<   r=   r>   r?   )r   r   r   )r   r   ImportErrorr   r   rp   r   )r1   r   rq   r   r8   r7   r9   r   r<   r:   r;   r=   r>   r   r?   r   r"   r"   r#   *_get_boto_credentials_from_optional_params  sH   z5BaseAWSLLM._get_boto_credentials_from_optional_paramsr   extra_headersr   dataheadersapi_keyc                 C   s  |d ur|}nt d}|r1zddlm}	 W n ty    tdw d| |d< |	d|||d}
nOzdd	lm} ddlm}	 W n tyJ   tdw | |}||d
|}|	d|||d}
||
 | D ]	\}}||
j	|< qg|d urd|v r|d |
j	d< |

 }|S )NAWS_BEARER_TOKEN_BEDROCKr   
AWSRequestr   Bearer Authorizationr%   r&   r'   r   r   	SigV4Authbedrock)r   botocore.awsrequestr   r   botocore.authr   !_filter_headers_for_aws_signatureadd_authr_   r   prepare)r1   r   r   r   r   r   r   r   aws_bearer_tokenr   r)   r   aws_signature_headerssigv4header_nameheader_valueZpreppedr"   r"   r#   get_request_headers  sL   

zBaseAWSLLM.get_request_headersc                 C   sN   i }h d}|  D ]\}}| }||v s |ds |dr$|||< q
|S )z
        Filter headers to only include those that AWS SigV4 includes in signature calculation.
        This Fixes forwarded client headers from breaking the signature calculation.
        >
   hostz
x-amz-datedatezx-amz-signaturezx-amz-signedheaderszx-amz-credentialzx-amz-content-sha256zx-amz-algorithmzx-amz-security-tokenzcontent-typezx-amz-zx-amzn-)r_   r   rP   )r1   r   r  Zaws_headersr  r  Zheader_lowerr"   r"   r#   r     s   z,BaseAWSLLM._filter_headers_for_aws_signatureservice_name)r   Z	sagemakerzbedrock-agentcoreZ	s3vectorsrequest_datastreamfake_streamc
                 C   s  |	dur|	}
nt d}
|
r%|pi }d|d< d|
 |d< |t| fS zddlm} dd	lm} dd
lm	} W n t
yD   t
dw |dd}|dd}|dd}|dd}|dd}|dd}|dd}|dd}|dd}| j||d}| j||||||||||d
}||||}|durddi|}nddi}| |}|d|t||d}|| t|j}| D ]\}}|||< q|durd|v r|d |d< ||jfS )z
        Sign a request for Bedrock or Sagemaker

        Returns:
            Tuple[dict, Optional[str]]: A tuple containing the headers and the json str body of the request
        Nr   zapplication/jsonzContent-Typer   r   r   r   r   r   r   r8   r7   r9   r<   r:   r;   r=   r>   r?   )r   rq   r   r%   r   )r   rI   rJ   rM   r   r   r   r   r   r   r   r   r   rp   r   r   dictr   r_   body)r1   r	  r   r   r
  r   rq   r  r  r   r  r   r   r   r8   r7   r9   r<   r:   r;   r=   r>   r?   r   r   r  r  r)   Zrequest_headers_dictr  r  r"   r"   r#   _sign_request  sr   




zBaseAWSLLM._sign_request)r6   N)N)NNNNNNNNNNN)NN)NNN)NNNN)r   )5r   r   r   r0   r   r
   boolr!   rF   r   rO   r   wraprp   rz   staticmethodr   r   r   r  r   r   r   r   r   r   r   r	   r   ra   r   rc   r`   r   r   r   rf   rg   rh   ri   rb   r   r   r   r   r   r   bytesr   r  r   r  r4   r"   r"   r2   r#   r5   ;   s\   	
 +#2

/
<
(
?	Q	

P
,
	
 


&


4	
	;%	
r5   ))rK   rI   rZ   urllib.parser   r   typingr   r   r   r   r   r   r	   r
   r   r   r+   Zpydanticr   Zlitellm._loggingr   Zlitellm.caching.cachingr   Zlitellm.constantsr   r   r   Z%litellm.litellm_core_utils.dd_tracingr   Zlitellm.secret_managers.mainr   r   r   r   r   r   r   rw   r$   r5   r"   r"   r"   r#   <module>   s*    0