o
    ưiYo                     @   s   d dl Z d dlmZmZmZmZmZmZmZm	Z	m
Z
mZ d dlmZ d dlZd dlmZ d dlmZ d dlmZmZmZmZ d dlmZ d dlmZmZmZmZ G d	d
 d
ZG dd dZ dS )    N)
AnyDictIterableListOptionalTypeUnioncastget_type_hintsoverload)	BaseModel)verbose_logger)BaseResponsesAPIConfig)ResponseAPIUsage!ResponsesAPIOptionalRequestParamsResponsesAPIResponseResponseText)DecodedResponseId)CompletionTokensDetailsWrapperPromptTokensDetailsWrapperSpecialEnumsUsagec                   @   s8  e Zd ZdZedeee  dedee	 dee def
ddZ
e		dAded
ededeee  def
ddZedeeef defddZee		dAdedee deeeef  defddZee		dAdeeef dee deeeef  deeef fddZe		dAdeeeeef f dee deeeef  deeeeef f fddZedededefddZededeeeef  fddZed ededefd!d"Zed#edeee ef fd$d%Zed&ed'eeef f dee ded'eeef f fd(d)Zed*edefd+d,Zedee dee d-edefd.d/Zed-edefd0d1Zed-ee dee fd2d3Zed4edefd5d6Ze		dAd7eee d8 e!f  d9ed: ded: fd;d<Z"ed=eeeef  d>ee#e  deee eeeeeef f  eeeef  eeeef  f fd?d@Z$d	S )BResponsesAPIRequestUtilsz2Helper utils for constructing ResponseAPI requestssupported_paramsnon_default_paramsdrop_paramscustom_llm_providermodelc                 C   sx   | d u rd S i }|  D ]}|| vr|| ||< q|r:tjdu s(|d ur*|du r*d S tjd| d| d| ddd S )NTi  z does not support parameters: z, for model=zf. To drop these, set `litellm.drop_params=True` or for proxy:

`litellm_settings:
 drop_params: true`
)status_codemessage)keyslitellmr   ZUnsupportedParamsError)r   r   r   r   r   Zunsupported_paramsk r#   N/home/app/Keep/.python/lib/python3.10/site-packages/litellm/responses/utils.py_check_valid_arg&   s    
z)ResponsesAPIRequestUtils._check_valid_argNresponses_api_provider_configresponse_api_optional_paramsallowed_openai_paramsreturnc                 C   sh   ddl m} || }tt|}tj||pg  |tj|j	| d |j
|| tjd}||||p/g d}|S )aS  
        Get optional parameters for the responses API.

        Args:
            params: Dictionary of all parameters
            model: The model name
            responses_api_provider_config: The provider configuration for responses API

        Returns:
            A dictionary of supported parameters for the responses API
        r   )_apply_openai_param_overrides)r   r   r   r   r   )r'   r   r   )Zoptional_paramsr   r(   )litellm.utilsr*   Zget_supported_openai_paramsr	   r   r   r%   r!   r   r   Zmap_openai_params)r   r&   r'   r(   r*   r   r   Zmapped_paramsr#   r#   r$   !get_optional_params_responses_api?   s.   

	z:ResponsesAPIRequestUtils.get_optional_params_responses_apiparamsc           
      C   s   ddl m} tt }| dd}| di }| dd}|j| |||dd |D d	gd
}d|v r>t|d }||d< d|v r]ddl m	} ||d }	|	durW|	|d< n|dd t
t|S )a  
        Filter parameters to only include those defined in ResponsesAPIOptionalRequestParams.

        Args:
            params: Dictionary of parameters to filter

        Returns:
            ResponsesAPIOptionalRequestParams instance with only the valid parameters
        r   )PreProcessNonDefaultParamsr   Nkwargsadditional_drop_paramsc                 S   s   i | ]}|d qS Nr#   ).0r"   r#   r#   r$   
<dictcomp>   s    zVResponsesAPIRequestUtils.get_requested_response_api_optional_param.<locals>.<dictcomp>input)Zpassed_paramsspecial_paramsr   r0   Zdefault_param_valuesZ#additional_endpoint_specific_paramsprevious_response_idmetadata)add_openai_metadata)r+   r.   r
   r   r    popZ#base_pre_process_non_default_paramsr   <decode_previous_response_id_to_original_previous_response_idr8   r	   )
