o
    ưi8Z                     @   s   d dl mZmZmZmZmZmZmZ d dlZd dl	m
Z
 d dlmZmZ d dlZd dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lT d d
lT d dlmZ d dlmZ ddlm Z  erkd dl!m"Z# e#Z$neZ$G dd deZ%dS )    )TYPE_CHECKINGAnyDictOptionalUnioncastget_type_hintsN)ResponseReasoningItem)	BaseModelValidationError)verbose_logger)process_response_headers)_safe_convert_created_field)BaseResponsesAPIConfig)get_secret_str)*)GenericLiteLLMParams)LlmProviders   )OpenAIError)Loggingc                   @   s  e Zd ZedefddZdedefddZde	dede
defd	d
Zdedeeef dedededefddZdeeef deeef fddZdeeef deeef fddZdedejdedefddZdededee defddZdee dedefddZdedededefd d!Zed"edefd#d$Z 	%dIdee d&ee
 d'ee de
fd(d)Z!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jdede%fd/d0Z&d,edededede#eef f
d1d2Z'dejdedefd3d4Z(	%	%	%	5	6dJd,edededed7ee d8ee d9ee)e  d:e*d;e+d< de#eef fd=d>Z,dejdedefd?d@Z-d,edededede#eef f
dAdBZ.dejdedefdCdDZ/dedeeef dedededede#eef fdEdFZ0dejdedefdGdHZ1d%S )KOpenAIResponsesAPIConfigreturnc                 C   s   t jS N)r   ZOPENAIself r   c/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/openai/responses/transformation.pycustom_llm_provider   s   z,OpenAIResponsesAPIConfig.custom_llm_providermodelc                 C   s$   t t }ttg dt| S )z?
        All OpenAI Responses API params are supported
        )inputr   extra_headersZextra_queryZ
extra_bodytimeout)r   ResponsesAPIRequestParamskeyslistset)r   r   Zsupported_paramsr   r   r   get_supported_openai_params#   s   z4OpenAIResponsesAPIConfig.get_supported_openai_paramsresponse_api_optional_paramsdrop_paramsc                 C   s   t |S )z:No mapping applied since inputs are in OpenAI spec already)dict)r   r(   r   r)   r   r   r   map_openai_params6   s   z*OpenAIResponsesAPIConfig.map_openai_paramsr    $response_api_optional_request_paramslitellm_paramsheadersc                 C   s&   |  |}ttd||d|}|S )z<No transform applied since inputs are in OpenAI spec alreadyr   r    Nr   )_validate_input_paramr*   r#   )r   r   r    r,   r-   r.   Zfinal_request_paramsr   r   r   transform_responses_api_request?   s   

z8OpenAIResponsesAPIConfig.transform_responses_api_requestc                 C   s   t |trTg }|D ]H}t |tr||jdd q	t |trL|ddkr=td|  t	t
ttf |}| |}n	t	t
ttf |}|| q	|| q	|S |S )z
        Ensure all input fields if pydantic are converted to dict

        OpenAI API Fails when we try to JSON dumps specific input pydantic fields.
        This function ensures all input fields are converted to dict.
        TZexclude_nonetype	reasoningzHandling reasoning item: )
isinstancer%   r
   append
model_dumpr*   getr   debugr   r   strr   _handle_reasoning_item)r   r    Zvalidated_inputitemZ	dict_itemfiltered_itemr   r   r   r0   R   s   
	

z.OpenAIResponsesAPIConfig._validate_input_paramr<   c              
   C   s   | ddkrcz6t|}d|vr.t| dddkr&| dddd d n| dd|d< tdi |}|jd	d
}|W S  tyb } ztd|  dd | D }|W  Y d}~S d}~ww |S )a  
        Handle reasoning items specifically to filter out status=None using OpenAI's model.
        Issue: https://github.com/BerriAI/litellm/issues/13484
        OpenAI API does not accept ReasoningItem(status=None), so we need to:
        1. Check if the item is a reasoning type
        2. Create a ResponseReasoningItem object with the item data
        3. Convert it back to dict with exclude_none=True to filter None values
        r3   r4   summaryZreasoning_content d   Nz...Tr2   zJFailed to create ResponseReasoningItem, falling back to manual filtering: c                 S   s&   i | ]\}}|d us|dvr||qS )N>   Zencrypted_contentstatuscontentr   ).0kvr   r   r   
