Ë
    tPêjb ã                   óŽ  — 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 d dlmZ d dlmZ d dlmZ d dlmZmZ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! d dl"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( 	 d dl)m*Z* erd dl,m-Z.  e«       Z/e	e0d<   d dl1m2Z2m3Z3 d dl4m5Z5m6Z6m7Z7m8Z8  ejr                  d«      Z:e	e0d<    e;h d£«      Z<e	e0d<   dZ=e	e0d<    e j|                  dd¬«      Z?e	e j|                  e@      e0d<   deAde@fd„ZBde@fd„ZCd eDeEef   deEdz  fd!„ZF G d"„ d#e«      ZGd$eHd%eIddfd&„ZJd eDd'eHddfd(„ZKd)„ ZLy# e+$ r dZ*Y ŒÈw xY w)*é    N)Údatetime)ÚTYPE_CHECKINGÚAnyÚClassVarÚFinalÚLiteralÚOptionalÚget_args)Úverbose_logger)Ú	DualCache)ÚCustomLogger)Ú&get_metadata_variable_name_from_kwargsÚget_or_create_metadata_bucketÚ"redact_nested_match_and_regex_keys)Ústr_to_bool)ÚDynamicGuardrailParamsÚGuardrailEventHooksÚLitellmParamsÚMode)ÚAllMessageValues)ÚGuardrailConfigModel)Ú	CallTypesÚGenericGuardrailAPIInputsÚGuardrailStatusÚGuardrailTracingDetailÚLLMResponseTypesÚ#StandardLoggingGuardrailInformation)ÚHTTPException)ÚLoggingÚdc)Ú,GUARDRAIL_SCANNED_MESSAGES_CACHE_TTL_SECONDSÚ PRE_CALL_EXECUTED_GUARDRAILS_KEY)ÚBlockedPiiEntityErrorÚGuardrailRaisedExceptionÚModifyResponseExceptionÚSensitiveDataRouteExceptioné   Ú_PRE_CALL_EXECUTED_TOKEN>   é�  é“  é¦  Ú_GUARDRAIL_BLOCK_STATUS_CODESzËThe user's latest message was flagged for {reason} by a content safety guardrail. This may be a false positive. Use your judgment: respond helpfully if the request is legitimate, or decline if it is not.ÚDEFAULT_ADVISORY_MESSAGEÚlitellm_guardrail_self_recordedF)ÚdefaultÚ_guardrail_self_recordedÚeÚreturnc                 ó°   — t        | t        «      ryt        | t        t        t        f«      ryt
        �#t        | t
        «      r| j                  t        v ryy)aÔ  
    Returns True if the exception represents an intentional guardrail block
    (this was logged previously as an API failure - guardrail_failed_to_respond).

    Guardrails signal intentional blocks by raising:
    - GuardrailRaisedException (generic guardrail API, tool permission)
    - BlockedPiiEntityError (Presidio PII detection)
    - SensitiveDataRouteException (sensitive-data reroute to on-premise model)
    - HTTPException with a block-signalling status (400, 403, 422)
    - ModifyResponseException (passthrough mode violation)

    Only the statuses guardrails use in-tree to signal a deliberate rejection
    count as an intervention: 400 (content policy), 403 (e.g. akto) and 422
    (e.g. llm_as_a_judge). Other 4xx codes are commonly propagated from an
    upstream guardrail provider response (401 bad key, 408 timeout, 429 rate
    limit, or a raw upstream status), which are technical failures, not
    blocks, so they stay guardrail_failed_to_respond.
    TF)Ú
isinstancer%   r$   r#   r&   r   Ústatus_coder,   ©r1   s    új/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/integrations/custom_guardrail.pyÚis_guardrail_interventionr8   J   sQ   € ô& �!Ô,Ô-ØÜØ	ä$Ü!Ü'ð	
ôð ÜÐ ¤Z°´=Ô%AÀaÇmÁmÔWtÑFtØØó    c                  óh   — t         j                  j                  d«      } | €yt        | «      }|€dS |S )a4  Whether guardrail-mode validation raises (default) or logs a warning.

    Set `LITELLM_STRICT_GUARDRAIL_MODES=false` to keep the pre-LIT-4226 behavior
    for guardrails whose supported_event_hooks list newly includes their
    configured mode: log the mismatch and continue instead of raising at boot.
    ÚLITELLM_STRICT_GUARDRAIL_MODEST)ÚosÚenvironÚgetr   )ÚrawÚparseds     r7   Ú_strict_guardrail_modes_enabledrA   m   s8   € ô —‘—‘Ð @ÓA€CØ
€{ØÜ Ó$€FØ�>ˆ4Ð- vÐ-r9   Úrequest_datac                 ó  — | j                  d«      }|rt        |«      S | j                  d«      xs i }|j                  d«      }|rt        |«      S | j                  d«      xs i }|j                  d«      }|rt        |«      S y)zFExtract session_id from request data (litellm_session_id or metadata).Úlitellm_session_idÚmetadataÚ
session_idÚlitellm_metadataN)r>   Ústr)rB   rF   rE   rG   s       r7   Ú get_session_id_from_request_datarI   {   s‡   € à×!Ñ!Ð"6Ó7€JÙÜ�:‹Ðà"×&Ñ& zÓ2Ò8°b€HØ—‘˜lÓ+€JÙÜ�:‹Ðà*×.Ñ.Ð/AÓBÒHÀbÐØ!×%Ñ% lÓ3€JÙÜ�:‹Ðàr9   c            !       óª  ‡ — e Zd ZU dZee   ed<   dZee   ed<   dZee   ed<   	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 djde	dz  de
e   dz  dee
e   z  ez  dz  d	ed
edede	dz  dedz  de	dz  de	dz  de	dz  de	dz  dedededef ˆ fd„Zdkde	dee	ef   dz  de	fd„Z	 	 dlde	dee	ef   dee	ef   dz  deddf
d„Zd ee	ef   d!e	defd"„Z	 dkd#e	dee	ef   dee	ef   dz  ddfd$„Zdee	ef   de	dz  fd%„Zed&e	de	fd'„«       Zd(e	de	fd)„Zd*e
e	   dz  dee	ef   d+ede
e	   dz  fd,„Zd*e
e	   dz  dee	ef   d+eddfd-„Zdefd.„Z	 dkdee	ef   dee	ef   dz  ddfd/„Zeded0   dz  fd1„«       Z e!de
e   dz  fd2„«       Z"dee
e   z  ez  dz  de
e   ddfd3„Z#ed edefd4„«       Z$d ededz  fd5„Z%d ede
e	   fd6„Z&d7edefd8„Z'd ede
e	   e
ee	e(f      z  fd9„Z)d:e
e	   e
ee	e(f      z  defd;„Z*de	dz  fd<„Z+d ee	ef   ddfd=„Z,d ee	ef   defd>„Z-defd?„Z.dmd@„Z/dAee	ef   dBe0dz  dedz  fdC„Z1dedDe2dBe0dz  de2dz  fdE„Z3defdF„Z4defdG„Z5dHedefdI„Z6dHedefdJ„Z7dedefdK„Z8defdL„Z9	 	 	 	 	 	 	 dndMe:e	z  ez  e
e   z  dedNe;dOe<dz  dPe<dz  dQe<dz  dRee	ef   dz  dSe	dz  dHedz  dTe=dz  ddfdU„Z>	 dkdVe?dedWe@dX   dYeAdZ   de?f
d[„ZB	 	 	 	 	 dodDedz  dedOe<dz  dPe<dz  dQe<dz  dHedz  d\edz  fd]„ZCed^e:defd_„«       ZD	 	 	 	 dpd^e:dedOe<dz  dPe<dz  dQe<dz  dHedz  fd`„ZEd\edDedefda„ZFdbe	dce	ddedeede	f
df„ZGdgeHddfdh„ZI	 dkdBe0d edz  de
eJ   dz  fdi„ZKˆ xZLS )qÚCustomGuardrailFÚuse_native_during_call_hookÚuse_native_lifecycle_hooksÚ!records_own_guardrail_informationNÚguardrail_nameÚsupported_event_hooksÚ
event_hookÚ
default_onÚmask_request_contentÚmask_response_contentÚviolation_message_templateÚend_session_after_n_failsÚon_violationÚrealtime_violation_messageÚon_sensitive_dataÚsensitive_data_route_to_modelÚsticky_session_routingÚrun_in_parallelÚscan_raw_requestÚonly_scan_new_messagesc                 óœ  •— || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        || _
        || _        || _        || _        || _        || _        |r	 | j!                  ||«       t+        ‰| �X  di |¤Ž y# t"        $ r+}t%        «       r‚ t'        j(                  d|«       Y d}~Œ?d}~ww xY w)a!  
        Initialize the CustomGuardrail class

        Args:
            guardrail_name: The name of the guardrail. This is the name used in your requests.
            supported_event_hooks: The event hooks that the guardrail supports
            event_hook: The event hook to run the guardrail on
            default_on: If True, the guardrail will be run by default on all requests
            mask_request_content: If True, the guardrail will mask the request content
            mask_response_content: If True, the guardrail will mask the response content
            end_session_after_n_fails: For /v1/realtime sessions, end the session after this many violations
            on_violation: For /v1/realtime sessions, 'warn' or 'end_session'
            realtime_violation_message: Message the bot speaks aloud when a /v1/realtime guardrail fires
            on_sensitive_data: Action when sensitive data is detected. 'block' (default) or 'route'
            sensitive_data_route_to_model: Model to route to when on_sensitive_data='route'
            sticky_session_routing: When True, all subsequent requests in the session use the same model
            run_in_parallel: When True, this pre_call or post_call guardrail runs concurrently with
                other opted-in guardrails of the same hook. Only safe for block-only guardrails that
                do not mutate the request or response.
            scan_raw_request: When True, this pre_call guardrail always evaluates the request as it
                was before any guardrail in this hook ran, regardless of where it's declared in the
                guardrails list -- so an earlier guardrail that masks/rewrites content (e.g. PII
                redaction) can never hide a violation from this one. Only safe for block-only
                guardrails: any data this guardrail returns is discarded, matching run_in_parallel's
                contract, since applying its mutations on top of a stale snapshot would silently
                undo whatever later guardrails already did to the live request.
        zž%s. LITELLM_STRICT_GUARDRAIL_MODES=false; continuing with unsupported event_hook. Set the env var to true (default) to enforce validation and fail at startup.N© )rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   Ú_validate_event_hookÚ
ValueErrorrA   r   ÚwarningÚsuperÚ__init__)ÚselfrO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   ÚkwargsÚvalidation_errorÚ	__class__s                      €r7   re   zCustomGuardrail.__init__—   sè   ø€ ð^ -ˆÔØ%:ˆÔ"ØYcˆŒØ *ˆŒØ*>ˆÔ!Ø+@ˆÔ"Ø6PˆÔ'Ø5NˆÔ&Ø(4ˆÔØ6PˆÔ'Ø->ˆÔØ9VˆÔ*Ø,BˆÔ#Ø%4ˆÔØ&6ˆÔØ,BˆÔ#á ð
Ø×)Ñ)¨*Ð6KÔLô 	‰ÑÑ"˜6Ó"øô ò Ü2Ô4ØÜ×&Ñ&ðKð %÷	ñ ûðús   Á5B Â	CÂ !CÃCr/   Úcontextr2   c                 óø   — | j                   s|S d|i}|r|j                  |«       	  | j                   j                  di |¤ŽS # t        $ r-}t	        j
                  d| j                  |«       |cY d}~S d}~ww xY w)z<Return a custom violation message if template is configured.Údefault_messagez@Failed to format violation message template for guardrail %s: %sNr`   )rU   ÚupdateÚformatÚ	Exceptionr   rc   rO   )rf   r/   rj   Úformat_contextr1   s        r7   Úrender_violation_messagez(CustomGuardrail.render_violation_messageæ   s‚   € ð ×.Ò.ØˆNà1BÀGÐ0LˆÙØ×!Ñ! 'Ô*ð	Ø9�4×2Ñ2×9Ñ9ÑK¸NÑKÐKøÜò 	Ü×"Ñ"ØRØ×#Ñ#Øôð
 �Nûð	ús   §A Á	A9Á"A4Á.A9Á4A9Úviolation_messagerB   Údetection_infoÚoriginal_responsec                 ó\   — |j                  dd«      }t        |||| j                  ||¬«      ‚)a*  
        Raise a passthrough exception for guardrail violations.

        This helper method should be used by guardrails when they detect a violation
        in passthrough mode.

        The exception will be caught by the proxy endpoints and converted to a 200 response
        with the violation message, preventing the LLM call from being made (pre_call/during_call)
        or replacing the LLM response (post_call).

        Args:
            violation_message: The formatted violation message to return to the user
            request_data: The original request data dictionary
            detection_info: Optional dictionary with detection metadata (scores, rules, etc.)
            original_response: The blocked LLM response when raising from a post-call
                hook. It carries the real token usage the upstream call consumed, so
                the synthetic block response reports it instead of zeros. Leave None
                for pre-call/during-call blocks (the LLM was never invoked).

        Raises:
            ModifyResponseException: Always raises this exception to short-circuit
                                     the LLM call and return the violation message

        Example:
            if violation_detected and self.on_flagged_action == "passthrough":
                message = self._format_violation_message(detection_info)
                self.raise_passthrough_exception(
                    violation_message=message,
                    request_data=data,
                    detection_info=detection_info
                )
        ÚmodelÚunknown)Úmessagerv   rB   rO   rs   rt   )r>   r%   rO   )rf   rr   rB   rs   rt   rv   s         r7   Úraise_passthrough_exceptionz+CustomGuardrail.raise_passthrough_exceptionù   s<   € ðN $×'Ñ'¨°Ó;ˆä%Ø%ØØ%Ø×.Ñ.Ø)Ø/ô