r-   r.   Z
valid_keysr   r5   r0   r   Zdecoded_previous_response_idr8   Zconverted_metadatar#   r#   r$   )get_requested_response_api_optional_params   s4   

zBResponsesAPIRequestUtils.get_requested_response_api_optional_paramresponses_api_responselitellm_metadatac                 C      d S r1   r#   r<   r   r=   r#   r#   r$   /_update_responses_api_response_id_with_model_id      zHResponsesAPIRequestUtils._update_responses_api_response_id_with_model_idc                 C   r>   r1   r#   r?   r#   r#   r$   r@      rA   c                 C   s   |pi }| di pi }| d}t| tr|  d}nt| dd}|du r(| S tj|||d}t| tr:|| d< n|| _| drItj| |d} | S )zUpdate the responses_api_response_id with model_id and custom_llm_provider.

        Handles both ``ResponsesAPIResponse`` objects and plain dictionaries returned
        by some streaming providers.
        
model_infoidN)model_idr   response_idZ"encrypted_content_affinity_enabled)responserD   )get
isinstancedictgetattrr    _build_responses_api_response_idrC   ._update_encrypted_content_item_ids_in_response)r<   r   r=   rB   rD   rE   Z
updated_idr#   r#   r$   r@      s.   




rD   item_idc                 C   s0   d|  d| }t |dd}d| S )zEncode model_id into an output item ID for encrypted-content items.

        Format: ``encitem_{base64("litellm:model_id:{model_id};item_id:{original_id}")}``
        litellm:model_id:z	;item_id:utf-8encitem_base64	b64encodeencodedecode)rD   rM   Z	assembledencodedr#   r#   r$   _build_encrypted_item_id   s   
z1ResponsesAPIRequestUtils._build_encrypted_item_id
encoded_idc                 C   s   |  dsdS zH| tdd }t|d }|r |dd|  7 }t|dd}|dd}t|dk r:W dS |d	 d
d}|d dd}||dW S  tyY   Y dS w )zDecode a litellm-encoded encrypted-content item ID.

        Returns a dict with ``model_id`` and ``item_id`` keys, or ``None`` if
        the string is not a litellm-encoded item ID.
        rP   N   =rO   ;      r   rN    zitem_id:)rD   rM   )	
startswithlenrR   	b64decoderT   rU   splitreplace	Exception)rX   cleanedmissingdecodedpartsrD   rM   r#   r#   r$   _decode_encrypted_item_id   s"   
z2ResponsesAPIRequestUtils._decode_encrypted_item_idencrypted_contentc                 C   s0   d| }t |dd}d| d|  S )aG  Wrap encrypted_content with model_id metadata for affinity routing.

        When Codex or other clients send items with encrypted_content but no ID,
        we encode the model_id directly into the encrypted_content itself.

        Format: ``litellm_enc:{base64("model_id:{model_id}")};{original_encrypted_content}``
        	model_id:rO   litellm_enc:r[   rQ   )rj   rD   r7   Zencoded_metadatar#   r#   r$   %_wrap_encrypted_content_with_model_id  s   
