
    AHj                        d dl Z d dlZd dlmZmZmZmZmZmZm	Z	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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! er6d 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.m/Z/m0Z0m1Z1 d dl2m3Z3 e
e&ef   Z%neZ%eZ+eZ-eZ/eZ0eZ1eZ4eZ5eZ3 e jl                  de jn                        Z8 G d d      Z9y)    N)TYPE_CHECKINGAnyAsyncGeneratorDictListOptionalTupleUnion)	BaseModelverbose_logger)/DEFAULT_MAX_RECURSE_DEPTH_SENSITIVE_DATA_MASKER)ArgillaItem)AllMessageValuesChatCompletionRequest)
PromptSpec)	AdapterCompletionStreamWrapper	CallTypesCallTypesLiteralLLMResponseTypesModelResponseModelResponseStreamStandardAuditLogPayloadStandardCallbackDynamicParamsStandardLoggingPayload)HTTPException)Span)	DualCache)Logging)UserAPIKeyAuth)MCPPostCallResponseObjectMCPPreCallRequestObjectMCPPreCallResponseObject)PreRoutingHookResponsezOdata:(?:application|image|audio|video)/[a-zA-Z0-9.+-]+;base64,[A-Za-z0-9+/=\s]+c                    D   e Zd Z	 	 d}dededdfdZed~dee   dee   fd       Z	d Z
d	 Zd
 Zd Zd Zd Zd Zdedededee   fdZd Zd ZddZ	 	 	 	 	 	 ddedee   dedee   dee   dededee   deee      dee   dee   dee   d ee   deeee   ef   fd!Z	 	 	 	 	 ddedee   dedee   dee   dedee   dee   dee   dee   d ee   deeee   ef   fd"Z	 	 	 	 dded#edeeeeef         d$eeeef      d%ee   dee    fd&Z!	 	 dded'edeee      d#ee   d(ee"   dee   fd)Z#deee$f   d*ee%   dee   fd+Z&d,ed(ee"   dee   fd-Z'd,edee   fd.Z(d/ed0e)d*ee%   dee)   fd1Z*d/ed2e$d*ee%   dee$   fd3Z+d4e,d5ee   defd6Z-d5eded7e,fd8Z.d5eded7e,fd9Z/dee0   fd:Z1d0e2dee3   fd;Z4d<e$dee5   fd=Z6d>e7d?ee8   dee7   fd@Z9	 dAe:dBdCdDed*e;deee,eef      f