ð 	
r9   Údatarx   c                 óš  — d|dœ}|j                  d«      }|j                  d«      }|j                  d«      }t        |t        «      r&t        |t        «      rg |¢|‘}||d<   |› d|› �|d<   yt        |t        «      r&t        |t        «      rg |¢|‘}||d<   |› d|› �|d<   y|�yt        |t        «      rg |¢|‘}	|	|d<   y|g}
|
|d<   y)	aÔ  
        Append an advisory system message to the request in place, so the LLM
        itself can weigh a possible false-positive guardrail flag rather than
        the request being hard-blocked or silently allowed.

        Unlike raise_passthrough_exception, this does NOT short-circuit the LLM
        call; the request proceeds normally with the extra message appended.
        Guardrails should call this from on_flagged handling analogous to how
        passthrough-supporting guardrails call raise_passthrough_exception.

        Args:
            data: The request data dictionary, mutated in place to append the
                advisory message to its "messages" list and/or "input"/
                "instructions" text.
            message: The formatted advisory message to append as a system message.

        Returns:
            True if the advisory was actually written somewhere the model will
            see it. False if ``data["input"]`` is a structured Responses-API
            list (not a plain string) -- the Responses API reads only
            ``input``, so appending to ``messages`` would be inert regardless
            of whether a ``messages`` list also happens to be present, and
            there is no field this helper can safely append into. The caller
            must treat this like any other case where the mitigation can't
            land and degrade to blocking instead of silently letting the
            flagged request through unmodified.
        Úsystem)ÚroleÚcontentÚmessagesÚinputÚinstructionsz

TF)r>   r4   rH   Úlist)rf   rz   rx   Úadvisory_messageÚexisting_messagesÚexisting_inputÚexisting_instructionsÚmessages_with_instructions_noteÚmessages_with_input_noteÚmessages_without_input_noteÚsole_messages              r7   Úinject_advisory_messagez'CustomGuardrail.inject_advisory_message+  s)  € ð@ ,4ÀÑ"HÐØ#'§8¡8¨JÓ#7ÐØ $§¡¨Ó 1ˆØ'+§x¡x°Ó'?ÐÜÐ+¬SÔ1ô Ð+¬TÔ2ð:Ø&ð:à$ð:Ð/ð $C��ZÑ Ø&;Ð%<¸DÀÀ	Ð#JˆD�Ñ ØÜ�n¤cÔ*ô Ð+¬TÔ2Ø2XÐ4EÐ2XÐGWÐ2XÐ(Ø#;��ZÑ ð  .Ð.¨d°7°)Ð<ˆD�‰MØØÐ%ð ÜÐ'¬Ô.Ø1WÐ3DÐ1WÐFVÐ1WÐ'Ø:ˆD�ÑØØ/Ð0ˆØ'ˆˆZÑØr9   Úroute_to_modelc                 ó†   — | j                  |«      }|st        d«      ‚t        ||| j                  || j                  ¬«      ‚)aÁ  
        Raise an exception to reroute the request to a different model.

        Use this when sensitive data is detected and the guardrail is configured
        to route to an on-premise model instead of blocking.

        The exception will reroute this request to the specified model. When
        sticky_session_routing is enabled (the default), it also stores the
        routing decision so subsequent requests in this session reuse the model.

        Args:
            route_to_model: The model to route this request (and session) to
            request_data: The original request data dictionary
            detection_info: Optional non-sensitive detection metadata (e.g. matched
                entity types, rule ids, scores). This is surfaced in request metadata
                and logs, so it must not contain the raw detected sensitive values.

        Raises:
            SensitiveDataRouteException: Always raises to trigger rerouting
        zrCannot route sensitive data without a session_id. Ensure the request includes a session_id in metadata or headers.)rŒ   rF   rO   rs   r[   )Ú!_get_session_id_from_request_datarb   r&   rO   r[   )rf   rŒ   rB   rs   rF   s        r7   Ú$raise_sensitive_data_route_exceptionz4CustomGuardrail.raise_sensitive_data_route_exceptionw  sT   € ð4 !×BÑBÀ<ÓPˆ
ÙÜðSóð ô
 *Ø)Ø!Ø×.Ñ.Ø)Ø#'×#>Ñ#>ô
ð 	
r9   c                 ó   — t        |«      S )z%Extract session_id from request data.)rI   )rf   rB   s     r7   rŽ   z1CustomGuardrail._get_session_id_from_request_data   s   € ä/°Ó=Ð=r9   Útextc                 óf   — t        j                  | j                  d«      «      j                  «       S )a  Stable content hash for a single scannable text segment.

        Hashing the exact text the provider would receive means an edited earlier
        segment produces a different hash and gets re-scanned, while an unchanged
        segment repeated on a later turn is skipped.
        zutf-8)ÚhashlibÚsha256ÚencodeÚ	hexdigest)r‘   s    r7   Ú_scanned_text_hashz"CustomGuardrail._scanned_text_hash¤  s%   € ô �~‰~˜dŸk™k¨'Ó2Ó3×=Ñ=Ó?Ð?r9   rF   c                 ó&   — d| j                   › d|› �S )Nzguardrail_scanned_texts:ú:)rO   )rf   rF   s     r7   Ú_scanned_texts_cache_keyz(CustomGuardrail._scanned_texts_cache_key®  s   € Ø)¨$×*=Ñ*=Ð)>¸aÀ
