
    jl                        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/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5 d d
l6m7Z7 d dl8m9Z9m:Z:m;Z;m<Z<m=Z= d dl>m?Z?m@Z@mAZA er	d dlBmCZD eDZEneZE G d de      ZFe G d d             ZGdeHdeIfdZJd ZKdeIfdZLdeIfdZMdeIde5fdZNdZO G d de      ZPdd d!d"d#ZQe
eIe/f   eRd$<   d%eId&eeIeSf   de.fd'ZTd%eId(eSde.fd)ZUd%eId*eId&eIde.fd+ZVd,ee7   dee.   fd-ZWd.ee
   d/e5fd0ZXd.ee3   dee?   fd1ZY G d2 d3e@      ZZy)4    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
OCIMessageOCIRolesOCIServingModeOCIStreamChunkOCITextContentPartOCIToolCallOCIToolDefinition
OCIVendors)AllMessageValues)DeltaLlmProvidersModelResponseModelResponseStreamStreamingChoices)ChatCompletionMessageToolCallCustomStreamWrapperUsage)Loggingc                   *    e Zd ZdZdddededdfdZy)	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requestr9   returnNc                     y)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 )selfr:   r9   s      }/Users/manta/Documents/Projects/TheRoad-I1/backend/.venv/lib/python3.12/site-packages/litellm/llms/oci/chat/transformation.pydo_request_signz!OCISignerProtocol.do_request_signL   s     	    )__name__
__module____qualname____doc__r   boolr@   r=   rA   r?   r7   r7   B   s)     PU s  Y] rA   r7   c                   P    e Zd ZU dZeed<   eed<   eed<   eed<   edefd       Z	y)	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                     t        | j                        }|j                  |j                  rd|j                  z   z   S dz   S )z0Returns the path + query string for OCI signing.? )r   rJ   pathquery)r>   
parsed_urls     r?   path_urlzOCIRequestWrapper.path_urld   s=     dhh'
J<L<L#
(8(8"8UURTUUrA   N)
rB   rC   rD   rE   str__annotations__dictbytespropertyrS   r=   rA   r?   rH   rH   W   s9     K	HM
KV# V VrA   rH   datar;   c                     t        j                  |       j                         }t        j                  |      j                         S N)hashlibsha256digestbase64	b64encodedecode)rY   r^   s     r?   sha256_base64rb   k   s3    ^^D!((*FF#**,,rA   c                     g }|D ]8  }|dk(  r| j                          d| }n||   }|j                  | d|        : dj                  |      S )N(request-target) z: 
)lowerappendjoin)rI   rP   rK   signed_headerslinesheadervalues          r?   build_signature_stringrn   p   sb    E ''||~&av.EFOExr%)* ! 99UrA   key_strc                     	 ddl m} ddlm} |j                  | j                  d      d       }t        ||j                        st        d      |S # t        $ r}t	        d      |d }~ww xY w)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.primitivesrq   )cryptography.hazmat.primitives.asymmetricrr   ImportErrorload_pem_private_keyencode
isinstanceRSAPrivateKey	TypeError)ro   rq   rr   ekeys        r?   load_private_key_from_strr   {   s    @A 
,
,w - C c3,,-\
 	
 J  ?
 	s   A 	A-A((A-	file_pathc                 .   	 t        | dd      5 }|j                         j                         }ddd       st        d|        t        |      S # 1 sw Y   $xY w# t        $ r t        d|        t        $ r}t	        d|  d|       |d}~ww xY w)	z$Loads a private key from a file pathrrt   )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
ValueErrorr   )r   fro   r~   s       r?   load_private_key_from_filer      s    T)S73qffhnn&G 4 6ykBCC$W-- 43 L">yk JKK T9)CsKLRSSTs-   A AA AA B=BBmodelc                     | j                  d      d   j                         }|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   cohere)splitrg   r+   COHEREGENERIC)r   vendors     r?   get_vendor_from_modelr      s@     [[a &&(F   !!!rA   i,  c                      e Zd ZdZ	 	 d4dZdedee   fdZdededed	e	def
d
Z
dededededeeef   f
dZdededededeedf   f
dZ	 	 	 	 d5d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Z	 	 d6dededee   dededee   dee   defdZ	 d7dee   dee   dedededee	   defdZdededefdZdee   dee   fdZdeeeef      dee   fdZdedefdZdedee   dedededefdZd eded!edefd"Zd#eded!ed$e jB                  def
d%Z"	 	 d6ded$e jB                  d!ed&e#dedee   deded'edee   d(ee	   defd)Z$ e%       	 	 	 d8ded*ed&e#deded+ede&d,ee'e(e)f      d(ee	   d-ee   dd.fd/       Z* e%       	 	 	 d8ded*ed&e#deded+ede&d,ee'e(e)f      d(ee	   d-ee   dd.fd0       Z+d1ed2e,de'ee jZ                  f   de.fd3Z/y)9OCIChatConfigz6
    Configuration class for OCI's API interface.
    r;   Nc           
         t               j                         }|j                         D ]%  \  }}|dk7  s|t        | j                  ||       ' 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| _        | j
                  j                         | _        y ) Nr>   has_custom_stream_wrapperTstreamisStream
