Ë
    tPêj/  ã                   óô   — d dl 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 d dlmZmZ d dl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mZ erd dlmZ  G d„ de«      Z  G d„ d«      Z! G d„ de«      Z"y)é    N)ÚTYPE_CHECKINGÚAnyÚFinalÚcast)ÚHTTPException)Úverbose_proxy_logger)Ú	DualCache)ÚCustomGuardrailÚlog_guardrail_information)Úget_async_httpx_clientÚhttpxSpecialProvider)ÚUserAPIKeyAuth)Ú*add_guardrail_to_applied_guardrails_header)ÚGuardrailEventHooks)ÚChoicesÚLLMResponseTypesÚModelResponseÚTextCompletionResponse)ÚGuardrailConfigModelc                   ó   — e Zd ZdZy)ÚPangeaGuardrailMissingSecretsz,Custom exception for missing Pangea secrets.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    ú{/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/guardrails/guardrail_hooks/pangea/pangea.pyr   r   !   s   „ Ú6r   r   c                   ó:   — e Zd Zd„ Zdee   fd„Zdee   defd„Zy)Ú_TextCompletionRequestc                 ó   — || _         y ©N©Úbody)Úselfr$   s     r   Ú__init__z_TextCompletionRequest.__init__&   s	   € Øˆ�	r   Úreturnc                 ó(   — d| j                   d   dœgS )NÚuserÚprompt)ÚroleÚcontentr#   )r%   s    r   Úget_messagesz#_TextCompletionRequest.get_messages)   s   € Ø¨D¯I©I°hÑ,?Ñ@ÐAÐAr   Úprompt_messagesc                 ód   — t        |«      dk(  sJ ‚|d   d   | j                  d<   | j                  S )Né   r   r,   r*   )Úlenr$   )r%   r.   s     r   Úupdate_original_bodyz+_TextCompletionRequest.update_original_body-   s7   € Ü�?Ó# qÒ(Ð(Ð(Ø-¨aÑ0°Ñ;ˆ�	‰	�(ÑØ�y‰yÐr   N)	r   r   r   r&   ÚlistÚdictr-   r   r2   r   r   r   r    r    %   s0   „ òðB˜d 4™jó Bð°D¸±Jð À3ô r   r    c                   ó  ‡ — e Zd ZdZ	 	 	 	 ddededz  dedz  dedz  dedz  f
ˆ fd„Zd	ed
ededefd„Zdede	dedefd„Z
edede	dedefd„«       Zdededefd„Zedededefd„«       Zeded   dz  fd„«       Zedee   fd„«       Zˆ xZS )ÚPangeaHandlerzä
    Pangea AI Guardrail handler to interact with the Pangea AI Guard service.

    This class implements the necessary hooks to call the Pangea AI Guard API
    for input and output scanning based on the configured recipe.
    NÚguardrail_nameÚpangea_input_recipeÚpangea_output_recipeÚapi_keyÚapi_basec                 óÌ  •— t        t        j                  ¬«      | _        |xs t        j
                  j                  d«      | _        | j                  st        d«      ‚|xs# t        j
                  j                  d«      xs d| _	        || _
        || _        t        ‰| �4  d	|t        | j                  «       «      dœ|¤Ž t!        j"                  d||| j                  «       y)
a  
        Initializes the PangeaHandler.

        Args:
            guardrail_name (str): The name of the guardrail instance.
            pangea_recipe (str): The Pangea recipe key to use for scanning.
            api_key (Optional[str]): The Pangea API key. Reads from PANGEA_API_KEY env var if None.
            api_base (Optional[str]): The Pangea API base URL. Reads from PANGEA_API_BASE env var or uses default if None.
            **kwargs: Additional arguments passed to the CustomGuardrail base class.
        )Úllm_providerÚPANGEA_API_KEYz_Pangea API Key not found. Set PANGEA_API_KEY environment variable or pass it in litellm_params.ÚPANGEA_API_BASEz$https://ai-guard.aws.us.pangea.cloud)r7   Úsupported_event_hooksz=Initialized Pangea Guardrail: name=%s, recipe=%s, api_base=%sNr   )r   r   ÚGuardrailCallbackÚasync_handlerÚosÚenvironÚgetr:   r   r;   r8   r9   Úsuperr&   r3   Úget_supported_event_hooksr   Údebug)r%   r7   r8   r9   r:   r;   ÚkwargsÚ	__class__s          €r   r&   zPangeaHandler.__init__;   sÎ   ø€ ô& 4ÔAU×AgÑAgÔhˆÔØÒB¤"§*¡*§.¡.Ð1AÓ"BˆŒØ�|Š|Ü/Øqóð ð
 !Òo¤B§J¡J§N¡NÐ3DÓ$EÒoÐIoˆŒØ#6ˆÔ Ø$8ˆÔ!ô 	‰Ñð 	