¸|ÐLÐLr9   ÚtextsÚcachec              ƒ   ó~  K  — | j                   r|sy| j                  s| j                  r!t        j                  d| j
                  «       yt        |«      }|s!t        j                  d| j
                  «       y	 |j                  | j                  |«      ¬«      ƒ d{  –—† }t        |t        «      r|D �ch c]  }t        |«      ’Œ c}n	t        «       }|D �	cg c]  }	| j                  |	«      |vsŒ|	‘Œ c}	S 7 Œ[# t        $ r+}t        j                  d| j
                  |«       Y d}~yd}~ww xY wc c}w c c}	w ­w)a—  Return only the text segments not already scanned earlier in this session.

        Returns ``None`` when incremental scanning is inactive (feature off, no
        session id, masking enabled, or the cache read failed). ``None`` signals
        the caller to fall back to a full scan; a returned list (possibly empty)
        signals the caller to scan only that subset and skip masking write-back.
        NzZGuardrail %s: only_scan_new_messages is not supported with masking; scanning full context.zbGuardrail %s: only_scan_new_messages enabled but request has no session id; scanning full context.©ÚkeyzOGuardrail %s: failed to read scanned-message cache (%s); scanning full context.)r^   rS   rT   r   rc   rO   rI   ÚdebugÚasync_get_cacherš   ro   r4   r‚   rH   Úsetr—   )
rf   r›   rB   rœ   rF   Úcachedr1   ÚhÚseenr‘   s
             r7   Úfilter_new_texts_for_sessionz,CustomGuardrail.filter_new_texts_for_session±  s!  è ø€ ð ×*Ò*±%Øà×$Ò$¨×(BÒ(BÜ×"Ñ"ØlØ×#Ñ#ôð ä<¸\ÓJˆ
ÙÜ× Ñ ØtØ×#Ñ#ôð ð	Ø*/×*?Ñ*?ÀD×DaÑDaÐblÓDmÐ*?Ó*n×$nˆFô =GÀvÌtÔ<T°Ö 8¨A¤ Q¥Ó 8ÔZ]ÓZ_ˆØ!&ÖT˜¨$×*AÑ*AÀ$Ó*GÈtÒ*S’ÒTÐTð %oùÜò 	Ü×"Ñ"ØaØ×#Ñ#Øôô
 ûð	üò !9ùÚTùs`   ‚A7D=Á:$C< ÂC:ÂC< Â#D=Â7D3Ã	D=ÃD8Ã3D8Ã7D=Ã:C< Ã<	D0Ä!D+Ä&D=Ä+D0Ä0D=c              ƒ   ón  K  — | j                   r|sy| j                  s| j                  ryt        |«      }|sy| j	                  |«      }|D �cg c]  }| j                  |«      ‘Œ }}	 |j                  |¬«      ƒ d{  –—† }t        |t        «      r|D �	cg c]  }	t        |	«      ‘Œ c}	ng }
t        t        j                  |
|z   «      «      }|j                  ||t        ¬«      ƒ d{  –—†  yc c}w 7 Œvc c}	w 7 Œ# t        $ r+}t        j                   d| j"                  |«       Y d}~yd}~ww xY w­w)zûRecord the hashes of all text segments present on a successful (non-blocked) scan.

        Called only after the guardrail allows the request, so a blocked segment is
        never marked scanned and will be re-checked if the client retries.
        Nrž   )rŸ   ÚvalueÚttlzSGuardrail %s: failed to persist scanned-message cache (%s); next call will re-scan.)r^   rS   rT   rI   rš   r—   r¡   r4   r‚   rH   ÚdictÚfromkeysÚasync_set_cacher!   ro   r   rc   rO   )rf   r›   rB   rœ   rF   Ú	cache_keyr‘   Úcurrent_hashesÚexistingr¤   Úexisting_hashesÚmergedr1   s                r7   Úmark_texts_scannedz"CustomGuardrail.mark_texts_scannedÝ  s'  è ø€ ð ×*Ò*±%ØØ×$Ò$¨×(BÒ(BØÜ<¸\ÓJˆ
ÙØà×8Ñ8¸ÓDˆ	ØKPÖ QÀ4 ×!8Ñ!8¸Õ!>Ð QˆÐ Qð	Ø,1×,AÑ,AÀiÐ,AÓ,P×&PˆHÜNXÐYaÔcgÔNhÀÖ0J¸A´°QµÓ0JÐnpˆOÜ'+¬D¯M©M¸/ÈNÑ:ZÓ,[Ó'\ˆFØ×'Ñ'ØØÜ@ð (ó ÷ ñ ùò !Rà&PúÚ0Jðùô
 ò 	Ü×"Ñ"ØeØ×#Ñ#Ø÷ñ ûð	üsm   ‚AD5ÁC0Á&D5Á)C> Á>C5Á?C> ÂC7Â)AC> Ã*C<Ã+C> Ã/D5Ã5C> Ã7C> Ã>	D2Ä!D-Ä(D5Ä-D2Ä2D5c                 ó@   — | j                   dk(  xr | j                  duS )zŽ
        Returns True if this guardrail is configured to route requests
        to a different model when sensitive data is detected.
        ÚrouteN)rY   rZ   ©rf   s    r7   Úshould_route_on_sensitive_dataz.CustomGuardrail.should_route_on_sensitive_data  s&   € ð
 ×%Ñ%¨Ñ0Òc°T×5WÑ5WÐ_cÐ5cÐcr9   c                 ó  — | j                  «       r 	 | j                  | j                  ||¬«       yt	        d| j
                  › �| j
                  d¬«      ‚# t        $ r' t	        d| j
                  › d�| j
                  d¬«      ‚w xY w)až  
        Handle sensitive data detection based on guardrail configuration.

        If on_sensitive_data='route', raises SensitiveDataRouteException to reroute.
        Otherwise, raises GuardrailRaisedException to block. When routing is
        configured but the request carries no session_id, routing is not possible
        so the request falls back to a graceful block.

        Args:
            request_data: The request data dictionary
            detection_info: Optional non-sensitive detection metadata. When routing,
                this is surfaced in request metadata and logs, so it must not contain
                the raw detected sensitive values.

        Raises:
            SensitiveDataRouteException: When configured to route and a session_id is present
            GuardrailRaisedException: When configured to block, or when routing is
                configured but no session_id is available
        )rŒ   rB   rs   zSensitive data detected by z- (routing skipped: request has no session_id)T)rx   rO   Úblocked_contentN)r¶   r�   rZ   rb   r$   rO   )rf   rB   rs   s      r7   Úhandle_sensitive_data_detectionz/CustomGuardrail.handle_sensitive_data_detection	  s¡   € ð0 ×.Ñ.Ô0ðØ×9Ñ9Ø#'×#EÑ#EØ!-Ø#1ð :õ ô +Ø5°d×6IÑ6IÐ5JÐKØ#×2Ñ2Ø $ôð øô ò Ü.à5°d×6IÑ6IÐ5JÐJwÐxà#'×#6Ñ#6Ø$(ôð ðús   ’A Á0Br   c                   ó   — y)zx
        Returns the config model for the guardrail

        This is used to render the config model in the UI.
        Nr`   r`   r9   r7   Úget_config_modelz CustomGuardrail.get_config_model7  s   € ð r9   c                  ó   — y)a^  
        Returns the event hooks this guardrail supports, for the UI to render.

        Subclasses should override to return their supported hooks list. When a
        subclass returns None, the endpoint omits it from the per-provider map
        and the UI is expected to fall back to the global `supported_modes`
        list client-side.
        Nr`   )Úclss    r7   Úget_supported_event_hooksz)CustomGuardrail.get_supported_event_hooks@  s   € ð r9   c                 óŠ  — dt         t           t         t           z  dt         t           dd fd„}|€y t        |t        «      rt        |«      }t        |t         «      r
 |||«       y t        |t        «      r§g }|j
                  j                  «       D ]5  }t        |t         «      r|j                  |«       Œ%|j                  |«       Œ7  |||«       |j                  r=t        |j                  t         «      r|j                  n|j                  g} |||«       y y t        |t        «      r||vrt        d|› d|› �«      ‚y y )NrQ   rP   r2   c                 ór   — | D ]2  }t        |t        «      rt        |«      }||vsŒ#t        d|› d|› �«      ‚ y )NúEvent hook ú% is not in the supported event hooks )r4   rH   r   rb   )rQ   rP   Úhooks      r7   Ú5_validate_event_hook_list_is_in_supported_event_hookszcCustomGuardrail._validate_event_hook.<locals>._validate_event_hook_list_is_in_supported_event_hooksQ  sM   € ð #ò w�Ü˜d¤CÔ(Ü.¨tÓ4�DØÐ4Ò4Ü$ {°4°&Ð8]Ð^sÐ]tÐ%uÓvÐvñ	wr9   rÁ   rÂ   )r‚   r   rH   r4   r   ÚtagsÚvaluesÚextendÚappendr/   rb   )rf   rQ   rP   rÄ   Útag_values_flatÚvÚdefault_lists          r7   ra   z$CustomGuardrail._validate_event_hookL  sH  € ð
	wÜÔ0Ñ1´D¼±IÑ=ð	wä#'Ô(;Ñ#<ð	wð ó	wð ÐØÜ�j¤#Ô&Ü,¨ZÓ8ˆJÜ�j¤$Ô'ÙAÀ*ÐNcÕdÜ˜
¤DÔ)Ø+-ˆOØ—_‘_×+Ñ+Ó-ò .�Ü˜a¤Ô&Ø#×*Ñ*¨1Õ-à#×*Ñ*¨1Õ-ð	.ñ
 BÀ/ÐShÔiØ×!Ò!Ü5?À