max_tokens	maxTokensmax_completion_tokenstemperaturetoolsfrequency_penaltyfrequencyPenaltylogprobslogProbs
logit_bias	logitBiasnnumGenerationspresence_penaltypresencePenaltyseedstoptool_choice
toolChoicetop_ptopPmax_retriesFtop_logprobs
modalities)
predictionstream_optionsfunction_call	functionsextra_headersparallel_tool_callsaudioweb_search_options)localscopyitemssetattr	__class__openai_to_oci_generic_param_mapopenai_to_oci_cohere_param_map)r>   locals_r   rm   s       r?   __init__zOCIChatConfig.__init__   sa    (--/!--/JCf}!2U3 * 	 ;TB0
j0
+0
 $[0
 =	0

 W0
  !30
 
0
 +0
 !0
  10
 F0
 F0
 <0
 V0
 50
  E!0
" %#0
$  #""#("'30
,: /3.R.R.W.W.Y+rA   r   c                    g }t        |      }|t        j                  k(  r/| j                  }|j	                  d       |j	                  d       n| j
                  }|j                         D ]  \  }}|s	|j                  |        |S )Nr   r   )r   r+   r   r   popr   r   rh   )r>   r   supported_paramsr   open_ai_to_oci_param_mapr   rm   s          r?   get_supported_openai_paramsz)OCIChatConfig.get_supported_openai_params   s    &u-Z&&&'+'J'J$$((7$((7'+'K'K$288:JC '', ;  rA   non_default_paramsoptional_paramsdrop_paramsc                 <   i }t        |      }|t        j                  k(  r| j                  }n| j                  }i ||}|j                         D ]I  \  }	}
|j                  |	      }|du r"|st        j                  r.t        d|	 d      ||
||	<   E|
||<   K |S )NFzparam `z` is not supported on OCI)
r   r+   r   r   r   r   getlitellmr   	Exception)r>   r   r   r   r   adapted_paramsr   r   
all_paramsr   rm   aliass               r?   map_openai_paramszOCIChatConfig.map_openai_params   s     &u-Z&&&'+'J'J$'+'K'K$>*>o>
$**,JC,005E~'"5"5'#.G HII}&+s#$)N5! - rA   rK   request_dataapi_basec                 d   |j                  d      }t        j                  |      j                  d      }t	        |j                  dd            j                         }|dvrt        d|       |j                         }|j                  dd       |j                  d	t	        t        |                   t        ||||
      }	|t        d      	 |j                  |	d       |j                  |	j                         ||fS # t        $ r }
t        ddt	        |
       d      |
d}
~
ww xY w)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_signerrt   rI   POST)r   GETPUTDELETEPATCHzUnsupported HTTP method: content-typeapplication/jsoncontent-length)rI   rJ   rK   rL   Nz<oci_signer cannot be None when calling _sign_with_oci_signerTr8   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dumpsrz   rT   upperr   r   
setdefaultlenrH   r@   r   r   updaterK   )r>   rK   r   r   r   r   rL   rI   prepared_headersrequest_wrapperr~   s              r?   _sign_with_oci_signerz#OCIChatConfig._sign_with_oci_signer  s?   . %((6
zz,'..w7_((6:;AACBB8ABB"<<>##N4FG##$4c#d)nE+$	
 [\\	&&PT&U 	../}  		GAx Pc c 		s   D 	D/D**D/c           	         |j                  dd      }|xs t        j                  xs d| d}|j                  d      }|j                  d      }|j                  d      }|j                  d      }	|j                  d	      }
