Ë
    tPêj_l  ã                   ó  — U d Z ddlZddlZddl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mZ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 erddlmZ dZee d<    G d„ de!«      Z" G d„ de!«      Z# G d„ de«      Z$y)z'Gray Swan Cygnal guardrail integration.é    N)ÚTYPE_CHECKINGÚAnyÚFinalÚLiteralÚOptional)ÚHTTPException)Úverbose_proxy_logger)ÚCustomGuardrailÚModifyResponseExceptionÚlog_guardrail_information)Ú
safe_dumps)Úsafe_json_loads)Úget_async_httpx_clientÚhttpxSpecialProvider)ÚGuardrailEventHooks)ÚGenericGuardrailAPIInputs)ÚLoggingzBlocked by Gray Swan GuardrailÚGRAYSWAN_BLOCK_ERROR_MSGc                   ó   — e Zd ZdZy)ÚGraySwanGuardrailMissingSecretsz-Raised when the Gray Swan API key is missing.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    ú/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/guardrails/guardrail_hooks/grayswan/grayswan.pyr   r      s   „ Ú7r   r   c                   ó8   ‡ — e Zd ZdZddededz  ddfˆ fd„Zˆ xZS )ÚGraySwanGuardrailAPIErrorz/Raised when the Gray Swan API returns an error.NÚmessageÚstatus_codeÚreturnc                 ó2   •— t         ‰| �  |«       || _        y ©N)ÚsuperÚ__init__r!   )Úselfr    r!   Ú	__class__s      €r   r&   z"GraySwanGuardrailAPIError.__init__%   s   ø€ Ü‰Ñ˜Ô!Ø&ˆÕr   r$   )r   r   r   r   ÚstrÚintr&   Ú__classcell__©r(   s   @r   r   r   "   s)   ø„ Ù9ñ' ð '°#¸±*ð 'È÷ 'ñ 'r   r   c                   óÚ  ‡ — e Zd ZdZh d£ZdZdZdZh d£Z	 	 	 	 	 	 	 	 	 	 	 	 d;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e	e	f   dz  de	dz  dedededz  de
dz  deddfˆ fd„Zedee   fd„«       Zdefˆ fd„Ze	 d<dededed   ded   def
d„«       Zd edefd!„Zd"edee	ef   fd#„Z	 	 d=d$ed%edz  d&edz  ddfd'„Zd"edee	ef   fd(„Zd$ee	ef   deded)edef
d*„Zdee	e	f   fd+„Z 	 d<deded   dee	e	f   dz  fd,„Z!	 d<d-eee	e	f      d.ededed   dee	ef   dz  f
d/„Z"d>d0ed)ede	fd1„Z#d2ede	fd3„Z$d4e
dz  de
fd5„Z%d4e	dz  de	dz  fd6„Z&	 d<d eded7e
d8e
d9edz  ddfd:„Z'ˆ xZ(S )?ÚGraySwanGuardraila™  
    Guardrail that calls Gray Swan's Cygnal monitoring endpoint.

    Uses the unified guardrail system via `apply_guardrail` method,
    which automatically works with all LiteLLM endpoints:
    - OpenAI Chat Completions
    - OpenAI Responses API
    - OpenAI Text Completions
    - Anthropic Messages
    - Image Generation
    - And more...

    see: https://docs.grayswan.ai/cygnal/monitor-requests
    >   ÚblockÚmonitorÚpassthroughr0   zhttps://api.grayswan.aiz/cygnal/monitor>   ÚoffÚhybridÚthinkingNÚguardrail_nameÚapi_keyÚapi_baseÚon_flagged_actionÚviolation_thresholdÚreasoning_modeÚ
categoriesÚ	policy_idÚstreaming_end_of_stream_onlyÚstreaming_sampling_rateÚ	fail_openÚguardrail_timeoutÚkwargsr"   c                 óŠ  •— t        t        j                  ¬«      | _        |xs t	        j
                  d«      }|st        d«      ‚|| _        |xs# t	        j
                  d«      xs | j                  }|j                  d«      | _
        | j                  › | j                  › �| _        |}|r2|j                  «       | j                  v r|j                  «       | _        n4|r!t!        j"                  d|| j$                  «       | j$                  | _        | j'                  |«      | _        | j+                  |«      | _        || _        || _        |€dn
