Ë
    tPêjP  ã                   óà   — U d dl Z d dl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mZ d dl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Zeed<   dZ eed<    G d„ de«      Z!y)é    N)ÚAnyÚFinalÚLiteral)ÚHTTPException)Úverbose_proxy_logger)ÚCustomGuardrailÚlog_guardrail_information)ÚLogging)Úget_async_httpx_clientÚhttpxSpecialProvider)Úget_secret_str)ÚGuardrailEventHooksÚLitellmParams)ÚAllMessageValues)ÚGuardrailConfigModel)ÚGenericGuardrailAPIInputsÚ	qualifireÚGUARDRAIL_NAMEzhttps://proxy.qualifire.aiÚDEFAULT_QUALIFIRE_API_BASEc                   ób  ‡ — e Zd Zedee   f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dz  dedz  dedz  dee   dz  dedz  fˆ fd„Z	deddfd„Z
deddfˆ fd„Zdefd„Zdee   deeeef      fd„Zdee   dz  deeeef      dz  fd„Zdeeef   defd„Zdeeeef      dedz  dee   dz  deeeef      dz  deeef   f
d„Z	 d)dee   dedz  deeef   dee   dz  ddf
d„Ze	 d)d ed!ed"ed#   d$edz  def
d%„«       Zeded&   dz  fd'„«       Zˆ xZS )*ÚQualifireGuardrailÚreturnc                 ó`   — t         j                  t         j                  t         j                  gS ©N)r   Úpre_callÚduring_callÚ	post_call)Úclss    ú�/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/guardrails/guardrail_hooks/qualifire/qualifire.pyÚget_supported_event_hooksz,QualifireGuardrail.get_supported_event_hooks#   s)   € ô  ×(Ñ(Ü×+Ñ+Ü×)Ñ)ð
ð 	
ó    NÚapi_keyÚapi_baseÚevaluation_idÚprompt_injectionsÚhallucinations_checkÚgrounding_checkÚ	pii_checkÚcontent_moderation_checkÚtool_selection_quality_checkÚ
assertionsÚ
on_flaggedc                 óš  •— |xs, t        d«      xs t        j                  j                  d«      | _        |xs4 t        d«      xs' t        j                  j                  d«      xs t
        | _        || _        || _        || _	        || _
        || _        || _        |	| _        |
| _        |xs d| _        | j!                  | j                  «       | j#                  «       s| j                  sd| _        t%        t&        j(                  ¬«      | _        |j-                  dt/        | j1                  «       «      «       t3        ‰| �h  di |¤Ž y)	al  
        Initialize the QualifireGuardrail class.

        Args:
            api_key: API key for Qualifire (or use QUALIFIRE_API_KEY env var)
            api_base: Optional custom API base URL (defaults to https://api.qualifire.ai)
            evaluation_id: Pre-configured evaluation ID from Qualifire dashboard
            prompt_injections: Enable prompt injection detection (default if no other checks)
            hallucinations_check: Enable hallucination detection
            grounding_check: Enable grounding verification
            pii_check: Enable PII detection
            content_moderation_check: Enable content moderation
            tool_selection_quality_check: Enable tool selection quality check
            assertions: Custom assertions to validate against the output
            on_flagged: Action when content is flagged: "block" or "monitor"
        ÚQUALIFIRE_API_KEYÚQUALIFIRE_BASE_URLÚblockT)Úllm_providerÚsupported_event_hooksN© )r   ÚosÚenvironÚgetÚqualifire_api_keyr   Úqualifire_api_baser$   r%   r&   r'   r(   r)   r*   r+   r,   Ú_validate_on_flaggedÚ_has_any_check_enabledr   r   ÚGuardrailCallbackÚasync_handlerÚ