×@RÑ@RÔTXÔ5Y˜z×1Ò1Ð`j×`rÑ`rÐ_s�ÙEÀlÐTiÕjð "ô ˜
Ô$7Ô8ØÐ!6Ñ6Ü  ;¨z¨lÐ:_Ð`uÐ_vÐ!wÓxÐxð 7ð 9r9   c                 ó¼   — i }i }dD ]N  }| j                  |«      }t        |t        «      sŒ%|j                  d«      xs |}|j                  d«      xs |}ŒP i |¥|¥S )a˜  Return merged admin-configured key and team metadata from the request data.

        The proxy may inject admin metadata (user_api_key_metadata,
        user_api_key_team_metadata) into either ``metadata`` or
        ``litellm_metadata`` depending on endpoint. Check both so a caller
        cannot shadow admin config by pre-populating the other key.
        Key-level settings override team-level.
        ©rE   rG   Úuser_api_key_team_metadataÚuser_api_key_metadata©r>   r4   rª   )rz   Ú	team_metaÚkey_metarŸ   Úmetas        r7   Ú_get_admin_metadataz#CustomGuardrail._get_admin_metadatap  su   € ð ˆ	ØˆØ3ò 	EˆCð —8‘8˜C“=ˆDÜ˜d¤DÔ)ØØŸ™Ð!=Ó>ÒKÀ)ˆIØ—x‘xÐ 7Ó8ÒD¸H‰Hð	Eð )�)Ð(˜xÐ(Ð(r9   c                 óD   — | j                  |«      j                  dd«      S )zØ
        Returns True if the global guardrail should be disabled.

        Reads from admin-configured key/team metadata only, not from
        the request body, to prevent callers from disabling guardrails.
        Údisable_global_guardrailsF)rÔ   r>   )rf   rz   s     r7   Úget_disable_global_guardrailz,CustomGuardrail.get_disable_global_guardrail†  s#   € ð ×'Ñ'¨Ó-×1Ñ1Ð2MÈuÓUÐUr9   c                 ój   — | j                  |«      j                  d«      }t        |t        «      r|S g S )z˜
        Returns the list of global guardrail names the team/key has opted out of.

        Reads from admin-configured key/team metadata only.
        Úopted_out_global_guardrails)rÔ   r>   r4   r‚   )rf   rz   r¨   s      r7   Ú-get_opted_out_global_guardrails_from_metadataz=CustomGuardrail.get_opted_out_global_guardrails_from_metadata�  s4   € ð ×/Ñ/°Ó5×9Ñ9Ð:WÓXˆÜ" 5¬$Ô/ˆuÐ7°RÐ7r9   Úresultc                 óˆ   — |€y	 t        t        «      }t        ||«      S # t        $ r}dt	        |«      v rY d}~y‚ d}~ww xY w)a  
        Check if result is a valid LLMResponseTypes instance.

        Safely handles TypedDict types which don't support isinstance checks.
        For non-LiteLLM responses (like passthrough httpx.Response), returns True
        to allow them through.
        NFÚ	TypedDictT)r
   r   r4   Ú	TypeErrorrH   )rf   rÛ   Úresponse_typesr1   s       r7   Ú_is_valid_response_typez'CustomGuardrail._is_valid_response_type˜  sM   € ð ˆ>Øð		ä$,Ô-=Ó$>ˆNÜ˜f nÓ5Ð5øÜò 	ð œc !›fÑ$ÜØûð	ús   …   	A©<»<¼Ac                 ó¨   — d|v r|d   S dD ]C  }|j                  |«      xs i }t        |t        «      sŒ)d|v sŒ.|j                  d«      xs g c S  g S )zN
        Returns the guardrail(s) to be run from the metadata or root
        Ú
guardrailsrÍ   rÐ   )rf   rz   Úmeta_keyrÓ   s       r7   Úget_guardrail_from_metadataz+CustomGuardrail.get_guardrail_from_metadata®  sg   € ð
 ˜4ÑØ˜Ñ%Ð%ð 9ò 	4ˆHØ—8‘8˜HÓ%Ò+¨ˆDÜ˜$¤Õ%¨,¸$Ò*>Ø—x‘x Ó-Ò3°Ò3ð	4ð ˆ	r9   Úrequested_guardrailsc                 ó˜   — |D ]E  }t        |t        «      r| j                  |v sŒ" yt        |t        «      sŒ5| j                  |k(  sŒE y y)NTF)r4   rª   rO   rH   )rf   rå   Ú
_guardrails      r7   Ú%_guardrail_is_in_requested_guardrailsz5CustomGuardrail._guardrail_is_in_requested_guardrailsÁ  sN   € ð /ò 	 ˆJÜ˜*¤dÔ+Ø×&Ñ&¨*Ò4ÙÜ˜J¬Õ,Ø×&Ñ&¨*Ó4Ùð	 ð r9   c                 ó6   — | j                   }|sy t        › d|› �S )Nr™   )rO   r(   )rf   Únames     r7   Ú_pre_call_markerz CustomGuardrail._pre_call_markerÏ  s%   € Ø×)Ñ)ˆÙØÜ*Ð+¨1¨T¨FÐ3Ð3r9   c                 ó"  — | j                  «       }|€ydD ]k  }|j                  |«      }t        |t        «      sŒ%|j                  t        «      }t        |t
        «      r||vr|j                  |«        y|g|t        <    y t        |gi|d<   y)aÍ  
        Record that this guardrail's ``async_pre_call_hook`` already ran for this
        request, so the deployment-level hook does not run it a second time.

        The proxy runs pre-call guardrails in ``ProxyLogging.pre_call_hook``. The
        router later spreads a deployment's model-level ``guardrails`` into the
        top-level request kwargs, which would otherwise re-trigger the same hook
        from ``async_pre_call_deployment_hook``.
        NrÍ   rE   )rë   r>   r4   rª   r"   r‚   rÈ   ©rf   rz   Úmarkerrã   rÓ   Úexecuteds         r7   Úmark_pre_call_hook_ranz&CustomGuardrail.mark_pre_call_hook_ranÕ  s™   € ð ×-Ñ-Ó/ˆØˆ>ØØ8ò 		ˆHØ—8‘8˜HÓ%ˆDÜ˜$¤Õ%ØŸ8™8Ô$DÓE�Ü˜h¬Ô-Ø XÑ-Ø Ÿ™¨Ô/ñ ð ?E¸X�DÔ9Ñ:Ùð		ô =¸v¸hÐGˆˆZÒr9   c                 óÔ   — | j                  «       }|€ydD ]P  }|j                  |«      }t        |t        «      sŒ%|j                  t        «      }t        |t
        «      sŒK||v sŒP y y)NFrÍ   T)rë   r>   r4   rª   r"   r‚   rí   s         r7   Ú_pre_call_hook_already_ranz*CustomGuardrail._pre_call_hook_already_ranî  sg   € Ø×-Ñ-Ó/ˆØˆ>ØØ8ò 	 ˆHØ—8‘8˜HÓ%ˆDÜ˜$¤Õ%ØŸ8™8Ô$DÓE�Ü˜h¬Õ-°&¸HÒ2DÙð	 ð r9   c                 óL   — t        | «      j                  t        j                  uS ©N)ÚtypeÚapply_guardrailrK   rµ   s    r7   Úuses_apply_guardrail_interfacez.CustomGuardrail.uses_apply_guardrail_interfaceú  s   € Ü�D‹z×)Ñ)´×1PÑ1PÐPÐPr9   c                 óÔ   — | j                  «       r| j                  r| S 	 ddlm} |S # t        $ r6}t	        d| j
                  xs t        | «      j                  › d�«      |‚d }~ww xY w)Nr   )Úunified_guardrailz
Guardrail z— implements apply_guardrail, which needs the litellm proxy dependencies to run at the deployment level. Install them with: pip install 'litellm[proxy]')r÷   rM   Úlitellm.proxy.utilsrù   ÚImportErrorrO   rõ   Ú__name__)rf   rù   r1   s      r7   Ú_deployment_pre_call_targetz+CustomGuardrail._deployment_pre_call_targetý  sy   € Ø×2Ñ2Ô4¸×8WÒ8WØˆKð	Ý=ð !Ð øô ò 	ÜØ˜T×0Ñ0ÒG´D¸³J×4GÑ4GÐHð IBð Bóð ð	ûð	ús    ( ¨	A'±1A"Á"A'rg   Ú	call_typec              ƒ   óÂ  K  — ddl m} |j                  d«      }|�t        |t        «      s|S | j                  |«      r|S | j                  |t        j                  ¬«      dur|S |t        j                  k(  s|t        j                  k(  rÏ| j                  «       }|| ur| |d<   |j                   ||j                  d«      |j                  d«      |j                  d	«      |j                  d
«      |j                  d«      ¬«      t        ||t        j                  k(  rdnd¬«      ƒ d {  –—† }|�(t        |t        «      r|j                  d«      }|�||d<   |S 7 Œ0­w)Nr   ©ÚUserAPIKeyAuthrâ   ©rz   Ú
event_typeTÚguardrail_to_applyÚuser_api_key_user_idÚuser_api_key_team_idÚuser_api_key_end_user_idÚuser_api_key_hashÚuser_api_key_request_route©Úuser_idÚteam_idÚend_user_idÚapi_keyÚrequest_routeÚ
completionÚacompletion)Úuser_api_key_dictrœ   rz   rþ   r   )Úlitellm.proxy._typesr  r>   r4   r‚   rò   Úshould_run_guardrailr   Úpre_callr   r  r  rý   Úasync_pre_call_hookr    rª   )rf   rg   rþ   r  Úlitellm_guardrailsÚtargetrÛ   Úresult_messagess           r7   Úasync_pre_call_deployment_hookz.CustomGuardrail.async_pre_call_deployment_hook
  s\  è ø€ Ý7ð %+§J¡J¨|Ó$<ÐØÐ%¬ZÐ8JÌDÔ-QØˆMà×*Ñ*¨6Ô2ØˆMà×$Ñ$¨&Ô=P×=YÑ=YÐ$ÓZÐbfÑfØˆMð œ	×,Ñ,Ò,°	¼Y×=RÑ=RÒ0RØ ×<Ñ<Ó>ˆFØ˜TÑ!Ø/3�Ð+Ñ,Ø"(×"<Ñ"<Ù"0Ø"ŸJ™JÐ'=Ó>Ø"ŸJ™JÐ'=Ó>Ø &§