Ø)Ü"& t×'EÑ'EÓ'GÓ"Hñ	
ð ò	
ô
 	×"Ñ"ØKØØØ�M‰Mõ		
r   ÚapiÚpayloadÚ	hook_namer'   c              ƒ   ó$  K  — | j                   › d|› �}d| j                  › �ddœ}t        j                  d|||«       | j                  j                  |||¬«      ƒ d{  –—† }|j                  «        |j                  «       }|j                  di «      j                  d	«      r1t        j                  d
||«       t        dd| j                  dœ¬«      ‚t        j                  d||j                  di «      j                  d«      «       |S 7 Œ®­w)a  
        Makes the API call to the Pangea AI Guard endpoint.
        The function itself will raise an error in the case that a response
        should be blocked, but will return a list of redacted messages that the caller
        should act on.

        Args:
            api (str): Which API to use (text/guard or v1beta/guard)
            payload (dict): The request payload.
            request_data (dict): Original request data (used for logging/headers).
            hook_name (str): Name of the hook calling this function (for logging).

        Raises:
            HTTPException: If the Pangea API returns a 'blocked: true' response.
            Exception: For other API call failures.

        Returns:
            list[dict]: The original response body
        ú/zBearer zapplication/json)ÚAuthorizationzContent-Typez;Pangea Guardrail (%s): Calling endpoint %s with payload: %s)ÚurlÚjsonÚheadersNÚresultÚblockedz4Pangea Guardrail (%s): Request blocked. Response: %si�  z Violated Pangea guardrail policy)Úerrorr7   ©Ústatus_codeÚdetailz3Pangea Guardrail (%s): Request passed. Response: %sÚ	detectors)r;   r:   r   rH   rB   ÚpostÚraise_for_statusrR   rE   Úwarningr   r7   )r%   rK   rL   rM   ÚendpointrS   ÚresponserT   s           r   Ú_call_pangea_ai_guardz#PangeaHandler._call_pangea_ai_guardg   s  è ø€ ð( "Ÿ]™]˜O¨1¨S¨EÐ2ˆð  ' t§|¡| nÐ5Ø.ñ
ˆô
 	×"Ñ"ØIÈ9ÐV^Ð`gô	
ð !%× 2Ñ 2× 7Ñ 7¸HÈ7Ð\cÐ 7Ó d×dˆØ×!Ñ!Ô#à Ÿ™›ˆà�:‰:�h Ó#×'Ñ'¨	Ô2Ü ×(Ñ(Ð)_ÐajÐlrÔsÜØà?Ø&*×&9Ñ&9ñôð ô 	×"Ñ"ØAÀ9ÈfÏjÉjÐYaÐceÓNf×NjÑNjÐkvÓNwô	
ð ˆð% eús   ‚ADÁDÁ B/DÚuser_api_key_dictÚcacheÚdataÚ	call_typec              ƒ   ó*  K  — d }d }|dk(  s|dk(  rt        |«      }|j                  «       }n|j                  d«      }d||j                  d«      dœddœ}| j                  r| j                  |d	<   | j	                  d
|d«      ƒ d {  –—† }t        || j                  ¬«       |j                  di «      j                  d«      sy |j                  di «      j                  di «      }	|dk(  s|dk(  r|j                  |	d   «      }|S |	d   |d<   |S 7 Œ‰­w)NÚtext_completionÚatext_completionÚmessagesFÚtools)rh   ri   Úinput©rH   rj   Ú
event_typeÚrecipeúv1beta/guardÚasync_pre_call_hook©Úrequest_datar7   rT   ÚtransformedÚoutput)r    r-   rE   r8   r`   r   r7   r2   )
r%   ra   rb   rc   rd   Útransformerrh   Úai_guard_payloadÚai_guard_responsers   s
             r   Ú_async_pre_call_hookz"PangeaHandler._async_pre_call_hookš   s7  è ø€ ð ˆØˆØÐ)Ò)¨YÐ:LÒ-LÜ0°Ó6ˆKØ"×/Ñ/Ó1‰Hà—x‘x 