setdefaultÚlistr    ÚsuperÚ__init__)Úselfr"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   ÚkwargsÚ	__class__s                €r   r@   zQualifireGuardrail.__init__+   s*  ø€ ð> ")Ò!v¬NÐ;NÓ,OÒ!vÔSU×S]ÑS]×SaÑSaÐbuÓSvˆÔàò *ÜÐ2Ó3ò*ä�z‰z�~‰~Ð2Ó3ò*ô *ð	 	Ôð +ˆÔØ!2ˆÔØ$8ˆÔ!Ø.ˆÔØ"ˆŒØ(@ˆÔ%Ø,HˆÔ)Ø$ˆŒØ$Ò/¨ˆŒØ×!Ñ! $§/¡/Ô2ð ×*Ñ*Ô,°T×5GÒ5GØ%)ˆDÔ"ô 4ÔAU×AgÑAgÔhˆÔà×ÑÐ1´4¸×8VÑ8VÓ8XÓ3YÔZÜ‰ÑÑ"˜6Ó"r!   c                 ó*   — |dvrt        d|›d�«      ‚y )N)r0   Úmonitorz0Qualifire guardrail does not support on_flagged=z+; only 'block' and 'monitor' are supported.)Ú
ValueError)rA   r,   s     r   r9   z'QualifireGuardrail._validate_on_flaggedf   s1   € ØÐ1Ñ1ô ØBÀ:À.ð Q<ð <óð ð 2r!   Úlitellm_paramsc                 ó|   •— |j                   xs | j                   }| j                  |«       t        ‰| �  |¬«       y)aT  
        The base implementation blindly ``setattr``s every field on ``litellm_params``
        (including ``on_flagged``) onto this live instance with no revalidation, so an
        in-place config update (via the DB/UI, without a restart) could otherwise
        reintroduce the exact invalid on_flagged value __init__ rejects. Validate the
        prospective post-update value *before* mutating, so a rejected update leaves
        the live instance untouched instead of raising after it's already been
        corrupted. Mirrors LakeraAIGuardrail's own override of this same method.
        )rG   N)r,   r9   r?   Úupdate_in_memory_litellm_params)rA   rG   Úprospective_on_flaggedrC   s      €r   rI   z2QualifireGuardrail.update_in_memory_litellm_paramsr   s9   ø€ ð )7×(AÑ(AÒ(TÀTÇ_Á_ÐØ×!Ñ!Ð"8Ô9Ü‰Ñ/¸~Ð/ÕNr!   c           	      ó²   — t        | j                  | j                  | j                  | j                  | j
                  | j                  | j                  g«      S )z4Check if any evaluation check is explicitly enabled.)Úanyr%   r&   r'   r(   r)   r*   r+   )rA   s    r   r:   z)QualifireGuardrail._has_any_check_enabled€   sO   € äà×&Ñ&Ø×)Ñ)Ø×$Ñ$Ø—‘Ø×-Ñ-Ø×1Ñ1Ø—‘ðó

ð 
	
r!   Úmessagesc           
      ó  — g }|D �]Ý  }|j                  dd«      }|j                  dd«      }t        |t        «      r‚g }|D ]j  }t        |t        «      r6|j                  d«      dk(  r"|j	                  |j                  dd«      «       ŒIt        |t
        «      sŒZ|j	                  |«       Œl dj                  |«      }|t        |t
        «      r|n
t        |«      dœ}|j                  d	«      }	|	r|	|d	<   |j                  d
«      }
|
rÈt        |
t        «      r¸g }|
D ]ª  }t        |t        «      sŒ|j                  di «      }|j                  di «      }t        |t
        «      r	 t        j                  |«      }|j	                  |j                  d«      xs d|j                  d«      xs dt        |t        «      r|ni dœ«       Œ¬ |r||d
<   |j	                  |«       �Œà |S # t        j                  $ r i }Y Œƒw xY w)aÕ  
        Convert LiteLLM messages to Qualifire API format.
        Supports tool calls for tool_selection_quality_check.

        Returns a list of dicts matching the API's ModelInvocationCanonicalMessage schema:
        {
            "role": "user" | "assistant" | "system" | "tool",
            "content": "...",
            "tool_call_id": "...",  # optional
            "tool_calls": [{"id": "...", "name": "...", "arguments": {...}}]  # optional
        }
        ÚroleÚuserÚcontentÚ ÚtypeÚtextú