¡
Ð+EÓ FØ"ŸJ™JÐ':Ó;Ø"(§*¡*Ð-IÓ"Jô#ô ØØ*3´y×7KÑ7KÒ*K™,ÐQ^ð #=ó #÷ ˆFð Ð!¤j°¼Ô&>Ø)/¯©°JÓ)?�Ø"Ð.Ø)8�F˜:Ñ&àˆð%ús   ‚D*EÄ,EÄ-1EÚresponsec              ƒ   ó¼  K  — ddl m} |j                  d«      }|�t        |t        «      s|S | j                  |t        j                  ¬«      dur|S | j                   ||j                  d«      |j                  d«      |j                  d	«      |j                  d
«      |j                  d«      ¬«      ||¬«      ƒ d{  –—† }| j                  |«      s|S |S 7 Œ­w)zh
        Allow modifying / reviewing the response just after it's received from the deployment.
        r   r   râ   Nr  Tr  r  r  r  r	  r
  )r  rz   r  )
r  r  r>   r4   r‚   r  r   Ú	post_callÚasync_post_call_success_hookrà   )rf   rB   r  rþ   r  r  rÛ   s          r7   Ú'async_post_call_success_deployment_hookz7CustomGuardrail.async_post_call_success_deployment_hook1  sï   è ø€ õ 	8ð %1×$4Ñ$4°\Ó$BÐØÐ%¬ZÐ8JÌDÔ-QØˆOà×$Ñ$¨,ÔCV×C`ÑC`Ð$ÓaÐimÑmØˆOð #×?Ñ?Ù,Ø$×(Ñ(Ð)?Ó@Ø$×(Ñ(Ð)?Ó@Ø(×,Ñ,Ð-GÓHØ$×(Ñ(Ð)<Ó=Ø*×.Ñ.Ð/KÓLôð Øð @ó 

÷ 

ˆð ×+Ñ+¨FÔ3ØˆOàˆð

ús   ‚B>CÃ CÃCc                  ó   — y)aR  Whether this guardrail can scan tool-result content.

        Guardrails whose own role filtering only ever scans human-authored
        messages override this to return False, so configuring them with
        ``scan_only_tool_results`` is rejected at initialization instead of
        silently scanning nothing on every request.
        Tr`   rµ   s    r7   Úsupports_scan_only_tool_resultsz/CustomGuardrail.supports_scan_only_tool_resultsV  s   € ð r9   c                  ó   — y)a>  Whether returned ``structured_messages`` span the whole request.

        Translation handlers hand guardrails only the in-scope subset of the
        conversation and merge a returned ``structured_messages`` list back
        into the full request. A guardrail that already rebuilds the complete
        conversation itself (like CrowdStrike AIDR with its skip filters
        active) overrides this to return True so the handler installs the
        returned list as-is instead of merging it a second time, which would
        duplicate the out-of-scope messages.
        Fr`   rµ   s    r7   Ú&structured_messages_cover_full_requestz6CustomGuardrail.structured_messages_cover_full_request`  s   € ð r9   r  c                 ój  — | j                  |«      }| j                  |«      }| j                  |«      }t        j                  d| j
                  || j                  || j                  «       | j                  du r| j
                  |v ry| j                  du r|du ry| j                  du rY|durU| j                  |«      rCt        | j                  t        «      r(	 ddlm} |j                  || j                  |«      }|�|S yy| j                  r!| j                  |«      s|j                   dk7  ry| j                  |«      syt        | j                  t        «      r(	 ddlm} |j                  || j                  |«      }|�|S y# t        $ r t        d«      ‚w xY w# t        $ r t        d«      ‚w xY w)zO
        Returns True if the guardrail should be run on the event_type
        zŒinside should_run_guardrail for guardrail=%s event_type= %s guardrail_supported_event_hooks= %s requested_guardrails= %s self.default_on= %sTFr   )ÚEnterpriseCustomGuardrailHelperzuSetting tag-based guardrails is only available in litellm-enterprise. You must be a premium user to use this feature.Úlogging_only)rä   r×   rÚ   r   r    rO   rQ   rR   Ú_event_hook_is_event_typer4   r   Ú0litellm_enterprise.integrations.custom_guardrailr%  rû   Ú_should_run_if_mode_by_tagrè   r¨   )rf   rz   r  rå   Údisable_global_guardrailrÙ   r%  rÛ   s           r7   r  z$CustomGuardrail.should_run_guardrailm  sÐ  € ð '+×&FÑ&FÀtÓ&LÐØ*.×*KÑ*KÈDÓ*QÐ Ø-1×-_Ñ-_Ð`dÓ-eÐ#Ü×Ñð [Ø×ÑØØ�O‰OØ Ø�O‰Oô	
ð �?‰?˜dÑ" t×':Ñ':Ð>YÑ'YØà�?‰?˜dÑ"Ð'?À4Ñ'GØà�?‰?˜dÑ"Ð'?ÀtÑ'KØ×-Ñ-¨jÔ9Ü˜dŸo™o¬tÔ4ðõð =×WÑWØ˜dŸo™o¨zó�Fð Ð)Ø%˜ØØð �OŠOØ×>Ñ>Ð?SÔTØ× Ñ  NÒ2àà×-Ñ-¨jÔ9Øä�d—o‘o¤tÔ,ðõð 5×OÑOÐPTÐVZ×VeÑVeÐgqÓrˆFØÐ!Ø�ØøôE 'ò Ü)ð Tóð ðûô6 ò Ü!ð Lóð ðús   ÃF ÅF ÆFÆF2c                 óˆ  — | j                   €yt        | j                   t        «      r|j                  | j                   v S t        | j                   t        «      rÑ| j                   j
                  j                  «       D ]4  }t        |t        «      r|j                  |v sŒ" y|j                  |k(  sŒ4 y | j                   j                  r_t        | j                   j                  t        «      r| j                   j                  n| j                   j                  g}|j                  |v S y| j                   |j                  k(  S )a  
        Returns True if the event_hook is the same as the event_type

        eg. if `self.event_hook == "pre_call" and event_type == "pre_call"` -> then True
        eg. if `self.event_hook == "pre_call" and event_type == "post_call"` -> then False
        TF)rQ   r4   r‚   r¨   r   rÅ   rÆ   r/   )rf   r  Ú	tag_valuerË   s       r7   r'  z)CustomGuardrail._event_hook_is_event_type±  s  € ð �?‰?Ð"ØÜ�d—o‘o¤tÔ,Ø×#Ñ# t§¡Ð6Ð6Ü�d—o‘o¤tÔ,Ø!Ÿ_™_×1Ñ1×8Ñ8Ó:ò  �	Ü˜i¬Ô.Ø!×'Ñ'¨9Ò4Ù#Ø×%Ñ%¨Ó2Ùð ð �‰×&Ò&ä/9¸$¿/¹/×:QÑ:QÔSWÔ/X�D—O‘O×+Ò+Ð_c×_nÑ_n×_vÑ_vÐ^wð ð "×'Ñ'¨<Ð7Ð7ØØ�‰ *×"2Ñ"2Ñ2Ð2r9   c           	      ó�  — | j                  |«      }|D ]¯  }t        |t        «      sŒ| j                  |v sŒ#t	        di || j                     ¤Ž}|j                  di «      }| j                  «       durNt        |t        «      r:|r8t        j                  d| j                  t        |j                  «       «      «       i c S |c S  i S )aç  
        Returns `extra_body` to be added to the request body for the Guardrail API call

        Use this to pass dynamic params to the guardrail API call - eg. success_threshold, failure_threshold, etc.

        ```
        [{"lakera_guard": {"extra_body": {"foo": "bar"}}}]
        ```

        Will return: for guardrail=`lakera-guard`:
        {
            "foo": "bar"
        }

        Args:
            request_data: The original `request_data` passed to LiteLLM Proxy
        Ú