t3        |«      | _        |€dn
t7        |«      | _        |	| _        |
| _        t!        j>                  d	|	|
«       tA        ‰| �„  d|tE        | jG                  «       «      d
œ|¤Ž y )N)Úllm_providerÚGRAYSWAN_API_KEYzDGray Swan API key missing. Set `GRAYSWAN_API_KEY` or pass `api_key`.ÚGRAYSWAN_API_BASEú/zLGray Swan Guardrail: Unsupported on_flagged_action '%s', defaulting to '%s'.Tç      >@zNGraySwan __init__: streaming_end_of_stream_only=%s, streaming_sampling_rate=%s)r5   Úsupported_event_hooksr   )$r   r   ÚGuardrailCallbackÚasync_handlerÚosÚgetenvr   r6   ÚBASE_API_URLÚrstripr7   ÚMONITOR_PATHÚmonitor_urlÚlowerÚSUPPORTED_ON_FLAGGED_ACTIONSr8   r	   ÚwarningÚDEFAULT_ON_FLAGGED_ACTIONÚ_resolve_thresholdr9   Ú_resolve_reasoning_moder:   r;   r<   Úboolr?   Úfloatr@   r=   r>   Údebugr%   r&   ÚlistÚget_supported_event_hooks)r'   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   Úapi_key_valueÚbaseÚactionr(   s                    €r   r&   zGraySwanGuardrail.__init__@   s¥  ø€ ô  4ÔAU×AgÑAgÔhˆÔà&ÒG¬"¯)©)Ð4FÓ*GˆÙÜ1ØVóð ð *ˆŒàÒU¤"§)¡)Ð,?Ó"@ÒUÀD×DUÑDUˆØŸ™ CÓ(ˆŒØ"Ÿm™m˜_¨T×->Ñ->Ð,?Ð@ˆÔà)ˆÙ�f—l‘l“n¨×(IÑ(IÑIØ%+§\¡\£^ˆDÕ"áÜ$×,Ñ,ØbØØ×2Ñ2ôð
 &*×%CÑ%CˆDÔ"à#'×#:Ñ#:Ð;NÓ#OˆÔ Ø"×:Ñ:¸>ÓJˆÔØ$ˆŒØ"ˆŒØ!*Ð!2™¼¸Y»ˆŒØ):Ð)B¡ÌÐN_ÓH`ˆÔð -IˆÔ)Ø'>ˆÔ$ä×"Ñ"Ø\Ø(Ø#ô	