Ó+ˆHð Ø"*°T·X±X¸gÓ5FÑGØ!ñ#
Ðð
 ×#Ò#Ø)-×)AÑ)AÐ˜XÑ&à"&×"<Ñ"<¸^ÐM]Ð_tÓ"u×uÐÜ2ÀÐUY×UhÑUhÕià ×$Ñ$ X¨rÓ2×6Ñ6°}ÔEØà)×-Ñ-¨h¸Ó;×?Ñ?ÀÈ"ÓMˆØÐ)Ò)¨YÐ:LÒ-LØ×3Ñ3°F¸:Ñ4FÓGˆDð ˆð  & jÑ1ˆD�ÑØˆð vús   ‚BDÂDÂB
Dc           	   ƒ   óT  K  — t         j                  }| j                  ||¬«      dur"t        j                  d| j
                  «       |S 	 | j                  ||||«      ƒ d {  –—† S 7 Œ# t        $ r ‚ t        $ r*}t        dd| j
                  t        |«      dœ¬«      |‚d }~ww xY w­w)N©rc   rl   TúAPangea Guardrail (async_pre_call_hook): Guardrail is disabled %s.éô  úError in Pangea Guardrail©rV   r7   Ú
exceptionsrW   )
r   Úpre_callÚshould_run_guardrailr   rH   r7   rw   r   Ú	ExceptionÚstr)r%   ra   rb   rc   rd   rl   Úes          r   ro   z!PangeaHandler.async_pre_call_hook¾   s·   è ø€ ô 0×8Ñ8ˆ
Ø×$Ñ$¨$¸:Ð$ÓFÈdÑRÜ ×&Ñ&ØSÐUY×UhÑUhôð ˆKð	Ø×2Ñ2Ð3DÀeÈTÐS\Ó]×]Ð]Ð]ùÜò 	ØÜò 	ÜØà8Ø&*×&9Ñ&9Ü"% a£&ñôð ðûð	üs<   ‚AB(ÁA) Á"A'Á#A) Á&B(Á'A) Á)B%Á;%B Â B%Â%B(r_   c              ƒ   ó   K  — t        |t        «      rt        |«      j                  «       }nJt        |t        «      r9|j                  d«      }|€y t        t        t        t        t        f      |«      }ny |j                  d«      x}r]t        |t        «      rMg }|D ]D  }t        |t        «      r!	 |j                  |j                  «       «       Œ4|j                  |«       ŒF |}d||j                  d«      |dœddœ}	| j                  r| j                  |	d<   | j                  d	|	d
«      ƒ d {  –—† }
t!        || j"                  ¬«       |
j                  di «      j                  d«      sy |
j                  di «      j                  di «      }|d   |_        |S # t        $ r# |j                  |j                  «       «       Y �Œ*w xY w7 Œš­w)Nrh   ÚchoicesFri   )rh   ri   r…   rs   rk   rm   rn   ro   rp   rT   rr   )Ú
isinstancer   r    r-   r   rE   r   r3   r4   r   r   ÚappendÚ
model_dumpr�   r9   r`   r   r7   r…   )r%   rc   ra   r_   Úinput_messagesrh   r…   Úserialized_choicesÚcru   rv   rs   s               r   Ú_async_post_call_success_hookz+PangeaHandler._async_post_call_success_hookÛ   s½  è ø€ ô �hÔ 6Ô7ä3°DÓ9×FÑFÓH‰NÜ˜¤-Ô0Ø"Ÿh™h zÓ2ˆHØÐØÜ!¤$¤t¬C´¨H¡~Ñ"6¸ÓA‰Nàà—l‘l 9Ó-Ð-ˆ7Ð-Ü˜'¤4Ô(Ø,.Ð"Ø ò 5�AÜ! !¤WÔ-ð@Ø.×5Ñ5°a·l±l³nÕEð +×1Ñ1°!Õ4ð5ð -�ð à*ØŸ™ 'Ó*Ø"ñð
 #ñ#
Ðð ×$Ò$Ø)-×)BÑ)BÐ˜XÑ&à"&×"<Ñ"<¸^ÐM]Ð_tÓ"u×uÐÜ2ÀÐUY×UhÑUhÕià ×$Ñ$ X¨rÓ2×6Ñ6°}ÔEØà)×-Ñ-¨h¸Ó;×?Ñ?ÀÈ"ÓMˆØ! )Ñ,ˆÔØˆøô7  )ò @Ø.×5Ñ5°a·f±f³h×?ð@úð& vús8   ‚B/GÂ2FÃA GÄ1GÄ2A+GÆ(G	ÇGÇG	Ç	Gc           	   ƒ   óR  K  — t         j                  }| j                  ||¬«      dur"t        j                  d| j
                  «       |S 	 | j                  |||«      ƒ d{  –—† S 7 Œ# t        $ r ‚ t        $ r*}t        dd| j
                  t        |«      dœ¬«      |‚d}~ww xY w­w)	a)  
        Guardrail hook run after a successful LLM call (scans output).

        Args:
            data (dict): The original request data.
            user_api_key_dict (UserAPIKeyAuth): User API key details.
            response (LLMResponseTypes): The response object from the LLM call.
        ry   Trz   Nr{   r|   r}   rW   )
r   Ú	post_callr€   r   rH   r7   rŒ   r   r�   r‚   )r%   rc   ra   r_   rl   rƒ   s         r   Úasync_post_call_success_hookz*PangeaHandler.async_post_call_success_hook  sµ   è ø€ ô  0×9Ñ9ˆ
Ø×$Ñ$¨$¸:Ð$ÓFÈdÑRÜ ×&Ñ&ØSÐUY×UhÑUhôð ˆKð	Ø×;Ñ;¸DÐBSÐU]Ó^×^Ð^Ð^ùÜò 	ØÜò 	ÜØà8Ø&*×&9Ñ&9Ü"% a£&ñôð ðûð	üs<   ‚AB'ÁA( Á!A&Á"A( Á%B'Á&A( Á(B$Á:%BÂB$Â$B'r   c                  ó   — ddl m}  | S )Nr   ©ÚPangeaGuardrailConfigModel)Ú5litellm.types.proxy.guardrails.guardrail_hooks.pangear’   r‘   s    r   Úget_config_modelzPangeaHandler.get_config_model5  s   € õ	
ð *Ð)r   c                 óB   — t         j                  t         j                  gS r"   )r   r   rŽ   )Úclss    r   rG   z'PangeaHandler.get_supported_event_hooks=  s    € ô  ×(Ñ(Ü×)Ñ)ð
ð 	
r   )NNNN)r   r   r   r   r‚   r&   r4   r`   r   r	   rw   r   ro   r   rŒ   r�   ÚstaticmethodÚtyper”   Úclassmethodr3   r   rG   Ú__classcell__)rJ   s   @r   r6   r6   3   s  ø„ ñð +/Ø+/Ø"Ø#ñ*
àð*
ð ! 4™Zð*
ð " D™jð	*
ð
 �t‘ð*