extra_bodyTzOGuardrail %s: ignoring dynamic extra_body keys %s because premium_user is Falser`   )rä   r4   rª   rO   r   r>   Ú_validate_premium_userr   rc   r‚   Úkeys)rf   rB   rå   Ú	guardrailÚguardrail_configr.  s         r7   Ú)get_guardrail_dynamic_request_body_paramsz9CustomGuardrail.get_guardrail_dynamic_request_body_paramsÌ  sÆ   € ð$ '+×&FÑ&FÀ|Ó&TÐð .ò 	"ˆIÜ˜)¤TÕ*¨t×/BÑ/BÀiÒ/Oä;QÑ;sÐT]Ð^b×^qÑ^qÑTrÑ;sÐ Ø-×1Ñ1°,ÀÓC�
Ø×.Ñ.Ó0¸Ñ<Ü! *¬dÔ3¹
Ü&×.Ñ.ØmØ ×/Ñ/Ü  §¡Ó!2Ó3ôð
 ’Ið "Ò!ð	"ð" ˆ	r9   c                 ór   — ddl m}m} |dur+t        j                  d|j
                  j                  «       yy)z<
        Returns True if the user is a premium user
        r   )ÚCommonProxyErrorsÚpremium_userTz7Trying to use premium guardrail without premium user %sF)Úlitellm.proxy.proxy_serverr5  r6  r   rc   Únot_premium_userr¨   )rf   r5  r6  s      r7   r/  z&CustomGuardrail._validate_premium_userô  s8   € ÷ 	Oà˜tÑ#Ü×"Ñ"ØIÐK\×KmÑKm×KsÑKsôð Ør9   Úguardrail_json_responseÚguardrail_statusÚ
start_timeÚend_timeÚdurationÚmasked_entity_countÚguardrail_providerÚtracing_detailc                 óî  ‡— t        |t        «      rt        |«      }ddlm} |	�|	}nPt        | j
                  t        «      r* |di t        | j
                  j                  «       «      ¤Ž}n| j
                  }ddl	m
}  ||«      }t        |t        «      r|j                  dd«       n:t        |t        «      r*|D ]%  }t        |t        «      sŒ|j                  dd«       Œ' t        |«      }ddlm}  ||«      }t!        d| j"                  ||||||||dœ	|
xs i ¤ŽŠdt        d	dfˆfd
„}t%        |«      \  }} ||«       t&        j)                  d«       	 ddlm}  |‰«       y# t        $ r Y yw xY w)a¨  
        Builds `StandardLoggingGuardrailInformation` and adds it to the request metadata so it can be used for logging to DataDog, Langfuse, etc.

        Args:
            tracing_detail: Optional typed dict with provider-specific tracing fields
                (guardrail_id, policy_template, detection_method, confidence_score,
                classification, match_details, patterns_checked, alert_recipients).
        r   )ÚGuardrailModeN)Úfilter_exceptions_from_paramsÚsecret_fields)Úmask_credentials_in_payload)	rO   r?  Úguardrail_modeÚguardrail_responser:  r;  r<  r=  r>  Ú	containerr2   c                 ó�   •— d}| j                  |«      }|€‰g| |<   y t        |t        «      r|j                  ‰«       y |‰g| |<   y )NÚ&standard_logging_guardrail_information)r>   r4   r‚   rÈ   )rH  rŸ   r¯   Úslgs      €r7   Ú_append_guardrail_infozjCustomGuardrail.add_standard_logging_guardrail_information_to_request_data.<locals>._append_guardrail_infoM  sL   ø€ ØAˆCØ'Ÿm™m¨CÓ0ˆHØÐØ"% �	˜#’Ü˜H¤dÔ+Ø—‘ Õ$ð #+¨C �	˜#’r9   T)Úemit_guardrail_spanr`   )r4   ro   rH   Úlitellm.types.utilsrB  rQ   r   rª   Ú
model_dumpÚ'litellm.litellm_core_utils.core_helpersrC  Úpopr‚   r   Ú0litellm.litellm_core_utils.sensitive_data_maskerrE  r   rO   r   r0   r¢   Ú litellm.integrations.otel.loggerrM  )rf   r9  rB   r:  r;  r<  r=  r>  r?  r  r@  rB  rF  rC  Úclean_guardrail_responseÚitemrE  rL  Ú_Úmetadata_bucketrM  rK  s                        @r7   Ú:add_standard_logging_guardrail_information_to_request_datazJCustomGuardrail.add_standard_logging_guardrail_information_to_request_data  s‚  ø€ ô* Ð-¬yÔ9Ü&)Ð*AÓ&BÐ#Ý5ð Ð!Ø'‰NÜ˜Ÿ™¬Ô.Ù*ÑP¬T°$·/±/×2LÑ2LÓ2NÓ-OÑP‰Nà!Ÿ_™_ˆNõ	
ñ $AÐAXÓ#YÐ ô
 Ð.´Ô5Ø$×(Ñ(¨¸$Õ?ÜÐ0´$Ô7Ø0ò 4�Ü˜d¤DÕ)Ø—H‘H˜_¨dÕ3ð4ô $FÐF^Ó#_Ð õ	
ñ $?Ð?WÓ#XÐ ä8ð 
Ø×.Ñ.Ø1Ø)Ø7Ø-Ø!ØØØ 3ñ
ð Ò# ñ
ˆð		1¬dð 		1°tõ 		1ô ;¸<ÓHÑˆˆ?Ù˜Ô/ä ×$Ñ$ TÔ*ð
	ÝLá Õ$øÜò 	Ùð	ús   ÅE( Å(	E4Å3E4ÚinputsÚ
input_type)Úrequestr  Úlogging_objÚLiteLLMLoggingObjc              ƒ   ó   K  — |S ­w)a°  
        Apply your guardrail logic to the given inputs

        Args:
            inputs: Dictionary containing:
                - texts: List of texts to apply the guardrail to
                - images: Optional list of images to apply the guardrail to
                - tool_calls: Optional list of tool calls to apply the guardrail to
            request_data: The request data dictionary - containing user api key metadata (e.g. user_id, team_id, etc.)
            input_type: The type of input to apply the guardrail to - "request" or "response"
            logging_obj: Optional logging object for tracking the guardrail execution

        Any of the custom guardrails can override this method to provide custom guardrail logic

        Returns the texts with the guardrail applied and the images with the guardrail applied (if any)

        Raises:
            Exception:
                - If the guardrail raises an exception

        r`   )rf   rY  rB   rZ  r\  s        r7   rö   zCustomGuardrail.apply_guardrailg  s   è ø€ ð8 ˆùs   ‚Úoriginal_inputsc           	      óÀ   — |€i n|}|�'t        |t        «      r| j                  ||«      rd}nd}t        j                  d|«       | j                  ||d||||¬«       |S )úŒ
        Add StandardLoggingGuardrailInformation to the request data

        This gets logged on downsteam Langfuse, DataDog, etc.
        ÚmaskÚallowzGuardrail response: %sÚsuccess©r9  rB   r:  r=  r;  r<  r  )r4   rª   Ú_inputs_were_modifiedr   r    rX  )	rf   r  rB   r;  r<  r=  r  r_  rG  s	            r7   Ú_process_responsez!CustomGuardrail._process_response…  s€   € ð  :BÐ9I±2ÈxÐð Ð&¬:°hÄÔ+Eà×)Ñ)¨/¸8ÔDØ%+Ñ"à%,Ð"ä×ÑÐ5°xÔ@à×GÑGØ$6Ø%Ø&ØØ!ØØ!ð 	Hô 	
ð ˆr9   r1   c                 ó   — t        | «      S )zMRetained spelling for existing callers; prefer ``is_guardrail_intervention``.)r8   r6   s    r7   Ú_is_guardrail_interventionz*CustomGuardrail._is_guardrail_intervention­  s   € ô )¨Ó+Ð+r9   c           	      ó˜   — | j                  |«      rdnd}|}d| j                  j                  v rd}| j                  |||||||¬«       |‚)ra  Úguardrail_intervenedÚguardrail_failed_to_respondÚCustomCodeGuardrailÚdenyre  )ri  ri   rü   rX  )	rf   r1   rB   r;  r<  r=  r  r:  rG  s	            r7   Ú_process_errorzCustomGuardrail._process_error²  sm   € ð '+×&EÑ&EÀaÔ&HÑ"ÐNkð 	ð
 /0ÐØ  D§N¡N×$;Ñ$;Ñ;Ø!'Ðà×GÑGØ$6Ø%Ø-ØØ!ØØ!ð 	Hô 	
ð ˆr9   c                 óÊ   — t        |j                  «       «      t        |j                  «       «      z  }|D ]+  }|j                  |«      }|j                  |«      }||k7  sŒ+ y y)zÂ
        Compare original inputs with response to determine if content was modified.

        Returns True if the inputs were modified (mask scenario), False otherwise (allow scenario).
        TF)r¢   r0  r>   )rf   r_  r  Úall_keysrŸ   Úoriginal_valueÚresponse_values          r7   rf  z%CustomGuardrail._inputs_were_modifiedÔ  sf   € ô ˜o×2Ñ2Ó4Ó5¼¸H¿M¹M»OÓ8LÑLˆð ò 	ˆCØ,×0Ñ0°Ó5ˆNØ%Ÿ\™\¨#Ó.ˆNØ Ó/Ùð		ð r9   Úcontent_stringÚmask_stringÚstart_indexÚ	end_indexc                 ó\   — d|cxk  r|cxk  rt        |«      k  s|S  |S |d| |z   ||d z   S )zS
        Mask the content in the string between the start and end indices.
        r   N)Úlen)rf   rt  ru  rv  rw  s        r7   Úmask_content_in_stringz&CustomGuardrail.mask_content_in_stringç  sM   € ð �[ÔC 9ÔC´°NÓ0CÒCØ!Ð!ð DØ!Ð!ð ˜l˜{Ð+¨kÑ9¸NÈ9È:Ð<VÑVÐVr9   Úlitellm_paramsc                 ó`   — t        |«      j                  «       D ]  \  }}t        | ||«       Œ y)z@
        Update the guardrails litellm params in memory
        N)ÚvarsÚitemsÚsetattr)rf   r{  rŸ   r¨   s       r7   Úupdate_in_memory_litellm_paramsz/CustomGuardrail.update_in_memory_litellm_paramsù  s1   € ô ˜~Ó.×4Ñ4Ó6ò 	&‰JˆC�Ü�D˜#˜uÕ%ñ	&r9   c                 ó  — |�|€y|t         j                  j                  k(  sW|t         j                  j                  k(  s:|t         j                  j                  k(  s|t         j
                  j                  k(  r|j                  d«      S |t         j                  j                  k(  s|t         j                  j                  k(  rGddl	m
} ddlm} |j                  d«      }|€y|j                  ||¬«      } |t        t           |«      S y)zG
        Returns the messages for the given call type and data
        Nr   r   )Úcast)Ú LiteLLMCompletionResponsesConfigr€   )r€   Úresponses_api_request)r   r  r¨   r  Úanthropic_messagesÚcall_mcp_toolr>   Ú	responsesÚ
