o
    ưi                     @   s  U 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 d dlmZ d dlZd dlZd dlmZ d dlmZmZ d dlmZmZmZmZm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+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6 d d
l7m8Z8 d dl9m:Z:m;Z;m<Z<m=Z=m>Z> d dl?m@Z@mAZAmBZB erd dlCmDZE eEZFneZFG dd deZGeG dd dZHdeIdeJfddZKdd ZLdeJfddZMdeJfddZNdeJde6fdd ZOd!ZPG d"d# d#eZQd$d%d&d'd(ZRe
eJe0f eSd)< d*eJd+eeJeTf de/fd,d-ZUd*eJd.eTde/fd/d0ZVd*eJd1eJd+eJde/fd2d3ZWd4ee8 dee/ fd5d6ZXd7ee
 d8e6fd9d:ZYd7ee4 dee@ fd;d<ZZG d=d> d>eAZ[dS )?    N)	dataclass)	TYPE_CHECKINGAnyAsyncIteratorDictListOptionalProtocolTupleUnion)urlparse)track_llm_api_timing)
BaseConfigBaseLLMException)AsyncHTTPHandlerHTTPHandler_get_httpx_clientget_async_httpx_clientversionOCIError)CohereChatRequestCohereMessageCohereChatResultCohereParameterDefinitionCohereStreamChunk
CohereToolCohereToolCallOCIChatRequestPayloadOCICompletionPayloadOCICompletionResponseOCIContentPartUnionOCIImageContentPartOCIImageUrl
OCIMessageOCIRolesOCIServingModeOCIStreamChunkOCITextContentPartOCIToolCallOCIToolDefinition
OCIVendors)AllMessageValues)DeltaLlmProvidersModelResponseModelResponseStreamStreamingChoices)ChatCompletionMessageToolCallCustomStreamWrapperUsage)Loggingc                   @   s,   e Zd ZdZdddededdfdd	ZdS )
OCISignerProtocola  
    Protocol for OCI request signers (e.g., oci.signer.Signer).

    This protocol defines the interface expected for OCI SDK signer objects.
    Compatible with the OCI Python SDK's Signer class.

    See: https://docs.oracle.com/en-us/iaas/tools/python/latest/api/signing.html
    Fenforce_content_headersrequestr8   returnNc                C   s   dS )a  
        Sign an HTTP request by adding authentication headers.

        Args:
            request: Request object with method, url, headers, body, and path_url attributes
            enforce_content_headers: Whether to enforce content-type and content-length headers
        N )selfr9   r8   r;   r;   [/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/oci/chat/transformation.pydo_request_signM   s   z!OCISignerProtocol.do_request_sign)__name__
__module____qualname____doc__r   boolr>   r;   r;   r;   r=   r6   C   s     	r6   c                   @   sD   e Zd ZU dZeed< eed< eed< eed< edefddZ	d	S )
OCIRequestWrapperz
    Wrapper for HTTP requests compatible with OCI signer interface.

    This class wraps request data in a format compatible with OCI SDK signers,
    which expect objects with method, url, headers, body, and path_url attributes.
    methodurlheadersbodyr:   c                 C   s&   t | j}|j|jrd|j  S d S )z0Returns the path + query string for OCI signing.? )r   rF   pathquery)r<   
parsed_urlr;   r;   r=   path_urle   s   
zOCIRequestWrapper.path_urlN)
r?   r@   rA   rB   str__annotations__dictbytespropertyrN   r;   r;   r;   r=   rD   X   s   
 rD   datar:   c                 C   s   t |  }t| S N)hashlibsha256digestbase64	b64encodedecode)rT   rX   r;   r;   r=   sha256_base64l   s   r\   c                 C   sP   g }|D ]}|dkr|    d| }n|| }|| d|  qd|S )N(request-target) z: 
)lowerappendjoin)rE   rK   rG   signed_headerslinesheadervaluer;   r;   r=   build_signature_stringq   s   
rg   key_strc              
   C   sl   zddl m} ddlm} W n ty } ztd|d }~ww |j| dd d}t||js4t	d|S )Nr   )serialization)rsaicryptography package is required for OCI authentication. Please install it with: pip install cryptographyutf-8)passwordzNThe provided private key is not an RSA key, which is required for OCI signing.)