©rO   rQ   Útool_call_idÚ
tool_callsÚfunctionÚ	argumentsÚidÚname)r[   r\   rZ   )
r6   Ú
isinstancer>   ÚdictÚappendÚstrÚjoinÚjsonÚloadsÚJSONDecodeError)rA   rM   Úapi_messagesÚmsgrO   rQ   Ú
text_partsÚpartÚapi_messagerW   rX   Úapi_tool_callsÚtcÚfunction_infoÚargss                  r   Ú_convert_messages_to_api_formatz2QualifireGuardrail._convert_messages_to_api_formatŽ   sñ  € ð !ˆØó 0	-ˆCØ—7‘7˜6 6Ó*ˆDØ—g‘g˜i¨Ó,ˆGô ˜'¤4Ô(Ø�
Ø#ò 0�DÜ! $¬Ô-°$·(±(¸6Ó2BÀfÒ2LØ"×)Ñ)¨$¯(©(°6¸2Ó*>Õ?Ü# D¬#Õ.Ø"×)Ñ)¨$Õ/ð	0ð
 Ÿ)™) JÓ/�ð Ü&0°¼#Ô&>™7ÄCÈÃLñ+ˆKð Ÿ7™7 >Ó2ˆLÙØ.:�˜NÑ+ð Ÿ™ Ó.ˆJÙœj¨´TÔ:Ø!#�Ø$ò �BÜ! "¤dÕ+Ø(*¯©¨z¸2Ó(>˜à,×0Ñ0°¸bÓA˜Ü% d¬CÔ0ð*Ü'+§z¡z°$Ó'7 ð '×-Ñ-à&(§f¡f¨T£lÒ&8°bØ(5×(9Ñ(9¸&Ó(AÒ(GÀRÜ5?ÀÄdÔ5K©TÐQSñõðñ" "Ø0>�K Ñ-à×Ñ Ö,ða0	-ðd Ðøô $(×#7Ñ#7ò *Ø')¢ð*ús   Å'G(Ç(H Ç?H Útoolsc           	      ó´  — |syg }|D ]É  }t        |t        «      sŒ|j                  d«      dk(  rX|j                  di «      }|j                  |j                  dd«      |j                  dd«      |j                  di «      dœ«       Œ€d|v sŒ…|j                  |j                  dd«      |j                  dd«      |j                  di «      dœ«       ŒË |r|S dS )	a  
        Convert OpenAI-format tools to Qualifire API format.

        Returns a list of dicts matching the API's ModelInvocationToolDefinition schema:
        {
            "name": "...",
            "description": "...",
            "parameters": {...}
        }
        NrS   rY   r\   rR   ÚdescriptionÚ
parameters)r\   rq   rr   )r]   r^   r6   r_   )rA   ro   Ú	api_toolsÚtoolÚfunction_defs        r   Ú_convert_tools_to_api_formatz/QualifireGuardrail._convert_tools_to_api_formatÐ   sá   € ñ Øàˆ	Øò 	ˆDÜ˜$¤Õ%à—8‘8˜FÓ# zÒ1Ø#'§8¡8¨J¸Ó#;�LØ×$Ñ$à$0×$4Ñ$4°V¸RÓ$@Ø+7×+;Ñ+;¸MÈ2Ó+NØ*6×*:Ñ*:¸<ÈÓ*Lñõð ˜t’^Ø×$Ñ$à$(§H¡H¨V°RÓ$8Ø+/¯8©8°MÀ2Ó+FØ*.¯(©(°<ÀÓ*Dñõð	ñ, &ˆyÐ/¨4Ð/r!   Úresultc                 ó    — |j                  dg «      xs g }|D ]3  }|j                  dg «      xs g }|D ]  }|j                  d«      sŒ  y Œ5 y)a  
        Check if the Qualifire evaluation result indicates flagged content.

        Returns True only if there are explicitly flagged items in the evaluation results.
        A high score (close to 100) indicates GOOD content, low score indicates problems.
        ÚevaluationResultsÚresultsÚflaggedTF)r6   )rA   rw   Úevaluation_resultsÚeval_resultrz   Úrs         r   Ú_check_if_flaggedz$QualifireGuardrail._check_if_flagged÷   sb   € ð %+§J¡JÐ/BÀBÓ$GÒ$MÈ2Ðà-ò 	 ˆKØ!—o‘o i°Ó4Ò:¸ˆGØò  �Ø—5‘5˜Õ#Úñ ð	 ð r!   re   ÚoutputÚavailable_toolsc                 ó0  — d|i}|�||d<   | j                   rd|d<   | j                  rd|d<   | j                  rd|d<   | j                  rd|d<   | j                  rd|d<   | j
                  r"|rd|d	<   ||d