aresponsesÚtypingr‚  ÚBlitellm.responses.litellm_completion_transformation.transformationrƒ  Ú)transform_responses_api_input_to_messagesr‚   r   )rf   rþ   rz   r‚  rƒ  Ú
input_datar   s          r7   Ú%get_guardrails_messages_for_call_typez5CustomGuardrail.get_guardrails_messages_for_call_type   sð   € ð Ð  Øð œ×-Ñ-×3Ñ3Ò3ØœI×1Ñ1×7Ñ7Ò7ØœI×8Ñ8×>Ñ>Ò>ØœI×3Ñ3×9Ñ9Ò9à—8‘8˜JÓ'Ð'ð œ	×+Ñ+×1Ñ1Ò1°YÄ)×BVÑBV×B\ÑB\Ò5\Ý#õð !%§¡¨Ó 1ˆJØÐ!Øà>×hÑhØ Ø&*ð ió ˆHñ œÔ-Ñ.°Ó9Ð9Ør9   )NNNFFFNNNNNNTFFFrô   )NN)r2   r   )NNNNNNN)NNNNN)NNNN)Mrü   Ú
__module__Ú__qualname__rL   r   ÚboolÚ__annotations__rM   rN   rH   r‚   r   r   Úintre   rª   r   rq   Úobjectry   r‹   r�   rŽ   Ústaticmethodr—   rš   r   r¦   r²   r¶   r¹   rõ   r»   Úclassmethodr¾   ra   rÔ   r×   rÚ   rà   r   rä   rè   rë   rð   rò   r÷   rý   r   r  r   r  r!  r#  r  r'  r3  r/  ro   r   Úfloatr   rX  r   r   r	   rö   rg  ri  ro  rf  rz  r   r€  r   r�  Ú__classcell__)ri   s   @r7   rK   rK   Ž   s–  ø… à27Ð ¨$¡Ó7ð 27Ð ¨¡Ó6à8=Ð% x°¡~Ó=ð &*ØBFØTXØ Ø%*Ø&+Ø15Ø04Ø#'Ø15Ø(,Ø48Ø'+Ø %Ø!&Ø',ñ#M#à˜d™
ðM#ð  $Ð$7Ñ8¸4Ñ?ðM#ð (¨$Ð/BÑ*CÑCÀdÑJÈTÑQð	M#ð
 ðM#ð #ðM#ð  $ðM#ð %(¨$¡JðM#ð $'¨¡:ðM#ð ˜D‘jðM#ð %(¨$¡JðM#ð  ™:ðM#ð (+¨T¡zðM#ð !%ðM#ð ðM#ð  ð!M#ð" !%õ#M#ñ^°ð ¸dÀ3ÈÀ8¹nÈtÑ>Sð Ð_bó ð. 15Ø$(ñ0
àð0
ð ˜3 ˜8‘nð0
ð ˜S #˜X™¨Ñ-ð	0
ð
 "ð0
ð 
ó0
ðdJà�3˜�8‰nðJð ðJð 
ó	Jð` 15ñ	'
àð'
ð ˜3 ˜8‘nð'
ð ˜S #˜X™¨Ñ-ð	'
ð
 
ó'
ðR>¸dÀ3ÈÀ8¹nð >ÐQTÐW[ÑQ[ó >ð ð@ ð @¨ò @ó ð@ðM°3ð M¸3ó Mð*Uà�C‰y˜4Ñð*Uð ˜3 ˜;Ñ'ð*Uð ð	*Uð
 
ˆc‰�TÑ	ó*UðX#à�C‰y˜4Ñð#ð ˜3 ˜;Ñ'ð#ð ð	#ð
 
ó#ðJd°ó dð 15ñ,à˜3 ˜8‘nð,ð ˜S #˜X™¨Ñ-ð,ð 
ó	,ð\ ð˜dÐ#9Ñ:¸TÑAò ó ðð ð	¨$Ð/BÑ*CÀdÑ*Jò 	ó ð	ð"yà'¨$Ð/BÑ*CÑCÀdÑJÈTÑQð"yð  $Ð$7Ñ8ð"yð 
ó	"yðH ð) $ð )¨4ò )ó ð)ð*V°ð V¸$À¹+ó Vð8À$ð 8È4ÐPSÉ9ó 8ð¨cð °dó ð,°ð ¸¸c¹ÀTÈ$ÈsÐTjÐOjÑJkÑElÑ9ló ð&à" 3™i¨$¨t°CÐ9OÐ4OÑ/PÑ*QÑQðð 
óð4 #¨¡*ó 4ðH¨4°°S°©>ð H¸dó Hð2
¨t°C¸°H©~ð 
À$ó 
ðQ°ó Qó!ð%¸4ÀÀSÀ¹>ð %ÐV_ÐbfÑVfð %ÐkoÐrvÑkvó %ðN#àð#ð #ð#ð ˜tÑ#ð	#ð
 
˜DÑ	 ó#ðJ°ó ð¸ó ðBð (ðBð 
ó	BðH3Ð4Gð 3ÈDó 3ð6&Àdð &Ètó &ðP¨ó ð$ $(Ø!%Ø!%Ø59Ø)-Ø15Ø8<ñdà!*¨S¡°4Ñ!7¸$¸t¹*Ñ!Dðdð ðdð *ð	dð
 ˜D‘Lðdð ˜$‘,ðdð ˜$‘,ðdð " # s (™^¨dÑ2ðdð   $™Jðdð (¨$Ñ.ðdð /°Ñ5ðdð 
ódðV 6:ñà)ðð ðð Ð1Ñ2ð	ð
 Ð1Ñ2ðð 
#óðD $(Ø!%Ø!%Ø15Ø'+ñ&à˜‘+ð&ð ð&ð ˜D‘Lð	&ð
 ˜$‘,ð&ð ˜$‘,ð&ð (¨$Ñ.ð&ð  ™ó&ðP ð, ið ,°Dò ,ó ð,ð $(Ø!%Ø!%Ø15ñ àð ð ð ð ˜D‘Lð	 ð
 ˜$‘,ð ð ˜$‘,ð ð (¨$Ñ.ó ðD°Tð ÀTð Èdó ð&WàðWð ðWð ð	Wð
 ðWð 
óWð$&¸mð &ÐPTó &ð 9=ñ*Ø"ð*Ø*.°©+ð*à	ÐÑ	 $Ñ	&÷*r9   rK   ÚlpÚentriesc                 ó¶   — t        | t        «      sy| j                  d«      €i | d<   | d   j                  dg «      }|D ]  }||vsŒ|j	                  |«       Œ y)z:Merge guardrail entries into a single litellm_params dict.NrE   rJ  )r4   rª   r>   Ú
setdefaultrÈ   )r˜  r™  r¯   Úentrys       r7   Ú_append_slg_to_litellm_paramsr�  -  sb   € ä�bœ$ÔØØ	‡v�vˆjÓÐ!Øˆˆ:‰Ø˜‘n×/Ñ/Ð0XÐZ\Ó]€HØò #ˆØ˜Ò Ø�O‰O˜EÕ"ñ#r9   r\  c                 ó  — |€y| j                  t        | «      «      xs i }|j                  d«      }|syt        |t        «      r|n|g}t	        |dd«      xs i }t        t	        |dd«      |«       t        |j                  d«      |«       y)aG  Copy standard_logging_guardrail_information from request_data into logging_obj.

    The @log_guardrail_information decorator writes guardrail info to
    request_data["metadata"] or request_data["litellm_metadata"].  For
    passthrough routes (/v1/messages, /v1/responses) the spend-log payload is
    built from logging_obj.litellm_params["metadata"], which is a separate dict
    that does not share identity with the one in request_data.  This helper
    bridges that gap so guardrail_information is non-null in spend logs for all
    routes, not just /v1/chat/completions.
    NrJ  Úmodel_call_detailsr{  )r>   r   r4   r‚   Úgetattrr�  )rB   r\  Úmeta_srcÚslg_infor™  Úmcds         r7   Ú#_sync_guardrail_info_to_logging_objr¤  9  s�   € ð ÐØØ"×&Ñ&Ô'MÈlÓ'[Ó\ÒbÐ`b€HØ—l‘lÐ#KÓL€HÙØÜ'1°(¼DÔ'A™8ÈÀz€GÜ˜Ð&:¸DÓAÒGÀR€CÜ!¤'¨+Ð7GÈÓ"NÐPWÔXÜ! #§'¡'Ð*:Ó";¸WÕEr9   c                 óæ   ‡ ‡‡‡‡— ddl }ddlŠdt        dt        dz  fd„Š|j	                  ‰ «      ˆˆ fd„«       Š|j	                  ‰ «      ˆˆ fd„«       Š|j	                  ‰ «      ˆˆ ˆˆfd„«       }|S )	at  
    Decorator to add standard logging guardrail information to any function

    Add this decorator to ensure your guardrail response is logged to DataDog, OTEL, s3, GCS etc.

    Logs for:
        - pre_call
        - during_call
        - post_call

    Some guardrails (e.g. ``block_code_execution``) call
    ``add_standard_logging_guardrail_information_to_request_data`` directly
    from inside the wrapped function so they can record a richer payload
    (structured detections, tracing detail) than this decorator's
    "allow"/"mask"/raw-response default. To avoid double-recording in that
    case (which would emit two spans, two Datadog records, two spend-log
    entries, etc.), a context-local flag records whether the wrapped function
    appended its own entry; if so, the auto-record is skipped. The flag is a
    ``ContextVar`` rather than a count of entries in the shared ``request_data``
    so it stays correct when guardrails run concurrently (asyncio copies the
    context into each gathered task): counting shared entries would let one
    guardrail's append hide another guardrail's missing record.

    A guardrail that only records an entry when it actually runs (e.g.
    ``HeadroomGuardrail``, which returns the inputs untouched on an endpoint
    whose payload it cannot act on) sets ``records_own_guardrail_information =
    True`` so the auto-record is skipped even on the return paths where it
    recorded nothing; otherwise a no-op early return would be logged as an
    "allow"/"success" run even though the guardrail did nothing. The exception
    branch below still records so a genuine failure is not lost.
    r   NÚ	func_namer2   c                 ó€   — | dk(  rt         j                  S | dk(  rt         j                  S | dv rt         j                  S y)z2Infer the actual event type from the function namer  Úasync_moderation_hook)r  Úasync_post_call_streaming_hookN)r   r  Úduring_callr  )r¦  s    r7   Ú$_infer_event_type_from_function_namezGlog_guardrail_information.<locals>._infer_event_type_from_function_names  sL   € ð Ð-Ò-Ü&×/Ñ/Ð/ØÐ1Ò1Ü&×2Ñ2Ð2Øð 