|r|r|r|	s|
st        d
      t	        |j                  dd            j                         }t        j                  |      j                  d      }t        |      }|j                  xs d}|j                  }t        j                  j                         j                  d      }|j                  dd      }t	        t        |            }t!        |      }|||||d}g d}t#        ||||      }	 ddlm} ddlm} |	rt/        |	      n|
rt1        |
      nd}|t        d      |j3                  |j                  d      |j5                         |j7                               }t9        j:                  |      j=                         }| d| d| }d| ddj?                  |       d| d}|jA                  ||||||d       |dfS # t,        $ r}t-        d      |d}~ww xY w) 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.rI   r   rt   /z%a, %d %b %Y %H:%M:%S GMTr   r   )datehostr   r   x-content-sha256)r   rd   r   r   r   r   r   )hashes)paddingrs   Nz^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="re   z",signature="")authorizationr   r   r   r   r   )!r   r   r   r   rT   r   r   r   rz   r   rP   netlocdatetimeutcnowstrftimer   rb   rn   rv   r   rw   r   rx   r   r   signPKCS1v15SHA256r_   r`   ra   ri   r   )r>   rK   r   r   r   r   r   r   r   r   r   rI   rL   parsedrP   r   r   content_typecontent_lengthx_content_sha256headers_to_signrj   signing_stringr   r   r~   private_key	signaturesignature_b64key_idr   s                                  r?   _sign_with_manual_credentialsz+OCIChatConfig._sign_with_manual_credentialsM  s   . %((~F
 RR0<PQ 	
 #&&z2)--.?@%))-8!%%i0&**>: "|? 
 _((6:;AACzz,'..w7(#{{!c}}  '')223NO{{>3EFSY(. (, 0

 0D/>
	=I  &g.=I+L9t 	 p   $$!!'*MMO
	
 ((3::<=(1_,=>X 01 2'	+ 	 	!. ,"0$4		
 }[  	C 	s   I 	I7&I22I7api_keyr   fake_streamc	                 x    |j                  d      }	|	| j                  ||||      S | j                  ||||      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   )r   r   r  )
r>   rK   r   r   r   r  r   r   r  r   s
             r?   sign_requestzOCIChatConfig.sign_request  sO    l %((6
 !--gV^__ 11'?LZbccrA   messageslitellm_paramsc                    |j                  d      }|j                  dd      }	|xs t        j                  xs d|	 d}|st        d      |}|j                  d      }
|j                  d      }|j                  d	      }|j                  d
      }|j                  d      }|j                  d      }|