ô 	‰Ñð 	
Ø)Ü"& t×'EÑ'EÓ'GÓ"Hñ	
ð ó	
r   c                 ó`   — t         j                  t         j                  t         j                  gS r$   )r   Úpre_callÚduring_callÚ	post_call)Úclss    r   r[   z+GraySwanGuardrail.get_supported_event_hooks€   s)   € ô  ×(Ñ(Ü×+Ñ+Ü×)Ñ)ð
ð 	
r   c           
      óÄ   •— t         ‰| �  ||«      }dt        | «      j                  v }t	        j
                  d||| j                  |t        | «      j                  «       |S )zOverride to add debug logging.Úapply_guardrailznGraySwan DEBUG: should_run_guardrail event_type=%s, result=%s, event_hook=%s, has_apply_guardrail=%s, class=%s)r%   Úshould_run_guardrailÚtypeÚ__dict__r	   rY   Ú
event_hookr   )r'   ÚdataÚ
event_typeÚresultÚhas_apply_guardrailr(   s        €r   rf   z&GraySwanGuardrail.should_run_guardrailŒ   s^   ø€ ä™Ñ4°T¸:ÓFˆà%6¼$¸t»*×:MÑ:MÐ%MÐÜ×"Ñ"Ø|ØØØ�O‰OØÜ�‹J×Ñô	
ð ˆr   ÚinputsÚrequest_dataÚ
input_type)ÚrequestÚresponseÚlogging_objÚLiteLLMLoggingObjc              ƒ   ó  K  — t        j                  d||j                  d«      r|j                  dg «      dd nd«       |j                  dg «      }|st        j                  d«       |S t        j                  dt        |«      |«       |dk(  rd	nd
}|D �cg c]  }||dœ‘Œ	 }}| j	                  |«      xs i }	|	rt        j                  dt        |	«      «       | j                  ||	||«      }
|
€|S t        j                  «       }	 | j                  |
«      ƒ d{  –—† }|dk(  }| j                  ||||¬«      }|S c c}w 7 Œ%# t        $ r³}| j                  |«      r‚ t        j                  «       }t        |dd«      xs t        |dd«      }| j                  ||xs i |||¬«       | j                  rt        j                  d|«       |cY d}~S t!        |t"        «      r|‚t#        t%        |«      |¬«      |‚d}~ww xY w­w)a‘  
        Apply Gray Swan guardrail to extracted text content.

        This method is called by the unified guardrail system which handles
        extracting text from any request format (OpenAI, Anthropic, etc.).

        Args:
            inputs: Dictionary containing:
                - texts: List of texts to scan
                - images: Optional list of images (not currently used by GraySwan)
                - tool_calls: Optional list of tool calls (not currently used)
            request_data: The original request data
            input_type: "request" for pre-call, "response" for post-call
            logging_obj: Optional logging object

        Returns:
            GenericGuardrailAPIInputs - texts may be replaced with violation message in passthrough mode

        Raises:
            HTTPException: If content is blocked (block mode)
            Exception: If guardrail check fails
        zCGraySwan DEBUG: apply_guardrail called with input_type=%s, texts=%sÚtextsNéd   ÚNONEz%Gray Swan Guardrail: No texts to scanz/Gray Swan Guardrail: Scanning %d text(s) for %srr   Ú	assistantÚuser)ÚroleÚcontentz*Gray Swan Guardrail: dynamic extra_body=%s)Úresponse_jsonro   rn   Ú	is_outputr!   Úexception_status_code)Úexcro   Ú
start_timeÚend_timer!   zRGray Swan Guardrail: fail_open=True. Allowing request to proceed despite error: %s©r!   )r	   rY   ÚgetÚlenÚ)get_guardrail_dynamic_request_body_paramsr   Ú_prepare_payloadÚtimeÚ_call_grayswan_apiÚ_process_response_internalÚ	ExceptionÚ_is_grayswan_exceptionÚgetattrÚ_log_guardrail_failurer?   rS   Ú
isinstancer   r)   )r'   rn   ro   rp   rs   rv   r{   ÚtextÚmessagesÚdynamic_bodyÚpayloadr�   r}   r~   rl   r€   r‚   r!   s                     r   re   z!GraySwanGuardrail.apply_guardrailŸ   s  è ø€ ô> 	×"Ñ"ØQØØ-3¯Z©Z¸Ô-@ˆF�J‰J�w Ó# D SÑ)Àfô	
ð —z‘z '¨2Ó.ˆÙÜ ×&Ñ&Ð'NÔOØˆMä×"Ñ"Ø=Ü�‹JØô	
ð &0°:Ò%=‘kÀ6ˆØGLÖM¸t D°TÓ:ÐMˆÐMð #×LÑLÈ\ÓZÒ`Ð^`ˆÙÜ ×&Ñ&Ð'SÔU_Ð`lÓUmÔnð ×.Ñ.¨x¸À|ÐU`ÓaˆØˆ?ØˆMä ŸI™I›Kˆ
ð	XØ)-×)@Ñ)@ÀÓ)I×#IˆMØ)¨ZÑ7ˆIØ ×;Ñ;Ø+Ø)ØØ#ð	 <ó ˆFð ˆMùò- Nð $Jùô ò 	XØ×*Ñ*¨3Ô/ØÜ"Ÿi™i›kˆHÜ!(¨¨m¸TÓ!BÒ!qÄgÈcÐSjÐlpÓFqˆKØ×'Ñ'ØØ)Ò/¨RØ%Ø!Ø'ð (ô ð �~Š~Ü$×,Ñ,ØhØôð •Ü˜#Ô8Ô9Ø�	Ü+¬C°«HÀ+ÔNÐTWÐWûð)	Xüs\   ‚BHÂD>Â$A$HÄ	E ÄEÄE Ä=HÅE Å	HÅA?G<ÇHÇHÇ)G<Ç<HÈHr€   c                 ó�   — t        |t        «      ryt        |dd «      }t        |t        «      r|j	                  d«      t
        k(  S y)NTÚdetailÚerrorF)r�   r   r�   Údictr„   r   )r'   r€   r•   s      r   rŒ   z(GraySwanGuardrail._is_grayswan_exceptionÿ   sB   € ô �cÔ2Ô3ØÜ  X¨tÓ4ˆÜ�fœdÔ#Ø—:‘:˜gÓ&Ô*BÑBÐBØr   r“   c              ƒ   óf   K  — | j                  |«      ƒ d{  –—† }| j                  |«       |S 7 Œ­w)zñ
        Run the GraySwan guardrail on a payload.

        This is a legacy method for testing purposes.

        Args:
            payload: The payload to scan

        Returns:
            Dict containing the GraySwan API response
        N)r‰   Ú_process_grayswan_response)r'   r“   r}   s      r   Úrun_grayswan_guardrailz(GraySwanGuardrail.run_grayswan_guardrail  s5   è ø€ ð &*×%<Ñ%<¸WÓ%E×Eˆà×'Ñ'¨Ô6ØÐð  Fús   ‚1—/˜1r}   rj   Ú	hook_typec           
      óˆ  — t        |j                  dd«      xs d«      }|j                  dg «      }|j                  d«      }|j                  d«      }|| j                  k\  }|s"t        j                  d|| j                  «       yt        j
                  d|| j                  «       d	d
||||dœ}	|�#|t        j                  t        j                  fv }
nd
}
| j                  dk(  r|
sdnd}t        dt        |||||dœ¬«      ‚| j                  dk(  r¯|	g}| j                  ||
 ¬«      }t        j                  d«       |t        j                  t        j                  fv r|€i }| j                  |||	¬«       y|t        j                  k(  r4|€i }d|vri |d<   d|d   vrg |d   d<   |d   d   j!                  |	«       yyy)a  
        Legacy method for processing GraySwan API responses.

        This method is maintained for backward compatibility with existing tests.
        It handles the test scenarios where responses need to be processed with
        knowledge of the request context (pre/during/post call hooks).

        Args:
            response_json: Response from GraySwan API
            data: Optional request data (for passthrough exceptions)
            hook_type: Optional GuardrailEventHooks for determining behavior
        Ú	violationç        Úviolated_rulesÚmutationÚipiú<Gray Swan Guardrail: content passed (score=%s, threshold=%s)Nú@Gray Swan Guardrail: violation score %.3f exceeds threshold %.3fÚgrayswanT©Ú	guardrailÚflaggedÚviolation_scorerŸ   r    r¡   r/   ÚoutputÚinputé�  ©r–   Úviolation_locationr�   rŸ   r    r¡   ©r!   r•   r1   ©r~   z:Gray Swan Guardrail: Passthrough mode - handling violation©Úviolation_messagero   Údetection_infoÚmetadataÚguardrail_detections)rX   r„   r9   r	   rY   rS   r   r`   ra   r8   r   r   Ú_format_violation_messageÚinfoÚraise_passthrough_exceptionrb   Úappend)r'   r}   rj   r›   r¨   rŸ   Úmutation_detectedÚipi_detectedr§   r²   Úis_inputr­   Ú