cryptography.hazmat.primitivesri   )cryptography.hazmat.primitives.asymmetricrj   ImportErrorZload_pem_private_keyencode
isinstanceZRSAPrivateKey	TypeError)rh   ri   rj   ekeyr;   r;   r=   load_private_key_from_str|   s(   rv   	file_pathc              
   C   s   zt | ddd}|  }W d   n1 sw   Y  W n$ ty-   td|   tyC } ztd|  d| |d}~ww |sMtd|  t|S )	z$Loads a private key from a file pathrrl   )encodingNzPrivate key file not found: z!Failed to read private key file 'z': zPrivate key file is empty: )openreadstripFileNotFoundErrorOSError
ValueErrorrv   )rw   frh   rt   r;   r;   r=   load_private_key_from_file   s   r   modelc                 C   s&   |  dd  }|dkrtjS tjS )z
    Extracts the vendor from the model name.
    Args:
        model (str): The model name.
    Returns:
        str: The vendor name.
    .r   Zcohere)splitr`   r+   COHEREZGENERIC)r   vendorr;   r;   r=   get_vendor_from_model   s   r   i,  c                   @   sJ  e Zd ZdZ		dGddZdedee fddZd	ed
edede	def
ddZ
ded
edededeeef f
ddZded
edededeedf f
ddZ				dHded
edededee dee dee	 dee	 deeee f fddZ		dIdededee d
ededee dee defddZ	dJdee dee ded
ededee	 defddZd ed
edefd!d"Zdee dee fd#d$Zd%eeeef  dee fd&d'Zd(edefd)d*Zdedee d
edededefd+d,Zd-eded.edefd/d0Zd1eded.ed2e j!def
d3d4Z"		dIded2e j!d.ed5e#dedee d
eded6edee d7ee	 defd8d9Z$e% 			dKded:ed5e#deded;ede&d<ee'e(e)f  d7ee	 d=ee dd>fd?d@Z*e% 			dKded:ed5e#deded;ede&d<ee'e(e)f  d7ee	 d=ee dd>fdAdBZ+dCedDe,de'ee j-f de.fdEdFZ/dS )LOCIChatConfigz6
    Configuration class for OCI's API interface.
    r:   Nc                 C   s   t   }| D ]\}}|dkr|d urt| j|| q	t| jdd i ddddddd	d	d
d
dddddddddddddddddddddddddddddddddd 	| _| j | _d S )!Nr<   Zhas_custom_stream_wrapperTstreamZisStreamZ
max_tokens	maxTokensZmax_completion_tokenstemperaturetoolsZfrequency_penaltyfrequencyPenaltyZlogprobsZlogProbsZ
logit_biasZ	logitBiasnZnumGenerationsZpresence_penaltyZpresencePenaltyseedstoptool_choiceZ
toolChoiceZtop_ptopPmax_retriesFZtop_logprobsZ
modalitiesresponseFormat)	Z
predictionZstream_optionsZfunction_callZ	functionsextra_headersZparallel_tool_callsZaudioZweb_search_optionsresponse_format)localscopyitemssetattr	__class__openai_to_oci_generic_param_mapopenai_to_oci_cohere_param_map)r<   Zlocals_ru   rf   r;   r;   r=   __init__   sh   
	

zOCIChatConfig.__init__r   c                 C   s\   g }t |}|tjkr| j}|d |d n| j}| D ]\}}|r+|| q |S )Nr   r   )r   r+   r   r   popr   r   ra   )r<   r   Zsupported_paramsr   open_ai_to_oci_param_mapru   rf   r;   r;   r=   get_supported_openai_params   s   


z)OCIChatConfig.get_supported_openai_paramsnon_default_paramsoptional_paramsdrop_paramsc                 C   s   i }t |}|tjkr| j}n| j}i ||}| D ]0\}	}
||	}|du r7|s.tjr/qt	d|	 d|d u r@|
||	< q|
||< |dkrL|
|d< q|S )NFzparam `z` is not supported on OCIr   r   )
r   r+   r   r   r   r   getlitellmr   	Exception)r<   r   r   r   r   Zadapted_paramsr   r   
all_paramsru   rf   aliasr;   r;   r=   map_openai_params   s(   


zOCIChatConfig.map_openai_paramsrG   request_dataapi_basec              
   C   s   | d}t|d}t| dd }|dvr"td| | }|dd |d	tt	| t
||||d
}	|du rFtdz	|j|	dd W n tyh }
 ztddt|
 dd|
d}
~
ww ||	j ||fS )a  
        Sign request using OCI SDK Signer object.

        Args:
            headers: Request headers to be signed
            optional_params: Optional parameters including oci_signer
            request_data: The request body dict to be sent in HTTP request
            api_base: The complete URL for the HTTP request

        Returns:
            Tuple of (signed_headers, encoded_body)

        Raises:
            OCIError: If signing fails
            ValueError: If HTTP method is unsupported
        
oci_signerrl   rE   POST)r   GETPUTDELETEPATCHzUnsupported HTTP method: content-typeapplication/jsoncontent-length)rE   rF   rG   rH   Nz<oci_signer cannot be None when calling _sign_with_oci_signerTr7   i  z1Failed to sign request with provided oci_signer: z. The signer must implement the OCI SDK Signer interface with a do_request_sign(request, enforce_content_headers=True) method. See: https://docs.oracle.com/en-us/iaas/tools/python/latest/api/signing.htmlstatus_codemessage)r   jsondumpsrq   rO   upperr   r   
setdefaultlenrD   r>   r   r   updaterG   )r<   rG   r   r   r   r   rH   rE   Zprepared_headersZrequest_wrapperrt   r;   r;   r=   _sign_with_oci_signer  s:   
z#OCIChatConfig._sign_with_oci_signerc               
   C   s>  | dd}|ptjpd| d}| d}| d}| d}| d}	| d	}
|r4|r4|r4|	s8|
s8td
t| dd }t|d}t	|}|j
pRd}|j}tj d}| dd}tt|}t|}|||||d}g d}t||||}zddlm} ddlm} W n ty } ztd|d}~ww d}|	rt|	tr|	}|dd}d|v r|dd}ntddt|	j d|rt|n|
rt|
nd}|du rtddd||d| |  }t!"|# }| d| d| }d | d!d"$| d#| d$}|%||||||d% |dfS )&a  
        Sign request using manual OCI credentials.

        Args:
            headers: Request headers to be signed
            optional_params: Optional parameters including OCI credentials
            request_data: The request body dict to be sent in HTTP request
            api_base: The complete URL for the HTTP request

        Returns:
            Tuple of (signed_headers, None)

        Raises:
            Exception: If required credentials are missing
            ImportError: If cryptography package is not installed
        
oci_regionus-ashburn-1https://inference.generativeai..oci.oraclecloud.comoci_useroci_fingerprintoci_tenancyoci_keyoci_key_filezqMissing required parameters: oci_user, oci_fingerprint, oci_tenancy, and at least one of oci_key or oci_key_file.rE   r   rl   /z%a, %d %b %Y %H:%M:%S GMTr   r   )datehostr   r   x-content-sha256)r   r]   r   r   r   r   r   )hashes)paddingrk   Nz\nr_   z
i  zKoci_key must be a string containing the PEM private key content. Got type: r   z^Private key is required for OCI authentication. Please provide either oci_key or oci_key_file.zSignature version="1",keyId="z"",algorithm="rsa-sha256",headers="r^   z",signature="")authorizationr   r   r   r   r   )&r   r   r   r   rO   r   r   r   rq   r   rK   netlocdatetimeutcnowstrftimer   r\   rg   rn   r   ro   r   rp   rr   replacer   typer?   rv   r   signZPKCS1v15SHA256rY   rZ   r[   rb   r   ) r<   rG   r   r   r   r   r   r   r   r   r   rE   rH   parsedrK   r   r   content_typecontent_lengthZx_content_sha256Zheaders_to_signrc   Zsigning_stringr   r   rt   Zoci_key_contentZprivate_key	signatureZsignature_b64Zkey_idr   r;   r;   r=   _sign_with_manual_credentialsR  s   








z+OCIChatConfig._sign_with_manual_credentialsapi_keyr   fake_streamc	           
      C   s2   | d}	|	dur| ||||S | ||||S )an  
        Sign the OCI request by adding authentication headers.

        Supports two signing modes:
        1. OCI SDK Signer: Use an oci_signer object to sign the request
        2. Manual Signing: Use OCI credentials to manually sign the request

        Args:
            headers: Request headers to be signed
            optional_params: Optional parameters including auth credentials or oci_signer
            request_data: The request body dict to be sent in HTTP request
            api_base: The complete URL for the HTTP request
            api_key: Optional API key (not used for OCI)
            model: Optional model name
            stream: Optional streaming flag
            fake_stream: Optional fake streaming flag

        Returns:
            Tuple of (signed_headers, encoded_body):
            - If oci_signer is provided: Returns (headers, body) where body is the encoded JSON
            - If manual credentials are provided: Returns (headers, None) as body is not returned
              for the manual signing path

        Raises:
            OCIError: If signing fails with oci_signer
            Exception: If required credentials are missing
            ImportError: If cryptography package is not installed (manual signing only)

        Example:
            >>> from oci.signer import Signer
            >>> signer = Signer(
            ...     tenancy="ocid1.tenancy.oc1..",
            ...     user="ocid1.user.oc1..",
            ...     fingerprint="xx:xx:xx",
            ...     private_key_file_location="~/.oci/key.pem"
            ... )
            >>> headers, body = config.sign_request(
            ...     headers={},
            ...     optional_params={"oci_signer": signer},
            ...     request_data={"message": "Hello"},
            ...     api_base="https://inference.generativeai.us-ashburn-1.oci.oraclecloud.com/..."
            ... )
        r   N)r   r   r   )
r<   rG   r   r   r   r   r   r   r   r   r;   r;   r=   sign_request  s   
6zOCIChatConfig.sign_requestmessageslitellm_paramsc                 C   s   | d}| dd}	|ptjpd|	 d}|std|du rN| d}
| d	}| d
}| d}| d}| d}|
rJ|rJ|rJ|sH|rJ|sNtd|ddt d |s_td|S )a  
        Validate the OCI environment and credentials.

        Supports two authentication modes:
        1. OCI SDK Signer: Pass an oci_signer object (e.g., oci.signer.Signer)
        2. Manual Credentials: Pass oci_user, oci_fingerprint, oci_tenancy, and oci_key/oci_key_file

        Args:
            headers: Request headers to populate
            model: Model name
            messages: List of chat messages
            optional_params: Optional parameters including authentication credentials
            litellm_params: LiteLLM parameters
            api_key: Optional API key (not used for OCI)
            api_base: Optional API base URL

        Returns:
            Updated headers dict

        Raises:
            Exception: If required parameters are missing or invalid
        r   r   r   r   r   zEither `api_base` must be provided or `litellm.api_base` must be set. Alternatively, you can set the `oci_region` optional parameter to use the default OCI region.Nr   r   r   r   r   oci_compartment_idzMissing required parameters: oci_user, oci_fingerprint, oci_tenancy, oci_compartment_id and at least one of oci_key or oci_key_file. Alternatively, provide an oci_signer object from the OCI SDK.r   zlitellm/)r   z
user-agentzRkwarg `messages` must be an array of messages that follow the openai chat standard)r   r   r   r   r   r   )r<   rG   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r;   r;   r=   validate_environment#  sV   
 






z"OCIChatConfig.validate_environmentc                 C   s   | dd}d| dS )Nr   r   r   z*.oci.oraclecloud.com/20231130/actions/chatr   )r<   r   r   r   r   r   r   r   r;   r;   r=   get_complete_urlx  s   	zOCIChatConfig.get_complete_urlr   c                 C   st  i }|t jkr| j}|d dddddd}n| j}| D ]\}}|r/||v r/|| ||< q| D ]}|rF||v rF||vrF|| ||< q4d|v rc|t jkrZ| |d |d< n	t|d ||d< d|v r|d }t	|t
rd	|v rt
|}	|	|d< |	d	 }
d }d
|	v r|	d
}t	|t
rt
|}n|}|d ur||	d< |t jkr|
|	d	< |S |
 }|dkrd}||	d	< |S )Nr   iX     r   g      ?)r   r   ZtopKr   r   r   r   r   Zjson_schemaZ
jsonSchemaJSONZJSON_OBJECT)r+   r   r   r   r   r   values)adapt_tool_definitions_to_cohere_standard%adapt_tool_definition_to_oci_standardrr   rQ   r   )r<   r   r   Zselected_paramsr   Z
openai_keyr   Z	oci_valuerfZ
rf_payloadZresponse_typeZschema_payloadZraw_schema_payloadZformat_typer;   r;   r=   _get_optional_params  sb   







z"OCIChatConfig._get_optional_paramsc              
   C   s  g }|dd D ]}| d}| d}t|tr6d}|D ]}t|tr3| ddkr3|| dd7 }q|}t|tsE|durCt|nd}d}|dkrd	|v r| d	rg }|d	 D ]:}	|	 d
i  di }
t|
trzt|
}W n tjy~   i }Y nw |
}|t	t|	 d
i  dd|d qZ|dkr|t
d|d q|dkr|t
d||d q|dkr|t
d|dd q|S )z%Build chat history for Cohere models.NrolecontentrJ   r   text	assistant
tool_callsfunction	argumentsname)r   
parametersuserUSER)r   r   ZCHATBOT)r   r   	toolCallstoolTOOL)r   rr   listrQ   rO   r   loadsJSONDecodeErrorra   r   r   )r<   r   Zchat_historymsgr   r   text_contentcontent_itemr   	tool_callZraw_argumentsr   r;   r;   r=   !adapt_messages_to_cohere_standard  sR   





z/OCIChatConfig.adapt_messages_to_cohere_standardr   c           
   	   C   s   g }|D ]L}| di }| di  di }| di  dg }i }| D ]\}}	t|	 dd|	 dd||v d	||< q&|t| d
d| dd|d q|S )z(Adapt tool definitions to Cohere format.r   r   
propertiesrequireddescriptionrJ   r   string)r  r   Z
isRequiredr   )r   r  ZparameterDefinitions)r   r   r   ra   r   )
r<   r   Zcohere_toolsr   Zfunction_defr   r  Zparameter_definitions
param_nameZparam_schemar;   r;   r=   r     s$   




z7OCIChatConfig.adapt_tool_definitions_to_cohere_standardr   c                 C   sZ   t |tr|S t |tr)d}|D ]}t |tr&|ddkr&||dd7 }q|S t|S )z*Extract text content from message content.rJ   r   r   )rr   rO   r   rQ   r   )r<   r   r  r  r;   r;   r=   _extract_text_content  s   

z#OCIChatConfig._extract_text_contentc              
      sF  | dd }|stdt|}| dd}|dvrtd|dkr/| d|}	td|	d	}
ntd|d
}
|tjkrdd |D }|sGtddd |D }d }|rbd fdd|D }|rb|} tj|}tdd 	|d d  
||d|}t||
|d}nt||
td|jt|d ||d}|jddS )Nr   z7kwarg `oci_compartment_id` is required for OCI requestsoci_serving_mode	ON_DEMAND)r  	DEDICATEDzBkwarg `oci_serving_mode` must be either 'ON_DEMAND' or 'DEDICATED'r  oci_endpoint_id)servingTypeZ
endpointId)r  modelIdc                 S      g | ]}| d dkr|qS )r   r   r   .0r   r;   r;   r=   
<listcomp>E      z3OCIChatConfig.transform_request.<locals>.<listcomp>z&No user message found for Cohere modelc                 S   r  )r   systemr   r  r;   r;   r=   r  J  r  r_   c                 3   s    | ]
}  |d  V  qdS )r   N)r
  r  r<   r;   r=   	<genexpr>M  s    
z2OCIChatConfig.transform_request.<locals>.<genexpr>r   r   r   )	apiFormatr   ZchatHistoryZpreambleOverride)ZcompartmentIdservingModeZchatRequest)r  r   T)Zexclude_noner;   )r   r   r   r&   r+   r   rb   r   r   r
  r  r   r   rf   &adapt_messages_to_generic_oci_standard
model_dump)r<   r   r   r   r   rG   r   r   r  r  r  Zuser_messagesZsystem_messagesZpreamble_overridepreambleZoptional_cohere_paramsZchat_requestrT   r;   r  r=   transform_request!  sp   


zOCIChatConfig.transform_requestjson_responsemodel_responsec              	   C   s   t di |}|}||_ttj  |_|jj}|jj	}|dkr%d}n	|dkr,d}nd}d}	|jj
rSg }	|jj
D ]}
|	dt|	 d|
jt|
jdd	 q:d
dlm} |d
d||	d|d}|g|_|jj}d
dlm} ||j|j|jd|_|S )z'Handle Cohere-specific response format.COMPLETEr   
MAX_TOKENSlengthNZcall_r   r   r   idr   r   r   )Choicesr   )r   r   r   )indexr   finish_reason)r4   Zprompt_tokensZcompletion_tokensZtotal_tokensr;   )r   r   intr   now	timestampcreatedchatResponser   finishReasonr   ra   r   r   r   r   r   litellm.types.utilsr'  choicesusager4   promptTokenscompletionTokenstotalTokens)r<   r  r   r   Zcohere_responseZmodel_idZresponse_textZoci_finish_reasonr)  r   r  r'  choiceZ
usage_infor4   r;   r;   r=   _handle_cohere_responsep  sP   


	z%OCIChatConfig._handle_cohere_responser   raw_responsec              
   C   s   z	t d	i |}W n ty! } ztdt| |jdd}~ww |jj}tj|	dd}t
| |_|j|_|jd j}	|jjd j}
|
jrZ|
jd jdkrZ|
jd j|	_|
jrct|
j|	_t|jjj|jjj|jjjd}||_|S )
z#Handle generic OCI response format.z4Response cannot be casted to OCICompletionResponse: r   r   NZz+00:00r   ZTEXTr*  r;   )r    rs   r   rO   r   r/  ZtimeCreatedr   fromisoformatr   r+  r-  r.  r  r   r2  r   r   r   r   r   adapt_tools_to_openai_standardr   r4   r3  r4  r5  r6  )r<   r   r   r   r9  Zcompletion_responsert   Ziso_strdtr   Zresponse_messager3  r;   r;   r=   _handle_generic_response  s8   z&OCIChatConfig._handle_generic_responselogging_objry   	json_modec                 C   s   |  }|d}|d urtt|d |jdt|ts$td|jdt|}|tj	kr5| 
|||}n| ||||}|j|jd< |S )Nerrorr:  z Invalid response format from OCIZadditional_headers)r   r   r   rO   r   rr   rQ   r   r+   r   r8  r?  rG   Z_hidden_params)r<   r   r9  r   r@  r   r   r   r   ry   r   rA  r   rB  r   r;   r;   r=   transform_response  s$   



z OCIChatConfig.transform_responsecustom_llm_providerrT   clientsigned_json_bodyOCIStreamWrapperc              
   C   s   d|v r|d= |d u st |trti d}z|j||t|d|td}W n tjy< } z
t	|j
j|j
jdd }~ww |jdkrJt	|j|jd| }t||||d}|S )Nr   )paramsTrG   rT   r   r@  timeoutr      completion_streamr   rD  r@  )rr   r   r   postr   r   STREAMING_TIMEOUThttpxHTTPStatusErrorr   responser   r   	iter_textrG  )r<   r   rD  r@  r   rG   rT   r   rE  rA  rF  rR  rt   rM  streaming_responser;   r;   r=   get_sync_custom_stream_wrapper  s6   


z,OCIChatConfig.get_sync_custom_stream_wrapperc              
      s   d|v r|d= |d u st |trttji d}z|j||t|d|tdI d H }W n t	j
yB } z
t|jj|jjdd }~ww |jdkrPt|j|jd| }dtt fdd	}t|||||d
}|S )Nr   )Zllm_providerrH  TrI  r   rK  rM  c                 S  s:   | 2 z3 d H W }| dD ]
}|sq| V  qq6 d S )Nz

)r   r|   )rM  itemchunkr;   r;   r=   split_chunksT  s   zCOCIChatConfig.get_async_custom_stream_wrapper.<locals>.split_chunksrL  )rr   r   r   r.   ZBYTEZrN  r   r   rO  rP  rQ  r   rR  r   r   Z
aiter_textr   rO   rG  )r<   r   rD  r@  r   rG   rT   r   rE  rA  rF  rR  rt   rM  rX  rT  r;   r;   r=   get_async_custom_stream_wrapper/  s:   
z-OCIChatConfig.get_async_custom_stream_wrappererror_messager   c                 C   s   t ||dS )Nr   r   )r<   rZ  r   rG   r;   r;   r=   get_error_classc  s   zOCIChatConfig.get_error_class)r:   N)NNNN)NNrU   )NNN)0r?   r@   rA   rB   r   rO   r   r   rQ   rC   r   r
   rR   r   r   r   r   r,   r   r   r+   r   r   r   r  r   r   r   r
  r  r/   r8  rP  Responser?  LiteLLMLoggingObjrC  r   r   r   r   r   rU  rY  r+  ZHeadersr   r[  r;   r;   r;   r=   r      s   
*
$

<

 	

F	
\
D"5
O
A
3	

*
	
+
	
3r   ZSYSTEMr   Z	ASSISTANTr   )r  r   r   r   open_ai_to_generic_oci_role_mapr   r   c                 C   s  g }t |trtt|  t|dgd d dS |D ]g}t |ts"td|d}t |ts0td|dvr<td| d|d	krW|d	}t |tsNtd
|t|d q|dkr~|d}t |trj|d}t |tsstd|t	t
|dd qtt|  |d d dS )Nr   r   r   r   Z
toolCallIdz&Each content item must be a dictionaryr   zProp `type` is not a string)r   	image_urlzProp `z` is not supportedr   zProp `text` is not a stringra  rF   zDProp `image_url` must be a string or an object with a `url` property)rF   )ZimageUrl)rr   rO   r$   r^  r(   rQ   r   r   ra   r"   r#   )r   r   Znew_contentr  r   r   ra  r;   r;   r=   6adapt_messages_to_generic_oci_standard_content_messageq  sF   










rb  r   c              	   C   s   g }|D ]\}t |tstd|ddkrtd|d}t |ts(td|d}t |ts6td|d}t |tsDtd	|d d
d}t |tsUtd|t|d||d qtt|  d |d dS )Nz#Each tool call must be a dictionaryr   r    OCI only supports function toolsr&  zProp `id` is not a string#Prop `function` is not a dictionaryr   zProp `name` is not a stringr   z{}z Prop `arguments` is not a stringFUNCTION)r&  r   r   r   r`  )	rr   rQ   r   r   rO   ra   r)   r$   r^  )r   r   Ztool_calls_formatedr  tool_call_idtool_functionZfunction_namer   r;   r;   r=   0adapt_messages_to_generic_oci_standard_tool_call  s@   







	rh  rf  c                 C   s   t t|  t|dgd |dS )Nr_  r`  )r$   r^  r(   )r   rf  r   r;   r;   r=   4adapt_messages_to_generic_oci_standard_tool_response  s   
ri  r   c                 C   s   g }| D ]j}|d }| d}| d}| d}|dkr3|d ur3t|ts*td|t|| q|dv rO|d urOt|ttfsFtd|t|| q|d	krnt|ts\td
t|tsetd|t||| q|S )Nr   r   r   rf  r   z.Prop `tool_calls` must be a list of tool calls)r  r   r   z:Prop `content` must be a string or a list of content itemsr   z4Prop `tool_call_id` is required and must be a stringzProp `content` is not a string)	r   rr   r   r   ra   rh  rO   rb  ri  )r   Znew_messagesr   r   r   r   rf  r;   r;   r=   r    s@   





r  r   r   c              	   C   sr   g }| D ]2}|d dkrt d|d}t|tst dtd|d|dd|d	i d
}|| q|S )Nr   r   rc  rd  re  r   r  rJ   r   )r   r   r  r   )r   r   rr   rQ   r*   ra   )r   r   	new_toolsr   rg  new_toolr;   r;   r=   r     s   



r   c                 C   s6   g }| D ]}t |jd|j|jdd}|| q|S )Nr   r$  r%  )r2   r&  r   r   ra   )r   rj  r   rk  r;   r;   r=   r=  !  s   r=  c                       sP   e Zd ZdZdef fddZdefddZdefd	d
ZdefddZ	  Z
S )rG  zw
    Custom stream wrapper for OCI responses.
    This class is used to handle streaming responses from OCI's API.
    kwargsc                    s   t  jdi | d S )Nr;   )superr   )r<   rl  r   r;   r=   r   8  s   zOCIStreamWrapper.__init__rW  c                 C   sl   t |tstd| |dstd| t|dd  }d|v r1|ddkr1| |S | |S )NzChunk is not a string: zdata:z#Chunk does not start with 'data:':    r  r   )	rr   rO   r   
startswithr   r   r   _handle_cohere_stream_chunk_handle_generic_stream_chunk)r<   rW  
dict_chunkr;   r;   r=   chunk_creator>  s   



zOCIStreamWrapper.chunk_creatorrs  c              
   C   s   z	t di |}W n ty } z	tdt| d}~ww |jdu r'd|_|jp+d}|j}|dkr6d}n|dkr=d}n	|du rDd}nd}d}tt|jrP|jndt	||dddd	|d
gdS )z(Handle Cohere-specific streaming chunks.z-Chunk cannot be casted to CohereStreamChunk: Nr   rJ   r!  r   r"  r#  r   r   Zprovider_specific_fieldsZthinking_blocksZreasoning_contentr(  deltar)  r2  r;   )
r   rs   r   rO   r(  r   r0  r0   r1   r-   )r<   rs  typed_chunkrt   r   r)  r   r;   r;   r=   rq  K  s@   

z,OCIStreamWrapper._handle_cohere_stream_chunkc              
   C   s`  | dr-|d  dr-|d d D ]}d|vrd|d< d|vr$d|d< d|vr,d|d< qz	tdi |}W n tyK } z	tdt| d}~ww |jdu rTd	|_d}|jr|jjr|jjD ]}t|t	rn||j