r
|r|r|s|r|st        d      |j	                  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.r   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>   rK   r   r  r   r  r  r   r   r   r   r   r   r   r   r  s                   r?   validate_environmentz"OCIChatConfig.validate_environment  s8   @ %((6
$((~F
  RR0<PQ 	 p  &**:6H-112CDO)--m<K%)))4G*..~>L!0!4!45I!J &"<)T  	 2 (	2	
 d  rA   c                 2    |j                  dd      }d| dS )Nr   r   r   z*.oci.oraclecloud.com/20231130/actions/chat)r   )r>   r   r  r   r   r  r   r   s           r?   get_complete_urlzOCIChatConfig.get_complete_url`  s&     %((~F
0<fggrA   r   c                    i }|t         j                  k(  r&| j                  }|j                  d       dddddd}n| j                  }|j                         D ]  \  }}|s	||v s||   ||<    |j                         D ]  }|s||v s||vs||   ||<    d|v r>|t         j                  k(  r| j                  |d         |d<   |S t        |d   |      |d<   |S )Nr   iX     r   g      ?)r   r   topKr   r   r   )	r+   r   r   r   r   r   values)adapt_tool_definitions_to_cohere_standard%adapt_tool_definition_to_oci_standard)r>   r   r   selected_paramsr   
openai_keyr   	oci_values           r?   _get_optional_paramsz"OCIChatConfig._get_optional_paramsl  s   Z&&&'+'J'J$$((7 ! $%O (,'K'K$ $<#A#A#CJ:8+::+F( $D
 288:IY/9i>^-<Y-G	* ; o%***+/+Y+Y#G,,(  ,Q#G,f,( rA   c                    g }|dd D ]  }|j                  d      }|j                  d      }t        |t              rFd}|D ]=  }t        |t              s|j                  d      dk(  s)||j                  dd      z  }? |}t        |t              s|t	        |      nd}d}|dk(  rd	|v r|j                  d	      rg }|d	   D ]  }	|	j                  d
i       j                  di       }
t        |
t              r	 t        j                  |
      }n|
}|j                  t        t	        |	j                  d
i       j                  dd            |              |dk(  r|j                  t        d|             v|dk(  r|j                  t        d||             |dk(  s|j                  t        d|d              |S # t
        j                  $ r i }Y w xY w)z%Build chat history for Cohere models.NrolecontentrO   typetext	assistant
tool_callsfunction	argumentsname)r0  
parametersuserUSER)r(  r   CHATBOT)r(  r   	toolCallstoolTOOL)r   r{   listrV   rT   r   loadsJSONDecodeErrorrh   r   r   )r>   r  chat_historymsgr(  r)  text_contentcontent_itemr-  	tool_callraw_argumentsr/  s               r?   !adapt_messages_to_cohere_standardz/OCIChatConfig.adapt_messages_to_cohere_standard  s   CR=C776?Dggi(G'4(!$+L!,5,:J:J6:RV\:\$(8(8(DD %, ' gs+*1*=#g,2 :>J{"|s':sww|?T
!$\!2I)2z2)F)J)J;XZ)[M!-5+8<

=8QI %2	%%n z2!>!B!B62!NO#,'  "3  v~##Mvw$OP$##My']g$hi##M#"% U !` -  $33 +(*I+s   <GG#"G#r   c           
         g }|D ]  }|j                  di       }|j                  di       j                  di       }|j                  di       j                  dg       }i }|j                         D ]8  \  }}	t        |	j                  dd      |	j                  dd      ||v 	      ||<   : |j                  t	        |j                  d
d      |j                  dd      |              |S )z(Adapt tool definitions to Cohere format.r.  r1  
propertiesrequireddescriptionrO   r*  string)rE  r*  
isRequiredr0  )r0  rE  parameterDefinitions)r   r   r   rh   r   )
r>   r   cohere_toolsr6  function_defr1  rD  parameter_definitions
param_nameparam_schemas
             r?   r   z7OCIChatConfig.adapt_tool_definitions_to_cohere_standard  s    D88J3L%)),;??bQJ#''b9==j"MH$&!,6,<,<,>(
L4M , 0 0 C%))&(;)X55%j1 -? 
!%%fb1(,,]B?%:!  & rA   r)  c                     t        |t              r|S t        |t              rFd}|D ]=  }t        |t              s|j	                  d      dk(  s)||j	                  dd      z  }? |S t        |      S )z*Extract text content from message content.rO   r*  r+  )r{   rT   r8  rV   r   )r>   r)  r=  r>  s       r?   _extract_text_contentz#OCIChatConfig._extract_text_content  sp    gs#N&L 'lD1l6F6Fv6NRX6X L$4$4VR$@@L !(  7|rA   c                    |j                  dd       }|st        d      t        |      }|j                  dd      }|dvrt        d      |dk(  rt        d|      }	nt        d|	      }	|t        j
                  k(  r|D 
cg c]  }
|
j                  d
      dk(  s|
 }}
|st        d      t        dd| j                  |d   d         | j                  |      d| j                  t        j
                  |      }t        ||	|      }n=t        ||	t        d|j                  t        |      d| j                  ||            }|j                  d      S c c}