detectionsr±   s                 r   r™   z,GraySwanGuardrail._process_grayswan_response  s'  € ô$ "' }×'8Ñ'8¸ÀcÓ'JÒ'QÈcÓ!RˆØ -× 1Ñ 1Ð2BÀBÓ GˆØ#0×#4Ñ#4°ZÓ#@ÐØ+×/Ñ/°Ó6ˆà(¨D×,DÑ,DÑDˆÙÜ ×&Ñ&ØNØØ×(Ñ(ôð
 ä×$Ñ$ØNØØ×$Ñ$ô	
ð $ØØ.Ø,Ø)Øñ!
ˆð Ð Ø Ü#×,Ñ,Ü#×/Ñ/ð%ð ‰Hð
 ˆHà×!Ñ! WÒ,Ù9A©ÈÐÜØä5Ø*<Ø!0Ø&4Ø 1Ø'ñô
ð 
ð ×#Ñ# }Ò4à!/Ð 0ˆJØ'+×'EÑ'EÀjÐ`hÐ\hÐ'EÓ'iÐÜ ×%Ñ%Ð&bÔcð Ü#×,Ñ,Ü#×/Ñ/ðñ ð
 �<Ø�DØ×0Ñ0Ø&7Ø!%Ø#1ð 1õ ð
 Ô1×;Ñ;Ò;à�<Ø�DØ TÑ)Ø')�D˜Ñ$Ø)°°jÑ1AÑAØ?A�D˜Ñ$Ð%;Ñ<Ø�ZÑ Ð!7Ñ8×?Ñ?ÀÕOð <ð' 5r   c              ƒ   ó°  K  — | j                  «       }	 | j                  j                  | j                  ||| j                  ¬«      ƒ d{  –—† }|j                  «        |j                  «       }t        j                  dt        |«      «       |S 7 ŒE# t        $ r8}t        |dd«      xs t        |dd«      }t        t        |«      |¬«      |‚d}~ww xY w­w)z!Call the GraySwan monitoring API.)ÚurlÚheadersÚjsonÚtimeoutNz(Gray Swan Guardrail: monitor response %sr!   r   rƒ   )Ú_prepare_headersrJ   ÚpostrP   r@   Úraise_for_statusrÀ   r	   rY   r   r‹   r�   r   r)   )r'   r“   r¿   rr   rl   r€   r!   s          r   r‰   z$GraySwanGuardrail._call_grayswan_api„  sÒ   è ø€ à×.Ñ.Ó0ˆð	XØ$(×$6Ñ$6×$;Ñ$;Ø×$Ñ$ØØØ×.Ñ.ð	 %<ó %÷ ˆHð ×%Ñ%Ô'Ø$ŸM™M›OˆFÜ ×&Ñ&Ð'QÔS]Ð^dÓSeÔfØˆMðùô ò 	XÜ!(¨¨m¸TÓ!BÒ!qÄgÈcÐSjÐlpÓFqˆKÜ+¬C°«HÀ+ÔNÐTWÐWûð	Xüs;   ‚C”6B Á