dEZ<	 	 ddDedAe:d0e$dFeeeef      dGeeee$f      deeeef      fdHZ=	 d~d/ed7e,dAe:dIee   dedJ   f
dKZ>dDedAe:d0e)de$fdLZ?dedMe$d*edeee$f   fdNZ@dedMe$d*edeee$f   fdOZAdDedAe:d*e;de$fdPZBdAe:d0ede$fdQZCdAe:d0e$d/edeDeEdf   fdRZFdS ZGdT ZHdU ZIdV ZJdWeKdeeK   fdXZLd0e$dedee   deee      dYedZededeeef   fd[ZMdededee   d0e$d\e$d]ed^d_dYedede$fd`ZNd0e$dedee   deee      dYedZededeeef   fdaZOdededee   d0e$dbed^d_dYedede$fdcZPdde8fdeZQdde8dfedgeddfdhZRdiedgedefdjZS	 d~d#ee   dee   fdkZTdledefdmZUdnedee   fdoZVdefdpZWeXfdqdrdseddrfdtZYeXfdqdrdseddrfduZZdveXfdwe$dxedsede$fdyZ[dze$defd{Z\eXfdee$   dsedeeee$f      fd|Z]y)CustomLoggerturn_off_message_loggingmessage_loggingreturnNc                      || _         || _        y)a  
        Args:
            turn_off_message_logging: bool - if True, the message logging will be turned off. Message and response will be redacted from StandardLoggingPayload.
            message_logging: bool - deprecated param, use `turn_off_message_logging` instead
        N)r(   r'   )selfr'   r(   kwargss       Z/root/tools/cai/cai_env/lib/python3.12/site-packages/litellm/integrations/custom_logger.py__init__zCustomLogger.__init__F   s      /(@%    callback_namec                     | g S | j                         }ddi}|j                  ||      }	 ddlm}  |       }t        ||d      }|g S t        |dd      }|sg S t        |      S # t        $ r g cY S w xY w)a2  
        Return the environment variables associated with a given callback
        name as defined in the proxy callback registry.

        Args:
            callback_name: The name of the callback to look up.

        Returns:
            List[str]: A list of required environment variable names.
        Nlangfuse_otellangfuser   )AllCallbackslitellm_callback_params)lowergetlitellm.proxy._typesr4   	Exceptiongetattrlist)r0   normalized_name	alias_maplookup_namer4   	callbackscallback_infoparamss           r-   get_callback_env_varsz"CustomLogger.get_callback_env_varsV   s      I'--/ Z
	  mmO_E	9 !N		;= I(A4HIF|  	I	s   A& &A43A4c                      y N r+   modelmessagesr,   s       r-   log_pre_api_callzCustomLogger.log_pre_api_call|       r/   c                      y rD   rE   r+   r,   response_obj
start_timeend_times        r-   log_post_api_callzCustomLogger.log_post_api_call   rJ   r/   c                      y rD   rE   rL   s        r-   log_stream_eventzCustomLogger.log_stream_event   rJ   r/   c                      y rD   rE   rL   s        r-   log_success_eventzCustomLogger.log_success_event   rJ   r/   c                      y rD   rE   rL   s        r-   log_failure_eventzCustomLogger.log_failure_event   rJ   r/   c                    K   y wrD   rE   rL   s        r-   async_log_stream_eventz#CustomLogger.async_log_stream_event   	        c                    K   y wrD   rE   rF   s       r-   async_log_pre_api_callz#CustomLogger.async_log_pre_api_call   rY   rZ   rG   rH   r,   c                    K   yw)a  
        Hook called before making the API request to allow modifying request parameters.

        This is specifically designed for modifying the request before it's sent to the provider.
        Unlike async_log_pre_api_call (which is for logging), this hook is meant for transformations.

        Args:
            model: The model name
            messages: The messages list
            kwargs: The request parameters (tools, stream, temperature, etc.)

        Returns:
            Optional[Dict]: Modified kwargs to use for the request, or None if no modifications

        Example:
            ```python
            async def async_pre_request_hook(self, model, messages, kwargs):
                # Convert native tools to standard format
                if kwargs.get("tools"):
                    kwargs["tools"] = convert_tools(kwargs["tools"])
                return kwargs
            ```
        NrE   rF   s       r-   async_pre_request_hookz#CustomLogger.async_pre_request_hook   s     4 	rZ   c                    K   y wrD   rE   rL   s        r-   async_log_success_eventz$CustomLogger.async_log_success_event   rY   rZ   c                    K   y wrD   rE   rL   s        r-   async_log_failure_eventz$CustomLogger.async_log_failure_event   rY   rZ   c                    K   yw)zFCalled when an audit log is created. Override in subclasses to handle.NrE   )r+   	audit_logs     r-   async_log_audit_log_eventz&CustomLogger.async_log_audit_log_event   s	     rZ   non_default_params	prompt_idprompt_variablesdynamic_callback_paramslitellm_logging_objprompt_spectoolsprompt_labelprompt_versionignore_prompt_manager_model%ignore_prompt_manager_optional_paramsc                    K   |||fS wax  
        Returns:
        - model: str - the model to use (can be pulled from prompt management tool)
        - messages: List[AllMessageValues] - the messages to use (can be pulled from prompt management tool)
        - non_default_params: dict - update with any optional params (e.g. temperature, max_tokens, etc.) to use (can be pulled from prompt management tool)
        rE   )r+   rG   rH   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   s                 r-    async_get_chat_completion_promptz-CustomLogger.async_get_chat_completion_prompt   s     , h 222s   c                     |||fS rr   rE   )r+   rG   rH   rf   rg   rh   ri   rk   rm   rn   ro   rp   s               r-   get_chat_completion_promptz'CustomLogger.get_chat_completion_prompt   s    ( h 222r/   request_kwargsinputspecific_deploymentc                    K   yw)z
        This hook is called before the routing decision is made.

        Used for the litellm auto-router to modify the request before the routing decision is made.
        NrE   )r+   rG   rv   rH   rw   rx   s         r-   async_pre_routing_hookz#CustomLogger.async_pre_routing_hook   s      rZ   healthy_deploymentsparent_otel_spanc                    K   |S wrD   rE   )r+   rG   r{   rH   rv   r|   s         r-   async_filter_deploymentsz%CustomLogger.async_filter_deployments   s      #"s   	call_typec                    K   yw)a  
        Allow modifying the request just before it's sent to the deployment.

        Use this instead of 'async_pre_call_hook' when you need to modify the request AFTER a deployment is selected, but BEFORE the request is sent.

        Used in managed_files.py
        NrE   )r+   r,   r   s      r-   async_pre_call_deployment_hookz+CustomLogger.async_pre_call_deployment_hook  s      	rZ   
deploymentc                    K   y wrD   rE   )r+   r   r|   s      r-   async_pre_call_checkz!CustomLogger.async_pre_call_check        	rZ   c                      y rD   rE   )r+   r   s     r-   pre_call_checkzCustomLogger.pre_call_check  rJ   r/   request_dataresponsec                    K   yw)zh
        Allow modifying / reviewing the response just after it's received from the deployment.
        NrE   )r+   r   r   r   s       r-   'async_post_call_success_deployment_hookz4CustomLogger.async_post_call_success_deployment_hook        	rZ   response_chunkc                    K   yw)z
        Allow modifying streaming chunks just before they're returned to the user.

        This is called for each streaming chunk in the response.
        NrE   )r+   r   r   r   s       r-   )async_post_call_streaming_deployment_hookz6CustomLogger.async_post_call_streaming_deployment_hook&  s      	rZ   	exceptionoriginal_model_groupc                    K   y wrD   rE   )r+   r   r   r,   s       r-    log_model_group_rate_limit_errorz-CustomLogger.log_model_group_rate_limit_error4  r   rZ   original_exceptionc                    K   y wrD   rE   r+   r   r,   r   s       r-   log_success_fallback_eventz'CustomLogger.log_success_fallback_event9  r   rZ   c                    K   y wrD   rE   r   s       r-   log_failure_fallback_eventz'CustomLogger.log_failure_fallback_event>  r   rZ   c                      y)zt
        Translates the input params, from the provider's native format to the litellm.completion() format.
        NrE   )r+   r,   s     r-   !translate_completion_input_paramsz.CustomLogger.translate_completion_input_paramsE       	r/   c                      y)z\
        Translates the output params, from the OpenAI format to the custom format.
        NrE   )r+   r   s     r-   "translate_completion_output_paramsz/CustomLogger.translate_completion_output_paramsM  r   r/   completion_streamc                      y)z^
        Translates the streaming chunk, from the OpenAI format to the custom format.
        NrE   )r+   r   s     r-   ,translate_completion_output_params_streamingz9CustomLogger.translate_completion_output_params_streamingU  r   r/   logged_itemstandard_logging_payloadc                     K   t        d      w)z
        - Decide if the result should be logged to Argilla.
        - Modify the result before logging to Argilla.
        - Return None if the result should not be logged to Argilla.
        z"async_dataset_hook not implemented)NotImplementedError)r+   r   r   s      r-   async_dataset_hookzCustomLogger.async_dataset_hook_  s      ""FGGs   user_api_key_dictcacher   datac                    K   y wrD   rE   )r+   r   r   r   r   s        r-   async_pre_call_hookz CustomLogger.async_pre_call_hookp  r   rZ   request_headerslitellm_call_infoc                    K   yw)a  
        Called after an LLM API call (success or failure) to allow injecting custom HTTP response headers.

        Args:
            - data: dict - The request data.
            - user_api_key_dict: UserAPIKeyAuth - The user API key dictionary.
            - response: Any - The response object (None for failure cases).
            - request_headers: Optional[Dict[str, str]] - The original request headers.
            - litellm_call_info: Optional[Dict[str, Any]] - Normalized routing metadata:
                - custom_llm_provider: str - The LLM provider (e.g. "openai", "azure")
                - model_info: dict - The model_info from router config
                - api_base: str - The API base URL used
                - model_id: str - The deployment model ID

        Returns:
            - Optional[Dict[str, str]]: A dictionary of headers to inject into the HTTP response.
                                        Return None to not inject any headers.
        NrE   )r+   r   r   r   r   r   s         r-   %async_post_call_response_headers_hookz2CustomLogger.async_post_call_response_headers_hook{  s     4 rZ   traceback_strr   c                    K   yw)au  
        Called after an LLM API call fails. Can return or raise HTTPException to transform error responses.

        Args:
            - request_data: dict - The request data.
            - original_exception: Exception - The original exception that occurred.
            - user_api_key_dict: UserAPIKeyAuth - The user API key dictionary.
            - traceback_str: Optional[str] - The traceback string.

        Returns:
            - Optional[HTTPException]: Return an HTTPException to transform the error response sent to the client.
                                      Return None to use the original exception.
        NrE   )r+   r   r   r   r   s        r-   async_post_call_failure_hookz)CustomLogger.async_post_call_failure_hook  s     ( 	rZ   c                    K   y wrD   rE   )r+   r   r   r   s       r-   async_post_call_success_hookz)CustomLogger.async_post_call_success_hook        	rZ   resultc                    K   ||fS wzUFor masking logged request/response. Return a modified version of the request/result.rE   r+   r,   r   r   s       r-   async_logging_hookzCustomLogger.async_logging_hook  s      v~   c                 
    ||fS r   rE   r   s       r-   logging_hookzCustomLogger.logging_hook  s     v~r/   c                    K   y wrD   rE   )r+   r   r   r   s       r-   async_moderation_hookz"CustomLogger.async_moderation_hook  r   rZ   c                    K   y wrD   rE   )r+   r   r   s      r-   async_post_call_streaming_hookz+CustomLogger.async_post_call_streaming_hook  s     
 	rZ   c                4   K   |2 3 d {   }| 7 
6 y wrD   rE   )r+   r   r   r   items        r-   'async_post_call_streaming_iterator_hookz4CustomLogger.async_post_call_streaming_iterator_hook  s$      # 	 	$J	(s   c                     	 ||d<   ||d<   d|d<    ||        |d|        y # t         $ r   |dt        j                                 Y y w xY wNrG   rH   pre_api_calllog_event_typez$Custom Logger - model call details: Custom Logger Error - r9   	traceback
format_excr+   rG   rH   r,   print_verbosecallback_funcs         r-   log_input_eventzCustomLogger.log_input_event  sn    		M#F7O!)F:'5F#$ @IJ 	M293G3G3I2JKL	Ms   "% &AAc                    K   	 ||d<   ||d<   d|d<    ||       d {     |d|        y 7 # t         $ r   |dt        j                                 Y y w xY wwr   r   r   s         r-   async_log_input_eventz"CustomLogger.async_log_input_event  s     		M#F7O!)F:'5F#$   @IJ  	M293G3G3I2JKL	Ms1   A1 /1 A1 &AAAAc                 ~    	 d|d<    |||||       y # t         $ r   |dt        j                                 Y y w xY wNpost_api_callr   r   r   r+   r,   rM   rN   rO   r   r   s          r-   	log_eventzCustomLogger.log_event  sT    
	'6F#$	  	293G3G3I2JKL	s    &<<c                    K   	 d|d<    |||||       d {    y 7 # t         $ r   |dt        j                                 Y y w xY wwr   r   r   s          r-   async_log_eventzCustomLogger.async_log_event  sa     
	'6F#$	    	293G3G3I2JKL	s1   A  A &AAAArM   c                    K   yw)z
        This log gets called after the MCP tool call is made.

        Useful if you want to modiy the standard logging payload after the MCP tool call is made.
        NrE   rL   s        r-   async_post_mcp_tool_call_hookz*CustomLogger.async_post_mcp_tool_call_hook  s      rZ   streamcustom_llm_providerc                    K   di fS w)a  
        Hook to determine if agentic loop should be executed.

        Called after receiving response from model, before returning to user.

        USE CASE: Enables transparent server-side tool execution for models that
        don't natively support server-side tools. User makes ONE API call and gets
        back the final answer - the agentic loop happens transparently on the server.

        Example use cases:
        - WebSearch: Intercept WebSearch tool calls for Bedrock/Claude, execute
          litellm.search(), return final answer with search results
        - Code execution: Execute code in sandboxed environment, return results
        - Database queries: Execute queries server-side, return data to model
        - API calls: Make external API calls and inject responses back into context

        Flow:
        1. User calls litellm.messages.acreate(tools=[...])
        2. Model responds with tool_use
        3. THIS HOOK checks if tool should run server-side
        4. If True, async_run_agentic_loop executes the tool
        5. User receives final answer (never sees intermediate tool_use)

        Args:
            response: Response from model (AnthropicMessagesResponse or AsyncIterator)
            model: Model name
            messages: Original messages sent to model
            tools: List of tool definitions from request
            stream: Whether response is streaming
            custom_llm_provider: Provider name (e.g., "bedrock", "anthropic")
            kwargs: Additional request parameters

        Returns:
            (should_run, tools):
                should_run: True if agentic loop should execute
                tools: Dict with tool_calls and metadata for execution

        Example:
            # Detect WebSearch tool call
            if has_websearch_tool_use(response):
                return True, {
                    "tool_calls": extract_tool_calls(response),
                    "tool_type": "websearch"
                }
            return False, {}
        FrE   r+   r   rG   rH   rl   r   r   r,   s           r-   async_should_run_agentic_loopz*CustomLogger.async_should_run_agentic_loop'  s     p byr   "anthropic_messages_provider_config*anthropic_messages_optional_request_paramslogging_objLiteLLMLoggingObjc
                    K   yw)aI	  
        Hook to execute agentic loop based on context from should_run hook.

        Called only if async_messages_should_run_agentic_loop returns True.

        USE CASE: Execute server-side tools and orchestrate the agentic loop to
        return a complete answer to the user in a single API call.

        What to do here:
        1. Extract tool calls from tools dict
        2. Execute the tools (litellm.search, code execution, DB queries, etc.)
        3. Build assistant message with tool_use blocks
        4. Build user message with tool_result blocks containing results
        5. Make follow-up litellm.messages.acreate() call with results
        6. Return the final response

        Args:
            tools: Dict from async_should_run_agentic_loop
                  Contains tool_calls and metadata
            model: Model name
            messages: Original messages sent to model
            response: Original response from model (with tool_use)
            anthropic_messages_provider_config: Provider config for making requests
            anthropic_messages_optional_request_params: Request parameters (tools, etc.)
            logging_obj: LiteLLM logging object
            stream: Whether response is streaming
            kwargs: Additional request parameters

        Returns:
            Final response after executing agentic loop
            (AnthropicMessagesResponse with final answer)

        Example:
            # Extract tool calls
            tool_calls = agentic_context["tool_calls"]

            # Execute searches in parallel
            search_results = await asyncio.gather(
                *[litellm.asearch(tc["input"]["query"]) for tc in tool_calls]
            )

            # Build messages with tool results
            assistant_msg = {"role": "assistant", "content": [...tool_use blocks...]}
            user_msg = {"role": "user", "content": [...tool_result blocks...]}

            # Make follow-up request
            from litellm.anthropic_interface import messages
            final_response = await messages.acreate(
                model=model,
                messages=messages + [assistant_msg, user_msg],
                max_tokens=anthropic_messages_optional_request_params.get("max_tokens"),
                **anthropic_messages_optional_request_params
            )

            return final_response
        NrE   )
r+   rl   rG   rH   r   r   r   r   r   r,   s
             r-   async_run_agentic_loopz#CustomLogger.async_run_agentic_loopa  s     H 	rZ   c                    K   di fS w)zW
        Hook to determine if chat completion agentic loop should be executed.
        FrE   r   s           r-   -async_should_run_chat_completion_agentic_loopz:CustomLogger.async_should_run_chat_completion_agentic_loop  s      byr   optional_paramsc	                    K   yw)ze
        Hook to execute chat completion agentic loop based on context from should_run hook.
        NrE   )	r+   rl   rG   rH   r   r   r   r   r,   s	            r-   &async_run_chat_completion_agentic_loopz3CustomLogger.async_run_chat_completion_agentic_loop  s      	rZ   standard_logging_objectc                 F    d}g d}|D ]  }| j                  |||        y)a  
        Truncate error strings and message content in logging payload

        Some loggers like DataDog/ GCS Bucket have a limit on the size of the payload. (1MB)

        This function truncates the error string and the message content if they exceed a certain length.
        i'  )	error_strrH   r   )r   
field_name
max_lengthN)_truncate_field)r+   r   MAX_STR_LENGTHfields_to_truncatefields        r-   )truncate_standard_logging_payload_contentz6CustomLogger.truncate_standard_logging_payload_content  s=       C' 	E  (? ) ! 	r/   r   r   c                     |j                  |      }|r1t        |      }t        |      |kD  r| j                  ||      ||<   yyy)aP  
        Helper function to truncate a field in the logging payload

        This converts the field to a string and then truncates it if it exceeds the max length.

        Why convert to string ?
        1. User was sending a poorly formatted list for `messages` field, we could not predict where they would send content
            - Converting to string and then truncating the logged content catches this
        2. We want to avoid modifying the original `messages`, `response`, and `error_str` in the logging payload since these are in kwargs and could be returned to the user
        )textr   N)r7   strlen_truncate_text)r+   r   r   r   field_value	str_values         r-   r   zCustomLogger._truncate_field  sX      .11*=K(I9~
*6:6I6I"z 7J 7'
3 + r/   r   c                 2    t        |      |kD  r|d| dz   S |S )z&Truncate text if it exceeds max_lengthNzC...truncated by litellm, this logger does not support large content)r   )r+   r   r   s      r-   r   zCustomLogger._truncate_text  s4    
 4y:% *ST	
 		
r/   c                 (    ddl m}m} |y||v r|S |S )z
        Select the metadata field to use for logging

        1. If `litellm_metadata` is in the request kwargs, use it
        2. Otherwise, use `metadata`
        r   )LITELLM_METADATA_FIELDOLD_LITELLM_METADATA_FIELDN)litellm.constantsr   r   )r+   rv   r   r   s       r-   _select_metadata_fieldz#CustomLogger._select_metadata_field  s%     	Y!!^3))))r/   model_call_detailsc                 0   ddl }ddlm} ddl m}m}m} t        | dd      }t        |dd      }|du r|s|S  ||      }	|j                  d      }
|
|	S  ||
      }|r|D ]
  }||v s||=  |r!d	}d
|xs g vr,|j                  d
       ||      j                         g|d
<   d|xs g vr|j                  d      |d   }t        |t              rd|v rddlm
}  ||      }t        |j                  d      t              rY|d   D ]Q  }t        |t              sd|v st        |d   t              s-|d   D ]  }t        |t              sd|v s||d<    S ||d<   n- | | ||            g      }|j                         }||d<   ||	d<   |	S )a  
        Redacts or excludes fields from StandardLoggingPayload before callbacks receive it.

        This method handles two features:
        1. turn_off_message_logging: When True, redacts messages and responses
        2. standard_logging_payload_excluded_fields: Removes specified fields entirely

        Return a modified copy of the provided logging payload.

        This is useful for logging payloads that contain sensitive information.
        r   N)copy)ChoicesMessager   r'   F(standard_logging_payload_excluded_fieldsr   zredacted-by-litellmrH   contentr   output)deepcopyr
  r   )message)choices)litellmr  r  r  r   r:   r7   
model_dump
isinstancedictr  r;   )r+   r  r  r  r  r  r   r'   excluded_fieldsmodel_call_details_copyr   standard_logging_object_copyr   redacted_strr   r  response_copyoutput_itemcontent_itemmodel_responsemodel_response_dicts                        r-   7redact_standard_logging_payload_from_model_call_detailszDCustomLogger.redact_standard_logging_payload_from_model_call_details  s    	;;)0,e*
  07?0

 $u,_%% #''9":"4"8"89R"S"*** (,,C'D$ ( <884U;<
 $0L ?#8b9044Z@L L1<<><,Z8
 ?#8b9044Z@L7
Ch-(h2F-$,X$6M!-"3"3H"=tD+8+B PK *; =$-$<#-k).Dd#K8CI8N %P,6|T,J06,0FCOL,@%PP @M0< &3!(1N!O P&N +9*C*C*E'?R0< ) 	 %	
 '&r/   
object_keyc                    K   yw)z_
        Get the proxy server request from cold storage using the object key directly.
        NrE   )r+   r  s     r-   :get_proxy_server_request_from_cold_storage_with_object_keyzGCustomLogger.get_proxy_server_request_from_cold_storage_with_object_keyr  s      	rZ   c           	      l   	 ddl }ddlm} |j                  j	                         }|D ]7  }t        |d      s |j                  d|        |j                  |        y  |j                  d| d       y# t        $ r1}ddlm}  |j                  d	| d
t        |              Y d}~yd}~ww xY w)z
        Handle callback logging failures by incrementing Prometheus metrics.

        Call this method in exception handlers within your callback when logging fails.
        r   Nr   "increment_callback_logging_failurez)Incrementing callback failure metric for )r0   zENo callback with increment_callback_logging_failure method found for z2. Ensure 'prometheus' is in your callbacks config.z%Error in handle_callback_failure for z: )
r  litellm._loggingr   logging_callback_manager_get_all_callbackshasattrdebugr!  r9   r   )r+   r0   r  r   all_callbackscallback_objes          r-   handle_callback_failurez$CustomLogger.handle_callback_failure{  s    	7#<<OOQM - <)MN(N((CM?S !CCR_C` !N  WXeWf gC C
  	7 N  7bQQ 	s"   5A9 (A9 !A9 9	B3'B..B3payloadr   	max_depthc                   K   |j                  dg       }t        |t              r|ng }t        j                  dt        |       d       |r| j                  ||      |d<   d}|j                  dg       xs g D ]D  }t        |t              s|j                  dg       }t        |t              s7|t        |      z  }F t        j                  d| d       |S w	u  
        Removes or redacts base64-encoded file data (e.g., PDFs, images, audio)
        from messages and responses before sending to SQS.

        Behavior:
          • Drop entries with a 'file' key.
          • Drop entries with type == 'file' or any non-text type.
          • Keep untyped or text content.
          • Recursively redact inline base64 blobs in *any* string field, at any depth.
        rH   z%[CustomLogger] Stripping base64 from z	 messages)rH   r,  r   r
  z0[CustomLogger] Completed base64 strip; retained z content itemsr7   r  r;   r   r&  r   _process_messagesr  r+   r+  r,  raw_messagesrH   total_itemsmr
  s           r-   _strip_base64_from_messagesz(CustomLogger._strip_base64_from_messages  s      $KK
B7.8t.LlRT3CM?)L	
 "&"8"8!Y #9 #GJ Z,2 	0A!T"%%	2.gt,3w</K		0 	>{m>Z	
 s   BC"C2+Cc                    |j                  dg       }t        |t              r|ng }t        j                  dt        |       d       |r| j                  ||      |d<   d}|j                  dg       xs g D ]D  }t        |t              s|j                  dg       }t        |t              s7|t        |      z  }F t        j                  d| d       |S r.  r/  r1  s           r-    _strip_base64_from_messages_syncz-CustomLogger._strip_base64_from_messages_sync  s     $KK
B7.8t.LlRT3CM?)L	
 "&"8"8!Y #9 #GJ Z,2 	0A!T"%%	2.gt,3w</K		0 	>{m>Z	
 r/   r   valuedepthc           
         ||kD  rt        j                  d| d       yt        |t              rIt        j                  |      r2t        j                  d|dd  d       t        j                  d|      S |S t        |t              r%|D cg c]  }| j                  ||d	z   |
       c}S t        |t              r9|j                         D ci c]  \  }}|| j                  ||d	z   |
       c}}S |S c c}w c c}}w )z\Recursively redact inline base64 from any nested structure with a max recursion depth limit.z#[CustomLogger] Max recursion depth z reached while redacting base64z[MAX_DEPTH_REACHED]z.[CustomLogger] Redacted inline base64 string: N(   z...z[BASE64_REDACTED]   )r8  r9  r,  )r   warningr  r   _BASE64_INLINE_PATTERNsearchr&  subr;   _redact_base64r  items)r+   r8  r9  r,  vks         r-   rA  zCustomLogger._redact_base64  s    9""5i[@_` )eS!%,,U3$$DU3BZLPST .112EuMMLeT"  ##!519	#R 
 eT" "KKMAq 4&&Qeai9&UU 
 s   C9"C>r
  c                     t        |t              syd|v ry|j                  d      }t        |t              xr |dk7   S )z4Return True if this content item should be retained.TfileFtyper   )r  r  r7   r   )r+   r
  ctypes      r-   _should_keep_contentz!CustomLogger._should_keep_content
  sA    '4(WF#uc*>u??r/   c                    g }|D ]  }t        |t              s|j                  d      }t        |t              rDg }|D ]7  }| j	                  |      s|j                  | j                  ||             9 ||d<   n| j                  ||      |d<   t        |j                               D ]!  \  }}	|dk7  s| j                  |	|      ||<   # |j                  |        |S )Nr
  r	  )r8  r,  )r  r  r7   r;   rI  appendrA  rB  )