z>ResponsesAPIRequestUtils._wrap_encrypted_content_with_model_idwrapped_contentc                 C   s   |  ds	d| fS zC| dd}t|dk rd| fW S |d dd}|d }t|d }|r7|d	d|  7 }t|d
d
}|dd}||fW S  tyY   d| f Y S w )zUnwrap encrypted_content to extract model_id and original content.

        Returns:
            Tuple of (model_id, original_encrypted_content).
            If not wrapped, returns (None, original_content).
        rl   Nr[   r\   r]   r   r^   rY   rZ   rO   rk   )	r_   rb   r`   rc   rR   ra   rT   rU   rd   )rn   rh   Zmetadata_b64Zoriginal_contentrf   Zdecoded_metadatarD   r#   r#   r$   '_unwrap_encrypted_content_with_model_id  s&   



z@ResponsesAPIRequestUtils._unwrap_encrypted_content_with_model_idrF   r   c              	   C   s&  |s| S d}t | tr| d}nt| dd}t |ts| S |D ]p}t |trP|d}|d}|rOt |trOt|||d< |rOt |trOt|||d< q t|dd}t|dd}|rt |trz	t|||_	W n	 t
yu   Y nw |rt |trz	t|||_W q  t
y   Y q w q | S )ae  Rewrite item IDs for output items that contain ``encrypted_content``.

        Encodes ``model_id`` into the item ID so that follow-up requests can be
        routed back to the originating deployment without any cache lookup.

        For items without an ID (e.g., from Codex), encodes model_id directly
        into the encrypted_content itself.
        NoutputrC   rj   )rH   rI   rG   rJ   liststrr   rm   rW   rj   AttributeErrorrC   )rF   rD   rp   itemrM   rj   r#   r#   r$   rL   =  sV   





zGResponsesAPIRequestUtils._update_encrypted_content_item_ids_in_responserequest_inputc                 C   s   t | ts| S | D ];}t |trD|d}|r)t |tr)t|}|r)|d |d< |d}|rDt |trDt|\}}||krD||d< q	| S )aw  Decode litellm-encoded item IDs in request input back to original IDs.

        Called before forwarding the request to the upstream provider so the
        provider receives the original item IDs and unwrapped encrypted_content.

        Handles both:
        1. Items with encoded IDs (encitem_...)
        2. Items with wrapped encrypted_content (litellm_enc:...)
        rC   rM   rj   )rH   rq   rI   rG   rr   r   ri   ro   )ru   rt   rM   rg   rj   _Z	unwrappedr#   r#   r$   ,_restore_encrypted_content_item_ids_in_input  s&   




zEResponsesAPIRequestUtils._restore_encrypted_content_item_ids_in_inputrE   c                 C   s6   t tjj| ||}t|dd}d| S )z#Build the responses_api_response_idrO   resp_)	rr   r   Z%LITELLM_MANAGED_RESPONSE_COMPLETE_STRvalueformatrR   rS   rT   rU   )r   rD   rE   Zassembled_idZbase64_encoded_idr#   r#   r$   rK     s   

z9ResponsesAPIRequestUtils._build_responses_api_response_idc              
   C   s   zU|  dd}t|dd}d|vrtdd| dW S |d}d}d}t|dkrL|d }|d	 }|d
 }| dd}| dd}| dd}	n| }	t|||	dW S  tyy }
 zt	
d|  d|
  tdd| dW  Y d}
~
S d}
~
ww )z
        Decode the responses_api_response_id

        Returns:
            DecodedResponseId: Structured tuple with custom_llm_provider, model_id, and response_id
        rx   r^   rO   r[   N)r   rD   rE      r   r\   r]   zlitellm:custom_llm_provider:rk   zresponse_id:zError decoding response_id 'z': )rc   rR   ra   rT   rU   r   rb   r`   rd   r   debug)rE   Z
cleaned_idZ
decoded_idrh   r   rD   Zcustom_llm_provider_partZmodel_id_partZresponse_partdecoded_response_ider#   r#   r$   !_decode_responses_api_response_id  sH   

z:ResponsesAPIRequestUtils._decode_responses_api_response_idc                 C   s$   | du rdS t | }|dpdS )z%Get the model_id from the response_idNrD   r   r   rG   )rE   r}   r#   r#   r$   get_model_id_from_response_id  s
   z6ResponsesAPIRequestUtils.get_model_id_from_response_idr6   c                 C   s   t | }|d| S )aS  
        Decode the previous_response_id to the original previous_response_id

        Why?
            - LiteLLM encodes the `custom_llm_provider` and `model_id` into the `previous_response_id` this helps with maintaining session consistency when load balancing multiple deployments of the same model.
            - We cannot send the litellm encoded b64 to the upstream llm api, hence we decode it to the original `previous_response_id`

        Args:
            previous_response_id: The previous_response_id to decode

        Returns:
            The original previous_response_id
        rE   r   )r6   r}   r#   r#   r$   r:     s
   zUResponsesAPIRequestUtils.decode_previous_response_id_to_original_previous_response_idtext_formatr   textr   c                 C   sb   | dur/|du r/ddl m} || }|dur/d|d |d d |d d |d d	 d
i}|S |S )at  
        Convert text_format parameter to text parameter for the responses API.

        Args:
            text_format: Pydantic model class or dict to convert to response format
            text: Existing text parameter (if provided, text_format is ignored)

        Returns:
            ResponseText object with the converted format, or None if conversion fails
        Nr   )type_to_response_format_paramrz   typeZjson_schemanameschemastrict)r   r   r   r   )Z litellm.llms.base_llm.base_utilsr   )r   r   r   Zresponse_formatr#   r#   r$   !convert_text_format_to_text_param  s   