w )Nr  z7kwarg `oci_compartment_id` is required for OCI requestsoci_serving_mode	ON_DEMAND)rR  	DEDICATEDzBkwarg `oci_serving_mode` must be either 'ON_DEMAND' or 'DEDICATED'rS  )servingType
endpointId)rT  modelIdr(  r2  z&No user message found for Cohere modelr   r'  r)  )	apiFormatr   chatHistory)compartmentIdservingModechatRequest)rW  r  T)exclude_noner=   )r   r   r   r&   r+   r   r   rO  rA  r%  r    r   rm   &adapt_messages_to_generic_oci_standard
model_dump)r>   r   r  r   r  rK   r  r   rQ  rZ  r<  user_messageschat_requestrY   s                 r?   transform_requestzOCIChatConfig.transform_request  s    -001EtL!UVV&u-*../A;O#==T  {*(' K
 )'K Z&&& -5RHS68QSHMR  HII - "22=3DY3OP BB8L ++J,=,=O	L (0'(D (0'1 $llCHM //HD D11= Ss   EEjson_responsemodel_responsec           	         t        di |}|}||_        t        t        j                  j	                         j                               |_        |j                  j                  }|j                  j                  }|dk(  rd}n
|dk(  rd}nd}d}	|j                  j                  rhg }	|j                  j                  D ]M  }
|	j                  dt        |	       d|
j                  t        j                  |
j                         dd	       O d
dlm}  |d
d||	d|      }|g|_        |j                  j(                  }d
dlm}  ||j,                  |j.                  |j0                        |_        |S )z'Handle Cohere-specific response format.COMPLETEr   
MAX_TOKENSlengthNcall_r.  r0  r/  idr*  r.  r   )Choicesr,  )r(  r)  r-  )indexr   finish_reason)r4   prompt_tokenscompletion_tokenstotal_tokensr=   )r   r   intr   now	timestampcreatedchatResponser+  finishReasonr5  rh   r   r0  r   r   r1  litellm.types.utilsrl  choicesusager4   promptTokenscompletionTokenstotalTokens)r>   rb  r   rc  cohere_responsemodel_idresponse_textoci_finish_reasonrn  r-  r?  rl  choice
usage_infor4   s                  r?   _handle_cohere_responsez%OCIChatConfig._handle_cohere_response.  sw    +;];  (!$X%6%6%:%:%<%F%F%H!I (4499+88EE 
*"M,.$M"M 6:
''11J,99CC	!!!#j/!23& )%)ZZ	0D0D%E!#  D 	0#((
 (
 #) %1177
-$$11(99#// 
 rA   r   raw_responsec                    	 t        d	i |}|j
                  j                  }t        j                  j                  |j                  dd            }t        |j                               |_        |j                  |_        |j                  d   j                   }	|j
                  j                  d   j                   }
|
j"                  r:|
j"                  d   j$                  dk(  r|
j"                  d   j&                  |	_        |
j(                  rt+        |
j(                        |	_        t/        |j
                  j0                  j2                  |j
                  j0                  j4                  |j
                  j0                  j6                        }||_        |S # t        $ r(}t        dt        |       |j                        d}~ww xY w)
z#Handle generic OCI response format.z4Response cannot be casted to OCICompletionResponse: r   r   NZz+00:00r   TEXTro  r=   )r!   r}   r   rT   r   rw  timeCreatedr   fromisoformatreplacers  ru  rv  rV  r   rz  r   r)  r*  r+  r5  adapt_tools_to_openai_standardr-  r4   r{  r|  r}  r~  )r>   r   r   rc  r  completion_responser~   iso_strdtr   response_messager{  s               r?   _handle_generic_responsez&OCIChatConfig._handle_generic_responseo  s   	"7"?$"? &22>>,,W__S(-KL!$R\\^!42:: ((+33.;;CCAFNN##(8(@(@(C(H(HF(R.66q9>>GO%%!? **"G -::@@MM1>>DDUU,99??KK

  %9  	NsSTvhW(44 	s   F 	G##GGlogging_objr   	json_modec                    |j                         } |j                  d      }|#t        t        |d         |j                        t        |t              st        d|j                        t        |      }|t        j                  k(  r| j                  |||      }n| j                  ||||      }|j                  |j                  d<   |S )Nerrorr  z Invalid response format from OCIadditional_headers)r   r   r   rT   r   r{   rV   r   r+   r   r  r  rK   _hidden_params)r>   r   r  rc  r  r   r  r   r  r   r  r  r   r  r   s                  r?   transform_responsez OCIChatConfig.transform_response  s       "!DM*(44 
 $%:(44 
 'u- Z&&&!99$~VN!::4XdeN>J>R>R%%&:;rA   custom_llm_providerrY   clientsigned_json_bodyOCIStreamWrapperc                    d|v r|d= |t        |t              rt        i       }	 |j                  ||t	        j
                  |      d|t              }|j                  dk7  r!t        |j                  |j                        |j                         }t        ||||      }|S # t        j                  $ r:}t        |j                  j                  |j                  j                        d }~ww xY w)Nr   )paramsTrK   rY   r   r  timeoutr      completion_streamr   r  r  )r{   r   r   postr   r   STREAMING_TIMEOUThttpxHTTPStatusErrorr   responser   r+  	iter_textr  )r>   r   r  r  r   rK   rY   r  r  r  r  r  r~   r  streaming_responses                  r?   get_sync_custom_stream_wrapperz,OCIChatConfig.get_sync_custom_stream_wrapper  s     tX>Z0@A&b1F
	X{{ZZ%') # H 3&x';';X]]SS$..0-/ 3#	
 "! $$ 	Xqzz'='=qzzWW	Xs   .B& &C395C..C3c                 T  K   d|v r|d= |t        |t              rt        t        j                  i       }	 |j                  ||t        j                  |      d|t               d {   }|j                  dk7  r!t        |j                  |j                        |j                         }dt         t"           fd}t%         ||      |||	      }|S 7 l# t        j                  $ r:}t        |j                  j                  |j                  j                        d }~ww xY ww)