<   nt        j                  d«       |r||d<   |S )zCBuild payload dictionary for the /api/evaluation/evaluate endpoint.rM   r€   Tr%   r&   r'   r(   r)   r*   r�   znQualifire Guardrail: tool_selection_quality_check enabled but no available_tools provided, skipping this checkr+   )r%   r&   r'   r(   r)   r*   r   Údebug)rA   re   r€   r+   r�   Úpayloads         r   Ú_build_evaluate_payloadz*QualifireGuardrail._build_evaluate_payload	  sË   € ð +5°lÐ)CˆàÐØ &ˆG�HÑð ×!Ò!Ø+/ˆGÐ'Ñ(Ø×$Ò$Ø.2ˆGÐ*Ñ+Ø×ÒØ)-ˆGÐ%Ñ&Ø�>Š>Ø#'ˆG�KÑ Ø×(Ò(Ø26ˆGÐ.Ñ/Ø×,Ò,áØ:>�Ð6Ñ7Ø-<�Ð)Ò*ä$×*Ñ*ð Eôñ Ø$.ˆG�LÑ!àˆr!   Údynamic_paramsc              ƒ   ó˜  K  — |j                  d«      xs | j                  }|j                  d«      xs | j                  }|j                  d«      xs | j                  }| j                  xs dddœ}	 | j                  |«      }	|rd}
t        |«      D ]<  }|j                  d«      dk(  sŒ|j                  d	d«      }t        |t        «      r|}
 n ||