r+   rH   r,  filtered_messagesmsgcontentscleanedckeyvals
             r-   r0  zCustomLogger._process_messages  s   
 35 	*Cc4(GGI.H(D)%'! A000; //a9/M
 ")I!%!4!4"i "5 "I !- SS)##22	2RCHS $$S))	** ! r/   )FTrD   )rd   r   )NNNNFF)NNNFF)NNF)NN)^__name__
__module____qualname__boolr.   staticmethodr   r   r   rB   rI   rP   rR   rT   rV   rX   r\   r   r^   r`   rb   re   r   r  r   r   r   intr	   rs   ru   r
   r$   rz   r   r~   r   r   r   r   r   r   r   r   r9   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r!   r   r   r   r   r   r   r   r   r  r  r  r*  r   r5  r7  rA  rI  r0  rE   r/   r-   r&   r&   D   s>
    */ $	"& 	 
  #Xc] #d3i # #J
$(26	$8 -1&*&*(,6;@E33 '(3 !	3
 C=3 #4.3 "?3 /3 j)3 T
#3 sm3 !3 &.d^3 08~3 
sD)*D0	13@ -1&*(,6;@E33 '(3 !	3
 C=3 #4.3 "?3 j)3 sm3 !3 &.d^3 08~3 
sD)*D0	13. 48,0.3  4S#X/0	
 c4i() &d^ 
(	)( *.+/## "# 4 012	#
 !# #4.# 
d#
38n
19)1D
	$
2:4.	$
 (4. 		 #	 I&		
 
"	#	  I&	
 
#":B3-QU
$'15KT
$'15KT	'	(%	)	!$	0	1
H 
H #++A"B
H 
+		
H	)	 	 		
 $	 
id"#
	  596: * 	
 "$sCx.1 $DcN3 
$sCx.	!B (, & *	
  } 
/	", * #	
 
$'47	tSy	$'47	tSy	 * $	
 
)  
	)  	
 
+T1	2
MM ($=	+	,88 8 t*	8
 T
#8 8 !8 8 
tTz	8tDD D t*	D
 D -0D 59D )D D D 
DL  t*	
 T
#  !  
tTz	  t*	
   )   
$!7,!7  	
 
0
3 
C 
C 
 04*&tn*	#*"`'"&`'	`'D 
$S F I$)$ $ 
"	$R I$)$ $ 
"	$R H	!! ! 	!
 
!F@C @D @ I!s)! ! 
d38n		!r/   r&   ):rer   typingr   r   r   r   r   r   r	   r
   pydanticr   r"  r   r  r   "litellm.types.integrations.argillar   litellm.types.llms.openair   r   "litellm.types.prompts.init_promptsr   litellm.types.utilsr   r   r   r   r   r   r   r   r   fastapir   opentelemetry.tracer   _Spanlitellm.caching.cachingr   *litellm.litellm_core_utils.litellm_loggingr   r   r8   r    litellm.types.mcpr!   r"   r#   litellm.types.routerr$   MCPDuringCallRequestObjectMCPDuringCallResponseObjectcompile	MULTILINEr>  r&   rE   r/   r-   <module>rk     s    
 	 	 	  + M : M 9
 
 
 %11W3 
 <DDN #!"!$"%  $VLL j! j!r/   