z:ResponsesAPIRequestUtils.convert_text_format_to_text_paramsecret_fieldstoolsc                 C   s  ddl m} ddlm} d}| rt| tr| d}d}d}d}|r5||}||}||}|	|}|r|D ]O}	t|	tr|	ddkr|	di }
|
rt|
tr||
}||}|r}|du rei }|
 D ]\}}||vrui ||< || | qi|du ri }||
 q9||||fS )	z
        Extract MCP auth headers from the request to pass to MCP server.
        Headers from tools.headers in request body should be passed to MCP server.
        r   )Headers)MCPRequestHandlerNZraw_headersr   Zmcpheaders)Zstarlette.datastructuresr   ZAlitellm.proxy._experimental.mcp_server.auth.user_api_key_auth_mcpr   rH   rI   rG   Z!_get_mcp_auth_header_from_headersZ)_get_mcp_server_auth_headers_from_headersZ _get_oauth2_headers_from_headersitemsupdate)r   r   r   r   Zraw_headers_from_requestZmcp_auth_headerZmcp_server_auth_headersZoauth2_headersZheaders_objZtoolZtool_headersZheaders_obj_from_toolZtool_mcp_server_auth_headersZserver_aliasZheaders_dictr#   r#   r$    extract_mcp_headers_from_request.  s@   





z9ResponsesAPIRequestUtils.extract_mcp_headers_from_requestr1   )%__name__
__module____qualname____doc__staticmethodr   r   rr   r   boolr%   r   r   r,   r   r;   r   r   r@   r   rW   ri   rm   tuplero   rL   rw   rK   r   r   r   r:   r   rI   r   r   r   r#   r#   r#   r$   r   #   s   

3
1

	-	 "B!8	!
r   c                   @   sL   e Zd Zedeeef defddZede	eeef  de
fddZdS )	ResponseAPILoggingUtilsusager)   c                 C   s&   t | trdS d| v rd| v rdS dS )z1returns True if usage is from OpenAI Response APITinput_tokensoutput_tokensF)rH   r   )r   r#   r#   r$   _is_response_api_usagel  s
   
z.ResponseAPILoggingUtils._is_response_api_usageusage_inputc                 C   sd  | du rt ddddS t| tr;| d}|du r3| d}| d}|dur3|dur3|| }|| d< tdi | }n| }|jpAd}|jpFd}d}|jrwt|jtr[tdi |j}ntt	|jddt	|jddt	|jd	dt	|jd
dd}d}t	|dd}	|	rt
t	|	ddt	|	d
dt	|	d	dd}t |||| ||d}
t|dr|jdurt|
d|j |
S )z
        Transforms ResponseAPIUsage or ImageUsage to a Usage object.

        Both have the same spec with input_tokens, output_tokens, and
        input_tokens_details (text_tokens, image_tokens).
        Nr   )prompt_tokenscompletion_tokenstotal_tokensr   r   r   cached_tokensaudio_tokenstext_tokensimage_tokens)r   r   r   r   output_tokens_detailsreasoning_tokens)r   r   r   )r   r   r   prompt_tokens_detailscompletion_tokens_detailscostr#   )r   rH   rI   rG   r   r   r   Zinput_tokens_detailsr   rJ   r   hasattrr   setattr)r   r   r   r   Zresponse_api_usager   r   r   r   r   Z
chat_usager#   r#   r$   +_transform_response_api_usage_to_chat_usageu  s`   









	zCResponseAPILoggingUtils._transform_response_api_usage_to_chat_usageN)r   r   r   r   r   rI   r   r   r   r   r   r   r#   r#   r#   r$   r   k  s    r   )!rR   typingr   r   r   r   r   r   r   r	   r
   r   Zpydanticr   r!   Zlitellm._loggingr   Z.litellm.llms.base_llm.responses.transformationr   Zlitellm.types.llms.openair   r   r   r   Zlitellm.types.responses.mainr   Zlitellm.types.utilsr   r   r   r   r   r   r#   r#   r#   r$   <module>   s    0    L