|xs d|	d
œ}| j                  |«      }|r||d<   | j                  › d�}n5| j                  |«      }| j                  |	|||¬«      }| j                  › d�}t        j                  d|«       | j                  j                  |||¬«      ƒ d{  –—† }|j!                  «        |j#                  «       }|j                  d«      |j                  d«      dœ}t        j                  d|d   |d   «       | j%                  |«      }|r,|dk(  rt        j&                  d|«       yt)        dd|dœ¬«      ‚y7 Œ¤# t(        $ r ‚ t*        $ r}t        j,                  d|«       ‚ d}~ww xY w­w)aŸ  
        Core Qualifire check logic - shared between hooks.

        Args:
            messages: The conversation messages
            output: The LLM output text (for post_call)
            dynamic_params: Dynamic parameters from request body
            available_tools: Available tools from the request (for tool_selection_quality_check)

        Raises:
            HTTPException: If content is blocked
        r$   r+   r,   rR   zapplication/json)zX-Qualifire-API-KeyzContent-TyperO   rP   rQ   )r$   Úinputr€   rM   r�   z/api/evaluation/invoke)re   r€   r+   r�   z/api/evaluation/evaluatez)Qualifire Guardrail: Making request to %s)ÚurlÚheadersrb   NÚscoreÚstatus)r‹   rŒ   z=Qualifire Guardrail: Got result from API, score=%s, status=%srE   z\Qualifire Guardrail: Monitoring mode - violation detected but allowing request. Response: %si�  zViolated guardrail policy)ÚerrorÚqualifire_response)Ústatus_codeÚdetailzQualifire Guardrail error: %s)r6   r$   r+   r,   r7   rn   Úreversedr]   r`   rv   r8   r…   r   rƒ   r<   ÚpostÚraise_for_statusrb   r   Úwarningr   Ú	ExceptionÚ	exception)rA   rM   r€   r†   r�   r$   r+   r,   rŠ   re   Ú
input_textrf   rQ   r„   rs   r‰   Úresponserw   rŽ   Ú
is_flaggedÚes                        r   Ú_run_qualifire_checkz'QualifireGuardrail._run_qualifire_check/  s‘  è ø€ ð(  .×1Ñ1°/ÓBÒXÀd×FXÑFXˆØ*×.Ñ.¨|Ó<ÒOÀÇÁˆ
Ø*×.Ñ.¨|Ó<ÒOÀÇÁˆ
ð $(×#9Ñ#9Ò#?¸RØ.ñ
ˆð
W	à"&×"FÑ"FÀxÓ"PˆLñ à�
ô $ HÓ-ò �CØ—w‘w˜v“¨&Ó0Ø"%§'¡'¨)°RÓ"8˜Ü% g¬sÔ3Ø)0˜JÙðð &3Ø'Ø$šl¨Ø ,ñ	�ð !×=Ñ=¸oÓN�	ÙØ1:�GÐ-Ñ.à×0Ñ0Ð1Ð1GÐH‘ð !×=Ñ=¸oÓN�	Ø×6Ñ6Ø!-Ø!Ø)Ø$-ð	 7ó �ð ×0Ñ0Ð1Ð1IÐJ�ä ×&Ñ&Ð'RÐTWÔXð %)×$6Ñ$6×$;Ñ$;ØØØð %<ó %÷ ˆHð
 ×%Ñ%Ô'Ø$ŸM™M›OˆFð  Ÿ™ GÓ,Ø Ÿ*™* XÓ.ñ)Ðô
 !×&Ñ&ØOØ" 7Ñ+Ø" 8Ñ,ôð !%× 6Ñ 6°vÓ >ˆJáØ Ò*Ü(×0Ñ0ØvØ*õô (Ø$'à%@Ø2Dñ ôð ð ð/ùôN ò 	ØÜò 	Ü ×*Ñ*Ð+JÈAÔNØûð	üsP   ‚A1I
Á47H Â,CH Å2HÅ3BH ÈI
ÈH ÈI
ÈH ÈIÈ+IÉIÉI
ÚinputsÚrequest_dataÚ
input_type)Úrequestr˜   Úlogging_objc              ƒ   ó¾  K  — | j                  |¬«      }|j                  d«      }|s|j                  d«      }d}|j                  dg «      }|dk(  r0|r t        |t        «      r|d   n
t	        |«      }|s|r
d|xs d	d
œg}|s'|rd|r|d   nd	d
œg}nt        j                  d«       |S |j                  d«      }	| j                  ||||	¬«      ƒ d{  –—†  |S 7 Œ­w)a  
        Apply Qualifire guardrail to the given inputs.

        This method is called by the unified guardrail system for both
        input (request) and output (response) validation.

        Args:
            inputs: Dictionary containing:
                - texts: List of texts to check
                - structured_messages: Structured messages from the request (pre-call only)
                - tool_calls: Tool calls if present
            request_data: The original request data
            input_type: "request" for pre-call, "response" for post-call
            logging_obj: Optional logging object

        Returns:
            GenericGuardrailAPIInputs - unchanged if allowed through

        Raises:
            HTTPException: If content is blocked
        )r�   Ústructured_messagesrM   NÚtextsr˜   éÿÿÿÿÚ	assistantrR   rV   rP   z9Qualifire Guardrail: No messages or texts found, skippingro   )rM   r€   r†   r�   )Ú)get_guardrail_dynamic_request_body_paramsr6   r]   r>   r`   r   rƒ   r›   )