Nr   )llm_providerr  Tr  r   r  r  c                   K   | 2 3 d {   }|j                  d      D ]  }|s|j                           67 16 y w)Nz

)r   r   )r  itemchunks      r?   split_chunkszCOCIChatConfig.get_async_custom_stream_wrapper.<locals>.split_chunks  s>     / (d!ZZ/E  ++-' 0(/s   ?=;=.?=?r  )r{   r   r   r.   BYTEZr  r   r   r  r  r  r   r  r   r+  
aiter_textr   rT   r  )r>   r   r  r  r   rK   rY   r  r  r  r  r  r~   r  r  r  s                   r?   get_async_custom_stream_wrapperz-OCIChatConfig.get_async_custom_stream_wrapper  s     tX>Z<+9K9KTVWF
	X#[[ZZ%') )  H 3&x';';X]]SS$//1	(-2D 	( .*+<= 3#	
 "!; $$ 	Xqzz'='=qzzWW	Xs;   5D(1C )C*C .A(D(C D%+5D  D%%D(error_messager   c                     t        ||      S )Nr   r   )r>   r  r   rK   s       r?   get_error_classzOCIChatConfig.get_error_class!  s     KGGrA   )r;   N)NNNN)NNr[   )NNN)0rB   rC   rD   rE   r   rT   r   r   rV   rF   r   r   rW   r   r  r	   r  r,   r  r  r+   r   r%  r   rA  r   r   r   rO  ra  r/   r  r  Responser  LiteLLMLoggingObjr  r   r8  r   r   r   r  r  rs  Headersr   r  r=   rA   r?   r   r      s   'Z	'ZR   c     	
  
B:: : 	:
 : 
tU{	:x}} } 	}
 } 
tTz	}J "&#!%&*=d=d =d 	=d
 =d #=d }=d =d d^=d 
tXe_$	%=dL "&"&SS S '(	S
 S S #S 3-S 
Sx "&
h3-
h #
h 	
h
 
h 
h 
h 

h$: $ $QU $L3$?O:P 3UYZgUh 3jtDcN?S X\]gXh 0
S 
S 
A2A2 '(A2 	A2
 A2 A2 
A2F?? ? &	?
 
?B&& & &	&
 nn& 