BÁAB ÂCÂB Â	CÂ3CÃCÃCr~   c           
      ó¸  — t        |j                  dd«      xs d«      }|j                  dg «      }|j                  d«      }|j                  d«      }|| j                  k\  }	|	s#t        j                  d|| j                  «       |S t        j
                  d|| j                  «       dd	||||d
œ}
| j                  dk(  r|rdnd}t        dt        |||||dœ¬«      ‚| j                  dk(  rt        j                  d«       |S | j                  dk(  rF| j                  |
|¬«      }t        j                  d«       |s| j                  |||
¬«       |g|d<   |S |S )aà  
        Process GraySwan API response and handle violations.

        Args:
            response_json: Response from GraySwan API
            request_data: Original request data
            inputs: The inputs being scanned
            is_output: True if scanning model output, False for input

        Returns:
            GenericGuardrailAPIInputs - possibly modified with violation message

        Raises:
            HTTPException: If content is blocked (block mode)
        r�   rž   Úviolated_rule_descriptionsr    r¡   r¢   r£   r¤   Tr¥   r/   r©   rª   r«   r¬   r®   r0   z?Gray Swan Guardrail: Monitoring mode - allowing flagged contentr1   r¯   zPGray Swan Guardrail: Passthrough mode - replacing content with violation messager°   rv   )rX   r„   r9   r	   rY   rS   r8   r   r   r¶   rµ   r·   )r'   r}   ro   rn   r~   r¨   rŸ   r¹   rº   r§   r²   r­   r±   s                r   rŠ   z,GraySwanGuardrail._process_response_internal—  sš  € ô, "' }×'8Ñ'8¸ÀcÓ'JÒ'QÈcÓ!RˆØ -× 1Ñ 1Ð2NÐPRÓ SˆØ#0×#4Ñ#4°ZÓ#@ÐØ+×/Ñ/°Ó6ˆà(¨D×,DÑ,DÑDˆÙÜ ×&Ñ&ØNØØ×(Ñ(ôð
 ˆMä×$Ñ$ØNØØ×$Ñ$ô	