rA   rœ   r�   rž   r    r†   rM   r€   r£   r�   s
             r   Úapply_guardrailz"QualifireGuardrail.apply_guardrail¦  s	  è ø€ ð< !%× NÑ NÐ\hÐ NÓ iˆð 39·*±*Ð=RÓ2SˆÙØ#×'Ñ'¨
Ó3ˆHð "ˆØ—z‘z '¨2Ó.ˆà˜Ò#áÜ&0°¼Ô&=˜˜ršÄ3ÀuÃ:�ñ ¡à%0¸Vº\ÀrÑJÐK�ááØ%+ÁU¸¸bº	ÐPRÑSÐT‘ä$×*Ñ*Ð+fÔgØ�ð ".×!1Ñ!1°'Ó!:ˆà×'Ñ'ØØØ)Ø+ð	 (ó 
÷ 	
ð 	
ð ˆð	
ús   ‚CCÃCÃCr   c                  ó   — ddl m}  | S )Nr   ©ÚQualifireGuardrailConfigModel)Ú8litellm.types.proxy.guardrails.guardrail_hooks.qualifirerª   r©   s    r   Úget_config_modelz#QualifireGuardrail.get_config_modelî  s   € õ	
ð -Ð,r!   )NNNNNNNNNNr0   r   )Ú__name__Ú
__module__Ú__qualname__Úclassmethodr>   r   r    r`   Úboolr@   r9   r   rI   r:   r   r^   r   rn   rv   r   r…   r›   r	   r   r   ÚLiteLLMLoggingObjr§   ÚstaticmethodrS   r¬   Ú__classcell__)rC   s   @r   r   r   "   sä  ø„ Øð
¨$Ð/BÑ*Cò 
ó ð
ð #Ø#Ø$(Ø)-Ø,0Ø'+Ø!%Ø04Ø48Ø'+Ø!(ñ9#à�t‘ð9#ð ˜‘*ð9#ð ˜T‘zð	9#ð
   $™;ð9#ð # T™kð9#ð  ™ð9#ð ˜$‘;ð9#ð #'¨¡+ð9#ð '+¨T¡kð9#ð ˜‘I Ñ$ð9#ð ˜$‘Jõ9#ðv
¨sð 
°tó 
ðO¸mð OÐPTõ Oð
¨ó 
ð@¸Ð=MÑ8Nð @ÐSWÐX\Ð]`ÐbeÐ]eÑXfÑSgó @ðD%0°$°s±)¸dÑ2Bð %0ÀtÈDÐQTÐVYÐQYÉNÑG[Ð^bÑGbó %0ðN¨¨S°#¨X©ð ¸4ó ð$$à˜4  S ™>Ñ*ð$ð �d‘
ð$ð ˜‘I Ñ$ð	$ð
 ˜d 3¨ 8™nÑ-°Ñ4ð$ð 
ˆc�3ˆh‰ó$ðV -1ñuàÐ'Ñ(ðuð �d‘
ðuð ˜S #˜X™ð	uð
 ˜c™ TÑ)ðuð 
óuðn ð 15ñEà)ðEð ðEð Ð1Ñ2ð	Eð
 '¨Ñ-ðEð 
#òEó ðEðN ð-˜dÐ#9Ñ:¸TÑAò -ó ô-r!   r   )"rb   r4   Útypingr   r   r   Úfastapir   Úlitellm._loggingr   Ú%litellm.integrations.custom_guardrailr   r	   Ú*litellm.litellm_core_utils.litellm_loggingr
   r²   Ú&litellm.llms.custom_httpx.http_handlerr   r   Úlitellm.secret_managers.mainr   Úlitellm.types.guardrailsr   r   Úlitellm.types.llms.openair   Ú3litellm.types.proxy.guardrails.guardrail_hooks.baser   Úlitellm.types.utilsr   r   Ú__annotations__r   r   r3   r!   r   ú<module>rÁ      s]   ðô Û 	ß &Ñ &å !å 1÷õ T÷õ 8ß GÝ 6Ý TÝ 9à#€�Ó #Ø$@Ð ˜EÓ @ôR-˜õ R-r!   