&f "&$((( nn( &	(
 '( ( '(( ( ( ( #( D>( 
(T  BF$(,0)")" !)" '	)"
 )" )" )" )" {,<<=>)" D>)" #5/)" 
)" )"V  BF$(,01"1" !1" '	1"
 1" 1" 1" 1" {,<<=>1" D>1" #5/1" 
1" 1"fH H/2H=B4CV=WH	HrA   r   SYSTEMr3  	ASSISTANTr7  )systemr2  r,  r6  open_ai_to_generic_oci_role_mapr(  r)  c                    g }t        |t              r!t        t        |    t	        |      gd d       S |D ]  }t        |t
              st        d      |j                  d      }t        |t              st        d      |dvrt        d| d      |d	k(  rH|j                  d	      }t        |t              st        d
      |j                  t	        |             |dk(  s|j                  d      }t        |t              st        d      |j                  t        |              t        t        |    |d d       S )Nr+  r(  r)  r5  
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 stringr  z Prop `image_url` is not a string)imageUrl)
r{   rT   r$   r  r(   rV   r   r   rh   r#   )r(  r)  new_contentr>  r*  r+  r  s          r?   6adapt_messages_to_generic_oci_standard_content_messager  /  sB    .0K'306'W56	
 	
  ,-DEE'$$9::,,fTF*<=>>6>##F+DdC( =>>1t<=[ $((5Ii- BCC2IFG+  . ,T2	 rA   r-  c           	      \   g }|D ]  }t        |t              st        d      |j                  d      dk7  rt        d      |j                  d      }t        |t              st        d      |j                  d      }t        |t              st        d      |j                  d      }t        |t              st        d	      |d   j                  d
d      }t        |t              st        d      |j                  t        |d||              t        t        |    d |d       S )Nz#Each tool call must be a dictionaryr*  r.   OCI only supports function toolsrk  zProp `id` is not a string#Prop `function` is not a dictionaryr0  zProp `name` is not a stringr/  z{}z Prop `arguments` is not a stringFUNCTION)rk  r*  r0  r/  r  )	r{   rV   r   r   rT   rh   r)   r$   r  )r(  r-  tool_calls_formatedr?  tool_call_idtool_functionfunction_namer/  s           r?   0adapt_messages_to_generic_oci_standard_tool_callr  _  s(    	)T*ABB== J.>?? }}T*,,788!j1-.ABB%))&1--9::j)--k4@	)S)>?? 	"""#		
A  R ,T2%	 rA   r  c                 D    t        t        |    t        |      gd |      S )Nr  r  )r$   r  r(   )r(  r  r)  s      r?   4adapt_messages_to_generic_oci_standard_tool_responser    s*     ,T2#12	 rA   r  c                 >   g }| D ]  }|d   }|j                  d      }|j                  d      }|j                  d      }|dk(  r9|7t        |t              st        d      |j	                  t        ||             z|dv r?|=t        |t        t        f      st        d      |j	                  t        ||             |d	k(  st        |t              st        d
      t        |t              st        d      |j	                  t        |||              |S )Nr(  r)  r-  r  r,  z.Prop `tool_calls` must be a list of tool calls)r  r2  r,  z:Prop `content` must be a string or a list of content itemsr6  z4Prop `tool_call_id` is required and must be a stringzProp `content` is not a string)	r   r{   r8  r   rh   r  rT   r  r  )r  new_messagesr   r(  r)  r-  r  s          r?   r]  r]    s$    Lv++i([[.
{{>2;:#9j$/ PQQ@zR 449LgT{3P  FtWU V^lC0 VWWgs+ @AAD,7 B rA   r   r   c           
      4   g }| D ]  }|d   dk7  rt        d      |j                  d      }t        |t              st        d      t	        d|j                  d      |j                  dd      |j                  d	i       
      }|j                  |        |S )Nr*  r.  r  r  r  r0  rE  rO   r1  )r*  r0  rE  r1  )r   r   r{   rV   r*   rh   )r   r   	new_toolsr6  r  new_tools         r?   r!  r!    s    I<:%>??,-.ABB$""6*%))-<$((r:	
 	"   rA   c                     g }| D ]B  }t        |j                  d|j                  |j                  d      }|j	                  |       D |S )Nr.  ri  rj  )r2   rk  r0  r/  rh   )r   r  r6  r  s       r?   r  r    sR     I0ww		!^^
 	"  rA   c                   L     e Zd ZdZdef fdZdefdZdefdZdefdZ	 xZ
S )	r  zw
    Custom stream wrapper for OCI responses.
    This class is used to handle streaming responses from OCI's API.
    kwargsc                 $    t        |   di | y )Nr=   )superr   )r>   r  r   s     r?   r   zOCIStreamWrapper.__init__  s     	"6"rA   r  c                     t        |t              st        d|       |j                  d      st        d|       t	        j
                  |dd        }d|v r%|j                  d      dk(  r| j                  |      S | j                  |      S )NzChunk is not a string: zdata:z#Chunk does not start with 'data:':    rW  r   )	r{   rT   r   