ð $ØØ.Ø,Ø)Øñ!
ˆð ×!Ñ! WÒ,Ù4=©À7ÐÜØä5Ø*<Ø!0Ø&4Ø 1Ø'ñô
ð 
ð ×#Ñ# yÒ0Ü ×%Ñ%Ð&gÔhØˆMØ×#Ñ# }Ò4à'+×'EÑ'EÀnÐ`iÐ'EÓ'jÐÜ ×%Ñ%Øbôñ ð ×0Ñ0Ø&7Ø!-Ø#1ð 1ô ð  1Ð1ˆF�7‰OØˆMàˆr   c                 ó<   — d| j                   › �d| j                   dœS )NzBearer zapplication/json)ÚAuthorizationzContent-Typezgrayswan-api-key)r6   )r'   s    r   rÂ   z"GraySwanGuardrail._prepare_headersô  s$   € à& t§|¡| nÐ5Ø.Ø $§¡ñ
ð 	
r   c                 ó(  — |j                  d«      xs i j                  d«      }|s|j                  d«      }|s$|j                  d«      xs i j                  d«      }|sN|rLt        |dd «      r?|j                  xs i j                  di «      j                  di «      j                  d«      }t        |t        «      sy d}i }|j                  «       D ]8  \  }}t        |«      j                  «       |v sŒ"t        |«      |t        |«      <   Œ: |xs d S )NÚproxy_server_requestr¿   r³   Úmodel_call_detailsÚlitellm_params)Úshade_scan_id)r„   r�   rË   r�   r—   Úitemsr)   rQ   )r'   ro   rs   r¿   Úforwarded_header_namesÚforwarded_headersÚkeyÚvalues           r   Ú_extract_inbound_headersz*GraySwanGuardrail._extract_inbound_headersû  s  € ð
  ×#Ñ#Ð$:Ó;ÒA¸r×FÑFÀyÓQˆÙØ"×&Ñ& yÓ1ˆGÙØ#×'Ñ'¨