<dictcomp>   s    zCOpenAIResponsesAPIConfig._handle_reasoning_item.<locals>.<dictcomp>r   )	r8   r*   lenr	   r7   	Exceptionr   r9   items)r   r<   Z	item_dataZreasoning_itemZdict_reasoning_itemer=   r   r   r   r;   r   s,   	
z/OpenAIResponsesAPIConfig._handle_reasoning_itemraw_responselogging_objc                 C   s   z|j |jdi id | }t|d |d< W n ty'   t|j|jdw t|j}t	|}z	t
d
i |}W n tyT   td| d t
jd
i |}Y nw ||jd< ||jd< |S )z=No transform applied since outputs are in OpenAI spec alreadycomplete_input_dictoriginal_responseZadditional_args
created_atmessagestatus_code)Error constructing ResponsesAPIResponse: , using model_constructadditional_headersr.   Nr   Z	post_calltextjsonr   rH   r   rS   r*   r.   r   ResponsesAPIResponser   r9   model_construct_hidden_params)r   r   rK   rL   raw_response_jsonraw_response_headersprocessed_headersresponser   r   r   transform_response_api_response   s6   



z8OpenAIResponsesAPIConfig.transform_response_api_responsec                 C   s<   |pt  }|jptjptjptd}|dd| i |S )NZOPENAI_API_KEYAuthorizationzBearer )r   api_keylitellmZ
openai_keyr   update)r   r.   r   r-   rc   r   r   r   validate_environment   s   

z-OpenAIResponsesAPIConfig.validate_environmentapi_basec                 C   s2   |pt jptdptdpd}|d}| dS )z;
        Get the endpoint for OpenAI responses API
        ZOPENAI_BASE_URLZOPENAI_API_BASEzhttps://api.openai.com/v1/z
/responses)rd   rg   r   rstrip)r   rg   r-   r   r   r   get_complete_url   s   	
	
z)OpenAIResponsesAPIConfig.get_complete_urlparsed_chunkc                 C   s   t d| t|d}tj|d}z#|d}t|tr5|ddu r5t|}t||d< d|d d< W n tyD   t d Y nw z|d
i |W S  t	yf   t d	|j
| |jd
i | Y S w )zb
        Transform a parsed streaming response chunk into a ResponsesAPIStreamingResponse
        zRaw OpenAI Chunk=%sr3   )
event_typeerrorcodeNZunknown_errorz-Failed to coalesce error.code in parsed_chunkzPPydantic validation failed for %s with chunk %s, falling back to model_constructr   )r   r9   r:   r8   r   get_event_model_classr5   r*   rH   r   __name__r[   )r   r   rk   rL   rl   Zevent_pydantic_modelZ	error_objr   r   r   transform_streaming_response   s2   