startswithr   r9  r   _handle_cohere_stream_chunk_handle_generic_stream_chunk)r>   r  
dict_chunks      r?   chunk_creatorzOCIStreamWrapper.chunk_creator  s    %%6ug>??(B5'JKKZZab	*
 *$)D)P33J??44Z@@rA   r  c                 x   	 t        di |}|j                  d|_        |j
                  xs d}|j                  }|dk(  rd}n|dk(  rd}n|d}nd}d}t        t        |j                  r|j                  ndt        ||ddd	      |
      g      S # t        $ r}t        dt        |             d}~ww xY w)z(Handle Cohere-specific streaming chunks.z-Chunk cannot be casted to CohereStreamChunk: Nr   rO   re  r   rf  rg  r)  r-  provider_specific_fieldsthinking_blocksreasoning_contentrm  deltarn  rz  r=   )
r   r}   r   rT   rm  r+  rx  r0   r1   r-   )r>   r  typed_chunkr~   r+  rn  r-  s          r?   r  z,OCIStreamWrapper._handle_cohere_stream_chunk  s    	W+9j9K $ !K %2 $00J&"Ml*$M" M"M 
" /:/@/@+++a $#-15(,*. #0

 	
/  	WLSQRVHUVV	Ws   B 	B9B44B9c                    	 t        d
i |}|j                  d|_        d}|j
                  r|j
                  j                  rm|j
                  j                  D ]T  }t        |t              r||j                  z  }#t        |t              rt        d      t        d|j                          d}|j
                  r5|j
                  j                  rt        |j
                  j                        }t        t        |j                  r|j                  ndt!        ||r|D cg c]  }|j#                          c}ndddd      |j$                        g	      S # t        $ r}t        dt        |             d}~ww xY wc c}w )z$Handle generic OCI streaming chunks.z*Chunk cannot be casted to OCIStreamChunk: Nr   rO   z9OCI does not support image content in streaming responsesz*Unsupported content type in OCI response: r  r  r  r=   )r'   r}   r   rT   rm  r   r)  r{   r(   r+  r#   r*  r5  r  r0   r1   r-   r^  rx  )r>   r  r  r~   r+  r  r-  r6  s           r?   r  z-OCIStreamWrapper._handle_generic_stream_chunk1  s   	T(6:6K $ !K;#6#6#>#>#++33d$67DII%D&9:$S  %DTYYKP  4 
;#6#6#@#@78K8K8U8UVJ" /:/@/@+++a $  * <FF:4T__.:F!%15(,*.
 #.":":
 	
1  	TI#a&RSS	T> Gs   E #F	F&E==F)rB   rC   rD   rE   r   r   r  rV   r  r  __classcell__)r   s   @r?   r  r    s<    
##A3 A)
d )
V.
t .
rA   r  )[r_   r   r\   r   dataclassesr   typingr   r   r   r   r   r	   r
   r   r   urllib.parser   r  r   (litellm.litellm_core_utils.logging_utilsr   )litellm.llms.base_llm.chat.transformationr   r   &litellm.llms.custom_httpx.http_handlerr   r   r   r   r   litellm.llms.oci.common_utilsr   litellm.types.llms.ocir   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   litellm.types.llms.openair,   ry  r-   r.   r/   r0   r1   litellm.utilsr2   r3   r4   *litellm.litellm_core_utils.litellm_loggingr5   _LiteLLMLoggingObjr  r7   rH   rW   rT   rb   rn   r   r   r   r  r   r  rU   r8  r  r  r  r]  r!  r  r  r=   rA   r?   <module>r     s       ! b b b !   I R  3     , 7   X* * V V V&- -# -
s *.# . " " "   qHJ qHj 	8 c8m!4 -
-c4i(--`2
222j
 +.%#$%	*%Pd Z *	
'("r
* r
rA   