Ó3Ò9°r×>Ñ>¸yÓIˆGÙ™;¬7°;Ð@TÐVZÔ+[à×/Ñ/Ò5°2×:Ñ:Ð;KÈRÓP×TÑTÐU_ÐacÓd×hÑhÐirÓsð ô ˜'¤4Ô(Øà(:ÐØ#%ÐØ!Ÿ-™-›/ò 	9‰JˆC�Ü�3‹x�~‰~ÓÐ#9Ò9Ü.1°%«jÐ!¤# c£(Ò+ð	9ð !Ò( DÐ(r   r‘   r’   c                 óD  — d|i}|j                  d«      xs | j                  }|r||d<   |j                  d«      xs | j                  }|r||d<   |j                  d«      xs | j                  }|r||d<   d|v r|d   |d<   | j	                  ||«      }	|j                  d«      }
t        |
t        «      rt        |
«      ni }|	r,|j                  d«      }t        |t        «      ri |¥|	¥n|	|d<   |r-t        t        |«      i ¬«      }t        |t        «      r|r||d<   |S )	Nr‘   r;   r<   r:   r³   Úlitellm_metadatar¿   )Údefault)	r„   r;   r<   r:   rÓ   r�   r—   r   r   )r'   r‘   r’   ro   rs   r“   r;   r<   r:   Úinbound_headersrÕ   Úcleaned_litellm_metadataÚexisting_headersÚ	sanitizeds                 r   r‡   z"GraySwanGuardrail._prepare_payload  sJ  € ð +5°hÐ)?ˆà(×,Ñ,¨\Ó:ÒM¸d¿o¹oˆ
ÙØ$.ˆG�LÑ!à'×+Ñ+¨KÓ8ÒJ¸D¿N¹Nˆ	ÙØ#,ˆG�KÑ à ,× 0Ñ 0Ð1AÓ BÒ YÀd×FYÑFYˆÙØ(6ˆGÐ$Ñ%ð ˜Ñ%Ø".¨zÑ":ˆG�JÑà!%×!>Ñ!>¸|È[Ó!Yˆà".×"2Ñ"2Ð3EÓ"FÐÜDNÐO_ÔaeÔDf¬$Ð/?Ô*@ÐlnÐ ÙØ&>×&BÑ&BÀ9Ó&MÐä;EÐFVÔX\Ô;]Ð7Ð#Ð7 Ñ7Ðcrð % YÑ/ñ $Ü.¬zÐ:RÓ/SÐ]_Ô`ˆIÜ˜)¤TÔ*©yØ.7�Ð*Ñ+àˆr   r²   c                 óä  — t        |t        «      rt        |«      dkD  r|d   }t        |t        «      r|ni }|j	                  dd«      }|j	                  dg «      }|j	                  dd«      }|j	                  dd«      }|rdnd	}d
|› d|d›d�g}	|r(| j                  |«      }
|
r|	j                  d|
› d�«       |r|	j                  d«       |r|	j                  d«       dj                  |	«      S )a©  
        Format detection info into a user-friendly violation message.

        Args:
            detection_info: Can be either:
                - A single dict with violation_score, violated_rules, mutation, ipi keys
                - A list of such dicts (legacy format)
            is_output: True if violation is in model output, False if in input

        Returns:
            Formatted violation message string
        r   r¨   rž   rŸ   r    Fr¡   zthe model responsezinput queryzOSorry I can't help with that. According to the Gray Swan Cygnal Guardrail, the z has a violation score of z.2fú.zIt was violating the rule(s): zEMutation effort to make the harmful intention disguised was DETECTED.z'Indirect Prompt Injection was DETECTED.ú
)r�   rZ   r…   r—   r„   Ú_format_violated_rulesr¸   Újoin)r'   r²   r~   Údetection_dictr¨   rŸ   r    r¡   r­   Úmessage_partsÚformatted_ruless              r   rµ   z+GraySwanGuardrail._format_violation_message<  s  € ô �n¤dÔ+´°NÓ0CÀaÒ0GØ+¨AÑ.ˆNô 9CÀ>ÔSWÔ8X¡nÐ^`ˆØ!/×!3Ñ!3Ð4EÀsÓ!KˆØ .× 2Ñ 2Ð3CÀRÓ HˆØ(×,Ñ,¨Z¸Ó?ˆØ#×'Ñ'¨¨uÓ5ˆá<EÑ$8È=ÐðØ%Ð&Ð&@ÀÐQTÐ@UÐUVðXð 
ˆñ
 Ø%)×%@Ñ%@ÀÓ%PˆOÙØ×$Ñ$Ð'EÀoÐEVÐVWÐ%XÔYáØ× Ñ Ð!hÔiáØ× Ñ Ð!JÔKà�y‰y˜Ó'Ð'r   rŸ   c           	      óÆ  — g }|D ]Ê  }t        |t        «      rž|j                  dd«      }|j                  dd«      }|j                  dd«      }|r7|r5|r|j                  d|› d|› d|› �«       Œj|j                  d|› d|› �«       Œ‚|r|j                  |«       Œ–|j                  t	        |«      «       Œ±|j                  t	        |«      «       ŒÌ dj                  |«      S )	z2Format violated rules list into a readable string.ÚruleÚ ÚnameÚdescriptionú#ú z: z, )r�   r—   r„   r¸   r)   rß   )r'   rŸ   Ú	formattedrä   Úrule_numÚ	rule_nameÚ	rule_descs          r   rÞ   z(GraySwanGuardrail._format_violated_rulesh  sÜ   € à&(ˆ	Ø"ò 	,ˆDÜ˜$¤Ô%àŸ8™8 F¨BÓ/�Ø ŸH™H V¨RÓ0�	Ø ŸH™H ]°BÓ7�	Ù¡	Ù Ø!×(Ñ(¨1¨X¨J°a¸	°{À"ÀYÀKÐ)PÕQà!×(Ñ(¨1¨X¨J°a¸	°{Ð)CÕDÙØ×$Ñ$ YÕ/à×$Ñ$¤S¨£YÕ/ð × Ñ ¤ T£Õ+ð#	,ð& �y‰y˜Ó#Ð#r   rÒ   c                 ó‚   — |�t        |«      S t        j                  d«      }|r	 t        |«      S y# t        $ r Y yw xY w)NÚGRAYSWAN_VIOLATION_THRESHOLDg      à?)rX   rK   rL   Ú
ValueError©r'   rÒ   Úenv_vals      r   rU   z$GraySwanGuardrail._resolve_threshold€  sO   € ØÐÜ˜“<ÐÜŸ™Ð#AÓBˆÙðÜ˜W“~Ð%ð øô ò ØØðús   ¦
2 ²	>½>c                 óæ   — |r,|j                  «       | j                  v r|j                  «       S t        j                  d«      }|r,|j                  «       | j                  v r|j                  «       S y )NÚGRAYSWAN_REASONING_MODE)rQ   ÚSUPPORTED_REASONING_MODESrK   rL   rñ   s      r   rV   z)GraySwanGuardrail._resolve_reasoning_mode‹  sX   € Ù�U—[‘[“] d×&DÑ&DÑDØ—;‘;“=Ð ÜŸ™Ð#<Ó=ˆÙ�w—}‘}“¨$×*HÑ*HÑHØ—=‘=“?Ð"Ør   r�   r‚   r!   c           	      óâ   — 	 | j                  t        |«      |d||||z
  d¬«       t        j
                  d|rd|› d�|«       y	d|«       y	# t        $ r t        j                  d|«       Y ŒGw xY w)
z;Log guardrail failure and attach standard logging metadata.Úguardrail_failed_to_respondr¤   )Úguardrail_json_responsero   Úguardrail_statusr�   r‚   ÚdurationÚguardrail_providerzBGray Swan Guardrail: failed to log guardrail failure for error: %sz-Gray Swan Guardrail: API request failed%s: %sz (status_code=ú)rå   N)Ú:add_standard_logging_guardrail_information_to_request_datar)   r‹   r	   Ú	exceptionr–   )r'   r€   ro   r�   r‚   r!   s         r   rŽ   z(GraySwanGuardrail._log_guardrail_failure“  s�   € ð	Ø×KÑKÜ(+¨C«Ø)Ø!>Ø%Ø!Ø! JÑ.Ø#-ð Lô ô 	×"Ñ"Ø;Ù/:ˆn˜[˜M¨Ð+Øõ	
à@BØõ	
øô ò 	Ü ×*Ñ*ØTØöð	ús   ‚$A ÁA.Á-A.)r¤   NNNNNNNFé   TrG   r$   )NN)F))r   r   r   r   rR   rT   rM   rO   rõ   r)   rX   r—   rW   r*   r   r&   ÚclassmethodrZ   r   r[   rf   r   r   r   r   re   r‹   rŒ   rš   r™   r‰   rŠ   rÂ   rÓ   r‡   rµ   rÞ   rU   rV   rŽ   r+   r,   s   @r   r.   r.   *   sÇ  ø„ ñò $GÐ Ø )ÐØ,€LØ$€LÚ =Ðð &0Ø"Ø#Ø(,Ø,0Ø%)Ø,0Ø $Ø-2Ø'(Ø!%Ø*.ñ>
à˜d™
ð>
ð �t‘ð>
ð ˜‘*ð	>
ð
  ™:ð>