7 }qat|trwtd
td|j d}|jr|jjrt|jj}tt|jr|jnd	t||rdd |D nddddd|jdgdS )z$Handle generic OCI streaming chunks.r   r   r   rJ   r&  r   z*Chunk cannot be casted to OCIStreamChunk: Nr   z9OCI does not support image content in streaming responsesz*Unsupported content type in OCI response: c                 S   s   g | ]}|  qS r;   )r  )r  r   r;   r;   r=   r    s    zAOCIStreamWrapper._handle_generic_stream_chunk.<locals>.<listcomp>ru  rv  rx  r;   )r   r'   rs   r   rO   r(  r   r   rr   r(   r   r"   r   r   r=  r0   r1   r-   r0  )r<   rs  r  ry  rt   r   rV  r   r;   r;   r=   rr  v  s`   



z-OCIStreamWrapper._handle_generic_stream_chunk)r?   r@   rA   rB   r   r   rt  rQ   rq  rr  __classcell__r;   r;   rn  r=   rG  2  s    +rG  )\rY   r   rV   r   dataclassesr   typingr   r   r   r   r   r   r	   r
   r   urllib.parser   rP  r   Z(litellm.litellm_core_utils.logging_utilsr   Z)litellm.llms.base_llm.chat.transformationr   r   Z&litellm.llms.custom_httpx.http_handlerr   r   r   r   r   Zlitellm.llms.oci.common_utilsr   Zlitellm.types.llms.ocir   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   Zlitellm.types.llms.openair,   r1  r-   r.   r/   r0   r1   Zlitellm.utilsr2   r3   r4   Z*litellm.litellm_core_utils.litellm_loggingr5   Z_LiteLLMLoggingObjr]  r6   rD   rR   rO   r\   rg   rv   r   r   rO  r   r^  rP   r   rb  rh  ri  r  r   r=  rG  r;   r;   r;   r=   <module>   s   
 ,\       =

3
5

(