ð ˜‘*õ*
ðX1¨sð 1¸Tð 1Ècð 1ÐVZó 1ðf"à)ð"ð ð"ð ð	"ð
 ó"ðH ðà)ðð ðð ð	ð
 òó ðð84àð4ð *ð4ð
 #ó4ðl ð!àð!ð *ð!ð
 #ò!ó ð!ðF ð*˜dÐ#9Ñ:¸TÑAò *ó ð*ð ð
¨$Ð/BÑ*Cò 
ó ô
r   r6   )#rC   Útypingr   r   r   r   Úfastapir   Úlitellm._loggingr   Úlitellm.caching.dual_cacher	   Ú%litellm.integrations.custom_guardrailr
   r   Ú&litellm.llms.custom_httpx.http_handlerr   r   Úlitellm.proxy._typesr   Ú)litellm.proxy.common_utils.callback_utilsr   Úlitellm.types.guardrailsr   Úlitellm.types.utilsr   r   r   r   Ú3litellm.types.proxy.guardrails.guardrail_hooks.baser   r�   r   r    r6   r   r   r   ú<module>r¦      sf   ðã 	ß 2Ó 2å !å 1Ý 0÷÷õ 0õõ 9÷ó ñ ÝXô7 Iô 7÷ñ ôO
�Oõ O
r   