ð # T™\ð>
ð ˜d™
ð>
ð ˜˜c˜‘N TÑ)ð>
ð ˜‘:ð>
ð '+ð>
ð "%ð>
ð ˜$‘;ð>
ð ! 4™<ð>
ð ð>
ð 
õ>
ð@ ð
¨$Ð/BÑ*Cò 
ó ð
ð¸õ ð& ð 6:ñ]Xà)ð]Xð ð]Xð Ð1Ñ2ð	]Xð
 Ð1Ñ2ð]Xð 
#ò]Xó ð]Xð~¨)ð ¸ó ð°Dð ¸TÀ#ÀsÀ(¹^ó ð( !Ø04ñ	`Pàð`Pð �T‰kð`Pð '¨Ñ-ð	`Pð
 
ó`PðLX°ð X¸¸cÀ3¸h¹ó Xð&Wà˜C ˜H‘~ðWð ðWð *ð	Wð
 ðWð 
#óWðz
 $ s¨C x¡.ó 
ð 6:ñ)àð)ð Ð1Ñ2ð)ð 
ˆc�3ˆh‰˜$Ñ	ó	)ð: 6:ñ'à�t˜C ˜H‘~Ñ&ð'ð ð'ð ð	'ð
 Ð1Ñ2ð'ð 
ˆc�3ˆh‰˜$Ñ	ó'ñR*(¸ð *(Èð *(ÐY\ó *(ðX$°Tð $¸có $ð0	¨°©ð 	¸ó 	ð¨S°4©Zð ¸CÀ$¹Jó ð #'ñ
àð
ð ð
ð ð	
ð
 ð
ð ˜4‘Zð
ð 
÷
r   r.   )%r   rK   rˆ   Útypingr   r   r   r   r   Úfastapir   Úlitellm._loggingr	   Ú%litellm.integrations.custom_guardrailr
   r   r   Ú*litellm.litellm_core_utils.safe_json_dumpsr   Ú*litellm.litellm_core_utils.safe_json_loadsr   Ú&litellm.llms.custom_httpx.http_handlerr   r   Úlitellm.types.guardrailsr   Úlitellm.types.utilsr   Ú*litellm.litellm_core_utils.litellm_loggingr   rt   r   Ú__annotations__r‹   r   r   r.   r   r   r   ú<module>r     sq   ðÚ -ã 	Û ß ?Õ ?å !å 1÷ñ õ
 BÝ F÷õ 9Ý 9áÝWà"BÐ ˜%Ó Bô8 iô 8ô' 	ô 'ôE

˜õ E

r   