ñ 
ô '×0Ñ0Ð0Ør9   c            	   Ÿ   ó¾  •K  — t        j                  «       }| d   }|j                  d«      xs |j                  d«      xs i } ‰‰j                  «      }d }‰j                  dk(  rd|v r|j                  d«      }|j                  d«      }t        j                  d«      }	  ‰| i |¤Žƒ d {  –—† }	|j                  st        j                  «       r#|	t        j                  |«       t        ||«       S |j                  |	||j                  «       t        j                  «       j                  «       t        j                  «       |z
  j                  «       ||¬«      t        j                  |«       t        ||«       S 7 ŒÑ# t        $ r¨}
t        j                  «       r‚ |j                  |
||j                  «       t        j                  «       j                  «       t        j                  «       |z
  j                  «       |¬	«      cY d }
~
t        j                  |«       t        ||«       S d }
~
ww xY w# t        j                  |«       t        ||«       w xY w­w)
Nr   rz   rB   rö   rY  r\  F)r  rB   r;  r<  r=  r  r_  )r1   rB   r;  r<  r=  r  )r   Únowr>   rü   r0   r¢   rN   Úresetr¤  rg  Ú	timestampÚtotal_secondsro   ro  ©Úargsrg   r;  rf   rB   r  r_  r\  Úself_recorded_tokenr  r1   r«  Úfuncs              €€r7   Úasync_wrapperz0log_guardrail_information.<locals>.async_wrapper‚  s  øè ø€ ä$ŸL™L›Nˆ
Ø'+¨A¡wˆØ$*§J¡J¨vÓ$6Ò$Z¸&¿*¹*À^Ó:TÒ$ZÐXZˆÙ@ÀÇÁÓOˆ
ð ˆØ�=‰=Ð-Ò-°(¸fÑ2DØ$Ÿj™j¨Ó2ˆOà#ŸZ™Z¨Ó6ˆÜ%=×%AÑ%AÀ%Ó%HÐð	KÙ$(¨$Ð$9°&Ñ$9×9ˆHØ×5Ò5Ô9Q×9UÑ9UÔ9WØô, %×*Ñ*Ð+>Ô?Ü/°¸kÕJð- ×)Ñ)Ø!Ø)Ø%×/Ñ/Ó1Ü!Ÿ™›×1Ñ1Ó3Ü"Ÿ,™,›.¨:Ñ5×DÑDÓFØ%Ø /ð *ó ô* %×*Ñ*Ð+>Ô?Ü/°¸kÕJð3 :ùô ò 
	Ü'×+Ñ+Ô-ØØ×&Ñ&ØØ)Ø%×/Ñ/Ó1Ü!Ÿ™›×1Ñ1Ó3Ü"Ÿ,™,›.¨:Ñ5×DÑDÓFØ%ð 'ó ô ô %×*Ñ*Ð+>Ô?Ü/°¸kÕJûð
	ûô %×*Ñ*Ð+>Ô?Ü/°¸kÕJüsh   ƒB IÂ$F Â/FÂ0%F Ã"IÃ7A(F Å"IÆF Æ	H4ÆA<H/ÈH4È	H7 È"IÈ/H4È4H7 È7#IÉIc                  óâ  •— t        j                  «       }| d   }|j                  d«      xs |j                  d«      xs i } ‰‰j                  «      }d }‰j                  dk(  rd|v r|j                  d«      }|j                  d«      }t        j                  d«      }	  ‰| i |¤Ž}	|j                  st        j                  «       r#|	t        j                  |«       t        ||«       S |j                  |	|t        j                  «       |z
  j                  «       ||¬«      t        j                  |«       t        ||«       S # t        $ rx}
t        j                  «       r‚ |j                  |
|t        j                  «       |z
  j                  «       |¬	«      cY d }
~
t        j                  |«       t        ||«       S d }
~
ww xY w# t        j                  |«       t        ||«       w xY w)
Nr   rz   rB   rö   rY  r\  F)r  rB   r=  r  r_  )r1   rB   r=  r  )r   r­  r>   rü   r0   r¢   rN   r®  r¤  rg  r°  ro   ro  r±  s              €€r7   Úsync_wrapperz/log_guardrail_information.<locals>.sync_wrapper¬  sº  ø€ ä$ŸL™L›Nˆ
Ø'+¨A¡wˆØ$*§J¡J¨vÓ$6Ò$Z¸&¿*¹*À^Ó:TÒ$ZÐXZˆÙ@ÀÇÁÓOˆ
ð ˆØ�=‰=Ð-Ò-°(¸fÑ2DØ$Ÿj™j¨Ó2ˆOà#ŸZ™Z¨Ó6ˆÜ%=×%AÑ%AÀ%Ó%HÐð	KÙ" DÐ3¨FÑ3ˆHØ×5Ò5Ô9Q×9UÑ9UÔ9WØô$ %×*Ñ*Ð+>Ô?Ü/°¸kÕJð% ×)Ñ)Ø!Ø)Ü"Ÿ,™,›.¨:Ñ5×DÑDÓFØ%Ø /ð *ó ô" %×*Ñ*Ð+>Ô?Ü/°¸kÕJøô ò 	Ü'×+Ñ+Ô-ØØ×&Ñ&ØØ)Ü"Ÿ,™,›.¨:Ñ5×DÑDÓFØ%ð	 'ó ô ô %×*Ñ*Ð+>Ô?Ü/°¸kÕJûð	ûô %×*Ñ*Ð+>Ô?Ü/°¸kÕJús7   Â")E Ã-8E Å	GÅAGÆGÆG ÇGÇG Ç#G.c                  óF   •— ‰j                  ‰«      r ‰| i |¤ŽS  ‰| i |¤ŽS rô   )Úiscoroutinefunction)r²  rg   rµ  r´  Úinspectr·  s     €€€€r7   Úwrapperz*log_guardrail_information.<locals>.wrapperÒ  s1   ø€ à×&Ñ& tÔ,Ù  $Ð1¨&Ñ1Ð1Ù˜TÐ, VÑ,Ð,r9   )Ú	functoolsrº  rH   r   Úwraps)r´  r¼  r»  r«  rµ  rº  r·  s   `  @@@@r7   Úlog_guardrail_informationr¾  P  sŠ   ü€ ó@ ÛðÜðä	˜tÑ	#óð ‡_�_�TÓô'Kó ð'KðR ‡_�_�TÓô#Kó ð#KðJ ‡_�_�TÓö-ó ð-ð
 €Nr9   )MÚcontextvarsr“   r<   Úsecretsr   r‰  r   r   r   r   r   r	   r
   Úlitellm._loggingr   Úlitellm.cachingr   Ú"litellm.integrations.custom_loggerr   rP  r   r   r   Úlitellm.secret_managers.mainr   Úlitellm.types.guardrailsr   r   r   r   Úlitellm.types.llms.openair   Ú3litellm.types.proxy.guardrails.guardrail_hooks.baser   rN  r   r   r   r   r   r   Úfastapi.exceptionsr   rû   Ú*litellm.litellm_core_utils.litellm_loggingr   r]  r    r‘  Úlitellm.constantsr!   r"   Úlitellm.exceptionsr#   r$   r%   r&   Ú	token_hexr(   Ú	frozensetr,   r-   Ú
ContextVarr0   r�  ro   r8   rA   rª   rH   rI   rK   r“  r‚   r�  r¤  r¾  r`   r9   r7   ú<module>rÏ     s�  ðÜ Û Û 	Û Ý ß S× SÑ Så +Ý %Ý ;÷ñ õ
 5÷ó õ 7Ý T÷÷ ðÝ0ñ ÝWÙ‹K€€EÓ ÷÷ó ð #4 '×"3Ñ"3°BÓ"7Ð ˜%Ó 7á'0²Ó'AÐ ˜uÓ AðGð ˜%ó ð AWÀ×@VÑ@VØ%¨uôAÐ ˜% × 6Ñ 6°tÑ <Ñ=ó ð
  ð  ¨tó  ðF.¨ó .ð°4¸¸S¸±>ð ÀcÈDÁjó ô&\�lô \ð~$	# fð 	#°tð 	#Àó 	#ðF°dð FÈð FÐTXó Fó.HøðY) ò Ø‚Mðús   Á5D: Ä:EÅE