z5OpenAIResponsesAPIConfig.transform_streaming_responserl   c                 C   s>  i t jtt jtt jtt jtt j	t
t jtt jtt jtt jtt jtt jtt jtt jtt jtt jtt jt t j!t"i t j#t$t j%t&t j't(t j)t*t j+t,t j-t.t j/t0t j1t2t j3t4t j5t6t j7t8t j9t:t j;t<t j=t>t j?t@t jAtBt jCtBt jDtBi}|EtFt | }|stBS |S )a8  
        Returns the appropriate event model class based on the event type.

        Args:
            event_type (str): The type of event from the response chunk

        Returns:
            Any: The corresponding event model class

        Raises:
            ValueError: If the event type is unknown
        )GZResponsesAPIStreamEventsZRESPONSE_CREATEDZResponseCreatedEventZRESPONSE_IN_PROGRESSZResponseInProgressEventZRESPONSE_COMPLETEDZResponseCompletedEventZRESPONSE_FAILEDZResponseFailedEventZRESPONSE_INCOMPLETEZResponseIncompleteEventZOUTPUT_ITEM_ADDEDZOutputItemAddedEventZOUTPUT_ITEM_DONEZOutputItemDoneEventZCONTENT_PART_ADDEDZContentPartAddedEventZCONTENT_PART_DONEZContentPartDoneEventZOUTPUT_TEXT_DELTAZOutputTextDeltaEventZOUTPUT_TEXT_ANNOTATION_ADDEDZOutputTextAnnotationAddedEventZOUTPUT_TEXT_DONEZOutputTextDoneEventZREFUSAL_DELTAZRefusalDeltaEventZREFUSAL_DONEZRefusalDoneEventZFUNCTION_CALL_ARGUMENTS_DELTAZFunctionCallArgumentsDeltaEventZFUNCTION_CALL_ARGUMENTS_DONEZFunctionCallArgumentsDoneEventZFILE_SEARCH_CALL_IN_PROGRESSZFileSearchCallInProgressEventZFILE_SEARCH_CALL_SEARCHINGZFileSearchCallSearchingEventZFILE_SEARCH_CALL_COMPLETEDZFileSearchCallCompletedEventZWEB_SEARCH_CALL_IN_PROGRESSZWebSearchCallInProgressEventZWEB_SEARCH_CALL_SEARCHINGZWebSearchCallSearchingEventZWEB_SEARCH_CALL_COMPLETEDZWebSearchCallCompletedEventZMCP_LIST_TOOLS_IN_PROGRESSZMCPListToolsInProgressEventZMCP_LIST_TOOLS_COMPLETEDZMCPListToolsCompletedEventZMCP_LIST_TOOLS_FAILEDZMCPListToolsFailedEventZMCP_CALL_IN_PROGRESSZMCPCallInProgressEventZMCP_CALL_ARGUMENTS_DELTAZMCPCallArgumentsDeltaEventZMCP_CALL_ARGUMENTS_DONEZMCPCallArgumentsDoneEventZMCP_CALL_COMPLETEDZMCPCallCompletedEventZMCP_CALL_FAILEDZMCPCallFailedEventZIMAGE_GENERATION_PARTIAL_IMAGEZ ImageGenerationPartialImageEventERRORZ
ErrorEventZSHELL_CALL_IN_PROGRESSZGenericEventZSHELL_CALL_COMPLETEDZSHELL_CALL_OUTPUTr8   r   )rl   Zevent_modelsZmodel_classr   r   r   ro     s   	
 "#$'z.OpenAIResponsesAPIConfig.get_event_model_classNstreamr   c              
   C   sp   |durdS |d ur6zt jj||ddu rW dS W dS  ty5 } ztd|  W Y d }~dS d }~ww dS )NTF)r   r   z6Error getting model info in OpenAIResponsesAPIConfig: )rd   utilsZsupports_native_streamingrH   r   r9   )r   r   rs   r   rJ   r   r   r   should_fake_streamC  s*   z+OpenAIResponsesAPIConfig.should_fake_streamc                 C   s   dS )z2OpenAI supports native WebSocket for Responses APITr   r   r   r   r   supports_native_websocket[  s   z2OpenAIResponsesAPIConfig.supports_native_websocketresponse_idc                 C      | d| }i }||fS )z
        Transform the delete response API request into a URL and data

        OpenAI API expects the following request
        - DELETE /v1/responses/{response_id}
        rh   r   r   rw   rg   r-   r.   urldatar   r   r   %transform_delete_response_api_requestb     z>OpenAIResponsesAPIConfig.transform_delete_response_api_requestc                 C   s:   z|  }W n ty   t|j|jdw tdi |S )zX
        Transform the delete response API response into a DeleteResponseResult
        rQ   Nr   )rY   rH   r   rX   rS   DeleteResponseResult)r   rK   rL   r]   r   r   r   &transform_delete_response_api_responses  s   z?OpenAIResponsesAPIConfig.transform_delete_response_api_responsec                 C   rx   )z
        Transform the get response API request into a URL and data

        OpenAI API expects the following request
        - GET /v1/responses/{response_id}
        rh   r   ry   r   r   r   "transform_get_response_api_request  r}   z;OpenAIResponsesAPIConfig.transform_get_response_api_requestc                 C   d   z|  }W n ty   t|j|jdw t|j}t|}tdi |}||j	d< ||j	d< |S )zU
        Transform the get response API response into a ResponsesAPIResponse
        rQ   rV   r.   Nr   
rY   rH   r   rX   rS   r*   r.   r   rZ   r\   r   rK   rL   r]   r^   r_   r`   r   r   r   #transform_get_response_api_response  s   


z<OpenAIResponsesAPIConfig.transform_get_response_api_response   descafterbeforeincludelimitorder)ascr   c
                 C   sn   | d| d}
i }|d ur||d< |d ur||d< |r#d ||d< |d ur+||d< |	d ur3|	|d< |
|fS )	Nrh   z/input_itemsr   r   ,r   r   r   )join)r   rw   rg   r-   r.   r   r   r   r   r   rz   paramsr   r   r   "transform_list_input_items_request  s   z;OpenAIResponsesAPIConfig.transform_list_input_items_requestc                 C   s*   z|  W S  ty   t|j|jdw )NrQ   )rY   rH   r   rX   rS   )r   rK   rL   r   r   r   #transform_list_input_items_response  s   
z<OpenAIResponsesAPIConfig.transform_list_input_items_responsec                 C   s   | d| d}i }||fS )z
        Transform the cancel response API request into a URL and data

        OpenAI API expects the following request
        - POST /v1/responses/{response_id}/cancel
        rh   z/cancelr   ry   r   r   r   %transform_cancel_response_api_request  s   z>OpenAIResponsesAPIConfig.transform_cancel_response_api_requestc                 C   r   )zX
        Transform the cancel response API response into a ResponsesAPIResponse
        rQ   rV   r.   Nr   r   r   r   r   r   &transform_cancel_response_api_response  s   


z?OpenAIResponsesAPIConfig.transform_cancel_response_api_responsec                 C   sT   t |}|jdd }t|j|d}	| |}ttd||d|}
|	|
fS )z
        Transform the compact response API request into a URL and data

        OpenAI API expects the following request
        - POST /v1/responses/compact
        rh   z/compact)pathr/   Nr   )	httpxURLr   ri   r:   	copy_withr0   r*   r#   )r   r   r    r,   rg   r-   r.   
parsed_urlZcompact_pathrz   r{   r   r   r   &transform_compact_response_api_request  s   

z?OpenAIResponsesAPIConfig.transform_compact_response_api_requestc                 C   s   z|j |jdi id | }t|d |d< W n ty'   t|j|jdw t|j}t	|}z	t
d
i |}W n tyT   td| d t
jd
i |}Y nw ||jd< ||jd< |S )zY
        Transform the compact response API response into a ResponsesAPIResponse
        rM   rN   rP   rQ   rT   rU   rV   r.   Nr   rW   r   r   r   r   'transform_compact_response_api_response!  s6   



z@OpenAIResponsesAPIConfig.transform_compact_response_api_responser   )NNNr   r   )2rp   
__module____qualname__propertyr   r   r:   r%   r'   Z!ResponsesAPIOptionalRequestParamsboolr   r+   r   ZResponseInputParamr   r*   r1   r0   r   r;   r   ResponseLiteLLMLoggingObjrZ   ra   r   rf   rj   ZResponsesAPIStreamingResponserq   staticmethodro   ru   rv   Tupler|   r~   r   r   r   ListintLiteralr   r   r   r   r   r   r   r   r   r   r      sx   
	




" )
#


$>







	









r   )&typingr   r   r   r   r   r   r   r   Zopenai.types.responsesr	   Zpydanticr
   r   rd   Zlitellm._loggingr   Z'litellm.litellm_core_utils.core_helpersr   ZFlitellm.litellm_core_utils.llm_response_utils.convert_dict_to_responser   Z.litellm.llms.base_llm.responses.transformationr   Zlitellm.secret_managers.mainr   Zlitellm.types.llms.openaiZlitellm.types.responses.mainZlitellm.types.routerr   Zlitellm.types.utilsr   Zcommon_utilsr   Z*litellm.litellm_core_utils.litellm_loggingr   Z_LiteLLMLoggingObjr   r   r   r   r   r   <module>   s(   $ 